From 8d3ba2a47df0d0961ac749775f44c136c30aa765 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 6 Oct 2026 13:28:26 +0000 Subject: [PATCH] SDK 0.3.0: Windows support (platforms, sdk.platform, named pipes) Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01YBUx1d4niJfMeuwPGpikuu --- CHANGELOG.md | 10 ++++++++++ README.md | 2 +- docs/sdk.md | 46 +++++++++++++++++++++++++++++++++++++++++++ index.d.ts | 2 ++ manifest.d.ts | 19 +++++++++++++++++- package.json | 2 +- template/package.json | 2 +- 7 files changed, 79 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 441c64d..e7d390a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,15 @@ # Changelog +## 0.3.0 + +Windows support (Ervisio 0.6). Plugins written for 0.2 run unchanged on Linux; the contract version stays 3. + +- `Manifest.platforms` (`'linux' | 'windows'`, type `Platform`): where the plugin works (Ervisio 0.6.1). Missing = Linux only. +- `platforms` on `Command`, `HttpApi` and object `Folder` entries (Ervisio 0.6.2): per-system forms of one command or API + under one name; Windows named pipes as `socket`. +- `sdk.platform`: the server's system. +- docs/sdk.md: "Windows" section. + ## 0.2.0 Needs Ervisio 0.5 for the new members; plugins written for 0.1 run unchanged and the contract version stays 3. The new diff --git a/README.md b/README.md index adaf2f6..0031b20 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ Then turn on developer mode in Ervisio and load `dist/hello` from Plugins › De The package is not on npm yet; the template depends on it through git: ```json -"devDependencies": { "@ervisio/plugin-sdk": "github:Ervisio/plugin-sdk#v0.2.0" } +"devDependencies": { "@ervisio/plugin-sdk": "github:Ervisio/plugin-sdk#v0.3.0" } ``` npm 12 refuses git dependencies by default; the template's `.npmrc` allows them for direct dependencies only diff --git a/docs/sdk.md b/docs/sdk.md index cbe06bf..a27eff0 100644 --- a/docs/sdk.md +++ b/docs/sdk.md @@ -119,6 +119,7 @@ types (`Manifest`, `Capabilities`, `Command`, `HttpApi`, `Folder`, `Contributes` | `version` | `3`. Check it if your plugin also supports older consoles: `if (sdk.version < 3) …` (v3 adds `api.http`, `api.httpStream`, `api.pty`, `files.mkdir`, `files.remove`). | | `plugin` | `{ id, name, version }`. | | `appOrigin` | The console's origin as the user reaches it (`https://host:9090`, or the proxy's). Use it for webhook URLs: `location.origin` is opaque inside the frame. Ervisio 0.5.0 and later. | +| `platform` | `'linux'` or `'windows'`: the server's system. Ervisio 0.6.1 and later; undefined (Linux) on older consoles. See "Windows" below. | | `view` | `{ kind: 'page' \| 'widget', id }`: what this frame shows. | | `react` | React 18, shared by the runtime and the UI kit. | | `ui` | The app's own component kit (`Button`, `IconButton`, `Input`, `Select`, `Switch`, `Checkbox`, `Segmented`, `Table`, `Card`, `StatCard`, `Page`, `Panel`, `Dialog`, `ConfirmDialog`, `Sheet`, `Tabs`, `Badge`, `Chip`, `Progress`, `Skeleton`, `EmptyState`, `Menu`, `DropdownMenu`, `Tooltip`, `Icon`, `Sparkline`, `AreaChart`, `toast`, ...). `toast.ok/err/info(title, detail?)` shows the toast in the app, prefixed with your plugin's name. | @@ -447,6 +448,51 @@ the field refuse the manifest ("unknown field"), with the same result. Put the s when you publish (see [publishing.md](publishing.md)) so Browse shows "Needs a newer Ervisio" instead of an Install button. To use a new member on a console that may be older, guard on it instead (`if (sdk.appOrigin)`, `if (sdk.api.jobs)`). +## Windows (SDK 0.3) + +Ervisio 0.6 runs on Windows too. A plugin says where it works with `platforms` in the manifest: +`["linux"]`, `["windows"]` or `["linux", "windows"]`. Without it the plugin is Linux only (every plugin written +before 0.6 was). Plugins and Browse show a Linux and/or Windows mark next to Install, and a plugin for the other +system cannot be installed. `platforms` needs Ervisio 0.6.1: add `"minCore": "0.6.1"` (0.6.2 if you use the +per-entry form below), or older consoles refuse the manifest. + +The page code, the UI kit and the SDK calls are the same on both systems. What differs is what the manifest +declares, so commands, HTTP APIs and folders take `platforms` too (Ervisio 0.6.2). Two entries may share a name +when their systems do not overlap; the daemon keeps the one for its system, so the page calls the same name: + +```json +{ + "platforms": ["linux", "windows"], + "minCore": "0.6.2", + "capabilities": { + "commands": [ + {"name": "services", "argv": ["systemctl", "list-units", "--type=service", "--output=json"], "platforms": ["linux"]}, + {"name": "services", "argv": ["powershell.exe", "-NoProfile", "-NonInteractive", "-Command", "Get-Service | Select-Object Name,Status | ConvertTo-Json"], "platforms": ["windows"]} + ], + "http": [ + {"name": "docker", "socket": "/run/docker.sock", "platforms": ["linux"], "rules": [{"methods": ["GET"], "path": "/.*"}]}, + {"name": "docker", "socket": "\\\\.\\pipe\\docker_engine", "platforms": ["windows"], "rules": [{"methods": ["GET"], "path": "/.*"}]} + ], + "files": {"read": [{"path": "/var/log/demo", "platforms": ["linux"]}, {"path": "C:\\ProgramData\\Demo", "platforms": ["windows"]}]} + } +} +``` + +```ts +const r = await sdk.api.exec('services'); // systemctl on Linux, PowerShell on Windows +const parse = sdk.platform === 'windows' ? parseGetService : parseSystemctl; +``` + +* Commands run without a shell on both systems. On Windows `argv[0]` is a program on the `PATH` (`powershell.exe`, + `sc.exe`, `netsh.exe`, `winget.exe`) or an absolute path. Keep PowerShell scripts fixed in the manifest and pass + values as `{N}` arguments (read them from `$args`), never build a script from user input. +* HTTP APIs: a unix socket, or on Windows a named pipe (`\\.\pipe\name`, only in an entry for `["windows"]`). Docker + Desktop and Docker Engine on Windows listen on `\\.\pipe\docker_engine`. +* Folders: `C:\dir` paths on Windows, `/dir` on Linux, `~/...` on both (the user's home or profile). +* `admin` asks members of Administrators to unlock administrator rights; `adminUnlessGroup` takes a Windows group + name (`docker-users`). +* `pty: true` commands run in a ConPTY on Windows. + ## Styling The frame already carries the app's tokens, the UI kit CSS and the Figtree / JetBrains Mono fonts. All theme tokens are diff --git a/index.d.ts b/index.d.ts index 543fac2..4a36c91 100644 --- a/index.d.ts +++ b/index.d.ts @@ -305,6 +305,8 @@ export interface PluginSDK { * on older consoles it is undefined. */ appOrigin: string; + /** SDK 0.3: the server's system, `'linux'` or `'windows'` (Ervisio 0.6.1; undefined on older consoles, which are Linux). */ + platform: 'linux' | 'windows'; plugin: { id: string; name: string; version: string }; /** What this frame shows. */ view: { kind: 'page' | 'widget'; id: string }; diff --git a/manifest.d.ts b/manifest.d.ts index c12f29c..efc6046 100644 --- a/manifest.d.ts +++ b/manifest.d.ts @@ -35,6 +35,8 @@ export interface Command { * `docker` and argv must hold exactly one `{env}` item, which the daemon replaces with the environment's address. */ remote?: 'docker'; + /** SDK 0.3: systems this entry is for (Ervisio 0.6.2). Missing = all the plugin's `platforms`. Two entries may share a name when their systems do not overlap; the daemon uses the one for its system. */ + platforms?: Platform[]; } /** One rule of an HTTP API: methods allowed on paths matching the regular expression. */ @@ -61,10 +63,19 @@ export interface HttpApi { remote?: 'docker'; /** Default 30, max 600. */ timeoutSec?: number; + /** + * SDK 0.3: systems this entry is for (Ervisio 0.6.2). In an entry for `["windows"]` alone, `socket` may be a named + * pipe, `\\.\pipe\docker_engine`. + */ + platforms?: Platform[]; } /** A capabilities.files entry: a path, or an object with options (SDK v3). */ -export type Folder = string | { path: string; admin?: boolean; adminUnlessGroup?: string; create?: boolean }; +/** A system Ervisio runs on. */ +export type Platform = 'linux' | 'windows'; + +/** A capabilities.files entry. SDK 0.3: `platforms` limits it to some systems (Windows paths are `C:\\dir`). */ +export type Folder = string | { path: string; admin?: boolean; adminUnlessGroup?: string; create?: boolean; platforms?: Platform[] }; /** A parameter of a job: the whole value must match `pattern`. */ export interface JobParam { @@ -173,6 +184,12 @@ export interface Manifest { minCore?: string; /** `{ ervisio: ">=0.5.0" }`: another spelling of `minCore`. Only `>=` or a bare version is understood. */ requires?: { ervisio?: string }; + /** + * SDK 0.3: the systems the plugin works on (Ervisio 0.6.1). Missing = Linux only. On another system the plugin is + * shown with a Linux/Windows mark but cannot be installed, enabled or run. Older cores refuse the field ("unknown + * field"), so add `minCore: "0.6.1"` with it. + */ + platforms?: Platform[]; /** sha256 of every file; written by the signer, never by hand. */ files?: Record; capabilities?: Capabilities; diff --git a/package.json b/package.json index f7cbb2a..1e1ffbf 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@ervisio/plugin-sdk", - "version": "0.2.0", + "version": "0.3.0", "description": "Types, React shim and Vite preset for Ervisio plugins (plugin SDK contract version 3).", "type": "module", "license": "MIT", diff --git a/template/package.json b/template/package.json index 1b9421e..32dbcdf 100644 --- a/template/package.json +++ b/template/package.json @@ -10,7 +10,7 @@ "typecheck": "tsc --noEmit" }, "devDependencies": { - "@ervisio/plugin-sdk": "github:Ervisio/plugin-sdk#v0.2.0", + "@ervisio/plugin-sdk": "github:Ervisio/plugin-sdk#v0.3.0", "@types/react": "^18.3.31", "typescript": "^6.0.3", "vite": "^8.3.2"