diff --git a/README.md b/README.md index a487392..59815cd 100644 --- a/README.md +++ b/README.md @@ -321,7 +321,7 @@ bun run check # complete fail-closed local CI sequence ``` Marketplace publication consumes the public authoring contracts -`@convax/plugin-api@1.0.0`, `@convax/plugin-sdk@0.1.0`, and +`@convax/plugin-api@2.0.0`, `@convax/plugin-sdk@0.1.0`, and `@convax/marketplace-kit@0.2.0`. Local source links are validation aids, not valid publication dependencies. All three exact packages must be available from the configured registry before a clean frozen install or publication can succeed. diff --git a/README.zh-CN.md b/README.zh-CN.md index cbc9c81..b51f469 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -244,7 +244,7 @@ bun run check # 执行完整 fail-closed 本地 CI ``` Marketplace 发布消费公开 authoring contract: -`@convax/plugin-api@1.0.0`、`@convax/plugin-sdk@0.1.0` 与 +`@convax/plugin-api@2.0.0`、`@convax/plugin-sdk@0.1.0` 与 `@convax/marketplace-kit@0.2.0`。本地源码 link 只用于验证,不是有效的发布依赖; 三个精确版本都必须先在配置的 registry 可用,干净 frozen install 与发布才可成功。 参见 [SDK authoring rollout blocker](docs/sdk-authoring-contract-rollout.md)。 diff --git a/bun.lock b/bun.lock index c982833..0390640 100644 --- a/bun.lock +++ b/bun.lock @@ -15,36 +15,36 @@ }, "packages/plugins/chatcut": { "name": "@microvoid/convax-plugin-chatcut", - "version": "0.3.2", + "version": "0.4.0", "dependencies": { "@microvoid/convax-chatcut-media-import-mcp": "workspace:*", "@microvoid/convax-skill-chatcut": "workspace:*", }, "devDependencies": { - "@convax/plugin-sdk": "workspace:*", + "@convax/plugin-sdk": "0.1.0", }, }, "packages/plugins/codex-service": { "name": "@microvoid/convax-plugin-codex-service", - "version": "0.1.2", + "version": "0.2.0", "dependencies": { "@microvoid/convax-codex-mcp": "workspace:*", }, }, "packages/plugins/convax-pet": { "name": "@microvoid/convax-plugin-convax-pet", - "version": "0.2.3", + "version": "0.3.0", }, "packages/plugins/cutout-studio": { "name": "@microvoid/convax-plugin-cutout-studio", - "version": "0.2.1", + "version": "0.3.0", "dependencies": { "@microvoid/convax-cutout-mcp": "workspace:*", }, }, "packages/plugins/ffmpeg-tools": { "name": "@microvoid/convax-plugin-ffmpeg-tools", - "version": "0.3.3", + "version": "0.4.0", "dependencies": { "@microvoid/convax-ffmpeg-mcp": "workspace:*", "@microvoid/convax-skill-ffmpeg-canvas": "workspace:*", @@ -52,54 +52,54 @@ }, "packages/plugins/hello-convax": { "name": "@microvoid/convax-plugin-hello-convax", - "version": "0.1.3", + "version": "0.2.0", "dependencies": { "@microvoid/convax-skill-hello-convax-guide": "workspace:*", }, "devDependencies": { - "@convax/plugin-sdk": "workspace:*", + "@convax/plugin-sdk": "0.1.0", }, }, "packages/plugins/jianying-editor": { "name": "@microvoid/convax-plugin-jianying-editor", - "version": "2.1.2", + "version": "3.0.0", "dependencies": { "@microvoid/convax-jianying-editor-mcp": "workspace:*", "@microvoid/convax-skill-jianying-editor": "workspace:*", }, "devDependencies": { - "@convax/plugin-sdk": "workspace:*", + "@convax/plugin-sdk": "0.1.0", }, }, "packages/plugins/multi-angle": { "name": "@microvoid/convax-plugin-multi-angle", - "version": "0.1.3", + "version": "0.2.0", "devDependencies": { - "@convax/plugin-sdk": "workspace:*", + "@convax/plugin-sdk": "0.1.0", }, }, "packages/plugins/nexus-service": { "name": "@microvoid/convax-plugin-nexus-service", - "version": "0.3.14", + "version": "0.4.0", "dependencies": { "@microvoid/convax-nexus-mcp": "workspace:*", }, }, "packages/plugins/panorama-viewer": { "name": "@microvoid/convax-plugin-panorama-viewer", - "version": "0.2.4", + "version": "0.3.0", "devDependencies": { - "@convax/plugin-sdk": "workspace:*", + "@convax/plugin-sdk": "0.1.0", }, }, "packages/plugins/relight-studio": { "name": "@microvoid/convax-plugin-relight-studio", - "version": "0.1.4", + "version": "0.2.0", "dependencies": { "@microvoid/convax-skill-relight-studio": "workspace:*", }, "devDependencies": { - "@convax/plugin-sdk": "workspace:*", + "@convax/plugin-sdk": "0.1.0", "@types/react": "19.2.14", "@types/react-dom": "19.2.3", "radix-ui": "1.6.2", @@ -110,34 +110,34 @@ }, "packages/plugins/storyai-3d-director-desk": { "name": "@microvoid/convax-plugin-storyai-3d-director-desk", - "version": "0.2.0", + "version": "0.3.0", "dependencies": { "@microvoid/convax-skill-storyai-3d-director-desk": "workspace:*", }, "devDependencies": { - "@convax/plugin-sdk": "workspace:*", + "@convax/plugin-sdk": "0.1.0", }, }, "packages/plugins/storyboard-studio": { "name": "@microvoid/convax-plugin-storyboard-studio", - "version": "0.1.1", + "version": "0.2.0", "dependencies": { "@microvoid/convax-skill-storyboard-studio": "workspace:*", }, "devDependencies": { - "@convax/plugin-sdk": "workspace:*", + "@convax/plugin-sdk": "0.1.0", }, }, "packages/plugins/video-timeline": { "name": "@microvoid/convax-plugin-video-timeline", - "version": "0.1.5", + "version": "0.2.0", "devDependencies": { - "@convax/plugin-sdk": "workspace:*", + "@convax/plugin-sdk": "0.1.0", }, }, "packages/plugins/xiaoyunque-generation": { "name": "@microvoid/convax-plugin-xiaoyunque-generation", - "version": "0.3.7", + "version": "0.4.0", "dependencies": { "@microvoid/convax-xiaoyunque-mcp": "workspace:*", }, @@ -156,7 +156,7 @@ }, "packages/skills/chatcut": { "name": "@microvoid/convax-skill-chatcut", - "version": "0.3.2", + "version": "0.4.0", }, "packages/skills/clip-export": { "name": "@microvoid/convax-skill-clip-export", @@ -172,7 +172,7 @@ }, "packages/skills/ffmpeg-canvas": { "name": "@microvoid/convax-skill-ffmpeg-canvas", - "version": "0.3.3", + "version": "0.4.0", }, "packages/skills/film-shot": { "name": "@microvoid/convax-skill-film-shot", @@ -180,7 +180,7 @@ }, "packages/skills/hello-convax-guide": { "name": "@microvoid/convax-skill-hello-convax-guide", - "version": "0.2.2", + "version": "0.3.0", }, "packages/skills/image-remix": { "name": "@microvoid/convax-skill-image-remix", @@ -188,11 +188,11 @@ }, "packages/skills/jianying-editor": { "name": "@microvoid/convax-skill-jianying-editor", - "version": "2.0.1", + "version": "3.0.0", }, "packages/skills/relight-studio": { "name": "@microvoid/convax-skill-relight-studio", - "version": "0.1.0", + "version": "0.2.0", }, "packages/skills/short-drama-screenwriter": { "name": "@microvoid/convax-skill-short-drama-screenwriter", @@ -208,11 +208,11 @@ }, "packages/skills/storyai-3d-director-desk": { "name": "@microvoid/convax-skill-storyai-3d-director-desk", - "version": "0.1.1", + "version": "0.2.0", }, "packages/skills/storyboard-studio": { "name": "@microvoid/convax-skill-storyboard-studio", - "version": "0.1.1", + "version": "0.2.0", }, "packages/skills/video-prompting": { "name": "@microvoid/convax-skill-video-prompting", @@ -316,7 +316,7 @@ }, "vendor/host-packages/plugin-api": { "name": "@convax/plugin-api", - "version": "1.0.0", + "version": "2.0.0", "bin": { "convax-plugin-api": "./dist/cli.js", }, diff --git a/docs/host-capability-requests/sdk-owned-pet-surface-client.md b/docs/host-capability-requests/sdk-owned-pet-surface-client.md index 5962e49..2d71fe1 100644 --- a/docs/host-capability-requests/sdk-owned-pet-surface-client.md +++ b/docs/host-capability-requests/sdk-owned-pet-surface-client.md @@ -24,7 +24,7 @@ have. ## Catalog evidence -- Checked Catalog version: `@convax/plugin-api@1.0.0`, canonical JSON SHA-256 `5647290670309c550c144b2746a17bc0fa0dd504484fb137952620896dc889e4`. +- Checked Catalog version: `@convax/plugin-api@2.0.0`, canonical JSON SHA-256 `a23b847c3513e810777a0444ee3c3cd20414b4ee57e2b93a0a663fba2545e99d`. - Closest existing APIs: `@convax/plugin-sdk/client` exports the normal Web Plugin client; the Host API Catalog contains no Pet-surface transport factory because Pet operations are contribution-scoped rather than ordinary `hostApi` calls. - Availability result: the installed public SDK has no SDK-owned Pet overlay/settings client, connection parser, typed request/result parser, cancellation contract, or late-response policy. - Why required/optional declaration does not solve it: `hostApi` negotiation cannot change a `contributes.pet` surface into a normal Web `entry` or manufacture a missing SDK transport owner. diff --git a/docs/host-capability-requests/verified-companion-toolchain.md b/docs/host-capability-requests/verified-companion-toolchain.md index 974d7ad..1b3746c 100644 --- a/docs/host-capability-requests/verified-companion-toolchain.md +++ b/docs/host-capability-requests/verified-companion-toolchain.md @@ -31,7 +31,7 @@ Status: pending human review ## Catalog evidence -- Checked Catalog version: `@convax/plugin-api@1.0.0`, canonical JSON SHA-256 `5647290670309c550c144b2746a17bc0fa0dd504484fb137952620896dc889e4`. +- Checked Catalog version: `@convax/plugin-api@2.0.0`, canonical JSON SHA-256 `a23b847c3513e810777a0444ee3c3cd20414b4ee57e2b93a0a663fba2545e99d`. - Closest existing APIs: none; this is an authoring, Registry, installation, and companion-launch contract rather than a Web or Agent callable API. - Availability result: the current contracts admit one verified primary diff --git a/docs/host-capability-requests/web-plugin-generation-input-binding.md b/docs/host-capability-requests/web-plugin-generation-input-binding.md new file mode 100644 index 0000000..0e03e8d --- /dev/null +++ b/docs/host-capability-requests/web-plugin-generation-input-binding.md @@ -0,0 +1,140 @@ +# Host capability request: Web Plugin generation input binding + +Status: pending human review + +## User problem + +- Affected Plugins and source versions: `jianying-editor@3.0.0`, + `multi-angle@0.2.0`, and `relight-studio@0.2.0`. +- Checked Catalog: `@convax/plugin-api@2.0.0`, schema + `convax.plugin-api-catalog/3`. +- Released-authority mismatch: `canvas.inputs.list` deliberately returns only an + opaque `inputKey`, while the prior generation contract required a `nodeId`. + Treating the opaque key as a Canvas node id was an invalid hidden assumption. +- The local API 2 development Catalog corrects that shape, but it is not + publication authority until the protected receipt binds the exact contract. + +## Blocked Plugin use case + +- A Web Plugin selects one directly connected image through + `canvas.inputs.list`, previews it through the separately governed image + session APIs, and then submits that exact input as a generation reference. +- The Plugin must not learn or reconstruct a Canvas node id, native path, resource + hash, or Host implementation detail. +- Edge, resource, revision, caller, cancellation, and stale-scope checks remain + Host-owned immediately before the external generation call. + +## Catalog evidence + +- Checked Catalog version: `@convax/plugin-api@2.0.0`, canonical JSON SHA-256 + `a23b847c3513e810777a0444ee3c3cd20414b4ee57e2b93a0a663fba2545e99d`. +- Closest existing APIs: `canvas.inputs.list`, `canvas.inputs.image.open`, and + `generation.execute`; `canvas.inputs.list` returns pathless descriptors keyed + by `inputKey`. +- Availability result: the mechanically vendored API 2 candidate accepts + `references: [{ inputKey, role }]`, with `since: 1.0.0`, + `contractSince: 2.0.0`, and contract digest + `sha256:a7ec11a6894247ae4485414a82a8a409f618d00bf3206e973ab111d4e7fa8247`. +- Why required/optional declaration does not solve it: declaring + `generation.execute` negotiates only an already-published contract; it cannot + approve candidate bytes or let `canvas.inputs.image.open` bearer possession + grant generation authority. +- `acceptedApiContracts` binds the exact generated candidate digest while the + request and all affected versions remain pending. Local bytes do not approve + the contract or replace the protected Host release and human decision receipt. + +## Requested generic contract + +- Proposed capability id or contribution: correct the API 2 + `convax.plugin-api-wire-schema/3` `generation.execute.references[]` item to + `{ "inputKey": "", "role": "" }`; + keep `generation.execute` as the API id because this is a breaking correction + within the unpublished API 2 cutover, not a Plugin-specific method. +- Intended audiences: `web-plugin`. +- Scope: the exact installed Plugin principal and owning Canvas node connection. +- Side effect: unchanged `execute`. +- Required grant: unchanged `generation.execute`; image-preview grants do not + imply it. +- Bounded request: accept at most the Catalog-defined number of unique + `{ inputKey, role }` references plus the existing bounded prompt, output, + result mode, and tool id; reject `nodeId`, paths, URLs, session ids, unknown + fields, unrelated keys, duplicate bindings, and unsupported roles. +- Bounded response: retain the existing bounded generation result and never + return the resolved Canvas node identity, native path, or staged resource. +- Stable errors: retain the published generation errors and use + `stale-context`, `permission-denied`, and `resource-unavailable` for invalidated + authority or resources without exposing private diagnostics. +- Cancellation and stale-scope behavior: resolve each key only against the + caller's current direct incoming inputs, bind caller and resource revisions, + propagate cancellation, and revalidate the exact edge and resource immediately + before execution; cancellation or staleness before the billable boundary + prevents execution. + +## Alternatives considered + +- Expose `nodeId` from `canvas.inputs.list`: rejected because it widens a + pathless capability into Canvas structure disclosure and encourages callers to + retain stale authority-shaped identifiers. +- Add an `inputKey -> nodeId` mapping API: rejected because it creates a reusable + identity leak and a confused-deputy surface with no Plugin need. +- Reuse the image bearer URL or session id: rejected because preview possession + is not generation consent and the session is revoked promptly after decode. +- Omit references and infer an arbitrary connection: rejected because multiple + direct inputs require an explicit, stable caller selection. + +## Security and authority + +- Bind every key to the caller snapshot, frame, Project, Canvas, owning node, + direct edge, source resource identity, and current media revision. +- Reject caller-supplied node ids, paths, URLs, session ids, unrelated keys, + duplicate bindings, unsupported roles, stale edges, and changed resources. +- Revalidate after asynchronous preparation and immediately before a billable + call. Cancellation before that boundary must prevent execution. +- The callee receives only the Host-staged resource permitted by the selected + generation tool contract; no identifier or native path crosses renderer IPC. + +## Compatibility + +- API major 1 packages remain unsupported by the API 2 flag day and are not + reinterpreted. +- API 2 packages using the corrected reference shape remain publication-blocked + until the generated Catalog, SDK parser/client, runtime conformance evidence, + and protected external decision receipt agree on one exact digest. +- Rollback removes the new Plugin versions; it never treats an opaque key as a + node id or falls back to private IPC. + +## Falsifiable acceptance tests + +1. Generated Catalog and SDK accept only `{ inputKey, role }` for + `generation.execute.references[]` and reject `nodeId`. +2. A current opaque key for one direct incoming image reaches the existing + generation executor without exposing its resolved Canvas identity. +3. Wrong Plugin/frame/Project/Canvas/node, unrelated or malformed key, removed or + replaced edge, changed media revision, duplicate reference, and unsupported + role fail before external execution. +4. Cancellation and stale scope after preparation but before the billable + boundary produce no external call and no Canvas mutation. +5. Preview-session possession alone cannot authorize generation, and closing the + preview session neither invalidates nor broadens the separately revalidated + generation request. +6. Jianying Editor, Multi Angle, and Relight Studio packed assets contain no + `nodeId` reference workaround and submit only opaque keys returned by their + current input list. + +## Plugin-side plan after approval + +- Persist only the selected opaque input key plus harmless revision/dimension + metadata; never persist a resolved Canvas identity or bearer URL. +- Submit `{ inputKey, role }` through the generated SDK client and keep + cancellation and stale-input tests. +- Audit any future Web generation Plugin as a separate affected identity before + moving it to the corrected contract. + +## Human decision audit record + +- Decision: pending +- Reviewer identity: pending +- Decision time: pending +- Protected receipt URL and SHA-256: pending +- Accepted published contract version and digest: pending +- Runtime conformance evidence: pending diff --git a/docs/host-capability-requests/web-plugin-image-input-read.md b/docs/host-capability-requests/web-plugin-image-input-read.md index 8071302..2a6bf5a 100644 --- a/docs/host-capability-requests/web-plugin-image-input-read.md +++ b/docs/host-capability-requests/web-plugin-image-input-read.md @@ -33,8 +33,8 @@ Status: pending human review ## Catalog evidence -- Checked Catalog version: `@convax/plugin-api@1.0.0`, canonical JSON SHA-256 - `5647290670309c550c144b2746a17bc0fa0dd504484fb137952620896dc889e4`. +- Checked Catalog version: `@convax/plugin-api@2.0.0`, canonical JSON SHA-256 + `a23b847c3513e810777a0444ee3c3cd20414b4ee57e2b93a0a663fba2545e99d`. - Closest existing APIs: `canvas.inputs.list`, `canvas.inputs.open`, and `canvas.inputs.close`. - Availability result: those APIs are declared for Web Plugins, but the catalog diff --git a/docs/packaging.md b/docs/packaging.md index 2affe40..b97c384 100644 --- a/docs/packaging.md +++ b/docs/packaging.md @@ -68,7 +68,7 @@ controls and must be verified outside repository source. A headless `convax.plugin/8` local Tool Plugin may contain only `manifest.json` and a license notice. It still declares -`hostApi: {"major":1,"required":[],"optional":[]}` and must not claim Web APIs. +`hostApi: {"major":2,"required":[],"optional":[]}` and must not claim Web APIs. Its executable contributions use one declared `mcp-stdio` executable that is a separate distributable and must never appear anywhere below `package/`; validation and packing do not install, build, or execute companion source under @@ -101,7 +101,7 @@ HTTPS endpoint, OAuth mode, and optional bounded literal non-credential headers; never package credentials, tokens, local executables, or an adapter. OpenCode/the native host owns the remote connection and standard OAuth flow. A pure headless remote MCP Plugin explicitly declares -`hostApi: {"major":1,"required":[],"optional":[]}`. The concrete manifest and any +`hostApi: {"major":2,"required":[],"optional":[]}`. The concrete manifest and any owned Skill source remain under this repository's package workspaces. The matching source metadata declares the reviewed tool directory and build output diff --git a/docs/panorama-viewer.md b/docs/panorama-viewer.md index 83f8485..e1e3b96 100644 --- a/docs/panorama-viewer.md +++ b/docs/panorama-viewer.md @@ -12,8 +12,8 @@ Plugins: `host.context.get`; - `canvas.inputs.list` plus `canvas.inputs.changed` for pathless direct-input metadata and opaque `inputKey` values; -- the `canvas.inputs.open`/`canvas.inputs.close` lifecycle, pending generic Host - admission for direct image inputs; +- the `canvas.inputs.image.open`/`canvas.inputs.image.close` lifecycle, pending + generic Host admission for direct image inputs; - `canvas.node.state.replace` for bounded Plugin-owned view state; - `canvas.resource.image.create` for one validated PNG; - managed Project asset admission and rollback; @@ -22,7 +22,7 @@ Plugins: buttons. Desktop must not carry a second Panorama Viewer static bundle or reserve -`panorama-viewer` as a built-in id. Version `0.2.3` targets clean/current profiles +`panorama-viewer` as a built-in id. Version `0.3.0` targets clean/current profiles but remains publication-blocked pending the generic Web image-input capability review. Once admitted, it is installed only as an ordinary Registry package. This release deliberately does not migrate profiles created by the unreleased trusted @@ -44,6 +44,6 @@ and offline, the manifest requests only the documented capabilities, and current viewport capture calls `canvas.resource.image.create`. Until the image-input capability is approved, source admission reports the package as blocked, exact packing rejects it, and Marketplace/release output omits it. End-to-end Electron -acceptance after approval must install the packed `0.2.4` artifact through a +acceptance after approval must install the packed `0.3.0` artifact through a validated Registry entry, exercise list/open/close with an opaque `inputKey`, and verify that the installed summary does not contain `trustedBuiltin`. diff --git a/docs/plugin-authoring.md b/docs/plugin-authoring.md index 5ff1073..cf75386 100644 --- a/docs/plugin-authoring.md +++ b/docs/plugin-authoring.md @@ -121,7 +121,7 @@ and optional API ids: "version": "1.0.0", "entry": "index.html", "hostApi": { - "major": 1, + "major": 2, "required": ["host.context.get"], "optional": [] }, @@ -137,7 +137,7 @@ and optional API ids: A Plugin with `entry` must require `host.context.get`; the negotiated profile and availability query are exposed through that connection API. A pure headless Tool, Hook, Pet, or remote MCP Plugin still declares -`{"major":1,"required":[],"optional":[]}` and must not claim Web-only APIs. +`{"major":2,"required":[],"optional":[]}` and must not claim Web-only APIs. `hostApi` is an availability/compatibility declaration. Existing capability grants remain the authority request. Declaring an API does not bypass permission, diff --git a/docs/sdk-authoring-contract-rollout.md b/docs/sdk-authoring-contract-rollout.md index 36c3eea..9491780 100644 --- a/docs/sdk-authoring-contract-rollout.md +++ b/docs/sdk-authoring-contract-rollout.md @@ -6,7 +6,7 @@ Status: consumer gate implemented; npm/immutable Host evidence still unavailable - `convax-plugins` admits only `convax.package/2` and `convax.plugin/8` authoring input through the Host-owned SDK and Marketplace Kit. -- The required dependency versions are `@convax/plugin-api@1.0.0`, +- The required dependency versions are `@convax/plugin-api@2.0.0`, `@convax/plugin-sdk@0.1.0`, and `@convax/marketplace-kit@0.2.0`. - As of 2026-07-31, npm returns 404 for Plugin API and SDK and exposes Marketplace Kit only through `0.1.1`. A clean frozen install therefore cannot diff --git a/docs/storyai-3d-director-desk.md b/docs/storyai-3d-director-desk.md index 80bc921..fcbe685 100644 --- a/docs/storyai-3d-director-desk.md +++ b/docs/storyai-3d-director-desk.md @@ -16,7 +16,7 @@ Plugins: - sandboxed static Web Plugin frames and manifest-driven Canvas renderers; - bounded Plugin-owned Canvas node state; -- `host.context.get` for the negotiated Host API major 1 profile; +- `host.context.get` for the negotiated Host API major 2 profile; - `canvas.node.state.replace` for bounded Plugin-owned state; - `canvas.resource.image.create` for one validated PNG; - managed Project asset admission, Canvas image-node creation, connection, and diff --git a/packages/plugins/chatcut/convax-package.json b/packages/plugins/chatcut/convax-package.json index 90faf6d..cf72cf1 100644 --- a/packages/plugins/chatcut/convax-package.json +++ b/packages/plugins/chatcut/convax-package.json @@ -4,7 +4,7 @@ "id": "chatcut", "name": "ChatCut", "description": "Imports directly connected Canvas media into ChatCut and connects Convax Agent sessions to ChatCut's hosted MCP server for authenticated, editable video workflows.", - "version": "0.3.2", + "version": "0.4.0", "companions": [ { "command": "convax-chatcut-media-import-mcp", diff --git a/packages/plugins/chatcut/package.json b/packages/plugins/chatcut/package.json index 1337e60..14c7861 100644 --- a/packages/plugins/chatcut/package.json +++ b/packages/plugins/chatcut/package.json @@ -1,6 +1,6 @@ { "name": "@microvoid/convax-plugin-chatcut", - "version": "0.3.2", + "version": "0.4.0", "private": true, "type": "module", "convax.hostCapabilityRequests": [ diff --git a/packages/plugins/chatcut/package/assets/app.js b/packages/plugins/chatcut/package/assets/app.js index 5f19e1b..8771662 100644 --- a/packages/plugins/chatcut/package/assets/app.js +++ b/packages/plugins/chatcut/package/assets/app.js @@ -224,7 +224,7 @@ import { acceptPluginHostConnection } from "./plugin-host-client.js" "First select or create the exact ChatCut project and target timeline; ask only if either target is materially ambiguous.", "Use the ChatCut remote MCP tool advertised for import_media with action=create_session.", `Partition the ordered references into batches of at most four. For each batch, obtain exactly one current import session, then immediately call the installed local Plugin operation ${LOCAL_IMPORT_TOOL}.`, - 'Pass ownerNodeId at the local operation top level. Pass references as [{"nodeId":"…","role":"reference_image|reference_video|audio"}] in the same order, setting each nodeId field to the exact opaque inputKey supplied by the host. Map the exact returned token and endpoint to toolInput: {"session_token":"","endpoint":""}.', + 'Pass ownerNodeId at the local operation top level. Pass references as [{"inputKey":"…","role":"reference_image|reference_video|audio"}] in the same order, setting each inputKey field to the exact opaque inputKey supplied by the host. Map the exact returned token and endpoint to toolInput: {"session_token":"","endpoint":""}.', `Do not call import_media action=create_session a second time for the same batch. If ${LOCAL_IMPORT_TOOL} is absent or fails, stop and report that failure; never loop by creating another session in this turn.`, "The host must reject the operation unless ownerNodeId is a Canvas node owned by this installed Plugin and every reference is still directly connected to it.", "Never repeat the short-lived session token in prose, logs, or the final answer. Do not send it to any tool except this installed local import operation.", diff --git a/packages/plugins/chatcut/package/assets/plugin-host-client.js b/packages/plugins/chatcut/package/assets/plugin-host-client.js index d18fc79..29593b8 100644 --- a/packages/plugins/chatcut/package/assets/plugin-host-client.js +++ b/packages/plugins/chatcut/package/assets/plugin-host-client.js @@ -1 +1 @@ -var cF=/^[a-z][a-z0-9]*(?:\.[a-z][a-z0-9]*)+$/,bF=/^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/,dF=/^[a-z][A-Za-z0-9]*(?:\.[a-z][A-Za-z0-9]*)+$/,vF=/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/,mF=new Set(["web-plugin","agent-skill","companion","host"]),pF=new Set(["connection","plugin","own-node","project","canvas"]),sF=new Set(["none","read","write","execute","subscribe"]),oF=new Set(["cancelable","commit-preserving"]);function _0(G,F){if(G.trim().length===0)throw TypeError(`${F} must not be empty`)}function y0(G,F){if(!vF.test(G))throw TypeError(`${F} must be a strict semantic version`)}function DF(G,F){let J=G.split(".").map(Number),Q=F.split(".").map(Number);for(let X=0;X<3;X+=1){let Y=J[X]-Q[X];if(Y!==0)return Y}return 0}function UF(G){if(!cF.test(G.id))throw TypeError(`Plugin API id is invalid: ${G.id}`);if(G.grant!==null&&!dF.test(G.grant))throw TypeError(`Plugin API grant is invalid: ${G.grant}`);if(!pF.has(G.scope))throw TypeError(`Plugin API scope is invalid: ${G.scope}`);if(!sF.has(G.sideEffect))throw TypeError(`Plugin API sideEffect is invalid: ${G.sideEffect}`);if(!oF.has(G.completion))throw TypeError(`Plugin API completion is invalid: ${G.completion}`);let F=G.audience??["web-plugin"];if(F.length===0||new Set(F).size!==F.length||F.some((X)=>!mF.has(X)))throw TypeError(`Plugin API audience is invalid: ${G.id}`);_0(G.docs.summary,`${G.id} docs.summary`),_0(G.docs.description,`${G.id} docs.description`),_0(G.docs.request,`${G.id} docs.request`),_0(G.docs.response,`${G.id} docs.response`);let J=new Set,Q=G.errors.map((X)=>{if(!bF.test(X.code)||J.has(X.code))throw TypeError(`Plugin API error code is invalid or duplicated: ${G.id}/${X.code}`);return J.add(X.code),_0(X.description,`${G.id}/${X.code} description`),Object.freeze({...X})});return Object.freeze({...G,audience:Object.freeze([...F]),errors:Object.freeze(Q),docs:Object.freeze({...G.docs})})}function H(G){return UF(G)}function rF(G,F){return y0(G,"Plugin API release version"),Object.freeze({version:G,apis:Object.freeze([...F])})}function uF(...G){if(G.length===0)throw TypeError("Plugin API catalog requires at least one release");let F=new Set,J=[],Q;for(let X of G){if(y0(X.version,"Plugin API release version"),Q&&DF(Q,X.version)>=0)throw TypeError("Plugin API releases must be strictly increasing");Q=X.version;for(let Y of X.apis){let Z=UF(Y);if(F.has(Z.id))throw TypeError(`Plugin API id is duplicated: ${Z.id}`);F.add(Z.id),J.push(Object.freeze({...Z,since:X.version}))}}if(J.length===0)throw TypeError("Plugin API catalog must contain at least one API");return Object.freeze({schema:"convax.plugin-api-catalog/1",version:G[G.length-1].version,apis:Object.freeze(J)})}var i6=Object.freeze({assertVersion:y0,compareVersions:DF}),z=1024,I=z*z,$0={type:"none"},s={type:"boolean"},B={finite:!0,type:"number"},o={finite:!0,minimum:0,type:"integer"},E0={type:"null"},g=(G)=>({const:G}),$=(G=2048,F={})=>({controlCharacters:!1,maxLength:G,minLength:F.allowEmpty?0:1,...F.prefix?{prefix:F.prefix}:{},...F.refinement?{refinement:F.refinement}:{},type:"string"}),w=(G,F,J=0,Q)=>({items:G,maxItems:F,minItems:J,type:"array",...Q?{uniqueBy:Q}:{}}),S=(G,F)=>({additionalProperties:!1,properties:G,required:F,type:"object"}),a=(...G)=>({oneOf:G}),w0=(G=I)=>({keyMaxLength:128,maxBytes:G,maxDepth:32,type:"json-object"}),y=(G)=>({controlCharacters:!1,enum:G,maxLength:Math.max(...G.map((F)=>F.length)),minLength:1,type:"string"}),Z0=S({x:B,y:B},["x","y"]),c0=S({height:B,width:B},["height","width"]),t=S({canvasId:$(256),projectId:$(256)},["canvasId","projectId"]),P0=y(["text","image","video","audio"]),WF=y(["text","reference_image","reference_video","first_frame","last_frame","audio"]),x=(G=1000)=>w($(),G),nF=a(S({available:g(!0),catalogVersion:$(64),id:$(128),since:$(64)},["available","catalogVersion","id","since"]),S({available:g(!1),id:$(128),reason:y(["unsupported-host","not-declared","permission-denied","wrong-surface","missing-context","setup-required","disabled","recovering"]),recoverable:s,since:$(64)},["available","id","reason","recoverable"])),jF=S({data:w0(),id:$(),parentId:$(),position:Z0,revision:o,style:w0(),type:$(80)},["data","id","position","revision","type"]),tF=S({nodeId:$(),role:WF},["nodeId","role"]),iF=S({ids:x(),kinds:x(),limit:o,relatedToNodeIds:x(),text:$(2000,{allowEmpty:!0})},[]),aF=S({animated:s,id:$(),source:$(),target:$(),type:$(80)},["source","target"]),lF=S({nodeId:$(),position:Z0,size:c0},["nodeId","position"]),eF=S({componentGap:B,componentPackingScale:B,crossGap:B,isolatedPlacement:y(["left","preserve"]),mainGap:B,nodeGap:B,nodePackingScale:B,strategy:y(["component-packing","horizontal-directed-cluster","vertical-directed-cluster"])},[]),F1=a(S({edgeIds:x(),nodeIds:x(),type:g("elements.remove")},["type"]),S({direction:y(["left","center","right","top","middle","bottom"]),nodeIds:x(),type:g("nodes.align")},["direction","nodeIds","type"]),S({connection:aF,type:g("nodes.connect")},["connection","type"]),S({axis:y(["horizontal","vertical"]),nodeIds:x(),type:g("nodes.distribute")},["axis","nodeIds","type"]),S({label:$(512),nodeIds:x(),type:g("nodes.group")},["nodeIds","type"]),S({gap:B,layout:y(["grid","horizontal","vertical"]),nodeIds:x(),type:g("nodes.layout")},["nodeIds","type"]),S({delta:Z0,nodeIds:x(),type:g("nodes.move")},["delta","nodeIds","type"]),S({type:g("nodes.setGeometry"),updates:w(lF,1000)},["type","updates"]),S({nodeId:$(),type:g("nodes.ungroup")},["nodeId","type"]),S({nodeIds:x(),options:eF,type:g("canvas.auto-layout")},["type"])),G1=S({durationMs:B,height:B,inputKey:$(),kind:$(80),label:$(512),mediaRevision:$(512),mimeType:$(512),name:$(512),status:y(["error","idle","pending"]),width:B},["inputKey","kind","label"]),J1=S({acceptedInputs:w(WF,6),description:$(2000),id:$(256),kind:y(["model","operation"]),output:P0,title:$(120)},["acceptedInputs","description","id","kind","output","title"]),VF=S({id:$(),source:$(),target:$()},["id","source","target"]),Q1=S({id:$(),kind:$(80),label:$(512),parentId:$(64*z,{allowEmpty:!0}),position:Z0,size:c0,type:$(64*z,{allowEmpty:!0})},["id","kind","label","position","size"]),X1=S({description:$(64*z,{allowEmpty:!0}),durationMs:B,id:$(),kind:$(80),label:$(512),mimeType:$(64*z,{allowEmpty:!0}),name:$(64*z,{allowEmpty:!0}),parentId:$(64*z,{allowEmpty:!0}),position:Z0,resource:S({kind:g("project-file"),path:$(1024)},["kind","path"]),size:c0,status:$(64*z,{allowEmpty:!0}),text:$(64*z,{allowEmpty:!0}),type:$(64*z,{allowEmpty:!0})},["id","kind","label","position","size"]),Y1=S({edges:w(VF,1e4),id:$(256),nodes:w(Q1,1e4),revision:o,title:$(512)},["edges","id","nodes","revision","title"]),Z1=S({description:$(8000,{allowEmpty:!0}),edges:w(VF,1e4),id:$(256),nodes:w(X1,1e4),revision:o,tags:w($(),256),title:$(512)},["edges","id","nodes","revision","title"]),_1=S({id:$(),incomingNodeIds:x(),kind:$(80),label:$(512),outgoingNodeIds:x(),parentId:$(64*z,{allowEmpty:!0}),position:Z0,text:$(64*z,{allowEmpty:!0}),type:$(64*z,{allowEmpty:!0})},["id","incomingNodeIds","kind","label","outgoingNodeIds","position"]),$1=S({canvas:S({id:$(256),name:$(512)},["id"]),hostApi:S({availability:w(nF,256,0,"id"),catalogVersion:$(64)},["availability","catalogVersion"]),node:jF,plugin:S({id:$(128),name:$(512),version:$(128)},["id","name","version"]),project:S({id:$(256),name:$(512)},["id"])},["canvas","hostApi","node","plugin","project"]),C=(G,F,J={})=>({request:{maxBytes:J.request??64*z,schema:G},result:{maxBytes:J.result??64*z,schema:F}}),F0=Object.freeze({"host.context.get":C($0,$1,{result:I}),"canvas.inputs.list":C($0,S({inputs:w(G1,256)},["inputs"]),{result:I}),"canvas.inputs.open":C(S({inputKey:$()},["inputKey"]),S({probe:S({duration:S({estimated:s,milliseconds:B},["estimated","milliseconds"]),height:B,kind:y(["audio","video"]),mediaRevision:$(128),mimeType:$(256),size:B,width:B},["duration","kind","mediaRevision","mimeType","size"]),sessionId:$(128),url:$(2048,{prefix:"convax-connected-media://"})},["probe","sessionId","url"])),"canvas.inputs.close":C(S({sessionId:$(128)},["sessionId"]),S({closed:s},["closed"])),"canvas.node.get":C($0,jF,{result:I}),"canvas.node.state.replace":C(S({state:w0(256*z)},["state"]),S({updated:g(!0)},["updated"]),{request:256*z+4*z}),"canvas.resource.image.create":C(S({dataUrl:$(24*I,{prefix:"data:image/png;base64,"}),name:$(120,{refinement:"safe-png-file-name"})},["dataUrl","name"]),S({createdNodeId:$(),revision:o},["createdNodeId","revision"]),{request:24*I+4*z}),"project.file.text.read":C(S({path:$(1024,{refinement:"portable-project-relative-path"})},["path"]),S({content:$(I,{allowEmpty:!0}),exists:s,path:$(1024,{refinement:"portable-project-relative-path"})},["content","exists","path"]),{result:I+4*z}),"agent.prompt":C(S({text:$(20000,{refinement:"trimmed"})},["text"]),S({text:$(64*z,{allowEmpty:!0})},["text"])),"generation.tools.list":C(a($0,S({output:P0},[])),S({tools:w(J1,256)},["tools"]),{result:I}),"generation.execute":C(S({output:P0,prompt:$(20000,{refinement:"trimmed"}),references:w(tF,32),resultMode:y(["create-pending-node","return"]),toolId:$(256)},["prompt"]),S({createdNodeIds:w($(),32),outputText:$(64*z,{allowEmpty:!0}),revision:o,toolId:$(256),warnings:w($(),32)},["createdNodeIds","revision","toolId","warnings"]),{result:256*z}),"projects.list":C($0,S({projects:w(S({available:s,id:$(256),name:$(512)},["available","id","name"]),1000)},["projects"]),{result:I}),"canvas.catalog.list":C(S({projectId:$(256)},["projectId"]),S({canvases:w(S({createdAt:B,id:$(256),name:$(512),updatedAt:B},["createdAt","id","name","updatedAt"]),1e4),projectId:$(256)},["canvases","projectId"]),{result:8*I}),"canvas.document.get":C(S({projection:y(["geometry","structure"]),ref:t},["ref"]),a(S({document:Y1,projection:g("geometry"),ref:t,storageVersion:a(E0,$(256))},["document","projection","ref","storageVersion"]),S({document:Z1,projection:g("structure"),ref:t,storageVersion:a(E0,$(256))},["document","projection","ref","storageVersion"])),{result:8*I}),"canvas.nodes.query":C(S({query:iF,ref:t},["ref"]),S({nodes:w(_1,1000),ref:t,revision:o,storageVersion:a(E0,$(256))},["nodes","ref","revision","storageVersion"]),{request:I,result:8*I}),"canvas.transaction.execute":C(S({commands:w(F1,256,1),expectedRevision:o,ref:t,transactionId:$(128)},["commands","expectedRevision","ref","transactionId"]),S({affectedNodeIds:x(1e4),changed:s,createdNodeIds:x(1e4),ref:t,revision:o,storageVersion:$(256),summaryTruncated:s,warnings:x()},["affectedNodeIds","changed","createdNodeIds","ref","revision","storageVersion","warnings"]),{request:I,result:2*I}),"canvas.events.subscribe":C(S({ref:S({canvasId:$(256),projectId:$(256)},["projectId"])},["ref"]),S({subscriptionId:$(128)},["subscriptionId"])),"canvas.events.unsubscribe":C(S({subscriptionId:$(128)},["subscriptionId"]),S({removed:s},["removed"]))}),K1=Math.max(...Object.values(F0).map(({request:G})=>G.maxBytes)),M1=Math.max(...Object.values(F0).map(({result:G})=>G.maxBytes));function S1(G){return F0[G]}function q0(G,F){if(!G||typeof G!=="object"||Array.isArray(G))throw TypeError(`${F} must be an object`);let J=Object.getPrototypeOf(G);if(J!==Object.prototype&&J!==null)throw TypeError(`${F} must be a plain object`);return G}var D1=/^(CON|PRN|AUX|NUL|COM[1-9¹²³]|LPT[1-9¹²³]|CONIN\$|CONOUT\$)$/iu;function LF(G){for(let F of G){let J=F.codePointAt(0);if(J>=55296&&J<=57343)return!1}return!0}function s0(G){let F=G.split(".",1)[0]??"";return Boolean(G&&G!=="."&&G!==".."&&LF(G)&&!/[\\/:*?"<>|\u0000-\u001f\u007f]/u.test(G)&&!/[. ]$/u.test(G)&&!D1.test(F))}function U1(G,F){if(F===void 0)return!0;if(F==="trimmed")return G===G.trim();if(F==="safe-png-file-name")return G===G.trim()&&G.toLowerCase().endsWith(".png")&&s0(G);if(F==="portable-project-relative-path"){if(G!==G.trim()||G.includes("\\")||G.startsWith("/")||G.startsWith("//")||/^[A-Za-z]:/u.test(G)||!LF(G))return!1;let J=G.split("/");return J[0]?.toLowerCase()!==".convax"&&J.length>0&&J.every((Q)=>s0(Q))}return!1}function W1(G,F,J){let Q=new Set,X=(_,M,K)=>{if(_===null||typeof _==="string"||typeof _==="boolean")return _;if(typeof _==="number"){if(!Number.isFinite(_))throw TypeError(`${M} must contain finite JSON numbers`);return _}if(!_||typeof _!=="object"||K>=F.maxDepth||Q.has(_))throw TypeError(`${M} must be bounded acyclic JSON`);let D=Object.getPrototypeOf(_);if(!Array.isArray(_)&&D!==Object.prototype&&D!==null)throw TypeError(`${M} must contain plain JSON objects`);Q.add(_);let W;if(Array.isArray(_))W=_.map((O,V)=>X(O,`${M}[${V}]`,K+1));else{let O=Object.create(null);for(let[V,P]of Object.entries(_)){if(V.length<1||V.length>F.keyMaxLength||/[\u0000-\u001f\u007f]/u.test(V))throw TypeError(`${M} key is invalid`);O[V]=X(P,`${M}.${V}`,K+1)}W=O}return Q.delete(_),W},Y=X(q0(G,J),J,0);if(Array.isArray(Y)||!Y||typeof Y!=="object")throw TypeError(`${J} must be an object`);let Z=JSON.stringify(Y);if(new TextEncoder().encode(Z).byteLength>F.maxBytes)throw TypeError(`${J} exceeds ${F.maxBytes} bytes`);return Y}function K0(G,F,J="Plugin API value"){if("oneOf"in G){let Y=[];for(let Z of G.oneOf)try{Y.push(K0(Z,F,J))}catch{}if(Y.length!==1)throw TypeError(`${J} must match exactly one schema variant`);return Y[0]}if("const"in G){if(F!==G.const)throw TypeError(`${J} must equal ${String(G.const)}`);return F}if("type"in G&&G.type==="none"){if(F!==void 0)throw TypeError(`${J} does not accept a value`);return}if("type"in G&&G.type==="null"){if(F!==null)throw TypeError(`${J} must be null`);return null}if("type"in G&&G.type==="boolean"){if(typeof F!=="boolean")throw TypeError(`${J} must be boolean`);return F}if("type"in G&&(G.type==="number"||G.type==="integer")){if(typeof F!=="number"||!Number.isFinite(F)||G.type==="integer"&&!Number.isSafeInteger(F)||G.minimum!==void 0&&FG.maxLength||G.controlCharacters===!1&&/[\u0000-\u001f\u007f]/u.test(F)||G.enum!==void 0&&!G.enum.includes(F)||G.prefix!==void 0&&!F.startsWith(G.prefix)||!U1(F,G.refinement))throw TypeError(`${J} must satisfy its bounded string contract`);return F}if("type"in G&&G.type==="array"){if(!Array.isArray(F)||F.lengthG.maxItems)throw TypeError(`${J} must satisfy its bounded array contract`);let Y=F.map((Z,_)=>K0(G.items,Z,`${J}[${_}]`));if(G.uniqueBy!==void 0){let Z=Y.map((_)=>{let K=q0(_,`${J} unique item`)[G.uniqueBy];if(typeof K!=="string"&&typeof K!=="number")throw TypeError(`${J} unique identity is invalid`);return`${typeof K}:${String(K)}`});if(new Set(Z).size!==Z.length)throw TypeError(`${J} contains duplicate ${G.uniqueBy}`)}return Y}if("type"in G&&G.type==="json-object")return W1(F,G,J);if(!("properties"in G))throw TypeError(`${J} has an unsupported schema`);let Q=q0(F,J),X=new Set(Object.keys(G.properties));if(G.required.some((Y)=>!Object.prototype.hasOwnProperty.call(Q,Y))||Object.keys(Q).some((Y)=>!X.has(Y)))throw TypeError(`${J} contains unsupported or missing fields`);return Object.fromEntries(Object.entries(Q).map(([Y,Z])=>[Y,K0(G.properties[Y],Z,`${J}.${Y}`)]))}function k0(G,F){if("oneOf"in G){let J=G.oneOf.map((Z)=>k0(Z,F)),Q=J.filter((Z)=>Z.type==="object");if(Q.length===0&&J.some((Z)=>Z.type==="none"))return{type:"none"};if(Q.length===0)throw TypeError(`${F} is not an object schema`);let X=new Set(Q.flatMap(({required:Z,optional:_})=>[...Z,..._])),Y=[...X].filter((Z)=>Q.every((_)=>_.required.includes(Z))).sort();return{additionalProperties:!1,optional:[...X].filter((Z)=>!Y.includes(Z)).sort(),required:Y,type:"object"}}if("type"in G&&G.type==="none")return{type:"none"};if(!("properties"in G))throw TypeError(`${F} is not an object schema`);return{additionalProperties:!1,optional:Object.keys(G.properties).filter((J)=>!G.required.includes(J)).sort(),required:[...G.required].sort(),type:"object"}}var I0=Object.freeze(Object.keys(F0).sort()),j1=Object.freeze(Object.fromEntries(I0.map((G)=>{let F=F0[G],J=k0(F.result.schema,`Plugin API ${G} result`);if(J.type!=="object")throw TypeError(`Plugin API ${G} result must be an object`);return[G,{params:k0(F.request.schema,`Plugin API ${G} params`),request:F.request,response:F.result,result:J}]})));function V1(G,F){return K0(F0[G].request.schema,F,`Plugin API ${G} params`)}function L1(G,F){return K0(F0[G].result.schema,F,`Plugin API ${G} result`)}var k=[{code:"stale-context",description:"The bound Project, Canvas, node, or connection changed before the call completed.",recoverable:!0}],q=[{code:"permission-denied",description:"The installed Plugin principal does not currently hold the required grant.",recoverable:!1}],o0=[{code:"resource-unavailable",description:"The authoritative Project resource is missing, changed, or cannot be read safely.",recoverable:!0}],r0=[{code:"partial-success",description:"A user-visible Project file was published, but the requested Canvas commit did not complete; retry is unsafe.",recoverable:!1}],U0=uF(rF("1.0.0",[H({id:"host.context.get",completion:"cancelable",grant:null,scope:"connection",sideEffect:"read",errors:k,docs:{summary:"Read the bounded context attached to the current Plugin connection.",description:"Returns only renderer-safe identifiers and feature metadata for the exact live connection; it grants no additional authority.",request:"No parameters.",response:"The current Plugin, Project, Canvas, node, and negotiated Host API context when present."}}),H({id:"canvas.inputs.list",completion:"cancelable",grant:"canvas.connectedInputs.read",scope:"own-node",sideEffect:"read",errors:[...k,...q],docs:{summary:"List direct incoming inputs of the owning Plugin node.",description:"Derives pathless input metadata from authoritative direct incoming Canvas edges and never reads resource bytes.",request:"No parameters; the owning node comes from the bound connection.",response:"A bounded list of direct incoming input descriptors and opaque input keys."}}),H({id:"canvas.inputs.open",completion:"cancelable",grant:"canvas.connectedMedia.stream",scope:"own-node",sideEffect:"read",errors:[...k,...q,...o0],docs:{summary:"Open a bounded stream for one previously listed direct input.",description:"Opens host-owned access to the exact authoritative input after topology and resource identity are revalidated.",request:"`{ inputKey }`, using an opaque key returned by canvas.inputs.list.",response:"A connection-bound stream descriptor and safe media metadata.",remarks:"Call canvas.inputs.close when the stream is no longer needed."}}),H({id:"canvas.inputs.close",completion:"cancelable",grant:"canvas.connectedMedia.stream",scope:"own-node",sideEffect:"write",errors:[...k,...q],docs:{summary:"Close one connection-bound input stream.",description:"Releases a stream created by canvas.inputs.open without changing Canvas or Project state.",request:"The stream handle returned by canvas.inputs.open.",response:"An acknowledgement; closing an already closed handle is idempotent."}}),H({id:"canvas.node.get",completion:"cancelable",grant:"canvas.node.read",scope:"own-node",sideEffect:"read",errors:[...k,...q],docs:{summary:"Read the owning Plugin node projection.",description:"Returns a bounded renderer-safe projection of the exact node bound to the connection.",request:"No parameters; the owning node comes from the bound connection.",response:"The owning node identity, revision, geometry, and Plugin state projection."}}),H({id:"canvas.node.state.replace",completion:"commit-preserving",grant:"canvas.node.write",scope:"own-node",sideEffect:"write",errors:[...k,...q],docs:{summary:"Replace the owning node's bounded Plugin state.",description:"Commits only the namespaced Plugin state through the authoritative Canvas application service with revision checks.",request:"`{ state }`, where state is a bounded JSON value.",response:"`{ updated: true }` after the authoritative state replacement commits."}}),H({id:"canvas.resource.image.create",completion:"commit-preserving",grant:"canvas.image.write",scope:"own-node",sideEffect:"write",errors:[...k,...q,...r0],docs:{summary:"Create a Project-backed Canvas image through the host lifecycle.",description:"Admits bounded image content as a user-visible Project resource and commits its Canvas reference without exposing native paths.",request:"`{ dataUrl, name }`, containing a bounded validated image data URL and safe file name.",response:"The created renderer-safe image result after Project publication and Canvas commit."}}),H({id:"project.file.text.read",completion:"cancelable",grant:"project.files.read",scope:"project",sideEffect:"read",errors:[...k,...q],docs:{summary:"Read one bounded UTF-8 Project file.",description:"Reads through the scoped Project Files capability using a normalized Project-relative path and never exposes a native path.",request:"`{ path }`, using a normalized Project-relative portable path.",response:"The bounded UTF-8 file text."}}),H({id:"agent.prompt",completion:"commit-preserving",grant:"agent.prompt",scope:"connection",sideEffect:"execute",errors:[...k,...q],docs:{summary:"Submit a bounded prompt through the host Agent capability.",description:"Uses the current host-owned Agent context; it does not grant direct OpenCode, filesystem, model, or credential access.",request:"`{ text }`, containing the bounded prompt text.",response:"`{ text }`, containing the bounded host acknowledgement."}}),H({id:"generation.tools.list",completion:"cancelable",grant:"generation.execute",scope:"plugin",sideEffect:"read",errors:q,docs:{summary:"List generation tools available to the installed Plugin principal.",description:"Returns normalized tool metadata derived from active verified contributions without exposing executable paths or credentials.",request:"Optional `{ output }` modality filter; omitting params lists every admitted modality.",response:"A bounded list of available generation tools and their public input contracts."}}),H({id:"generation.execute",completion:"commit-preserving",grant:"generation.execute",scope:"plugin",sideEffect:"execute",errors:[...k,...q,...o0,...r0],docs:{summary:"Execute one selected generation tool through the shared host executor.",description:"Revalidates the active Plugin, authorized executable, inputs, cancellation, and live resource guards immediately before execution.",request:"`{ output?, prompt, references?, resultMode?, toolId? }`, validated against the selected tool.",response:"The bounded selected tool result, created node ids, authoritative revision, and warnings."}}),H({id:"projects.list",completion:"cancelable",audience:["web-plugin","companion"],grant:"projects.read",scope:"plugin",sideEffect:"read",errors:q,docs:{summary:"List Projects visible to the installed Plugin principal.",description:"Returns portable Project identities and display metadata without native paths or private Project state.",request:"No parameters.",response:"A bounded list of renderer-safe Project summaries."}}),H({id:"canvas.catalog.list",completion:"cancelable",audience:["web-plugin","companion"],grant:"canvas.catalog.read",scope:"project",sideEffect:"read",errors:[...k,...q],docs:{summary:"List Canvas catalog entries for one authorized Project.",description:"Reads the Project-owned Canvas catalog without selecting a Project or Canvas in the Workbench.",request:"`{ projectId }`, naming one explicit portable Project.",response:"A bounded list of portable Canvas catalog entries."}}),H({id:"canvas.document.get",completion:"cancelable",audience:["web-plugin","companion"],grant:"canvas.document.read",scope:"canvas",sideEffect:"read",errors:[...k,...q],docs:{summary:"Read one authorized Canvas document projection.",description:"Returns a bounded portable structure or geometry projection from Main's authoritative Canvas application service.",request:"`{ ref, projection }`, using an explicit portable Project/Canvas reference and supported projection.",response:"The requested pathless document projection and authoritative revision."}}),H({id:"canvas.nodes.query",completion:"cancelable",audience:["web-plugin","companion"],grant:"canvas.document.read",scope:"canvas",sideEffect:"read",errors:[...k,...q],docs:{summary:"Query bounded node projections in one authorized Canvas.",description:"Executes a host-defined bounded query without exposing native paths or resource bytes.",request:"`{ ref, query }`, using an explicit portable Project/Canvas reference and bounded query.",response:"Matching node projections and the authoritative Canvas revision."}}),H({id:"canvas.transaction.execute",completion:"commit-preserving",audience:["web-plugin","companion"],grant:"canvas.document.write",scope:"canvas",sideEffect:"write",errors:[...k,...q],docs:{summary:"Commit one non-empty revision-bound Canvas transaction.",description:"Validates bounded commands against one authoritative revision and persists the accepted transaction atomically.",request:"`{ ref, expectedRevision, commands, transactionId }` with a bounded non-empty command list.",response:"The committed authoritative revision and bounded command results."}}),H({id:"canvas.events.subscribe",completion:"cancelable",audience:["web-plugin","companion"],grant:"canvas.events.subscribe",scope:"canvas",sideEffect:"subscribe",errors:[...k,...q],docs:{summary:"Subscribe to bounded events for one authorized Canvas.",description:"Creates a connection-scoped subscription; events are revisioned invalidations or safe projections, never native data.",request:"`{ ref }`, using an explicit portable Project/Canvas reference.",response:"A connection-bound subscription identifier."}}),H({id:"canvas.events.unsubscribe",completion:"cancelable",audience:["web-plugin","companion"],grant:"canvas.events.subscribe",scope:"canvas",sideEffect:"subscribe",errors:[...k,...q],docs:{summary:"Close one connection-bound Canvas event subscription.",description:"Releases a subscription created by canvas.events.subscribe without changing Canvas state.",request:"The subscription identifier returned by canvas.events.subscribe.",response:"An acknowledgement; closing an already closed subscription is idempotent."}})])),u0=U0.apis.map(({id:G})=>G).sort();if(u0.length!==I0.length||u0.some((G,F)=>G!==I0[F]))throw TypeError("Plugin API Catalog and portable method contracts are incomplete or inconsistent");var N1=U0.version,M0=Number(N1.split(".")[0]),NF=new Map(U0.apis.map((G)=>[G.id,G])),O1=new Set(NF.keys());function N0(G){return typeof G==="string"&&O1.has(G)}function OF(G){return NF.get(G)}var z1=/^[a-z][a-z0-9]*(?:\.[a-z][a-z0-9]*)+$/;function A1(G){return typeof G==="object"&&G!==null&&!Array.isArray(G)}function n0(G,F){if(!Array.isArray(G))throw TypeError(`${F} must be an array`);let J=[],Q=new Set;for(let X of G){if(typeof X!=="string"||!z1.test(X))throw TypeError(`${F} contains an invalid Plugin API id: ${String(X)}`);if(Q.has(X))throw TypeError(`${F} contains a duplicate Plugin API id: ${X}`);Q.add(X),J.push(X)}return J}function R1(G){let F=b0(G),J=[],Q=[];for(let X of F.required){if(!N0(X))throw TypeError(`Plugin API declaration contains an unknown Plugin API id: ${X}`);J.push(X)}for(let X of F.optional){if(!N0(X))throw TypeError(`Plugin API declaration contains an unknown Plugin API id: ${X}`);Q.push(X)}return Object.freeze({major:M0,required:Object.freeze(J),optional:Object.freeze(Q)})}function b0(G){if(!A1(G))throw TypeError("Plugin API declaration must be an object");if(Object.keys(G).some((Z)=>Z!=="major"&&Z!=="required"&&Z!=="optional"))throw TypeError("Plugin API declaration contains an unknown field");if(G.major!==M0)throw TypeError(`Plugin API declaration major must be ${M0}`);let J=n0(G.required,"Plugin API declaration required"),Q=n0(G.optional,"Plugin API declaration optional"),X=new Set(J),Y=Q.find((Z)=>X.has(Z));if(Y)throw TypeError(`Plugin API cannot be both required and optional: ${Y}`);return Object.freeze({major:M0,required:Object.freeze(J),optional:Object.freeze(Q)})}function E1(G,F){if(G.required.includes(F))return"required";if(G.optional.includes(F))return"optional";return}function t0(G,F){return E1(G,F)!==void 0}class zF extends Error{availability;constructor(G){super(`Plugin API ${G.id} is unavailable: ${G.reason}`);this.name="PluginApiUnavailableError",this.availability=G}}function T1(G,F){return typeof F==="string"&&OF(G).errors.some((J)=>J.code===F)}function B1(G,F){if(!F||typeof F!=="object"||Array.isArray(F))throw TypeError(`Plugin API ${G} failure must be an object`);let J=F;if(Object.keys(J).some((X)=>!["code","kind","message","recoverable"].includes(X))||!Object.prototype.hasOwnProperty.call(J,"code")||!Object.prototype.hasOwnProperty.call(J,"message")||!Object.prototype.hasOwnProperty.call(J,"recoverable")||J.kind!=="api"||!T1(G,J.code)||typeof J.message!=="string"||J.message.length<1||J.message.length>4096||typeof J.recoverable!=="boolean")throw TypeError(`Plugin API ${G} failure is invalid`);let Q=OF(G).errors.find(({code:X})=>X===J.code);if(J.recoverable!==Q.recoverable)throw TypeError(`Plugin API ${G} failure recoverability does not match the Catalog`);return Object.freeze({code:J.code,kind:"api",message:J.message,recoverable:J.recoverable})}var H1=/^[a-z][a-z0-9]*(?:\.[a-z][a-z0-9-]*)+$/,C1=/^[a-z][a-z0-9]*(?:[._-][a-z0-9]+)*$/,w1=/^[A-Za-z][A-Za-z0-9_-]{0,63}$/,P1=/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/,q1=new Set(["none","read","write","execute","subscribe"]),AF=128,k1=64,I1=8,g1=16384,x1=256;function d0(G){return typeof G==="string"&&G.length<=160&&H1.test(G)}function u(G,F){if(!G||typeof G!=="object"||Array.isArray(G))throw TypeError(`${F} must be an object`);let J=Object.getPrototypeOf(G);if(J!==Object.prototype&&J!==null)throw TypeError(`${F} must be a plain object`);return G}function d(G,F,J,Q){let X=new Set([...F,...J]);if(F.some((Y)=>!Object.prototype.hasOwnProperty.call(G,Y))||Object.keys(G).some((Y)=>!X.has(Y)))throw TypeError(`${Q} contains unsupported or missing fields`)}function i(G,F,J=2000){if(typeof G!=="string"||G.length<1||G.length>J||G!==G.trim()||/[\u0000-\u001f\u007f]/u.test(G))throw TypeError(`${F} must be a bounded, trimmed string`);return G}function j0(G,F,J){if(!Number.isSafeInteger(G)||Number(G)<0||Number(G)>J)throw TypeError(`${F} must be a bounded non-negative integer`);return Number(G)}function g0(G,F){if(typeof G!=="string"||!P1.test(G))throw TypeError(`${F} must be a strict semantic version`);return G}function f1(G,F){let J=G.split(".").map(Number),Q=F.split(".").map(Number);for(let X=0;X<3;X+=1){let Y=J[X]-Q[X];if(Y!==0)return Y}return 0}function x0(G,F,J){if(J>I1)throw TypeError(`${F} exceeds the schema depth limit`);let Q=u(G,F);if(Q.type==="null"||Q.type==="boolean")return d(Q,["type"],[],F),Object.freeze({type:Q.type});if(Q.type==="number"||Q.type==="integer"){d(Q,["type"],["minimum","maximum"],F);let{minimum:X,maximum:Y}=Q;if(X!==void 0&&(typeof X!=="number"||!Number.isFinite(X)))throw TypeError(`${F}.minimum must be finite`);if(Y!==void 0&&(typeof Y!=="number"||!Number.isFinite(Y)))throw TypeError(`${F}.maximum must be finite`);if(X!==void 0&&Y!==void 0&&X>Y)throw TypeError(`${F} minimum exceeds maximum`);return Object.freeze({type:Q.type,...X===void 0?{}:{minimum:X},...Y===void 0?{}:{maximum:Y}})}if(Q.type==="string"){if(!Object.prototype.hasOwnProperty.call(Q,"maxLength"))throw TypeError(`${F}.maxLength is required to keep values bounded`);d(Q,["type","maxLength"],["minLength","enum"],F);let X=j0(Q.maxLength,`${F}.maxLength`,g1),Y=Q.minLength===void 0?void 0:j0(Q.minLength,`${F}.minLength`,X),Z;if(Q.enum!==void 0){if(!Array.isArray(Q.enum)||Q.enum.length<1||Q.enum.length>128||Q.enum.some((_)=>typeof _!=="string"||_.length>X)||new Set(Q.enum).size!==Q.enum.length)throw TypeError(`${F}.enum must contain unique bounded strings`);Z=Object.freeze([...Q.enum])}return Object.freeze({type:"string",maxLength:X,...Y===void 0?{}:{minLength:Y},...Z===void 0?{}:{enum:Z}})}if(Q.type==="array"){d(Q,["type","items","maxItems"],["minItems"],F);let X=j0(Q.maxItems,`${F}.maxItems`,x1),Y=Q.minItems===void 0?void 0:j0(Q.minItems,`${F}.minItems`,X);return Object.freeze({type:"array",items:x0(Q.items,`${F}.items`,J+1),maxItems:X,...Y===void 0?{}:{minItems:Y}})}if(Q.type==="object"){if(d(Q,["type","properties","required","additionalProperties"],[],F),Q.additionalProperties!==!1)throw TypeError(`${F}.additionalProperties must be false`);let X=u(Q.properties,`${F}.properties`),Y=Object.keys(X);if(Y.length>k1)throw TypeError(`${F} has too many properties`);if(Y.some((_)=>!w1.test(_)))throw TypeError(`${F} contains an invalid property name`);if(!Array.isArray(Q.required)||Q.required.some((_)=>typeof _!=="string"||!Y.includes(_))||new Set(Q.required).size!==Q.required.length)throw TypeError(`${F}.required must contain unique declared properties`);let Z=Object.fromEntries(Y.sort().map((_)=>[_,x0(X[_],`${F}.properties.${_}`,J+1)]));return Object.freeze({type:"object",properties:Object.freeze(Z),required:Object.freeze([...Q.required].sort()),additionalProperties:!1})}throw TypeError(`${F}.type is unsupported`)}function O0(G,F){let J=x0(G,F,0);if(J.type!=="object")throw TypeError(`${F} must be a closed object schema`);return J}function h1(G,F){let J=u(G,F);d(J,["id","inputSchema","outputSchema","version"],[],F);let Q=i(J.id,`${F}.id`,160);if(!d0(Q))throw TypeError(`${F}.id is invalid`);let X=u(J.version,`${F}.version`);d(X,["minimum","maximumExclusive"],[],`${F}.version`);let Y=g0(X.minimum,`${F}.version.minimum`),Z=g0(X.maximumExclusive,`${F}.version.maximumExclusive`);if(f1(Y,Z)>=0)throw TypeError(`${F}.version must be a non-empty half-open interval`);return Object.freeze({id:Q,inputSchema:O0(J.inputSchema,`${F}.inputSchema`),outputSchema:O0(J.outputSchema,`${F}.outputSchema`),version:Object.freeze({minimum:Y,maximumExclusive:Z})})}function i0(G,F){if(!Array.isArray(G)||G.length>AF)throw TypeError(`${F} must be a bounded array`);let J=G.map((Q,X)=>h1(Q,`${F}[${X}]`)).sort((Q,X)=>Q.id.localeCompare(X.id));if(J.some((Q,X)=>X>0&&J[X-1].id===Q.id))throw TypeError(`${F} contains a duplicate capability id`);return Object.freeze(J)}function y1(G,F){let J=u(G,F);d(J,["id","version","operation","sideEffect","inputSchema","outputSchema","docs"],[],F);let Q=i(J.id,`${F}.id`,160);if(!d0(Q))throw TypeError(`${F}.id is invalid`);let X=i(J.operation,`${F}.operation`,128);if(!C1.test(X))throw TypeError(`${F}.operation is invalid`);if(!q1.has(J.sideEffect))throw TypeError(`${F}.sideEffect is invalid`);let Y=u(J.docs,`${F}.docs`);d(Y,["summary","request","response"],["remarks"],`${F}.docs`);let Z=Object.freeze({summary:i(Y.summary,`${F}.docs.summary`),request:i(Y.request,`${F}.docs.request`),response:i(Y.response,`${F}.docs.response`),...Y.remarks===void 0?{}:{remarks:i(Y.remarks,`${F}.docs.remarks`)}});return Object.freeze({id:Q,version:g0(J.version,`${F}.version`),operation:X,sideEffect:J.sideEffect,inputSchema:O0(J.inputSchema,`${F}.inputSchema`),outputSchema:O0(J.outputSchema,`${F}.outputSchema`),docs:Z})}function c1(G){let F=u(G,"Plugin capability declaration");if(d(F,["exports","imports"],[],"Plugin capability declaration"),!Array.isArray(F.exports)||F.exports.length>AF)throw TypeError("Plugin capability exports must be a bounded array");let J=F.exports.map((M,K)=>y1(M,`Plugin capability exports[${K}]`)).sort((M,K)=>M.id.localeCompare(K.id));if(J.some((M,K)=>K>0&&J[K-1].id===M.id))throw TypeError("Plugin capability exports contain a duplicate capability id");if(new Set(J.map((M)=>M.operation)).size!==J.length)throw TypeError("Plugin capability exports contain a duplicate provider operation");let Q=u(F.imports,"Plugin capability imports");d(Q,["required","optional"],[],"Plugin capability imports");let X=i0(Q.required,"Plugin required capability imports"),Y=i0(Q.optional,"Plugin optional capability imports"),Z=new Set(X.map(({id:M})=>M)),_=Y.find(({id:M})=>Z.has(M));if(_)throw TypeError(`Plugin capability import cannot be both required and optional: ${_.id}`);return Object.freeze({exports:Object.freeze(J),imports:Object.freeze({required:X,optional:Y})})}function f0(G,F,J,Q){if(G.type==="null"){if(F!==null)throw TypeError(`${J} must be null`);return}if(G.type==="boolean"){if(typeof F!=="boolean")throw TypeError(`${J} must be boolean`);return}if(G.type==="number"||G.type==="integer"){if(typeof F!=="number"||!Number.isFinite(F)||G.type==="integer"&&!Number.isSafeInteger(F))throw TypeError(`${J} must be a finite ${G.type==="integer"?"safe integer":"number"}`);if(G.minimum!==void 0&&FG.maximum)throw TypeError(`${J} exceeds maximum`);return}if(G.type==="string"){if(typeof F!=="string"||F.length<(G.minLength??0)||F.length>G.maxLength||G.enum!==void 0&&!G.enum.includes(F))throw TypeError(`${J} is not an admitted string`);return}if(!F||typeof F!=="object")throw TypeError(`${J} must be ${G.type}`);if(Q.has(F))throw TypeError(`${J} cannot be cyclic`);Q.add(F);try{if(G.type==="array"){if(!Array.isArray(F)||F.length<(G.minItems??0)||F.length>G.maxItems)throw TypeError(`${J} is not an admitted array`);F.forEach((Z,_)=>f0(G.items,Z,`${J}[${_}]`,Q));return}if(Array.isArray(F))throw TypeError(`${J} must be an object`);let X=Object.getPrototypeOf(F);if(X!==Object.prototype&&X!==null)throw TypeError(`${J} must be a plain object`);let Y=F;for(let Z of G.required)if(!Object.prototype.hasOwnProperty.call(Y,Z))throw TypeError(`${J}.${Z} is required`);for(let[Z,_]of Object.entries(Y)){let M=G.properties[Z];if(!M)throw TypeError(`${J} contains unsupported property: ${Z}`);f0(M,_,`${J}.${Z}`,Q)}}finally{Q.delete(F)}}function a0(G,F,J="Plugin capability value"){f0(G,F,J,new Set)}var b1=/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[A-Za-z-][0-9A-Za-z-]*)(?:\.(?:0|[1-9]\d*|\d*[A-Za-z-][0-9A-Za-z-]*))*))?(?:\+([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?$/,d1=/^(CON|PRN|AUX|NUL|COM[1-9¹²³]|LPT[1-9¹²³]|CONIN\$|CONOUT\$)$/i;function A(G,F){if(!G||typeof G!=="object"||Array.isArray(G))throw TypeError(`${F} must be an object`);let J=Object.getPrototypeOf(G);if(J!==Object.prototype&&J!==null)throw TypeError(`${F} must be a plain object`);return G}function R(G,F,J){let Q=new Set(F),X=Object.keys(G).find((Y)=>!Q.has(Y));if(X)throw TypeError(`${J} contains an unsupported field: ${X}`)}function E(G,F,J){if(typeof G!=="string"||G.length<1||G.length>J||G!==G.trim()||/[\u0000-\u001f\u007f]/u.test(G))throw TypeError(`${F} must be a bounded, trimmed string`);return G}function c(G,F,J,Q=!1){if(!Array.isArray(G)||G.length>J||Q&&G.length===0)throw TypeError(`${F} must be ${Q?"a non-empty ":"a "}bounded array with at most ${J} items`);return G}function RF(G){if(G&&typeof G==="object"&&!Object.isFrozen(G)){for(let F of Object.values(G))RF(F);Object.freeze(G)}return G}function v1(G){let F=E(G,"Plugin version",128);if(!b1.test(F))throw TypeError("Plugin version must be valid SemVer");return F}function R0(G){let F=G.split(".")[0]??"";if(!G||G.length>255||G==="."||G===".."||/[\\/:*?"<>|\u0000-\u001f\u007f]/u.test(G)||/[. ]$/u.test(G)||d1.test(F))throw TypeError(`Plugin path contains an invalid Windows filename: ${G}`);return G}function EF(G){let F=E(G,"Plugin id",80);if(!/^[a-z0-9]+(?:-[a-z0-9]+)*$/u.test(F))throw TypeError("Plugin id must use kebab-case");return R0(F),F}function X0(G,F="Plugin path"){let J=E(G,F,1024);if(J.includes("\\")||J.startsWith("/")||/^[A-Za-z]:/u.test(J)||J.startsWith("//"))throw TypeError(`${F} must be a portable relative path`);let Q=J.split("/");if(Q.some((X)=>!X||X==="."||X===".."))throw TypeError(`${F} must be a portable relative path`);return Q.forEach(R0),J}function T0(G,F,J){if(G===void 0)return;let Q=c(G,F,64).map((X)=>J(E(X,F,128)));if(new Set(Q).size!==Q.length)throw TypeError(`${F} contains duplicate values`);return Q}function Y0(G,F,J=80){let Q=E(G,F,J);if(!/^[a-z0-9]+(?:[._-][a-z0-9]+)*$/u.test(Q))throw TypeError(`${F} is invalid: ${Q}`);return Q}var l="convax.plugin-host/8",m1=K1,p1=M1,B0=1048576,l0=4194304,e0=16,s1=128,o1=64,V0=Math.ceil(m1/2),r1=/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/,u1=new Set(["not-declared","provider-missing","provider-incompatible","provider-ambiguous","self-provider","dependency-cycle","setup-required","disabled","recovering","contract-mismatch"]),TF=Object.freeze({canceled:{recoverable:!0},"contract-mismatch":{recoverable:!1},"depth-exceeded":{recoverable:!1},"duplicate-request":{recoverable:!1},"execution-failed":{recoverable:!1},"invalid-input":{recoverable:!1},"invalid-output":{recoverable:!1},overloaded:{recoverable:!0},"provider-unavailable":{recoverable:!0},"reentrant-call":{recoverable:!1}}),BF=new Set(Object.keys(TF)),HF=Object.freeze({canceled:{recoverable:!0},"internal-error":{recoverable:!1},"invalid-request":{recoverable:!1},overloaded:{recoverable:!0},"transport-closed":{recoverable:!0}}),CF=new Set(Object.keys(HF)),n1=new Set(U0.apis.flatMap((G)=>G.errors.map(({code:F})=>F)));function e(G){if(!G||typeof G!=="object"||Array.isArray(G))return;let F=Object.getPrototypeOf(G);return F===Object.prototype||F===null?G:void 0}function FF(G){let F=2;for(let J=0;J=55296&&Q<=57343){let X=G.charCodeAt(J+1);if(Q>=55296&&Q<=56319&&X>=56320&&X<=57343)F+=4,J+=1;else F+=6}else if(Q<128)F+=1;else if(Q<2048)F+=2;else F+=3}return F}function GF(G,F,J="Plugin Host message"){if(!Number.isSafeInteger(F)||F<1)throw TypeError(`${J} byte limit is invalid`);let Q=[{depth:0,value:G}],X=new WeakSet,Y=0,Z=0,_=(M)=>{if(Y+=M,Y>F)throw RangeError(`${J} exceeds ${F} bytes`)};while(Q.length>0){let M=Q.pop(),K=M.value;if(K===null){_(4);continue}if(typeof K==="string"){_(FF(K));continue}if(typeof K==="boolean"){_(K?4:5);continue}if(typeof K==="number"){if(!Number.isFinite(K))throw TypeError(`${J} must contain finite JSON numbers`);_(Object.is(K,-0)?1:String(K).length);continue}if(!K||typeof K!=="object")throw TypeError(`${J} must be a JSON value`);if(M.depth>o1||X.has(K))throw TypeError(`${J} must be a bounded acyclic JSON tree`);if(X.add(K),Array.isArray(K)){if(Z+=K.length,Z>V0)throw RangeError(`${J} exceeds ${V0} JSON entries`);if(_(2+Math.max(0,K.length-1)),Object.getOwnPropertySymbols(K).length>0)throw TypeError(`${J} arrays must not contain symbol properties`);let O=0;for(let V in K){if(!Object.prototype.hasOwnProperty.call(K,V))continue;if(!/^(0|[1-9]\d*)$/u.test(V)||Number(V)>=K.length)throw TypeError(`${J} arrays must contain only indexed entries`);let P=Object.getOwnPropertyDescriptor(K,V);if(!P?.enumerable||!("value"in P))throw TypeError(`${J} arrays must contain enumerable data properties`);O+=1,Q.push({depth:M.depth+1,value:P.value})}if(O!==K.length)throw TypeError(`${J} arrays must be dense JSON arrays`);continue}let D=Object.getPrototypeOf(K);if(D!==Object.prototype&&D!==null)throw TypeError(`${J} must contain plain JSON objects`);if(Object.getOwnPropertySymbols(K).length>0)throw TypeError(`${J} must not contain symbol properties`);_(2);let W=0;for(let O in K){if(!Object.prototype.hasOwnProperty.call(K,O))continue;let V=Object.getOwnPropertyDescriptor(K,O);if(!V?.enumerable||!("value"in V))throw TypeError(`${J} objects must contain enumerable data properties`);if(W+=1,Z+=1,Z>V0)throw RangeError(`${J} exceeds ${V0} JSON entries`);_((W===1?0:1)+FF(O)+1),Q.push({depth:M.depth+1,value:V.value})}}return Y}function r(G,F,J=[]){let Q=new Set([...F,...J]);return F.every((X)=>Object.prototype.hasOwnProperty.call(G,X))&&Object.keys(G).every((X)=>Q.has(X))}function wF(G){return typeof G==="string"&&G.length>0&&G.length<=s1&&G===G.trim()&&!/[\u0000-\u001f\u007f]/u.test(G)}function t1(G){return typeof G==="string"&&G.length>0&&G.length<=128&&G===G.trim()&&!/[\u0000-\u001f\u007f]/u.test(G)}function PF(G){let F=e(G);if(!F||!r(F,["pluginId","protocol","type"])||F.protocol!==l||F.type!=="connect")return!1;try{return EF(F.pluginId),!0}catch{return!1}}function i1(G){let F=e(G);if(!F||F.protocol!==l||F.type!=="response"||!wF(F.id))return!1;if(F.ok===!0)return r(F,["id","ok","protocol","result","type"]);if(F.ok!==!1||!r(F,["error","id","ok","protocol","type"]))return!1;let J=e(F.error);return Boolean(J&&r(J,["code","kind","message","recoverable"])&&typeof J.code==="string"&&(J.kind==="api"&&n1.has(J.code)||J.kind==="capability"&&BF.has(J.code)||J.kind==="protocol"&&CF.has(J.code))&&typeof J.message==="string"&&J.message.length>0&&J.message.length<=4096&&typeof J.recoverable==="boolean")}function a1(G){let F=e(G);return Boolean(F&&r(F,["command","protocol","type"],["params"])&&F.protocol===l&&F.type==="command"&&t1(F.command))}function l1(G){let F=e(G);if(!F||typeof F.available!=="boolean")throw TypeError("Plugin capability availability must be a closed object");let J=F.requirement;if(J!=="required"&&J!=="optional")throw TypeError("Plugin capability availability requirement is invalid");if(!d0(F.capabilityId))throw TypeError("Plugin capability availability id is invalid");if(F.available){if(!r(F,["available","capabilityId","requirement","version"])||typeof F.version!=="string"||!r1.test(F.version))throw TypeError("Available Plugin capability result is invalid");return Object.freeze({available:!0,capabilityId:F.capabilityId,requirement:J,version:F.version})}if(!r(F,["available","capabilityId","reason","recoverable","requirement"])||typeof F.reason!=="string"||!u1.has(F.reason)||typeof F.recoverable!=="boolean")throw TypeError("Unavailable Plugin capability result is invalid");return Object.freeze({available:!1,capabilityId:F.capabilityId,reason:F.reason,recoverable:F.recoverable,requirement:J})}function e1(G){let F=e(G);if(!F||!r(F,["code","kind","message","recoverable"])||F.kind!=="capability"||typeof F.code!=="string"||!BF.has(F.code)||typeof F.message!=="string"||F.message.length<1||F.message.length>4096||typeof F.recoverable!=="boolean")throw TypeError("Plugin capability failure is invalid");let J=F.code;if(F.recoverable!==TF[J].recoverable)throw TypeError("Plugin capability failure recoverability is invalid");return Object.freeze({code:J,kind:"capability",message:F.message,recoverable:F.recoverable})}function qF(G){let F=e(G);if(!F||!r(F,["code","kind","message","recoverable"])||F.kind!=="protocol"||typeof F.code!=="string"||!CF.has(F.code)||typeof F.message!=="string"||F.message.length<1||F.message.length>4096||typeof F.recoverable!=="boolean")throw TypeError("Plugin Host protocol failure is invalid");let J=F.code;if(F.recoverable!==HF[J].recoverable)throw TypeError("Plugin Host protocol failure recoverability is invalid");return Object.freeze({code:J,kind:"protocol",message:F.message,recoverable:F.recoverable})}var F6=["download","edit","open","play","refresh","settings","sparkles","upload"],kF=/^[a-z][a-z0-9]*(?:[._-][a-z0-9]+)*$/,G6=/^[a-z][a-z0-9]*(?:[._-][a-z0-9]+)*$/,J6=/^[a-z][a-z0-9]*(?:[._-][a-z0-9]+)*$/,Q6=128,JF=128,QF=1e4;function X6(G){return Boolean(G)&&typeof G==="object"&&!Array.isArray(G)}function S0(G,F){if(!X6(G))throw TypeError(`${F} must be an object`);let J=Object.getPrototypeOf(G);if(J!==Object.prototype&&J!==null)throw TypeError(`${F} must be a plain object`);return G}function D0(G,F,J,Q){let X=new Set([...F,...J]);if(F.some((Y)=>!Object.prototype.hasOwnProperty.call(G,Y))||Object.keys(G).some((Y)=>!X.has(Y)))throw TypeError(`${Q} contains unsupported or missing fields`)}function z0(G,F,J){if(typeof G!=="string"||G.length<1||G.length>J||G!==G.trim()||/[\u0000-\u001f\u007f]/u.test(G))throw TypeError(`${F} must be a bounded, trimmed string`);return G}function A0(G,F,J,Q){let X=z0(G,F,Q);if(!J.test(X))throw TypeError(`${F} must be a stable Plugin-local id`);return X}function Y6(G,F){if(!Number.isSafeInteger(G)||Number(G)<-QF||Number(G)>QF)throw TypeError(`${F} must be a bounded safe integer`);return Number(G)}function Z6(G,F){let J=S0(G,F);return D0(J,["default"],["zh-CN"],F),Object.freeze({default:z0(J.default,`${F}.default`,120),...J["zh-CN"]===void 0?{}:{"zh-CN":z0(J["zh-CN"],`${F}.zh-CN`,120)}})}function _6(G){return F6.some((F)=>F===G)}function $6(G,F){let J=`Plugin UI commands[${F}]`,Q=S0(G,J);D0(Q,["id","title","target"],["icon"],J);let X=S0(Q.target,`${J}.target`);if(X.type!=="renderer-message")throw TypeError(`${J}.target.type must be renderer-message`);D0(X,["type","message"],[],`${J}.target`);let Y=Q.icon;if(Y!==void 0&&!_6(Y))throw TypeError(`${J}.icon must be a supported Host icon token`);return Object.freeze({id:A0(Q.id,`${J}.id`,kF,128),title:Z6(Q.title,`${J}.title`),target:Object.freeze({type:"renderer-message",message:z0(X.message,`${J}.target.message`,128)}),...Y===void 0?{}:{icon:Y}})}function IF(G,F,J,Q){let X=S0(G,F);return D0(X,J,Q,F),{input:X,id:A0(X.id,`${F}.id`,G6,128),command:A0(X.command,`${F}.command`,kF,128),...X.order===void 0?{}:{order:Y6(X.order,`${F}.order`)}}}function K6(G,F){let{input:J,...Q}=IF(G,`Plugin UI toolbar[${F}]`,["id","command"],["order"]);return Object.freeze(Q)}function M6(G,F){let J=`Plugin UI menus[${F}]`,Q=IF(G,J,["id","command","placement"],["group","order"]);if(Q.input.placement!=="overflow")throw TypeError(`${J}.placement must be overflow`);let X=Q.input.group===void 0?void 0:A0(Q.input.group,`${J}.group`,J6,64),{input:Y,...Z}=Q;return Object.freeze({...Z,placement:"overflow",...X===void 0?{}:{group:X}})}function H0(G,F,J){if(!Array.isArray(G)||G.length>J)throw TypeError(`${F} must be a bounded array`);return G}function C0(G,F){let J=new Set;for(let Q of G){if(J.has(Q.id))throw TypeError(`${F} contains a duplicate id: ${Q.id}`);J.add(Q.id)}}function XF(G,F){let J=new Set;for(let Q of G){if(J.has(Q.command))throw TypeError(`${F} contains a duplicate command reference: ${Q.command}`);J.add(Q.command)}}function S6(G){let F=S0(G,"Plugin Canvas UI contribution");D0(F,[],["commands","menus","toolbar"],"Plugin Canvas UI contribution");let J=Object.freeze(H0(F.commands===void 0?[]:F.commands,"Plugin UI commands",Q6).map($6)),Q=Object.freeze(H0(F.menus===void 0?[]:F.menus,"Plugin UI menus",JF).map(M6)),X=Object.freeze(H0(F.toolbar===void 0?[]:F.toolbar,"Plugin UI toolbar",JF).map(K6));C0(J,"Plugin UI commands"),C0(Q,"Plugin UI menus"),C0(X,"Plugin UI toolbar");let Y=new Set(Q.map((W)=>W.id)),Z=X.find((W)=>Y.has(W.id));if(Z)throw TypeError(`Plugin UI placements contain a duplicate id: ${Z.id}`);XF(Q,"Plugin UI menus"),XF(X,"Plugin UI toolbar");let _=new Set(J.map((W)=>W.id)),M=[...Q,...X].find((W)=>!_.has(W.command));if(M)throw TypeError(`Plugin UI placement references an unknown command: ${M.command}`);let K=new Set([...Q,...X].map((W)=>W.command)),D=J.find((W)=>!K.has(W.id));if(D)throw TypeError(`Plugin UI command has no owning-node placement: ${D.id}`);return Object.freeze({commands:J,menus:Q,toolbar:X})}var D6=["time-point","time-range","crop-region","confirmation","immediate"];function U6(G){return D6.some((F)=>F===G)}function W6(G,F){if(G==="image"||G==="video")return G;throw TypeError(`${F} target must be image or video`)}function YF(G,F){if(!Number.isSafeInteger(G)||Number(G)<1||Number(G)>8192)throw TypeError(`${F} must be an integer between 1 and 8192`);return Number(G)}function j6(G){let F=A(G,"Canvas renderer contribution");if(R(F,["create","extensions","height","mimeTypes","nodeKinds","width"],"Canvas renderer contribution"),F.create!==void 0&&typeof F.create!=="boolean")throw TypeError("Canvas renderer create must be a boolean");let J=T0(F.extensions,"Canvas renderer extensions",(Y)=>{let Z=Y.toLowerCase();if(!/^\.[a-z0-9][a-z0-9._+-]{0,31}$/u.test(Z))throw TypeError(`Invalid Canvas renderer extension: ${Y}`);return Z}),Q=T0(F.mimeTypes,"Canvas renderer MIME types",(Y)=>{let Z=Y.toLowerCase();if(!/^[a-z0-9][a-z0-9!#$&^_.+-]*\/[a-z0-9][a-z0-9!#$&^_.+-]*$/u.test(Z))throw TypeError(`Invalid Canvas renderer MIME type: ${Y}`);return Z}),X=T0(F.nodeKinds,"Canvas renderer node kinds",(Y)=>{if(!/^[a-z][a-z0-9]*(?:[._-][a-z0-9]+)*$/u.test(Y))throw TypeError(`Invalid Canvas renderer node kind: ${Y}`);return Y});if(F.create!==!0&&!J?.length&&!Q?.length&&!X?.length)throw TypeError("Canvas renderer must be creatable or match an extension, MIME type, or node kind");return{...F.create===void 0?{}:{create:F.create},...J===void 0?{}:{extensions:J},...F.height===void 0?{}:{height:YF(F.height,"Canvas renderer height")},...Q===void 0?{}:{mimeTypes:Q},...X===void 0?{}:{nodeKinds:X},...F.width===void 0?{}:{width:YF(F.width,"Canvas renderer width")}}}function L0(G,F,J){let Q=A(G,F);return R(Q,["default","zh-CN"],F),{default:E(Q.default,`${F} default`,J),...Q["zh-CN"]===void 0?{}:{"zh-CN":E(Q["zh-CN"],`${F} zh-CN`,J)}}}function V6(G){let F=c(G,"Canvas selection actions",32,!0).map((J,Q)=>{let X=`Canvas selection action ${Q}`,Y=A(J,X);if(Y.action!==void 0){R(Y,["action","description","id","target","title"],X);let D=Y0(Y.id,`${X} id`);if(Y.target!=="video")throw TypeError(`${X} target must be video`);let W=A(Y.action,`${X} action`);if(R(W,["connect","type"],`${X} action`),W.type!=="materialize-own-plugin-node"||W.connect!=="selection-to-created")throw TypeError(`${X} materialization action is not supported`);return{action:{connect:"selection-to-created",type:"materialize-own-plugin-node"},description:L0(Y.description,`${X} description`,2000),id:D,target:"video",title:L0(Y.title,`${X} title`,120)}}R(Y,["description","editor","id","presentation","steps","target","title"],X);let Z=Y0(Y.id,`${X} id`),_=W6(Y.target,X);if(!U6(Y.editor))throw TypeError(`${X} editor is not supported`);let M=Y.editor;if(M==="immediate"!==(_==="image"&&Y.presentation==="cutout-scan")||Y.presentation!==void 0&&Y.presentation!=="cutout-scan")throw TypeError(`${X} immediate editor requires image target and cutout-scan presentation`);let K=c(Y.steps,`${X} steps`,16,!0).map((D,W)=>{let O=`${X} step ${W}`,V=A(D,O);return R(V,["tool"],O),{tool:Y0(V.tool,`${O} tool`)}});if(M!=="confirmation"&&K.length!==1)throw TypeError(`${X} editor requires exactly one step`);return{description:L0(Y.description,`${X} description`,2000),editor:M,id:Z,...Y.presentation===void 0?{}:{presentation:"cutout-scan"},steps:K,target:_,title:L0(Y.title,`${X} title`,120)}});if(new Set(F.map((J)=>J.id)).size!==F.length)throw TypeError("Canvas selection actions contain duplicate ids");return F}function L6(G){let F=A(G,"Canvas contributions");R(F,["commands","menus","renderer","selectionActions","toolbar"],"Canvas contributions");let J=S6({...F.commands===void 0?{}:{commands:F.commands},...F.menus===void 0?{}:{menus:F.menus},...F.toolbar===void 0?{}:{toolbar:F.toolbar}});return{...F.commands===void 0?{}:{commands:J.commands},...F.menus===void 0?{}:{menus:J.menus},...F.renderer===void 0?{}:{renderer:j6(F.renderer)},...F.selectionActions===void 0?{}:{selectionActions:V6(F.selectionActions)},...F.toolbar===void 0?{}:{toolbar:J.toolbar}}}var N6=["text","image","video","audio"],gF=["reference_image","reference_video","first_frame","last_frame","audio","text"],O6=new Set(N6),z6=new Set(gF),A6=/^[a-z][a-z0-9_]{0,63}$/;function R6(G,F){let Q=c(G,F,gF.length).map((X)=>{if(typeof X!=="string"||!z6.has(X))throw TypeError(`${F} contain an unsupported or duplicate role`);return X});if(new Set(Q).size!==Q.length)throw TypeError(`${F} contain an unsupported or duplicate role`);return Q}function E6(G){let F=A(G,"Generation contribution");if(R(F,["models","tools"],"Generation contribution"),!Object.prototype.hasOwnProperty.call(F,"models"))throw TypeError("convax.plugin/8 generation models must be declared explicitly");let J=c(F.tools,"Generation tools",64,!0).map((_,M)=>{let K=`Generation tool ${M}`,D=A(_,K);R(D,["acceptedInputs","delivery","description","id","inputBinding","output","recovery","title"],K);let W=Y0(D.id,`${K} id`);if(typeof D.output!=="string"||!O6.has(D.output))throw TypeError(`${K} output is not supported`);if(D.delivery!==void 0&&D.delivery!=="canvas"&&D.delivery!=="return")throw TypeError(`${K} delivery is not supported`);if(D.delivery==="return"&&D.output!=="text")throw TypeError(`${K} return delivery requires text output`);let O=R6(D.acceptedInputs,`${K} acceptedInputs`);if(D.inputBinding!==void 0&&D.inputBinding!=="direct-incoming")throw TypeError(`${K} input binding is not supported`);if(D.inputBinding==="direct-incoming"&&O.length===0)throw TypeError(`${K} direct-incoming input binding requires accepted inputs`);let V;if(D.recovery!==void 0){let P=A(D.recovery,`${K} recovery`);if(R(P,["mode","schema"],`${K} recovery`),P.schema!=="convax.generation-lro/1"||P.mode!=="long-running-operation")throw TypeError(`${K} recovery contract is not supported`);V={mode:"long-running-operation",schema:"convax.generation-lro/1"}}return{acceptedInputs:O,...D.delivery===void 0?{}:{delivery:D.delivery},description:E(D.description,`${K} description`,2000),id:W,...D.inputBinding===void 0?{}:{inputBinding:D.inputBinding},output:D.output,...V===void 0?{}:{recovery:V},title:E(D.title,`${K} title`,120)}});if(new Set(J.map((_)=>_.id)).size!==J.length)throw TypeError("Generation tools contain duplicate ids");let Q=c(F.models,"Generation models",J.length).map((_,M)=>{let K=`Generation model ${M}`,D=A(_,K);return R(D,["name","tool"],K),{name:E(D.name,`${K} name`,120),tool:Y0(D.tool,`${K} tool`)}});if(new Set(Q.map((_)=>_.tool)).size!==Q.length)throw TypeError("Generation models contain duplicate tool references");let X=new Set(Q.map((_)=>_.tool)),Y=J.find((_)=>_.delivery==="return"&&X.has(_.id));if(Y)throw TypeError(`Generation model cannot reference a return-delivery operation: ${Y.id}`);let Z=J.find((_)=>_.inputBinding!==void 0&&X.has(_.id));if(Z)throw TypeError(`Generation model cannot reference an input-bound operation: ${Z.id}`);return{models:Q,tools:J}}function T6(G){let F=c(G,"Agent tools",32,!0).map((J,Q)=>{let X=`Agent tool ${Q}`,Y=A(J,X);R(Y,["id","tool"],X);let Z=E(Y.id,`${X} id`,64);if(!A6.test(Z))throw TypeError(`${X} id must use lower snake_case`);return{id:Z,tool:Y0(Y.tool,`${X} generation tool`)}});if(new Set(F.map((J)=>J.id)).size!==F.length)throw TypeError("Agent tools contain duplicate ids");if(new Set(F.map((J)=>J.tool)).size!==F.length)throw TypeError("Agent tools contain duplicate generation tool references");return F}function B6(G){let F=A(G,"Agent remote MCP contribution");if(R(F,["headers","oauth","type","url"],"Agent remote MCP contribution"),F.type!=="remote")throw TypeError("Agent MCP type must be remote");let J=E(F.url,"Agent remote MCP URL",2048);try{let X=new URL(J);if(X.protocol!=="https:"||X.username!==""||X.password!==""||X.hash!=="")throw TypeError()}catch{throw TypeError("Agent remote MCP URL must be an absolute HTTPS URL without credentials or a fragment")}if(F.oauth!==void 0&&F.oauth!=="auto"&&F.oauth!=="none")throw TypeError("Agent remote MCP oauth must be auto or none");let Q;if(F.headers!==void 0){let X=A(F.headers,"Agent remote MCP headers"),Y=Object.entries(X);if(Y.length>16)throw TypeError("Agent remote MCP headers must contain at most 16 entries");let Z=new Set;Q={};for(let[_,M]of Y){if(!/^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/u.test(_))throw TypeError(`Agent remote MCP header name is invalid: ${_}`);let K=_.toLowerCase();if(Z.has(K))throw TypeError(`Agent remote MCP headers contain a duplicate name: ${_}`);if(K==="authorization"||K==="cookie"||K==="proxy-authorization")throw TypeError(`Agent remote MCP header is not allowed: ${_}`);let D=E(M,`Agent remote MCP header ${_}`,2048);if(/\{(?:env|file):/iu.test(D)||/\$\{[^}]*\}/u.test(D))throw TypeError(`Agent remote MCP header ${_} must be a literal value`);Z.add(K),Q[_]=D}}return{...Q===void 0?{}:{headers:Q},oauth:F.oauth==="none"?"none":"auto",type:"remote",url:J}}function H6(G){let F=A(G,"Agent contribution");R(F,["mcp","tools"],"Agent contribution");let J=F.tools===void 0?void 0:T6(F.tools),Q=F.mcp===void 0?void 0:B6(F.mcp);if(J===void 0&&Q===void 0)throw TypeError("Agent contribution must declare tools or mcp");return{...Q===void 0?{}:{mcp:Q},...J===void 0?{}:{tools:J}}}function C6(G){let F=new Map(G.generation?.tools.map((Q)=>[Q.id,Q])??[]),J=new Set(G.generation?.models.map((Q)=>Q.tool)??[]);for(let Q of J)if(!F.has(Q))throw TypeError(`Generation model references an unknown tool: ${Q}`);for(let Q of G.agent?.tools??[]){if(!F.has(Q.tool))throw TypeError(`Agent tool references an unknown generation tool: ${Q.tool}`);if(J.has(Q.tool))throw TypeError(`Agent tool must reference an operation, not a generation model: ${Q.tool}`)}for(let Q of G.selectionActions??[]){if(!("steps"in Q))continue;for(let X of Q.steps){let Y=F.get(X.tool);if(!Y)throw TypeError(`Canvas selection action references an unknown generation tool: ${X.tool}`);if(J.has(X.tool))throw TypeError(`Canvas selection action must reference an operation, not a generation model: ${X.tool}`);if(Y.inputBinding!==void 0)throw TypeError(`Canvas selection action cannot reference an input-bound operation: ${X.tool}`);let Z=Q.target==="image"?"reference_image":"reference_video";if(!Y.acceptedInputs.includes(Z))throw TypeError(`Canvas ${Q.target} selection action tool must accept ${Z}: ${X.tool}`);if(Y.delivery==="return"){if(Q.editor!=="confirmation")throw TypeError(`Canvas return-delivery operation requires a confirmation editor: ${X.tool}`);if(Q.steps.length!==1)throw TypeError(`Canvas return-delivery operation requires exactly one step: ${X.tool}`);if(Y.output!=="text")throw TypeError(`Canvas return-delivery operation must return text: ${X.tool}`)}else if(Q.target==="image"&&(Q.editor!=="immediate"||Q.presentation!=="cutout-scan"||Q.steps.length!==1||Y.output!=="image"))throw TypeError(`Canvas image output requires one immediate image operation with cutout-scan presentation: ${X.tool}`)}}}var xF=["authorize","reauthorize","authorization.cancel","checkout","sign_out"],w6=new Set(xF);function P6(G){let F=A(G,"Service contribution");R(F,["actions"],"Service contribution");let J=c(F.actions,"Service actions",xF.length).map((Q)=>{if(typeof Q!=="string"||!w6.has(Q))throw TypeError("Service actions contain an unsupported or duplicate action");return Q});if(new Set(J).size!==J.length)throw TypeError("Service actions contain an unsupported or duplicate action");return{actions:J}}function q6(G){let F=A(G,"LLM contribution");R(F,["modelCatalog","models","provider"],"LLM contribution");let J=A(F.provider,"LLM provider");R(J,["id","name"],"LLM provider");let Q=E(J.id,"LLM provider id",80);if(!/^[a-z0-9]+(?:-[a-z0-9]+)*$/u.test(Q))throw TypeError("LLM provider id must use kebab-case");if(F.modelCatalog!==void 0&&F.modelCatalog!=="runtime")throw TypeError("LLM model catalog must be runtime");let X=c(F.models,"LLM models",32,!0).map((Y,Z)=>{let _=`LLM model ${Z}`,M=A(Y,_);R(M,["id","name"],_);let K=E(M.id,`${_} id`,128);if(!/^~?[a-z0-9]+(?:[._/:-][a-z0-9]+)*$/u.test(K))throw TypeError(`${_} id is invalid`);return{id:K,name:E(M.name,`${_} name`,120)}});if(new Set(X.map((Y)=>Y.id)).size!==X.length)throw TypeError("LLM models contain duplicate ids");return{...F.modelCatalog===void 0?{}:{modelCatalog:"runtime"},models:X,provider:{id:Q,name:E(J.name,"LLM provider name",120)}}}function k6(G){let F=A(G,"Pet contribution");R(F,["library","overlay","protocol","settings"],"Pet contribution");let J=X0(F.library,"Pet library"),Q=X0(F.overlay,"Pet overlay"),X=X0(F.settings,"Pet settings");if(!J.toLowerCase().endsWith(".json"))throw TypeError("Pet library must be a JSON file");if(!Q.toLowerCase().endsWith(".html"))throw TypeError("Pet overlay must be an HTML file");if(!X.toLowerCase().endsWith(".html"))throw TypeError("Pet settings must be an HTML file");if(F.protocol!=="convax.pet-host/1")throw TypeError("Pet protocol must equal convax.pet-host/1");return{library:J,overlay:Q,protocol:"convax.pet-host/1",settings:X}}function I6(G){let F=A(G,"Plugin runtime");if(R(F,["args","command","type"],"Plugin runtime"),F.type!=="mcp-stdio")throw TypeError("Plugin runtime type must be mcp-stdio");let J=E(F.command,"Plugin runtime command",128);if(!/^[A-Za-z0-9][A-Za-z0-9._-]*$/u.test(J))throw TypeError("Plugin runtime command must be a bare executable name");R0(J);let Q;if(F.args!==void 0)Q=c(F.args,"Plugin runtime args",64).map((X,Y)=>{let Z=E(X,`Plugin runtime arg ${Y}`,1024);if(/[\s"'`;|&`$(){}[\]<>]/u.test(Z)||Z.includes("\\")||/(^|=)(?:\/|[A-Za-z]:)/u.test(Z)||/(^|[=/])\.{1,2}(?:\/|$)/u.test(Z))throw TypeError(`Plugin runtime arg ${Y} must be a static CLI token without code, native paths, or traversal`);return Z});return{...Q===void 0?{}:{args:Q},command:J,type:"mcp-stdio"}}var ZF=new Set(U0.apis.filter((G)=>G.audience.includes("agent-skill")).map((G)=>G.id)),g6=/^[a-z][a-z0-9_]{0,63}$/;function x6(G,F){let J=E(G,F,64);if(!/^[a-z0-9]+(?:-[a-z0-9]+)*$/u.test(J))throw TypeError(`${F} must use kebab-case`);return R0(J),J}function f6(G,F,J){let Q=A(G,F);R(Q,["optionalHostApis","pluginTools","requiredHostApis"],F);let X=b0({major:M0,required:Q.requiredHostApis??[],optional:Q.optionalHostApis??[]}),Y=new Set(J.required),Z=new Set([...J.required,...J.optional]);for(let M of X.required){if(!Y.has(M))throw TypeError(`${F} required Host API must be required by the Plugin: ${M}`);if(N0(M)&&!ZF.has(M))throw TypeError(`${F} Host API is not available to Agent Skills: ${M}`)}for(let M of X.optional){if(!Z.has(M))throw TypeError(`${F} optional Host API must be declared by the Plugin: ${M}`);if(N0(M)&&!ZF.has(M))throw TypeError(`${F} Host API is not available to Agent Skills: ${M}`)}let _;if(Q.pluginTools!==void 0){if(_=c(Q.pluginTools,`${F} pluginTools`,32,!0).map((M,K)=>{let D=E(M,`${F} pluginTools ${K}`,64);if(!g6.test(D))throw TypeError(`${F} plugin tool id must use lower snake_case: ${D}`);return D}),new Set(_).size!==_.length)throw TypeError(`${F} pluginTools contain duplicate ids`)}if(X.required.length===0&&X.optional.length===0&&_===void 0)throw TypeError(`${F} must declare at least one Host API or Plugin tool`);return{...X.optional.length===0?{}:{optionalHostApis:[...X.optional]},..._===void 0?{}:{pluginTools:_},...X.required.length===0?{}:{requiredHostApis:[...X.required]}}}function h6(G,F){if(G===void 0)return;let J=c(G,"Plugin Skill contributions",32,!0).map((Q,X)=>{let Y=`Plugin Skill contribution ${X}`,Z=A(Q,Y);R(Z,["name","path","uses"],Y);let _=x6(Z.name,`${Y} name`),M=X0(Z.path,`${Y} path`);if(M.split("/").at(-1)!==_)throw TypeError(`${Y} path must name its Skill directory: ${_}`);let K=Z.uses===void 0?void 0:f6(Z.uses,`${Y} uses`,F);return{name:_,path:M,...K===void 0?{}:{uses:K}}});if(new Set(J.map((Q)=>Q.name)).size!==J.length)throw TypeError("Plugin Skill contributions contain duplicate names");if(new Set(J.map((Q)=>Q.path.toLocaleLowerCase("en-US"))).size!==J.length)throw TypeError("Plugin Skill contributions contain duplicate paths");return J}function y6(G,F){let J=new Set(F?.tools?.map((Q)=>Q.id)??[]);for(let Q of G??[])for(let X of Q.uses?.pluginTools??[])if(!J.has(X))throw TypeError(`Plugin Skill ${Q.name} references an unknown Agent tool: ${X}`)}var _F="convax.plugin/8";var fF=["canvas.connectedImages.read","canvas.connectedInputs.read","canvas.connectedMedia.stream","canvas.node.read","canvas.node.write","canvas.image.write","project.files.read","agent.prompt","generation.execute","ui.fullscreen","projects.read","canvas.catalog.read","canvas.document.read","canvas.document.write","canvas.events.subscribe","pet.activity.read","pet.activity.open","pet.preferences.write","pet.custom.manage"],c6=["projects.read","canvas.catalog.read","canvas.document.read","canvas.document.write","canvas.events.subscribe"],hF=["pet.activity.read","pet.activity.open","pet.preferences.write","pet.custom.manage"],$F=["pet.activity.read","pet.activity.open","pet.preferences.write"],b6=new Set(fF),d6=new Set(hF);function v6(G){let F=c(G??[],"Plugin capabilities",fF.length).map((J)=>{if(typeof J!=="string"||!b6.has(J))throw TypeError("Plugin capabilities contain an unsupported or duplicate capability");return J});if(new Set(F).size!==F.length)throw TypeError("Plugin capabilities contain an unsupported or duplicate capability");return F}function m6(G){let F=G.entry===void 0?void 0:X0(G.entry,"Plugin entry");if(F!==void 0&&!F.toLowerCase().endsWith(".html"))throw TypeError("Plugin entry must be an HTML file");let J=G.hooks===void 0?void 0:X0(G.hooks,"Plugin hooks");if(J!==void 0&&!/\.(?:js|mjs)$/u.test(J))throw TypeError("Plugin hooks must be a JavaScript ESM module");return{entry:F,hooks:J}}function p6(G){let{capabilities:F,canvas:J,entry:Q,hostApi:X}=G;if(Q!==void 0!==(J?.renderer!==void 0))throw TypeError("Plugin entry and Canvas renderer must appear together");if(Q!==void 0&&!X.required.includes("host.context.get"))throw TypeError("convax.plugin/8 Web Plugins must require host.context.get");if((J?.commands!==void 0||J?.menus!==void 0||J?.toolbar!==void 0)&&J.renderer===void 0)throw TypeError("Canvas UI commands require a sandboxed Canvas renderer");if(F.includes("generation.execute")&&J?.renderer===void 0)throw TypeError("generation.execute requires a sandboxed Canvas surface");if(J&&J.renderer===void 0&&!J.selectionActions?.length&&!J.commands?.length&&!J.menus?.length&&!J.toolbar?.length)throw TypeError("Canvas contributions must declare a renderer, selection actions, or UI commands");if(J?.selectionActions?.some((Y)=>("action"in Y)&&Y.action.type==="materialize-own-plugin-node")&&J.renderer===void 0)throw TypeError("materialize-own-plugin-node requires the contributing Plugin renderer")}function s6(G,F,J){if(F===void 0)return;if(G.length<$F.length||G.length>hF.length||$F.some((Q)=>!G.includes(Q))||G.some((Q)=>!d6.has(Q)))throw TypeError("Pet capabilities must include pet.activity.read, pet.activity.open, and pet.preferences.write; pet.custom.manage is optional");if(J!==void 0)throw TypeError("Pet feature cannot declare an executable runtime")}function o6(G,F={}){let J=A(G,"Plugin manifest");if(R(J,["capabilities","contributes","description","entry","hooks","hostApi","id","name","runtime","schema","version"],"Plugin manifest"),J.schema!==_F)throw TypeError("Plugin manifest must use convax.plugin/8");if(!Object.prototype.hasOwnProperty.call(J,"hostApi"))throw TypeError("convax.plugin/8 must declare hostApi explicitly");let Q=F.hostApiMode==="authoring"?R1(J.hostApi):b0(J.hostApi),X=v6(J.capabilities),Y=A(J.contributes,"Plugin contributions");R(Y,["agent","canvas","capabilities","generation","llm","pet","service","skills"],"Plugin contributions");let{entry:Z,hooks:_}=m6(J),M=Y.canvas===void 0?void 0:L6(Y.canvas);p6({capabilities:X,canvas:M,entry:Z,hostApi:Q});let K=Y.agent===void 0?void 0:H6(Y.agent),D=Y.capabilities===void 0?void 0:c1(Y.capabilities),W=Y.generation===void 0?void 0:E6(Y.generation),O=Y.llm===void 0?void 0:q6(Y.llm),V=Y.pet===void 0?void 0:k6(Y.pet),P=Y.service===void 0?void 0:P6(Y.service),G0=h6(Y.skills,Q),v=J.runtime===void 0?void 0:I6(J.runtime),J0=W!==void 0||P!==void 0||O!==void 0||Boolean(D?.exports.length);if(v!==void 0!==J0){if(D?.exports.length&&v===void 0)throw TypeError("Plugin capability exports require a verified mcp-stdio runtime");throw TypeError("convax.plugin/8 runtime and executable contribution must appear together")}if(D?.exports.length&&v===void 0)throw TypeError("Plugin capability exports require a verified mcp-stdio runtime");s6(X,V,v),C6({agent:K,generation:W,selectionActions:M?.selectionActions}),y6(G0,K);let U=new Set(c6),j=X.some((L)=>U.has(L));if(M?.renderer===void 0&&!M?.selectionActions?.length&&!J0&&_===void 0&&!X.includes("generation.execute")&&!j&&V===void 0&&(D?.exports.length??0)===0&&K?.mcp===void 0)throw TypeError("convax.plugin/8 must declare a Plugin capability beyond owned Skills");return RF({capabilities:X,contributes:{...K===void 0?{}:{agent:K},...D===void 0?{}:{capabilities:D},...M===void 0?{}:{canvas:M},...W===void 0?{}:{generation:W},...O===void 0?{}:{llm:O},...V===void 0?{}:{pet:V},...P===void 0?{}:{service:P},...G0===void 0?{}:{skills:G0}},description:E(J.description,"Plugin description",2000),...Z===void 0?{}:{entry:Z},..._===void 0?{}:{hooks:_},hostApi:Q,id:EF(J.id),name:E(J.name,"Plugin name",120),...v===void 0?{}:{runtime:v},schema:_F,version:v1(J.version)})}function r6(G){return o6(G,{hostApiMode:"authoring"})}class f extends Error{code;constructor(G,F){super(F);this.name="PluginHostProtocolError",this.code=G}}class v0 extends Error{code;kind;recoverable;constructor(G){super(G.message);this.name="PluginHostRemoteError",this.code=G.code,this.kind=G.kind,this.recoverable=G.recoverable}}class h0 extends Error{reason;constructor(G){super("Plugin Host request was aborted");this.name="AbortError",this.reason=G}}var KF=0;function u6(){return KF+=1,`sdk-${Date.now().toString(36)}-${KF.toString(36)}`}function n6(G){if(G.length<1||G.length>96||G!==G.trim()||!/^[A-Za-z0-9._-]+$/.test(G))throw TypeError("Plugin Host requestIdPrefix is invalid")}function MF(G,F){let J=G.contributes.capabilities,Q=J?.imports.required.find((Y)=>Y.id===F);if(Q)return{import:Q,requirement:"required"};let X=J?.imports.optional.find((Y)=>Y.id===F);if(X)return{import:X,requirement:"optional"};throw TypeError(`Plugin capability import is not declared: ${F}`)}function t6(G,F){let J=F.kind==="protocol"?qF(F):B1(G,F);return new v0(J)}function SF(G){let F=G.kind==="protocol"?qF(G):e1(G);return new v0(F)}function yF(G){let F=r6(G.manifest);if(F.entry===void 0||!F.hostApi.required.includes("host.context.get"))throw TypeError("Plugin Host Web client requires an entry and required host.context.get negotiation baseline");let J=G.requestIdPrefix??u6();n6(J);let Q=new Map,X=new Set,Y,Z,_=0,M=!1,K=(U)=>{for(let j of Q.values())j.abort?.(),j.reject(U);Q.clear()},D=(U)=>{if(M)return;M=!0,G.port.removeEventListener("message",G0),X.clear(),K(U);try{G.onFatalError?.(U)}catch{}},W=()=>{if(_>=Number.MAX_SAFE_INTEGER){let j=new f("request-id-exhausted","Plugin Host request id space is exhausted");throw D(j),j}_+=1;let U=`${J}-${_.toString(36)}`;if(!wF(U)){let j=new f("request-id-exhausted","Plugin Host request id is invalid");throw D(j),j}return U},O=(U,j)=>{GF(U,j,"Plugin Host request")},V=(U)=>{G.port.postMessage(U)},P=(U,j,L,N)=>{if(M)return Promise.reject(new f("closed","Plugin Host client is closed"));if(N?.aborted)return Promise.reject(new h0(N.reason));if(Q.size>=e0)return Promise.reject(RangeError(`Plugin Host client permits at most ${e0} in-flight requests`));try{O(U,L.maximumRequestBytes)}catch(b){return Promise.reject(b)}let T=U.id;return new Promise((b,h)=>{let Q0=N?()=>{let n=Q.get(T);if(!n)return;Q.delete(T),n.abort?.();let m={id:T,protocol:l,type:"cancel"};try{O(m,B0),V(m)}catch(p){let p0=new f("transport-failed",p instanceof Error?p.message:"Plugin Host cancel failed");h(p0),D(p0);return}h(new h0(N.reason))}:void 0,W0=Q0?()=>{N.removeEventListener("abort",Q0)}:void 0;if(Q.set(T,{abort:W0,maximumResponseBytes:L.maximumResponseBytes,parseFailure:L.parseFailure,parseResult:j,reject:h,resolve:b}),Q0)N.addEventListener("abort",Q0,{once:!0});try{V(U)}catch(n){D(new f("transport-failed",n instanceof Error?n.message:"Plugin Host transport failed"))}})};function G0(U){if(M)return;let j;try{j=GF(U.data,p1,"Plugin Host response")}catch{D(new f("invalid-envelope","Plugin Host sent a non-JSON message"));return}if(a1(U.data)){try{for(let T of X)T(U.data)}catch{D(new f("invalid-envelope","Plugin Host command listener failed"))}return}if(!i1(U.data)){D(new f("invalid-envelope","Plugin Host sent an invalid envelope"));return}let L=U.data,N=Q.get(L.id);if(!N){D(new f("unknown-response",`Plugin Host returned an unknown, duplicate, or late response id: ${L.id}`));return}if(j>N.maximumResponseBytes){D(new f("invalid-envelope",`Plugin Host response exceeds ${N.maximumResponseBytes} bytes for this request`));return}if(!L.ok){try{let T=N.parseFailure(L.error);Q.delete(L.id),N.abort?.(),N.reject(T)}catch(T){D(new f("invalid-result",T instanceof Error?T.message:"Plugin Host returned an invalid failure"))}return}try{let T=N.parseResult(L.result);Q.delete(L.id),N.abort?.(),N.resolve(T)}catch(T){D(new f("invalid-result",T instanceof Error?T.message:"Plugin Host returned an invalid result"))}}G.port.addEventListener("message",G0),G.port.start?.();let v=(U,j)=>{if(!t0(F.hostApi,U))return Promise.reject(TypeError(`Plugin Host API is not declared: ${U}`));let L=j1[U],N=L.params.type==="none"?void 0:j[0],T=L.params.type==="none"?j[0]:j[1],b;try{b=V1(U,N)}catch(m){return Promise.reject(m)}let Q0={id:W(),method:U,...b===void 0?{}:{params:b},protocol:l,type:"request"},W0=S1(U),n=L1;return P(Q0,(m)=>{let p=n(U,m);if(U==="host.context.get")Y=p;return p},{maximumRequestBytes:W0.request.maxBytes,maximumResponseBytes:W0.result.maxBytes,parseFailure:(m)=>{let p=t6(U,m);if(p.kind==="api"&&p.code==="stale-context")Y=void 0;return p}},T?.signal)},J0={get closed(){return M},callHostApi(U,...j){return v(U,j)},async getHostApiAvailability(U,j){if(!t0(F.hostApi,U))throw TypeError(`Plugin Host API is not declared: ${U}`);return(!Y||j?.refresh?await J0.refreshHostApiContext(j):Y).hostApi.availability.find(({id:N})=>N===U)??{available:!1,id:U,reason:"unsupported-host",recoverable:!1}},refreshHostApiContext(U){if(Y=void 0,Z)return Z;let L=v("host.context.get",[U]).finally(()=>{if(Z===L)Z=void 0});return Z=L,Z},async requireHostApi(U,j){let L=await J0.getHostApiAvailability(U,j);if(!L.available)throw new zF(L);return L},getCapabilityAvailability(U,j){let L;try{L=MF(F,U)}catch(b){return Promise.reject(b)}let N=W();return P({capabilityId:U,id:N,protocol:l,type:"capability-availability"},(b)=>{let h=l1(b);if(h.capabilityId!==U||h.requirement!==L.requirement)throw TypeError("Plugin capability availability does not match the declared import");return h},{maximumRequestBytes:B0,maximumResponseBytes:l0,parseFailure:SF},j?.signal)},invokeCapability(U,j,L){let N;try{N=MF(F,U),a0(N.import.inputSchema,j,`Plugin capability ${U} input`)}catch(h){return Promise.reject(h)}let T=W();return P({capabilityId:U,id:T,input:j,protocol:l,type:"capability-invoke"},(h)=>{return a0(N.import.outputSchema,h,`Plugin capability ${U} output`),h},{maximumRequestBytes:B0,maximumResponseBytes:l0,parseFailure:SF},L?.signal)},onCommand(U){if(M)throw new f("closed","Plugin Host client is closed");if(X.size>=64)throw RangeError("Plugin Host command listener limit exceeded");return X.add(U),()=>{X.delete(U)}},close(){D(new f("closed","Plugin Host client was closed"))}};return J0}var m0={schema:"convax.plugin/8",id:"chatcut",name:"ChatCut",description:"Imports directly connected Canvas media into ChatCut and connects Convax Agent sessions to ChatCut's hosted MCP server for authenticated, editable video workflows.",version:"0.3.2",entry:"index.html",capabilities:[],contributes:{canvas:{renderer:{create:!0,width:760,height:560}}},hostApi:{major:1,required:["agent.prompt","canvas.inputs.list","host.context.get"],optional:[]}};var G2="@convax/plugin-sdk/client:createPluginHostClient";function J2(G,F={}){if(G.source!==window.parent||G.ports.length!==1||!PF(G.data)||G.data.pluginId!==m0.id)return null;return yF({manifest:m0,onFatalError:F.onFatalError,port:G.ports[0],requestIdPrefix:F.requestIdPrefix})}export{G2 as pluginSdkClientBundleMarker,J2 as acceptPluginHostConnection}; +var mF=/^[a-z][a-z0-9]*(?:\.[a-z][a-z0-9]*)+$/,dF=/^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/,pF=/^[a-z][A-Za-z0-9]*(?:\.[a-z][A-Za-z0-9]*)+$/,sF=/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/,rF=new Set(["web-plugin","agent-skill","companion","host"]),oF=new Set(["connection","plugin","own-node","project","canvas"]),uF=new Set(["none","read","write","execute","subscribe"]),nF=new Set(["cancelable","commit-preserving"]);function _0(F,G){if(F.trim().length===0)throw TypeError(`${G} must not be empty`)}function R0(F,G){if(!sF.test(F))throw TypeError(`${G} must be a strict semantic version`)}function I0(F,G){let J=F.split(".").map(Number),Q=G.split(".").map(Number);for(let X=0;X<3;X+=1){let Y=J[X]-Q[X];if(Y!==0)return Y}return 0}function LF(F){if(!mF.test(F.id))throw TypeError(`Plugin API id is invalid: ${F.id}`);if(R0(F.contractSince,`${F.id} contractSince`),F.grant!==null&&!pF.test(F.grant))throw TypeError(`Plugin API grant is invalid: ${F.grant}`);if(!oF.has(F.scope))throw TypeError(`Plugin API scope is invalid: ${F.scope}`);if(!uF.has(F.sideEffect))throw TypeError(`Plugin API sideEffect is invalid: ${F.sideEffect}`);if(!nF.has(F.completion))throw TypeError(`Plugin API completion is invalid: ${F.completion}`);let G=F.audience??["web-plugin"];if(G.length===0||new Set(G).size!==G.length||G.some((X)=>!rF.has(X)))throw TypeError(`Plugin API audience is invalid: ${F.id}`);_0(F.docs.summary,`${F.id} docs.summary`),_0(F.docs.description,`${F.id} docs.description`),_0(F.docs.request,`${F.id} docs.request`),_0(F.docs.response,`${F.id} docs.response`);let J=new Set,Q=F.errors.map((X)=>{if(!dF.test(X.code)||J.has(X.code))throw TypeError(`Plugin API error code is invalid or duplicated: ${F.id}/${X.code}`);return J.add(X.code),_0(X.description,`${F.id}/${X.code} description`),Object.freeze({...X})});return Object.freeze({...F,audience:Object.freeze([...G]),errors:Object.freeze(Q),docs:Object.freeze({...F.docs})})}function tF(F){return LF(F)}function t0(F,G){return R0(F,"Plugin API release version"),Object.freeze({version:F,apis:Object.freeze([...G])})}function iF(...F){if(F.length===0)throw TypeError("Plugin API catalog requires at least one release");let G=new Set,J=[],Q=new Set(F.map((Y)=>Y.version)),X;for(let Y of F){if(R0(Y.version,"Plugin API release version"),X&&I0(X,Y.version)>=0)throw TypeError("Plugin API releases must be strictly increasing");X=Y.version;for(let Z of Y.apis){let _=LF(Z);if(G.has(_.id))throw TypeError(`Plugin API id is duplicated: ${_.id}`);if(I0(_.contractSince,Y.version)<0)throw TypeError(`Plugin API ${_.id} contractSince must not precede since`);if(!Q.has(_.contractSince))throw TypeError(`Plugin API ${_.id} contractSince must identify a Catalog release block`);G.add(_.id),J.push(Object.freeze({..._,since:Y.version}))}}if(J.length===0)throw TypeError("Plugin API catalog must contain at least one API");return Object.freeze({version:F[F.length-1].version,apis:Object.freeze(J)})}var Y2=Object.freeze({assertVersion:R0,compareVersions:I0}),aF="convax.plugin-api-wire-schema/3",z=1024,I=z*z,lF=16*I,i0=8192,eF=33554432,$0={type:"none"},m={type:"boolean"},B={finite:!0,type:"number"},r={finite:!0,minimum:0,type:"integer"},T0=(F)=>({finite:!0,maximum:F,minimum:1,type:"integer"}),B0={type:"null"},g=(F)=>({const:F}),$=(F=2048,G={})=>({controlCharacters:!1,maxLength:F,minLength:G.allowEmpty?0:1,...G.prefix?{prefix:G.prefix}:{},...G.refinement?{refinement:G.refinement}:{},type:"string"}),q=(F,G,J=0,Q)=>({items:F,maxItems:G,minItems:J,type:"array",...Q?{uniqueBy:Q}:{}}),S=(F,G,J)=>({additionalProperties:!1,properties:F,...J?{products:J}:{},required:G,type:"object"}),l=(...F)=>({oneOf:F}),g0=(F=I)=>({keyMaxLength:128,maxBytes:F,maxDepth:32,type:"json-object"}),h=(F)=>({controlCharacters:!1,enum:F,maxLength:Math.max(...F.map((G)=>G.length)),minLength:1,type:"string"}),Z0=S({x:B,y:B},["x","y"]),d0=S({height:B,width:B},["height","width"]),i=S({canvasId:$(256),projectId:$(256)},["canvasId","projectId"]),x0=h(["text","image","video","audio"]),NF=h(["text","reference_image","reference_video","first_frame","last_frame","audio"]),x=(F=1000)=>q($(),F),F6=l(S({available:g(!0),catalogVersion:$(64),contractSince:$(64),id:$(128),since:$(64)},["available","catalogVersion","contractSince","id","since"]),S({available:g(!1),contractSince:$(64),id:$(128),reason:h(["unsupported-host","not-declared","permission-denied","wrong-surface","missing-context","setup-required","disabled","recovering"]),recoverable:m,since:$(64)},["available","id","reason","recoverable"])),OF=S({data:g0(),id:$(),parentId:$(),position:Z0,revision:r,style:g0(),type:$(80)},["data","id","position","revision","type"]),G6=S({inputKey:$(),role:NF},["inputKey","role"]),J6=S({ids:x(),kinds:x(),limit:r,relatedToNodeIds:x(),text:$(2000,{allowEmpty:!0})},[]),Q6=S({animated:m,id:$(),source:$(),target:$(),type:$(80)},["source","target"]),X6=S({nodeId:$(),position:Z0,size:d0},["nodeId","position"]),Y6=S({componentGap:B,componentPackingScale:B,crossGap:B,isolatedPlacement:h(["left","preserve"]),mainGap:B,nodeGap:B,nodePackingScale:B,strategy:h(["component-packing","horizontal-directed-cluster","vertical-directed-cluster"])},[]),Z6=l(S({edgeIds:x(),nodeIds:x(),type:g("elements.remove")},["type"]),S({direction:h(["left","center","right","top","middle","bottom"]),nodeIds:x(),type:g("nodes.align")},["direction","nodeIds","type"]),S({connection:Q6,type:g("nodes.connect")},["connection","type"]),S({axis:h(["horizontal","vertical"]),nodeIds:x(),type:g("nodes.distribute")},["axis","nodeIds","type"]),S({label:$(512),nodeIds:x(),type:g("nodes.group")},["nodeIds","type"]),S({gap:B,layout:h(["grid","horizontal","vertical"]),nodeIds:x(),type:g("nodes.layout")},["nodeIds","type"]),S({delta:Z0,nodeIds:x(),type:g("nodes.move")},["delta","nodeIds","type"]),S({type:g("nodes.setGeometry"),updates:q(X6,1000)},["type","updates"]),S({nodeId:$(),type:g("nodes.ungroup")},["nodeId","type"]),S({nodeIds:x(),options:Y6,type:g("canvas.auto-layout")},["type"])),_6=S({durationMs:B,height:B,inputKey:$(),kind:$(80),label:$(512),mediaRevision:$(512),mimeType:$(512),name:$(512),status:h(["error","idle","pending"]),width:B},["inputKey","kind","label"]),$6=S({contentRevision:$(64,{refinement:"lowercase-sha256"}),height:T0(i0),kind:g("image"),mimeType:h(["image/jpeg","image/png","image/webp"]),size:T0(lF),width:T0(i0)},["contentRevision","height","kind","mimeType","size","width"],[{fields:["width","height"],maximum:eF}]),K6=S({acceptedInputs:q(NF,6),description:$(2000),id:$(256),kind:h(["model","operation"]),output:x0,title:$(120)},["acceptedInputs","description","id","kind","output","title"]),zF=S({id:$(),source:$(),target:$()},["id","source","target"]),M6=S({id:$(),kind:$(80),label:$(512),parentId:$(64*z,{allowEmpty:!0}),position:Z0,size:d0,type:$(64*z,{allowEmpty:!0})},["id","kind","label","position","size"]),S6=S({description:$(64*z,{allowEmpty:!0}),durationMs:B,id:$(),kind:$(80),label:$(512),mimeType:$(64*z,{allowEmpty:!0}),name:$(64*z,{allowEmpty:!0}),parentId:$(64*z,{allowEmpty:!0}),position:Z0,resource:S({kind:g("project-file"),path:$(1024)},["kind","path"]),size:d0,status:$(64*z,{allowEmpty:!0}),text:$(64*z,{allowEmpty:!0}),type:$(64*z,{allowEmpty:!0})},["id","kind","label","position","size"]),D6=S({edges:q(zF,1e4),id:$(256),nodes:q(M6,1e4),revision:r,title:$(512)},["edges","id","nodes","revision","title"]),U6=S({description:$(8000,{allowEmpty:!0}),edges:q(zF,1e4),id:$(256),nodes:q(S6,1e4),revision:r,tags:q($(),256),title:$(512)},["edges","id","nodes","revision","title"]),W6=S({id:$(),incomingNodeIds:x(),kind:$(80),label:$(512),outgoingNodeIds:x(),parentId:$(64*z,{allowEmpty:!0}),position:Z0,text:$(64*z,{allowEmpty:!0}),type:$(64*z,{allowEmpty:!0})},["id","incomingNodeIds","kind","label","outgoingNodeIds","position"]),j6=S({canvas:S({id:$(256),name:$(512)},["id"]),hostApi:S({availability:q(F6,256,0,"id"),catalogVersion:$(64)},["availability","catalogVersion"]),node:OF,plugin:S({id:$(128),name:$(512),version:$(128)},["id","name","version"]),project:S({id:$(256),name:$(512)},["id"])},["canvas","hostApi","node","plugin","project"]),H=(F,G,J={})=>({dialect:aF,request:{maxBytes:J.request??64*z,schema:F},result:{maxBytes:J.result??64*z,schema:G}}),F0=Object.freeze({"host.context.get":H($0,j6,{result:I}),"canvas.inputs.list":H($0,S({inputs:q(_6,256)},["inputs"]),{result:I}),"canvas.inputs.image.open":H(S({inputKey:$()},["inputKey"]),S({probe:$6,sessionId:$(128),url:$(2048,{prefix:"convax-connected-media://"})},["probe","sessionId","url"])),"canvas.inputs.image.close":H(S({sessionId:$(128)},["sessionId"]),S({closed:m},["closed"])),"canvas.inputs.open":H(S({inputKey:$()},["inputKey"]),S({probe:S({duration:S({estimated:m,milliseconds:B},["estimated","milliseconds"]),height:B,kind:h(["audio","video"]),mediaRevision:$(128),mimeType:$(256),size:B,width:B},["duration","kind","mediaRevision","mimeType","size"]),sessionId:$(128),url:$(2048,{prefix:"convax-connected-media://"})},["probe","sessionId","url"])),"canvas.inputs.close":H(S({sessionId:$(128)},["sessionId"]),S({closed:m},["closed"])),"canvas.node.get":H($0,OF,{result:I}),"canvas.node.state.replace":H(S({state:g0(256*z)},["state"]),S({updated:g(!0)},["updated"]),{request:256*z+4*z}),"canvas.resource.image.create":H(S({dataUrl:$(24*I,{prefix:"data:image/png;base64,"}),name:$(120,{refinement:"safe-png-file-name"})},["dataUrl","name"]),S({createdNodeId:$(),revision:r},["createdNodeId","revision"]),{request:24*I+4*z}),"project.file.text.read":H(S({path:$(1024,{refinement:"portable-project-relative-path"})},["path"]),S({content:$(I,{allowEmpty:!0}),exists:m,path:$(1024,{refinement:"portable-project-relative-path"})},["content","exists","path"]),{result:I+4*z}),"agent.prompt":H(S({text:$(20000,{refinement:"trimmed"})},["text"]),S({text:$(64*z,{allowEmpty:!0})},["text"])),"generation.tools.list":H(l($0,S({output:x0},[])),S({tools:q(K6,256)},["tools"]),{result:I}),"generation.execute":H(S({output:x0,prompt:$(20000,{refinement:"trimmed"}),references:q(G6,32),resultMode:h(["create-pending-node","return"]),toolId:$(256)},["prompt"]),S({createdNodeIds:q($(),32),outputText:$(64*z,{allowEmpty:!0}),revision:r,toolId:$(256),warnings:q($(),32)},["createdNodeIds","revision","toolId","warnings"]),{result:256*z}),"projects.list":H($0,S({projects:q(S({available:m,id:$(256),name:$(512)},["available","id","name"]),1000)},["projects"]),{result:I}),"canvas.catalog.list":H(S({projectId:$(256)},["projectId"]),S({canvases:q(S({createdAt:B,id:$(256),name:$(512),updatedAt:B},["createdAt","id","name","updatedAt"]),1e4),projectId:$(256)},["canvases","projectId"]),{result:8*I}),"canvas.document.get":H(S({projection:h(["geometry","structure"]),ref:i},["ref"]),l(S({document:D6,projection:g("geometry"),ref:i,storageVersion:l(B0,$(256))},["document","projection","ref","storageVersion"]),S({document:U6,projection:g("structure"),ref:i,storageVersion:l(B0,$(256))},["document","projection","ref","storageVersion"])),{result:8*I}),"canvas.nodes.query":H(S({query:J6,ref:i},["ref"]),S({nodes:q(W6,1000),ref:i,revision:r,storageVersion:l(B0,$(256))},["nodes","ref","revision","storageVersion"]),{request:I,result:8*I}),"canvas.transaction.execute":H(S({commands:q(Z6,256,1),expectedRevision:r,ref:i,transactionId:$(128)},["commands","expectedRevision","ref","transactionId"]),S({affectedNodeIds:x(1e4),changed:m,createdNodeIds:x(1e4),ref:i,revision:r,storageVersion:$(256),summaryTruncated:m,warnings:x()},["affectedNodeIds","changed","createdNodeIds","ref","revision","storageVersion","warnings"]),{request:I,result:2*I}),"canvas.events.subscribe":H(S({ref:S({canvasId:$(256),projectId:$(256)},["projectId"])},["ref"]),S({subscriptionId:$(128)},["subscriptionId"])),"canvas.events.unsubscribe":H(S({subscriptionId:$(128)},["subscriptionId"]),S({removed:m},["removed"]))}),V6=Math.max(...Object.values(F0).map(({request:F})=>F.maxBytes)),L6=Math.max(...Object.values(F0).map(({result:F})=>F.maxBytes));function N6(F){return F0[F]}function f0(F,G){if(!F||typeof F!=="object"||Array.isArray(F))throw TypeError(`${G} must be an object`);let J=Object.getPrototypeOf(F);if(J!==Object.prototype&&J!==null)throw TypeError(`${G} must be a plain object`);return F}var O6=/^(CON|PRN|AUX|NUL|COM[1-9¹²³]|LPT[1-9¹²³]|CONIN\$|CONOUT\$)$/iu;function AF(F){for(let G of F){let J=G.codePointAt(0);if(J>=55296&&J<=57343)return!1}return!0}function a0(F){let G=F.split(".",1)[0]??"";return Boolean(F&&F!=="."&&F!==".."&&AF(F)&&!/[\\/:*?"<>|\u0000-\u001f\u007f]/u.test(F)&&!/[. ]$/u.test(F)&&!O6.test(G))}function z6(F,G){if(G===void 0)return!0;if(G==="lowercase-sha256")return/^[a-f0-9]{64}$/u.test(F);if(G==="trimmed")return F===F.trim();if(G==="safe-png-file-name")return F===F.trim()&&F.toLowerCase().endsWith(".png")&&a0(F);if(G==="portable-project-relative-path"){if(F!==F.trim()||F.includes("\\")||F.startsWith("/")||F.startsWith("//")||/^[A-Za-z]:/u.test(F)||!AF(F))return!1;let J=F.split("/");return J[0]?.toLowerCase()!==".convax"&&J.length>0&&J.every((Q)=>a0(Q))}return!1}function A6(F,G,J){let Q=new Set,X=(_,M,K)=>{if(_===null||typeof _==="string"||typeof _==="boolean")return _;if(typeof _==="number"){if(!Number.isFinite(_))throw TypeError(`${M} must contain finite JSON numbers`);return _}if(!_||typeof _!=="object"||K>=G.maxDepth||Q.has(_))throw TypeError(`${M} must be bounded acyclic JSON`);let D=Object.getPrototypeOf(_);if(!Array.isArray(_)&&D!==Object.prototype&&D!==null)throw TypeError(`${M} must contain plain JSON objects`);Q.add(_);let j;if(Array.isArray(_))j=_.map((O,L)=>X(O,`${M}[${L}]`,K+1));else{let O=Object.create(null);for(let[L,k]of Object.entries(_)){if(L.length<1||L.length>G.keyMaxLength||/[\u0000-\u001f\u007f]/u.test(L))throw TypeError(`${M} key is invalid`);O[L]=X(k,`${M}.${L}`,K+1)}j=O}return Q.delete(_),j},Y=X(f0(F,J),J,0);if(Array.isArray(Y)||!Y||typeof Y!=="object")throw TypeError(`${J} must be an object`);let Z=JSON.stringify(Y);if(new TextEncoder().encode(Z).byteLength>G.maxBytes)throw TypeError(`${J} exceeds ${G.maxBytes} bytes`);return Y}function R6(F,G,J){for(let Q of G??[]){let X=1;for(let Y of Q.fields){let Z=F[Y];if(typeof Z!=="number"||!Number.isFinite(Z)||Z<0)throw TypeError(`${J}.${Y} must be a non-negative finite product factor`);if(Z!==0&&X>Q.maximum/Z)throw TypeError(`${J} must satisfy its numeric product limits`);X*=Z}if(X>Q.maximum)throw TypeError(`${J} must satisfy its numeric product limits`)}return F}function K0(F,G,J="Plugin API value"){if("oneOf"in F){let Z=[];for(let _ of F.oneOf)try{Z.push(K0(_,G,J))}catch{}if(Z.length!==1)throw TypeError(`${J} must match exactly one schema variant`);return Z[0]}if("const"in F){if(G!==F.const)throw TypeError(`${J} must equal ${String(F.const)}`);return G}if("type"in F&&F.type==="none"){if(G!==void 0)throw TypeError(`${J} does not accept a value`);return}if("type"in F&&F.type==="null"){if(G!==null)throw TypeError(`${J} must be null`);return null}if("type"in F&&F.type==="boolean"){if(typeof G!=="boolean")throw TypeError(`${J} must be boolean`);return G}if("type"in F&&(F.type==="number"||F.type==="integer")){if(typeof G!=="number"||!Number.isFinite(G)||F.type==="integer"&&!Number.isSafeInteger(G)||F.minimum!==void 0&&GF.maximum)throw TypeError(`${J} must be a valid ${F.type}`);return G}if("type"in F&&F.type==="string"){if(typeof G!=="string"||G.lengthF.maxLength||F.controlCharacters===!1&&/[\u0000-\u001f\u007f]/u.test(G)||F.enum!==void 0&&!F.enum.includes(G)||F.prefix!==void 0&&!G.startsWith(F.prefix)||!z6(G,F.refinement))throw TypeError(`${J} must satisfy its bounded string contract`);return G}if("type"in F&&F.type==="array"){if(!Array.isArray(G)||G.lengthF.maxItems)throw TypeError(`${J} must satisfy its bounded array contract`);let Z=G.map((_,M)=>K0(F.items,_,`${J}[${M}]`));if(F.uniqueBy!==void 0){let _=Z.map((M)=>{let D=f0(M,`${J} unique item`)[F.uniqueBy];if(typeof D!=="string"&&typeof D!=="number")throw TypeError(`${J} unique identity is invalid`);return`${typeof D}:${String(D)}`});if(new Set(_).size!==_.length)throw TypeError(`${J} contains duplicate ${F.uniqueBy}`)}return Z}if("type"in F&&F.type==="json-object")return A6(G,F,J);if(!("properties"in F))throw TypeError(`${J} has an unsupported schema`);let Q=f0(G,J),X=new Set(Object.keys(F.properties));if(F.required.some((Z)=>!Object.prototype.hasOwnProperty.call(Q,Z))||Object.keys(Q).some((Z)=>!X.has(Z)))throw TypeError(`${J} contains unsupported or missing fields`);let Y=Object.fromEntries(Object.entries(Q).map(([Z,_])=>[Z,K0(F.properties[Z],_,`${J}.${Z}`)]));return R6(Y,F.products,J)}function h0(F,G){if("oneOf"in F){let J=F.oneOf.map((Z)=>h0(Z,G)),Q=J.filter((Z)=>Z.type==="object");if(Q.length===0&&J.some((Z)=>Z.type==="none"))return{type:"none"};if(Q.length===0)throw TypeError(`${G} is not an object schema`);let X=new Set(Q.flatMap(({required:Z,optional:_})=>[...Z,..._])),Y=[...X].filter((Z)=>Q.every((_)=>_.required.includes(Z))).sort();return{additionalProperties:!1,optional:[...X].filter((Z)=>!Y.includes(Z)).sort(),required:Y,type:"object"}}if("type"in F&&F.type==="none")return{type:"none"};if(!("properties"in F))throw TypeError(`${G} is not an object schema`);return{additionalProperties:!1,optional:Object.keys(F.properties).filter((J)=>!F.required.includes(J)).sort(),required:[...F.required].sort(),type:"object"}}var y0=Object.freeze(Object.keys(F0).sort()),E6=Object.freeze(Object.fromEntries(y0.map((F)=>{let G=F0[F],J=h0(G.result.schema,`Plugin API ${F} result`);if(J.type!=="object")throw TypeError(`Plugin API ${F} result must be an object`);return[F,{dialect:G.dialect,params:h0(G.request.schema,`Plugin API ${F} params`),request:G.request,response:G.result,result:J}]})));function T6(F,G){return K0(F0[F].request.schema,G,`Plugin API ${F} params`)}function B6(F,G){return K0(F0[F].result.schema,G,`Plugin API ${F} result`)}var P=[{code:"stale-context",description:"The bound Project, Canvas, node, or connection changed before the call completed.",recoverable:!0}],w=[{code:"permission-denied",description:"The installed Plugin principal does not currently hold the required grant.",recoverable:!1}],H0=[{code:"resource-unavailable",description:"The authoritative Project resource is missing, changed, or cannot be read safely.",recoverable:!0}],l0=[{code:"partial-success",description:"A user-visible Project file was published, but the requested Canvas commit did not complete; retry is unsafe.",recoverable:!1}],C=(F)=>tF({...F,contractSince:"2.0.0"}),U0=iF(t0("1.0.0",[C({id:"host.context.get",completion:"cancelable",grant:null,scope:"connection",sideEffect:"read",errors:P,docs:{summary:"Read the bounded context attached to the current Plugin connection.",description:"Returns only renderer-safe identifiers and feature metadata for the exact live connection; it grants no additional authority.",request:"No parameters.",response:"The current Plugin, Project, Canvas, node, and negotiated Host API context when present."}}),C({id:"canvas.inputs.list",completion:"cancelable",grant:"canvas.connectedInputs.read",scope:"own-node",sideEffect:"read",errors:[...P,...w],docs:{summary:"List direct incoming inputs of the owning Plugin node.",description:"Derives pathless input metadata from authoritative direct incoming Canvas edges and never reads resource bytes.",request:"No parameters; the owning node comes from the bound connection.",response:"A bounded list of direct incoming input descriptors and opaque input keys."}}),C({id:"canvas.inputs.open",completion:"cancelable",grant:"canvas.connectedMedia.stream",scope:"own-node",sideEffect:"read",errors:[...P,...w,...H0],docs:{summary:"Open a bounded stream for one previously listed direct input.",description:"Opens host-owned access to the exact authoritative input after topology and resource identity are revalidated.",request:"`{ inputKey }`, using an opaque key returned by canvas.inputs.list.",response:"A connection-bound stream descriptor and safe media metadata.",remarks:"Call canvas.inputs.close when the stream is no longer needed."}}),C({id:"canvas.inputs.close",completion:"cancelable",grant:"canvas.connectedMedia.stream",scope:"own-node",sideEffect:"write",errors:[...P,...w],docs:{summary:"Close one connection-bound input stream.",description:"Releases a stream created by canvas.inputs.open without changing Canvas or Project state.",request:"The stream handle returned by canvas.inputs.open.",response:"An acknowledgement; closing an already closed handle is idempotent."}}),C({id:"canvas.node.get",completion:"cancelable",grant:"canvas.node.read",scope:"own-node",sideEffect:"read",errors:[...P,...w],docs:{summary:"Read the owning Plugin node projection.",description:"Returns a bounded renderer-safe projection of the exact node bound to the connection.",request:"No parameters; the owning node comes from the bound connection.",response:"The owning node identity, revision, geometry, and Plugin state projection."}}),C({id:"canvas.node.state.replace",completion:"commit-preserving",grant:"canvas.node.write",scope:"own-node",sideEffect:"write",errors:[...P,...w],docs:{summary:"Replace the owning node's bounded Plugin state.",description:"Commits only the namespaced Plugin state through the authoritative Canvas application service with revision checks.",request:"`{ state }`, where state is a bounded JSON value.",response:"`{ updated: true }` after the authoritative state replacement commits."}}),C({id:"canvas.resource.image.create",completion:"commit-preserving",grant:"canvas.image.write",scope:"own-node",sideEffect:"write",errors:[...P,...w,...l0],docs:{summary:"Create a Project-backed Canvas image through the host lifecycle.",description:"Admits bounded image content as a user-visible Project resource and commits its Canvas reference without exposing native paths.",request:"`{ dataUrl, name }`, containing a bounded validated image data URL and safe file name.",response:"The created renderer-safe image result after Project publication and Canvas commit."}}),C({id:"project.file.text.read",completion:"cancelable",grant:"project.files.read",scope:"project",sideEffect:"read",errors:[...P,...w],docs:{summary:"Read one bounded UTF-8 Project file.",description:"Reads through the scoped Project Files capability using a normalized Project-relative path and never exposes a native path.",request:"`{ path }`, using a normalized Project-relative portable path.",response:"The bounded UTF-8 file text."}}),C({id:"agent.prompt",completion:"commit-preserving",grant:"agent.prompt",scope:"connection",sideEffect:"execute",errors:[...P,...w],docs:{summary:"Submit a bounded prompt through the host Agent capability.",description:"Uses the current host-owned Agent context; it does not grant direct OpenCode, filesystem, model, or credential access.",request:"`{ text }`, containing the bounded prompt text.",response:"`{ text }`, containing the bounded host acknowledgement."}}),C({id:"generation.tools.list",completion:"cancelable",grant:"generation.execute",scope:"plugin",sideEffect:"read",errors:w,docs:{summary:"List generation tools available to the installed Plugin principal.",description:"Returns normalized tool metadata derived from active verified contributions without exposing executable paths or credentials.",request:"Optional `{ output }` modality filter; omitting params lists every admitted modality.",response:"A bounded list of available generation tools and their public input contracts."}}),C({id:"generation.execute",completion:"commit-preserving",grant:"generation.execute",scope:"plugin",sideEffect:"execute",errors:[...P,...w,...H0,...l0],docs:{summary:"Execute one selected generation tool through the shared host executor.",description:"Revalidates the active Plugin, authorized executable, inputs, cancellation, and live resource guards immediately before execution.",request:"`{ output?, prompt, references?: Array<{ inputKey, role }>, resultMode?, toolId? }`; every opaque input key must come from the current owning node's canvas.inputs.list result.",response:"The bounded selected tool result, created node ids, authoritative revision, and warnings."}}),C({id:"projects.list",completion:"cancelable",audience:["web-plugin","companion"],grant:"projects.read",scope:"plugin",sideEffect:"read",errors:w,docs:{summary:"List Projects visible to the installed Plugin principal.",description:"Returns portable Project identities and display metadata without native paths or private Project state.",request:"No parameters.",response:"A bounded list of renderer-safe Project summaries."}}),C({id:"canvas.catalog.list",completion:"cancelable",audience:["web-plugin","companion"],grant:"canvas.catalog.read",scope:"project",sideEffect:"read",errors:[...P,...w],docs:{summary:"List Canvas catalog entries for one authorized Project.",description:"Reads the Project-owned Canvas catalog without selecting a Project or Canvas in the Workbench.",request:"`{ projectId }`, naming one explicit portable Project.",response:"A bounded list of portable Canvas catalog entries."}}),C({id:"canvas.document.get",completion:"cancelable",audience:["web-plugin","companion"],grant:"canvas.document.read",scope:"canvas",sideEffect:"read",errors:[...P,...w],docs:{summary:"Read one authorized Canvas document projection.",description:"Returns a bounded portable structure or geometry projection from Main's authoritative Canvas application service.",request:"`{ ref, projection }`, using an explicit portable Project/Canvas reference and supported projection.",response:"The requested pathless document projection and authoritative revision."}}),C({id:"canvas.nodes.query",completion:"cancelable",audience:["web-plugin","companion"],grant:"canvas.document.read",scope:"canvas",sideEffect:"read",errors:[...P,...w],docs:{summary:"Query bounded node projections in one authorized Canvas.",description:"Executes a host-defined bounded query without exposing native paths or resource bytes.",request:"`{ ref, query }`, using an explicit portable Project/Canvas reference and bounded query.",response:"Matching node projections and the authoritative Canvas revision."}}),C({id:"canvas.transaction.execute",completion:"commit-preserving",audience:["web-plugin","companion"],grant:"canvas.document.write",scope:"canvas",sideEffect:"write",errors:[...P,...w],docs:{summary:"Commit one non-empty revision-bound Canvas transaction.",description:"Validates bounded commands against one authoritative revision and persists the accepted transaction atomically.",request:"`{ ref, expectedRevision, commands, transactionId }` with a bounded non-empty command list.",response:"The committed authoritative revision and bounded command results."}}),C({id:"canvas.events.subscribe",completion:"cancelable",audience:["web-plugin","companion"],grant:"canvas.events.subscribe",scope:"canvas",sideEffect:"subscribe",errors:[...P,...w],docs:{summary:"Subscribe to bounded events for one authorized Canvas.",description:"Creates a connection-scoped subscription; events are revisioned invalidations or safe projections, never native data.",request:"`{ ref }`, using an explicit portable Project/Canvas reference.",response:"A connection-bound subscription identifier."}}),C({id:"canvas.events.unsubscribe",completion:"cancelable",audience:["web-plugin","companion"],grant:"canvas.events.subscribe",scope:"canvas",sideEffect:"subscribe",errors:[...P,...w],docs:{summary:"Close one connection-bound Canvas event subscription.",description:"Releases a subscription created by canvas.events.subscribe without changing Canvas state.",request:"The subscription identifier returned by canvas.events.subscribe.",response:"An acknowledgement; closing an already closed subscription is idempotent."}})]),t0("2.0.0",[C({id:"canvas.inputs.image.open",completion:"cancelable",grant:"canvas.connectedImages.read",scope:"own-node",sideEffect:"read",errors:[...P,...w,...H0],docs:{summary:"Open one directly connected image through the owning Plugin node.",description:"Issues a revocable Host-owned session for signature-validated JPEG, PNG, or WebP content after validating the Plugin principal, owning node, direct edge, resource identity, and image limits. Every protocol read revalidates the issued principal and direct edge against current Host state.",request:"`{ inputKey }`, using an opaque image key returned by canvas.inputs.list.",response:"A connection-issued, revocable session with an opaque 128-bit bearer URL, bounded image probe, and lowercase SHA-256 content revision.",remarks:"Electron protocol GET/HEAD requests have no trusted sender or frame principal. Possession of the convax-connected-media URL therefore carries bearer authority until the Host revokes the session or its principal/edge revalidation fails; the URL must be kept secret and closed promptly. The response contains no image bytes, native path, or unrestricted URL. The Host rejects images above 16 MiB, dimensions above 8192 pixels, or more than 33,554,432 pixels."}}),C({id:"canvas.inputs.image.close",completion:"cancelable",grant:"canvas.connectedImages.read",scope:"own-node",sideEffect:"write",errors:[...P,...w],docs:{summary:"Close one revocable connected-image bearer session.",description:"Revokes a session and bearer URL created by canvas.inputs.image.open after validating the calling Plugin principal, without changing Canvas or Project state.",request:"`{ sessionId }`, using the opaque handle returned by canvas.inputs.image.open.",response:"An acknowledgement that the caller's image session is closed; repeated close calls are idempotent."}})])),e0=U0.apis.map(({id:F})=>F).sort();if(e0.length!==y0.length||e0.some((F,G)=>F!==y0[G]))throw TypeError("Plugin API Catalog and portable method contracts are incomplete or inconsistent");var H6=U0.version,M0=Number(H6.split(".")[0]),RF=new Map(U0.apis.map((F)=>[F.id,F])),C6=new Set(RF.keys());function N0(F){return typeof F==="string"&&C6.has(F)}function p0(F){return RF.get(F)}var w6=/^[a-z][a-z0-9]*(?:\.[a-z][a-z0-9]*)+$/;function P6(F){return typeof F==="object"&&F!==null&&!Array.isArray(F)}function FF(F,G){if(!Array.isArray(F))throw TypeError(`${G} must be an array`);let J=[],Q=new Set;for(let X of F){if(typeof X!=="string"||!w6.test(X))throw TypeError(`${G} contains an invalid Plugin API id: ${String(X)}`);if(Q.has(X))throw TypeError(`${G} contains a duplicate Plugin API id: ${X}`);Q.add(X),J.push(X)}return J}function q6(F){let G=s0(F),J=[],Q=[];for(let X of G.required){if(!N0(X))throw TypeError(`Plugin API declaration contains an unknown Plugin API id: ${X}`);J.push(X)}for(let X of G.optional){if(!N0(X))throw TypeError(`Plugin API declaration contains an unknown Plugin API id: ${X}`);Q.push(X)}return Object.freeze({major:M0,required:Object.freeze(J),optional:Object.freeze(Q)})}function s0(F){if(!P6(F))throw TypeError("Plugin API declaration must be an object");if(Object.keys(F).some((Z)=>Z!=="major"&&Z!=="required"&&Z!=="optional"))throw TypeError("Plugin API declaration contains an unknown field");if(F.major!==M0)throw TypeError(`Plugin API declaration major must be ${M0}`);let J=FF(F.required,"Plugin API declaration required"),Q=FF(F.optional,"Plugin API declaration optional"),X=new Set(J),Y=Q.find((Z)=>X.has(Z));if(Y)throw TypeError(`Plugin API cannot be both required and optional: ${Y}`);return Object.freeze({major:M0,required:Object.freeze(J),optional:Object.freeze(Q)})}function k6(F,G){if(F.required.includes(G))return"required";if(F.optional.includes(G))return"optional";return}function GF(F,G){return k6(F,G)!==void 0}class EF extends Error{availability;constructor(F){super(`Plugin API ${F.id} is unavailable: ${F.reason}`);this.name="PluginApiUnavailableError",this.availability=F}}function I6(F,G){return typeof G==="string"&&p0(F).errors.some((J)=>J.code===G)}function g6(F,G){if(!G||typeof G!=="object"||Array.isArray(G))throw TypeError(`Plugin API ${F} failure must be an object`);let J=G;if(Object.keys(J).some((X)=>!["code","kind","message","recoverable"].includes(X))||!Object.prototype.hasOwnProperty.call(J,"code")||!Object.prototype.hasOwnProperty.call(J,"message")||!Object.prototype.hasOwnProperty.call(J,"recoverable")||J.kind!=="api"||!I6(F,J.code)||typeof J.message!=="string"||J.message.length<1||J.message.length>4096||typeof J.recoverable!=="boolean")throw TypeError(`Plugin API ${F} failure is invalid`);let Q=p0(F).errors.find(({code:X})=>X===J.code);if(J.recoverable!==Q.recoverable)throw TypeError(`Plugin API ${F} failure recoverability does not match the Catalog`);return Object.freeze({code:J.code,kind:"api",message:J.message,recoverable:J.recoverable})}var x6=/^[a-z][a-z0-9]*(?:\.[a-z][a-z0-9-]*)+$/,f6=/^[a-z][a-z0-9]*(?:[._-][a-z0-9]+)*$/,h6=/^[A-Za-z][A-Za-z0-9_-]{0,63}$/,y6=/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/,c6=new Set(["none","read","write","execute","subscribe"]),TF=128,b6=64,v6=8,m6=16384,d6=256;function r0(F){return typeof F==="string"&&F.length<=160&&x6.test(F)}function n(F,G){if(!F||typeof F!=="object"||Array.isArray(F))throw TypeError(`${G} must be an object`);let J=Object.getPrototypeOf(F);if(J!==Object.prototype&&J!==null)throw TypeError(`${G} must be a plain object`);return F}function v(F,G,J,Q){let X=new Set([...G,...J]);if(G.some((Y)=>!Object.prototype.hasOwnProperty.call(F,Y))||Object.keys(F).some((Y)=>!X.has(Y)))throw TypeError(`${Q} contains unsupported or missing fields`)}function a(F,G,J=2000){if(typeof F!=="string"||F.length<1||F.length>J||F!==F.trim()||/[\u0000-\u001f\u007f]/u.test(F))throw TypeError(`${G} must be a bounded, trimmed string`);return F}function j0(F,G,J){if(!Number.isSafeInteger(F)||Number(F)<0||Number(F)>J)throw TypeError(`${G} must be a bounded non-negative integer`);return Number(F)}function c0(F,G){if(typeof F!=="string"||!y6.test(F))throw TypeError(`${G} must be a strict semantic version`);return F}function p6(F,G){let J=F.split(".").map(Number),Q=G.split(".").map(Number);for(let X=0;X<3;X+=1){let Y=J[X]-Q[X];if(Y!==0)return Y}return 0}function b0(F,G,J){if(J>v6)throw TypeError(`${G} exceeds the schema depth limit`);let Q=n(F,G);if(Q.type==="null"||Q.type==="boolean")return v(Q,["type"],[],G),Object.freeze({type:Q.type});if(Q.type==="number"||Q.type==="integer"){v(Q,["type"],["minimum","maximum"],G);let{minimum:X,maximum:Y}=Q;if(X!==void 0&&(typeof X!=="number"||!Number.isFinite(X)))throw TypeError(`${G}.minimum must be finite`);if(Y!==void 0&&(typeof Y!=="number"||!Number.isFinite(Y)))throw TypeError(`${G}.maximum must be finite`);if(X!==void 0&&Y!==void 0&&X>Y)throw TypeError(`${G} minimum exceeds maximum`);return Object.freeze({type:Q.type,...X===void 0?{}:{minimum:X},...Y===void 0?{}:{maximum:Y}})}if(Q.type==="string"){if(!Object.prototype.hasOwnProperty.call(Q,"maxLength"))throw TypeError(`${G}.maxLength is required to keep values bounded`);v(Q,["type","maxLength"],["minLength","enum"],G);let X=j0(Q.maxLength,`${G}.maxLength`,m6),Y=Q.minLength===void 0?void 0:j0(Q.minLength,`${G}.minLength`,X),Z;if(Q.enum!==void 0){if(!Array.isArray(Q.enum)||Q.enum.length<1||Q.enum.length>128||Q.enum.some((_)=>typeof _!=="string"||_.length>X)||new Set(Q.enum).size!==Q.enum.length)throw TypeError(`${G}.enum must contain unique bounded strings`);Z=Object.freeze([...Q.enum])}return Object.freeze({type:"string",maxLength:X,...Y===void 0?{}:{minLength:Y},...Z===void 0?{}:{enum:Z}})}if(Q.type==="array"){v(Q,["type","items","maxItems"],["minItems"],G);let X=j0(Q.maxItems,`${G}.maxItems`,d6),Y=Q.minItems===void 0?void 0:j0(Q.minItems,`${G}.minItems`,X);return Object.freeze({type:"array",items:b0(Q.items,`${G}.items`,J+1),maxItems:X,...Y===void 0?{}:{minItems:Y}})}if(Q.type==="object"){if(v(Q,["type","properties","required","additionalProperties"],[],G),Q.additionalProperties!==!1)throw TypeError(`${G}.additionalProperties must be false`);let X=n(Q.properties,`${G}.properties`),Y=Object.keys(X);if(Y.length>b6)throw TypeError(`${G} has too many properties`);if(Y.some((_)=>!h6.test(_)))throw TypeError(`${G} contains an invalid property name`);if(!Array.isArray(Q.required)||Q.required.some((_)=>typeof _!=="string"||!Y.includes(_))||new Set(Q.required).size!==Q.required.length)throw TypeError(`${G}.required must contain unique declared properties`);let Z=Object.fromEntries(Y.sort().map((_)=>[_,b0(X[_],`${G}.properties.${_}`,J+1)]));return Object.freeze({type:"object",properties:Object.freeze(Z),required:Object.freeze([...Q.required].sort()),additionalProperties:!1})}throw TypeError(`${G}.type is unsupported`)}function O0(F,G){let J=b0(F,G,0);if(J.type!=="object")throw TypeError(`${G} must be a closed object schema`);return J}function s6(F,G){let J=n(F,G);v(J,["id","inputSchema","outputSchema","version"],[],G);let Q=a(J.id,`${G}.id`,160);if(!r0(Q))throw TypeError(`${G}.id is invalid`);let X=n(J.version,`${G}.version`);v(X,["minimum","maximumExclusive"],[],`${G}.version`);let Y=c0(X.minimum,`${G}.version.minimum`),Z=c0(X.maximumExclusive,`${G}.version.maximumExclusive`);if(p6(Y,Z)>=0)throw TypeError(`${G}.version must be a non-empty half-open interval`);return Object.freeze({id:Q,inputSchema:O0(J.inputSchema,`${G}.inputSchema`),outputSchema:O0(J.outputSchema,`${G}.outputSchema`),version:Object.freeze({minimum:Y,maximumExclusive:Z})})}function JF(F,G){if(!Array.isArray(F)||F.length>TF)throw TypeError(`${G} must be a bounded array`);let J=F.map((Q,X)=>s6(Q,`${G}[${X}]`)).sort((Q,X)=>Q.id.localeCompare(X.id));if(J.some((Q,X)=>X>0&&J[X-1].id===Q.id))throw TypeError(`${G} contains a duplicate capability id`);return Object.freeze(J)}function r6(F,G){let J=n(F,G);v(J,["id","version","operation","sideEffect","inputSchema","outputSchema","docs"],[],G);let Q=a(J.id,`${G}.id`,160);if(!r0(Q))throw TypeError(`${G}.id is invalid`);let X=a(J.operation,`${G}.operation`,128);if(!f6.test(X))throw TypeError(`${G}.operation is invalid`);if(!c6.has(J.sideEffect))throw TypeError(`${G}.sideEffect is invalid`);let Y=n(J.docs,`${G}.docs`);v(Y,["summary","request","response"],["remarks"],`${G}.docs`);let Z=Object.freeze({summary:a(Y.summary,`${G}.docs.summary`),request:a(Y.request,`${G}.docs.request`),response:a(Y.response,`${G}.docs.response`),...Y.remarks===void 0?{}:{remarks:a(Y.remarks,`${G}.docs.remarks`)}});return Object.freeze({id:Q,version:c0(J.version,`${G}.version`),operation:X,sideEffect:J.sideEffect,inputSchema:O0(J.inputSchema,`${G}.inputSchema`),outputSchema:O0(J.outputSchema,`${G}.outputSchema`),docs:Z})}function o6(F){let G=n(F,"Plugin capability declaration");if(v(G,["exports","imports"],[],"Plugin capability declaration"),!Array.isArray(G.exports)||G.exports.length>TF)throw TypeError("Plugin capability exports must be a bounded array");let J=G.exports.map((M,K)=>r6(M,`Plugin capability exports[${K}]`)).sort((M,K)=>M.id.localeCompare(K.id));if(J.some((M,K)=>K>0&&J[K-1].id===M.id))throw TypeError("Plugin capability exports contain a duplicate capability id");if(new Set(J.map((M)=>M.operation)).size!==J.length)throw TypeError("Plugin capability exports contain a duplicate provider operation");let Q=n(G.imports,"Plugin capability imports");v(Q,["required","optional"],[],"Plugin capability imports");let X=JF(Q.required,"Plugin required capability imports"),Y=JF(Q.optional,"Plugin optional capability imports"),Z=new Set(X.map(({id:M})=>M)),_=Y.find(({id:M})=>Z.has(M));if(_)throw TypeError(`Plugin capability import cannot be both required and optional: ${_.id}`);return Object.freeze({exports:Object.freeze(J),imports:Object.freeze({required:X,optional:Y})})}function v0(F,G,J,Q){if(F.type==="null"){if(G!==null)throw TypeError(`${J} must be null`);return}if(F.type==="boolean"){if(typeof G!=="boolean")throw TypeError(`${J} must be boolean`);return}if(F.type==="number"||F.type==="integer"){if(typeof G!=="number"||!Number.isFinite(G)||F.type==="integer"&&!Number.isSafeInteger(G))throw TypeError(`${J} must be a finite ${F.type==="integer"?"safe integer":"number"}`);if(F.minimum!==void 0&&GF.maximum)throw TypeError(`${J} exceeds maximum`);return}if(F.type==="string"){if(typeof G!=="string"||G.length<(F.minLength??0)||G.length>F.maxLength||F.enum!==void 0&&!F.enum.includes(G))throw TypeError(`${J} is not an admitted string`);return}if(!G||typeof G!=="object")throw TypeError(`${J} must be ${F.type}`);if(Q.has(G))throw TypeError(`${J} cannot be cyclic`);Q.add(G);try{if(F.type==="array"){if(!Array.isArray(G)||G.length<(F.minItems??0)||G.length>F.maxItems)throw TypeError(`${J} is not an admitted array`);G.forEach((Z,_)=>v0(F.items,Z,`${J}[${_}]`,Q));return}if(Array.isArray(G))throw TypeError(`${J} must be an object`);let X=Object.getPrototypeOf(G);if(X!==Object.prototype&&X!==null)throw TypeError(`${J} must be a plain object`);let Y=G;for(let Z of F.required)if(!Object.prototype.hasOwnProperty.call(Y,Z))throw TypeError(`${J}.${Z} is required`);for(let[Z,_]of Object.entries(Y)){let M=F.properties[Z];if(!M)throw TypeError(`${J} contains unsupported property: ${Z}`);v0(M,_,`${J}.${Z}`,Q)}}finally{Q.delete(G)}}function QF(F,G,J="Plugin capability value"){v0(F,G,J,new Set)}var u6=/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[A-Za-z-][0-9A-Za-z-]*)(?:\.(?:0|[1-9]\d*|\d*[A-Za-z-][0-9A-Za-z-]*))*))?(?:\+([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?$/,n6=/^(CON|PRN|AUX|NUL|COM[1-9¹²³]|LPT[1-9¹²³]|CONIN\$|CONOUT\$)$/i;function A(F,G){if(!F||typeof F!=="object"||Array.isArray(F))throw TypeError(`${G} must be an object`);let J=Object.getPrototypeOf(F);if(J!==Object.prototype&&J!==null)throw TypeError(`${G} must be a plain object`);return F}function R(F,G,J){let Q=new Set(G),X=Object.keys(F).find((Y)=>!Q.has(Y));if(X)throw TypeError(`${J} contains an unsupported field: ${X}`)}function T(F,G,J){if(typeof F!=="string"||F.length<1||F.length>J||F!==F.trim()||/[\u0000-\u001f\u007f]/u.test(F))throw TypeError(`${G} must be a bounded, trimmed string`);return F}function c(F,G,J,Q=!1){if(!Array.isArray(F)||F.length>J||Q&&F.length===0)throw TypeError(`${G} must be ${Q?"a non-empty ":"a "}bounded array with at most ${J} items`);return F}function BF(F){if(F&&typeof F==="object"&&!Object.isFrozen(F)){for(let G of Object.values(F))BF(G);Object.freeze(F)}return F}function t6(F){let G=T(F,"Plugin version",128);if(!u6.test(G))throw TypeError("Plugin version must be valid SemVer");return G}function E0(F){let G=F.split(".")[0]??"";if(!F||F.length>255||F==="."||F===".."||/[\\/:*?"<>|\u0000-\u001f\u007f]/u.test(F)||/[. ]$/u.test(F)||n6.test(G))throw TypeError(`Plugin path contains an invalid Windows filename: ${F}`);return F}function HF(F){let G=T(F,"Plugin id",80);if(!/^[a-z0-9]+(?:-[a-z0-9]+)*$/u.test(G))throw TypeError("Plugin id must use kebab-case");return E0(G),G}function X0(F,G="Plugin path"){let J=T(F,G,1024);if(J.includes("\\")||J.startsWith("/")||/^[A-Za-z]:/u.test(J)||J.startsWith("//"))throw TypeError(`${G} must be a portable relative path`);let Q=J.split("/");if(Q.some((X)=>!X||X==="."||X===".."))throw TypeError(`${G} must be a portable relative path`);return Q.forEach(E0),J}function C0(F,G,J){if(F===void 0)return;let Q=c(F,G,64).map((X)=>J(T(X,G,128)));if(new Set(Q).size!==Q.length)throw TypeError(`${G} contains duplicate values`);return Q}function Y0(F,G,J=80){let Q=T(F,G,J);if(!/^[a-z0-9]+(?:[._-][a-z0-9]+)*$/u.test(Q))throw TypeError(`${G} is invalid: ${Q}`);return Q}var u="convax.plugin-host/8",i6=V6,a6=L6,w0=1048576,XF=4194304,l6=128,YF=16,e6=128,F1=64,V0=Math.ceil(i6/2),G1=/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/,J1=new Set(["not-declared","provider-missing","provider-incompatible","provider-ambiguous","self-provider","dependency-cycle","setup-required","disabled","recovering","contract-mismatch"]),CF=Object.freeze({canceled:{recoverable:!0},"contract-mismatch":{recoverable:!1},"depth-exceeded":{recoverable:!1},"duplicate-request":{recoverable:!1},"execution-failed":{recoverable:!1},"invalid-input":{recoverable:!1},"invalid-output":{recoverable:!1},overloaded:{recoverable:!0},"provider-unavailable":{recoverable:!0},"reentrant-call":{recoverable:!1}}),wF=new Set(Object.keys(CF)),PF=Object.freeze({canceled:{recoverable:!0},"internal-error":{recoverable:!1},"invalid-request":{recoverable:!1},overloaded:{recoverable:!0},"transport-closed":{recoverable:!0}}),qF=new Set(Object.keys(PF)),Q1=new Set(U0.apis.flatMap((F)=>F.errors.map(({code:G})=>G)));function e(F){if(!F||typeof F!=="object"||Array.isArray(F))return;let G=Object.getPrototypeOf(F);return G===Object.prototype||G===null?F:void 0}function ZF(F){let G=2;for(let J=0;J=55296&&Q<=57343){let X=F.charCodeAt(J+1);if(Q>=55296&&Q<=56319&&X>=56320&&X<=57343)G+=4,J+=1;else G+=6}else if(Q<128)G+=1;else if(Q<2048)G+=2;else G+=3}return G}function P0(F,G,J="Plugin Host message"){if(!Number.isSafeInteger(G)||G<1)throw TypeError(`${J} byte limit is invalid`);let Q=[{depth:0,value:F}],X=new WeakSet,Y=0,Z=0,_=(M)=>{if(Y+=M,Y>G)throw RangeError(`${J} exceeds ${G} bytes`)};while(Q.length>0){let M=Q.pop(),K=M.value;if(K===null){_(4);continue}if(typeof K==="string"){_(ZF(K));continue}if(typeof K==="boolean"){_(K?4:5);continue}if(typeof K==="number"){if(!Number.isFinite(K))throw TypeError(`${J} must contain finite JSON numbers`);_(Object.is(K,-0)?1:String(K).length);continue}if(!K||typeof K!=="object")throw TypeError(`${J} must be a JSON value`);if(M.depth>F1||X.has(K))throw TypeError(`${J} must be a bounded acyclic JSON tree`);if(X.add(K),Array.isArray(K)){if(Z+=K.length,Z>V0)throw RangeError(`${J} exceeds ${V0} JSON entries`);if(_(2+Math.max(0,K.length-1)),Object.getOwnPropertySymbols(K).length>0)throw TypeError(`${J} arrays must not contain symbol properties`);let O=0;for(let L in K){if(!Object.prototype.hasOwnProperty.call(K,L))continue;if(!/^(0|[1-9]\d*)$/u.test(L)||Number(L)>=K.length)throw TypeError(`${J} arrays must contain only indexed entries`);let k=Object.getOwnPropertyDescriptor(K,L);if(!k?.enumerable||!("value"in k))throw TypeError(`${J} arrays must contain enumerable data properties`);O+=1,Q.push({depth:M.depth+1,value:k.value})}if(O!==K.length)throw TypeError(`${J} arrays must be dense JSON arrays`);continue}let D=Object.getPrototypeOf(K);if(D!==Object.prototype&&D!==null)throw TypeError(`${J} must contain plain JSON objects`);if(Object.getOwnPropertySymbols(K).length>0)throw TypeError(`${J} must not contain symbol properties`);_(2);let j=0;for(let O in K){if(!Object.prototype.hasOwnProperty.call(K,O))continue;let L=Object.getOwnPropertyDescriptor(K,O);if(!L?.enumerable||!("value"in L))throw TypeError(`${J} objects must contain enumerable data properties`);if(j+=1,Z+=1,Z>V0)throw RangeError(`${J} exceeds ${V0} JSON entries`);_((j===1?0:1)+ZF(O)+1),Q.push({depth:M.depth+1,value:L.value})}}return Y}function o(F,G,J=[]){let Q=new Set([...G,...J]);return G.every((X)=>Object.prototype.hasOwnProperty.call(F,X))&&Object.keys(F).every((X)=>Q.has(X))}function kF(F){return typeof F==="string"&&F.length>0&&F.length<=e6&&F===F.trim()&&!/[\u0000-\u001f\u007f]/u.test(F)}function X1(F){return typeof F==="string"&&F.length>0&&F.length<=128&&F===F.trim()&&!/[\u0000-\u001f\u007f]/u.test(F)}function IF(F){let G=e(F);if(!G||!o(G,["pluginId","protocol","type"])||G.protocol!==u||G.type!=="connect")return!1;try{return HF(G.pluginId),!0}catch{return!1}}function Y1(F){let G=e(F);if(!G||G.protocol!==u||G.type!=="response"||!kF(G.id))return!1;if(G.ok===!0)return o(G,["id","ok","protocol","result","type"]);if(G.ok!==!1||!o(G,["error","id","ok","protocol","type"]))return!1;let J=e(G.error);return Boolean(J&&o(J,["code","kind","message","recoverable"])&&typeof J.code==="string"&&(J.kind==="api"&&Q1.has(J.code)||J.kind==="capability"&&wF.has(J.code)||J.kind==="protocol"&&qF.has(J.code))&&typeof J.message==="string"&&J.message.length>0&&J.message.length<=4096&&typeof J.recoverable==="boolean")}function Z1(F){let G=e(F);return Boolean(G&&o(G,["command","protocol","type"],["params"])&&G.protocol===u&&G.type==="command"&&X1(G.command))}function _1(F){let G=e(F);if(!G||typeof G.available!=="boolean")throw TypeError("Plugin capability availability must be a closed object");let J=G.requirement;if(J!=="required"&&J!=="optional")throw TypeError("Plugin capability availability requirement is invalid");if(!r0(G.capabilityId))throw TypeError("Plugin capability availability id is invalid");if(G.available){if(!o(G,["available","capabilityId","requirement","version"])||typeof G.version!=="string"||!G1.test(G.version))throw TypeError("Available Plugin capability result is invalid");return Object.freeze({available:!0,capabilityId:G.capabilityId,requirement:J,version:G.version})}if(!o(G,["available","capabilityId","reason","recoverable","requirement"])||typeof G.reason!=="string"||!J1.has(G.reason)||typeof G.recoverable!=="boolean")throw TypeError("Unavailable Plugin capability result is invalid");return Object.freeze({available:!1,capabilityId:G.capabilityId,reason:G.reason,recoverable:G.recoverable,requirement:J})}function $1(F){let G=e(F);if(!G||!o(G,["code","kind","message","recoverable"])||G.kind!=="capability"||typeof G.code!=="string"||!wF.has(G.code)||typeof G.message!=="string"||G.message.length<1||G.message.length>4096||typeof G.recoverable!=="boolean")throw TypeError("Plugin capability failure is invalid");let J=G.code;if(G.recoverable!==CF[J].recoverable)throw TypeError("Plugin capability failure recoverability is invalid");return Object.freeze({code:J,kind:"capability",message:G.message,recoverable:G.recoverable})}function gF(F){let G=e(F);if(!G||!o(G,["code","kind","message","recoverable"])||G.kind!=="protocol"||typeof G.code!=="string"||!qF.has(G.code)||typeof G.message!=="string"||G.message.length<1||G.message.length>4096||typeof G.recoverable!=="boolean")throw TypeError("Plugin Host protocol failure is invalid");let J=G.code;if(G.recoverable!==PF[J].recoverable)throw TypeError("Plugin Host protocol failure recoverability is invalid");return Object.freeze({code:J,kind:"protocol",message:G.message,recoverable:G.recoverable})}var K1=["download","edit","open","play","refresh","settings","sparkles","upload"],xF=/^[a-z][a-z0-9]*(?:[._-][a-z0-9]+)*$/,M1=/^[a-z][a-z0-9]*(?:[._-][a-z0-9]+)*$/,S1=/^[a-z][a-z0-9]*(?:[._-][a-z0-9]+)*$/,D1=128,_F=128,$F=1e4;function U1(F){return Boolean(F)&&typeof F==="object"&&!Array.isArray(F)}function S0(F,G){if(!U1(F))throw TypeError(`${G} must be an object`);let J=Object.getPrototypeOf(F);if(J!==Object.prototype&&J!==null)throw TypeError(`${G} must be a plain object`);return F}function D0(F,G,J,Q){let X=new Set([...G,...J]);if(G.some((Y)=>!Object.prototype.hasOwnProperty.call(F,Y))||Object.keys(F).some((Y)=>!X.has(Y)))throw TypeError(`${Q} contains unsupported or missing fields`)}function z0(F,G,J){if(typeof F!=="string"||F.length<1||F.length>J||F!==F.trim()||/[\u0000-\u001f\u007f]/u.test(F))throw TypeError(`${G} must be a bounded, trimmed string`);return F}function A0(F,G,J,Q){let X=z0(F,G,Q);if(!J.test(X))throw TypeError(`${G} must be a stable Plugin-local id`);return X}function W1(F,G){if(!Number.isSafeInteger(F)||Number(F)<-$F||Number(F)>$F)throw TypeError(`${G} must be a bounded safe integer`);return Number(F)}function j1(F,G){let J=S0(F,G);return D0(J,["default"],["zh-CN"],G),Object.freeze({default:z0(J.default,`${G}.default`,120),...J["zh-CN"]===void 0?{}:{"zh-CN":z0(J["zh-CN"],`${G}.zh-CN`,120)}})}function V1(F){return K1.some((G)=>G===F)}function L1(F,G){let J=`Plugin UI commands[${G}]`,Q=S0(F,J);D0(Q,["id","title","target"],["icon"],J);let X=S0(Q.target,`${J}.target`);if(X.type!=="renderer-message")throw TypeError(`${J}.target.type must be renderer-message`);D0(X,["type","message"],[],`${J}.target`);let Y=Q.icon;if(Y!==void 0&&!V1(Y))throw TypeError(`${J}.icon must be a supported Host icon token`);return Object.freeze({id:A0(Q.id,`${J}.id`,xF,128),title:j1(Q.title,`${J}.title`),target:Object.freeze({type:"renderer-message",message:z0(X.message,`${J}.target.message`,128)}),...Y===void 0?{}:{icon:Y}})}function fF(F,G,J,Q){let X=S0(F,G);return D0(X,J,Q,G),{input:X,id:A0(X.id,`${G}.id`,M1,128),command:A0(X.command,`${G}.command`,xF,128),...X.order===void 0?{}:{order:W1(X.order,`${G}.order`)}}}function N1(F,G){let{input:J,...Q}=fF(F,`Plugin UI toolbar[${G}]`,["id","command"],["order"]);return Object.freeze(Q)}function O1(F,G){let J=`Plugin UI menus[${G}]`,Q=fF(F,J,["id","command","placement"],["group","order"]);if(Q.input.placement!=="overflow")throw TypeError(`${J}.placement must be overflow`);let X=Q.input.group===void 0?void 0:A0(Q.input.group,`${J}.group`,S1,64),{input:Y,...Z}=Q;return Object.freeze({...Z,placement:"overflow",...X===void 0?{}:{group:X}})}function q0(F,G,J){if(!Array.isArray(F)||F.length>J)throw TypeError(`${G} must be a bounded array`);return F}function k0(F,G){let J=new Set;for(let Q of F){if(J.has(Q.id))throw TypeError(`${G} contains a duplicate id: ${Q.id}`);J.add(Q.id)}}function KF(F,G){let J=new Set;for(let Q of F){if(J.has(Q.command))throw TypeError(`${G} contains a duplicate command reference: ${Q.command}`);J.add(Q.command)}}function z1(F){let G=S0(F,"Plugin Canvas UI contribution");D0(G,[],["commands","menus","toolbar"],"Plugin Canvas UI contribution");let J=Object.freeze(q0(G.commands===void 0?[]:G.commands,"Plugin UI commands",D1).map(L1)),Q=Object.freeze(q0(G.menus===void 0?[]:G.menus,"Plugin UI menus",_F).map(O1)),X=Object.freeze(q0(G.toolbar===void 0?[]:G.toolbar,"Plugin UI toolbar",_F).map(N1));k0(J,"Plugin UI commands"),k0(Q,"Plugin UI menus"),k0(X,"Plugin UI toolbar");let Y=new Set(Q.map((j)=>j.id)),Z=X.find((j)=>Y.has(j.id));if(Z)throw TypeError(`Plugin UI placements contain a duplicate id: ${Z.id}`);KF(Q,"Plugin UI menus"),KF(X,"Plugin UI toolbar");let _=new Set(J.map((j)=>j.id)),M=[...Q,...X].find((j)=>!_.has(j.command));if(M)throw TypeError(`Plugin UI placement references an unknown command: ${M.command}`);let K=new Set([...Q,...X].map((j)=>j.command)),D=J.find((j)=>!K.has(j.id));if(D)throw TypeError(`Plugin UI command has no owning-node placement: ${D.id}`);return Object.freeze({commands:J,menus:Q,toolbar:X})}var A1=["time-point","time-range","crop-region","confirmation","immediate"];function R1(F){return A1.some((G)=>G===F)}function E1(F,G){if(F==="image"||F==="video")return F;throw TypeError(`${G} target must be image or video`)}function MF(F,G){if(!Number.isSafeInteger(F)||Number(F)<1||Number(F)>8192)throw TypeError(`${G} must be an integer between 1 and 8192`);return Number(F)}function T1(F){let G=A(F,"Canvas renderer contribution");if(R(G,["create","extensions","height","mimeTypes","nodeKinds","width"],"Canvas renderer contribution"),G.create!==void 0&&typeof G.create!=="boolean")throw TypeError("Canvas renderer create must be a boolean");let J=C0(G.extensions,"Canvas renderer extensions",(Y)=>{let Z=Y.toLowerCase();if(!/^\.[a-z0-9][a-z0-9._+-]{0,31}$/u.test(Z))throw TypeError(`Invalid Canvas renderer extension: ${Y}`);return Z}),Q=C0(G.mimeTypes,"Canvas renderer MIME types",(Y)=>{let Z=Y.toLowerCase();if(!/^[a-z0-9][a-z0-9!#$&^_.+-]*\/[a-z0-9][a-z0-9!#$&^_.+-]*$/u.test(Z))throw TypeError(`Invalid Canvas renderer MIME type: ${Y}`);return Z}),X=C0(G.nodeKinds,"Canvas renderer node kinds",(Y)=>{if(!/^[a-z][a-z0-9]*(?:[._-][a-z0-9]+)*$/u.test(Y))throw TypeError(`Invalid Canvas renderer node kind: ${Y}`);return Y});if(G.create!==!0&&!J?.length&&!Q?.length&&!X?.length)throw TypeError("Canvas renderer must be creatable or match an extension, MIME type, or node kind");return{...G.create===void 0?{}:{create:G.create},...J===void 0?{}:{extensions:J},...G.height===void 0?{}:{height:MF(G.height,"Canvas renderer height")},...Q===void 0?{}:{mimeTypes:Q},...X===void 0?{}:{nodeKinds:X},...G.width===void 0?{}:{width:MF(G.width,"Canvas renderer width")}}}function L0(F,G,J){let Q=A(F,G);return R(Q,["default","zh-CN"],G),{default:T(Q.default,`${G} default`,J),...Q["zh-CN"]===void 0?{}:{"zh-CN":T(Q["zh-CN"],`${G} zh-CN`,J)}}}function B1(F){let G=c(F,"Canvas selection actions",32,!0).map((J,Q)=>{let X=`Canvas selection action ${Q}`,Y=A(J,X);if(Y.action!==void 0){R(Y,["action","description","id","target","title"],X);let D=Y0(Y.id,`${X} id`);if(Y.target!=="video")throw TypeError(`${X} target must be video`);let j=A(Y.action,`${X} action`);if(R(j,["connect","type"],`${X} action`),j.type!=="materialize-own-plugin-node"||j.connect!=="selection-to-created")throw TypeError(`${X} materialization action is not supported`);return{action:{connect:"selection-to-created",type:"materialize-own-plugin-node"},description:L0(Y.description,`${X} description`,2000),id:D,target:"video",title:L0(Y.title,`${X} title`,120)}}R(Y,["description","editor","id","presentation","steps","target","title"],X);let Z=Y0(Y.id,`${X} id`),_=E1(Y.target,X);if(!R1(Y.editor))throw TypeError(`${X} editor is not supported`);let M=Y.editor;if(M==="immediate"!==(_==="image"&&Y.presentation==="cutout-scan")||Y.presentation!==void 0&&Y.presentation!=="cutout-scan")throw TypeError(`${X} immediate editor requires image target and cutout-scan presentation`);let K=c(Y.steps,`${X} steps`,16,!0).map((D,j)=>{let O=`${X} step ${j}`,L=A(D,O);return R(L,["tool"],O),{tool:Y0(L.tool,`${O} tool`)}});if(M!=="confirmation"&&K.length!==1)throw TypeError(`${X} editor requires exactly one step`);return{description:L0(Y.description,`${X} description`,2000),editor:M,id:Z,...Y.presentation===void 0?{}:{presentation:"cutout-scan"},steps:K,target:_,title:L0(Y.title,`${X} title`,120)}});if(new Set(G.map((J)=>J.id)).size!==G.length)throw TypeError("Canvas selection actions contain duplicate ids");return G}function H1(F){let G=A(F,"Canvas contributions");R(G,["commands","menus","renderer","selectionActions","toolbar"],"Canvas contributions");let J=z1({...G.commands===void 0?{}:{commands:G.commands},...G.menus===void 0?{}:{menus:G.menus},...G.toolbar===void 0?{}:{toolbar:G.toolbar}});return{...G.commands===void 0?{}:{commands:J.commands},...G.menus===void 0?{}:{menus:J.menus},...G.renderer===void 0?{}:{renderer:T1(G.renderer)},...G.selectionActions===void 0?{}:{selectionActions:B1(G.selectionActions)},...G.toolbar===void 0?{}:{toolbar:J.toolbar}}}var C1=["text","image","video","audio"],hF=["reference_image","reference_video","first_frame","last_frame","audio","text"],w1=new Set(C1),P1=new Set(hF),q1=/^[a-z][a-z0-9_]{0,63}$/;function k1(F,G){let Q=c(F,G,hF.length).map((X)=>{if(typeof X!=="string"||!P1.has(X))throw TypeError(`${G} contain an unsupported or duplicate role`);return X});if(new Set(Q).size!==Q.length)throw TypeError(`${G} contain an unsupported or duplicate role`);return Q}function I1(F){let G=A(F,"Generation contribution");if(R(G,["models","tools"],"Generation contribution"),!Object.prototype.hasOwnProperty.call(G,"models"))throw TypeError("convax.plugin/8 generation models must be declared explicitly");let J=c(G.tools,"Generation tools",64,!0).map((_,M)=>{let K=`Generation tool ${M}`,D=A(_,K);R(D,["acceptedInputs","delivery","description","id","inputBinding","output","recovery","title"],K);let j=Y0(D.id,`${K} id`);if(typeof D.output!=="string"||!w1.has(D.output))throw TypeError(`${K} output is not supported`);if(D.delivery!==void 0&&D.delivery!=="canvas"&&D.delivery!=="return")throw TypeError(`${K} delivery is not supported`);if(D.delivery==="return"&&D.output!=="text")throw TypeError(`${K} return delivery requires text output`);let O=k1(D.acceptedInputs,`${K} acceptedInputs`);if(D.inputBinding!==void 0&&D.inputBinding!=="direct-incoming")throw TypeError(`${K} input binding is not supported`);if(D.inputBinding==="direct-incoming"&&O.length===0)throw TypeError(`${K} direct-incoming input binding requires accepted inputs`);let L;if(D.recovery!==void 0){let k=A(D.recovery,`${K} recovery`);if(R(k,["mode","schema"],`${K} recovery`),k.schema!=="convax.generation-lro/1"||k.mode!=="long-running-operation")throw TypeError(`${K} recovery contract is not supported`);L={mode:"long-running-operation",schema:"convax.generation-lro/1"}}return{acceptedInputs:O,...D.delivery===void 0?{}:{delivery:D.delivery},description:T(D.description,`${K} description`,2000),id:j,...D.inputBinding===void 0?{}:{inputBinding:D.inputBinding},output:D.output,...L===void 0?{}:{recovery:L},title:T(D.title,`${K} title`,120)}});if(new Set(J.map((_)=>_.id)).size!==J.length)throw TypeError("Generation tools contain duplicate ids");let Q=c(G.models,"Generation models",J.length).map((_,M)=>{let K=`Generation model ${M}`,D=A(_,K);return R(D,["name","tool"],K),{name:T(D.name,`${K} name`,120),tool:Y0(D.tool,`${K} tool`)}});if(new Set(Q.map((_)=>_.tool)).size!==Q.length)throw TypeError("Generation models contain duplicate tool references");let X=new Set(Q.map((_)=>_.tool)),Y=J.find((_)=>_.delivery==="return"&&X.has(_.id));if(Y)throw TypeError(`Generation model cannot reference a return-delivery operation: ${Y.id}`);let Z=J.find((_)=>_.inputBinding!==void 0&&X.has(_.id));if(Z)throw TypeError(`Generation model cannot reference an input-bound operation: ${Z.id}`);return{models:Q,tools:J}}function g1(F){let G=c(F,"Agent tools",32,!0).map((J,Q)=>{let X=`Agent tool ${Q}`,Y=A(J,X);R(Y,["id","tool"],X);let Z=T(Y.id,`${X} id`,64);if(!q1.test(Z))throw TypeError(`${X} id must use lower snake_case`);return{id:Z,tool:Y0(Y.tool,`${X} generation tool`)}});if(new Set(G.map((J)=>J.id)).size!==G.length)throw TypeError("Agent tools contain duplicate ids");if(new Set(G.map((J)=>J.tool)).size!==G.length)throw TypeError("Agent tools contain duplicate generation tool references");return G}function x1(F){let G=A(F,"Agent remote MCP contribution");if(R(G,["headers","oauth","type","url"],"Agent remote MCP contribution"),G.type!=="remote")throw TypeError("Agent MCP type must be remote");let J=T(G.url,"Agent remote MCP URL",2048);try{let X=new URL(J);if(X.protocol!=="https:"||X.username!==""||X.password!==""||X.hash!=="")throw TypeError()}catch{throw TypeError("Agent remote MCP URL must be an absolute HTTPS URL without credentials or a fragment")}if(G.oauth!==void 0&&G.oauth!=="auto"&&G.oauth!=="none")throw TypeError("Agent remote MCP oauth must be auto or none");let Q;if(G.headers!==void 0){let X=A(G.headers,"Agent remote MCP headers"),Y=Object.entries(X);if(Y.length>16)throw TypeError("Agent remote MCP headers must contain at most 16 entries");let Z=new Set;Q={};for(let[_,M]of Y){if(!/^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/u.test(_))throw TypeError(`Agent remote MCP header name is invalid: ${_}`);let K=_.toLowerCase();if(Z.has(K))throw TypeError(`Agent remote MCP headers contain a duplicate name: ${_}`);if(K==="authorization"||K==="cookie"||K==="proxy-authorization")throw TypeError(`Agent remote MCP header is not allowed: ${_}`);let D=T(M,`Agent remote MCP header ${_}`,2048);if(/\{(?:env|file):/iu.test(D)||/\$\{[^}]*\}/u.test(D))throw TypeError(`Agent remote MCP header ${_} must be a literal value`);Z.add(K),Q[_]=D}}return{...Q===void 0?{}:{headers:Q},oauth:G.oauth==="none"?"none":"auto",type:"remote",url:J}}function f1(F){let G=A(F,"Agent contribution");R(G,["mcp","tools"],"Agent contribution");let J=G.tools===void 0?void 0:g1(G.tools),Q=G.mcp===void 0?void 0:x1(G.mcp);if(J===void 0&&Q===void 0)throw TypeError("Agent contribution must declare tools or mcp");return{...Q===void 0?{}:{mcp:Q},...J===void 0?{}:{tools:J}}}function h1(F){let G=new Map(F.generation?.tools.map((Q)=>[Q.id,Q])??[]),J=new Set(F.generation?.models.map((Q)=>Q.tool)??[]);for(let Q of J)if(!G.has(Q))throw TypeError(`Generation model references an unknown tool: ${Q}`);for(let Q of F.agent?.tools??[]){if(!G.has(Q.tool))throw TypeError(`Agent tool references an unknown generation tool: ${Q.tool}`);if(J.has(Q.tool))throw TypeError(`Agent tool must reference an operation, not a generation model: ${Q.tool}`)}for(let Q of F.selectionActions??[]){if(!("steps"in Q))continue;for(let X of Q.steps){let Y=G.get(X.tool);if(!Y)throw TypeError(`Canvas selection action references an unknown generation tool: ${X.tool}`);if(J.has(X.tool))throw TypeError(`Canvas selection action must reference an operation, not a generation model: ${X.tool}`);if(Y.inputBinding!==void 0)throw TypeError(`Canvas selection action cannot reference an input-bound operation: ${X.tool}`);let Z=Q.target==="image"?"reference_image":"reference_video";if(!Y.acceptedInputs.includes(Z))throw TypeError(`Canvas ${Q.target} selection action tool must accept ${Z}: ${X.tool}`);if(Y.delivery==="return"){if(Q.editor!=="confirmation")throw TypeError(`Canvas return-delivery operation requires a confirmation editor: ${X.tool}`);if(Q.steps.length!==1)throw TypeError(`Canvas return-delivery operation requires exactly one step: ${X.tool}`);if(Y.output!=="text")throw TypeError(`Canvas return-delivery operation must return text: ${X.tool}`)}else if(Q.target==="image"&&(Q.editor!=="immediate"||Q.presentation!=="cutout-scan"||Q.steps.length!==1||Y.output!=="image"))throw TypeError(`Canvas image output requires one immediate image operation with cutout-scan presentation: ${X.tool}`)}}}var yF=["authorize","reauthorize","authorization.cancel","checkout","sign_out"],y1=new Set(yF);function c1(F){let G=A(F,"Service contribution");R(G,["actions"],"Service contribution");let J=c(G.actions,"Service actions",yF.length).map((Q)=>{if(typeof Q!=="string"||!y1.has(Q))throw TypeError("Service actions contain an unsupported or duplicate action");return Q});if(new Set(J).size!==J.length)throw TypeError("Service actions contain an unsupported or duplicate action");return{actions:J}}function b1(F){let G=A(F,"LLM contribution");R(G,["modelCatalog","models","provider"],"LLM contribution");let J=A(G.provider,"LLM provider");R(J,["id","name"],"LLM provider");let Q=T(J.id,"LLM provider id",80);if(!/^[a-z0-9]+(?:-[a-z0-9]+)*$/u.test(Q))throw TypeError("LLM provider id must use kebab-case");if(G.modelCatalog!==void 0&&G.modelCatalog!=="runtime")throw TypeError("LLM model catalog must be runtime");let X=c(G.models,"LLM models",32,!0).map((Y,Z)=>{let _=`LLM model ${Z}`,M=A(Y,_);R(M,["id","name"],_);let K=T(M.id,`${_} id`,128);if(!/^~?[a-z0-9]+(?:[._/:-][a-z0-9]+)*$/u.test(K))throw TypeError(`${_} id is invalid`);return{id:K,name:T(M.name,`${_} name`,120)}});if(new Set(X.map((Y)=>Y.id)).size!==X.length)throw TypeError("LLM models contain duplicate ids");return{...G.modelCatalog===void 0?{}:{modelCatalog:"runtime"},models:X,provider:{id:Q,name:T(J.name,"LLM provider name",120)}}}function v1(F){let G=A(F,"Pet contribution");R(G,["library","overlay","protocol","settings"],"Pet contribution");let J=X0(G.library,"Pet library"),Q=X0(G.overlay,"Pet overlay"),X=X0(G.settings,"Pet settings");if(!J.toLowerCase().endsWith(".json"))throw TypeError("Pet library must be a JSON file");if(!Q.toLowerCase().endsWith(".html"))throw TypeError("Pet overlay must be an HTML file");if(!X.toLowerCase().endsWith(".html"))throw TypeError("Pet settings must be an HTML file");if(G.protocol!=="convax.pet-host/1")throw TypeError("Pet protocol must equal convax.pet-host/1");return{library:J,overlay:Q,protocol:"convax.pet-host/1",settings:X}}function m1(F){let G=A(F,"Plugin runtime");if(R(G,["args","command","type"],"Plugin runtime"),G.type!=="mcp-stdio")throw TypeError("Plugin runtime type must be mcp-stdio");let J=T(G.command,"Plugin runtime command",128);if(!/^[A-Za-z0-9][A-Za-z0-9._-]*$/u.test(J))throw TypeError("Plugin runtime command must be a bare executable name");E0(J);let Q;if(G.args!==void 0)Q=c(G.args,"Plugin runtime args",64).map((X,Y)=>{let Z=T(X,`Plugin runtime arg ${Y}`,1024);if(/[\s"'`;|&`$(){}[\]<>]/u.test(Z)||Z.includes("\\")||/(^|=)(?:\/|[A-Za-z]:)/u.test(Z)||/(^|[=/])\.{1,2}(?:\/|$)/u.test(Z))throw TypeError(`Plugin runtime arg ${Y} must be a static CLI token without code, native paths, or traversal`);return Z});return{...Q===void 0?{}:{args:Q},command:J,type:"mcp-stdio"}}var SF=new Set(U0.apis.filter((F)=>F.audience.includes("agent-skill")).map((F)=>F.id)),d1=/^[a-z][a-z0-9_]{0,63}$/;function p1(F,G){let J=T(F,G,64);if(!/^[a-z0-9]+(?:-[a-z0-9]+)*$/u.test(J))throw TypeError(`${G} must use kebab-case`);return E0(J),J}function s1(F,G,J){let Q=A(F,G);R(Q,["optionalHostApis","pluginTools","requiredHostApis"],G);let X=s0({major:M0,required:Q.requiredHostApis??[],optional:Q.optionalHostApis??[]}),Y=new Set(J.required),Z=new Set([...J.required,...J.optional]);for(let M of X.required){if(!Y.has(M))throw TypeError(`${G} required Host API must be required by the Plugin: ${M}`);if(N0(M)&&!SF.has(M))throw TypeError(`${G} Host API is not available to Agent Skills: ${M}`)}for(let M of X.optional){if(!Z.has(M))throw TypeError(`${G} optional Host API must be declared by the Plugin: ${M}`);if(N0(M)&&!SF.has(M))throw TypeError(`${G} Host API is not available to Agent Skills: ${M}`)}let _;if(Q.pluginTools!==void 0){if(_=c(Q.pluginTools,`${G} pluginTools`,32,!0).map((M,K)=>{let D=T(M,`${G} pluginTools ${K}`,64);if(!d1.test(D))throw TypeError(`${G} plugin tool id must use lower snake_case: ${D}`);return D}),new Set(_).size!==_.length)throw TypeError(`${G} pluginTools contain duplicate ids`)}if(X.required.length===0&&X.optional.length===0&&_===void 0)throw TypeError(`${G} must declare at least one Host API or Plugin tool`);return{...X.optional.length===0?{}:{optionalHostApis:[...X.optional]},..._===void 0?{}:{pluginTools:_},...X.required.length===0?{}:{requiredHostApis:[...X.required]}}}function r1(F,G){if(F===void 0)return;let J=c(F,"Plugin Skill contributions",32,!0).map((Q,X)=>{let Y=`Plugin Skill contribution ${X}`,Z=A(Q,Y);R(Z,["name","path","uses"],Y);let _=p1(Z.name,`${Y} name`),M=X0(Z.path,`${Y} path`);if(M.split("/").at(-1)!==_)throw TypeError(`${Y} path must name its Skill directory: ${_}`);let K=Z.uses===void 0?void 0:s1(Z.uses,`${Y} uses`,G);return{name:_,path:M,...K===void 0?{}:{uses:K}}});if(new Set(J.map((Q)=>Q.name)).size!==J.length)throw TypeError("Plugin Skill contributions contain duplicate names");if(new Set(J.map((Q)=>Q.path.toLocaleLowerCase("en-US"))).size!==J.length)throw TypeError("Plugin Skill contributions contain duplicate paths");return J}function o1(F,G){let J=new Set(G?.tools?.map((Q)=>Q.id)??[]);for(let Q of F??[])for(let X of Q.uses?.pluginTools??[])if(!J.has(X))throw TypeError(`Plugin Skill ${Q.name} references an unknown Agent tool: ${X}`)}var DF="convax.plugin/8";var cF=["canvas.connectedImages.read","canvas.connectedInputs.read","canvas.connectedMedia.stream","canvas.node.read","canvas.node.write","canvas.image.write","project.files.read","agent.prompt","generation.execute","ui.fullscreen","projects.read","canvas.catalog.read","canvas.document.read","canvas.document.write","canvas.events.subscribe","pet.activity.read","pet.activity.open","pet.preferences.write","pet.custom.manage"],u1=["projects.read","canvas.catalog.read","canvas.document.read","canvas.document.write","canvas.events.subscribe"],bF=["pet.activity.read","pet.activity.open","pet.preferences.write","pet.custom.manage"],UF=["pet.activity.read","pet.activity.open","pet.preferences.write"],n1=new Set(cF),t1=new Set(bF);function i1(F){let G=c(F??[],"Plugin capabilities",cF.length).map((J)=>{if(typeof J!=="string"||!n1.has(J))throw TypeError("Plugin capabilities contain an unsupported or duplicate capability");return J});if(new Set(G).size!==G.length)throw TypeError("Plugin capabilities contain an unsupported or duplicate capability");return G}function a1(F){let G=F.entry===void 0?void 0:X0(F.entry,"Plugin entry");if(G!==void 0&&!G.toLowerCase().endsWith(".html"))throw TypeError("Plugin entry must be an HTML file");let J=F.hooks===void 0?void 0:X0(F.hooks,"Plugin hooks");if(J!==void 0&&!/\.(?:js|mjs)$/u.test(J))throw TypeError("Plugin hooks must be a JavaScript ESM module");return{entry:G,hooks:J}}function l1(F){let{capabilities:G,canvas:J,entry:Q,hostApi:X}=F;if(Q!==void 0!==(J?.renderer!==void 0))throw TypeError("Plugin entry and Canvas renderer must appear together");if(Q!==void 0&&!X.required.includes("host.context.get"))throw TypeError("convax.plugin/8 Web Plugins must require host.context.get");if((J?.commands!==void 0||J?.menus!==void 0||J?.toolbar!==void 0)&&J.renderer===void 0)throw TypeError("Canvas UI commands require a sandboxed Canvas renderer");if(G.includes("generation.execute")&&J?.renderer===void 0)throw TypeError("generation.execute requires a sandboxed Canvas surface");if(J&&J.renderer===void 0&&!J.selectionActions?.length&&!J.commands?.length&&!J.menus?.length&&!J.toolbar?.length)throw TypeError("Canvas contributions must declare a renderer, selection actions, or UI commands");if(J?.selectionActions?.some((Y)=>("action"in Y)&&Y.action.type==="materialize-own-plugin-node")&&J.renderer===void 0)throw TypeError("materialize-own-plugin-node requires the contributing Plugin renderer")}function e1(F,G,J){if(G===void 0)return;if(F.lengthbF.length||UF.some((Q)=>!F.includes(Q))||F.some((Q)=>!t1.has(Q)))throw TypeError("Pet capabilities must include pet.activity.read, pet.activity.open, and pet.preferences.write; pet.custom.manage is optional");if(J!==void 0)throw TypeError("Pet feature cannot declare an executable runtime")}function F2(F,G={}){let J=A(F,"Plugin manifest");if(R(J,["capabilities","contributes","description","entry","hooks","hostApi","id","name","runtime","schema","version"],"Plugin manifest"),J.schema!==DF)throw TypeError("Plugin manifest must use convax.plugin/8");if(!Object.prototype.hasOwnProperty.call(J,"hostApi"))throw TypeError("convax.plugin/8 must declare hostApi explicitly");let Q=G.hostApiMode==="authoring"?q6(J.hostApi):s0(J.hostApi),X=i1(J.capabilities),Y=A(J.contributes,"Plugin contributions");R(Y,["agent","canvas","capabilities","generation","llm","pet","service","skills"],"Plugin contributions");let{entry:Z,hooks:_}=a1(J),M=Y.canvas===void 0?void 0:H1(Y.canvas);l1({capabilities:X,canvas:M,entry:Z,hostApi:Q});let K=Y.agent===void 0?void 0:f1(Y.agent),D=Y.capabilities===void 0?void 0:o6(Y.capabilities),j=Y.generation===void 0?void 0:I1(Y.generation),O=Y.llm===void 0?void 0:b1(Y.llm),L=Y.pet===void 0?void 0:v1(Y.pet),k=Y.service===void 0?void 0:c1(Y.service),G0=r1(Y.skills,Q),d=J.runtime===void 0?void 0:m1(J.runtime),J0=j!==void 0||k!==void 0||O!==void 0||Boolean(D?.exports.length);if(d!==void 0!==J0){if(D?.exports.length&&d===void 0)throw TypeError("Plugin capability exports require a verified mcp-stdio runtime");throw TypeError("convax.plugin/8 runtime and executable contribution must appear together")}if(D?.exports.length&&d===void 0)throw TypeError("Plugin capability exports require a verified mcp-stdio runtime");e1(X,L,d),h1({agent:K,generation:j,selectionActions:M?.selectionActions}),o1(G0,K);let U=new Set(u1),W=X.some((V)=>U.has(V));if(M?.renderer===void 0&&!M?.selectionActions?.length&&!J0&&_===void 0&&!X.includes("generation.execute")&&!W&&L===void 0&&(D?.exports.length??0)===0&&K?.mcp===void 0)throw TypeError("convax.plugin/8 must declare a Plugin capability beyond owned Skills");return BF({capabilities:X,contributes:{...K===void 0?{}:{agent:K},...D===void 0?{}:{capabilities:D},...M===void 0?{}:{canvas:M},...j===void 0?{}:{generation:j},...O===void 0?{}:{llm:O},...L===void 0?{}:{pet:L},...k===void 0?{}:{service:k},...G0===void 0?{}:{skills:G0}},description:T(J.description,"Plugin description",2000),...Z===void 0?{}:{entry:Z},..._===void 0?{}:{hooks:_},hostApi:Q,id:HF(J.id),name:T(J.name,"Plugin name",120),...d===void 0?{}:{runtime:d},schema:DF,version:t6(J.version)})}function G2(F){return F2(F,{hostApiMode:"authoring"})}class f extends Error{code;constructor(F,G){super(G);this.name="PluginHostProtocolError",this.code=F}}class o0 extends Error{code;kind;recoverable;constructor(F){super(F.message);this.name="PluginHostRemoteError",this.code=F.code,this.kind=F.kind,this.recoverable=F.recoverable}}class m0 extends Error{reason;constructor(F){super("Plugin Host request was aborted");this.name="AbortError",this.reason=F}}var WF=0;function J2(){return WF+=1,`sdk-${Date.now().toString(36)}-${WF.toString(36)}`}function Q2(F){if(F.length<1||F.length>96||F!==F.trim()||!/^[A-Za-z0-9._-]+$/.test(F))throw TypeError("Plugin Host requestIdPrefix is invalid")}function jF(F,G){let J=F.contributes.capabilities,Q=J?.imports.required.find((Y)=>Y.id===G);if(Q)return{import:Q,requirement:"required"};let X=J?.imports.optional.find((Y)=>Y.id===G);if(X)return{import:X,requirement:"optional"};throw TypeError(`Plugin capability import is not declared: ${G}`)}function X2(F,G){let J=G.kind==="protocol"?gF(G):g6(F,G);return new o0(J)}function VF(F){let G=F.kind==="protocol"?gF(F):$1(F);return new o0(G)}function vF(F){let G=G2(F.manifest);if(G.entry===void 0||!G.hostApi.required.includes("host.context.get"))throw TypeError("Plugin Host Web client requires an entry and required host.context.get negotiation baseline");let J=F.requestIdPrefix??J2();Q2(J);let Q=new Map,X=new Set,Y,Z,_=0,M=!1,K=(U)=>{for(let W of Q.values())W.abort?.(),W.reject(U);Q.clear()},D=(U,W=!0)=>{if(M)return;M=!0,F.port.removeEventListener("message",G0),X.clear(),Y=void 0,Z=void 0,K(U);let V={protocol:u,type:"disconnect"};try{P0(V,l6,"Plugin Host disconnect"),L(V)}catch{}try{F.port.close()}catch{}if(!W)return;try{F.onFatalError?.(U)}catch{}},j=()=>{if(_>=Number.MAX_SAFE_INTEGER){let W=new f("request-id-exhausted","Plugin Host request id space is exhausted");throw D(W),W}_+=1;let U=`${J}-${_.toString(36)}`;if(!kF(U)){let W=new f("request-id-exhausted","Plugin Host request id is invalid");throw D(W),W}return U},O=(U,W)=>{P0(U,W,"Plugin Host request")},L=(U)=>{F.port.postMessage(U)},k=(U,W,V,N)=>{if(M)return Promise.reject(new f("closed","Plugin Host client is closed"));if(N?.aborted)return Promise.reject(new m0(N.reason));if(Q.size>=YF)return Promise.reject(RangeError(`Plugin Host client permits at most ${YF} in-flight requests`));try{O(U,V.maximumRequestBytes)}catch(b){return Promise.reject(b)}let E=U.id;return new Promise((b,y)=>{let Q0=N?()=>{let t=Q.get(E);if(!t)return;Q.delete(E),t.abort?.();let p={id:E,protocol:u,type:"cancel"};try{O(p,w0),L(p)}catch(s){let n0=new f("transport-failed",s instanceof Error?s.message:"Plugin Host cancel failed");y(n0),D(n0);return}y(new m0(N.reason))}:void 0,W0=Q0?()=>{N.removeEventListener("abort",Q0)}:void 0;if(Q.set(E,{abort:W0,maximumResponseBytes:V.maximumResponseBytes,parseFailure:V.parseFailure,parseResult:W,reject:y,resolve:b}),Q0)N.addEventListener("abort",Q0,{once:!0});try{L(U)}catch(t){D(new f("transport-failed",t instanceof Error?t.message:"Plugin Host transport failed"))}})};function G0(U){if(M)return;let W;try{W=P0(U.data,a6,"Plugin Host response")}catch{D(new f("invalid-envelope","Plugin Host sent a non-JSON message"));return}if(Z1(U.data)){try{for(let E of X)E(U.data)}catch{D(new f("invalid-envelope","Plugin Host command listener failed"))}return}if(!Y1(U.data)){D(new f("invalid-envelope","Plugin Host sent an invalid envelope"));return}let V=U.data,N=Q.get(V.id);if(!N){D(new f("unknown-response",`Plugin Host returned an unknown, duplicate, or late response id: ${V.id}`));return}if(W>N.maximumResponseBytes){D(new f("invalid-envelope",`Plugin Host response exceeds ${N.maximumResponseBytes} bytes for this request`));return}if(!V.ok){try{let E=N.parseFailure(V.error);Q.delete(V.id),N.abort?.(),N.reject(E)}catch(E){D(new f("invalid-result",E instanceof Error?E.message:"Plugin Host returned an invalid failure"))}return}try{let E=N.parseResult(V.result);Q.delete(V.id),N.abort?.(),N.resolve(E)}catch(E){D(new f("invalid-result",E instanceof Error?E.message:"Plugin Host returned an invalid result"))}}F.port.addEventListener("message",G0),F.port.start?.();let d=(U,W)=>{if(!GF(G.hostApi,U))return Promise.reject(TypeError(`Plugin Host API is not declared: ${U}`));let V=E6[U],N=V.params.type==="none"?void 0:W[0],E=V.params.type==="none"?W[0]:W[1],b;try{b=T6(U,N)}catch(p){return Promise.reject(p)}let Q0={id:j(),method:U,...b===void 0?{}:{params:b},protocol:u,type:"request"},W0=N6(U),t=B6;return k(Q0,(p)=>{let s=t(U,p);if(U==="host.context.get")Y=s;return s},{maximumRequestBytes:W0.request.maxBytes,maximumResponseBytes:W0.result.maxBytes,parseFailure:(p)=>{let s=X2(U,p);if(s.kind==="api"&&s.code==="stale-context")Y=void 0;return s}},E?.signal)},J0={get closed(){return M},callHostApi(U,...W){return d(U,W)},async getHostApiAvailability(U,W){if(!GF(G.hostApi,U))throw TypeError(`Plugin Host API is not declared: ${U}`);let V=!Y||W?.refresh?await J0.refreshHostApiContext(W):Y,N=p0(U);return V.hostApi.availability.find(({id:E})=>E===U)??{available:!1,contractSince:N.contractSince,id:U,reason:"unsupported-host",recoverable:!1,since:N.since}},refreshHostApiContext(U){if(Y=void 0,Z)return Z;let V=d("host.context.get",[U]).finally(()=>{if(Z===V)Z=void 0});return Z=V,Z},async requireHostApi(U,W){let V=await J0.getHostApiAvailability(U,W);if(!V.available)throw new EF(V);return V},getCapabilityAvailability(U,W){let V;try{V=jF(G,U)}catch(b){return Promise.reject(b)}let N=j();return k({capabilityId:U,id:N,protocol:u,type:"capability-availability"},(b)=>{let y=_1(b);if(y.capabilityId!==U||y.requirement!==V.requirement)throw TypeError("Plugin capability availability does not match the declared import");return y},{maximumRequestBytes:w0,maximumResponseBytes:XF,parseFailure:VF},W?.signal)},invokeCapability(U,W,V){let N;try{N=jF(G,U),QF(N.import.inputSchema,W,`Plugin capability ${U} input`)}catch(y){return Promise.reject(y)}let E=j();return k({capabilityId:U,id:E,input:W,protocol:u,type:"capability-invoke"},(y)=>{return QF(N.import.outputSchema,y,`Plugin capability ${U} output`),y},{maximumRequestBytes:w0,maximumResponseBytes:XF,parseFailure:VF},V?.signal)},onCommand(U){if(M)throw new f("closed","Plugin Host client is closed");if(X.size>=64)throw RangeError("Plugin Host command listener limit exceeded");return X.add(U),()=>{X.delete(U)}},close(){D(new f("closed","Plugin Host client was closed"),!1)}};return J0}var u0={schema:"convax.plugin/8",id:"chatcut",name:"ChatCut",description:"Imports directly connected Canvas media into ChatCut and connects Convax Agent sessions to ChatCut's hosted MCP server for authenticated, editable video workflows.",version:"0.4.0",entry:"index.html",capabilities:[],contributes:{canvas:{renderer:{create:!0,width:760,height:560}}},hostApi:{major:2,required:["agent.prompt","canvas.inputs.list","host.context.get"],optional:[]}};var M2="@convax/plugin-sdk/client:createPluginHostClient";function S2(F,G={}){if(F.source!==window.parent||F.ports.length!==1||!IF(F.data)||F.data.pluginId!==u0.id)return null;return vF({manifest:u0,onFatalError:G.onFatalError,port:F.ports[0],requestIdPrefix:G.requestIdPrefix})}export{M2 as pluginSdkClientBundleMarker,S2 as acceptPluginHostConnection}; diff --git a/packages/plugins/chatcut/package/manifest.json b/packages/plugins/chatcut/package/manifest.json index 90ea9f1..01d0829 100644 --- a/packages/plugins/chatcut/package/manifest.json +++ b/packages/plugins/chatcut/package/manifest.json @@ -3,7 +3,7 @@ "id": "chatcut", "name": "ChatCut", "description": "Imports directly connected Canvas media into ChatCut and connects Convax Agent sessions to ChatCut's hosted MCP server for authenticated, editable video workflows.", - "version": "0.3.2", + "version": "0.4.0", "entry": "index.html", "capabilities": [ "agent.prompt", @@ -68,7 +68,7 @@ "command": "convax-chatcut-media-import-mcp" }, "hostApi": { - "major": 1, + "major": 2, "required": [ "agent.prompt", "canvas.inputs.list", diff --git a/packages/plugins/chatcut/test/package.test.ts b/packages/plugins/chatcut/test/package.test.ts index 603ebd8..f4b0634 100644 --- a/packages/plugins/chatcut/test/package.test.ts +++ b/packages/plugins/chatcut/test/package.test.ts @@ -80,6 +80,8 @@ describe("ChatCut Plugin package", () => { expect(application).toContain("convax_plugin_chatcut_import_connected_media") expect(application).toContain("Do not call import_media action=create_session a second time") expect(application).toContain("ownerNodeId") + expect(application).toContain('references as [{"inputKey":"…","role":') + expect(application).not.toContain('references as [{"nodeId"') expect(application).toContain("every reference is still directly connected") expect(application).toContain("action=create_session") expect(application).toContain("edit_item") @@ -141,13 +143,13 @@ describe("ChatCut Plugin package", () => { }, entry: "index.html", hostApi: { - major: 1, + major: 2, optional: [], required: ["agent.prompt", "canvas.inputs.list", "host.context.get"], }, id: "chatcut", schema: "convax.plugin/8", - version: "0.3.2", + version: "0.4.0", runtime: { command: "convax-chatcut-media-import-mcp", type: "mcp-stdio", diff --git a/packages/plugins/codex-service/convax-package.json b/packages/plugins/codex-service/convax-package.json index 4a32ef2..61818ae 100644 --- a/packages/plugins/codex-service/convax-package.json +++ b/packages/plugins/codex-service/convax-package.json @@ -4,7 +4,7 @@ "id": "codex-service", "name": "Codex", "description": "Binds an existing local Codex installation and account to Convax for GPT-5.6, GPT-5.5, and GPT Image 2 without copying Codex credentials.", - "version": "0.1.2", + "version": "0.2.0", "companions": [ { "command": "convax-codex-mcp", diff --git a/packages/plugins/codex-service/package.json b/packages/plugins/codex-service/package.json index 996005b..04721b8 100644 --- a/packages/plugins/codex-service/package.json +++ b/packages/plugins/codex-service/package.json @@ -1,6 +1,6 @@ { "name": "@microvoid/convax-plugin-codex-service", - "version": "0.1.2", + "version": "0.2.0", "private": true, "type": "module", "dependencies": { diff --git a/packages/plugins/codex-service/package/manifest.json b/packages/plugins/codex-service/package/manifest.json index 826f70a..7008535 100644 --- a/packages/plugins/codex-service/package/manifest.json +++ b/packages/plugins/codex-service/package/manifest.json @@ -3,7 +3,7 @@ "id": "codex-service", "name": "Codex", "description": "Binds an existing local Codex installation and account to Convax for GPT-5.6, GPT-5.5, and GPT Image 2 without copying Codex credentials.", - "version": "0.1.2", + "version": "0.2.0", "contributes": { "generation": { "models": [ @@ -60,7 +60,7 @@ "command": "convax-codex-mcp" }, "hostApi": { - "major": 1, + "major": 2, "required": [], "optional": [] } diff --git a/packages/plugins/convax-pet/convax-package.json b/packages/plugins/convax-pet/convax-package.json index fbc684c..431d8a4 100644 --- a/packages/plugins/convax-pet/convax-package.json +++ b/packages/plugins/convax-pet/convax-package.json @@ -4,6 +4,6 @@ "id": "convax-pet", "name": "Convax Pet", "description": "A local desktop companion and pet library for Convax activity.", - "version": "0.2.3", + "version": "0.3.0", "yanked": false } diff --git a/packages/plugins/convax-pet/package.json b/packages/plugins/convax-pet/package.json index 777e157..a741baf 100644 --- a/packages/plugins/convax-pet/package.json +++ b/packages/plugins/convax-pet/package.json @@ -1,6 +1,6 @@ { "name": "@microvoid/convax-plugin-convax-pet", - "version": "0.2.3", + "version": "0.3.0", "private": true, "type": "module", "convax.hostCapabilityRequests": [ diff --git a/packages/plugins/convax-pet/package/manifest.json b/packages/plugins/convax-pet/package/manifest.json index 1924a4c..7816e6c 100644 --- a/packages/plugins/convax-pet/package/manifest.json +++ b/packages/plugins/convax-pet/package/manifest.json @@ -3,7 +3,7 @@ "id": "convax-pet", "name": "Convax Pet", "description": "A local desktop companion and pet library for Convax activity.", - "version": "0.2.3", + "version": "0.3.0", "capabilities": [ "pet.activity.read", "pet.activity.open", @@ -19,7 +19,7 @@ } }, "hostApi": { - "major": 1, + "major": 2, "required": [], "optional": [] } diff --git a/packages/plugins/cutout-studio/convax-package.json b/packages/plugins/cutout-studio/convax-package.json index 31c5d9d..86ae54f 100644 --- a/packages/plugins/cutout-studio/convax-package.json +++ b/packages/plugins/cutout-studio/convax-package.json @@ -4,7 +4,7 @@ "id": "cutout-studio", "name": "智能抠图", "description": "使用 U²-Netp 在本机快速移除图片背景,保留柔和边缘;图片不会上传到远程服务。", - "version": "0.2.1", + "version": "0.3.0", "companions": [ { "command": "convax-cutout-mcp", diff --git a/packages/plugins/cutout-studio/package.json b/packages/plugins/cutout-studio/package.json index f14f6f1..5c9ca83 100644 --- a/packages/plugins/cutout-studio/package.json +++ b/packages/plugins/cutout-studio/package.json @@ -1,6 +1,6 @@ { "name": "@microvoid/convax-plugin-cutout-studio", - "version": "0.2.1", + "version": "0.3.0", "private": true, "license": "MIT", "type": "module", diff --git a/packages/plugins/cutout-studio/package/manifest.json b/packages/plugins/cutout-studio/package/manifest.json index a009009..df6aa89 100644 --- a/packages/plugins/cutout-studio/package/manifest.json +++ b/packages/plugins/cutout-studio/package/manifest.json @@ -3,7 +3,7 @@ "id": "cutout-studio", "name": "智能抠图", "description": "使用 U²-Netp 在本机快速移除图片背景,保留柔和边缘;图片不会上传到远程服务。", - "version": "0.2.1", + "version": "0.3.0", "contributes": { "generation": { "models": [], @@ -48,7 +48,7 @@ "command": "convax-cutout-mcp" }, "hostApi": { - "major": 1, + "major": 2, "required": [], "optional": [] } diff --git a/packages/plugins/cutout-studio/test/package.test.ts b/packages/plugins/cutout-studio/test/package.test.ts index fb2efca..50bdeda 100644 --- a/packages/plugins/cutout-studio/test/package.test.ts +++ b/packages/plugins/cutout-studio/test/package.test.ts @@ -10,7 +10,7 @@ describe("Cutout Studio package", () => { expect(manifest).toMatchObject({ schema: "convax.plugin/8", id: "cutout-studio", - version: "0.2.1", + version: "0.3.0", runtime: { type: "mcp-stdio", command: "convax-cutout-mcp" }, contributes: { generation: { @@ -26,7 +26,7 @@ describe("Cutout Studio package", () => { expect(manifest).not.toHaveProperty("entry") expect(manifest).not.toHaveProperty("capabilities") expect(manifest.hostApi).toEqual({ - major: 1, + major: 2, required: [], optional: [], }) diff --git a/packages/plugins/ffmpeg-tools/convax-package.json b/packages/plugins/ffmpeg-tools/convax-package.json index c8cb920..7431a9c 100644 --- a/packages/plugins/ffmpeg-tools/convax-package.json +++ b/packages/plugins/ffmpeg-tools/convax-package.json @@ -4,7 +4,7 @@ "id": "ffmpeg-tools", "name": "FFmpeg Tools", "description": "Runs reviewed local FFmpeg transforms against host-staged Canvas media without exposing native paths or a shell.", - "version": "0.3.3", + "version": "0.4.0", "companions": [ { "command": "convax-ffmpeg-mcp", diff --git a/packages/plugins/ffmpeg-tools/package.json b/packages/plugins/ffmpeg-tools/package.json index d88a608..5a808ed 100644 --- a/packages/plugins/ffmpeg-tools/package.json +++ b/packages/plugins/ffmpeg-tools/package.json @@ -1,6 +1,6 @@ { "name": "@microvoid/convax-plugin-ffmpeg-tools", - "version": "0.3.3", + "version": "0.4.0", "private": true, "type": "module", "dependencies": { diff --git a/packages/plugins/ffmpeg-tools/package/manifest.json b/packages/plugins/ffmpeg-tools/package/manifest.json index 39e1f1d..8e31f7a 100644 --- a/packages/plugins/ffmpeg-tools/package/manifest.json +++ b/packages/plugins/ffmpeg-tools/package/manifest.json @@ -3,7 +3,7 @@ "id": "ffmpeg-tools", "name": "FFmpeg Tools", "description": "Runs reviewed local FFmpeg transforms against host-staged Canvas media without exposing native paths or a shell.", - "version": "0.3.3", + "version": "0.4.0", "contributes": { "generation": { "models": [], @@ -208,7 +208,7 @@ "command": "convax-ffmpeg-mcp" }, "hostApi": { - "major": 1, + "major": 2, "required": [], "optional": [] } diff --git a/packages/plugins/hello-convax/convax-package.json b/packages/plugins/hello-convax/convax-package.json index 12c6b90..c499547 100644 --- a/packages/plugins/hello-convax/convax-package.json +++ b/packages/plugins/hello-convax/convax-package.json @@ -4,6 +4,6 @@ "id": "hello-convax", "name": "Hello Convax", "description": "Checks the scoped Convax Plugin host connection and shows its active context.", - "version": "0.1.3", + "version": "0.2.0", "yanked": false } diff --git a/packages/plugins/hello-convax/package.json b/packages/plugins/hello-convax/package.json index 549429f..8c5ca67 100644 --- a/packages/plugins/hello-convax/package.json +++ b/packages/plugins/hello-convax/package.json @@ -1,6 +1,6 @@ { "name": "@microvoid/convax-plugin-hello-convax", - "version": "0.1.3", + "version": "0.2.0", "private": true, "type": "module", "dependencies": { diff --git a/packages/plugins/hello-convax/package/assets/plugin-host-client.js b/packages/plugins/hello-convax/package/assets/plugin-host-client.js index a2f3d6c..09732f5 100644 --- a/packages/plugins/hello-convax/package/assets/plugin-host-client.js +++ b/packages/plugins/hello-convax/package/assets/plugin-host-client.js @@ -1 +1 @@ -var c1=/^[a-z][a-z0-9]*(?:\.[a-z][a-z0-9]*)+$/,b1=/^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/,d1=/^[a-z][A-Za-z0-9]*(?:\.[a-z][A-Za-z0-9]*)+$/,v1=/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/,m1=new Set(["web-plugin","agent-skill","companion","host"]),p1=new Set(["connection","plugin","own-node","project","canvas"]),s1=new Set(["none","read","write","execute","subscribe"]),o1=new Set(["cancelable","commit-preserving"]);function _0(G,F){if(G.trim().length===0)throw TypeError(`${F} must not be empty`)}function y0(G,F){if(!v1.test(G))throw TypeError(`${F} must be a strict semantic version`)}function D1(G,F){let J=G.split(".").map(Number),Q=F.split(".").map(Number);for(let X=0;X<3;X+=1){let Y=J[X]-Q[X];if(Y!==0)return Y}return 0}function U1(G){if(!c1.test(G.id))throw TypeError(`Plugin API id is invalid: ${G.id}`);if(G.grant!==null&&!d1.test(G.grant))throw TypeError(`Plugin API grant is invalid: ${G.grant}`);if(!p1.has(G.scope))throw TypeError(`Plugin API scope is invalid: ${G.scope}`);if(!s1.has(G.sideEffect))throw TypeError(`Plugin API sideEffect is invalid: ${G.sideEffect}`);if(!o1.has(G.completion))throw TypeError(`Plugin API completion is invalid: ${G.completion}`);let F=G.audience??["web-plugin"];if(F.length===0||new Set(F).size!==F.length||F.some((X)=>!m1.has(X)))throw TypeError(`Plugin API audience is invalid: ${G.id}`);_0(G.docs.summary,`${G.id} docs.summary`),_0(G.docs.description,`${G.id} docs.description`),_0(G.docs.request,`${G.id} docs.request`),_0(G.docs.response,`${G.id} docs.response`);let J=new Set,Q=G.errors.map((X)=>{if(!b1.test(X.code)||J.has(X.code))throw TypeError(`Plugin API error code is invalid or duplicated: ${G.id}/${X.code}`);return J.add(X.code),_0(X.description,`${G.id}/${X.code} description`),Object.freeze({...X})});return Object.freeze({...G,audience:Object.freeze([...F]),errors:Object.freeze(Q),docs:Object.freeze({...G.docs})})}function H(G){return U1(G)}function r1(G,F){return y0(G,"Plugin API release version"),Object.freeze({version:G,apis:Object.freeze([...F])})}function u1(...G){if(G.length===0)throw TypeError("Plugin API catalog requires at least one release");let F=new Set,J=[],Q;for(let X of G){if(y0(X.version,"Plugin API release version"),Q&&D1(Q,X.version)>=0)throw TypeError("Plugin API releases must be strictly increasing");Q=X.version;for(let Y of X.apis){let Z=U1(Y);if(F.has(Z.id))throw TypeError(`Plugin API id is duplicated: ${Z.id}`);F.add(Z.id),J.push(Object.freeze({...Z,since:X.version}))}}if(J.length===0)throw TypeError("Plugin API catalog must contain at least one API");return Object.freeze({schema:"convax.plugin-api-catalog/1",version:G[G.length-1].version,apis:Object.freeze(J)})}var i8=Object.freeze({assertVersion:y0,compareVersions:D1}),z=1024,I=z*z,$0={type:"none"},s={type:"boolean"},B={finite:!0,type:"number"},o={finite:!0,minimum:0,type:"integer"},E0={type:"null"},x=(G)=>({const:G}),$=(G=2048,F={})=>({controlCharacters:!1,maxLength:G,minLength:F.allowEmpty?0:1,...F.prefix?{prefix:F.prefix}:{},...F.refinement?{refinement:F.refinement}:{},type:"string"}),C=(G,F,J=0,Q)=>({items:G,maxItems:F,minItems:J,type:"array",...Q?{uniqueBy:Q}:{}}),S=(G,F)=>({additionalProperties:!1,properties:G,required:F,type:"object"}),a=(...G)=>({oneOf:G}),C0=(G=I)=>({keyMaxLength:128,maxBytes:G,maxDepth:32,type:"json-object"}),y=(G)=>({controlCharacters:!1,enum:G,maxLength:Math.max(...G.map((F)=>F.length)),minLength:1,type:"string"}),Z0=S({x:B,y:B},["x","y"]),c0=S({height:B,width:B},["height","width"]),t=S({canvasId:$(256),projectId:$(256)},["canvasId","projectId"]),P0=y(["text","image","video","audio"]),W1=y(["text","reference_image","reference_video","first_frame","last_frame","audio"]),g=(G=1000)=>C($(),G),n1=a(S({available:x(!0),catalogVersion:$(64),id:$(128),since:$(64)},["available","catalogVersion","id","since"]),S({available:x(!1),id:$(128),reason:y(["unsupported-host","not-declared","permission-denied","wrong-surface","missing-context","setup-required","disabled","recovering"]),recoverable:s,since:$(64)},["available","id","reason","recoverable"])),j1=S({data:C0(),id:$(),parentId:$(),position:Z0,revision:o,style:C0(),type:$(80)},["data","id","position","revision","type"]),t1=S({nodeId:$(),role:W1},["nodeId","role"]),i1=S({ids:g(),kinds:g(),limit:o,relatedToNodeIds:g(),text:$(2000,{allowEmpty:!0})},[]),a1=S({animated:s,id:$(),source:$(),target:$(),type:$(80)},["source","target"]),l1=S({nodeId:$(),position:Z0,size:c0},["nodeId","position"]),e1=S({componentGap:B,componentPackingScale:B,crossGap:B,isolatedPlacement:y(["left","preserve"]),mainGap:B,nodeGap:B,nodePackingScale:B,strategy:y(["component-packing","horizontal-directed-cluster","vertical-directed-cluster"])},[]),FF=a(S({edgeIds:g(),nodeIds:g(),type:x("elements.remove")},["type"]),S({direction:y(["left","center","right","top","middle","bottom"]),nodeIds:g(),type:x("nodes.align")},["direction","nodeIds","type"]),S({connection:a1,type:x("nodes.connect")},["connection","type"]),S({axis:y(["horizontal","vertical"]),nodeIds:g(),type:x("nodes.distribute")},["axis","nodeIds","type"]),S({label:$(512),nodeIds:g(),type:x("nodes.group")},["nodeIds","type"]),S({gap:B,layout:y(["grid","horizontal","vertical"]),nodeIds:g(),type:x("nodes.layout")},["nodeIds","type"]),S({delta:Z0,nodeIds:g(),type:x("nodes.move")},["delta","nodeIds","type"]),S({type:x("nodes.setGeometry"),updates:C(l1,1000)},["type","updates"]),S({nodeId:$(),type:x("nodes.ungroup")},["nodeId","type"]),S({nodeIds:g(),options:e1,type:x("canvas.auto-layout")},["type"])),GF=S({durationMs:B,height:B,inputKey:$(),kind:$(80),label:$(512),mediaRevision:$(512),mimeType:$(512),name:$(512),status:y(["error","idle","pending"]),width:B},["inputKey","kind","label"]),JF=S({acceptedInputs:C(W1,6),description:$(2000),id:$(256),kind:y(["model","operation"]),output:P0,title:$(120)},["acceptedInputs","description","id","kind","output","title"]),V1=S({id:$(),source:$(),target:$()},["id","source","target"]),QF=S({id:$(),kind:$(80),label:$(512),parentId:$(64*z,{allowEmpty:!0}),position:Z0,size:c0,type:$(64*z,{allowEmpty:!0})},["id","kind","label","position","size"]),XF=S({description:$(64*z,{allowEmpty:!0}),durationMs:B,id:$(),kind:$(80),label:$(512),mimeType:$(64*z,{allowEmpty:!0}),name:$(64*z,{allowEmpty:!0}),parentId:$(64*z,{allowEmpty:!0}),position:Z0,resource:S({kind:x("project-file"),path:$(1024)},["kind","path"]),size:c0,status:$(64*z,{allowEmpty:!0}),text:$(64*z,{allowEmpty:!0}),type:$(64*z,{allowEmpty:!0})},["id","kind","label","position","size"]),YF=S({edges:C(V1,1e4),id:$(256),nodes:C(QF,1e4),revision:o,title:$(512)},["edges","id","nodes","revision","title"]),ZF=S({description:$(8000,{allowEmpty:!0}),edges:C(V1,1e4),id:$(256),nodes:C(XF,1e4),revision:o,tags:C($(),256),title:$(512)},["edges","id","nodes","revision","title"]),_F=S({id:$(),incomingNodeIds:g(),kind:$(80),label:$(512),outgoingNodeIds:g(),parentId:$(64*z,{allowEmpty:!0}),position:Z0,text:$(64*z,{allowEmpty:!0}),type:$(64*z,{allowEmpty:!0})},["id","incomingNodeIds","kind","label","outgoingNodeIds","position"]),$F=S({canvas:S({id:$(256),name:$(512)},["id"]),hostApi:S({availability:C(n1,256,0,"id"),catalogVersion:$(64)},["availability","catalogVersion"]),node:j1,plugin:S({id:$(128),name:$(512),version:$(128)},["id","name","version"]),project:S({id:$(256),name:$(512)},["id"])},["canvas","hostApi","node","plugin","project"]),w=(G,F,J={})=>({request:{maxBytes:J.request??64*z,schema:G},result:{maxBytes:J.result??64*z,schema:F}}),F0=Object.freeze({"host.context.get":w($0,$F,{result:I}),"canvas.inputs.list":w($0,S({inputs:C(GF,256)},["inputs"]),{result:I}),"canvas.inputs.open":w(S({inputKey:$()},["inputKey"]),S({probe:S({duration:S({estimated:s,milliseconds:B},["estimated","milliseconds"]),height:B,kind:y(["audio","video"]),mediaRevision:$(128),mimeType:$(256),size:B,width:B},["duration","kind","mediaRevision","mimeType","size"]),sessionId:$(128),url:$(2048,{prefix:"convax-connected-media://"})},["probe","sessionId","url"])),"canvas.inputs.close":w(S({sessionId:$(128)},["sessionId"]),S({closed:s},["closed"])),"canvas.node.get":w($0,j1,{result:I}),"canvas.node.state.replace":w(S({state:C0(256*z)},["state"]),S({updated:x(!0)},["updated"]),{request:256*z+4*z}),"canvas.resource.image.create":w(S({dataUrl:$(24*I,{prefix:"data:image/png;base64,"}),name:$(120,{refinement:"safe-png-file-name"})},["dataUrl","name"]),S({createdNodeId:$(),revision:o},["createdNodeId","revision"]),{request:24*I+4*z}),"project.file.text.read":w(S({path:$(1024,{refinement:"portable-project-relative-path"})},["path"]),S({content:$(I,{allowEmpty:!0}),exists:s,path:$(1024,{refinement:"portable-project-relative-path"})},["content","exists","path"]),{result:I+4*z}),"agent.prompt":w(S({text:$(20000,{refinement:"trimmed"})},["text"]),S({text:$(64*z,{allowEmpty:!0})},["text"])),"generation.tools.list":w(a($0,S({output:P0},[])),S({tools:C(JF,256)},["tools"]),{result:I}),"generation.execute":w(S({output:P0,prompt:$(20000,{refinement:"trimmed"}),references:C(t1,32),resultMode:y(["create-pending-node","return"]),toolId:$(256)},["prompt"]),S({createdNodeIds:C($(),32),outputText:$(64*z,{allowEmpty:!0}),revision:o,toolId:$(256),warnings:C($(),32)},["createdNodeIds","revision","toolId","warnings"]),{result:256*z}),"projects.list":w($0,S({projects:C(S({available:s,id:$(256),name:$(512)},["available","id","name"]),1000)},["projects"]),{result:I}),"canvas.catalog.list":w(S({projectId:$(256)},["projectId"]),S({canvases:C(S({createdAt:B,id:$(256),name:$(512),updatedAt:B},["createdAt","id","name","updatedAt"]),1e4),projectId:$(256)},["canvases","projectId"]),{result:8*I}),"canvas.document.get":w(S({projection:y(["geometry","structure"]),ref:t},["ref"]),a(S({document:YF,projection:x("geometry"),ref:t,storageVersion:a(E0,$(256))},["document","projection","ref","storageVersion"]),S({document:ZF,projection:x("structure"),ref:t,storageVersion:a(E0,$(256))},["document","projection","ref","storageVersion"])),{result:8*I}),"canvas.nodes.query":w(S({query:i1,ref:t},["ref"]),S({nodes:C(_F,1000),ref:t,revision:o,storageVersion:a(E0,$(256))},["nodes","ref","revision","storageVersion"]),{request:I,result:8*I}),"canvas.transaction.execute":w(S({commands:C(FF,256,1),expectedRevision:o,ref:t,transactionId:$(128)},["commands","expectedRevision","ref","transactionId"]),S({affectedNodeIds:g(1e4),changed:s,createdNodeIds:g(1e4),ref:t,revision:o,storageVersion:$(256),summaryTruncated:s,warnings:g()},["affectedNodeIds","changed","createdNodeIds","ref","revision","storageVersion","warnings"]),{request:I,result:2*I}),"canvas.events.subscribe":w(S({ref:S({canvasId:$(256),projectId:$(256)},["projectId"])},["ref"]),S({subscriptionId:$(128)},["subscriptionId"])),"canvas.events.unsubscribe":w(S({subscriptionId:$(128)},["subscriptionId"]),S({removed:s},["removed"]))}),KF=Math.max(...Object.values(F0).map(({request:G})=>G.maxBytes)),MF=Math.max(...Object.values(F0).map(({result:G})=>G.maxBytes));function SF(G){return F0[G]}function q0(G,F){if(!G||typeof G!=="object"||Array.isArray(G))throw TypeError(`${F} must be an object`);let J=Object.getPrototypeOf(G);if(J!==Object.prototype&&J!==null)throw TypeError(`${F} must be a plain object`);return G}var DF=/^(CON|PRN|AUX|NUL|COM[1-9¹²³]|LPT[1-9¹²³]|CONIN\$|CONOUT\$)$/iu;function L1(G){for(let F of G){let J=F.codePointAt(0);if(J>=55296&&J<=57343)return!1}return!0}function s0(G){let F=G.split(".",1)[0]??"";return Boolean(G&&G!=="."&&G!==".."&&L1(G)&&!/[\\/:*?"<>|\u0000-\u001f\u007f]/u.test(G)&&!/[. ]$/u.test(G)&&!DF.test(F))}function UF(G,F){if(F===void 0)return!0;if(F==="trimmed")return G===G.trim();if(F==="safe-png-file-name")return G===G.trim()&&G.toLowerCase().endsWith(".png")&&s0(G);if(F==="portable-project-relative-path"){if(G!==G.trim()||G.includes("\\")||G.startsWith("/")||G.startsWith("//")||/^[A-Za-z]:/u.test(G)||!L1(G))return!1;let J=G.split("/");return J[0]?.toLowerCase()!==".convax"&&J.length>0&&J.every((Q)=>s0(Q))}return!1}function WF(G,F,J){let Q=new Set,X=(_,M,K)=>{if(_===null||typeof _==="string"||typeof _==="boolean")return _;if(typeof _==="number"){if(!Number.isFinite(_))throw TypeError(`${M} must contain finite JSON numbers`);return _}if(!_||typeof _!=="object"||K>=F.maxDepth||Q.has(_))throw TypeError(`${M} must be bounded acyclic JSON`);let D=Object.getPrototypeOf(_);if(!Array.isArray(_)&&D!==Object.prototype&&D!==null)throw TypeError(`${M} must contain plain JSON objects`);Q.add(_);let W;if(Array.isArray(_))W=_.map((O,V)=>X(O,`${M}[${V}]`,K+1));else{let O=Object.create(null);for(let[V,P]of Object.entries(_)){if(V.length<1||V.length>F.keyMaxLength||/[\u0000-\u001f\u007f]/u.test(V))throw TypeError(`${M} key is invalid`);O[V]=X(P,`${M}.${V}`,K+1)}W=O}return Q.delete(_),W},Y=X(q0(G,J),J,0);if(Array.isArray(Y)||!Y||typeof Y!=="object")throw TypeError(`${J} must be an object`);let Z=JSON.stringify(Y);if(new TextEncoder().encode(Z).byteLength>F.maxBytes)throw TypeError(`${J} exceeds ${F.maxBytes} bytes`);return Y}function K0(G,F,J="Plugin API value"){if("oneOf"in G){let Y=[];for(let Z of G.oneOf)try{Y.push(K0(Z,F,J))}catch{}if(Y.length!==1)throw TypeError(`${J} must match exactly one schema variant`);return Y[0]}if("const"in G){if(F!==G.const)throw TypeError(`${J} must equal ${String(G.const)}`);return F}if("type"in G&&G.type==="none"){if(F!==void 0)throw TypeError(`${J} does not accept a value`);return}if("type"in G&&G.type==="null"){if(F!==null)throw TypeError(`${J} must be null`);return null}if("type"in G&&G.type==="boolean"){if(typeof F!=="boolean")throw TypeError(`${J} must be boolean`);return F}if("type"in G&&(G.type==="number"||G.type==="integer")){if(typeof F!=="number"||!Number.isFinite(F)||G.type==="integer"&&!Number.isSafeInteger(F)||G.minimum!==void 0&&FG.maxLength||G.controlCharacters===!1&&/[\u0000-\u001f\u007f]/u.test(F)||G.enum!==void 0&&!G.enum.includes(F)||G.prefix!==void 0&&!F.startsWith(G.prefix)||!UF(F,G.refinement))throw TypeError(`${J} must satisfy its bounded string contract`);return F}if("type"in G&&G.type==="array"){if(!Array.isArray(F)||F.lengthG.maxItems)throw TypeError(`${J} must satisfy its bounded array contract`);let Y=F.map((Z,_)=>K0(G.items,Z,`${J}[${_}]`));if(G.uniqueBy!==void 0){let Z=Y.map((_)=>{let K=q0(_,`${J} unique item`)[G.uniqueBy];if(typeof K!=="string"&&typeof K!=="number")throw TypeError(`${J} unique identity is invalid`);return`${typeof K}:${String(K)}`});if(new Set(Z).size!==Z.length)throw TypeError(`${J} contains duplicate ${G.uniqueBy}`)}return Y}if("type"in G&&G.type==="json-object")return WF(F,G,J);if(!("properties"in G))throw TypeError(`${J} has an unsupported schema`);let Q=q0(F,J),X=new Set(Object.keys(G.properties));if(G.required.some((Y)=>!Object.prototype.hasOwnProperty.call(Q,Y))||Object.keys(Q).some((Y)=>!X.has(Y)))throw TypeError(`${J} contains unsupported or missing fields`);return Object.fromEntries(Object.entries(Q).map(([Y,Z])=>[Y,K0(G.properties[Y],Z,`${J}.${Y}`)]))}function k0(G,F){if("oneOf"in G){let J=G.oneOf.map((Z)=>k0(Z,F)),Q=J.filter((Z)=>Z.type==="object");if(Q.length===0&&J.some((Z)=>Z.type==="none"))return{type:"none"};if(Q.length===0)throw TypeError(`${F} is not an object schema`);let X=new Set(Q.flatMap(({required:Z,optional:_})=>[...Z,..._])),Y=[...X].filter((Z)=>Q.every((_)=>_.required.includes(Z))).sort();return{additionalProperties:!1,optional:[...X].filter((Z)=>!Y.includes(Z)).sort(),required:Y,type:"object"}}if("type"in G&&G.type==="none")return{type:"none"};if(!("properties"in G))throw TypeError(`${F} is not an object schema`);return{additionalProperties:!1,optional:Object.keys(G.properties).filter((J)=>!G.required.includes(J)).sort(),required:[...G.required].sort(),type:"object"}}var I0=Object.freeze(Object.keys(F0).sort()),jF=Object.freeze(Object.fromEntries(I0.map((G)=>{let F=F0[G],J=k0(F.result.schema,`Plugin API ${G} result`);if(J.type!=="object")throw TypeError(`Plugin API ${G} result must be an object`);return[G,{params:k0(F.request.schema,`Plugin API ${G} params`),request:F.request,response:F.result,result:J}]})));function VF(G,F){return K0(F0[G].request.schema,F,`Plugin API ${G} params`)}function LF(G,F){return K0(F0[G].result.schema,F,`Plugin API ${G} result`)}var k=[{code:"stale-context",description:"The bound Project, Canvas, node, or connection changed before the call completed.",recoverable:!0}],q=[{code:"permission-denied",description:"The installed Plugin principal does not currently hold the required grant.",recoverable:!1}],o0=[{code:"resource-unavailable",description:"The authoritative Project resource is missing, changed, or cannot be read safely.",recoverable:!0}],r0=[{code:"partial-success",description:"A user-visible Project file was published, but the requested Canvas commit did not complete; retry is unsafe.",recoverable:!1}],U0=u1(r1("1.0.0",[H({id:"host.context.get",completion:"cancelable",grant:null,scope:"connection",sideEffect:"read",errors:k,docs:{summary:"Read the bounded context attached to the current Plugin connection.",description:"Returns only renderer-safe identifiers and feature metadata for the exact live connection; it grants no additional authority.",request:"No parameters.",response:"The current Plugin, Project, Canvas, node, and negotiated Host API context when present."}}),H({id:"canvas.inputs.list",completion:"cancelable",grant:"canvas.connectedInputs.read",scope:"own-node",sideEffect:"read",errors:[...k,...q],docs:{summary:"List direct incoming inputs of the owning Plugin node.",description:"Derives pathless input metadata from authoritative direct incoming Canvas edges and never reads resource bytes.",request:"No parameters; the owning node comes from the bound connection.",response:"A bounded list of direct incoming input descriptors and opaque input keys."}}),H({id:"canvas.inputs.open",completion:"cancelable",grant:"canvas.connectedMedia.stream",scope:"own-node",sideEffect:"read",errors:[...k,...q,...o0],docs:{summary:"Open a bounded stream for one previously listed direct input.",description:"Opens host-owned access to the exact authoritative input after topology and resource identity are revalidated.",request:"`{ inputKey }`, using an opaque key returned by canvas.inputs.list.",response:"A connection-bound stream descriptor and safe media metadata.",remarks:"Call canvas.inputs.close when the stream is no longer needed."}}),H({id:"canvas.inputs.close",completion:"cancelable",grant:"canvas.connectedMedia.stream",scope:"own-node",sideEffect:"write",errors:[...k,...q],docs:{summary:"Close one connection-bound input stream.",description:"Releases a stream created by canvas.inputs.open without changing Canvas or Project state.",request:"The stream handle returned by canvas.inputs.open.",response:"An acknowledgement; closing an already closed handle is idempotent."}}),H({id:"canvas.node.get",completion:"cancelable",grant:"canvas.node.read",scope:"own-node",sideEffect:"read",errors:[...k,...q],docs:{summary:"Read the owning Plugin node projection.",description:"Returns a bounded renderer-safe projection of the exact node bound to the connection.",request:"No parameters; the owning node comes from the bound connection.",response:"The owning node identity, revision, geometry, and Plugin state projection."}}),H({id:"canvas.node.state.replace",completion:"commit-preserving",grant:"canvas.node.write",scope:"own-node",sideEffect:"write",errors:[...k,...q],docs:{summary:"Replace the owning node's bounded Plugin state.",description:"Commits only the namespaced Plugin state through the authoritative Canvas application service with revision checks.",request:"`{ state }`, where state is a bounded JSON value.",response:"`{ updated: true }` after the authoritative state replacement commits."}}),H({id:"canvas.resource.image.create",completion:"commit-preserving",grant:"canvas.image.write",scope:"own-node",sideEffect:"write",errors:[...k,...q,...r0],docs:{summary:"Create a Project-backed Canvas image through the host lifecycle.",description:"Admits bounded image content as a user-visible Project resource and commits its Canvas reference without exposing native paths.",request:"`{ dataUrl, name }`, containing a bounded validated image data URL and safe file name.",response:"The created renderer-safe image result after Project publication and Canvas commit."}}),H({id:"project.file.text.read",completion:"cancelable",grant:"project.files.read",scope:"project",sideEffect:"read",errors:[...k,...q],docs:{summary:"Read one bounded UTF-8 Project file.",description:"Reads through the scoped Project Files capability using a normalized Project-relative path and never exposes a native path.",request:"`{ path }`, using a normalized Project-relative portable path.",response:"The bounded UTF-8 file text."}}),H({id:"agent.prompt",completion:"commit-preserving",grant:"agent.prompt",scope:"connection",sideEffect:"execute",errors:[...k,...q],docs:{summary:"Submit a bounded prompt through the host Agent capability.",description:"Uses the current host-owned Agent context; it does not grant direct OpenCode, filesystem, model, or credential access.",request:"`{ text }`, containing the bounded prompt text.",response:"`{ text }`, containing the bounded host acknowledgement."}}),H({id:"generation.tools.list",completion:"cancelable",grant:"generation.execute",scope:"plugin",sideEffect:"read",errors:q,docs:{summary:"List generation tools available to the installed Plugin principal.",description:"Returns normalized tool metadata derived from active verified contributions without exposing executable paths or credentials.",request:"Optional `{ output }` modality filter; omitting params lists every admitted modality.",response:"A bounded list of available generation tools and their public input contracts."}}),H({id:"generation.execute",completion:"commit-preserving",grant:"generation.execute",scope:"plugin",sideEffect:"execute",errors:[...k,...q,...o0,...r0],docs:{summary:"Execute one selected generation tool through the shared host executor.",description:"Revalidates the active Plugin, authorized executable, inputs, cancellation, and live resource guards immediately before execution.",request:"`{ output?, prompt, references?, resultMode?, toolId? }`, validated against the selected tool.",response:"The bounded selected tool result, created node ids, authoritative revision, and warnings."}}),H({id:"projects.list",completion:"cancelable",audience:["web-plugin","companion"],grant:"projects.read",scope:"plugin",sideEffect:"read",errors:q,docs:{summary:"List Projects visible to the installed Plugin principal.",description:"Returns portable Project identities and display metadata without native paths or private Project state.",request:"No parameters.",response:"A bounded list of renderer-safe Project summaries."}}),H({id:"canvas.catalog.list",completion:"cancelable",audience:["web-plugin","companion"],grant:"canvas.catalog.read",scope:"project",sideEffect:"read",errors:[...k,...q],docs:{summary:"List Canvas catalog entries for one authorized Project.",description:"Reads the Project-owned Canvas catalog without selecting a Project or Canvas in the Workbench.",request:"`{ projectId }`, naming one explicit portable Project.",response:"A bounded list of portable Canvas catalog entries."}}),H({id:"canvas.document.get",completion:"cancelable",audience:["web-plugin","companion"],grant:"canvas.document.read",scope:"canvas",sideEffect:"read",errors:[...k,...q],docs:{summary:"Read one authorized Canvas document projection.",description:"Returns a bounded portable structure or geometry projection from Main's authoritative Canvas application service.",request:"`{ ref, projection }`, using an explicit portable Project/Canvas reference and supported projection.",response:"The requested pathless document projection and authoritative revision."}}),H({id:"canvas.nodes.query",completion:"cancelable",audience:["web-plugin","companion"],grant:"canvas.document.read",scope:"canvas",sideEffect:"read",errors:[...k,...q],docs:{summary:"Query bounded node projections in one authorized Canvas.",description:"Executes a host-defined bounded query without exposing native paths or resource bytes.",request:"`{ ref, query }`, using an explicit portable Project/Canvas reference and bounded query.",response:"Matching node projections and the authoritative Canvas revision."}}),H({id:"canvas.transaction.execute",completion:"commit-preserving",audience:["web-plugin","companion"],grant:"canvas.document.write",scope:"canvas",sideEffect:"write",errors:[...k,...q],docs:{summary:"Commit one non-empty revision-bound Canvas transaction.",description:"Validates bounded commands against one authoritative revision and persists the accepted transaction atomically.",request:"`{ ref, expectedRevision, commands, transactionId }` with a bounded non-empty command list.",response:"The committed authoritative revision and bounded command results."}}),H({id:"canvas.events.subscribe",completion:"cancelable",audience:["web-plugin","companion"],grant:"canvas.events.subscribe",scope:"canvas",sideEffect:"subscribe",errors:[...k,...q],docs:{summary:"Subscribe to bounded events for one authorized Canvas.",description:"Creates a connection-scoped subscription; events are revisioned invalidations or safe projections, never native data.",request:"`{ ref }`, using an explicit portable Project/Canvas reference.",response:"A connection-bound subscription identifier."}}),H({id:"canvas.events.unsubscribe",completion:"cancelable",audience:["web-plugin","companion"],grant:"canvas.events.subscribe",scope:"canvas",sideEffect:"subscribe",errors:[...k,...q],docs:{summary:"Close one connection-bound Canvas event subscription.",description:"Releases a subscription created by canvas.events.subscribe without changing Canvas state.",request:"The subscription identifier returned by canvas.events.subscribe.",response:"An acknowledgement; closing an already closed subscription is idempotent."}})])),u0=U0.apis.map(({id:G})=>G).sort();if(u0.length!==I0.length||u0.some((G,F)=>G!==I0[F]))throw TypeError("Plugin API Catalog and portable method contracts are incomplete or inconsistent");var NF=U0.version,M0=Number(NF.split(".")[0]),N1=new Map(U0.apis.map((G)=>[G.id,G])),OF=new Set(N1.keys());function N0(G){return typeof G==="string"&&OF.has(G)}function O1(G){return N1.get(G)}var zF=/^[a-z][a-z0-9]*(?:\.[a-z][a-z0-9]*)+$/;function AF(G){return typeof G==="object"&&G!==null&&!Array.isArray(G)}function n0(G,F){if(!Array.isArray(G))throw TypeError(`${F} must be an array`);let J=[],Q=new Set;for(let X of G){if(typeof X!=="string"||!zF.test(X))throw TypeError(`${F} contains an invalid Plugin API id: ${String(X)}`);if(Q.has(X))throw TypeError(`${F} contains a duplicate Plugin API id: ${X}`);Q.add(X),J.push(X)}return J}function RF(G){let F=b0(G),J=[],Q=[];for(let X of F.required){if(!N0(X))throw TypeError(`Plugin API declaration contains an unknown Plugin API id: ${X}`);J.push(X)}for(let X of F.optional){if(!N0(X))throw TypeError(`Plugin API declaration contains an unknown Plugin API id: ${X}`);Q.push(X)}return Object.freeze({major:M0,required:Object.freeze(J),optional:Object.freeze(Q)})}function b0(G){if(!AF(G))throw TypeError("Plugin API declaration must be an object");if(Object.keys(G).some((Z)=>Z!=="major"&&Z!=="required"&&Z!=="optional"))throw TypeError("Plugin API declaration contains an unknown field");if(G.major!==M0)throw TypeError(`Plugin API declaration major must be ${M0}`);let J=n0(G.required,"Plugin API declaration required"),Q=n0(G.optional,"Plugin API declaration optional"),X=new Set(J),Y=Q.find((Z)=>X.has(Z));if(Y)throw TypeError(`Plugin API cannot be both required and optional: ${Y}`);return Object.freeze({major:M0,required:Object.freeze(J),optional:Object.freeze(Q)})}function EF(G,F){if(G.required.includes(F))return"required";if(G.optional.includes(F))return"optional";return}function t0(G,F){return EF(G,F)!==void 0}class z1 extends Error{availability;constructor(G){super(`Plugin API ${G.id} is unavailable: ${G.reason}`);this.name="PluginApiUnavailableError",this.availability=G}}function TF(G,F){return typeof F==="string"&&O1(G).errors.some((J)=>J.code===F)}function BF(G,F){if(!F||typeof F!=="object"||Array.isArray(F))throw TypeError(`Plugin API ${G} failure must be an object`);let J=F;if(Object.keys(J).some((X)=>!["code","kind","message","recoverable"].includes(X))||!Object.prototype.hasOwnProperty.call(J,"code")||!Object.prototype.hasOwnProperty.call(J,"message")||!Object.prototype.hasOwnProperty.call(J,"recoverable")||J.kind!=="api"||!TF(G,J.code)||typeof J.message!=="string"||J.message.length<1||J.message.length>4096||typeof J.recoverable!=="boolean")throw TypeError(`Plugin API ${G} failure is invalid`);let Q=O1(G).errors.find(({code:X})=>X===J.code);if(J.recoverable!==Q.recoverable)throw TypeError(`Plugin API ${G} failure recoverability does not match the Catalog`);return Object.freeze({code:J.code,kind:"api",message:J.message,recoverable:J.recoverable})}var HF=/^[a-z][a-z0-9]*(?:\.[a-z][a-z0-9-]*)+$/,wF=/^[a-z][a-z0-9]*(?:[._-][a-z0-9]+)*$/,CF=/^[A-Za-z][A-Za-z0-9_-]{0,63}$/,PF=/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/,qF=new Set(["none","read","write","execute","subscribe"]),A1=128,kF=64,IF=8,xF=16384,gF=256;function d0(G){return typeof G==="string"&&G.length<=160&&HF.test(G)}function u(G,F){if(!G||typeof G!=="object"||Array.isArray(G))throw TypeError(`${F} must be an object`);let J=Object.getPrototypeOf(G);if(J!==Object.prototype&&J!==null)throw TypeError(`${F} must be a plain object`);return G}function d(G,F,J,Q){let X=new Set([...F,...J]);if(F.some((Y)=>!Object.prototype.hasOwnProperty.call(G,Y))||Object.keys(G).some((Y)=>!X.has(Y)))throw TypeError(`${Q} contains unsupported or missing fields`)}function i(G,F,J=2000){if(typeof G!=="string"||G.length<1||G.length>J||G!==G.trim()||/[\u0000-\u001f\u007f]/u.test(G))throw TypeError(`${F} must be a bounded, trimmed string`);return G}function j0(G,F,J){if(!Number.isSafeInteger(G)||Number(G)<0||Number(G)>J)throw TypeError(`${F} must be a bounded non-negative integer`);return Number(G)}function x0(G,F){if(typeof G!=="string"||!PF.test(G))throw TypeError(`${F} must be a strict semantic version`);return G}function fF(G,F){let J=G.split(".").map(Number),Q=F.split(".").map(Number);for(let X=0;X<3;X+=1){let Y=J[X]-Q[X];if(Y!==0)return Y}return 0}function g0(G,F,J){if(J>IF)throw TypeError(`${F} exceeds the schema depth limit`);let Q=u(G,F);if(Q.type==="null"||Q.type==="boolean")return d(Q,["type"],[],F),Object.freeze({type:Q.type});if(Q.type==="number"||Q.type==="integer"){d(Q,["type"],["minimum","maximum"],F);let{minimum:X,maximum:Y}=Q;if(X!==void 0&&(typeof X!=="number"||!Number.isFinite(X)))throw TypeError(`${F}.minimum must be finite`);if(Y!==void 0&&(typeof Y!=="number"||!Number.isFinite(Y)))throw TypeError(`${F}.maximum must be finite`);if(X!==void 0&&Y!==void 0&&X>Y)throw TypeError(`${F} minimum exceeds maximum`);return Object.freeze({type:Q.type,...X===void 0?{}:{minimum:X},...Y===void 0?{}:{maximum:Y}})}if(Q.type==="string"){if(!Object.prototype.hasOwnProperty.call(Q,"maxLength"))throw TypeError(`${F}.maxLength is required to keep values bounded`);d(Q,["type","maxLength"],["minLength","enum"],F);let X=j0(Q.maxLength,`${F}.maxLength`,xF),Y=Q.minLength===void 0?void 0:j0(Q.minLength,`${F}.minLength`,X),Z;if(Q.enum!==void 0){if(!Array.isArray(Q.enum)||Q.enum.length<1||Q.enum.length>128||Q.enum.some((_)=>typeof _!=="string"||_.length>X)||new Set(Q.enum).size!==Q.enum.length)throw TypeError(`${F}.enum must contain unique bounded strings`);Z=Object.freeze([...Q.enum])}return Object.freeze({type:"string",maxLength:X,...Y===void 0?{}:{minLength:Y},...Z===void 0?{}:{enum:Z}})}if(Q.type==="array"){d(Q,["type","items","maxItems"],["minItems"],F);let X=j0(Q.maxItems,`${F}.maxItems`,gF),Y=Q.minItems===void 0?void 0:j0(Q.minItems,`${F}.minItems`,X);return Object.freeze({type:"array",items:g0(Q.items,`${F}.items`,J+1),maxItems:X,...Y===void 0?{}:{minItems:Y}})}if(Q.type==="object"){if(d(Q,["type","properties","required","additionalProperties"],[],F),Q.additionalProperties!==!1)throw TypeError(`${F}.additionalProperties must be false`);let X=u(Q.properties,`${F}.properties`),Y=Object.keys(X);if(Y.length>kF)throw TypeError(`${F} has too many properties`);if(Y.some((_)=>!CF.test(_)))throw TypeError(`${F} contains an invalid property name`);if(!Array.isArray(Q.required)||Q.required.some((_)=>typeof _!=="string"||!Y.includes(_))||new Set(Q.required).size!==Q.required.length)throw TypeError(`${F}.required must contain unique declared properties`);let Z=Object.fromEntries(Y.sort().map((_)=>[_,g0(X[_],`${F}.properties.${_}`,J+1)]));return Object.freeze({type:"object",properties:Object.freeze(Z),required:Object.freeze([...Q.required].sort()),additionalProperties:!1})}throw TypeError(`${F}.type is unsupported`)}function O0(G,F){let J=g0(G,F,0);if(J.type!=="object")throw TypeError(`${F} must be a closed object schema`);return J}function hF(G,F){let J=u(G,F);d(J,["id","inputSchema","outputSchema","version"],[],F);let Q=i(J.id,`${F}.id`,160);if(!d0(Q))throw TypeError(`${F}.id is invalid`);let X=u(J.version,`${F}.version`);d(X,["minimum","maximumExclusive"],[],`${F}.version`);let Y=x0(X.minimum,`${F}.version.minimum`),Z=x0(X.maximumExclusive,`${F}.version.maximumExclusive`);if(fF(Y,Z)>=0)throw TypeError(`${F}.version must be a non-empty half-open interval`);return Object.freeze({id:Q,inputSchema:O0(J.inputSchema,`${F}.inputSchema`),outputSchema:O0(J.outputSchema,`${F}.outputSchema`),version:Object.freeze({minimum:Y,maximumExclusive:Z})})}function i0(G,F){if(!Array.isArray(G)||G.length>A1)throw TypeError(`${F} must be a bounded array`);let J=G.map((Q,X)=>hF(Q,`${F}[${X}]`)).sort((Q,X)=>Q.id.localeCompare(X.id));if(J.some((Q,X)=>X>0&&J[X-1].id===Q.id))throw TypeError(`${F} contains a duplicate capability id`);return Object.freeze(J)}function yF(G,F){let J=u(G,F);d(J,["id","version","operation","sideEffect","inputSchema","outputSchema","docs"],[],F);let Q=i(J.id,`${F}.id`,160);if(!d0(Q))throw TypeError(`${F}.id is invalid`);let X=i(J.operation,`${F}.operation`,128);if(!wF.test(X))throw TypeError(`${F}.operation is invalid`);if(!qF.has(J.sideEffect))throw TypeError(`${F}.sideEffect is invalid`);let Y=u(J.docs,`${F}.docs`);d(Y,["summary","request","response"],["remarks"],`${F}.docs`);let Z=Object.freeze({summary:i(Y.summary,`${F}.docs.summary`),request:i(Y.request,`${F}.docs.request`),response:i(Y.response,`${F}.docs.response`),...Y.remarks===void 0?{}:{remarks:i(Y.remarks,`${F}.docs.remarks`)}});return Object.freeze({id:Q,version:x0(J.version,`${F}.version`),operation:X,sideEffect:J.sideEffect,inputSchema:O0(J.inputSchema,`${F}.inputSchema`),outputSchema:O0(J.outputSchema,`${F}.outputSchema`),docs:Z})}function cF(G){let F=u(G,"Plugin capability declaration");if(d(F,["exports","imports"],[],"Plugin capability declaration"),!Array.isArray(F.exports)||F.exports.length>A1)throw TypeError("Plugin capability exports must be a bounded array");let J=F.exports.map((M,K)=>yF(M,`Plugin capability exports[${K}]`)).sort((M,K)=>M.id.localeCompare(K.id));if(J.some((M,K)=>K>0&&J[K-1].id===M.id))throw TypeError("Plugin capability exports contain a duplicate capability id");if(new Set(J.map((M)=>M.operation)).size!==J.length)throw TypeError("Plugin capability exports contain a duplicate provider operation");let Q=u(F.imports,"Plugin capability imports");d(Q,["required","optional"],[],"Plugin capability imports");let X=i0(Q.required,"Plugin required capability imports"),Y=i0(Q.optional,"Plugin optional capability imports"),Z=new Set(X.map(({id:M})=>M)),_=Y.find(({id:M})=>Z.has(M));if(_)throw TypeError(`Plugin capability import cannot be both required and optional: ${_.id}`);return Object.freeze({exports:Object.freeze(J),imports:Object.freeze({required:X,optional:Y})})}function f0(G,F,J,Q){if(G.type==="null"){if(F!==null)throw TypeError(`${J} must be null`);return}if(G.type==="boolean"){if(typeof F!=="boolean")throw TypeError(`${J} must be boolean`);return}if(G.type==="number"||G.type==="integer"){if(typeof F!=="number"||!Number.isFinite(F)||G.type==="integer"&&!Number.isSafeInteger(F))throw TypeError(`${J} must be a finite ${G.type==="integer"?"safe integer":"number"}`);if(G.minimum!==void 0&&FG.maximum)throw TypeError(`${J} exceeds maximum`);return}if(G.type==="string"){if(typeof F!=="string"||F.length<(G.minLength??0)||F.length>G.maxLength||G.enum!==void 0&&!G.enum.includes(F))throw TypeError(`${J} is not an admitted string`);return}if(!F||typeof F!=="object")throw TypeError(`${J} must be ${G.type}`);if(Q.has(F))throw TypeError(`${J} cannot be cyclic`);Q.add(F);try{if(G.type==="array"){if(!Array.isArray(F)||F.length<(G.minItems??0)||F.length>G.maxItems)throw TypeError(`${J} is not an admitted array`);F.forEach((Z,_)=>f0(G.items,Z,`${J}[${_}]`,Q));return}if(Array.isArray(F))throw TypeError(`${J} must be an object`);let X=Object.getPrototypeOf(F);if(X!==Object.prototype&&X!==null)throw TypeError(`${J} must be a plain object`);let Y=F;for(let Z of G.required)if(!Object.prototype.hasOwnProperty.call(Y,Z))throw TypeError(`${J}.${Z} is required`);for(let[Z,_]of Object.entries(Y)){let M=G.properties[Z];if(!M)throw TypeError(`${J} contains unsupported property: ${Z}`);f0(M,_,`${J}.${Z}`,Q)}}finally{Q.delete(F)}}function a0(G,F,J="Plugin capability value"){f0(G,F,J,new Set)}var bF=/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[A-Za-z-][0-9A-Za-z-]*)(?:\.(?:0|[1-9]\d*|\d*[A-Za-z-][0-9A-Za-z-]*))*))?(?:\+([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?$/,dF=/^(CON|PRN|AUX|NUL|COM[1-9¹²³]|LPT[1-9¹²³]|CONIN\$|CONOUT\$)$/i;function A(G,F){if(!G||typeof G!=="object"||Array.isArray(G))throw TypeError(`${F} must be an object`);let J=Object.getPrototypeOf(G);if(J!==Object.prototype&&J!==null)throw TypeError(`${F} must be a plain object`);return G}function R(G,F,J){let Q=new Set(F),X=Object.keys(G).find((Y)=>!Q.has(Y));if(X)throw TypeError(`${J} contains an unsupported field: ${X}`)}function E(G,F,J){if(typeof G!=="string"||G.length<1||G.length>J||G!==G.trim()||/[\u0000-\u001f\u007f]/u.test(G))throw TypeError(`${F} must be a bounded, trimmed string`);return G}function c(G,F,J,Q=!1){if(!Array.isArray(G)||G.length>J||Q&&G.length===0)throw TypeError(`${F} must be ${Q?"a non-empty ":"a "}bounded array with at most ${J} items`);return G}function R1(G){if(G&&typeof G==="object"&&!Object.isFrozen(G)){for(let F of Object.values(G))R1(F);Object.freeze(G)}return G}function vF(G){let F=E(G,"Plugin version",128);if(!bF.test(F))throw TypeError("Plugin version must be valid SemVer");return F}function R0(G){let F=G.split(".")[0]??"";if(!G||G.length>255||G==="."||G===".."||/[\\/:*?"<>|\u0000-\u001f\u007f]/u.test(G)||/[. ]$/u.test(G)||dF.test(F))throw TypeError(`Plugin path contains an invalid Windows filename: ${G}`);return G}function E1(G){let F=E(G,"Plugin id",80);if(!/^[a-z0-9]+(?:-[a-z0-9]+)*$/u.test(F))throw TypeError("Plugin id must use kebab-case");return R0(F),F}function X0(G,F="Plugin path"){let J=E(G,F,1024);if(J.includes("\\")||J.startsWith("/")||/^[A-Za-z]:/u.test(J)||J.startsWith("//"))throw TypeError(`${F} must be a portable relative path`);let Q=J.split("/");if(Q.some((X)=>!X||X==="."||X===".."))throw TypeError(`${F} must be a portable relative path`);return Q.forEach(R0),J}function T0(G,F,J){if(G===void 0)return;let Q=c(G,F,64).map((X)=>J(E(X,F,128)));if(new Set(Q).size!==Q.length)throw TypeError(`${F} contains duplicate values`);return Q}function Y0(G,F,J=80){let Q=E(G,F,J);if(!/^[a-z0-9]+(?:[._-][a-z0-9]+)*$/u.test(Q))throw TypeError(`${F} is invalid: ${Q}`);return Q}var l="convax.plugin-host/8",mF=KF,pF=MF,B0=1048576,l0=4194304,e0=16,sF=128,oF=64,V0=Math.ceil(mF/2),rF=/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/,uF=new Set(["not-declared","provider-missing","provider-incompatible","provider-ambiguous","self-provider","dependency-cycle","setup-required","disabled","recovering","contract-mismatch"]),T1=Object.freeze({canceled:{recoverable:!0},"contract-mismatch":{recoverable:!1},"depth-exceeded":{recoverable:!1},"duplicate-request":{recoverable:!1},"execution-failed":{recoverable:!1},"invalid-input":{recoverable:!1},"invalid-output":{recoverable:!1},overloaded:{recoverable:!0},"provider-unavailable":{recoverable:!0},"reentrant-call":{recoverable:!1}}),B1=new Set(Object.keys(T1)),H1=Object.freeze({canceled:{recoverable:!0},"internal-error":{recoverable:!1},"invalid-request":{recoverable:!1},overloaded:{recoverable:!0},"transport-closed":{recoverable:!0}}),w1=new Set(Object.keys(H1)),nF=new Set(U0.apis.flatMap((G)=>G.errors.map(({code:F})=>F)));function e(G){if(!G||typeof G!=="object"||Array.isArray(G))return;let F=Object.getPrototypeOf(G);return F===Object.prototype||F===null?G:void 0}function F1(G){let F=2;for(let J=0;J=55296&&Q<=57343){let X=G.charCodeAt(J+1);if(Q>=55296&&Q<=56319&&X>=56320&&X<=57343)F+=4,J+=1;else F+=6}else if(Q<128)F+=1;else if(Q<2048)F+=2;else F+=3}return F}function G1(G,F,J="Plugin Host message"){if(!Number.isSafeInteger(F)||F<1)throw TypeError(`${J} byte limit is invalid`);let Q=[{depth:0,value:G}],X=new WeakSet,Y=0,Z=0,_=(M)=>{if(Y+=M,Y>F)throw RangeError(`${J} exceeds ${F} bytes`)};while(Q.length>0){let M=Q.pop(),K=M.value;if(K===null){_(4);continue}if(typeof K==="string"){_(F1(K));continue}if(typeof K==="boolean"){_(K?4:5);continue}if(typeof K==="number"){if(!Number.isFinite(K))throw TypeError(`${J} must contain finite JSON numbers`);_(Object.is(K,-0)?1:String(K).length);continue}if(!K||typeof K!=="object")throw TypeError(`${J} must be a JSON value`);if(M.depth>oF||X.has(K))throw TypeError(`${J} must be a bounded acyclic JSON tree`);if(X.add(K),Array.isArray(K)){if(Z+=K.length,Z>V0)throw RangeError(`${J} exceeds ${V0} JSON entries`);if(_(2+Math.max(0,K.length-1)),Object.getOwnPropertySymbols(K).length>0)throw TypeError(`${J} arrays must not contain symbol properties`);let O=0;for(let V in K){if(!Object.prototype.hasOwnProperty.call(K,V))continue;if(!/^(0|[1-9]\d*)$/u.test(V)||Number(V)>=K.length)throw TypeError(`${J} arrays must contain only indexed entries`);let P=Object.getOwnPropertyDescriptor(K,V);if(!P?.enumerable||!("value"in P))throw TypeError(`${J} arrays must contain enumerable data properties`);O+=1,Q.push({depth:M.depth+1,value:P.value})}if(O!==K.length)throw TypeError(`${J} arrays must be dense JSON arrays`);continue}let D=Object.getPrototypeOf(K);if(D!==Object.prototype&&D!==null)throw TypeError(`${J} must contain plain JSON objects`);if(Object.getOwnPropertySymbols(K).length>0)throw TypeError(`${J} must not contain symbol properties`);_(2);let W=0;for(let O in K){if(!Object.prototype.hasOwnProperty.call(K,O))continue;let V=Object.getOwnPropertyDescriptor(K,O);if(!V?.enumerable||!("value"in V))throw TypeError(`${J} objects must contain enumerable data properties`);if(W+=1,Z+=1,Z>V0)throw RangeError(`${J} exceeds ${V0} JSON entries`);_((W===1?0:1)+F1(O)+1),Q.push({depth:M.depth+1,value:V.value})}}return Y}function r(G,F,J=[]){let Q=new Set([...F,...J]);return F.every((X)=>Object.prototype.hasOwnProperty.call(G,X))&&Object.keys(G).every((X)=>Q.has(X))}function C1(G){return typeof G==="string"&&G.length>0&&G.length<=sF&&G===G.trim()&&!/[\u0000-\u001f\u007f]/u.test(G)}function tF(G){return typeof G==="string"&&G.length>0&&G.length<=128&&G===G.trim()&&!/[\u0000-\u001f\u007f]/u.test(G)}function P1(G){let F=e(G);if(!F||!r(F,["pluginId","protocol","type"])||F.protocol!==l||F.type!=="connect")return!1;try{return E1(F.pluginId),!0}catch{return!1}}function iF(G){let F=e(G);if(!F||F.protocol!==l||F.type!=="response"||!C1(F.id))return!1;if(F.ok===!0)return r(F,["id","ok","protocol","result","type"]);if(F.ok!==!1||!r(F,["error","id","ok","protocol","type"]))return!1;let J=e(F.error);return Boolean(J&&r(J,["code","kind","message","recoverable"])&&typeof J.code==="string"&&(J.kind==="api"&&nF.has(J.code)||J.kind==="capability"&&B1.has(J.code)||J.kind==="protocol"&&w1.has(J.code))&&typeof J.message==="string"&&J.message.length>0&&J.message.length<=4096&&typeof J.recoverable==="boolean")}function aF(G){let F=e(G);return Boolean(F&&r(F,["command","protocol","type"],["params"])&&F.protocol===l&&F.type==="command"&&tF(F.command))}function lF(G){let F=e(G);if(!F||typeof F.available!=="boolean")throw TypeError("Plugin capability availability must be a closed object");let J=F.requirement;if(J!=="required"&&J!=="optional")throw TypeError("Plugin capability availability requirement is invalid");if(!d0(F.capabilityId))throw TypeError("Plugin capability availability id is invalid");if(F.available){if(!r(F,["available","capabilityId","requirement","version"])||typeof F.version!=="string"||!rF.test(F.version))throw TypeError("Available Plugin capability result is invalid");return Object.freeze({available:!0,capabilityId:F.capabilityId,requirement:J,version:F.version})}if(!r(F,["available","capabilityId","reason","recoverable","requirement"])||typeof F.reason!=="string"||!uF.has(F.reason)||typeof F.recoverable!=="boolean")throw TypeError("Unavailable Plugin capability result is invalid");return Object.freeze({available:!1,capabilityId:F.capabilityId,reason:F.reason,recoverable:F.recoverable,requirement:J})}function eF(G){let F=e(G);if(!F||!r(F,["code","kind","message","recoverable"])||F.kind!=="capability"||typeof F.code!=="string"||!B1.has(F.code)||typeof F.message!=="string"||F.message.length<1||F.message.length>4096||typeof F.recoverable!=="boolean")throw TypeError("Plugin capability failure is invalid");let J=F.code;if(F.recoverable!==T1[J].recoverable)throw TypeError("Plugin capability failure recoverability is invalid");return Object.freeze({code:J,kind:"capability",message:F.message,recoverable:F.recoverable})}function q1(G){let F=e(G);if(!F||!r(F,["code","kind","message","recoverable"])||F.kind!=="protocol"||typeof F.code!=="string"||!w1.has(F.code)||typeof F.message!=="string"||F.message.length<1||F.message.length>4096||typeof F.recoverable!=="boolean")throw TypeError("Plugin Host protocol failure is invalid");let J=F.code;if(F.recoverable!==H1[J].recoverable)throw TypeError("Plugin Host protocol failure recoverability is invalid");return Object.freeze({code:J,kind:"protocol",message:F.message,recoverable:F.recoverable})}var F8=["download","edit","open","play","refresh","settings","sparkles","upload"],k1=/^[a-z][a-z0-9]*(?:[._-][a-z0-9]+)*$/,G8=/^[a-z][a-z0-9]*(?:[._-][a-z0-9]+)*$/,J8=/^[a-z][a-z0-9]*(?:[._-][a-z0-9]+)*$/,Q8=128,J1=128,Q1=1e4;function X8(G){return Boolean(G)&&typeof G==="object"&&!Array.isArray(G)}function S0(G,F){if(!X8(G))throw TypeError(`${F} must be an object`);let J=Object.getPrototypeOf(G);if(J!==Object.prototype&&J!==null)throw TypeError(`${F} must be a plain object`);return G}function D0(G,F,J,Q){let X=new Set([...F,...J]);if(F.some((Y)=>!Object.prototype.hasOwnProperty.call(G,Y))||Object.keys(G).some((Y)=>!X.has(Y)))throw TypeError(`${Q} contains unsupported or missing fields`)}function z0(G,F,J){if(typeof G!=="string"||G.length<1||G.length>J||G!==G.trim()||/[\u0000-\u001f\u007f]/u.test(G))throw TypeError(`${F} must be a bounded, trimmed string`);return G}function A0(G,F,J,Q){let X=z0(G,F,Q);if(!J.test(X))throw TypeError(`${F} must be a stable Plugin-local id`);return X}function Y8(G,F){if(!Number.isSafeInteger(G)||Number(G)<-Q1||Number(G)>Q1)throw TypeError(`${F} must be a bounded safe integer`);return Number(G)}function Z8(G,F){let J=S0(G,F);return D0(J,["default"],["zh-CN"],F),Object.freeze({default:z0(J.default,`${F}.default`,120),...J["zh-CN"]===void 0?{}:{"zh-CN":z0(J["zh-CN"],`${F}.zh-CN`,120)}})}function _8(G){return F8.some((F)=>F===G)}function $8(G,F){let J=`Plugin UI commands[${F}]`,Q=S0(G,J);D0(Q,["id","title","target"],["icon"],J);let X=S0(Q.target,`${J}.target`);if(X.type!=="renderer-message")throw TypeError(`${J}.target.type must be renderer-message`);D0(X,["type","message"],[],`${J}.target`);let Y=Q.icon;if(Y!==void 0&&!_8(Y))throw TypeError(`${J}.icon must be a supported Host icon token`);return Object.freeze({id:A0(Q.id,`${J}.id`,k1,128),title:Z8(Q.title,`${J}.title`),target:Object.freeze({type:"renderer-message",message:z0(X.message,`${J}.target.message`,128)}),...Y===void 0?{}:{icon:Y}})}function I1(G,F,J,Q){let X=S0(G,F);return D0(X,J,Q,F),{input:X,id:A0(X.id,`${F}.id`,G8,128),command:A0(X.command,`${F}.command`,k1,128),...X.order===void 0?{}:{order:Y8(X.order,`${F}.order`)}}}function K8(G,F){let{input:J,...Q}=I1(G,`Plugin UI toolbar[${F}]`,["id","command"],["order"]);return Object.freeze(Q)}function M8(G,F){let J=`Plugin UI menus[${F}]`,Q=I1(G,J,["id","command","placement"],["group","order"]);if(Q.input.placement!=="overflow")throw TypeError(`${J}.placement must be overflow`);let X=Q.input.group===void 0?void 0:A0(Q.input.group,`${J}.group`,J8,64),{input:Y,...Z}=Q;return Object.freeze({...Z,placement:"overflow",...X===void 0?{}:{group:X}})}function H0(G,F,J){if(!Array.isArray(G)||G.length>J)throw TypeError(`${F} must be a bounded array`);return G}function w0(G,F){let J=new Set;for(let Q of G){if(J.has(Q.id))throw TypeError(`${F} contains a duplicate id: ${Q.id}`);J.add(Q.id)}}function X1(G,F){let J=new Set;for(let Q of G){if(J.has(Q.command))throw TypeError(`${F} contains a duplicate command reference: ${Q.command}`);J.add(Q.command)}}function S8(G){let F=S0(G,"Plugin Canvas UI contribution");D0(F,[],["commands","menus","toolbar"],"Plugin Canvas UI contribution");let J=Object.freeze(H0(F.commands===void 0?[]:F.commands,"Plugin UI commands",Q8).map($8)),Q=Object.freeze(H0(F.menus===void 0?[]:F.menus,"Plugin UI menus",J1).map(M8)),X=Object.freeze(H0(F.toolbar===void 0?[]:F.toolbar,"Plugin UI toolbar",J1).map(K8));w0(J,"Plugin UI commands"),w0(Q,"Plugin UI menus"),w0(X,"Plugin UI toolbar");let Y=new Set(Q.map((W)=>W.id)),Z=X.find((W)=>Y.has(W.id));if(Z)throw TypeError(`Plugin UI placements contain a duplicate id: ${Z.id}`);X1(Q,"Plugin UI menus"),X1(X,"Plugin UI toolbar");let _=new Set(J.map((W)=>W.id)),M=[...Q,...X].find((W)=>!_.has(W.command));if(M)throw TypeError(`Plugin UI placement references an unknown command: ${M.command}`);let K=new Set([...Q,...X].map((W)=>W.command)),D=J.find((W)=>!K.has(W.id));if(D)throw TypeError(`Plugin UI command has no owning-node placement: ${D.id}`);return Object.freeze({commands:J,menus:Q,toolbar:X})}var D8=["time-point","time-range","crop-region","confirmation","immediate"];function U8(G){return D8.some((F)=>F===G)}function W8(G,F){if(G==="image"||G==="video")return G;throw TypeError(`${F} target must be image or video`)}function Y1(G,F){if(!Number.isSafeInteger(G)||Number(G)<1||Number(G)>8192)throw TypeError(`${F} must be an integer between 1 and 8192`);return Number(G)}function j8(G){let F=A(G,"Canvas renderer contribution");if(R(F,["create","extensions","height","mimeTypes","nodeKinds","width"],"Canvas renderer contribution"),F.create!==void 0&&typeof F.create!=="boolean")throw TypeError("Canvas renderer create must be a boolean");let J=T0(F.extensions,"Canvas renderer extensions",(Y)=>{let Z=Y.toLowerCase();if(!/^\.[a-z0-9][a-z0-9._+-]{0,31}$/u.test(Z))throw TypeError(`Invalid Canvas renderer extension: ${Y}`);return Z}),Q=T0(F.mimeTypes,"Canvas renderer MIME types",(Y)=>{let Z=Y.toLowerCase();if(!/^[a-z0-9][a-z0-9!#$&^_.+-]*\/[a-z0-9][a-z0-9!#$&^_.+-]*$/u.test(Z))throw TypeError(`Invalid Canvas renderer MIME type: ${Y}`);return Z}),X=T0(F.nodeKinds,"Canvas renderer node kinds",(Y)=>{if(!/^[a-z][a-z0-9]*(?:[._-][a-z0-9]+)*$/u.test(Y))throw TypeError(`Invalid Canvas renderer node kind: ${Y}`);return Y});if(F.create!==!0&&!J?.length&&!Q?.length&&!X?.length)throw TypeError("Canvas renderer must be creatable or match an extension, MIME type, or node kind");return{...F.create===void 0?{}:{create:F.create},...J===void 0?{}:{extensions:J},...F.height===void 0?{}:{height:Y1(F.height,"Canvas renderer height")},...Q===void 0?{}:{mimeTypes:Q},...X===void 0?{}:{nodeKinds:X},...F.width===void 0?{}:{width:Y1(F.width,"Canvas renderer width")}}}function L0(G,F,J){let Q=A(G,F);return R(Q,["default","zh-CN"],F),{default:E(Q.default,`${F} default`,J),...Q["zh-CN"]===void 0?{}:{"zh-CN":E(Q["zh-CN"],`${F} zh-CN`,J)}}}function V8(G){let F=c(G,"Canvas selection actions",32,!0).map((J,Q)=>{let X=`Canvas selection action ${Q}`,Y=A(J,X);if(Y.action!==void 0){R(Y,["action","description","id","target","title"],X);let D=Y0(Y.id,`${X} id`);if(Y.target!=="video")throw TypeError(`${X} target must be video`);let W=A(Y.action,`${X} action`);if(R(W,["connect","type"],`${X} action`),W.type!=="materialize-own-plugin-node"||W.connect!=="selection-to-created")throw TypeError(`${X} materialization action is not supported`);return{action:{connect:"selection-to-created",type:"materialize-own-plugin-node"},description:L0(Y.description,`${X} description`,2000),id:D,target:"video",title:L0(Y.title,`${X} title`,120)}}R(Y,["description","editor","id","presentation","steps","target","title"],X);let Z=Y0(Y.id,`${X} id`),_=W8(Y.target,X);if(!U8(Y.editor))throw TypeError(`${X} editor is not supported`);let M=Y.editor;if(M==="immediate"!==(_==="image"&&Y.presentation==="cutout-scan")||Y.presentation!==void 0&&Y.presentation!=="cutout-scan")throw TypeError(`${X} immediate editor requires image target and cutout-scan presentation`);let K=c(Y.steps,`${X} steps`,16,!0).map((D,W)=>{let O=`${X} step ${W}`,V=A(D,O);return R(V,["tool"],O),{tool:Y0(V.tool,`${O} tool`)}});if(M!=="confirmation"&&K.length!==1)throw TypeError(`${X} editor requires exactly one step`);return{description:L0(Y.description,`${X} description`,2000),editor:M,id:Z,...Y.presentation===void 0?{}:{presentation:"cutout-scan"},steps:K,target:_,title:L0(Y.title,`${X} title`,120)}});if(new Set(F.map((J)=>J.id)).size!==F.length)throw TypeError("Canvas selection actions contain duplicate ids");return F}function L8(G){let F=A(G,"Canvas contributions");R(F,["commands","menus","renderer","selectionActions","toolbar"],"Canvas contributions");let J=S8({...F.commands===void 0?{}:{commands:F.commands},...F.menus===void 0?{}:{menus:F.menus},...F.toolbar===void 0?{}:{toolbar:F.toolbar}});return{...F.commands===void 0?{}:{commands:J.commands},...F.menus===void 0?{}:{menus:J.menus},...F.renderer===void 0?{}:{renderer:j8(F.renderer)},...F.selectionActions===void 0?{}:{selectionActions:V8(F.selectionActions)},...F.toolbar===void 0?{}:{toolbar:J.toolbar}}}var N8=["text","image","video","audio"],x1=["reference_image","reference_video","first_frame","last_frame","audio","text"],O8=new Set(N8),z8=new Set(x1),A8=/^[a-z][a-z0-9_]{0,63}$/;function R8(G,F){let Q=c(G,F,x1.length).map((X)=>{if(typeof X!=="string"||!z8.has(X))throw TypeError(`${F} contain an unsupported or duplicate role`);return X});if(new Set(Q).size!==Q.length)throw TypeError(`${F} contain an unsupported or duplicate role`);return Q}function E8(G){let F=A(G,"Generation contribution");if(R(F,["models","tools"],"Generation contribution"),!Object.prototype.hasOwnProperty.call(F,"models"))throw TypeError("convax.plugin/8 generation models must be declared explicitly");let J=c(F.tools,"Generation tools",64,!0).map((_,M)=>{let K=`Generation tool ${M}`,D=A(_,K);R(D,["acceptedInputs","delivery","description","id","inputBinding","output","recovery","title"],K);let W=Y0(D.id,`${K} id`);if(typeof D.output!=="string"||!O8.has(D.output))throw TypeError(`${K} output is not supported`);if(D.delivery!==void 0&&D.delivery!=="canvas"&&D.delivery!=="return")throw TypeError(`${K} delivery is not supported`);if(D.delivery==="return"&&D.output!=="text")throw TypeError(`${K} return delivery requires text output`);let O=R8(D.acceptedInputs,`${K} acceptedInputs`);if(D.inputBinding!==void 0&&D.inputBinding!=="direct-incoming")throw TypeError(`${K} input binding is not supported`);if(D.inputBinding==="direct-incoming"&&O.length===0)throw TypeError(`${K} direct-incoming input binding requires accepted inputs`);let V;if(D.recovery!==void 0){let P=A(D.recovery,`${K} recovery`);if(R(P,["mode","schema"],`${K} recovery`),P.schema!=="convax.generation-lro/1"||P.mode!=="long-running-operation")throw TypeError(`${K} recovery contract is not supported`);V={mode:"long-running-operation",schema:"convax.generation-lro/1"}}return{acceptedInputs:O,...D.delivery===void 0?{}:{delivery:D.delivery},description:E(D.description,`${K} description`,2000),id:W,...D.inputBinding===void 0?{}:{inputBinding:D.inputBinding},output:D.output,...V===void 0?{}:{recovery:V},title:E(D.title,`${K} title`,120)}});if(new Set(J.map((_)=>_.id)).size!==J.length)throw TypeError("Generation tools contain duplicate ids");let Q=c(F.models,"Generation models",J.length).map((_,M)=>{let K=`Generation model ${M}`,D=A(_,K);return R(D,["name","tool"],K),{name:E(D.name,`${K} name`,120),tool:Y0(D.tool,`${K} tool`)}});if(new Set(Q.map((_)=>_.tool)).size!==Q.length)throw TypeError("Generation models contain duplicate tool references");let X=new Set(Q.map((_)=>_.tool)),Y=J.find((_)=>_.delivery==="return"&&X.has(_.id));if(Y)throw TypeError(`Generation model cannot reference a return-delivery operation: ${Y.id}`);let Z=J.find((_)=>_.inputBinding!==void 0&&X.has(_.id));if(Z)throw TypeError(`Generation model cannot reference an input-bound operation: ${Z.id}`);return{models:Q,tools:J}}function T8(G){let F=c(G,"Agent tools",32,!0).map((J,Q)=>{let X=`Agent tool ${Q}`,Y=A(J,X);R(Y,["id","tool"],X);let Z=E(Y.id,`${X} id`,64);if(!A8.test(Z))throw TypeError(`${X} id must use lower snake_case`);return{id:Z,tool:Y0(Y.tool,`${X} generation tool`)}});if(new Set(F.map((J)=>J.id)).size!==F.length)throw TypeError("Agent tools contain duplicate ids");if(new Set(F.map((J)=>J.tool)).size!==F.length)throw TypeError("Agent tools contain duplicate generation tool references");return F}function B8(G){let F=A(G,"Agent remote MCP contribution");if(R(F,["headers","oauth","type","url"],"Agent remote MCP contribution"),F.type!=="remote")throw TypeError("Agent MCP type must be remote");let J=E(F.url,"Agent remote MCP URL",2048);try{let X=new URL(J);if(X.protocol!=="https:"||X.username!==""||X.password!==""||X.hash!=="")throw TypeError()}catch{throw TypeError("Agent remote MCP URL must be an absolute HTTPS URL without credentials or a fragment")}if(F.oauth!==void 0&&F.oauth!=="auto"&&F.oauth!=="none")throw TypeError("Agent remote MCP oauth must be auto or none");let Q;if(F.headers!==void 0){let X=A(F.headers,"Agent remote MCP headers"),Y=Object.entries(X);if(Y.length>16)throw TypeError("Agent remote MCP headers must contain at most 16 entries");let Z=new Set;Q={};for(let[_,M]of Y){if(!/^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/u.test(_))throw TypeError(`Agent remote MCP header name is invalid: ${_}`);let K=_.toLowerCase();if(Z.has(K))throw TypeError(`Agent remote MCP headers contain a duplicate name: ${_}`);if(K==="authorization"||K==="cookie"||K==="proxy-authorization")throw TypeError(`Agent remote MCP header is not allowed: ${_}`);let D=E(M,`Agent remote MCP header ${_}`,2048);if(/\{(?:env|file):/iu.test(D)||/\$\{[^}]*\}/u.test(D))throw TypeError(`Agent remote MCP header ${_} must be a literal value`);Z.add(K),Q[_]=D}}return{...Q===void 0?{}:{headers:Q},oauth:F.oauth==="none"?"none":"auto",type:"remote",url:J}}function H8(G){let F=A(G,"Agent contribution");R(F,["mcp","tools"],"Agent contribution");let J=F.tools===void 0?void 0:T8(F.tools),Q=F.mcp===void 0?void 0:B8(F.mcp);if(J===void 0&&Q===void 0)throw TypeError("Agent contribution must declare tools or mcp");return{...Q===void 0?{}:{mcp:Q},...J===void 0?{}:{tools:J}}}function w8(G){let F=new Map(G.generation?.tools.map((Q)=>[Q.id,Q])??[]),J=new Set(G.generation?.models.map((Q)=>Q.tool)??[]);for(let Q of J)if(!F.has(Q))throw TypeError(`Generation model references an unknown tool: ${Q}`);for(let Q of G.agent?.tools??[]){if(!F.has(Q.tool))throw TypeError(`Agent tool references an unknown generation tool: ${Q.tool}`);if(J.has(Q.tool))throw TypeError(`Agent tool must reference an operation, not a generation model: ${Q.tool}`)}for(let Q of G.selectionActions??[]){if(!("steps"in Q))continue;for(let X of Q.steps){let Y=F.get(X.tool);if(!Y)throw TypeError(`Canvas selection action references an unknown generation tool: ${X.tool}`);if(J.has(X.tool))throw TypeError(`Canvas selection action must reference an operation, not a generation model: ${X.tool}`);if(Y.inputBinding!==void 0)throw TypeError(`Canvas selection action cannot reference an input-bound operation: ${X.tool}`);let Z=Q.target==="image"?"reference_image":"reference_video";if(!Y.acceptedInputs.includes(Z))throw TypeError(`Canvas ${Q.target} selection action tool must accept ${Z}: ${X.tool}`);if(Y.delivery==="return"){if(Q.editor!=="confirmation")throw TypeError(`Canvas return-delivery operation requires a confirmation editor: ${X.tool}`);if(Q.steps.length!==1)throw TypeError(`Canvas return-delivery operation requires exactly one step: ${X.tool}`);if(Y.output!=="text")throw TypeError(`Canvas return-delivery operation must return text: ${X.tool}`)}else if(Q.target==="image"&&(Q.editor!=="immediate"||Q.presentation!=="cutout-scan"||Q.steps.length!==1||Y.output!=="image"))throw TypeError(`Canvas image output requires one immediate image operation with cutout-scan presentation: ${X.tool}`)}}}var g1=["authorize","reauthorize","authorization.cancel","checkout","sign_out"],C8=new Set(g1);function P8(G){let F=A(G,"Service contribution");R(F,["actions"],"Service contribution");let J=c(F.actions,"Service actions",g1.length).map((Q)=>{if(typeof Q!=="string"||!C8.has(Q))throw TypeError("Service actions contain an unsupported or duplicate action");return Q});if(new Set(J).size!==J.length)throw TypeError("Service actions contain an unsupported or duplicate action");return{actions:J}}function q8(G){let F=A(G,"LLM contribution");R(F,["modelCatalog","models","provider"],"LLM contribution");let J=A(F.provider,"LLM provider");R(J,["id","name"],"LLM provider");let Q=E(J.id,"LLM provider id",80);if(!/^[a-z0-9]+(?:-[a-z0-9]+)*$/u.test(Q))throw TypeError("LLM provider id must use kebab-case");if(F.modelCatalog!==void 0&&F.modelCatalog!=="runtime")throw TypeError("LLM model catalog must be runtime");let X=c(F.models,"LLM models",32,!0).map((Y,Z)=>{let _=`LLM model ${Z}`,M=A(Y,_);R(M,["id","name"],_);let K=E(M.id,`${_} id`,128);if(!/^~?[a-z0-9]+(?:[._/:-][a-z0-9]+)*$/u.test(K))throw TypeError(`${_} id is invalid`);return{id:K,name:E(M.name,`${_} name`,120)}});if(new Set(X.map((Y)=>Y.id)).size!==X.length)throw TypeError("LLM models contain duplicate ids");return{...F.modelCatalog===void 0?{}:{modelCatalog:"runtime"},models:X,provider:{id:Q,name:E(J.name,"LLM provider name",120)}}}function k8(G){let F=A(G,"Pet contribution");R(F,["library","overlay","protocol","settings"],"Pet contribution");let J=X0(F.library,"Pet library"),Q=X0(F.overlay,"Pet overlay"),X=X0(F.settings,"Pet settings");if(!J.toLowerCase().endsWith(".json"))throw TypeError("Pet library must be a JSON file");if(!Q.toLowerCase().endsWith(".html"))throw TypeError("Pet overlay must be an HTML file");if(!X.toLowerCase().endsWith(".html"))throw TypeError("Pet settings must be an HTML file");if(F.protocol!=="convax.pet-host/1")throw TypeError("Pet protocol must equal convax.pet-host/1");return{library:J,overlay:Q,protocol:"convax.pet-host/1",settings:X}}function I8(G){let F=A(G,"Plugin runtime");if(R(F,["args","command","type"],"Plugin runtime"),F.type!=="mcp-stdio")throw TypeError("Plugin runtime type must be mcp-stdio");let J=E(F.command,"Plugin runtime command",128);if(!/^[A-Za-z0-9][A-Za-z0-9._-]*$/u.test(J))throw TypeError("Plugin runtime command must be a bare executable name");R0(J);let Q;if(F.args!==void 0)Q=c(F.args,"Plugin runtime args",64).map((X,Y)=>{let Z=E(X,`Plugin runtime arg ${Y}`,1024);if(/[\s"'`;|&`$(){}[\]<>]/u.test(Z)||Z.includes("\\")||/(^|=)(?:\/|[A-Za-z]:)/u.test(Z)||/(^|[=/])\.{1,2}(?:\/|$)/u.test(Z))throw TypeError(`Plugin runtime arg ${Y} must be a static CLI token without code, native paths, or traversal`);return Z});return{...Q===void 0?{}:{args:Q},command:J,type:"mcp-stdio"}}var Z1=new Set(U0.apis.filter((G)=>G.audience.includes("agent-skill")).map((G)=>G.id)),x8=/^[a-z][a-z0-9_]{0,63}$/;function g8(G,F){let J=E(G,F,64);if(!/^[a-z0-9]+(?:-[a-z0-9]+)*$/u.test(J))throw TypeError(`${F} must use kebab-case`);return R0(J),J}function f8(G,F,J){let Q=A(G,F);R(Q,["optionalHostApis","pluginTools","requiredHostApis"],F);let X=b0({major:M0,required:Q.requiredHostApis??[],optional:Q.optionalHostApis??[]}),Y=new Set(J.required),Z=new Set([...J.required,...J.optional]);for(let M of X.required){if(!Y.has(M))throw TypeError(`${F} required Host API must be required by the Plugin: ${M}`);if(N0(M)&&!Z1.has(M))throw TypeError(`${F} Host API is not available to Agent Skills: ${M}`)}for(let M of X.optional){if(!Z.has(M))throw TypeError(`${F} optional Host API must be declared by the Plugin: ${M}`);if(N0(M)&&!Z1.has(M))throw TypeError(`${F} Host API is not available to Agent Skills: ${M}`)}let _;if(Q.pluginTools!==void 0){if(_=c(Q.pluginTools,`${F} pluginTools`,32,!0).map((M,K)=>{let D=E(M,`${F} pluginTools ${K}`,64);if(!x8.test(D))throw TypeError(`${F} plugin tool id must use lower snake_case: ${D}`);return D}),new Set(_).size!==_.length)throw TypeError(`${F} pluginTools contain duplicate ids`)}if(X.required.length===0&&X.optional.length===0&&_===void 0)throw TypeError(`${F} must declare at least one Host API or Plugin tool`);return{...X.optional.length===0?{}:{optionalHostApis:[...X.optional]},..._===void 0?{}:{pluginTools:_},...X.required.length===0?{}:{requiredHostApis:[...X.required]}}}function h8(G,F){if(G===void 0)return;let J=c(G,"Plugin Skill contributions",32,!0).map((Q,X)=>{let Y=`Plugin Skill contribution ${X}`,Z=A(Q,Y);R(Z,["name","path","uses"],Y);let _=g8(Z.name,`${Y} name`),M=X0(Z.path,`${Y} path`);if(M.split("/").at(-1)!==_)throw TypeError(`${Y} path must name its Skill directory: ${_}`);let K=Z.uses===void 0?void 0:f8(Z.uses,`${Y} uses`,F);return{name:_,path:M,...K===void 0?{}:{uses:K}}});if(new Set(J.map((Q)=>Q.name)).size!==J.length)throw TypeError("Plugin Skill contributions contain duplicate names");if(new Set(J.map((Q)=>Q.path.toLocaleLowerCase("en-US"))).size!==J.length)throw TypeError("Plugin Skill contributions contain duplicate paths");return J}function y8(G,F){let J=new Set(F?.tools?.map((Q)=>Q.id)??[]);for(let Q of G??[])for(let X of Q.uses?.pluginTools??[])if(!J.has(X))throw TypeError(`Plugin Skill ${Q.name} references an unknown Agent tool: ${X}`)}var _1="convax.plugin/8";var f1=["canvas.connectedImages.read","canvas.connectedInputs.read","canvas.connectedMedia.stream","canvas.node.read","canvas.node.write","canvas.image.write","project.files.read","agent.prompt","generation.execute","ui.fullscreen","projects.read","canvas.catalog.read","canvas.document.read","canvas.document.write","canvas.events.subscribe","pet.activity.read","pet.activity.open","pet.preferences.write","pet.custom.manage"],c8=["projects.read","canvas.catalog.read","canvas.document.read","canvas.document.write","canvas.events.subscribe"],h1=["pet.activity.read","pet.activity.open","pet.preferences.write","pet.custom.manage"],$1=["pet.activity.read","pet.activity.open","pet.preferences.write"],b8=new Set(f1),d8=new Set(h1);function v8(G){let F=c(G??[],"Plugin capabilities",f1.length).map((J)=>{if(typeof J!=="string"||!b8.has(J))throw TypeError("Plugin capabilities contain an unsupported or duplicate capability");return J});if(new Set(F).size!==F.length)throw TypeError("Plugin capabilities contain an unsupported or duplicate capability");return F}function m8(G){let F=G.entry===void 0?void 0:X0(G.entry,"Plugin entry");if(F!==void 0&&!F.toLowerCase().endsWith(".html"))throw TypeError("Plugin entry must be an HTML file");let J=G.hooks===void 0?void 0:X0(G.hooks,"Plugin hooks");if(J!==void 0&&!/\.(?:js|mjs)$/u.test(J))throw TypeError("Plugin hooks must be a JavaScript ESM module");return{entry:F,hooks:J}}function p8(G){let{capabilities:F,canvas:J,entry:Q,hostApi:X}=G;if(Q!==void 0!==(J?.renderer!==void 0))throw TypeError("Plugin entry and Canvas renderer must appear together");if(Q!==void 0&&!X.required.includes("host.context.get"))throw TypeError("convax.plugin/8 Web Plugins must require host.context.get");if((J?.commands!==void 0||J?.menus!==void 0||J?.toolbar!==void 0)&&J.renderer===void 0)throw TypeError("Canvas UI commands require a sandboxed Canvas renderer");if(F.includes("generation.execute")&&J?.renderer===void 0)throw TypeError("generation.execute requires a sandboxed Canvas surface");if(J&&J.renderer===void 0&&!J.selectionActions?.length&&!J.commands?.length&&!J.menus?.length&&!J.toolbar?.length)throw TypeError("Canvas contributions must declare a renderer, selection actions, or UI commands");if(J?.selectionActions?.some((Y)=>("action"in Y)&&Y.action.type==="materialize-own-plugin-node")&&J.renderer===void 0)throw TypeError("materialize-own-plugin-node requires the contributing Plugin renderer")}function s8(G,F,J){if(F===void 0)return;if(G.length<$1.length||G.length>h1.length||$1.some((Q)=>!G.includes(Q))||G.some((Q)=>!d8.has(Q)))throw TypeError("Pet capabilities must include pet.activity.read, pet.activity.open, and pet.preferences.write; pet.custom.manage is optional");if(J!==void 0)throw TypeError("Pet feature cannot declare an executable runtime")}function o8(G,F={}){let J=A(G,"Plugin manifest");if(R(J,["capabilities","contributes","description","entry","hooks","hostApi","id","name","runtime","schema","version"],"Plugin manifest"),J.schema!==_1)throw TypeError("Plugin manifest must use convax.plugin/8");if(!Object.prototype.hasOwnProperty.call(J,"hostApi"))throw TypeError("convax.plugin/8 must declare hostApi explicitly");let Q=F.hostApiMode==="authoring"?RF(J.hostApi):b0(J.hostApi),X=v8(J.capabilities),Y=A(J.contributes,"Plugin contributions");R(Y,["agent","canvas","capabilities","generation","llm","pet","service","skills"],"Plugin contributions");let{entry:Z,hooks:_}=m8(J),M=Y.canvas===void 0?void 0:L8(Y.canvas);p8({capabilities:X,canvas:M,entry:Z,hostApi:Q});let K=Y.agent===void 0?void 0:H8(Y.agent),D=Y.capabilities===void 0?void 0:cF(Y.capabilities),W=Y.generation===void 0?void 0:E8(Y.generation),O=Y.llm===void 0?void 0:q8(Y.llm),V=Y.pet===void 0?void 0:k8(Y.pet),P=Y.service===void 0?void 0:P8(Y.service),G0=h8(Y.skills,Q),v=J.runtime===void 0?void 0:I8(J.runtime),J0=W!==void 0||P!==void 0||O!==void 0||Boolean(D?.exports.length);if(v!==void 0!==J0){if(D?.exports.length&&v===void 0)throw TypeError("Plugin capability exports require a verified mcp-stdio runtime");throw TypeError("convax.plugin/8 runtime and executable contribution must appear together")}if(D?.exports.length&&v===void 0)throw TypeError("Plugin capability exports require a verified mcp-stdio runtime");s8(X,V,v),w8({agent:K,generation:W,selectionActions:M?.selectionActions}),y8(G0,K);let U=new Set(c8),j=X.some((L)=>U.has(L));if(M?.renderer===void 0&&!M?.selectionActions?.length&&!J0&&_===void 0&&!X.includes("generation.execute")&&!j&&V===void 0&&(D?.exports.length??0)===0&&K?.mcp===void 0)throw TypeError("convax.plugin/8 must declare a Plugin capability beyond owned Skills");return R1({capabilities:X,contributes:{...K===void 0?{}:{agent:K},...D===void 0?{}:{capabilities:D},...M===void 0?{}:{canvas:M},...W===void 0?{}:{generation:W},...O===void 0?{}:{llm:O},...V===void 0?{}:{pet:V},...P===void 0?{}:{service:P},...G0===void 0?{}:{skills:G0}},description:E(J.description,"Plugin description",2000),...Z===void 0?{}:{entry:Z},..._===void 0?{}:{hooks:_},hostApi:Q,id:E1(J.id),name:E(J.name,"Plugin name",120),...v===void 0?{}:{runtime:v},schema:_1,version:vF(J.version)})}function r8(G){return o8(G,{hostApiMode:"authoring"})}class f extends Error{code;constructor(G,F){super(F);this.name="PluginHostProtocolError",this.code=G}}class v0 extends Error{code;kind;recoverable;constructor(G){super(G.message);this.name="PluginHostRemoteError",this.code=G.code,this.kind=G.kind,this.recoverable=G.recoverable}}class h0 extends Error{reason;constructor(G){super("Plugin Host request was aborted");this.name="AbortError",this.reason=G}}var K1=0;function u8(){return K1+=1,`sdk-${Date.now().toString(36)}-${K1.toString(36)}`}function n8(G){if(G.length<1||G.length>96||G!==G.trim()||!/^[A-Za-z0-9._-]+$/.test(G))throw TypeError("Plugin Host requestIdPrefix is invalid")}function M1(G,F){let J=G.contributes.capabilities,Q=J?.imports.required.find((Y)=>Y.id===F);if(Q)return{import:Q,requirement:"required"};let X=J?.imports.optional.find((Y)=>Y.id===F);if(X)return{import:X,requirement:"optional"};throw TypeError(`Plugin capability import is not declared: ${F}`)}function t8(G,F){let J=F.kind==="protocol"?q1(F):BF(G,F);return new v0(J)}function S1(G){let F=G.kind==="protocol"?q1(G):eF(G);return new v0(F)}function y1(G){let F=r8(G.manifest);if(F.entry===void 0||!F.hostApi.required.includes("host.context.get"))throw TypeError("Plugin Host Web client requires an entry and required host.context.get negotiation baseline");let J=G.requestIdPrefix??u8();n8(J);let Q=new Map,X=new Set,Y,Z,_=0,M=!1,K=(U)=>{for(let j of Q.values())j.abort?.(),j.reject(U);Q.clear()},D=(U)=>{if(M)return;M=!0,G.port.removeEventListener("message",G0),X.clear(),K(U);try{G.onFatalError?.(U)}catch{}},W=()=>{if(_>=Number.MAX_SAFE_INTEGER){let j=new f("request-id-exhausted","Plugin Host request id space is exhausted");throw D(j),j}_+=1;let U=`${J}-${_.toString(36)}`;if(!C1(U)){let j=new f("request-id-exhausted","Plugin Host request id is invalid");throw D(j),j}return U},O=(U,j)=>{G1(U,j,"Plugin Host request")},V=(U)=>{G.port.postMessage(U)},P=(U,j,L,N)=>{if(M)return Promise.reject(new f("closed","Plugin Host client is closed"));if(N?.aborted)return Promise.reject(new h0(N.reason));if(Q.size>=e0)return Promise.reject(RangeError(`Plugin Host client permits at most ${e0} in-flight requests`));try{O(U,L.maximumRequestBytes)}catch(b){return Promise.reject(b)}let T=U.id;return new Promise((b,h)=>{let Q0=N?()=>{let n=Q.get(T);if(!n)return;Q.delete(T),n.abort?.();let m={id:T,protocol:l,type:"cancel"};try{O(m,B0),V(m)}catch(p){let p0=new f("transport-failed",p instanceof Error?p.message:"Plugin Host cancel failed");h(p0),D(p0);return}h(new h0(N.reason))}:void 0,W0=Q0?()=>{N.removeEventListener("abort",Q0)}:void 0;if(Q.set(T,{abort:W0,maximumResponseBytes:L.maximumResponseBytes,parseFailure:L.parseFailure,parseResult:j,reject:h,resolve:b}),Q0)N.addEventListener("abort",Q0,{once:!0});try{V(U)}catch(n){D(new f("transport-failed",n instanceof Error?n.message:"Plugin Host transport failed"))}})};function G0(U){if(M)return;let j;try{j=G1(U.data,pF,"Plugin Host response")}catch{D(new f("invalid-envelope","Plugin Host sent a non-JSON message"));return}if(aF(U.data)){try{for(let T of X)T(U.data)}catch{D(new f("invalid-envelope","Plugin Host command listener failed"))}return}if(!iF(U.data)){D(new f("invalid-envelope","Plugin Host sent an invalid envelope"));return}let L=U.data,N=Q.get(L.id);if(!N){D(new f("unknown-response",`Plugin Host returned an unknown, duplicate, or late response id: ${L.id}`));return}if(j>N.maximumResponseBytes){D(new f("invalid-envelope",`Plugin Host response exceeds ${N.maximumResponseBytes} bytes for this request`));return}if(!L.ok){try{let T=N.parseFailure(L.error);Q.delete(L.id),N.abort?.(),N.reject(T)}catch(T){D(new f("invalid-result",T instanceof Error?T.message:"Plugin Host returned an invalid failure"))}return}try{let T=N.parseResult(L.result);Q.delete(L.id),N.abort?.(),N.resolve(T)}catch(T){D(new f("invalid-result",T instanceof Error?T.message:"Plugin Host returned an invalid result"))}}G.port.addEventListener("message",G0),G.port.start?.();let v=(U,j)=>{if(!t0(F.hostApi,U))return Promise.reject(TypeError(`Plugin Host API is not declared: ${U}`));let L=jF[U],N=L.params.type==="none"?void 0:j[0],T=L.params.type==="none"?j[0]:j[1],b;try{b=VF(U,N)}catch(m){return Promise.reject(m)}let Q0={id:W(),method:U,...b===void 0?{}:{params:b},protocol:l,type:"request"},W0=SF(U),n=LF;return P(Q0,(m)=>{let p=n(U,m);if(U==="host.context.get")Y=p;return p},{maximumRequestBytes:W0.request.maxBytes,maximumResponseBytes:W0.result.maxBytes,parseFailure:(m)=>{let p=t8(U,m);if(p.kind==="api"&&p.code==="stale-context")Y=void 0;return p}},T?.signal)},J0={get closed(){return M},callHostApi(U,...j){return v(U,j)},async getHostApiAvailability(U,j){if(!t0(F.hostApi,U))throw TypeError(`Plugin Host API is not declared: ${U}`);return(!Y||j?.refresh?await J0.refreshHostApiContext(j):Y).hostApi.availability.find(({id:N})=>N===U)??{available:!1,id:U,reason:"unsupported-host",recoverable:!1}},refreshHostApiContext(U){if(Y=void 0,Z)return Z;let L=v("host.context.get",[U]).finally(()=>{if(Z===L)Z=void 0});return Z=L,Z},async requireHostApi(U,j){let L=await J0.getHostApiAvailability(U,j);if(!L.available)throw new z1(L);return L},getCapabilityAvailability(U,j){let L;try{L=M1(F,U)}catch(b){return Promise.reject(b)}let N=W();return P({capabilityId:U,id:N,protocol:l,type:"capability-availability"},(b)=>{let h=lF(b);if(h.capabilityId!==U||h.requirement!==L.requirement)throw TypeError("Plugin capability availability does not match the declared import");return h},{maximumRequestBytes:B0,maximumResponseBytes:l0,parseFailure:S1},j?.signal)},invokeCapability(U,j,L){let N;try{N=M1(F,U),a0(N.import.inputSchema,j,`Plugin capability ${U} input`)}catch(h){return Promise.reject(h)}let T=W();return P({capabilityId:U,id:T,input:j,protocol:l,type:"capability-invoke"},(h)=>{return a0(N.import.outputSchema,h,`Plugin capability ${U} output`),h},{maximumRequestBytes:B0,maximumResponseBytes:l0,parseFailure:S1},L?.signal)},onCommand(U){if(M)throw new f("closed","Plugin Host client is closed");if(X.size>=64)throw RangeError("Plugin Host command listener limit exceeded");return X.add(U),()=>{X.delete(U)}},close(){D(new f("closed","Plugin Host client was closed"))}};return J0}var m0={schema:"convax.plugin/8",id:"hello-convax",name:"Hello Convax",description:"Checks the scoped Convax Plugin host connection and shows its active context.",version:"0.1.3",entry:"index.html",capabilities:[],contributes:{canvas:{renderer:{create:!0,width:480,height:300}}},hostApi:{major:1,required:["host.context.get"],optional:[]}};var G4="@convax/plugin-sdk/client:createPluginHostClient";function J4(G,F={}){if(G.source!==window.parent||G.ports.length!==1||!P1(G.data)||G.data.pluginId!==m0.id)return null;return y1({manifest:m0,onFatalError:F.onFatalError,port:G.ports[0],requestIdPrefix:F.requestIdPrefix})}export{G4 as pluginSdkClientBundleMarker,J4 as acceptPluginHostConnection}; +var mF=/^[a-z][a-z0-9]*(?:\.[a-z][a-z0-9]*)+$/,dF=/^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/,pF=/^[a-z][A-Za-z0-9]*(?:\.[a-z][A-Za-z0-9]*)+$/,sF=/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/,oF=new Set(["web-plugin","agent-skill","companion","host"]),rF=new Set(["connection","plugin","own-node","project","canvas"]),uF=new Set(["none","read","write","execute","subscribe"]),nF=new Set(["cancelable","commit-preserving"]);function _0(F,G){if(F.trim().length===0)throw TypeError(`${G} must not be empty`)}function R0(F,G){if(!sF.test(F))throw TypeError(`${G} must be a strict semantic version`)}function I0(F,G){let J=F.split(".").map(Number),Q=G.split(".").map(Number);for(let X=0;X<3;X+=1){let Y=J[X]-Q[X];if(Y!==0)return Y}return 0}function LF(F){if(!mF.test(F.id))throw TypeError(`Plugin API id is invalid: ${F.id}`);if(R0(F.contractSince,`${F.id} contractSince`),F.grant!==null&&!pF.test(F.grant))throw TypeError(`Plugin API grant is invalid: ${F.grant}`);if(!rF.has(F.scope))throw TypeError(`Plugin API scope is invalid: ${F.scope}`);if(!uF.has(F.sideEffect))throw TypeError(`Plugin API sideEffect is invalid: ${F.sideEffect}`);if(!nF.has(F.completion))throw TypeError(`Plugin API completion is invalid: ${F.completion}`);let G=F.audience??["web-plugin"];if(G.length===0||new Set(G).size!==G.length||G.some((X)=>!oF.has(X)))throw TypeError(`Plugin API audience is invalid: ${F.id}`);_0(F.docs.summary,`${F.id} docs.summary`),_0(F.docs.description,`${F.id} docs.description`),_0(F.docs.request,`${F.id} docs.request`),_0(F.docs.response,`${F.id} docs.response`);let J=new Set,Q=F.errors.map((X)=>{if(!dF.test(X.code)||J.has(X.code))throw TypeError(`Plugin API error code is invalid or duplicated: ${F.id}/${X.code}`);return J.add(X.code),_0(X.description,`${F.id}/${X.code} description`),Object.freeze({...X})});return Object.freeze({...F,audience:Object.freeze([...G]),errors:Object.freeze(Q),docs:Object.freeze({...F.docs})})}function tF(F){return LF(F)}function t0(F,G){return R0(F,"Plugin API release version"),Object.freeze({version:F,apis:Object.freeze([...G])})}function iF(...F){if(F.length===0)throw TypeError("Plugin API catalog requires at least one release");let G=new Set,J=[],Q=new Set(F.map((Y)=>Y.version)),X;for(let Y of F){if(R0(Y.version,"Plugin API release version"),X&&I0(X,Y.version)>=0)throw TypeError("Plugin API releases must be strictly increasing");X=Y.version;for(let Z of Y.apis){let _=LF(Z);if(G.has(_.id))throw TypeError(`Plugin API id is duplicated: ${_.id}`);if(I0(_.contractSince,Y.version)<0)throw TypeError(`Plugin API ${_.id} contractSince must not precede since`);if(!Q.has(_.contractSince))throw TypeError(`Plugin API ${_.id} contractSince must identify a Catalog release block`);G.add(_.id),J.push(Object.freeze({..._,since:Y.version}))}}if(J.length===0)throw TypeError("Plugin API catalog must contain at least one API");return Object.freeze({version:F[F.length-1].version,apis:Object.freeze(J)})}var Y1=Object.freeze({assertVersion:R0,compareVersions:I0}),aF="convax.plugin-api-wire-schema/3",z=1024,I=z*z,lF=16*I,i0=8192,eF=33554432,$0={type:"none"},m={type:"boolean"},B={finite:!0,type:"number"},o={finite:!0,minimum:0,type:"integer"},T0=(F)=>({finite:!0,maximum:F,minimum:1,type:"integer"}),B0={type:"null"},g=(F)=>({const:F}),$=(F=2048,G={})=>({controlCharacters:!1,maxLength:F,minLength:G.allowEmpty?0:1,...G.prefix?{prefix:G.prefix}:{},...G.refinement?{refinement:G.refinement}:{},type:"string"}),q=(F,G,J=0,Q)=>({items:F,maxItems:G,minItems:J,type:"array",...Q?{uniqueBy:Q}:{}}),S=(F,G,J)=>({additionalProperties:!1,properties:F,...J?{products:J}:{},required:G,type:"object"}),l=(...F)=>({oneOf:F}),g0=(F=I)=>({keyMaxLength:128,maxBytes:F,maxDepth:32,type:"json-object"}),h=(F)=>({controlCharacters:!1,enum:F,maxLength:Math.max(...F.map((G)=>G.length)),minLength:1,type:"string"}),Z0=S({x:B,y:B},["x","y"]),d0=S({height:B,width:B},["height","width"]),i=S({canvasId:$(256),projectId:$(256)},["canvasId","projectId"]),x0=h(["text","image","video","audio"]),NF=h(["text","reference_image","reference_video","first_frame","last_frame","audio"]),x=(F=1000)=>q($(),F),F2=l(S({available:g(!0),catalogVersion:$(64),contractSince:$(64),id:$(128),since:$(64)},["available","catalogVersion","contractSince","id","since"]),S({available:g(!1),contractSince:$(64),id:$(128),reason:h(["unsupported-host","not-declared","permission-denied","wrong-surface","missing-context","setup-required","disabled","recovering"]),recoverable:m,since:$(64)},["available","id","reason","recoverable"])),OF=S({data:g0(),id:$(),parentId:$(),position:Z0,revision:o,style:g0(),type:$(80)},["data","id","position","revision","type"]),G2=S({inputKey:$(),role:NF},["inputKey","role"]),J2=S({ids:x(),kinds:x(),limit:o,relatedToNodeIds:x(),text:$(2000,{allowEmpty:!0})},[]),Q2=S({animated:m,id:$(),source:$(),target:$(),type:$(80)},["source","target"]),X2=S({nodeId:$(),position:Z0,size:d0},["nodeId","position"]),Y2=S({componentGap:B,componentPackingScale:B,crossGap:B,isolatedPlacement:h(["left","preserve"]),mainGap:B,nodeGap:B,nodePackingScale:B,strategy:h(["component-packing","horizontal-directed-cluster","vertical-directed-cluster"])},[]),Z2=l(S({edgeIds:x(),nodeIds:x(),type:g("elements.remove")},["type"]),S({direction:h(["left","center","right","top","middle","bottom"]),nodeIds:x(),type:g("nodes.align")},["direction","nodeIds","type"]),S({connection:Q2,type:g("nodes.connect")},["connection","type"]),S({axis:h(["horizontal","vertical"]),nodeIds:x(),type:g("nodes.distribute")},["axis","nodeIds","type"]),S({label:$(512),nodeIds:x(),type:g("nodes.group")},["nodeIds","type"]),S({gap:B,layout:h(["grid","horizontal","vertical"]),nodeIds:x(),type:g("nodes.layout")},["nodeIds","type"]),S({delta:Z0,nodeIds:x(),type:g("nodes.move")},["delta","nodeIds","type"]),S({type:g("nodes.setGeometry"),updates:q(X2,1000)},["type","updates"]),S({nodeId:$(),type:g("nodes.ungroup")},["nodeId","type"]),S({nodeIds:x(),options:Y2,type:g("canvas.auto-layout")},["type"])),_2=S({durationMs:B,height:B,inputKey:$(),kind:$(80),label:$(512),mediaRevision:$(512),mimeType:$(512),name:$(512),status:h(["error","idle","pending"]),width:B},["inputKey","kind","label"]),$2=S({contentRevision:$(64,{refinement:"lowercase-sha256"}),height:T0(i0),kind:g("image"),mimeType:h(["image/jpeg","image/png","image/webp"]),size:T0(lF),width:T0(i0)},["contentRevision","height","kind","mimeType","size","width"],[{fields:["width","height"],maximum:eF}]),K2=S({acceptedInputs:q(NF,6),description:$(2000),id:$(256),kind:h(["model","operation"]),output:x0,title:$(120)},["acceptedInputs","description","id","kind","output","title"]),zF=S({id:$(),source:$(),target:$()},["id","source","target"]),M2=S({id:$(),kind:$(80),label:$(512),parentId:$(64*z,{allowEmpty:!0}),position:Z0,size:d0,type:$(64*z,{allowEmpty:!0})},["id","kind","label","position","size"]),S2=S({description:$(64*z,{allowEmpty:!0}),durationMs:B,id:$(),kind:$(80),label:$(512),mimeType:$(64*z,{allowEmpty:!0}),name:$(64*z,{allowEmpty:!0}),parentId:$(64*z,{allowEmpty:!0}),position:Z0,resource:S({kind:g("project-file"),path:$(1024)},["kind","path"]),size:d0,status:$(64*z,{allowEmpty:!0}),text:$(64*z,{allowEmpty:!0}),type:$(64*z,{allowEmpty:!0})},["id","kind","label","position","size"]),D2=S({edges:q(zF,1e4),id:$(256),nodes:q(M2,1e4),revision:o,title:$(512)},["edges","id","nodes","revision","title"]),U2=S({description:$(8000,{allowEmpty:!0}),edges:q(zF,1e4),id:$(256),nodes:q(S2,1e4),revision:o,tags:q($(),256),title:$(512)},["edges","id","nodes","revision","title"]),W2=S({id:$(),incomingNodeIds:x(),kind:$(80),label:$(512),outgoingNodeIds:x(),parentId:$(64*z,{allowEmpty:!0}),position:Z0,text:$(64*z,{allowEmpty:!0}),type:$(64*z,{allowEmpty:!0})},["id","incomingNodeIds","kind","label","outgoingNodeIds","position"]),j2=S({canvas:S({id:$(256),name:$(512)},["id"]),hostApi:S({availability:q(F2,256,0,"id"),catalogVersion:$(64)},["availability","catalogVersion"]),node:OF,plugin:S({id:$(128),name:$(512),version:$(128)},["id","name","version"]),project:S({id:$(256),name:$(512)},["id"])},["canvas","hostApi","node","plugin","project"]),H=(F,G,J={})=>({dialect:aF,request:{maxBytes:J.request??64*z,schema:F},result:{maxBytes:J.result??64*z,schema:G}}),F0=Object.freeze({"host.context.get":H($0,j2,{result:I}),"canvas.inputs.list":H($0,S({inputs:q(_2,256)},["inputs"]),{result:I}),"canvas.inputs.image.open":H(S({inputKey:$()},["inputKey"]),S({probe:$2,sessionId:$(128),url:$(2048,{prefix:"convax-connected-media://"})},["probe","sessionId","url"])),"canvas.inputs.image.close":H(S({sessionId:$(128)},["sessionId"]),S({closed:m},["closed"])),"canvas.inputs.open":H(S({inputKey:$()},["inputKey"]),S({probe:S({duration:S({estimated:m,milliseconds:B},["estimated","milliseconds"]),height:B,kind:h(["audio","video"]),mediaRevision:$(128),mimeType:$(256),size:B,width:B},["duration","kind","mediaRevision","mimeType","size"]),sessionId:$(128),url:$(2048,{prefix:"convax-connected-media://"})},["probe","sessionId","url"])),"canvas.inputs.close":H(S({sessionId:$(128)},["sessionId"]),S({closed:m},["closed"])),"canvas.node.get":H($0,OF,{result:I}),"canvas.node.state.replace":H(S({state:g0(256*z)},["state"]),S({updated:g(!0)},["updated"]),{request:256*z+4*z}),"canvas.resource.image.create":H(S({dataUrl:$(24*I,{prefix:"data:image/png;base64,"}),name:$(120,{refinement:"safe-png-file-name"})},["dataUrl","name"]),S({createdNodeId:$(),revision:o},["createdNodeId","revision"]),{request:24*I+4*z}),"project.file.text.read":H(S({path:$(1024,{refinement:"portable-project-relative-path"})},["path"]),S({content:$(I,{allowEmpty:!0}),exists:m,path:$(1024,{refinement:"portable-project-relative-path"})},["content","exists","path"]),{result:I+4*z}),"agent.prompt":H(S({text:$(20000,{refinement:"trimmed"})},["text"]),S({text:$(64*z,{allowEmpty:!0})},["text"])),"generation.tools.list":H(l($0,S({output:x0},[])),S({tools:q(K2,256)},["tools"]),{result:I}),"generation.execute":H(S({output:x0,prompt:$(20000,{refinement:"trimmed"}),references:q(G2,32),resultMode:h(["create-pending-node","return"]),toolId:$(256)},["prompt"]),S({createdNodeIds:q($(),32),outputText:$(64*z,{allowEmpty:!0}),revision:o,toolId:$(256),warnings:q($(),32)},["createdNodeIds","revision","toolId","warnings"]),{result:256*z}),"projects.list":H($0,S({projects:q(S({available:m,id:$(256),name:$(512)},["available","id","name"]),1000)},["projects"]),{result:I}),"canvas.catalog.list":H(S({projectId:$(256)},["projectId"]),S({canvases:q(S({createdAt:B,id:$(256),name:$(512),updatedAt:B},["createdAt","id","name","updatedAt"]),1e4),projectId:$(256)},["canvases","projectId"]),{result:8*I}),"canvas.document.get":H(S({projection:h(["geometry","structure"]),ref:i},["ref"]),l(S({document:D2,projection:g("geometry"),ref:i,storageVersion:l(B0,$(256))},["document","projection","ref","storageVersion"]),S({document:U2,projection:g("structure"),ref:i,storageVersion:l(B0,$(256))},["document","projection","ref","storageVersion"])),{result:8*I}),"canvas.nodes.query":H(S({query:J2,ref:i},["ref"]),S({nodes:q(W2,1000),ref:i,revision:o,storageVersion:l(B0,$(256))},["nodes","ref","revision","storageVersion"]),{request:I,result:8*I}),"canvas.transaction.execute":H(S({commands:q(Z2,256,1),expectedRevision:o,ref:i,transactionId:$(128)},["commands","expectedRevision","ref","transactionId"]),S({affectedNodeIds:x(1e4),changed:m,createdNodeIds:x(1e4),ref:i,revision:o,storageVersion:$(256),summaryTruncated:m,warnings:x()},["affectedNodeIds","changed","createdNodeIds","ref","revision","storageVersion","warnings"]),{request:I,result:2*I}),"canvas.events.subscribe":H(S({ref:S({canvasId:$(256),projectId:$(256)},["projectId"])},["ref"]),S({subscriptionId:$(128)},["subscriptionId"])),"canvas.events.unsubscribe":H(S({subscriptionId:$(128)},["subscriptionId"]),S({removed:m},["removed"]))}),V2=Math.max(...Object.values(F0).map(({request:F})=>F.maxBytes)),L2=Math.max(...Object.values(F0).map(({result:F})=>F.maxBytes));function N2(F){return F0[F]}function f0(F,G){if(!F||typeof F!=="object"||Array.isArray(F))throw TypeError(`${G} must be an object`);let J=Object.getPrototypeOf(F);if(J!==Object.prototype&&J!==null)throw TypeError(`${G} must be a plain object`);return F}var O2=/^(CON|PRN|AUX|NUL|COM[1-9¹²³]|LPT[1-9¹²³]|CONIN\$|CONOUT\$)$/iu;function AF(F){for(let G of F){let J=G.codePointAt(0);if(J>=55296&&J<=57343)return!1}return!0}function a0(F){let G=F.split(".",1)[0]??"";return Boolean(F&&F!=="."&&F!==".."&&AF(F)&&!/[\\/:*?"<>|\u0000-\u001f\u007f]/u.test(F)&&!/[. ]$/u.test(F)&&!O2.test(G))}function z2(F,G){if(G===void 0)return!0;if(G==="lowercase-sha256")return/^[a-f0-9]{64}$/u.test(F);if(G==="trimmed")return F===F.trim();if(G==="safe-png-file-name")return F===F.trim()&&F.toLowerCase().endsWith(".png")&&a0(F);if(G==="portable-project-relative-path"){if(F!==F.trim()||F.includes("\\")||F.startsWith("/")||F.startsWith("//")||/^[A-Za-z]:/u.test(F)||!AF(F))return!1;let J=F.split("/");return J[0]?.toLowerCase()!==".convax"&&J.length>0&&J.every((Q)=>a0(Q))}return!1}function A2(F,G,J){let Q=new Set,X=(_,M,K)=>{if(_===null||typeof _==="string"||typeof _==="boolean")return _;if(typeof _==="number"){if(!Number.isFinite(_))throw TypeError(`${M} must contain finite JSON numbers`);return _}if(!_||typeof _!=="object"||K>=G.maxDepth||Q.has(_))throw TypeError(`${M} must be bounded acyclic JSON`);let D=Object.getPrototypeOf(_);if(!Array.isArray(_)&&D!==Object.prototype&&D!==null)throw TypeError(`${M} must contain plain JSON objects`);Q.add(_);let j;if(Array.isArray(_))j=_.map((O,L)=>X(O,`${M}[${L}]`,K+1));else{let O=Object.create(null);for(let[L,k]of Object.entries(_)){if(L.length<1||L.length>G.keyMaxLength||/[\u0000-\u001f\u007f]/u.test(L))throw TypeError(`${M} key is invalid`);O[L]=X(k,`${M}.${L}`,K+1)}j=O}return Q.delete(_),j},Y=X(f0(F,J),J,0);if(Array.isArray(Y)||!Y||typeof Y!=="object")throw TypeError(`${J} must be an object`);let Z=JSON.stringify(Y);if(new TextEncoder().encode(Z).byteLength>G.maxBytes)throw TypeError(`${J} exceeds ${G.maxBytes} bytes`);return Y}function R2(F,G,J){for(let Q of G??[]){let X=1;for(let Y of Q.fields){let Z=F[Y];if(typeof Z!=="number"||!Number.isFinite(Z)||Z<0)throw TypeError(`${J}.${Y} must be a non-negative finite product factor`);if(Z!==0&&X>Q.maximum/Z)throw TypeError(`${J} must satisfy its numeric product limits`);X*=Z}if(X>Q.maximum)throw TypeError(`${J} must satisfy its numeric product limits`)}return F}function K0(F,G,J="Plugin API value"){if("oneOf"in F){let Z=[];for(let _ of F.oneOf)try{Z.push(K0(_,G,J))}catch{}if(Z.length!==1)throw TypeError(`${J} must match exactly one schema variant`);return Z[0]}if("const"in F){if(G!==F.const)throw TypeError(`${J} must equal ${String(F.const)}`);return G}if("type"in F&&F.type==="none"){if(G!==void 0)throw TypeError(`${J} does not accept a value`);return}if("type"in F&&F.type==="null"){if(G!==null)throw TypeError(`${J} must be null`);return null}if("type"in F&&F.type==="boolean"){if(typeof G!=="boolean")throw TypeError(`${J} must be boolean`);return G}if("type"in F&&(F.type==="number"||F.type==="integer")){if(typeof G!=="number"||!Number.isFinite(G)||F.type==="integer"&&!Number.isSafeInteger(G)||F.minimum!==void 0&&GF.maximum)throw TypeError(`${J} must be a valid ${F.type}`);return G}if("type"in F&&F.type==="string"){if(typeof G!=="string"||G.lengthF.maxLength||F.controlCharacters===!1&&/[\u0000-\u001f\u007f]/u.test(G)||F.enum!==void 0&&!F.enum.includes(G)||F.prefix!==void 0&&!G.startsWith(F.prefix)||!z2(G,F.refinement))throw TypeError(`${J} must satisfy its bounded string contract`);return G}if("type"in F&&F.type==="array"){if(!Array.isArray(G)||G.lengthF.maxItems)throw TypeError(`${J} must satisfy its bounded array contract`);let Z=G.map((_,M)=>K0(F.items,_,`${J}[${M}]`));if(F.uniqueBy!==void 0){let _=Z.map((M)=>{let D=f0(M,`${J} unique item`)[F.uniqueBy];if(typeof D!=="string"&&typeof D!=="number")throw TypeError(`${J} unique identity is invalid`);return`${typeof D}:${String(D)}`});if(new Set(_).size!==_.length)throw TypeError(`${J} contains duplicate ${F.uniqueBy}`)}return Z}if("type"in F&&F.type==="json-object")return A2(G,F,J);if(!("properties"in F))throw TypeError(`${J} has an unsupported schema`);let Q=f0(G,J),X=new Set(Object.keys(F.properties));if(F.required.some((Z)=>!Object.prototype.hasOwnProperty.call(Q,Z))||Object.keys(Q).some((Z)=>!X.has(Z)))throw TypeError(`${J} contains unsupported or missing fields`);let Y=Object.fromEntries(Object.entries(Q).map(([Z,_])=>[Z,K0(F.properties[Z],_,`${J}.${Z}`)]));return R2(Y,F.products,J)}function h0(F,G){if("oneOf"in F){let J=F.oneOf.map((Z)=>h0(Z,G)),Q=J.filter((Z)=>Z.type==="object");if(Q.length===0&&J.some((Z)=>Z.type==="none"))return{type:"none"};if(Q.length===0)throw TypeError(`${G} is not an object schema`);let X=new Set(Q.flatMap(({required:Z,optional:_})=>[...Z,..._])),Y=[...X].filter((Z)=>Q.every((_)=>_.required.includes(Z))).sort();return{additionalProperties:!1,optional:[...X].filter((Z)=>!Y.includes(Z)).sort(),required:Y,type:"object"}}if("type"in F&&F.type==="none")return{type:"none"};if(!("properties"in F))throw TypeError(`${G} is not an object schema`);return{additionalProperties:!1,optional:Object.keys(F.properties).filter((J)=>!F.required.includes(J)).sort(),required:[...F.required].sort(),type:"object"}}var y0=Object.freeze(Object.keys(F0).sort()),E2=Object.freeze(Object.fromEntries(y0.map((F)=>{let G=F0[F],J=h0(G.result.schema,`Plugin API ${F} result`);if(J.type!=="object")throw TypeError(`Plugin API ${F} result must be an object`);return[F,{dialect:G.dialect,params:h0(G.request.schema,`Plugin API ${F} params`),request:G.request,response:G.result,result:J}]})));function T2(F,G){return K0(F0[F].request.schema,G,`Plugin API ${F} params`)}function B2(F,G){return K0(F0[F].result.schema,G,`Plugin API ${F} result`)}var P=[{code:"stale-context",description:"The bound Project, Canvas, node, or connection changed before the call completed.",recoverable:!0}],C=[{code:"permission-denied",description:"The installed Plugin principal does not currently hold the required grant.",recoverable:!1}],H0=[{code:"resource-unavailable",description:"The authoritative Project resource is missing, changed, or cannot be read safely.",recoverable:!0}],l0=[{code:"partial-success",description:"A user-visible Project file was published, but the requested Canvas commit did not complete; retry is unsafe.",recoverable:!1}],w=(F)=>tF({...F,contractSince:"2.0.0"}),U0=iF(t0("1.0.0",[w({id:"host.context.get",completion:"cancelable",grant:null,scope:"connection",sideEffect:"read",errors:P,docs:{summary:"Read the bounded context attached to the current Plugin connection.",description:"Returns only renderer-safe identifiers and feature metadata for the exact live connection; it grants no additional authority.",request:"No parameters.",response:"The current Plugin, Project, Canvas, node, and negotiated Host API context when present."}}),w({id:"canvas.inputs.list",completion:"cancelable",grant:"canvas.connectedInputs.read",scope:"own-node",sideEffect:"read",errors:[...P,...C],docs:{summary:"List direct incoming inputs of the owning Plugin node.",description:"Derives pathless input metadata from authoritative direct incoming Canvas edges and never reads resource bytes.",request:"No parameters; the owning node comes from the bound connection.",response:"A bounded list of direct incoming input descriptors and opaque input keys."}}),w({id:"canvas.inputs.open",completion:"cancelable",grant:"canvas.connectedMedia.stream",scope:"own-node",sideEffect:"read",errors:[...P,...C,...H0],docs:{summary:"Open a bounded stream for one previously listed direct input.",description:"Opens host-owned access to the exact authoritative input after topology and resource identity are revalidated.",request:"`{ inputKey }`, using an opaque key returned by canvas.inputs.list.",response:"A connection-bound stream descriptor and safe media metadata.",remarks:"Call canvas.inputs.close when the stream is no longer needed."}}),w({id:"canvas.inputs.close",completion:"cancelable",grant:"canvas.connectedMedia.stream",scope:"own-node",sideEffect:"write",errors:[...P,...C],docs:{summary:"Close one connection-bound input stream.",description:"Releases a stream created by canvas.inputs.open without changing Canvas or Project state.",request:"The stream handle returned by canvas.inputs.open.",response:"An acknowledgement; closing an already closed handle is idempotent."}}),w({id:"canvas.node.get",completion:"cancelable",grant:"canvas.node.read",scope:"own-node",sideEffect:"read",errors:[...P,...C],docs:{summary:"Read the owning Plugin node projection.",description:"Returns a bounded renderer-safe projection of the exact node bound to the connection.",request:"No parameters; the owning node comes from the bound connection.",response:"The owning node identity, revision, geometry, and Plugin state projection."}}),w({id:"canvas.node.state.replace",completion:"commit-preserving",grant:"canvas.node.write",scope:"own-node",sideEffect:"write",errors:[...P,...C],docs:{summary:"Replace the owning node's bounded Plugin state.",description:"Commits only the namespaced Plugin state through the authoritative Canvas application service with revision checks.",request:"`{ state }`, where state is a bounded JSON value.",response:"`{ updated: true }` after the authoritative state replacement commits."}}),w({id:"canvas.resource.image.create",completion:"commit-preserving",grant:"canvas.image.write",scope:"own-node",sideEffect:"write",errors:[...P,...C,...l0],docs:{summary:"Create a Project-backed Canvas image through the host lifecycle.",description:"Admits bounded image content as a user-visible Project resource and commits its Canvas reference without exposing native paths.",request:"`{ dataUrl, name }`, containing a bounded validated image data URL and safe file name.",response:"The created renderer-safe image result after Project publication and Canvas commit."}}),w({id:"project.file.text.read",completion:"cancelable",grant:"project.files.read",scope:"project",sideEffect:"read",errors:[...P,...C],docs:{summary:"Read one bounded UTF-8 Project file.",description:"Reads through the scoped Project Files capability using a normalized Project-relative path and never exposes a native path.",request:"`{ path }`, using a normalized Project-relative portable path.",response:"The bounded UTF-8 file text."}}),w({id:"agent.prompt",completion:"commit-preserving",grant:"agent.prompt",scope:"connection",sideEffect:"execute",errors:[...P,...C],docs:{summary:"Submit a bounded prompt through the host Agent capability.",description:"Uses the current host-owned Agent context; it does not grant direct OpenCode, filesystem, model, or credential access.",request:"`{ text }`, containing the bounded prompt text.",response:"`{ text }`, containing the bounded host acknowledgement."}}),w({id:"generation.tools.list",completion:"cancelable",grant:"generation.execute",scope:"plugin",sideEffect:"read",errors:C,docs:{summary:"List generation tools available to the installed Plugin principal.",description:"Returns normalized tool metadata derived from active verified contributions without exposing executable paths or credentials.",request:"Optional `{ output }` modality filter; omitting params lists every admitted modality.",response:"A bounded list of available generation tools and their public input contracts."}}),w({id:"generation.execute",completion:"commit-preserving",grant:"generation.execute",scope:"plugin",sideEffect:"execute",errors:[...P,...C,...H0,...l0],docs:{summary:"Execute one selected generation tool through the shared host executor.",description:"Revalidates the active Plugin, authorized executable, inputs, cancellation, and live resource guards immediately before execution.",request:"`{ output?, prompt, references?: Array<{ inputKey, role }>, resultMode?, toolId? }`; every opaque input key must come from the current owning node's canvas.inputs.list result.",response:"The bounded selected tool result, created node ids, authoritative revision, and warnings."}}),w({id:"projects.list",completion:"cancelable",audience:["web-plugin","companion"],grant:"projects.read",scope:"plugin",sideEffect:"read",errors:C,docs:{summary:"List Projects visible to the installed Plugin principal.",description:"Returns portable Project identities and display metadata without native paths or private Project state.",request:"No parameters.",response:"A bounded list of renderer-safe Project summaries."}}),w({id:"canvas.catalog.list",completion:"cancelable",audience:["web-plugin","companion"],grant:"canvas.catalog.read",scope:"project",sideEffect:"read",errors:[...P,...C],docs:{summary:"List Canvas catalog entries for one authorized Project.",description:"Reads the Project-owned Canvas catalog without selecting a Project or Canvas in the Workbench.",request:"`{ projectId }`, naming one explicit portable Project.",response:"A bounded list of portable Canvas catalog entries."}}),w({id:"canvas.document.get",completion:"cancelable",audience:["web-plugin","companion"],grant:"canvas.document.read",scope:"canvas",sideEffect:"read",errors:[...P,...C],docs:{summary:"Read one authorized Canvas document projection.",description:"Returns a bounded portable structure or geometry projection from Main's authoritative Canvas application service.",request:"`{ ref, projection }`, using an explicit portable Project/Canvas reference and supported projection.",response:"The requested pathless document projection and authoritative revision."}}),w({id:"canvas.nodes.query",completion:"cancelable",audience:["web-plugin","companion"],grant:"canvas.document.read",scope:"canvas",sideEffect:"read",errors:[...P,...C],docs:{summary:"Query bounded node projections in one authorized Canvas.",description:"Executes a host-defined bounded query without exposing native paths or resource bytes.",request:"`{ ref, query }`, using an explicit portable Project/Canvas reference and bounded query.",response:"Matching node projections and the authoritative Canvas revision."}}),w({id:"canvas.transaction.execute",completion:"commit-preserving",audience:["web-plugin","companion"],grant:"canvas.document.write",scope:"canvas",sideEffect:"write",errors:[...P,...C],docs:{summary:"Commit one non-empty revision-bound Canvas transaction.",description:"Validates bounded commands against one authoritative revision and persists the accepted transaction atomically.",request:"`{ ref, expectedRevision, commands, transactionId }` with a bounded non-empty command list.",response:"The committed authoritative revision and bounded command results."}}),w({id:"canvas.events.subscribe",completion:"cancelable",audience:["web-plugin","companion"],grant:"canvas.events.subscribe",scope:"canvas",sideEffect:"subscribe",errors:[...P,...C],docs:{summary:"Subscribe to bounded events for one authorized Canvas.",description:"Creates a connection-scoped subscription; events are revisioned invalidations or safe projections, never native data.",request:"`{ ref }`, using an explicit portable Project/Canvas reference.",response:"A connection-bound subscription identifier."}}),w({id:"canvas.events.unsubscribe",completion:"cancelable",audience:["web-plugin","companion"],grant:"canvas.events.subscribe",scope:"canvas",sideEffect:"subscribe",errors:[...P,...C],docs:{summary:"Close one connection-bound Canvas event subscription.",description:"Releases a subscription created by canvas.events.subscribe without changing Canvas state.",request:"The subscription identifier returned by canvas.events.subscribe.",response:"An acknowledgement; closing an already closed subscription is idempotent."}})]),t0("2.0.0",[w({id:"canvas.inputs.image.open",completion:"cancelable",grant:"canvas.connectedImages.read",scope:"own-node",sideEffect:"read",errors:[...P,...C,...H0],docs:{summary:"Open one directly connected image through the owning Plugin node.",description:"Issues a revocable Host-owned session for signature-validated JPEG, PNG, or WebP content after validating the Plugin principal, owning node, direct edge, resource identity, and image limits. Every protocol read revalidates the issued principal and direct edge against current Host state.",request:"`{ inputKey }`, using an opaque image key returned by canvas.inputs.list.",response:"A connection-issued, revocable session with an opaque 128-bit bearer URL, bounded image probe, and lowercase SHA-256 content revision.",remarks:"Electron protocol GET/HEAD requests have no trusted sender or frame principal. Possession of the convax-connected-media URL therefore carries bearer authority until the Host revokes the session or its principal/edge revalidation fails; the URL must be kept secret and closed promptly. The response contains no image bytes, native path, or unrestricted URL. The Host rejects images above 16 MiB, dimensions above 8192 pixels, or more than 33,554,432 pixels."}}),w({id:"canvas.inputs.image.close",completion:"cancelable",grant:"canvas.connectedImages.read",scope:"own-node",sideEffect:"write",errors:[...P,...C],docs:{summary:"Close one revocable connected-image bearer session.",description:"Revokes a session and bearer URL created by canvas.inputs.image.open after validating the calling Plugin principal, without changing Canvas or Project state.",request:"`{ sessionId }`, using the opaque handle returned by canvas.inputs.image.open.",response:"An acknowledgement that the caller's image session is closed; repeated close calls are idempotent."}})])),e0=U0.apis.map(({id:F})=>F).sort();if(e0.length!==y0.length||e0.some((F,G)=>F!==y0[G]))throw TypeError("Plugin API Catalog and portable method contracts are incomplete or inconsistent");var H2=U0.version,M0=Number(H2.split(".")[0]),RF=new Map(U0.apis.map((F)=>[F.id,F])),w2=new Set(RF.keys());function N0(F){return typeof F==="string"&&w2.has(F)}function p0(F){return RF.get(F)}var C2=/^[a-z][a-z0-9]*(?:\.[a-z][a-z0-9]*)+$/;function P2(F){return typeof F==="object"&&F!==null&&!Array.isArray(F)}function FF(F,G){if(!Array.isArray(F))throw TypeError(`${G} must be an array`);let J=[],Q=new Set;for(let X of F){if(typeof X!=="string"||!C2.test(X))throw TypeError(`${G} contains an invalid Plugin API id: ${String(X)}`);if(Q.has(X))throw TypeError(`${G} contains a duplicate Plugin API id: ${X}`);Q.add(X),J.push(X)}return J}function q2(F){let G=s0(F),J=[],Q=[];for(let X of G.required){if(!N0(X))throw TypeError(`Plugin API declaration contains an unknown Plugin API id: ${X}`);J.push(X)}for(let X of G.optional){if(!N0(X))throw TypeError(`Plugin API declaration contains an unknown Plugin API id: ${X}`);Q.push(X)}return Object.freeze({major:M0,required:Object.freeze(J),optional:Object.freeze(Q)})}function s0(F){if(!P2(F))throw TypeError("Plugin API declaration must be an object");if(Object.keys(F).some((Z)=>Z!=="major"&&Z!=="required"&&Z!=="optional"))throw TypeError("Plugin API declaration contains an unknown field");if(F.major!==M0)throw TypeError(`Plugin API declaration major must be ${M0}`);let J=FF(F.required,"Plugin API declaration required"),Q=FF(F.optional,"Plugin API declaration optional"),X=new Set(J),Y=Q.find((Z)=>X.has(Z));if(Y)throw TypeError(`Plugin API cannot be both required and optional: ${Y}`);return Object.freeze({major:M0,required:Object.freeze(J),optional:Object.freeze(Q)})}function k2(F,G){if(F.required.includes(G))return"required";if(F.optional.includes(G))return"optional";return}function GF(F,G){return k2(F,G)!==void 0}class EF extends Error{availability;constructor(F){super(`Plugin API ${F.id} is unavailable: ${F.reason}`);this.name="PluginApiUnavailableError",this.availability=F}}function I2(F,G){return typeof G==="string"&&p0(F).errors.some((J)=>J.code===G)}function g2(F,G){if(!G||typeof G!=="object"||Array.isArray(G))throw TypeError(`Plugin API ${F} failure must be an object`);let J=G;if(Object.keys(J).some((X)=>!["code","kind","message","recoverable"].includes(X))||!Object.prototype.hasOwnProperty.call(J,"code")||!Object.prototype.hasOwnProperty.call(J,"message")||!Object.prototype.hasOwnProperty.call(J,"recoverable")||J.kind!=="api"||!I2(F,J.code)||typeof J.message!=="string"||J.message.length<1||J.message.length>4096||typeof J.recoverable!=="boolean")throw TypeError(`Plugin API ${F} failure is invalid`);let Q=p0(F).errors.find(({code:X})=>X===J.code);if(J.recoverable!==Q.recoverable)throw TypeError(`Plugin API ${F} failure recoverability does not match the Catalog`);return Object.freeze({code:J.code,kind:"api",message:J.message,recoverable:J.recoverable})}var x2=/^[a-z][a-z0-9]*(?:\.[a-z][a-z0-9-]*)+$/,f2=/^[a-z][a-z0-9]*(?:[._-][a-z0-9]+)*$/,h2=/^[A-Za-z][A-Za-z0-9_-]{0,63}$/,y2=/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/,c2=new Set(["none","read","write","execute","subscribe"]),TF=128,b2=64,v2=8,m2=16384,d2=256;function o0(F){return typeof F==="string"&&F.length<=160&&x2.test(F)}function n(F,G){if(!F||typeof F!=="object"||Array.isArray(F))throw TypeError(`${G} must be an object`);let J=Object.getPrototypeOf(F);if(J!==Object.prototype&&J!==null)throw TypeError(`${G} must be a plain object`);return F}function v(F,G,J,Q){let X=new Set([...G,...J]);if(G.some((Y)=>!Object.prototype.hasOwnProperty.call(F,Y))||Object.keys(F).some((Y)=>!X.has(Y)))throw TypeError(`${Q} contains unsupported or missing fields`)}function a(F,G,J=2000){if(typeof F!=="string"||F.length<1||F.length>J||F!==F.trim()||/[\u0000-\u001f\u007f]/u.test(F))throw TypeError(`${G} must be a bounded, trimmed string`);return F}function j0(F,G,J){if(!Number.isSafeInteger(F)||Number(F)<0||Number(F)>J)throw TypeError(`${G} must be a bounded non-negative integer`);return Number(F)}function c0(F,G){if(typeof F!=="string"||!y2.test(F))throw TypeError(`${G} must be a strict semantic version`);return F}function p2(F,G){let J=F.split(".").map(Number),Q=G.split(".").map(Number);for(let X=0;X<3;X+=1){let Y=J[X]-Q[X];if(Y!==0)return Y}return 0}function b0(F,G,J){if(J>v2)throw TypeError(`${G} exceeds the schema depth limit`);let Q=n(F,G);if(Q.type==="null"||Q.type==="boolean")return v(Q,["type"],[],G),Object.freeze({type:Q.type});if(Q.type==="number"||Q.type==="integer"){v(Q,["type"],["minimum","maximum"],G);let{minimum:X,maximum:Y}=Q;if(X!==void 0&&(typeof X!=="number"||!Number.isFinite(X)))throw TypeError(`${G}.minimum must be finite`);if(Y!==void 0&&(typeof Y!=="number"||!Number.isFinite(Y)))throw TypeError(`${G}.maximum must be finite`);if(X!==void 0&&Y!==void 0&&X>Y)throw TypeError(`${G} minimum exceeds maximum`);return Object.freeze({type:Q.type,...X===void 0?{}:{minimum:X},...Y===void 0?{}:{maximum:Y}})}if(Q.type==="string"){if(!Object.prototype.hasOwnProperty.call(Q,"maxLength"))throw TypeError(`${G}.maxLength is required to keep values bounded`);v(Q,["type","maxLength"],["minLength","enum"],G);let X=j0(Q.maxLength,`${G}.maxLength`,m2),Y=Q.minLength===void 0?void 0:j0(Q.minLength,`${G}.minLength`,X),Z;if(Q.enum!==void 0){if(!Array.isArray(Q.enum)||Q.enum.length<1||Q.enum.length>128||Q.enum.some((_)=>typeof _!=="string"||_.length>X)||new Set(Q.enum).size!==Q.enum.length)throw TypeError(`${G}.enum must contain unique bounded strings`);Z=Object.freeze([...Q.enum])}return Object.freeze({type:"string",maxLength:X,...Y===void 0?{}:{minLength:Y},...Z===void 0?{}:{enum:Z}})}if(Q.type==="array"){v(Q,["type","items","maxItems"],["minItems"],G);let X=j0(Q.maxItems,`${G}.maxItems`,d2),Y=Q.minItems===void 0?void 0:j0(Q.minItems,`${G}.minItems`,X);return Object.freeze({type:"array",items:b0(Q.items,`${G}.items`,J+1),maxItems:X,...Y===void 0?{}:{minItems:Y}})}if(Q.type==="object"){if(v(Q,["type","properties","required","additionalProperties"],[],G),Q.additionalProperties!==!1)throw TypeError(`${G}.additionalProperties must be false`);let X=n(Q.properties,`${G}.properties`),Y=Object.keys(X);if(Y.length>b2)throw TypeError(`${G} has too many properties`);if(Y.some((_)=>!h2.test(_)))throw TypeError(`${G} contains an invalid property name`);if(!Array.isArray(Q.required)||Q.required.some((_)=>typeof _!=="string"||!Y.includes(_))||new Set(Q.required).size!==Q.required.length)throw TypeError(`${G}.required must contain unique declared properties`);let Z=Object.fromEntries(Y.sort().map((_)=>[_,b0(X[_],`${G}.properties.${_}`,J+1)]));return Object.freeze({type:"object",properties:Object.freeze(Z),required:Object.freeze([...Q.required].sort()),additionalProperties:!1})}throw TypeError(`${G}.type is unsupported`)}function O0(F,G){let J=b0(F,G,0);if(J.type!=="object")throw TypeError(`${G} must be a closed object schema`);return J}function s2(F,G){let J=n(F,G);v(J,["id","inputSchema","outputSchema","version"],[],G);let Q=a(J.id,`${G}.id`,160);if(!o0(Q))throw TypeError(`${G}.id is invalid`);let X=n(J.version,`${G}.version`);v(X,["minimum","maximumExclusive"],[],`${G}.version`);let Y=c0(X.minimum,`${G}.version.minimum`),Z=c0(X.maximumExclusive,`${G}.version.maximumExclusive`);if(p2(Y,Z)>=0)throw TypeError(`${G}.version must be a non-empty half-open interval`);return Object.freeze({id:Q,inputSchema:O0(J.inputSchema,`${G}.inputSchema`),outputSchema:O0(J.outputSchema,`${G}.outputSchema`),version:Object.freeze({minimum:Y,maximumExclusive:Z})})}function JF(F,G){if(!Array.isArray(F)||F.length>TF)throw TypeError(`${G} must be a bounded array`);let J=F.map((Q,X)=>s2(Q,`${G}[${X}]`)).sort((Q,X)=>Q.id.localeCompare(X.id));if(J.some((Q,X)=>X>0&&J[X-1].id===Q.id))throw TypeError(`${G} contains a duplicate capability id`);return Object.freeze(J)}function o2(F,G){let J=n(F,G);v(J,["id","version","operation","sideEffect","inputSchema","outputSchema","docs"],[],G);let Q=a(J.id,`${G}.id`,160);if(!o0(Q))throw TypeError(`${G}.id is invalid`);let X=a(J.operation,`${G}.operation`,128);if(!f2.test(X))throw TypeError(`${G}.operation is invalid`);if(!c2.has(J.sideEffect))throw TypeError(`${G}.sideEffect is invalid`);let Y=n(J.docs,`${G}.docs`);v(Y,["summary","request","response"],["remarks"],`${G}.docs`);let Z=Object.freeze({summary:a(Y.summary,`${G}.docs.summary`),request:a(Y.request,`${G}.docs.request`),response:a(Y.response,`${G}.docs.response`),...Y.remarks===void 0?{}:{remarks:a(Y.remarks,`${G}.docs.remarks`)}});return Object.freeze({id:Q,version:c0(J.version,`${G}.version`),operation:X,sideEffect:J.sideEffect,inputSchema:O0(J.inputSchema,`${G}.inputSchema`),outputSchema:O0(J.outputSchema,`${G}.outputSchema`),docs:Z})}function r2(F){let G=n(F,"Plugin capability declaration");if(v(G,["exports","imports"],[],"Plugin capability declaration"),!Array.isArray(G.exports)||G.exports.length>TF)throw TypeError("Plugin capability exports must be a bounded array");let J=G.exports.map((M,K)=>o2(M,`Plugin capability exports[${K}]`)).sort((M,K)=>M.id.localeCompare(K.id));if(J.some((M,K)=>K>0&&J[K-1].id===M.id))throw TypeError("Plugin capability exports contain a duplicate capability id");if(new Set(J.map((M)=>M.operation)).size!==J.length)throw TypeError("Plugin capability exports contain a duplicate provider operation");let Q=n(G.imports,"Plugin capability imports");v(Q,["required","optional"],[],"Plugin capability imports");let X=JF(Q.required,"Plugin required capability imports"),Y=JF(Q.optional,"Plugin optional capability imports"),Z=new Set(X.map(({id:M})=>M)),_=Y.find(({id:M})=>Z.has(M));if(_)throw TypeError(`Plugin capability import cannot be both required and optional: ${_.id}`);return Object.freeze({exports:Object.freeze(J),imports:Object.freeze({required:X,optional:Y})})}function v0(F,G,J,Q){if(F.type==="null"){if(G!==null)throw TypeError(`${J} must be null`);return}if(F.type==="boolean"){if(typeof G!=="boolean")throw TypeError(`${J} must be boolean`);return}if(F.type==="number"||F.type==="integer"){if(typeof G!=="number"||!Number.isFinite(G)||F.type==="integer"&&!Number.isSafeInteger(G))throw TypeError(`${J} must be a finite ${F.type==="integer"?"safe integer":"number"}`);if(F.minimum!==void 0&&GF.maximum)throw TypeError(`${J} exceeds maximum`);return}if(F.type==="string"){if(typeof G!=="string"||G.length<(F.minLength??0)||G.length>F.maxLength||F.enum!==void 0&&!F.enum.includes(G))throw TypeError(`${J} is not an admitted string`);return}if(!G||typeof G!=="object")throw TypeError(`${J} must be ${F.type}`);if(Q.has(G))throw TypeError(`${J} cannot be cyclic`);Q.add(G);try{if(F.type==="array"){if(!Array.isArray(G)||G.length<(F.minItems??0)||G.length>F.maxItems)throw TypeError(`${J} is not an admitted array`);G.forEach((Z,_)=>v0(F.items,Z,`${J}[${_}]`,Q));return}if(Array.isArray(G))throw TypeError(`${J} must be an object`);let X=Object.getPrototypeOf(G);if(X!==Object.prototype&&X!==null)throw TypeError(`${J} must be a plain object`);let Y=G;for(let Z of F.required)if(!Object.prototype.hasOwnProperty.call(Y,Z))throw TypeError(`${J}.${Z} is required`);for(let[Z,_]of Object.entries(Y)){let M=F.properties[Z];if(!M)throw TypeError(`${J} contains unsupported property: ${Z}`);v0(M,_,`${J}.${Z}`,Q)}}finally{Q.delete(G)}}function QF(F,G,J="Plugin capability value"){v0(F,G,J,new Set)}var u2=/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[A-Za-z-][0-9A-Za-z-]*)(?:\.(?:0|[1-9]\d*|\d*[A-Za-z-][0-9A-Za-z-]*))*))?(?:\+([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?$/,n2=/^(CON|PRN|AUX|NUL|COM[1-9¹²³]|LPT[1-9¹²³]|CONIN\$|CONOUT\$)$/i;function A(F,G){if(!F||typeof F!=="object"||Array.isArray(F))throw TypeError(`${G} must be an object`);let J=Object.getPrototypeOf(F);if(J!==Object.prototype&&J!==null)throw TypeError(`${G} must be a plain object`);return F}function R(F,G,J){let Q=new Set(G),X=Object.keys(F).find((Y)=>!Q.has(Y));if(X)throw TypeError(`${J} contains an unsupported field: ${X}`)}function T(F,G,J){if(typeof F!=="string"||F.length<1||F.length>J||F!==F.trim()||/[\u0000-\u001f\u007f]/u.test(F))throw TypeError(`${G} must be a bounded, trimmed string`);return F}function c(F,G,J,Q=!1){if(!Array.isArray(F)||F.length>J||Q&&F.length===0)throw TypeError(`${G} must be ${Q?"a non-empty ":"a "}bounded array with at most ${J} items`);return F}function BF(F){if(F&&typeof F==="object"&&!Object.isFrozen(F)){for(let G of Object.values(F))BF(G);Object.freeze(F)}return F}function t2(F){let G=T(F,"Plugin version",128);if(!u2.test(G))throw TypeError("Plugin version must be valid SemVer");return G}function E0(F){let G=F.split(".")[0]??"";if(!F||F.length>255||F==="."||F===".."||/[\\/:*?"<>|\u0000-\u001f\u007f]/u.test(F)||/[. ]$/u.test(F)||n2.test(G))throw TypeError(`Plugin path contains an invalid Windows filename: ${F}`);return F}function HF(F){let G=T(F,"Plugin id",80);if(!/^[a-z0-9]+(?:-[a-z0-9]+)*$/u.test(G))throw TypeError("Plugin id must use kebab-case");return E0(G),G}function X0(F,G="Plugin path"){let J=T(F,G,1024);if(J.includes("\\")||J.startsWith("/")||/^[A-Za-z]:/u.test(J)||J.startsWith("//"))throw TypeError(`${G} must be a portable relative path`);let Q=J.split("/");if(Q.some((X)=>!X||X==="."||X===".."))throw TypeError(`${G} must be a portable relative path`);return Q.forEach(E0),J}function w0(F,G,J){if(F===void 0)return;let Q=c(F,G,64).map((X)=>J(T(X,G,128)));if(new Set(Q).size!==Q.length)throw TypeError(`${G} contains duplicate values`);return Q}function Y0(F,G,J=80){let Q=T(F,G,J);if(!/^[a-z0-9]+(?:[._-][a-z0-9]+)*$/u.test(Q))throw TypeError(`${G} is invalid: ${Q}`);return Q}var u="convax.plugin-host/8",i2=V2,a2=L2,C0=1048576,XF=4194304,l2=128,YF=16,e2=128,F8=64,V0=Math.ceil(i2/2),G8=/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/,J8=new Set(["not-declared","provider-missing","provider-incompatible","provider-ambiguous","self-provider","dependency-cycle","setup-required","disabled","recovering","contract-mismatch"]),wF=Object.freeze({canceled:{recoverable:!0},"contract-mismatch":{recoverable:!1},"depth-exceeded":{recoverable:!1},"duplicate-request":{recoverable:!1},"execution-failed":{recoverable:!1},"invalid-input":{recoverable:!1},"invalid-output":{recoverable:!1},overloaded:{recoverable:!0},"provider-unavailable":{recoverable:!0},"reentrant-call":{recoverable:!1}}),CF=new Set(Object.keys(wF)),PF=Object.freeze({canceled:{recoverable:!0},"internal-error":{recoverable:!1},"invalid-request":{recoverable:!1},overloaded:{recoverable:!0},"transport-closed":{recoverable:!0}}),qF=new Set(Object.keys(PF)),Q8=new Set(U0.apis.flatMap((F)=>F.errors.map(({code:G})=>G)));function e(F){if(!F||typeof F!=="object"||Array.isArray(F))return;let G=Object.getPrototypeOf(F);return G===Object.prototype||G===null?F:void 0}function ZF(F){let G=2;for(let J=0;J=55296&&Q<=57343){let X=F.charCodeAt(J+1);if(Q>=55296&&Q<=56319&&X>=56320&&X<=57343)G+=4,J+=1;else G+=6}else if(Q<128)G+=1;else if(Q<2048)G+=2;else G+=3}return G}function P0(F,G,J="Plugin Host message"){if(!Number.isSafeInteger(G)||G<1)throw TypeError(`${J} byte limit is invalid`);let Q=[{depth:0,value:F}],X=new WeakSet,Y=0,Z=0,_=(M)=>{if(Y+=M,Y>G)throw RangeError(`${J} exceeds ${G} bytes`)};while(Q.length>0){let M=Q.pop(),K=M.value;if(K===null){_(4);continue}if(typeof K==="string"){_(ZF(K));continue}if(typeof K==="boolean"){_(K?4:5);continue}if(typeof K==="number"){if(!Number.isFinite(K))throw TypeError(`${J} must contain finite JSON numbers`);_(Object.is(K,-0)?1:String(K).length);continue}if(!K||typeof K!=="object")throw TypeError(`${J} must be a JSON value`);if(M.depth>F8||X.has(K))throw TypeError(`${J} must be a bounded acyclic JSON tree`);if(X.add(K),Array.isArray(K)){if(Z+=K.length,Z>V0)throw RangeError(`${J} exceeds ${V0} JSON entries`);if(_(2+Math.max(0,K.length-1)),Object.getOwnPropertySymbols(K).length>0)throw TypeError(`${J} arrays must not contain symbol properties`);let O=0;for(let L in K){if(!Object.prototype.hasOwnProperty.call(K,L))continue;if(!/^(0|[1-9]\d*)$/u.test(L)||Number(L)>=K.length)throw TypeError(`${J} arrays must contain only indexed entries`);let k=Object.getOwnPropertyDescriptor(K,L);if(!k?.enumerable||!("value"in k))throw TypeError(`${J} arrays must contain enumerable data properties`);O+=1,Q.push({depth:M.depth+1,value:k.value})}if(O!==K.length)throw TypeError(`${J} arrays must be dense JSON arrays`);continue}let D=Object.getPrototypeOf(K);if(D!==Object.prototype&&D!==null)throw TypeError(`${J} must contain plain JSON objects`);if(Object.getOwnPropertySymbols(K).length>0)throw TypeError(`${J} must not contain symbol properties`);_(2);let j=0;for(let O in K){if(!Object.prototype.hasOwnProperty.call(K,O))continue;let L=Object.getOwnPropertyDescriptor(K,O);if(!L?.enumerable||!("value"in L))throw TypeError(`${J} objects must contain enumerable data properties`);if(j+=1,Z+=1,Z>V0)throw RangeError(`${J} exceeds ${V0} JSON entries`);_((j===1?0:1)+ZF(O)+1),Q.push({depth:M.depth+1,value:L.value})}}return Y}function r(F,G,J=[]){let Q=new Set([...G,...J]);return G.every((X)=>Object.prototype.hasOwnProperty.call(F,X))&&Object.keys(F).every((X)=>Q.has(X))}function kF(F){return typeof F==="string"&&F.length>0&&F.length<=e2&&F===F.trim()&&!/[\u0000-\u001f\u007f]/u.test(F)}function X8(F){return typeof F==="string"&&F.length>0&&F.length<=128&&F===F.trim()&&!/[\u0000-\u001f\u007f]/u.test(F)}function IF(F){let G=e(F);if(!G||!r(G,["pluginId","protocol","type"])||G.protocol!==u||G.type!=="connect")return!1;try{return HF(G.pluginId),!0}catch{return!1}}function Y8(F){let G=e(F);if(!G||G.protocol!==u||G.type!=="response"||!kF(G.id))return!1;if(G.ok===!0)return r(G,["id","ok","protocol","result","type"]);if(G.ok!==!1||!r(G,["error","id","ok","protocol","type"]))return!1;let J=e(G.error);return Boolean(J&&r(J,["code","kind","message","recoverable"])&&typeof J.code==="string"&&(J.kind==="api"&&Q8.has(J.code)||J.kind==="capability"&&CF.has(J.code)||J.kind==="protocol"&&qF.has(J.code))&&typeof J.message==="string"&&J.message.length>0&&J.message.length<=4096&&typeof J.recoverable==="boolean")}function Z8(F){let G=e(F);return Boolean(G&&r(G,["command","protocol","type"],["params"])&&G.protocol===u&&G.type==="command"&&X8(G.command))}function _8(F){let G=e(F);if(!G||typeof G.available!=="boolean")throw TypeError("Plugin capability availability must be a closed object");let J=G.requirement;if(J!=="required"&&J!=="optional")throw TypeError("Plugin capability availability requirement is invalid");if(!o0(G.capabilityId))throw TypeError("Plugin capability availability id is invalid");if(G.available){if(!r(G,["available","capabilityId","requirement","version"])||typeof G.version!=="string"||!G8.test(G.version))throw TypeError("Available Plugin capability result is invalid");return Object.freeze({available:!0,capabilityId:G.capabilityId,requirement:J,version:G.version})}if(!r(G,["available","capabilityId","reason","recoverable","requirement"])||typeof G.reason!=="string"||!J8.has(G.reason)||typeof G.recoverable!=="boolean")throw TypeError("Unavailable Plugin capability result is invalid");return Object.freeze({available:!1,capabilityId:G.capabilityId,reason:G.reason,recoverable:G.recoverable,requirement:J})}function $8(F){let G=e(F);if(!G||!r(G,["code","kind","message","recoverable"])||G.kind!=="capability"||typeof G.code!=="string"||!CF.has(G.code)||typeof G.message!=="string"||G.message.length<1||G.message.length>4096||typeof G.recoverable!=="boolean")throw TypeError("Plugin capability failure is invalid");let J=G.code;if(G.recoverable!==wF[J].recoverable)throw TypeError("Plugin capability failure recoverability is invalid");return Object.freeze({code:J,kind:"capability",message:G.message,recoverable:G.recoverable})}function gF(F){let G=e(F);if(!G||!r(G,["code","kind","message","recoverable"])||G.kind!=="protocol"||typeof G.code!=="string"||!qF.has(G.code)||typeof G.message!=="string"||G.message.length<1||G.message.length>4096||typeof G.recoverable!=="boolean")throw TypeError("Plugin Host protocol failure is invalid");let J=G.code;if(G.recoverable!==PF[J].recoverable)throw TypeError("Plugin Host protocol failure recoverability is invalid");return Object.freeze({code:J,kind:"protocol",message:G.message,recoverable:G.recoverable})}var K8=["download","edit","open","play","refresh","settings","sparkles","upload"],xF=/^[a-z][a-z0-9]*(?:[._-][a-z0-9]+)*$/,M8=/^[a-z][a-z0-9]*(?:[._-][a-z0-9]+)*$/,S8=/^[a-z][a-z0-9]*(?:[._-][a-z0-9]+)*$/,D8=128,_F=128,$F=1e4;function U8(F){return Boolean(F)&&typeof F==="object"&&!Array.isArray(F)}function S0(F,G){if(!U8(F))throw TypeError(`${G} must be an object`);let J=Object.getPrototypeOf(F);if(J!==Object.prototype&&J!==null)throw TypeError(`${G} must be a plain object`);return F}function D0(F,G,J,Q){let X=new Set([...G,...J]);if(G.some((Y)=>!Object.prototype.hasOwnProperty.call(F,Y))||Object.keys(F).some((Y)=>!X.has(Y)))throw TypeError(`${Q} contains unsupported or missing fields`)}function z0(F,G,J){if(typeof F!=="string"||F.length<1||F.length>J||F!==F.trim()||/[\u0000-\u001f\u007f]/u.test(F))throw TypeError(`${G} must be a bounded, trimmed string`);return F}function A0(F,G,J,Q){let X=z0(F,G,Q);if(!J.test(X))throw TypeError(`${G} must be a stable Plugin-local id`);return X}function W8(F,G){if(!Number.isSafeInteger(F)||Number(F)<-$F||Number(F)>$F)throw TypeError(`${G} must be a bounded safe integer`);return Number(F)}function j8(F,G){let J=S0(F,G);return D0(J,["default"],["zh-CN"],G),Object.freeze({default:z0(J.default,`${G}.default`,120),...J["zh-CN"]===void 0?{}:{"zh-CN":z0(J["zh-CN"],`${G}.zh-CN`,120)}})}function V8(F){return K8.some((G)=>G===F)}function L8(F,G){let J=`Plugin UI commands[${G}]`,Q=S0(F,J);D0(Q,["id","title","target"],["icon"],J);let X=S0(Q.target,`${J}.target`);if(X.type!=="renderer-message")throw TypeError(`${J}.target.type must be renderer-message`);D0(X,["type","message"],[],`${J}.target`);let Y=Q.icon;if(Y!==void 0&&!V8(Y))throw TypeError(`${J}.icon must be a supported Host icon token`);return Object.freeze({id:A0(Q.id,`${J}.id`,xF,128),title:j8(Q.title,`${J}.title`),target:Object.freeze({type:"renderer-message",message:z0(X.message,`${J}.target.message`,128)}),...Y===void 0?{}:{icon:Y}})}function fF(F,G,J,Q){let X=S0(F,G);return D0(X,J,Q,G),{input:X,id:A0(X.id,`${G}.id`,M8,128),command:A0(X.command,`${G}.command`,xF,128),...X.order===void 0?{}:{order:W8(X.order,`${G}.order`)}}}function N8(F,G){let{input:J,...Q}=fF(F,`Plugin UI toolbar[${G}]`,["id","command"],["order"]);return Object.freeze(Q)}function O8(F,G){let J=`Plugin UI menus[${G}]`,Q=fF(F,J,["id","command","placement"],["group","order"]);if(Q.input.placement!=="overflow")throw TypeError(`${J}.placement must be overflow`);let X=Q.input.group===void 0?void 0:A0(Q.input.group,`${J}.group`,S8,64),{input:Y,...Z}=Q;return Object.freeze({...Z,placement:"overflow",...X===void 0?{}:{group:X}})}function q0(F,G,J){if(!Array.isArray(F)||F.length>J)throw TypeError(`${G} must be a bounded array`);return F}function k0(F,G){let J=new Set;for(let Q of F){if(J.has(Q.id))throw TypeError(`${G} contains a duplicate id: ${Q.id}`);J.add(Q.id)}}function KF(F,G){let J=new Set;for(let Q of F){if(J.has(Q.command))throw TypeError(`${G} contains a duplicate command reference: ${Q.command}`);J.add(Q.command)}}function z8(F){let G=S0(F,"Plugin Canvas UI contribution");D0(G,[],["commands","menus","toolbar"],"Plugin Canvas UI contribution");let J=Object.freeze(q0(G.commands===void 0?[]:G.commands,"Plugin UI commands",D8).map(L8)),Q=Object.freeze(q0(G.menus===void 0?[]:G.menus,"Plugin UI menus",_F).map(O8)),X=Object.freeze(q0(G.toolbar===void 0?[]:G.toolbar,"Plugin UI toolbar",_F).map(N8));k0(J,"Plugin UI commands"),k0(Q,"Plugin UI menus"),k0(X,"Plugin UI toolbar");let Y=new Set(Q.map((j)=>j.id)),Z=X.find((j)=>Y.has(j.id));if(Z)throw TypeError(`Plugin UI placements contain a duplicate id: ${Z.id}`);KF(Q,"Plugin UI menus"),KF(X,"Plugin UI toolbar");let _=new Set(J.map((j)=>j.id)),M=[...Q,...X].find((j)=>!_.has(j.command));if(M)throw TypeError(`Plugin UI placement references an unknown command: ${M.command}`);let K=new Set([...Q,...X].map((j)=>j.command)),D=J.find((j)=>!K.has(j.id));if(D)throw TypeError(`Plugin UI command has no owning-node placement: ${D.id}`);return Object.freeze({commands:J,menus:Q,toolbar:X})}var A8=["time-point","time-range","crop-region","confirmation","immediate"];function R8(F){return A8.some((G)=>G===F)}function E8(F,G){if(F==="image"||F==="video")return F;throw TypeError(`${G} target must be image or video`)}function MF(F,G){if(!Number.isSafeInteger(F)||Number(F)<1||Number(F)>8192)throw TypeError(`${G} must be an integer between 1 and 8192`);return Number(F)}function T8(F){let G=A(F,"Canvas renderer contribution");if(R(G,["create","extensions","height","mimeTypes","nodeKinds","width"],"Canvas renderer contribution"),G.create!==void 0&&typeof G.create!=="boolean")throw TypeError("Canvas renderer create must be a boolean");let J=w0(G.extensions,"Canvas renderer extensions",(Y)=>{let Z=Y.toLowerCase();if(!/^\.[a-z0-9][a-z0-9._+-]{0,31}$/u.test(Z))throw TypeError(`Invalid Canvas renderer extension: ${Y}`);return Z}),Q=w0(G.mimeTypes,"Canvas renderer MIME types",(Y)=>{let Z=Y.toLowerCase();if(!/^[a-z0-9][a-z0-9!#$&^_.+-]*\/[a-z0-9][a-z0-9!#$&^_.+-]*$/u.test(Z))throw TypeError(`Invalid Canvas renderer MIME type: ${Y}`);return Z}),X=w0(G.nodeKinds,"Canvas renderer node kinds",(Y)=>{if(!/^[a-z][a-z0-9]*(?:[._-][a-z0-9]+)*$/u.test(Y))throw TypeError(`Invalid Canvas renderer node kind: ${Y}`);return Y});if(G.create!==!0&&!J?.length&&!Q?.length&&!X?.length)throw TypeError("Canvas renderer must be creatable or match an extension, MIME type, or node kind");return{...G.create===void 0?{}:{create:G.create},...J===void 0?{}:{extensions:J},...G.height===void 0?{}:{height:MF(G.height,"Canvas renderer height")},...Q===void 0?{}:{mimeTypes:Q},...X===void 0?{}:{nodeKinds:X},...G.width===void 0?{}:{width:MF(G.width,"Canvas renderer width")}}}function L0(F,G,J){let Q=A(F,G);return R(Q,["default","zh-CN"],G),{default:T(Q.default,`${G} default`,J),...Q["zh-CN"]===void 0?{}:{"zh-CN":T(Q["zh-CN"],`${G} zh-CN`,J)}}}function B8(F){let G=c(F,"Canvas selection actions",32,!0).map((J,Q)=>{let X=`Canvas selection action ${Q}`,Y=A(J,X);if(Y.action!==void 0){R(Y,["action","description","id","target","title"],X);let D=Y0(Y.id,`${X} id`);if(Y.target!=="video")throw TypeError(`${X} target must be video`);let j=A(Y.action,`${X} action`);if(R(j,["connect","type"],`${X} action`),j.type!=="materialize-own-plugin-node"||j.connect!=="selection-to-created")throw TypeError(`${X} materialization action is not supported`);return{action:{connect:"selection-to-created",type:"materialize-own-plugin-node"},description:L0(Y.description,`${X} description`,2000),id:D,target:"video",title:L0(Y.title,`${X} title`,120)}}R(Y,["description","editor","id","presentation","steps","target","title"],X);let Z=Y0(Y.id,`${X} id`),_=E8(Y.target,X);if(!R8(Y.editor))throw TypeError(`${X} editor is not supported`);let M=Y.editor;if(M==="immediate"!==(_==="image"&&Y.presentation==="cutout-scan")||Y.presentation!==void 0&&Y.presentation!=="cutout-scan")throw TypeError(`${X} immediate editor requires image target and cutout-scan presentation`);let K=c(Y.steps,`${X} steps`,16,!0).map((D,j)=>{let O=`${X} step ${j}`,L=A(D,O);return R(L,["tool"],O),{tool:Y0(L.tool,`${O} tool`)}});if(M!=="confirmation"&&K.length!==1)throw TypeError(`${X} editor requires exactly one step`);return{description:L0(Y.description,`${X} description`,2000),editor:M,id:Z,...Y.presentation===void 0?{}:{presentation:"cutout-scan"},steps:K,target:_,title:L0(Y.title,`${X} title`,120)}});if(new Set(G.map((J)=>J.id)).size!==G.length)throw TypeError("Canvas selection actions contain duplicate ids");return G}function H8(F){let G=A(F,"Canvas contributions");R(G,["commands","menus","renderer","selectionActions","toolbar"],"Canvas contributions");let J=z8({...G.commands===void 0?{}:{commands:G.commands},...G.menus===void 0?{}:{menus:G.menus},...G.toolbar===void 0?{}:{toolbar:G.toolbar}});return{...G.commands===void 0?{}:{commands:J.commands},...G.menus===void 0?{}:{menus:J.menus},...G.renderer===void 0?{}:{renderer:T8(G.renderer)},...G.selectionActions===void 0?{}:{selectionActions:B8(G.selectionActions)},...G.toolbar===void 0?{}:{toolbar:J.toolbar}}}var w8=["text","image","video","audio"],hF=["reference_image","reference_video","first_frame","last_frame","audio","text"],C8=new Set(w8),P8=new Set(hF),q8=/^[a-z][a-z0-9_]{0,63}$/;function k8(F,G){let Q=c(F,G,hF.length).map((X)=>{if(typeof X!=="string"||!P8.has(X))throw TypeError(`${G} contain an unsupported or duplicate role`);return X});if(new Set(Q).size!==Q.length)throw TypeError(`${G} contain an unsupported or duplicate role`);return Q}function I8(F){let G=A(F,"Generation contribution");if(R(G,["models","tools"],"Generation contribution"),!Object.prototype.hasOwnProperty.call(G,"models"))throw TypeError("convax.plugin/8 generation models must be declared explicitly");let J=c(G.tools,"Generation tools",64,!0).map((_,M)=>{let K=`Generation tool ${M}`,D=A(_,K);R(D,["acceptedInputs","delivery","description","id","inputBinding","output","recovery","title"],K);let j=Y0(D.id,`${K} id`);if(typeof D.output!=="string"||!C8.has(D.output))throw TypeError(`${K} output is not supported`);if(D.delivery!==void 0&&D.delivery!=="canvas"&&D.delivery!=="return")throw TypeError(`${K} delivery is not supported`);if(D.delivery==="return"&&D.output!=="text")throw TypeError(`${K} return delivery requires text output`);let O=k8(D.acceptedInputs,`${K} acceptedInputs`);if(D.inputBinding!==void 0&&D.inputBinding!=="direct-incoming")throw TypeError(`${K} input binding is not supported`);if(D.inputBinding==="direct-incoming"&&O.length===0)throw TypeError(`${K} direct-incoming input binding requires accepted inputs`);let L;if(D.recovery!==void 0){let k=A(D.recovery,`${K} recovery`);if(R(k,["mode","schema"],`${K} recovery`),k.schema!=="convax.generation-lro/1"||k.mode!=="long-running-operation")throw TypeError(`${K} recovery contract is not supported`);L={mode:"long-running-operation",schema:"convax.generation-lro/1"}}return{acceptedInputs:O,...D.delivery===void 0?{}:{delivery:D.delivery},description:T(D.description,`${K} description`,2000),id:j,...D.inputBinding===void 0?{}:{inputBinding:D.inputBinding},output:D.output,...L===void 0?{}:{recovery:L},title:T(D.title,`${K} title`,120)}});if(new Set(J.map((_)=>_.id)).size!==J.length)throw TypeError("Generation tools contain duplicate ids");let Q=c(G.models,"Generation models",J.length).map((_,M)=>{let K=`Generation model ${M}`,D=A(_,K);return R(D,["name","tool"],K),{name:T(D.name,`${K} name`,120),tool:Y0(D.tool,`${K} tool`)}});if(new Set(Q.map((_)=>_.tool)).size!==Q.length)throw TypeError("Generation models contain duplicate tool references");let X=new Set(Q.map((_)=>_.tool)),Y=J.find((_)=>_.delivery==="return"&&X.has(_.id));if(Y)throw TypeError(`Generation model cannot reference a return-delivery operation: ${Y.id}`);let Z=J.find((_)=>_.inputBinding!==void 0&&X.has(_.id));if(Z)throw TypeError(`Generation model cannot reference an input-bound operation: ${Z.id}`);return{models:Q,tools:J}}function g8(F){let G=c(F,"Agent tools",32,!0).map((J,Q)=>{let X=`Agent tool ${Q}`,Y=A(J,X);R(Y,["id","tool"],X);let Z=T(Y.id,`${X} id`,64);if(!q8.test(Z))throw TypeError(`${X} id must use lower snake_case`);return{id:Z,tool:Y0(Y.tool,`${X} generation tool`)}});if(new Set(G.map((J)=>J.id)).size!==G.length)throw TypeError("Agent tools contain duplicate ids");if(new Set(G.map((J)=>J.tool)).size!==G.length)throw TypeError("Agent tools contain duplicate generation tool references");return G}function x8(F){let G=A(F,"Agent remote MCP contribution");if(R(G,["headers","oauth","type","url"],"Agent remote MCP contribution"),G.type!=="remote")throw TypeError("Agent MCP type must be remote");let J=T(G.url,"Agent remote MCP URL",2048);try{let X=new URL(J);if(X.protocol!=="https:"||X.username!==""||X.password!==""||X.hash!=="")throw TypeError()}catch{throw TypeError("Agent remote MCP URL must be an absolute HTTPS URL without credentials or a fragment")}if(G.oauth!==void 0&&G.oauth!=="auto"&&G.oauth!=="none")throw TypeError("Agent remote MCP oauth must be auto or none");let Q;if(G.headers!==void 0){let X=A(G.headers,"Agent remote MCP headers"),Y=Object.entries(X);if(Y.length>16)throw TypeError("Agent remote MCP headers must contain at most 16 entries");let Z=new Set;Q={};for(let[_,M]of Y){if(!/^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/u.test(_))throw TypeError(`Agent remote MCP header name is invalid: ${_}`);let K=_.toLowerCase();if(Z.has(K))throw TypeError(`Agent remote MCP headers contain a duplicate name: ${_}`);if(K==="authorization"||K==="cookie"||K==="proxy-authorization")throw TypeError(`Agent remote MCP header is not allowed: ${_}`);let D=T(M,`Agent remote MCP header ${_}`,2048);if(/\{(?:env|file):/iu.test(D)||/\$\{[^}]*\}/u.test(D))throw TypeError(`Agent remote MCP header ${_} must be a literal value`);Z.add(K),Q[_]=D}}return{...Q===void 0?{}:{headers:Q},oauth:G.oauth==="none"?"none":"auto",type:"remote",url:J}}function f8(F){let G=A(F,"Agent contribution");R(G,["mcp","tools"],"Agent contribution");let J=G.tools===void 0?void 0:g8(G.tools),Q=G.mcp===void 0?void 0:x8(G.mcp);if(J===void 0&&Q===void 0)throw TypeError("Agent contribution must declare tools or mcp");return{...Q===void 0?{}:{mcp:Q},...J===void 0?{}:{tools:J}}}function h8(F){let G=new Map(F.generation?.tools.map((Q)=>[Q.id,Q])??[]),J=new Set(F.generation?.models.map((Q)=>Q.tool)??[]);for(let Q of J)if(!G.has(Q))throw TypeError(`Generation model references an unknown tool: ${Q}`);for(let Q of F.agent?.tools??[]){if(!G.has(Q.tool))throw TypeError(`Agent tool references an unknown generation tool: ${Q.tool}`);if(J.has(Q.tool))throw TypeError(`Agent tool must reference an operation, not a generation model: ${Q.tool}`)}for(let Q of F.selectionActions??[]){if(!("steps"in Q))continue;for(let X of Q.steps){let Y=G.get(X.tool);if(!Y)throw TypeError(`Canvas selection action references an unknown generation tool: ${X.tool}`);if(J.has(X.tool))throw TypeError(`Canvas selection action must reference an operation, not a generation model: ${X.tool}`);if(Y.inputBinding!==void 0)throw TypeError(`Canvas selection action cannot reference an input-bound operation: ${X.tool}`);let Z=Q.target==="image"?"reference_image":"reference_video";if(!Y.acceptedInputs.includes(Z))throw TypeError(`Canvas ${Q.target} selection action tool must accept ${Z}: ${X.tool}`);if(Y.delivery==="return"){if(Q.editor!=="confirmation")throw TypeError(`Canvas return-delivery operation requires a confirmation editor: ${X.tool}`);if(Q.steps.length!==1)throw TypeError(`Canvas return-delivery operation requires exactly one step: ${X.tool}`);if(Y.output!=="text")throw TypeError(`Canvas return-delivery operation must return text: ${X.tool}`)}else if(Q.target==="image"&&(Q.editor!=="immediate"||Q.presentation!=="cutout-scan"||Q.steps.length!==1||Y.output!=="image"))throw TypeError(`Canvas image output requires one immediate image operation with cutout-scan presentation: ${X.tool}`)}}}var yF=["authorize","reauthorize","authorization.cancel","checkout","sign_out"],y8=new Set(yF);function c8(F){let G=A(F,"Service contribution");R(G,["actions"],"Service contribution");let J=c(G.actions,"Service actions",yF.length).map((Q)=>{if(typeof Q!=="string"||!y8.has(Q))throw TypeError("Service actions contain an unsupported or duplicate action");return Q});if(new Set(J).size!==J.length)throw TypeError("Service actions contain an unsupported or duplicate action");return{actions:J}}function b8(F){let G=A(F,"LLM contribution");R(G,["modelCatalog","models","provider"],"LLM contribution");let J=A(G.provider,"LLM provider");R(J,["id","name"],"LLM provider");let Q=T(J.id,"LLM provider id",80);if(!/^[a-z0-9]+(?:-[a-z0-9]+)*$/u.test(Q))throw TypeError("LLM provider id must use kebab-case");if(G.modelCatalog!==void 0&&G.modelCatalog!=="runtime")throw TypeError("LLM model catalog must be runtime");let X=c(G.models,"LLM models",32,!0).map((Y,Z)=>{let _=`LLM model ${Z}`,M=A(Y,_);R(M,["id","name"],_);let K=T(M.id,`${_} id`,128);if(!/^~?[a-z0-9]+(?:[._/:-][a-z0-9]+)*$/u.test(K))throw TypeError(`${_} id is invalid`);return{id:K,name:T(M.name,`${_} name`,120)}});if(new Set(X.map((Y)=>Y.id)).size!==X.length)throw TypeError("LLM models contain duplicate ids");return{...G.modelCatalog===void 0?{}:{modelCatalog:"runtime"},models:X,provider:{id:Q,name:T(J.name,"LLM provider name",120)}}}function v8(F){let G=A(F,"Pet contribution");R(G,["library","overlay","protocol","settings"],"Pet contribution");let J=X0(G.library,"Pet library"),Q=X0(G.overlay,"Pet overlay"),X=X0(G.settings,"Pet settings");if(!J.toLowerCase().endsWith(".json"))throw TypeError("Pet library must be a JSON file");if(!Q.toLowerCase().endsWith(".html"))throw TypeError("Pet overlay must be an HTML file");if(!X.toLowerCase().endsWith(".html"))throw TypeError("Pet settings must be an HTML file");if(G.protocol!=="convax.pet-host/1")throw TypeError("Pet protocol must equal convax.pet-host/1");return{library:J,overlay:Q,protocol:"convax.pet-host/1",settings:X}}function m8(F){let G=A(F,"Plugin runtime");if(R(G,["args","command","type"],"Plugin runtime"),G.type!=="mcp-stdio")throw TypeError("Plugin runtime type must be mcp-stdio");let J=T(G.command,"Plugin runtime command",128);if(!/^[A-Za-z0-9][A-Za-z0-9._-]*$/u.test(J))throw TypeError("Plugin runtime command must be a bare executable name");E0(J);let Q;if(G.args!==void 0)Q=c(G.args,"Plugin runtime args",64).map((X,Y)=>{let Z=T(X,`Plugin runtime arg ${Y}`,1024);if(/[\s"'`;|&`$(){}[\]<>]/u.test(Z)||Z.includes("\\")||/(^|=)(?:\/|[A-Za-z]:)/u.test(Z)||/(^|[=/])\.{1,2}(?:\/|$)/u.test(Z))throw TypeError(`Plugin runtime arg ${Y} must be a static CLI token without code, native paths, or traversal`);return Z});return{...Q===void 0?{}:{args:Q},command:J,type:"mcp-stdio"}}var SF=new Set(U0.apis.filter((F)=>F.audience.includes("agent-skill")).map((F)=>F.id)),d8=/^[a-z][a-z0-9_]{0,63}$/;function p8(F,G){let J=T(F,G,64);if(!/^[a-z0-9]+(?:-[a-z0-9]+)*$/u.test(J))throw TypeError(`${G} must use kebab-case`);return E0(J),J}function s8(F,G,J){let Q=A(F,G);R(Q,["optionalHostApis","pluginTools","requiredHostApis"],G);let X=s0({major:M0,required:Q.requiredHostApis??[],optional:Q.optionalHostApis??[]}),Y=new Set(J.required),Z=new Set([...J.required,...J.optional]);for(let M of X.required){if(!Y.has(M))throw TypeError(`${G} required Host API must be required by the Plugin: ${M}`);if(N0(M)&&!SF.has(M))throw TypeError(`${G} Host API is not available to Agent Skills: ${M}`)}for(let M of X.optional){if(!Z.has(M))throw TypeError(`${G} optional Host API must be declared by the Plugin: ${M}`);if(N0(M)&&!SF.has(M))throw TypeError(`${G} Host API is not available to Agent Skills: ${M}`)}let _;if(Q.pluginTools!==void 0){if(_=c(Q.pluginTools,`${G} pluginTools`,32,!0).map((M,K)=>{let D=T(M,`${G} pluginTools ${K}`,64);if(!d8.test(D))throw TypeError(`${G} plugin tool id must use lower snake_case: ${D}`);return D}),new Set(_).size!==_.length)throw TypeError(`${G} pluginTools contain duplicate ids`)}if(X.required.length===0&&X.optional.length===0&&_===void 0)throw TypeError(`${G} must declare at least one Host API or Plugin tool`);return{...X.optional.length===0?{}:{optionalHostApis:[...X.optional]},..._===void 0?{}:{pluginTools:_},...X.required.length===0?{}:{requiredHostApis:[...X.required]}}}function o8(F,G){if(F===void 0)return;let J=c(F,"Plugin Skill contributions",32,!0).map((Q,X)=>{let Y=`Plugin Skill contribution ${X}`,Z=A(Q,Y);R(Z,["name","path","uses"],Y);let _=p8(Z.name,`${Y} name`),M=X0(Z.path,`${Y} path`);if(M.split("/").at(-1)!==_)throw TypeError(`${Y} path must name its Skill directory: ${_}`);let K=Z.uses===void 0?void 0:s8(Z.uses,`${Y} uses`,G);return{name:_,path:M,...K===void 0?{}:{uses:K}}});if(new Set(J.map((Q)=>Q.name)).size!==J.length)throw TypeError("Plugin Skill contributions contain duplicate names");if(new Set(J.map((Q)=>Q.path.toLocaleLowerCase("en-US"))).size!==J.length)throw TypeError("Plugin Skill contributions contain duplicate paths");return J}function r8(F,G){let J=new Set(G?.tools?.map((Q)=>Q.id)??[]);for(let Q of F??[])for(let X of Q.uses?.pluginTools??[])if(!J.has(X))throw TypeError(`Plugin Skill ${Q.name} references an unknown Agent tool: ${X}`)}var DF="convax.plugin/8";var cF=["canvas.connectedImages.read","canvas.connectedInputs.read","canvas.connectedMedia.stream","canvas.node.read","canvas.node.write","canvas.image.write","project.files.read","agent.prompt","generation.execute","ui.fullscreen","projects.read","canvas.catalog.read","canvas.document.read","canvas.document.write","canvas.events.subscribe","pet.activity.read","pet.activity.open","pet.preferences.write","pet.custom.manage"],u8=["projects.read","canvas.catalog.read","canvas.document.read","canvas.document.write","canvas.events.subscribe"],bF=["pet.activity.read","pet.activity.open","pet.preferences.write","pet.custom.manage"],UF=["pet.activity.read","pet.activity.open","pet.preferences.write"],n8=new Set(cF),t8=new Set(bF);function i8(F){let G=c(F??[],"Plugin capabilities",cF.length).map((J)=>{if(typeof J!=="string"||!n8.has(J))throw TypeError("Plugin capabilities contain an unsupported or duplicate capability");return J});if(new Set(G).size!==G.length)throw TypeError("Plugin capabilities contain an unsupported or duplicate capability");return G}function a8(F){let G=F.entry===void 0?void 0:X0(F.entry,"Plugin entry");if(G!==void 0&&!G.toLowerCase().endsWith(".html"))throw TypeError("Plugin entry must be an HTML file");let J=F.hooks===void 0?void 0:X0(F.hooks,"Plugin hooks");if(J!==void 0&&!/\.(?:js|mjs)$/u.test(J))throw TypeError("Plugin hooks must be a JavaScript ESM module");return{entry:G,hooks:J}}function l8(F){let{capabilities:G,canvas:J,entry:Q,hostApi:X}=F;if(Q!==void 0!==(J?.renderer!==void 0))throw TypeError("Plugin entry and Canvas renderer must appear together");if(Q!==void 0&&!X.required.includes("host.context.get"))throw TypeError("convax.plugin/8 Web Plugins must require host.context.get");if((J?.commands!==void 0||J?.menus!==void 0||J?.toolbar!==void 0)&&J.renderer===void 0)throw TypeError("Canvas UI commands require a sandboxed Canvas renderer");if(G.includes("generation.execute")&&J?.renderer===void 0)throw TypeError("generation.execute requires a sandboxed Canvas surface");if(J&&J.renderer===void 0&&!J.selectionActions?.length&&!J.commands?.length&&!J.menus?.length&&!J.toolbar?.length)throw TypeError("Canvas contributions must declare a renderer, selection actions, or UI commands");if(J?.selectionActions?.some((Y)=>("action"in Y)&&Y.action.type==="materialize-own-plugin-node")&&J.renderer===void 0)throw TypeError("materialize-own-plugin-node requires the contributing Plugin renderer")}function e8(F,G,J){if(G===void 0)return;if(F.lengthbF.length||UF.some((Q)=>!F.includes(Q))||F.some((Q)=>!t8.has(Q)))throw TypeError("Pet capabilities must include pet.activity.read, pet.activity.open, and pet.preferences.write; pet.custom.manage is optional");if(J!==void 0)throw TypeError("Pet feature cannot declare an executable runtime")}function F1(F,G={}){let J=A(F,"Plugin manifest");if(R(J,["capabilities","contributes","description","entry","hooks","hostApi","id","name","runtime","schema","version"],"Plugin manifest"),J.schema!==DF)throw TypeError("Plugin manifest must use convax.plugin/8");if(!Object.prototype.hasOwnProperty.call(J,"hostApi"))throw TypeError("convax.plugin/8 must declare hostApi explicitly");let Q=G.hostApiMode==="authoring"?q2(J.hostApi):s0(J.hostApi),X=i8(J.capabilities),Y=A(J.contributes,"Plugin contributions");R(Y,["agent","canvas","capabilities","generation","llm","pet","service","skills"],"Plugin contributions");let{entry:Z,hooks:_}=a8(J),M=Y.canvas===void 0?void 0:H8(Y.canvas);l8({capabilities:X,canvas:M,entry:Z,hostApi:Q});let K=Y.agent===void 0?void 0:f8(Y.agent),D=Y.capabilities===void 0?void 0:r2(Y.capabilities),j=Y.generation===void 0?void 0:I8(Y.generation),O=Y.llm===void 0?void 0:b8(Y.llm),L=Y.pet===void 0?void 0:v8(Y.pet),k=Y.service===void 0?void 0:c8(Y.service),G0=o8(Y.skills,Q),d=J.runtime===void 0?void 0:m8(J.runtime),J0=j!==void 0||k!==void 0||O!==void 0||Boolean(D?.exports.length);if(d!==void 0!==J0){if(D?.exports.length&&d===void 0)throw TypeError("Plugin capability exports require a verified mcp-stdio runtime");throw TypeError("convax.plugin/8 runtime and executable contribution must appear together")}if(D?.exports.length&&d===void 0)throw TypeError("Plugin capability exports require a verified mcp-stdio runtime");e8(X,L,d),h8({agent:K,generation:j,selectionActions:M?.selectionActions}),r8(G0,K);let U=new Set(u8),W=X.some((V)=>U.has(V));if(M?.renderer===void 0&&!M?.selectionActions?.length&&!J0&&_===void 0&&!X.includes("generation.execute")&&!W&&L===void 0&&(D?.exports.length??0)===0&&K?.mcp===void 0)throw TypeError("convax.plugin/8 must declare a Plugin capability beyond owned Skills");return BF({capabilities:X,contributes:{...K===void 0?{}:{agent:K},...D===void 0?{}:{capabilities:D},...M===void 0?{}:{canvas:M},...j===void 0?{}:{generation:j},...O===void 0?{}:{llm:O},...L===void 0?{}:{pet:L},...k===void 0?{}:{service:k},...G0===void 0?{}:{skills:G0}},description:T(J.description,"Plugin description",2000),...Z===void 0?{}:{entry:Z},..._===void 0?{}:{hooks:_},hostApi:Q,id:HF(J.id),name:T(J.name,"Plugin name",120),...d===void 0?{}:{runtime:d},schema:DF,version:t2(J.version)})}function G1(F){return F1(F,{hostApiMode:"authoring"})}class f extends Error{code;constructor(F,G){super(G);this.name="PluginHostProtocolError",this.code=F}}class r0 extends Error{code;kind;recoverable;constructor(F){super(F.message);this.name="PluginHostRemoteError",this.code=F.code,this.kind=F.kind,this.recoverable=F.recoverable}}class m0 extends Error{reason;constructor(F){super("Plugin Host request was aborted");this.name="AbortError",this.reason=F}}var WF=0;function J1(){return WF+=1,`sdk-${Date.now().toString(36)}-${WF.toString(36)}`}function Q1(F){if(F.length<1||F.length>96||F!==F.trim()||!/^[A-Za-z0-9._-]+$/.test(F))throw TypeError("Plugin Host requestIdPrefix is invalid")}function jF(F,G){let J=F.contributes.capabilities,Q=J?.imports.required.find((Y)=>Y.id===G);if(Q)return{import:Q,requirement:"required"};let X=J?.imports.optional.find((Y)=>Y.id===G);if(X)return{import:X,requirement:"optional"};throw TypeError(`Plugin capability import is not declared: ${G}`)}function X1(F,G){let J=G.kind==="protocol"?gF(G):g2(F,G);return new r0(J)}function VF(F){let G=F.kind==="protocol"?gF(F):$8(F);return new r0(G)}function vF(F){let G=G1(F.manifest);if(G.entry===void 0||!G.hostApi.required.includes("host.context.get"))throw TypeError("Plugin Host Web client requires an entry and required host.context.get negotiation baseline");let J=F.requestIdPrefix??J1();Q1(J);let Q=new Map,X=new Set,Y,Z,_=0,M=!1,K=(U)=>{for(let W of Q.values())W.abort?.(),W.reject(U);Q.clear()},D=(U,W=!0)=>{if(M)return;M=!0,F.port.removeEventListener("message",G0),X.clear(),Y=void 0,Z=void 0,K(U);let V={protocol:u,type:"disconnect"};try{P0(V,l2,"Plugin Host disconnect"),L(V)}catch{}try{F.port.close()}catch{}if(!W)return;try{F.onFatalError?.(U)}catch{}},j=()=>{if(_>=Number.MAX_SAFE_INTEGER){let W=new f("request-id-exhausted","Plugin Host request id space is exhausted");throw D(W),W}_+=1;let U=`${J}-${_.toString(36)}`;if(!kF(U)){let W=new f("request-id-exhausted","Plugin Host request id is invalid");throw D(W),W}return U},O=(U,W)=>{P0(U,W,"Plugin Host request")},L=(U)=>{F.port.postMessage(U)},k=(U,W,V,N)=>{if(M)return Promise.reject(new f("closed","Plugin Host client is closed"));if(N?.aborted)return Promise.reject(new m0(N.reason));if(Q.size>=YF)return Promise.reject(RangeError(`Plugin Host client permits at most ${YF} in-flight requests`));try{O(U,V.maximumRequestBytes)}catch(b){return Promise.reject(b)}let E=U.id;return new Promise((b,y)=>{let Q0=N?()=>{let t=Q.get(E);if(!t)return;Q.delete(E),t.abort?.();let p={id:E,protocol:u,type:"cancel"};try{O(p,C0),L(p)}catch(s){let n0=new f("transport-failed",s instanceof Error?s.message:"Plugin Host cancel failed");y(n0),D(n0);return}y(new m0(N.reason))}:void 0,W0=Q0?()=>{N.removeEventListener("abort",Q0)}:void 0;if(Q.set(E,{abort:W0,maximumResponseBytes:V.maximumResponseBytes,parseFailure:V.parseFailure,parseResult:W,reject:y,resolve:b}),Q0)N.addEventListener("abort",Q0,{once:!0});try{L(U)}catch(t){D(new f("transport-failed",t instanceof Error?t.message:"Plugin Host transport failed"))}})};function G0(U){if(M)return;let W;try{W=P0(U.data,a2,"Plugin Host response")}catch{D(new f("invalid-envelope","Plugin Host sent a non-JSON message"));return}if(Z8(U.data)){try{for(let E of X)E(U.data)}catch{D(new f("invalid-envelope","Plugin Host command listener failed"))}return}if(!Y8(U.data)){D(new f("invalid-envelope","Plugin Host sent an invalid envelope"));return}let V=U.data,N=Q.get(V.id);if(!N){D(new f("unknown-response",`Plugin Host returned an unknown, duplicate, or late response id: ${V.id}`));return}if(W>N.maximumResponseBytes){D(new f("invalid-envelope",`Plugin Host response exceeds ${N.maximumResponseBytes} bytes for this request`));return}if(!V.ok){try{let E=N.parseFailure(V.error);Q.delete(V.id),N.abort?.(),N.reject(E)}catch(E){D(new f("invalid-result",E instanceof Error?E.message:"Plugin Host returned an invalid failure"))}return}try{let E=N.parseResult(V.result);Q.delete(V.id),N.abort?.(),N.resolve(E)}catch(E){D(new f("invalid-result",E instanceof Error?E.message:"Plugin Host returned an invalid result"))}}F.port.addEventListener("message",G0),F.port.start?.();let d=(U,W)=>{if(!GF(G.hostApi,U))return Promise.reject(TypeError(`Plugin Host API is not declared: ${U}`));let V=E2[U],N=V.params.type==="none"?void 0:W[0],E=V.params.type==="none"?W[0]:W[1],b;try{b=T2(U,N)}catch(p){return Promise.reject(p)}let Q0={id:j(),method:U,...b===void 0?{}:{params:b},protocol:u,type:"request"},W0=N2(U),t=B2;return k(Q0,(p)=>{let s=t(U,p);if(U==="host.context.get")Y=s;return s},{maximumRequestBytes:W0.request.maxBytes,maximumResponseBytes:W0.result.maxBytes,parseFailure:(p)=>{let s=X1(U,p);if(s.kind==="api"&&s.code==="stale-context")Y=void 0;return s}},E?.signal)},J0={get closed(){return M},callHostApi(U,...W){return d(U,W)},async getHostApiAvailability(U,W){if(!GF(G.hostApi,U))throw TypeError(`Plugin Host API is not declared: ${U}`);let V=!Y||W?.refresh?await J0.refreshHostApiContext(W):Y,N=p0(U);return V.hostApi.availability.find(({id:E})=>E===U)??{available:!1,contractSince:N.contractSince,id:U,reason:"unsupported-host",recoverable:!1,since:N.since}},refreshHostApiContext(U){if(Y=void 0,Z)return Z;let V=d("host.context.get",[U]).finally(()=>{if(Z===V)Z=void 0});return Z=V,Z},async requireHostApi(U,W){let V=await J0.getHostApiAvailability(U,W);if(!V.available)throw new EF(V);return V},getCapabilityAvailability(U,W){let V;try{V=jF(G,U)}catch(b){return Promise.reject(b)}let N=j();return k({capabilityId:U,id:N,protocol:u,type:"capability-availability"},(b)=>{let y=_8(b);if(y.capabilityId!==U||y.requirement!==V.requirement)throw TypeError("Plugin capability availability does not match the declared import");return y},{maximumRequestBytes:C0,maximumResponseBytes:XF,parseFailure:VF},W?.signal)},invokeCapability(U,W,V){let N;try{N=jF(G,U),QF(N.import.inputSchema,W,`Plugin capability ${U} input`)}catch(y){return Promise.reject(y)}let E=j();return k({capabilityId:U,id:E,input:W,protocol:u,type:"capability-invoke"},(y)=>{return QF(N.import.outputSchema,y,`Plugin capability ${U} output`),y},{maximumRequestBytes:C0,maximumResponseBytes:XF,parseFailure:VF},V?.signal)},onCommand(U){if(M)throw new f("closed","Plugin Host client is closed");if(X.size>=64)throw RangeError("Plugin Host command listener limit exceeded");return X.add(U),()=>{X.delete(U)}},close(){D(new f("closed","Plugin Host client was closed"),!1)}};return J0}var u0={schema:"convax.plugin/8",id:"hello-convax",name:"Hello Convax",description:"Checks the scoped Convax Plugin host connection and shows its active context.",version:"0.2.0",entry:"index.html",capabilities:[],contributes:{canvas:{renderer:{create:!0,width:480,height:300}}},hostApi:{major:2,required:["host.context.get"],optional:[]}};var M1="@convax/plugin-sdk/client:createPluginHostClient";function S1(F,G={}){if(F.source!==window.parent||F.ports.length!==1||!IF(F.data)||F.data.pluginId!==u0.id)return null;return vF({manifest:u0,onFatalError:G.onFatalError,port:F.ports[0],requestIdPrefix:G.requestIdPrefix})}export{M1 as pluginSdkClientBundleMarker,S1 as acceptPluginHostConnection}; diff --git a/packages/plugins/hello-convax/package/manifest.json b/packages/plugins/hello-convax/package/manifest.json index 25d19b8..0ae1e13 100644 --- a/packages/plugins/hello-convax/package/manifest.json +++ b/packages/plugins/hello-convax/package/manifest.json @@ -3,7 +3,7 @@ "id": "hello-convax", "name": "Hello Convax", "description": "Checks the scoped Convax Plugin host connection and shows its active context.", - "version": "0.1.3", + "version": "0.2.0", "entry": "index.html", "capabilities": [], "contributes": { @@ -43,7 +43,7 @@ ] }, "hostApi": { - "major": 1, + "major": 2, "required": [ "host.context.get" ], diff --git a/packages/plugins/hello-convax/test/protocol.test.js b/packages/plugins/hello-convax/test/protocol.test.js index c3f8b10..69efe30 100644 --- a/packages/plugins/hello-convax/test/protocol.test.js +++ b/packages/plugins/hello-convax/test/protocol.test.js @@ -18,13 +18,13 @@ describe("hello-convax v8 Web Host API", () => { ]) expect([manifest.version, metadata.version, workspace.version]).toEqual([ - "0.1.3", - "0.1.3", - "0.1.3", + "0.2.0", + "0.2.0", + "0.2.0", ]) - expect([skillMetadata.version, skillWorkspace.version]).toEqual(["0.2.2", "0.2.2"]) + expect([skillMetadata.version, skillWorkspace.version]).toEqual(["0.3.0", "0.3.0"]) expect(manifest.hostApi).toEqual({ - major: 1, + major: 2, required: ["host.context.get"], optional: [], }) diff --git a/packages/plugins/jianying-editor/convax-package.json b/packages/plugins/jianying-editor/convax-package.json index 1cd3db3..0f0dfbe 100644 --- a/packages/plugins/jianying-editor/convax-package.json +++ b/packages/plugins/jianying-editor/convax-package.json @@ -4,7 +4,7 @@ "id": "jianying-editor", "name": "剪映导入", "description": "将直接连接的 Canvas 图片和视频安全导入剪映当前草稿或新草稿。", - "version": "2.1.2", + "version": "3.0.0", "companions": [ { "command": "convax-jianying-editor-mcp", diff --git a/packages/plugins/jianying-editor/package.json b/packages/plugins/jianying-editor/package.json index f8fa919..682ec54 100644 --- a/packages/plugins/jianying-editor/package.json +++ b/packages/plugins/jianying-editor/package.json @@ -1,8 +1,11 @@ { "name": "@microvoid/convax-plugin-jianying-editor", - "version": "2.1.2", + "version": "3.0.0", "private": true, "type": "module", + "convax.hostCapabilityRequests": [ + "web-plugin-generation-input-binding" + ], "dependencies": { "@microvoid/convax-jianying-editor-mcp": "workspace:*", "@microvoid/convax-skill-jianying-editor": "workspace:*" diff --git a/packages/plugins/jianying-editor/package/assets/app.js b/packages/plugins/jianying-editor/package/assets/app.js index 9ddaa4a..313ba9e 100644 --- a/packages/plugins/jianying-editor/package/assets/app.js +++ b/packages/plugins/jianying-editor/package/assets/app.js @@ -95,7 +95,10 @@ import { acceptPluginHostConnection } from "./plugin-host-client.js" try { elements.result.textContent = action === "inspect" ? await execute("draft.status") - : await execute("media.export", inputs.map((input) => ({ nodeId: input.inputKey, role: input.role }))) + : await execute("media.export", inputs.map((input) => ({ + inputKey: input.inputKey, + role: input.role, + }))) } catch (error) { elements.result.textContent = error instanceof Error ? error.message : String(error) } finally { diff --git a/packages/plugins/jianying-editor/package/assets/plugin-host-client.js b/packages/plugins/jianying-editor/package/assets/plugin-host-client.js index 1b1e586..a8dcc04 100644 --- a/packages/plugins/jianying-editor/package/assets/plugin-host-client.js +++ b/packages/plugins/jianying-editor/package/assets/plugin-host-client.js @@ -1 +1 @@ -var c1=/^[a-z][a-z0-9]*(?:\.[a-z][a-z0-9]*)+$/,b1=/^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/,d1=/^[a-z][A-Za-z0-9]*(?:\.[a-z][A-Za-z0-9]*)+$/,v1=/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/,m1=new Set(["web-plugin","agent-skill","companion","host"]),p1=new Set(["connection","plugin","own-node","project","canvas"]),s1=new Set(["none","read","write","execute","subscribe"]),o1=new Set(["cancelable","commit-preserving"]);function _0(G,F){if(G.trim().length===0)throw TypeError(`${F} must not be empty`)}function y0(G,F){if(!v1.test(G))throw TypeError(`${F} must be a strict semantic version`)}function D1(G,F){let J=G.split(".").map(Number),Q=F.split(".").map(Number);for(let X=0;X<3;X+=1){let Y=J[X]-Q[X];if(Y!==0)return Y}return 0}function U1(G){if(!c1.test(G.id))throw TypeError(`Plugin API id is invalid: ${G.id}`);if(G.grant!==null&&!d1.test(G.grant))throw TypeError(`Plugin API grant is invalid: ${G.grant}`);if(!p1.has(G.scope))throw TypeError(`Plugin API scope is invalid: ${G.scope}`);if(!s1.has(G.sideEffect))throw TypeError(`Plugin API sideEffect is invalid: ${G.sideEffect}`);if(!o1.has(G.completion))throw TypeError(`Plugin API completion is invalid: ${G.completion}`);let F=G.audience??["web-plugin"];if(F.length===0||new Set(F).size!==F.length||F.some((X)=>!m1.has(X)))throw TypeError(`Plugin API audience is invalid: ${G.id}`);_0(G.docs.summary,`${G.id} docs.summary`),_0(G.docs.description,`${G.id} docs.description`),_0(G.docs.request,`${G.id} docs.request`),_0(G.docs.response,`${G.id} docs.response`);let J=new Set,Q=G.errors.map((X)=>{if(!b1.test(X.code)||J.has(X.code))throw TypeError(`Plugin API error code is invalid or duplicated: ${G.id}/${X.code}`);return J.add(X.code),_0(X.description,`${G.id}/${X.code} description`),Object.freeze({...X})});return Object.freeze({...G,audience:Object.freeze([...F]),errors:Object.freeze(Q),docs:Object.freeze({...G.docs})})}function H(G){return U1(G)}function r1(G,F){return y0(G,"Plugin API release version"),Object.freeze({version:G,apis:Object.freeze([...F])})}function u1(...G){if(G.length===0)throw TypeError("Plugin API catalog requires at least one release");let F=new Set,J=[],Q;for(let X of G){if(y0(X.version,"Plugin API release version"),Q&&D1(Q,X.version)>=0)throw TypeError("Plugin API releases must be strictly increasing");Q=X.version;for(let Y of X.apis){let Z=U1(Y);if(F.has(Z.id))throw TypeError(`Plugin API id is duplicated: ${Z.id}`);F.add(Z.id),J.push(Object.freeze({...Z,since:X.version}))}}if(J.length===0)throw TypeError("Plugin API catalog must contain at least one API");return Object.freeze({schema:"convax.plugin-api-catalog/1",version:G[G.length-1].version,apis:Object.freeze(J)})}var i2=Object.freeze({assertVersion:y0,compareVersions:D1}),z=1024,I=z*z,$0={type:"none"},s={type:"boolean"},B={finite:!0,type:"number"},o={finite:!0,minimum:0,type:"integer"},E0={type:"null"},g=(G)=>({const:G}),$=(G=2048,F={})=>({controlCharacters:!1,maxLength:G,minLength:F.allowEmpty?0:1,...F.prefix?{prefix:F.prefix}:{},...F.refinement?{refinement:F.refinement}:{},type:"string"}),C=(G,F,J=0,Q)=>({items:G,maxItems:F,minItems:J,type:"array",...Q?{uniqueBy:Q}:{}}),S=(G,F)=>({additionalProperties:!1,properties:G,required:F,type:"object"}),a=(...G)=>({oneOf:G}),C0=(G=I)=>({keyMaxLength:128,maxBytes:G,maxDepth:32,type:"json-object"}),y=(G)=>({controlCharacters:!1,enum:G,maxLength:Math.max(...G.map((F)=>F.length)),minLength:1,type:"string"}),Z0=S({x:B,y:B},["x","y"]),c0=S({height:B,width:B},["height","width"]),t=S({canvasId:$(256),projectId:$(256)},["canvasId","projectId"]),P0=y(["text","image","video","audio"]),W1=y(["text","reference_image","reference_video","first_frame","last_frame","audio"]),x=(G=1000)=>C($(),G),n1=a(S({available:g(!0),catalogVersion:$(64),id:$(128),since:$(64)},["available","catalogVersion","id","since"]),S({available:g(!1),id:$(128),reason:y(["unsupported-host","not-declared","permission-denied","wrong-surface","missing-context","setup-required","disabled","recovering"]),recoverable:s,since:$(64)},["available","id","reason","recoverable"])),j1=S({data:C0(),id:$(),parentId:$(),position:Z0,revision:o,style:C0(),type:$(80)},["data","id","position","revision","type"]),t1=S({nodeId:$(),role:W1},["nodeId","role"]),i1=S({ids:x(),kinds:x(),limit:o,relatedToNodeIds:x(),text:$(2000,{allowEmpty:!0})},[]),a1=S({animated:s,id:$(),source:$(),target:$(),type:$(80)},["source","target"]),l1=S({nodeId:$(),position:Z0,size:c0},["nodeId","position"]),e1=S({componentGap:B,componentPackingScale:B,crossGap:B,isolatedPlacement:y(["left","preserve"]),mainGap:B,nodeGap:B,nodePackingScale:B,strategy:y(["component-packing","horizontal-directed-cluster","vertical-directed-cluster"])},[]),FF=a(S({edgeIds:x(),nodeIds:x(),type:g("elements.remove")},["type"]),S({direction:y(["left","center","right","top","middle","bottom"]),nodeIds:x(),type:g("nodes.align")},["direction","nodeIds","type"]),S({connection:a1,type:g("nodes.connect")},["connection","type"]),S({axis:y(["horizontal","vertical"]),nodeIds:x(),type:g("nodes.distribute")},["axis","nodeIds","type"]),S({label:$(512),nodeIds:x(),type:g("nodes.group")},["nodeIds","type"]),S({gap:B,layout:y(["grid","horizontal","vertical"]),nodeIds:x(),type:g("nodes.layout")},["nodeIds","type"]),S({delta:Z0,nodeIds:x(),type:g("nodes.move")},["delta","nodeIds","type"]),S({type:g("nodes.setGeometry"),updates:C(l1,1000)},["type","updates"]),S({nodeId:$(),type:g("nodes.ungroup")},["nodeId","type"]),S({nodeIds:x(),options:e1,type:g("canvas.auto-layout")},["type"])),GF=S({durationMs:B,height:B,inputKey:$(),kind:$(80),label:$(512),mediaRevision:$(512),mimeType:$(512),name:$(512),status:y(["error","idle","pending"]),width:B},["inputKey","kind","label"]),JF=S({acceptedInputs:C(W1,6),description:$(2000),id:$(256),kind:y(["model","operation"]),output:P0,title:$(120)},["acceptedInputs","description","id","kind","output","title"]),V1=S({id:$(),source:$(),target:$()},["id","source","target"]),QF=S({id:$(),kind:$(80),label:$(512),parentId:$(64*z,{allowEmpty:!0}),position:Z0,size:c0,type:$(64*z,{allowEmpty:!0})},["id","kind","label","position","size"]),XF=S({description:$(64*z,{allowEmpty:!0}),durationMs:B,id:$(),kind:$(80),label:$(512),mimeType:$(64*z,{allowEmpty:!0}),name:$(64*z,{allowEmpty:!0}),parentId:$(64*z,{allowEmpty:!0}),position:Z0,resource:S({kind:g("project-file"),path:$(1024)},["kind","path"]),size:c0,status:$(64*z,{allowEmpty:!0}),text:$(64*z,{allowEmpty:!0}),type:$(64*z,{allowEmpty:!0})},["id","kind","label","position","size"]),YF=S({edges:C(V1,1e4),id:$(256),nodes:C(QF,1e4),revision:o,title:$(512)},["edges","id","nodes","revision","title"]),ZF=S({description:$(8000,{allowEmpty:!0}),edges:C(V1,1e4),id:$(256),nodes:C(XF,1e4),revision:o,tags:C($(),256),title:$(512)},["edges","id","nodes","revision","title"]),_F=S({id:$(),incomingNodeIds:x(),kind:$(80),label:$(512),outgoingNodeIds:x(),parentId:$(64*z,{allowEmpty:!0}),position:Z0,text:$(64*z,{allowEmpty:!0}),type:$(64*z,{allowEmpty:!0})},["id","incomingNodeIds","kind","label","outgoingNodeIds","position"]),$F=S({canvas:S({id:$(256),name:$(512)},["id"]),hostApi:S({availability:C(n1,256,0,"id"),catalogVersion:$(64)},["availability","catalogVersion"]),node:j1,plugin:S({id:$(128),name:$(512),version:$(128)},["id","name","version"]),project:S({id:$(256),name:$(512)},["id"])},["canvas","hostApi","node","plugin","project"]),w=(G,F,J={})=>({request:{maxBytes:J.request??64*z,schema:G},result:{maxBytes:J.result??64*z,schema:F}}),F0=Object.freeze({"host.context.get":w($0,$F,{result:I}),"canvas.inputs.list":w($0,S({inputs:C(GF,256)},["inputs"]),{result:I}),"canvas.inputs.open":w(S({inputKey:$()},["inputKey"]),S({probe:S({duration:S({estimated:s,milliseconds:B},["estimated","milliseconds"]),height:B,kind:y(["audio","video"]),mediaRevision:$(128),mimeType:$(256),size:B,width:B},["duration","kind","mediaRevision","mimeType","size"]),sessionId:$(128),url:$(2048,{prefix:"convax-connected-media://"})},["probe","sessionId","url"])),"canvas.inputs.close":w(S({sessionId:$(128)},["sessionId"]),S({closed:s},["closed"])),"canvas.node.get":w($0,j1,{result:I}),"canvas.node.state.replace":w(S({state:C0(256*z)},["state"]),S({updated:g(!0)},["updated"]),{request:256*z+4*z}),"canvas.resource.image.create":w(S({dataUrl:$(24*I,{prefix:"data:image/png;base64,"}),name:$(120,{refinement:"safe-png-file-name"})},["dataUrl","name"]),S({createdNodeId:$(),revision:o},["createdNodeId","revision"]),{request:24*I+4*z}),"project.file.text.read":w(S({path:$(1024,{refinement:"portable-project-relative-path"})},["path"]),S({content:$(I,{allowEmpty:!0}),exists:s,path:$(1024,{refinement:"portable-project-relative-path"})},["content","exists","path"]),{result:I+4*z}),"agent.prompt":w(S({text:$(20000,{refinement:"trimmed"})},["text"]),S({text:$(64*z,{allowEmpty:!0})},["text"])),"generation.tools.list":w(a($0,S({output:P0},[])),S({tools:C(JF,256)},["tools"]),{result:I}),"generation.execute":w(S({output:P0,prompt:$(20000,{refinement:"trimmed"}),references:C(t1,32),resultMode:y(["create-pending-node","return"]),toolId:$(256)},["prompt"]),S({createdNodeIds:C($(),32),outputText:$(64*z,{allowEmpty:!0}),revision:o,toolId:$(256),warnings:C($(),32)},["createdNodeIds","revision","toolId","warnings"]),{result:256*z}),"projects.list":w($0,S({projects:C(S({available:s,id:$(256),name:$(512)},["available","id","name"]),1000)},["projects"]),{result:I}),"canvas.catalog.list":w(S({projectId:$(256)},["projectId"]),S({canvases:C(S({createdAt:B,id:$(256),name:$(512),updatedAt:B},["createdAt","id","name","updatedAt"]),1e4),projectId:$(256)},["canvases","projectId"]),{result:8*I}),"canvas.document.get":w(S({projection:y(["geometry","structure"]),ref:t},["ref"]),a(S({document:YF,projection:g("geometry"),ref:t,storageVersion:a(E0,$(256))},["document","projection","ref","storageVersion"]),S({document:ZF,projection:g("structure"),ref:t,storageVersion:a(E0,$(256))},["document","projection","ref","storageVersion"])),{result:8*I}),"canvas.nodes.query":w(S({query:i1,ref:t},["ref"]),S({nodes:C(_F,1000),ref:t,revision:o,storageVersion:a(E0,$(256))},["nodes","ref","revision","storageVersion"]),{request:I,result:8*I}),"canvas.transaction.execute":w(S({commands:C(FF,256,1),expectedRevision:o,ref:t,transactionId:$(128)},["commands","expectedRevision","ref","transactionId"]),S({affectedNodeIds:x(1e4),changed:s,createdNodeIds:x(1e4),ref:t,revision:o,storageVersion:$(256),summaryTruncated:s,warnings:x()},["affectedNodeIds","changed","createdNodeIds","ref","revision","storageVersion","warnings"]),{request:I,result:2*I}),"canvas.events.subscribe":w(S({ref:S({canvasId:$(256),projectId:$(256)},["projectId"])},["ref"]),S({subscriptionId:$(128)},["subscriptionId"])),"canvas.events.unsubscribe":w(S({subscriptionId:$(128)},["subscriptionId"]),S({removed:s},["removed"]))}),KF=Math.max(...Object.values(F0).map(({request:G})=>G.maxBytes)),MF=Math.max(...Object.values(F0).map(({result:G})=>G.maxBytes));function SF(G){return F0[G]}function q0(G,F){if(!G||typeof G!=="object"||Array.isArray(G))throw TypeError(`${F} must be an object`);let J=Object.getPrototypeOf(G);if(J!==Object.prototype&&J!==null)throw TypeError(`${F} must be a plain object`);return G}var DF=/^(CON|PRN|AUX|NUL|COM[1-9¹²³]|LPT[1-9¹²³]|CONIN\$|CONOUT\$)$/iu;function L1(G){for(let F of G){let J=F.codePointAt(0);if(J>=55296&&J<=57343)return!1}return!0}function s0(G){let F=G.split(".",1)[0]??"";return Boolean(G&&G!=="."&&G!==".."&&L1(G)&&!/[\\/:*?"<>|\u0000-\u001f\u007f]/u.test(G)&&!/[. ]$/u.test(G)&&!DF.test(F))}function UF(G,F){if(F===void 0)return!0;if(F==="trimmed")return G===G.trim();if(F==="safe-png-file-name")return G===G.trim()&&G.toLowerCase().endsWith(".png")&&s0(G);if(F==="portable-project-relative-path"){if(G!==G.trim()||G.includes("\\")||G.startsWith("/")||G.startsWith("//")||/^[A-Za-z]:/u.test(G)||!L1(G))return!1;let J=G.split("/");return J[0]?.toLowerCase()!==".convax"&&J.length>0&&J.every((Q)=>s0(Q))}return!1}function WF(G,F,J){let Q=new Set,X=(_,M,K)=>{if(_===null||typeof _==="string"||typeof _==="boolean")return _;if(typeof _==="number"){if(!Number.isFinite(_))throw TypeError(`${M} must contain finite JSON numbers`);return _}if(!_||typeof _!=="object"||K>=F.maxDepth||Q.has(_))throw TypeError(`${M} must be bounded acyclic JSON`);let D=Object.getPrototypeOf(_);if(!Array.isArray(_)&&D!==Object.prototype&&D!==null)throw TypeError(`${M} must contain plain JSON objects`);Q.add(_);let W;if(Array.isArray(_))W=_.map((O,V)=>X(O,`${M}[${V}]`,K+1));else{let O=Object.create(null);for(let[V,P]of Object.entries(_)){if(V.length<1||V.length>F.keyMaxLength||/[\u0000-\u001f\u007f]/u.test(V))throw TypeError(`${M} key is invalid`);O[V]=X(P,`${M}.${V}`,K+1)}W=O}return Q.delete(_),W},Y=X(q0(G,J),J,0);if(Array.isArray(Y)||!Y||typeof Y!=="object")throw TypeError(`${J} must be an object`);let Z=JSON.stringify(Y);if(new TextEncoder().encode(Z).byteLength>F.maxBytes)throw TypeError(`${J} exceeds ${F.maxBytes} bytes`);return Y}function K0(G,F,J="Plugin API value"){if("oneOf"in G){let Y=[];for(let Z of G.oneOf)try{Y.push(K0(Z,F,J))}catch{}if(Y.length!==1)throw TypeError(`${J} must match exactly one schema variant`);return Y[0]}if("const"in G){if(F!==G.const)throw TypeError(`${J} must equal ${String(G.const)}`);return F}if("type"in G&&G.type==="none"){if(F!==void 0)throw TypeError(`${J} does not accept a value`);return}if("type"in G&&G.type==="null"){if(F!==null)throw TypeError(`${J} must be null`);return null}if("type"in G&&G.type==="boolean"){if(typeof F!=="boolean")throw TypeError(`${J} must be boolean`);return F}if("type"in G&&(G.type==="number"||G.type==="integer")){if(typeof F!=="number"||!Number.isFinite(F)||G.type==="integer"&&!Number.isSafeInteger(F)||G.minimum!==void 0&&FG.maxLength||G.controlCharacters===!1&&/[\u0000-\u001f\u007f]/u.test(F)||G.enum!==void 0&&!G.enum.includes(F)||G.prefix!==void 0&&!F.startsWith(G.prefix)||!UF(F,G.refinement))throw TypeError(`${J} must satisfy its bounded string contract`);return F}if("type"in G&&G.type==="array"){if(!Array.isArray(F)||F.lengthG.maxItems)throw TypeError(`${J} must satisfy its bounded array contract`);let Y=F.map((Z,_)=>K0(G.items,Z,`${J}[${_}]`));if(G.uniqueBy!==void 0){let Z=Y.map((_)=>{let K=q0(_,`${J} unique item`)[G.uniqueBy];if(typeof K!=="string"&&typeof K!=="number")throw TypeError(`${J} unique identity is invalid`);return`${typeof K}:${String(K)}`});if(new Set(Z).size!==Z.length)throw TypeError(`${J} contains duplicate ${G.uniqueBy}`)}return Y}if("type"in G&&G.type==="json-object")return WF(F,G,J);if(!("properties"in G))throw TypeError(`${J} has an unsupported schema`);let Q=q0(F,J),X=new Set(Object.keys(G.properties));if(G.required.some((Y)=>!Object.prototype.hasOwnProperty.call(Q,Y))||Object.keys(Q).some((Y)=>!X.has(Y)))throw TypeError(`${J} contains unsupported or missing fields`);return Object.fromEntries(Object.entries(Q).map(([Y,Z])=>[Y,K0(G.properties[Y],Z,`${J}.${Y}`)]))}function k0(G,F){if("oneOf"in G){let J=G.oneOf.map((Z)=>k0(Z,F)),Q=J.filter((Z)=>Z.type==="object");if(Q.length===0&&J.some((Z)=>Z.type==="none"))return{type:"none"};if(Q.length===0)throw TypeError(`${F} is not an object schema`);let X=new Set(Q.flatMap(({required:Z,optional:_})=>[...Z,..._])),Y=[...X].filter((Z)=>Q.every((_)=>_.required.includes(Z))).sort();return{additionalProperties:!1,optional:[...X].filter((Z)=>!Y.includes(Z)).sort(),required:Y,type:"object"}}if("type"in G&&G.type==="none")return{type:"none"};if(!("properties"in G))throw TypeError(`${F} is not an object schema`);return{additionalProperties:!1,optional:Object.keys(G.properties).filter((J)=>!G.required.includes(J)).sort(),required:[...G.required].sort(),type:"object"}}var I0=Object.freeze(Object.keys(F0).sort()),jF=Object.freeze(Object.fromEntries(I0.map((G)=>{let F=F0[G],J=k0(F.result.schema,`Plugin API ${G} result`);if(J.type!=="object")throw TypeError(`Plugin API ${G} result must be an object`);return[G,{params:k0(F.request.schema,`Plugin API ${G} params`),request:F.request,response:F.result,result:J}]})));function VF(G,F){return K0(F0[G].request.schema,F,`Plugin API ${G} params`)}function LF(G,F){return K0(F0[G].result.schema,F,`Plugin API ${G} result`)}var k=[{code:"stale-context",description:"The bound Project, Canvas, node, or connection changed before the call completed.",recoverable:!0}],q=[{code:"permission-denied",description:"The installed Plugin principal does not currently hold the required grant.",recoverable:!1}],o0=[{code:"resource-unavailable",description:"The authoritative Project resource is missing, changed, or cannot be read safely.",recoverable:!0}],r0=[{code:"partial-success",description:"A user-visible Project file was published, but the requested Canvas commit did not complete; retry is unsafe.",recoverable:!1}],U0=u1(r1("1.0.0",[H({id:"host.context.get",completion:"cancelable",grant:null,scope:"connection",sideEffect:"read",errors:k,docs:{summary:"Read the bounded context attached to the current Plugin connection.",description:"Returns only renderer-safe identifiers and feature metadata for the exact live connection; it grants no additional authority.",request:"No parameters.",response:"The current Plugin, Project, Canvas, node, and negotiated Host API context when present."}}),H({id:"canvas.inputs.list",completion:"cancelable",grant:"canvas.connectedInputs.read",scope:"own-node",sideEffect:"read",errors:[...k,...q],docs:{summary:"List direct incoming inputs of the owning Plugin node.",description:"Derives pathless input metadata from authoritative direct incoming Canvas edges and never reads resource bytes.",request:"No parameters; the owning node comes from the bound connection.",response:"A bounded list of direct incoming input descriptors and opaque input keys."}}),H({id:"canvas.inputs.open",completion:"cancelable",grant:"canvas.connectedMedia.stream",scope:"own-node",sideEffect:"read",errors:[...k,...q,...o0],docs:{summary:"Open a bounded stream for one previously listed direct input.",description:"Opens host-owned access to the exact authoritative input after topology and resource identity are revalidated.",request:"`{ inputKey }`, using an opaque key returned by canvas.inputs.list.",response:"A connection-bound stream descriptor and safe media metadata.",remarks:"Call canvas.inputs.close when the stream is no longer needed."}}),H({id:"canvas.inputs.close",completion:"cancelable",grant:"canvas.connectedMedia.stream",scope:"own-node",sideEffect:"write",errors:[...k,...q],docs:{summary:"Close one connection-bound input stream.",description:"Releases a stream created by canvas.inputs.open without changing Canvas or Project state.",request:"The stream handle returned by canvas.inputs.open.",response:"An acknowledgement; closing an already closed handle is idempotent."}}),H({id:"canvas.node.get",completion:"cancelable",grant:"canvas.node.read",scope:"own-node",sideEffect:"read",errors:[...k,...q],docs:{summary:"Read the owning Plugin node projection.",description:"Returns a bounded renderer-safe projection of the exact node bound to the connection.",request:"No parameters; the owning node comes from the bound connection.",response:"The owning node identity, revision, geometry, and Plugin state projection."}}),H({id:"canvas.node.state.replace",completion:"commit-preserving",grant:"canvas.node.write",scope:"own-node",sideEffect:"write",errors:[...k,...q],docs:{summary:"Replace the owning node's bounded Plugin state.",description:"Commits only the namespaced Plugin state through the authoritative Canvas application service with revision checks.",request:"`{ state }`, where state is a bounded JSON value.",response:"`{ updated: true }` after the authoritative state replacement commits."}}),H({id:"canvas.resource.image.create",completion:"commit-preserving",grant:"canvas.image.write",scope:"own-node",sideEffect:"write",errors:[...k,...q,...r0],docs:{summary:"Create a Project-backed Canvas image through the host lifecycle.",description:"Admits bounded image content as a user-visible Project resource and commits its Canvas reference without exposing native paths.",request:"`{ dataUrl, name }`, containing a bounded validated image data URL and safe file name.",response:"The created renderer-safe image result after Project publication and Canvas commit."}}),H({id:"project.file.text.read",completion:"cancelable",grant:"project.files.read",scope:"project",sideEffect:"read",errors:[...k,...q],docs:{summary:"Read one bounded UTF-8 Project file.",description:"Reads through the scoped Project Files capability using a normalized Project-relative path and never exposes a native path.",request:"`{ path }`, using a normalized Project-relative portable path.",response:"The bounded UTF-8 file text."}}),H({id:"agent.prompt",completion:"commit-preserving",grant:"agent.prompt",scope:"connection",sideEffect:"execute",errors:[...k,...q],docs:{summary:"Submit a bounded prompt through the host Agent capability.",description:"Uses the current host-owned Agent context; it does not grant direct OpenCode, filesystem, model, or credential access.",request:"`{ text }`, containing the bounded prompt text.",response:"`{ text }`, containing the bounded host acknowledgement."}}),H({id:"generation.tools.list",completion:"cancelable",grant:"generation.execute",scope:"plugin",sideEffect:"read",errors:q,docs:{summary:"List generation tools available to the installed Plugin principal.",description:"Returns normalized tool metadata derived from active verified contributions without exposing executable paths or credentials.",request:"Optional `{ output }` modality filter; omitting params lists every admitted modality.",response:"A bounded list of available generation tools and their public input contracts."}}),H({id:"generation.execute",completion:"commit-preserving",grant:"generation.execute",scope:"plugin",sideEffect:"execute",errors:[...k,...q,...o0,...r0],docs:{summary:"Execute one selected generation tool through the shared host executor.",description:"Revalidates the active Plugin, authorized executable, inputs, cancellation, and live resource guards immediately before execution.",request:"`{ output?, prompt, references?, resultMode?, toolId? }`, validated against the selected tool.",response:"The bounded selected tool result, created node ids, authoritative revision, and warnings."}}),H({id:"projects.list",completion:"cancelable",audience:["web-plugin","companion"],grant:"projects.read",scope:"plugin",sideEffect:"read",errors:q,docs:{summary:"List Projects visible to the installed Plugin principal.",description:"Returns portable Project identities and display metadata without native paths or private Project state.",request:"No parameters.",response:"A bounded list of renderer-safe Project summaries."}}),H({id:"canvas.catalog.list",completion:"cancelable",audience:["web-plugin","companion"],grant:"canvas.catalog.read",scope:"project",sideEffect:"read",errors:[...k,...q],docs:{summary:"List Canvas catalog entries for one authorized Project.",description:"Reads the Project-owned Canvas catalog without selecting a Project or Canvas in the Workbench.",request:"`{ projectId }`, naming one explicit portable Project.",response:"A bounded list of portable Canvas catalog entries."}}),H({id:"canvas.document.get",completion:"cancelable",audience:["web-plugin","companion"],grant:"canvas.document.read",scope:"canvas",sideEffect:"read",errors:[...k,...q],docs:{summary:"Read one authorized Canvas document projection.",description:"Returns a bounded portable structure or geometry projection from Main's authoritative Canvas application service.",request:"`{ ref, projection }`, using an explicit portable Project/Canvas reference and supported projection.",response:"The requested pathless document projection and authoritative revision."}}),H({id:"canvas.nodes.query",completion:"cancelable",audience:["web-plugin","companion"],grant:"canvas.document.read",scope:"canvas",sideEffect:"read",errors:[...k,...q],docs:{summary:"Query bounded node projections in one authorized Canvas.",description:"Executes a host-defined bounded query without exposing native paths or resource bytes.",request:"`{ ref, query }`, using an explicit portable Project/Canvas reference and bounded query.",response:"Matching node projections and the authoritative Canvas revision."}}),H({id:"canvas.transaction.execute",completion:"commit-preserving",audience:["web-plugin","companion"],grant:"canvas.document.write",scope:"canvas",sideEffect:"write",errors:[...k,...q],docs:{summary:"Commit one non-empty revision-bound Canvas transaction.",description:"Validates bounded commands against one authoritative revision and persists the accepted transaction atomically.",request:"`{ ref, expectedRevision, commands, transactionId }` with a bounded non-empty command list.",response:"The committed authoritative revision and bounded command results."}}),H({id:"canvas.events.subscribe",completion:"cancelable",audience:["web-plugin","companion"],grant:"canvas.events.subscribe",scope:"canvas",sideEffect:"subscribe",errors:[...k,...q],docs:{summary:"Subscribe to bounded events for one authorized Canvas.",description:"Creates a connection-scoped subscription; events are revisioned invalidations or safe projections, never native data.",request:"`{ ref }`, using an explicit portable Project/Canvas reference.",response:"A connection-bound subscription identifier."}}),H({id:"canvas.events.unsubscribe",completion:"cancelable",audience:["web-plugin","companion"],grant:"canvas.events.subscribe",scope:"canvas",sideEffect:"subscribe",errors:[...k,...q],docs:{summary:"Close one connection-bound Canvas event subscription.",description:"Releases a subscription created by canvas.events.subscribe without changing Canvas state.",request:"The subscription identifier returned by canvas.events.subscribe.",response:"An acknowledgement; closing an already closed subscription is idempotent."}})])),u0=U0.apis.map(({id:G})=>G).sort();if(u0.length!==I0.length||u0.some((G,F)=>G!==I0[F]))throw TypeError("Plugin API Catalog and portable method contracts are incomplete or inconsistent");var NF=U0.version,M0=Number(NF.split(".")[0]),N1=new Map(U0.apis.map((G)=>[G.id,G])),OF=new Set(N1.keys());function N0(G){return typeof G==="string"&&OF.has(G)}function O1(G){return N1.get(G)}var zF=/^[a-z][a-z0-9]*(?:\.[a-z][a-z0-9]*)+$/;function AF(G){return typeof G==="object"&&G!==null&&!Array.isArray(G)}function n0(G,F){if(!Array.isArray(G))throw TypeError(`${F} must be an array`);let J=[],Q=new Set;for(let X of G){if(typeof X!=="string"||!zF.test(X))throw TypeError(`${F} contains an invalid Plugin API id: ${String(X)}`);if(Q.has(X))throw TypeError(`${F} contains a duplicate Plugin API id: ${X}`);Q.add(X),J.push(X)}return J}function RF(G){let F=b0(G),J=[],Q=[];for(let X of F.required){if(!N0(X))throw TypeError(`Plugin API declaration contains an unknown Plugin API id: ${X}`);J.push(X)}for(let X of F.optional){if(!N0(X))throw TypeError(`Plugin API declaration contains an unknown Plugin API id: ${X}`);Q.push(X)}return Object.freeze({major:M0,required:Object.freeze(J),optional:Object.freeze(Q)})}function b0(G){if(!AF(G))throw TypeError("Plugin API declaration must be an object");if(Object.keys(G).some((Z)=>Z!=="major"&&Z!=="required"&&Z!=="optional"))throw TypeError("Plugin API declaration contains an unknown field");if(G.major!==M0)throw TypeError(`Plugin API declaration major must be ${M0}`);let J=n0(G.required,"Plugin API declaration required"),Q=n0(G.optional,"Plugin API declaration optional"),X=new Set(J),Y=Q.find((Z)=>X.has(Z));if(Y)throw TypeError(`Plugin API cannot be both required and optional: ${Y}`);return Object.freeze({major:M0,required:Object.freeze(J),optional:Object.freeze(Q)})}function EF(G,F){if(G.required.includes(F))return"required";if(G.optional.includes(F))return"optional";return}function t0(G,F){return EF(G,F)!==void 0}class z1 extends Error{availability;constructor(G){super(`Plugin API ${G.id} is unavailable: ${G.reason}`);this.name="PluginApiUnavailableError",this.availability=G}}function TF(G,F){return typeof F==="string"&&O1(G).errors.some((J)=>J.code===F)}function BF(G,F){if(!F||typeof F!=="object"||Array.isArray(F))throw TypeError(`Plugin API ${G} failure must be an object`);let J=F;if(Object.keys(J).some((X)=>!["code","kind","message","recoverable"].includes(X))||!Object.prototype.hasOwnProperty.call(J,"code")||!Object.prototype.hasOwnProperty.call(J,"message")||!Object.prototype.hasOwnProperty.call(J,"recoverable")||J.kind!=="api"||!TF(G,J.code)||typeof J.message!=="string"||J.message.length<1||J.message.length>4096||typeof J.recoverable!=="boolean")throw TypeError(`Plugin API ${G} failure is invalid`);let Q=O1(G).errors.find(({code:X})=>X===J.code);if(J.recoverable!==Q.recoverable)throw TypeError(`Plugin API ${G} failure recoverability does not match the Catalog`);return Object.freeze({code:J.code,kind:"api",message:J.message,recoverable:J.recoverable})}var HF=/^[a-z][a-z0-9]*(?:\.[a-z][a-z0-9-]*)+$/,wF=/^[a-z][a-z0-9]*(?:[._-][a-z0-9]+)*$/,CF=/^[A-Za-z][A-Za-z0-9_-]{0,63}$/,PF=/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/,qF=new Set(["none","read","write","execute","subscribe"]),A1=128,kF=64,IF=8,gF=16384,xF=256;function d0(G){return typeof G==="string"&&G.length<=160&&HF.test(G)}function u(G,F){if(!G||typeof G!=="object"||Array.isArray(G))throw TypeError(`${F} must be an object`);let J=Object.getPrototypeOf(G);if(J!==Object.prototype&&J!==null)throw TypeError(`${F} must be a plain object`);return G}function d(G,F,J,Q){let X=new Set([...F,...J]);if(F.some((Y)=>!Object.prototype.hasOwnProperty.call(G,Y))||Object.keys(G).some((Y)=>!X.has(Y)))throw TypeError(`${Q} contains unsupported or missing fields`)}function i(G,F,J=2000){if(typeof G!=="string"||G.length<1||G.length>J||G!==G.trim()||/[\u0000-\u001f\u007f]/u.test(G))throw TypeError(`${F} must be a bounded, trimmed string`);return G}function j0(G,F,J){if(!Number.isSafeInteger(G)||Number(G)<0||Number(G)>J)throw TypeError(`${F} must be a bounded non-negative integer`);return Number(G)}function g0(G,F){if(typeof G!=="string"||!PF.test(G))throw TypeError(`${F} must be a strict semantic version`);return G}function fF(G,F){let J=G.split(".").map(Number),Q=F.split(".").map(Number);for(let X=0;X<3;X+=1){let Y=J[X]-Q[X];if(Y!==0)return Y}return 0}function x0(G,F,J){if(J>IF)throw TypeError(`${F} exceeds the schema depth limit`);let Q=u(G,F);if(Q.type==="null"||Q.type==="boolean")return d(Q,["type"],[],F),Object.freeze({type:Q.type});if(Q.type==="number"||Q.type==="integer"){d(Q,["type"],["minimum","maximum"],F);let{minimum:X,maximum:Y}=Q;if(X!==void 0&&(typeof X!=="number"||!Number.isFinite(X)))throw TypeError(`${F}.minimum must be finite`);if(Y!==void 0&&(typeof Y!=="number"||!Number.isFinite(Y)))throw TypeError(`${F}.maximum must be finite`);if(X!==void 0&&Y!==void 0&&X>Y)throw TypeError(`${F} minimum exceeds maximum`);return Object.freeze({type:Q.type,...X===void 0?{}:{minimum:X},...Y===void 0?{}:{maximum:Y}})}if(Q.type==="string"){if(!Object.prototype.hasOwnProperty.call(Q,"maxLength"))throw TypeError(`${F}.maxLength is required to keep values bounded`);d(Q,["type","maxLength"],["minLength","enum"],F);let X=j0(Q.maxLength,`${F}.maxLength`,gF),Y=Q.minLength===void 0?void 0:j0(Q.minLength,`${F}.minLength`,X),Z;if(Q.enum!==void 0){if(!Array.isArray(Q.enum)||Q.enum.length<1||Q.enum.length>128||Q.enum.some((_)=>typeof _!=="string"||_.length>X)||new Set(Q.enum).size!==Q.enum.length)throw TypeError(`${F}.enum must contain unique bounded strings`);Z=Object.freeze([...Q.enum])}return Object.freeze({type:"string",maxLength:X,...Y===void 0?{}:{minLength:Y},...Z===void 0?{}:{enum:Z}})}if(Q.type==="array"){d(Q,["type","items","maxItems"],["minItems"],F);let X=j0(Q.maxItems,`${F}.maxItems`,xF),Y=Q.minItems===void 0?void 0:j0(Q.minItems,`${F}.minItems`,X);return Object.freeze({type:"array",items:x0(Q.items,`${F}.items`,J+1),maxItems:X,...Y===void 0?{}:{minItems:Y}})}if(Q.type==="object"){if(d(Q,["type","properties","required","additionalProperties"],[],F),Q.additionalProperties!==!1)throw TypeError(`${F}.additionalProperties must be false`);let X=u(Q.properties,`${F}.properties`),Y=Object.keys(X);if(Y.length>kF)throw TypeError(`${F} has too many properties`);if(Y.some((_)=>!CF.test(_)))throw TypeError(`${F} contains an invalid property name`);if(!Array.isArray(Q.required)||Q.required.some((_)=>typeof _!=="string"||!Y.includes(_))||new Set(Q.required).size!==Q.required.length)throw TypeError(`${F}.required must contain unique declared properties`);let Z=Object.fromEntries(Y.sort().map((_)=>[_,x0(X[_],`${F}.properties.${_}`,J+1)]));return Object.freeze({type:"object",properties:Object.freeze(Z),required:Object.freeze([...Q.required].sort()),additionalProperties:!1})}throw TypeError(`${F}.type is unsupported`)}function O0(G,F){let J=x0(G,F,0);if(J.type!=="object")throw TypeError(`${F} must be a closed object schema`);return J}function hF(G,F){let J=u(G,F);d(J,["id","inputSchema","outputSchema","version"],[],F);let Q=i(J.id,`${F}.id`,160);if(!d0(Q))throw TypeError(`${F}.id is invalid`);let X=u(J.version,`${F}.version`);d(X,["minimum","maximumExclusive"],[],`${F}.version`);let Y=g0(X.minimum,`${F}.version.minimum`),Z=g0(X.maximumExclusive,`${F}.version.maximumExclusive`);if(fF(Y,Z)>=0)throw TypeError(`${F}.version must be a non-empty half-open interval`);return Object.freeze({id:Q,inputSchema:O0(J.inputSchema,`${F}.inputSchema`),outputSchema:O0(J.outputSchema,`${F}.outputSchema`),version:Object.freeze({minimum:Y,maximumExclusive:Z})})}function i0(G,F){if(!Array.isArray(G)||G.length>A1)throw TypeError(`${F} must be a bounded array`);let J=G.map((Q,X)=>hF(Q,`${F}[${X}]`)).sort((Q,X)=>Q.id.localeCompare(X.id));if(J.some((Q,X)=>X>0&&J[X-1].id===Q.id))throw TypeError(`${F} contains a duplicate capability id`);return Object.freeze(J)}function yF(G,F){let J=u(G,F);d(J,["id","version","operation","sideEffect","inputSchema","outputSchema","docs"],[],F);let Q=i(J.id,`${F}.id`,160);if(!d0(Q))throw TypeError(`${F}.id is invalid`);let X=i(J.operation,`${F}.operation`,128);if(!wF.test(X))throw TypeError(`${F}.operation is invalid`);if(!qF.has(J.sideEffect))throw TypeError(`${F}.sideEffect is invalid`);let Y=u(J.docs,`${F}.docs`);d(Y,["summary","request","response"],["remarks"],`${F}.docs`);let Z=Object.freeze({summary:i(Y.summary,`${F}.docs.summary`),request:i(Y.request,`${F}.docs.request`),response:i(Y.response,`${F}.docs.response`),...Y.remarks===void 0?{}:{remarks:i(Y.remarks,`${F}.docs.remarks`)}});return Object.freeze({id:Q,version:g0(J.version,`${F}.version`),operation:X,sideEffect:J.sideEffect,inputSchema:O0(J.inputSchema,`${F}.inputSchema`),outputSchema:O0(J.outputSchema,`${F}.outputSchema`),docs:Z})}function cF(G){let F=u(G,"Plugin capability declaration");if(d(F,["exports","imports"],[],"Plugin capability declaration"),!Array.isArray(F.exports)||F.exports.length>A1)throw TypeError("Plugin capability exports must be a bounded array");let J=F.exports.map((M,K)=>yF(M,`Plugin capability exports[${K}]`)).sort((M,K)=>M.id.localeCompare(K.id));if(J.some((M,K)=>K>0&&J[K-1].id===M.id))throw TypeError("Plugin capability exports contain a duplicate capability id");if(new Set(J.map((M)=>M.operation)).size!==J.length)throw TypeError("Plugin capability exports contain a duplicate provider operation");let Q=u(F.imports,"Plugin capability imports");d(Q,["required","optional"],[],"Plugin capability imports");let X=i0(Q.required,"Plugin required capability imports"),Y=i0(Q.optional,"Plugin optional capability imports"),Z=new Set(X.map(({id:M})=>M)),_=Y.find(({id:M})=>Z.has(M));if(_)throw TypeError(`Plugin capability import cannot be both required and optional: ${_.id}`);return Object.freeze({exports:Object.freeze(J),imports:Object.freeze({required:X,optional:Y})})}function f0(G,F,J,Q){if(G.type==="null"){if(F!==null)throw TypeError(`${J} must be null`);return}if(G.type==="boolean"){if(typeof F!=="boolean")throw TypeError(`${J} must be boolean`);return}if(G.type==="number"||G.type==="integer"){if(typeof F!=="number"||!Number.isFinite(F)||G.type==="integer"&&!Number.isSafeInteger(F))throw TypeError(`${J} must be a finite ${G.type==="integer"?"safe integer":"number"}`);if(G.minimum!==void 0&&FG.maximum)throw TypeError(`${J} exceeds maximum`);return}if(G.type==="string"){if(typeof F!=="string"||F.length<(G.minLength??0)||F.length>G.maxLength||G.enum!==void 0&&!G.enum.includes(F))throw TypeError(`${J} is not an admitted string`);return}if(!F||typeof F!=="object")throw TypeError(`${J} must be ${G.type}`);if(Q.has(F))throw TypeError(`${J} cannot be cyclic`);Q.add(F);try{if(G.type==="array"){if(!Array.isArray(F)||F.length<(G.minItems??0)||F.length>G.maxItems)throw TypeError(`${J} is not an admitted array`);F.forEach((Z,_)=>f0(G.items,Z,`${J}[${_}]`,Q));return}if(Array.isArray(F))throw TypeError(`${J} must be an object`);let X=Object.getPrototypeOf(F);if(X!==Object.prototype&&X!==null)throw TypeError(`${J} must be a plain object`);let Y=F;for(let Z of G.required)if(!Object.prototype.hasOwnProperty.call(Y,Z))throw TypeError(`${J}.${Z} is required`);for(let[Z,_]of Object.entries(Y)){let M=G.properties[Z];if(!M)throw TypeError(`${J} contains unsupported property: ${Z}`);f0(M,_,`${J}.${Z}`,Q)}}finally{Q.delete(F)}}function a0(G,F,J="Plugin capability value"){f0(G,F,J,new Set)}var bF=/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[A-Za-z-][0-9A-Za-z-]*)(?:\.(?:0|[1-9]\d*|\d*[A-Za-z-][0-9A-Za-z-]*))*))?(?:\+([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?$/,dF=/^(CON|PRN|AUX|NUL|COM[1-9¹²³]|LPT[1-9¹²³]|CONIN\$|CONOUT\$)$/i;function A(G,F){if(!G||typeof G!=="object"||Array.isArray(G))throw TypeError(`${F} must be an object`);let J=Object.getPrototypeOf(G);if(J!==Object.prototype&&J!==null)throw TypeError(`${F} must be a plain object`);return G}function R(G,F,J){let Q=new Set(F),X=Object.keys(G).find((Y)=>!Q.has(Y));if(X)throw TypeError(`${J} contains an unsupported field: ${X}`)}function E(G,F,J){if(typeof G!=="string"||G.length<1||G.length>J||G!==G.trim()||/[\u0000-\u001f\u007f]/u.test(G))throw TypeError(`${F} must be a bounded, trimmed string`);return G}function c(G,F,J,Q=!1){if(!Array.isArray(G)||G.length>J||Q&&G.length===0)throw TypeError(`${F} must be ${Q?"a non-empty ":"a "}bounded array with at most ${J} items`);return G}function R1(G){if(G&&typeof G==="object"&&!Object.isFrozen(G)){for(let F of Object.values(G))R1(F);Object.freeze(G)}return G}function vF(G){let F=E(G,"Plugin version",128);if(!bF.test(F))throw TypeError("Plugin version must be valid SemVer");return F}function R0(G){let F=G.split(".")[0]??"";if(!G||G.length>255||G==="."||G===".."||/[\\/:*?"<>|\u0000-\u001f\u007f]/u.test(G)||/[. ]$/u.test(G)||dF.test(F))throw TypeError(`Plugin path contains an invalid Windows filename: ${G}`);return G}function E1(G){let F=E(G,"Plugin id",80);if(!/^[a-z0-9]+(?:-[a-z0-9]+)*$/u.test(F))throw TypeError("Plugin id must use kebab-case");return R0(F),F}function X0(G,F="Plugin path"){let J=E(G,F,1024);if(J.includes("\\")||J.startsWith("/")||/^[A-Za-z]:/u.test(J)||J.startsWith("//"))throw TypeError(`${F} must be a portable relative path`);let Q=J.split("/");if(Q.some((X)=>!X||X==="."||X===".."))throw TypeError(`${F} must be a portable relative path`);return Q.forEach(R0),J}function T0(G,F,J){if(G===void 0)return;let Q=c(G,F,64).map((X)=>J(E(X,F,128)));if(new Set(Q).size!==Q.length)throw TypeError(`${F} contains duplicate values`);return Q}function Y0(G,F,J=80){let Q=E(G,F,J);if(!/^[a-z0-9]+(?:[._-][a-z0-9]+)*$/u.test(Q))throw TypeError(`${F} is invalid: ${Q}`);return Q}var l="convax.plugin-host/8",mF=KF,pF=MF,B0=1048576,l0=4194304,e0=16,sF=128,oF=64,V0=Math.ceil(mF/2),rF=/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/,uF=new Set(["not-declared","provider-missing","provider-incompatible","provider-ambiguous","self-provider","dependency-cycle","setup-required","disabled","recovering","contract-mismatch"]),T1=Object.freeze({canceled:{recoverable:!0},"contract-mismatch":{recoverable:!1},"depth-exceeded":{recoverable:!1},"duplicate-request":{recoverable:!1},"execution-failed":{recoverable:!1},"invalid-input":{recoverable:!1},"invalid-output":{recoverable:!1},overloaded:{recoverable:!0},"provider-unavailable":{recoverable:!0},"reentrant-call":{recoverable:!1}}),B1=new Set(Object.keys(T1)),H1=Object.freeze({canceled:{recoverable:!0},"internal-error":{recoverable:!1},"invalid-request":{recoverable:!1},overloaded:{recoverable:!0},"transport-closed":{recoverable:!0}}),w1=new Set(Object.keys(H1)),nF=new Set(U0.apis.flatMap((G)=>G.errors.map(({code:F})=>F)));function e(G){if(!G||typeof G!=="object"||Array.isArray(G))return;let F=Object.getPrototypeOf(G);return F===Object.prototype||F===null?G:void 0}function F1(G){let F=2;for(let J=0;J=55296&&Q<=57343){let X=G.charCodeAt(J+1);if(Q>=55296&&Q<=56319&&X>=56320&&X<=57343)F+=4,J+=1;else F+=6}else if(Q<128)F+=1;else if(Q<2048)F+=2;else F+=3}return F}function G1(G,F,J="Plugin Host message"){if(!Number.isSafeInteger(F)||F<1)throw TypeError(`${J} byte limit is invalid`);let Q=[{depth:0,value:G}],X=new WeakSet,Y=0,Z=0,_=(M)=>{if(Y+=M,Y>F)throw RangeError(`${J} exceeds ${F} bytes`)};while(Q.length>0){let M=Q.pop(),K=M.value;if(K===null){_(4);continue}if(typeof K==="string"){_(F1(K));continue}if(typeof K==="boolean"){_(K?4:5);continue}if(typeof K==="number"){if(!Number.isFinite(K))throw TypeError(`${J} must contain finite JSON numbers`);_(Object.is(K,-0)?1:String(K).length);continue}if(!K||typeof K!=="object")throw TypeError(`${J} must be a JSON value`);if(M.depth>oF||X.has(K))throw TypeError(`${J} must be a bounded acyclic JSON tree`);if(X.add(K),Array.isArray(K)){if(Z+=K.length,Z>V0)throw RangeError(`${J} exceeds ${V0} JSON entries`);if(_(2+Math.max(0,K.length-1)),Object.getOwnPropertySymbols(K).length>0)throw TypeError(`${J} arrays must not contain symbol properties`);let O=0;for(let V in K){if(!Object.prototype.hasOwnProperty.call(K,V))continue;if(!/^(0|[1-9]\d*)$/u.test(V)||Number(V)>=K.length)throw TypeError(`${J} arrays must contain only indexed entries`);let P=Object.getOwnPropertyDescriptor(K,V);if(!P?.enumerable||!("value"in P))throw TypeError(`${J} arrays must contain enumerable data properties`);O+=1,Q.push({depth:M.depth+1,value:P.value})}if(O!==K.length)throw TypeError(`${J} arrays must be dense JSON arrays`);continue}let D=Object.getPrototypeOf(K);if(D!==Object.prototype&&D!==null)throw TypeError(`${J} must contain plain JSON objects`);if(Object.getOwnPropertySymbols(K).length>0)throw TypeError(`${J} must not contain symbol properties`);_(2);let W=0;for(let O in K){if(!Object.prototype.hasOwnProperty.call(K,O))continue;let V=Object.getOwnPropertyDescriptor(K,O);if(!V?.enumerable||!("value"in V))throw TypeError(`${J} objects must contain enumerable data properties`);if(W+=1,Z+=1,Z>V0)throw RangeError(`${J} exceeds ${V0} JSON entries`);_((W===1?0:1)+F1(O)+1),Q.push({depth:M.depth+1,value:V.value})}}return Y}function r(G,F,J=[]){let Q=new Set([...F,...J]);return F.every((X)=>Object.prototype.hasOwnProperty.call(G,X))&&Object.keys(G).every((X)=>Q.has(X))}function C1(G){return typeof G==="string"&&G.length>0&&G.length<=sF&&G===G.trim()&&!/[\u0000-\u001f\u007f]/u.test(G)}function tF(G){return typeof G==="string"&&G.length>0&&G.length<=128&&G===G.trim()&&!/[\u0000-\u001f\u007f]/u.test(G)}function P1(G){let F=e(G);if(!F||!r(F,["pluginId","protocol","type"])||F.protocol!==l||F.type!=="connect")return!1;try{return E1(F.pluginId),!0}catch{return!1}}function iF(G){let F=e(G);if(!F||F.protocol!==l||F.type!=="response"||!C1(F.id))return!1;if(F.ok===!0)return r(F,["id","ok","protocol","result","type"]);if(F.ok!==!1||!r(F,["error","id","ok","protocol","type"]))return!1;let J=e(F.error);return Boolean(J&&r(J,["code","kind","message","recoverable"])&&typeof J.code==="string"&&(J.kind==="api"&&nF.has(J.code)||J.kind==="capability"&&B1.has(J.code)||J.kind==="protocol"&&w1.has(J.code))&&typeof J.message==="string"&&J.message.length>0&&J.message.length<=4096&&typeof J.recoverable==="boolean")}function aF(G){let F=e(G);return Boolean(F&&r(F,["command","protocol","type"],["params"])&&F.protocol===l&&F.type==="command"&&tF(F.command))}function lF(G){let F=e(G);if(!F||typeof F.available!=="boolean")throw TypeError("Plugin capability availability must be a closed object");let J=F.requirement;if(J!=="required"&&J!=="optional")throw TypeError("Plugin capability availability requirement is invalid");if(!d0(F.capabilityId))throw TypeError("Plugin capability availability id is invalid");if(F.available){if(!r(F,["available","capabilityId","requirement","version"])||typeof F.version!=="string"||!rF.test(F.version))throw TypeError("Available Plugin capability result is invalid");return Object.freeze({available:!0,capabilityId:F.capabilityId,requirement:J,version:F.version})}if(!r(F,["available","capabilityId","reason","recoverable","requirement"])||typeof F.reason!=="string"||!uF.has(F.reason)||typeof F.recoverable!=="boolean")throw TypeError("Unavailable Plugin capability result is invalid");return Object.freeze({available:!1,capabilityId:F.capabilityId,reason:F.reason,recoverable:F.recoverable,requirement:J})}function eF(G){let F=e(G);if(!F||!r(F,["code","kind","message","recoverable"])||F.kind!=="capability"||typeof F.code!=="string"||!B1.has(F.code)||typeof F.message!=="string"||F.message.length<1||F.message.length>4096||typeof F.recoverable!=="boolean")throw TypeError("Plugin capability failure is invalid");let J=F.code;if(F.recoverable!==T1[J].recoverable)throw TypeError("Plugin capability failure recoverability is invalid");return Object.freeze({code:J,kind:"capability",message:F.message,recoverable:F.recoverable})}function q1(G){let F=e(G);if(!F||!r(F,["code","kind","message","recoverable"])||F.kind!=="protocol"||typeof F.code!=="string"||!w1.has(F.code)||typeof F.message!=="string"||F.message.length<1||F.message.length>4096||typeof F.recoverable!=="boolean")throw TypeError("Plugin Host protocol failure is invalid");let J=F.code;if(F.recoverable!==H1[J].recoverable)throw TypeError("Plugin Host protocol failure recoverability is invalid");return Object.freeze({code:J,kind:"protocol",message:F.message,recoverable:F.recoverable})}var F2=["download","edit","open","play","refresh","settings","sparkles","upload"],k1=/^[a-z][a-z0-9]*(?:[._-][a-z0-9]+)*$/,G2=/^[a-z][a-z0-9]*(?:[._-][a-z0-9]+)*$/,J2=/^[a-z][a-z0-9]*(?:[._-][a-z0-9]+)*$/,Q2=128,J1=128,Q1=1e4;function X2(G){return Boolean(G)&&typeof G==="object"&&!Array.isArray(G)}function S0(G,F){if(!X2(G))throw TypeError(`${F} must be an object`);let J=Object.getPrototypeOf(G);if(J!==Object.prototype&&J!==null)throw TypeError(`${F} must be a plain object`);return G}function D0(G,F,J,Q){let X=new Set([...F,...J]);if(F.some((Y)=>!Object.prototype.hasOwnProperty.call(G,Y))||Object.keys(G).some((Y)=>!X.has(Y)))throw TypeError(`${Q} contains unsupported or missing fields`)}function z0(G,F,J){if(typeof G!=="string"||G.length<1||G.length>J||G!==G.trim()||/[\u0000-\u001f\u007f]/u.test(G))throw TypeError(`${F} must be a bounded, trimmed string`);return G}function A0(G,F,J,Q){let X=z0(G,F,Q);if(!J.test(X))throw TypeError(`${F} must be a stable Plugin-local id`);return X}function Y2(G,F){if(!Number.isSafeInteger(G)||Number(G)<-Q1||Number(G)>Q1)throw TypeError(`${F} must be a bounded safe integer`);return Number(G)}function Z2(G,F){let J=S0(G,F);return D0(J,["default"],["zh-CN"],F),Object.freeze({default:z0(J.default,`${F}.default`,120),...J["zh-CN"]===void 0?{}:{"zh-CN":z0(J["zh-CN"],`${F}.zh-CN`,120)}})}function _2(G){return F2.some((F)=>F===G)}function $2(G,F){let J=`Plugin UI commands[${F}]`,Q=S0(G,J);D0(Q,["id","title","target"],["icon"],J);let X=S0(Q.target,`${J}.target`);if(X.type!=="renderer-message")throw TypeError(`${J}.target.type must be renderer-message`);D0(X,["type","message"],[],`${J}.target`);let Y=Q.icon;if(Y!==void 0&&!_2(Y))throw TypeError(`${J}.icon must be a supported Host icon token`);return Object.freeze({id:A0(Q.id,`${J}.id`,k1,128),title:Z2(Q.title,`${J}.title`),target:Object.freeze({type:"renderer-message",message:z0(X.message,`${J}.target.message`,128)}),...Y===void 0?{}:{icon:Y}})}function I1(G,F,J,Q){let X=S0(G,F);return D0(X,J,Q,F),{input:X,id:A0(X.id,`${F}.id`,G2,128),command:A0(X.command,`${F}.command`,k1,128),...X.order===void 0?{}:{order:Y2(X.order,`${F}.order`)}}}function K2(G,F){let{input:J,...Q}=I1(G,`Plugin UI toolbar[${F}]`,["id","command"],["order"]);return Object.freeze(Q)}function M2(G,F){let J=`Plugin UI menus[${F}]`,Q=I1(G,J,["id","command","placement"],["group","order"]);if(Q.input.placement!=="overflow")throw TypeError(`${J}.placement must be overflow`);let X=Q.input.group===void 0?void 0:A0(Q.input.group,`${J}.group`,J2,64),{input:Y,...Z}=Q;return Object.freeze({...Z,placement:"overflow",...X===void 0?{}:{group:X}})}function H0(G,F,J){if(!Array.isArray(G)||G.length>J)throw TypeError(`${F} must be a bounded array`);return G}function w0(G,F){let J=new Set;for(let Q of G){if(J.has(Q.id))throw TypeError(`${F} contains a duplicate id: ${Q.id}`);J.add(Q.id)}}function X1(G,F){let J=new Set;for(let Q of G){if(J.has(Q.command))throw TypeError(`${F} contains a duplicate command reference: ${Q.command}`);J.add(Q.command)}}function S2(G){let F=S0(G,"Plugin Canvas UI contribution");D0(F,[],["commands","menus","toolbar"],"Plugin Canvas UI contribution");let J=Object.freeze(H0(F.commands===void 0?[]:F.commands,"Plugin UI commands",Q2).map($2)),Q=Object.freeze(H0(F.menus===void 0?[]:F.menus,"Plugin UI menus",J1).map(M2)),X=Object.freeze(H0(F.toolbar===void 0?[]:F.toolbar,"Plugin UI toolbar",J1).map(K2));w0(J,"Plugin UI commands"),w0(Q,"Plugin UI menus"),w0(X,"Plugin UI toolbar");let Y=new Set(Q.map((W)=>W.id)),Z=X.find((W)=>Y.has(W.id));if(Z)throw TypeError(`Plugin UI placements contain a duplicate id: ${Z.id}`);X1(Q,"Plugin UI menus"),X1(X,"Plugin UI toolbar");let _=new Set(J.map((W)=>W.id)),M=[...Q,...X].find((W)=>!_.has(W.command));if(M)throw TypeError(`Plugin UI placement references an unknown command: ${M.command}`);let K=new Set([...Q,...X].map((W)=>W.command)),D=J.find((W)=>!K.has(W.id));if(D)throw TypeError(`Plugin UI command has no owning-node placement: ${D.id}`);return Object.freeze({commands:J,menus:Q,toolbar:X})}var D2=["time-point","time-range","crop-region","confirmation","immediate"];function U2(G){return D2.some((F)=>F===G)}function W2(G,F){if(G==="image"||G==="video")return G;throw TypeError(`${F} target must be image or video`)}function Y1(G,F){if(!Number.isSafeInteger(G)||Number(G)<1||Number(G)>8192)throw TypeError(`${F} must be an integer between 1 and 8192`);return Number(G)}function j2(G){let F=A(G,"Canvas renderer contribution");if(R(F,["create","extensions","height","mimeTypes","nodeKinds","width"],"Canvas renderer contribution"),F.create!==void 0&&typeof F.create!=="boolean")throw TypeError("Canvas renderer create must be a boolean");let J=T0(F.extensions,"Canvas renderer extensions",(Y)=>{let Z=Y.toLowerCase();if(!/^\.[a-z0-9][a-z0-9._+-]{0,31}$/u.test(Z))throw TypeError(`Invalid Canvas renderer extension: ${Y}`);return Z}),Q=T0(F.mimeTypes,"Canvas renderer MIME types",(Y)=>{let Z=Y.toLowerCase();if(!/^[a-z0-9][a-z0-9!#$&^_.+-]*\/[a-z0-9][a-z0-9!#$&^_.+-]*$/u.test(Z))throw TypeError(`Invalid Canvas renderer MIME type: ${Y}`);return Z}),X=T0(F.nodeKinds,"Canvas renderer node kinds",(Y)=>{if(!/^[a-z][a-z0-9]*(?:[._-][a-z0-9]+)*$/u.test(Y))throw TypeError(`Invalid Canvas renderer node kind: ${Y}`);return Y});if(F.create!==!0&&!J?.length&&!Q?.length&&!X?.length)throw TypeError("Canvas renderer must be creatable or match an extension, MIME type, or node kind");return{...F.create===void 0?{}:{create:F.create},...J===void 0?{}:{extensions:J},...F.height===void 0?{}:{height:Y1(F.height,"Canvas renderer height")},...Q===void 0?{}:{mimeTypes:Q},...X===void 0?{}:{nodeKinds:X},...F.width===void 0?{}:{width:Y1(F.width,"Canvas renderer width")}}}function L0(G,F,J){let Q=A(G,F);return R(Q,["default","zh-CN"],F),{default:E(Q.default,`${F} default`,J),...Q["zh-CN"]===void 0?{}:{"zh-CN":E(Q["zh-CN"],`${F} zh-CN`,J)}}}function V2(G){let F=c(G,"Canvas selection actions",32,!0).map((J,Q)=>{let X=`Canvas selection action ${Q}`,Y=A(J,X);if(Y.action!==void 0){R(Y,["action","description","id","target","title"],X);let D=Y0(Y.id,`${X} id`);if(Y.target!=="video")throw TypeError(`${X} target must be video`);let W=A(Y.action,`${X} action`);if(R(W,["connect","type"],`${X} action`),W.type!=="materialize-own-plugin-node"||W.connect!=="selection-to-created")throw TypeError(`${X} materialization action is not supported`);return{action:{connect:"selection-to-created",type:"materialize-own-plugin-node"},description:L0(Y.description,`${X} description`,2000),id:D,target:"video",title:L0(Y.title,`${X} title`,120)}}R(Y,["description","editor","id","presentation","steps","target","title"],X);let Z=Y0(Y.id,`${X} id`),_=W2(Y.target,X);if(!U2(Y.editor))throw TypeError(`${X} editor is not supported`);let M=Y.editor;if(M==="immediate"!==(_==="image"&&Y.presentation==="cutout-scan")||Y.presentation!==void 0&&Y.presentation!=="cutout-scan")throw TypeError(`${X} immediate editor requires image target and cutout-scan presentation`);let K=c(Y.steps,`${X} steps`,16,!0).map((D,W)=>{let O=`${X} step ${W}`,V=A(D,O);return R(V,["tool"],O),{tool:Y0(V.tool,`${O} tool`)}});if(M!=="confirmation"&&K.length!==1)throw TypeError(`${X} editor requires exactly one step`);return{description:L0(Y.description,`${X} description`,2000),editor:M,id:Z,...Y.presentation===void 0?{}:{presentation:"cutout-scan"},steps:K,target:_,title:L0(Y.title,`${X} title`,120)}});if(new Set(F.map((J)=>J.id)).size!==F.length)throw TypeError("Canvas selection actions contain duplicate ids");return F}function L2(G){let F=A(G,"Canvas contributions");R(F,["commands","menus","renderer","selectionActions","toolbar"],"Canvas contributions");let J=S2({...F.commands===void 0?{}:{commands:F.commands},...F.menus===void 0?{}:{menus:F.menus},...F.toolbar===void 0?{}:{toolbar:F.toolbar}});return{...F.commands===void 0?{}:{commands:J.commands},...F.menus===void 0?{}:{menus:J.menus},...F.renderer===void 0?{}:{renderer:j2(F.renderer)},...F.selectionActions===void 0?{}:{selectionActions:V2(F.selectionActions)},...F.toolbar===void 0?{}:{toolbar:J.toolbar}}}var N2=["text","image","video","audio"],g1=["reference_image","reference_video","first_frame","last_frame","audio","text"],O2=new Set(N2),z2=new Set(g1),A2=/^[a-z][a-z0-9_]{0,63}$/;function R2(G,F){let Q=c(G,F,g1.length).map((X)=>{if(typeof X!=="string"||!z2.has(X))throw TypeError(`${F} contain an unsupported or duplicate role`);return X});if(new Set(Q).size!==Q.length)throw TypeError(`${F} contain an unsupported or duplicate role`);return Q}function E2(G){let F=A(G,"Generation contribution");if(R(F,["models","tools"],"Generation contribution"),!Object.prototype.hasOwnProperty.call(F,"models"))throw TypeError("convax.plugin/8 generation models must be declared explicitly");let J=c(F.tools,"Generation tools",64,!0).map((_,M)=>{let K=`Generation tool ${M}`,D=A(_,K);R(D,["acceptedInputs","delivery","description","id","inputBinding","output","recovery","title"],K);let W=Y0(D.id,`${K} id`);if(typeof D.output!=="string"||!O2.has(D.output))throw TypeError(`${K} output is not supported`);if(D.delivery!==void 0&&D.delivery!=="canvas"&&D.delivery!=="return")throw TypeError(`${K} delivery is not supported`);if(D.delivery==="return"&&D.output!=="text")throw TypeError(`${K} return delivery requires text output`);let O=R2(D.acceptedInputs,`${K} acceptedInputs`);if(D.inputBinding!==void 0&&D.inputBinding!=="direct-incoming")throw TypeError(`${K} input binding is not supported`);if(D.inputBinding==="direct-incoming"&&O.length===0)throw TypeError(`${K} direct-incoming input binding requires accepted inputs`);let V;if(D.recovery!==void 0){let P=A(D.recovery,`${K} recovery`);if(R(P,["mode","schema"],`${K} recovery`),P.schema!=="convax.generation-lro/1"||P.mode!=="long-running-operation")throw TypeError(`${K} recovery contract is not supported`);V={mode:"long-running-operation",schema:"convax.generation-lro/1"}}return{acceptedInputs:O,...D.delivery===void 0?{}:{delivery:D.delivery},description:E(D.description,`${K} description`,2000),id:W,...D.inputBinding===void 0?{}:{inputBinding:D.inputBinding},output:D.output,...V===void 0?{}:{recovery:V},title:E(D.title,`${K} title`,120)}});if(new Set(J.map((_)=>_.id)).size!==J.length)throw TypeError("Generation tools contain duplicate ids");let Q=c(F.models,"Generation models",J.length).map((_,M)=>{let K=`Generation model ${M}`,D=A(_,K);return R(D,["name","tool"],K),{name:E(D.name,`${K} name`,120),tool:Y0(D.tool,`${K} tool`)}});if(new Set(Q.map((_)=>_.tool)).size!==Q.length)throw TypeError("Generation models contain duplicate tool references");let X=new Set(Q.map((_)=>_.tool)),Y=J.find((_)=>_.delivery==="return"&&X.has(_.id));if(Y)throw TypeError(`Generation model cannot reference a return-delivery operation: ${Y.id}`);let Z=J.find((_)=>_.inputBinding!==void 0&&X.has(_.id));if(Z)throw TypeError(`Generation model cannot reference an input-bound operation: ${Z.id}`);return{models:Q,tools:J}}function T2(G){let F=c(G,"Agent tools",32,!0).map((J,Q)=>{let X=`Agent tool ${Q}`,Y=A(J,X);R(Y,["id","tool"],X);let Z=E(Y.id,`${X} id`,64);if(!A2.test(Z))throw TypeError(`${X} id must use lower snake_case`);return{id:Z,tool:Y0(Y.tool,`${X} generation tool`)}});if(new Set(F.map((J)=>J.id)).size!==F.length)throw TypeError("Agent tools contain duplicate ids");if(new Set(F.map((J)=>J.tool)).size!==F.length)throw TypeError("Agent tools contain duplicate generation tool references");return F}function B2(G){let F=A(G,"Agent remote MCP contribution");if(R(F,["headers","oauth","type","url"],"Agent remote MCP contribution"),F.type!=="remote")throw TypeError("Agent MCP type must be remote");let J=E(F.url,"Agent remote MCP URL",2048);try{let X=new URL(J);if(X.protocol!=="https:"||X.username!==""||X.password!==""||X.hash!=="")throw TypeError()}catch{throw TypeError("Agent remote MCP URL must be an absolute HTTPS URL without credentials or a fragment")}if(F.oauth!==void 0&&F.oauth!=="auto"&&F.oauth!=="none")throw TypeError("Agent remote MCP oauth must be auto or none");let Q;if(F.headers!==void 0){let X=A(F.headers,"Agent remote MCP headers"),Y=Object.entries(X);if(Y.length>16)throw TypeError("Agent remote MCP headers must contain at most 16 entries");let Z=new Set;Q={};for(let[_,M]of Y){if(!/^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/u.test(_))throw TypeError(`Agent remote MCP header name is invalid: ${_}`);let K=_.toLowerCase();if(Z.has(K))throw TypeError(`Agent remote MCP headers contain a duplicate name: ${_}`);if(K==="authorization"||K==="cookie"||K==="proxy-authorization")throw TypeError(`Agent remote MCP header is not allowed: ${_}`);let D=E(M,`Agent remote MCP header ${_}`,2048);if(/\{(?:env|file):/iu.test(D)||/\$\{[^}]*\}/u.test(D))throw TypeError(`Agent remote MCP header ${_} must be a literal value`);Z.add(K),Q[_]=D}}return{...Q===void 0?{}:{headers:Q},oauth:F.oauth==="none"?"none":"auto",type:"remote",url:J}}function H2(G){let F=A(G,"Agent contribution");R(F,["mcp","tools"],"Agent contribution");let J=F.tools===void 0?void 0:T2(F.tools),Q=F.mcp===void 0?void 0:B2(F.mcp);if(J===void 0&&Q===void 0)throw TypeError("Agent contribution must declare tools or mcp");return{...Q===void 0?{}:{mcp:Q},...J===void 0?{}:{tools:J}}}function w2(G){let F=new Map(G.generation?.tools.map((Q)=>[Q.id,Q])??[]),J=new Set(G.generation?.models.map((Q)=>Q.tool)??[]);for(let Q of J)if(!F.has(Q))throw TypeError(`Generation model references an unknown tool: ${Q}`);for(let Q of G.agent?.tools??[]){if(!F.has(Q.tool))throw TypeError(`Agent tool references an unknown generation tool: ${Q.tool}`);if(J.has(Q.tool))throw TypeError(`Agent tool must reference an operation, not a generation model: ${Q.tool}`)}for(let Q of G.selectionActions??[]){if(!("steps"in Q))continue;for(let X of Q.steps){let Y=F.get(X.tool);if(!Y)throw TypeError(`Canvas selection action references an unknown generation tool: ${X.tool}`);if(J.has(X.tool))throw TypeError(`Canvas selection action must reference an operation, not a generation model: ${X.tool}`);if(Y.inputBinding!==void 0)throw TypeError(`Canvas selection action cannot reference an input-bound operation: ${X.tool}`);let Z=Q.target==="image"?"reference_image":"reference_video";if(!Y.acceptedInputs.includes(Z))throw TypeError(`Canvas ${Q.target} selection action tool must accept ${Z}: ${X.tool}`);if(Y.delivery==="return"){if(Q.editor!=="confirmation")throw TypeError(`Canvas return-delivery operation requires a confirmation editor: ${X.tool}`);if(Q.steps.length!==1)throw TypeError(`Canvas return-delivery operation requires exactly one step: ${X.tool}`);if(Y.output!=="text")throw TypeError(`Canvas return-delivery operation must return text: ${X.tool}`)}else if(Q.target==="image"&&(Q.editor!=="immediate"||Q.presentation!=="cutout-scan"||Q.steps.length!==1||Y.output!=="image"))throw TypeError(`Canvas image output requires one immediate image operation with cutout-scan presentation: ${X.tool}`)}}}var x1=["authorize","reauthorize","authorization.cancel","checkout","sign_out"],C2=new Set(x1);function P2(G){let F=A(G,"Service contribution");R(F,["actions"],"Service contribution");let J=c(F.actions,"Service actions",x1.length).map((Q)=>{if(typeof Q!=="string"||!C2.has(Q))throw TypeError("Service actions contain an unsupported or duplicate action");return Q});if(new Set(J).size!==J.length)throw TypeError("Service actions contain an unsupported or duplicate action");return{actions:J}}function q2(G){let F=A(G,"LLM contribution");R(F,["modelCatalog","models","provider"],"LLM contribution");let J=A(F.provider,"LLM provider");R(J,["id","name"],"LLM provider");let Q=E(J.id,"LLM provider id",80);if(!/^[a-z0-9]+(?:-[a-z0-9]+)*$/u.test(Q))throw TypeError("LLM provider id must use kebab-case");if(F.modelCatalog!==void 0&&F.modelCatalog!=="runtime")throw TypeError("LLM model catalog must be runtime");let X=c(F.models,"LLM models",32,!0).map((Y,Z)=>{let _=`LLM model ${Z}`,M=A(Y,_);R(M,["id","name"],_);let K=E(M.id,`${_} id`,128);if(!/^~?[a-z0-9]+(?:[._/:-][a-z0-9]+)*$/u.test(K))throw TypeError(`${_} id is invalid`);return{id:K,name:E(M.name,`${_} name`,120)}});if(new Set(X.map((Y)=>Y.id)).size!==X.length)throw TypeError("LLM models contain duplicate ids");return{...F.modelCatalog===void 0?{}:{modelCatalog:"runtime"},models:X,provider:{id:Q,name:E(J.name,"LLM provider name",120)}}}function k2(G){let F=A(G,"Pet contribution");R(F,["library","overlay","protocol","settings"],"Pet contribution");let J=X0(F.library,"Pet library"),Q=X0(F.overlay,"Pet overlay"),X=X0(F.settings,"Pet settings");if(!J.toLowerCase().endsWith(".json"))throw TypeError("Pet library must be a JSON file");if(!Q.toLowerCase().endsWith(".html"))throw TypeError("Pet overlay must be an HTML file");if(!X.toLowerCase().endsWith(".html"))throw TypeError("Pet settings must be an HTML file");if(F.protocol!=="convax.pet-host/1")throw TypeError("Pet protocol must equal convax.pet-host/1");return{library:J,overlay:Q,protocol:"convax.pet-host/1",settings:X}}function I2(G){let F=A(G,"Plugin runtime");if(R(F,["args","command","type"],"Plugin runtime"),F.type!=="mcp-stdio")throw TypeError("Plugin runtime type must be mcp-stdio");let J=E(F.command,"Plugin runtime command",128);if(!/^[A-Za-z0-9][A-Za-z0-9._-]*$/u.test(J))throw TypeError("Plugin runtime command must be a bare executable name");R0(J);let Q;if(F.args!==void 0)Q=c(F.args,"Plugin runtime args",64).map((X,Y)=>{let Z=E(X,`Plugin runtime arg ${Y}`,1024);if(/[\s"'`;|&`$(){}[\]<>]/u.test(Z)||Z.includes("\\")||/(^|=)(?:\/|[A-Za-z]:)/u.test(Z)||/(^|[=/])\.{1,2}(?:\/|$)/u.test(Z))throw TypeError(`Plugin runtime arg ${Y} must be a static CLI token without code, native paths, or traversal`);return Z});return{...Q===void 0?{}:{args:Q},command:J,type:"mcp-stdio"}}var Z1=new Set(U0.apis.filter((G)=>G.audience.includes("agent-skill")).map((G)=>G.id)),g2=/^[a-z][a-z0-9_]{0,63}$/;function x2(G,F){let J=E(G,F,64);if(!/^[a-z0-9]+(?:-[a-z0-9]+)*$/u.test(J))throw TypeError(`${F} must use kebab-case`);return R0(J),J}function f2(G,F,J){let Q=A(G,F);R(Q,["optionalHostApis","pluginTools","requiredHostApis"],F);let X=b0({major:M0,required:Q.requiredHostApis??[],optional:Q.optionalHostApis??[]}),Y=new Set(J.required),Z=new Set([...J.required,...J.optional]);for(let M of X.required){if(!Y.has(M))throw TypeError(`${F} required Host API must be required by the Plugin: ${M}`);if(N0(M)&&!Z1.has(M))throw TypeError(`${F} Host API is not available to Agent Skills: ${M}`)}for(let M of X.optional){if(!Z.has(M))throw TypeError(`${F} optional Host API must be declared by the Plugin: ${M}`);if(N0(M)&&!Z1.has(M))throw TypeError(`${F} Host API is not available to Agent Skills: ${M}`)}let _;if(Q.pluginTools!==void 0){if(_=c(Q.pluginTools,`${F} pluginTools`,32,!0).map((M,K)=>{let D=E(M,`${F} pluginTools ${K}`,64);if(!g2.test(D))throw TypeError(`${F} plugin tool id must use lower snake_case: ${D}`);return D}),new Set(_).size!==_.length)throw TypeError(`${F} pluginTools contain duplicate ids`)}if(X.required.length===0&&X.optional.length===0&&_===void 0)throw TypeError(`${F} must declare at least one Host API or Plugin tool`);return{...X.optional.length===0?{}:{optionalHostApis:[...X.optional]},..._===void 0?{}:{pluginTools:_},...X.required.length===0?{}:{requiredHostApis:[...X.required]}}}function h2(G,F){if(G===void 0)return;let J=c(G,"Plugin Skill contributions",32,!0).map((Q,X)=>{let Y=`Plugin Skill contribution ${X}`,Z=A(Q,Y);R(Z,["name","path","uses"],Y);let _=x2(Z.name,`${Y} name`),M=X0(Z.path,`${Y} path`);if(M.split("/").at(-1)!==_)throw TypeError(`${Y} path must name its Skill directory: ${_}`);let K=Z.uses===void 0?void 0:f2(Z.uses,`${Y} uses`,F);return{name:_,path:M,...K===void 0?{}:{uses:K}}});if(new Set(J.map((Q)=>Q.name)).size!==J.length)throw TypeError("Plugin Skill contributions contain duplicate names");if(new Set(J.map((Q)=>Q.path.toLocaleLowerCase("en-US"))).size!==J.length)throw TypeError("Plugin Skill contributions contain duplicate paths");return J}function y2(G,F){let J=new Set(F?.tools?.map((Q)=>Q.id)??[]);for(let Q of G??[])for(let X of Q.uses?.pluginTools??[])if(!J.has(X))throw TypeError(`Plugin Skill ${Q.name} references an unknown Agent tool: ${X}`)}var _1="convax.plugin/8";var f1=["canvas.connectedImages.read","canvas.connectedInputs.read","canvas.connectedMedia.stream","canvas.node.read","canvas.node.write","canvas.image.write","project.files.read","agent.prompt","generation.execute","ui.fullscreen","projects.read","canvas.catalog.read","canvas.document.read","canvas.document.write","canvas.events.subscribe","pet.activity.read","pet.activity.open","pet.preferences.write","pet.custom.manage"],c2=["projects.read","canvas.catalog.read","canvas.document.read","canvas.document.write","canvas.events.subscribe"],h1=["pet.activity.read","pet.activity.open","pet.preferences.write","pet.custom.manage"],$1=["pet.activity.read","pet.activity.open","pet.preferences.write"],b2=new Set(f1),d2=new Set(h1);function v2(G){let F=c(G??[],"Plugin capabilities",f1.length).map((J)=>{if(typeof J!=="string"||!b2.has(J))throw TypeError("Plugin capabilities contain an unsupported or duplicate capability");return J});if(new Set(F).size!==F.length)throw TypeError("Plugin capabilities contain an unsupported or duplicate capability");return F}function m2(G){let F=G.entry===void 0?void 0:X0(G.entry,"Plugin entry");if(F!==void 0&&!F.toLowerCase().endsWith(".html"))throw TypeError("Plugin entry must be an HTML file");let J=G.hooks===void 0?void 0:X0(G.hooks,"Plugin hooks");if(J!==void 0&&!/\.(?:js|mjs)$/u.test(J))throw TypeError("Plugin hooks must be a JavaScript ESM module");return{entry:F,hooks:J}}function p2(G){let{capabilities:F,canvas:J,entry:Q,hostApi:X}=G;if(Q!==void 0!==(J?.renderer!==void 0))throw TypeError("Plugin entry and Canvas renderer must appear together");if(Q!==void 0&&!X.required.includes("host.context.get"))throw TypeError("convax.plugin/8 Web Plugins must require host.context.get");if((J?.commands!==void 0||J?.menus!==void 0||J?.toolbar!==void 0)&&J.renderer===void 0)throw TypeError("Canvas UI commands require a sandboxed Canvas renderer");if(F.includes("generation.execute")&&J?.renderer===void 0)throw TypeError("generation.execute requires a sandboxed Canvas surface");if(J&&J.renderer===void 0&&!J.selectionActions?.length&&!J.commands?.length&&!J.menus?.length&&!J.toolbar?.length)throw TypeError("Canvas contributions must declare a renderer, selection actions, or UI commands");if(J?.selectionActions?.some((Y)=>("action"in Y)&&Y.action.type==="materialize-own-plugin-node")&&J.renderer===void 0)throw TypeError("materialize-own-plugin-node requires the contributing Plugin renderer")}function s2(G,F,J){if(F===void 0)return;if(G.length<$1.length||G.length>h1.length||$1.some((Q)=>!G.includes(Q))||G.some((Q)=>!d2.has(Q)))throw TypeError("Pet capabilities must include pet.activity.read, pet.activity.open, and pet.preferences.write; pet.custom.manage is optional");if(J!==void 0)throw TypeError("Pet feature cannot declare an executable runtime")}function o2(G,F={}){let J=A(G,"Plugin manifest");if(R(J,["capabilities","contributes","description","entry","hooks","hostApi","id","name","runtime","schema","version"],"Plugin manifest"),J.schema!==_1)throw TypeError("Plugin manifest must use convax.plugin/8");if(!Object.prototype.hasOwnProperty.call(J,"hostApi"))throw TypeError("convax.plugin/8 must declare hostApi explicitly");let Q=F.hostApiMode==="authoring"?RF(J.hostApi):b0(J.hostApi),X=v2(J.capabilities),Y=A(J.contributes,"Plugin contributions");R(Y,["agent","canvas","capabilities","generation","llm","pet","service","skills"],"Plugin contributions");let{entry:Z,hooks:_}=m2(J),M=Y.canvas===void 0?void 0:L2(Y.canvas);p2({capabilities:X,canvas:M,entry:Z,hostApi:Q});let K=Y.agent===void 0?void 0:H2(Y.agent),D=Y.capabilities===void 0?void 0:cF(Y.capabilities),W=Y.generation===void 0?void 0:E2(Y.generation),O=Y.llm===void 0?void 0:q2(Y.llm),V=Y.pet===void 0?void 0:k2(Y.pet),P=Y.service===void 0?void 0:P2(Y.service),G0=h2(Y.skills,Q),v=J.runtime===void 0?void 0:I2(J.runtime),J0=W!==void 0||P!==void 0||O!==void 0||Boolean(D?.exports.length);if(v!==void 0!==J0){if(D?.exports.length&&v===void 0)throw TypeError("Plugin capability exports require a verified mcp-stdio runtime");throw TypeError("convax.plugin/8 runtime and executable contribution must appear together")}if(D?.exports.length&&v===void 0)throw TypeError("Plugin capability exports require a verified mcp-stdio runtime");s2(X,V,v),w2({agent:K,generation:W,selectionActions:M?.selectionActions}),y2(G0,K);let U=new Set(c2),j=X.some((L)=>U.has(L));if(M?.renderer===void 0&&!M?.selectionActions?.length&&!J0&&_===void 0&&!X.includes("generation.execute")&&!j&&V===void 0&&(D?.exports.length??0)===0&&K?.mcp===void 0)throw TypeError("convax.plugin/8 must declare a Plugin capability beyond owned Skills");return R1({capabilities:X,contributes:{...K===void 0?{}:{agent:K},...D===void 0?{}:{capabilities:D},...M===void 0?{}:{canvas:M},...W===void 0?{}:{generation:W},...O===void 0?{}:{llm:O},...V===void 0?{}:{pet:V},...P===void 0?{}:{service:P},...G0===void 0?{}:{skills:G0}},description:E(J.description,"Plugin description",2000),...Z===void 0?{}:{entry:Z},..._===void 0?{}:{hooks:_},hostApi:Q,id:E1(J.id),name:E(J.name,"Plugin name",120),...v===void 0?{}:{runtime:v},schema:_1,version:vF(J.version)})}function r2(G){return o2(G,{hostApiMode:"authoring"})}class f extends Error{code;constructor(G,F){super(F);this.name="PluginHostProtocolError",this.code=G}}class v0 extends Error{code;kind;recoverable;constructor(G){super(G.message);this.name="PluginHostRemoteError",this.code=G.code,this.kind=G.kind,this.recoverable=G.recoverable}}class h0 extends Error{reason;constructor(G){super("Plugin Host request was aborted");this.name="AbortError",this.reason=G}}var K1=0;function u2(){return K1+=1,`sdk-${Date.now().toString(36)}-${K1.toString(36)}`}function n2(G){if(G.length<1||G.length>96||G!==G.trim()||!/^[A-Za-z0-9._-]+$/.test(G))throw TypeError("Plugin Host requestIdPrefix is invalid")}function M1(G,F){let J=G.contributes.capabilities,Q=J?.imports.required.find((Y)=>Y.id===F);if(Q)return{import:Q,requirement:"required"};let X=J?.imports.optional.find((Y)=>Y.id===F);if(X)return{import:X,requirement:"optional"};throw TypeError(`Plugin capability import is not declared: ${F}`)}function t2(G,F){let J=F.kind==="protocol"?q1(F):BF(G,F);return new v0(J)}function S1(G){let F=G.kind==="protocol"?q1(G):eF(G);return new v0(F)}function y1(G){let F=r2(G.manifest);if(F.entry===void 0||!F.hostApi.required.includes("host.context.get"))throw TypeError("Plugin Host Web client requires an entry and required host.context.get negotiation baseline");let J=G.requestIdPrefix??u2();n2(J);let Q=new Map,X=new Set,Y,Z,_=0,M=!1,K=(U)=>{for(let j of Q.values())j.abort?.(),j.reject(U);Q.clear()},D=(U)=>{if(M)return;M=!0,G.port.removeEventListener("message",G0),X.clear(),K(U);try{G.onFatalError?.(U)}catch{}},W=()=>{if(_>=Number.MAX_SAFE_INTEGER){let j=new f("request-id-exhausted","Plugin Host request id space is exhausted");throw D(j),j}_+=1;let U=`${J}-${_.toString(36)}`;if(!C1(U)){let j=new f("request-id-exhausted","Plugin Host request id is invalid");throw D(j),j}return U},O=(U,j)=>{G1(U,j,"Plugin Host request")},V=(U)=>{G.port.postMessage(U)},P=(U,j,L,N)=>{if(M)return Promise.reject(new f("closed","Plugin Host client is closed"));if(N?.aborted)return Promise.reject(new h0(N.reason));if(Q.size>=e0)return Promise.reject(RangeError(`Plugin Host client permits at most ${e0} in-flight requests`));try{O(U,L.maximumRequestBytes)}catch(b){return Promise.reject(b)}let T=U.id;return new Promise((b,h)=>{let Q0=N?()=>{let n=Q.get(T);if(!n)return;Q.delete(T),n.abort?.();let m={id:T,protocol:l,type:"cancel"};try{O(m,B0),V(m)}catch(p){let p0=new f("transport-failed",p instanceof Error?p.message:"Plugin Host cancel failed");h(p0),D(p0);return}h(new h0(N.reason))}:void 0,W0=Q0?()=>{N.removeEventListener("abort",Q0)}:void 0;if(Q.set(T,{abort:W0,maximumResponseBytes:L.maximumResponseBytes,parseFailure:L.parseFailure,parseResult:j,reject:h,resolve:b}),Q0)N.addEventListener("abort",Q0,{once:!0});try{V(U)}catch(n){D(new f("transport-failed",n instanceof Error?n.message:"Plugin Host transport failed"))}})};function G0(U){if(M)return;let j;try{j=G1(U.data,pF,"Plugin Host response")}catch{D(new f("invalid-envelope","Plugin Host sent a non-JSON message"));return}if(aF(U.data)){try{for(let T of X)T(U.data)}catch{D(new f("invalid-envelope","Plugin Host command listener failed"))}return}if(!iF(U.data)){D(new f("invalid-envelope","Plugin Host sent an invalid envelope"));return}let L=U.data,N=Q.get(L.id);if(!N){D(new f("unknown-response",`Plugin Host returned an unknown, duplicate, or late response id: ${L.id}`));return}if(j>N.maximumResponseBytes){D(new f("invalid-envelope",`Plugin Host response exceeds ${N.maximumResponseBytes} bytes for this request`));return}if(!L.ok){try{let T=N.parseFailure(L.error);Q.delete(L.id),N.abort?.(),N.reject(T)}catch(T){D(new f("invalid-result",T instanceof Error?T.message:"Plugin Host returned an invalid failure"))}return}try{let T=N.parseResult(L.result);Q.delete(L.id),N.abort?.(),N.resolve(T)}catch(T){D(new f("invalid-result",T instanceof Error?T.message:"Plugin Host returned an invalid result"))}}G.port.addEventListener("message",G0),G.port.start?.();let v=(U,j)=>{if(!t0(F.hostApi,U))return Promise.reject(TypeError(`Plugin Host API is not declared: ${U}`));let L=jF[U],N=L.params.type==="none"?void 0:j[0],T=L.params.type==="none"?j[0]:j[1],b;try{b=VF(U,N)}catch(m){return Promise.reject(m)}let Q0={id:W(),method:U,...b===void 0?{}:{params:b},protocol:l,type:"request"},W0=SF(U),n=LF;return P(Q0,(m)=>{let p=n(U,m);if(U==="host.context.get")Y=p;return p},{maximumRequestBytes:W0.request.maxBytes,maximumResponseBytes:W0.result.maxBytes,parseFailure:(m)=>{let p=t2(U,m);if(p.kind==="api"&&p.code==="stale-context")Y=void 0;return p}},T?.signal)},J0={get closed(){return M},callHostApi(U,...j){return v(U,j)},async getHostApiAvailability(U,j){if(!t0(F.hostApi,U))throw TypeError(`Plugin Host API is not declared: ${U}`);return(!Y||j?.refresh?await J0.refreshHostApiContext(j):Y).hostApi.availability.find(({id:N})=>N===U)??{available:!1,id:U,reason:"unsupported-host",recoverable:!1}},refreshHostApiContext(U){if(Y=void 0,Z)return Z;let L=v("host.context.get",[U]).finally(()=>{if(Z===L)Z=void 0});return Z=L,Z},async requireHostApi(U,j){let L=await J0.getHostApiAvailability(U,j);if(!L.available)throw new z1(L);return L},getCapabilityAvailability(U,j){let L;try{L=M1(F,U)}catch(b){return Promise.reject(b)}let N=W();return P({capabilityId:U,id:N,protocol:l,type:"capability-availability"},(b)=>{let h=lF(b);if(h.capabilityId!==U||h.requirement!==L.requirement)throw TypeError("Plugin capability availability does not match the declared import");return h},{maximumRequestBytes:B0,maximumResponseBytes:l0,parseFailure:S1},j?.signal)},invokeCapability(U,j,L){let N;try{N=M1(F,U),a0(N.import.inputSchema,j,`Plugin capability ${U} input`)}catch(h){return Promise.reject(h)}let T=W();return P({capabilityId:U,id:T,input:j,protocol:l,type:"capability-invoke"},(h)=>{return a0(N.import.outputSchema,h,`Plugin capability ${U} output`),h},{maximumRequestBytes:B0,maximumResponseBytes:l0,parseFailure:S1},L?.signal)},onCommand(U){if(M)throw new f("closed","Plugin Host client is closed");if(X.size>=64)throw RangeError("Plugin Host command listener limit exceeded");return X.add(U),()=>{X.delete(U)}},close(){D(new f("closed","Plugin Host client was closed"))}};return J0}var m0={schema:"convax.plugin/8",id:"jianying-editor",name:"剪映导入",description:"将直接连接的 Canvas 图片和视频安全导入剪映当前草稿或新草稿。",version:"2.1.2",entry:"index.html",capabilities:[],contributes:{canvas:{renderer:{create:!0,width:600,height:440}}},hostApi:{major:1,required:["canvas.inputs.list","generation.execute","host.context.get"],optional:[]}};var G4="@convax/plugin-sdk/client:createPluginHostClient";function J4(G,F={}){if(G.source!==window.parent||G.ports.length!==1||!P1(G.data)||G.data.pluginId!==m0.id)return null;return y1({manifest:m0,onFatalError:F.onFatalError,port:G.ports[0],requestIdPrefix:F.requestIdPrefix})}export{G4 as pluginSdkClientBundleMarker,J4 as acceptPluginHostConnection}; +var mF=/^[a-z][a-z0-9]*(?:\.[a-z][a-z0-9]*)+$/,dF=/^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/,pF=/^[a-z][A-Za-z0-9]*(?:\.[a-z][A-Za-z0-9]*)+$/,sF=/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/,rF=new Set(["web-plugin","agent-skill","companion","host"]),oF=new Set(["connection","plugin","own-node","project","canvas"]),uF=new Set(["none","read","write","execute","subscribe"]),nF=new Set(["cancelable","commit-preserving"]);function _0(F,G){if(F.trim().length===0)throw TypeError(`${G} must not be empty`)}function R0(F,G){if(!sF.test(F))throw TypeError(`${G} must be a strict semantic version`)}function I0(F,G){let J=F.split(".").map(Number),Q=G.split(".").map(Number);for(let X=0;X<3;X+=1){let Y=J[X]-Q[X];if(Y!==0)return Y}return 0}function LF(F){if(!mF.test(F.id))throw TypeError(`Plugin API id is invalid: ${F.id}`);if(R0(F.contractSince,`${F.id} contractSince`),F.grant!==null&&!pF.test(F.grant))throw TypeError(`Plugin API grant is invalid: ${F.grant}`);if(!oF.has(F.scope))throw TypeError(`Plugin API scope is invalid: ${F.scope}`);if(!uF.has(F.sideEffect))throw TypeError(`Plugin API sideEffect is invalid: ${F.sideEffect}`);if(!nF.has(F.completion))throw TypeError(`Plugin API completion is invalid: ${F.completion}`);let G=F.audience??["web-plugin"];if(G.length===0||new Set(G).size!==G.length||G.some((X)=>!rF.has(X)))throw TypeError(`Plugin API audience is invalid: ${F.id}`);_0(F.docs.summary,`${F.id} docs.summary`),_0(F.docs.description,`${F.id} docs.description`),_0(F.docs.request,`${F.id} docs.request`),_0(F.docs.response,`${F.id} docs.response`);let J=new Set,Q=F.errors.map((X)=>{if(!dF.test(X.code)||J.has(X.code))throw TypeError(`Plugin API error code is invalid or duplicated: ${F.id}/${X.code}`);return J.add(X.code),_0(X.description,`${F.id}/${X.code} description`),Object.freeze({...X})});return Object.freeze({...F,audience:Object.freeze([...G]),errors:Object.freeze(Q),docs:Object.freeze({...F.docs})})}function tF(F){return LF(F)}function t0(F,G){return R0(F,"Plugin API release version"),Object.freeze({version:F,apis:Object.freeze([...G])})}function iF(...F){if(F.length===0)throw TypeError("Plugin API catalog requires at least one release");let G=new Set,J=[],Q=new Set(F.map((Y)=>Y.version)),X;for(let Y of F){if(R0(Y.version,"Plugin API release version"),X&&I0(X,Y.version)>=0)throw TypeError("Plugin API releases must be strictly increasing");X=Y.version;for(let Z of Y.apis){let _=LF(Z);if(G.has(_.id))throw TypeError(`Plugin API id is duplicated: ${_.id}`);if(I0(_.contractSince,Y.version)<0)throw TypeError(`Plugin API ${_.id} contractSince must not precede since`);if(!Q.has(_.contractSince))throw TypeError(`Plugin API ${_.id} contractSince must identify a Catalog release block`);G.add(_.id),J.push(Object.freeze({..._,since:Y.version}))}}if(J.length===0)throw TypeError("Plugin API catalog must contain at least one API");return Object.freeze({version:F[F.length-1].version,apis:Object.freeze(J)})}var Y2=Object.freeze({assertVersion:R0,compareVersions:I0}),aF="convax.plugin-api-wire-schema/3",z=1024,I=z*z,lF=16*I,i0=8192,eF=33554432,$0={type:"none"},m={type:"boolean"},B={finite:!0,type:"number"},r={finite:!0,minimum:0,type:"integer"},T0=(F)=>({finite:!0,maximum:F,minimum:1,type:"integer"}),B0={type:"null"},g=(F)=>({const:F}),$=(F=2048,G={})=>({controlCharacters:!1,maxLength:F,minLength:G.allowEmpty?0:1,...G.prefix?{prefix:G.prefix}:{},...G.refinement?{refinement:G.refinement}:{},type:"string"}),q=(F,G,J=0,Q)=>({items:F,maxItems:G,minItems:J,type:"array",...Q?{uniqueBy:Q}:{}}),S=(F,G,J)=>({additionalProperties:!1,properties:F,...J?{products:J}:{},required:G,type:"object"}),l=(...F)=>({oneOf:F}),g0=(F=I)=>({keyMaxLength:128,maxBytes:F,maxDepth:32,type:"json-object"}),h=(F)=>({controlCharacters:!1,enum:F,maxLength:Math.max(...F.map((G)=>G.length)),minLength:1,type:"string"}),Z0=S({x:B,y:B},["x","y"]),d0=S({height:B,width:B},["height","width"]),i=S({canvasId:$(256),projectId:$(256)},["canvasId","projectId"]),x0=h(["text","image","video","audio"]),NF=h(["text","reference_image","reference_video","first_frame","last_frame","audio"]),x=(F=1000)=>q($(),F),F4=l(S({available:g(!0),catalogVersion:$(64),contractSince:$(64),id:$(128),since:$(64)},["available","catalogVersion","contractSince","id","since"]),S({available:g(!1),contractSince:$(64),id:$(128),reason:h(["unsupported-host","not-declared","permission-denied","wrong-surface","missing-context","setup-required","disabled","recovering"]),recoverable:m,since:$(64)},["available","id","reason","recoverable"])),OF=S({data:g0(),id:$(),parentId:$(),position:Z0,revision:r,style:g0(),type:$(80)},["data","id","position","revision","type"]),G4=S({inputKey:$(),role:NF},["inputKey","role"]),J4=S({ids:x(),kinds:x(),limit:r,relatedToNodeIds:x(),text:$(2000,{allowEmpty:!0})},[]),Q4=S({animated:m,id:$(),source:$(),target:$(),type:$(80)},["source","target"]),X4=S({nodeId:$(),position:Z0,size:d0},["nodeId","position"]),Y4=S({componentGap:B,componentPackingScale:B,crossGap:B,isolatedPlacement:h(["left","preserve"]),mainGap:B,nodeGap:B,nodePackingScale:B,strategy:h(["component-packing","horizontal-directed-cluster","vertical-directed-cluster"])},[]),Z4=l(S({edgeIds:x(),nodeIds:x(),type:g("elements.remove")},["type"]),S({direction:h(["left","center","right","top","middle","bottom"]),nodeIds:x(),type:g("nodes.align")},["direction","nodeIds","type"]),S({connection:Q4,type:g("nodes.connect")},["connection","type"]),S({axis:h(["horizontal","vertical"]),nodeIds:x(),type:g("nodes.distribute")},["axis","nodeIds","type"]),S({label:$(512),nodeIds:x(),type:g("nodes.group")},["nodeIds","type"]),S({gap:B,layout:h(["grid","horizontal","vertical"]),nodeIds:x(),type:g("nodes.layout")},["nodeIds","type"]),S({delta:Z0,nodeIds:x(),type:g("nodes.move")},["delta","nodeIds","type"]),S({type:g("nodes.setGeometry"),updates:q(X4,1000)},["type","updates"]),S({nodeId:$(),type:g("nodes.ungroup")},["nodeId","type"]),S({nodeIds:x(),options:Y4,type:g("canvas.auto-layout")},["type"])),_4=S({durationMs:B,height:B,inputKey:$(),kind:$(80),label:$(512),mediaRevision:$(512),mimeType:$(512),name:$(512),status:h(["error","idle","pending"]),width:B},["inputKey","kind","label"]),$4=S({contentRevision:$(64,{refinement:"lowercase-sha256"}),height:T0(i0),kind:g("image"),mimeType:h(["image/jpeg","image/png","image/webp"]),size:T0(lF),width:T0(i0)},["contentRevision","height","kind","mimeType","size","width"],[{fields:["width","height"],maximum:eF}]),K4=S({acceptedInputs:q(NF,6),description:$(2000),id:$(256),kind:h(["model","operation"]),output:x0,title:$(120)},["acceptedInputs","description","id","kind","output","title"]),zF=S({id:$(),source:$(),target:$()},["id","source","target"]),M4=S({id:$(),kind:$(80),label:$(512),parentId:$(64*z,{allowEmpty:!0}),position:Z0,size:d0,type:$(64*z,{allowEmpty:!0})},["id","kind","label","position","size"]),S4=S({description:$(64*z,{allowEmpty:!0}),durationMs:B,id:$(),kind:$(80),label:$(512),mimeType:$(64*z,{allowEmpty:!0}),name:$(64*z,{allowEmpty:!0}),parentId:$(64*z,{allowEmpty:!0}),position:Z0,resource:S({kind:g("project-file"),path:$(1024)},["kind","path"]),size:d0,status:$(64*z,{allowEmpty:!0}),text:$(64*z,{allowEmpty:!0}),type:$(64*z,{allowEmpty:!0})},["id","kind","label","position","size"]),D4=S({edges:q(zF,1e4),id:$(256),nodes:q(M4,1e4),revision:r,title:$(512)},["edges","id","nodes","revision","title"]),U4=S({description:$(8000,{allowEmpty:!0}),edges:q(zF,1e4),id:$(256),nodes:q(S4,1e4),revision:r,tags:q($(),256),title:$(512)},["edges","id","nodes","revision","title"]),W4=S({id:$(),incomingNodeIds:x(),kind:$(80),label:$(512),outgoingNodeIds:x(),parentId:$(64*z,{allowEmpty:!0}),position:Z0,text:$(64*z,{allowEmpty:!0}),type:$(64*z,{allowEmpty:!0})},["id","incomingNodeIds","kind","label","outgoingNodeIds","position"]),j4=S({canvas:S({id:$(256),name:$(512)},["id"]),hostApi:S({availability:q(F4,256,0,"id"),catalogVersion:$(64)},["availability","catalogVersion"]),node:OF,plugin:S({id:$(128),name:$(512),version:$(128)},["id","name","version"]),project:S({id:$(256),name:$(512)},["id"])},["canvas","hostApi","node","plugin","project"]),H=(F,G,J={})=>({dialect:aF,request:{maxBytes:J.request??64*z,schema:F},result:{maxBytes:J.result??64*z,schema:G}}),F0=Object.freeze({"host.context.get":H($0,j4,{result:I}),"canvas.inputs.list":H($0,S({inputs:q(_4,256)},["inputs"]),{result:I}),"canvas.inputs.image.open":H(S({inputKey:$()},["inputKey"]),S({probe:$4,sessionId:$(128),url:$(2048,{prefix:"convax-connected-media://"})},["probe","sessionId","url"])),"canvas.inputs.image.close":H(S({sessionId:$(128)},["sessionId"]),S({closed:m},["closed"])),"canvas.inputs.open":H(S({inputKey:$()},["inputKey"]),S({probe:S({duration:S({estimated:m,milliseconds:B},["estimated","milliseconds"]),height:B,kind:h(["audio","video"]),mediaRevision:$(128),mimeType:$(256),size:B,width:B},["duration","kind","mediaRevision","mimeType","size"]),sessionId:$(128),url:$(2048,{prefix:"convax-connected-media://"})},["probe","sessionId","url"])),"canvas.inputs.close":H(S({sessionId:$(128)},["sessionId"]),S({closed:m},["closed"])),"canvas.node.get":H($0,OF,{result:I}),"canvas.node.state.replace":H(S({state:g0(256*z)},["state"]),S({updated:g(!0)},["updated"]),{request:256*z+4*z}),"canvas.resource.image.create":H(S({dataUrl:$(24*I,{prefix:"data:image/png;base64,"}),name:$(120,{refinement:"safe-png-file-name"})},["dataUrl","name"]),S({createdNodeId:$(),revision:r},["createdNodeId","revision"]),{request:24*I+4*z}),"project.file.text.read":H(S({path:$(1024,{refinement:"portable-project-relative-path"})},["path"]),S({content:$(I,{allowEmpty:!0}),exists:m,path:$(1024,{refinement:"portable-project-relative-path"})},["content","exists","path"]),{result:I+4*z}),"agent.prompt":H(S({text:$(20000,{refinement:"trimmed"})},["text"]),S({text:$(64*z,{allowEmpty:!0})},["text"])),"generation.tools.list":H(l($0,S({output:x0},[])),S({tools:q(K4,256)},["tools"]),{result:I}),"generation.execute":H(S({output:x0,prompt:$(20000,{refinement:"trimmed"}),references:q(G4,32),resultMode:h(["create-pending-node","return"]),toolId:$(256)},["prompt"]),S({createdNodeIds:q($(),32),outputText:$(64*z,{allowEmpty:!0}),revision:r,toolId:$(256),warnings:q($(),32)},["createdNodeIds","revision","toolId","warnings"]),{result:256*z}),"projects.list":H($0,S({projects:q(S({available:m,id:$(256),name:$(512)},["available","id","name"]),1000)},["projects"]),{result:I}),"canvas.catalog.list":H(S({projectId:$(256)},["projectId"]),S({canvases:q(S({createdAt:B,id:$(256),name:$(512),updatedAt:B},["createdAt","id","name","updatedAt"]),1e4),projectId:$(256)},["canvases","projectId"]),{result:8*I}),"canvas.document.get":H(S({projection:h(["geometry","structure"]),ref:i},["ref"]),l(S({document:D4,projection:g("geometry"),ref:i,storageVersion:l(B0,$(256))},["document","projection","ref","storageVersion"]),S({document:U4,projection:g("structure"),ref:i,storageVersion:l(B0,$(256))},["document","projection","ref","storageVersion"])),{result:8*I}),"canvas.nodes.query":H(S({query:J4,ref:i},["ref"]),S({nodes:q(W4,1000),ref:i,revision:r,storageVersion:l(B0,$(256))},["nodes","ref","revision","storageVersion"]),{request:I,result:8*I}),"canvas.transaction.execute":H(S({commands:q(Z4,256,1),expectedRevision:r,ref:i,transactionId:$(128)},["commands","expectedRevision","ref","transactionId"]),S({affectedNodeIds:x(1e4),changed:m,createdNodeIds:x(1e4),ref:i,revision:r,storageVersion:$(256),summaryTruncated:m,warnings:x()},["affectedNodeIds","changed","createdNodeIds","ref","revision","storageVersion","warnings"]),{request:I,result:2*I}),"canvas.events.subscribe":H(S({ref:S({canvasId:$(256),projectId:$(256)},["projectId"])},["ref"]),S({subscriptionId:$(128)},["subscriptionId"])),"canvas.events.unsubscribe":H(S({subscriptionId:$(128)},["subscriptionId"]),S({removed:m},["removed"]))}),V4=Math.max(...Object.values(F0).map(({request:F})=>F.maxBytes)),L4=Math.max(...Object.values(F0).map(({result:F})=>F.maxBytes));function N4(F){return F0[F]}function f0(F,G){if(!F||typeof F!=="object"||Array.isArray(F))throw TypeError(`${G} must be an object`);let J=Object.getPrototypeOf(F);if(J!==Object.prototype&&J!==null)throw TypeError(`${G} must be a plain object`);return F}var O4=/^(CON|PRN|AUX|NUL|COM[1-9¹²³]|LPT[1-9¹²³]|CONIN\$|CONOUT\$)$/iu;function AF(F){for(let G of F){let J=G.codePointAt(0);if(J>=55296&&J<=57343)return!1}return!0}function a0(F){let G=F.split(".",1)[0]??"";return Boolean(F&&F!=="."&&F!==".."&&AF(F)&&!/[\\/:*?"<>|\u0000-\u001f\u007f]/u.test(F)&&!/[. ]$/u.test(F)&&!O4.test(G))}function z4(F,G){if(G===void 0)return!0;if(G==="lowercase-sha256")return/^[a-f0-9]{64}$/u.test(F);if(G==="trimmed")return F===F.trim();if(G==="safe-png-file-name")return F===F.trim()&&F.toLowerCase().endsWith(".png")&&a0(F);if(G==="portable-project-relative-path"){if(F!==F.trim()||F.includes("\\")||F.startsWith("/")||F.startsWith("//")||/^[A-Za-z]:/u.test(F)||!AF(F))return!1;let J=F.split("/");return J[0]?.toLowerCase()!==".convax"&&J.length>0&&J.every((Q)=>a0(Q))}return!1}function A4(F,G,J){let Q=new Set,X=(_,M,K)=>{if(_===null||typeof _==="string"||typeof _==="boolean")return _;if(typeof _==="number"){if(!Number.isFinite(_))throw TypeError(`${M} must contain finite JSON numbers`);return _}if(!_||typeof _!=="object"||K>=G.maxDepth||Q.has(_))throw TypeError(`${M} must be bounded acyclic JSON`);let D=Object.getPrototypeOf(_);if(!Array.isArray(_)&&D!==Object.prototype&&D!==null)throw TypeError(`${M} must contain plain JSON objects`);Q.add(_);let j;if(Array.isArray(_))j=_.map((O,L)=>X(O,`${M}[${L}]`,K+1));else{let O=Object.create(null);for(let[L,k]of Object.entries(_)){if(L.length<1||L.length>G.keyMaxLength||/[\u0000-\u001f\u007f]/u.test(L))throw TypeError(`${M} key is invalid`);O[L]=X(k,`${M}.${L}`,K+1)}j=O}return Q.delete(_),j},Y=X(f0(F,J),J,0);if(Array.isArray(Y)||!Y||typeof Y!=="object")throw TypeError(`${J} must be an object`);let Z=JSON.stringify(Y);if(new TextEncoder().encode(Z).byteLength>G.maxBytes)throw TypeError(`${J} exceeds ${G.maxBytes} bytes`);return Y}function R4(F,G,J){for(let Q of G??[]){let X=1;for(let Y of Q.fields){let Z=F[Y];if(typeof Z!=="number"||!Number.isFinite(Z)||Z<0)throw TypeError(`${J}.${Y} must be a non-negative finite product factor`);if(Z!==0&&X>Q.maximum/Z)throw TypeError(`${J} must satisfy its numeric product limits`);X*=Z}if(X>Q.maximum)throw TypeError(`${J} must satisfy its numeric product limits`)}return F}function K0(F,G,J="Plugin API value"){if("oneOf"in F){let Z=[];for(let _ of F.oneOf)try{Z.push(K0(_,G,J))}catch{}if(Z.length!==1)throw TypeError(`${J} must match exactly one schema variant`);return Z[0]}if("const"in F){if(G!==F.const)throw TypeError(`${J} must equal ${String(F.const)}`);return G}if("type"in F&&F.type==="none"){if(G!==void 0)throw TypeError(`${J} does not accept a value`);return}if("type"in F&&F.type==="null"){if(G!==null)throw TypeError(`${J} must be null`);return null}if("type"in F&&F.type==="boolean"){if(typeof G!=="boolean")throw TypeError(`${J} must be boolean`);return G}if("type"in F&&(F.type==="number"||F.type==="integer")){if(typeof G!=="number"||!Number.isFinite(G)||F.type==="integer"&&!Number.isSafeInteger(G)||F.minimum!==void 0&&GF.maximum)throw TypeError(`${J} must be a valid ${F.type}`);return G}if("type"in F&&F.type==="string"){if(typeof G!=="string"||G.lengthF.maxLength||F.controlCharacters===!1&&/[\u0000-\u001f\u007f]/u.test(G)||F.enum!==void 0&&!F.enum.includes(G)||F.prefix!==void 0&&!G.startsWith(F.prefix)||!z4(G,F.refinement))throw TypeError(`${J} must satisfy its bounded string contract`);return G}if("type"in F&&F.type==="array"){if(!Array.isArray(G)||G.lengthF.maxItems)throw TypeError(`${J} must satisfy its bounded array contract`);let Z=G.map((_,M)=>K0(F.items,_,`${J}[${M}]`));if(F.uniqueBy!==void 0){let _=Z.map((M)=>{let D=f0(M,`${J} unique item`)[F.uniqueBy];if(typeof D!=="string"&&typeof D!=="number")throw TypeError(`${J} unique identity is invalid`);return`${typeof D}:${String(D)}`});if(new Set(_).size!==_.length)throw TypeError(`${J} contains duplicate ${F.uniqueBy}`)}return Z}if("type"in F&&F.type==="json-object")return A4(G,F,J);if(!("properties"in F))throw TypeError(`${J} has an unsupported schema`);let Q=f0(G,J),X=new Set(Object.keys(F.properties));if(F.required.some((Z)=>!Object.prototype.hasOwnProperty.call(Q,Z))||Object.keys(Q).some((Z)=>!X.has(Z)))throw TypeError(`${J} contains unsupported or missing fields`);let Y=Object.fromEntries(Object.entries(Q).map(([Z,_])=>[Z,K0(F.properties[Z],_,`${J}.${Z}`)]));return R4(Y,F.products,J)}function h0(F,G){if("oneOf"in F){let J=F.oneOf.map((Z)=>h0(Z,G)),Q=J.filter((Z)=>Z.type==="object");if(Q.length===0&&J.some((Z)=>Z.type==="none"))return{type:"none"};if(Q.length===0)throw TypeError(`${G} is not an object schema`);let X=new Set(Q.flatMap(({required:Z,optional:_})=>[...Z,..._])),Y=[...X].filter((Z)=>Q.every((_)=>_.required.includes(Z))).sort();return{additionalProperties:!1,optional:[...X].filter((Z)=>!Y.includes(Z)).sort(),required:Y,type:"object"}}if("type"in F&&F.type==="none")return{type:"none"};if(!("properties"in F))throw TypeError(`${G} is not an object schema`);return{additionalProperties:!1,optional:Object.keys(F.properties).filter((J)=>!F.required.includes(J)).sort(),required:[...F.required].sort(),type:"object"}}var y0=Object.freeze(Object.keys(F0).sort()),E4=Object.freeze(Object.fromEntries(y0.map((F)=>{let G=F0[F],J=h0(G.result.schema,`Plugin API ${F} result`);if(J.type!=="object")throw TypeError(`Plugin API ${F} result must be an object`);return[F,{dialect:G.dialect,params:h0(G.request.schema,`Plugin API ${F} params`),request:G.request,response:G.result,result:J}]})));function T4(F,G){return K0(F0[F].request.schema,G,`Plugin API ${F} params`)}function B4(F,G){return K0(F0[F].result.schema,G,`Plugin API ${F} result`)}var P=[{code:"stale-context",description:"The bound Project, Canvas, node, or connection changed before the call completed.",recoverable:!0}],C=[{code:"permission-denied",description:"The installed Plugin principal does not currently hold the required grant.",recoverable:!1}],H0=[{code:"resource-unavailable",description:"The authoritative Project resource is missing, changed, or cannot be read safely.",recoverable:!0}],l0=[{code:"partial-success",description:"A user-visible Project file was published, but the requested Canvas commit did not complete; retry is unsafe.",recoverable:!1}],w=(F)=>tF({...F,contractSince:"2.0.0"}),U0=iF(t0("1.0.0",[w({id:"host.context.get",completion:"cancelable",grant:null,scope:"connection",sideEffect:"read",errors:P,docs:{summary:"Read the bounded context attached to the current Plugin connection.",description:"Returns only renderer-safe identifiers and feature metadata for the exact live connection; it grants no additional authority.",request:"No parameters.",response:"The current Plugin, Project, Canvas, node, and negotiated Host API context when present."}}),w({id:"canvas.inputs.list",completion:"cancelable",grant:"canvas.connectedInputs.read",scope:"own-node",sideEffect:"read",errors:[...P,...C],docs:{summary:"List direct incoming inputs of the owning Plugin node.",description:"Derives pathless input metadata from authoritative direct incoming Canvas edges and never reads resource bytes.",request:"No parameters; the owning node comes from the bound connection.",response:"A bounded list of direct incoming input descriptors and opaque input keys."}}),w({id:"canvas.inputs.open",completion:"cancelable",grant:"canvas.connectedMedia.stream",scope:"own-node",sideEffect:"read",errors:[...P,...C,...H0],docs:{summary:"Open a bounded stream for one previously listed direct input.",description:"Opens host-owned access to the exact authoritative input after topology and resource identity are revalidated.",request:"`{ inputKey }`, using an opaque key returned by canvas.inputs.list.",response:"A connection-bound stream descriptor and safe media metadata.",remarks:"Call canvas.inputs.close when the stream is no longer needed."}}),w({id:"canvas.inputs.close",completion:"cancelable",grant:"canvas.connectedMedia.stream",scope:"own-node",sideEffect:"write",errors:[...P,...C],docs:{summary:"Close one connection-bound input stream.",description:"Releases a stream created by canvas.inputs.open without changing Canvas or Project state.",request:"The stream handle returned by canvas.inputs.open.",response:"An acknowledgement; closing an already closed handle is idempotent."}}),w({id:"canvas.node.get",completion:"cancelable",grant:"canvas.node.read",scope:"own-node",sideEffect:"read",errors:[...P,...C],docs:{summary:"Read the owning Plugin node projection.",description:"Returns a bounded renderer-safe projection of the exact node bound to the connection.",request:"No parameters; the owning node comes from the bound connection.",response:"The owning node identity, revision, geometry, and Plugin state projection."}}),w({id:"canvas.node.state.replace",completion:"commit-preserving",grant:"canvas.node.write",scope:"own-node",sideEffect:"write",errors:[...P,...C],docs:{summary:"Replace the owning node's bounded Plugin state.",description:"Commits only the namespaced Plugin state through the authoritative Canvas application service with revision checks.",request:"`{ state }`, where state is a bounded JSON value.",response:"`{ updated: true }` after the authoritative state replacement commits."}}),w({id:"canvas.resource.image.create",completion:"commit-preserving",grant:"canvas.image.write",scope:"own-node",sideEffect:"write",errors:[...P,...C,...l0],docs:{summary:"Create a Project-backed Canvas image through the host lifecycle.",description:"Admits bounded image content as a user-visible Project resource and commits its Canvas reference without exposing native paths.",request:"`{ dataUrl, name }`, containing a bounded validated image data URL and safe file name.",response:"The created renderer-safe image result after Project publication and Canvas commit."}}),w({id:"project.file.text.read",completion:"cancelable",grant:"project.files.read",scope:"project",sideEffect:"read",errors:[...P,...C],docs:{summary:"Read one bounded UTF-8 Project file.",description:"Reads through the scoped Project Files capability using a normalized Project-relative path and never exposes a native path.",request:"`{ path }`, using a normalized Project-relative portable path.",response:"The bounded UTF-8 file text."}}),w({id:"agent.prompt",completion:"commit-preserving",grant:"agent.prompt",scope:"connection",sideEffect:"execute",errors:[...P,...C],docs:{summary:"Submit a bounded prompt through the host Agent capability.",description:"Uses the current host-owned Agent context; it does not grant direct OpenCode, filesystem, model, or credential access.",request:"`{ text }`, containing the bounded prompt text.",response:"`{ text }`, containing the bounded host acknowledgement."}}),w({id:"generation.tools.list",completion:"cancelable",grant:"generation.execute",scope:"plugin",sideEffect:"read",errors:C,docs:{summary:"List generation tools available to the installed Plugin principal.",description:"Returns normalized tool metadata derived from active verified contributions without exposing executable paths or credentials.",request:"Optional `{ output }` modality filter; omitting params lists every admitted modality.",response:"A bounded list of available generation tools and their public input contracts."}}),w({id:"generation.execute",completion:"commit-preserving",grant:"generation.execute",scope:"plugin",sideEffect:"execute",errors:[...P,...C,...H0,...l0],docs:{summary:"Execute one selected generation tool through the shared host executor.",description:"Revalidates the active Plugin, authorized executable, inputs, cancellation, and live resource guards immediately before execution.",request:"`{ output?, prompt, references?: Array<{ inputKey, role }>, resultMode?, toolId? }`; every opaque input key must come from the current owning node's canvas.inputs.list result.",response:"The bounded selected tool result, created node ids, authoritative revision, and warnings."}}),w({id:"projects.list",completion:"cancelable",audience:["web-plugin","companion"],grant:"projects.read",scope:"plugin",sideEffect:"read",errors:C,docs:{summary:"List Projects visible to the installed Plugin principal.",description:"Returns portable Project identities and display metadata without native paths or private Project state.",request:"No parameters.",response:"A bounded list of renderer-safe Project summaries."}}),w({id:"canvas.catalog.list",completion:"cancelable",audience:["web-plugin","companion"],grant:"canvas.catalog.read",scope:"project",sideEffect:"read",errors:[...P,...C],docs:{summary:"List Canvas catalog entries for one authorized Project.",description:"Reads the Project-owned Canvas catalog without selecting a Project or Canvas in the Workbench.",request:"`{ projectId }`, naming one explicit portable Project.",response:"A bounded list of portable Canvas catalog entries."}}),w({id:"canvas.document.get",completion:"cancelable",audience:["web-plugin","companion"],grant:"canvas.document.read",scope:"canvas",sideEffect:"read",errors:[...P,...C],docs:{summary:"Read one authorized Canvas document projection.",description:"Returns a bounded portable structure or geometry projection from Main's authoritative Canvas application service.",request:"`{ ref, projection }`, using an explicit portable Project/Canvas reference and supported projection.",response:"The requested pathless document projection and authoritative revision."}}),w({id:"canvas.nodes.query",completion:"cancelable",audience:["web-plugin","companion"],grant:"canvas.document.read",scope:"canvas",sideEffect:"read",errors:[...P,...C],docs:{summary:"Query bounded node projections in one authorized Canvas.",description:"Executes a host-defined bounded query without exposing native paths or resource bytes.",request:"`{ ref, query }`, using an explicit portable Project/Canvas reference and bounded query.",response:"Matching node projections and the authoritative Canvas revision."}}),w({id:"canvas.transaction.execute",completion:"commit-preserving",audience:["web-plugin","companion"],grant:"canvas.document.write",scope:"canvas",sideEffect:"write",errors:[...P,...C],docs:{summary:"Commit one non-empty revision-bound Canvas transaction.",description:"Validates bounded commands against one authoritative revision and persists the accepted transaction atomically.",request:"`{ ref, expectedRevision, commands, transactionId }` with a bounded non-empty command list.",response:"The committed authoritative revision and bounded command results."}}),w({id:"canvas.events.subscribe",completion:"cancelable",audience:["web-plugin","companion"],grant:"canvas.events.subscribe",scope:"canvas",sideEffect:"subscribe",errors:[...P,...C],docs:{summary:"Subscribe to bounded events for one authorized Canvas.",description:"Creates a connection-scoped subscription; events are revisioned invalidations or safe projections, never native data.",request:"`{ ref }`, using an explicit portable Project/Canvas reference.",response:"A connection-bound subscription identifier."}}),w({id:"canvas.events.unsubscribe",completion:"cancelable",audience:["web-plugin","companion"],grant:"canvas.events.subscribe",scope:"canvas",sideEffect:"subscribe",errors:[...P,...C],docs:{summary:"Close one connection-bound Canvas event subscription.",description:"Releases a subscription created by canvas.events.subscribe without changing Canvas state.",request:"The subscription identifier returned by canvas.events.subscribe.",response:"An acknowledgement; closing an already closed subscription is idempotent."}})]),t0("2.0.0",[w({id:"canvas.inputs.image.open",completion:"cancelable",grant:"canvas.connectedImages.read",scope:"own-node",sideEffect:"read",errors:[...P,...C,...H0],docs:{summary:"Open one directly connected image through the owning Plugin node.",description:"Issues a revocable Host-owned session for signature-validated JPEG, PNG, or WebP content after validating the Plugin principal, owning node, direct edge, resource identity, and image limits. Every protocol read revalidates the issued principal and direct edge against current Host state.",request:"`{ inputKey }`, using an opaque image key returned by canvas.inputs.list.",response:"A connection-issued, revocable session with an opaque 128-bit bearer URL, bounded image probe, and lowercase SHA-256 content revision.",remarks:"Electron protocol GET/HEAD requests have no trusted sender or frame principal. Possession of the convax-connected-media URL therefore carries bearer authority until the Host revokes the session or its principal/edge revalidation fails; the URL must be kept secret and closed promptly. The response contains no image bytes, native path, or unrestricted URL. The Host rejects images above 16 MiB, dimensions above 8192 pixels, or more than 33,554,432 pixels."}}),w({id:"canvas.inputs.image.close",completion:"cancelable",grant:"canvas.connectedImages.read",scope:"own-node",sideEffect:"write",errors:[...P,...C],docs:{summary:"Close one revocable connected-image bearer session.",description:"Revokes a session and bearer URL created by canvas.inputs.image.open after validating the calling Plugin principal, without changing Canvas or Project state.",request:"`{ sessionId }`, using the opaque handle returned by canvas.inputs.image.open.",response:"An acknowledgement that the caller's image session is closed; repeated close calls are idempotent."}})])),e0=U0.apis.map(({id:F})=>F).sort();if(e0.length!==y0.length||e0.some((F,G)=>F!==y0[G]))throw TypeError("Plugin API Catalog and portable method contracts are incomplete or inconsistent");var H4=U0.version,M0=Number(H4.split(".")[0]),RF=new Map(U0.apis.map((F)=>[F.id,F])),w4=new Set(RF.keys());function N0(F){return typeof F==="string"&&w4.has(F)}function p0(F){return RF.get(F)}var C4=/^[a-z][a-z0-9]*(?:\.[a-z][a-z0-9]*)+$/;function P4(F){return typeof F==="object"&&F!==null&&!Array.isArray(F)}function FF(F,G){if(!Array.isArray(F))throw TypeError(`${G} must be an array`);let J=[],Q=new Set;for(let X of F){if(typeof X!=="string"||!C4.test(X))throw TypeError(`${G} contains an invalid Plugin API id: ${String(X)}`);if(Q.has(X))throw TypeError(`${G} contains a duplicate Plugin API id: ${X}`);Q.add(X),J.push(X)}return J}function q4(F){let G=s0(F),J=[],Q=[];for(let X of G.required){if(!N0(X))throw TypeError(`Plugin API declaration contains an unknown Plugin API id: ${X}`);J.push(X)}for(let X of G.optional){if(!N0(X))throw TypeError(`Plugin API declaration contains an unknown Plugin API id: ${X}`);Q.push(X)}return Object.freeze({major:M0,required:Object.freeze(J),optional:Object.freeze(Q)})}function s0(F){if(!P4(F))throw TypeError("Plugin API declaration must be an object");if(Object.keys(F).some((Z)=>Z!=="major"&&Z!=="required"&&Z!=="optional"))throw TypeError("Plugin API declaration contains an unknown field");if(F.major!==M0)throw TypeError(`Plugin API declaration major must be ${M0}`);let J=FF(F.required,"Plugin API declaration required"),Q=FF(F.optional,"Plugin API declaration optional"),X=new Set(J),Y=Q.find((Z)=>X.has(Z));if(Y)throw TypeError(`Plugin API cannot be both required and optional: ${Y}`);return Object.freeze({major:M0,required:Object.freeze(J),optional:Object.freeze(Q)})}function k4(F,G){if(F.required.includes(G))return"required";if(F.optional.includes(G))return"optional";return}function GF(F,G){return k4(F,G)!==void 0}class EF extends Error{availability;constructor(F){super(`Plugin API ${F.id} is unavailable: ${F.reason}`);this.name="PluginApiUnavailableError",this.availability=F}}function I4(F,G){return typeof G==="string"&&p0(F).errors.some((J)=>J.code===G)}function g4(F,G){if(!G||typeof G!=="object"||Array.isArray(G))throw TypeError(`Plugin API ${F} failure must be an object`);let J=G;if(Object.keys(J).some((X)=>!["code","kind","message","recoverable"].includes(X))||!Object.prototype.hasOwnProperty.call(J,"code")||!Object.prototype.hasOwnProperty.call(J,"message")||!Object.prototype.hasOwnProperty.call(J,"recoverable")||J.kind!=="api"||!I4(F,J.code)||typeof J.message!=="string"||J.message.length<1||J.message.length>4096||typeof J.recoverable!=="boolean")throw TypeError(`Plugin API ${F} failure is invalid`);let Q=p0(F).errors.find(({code:X})=>X===J.code);if(J.recoverable!==Q.recoverable)throw TypeError(`Plugin API ${F} failure recoverability does not match the Catalog`);return Object.freeze({code:J.code,kind:"api",message:J.message,recoverable:J.recoverable})}var x4=/^[a-z][a-z0-9]*(?:\.[a-z][a-z0-9-]*)+$/,f4=/^[a-z][a-z0-9]*(?:[._-][a-z0-9]+)*$/,h4=/^[A-Za-z][A-Za-z0-9_-]{0,63}$/,y4=/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/,c4=new Set(["none","read","write","execute","subscribe"]),TF=128,b4=64,v4=8,m4=16384,d4=256;function r0(F){return typeof F==="string"&&F.length<=160&&x4.test(F)}function n(F,G){if(!F||typeof F!=="object"||Array.isArray(F))throw TypeError(`${G} must be an object`);let J=Object.getPrototypeOf(F);if(J!==Object.prototype&&J!==null)throw TypeError(`${G} must be a plain object`);return F}function v(F,G,J,Q){let X=new Set([...G,...J]);if(G.some((Y)=>!Object.prototype.hasOwnProperty.call(F,Y))||Object.keys(F).some((Y)=>!X.has(Y)))throw TypeError(`${Q} contains unsupported or missing fields`)}function a(F,G,J=2000){if(typeof F!=="string"||F.length<1||F.length>J||F!==F.trim()||/[\u0000-\u001f\u007f]/u.test(F))throw TypeError(`${G} must be a bounded, trimmed string`);return F}function j0(F,G,J){if(!Number.isSafeInteger(F)||Number(F)<0||Number(F)>J)throw TypeError(`${G} must be a bounded non-negative integer`);return Number(F)}function c0(F,G){if(typeof F!=="string"||!y4.test(F))throw TypeError(`${G} must be a strict semantic version`);return F}function p4(F,G){let J=F.split(".").map(Number),Q=G.split(".").map(Number);for(let X=0;X<3;X+=1){let Y=J[X]-Q[X];if(Y!==0)return Y}return 0}function b0(F,G,J){if(J>v4)throw TypeError(`${G} exceeds the schema depth limit`);let Q=n(F,G);if(Q.type==="null"||Q.type==="boolean")return v(Q,["type"],[],G),Object.freeze({type:Q.type});if(Q.type==="number"||Q.type==="integer"){v(Q,["type"],["minimum","maximum"],G);let{minimum:X,maximum:Y}=Q;if(X!==void 0&&(typeof X!=="number"||!Number.isFinite(X)))throw TypeError(`${G}.minimum must be finite`);if(Y!==void 0&&(typeof Y!=="number"||!Number.isFinite(Y)))throw TypeError(`${G}.maximum must be finite`);if(X!==void 0&&Y!==void 0&&X>Y)throw TypeError(`${G} minimum exceeds maximum`);return Object.freeze({type:Q.type,...X===void 0?{}:{minimum:X},...Y===void 0?{}:{maximum:Y}})}if(Q.type==="string"){if(!Object.prototype.hasOwnProperty.call(Q,"maxLength"))throw TypeError(`${G}.maxLength is required to keep values bounded`);v(Q,["type","maxLength"],["minLength","enum"],G);let X=j0(Q.maxLength,`${G}.maxLength`,m4),Y=Q.minLength===void 0?void 0:j0(Q.minLength,`${G}.minLength`,X),Z;if(Q.enum!==void 0){if(!Array.isArray(Q.enum)||Q.enum.length<1||Q.enum.length>128||Q.enum.some((_)=>typeof _!=="string"||_.length>X)||new Set(Q.enum).size!==Q.enum.length)throw TypeError(`${G}.enum must contain unique bounded strings`);Z=Object.freeze([...Q.enum])}return Object.freeze({type:"string",maxLength:X,...Y===void 0?{}:{minLength:Y},...Z===void 0?{}:{enum:Z}})}if(Q.type==="array"){v(Q,["type","items","maxItems"],["minItems"],G);let X=j0(Q.maxItems,`${G}.maxItems`,d4),Y=Q.minItems===void 0?void 0:j0(Q.minItems,`${G}.minItems`,X);return Object.freeze({type:"array",items:b0(Q.items,`${G}.items`,J+1),maxItems:X,...Y===void 0?{}:{minItems:Y}})}if(Q.type==="object"){if(v(Q,["type","properties","required","additionalProperties"],[],G),Q.additionalProperties!==!1)throw TypeError(`${G}.additionalProperties must be false`);let X=n(Q.properties,`${G}.properties`),Y=Object.keys(X);if(Y.length>b4)throw TypeError(`${G} has too many properties`);if(Y.some((_)=>!h4.test(_)))throw TypeError(`${G} contains an invalid property name`);if(!Array.isArray(Q.required)||Q.required.some((_)=>typeof _!=="string"||!Y.includes(_))||new Set(Q.required).size!==Q.required.length)throw TypeError(`${G}.required must contain unique declared properties`);let Z=Object.fromEntries(Y.sort().map((_)=>[_,b0(X[_],`${G}.properties.${_}`,J+1)]));return Object.freeze({type:"object",properties:Object.freeze(Z),required:Object.freeze([...Q.required].sort()),additionalProperties:!1})}throw TypeError(`${G}.type is unsupported`)}function O0(F,G){let J=b0(F,G,0);if(J.type!=="object")throw TypeError(`${G} must be a closed object schema`);return J}function s4(F,G){let J=n(F,G);v(J,["id","inputSchema","outputSchema","version"],[],G);let Q=a(J.id,`${G}.id`,160);if(!r0(Q))throw TypeError(`${G}.id is invalid`);let X=n(J.version,`${G}.version`);v(X,["minimum","maximumExclusive"],[],`${G}.version`);let Y=c0(X.minimum,`${G}.version.minimum`),Z=c0(X.maximumExclusive,`${G}.version.maximumExclusive`);if(p4(Y,Z)>=0)throw TypeError(`${G}.version must be a non-empty half-open interval`);return Object.freeze({id:Q,inputSchema:O0(J.inputSchema,`${G}.inputSchema`),outputSchema:O0(J.outputSchema,`${G}.outputSchema`),version:Object.freeze({minimum:Y,maximumExclusive:Z})})}function JF(F,G){if(!Array.isArray(F)||F.length>TF)throw TypeError(`${G} must be a bounded array`);let J=F.map((Q,X)=>s4(Q,`${G}[${X}]`)).sort((Q,X)=>Q.id.localeCompare(X.id));if(J.some((Q,X)=>X>0&&J[X-1].id===Q.id))throw TypeError(`${G} contains a duplicate capability id`);return Object.freeze(J)}function r4(F,G){let J=n(F,G);v(J,["id","version","operation","sideEffect","inputSchema","outputSchema","docs"],[],G);let Q=a(J.id,`${G}.id`,160);if(!r0(Q))throw TypeError(`${G}.id is invalid`);let X=a(J.operation,`${G}.operation`,128);if(!f4.test(X))throw TypeError(`${G}.operation is invalid`);if(!c4.has(J.sideEffect))throw TypeError(`${G}.sideEffect is invalid`);let Y=n(J.docs,`${G}.docs`);v(Y,["summary","request","response"],["remarks"],`${G}.docs`);let Z=Object.freeze({summary:a(Y.summary,`${G}.docs.summary`),request:a(Y.request,`${G}.docs.request`),response:a(Y.response,`${G}.docs.response`),...Y.remarks===void 0?{}:{remarks:a(Y.remarks,`${G}.docs.remarks`)}});return Object.freeze({id:Q,version:c0(J.version,`${G}.version`),operation:X,sideEffect:J.sideEffect,inputSchema:O0(J.inputSchema,`${G}.inputSchema`),outputSchema:O0(J.outputSchema,`${G}.outputSchema`),docs:Z})}function o4(F){let G=n(F,"Plugin capability declaration");if(v(G,["exports","imports"],[],"Plugin capability declaration"),!Array.isArray(G.exports)||G.exports.length>TF)throw TypeError("Plugin capability exports must be a bounded array");let J=G.exports.map((M,K)=>r4(M,`Plugin capability exports[${K}]`)).sort((M,K)=>M.id.localeCompare(K.id));if(J.some((M,K)=>K>0&&J[K-1].id===M.id))throw TypeError("Plugin capability exports contain a duplicate capability id");if(new Set(J.map((M)=>M.operation)).size!==J.length)throw TypeError("Plugin capability exports contain a duplicate provider operation");let Q=n(G.imports,"Plugin capability imports");v(Q,["required","optional"],[],"Plugin capability imports");let X=JF(Q.required,"Plugin required capability imports"),Y=JF(Q.optional,"Plugin optional capability imports"),Z=new Set(X.map(({id:M})=>M)),_=Y.find(({id:M})=>Z.has(M));if(_)throw TypeError(`Plugin capability import cannot be both required and optional: ${_.id}`);return Object.freeze({exports:Object.freeze(J),imports:Object.freeze({required:X,optional:Y})})}function v0(F,G,J,Q){if(F.type==="null"){if(G!==null)throw TypeError(`${J} must be null`);return}if(F.type==="boolean"){if(typeof G!=="boolean")throw TypeError(`${J} must be boolean`);return}if(F.type==="number"||F.type==="integer"){if(typeof G!=="number"||!Number.isFinite(G)||F.type==="integer"&&!Number.isSafeInteger(G))throw TypeError(`${J} must be a finite ${F.type==="integer"?"safe integer":"number"}`);if(F.minimum!==void 0&&GF.maximum)throw TypeError(`${J} exceeds maximum`);return}if(F.type==="string"){if(typeof G!=="string"||G.length<(F.minLength??0)||G.length>F.maxLength||F.enum!==void 0&&!F.enum.includes(G))throw TypeError(`${J} is not an admitted string`);return}if(!G||typeof G!=="object")throw TypeError(`${J} must be ${F.type}`);if(Q.has(G))throw TypeError(`${J} cannot be cyclic`);Q.add(G);try{if(F.type==="array"){if(!Array.isArray(G)||G.length<(F.minItems??0)||G.length>F.maxItems)throw TypeError(`${J} is not an admitted array`);G.forEach((Z,_)=>v0(F.items,Z,`${J}[${_}]`,Q));return}if(Array.isArray(G))throw TypeError(`${J} must be an object`);let X=Object.getPrototypeOf(G);if(X!==Object.prototype&&X!==null)throw TypeError(`${J} must be a plain object`);let Y=G;for(let Z of F.required)if(!Object.prototype.hasOwnProperty.call(Y,Z))throw TypeError(`${J}.${Z} is required`);for(let[Z,_]of Object.entries(Y)){let M=F.properties[Z];if(!M)throw TypeError(`${J} contains unsupported property: ${Z}`);v0(M,_,`${J}.${Z}`,Q)}}finally{Q.delete(G)}}function QF(F,G,J="Plugin capability value"){v0(F,G,J,new Set)}var u4=/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[A-Za-z-][0-9A-Za-z-]*)(?:\.(?:0|[1-9]\d*|\d*[A-Za-z-][0-9A-Za-z-]*))*))?(?:\+([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?$/,n4=/^(CON|PRN|AUX|NUL|COM[1-9¹²³]|LPT[1-9¹²³]|CONIN\$|CONOUT\$)$/i;function A(F,G){if(!F||typeof F!=="object"||Array.isArray(F))throw TypeError(`${G} must be an object`);let J=Object.getPrototypeOf(F);if(J!==Object.prototype&&J!==null)throw TypeError(`${G} must be a plain object`);return F}function R(F,G,J){let Q=new Set(G),X=Object.keys(F).find((Y)=>!Q.has(Y));if(X)throw TypeError(`${J} contains an unsupported field: ${X}`)}function T(F,G,J){if(typeof F!=="string"||F.length<1||F.length>J||F!==F.trim()||/[\u0000-\u001f\u007f]/u.test(F))throw TypeError(`${G} must be a bounded, trimmed string`);return F}function c(F,G,J,Q=!1){if(!Array.isArray(F)||F.length>J||Q&&F.length===0)throw TypeError(`${G} must be ${Q?"a non-empty ":"a "}bounded array with at most ${J} items`);return F}function BF(F){if(F&&typeof F==="object"&&!Object.isFrozen(F)){for(let G of Object.values(F))BF(G);Object.freeze(F)}return F}function t4(F){let G=T(F,"Plugin version",128);if(!u4.test(G))throw TypeError("Plugin version must be valid SemVer");return G}function E0(F){let G=F.split(".")[0]??"";if(!F||F.length>255||F==="."||F===".."||/[\\/:*?"<>|\u0000-\u001f\u007f]/u.test(F)||/[. ]$/u.test(F)||n4.test(G))throw TypeError(`Plugin path contains an invalid Windows filename: ${F}`);return F}function HF(F){let G=T(F,"Plugin id",80);if(!/^[a-z0-9]+(?:-[a-z0-9]+)*$/u.test(G))throw TypeError("Plugin id must use kebab-case");return E0(G),G}function X0(F,G="Plugin path"){let J=T(F,G,1024);if(J.includes("\\")||J.startsWith("/")||/^[A-Za-z]:/u.test(J)||J.startsWith("//"))throw TypeError(`${G} must be a portable relative path`);let Q=J.split("/");if(Q.some((X)=>!X||X==="."||X===".."))throw TypeError(`${G} must be a portable relative path`);return Q.forEach(E0),J}function w0(F,G,J){if(F===void 0)return;let Q=c(F,G,64).map((X)=>J(T(X,G,128)));if(new Set(Q).size!==Q.length)throw TypeError(`${G} contains duplicate values`);return Q}function Y0(F,G,J=80){let Q=T(F,G,J);if(!/^[a-z0-9]+(?:[._-][a-z0-9]+)*$/u.test(Q))throw TypeError(`${G} is invalid: ${Q}`);return Q}var u="convax.plugin-host/8",i4=V4,a4=L4,C0=1048576,XF=4194304,l4=128,YF=16,e4=128,F1=64,V0=Math.ceil(i4/2),G1=/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/,J1=new Set(["not-declared","provider-missing","provider-incompatible","provider-ambiguous","self-provider","dependency-cycle","setup-required","disabled","recovering","contract-mismatch"]),wF=Object.freeze({canceled:{recoverable:!0},"contract-mismatch":{recoverable:!1},"depth-exceeded":{recoverable:!1},"duplicate-request":{recoverable:!1},"execution-failed":{recoverable:!1},"invalid-input":{recoverable:!1},"invalid-output":{recoverable:!1},overloaded:{recoverable:!0},"provider-unavailable":{recoverable:!0},"reentrant-call":{recoverable:!1}}),CF=new Set(Object.keys(wF)),PF=Object.freeze({canceled:{recoverable:!0},"internal-error":{recoverable:!1},"invalid-request":{recoverable:!1},overloaded:{recoverable:!0},"transport-closed":{recoverable:!0}}),qF=new Set(Object.keys(PF)),Q1=new Set(U0.apis.flatMap((F)=>F.errors.map(({code:G})=>G)));function e(F){if(!F||typeof F!=="object"||Array.isArray(F))return;let G=Object.getPrototypeOf(F);return G===Object.prototype||G===null?F:void 0}function ZF(F){let G=2;for(let J=0;J=55296&&Q<=57343){let X=F.charCodeAt(J+1);if(Q>=55296&&Q<=56319&&X>=56320&&X<=57343)G+=4,J+=1;else G+=6}else if(Q<128)G+=1;else if(Q<2048)G+=2;else G+=3}return G}function P0(F,G,J="Plugin Host message"){if(!Number.isSafeInteger(G)||G<1)throw TypeError(`${J} byte limit is invalid`);let Q=[{depth:0,value:F}],X=new WeakSet,Y=0,Z=0,_=(M)=>{if(Y+=M,Y>G)throw RangeError(`${J} exceeds ${G} bytes`)};while(Q.length>0){let M=Q.pop(),K=M.value;if(K===null){_(4);continue}if(typeof K==="string"){_(ZF(K));continue}if(typeof K==="boolean"){_(K?4:5);continue}if(typeof K==="number"){if(!Number.isFinite(K))throw TypeError(`${J} must contain finite JSON numbers`);_(Object.is(K,-0)?1:String(K).length);continue}if(!K||typeof K!=="object")throw TypeError(`${J} must be a JSON value`);if(M.depth>F1||X.has(K))throw TypeError(`${J} must be a bounded acyclic JSON tree`);if(X.add(K),Array.isArray(K)){if(Z+=K.length,Z>V0)throw RangeError(`${J} exceeds ${V0} JSON entries`);if(_(2+Math.max(0,K.length-1)),Object.getOwnPropertySymbols(K).length>0)throw TypeError(`${J} arrays must not contain symbol properties`);let O=0;for(let L in K){if(!Object.prototype.hasOwnProperty.call(K,L))continue;if(!/^(0|[1-9]\d*)$/u.test(L)||Number(L)>=K.length)throw TypeError(`${J} arrays must contain only indexed entries`);let k=Object.getOwnPropertyDescriptor(K,L);if(!k?.enumerable||!("value"in k))throw TypeError(`${J} arrays must contain enumerable data properties`);O+=1,Q.push({depth:M.depth+1,value:k.value})}if(O!==K.length)throw TypeError(`${J} arrays must be dense JSON arrays`);continue}let D=Object.getPrototypeOf(K);if(D!==Object.prototype&&D!==null)throw TypeError(`${J} must contain plain JSON objects`);if(Object.getOwnPropertySymbols(K).length>0)throw TypeError(`${J} must not contain symbol properties`);_(2);let j=0;for(let O in K){if(!Object.prototype.hasOwnProperty.call(K,O))continue;let L=Object.getOwnPropertyDescriptor(K,O);if(!L?.enumerable||!("value"in L))throw TypeError(`${J} objects must contain enumerable data properties`);if(j+=1,Z+=1,Z>V0)throw RangeError(`${J} exceeds ${V0} JSON entries`);_((j===1?0:1)+ZF(O)+1),Q.push({depth:M.depth+1,value:L.value})}}return Y}function o(F,G,J=[]){let Q=new Set([...G,...J]);return G.every((X)=>Object.prototype.hasOwnProperty.call(F,X))&&Object.keys(F).every((X)=>Q.has(X))}function kF(F){return typeof F==="string"&&F.length>0&&F.length<=e4&&F===F.trim()&&!/[\u0000-\u001f\u007f]/u.test(F)}function X1(F){return typeof F==="string"&&F.length>0&&F.length<=128&&F===F.trim()&&!/[\u0000-\u001f\u007f]/u.test(F)}function IF(F){let G=e(F);if(!G||!o(G,["pluginId","protocol","type"])||G.protocol!==u||G.type!=="connect")return!1;try{return HF(G.pluginId),!0}catch{return!1}}function Y1(F){let G=e(F);if(!G||G.protocol!==u||G.type!=="response"||!kF(G.id))return!1;if(G.ok===!0)return o(G,["id","ok","protocol","result","type"]);if(G.ok!==!1||!o(G,["error","id","ok","protocol","type"]))return!1;let J=e(G.error);return Boolean(J&&o(J,["code","kind","message","recoverable"])&&typeof J.code==="string"&&(J.kind==="api"&&Q1.has(J.code)||J.kind==="capability"&&CF.has(J.code)||J.kind==="protocol"&&qF.has(J.code))&&typeof J.message==="string"&&J.message.length>0&&J.message.length<=4096&&typeof J.recoverable==="boolean")}function Z1(F){let G=e(F);return Boolean(G&&o(G,["command","protocol","type"],["params"])&&G.protocol===u&&G.type==="command"&&X1(G.command))}function _1(F){let G=e(F);if(!G||typeof G.available!=="boolean")throw TypeError("Plugin capability availability must be a closed object");let J=G.requirement;if(J!=="required"&&J!=="optional")throw TypeError("Plugin capability availability requirement is invalid");if(!r0(G.capabilityId))throw TypeError("Plugin capability availability id is invalid");if(G.available){if(!o(G,["available","capabilityId","requirement","version"])||typeof G.version!=="string"||!G1.test(G.version))throw TypeError("Available Plugin capability result is invalid");return Object.freeze({available:!0,capabilityId:G.capabilityId,requirement:J,version:G.version})}if(!o(G,["available","capabilityId","reason","recoverable","requirement"])||typeof G.reason!=="string"||!J1.has(G.reason)||typeof G.recoverable!=="boolean")throw TypeError("Unavailable Plugin capability result is invalid");return Object.freeze({available:!1,capabilityId:G.capabilityId,reason:G.reason,recoverable:G.recoverable,requirement:J})}function $1(F){let G=e(F);if(!G||!o(G,["code","kind","message","recoverable"])||G.kind!=="capability"||typeof G.code!=="string"||!CF.has(G.code)||typeof G.message!=="string"||G.message.length<1||G.message.length>4096||typeof G.recoverable!=="boolean")throw TypeError("Plugin capability failure is invalid");let J=G.code;if(G.recoverable!==wF[J].recoverable)throw TypeError("Plugin capability failure recoverability is invalid");return Object.freeze({code:J,kind:"capability",message:G.message,recoverable:G.recoverable})}function gF(F){let G=e(F);if(!G||!o(G,["code","kind","message","recoverable"])||G.kind!=="protocol"||typeof G.code!=="string"||!qF.has(G.code)||typeof G.message!=="string"||G.message.length<1||G.message.length>4096||typeof G.recoverable!=="boolean")throw TypeError("Plugin Host protocol failure is invalid");let J=G.code;if(G.recoverable!==PF[J].recoverable)throw TypeError("Plugin Host protocol failure recoverability is invalid");return Object.freeze({code:J,kind:"protocol",message:G.message,recoverable:G.recoverable})}var K1=["download","edit","open","play","refresh","settings","sparkles","upload"],xF=/^[a-z][a-z0-9]*(?:[._-][a-z0-9]+)*$/,M1=/^[a-z][a-z0-9]*(?:[._-][a-z0-9]+)*$/,S1=/^[a-z][a-z0-9]*(?:[._-][a-z0-9]+)*$/,D1=128,_F=128,$F=1e4;function U1(F){return Boolean(F)&&typeof F==="object"&&!Array.isArray(F)}function S0(F,G){if(!U1(F))throw TypeError(`${G} must be an object`);let J=Object.getPrototypeOf(F);if(J!==Object.prototype&&J!==null)throw TypeError(`${G} must be a plain object`);return F}function D0(F,G,J,Q){let X=new Set([...G,...J]);if(G.some((Y)=>!Object.prototype.hasOwnProperty.call(F,Y))||Object.keys(F).some((Y)=>!X.has(Y)))throw TypeError(`${Q} contains unsupported or missing fields`)}function z0(F,G,J){if(typeof F!=="string"||F.length<1||F.length>J||F!==F.trim()||/[\u0000-\u001f\u007f]/u.test(F))throw TypeError(`${G} must be a bounded, trimmed string`);return F}function A0(F,G,J,Q){let X=z0(F,G,Q);if(!J.test(X))throw TypeError(`${G} must be a stable Plugin-local id`);return X}function W1(F,G){if(!Number.isSafeInteger(F)||Number(F)<-$F||Number(F)>$F)throw TypeError(`${G} must be a bounded safe integer`);return Number(F)}function j1(F,G){let J=S0(F,G);return D0(J,["default"],["zh-CN"],G),Object.freeze({default:z0(J.default,`${G}.default`,120),...J["zh-CN"]===void 0?{}:{"zh-CN":z0(J["zh-CN"],`${G}.zh-CN`,120)}})}function V1(F){return K1.some((G)=>G===F)}function L1(F,G){let J=`Plugin UI commands[${G}]`,Q=S0(F,J);D0(Q,["id","title","target"],["icon"],J);let X=S0(Q.target,`${J}.target`);if(X.type!=="renderer-message")throw TypeError(`${J}.target.type must be renderer-message`);D0(X,["type","message"],[],`${J}.target`);let Y=Q.icon;if(Y!==void 0&&!V1(Y))throw TypeError(`${J}.icon must be a supported Host icon token`);return Object.freeze({id:A0(Q.id,`${J}.id`,xF,128),title:j1(Q.title,`${J}.title`),target:Object.freeze({type:"renderer-message",message:z0(X.message,`${J}.target.message`,128)}),...Y===void 0?{}:{icon:Y}})}function fF(F,G,J,Q){let X=S0(F,G);return D0(X,J,Q,G),{input:X,id:A0(X.id,`${G}.id`,M1,128),command:A0(X.command,`${G}.command`,xF,128),...X.order===void 0?{}:{order:W1(X.order,`${G}.order`)}}}function N1(F,G){let{input:J,...Q}=fF(F,`Plugin UI toolbar[${G}]`,["id","command"],["order"]);return Object.freeze(Q)}function O1(F,G){let J=`Plugin UI menus[${G}]`,Q=fF(F,J,["id","command","placement"],["group","order"]);if(Q.input.placement!=="overflow")throw TypeError(`${J}.placement must be overflow`);let X=Q.input.group===void 0?void 0:A0(Q.input.group,`${J}.group`,S1,64),{input:Y,...Z}=Q;return Object.freeze({...Z,placement:"overflow",...X===void 0?{}:{group:X}})}function q0(F,G,J){if(!Array.isArray(F)||F.length>J)throw TypeError(`${G} must be a bounded array`);return F}function k0(F,G){let J=new Set;for(let Q of F){if(J.has(Q.id))throw TypeError(`${G} contains a duplicate id: ${Q.id}`);J.add(Q.id)}}function KF(F,G){let J=new Set;for(let Q of F){if(J.has(Q.command))throw TypeError(`${G} contains a duplicate command reference: ${Q.command}`);J.add(Q.command)}}function z1(F){let G=S0(F,"Plugin Canvas UI contribution");D0(G,[],["commands","menus","toolbar"],"Plugin Canvas UI contribution");let J=Object.freeze(q0(G.commands===void 0?[]:G.commands,"Plugin UI commands",D1).map(L1)),Q=Object.freeze(q0(G.menus===void 0?[]:G.menus,"Plugin UI menus",_F).map(O1)),X=Object.freeze(q0(G.toolbar===void 0?[]:G.toolbar,"Plugin UI toolbar",_F).map(N1));k0(J,"Plugin UI commands"),k0(Q,"Plugin UI menus"),k0(X,"Plugin UI toolbar");let Y=new Set(Q.map((j)=>j.id)),Z=X.find((j)=>Y.has(j.id));if(Z)throw TypeError(`Plugin UI placements contain a duplicate id: ${Z.id}`);KF(Q,"Plugin UI menus"),KF(X,"Plugin UI toolbar");let _=new Set(J.map((j)=>j.id)),M=[...Q,...X].find((j)=>!_.has(j.command));if(M)throw TypeError(`Plugin UI placement references an unknown command: ${M.command}`);let K=new Set([...Q,...X].map((j)=>j.command)),D=J.find((j)=>!K.has(j.id));if(D)throw TypeError(`Plugin UI command has no owning-node placement: ${D.id}`);return Object.freeze({commands:J,menus:Q,toolbar:X})}var A1=["time-point","time-range","crop-region","confirmation","immediate"];function R1(F){return A1.some((G)=>G===F)}function E1(F,G){if(F==="image"||F==="video")return F;throw TypeError(`${G} target must be image or video`)}function MF(F,G){if(!Number.isSafeInteger(F)||Number(F)<1||Number(F)>8192)throw TypeError(`${G} must be an integer between 1 and 8192`);return Number(F)}function T1(F){let G=A(F,"Canvas renderer contribution");if(R(G,["create","extensions","height","mimeTypes","nodeKinds","width"],"Canvas renderer contribution"),G.create!==void 0&&typeof G.create!=="boolean")throw TypeError("Canvas renderer create must be a boolean");let J=w0(G.extensions,"Canvas renderer extensions",(Y)=>{let Z=Y.toLowerCase();if(!/^\.[a-z0-9][a-z0-9._+-]{0,31}$/u.test(Z))throw TypeError(`Invalid Canvas renderer extension: ${Y}`);return Z}),Q=w0(G.mimeTypes,"Canvas renderer MIME types",(Y)=>{let Z=Y.toLowerCase();if(!/^[a-z0-9][a-z0-9!#$&^_.+-]*\/[a-z0-9][a-z0-9!#$&^_.+-]*$/u.test(Z))throw TypeError(`Invalid Canvas renderer MIME type: ${Y}`);return Z}),X=w0(G.nodeKinds,"Canvas renderer node kinds",(Y)=>{if(!/^[a-z][a-z0-9]*(?:[._-][a-z0-9]+)*$/u.test(Y))throw TypeError(`Invalid Canvas renderer node kind: ${Y}`);return Y});if(G.create!==!0&&!J?.length&&!Q?.length&&!X?.length)throw TypeError("Canvas renderer must be creatable or match an extension, MIME type, or node kind");return{...G.create===void 0?{}:{create:G.create},...J===void 0?{}:{extensions:J},...G.height===void 0?{}:{height:MF(G.height,"Canvas renderer height")},...Q===void 0?{}:{mimeTypes:Q},...X===void 0?{}:{nodeKinds:X},...G.width===void 0?{}:{width:MF(G.width,"Canvas renderer width")}}}function L0(F,G,J){let Q=A(F,G);return R(Q,["default","zh-CN"],G),{default:T(Q.default,`${G} default`,J),...Q["zh-CN"]===void 0?{}:{"zh-CN":T(Q["zh-CN"],`${G} zh-CN`,J)}}}function B1(F){let G=c(F,"Canvas selection actions",32,!0).map((J,Q)=>{let X=`Canvas selection action ${Q}`,Y=A(J,X);if(Y.action!==void 0){R(Y,["action","description","id","target","title"],X);let D=Y0(Y.id,`${X} id`);if(Y.target!=="video")throw TypeError(`${X} target must be video`);let j=A(Y.action,`${X} action`);if(R(j,["connect","type"],`${X} action`),j.type!=="materialize-own-plugin-node"||j.connect!=="selection-to-created")throw TypeError(`${X} materialization action is not supported`);return{action:{connect:"selection-to-created",type:"materialize-own-plugin-node"},description:L0(Y.description,`${X} description`,2000),id:D,target:"video",title:L0(Y.title,`${X} title`,120)}}R(Y,["description","editor","id","presentation","steps","target","title"],X);let Z=Y0(Y.id,`${X} id`),_=E1(Y.target,X);if(!R1(Y.editor))throw TypeError(`${X} editor is not supported`);let M=Y.editor;if(M==="immediate"!==(_==="image"&&Y.presentation==="cutout-scan")||Y.presentation!==void 0&&Y.presentation!=="cutout-scan")throw TypeError(`${X} immediate editor requires image target and cutout-scan presentation`);let K=c(Y.steps,`${X} steps`,16,!0).map((D,j)=>{let O=`${X} step ${j}`,L=A(D,O);return R(L,["tool"],O),{tool:Y0(L.tool,`${O} tool`)}});if(M!=="confirmation"&&K.length!==1)throw TypeError(`${X} editor requires exactly one step`);return{description:L0(Y.description,`${X} description`,2000),editor:M,id:Z,...Y.presentation===void 0?{}:{presentation:"cutout-scan"},steps:K,target:_,title:L0(Y.title,`${X} title`,120)}});if(new Set(G.map((J)=>J.id)).size!==G.length)throw TypeError("Canvas selection actions contain duplicate ids");return G}function H1(F){let G=A(F,"Canvas contributions");R(G,["commands","menus","renderer","selectionActions","toolbar"],"Canvas contributions");let J=z1({...G.commands===void 0?{}:{commands:G.commands},...G.menus===void 0?{}:{menus:G.menus},...G.toolbar===void 0?{}:{toolbar:G.toolbar}});return{...G.commands===void 0?{}:{commands:J.commands},...G.menus===void 0?{}:{menus:J.menus},...G.renderer===void 0?{}:{renderer:T1(G.renderer)},...G.selectionActions===void 0?{}:{selectionActions:B1(G.selectionActions)},...G.toolbar===void 0?{}:{toolbar:J.toolbar}}}var w1=["text","image","video","audio"],hF=["reference_image","reference_video","first_frame","last_frame","audio","text"],C1=new Set(w1),P1=new Set(hF),q1=/^[a-z][a-z0-9_]{0,63}$/;function k1(F,G){let Q=c(F,G,hF.length).map((X)=>{if(typeof X!=="string"||!P1.has(X))throw TypeError(`${G} contain an unsupported or duplicate role`);return X});if(new Set(Q).size!==Q.length)throw TypeError(`${G} contain an unsupported or duplicate role`);return Q}function I1(F){let G=A(F,"Generation contribution");if(R(G,["models","tools"],"Generation contribution"),!Object.prototype.hasOwnProperty.call(G,"models"))throw TypeError("convax.plugin/8 generation models must be declared explicitly");let J=c(G.tools,"Generation tools",64,!0).map((_,M)=>{let K=`Generation tool ${M}`,D=A(_,K);R(D,["acceptedInputs","delivery","description","id","inputBinding","output","recovery","title"],K);let j=Y0(D.id,`${K} id`);if(typeof D.output!=="string"||!C1.has(D.output))throw TypeError(`${K} output is not supported`);if(D.delivery!==void 0&&D.delivery!=="canvas"&&D.delivery!=="return")throw TypeError(`${K} delivery is not supported`);if(D.delivery==="return"&&D.output!=="text")throw TypeError(`${K} return delivery requires text output`);let O=k1(D.acceptedInputs,`${K} acceptedInputs`);if(D.inputBinding!==void 0&&D.inputBinding!=="direct-incoming")throw TypeError(`${K} input binding is not supported`);if(D.inputBinding==="direct-incoming"&&O.length===0)throw TypeError(`${K} direct-incoming input binding requires accepted inputs`);let L;if(D.recovery!==void 0){let k=A(D.recovery,`${K} recovery`);if(R(k,["mode","schema"],`${K} recovery`),k.schema!=="convax.generation-lro/1"||k.mode!=="long-running-operation")throw TypeError(`${K} recovery contract is not supported`);L={mode:"long-running-operation",schema:"convax.generation-lro/1"}}return{acceptedInputs:O,...D.delivery===void 0?{}:{delivery:D.delivery},description:T(D.description,`${K} description`,2000),id:j,...D.inputBinding===void 0?{}:{inputBinding:D.inputBinding},output:D.output,...L===void 0?{}:{recovery:L},title:T(D.title,`${K} title`,120)}});if(new Set(J.map((_)=>_.id)).size!==J.length)throw TypeError("Generation tools contain duplicate ids");let Q=c(G.models,"Generation models",J.length).map((_,M)=>{let K=`Generation model ${M}`,D=A(_,K);return R(D,["name","tool"],K),{name:T(D.name,`${K} name`,120),tool:Y0(D.tool,`${K} tool`)}});if(new Set(Q.map((_)=>_.tool)).size!==Q.length)throw TypeError("Generation models contain duplicate tool references");let X=new Set(Q.map((_)=>_.tool)),Y=J.find((_)=>_.delivery==="return"&&X.has(_.id));if(Y)throw TypeError(`Generation model cannot reference a return-delivery operation: ${Y.id}`);let Z=J.find((_)=>_.inputBinding!==void 0&&X.has(_.id));if(Z)throw TypeError(`Generation model cannot reference an input-bound operation: ${Z.id}`);return{models:Q,tools:J}}function g1(F){let G=c(F,"Agent tools",32,!0).map((J,Q)=>{let X=`Agent tool ${Q}`,Y=A(J,X);R(Y,["id","tool"],X);let Z=T(Y.id,`${X} id`,64);if(!q1.test(Z))throw TypeError(`${X} id must use lower snake_case`);return{id:Z,tool:Y0(Y.tool,`${X} generation tool`)}});if(new Set(G.map((J)=>J.id)).size!==G.length)throw TypeError("Agent tools contain duplicate ids");if(new Set(G.map((J)=>J.tool)).size!==G.length)throw TypeError("Agent tools contain duplicate generation tool references");return G}function x1(F){let G=A(F,"Agent remote MCP contribution");if(R(G,["headers","oauth","type","url"],"Agent remote MCP contribution"),G.type!=="remote")throw TypeError("Agent MCP type must be remote");let J=T(G.url,"Agent remote MCP URL",2048);try{let X=new URL(J);if(X.protocol!=="https:"||X.username!==""||X.password!==""||X.hash!=="")throw TypeError()}catch{throw TypeError("Agent remote MCP URL must be an absolute HTTPS URL without credentials or a fragment")}if(G.oauth!==void 0&&G.oauth!=="auto"&&G.oauth!=="none")throw TypeError("Agent remote MCP oauth must be auto or none");let Q;if(G.headers!==void 0){let X=A(G.headers,"Agent remote MCP headers"),Y=Object.entries(X);if(Y.length>16)throw TypeError("Agent remote MCP headers must contain at most 16 entries");let Z=new Set;Q={};for(let[_,M]of Y){if(!/^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/u.test(_))throw TypeError(`Agent remote MCP header name is invalid: ${_}`);let K=_.toLowerCase();if(Z.has(K))throw TypeError(`Agent remote MCP headers contain a duplicate name: ${_}`);if(K==="authorization"||K==="cookie"||K==="proxy-authorization")throw TypeError(`Agent remote MCP header is not allowed: ${_}`);let D=T(M,`Agent remote MCP header ${_}`,2048);if(/\{(?:env|file):/iu.test(D)||/\$\{[^}]*\}/u.test(D))throw TypeError(`Agent remote MCP header ${_} must be a literal value`);Z.add(K),Q[_]=D}}return{...Q===void 0?{}:{headers:Q},oauth:G.oauth==="none"?"none":"auto",type:"remote",url:J}}function f1(F){let G=A(F,"Agent contribution");R(G,["mcp","tools"],"Agent contribution");let J=G.tools===void 0?void 0:g1(G.tools),Q=G.mcp===void 0?void 0:x1(G.mcp);if(J===void 0&&Q===void 0)throw TypeError("Agent contribution must declare tools or mcp");return{...Q===void 0?{}:{mcp:Q},...J===void 0?{}:{tools:J}}}function h1(F){let G=new Map(F.generation?.tools.map((Q)=>[Q.id,Q])??[]),J=new Set(F.generation?.models.map((Q)=>Q.tool)??[]);for(let Q of J)if(!G.has(Q))throw TypeError(`Generation model references an unknown tool: ${Q}`);for(let Q of F.agent?.tools??[]){if(!G.has(Q.tool))throw TypeError(`Agent tool references an unknown generation tool: ${Q.tool}`);if(J.has(Q.tool))throw TypeError(`Agent tool must reference an operation, not a generation model: ${Q.tool}`)}for(let Q of F.selectionActions??[]){if(!("steps"in Q))continue;for(let X of Q.steps){let Y=G.get(X.tool);if(!Y)throw TypeError(`Canvas selection action references an unknown generation tool: ${X.tool}`);if(J.has(X.tool))throw TypeError(`Canvas selection action must reference an operation, not a generation model: ${X.tool}`);if(Y.inputBinding!==void 0)throw TypeError(`Canvas selection action cannot reference an input-bound operation: ${X.tool}`);let Z=Q.target==="image"?"reference_image":"reference_video";if(!Y.acceptedInputs.includes(Z))throw TypeError(`Canvas ${Q.target} selection action tool must accept ${Z}: ${X.tool}`);if(Y.delivery==="return"){if(Q.editor!=="confirmation")throw TypeError(`Canvas return-delivery operation requires a confirmation editor: ${X.tool}`);if(Q.steps.length!==1)throw TypeError(`Canvas return-delivery operation requires exactly one step: ${X.tool}`);if(Y.output!=="text")throw TypeError(`Canvas return-delivery operation must return text: ${X.tool}`)}else if(Q.target==="image"&&(Q.editor!=="immediate"||Q.presentation!=="cutout-scan"||Q.steps.length!==1||Y.output!=="image"))throw TypeError(`Canvas image output requires one immediate image operation with cutout-scan presentation: ${X.tool}`)}}}var yF=["authorize","reauthorize","authorization.cancel","checkout","sign_out"],y1=new Set(yF);function c1(F){let G=A(F,"Service contribution");R(G,["actions"],"Service contribution");let J=c(G.actions,"Service actions",yF.length).map((Q)=>{if(typeof Q!=="string"||!y1.has(Q))throw TypeError("Service actions contain an unsupported or duplicate action");return Q});if(new Set(J).size!==J.length)throw TypeError("Service actions contain an unsupported or duplicate action");return{actions:J}}function b1(F){let G=A(F,"LLM contribution");R(G,["modelCatalog","models","provider"],"LLM contribution");let J=A(G.provider,"LLM provider");R(J,["id","name"],"LLM provider");let Q=T(J.id,"LLM provider id",80);if(!/^[a-z0-9]+(?:-[a-z0-9]+)*$/u.test(Q))throw TypeError("LLM provider id must use kebab-case");if(G.modelCatalog!==void 0&&G.modelCatalog!=="runtime")throw TypeError("LLM model catalog must be runtime");let X=c(G.models,"LLM models",32,!0).map((Y,Z)=>{let _=`LLM model ${Z}`,M=A(Y,_);R(M,["id","name"],_);let K=T(M.id,`${_} id`,128);if(!/^~?[a-z0-9]+(?:[._/:-][a-z0-9]+)*$/u.test(K))throw TypeError(`${_} id is invalid`);return{id:K,name:T(M.name,`${_} name`,120)}});if(new Set(X.map((Y)=>Y.id)).size!==X.length)throw TypeError("LLM models contain duplicate ids");return{...G.modelCatalog===void 0?{}:{modelCatalog:"runtime"},models:X,provider:{id:Q,name:T(J.name,"LLM provider name",120)}}}function v1(F){let G=A(F,"Pet contribution");R(G,["library","overlay","protocol","settings"],"Pet contribution");let J=X0(G.library,"Pet library"),Q=X0(G.overlay,"Pet overlay"),X=X0(G.settings,"Pet settings");if(!J.toLowerCase().endsWith(".json"))throw TypeError("Pet library must be a JSON file");if(!Q.toLowerCase().endsWith(".html"))throw TypeError("Pet overlay must be an HTML file");if(!X.toLowerCase().endsWith(".html"))throw TypeError("Pet settings must be an HTML file");if(G.protocol!=="convax.pet-host/1")throw TypeError("Pet protocol must equal convax.pet-host/1");return{library:J,overlay:Q,protocol:"convax.pet-host/1",settings:X}}function m1(F){let G=A(F,"Plugin runtime");if(R(G,["args","command","type"],"Plugin runtime"),G.type!=="mcp-stdio")throw TypeError("Plugin runtime type must be mcp-stdio");let J=T(G.command,"Plugin runtime command",128);if(!/^[A-Za-z0-9][A-Za-z0-9._-]*$/u.test(J))throw TypeError("Plugin runtime command must be a bare executable name");E0(J);let Q;if(G.args!==void 0)Q=c(G.args,"Plugin runtime args",64).map((X,Y)=>{let Z=T(X,`Plugin runtime arg ${Y}`,1024);if(/[\s"'`;|&`$(){}[\]<>]/u.test(Z)||Z.includes("\\")||/(^|=)(?:\/|[A-Za-z]:)/u.test(Z)||/(^|[=/])\.{1,2}(?:\/|$)/u.test(Z))throw TypeError(`Plugin runtime arg ${Y} must be a static CLI token without code, native paths, or traversal`);return Z});return{...Q===void 0?{}:{args:Q},command:J,type:"mcp-stdio"}}var SF=new Set(U0.apis.filter((F)=>F.audience.includes("agent-skill")).map((F)=>F.id)),d1=/^[a-z][a-z0-9_]{0,63}$/;function p1(F,G){let J=T(F,G,64);if(!/^[a-z0-9]+(?:-[a-z0-9]+)*$/u.test(J))throw TypeError(`${G} must use kebab-case`);return E0(J),J}function s1(F,G,J){let Q=A(F,G);R(Q,["optionalHostApis","pluginTools","requiredHostApis"],G);let X=s0({major:M0,required:Q.requiredHostApis??[],optional:Q.optionalHostApis??[]}),Y=new Set(J.required),Z=new Set([...J.required,...J.optional]);for(let M of X.required){if(!Y.has(M))throw TypeError(`${G} required Host API must be required by the Plugin: ${M}`);if(N0(M)&&!SF.has(M))throw TypeError(`${G} Host API is not available to Agent Skills: ${M}`)}for(let M of X.optional){if(!Z.has(M))throw TypeError(`${G} optional Host API must be declared by the Plugin: ${M}`);if(N0(M)&&!SF.has(M))throw TypeError(`${G} Host API is not available to Agent Skills: ${M}`)}let _;if(Q.pluginTools!==void 0){if(_=c(Q.pluginTools,`${G} pluginTools`,32,!0).map((M,K)=>{let D=T(M,`${G} pluginTools ${K}`,64);if(!d1.test(D))throw TypeError(`${G} plugin tool id must use lower snake_case: ${D}`);return D}),new Set(_).size!==_.length)throw TypeError(`${G} pluginTools contain duplicate ids`)}if(X.required.length===0&&X.optional.length===0&&_===void 0)throw TypeError(`${G} must declare at least one Host API or Plugin tool`);return{...X.optional.length===0?{}:{optionalHostApis:[...X.optional]},..._===void 0?{}:{pluginTools:_},...X.required.length===0?{}:{requiredHostApis:[...X.required]}}}function r1(F,G){if(F===void 0)return;let J=c(F,"Plugin Skill contributions",32,!0).map((Q,X)=>{let Y=`Plugin Skill contribution ${X}`,Z=A(Q,Y);R(Z,["name","path","uses"],Y);let _=p1(Z.name,`${Y} name`),M=X0(Z.path,`${Y} path`);if(M.split("/").at(-1)!==_)throw TypeError(`${Y} path must name its Skill directory: ${_}`);let K=Z.uses===void 0?void 0:s1(Z.uses,`${Y} uses`,G);return{name:_,path:M,...K===void 0?{}:{uses:K}}});if(new Set(J.map((Q)=>Q.name)).size!==J.length)throw TypeError("Plugin Skill contributions contain duplicate names");if(new Set(J.map((Q)=>Q.path.toLocaleLowerCase("en-US"))).size!==J.length)throw TypeError("Plugin Skill contributions contain duplicate paths");return J}function o1(F,G){let J=new Set(G?.tools?.map((Q)=>Q.id)??[]);for(let Q of F??[])for(let X of Q.uses?.pluginTools??[])if(!J.has(X))throw TypeError(`Plugin Skill ${Q.name} references an unknown Agent tool: ${X}`)}var DF="convax.plugin/8";var cF=["canvas.connectedImages.read","canvas.connectedInputs.read","canvas.connectedMedia.stream","canvas.node.read","canvas.node.write","canvas.image.write","project.files.read","agent.prompt","generation.execute","ui.fullscreen","projects.read","canvas.catalog.read","canvas.document.read","canvas.document.write","canvas.events.subscribe","pet.activity.read","pet.activity.open","pet.preferences.write","pet.custom.manage"],u1=["projects.read","canvas.catalog.read","canvas.document.read","canvas.document.write","canvas.events.subscribe"],bF=["pet.activity.read","pet.activity.open","pet.preferences.write","pet.custom.manage"],UF=["pet.activity.read","pet.activity.open","pet.preferences.write"],n1=new Set(cF),t1=new Set(bF);function i1(F){let G=c(F??[],"Plugin capabilities",cF.length).map((J)=>{if(typeof J!=="string"||!n1.has(J))throw TypeError("Plugin capabilities contain an unsupported or duplicate capability");return J});if(new Set(G).size!==G.length)throw TypeError("Plugin capabilities contain an unsupported or duplicate capability");return G}function a1(F){let G=F.entry===void 0?void 0:X0(F.entry,"Plugin entry");if(G!==void 0&&!G.toLowerCase().endsWith(".html"))throw TypeError("Plugin entry must be an HTML file");let J=F.hooks===void 0?void 0:X0(F.hooks,"Plugin hooks");if(J!==void 0&&!/\.(?:js|mjs)$/u.test(J))throw TypeError("Plugin hooks must be a JavaScript ESM module");return{entry:G,hooks:J}}function l1(F){let{capabilities:G,canvas:J,entry:Q,hostApi:X}=F;if(Q!==void 0!==(J?.renderer!==void 0))throw TypeError("Plugin entry and Canvas renderer must appear together");if(Q!==void 0&&!X.required.includes("host.context.get"))throw TypeError("convax.plugin/8 Web Plugins must require host.context.get");if((J?.commands!==void 0||J?.menus!==void 0||J?.toolbar!==void 0)&&J.renderer===void 0)throw TypeError("Canvas UI commands require a sandboxed Canvas renderer");if(G.includes("generation.execute")&&J?.renderer===void 0)throw TypeError("generation.execute requires a sandboxed Canvas surface");if(J&&J.renderer===void 0&&!J.selectionActions?.length&&!J.commands?.length&&!J.menus?.length&&!J.toolbar?.length)throw TypeError("Canvas contributions must declare a renderer, selection actions, or UI commands");if(J?.selectionActions?.some((Y)=>("action"in Y)&&Y.action.type==="materialize-own-plugin-node")&&J.renderer===void 0)throw TypeError("materialize-own-plugin-node requires the contributing Plugin renderer")}function e1(F,G,J){if(G===void 0)return;if(F.lengthbF.length||UF.some((Q)=>!F.includes(Q))||F.some((Q)=>!t1.has(Q)))throw TypeError("Pet capabilities must include pet.activity.read, pet.activity.open, and pet.preferences.write; pet.custom.manage is optional");if(J!==void 0)throw TypeError("Pet feature cannot declare an executable runtime")}function F2(F,G={}){let J=A(F,"Plugin manifest");if(R(J,["capabilities","contributes","description","entry","hooks","hostApi","id","name","runtime","schema","version"],"Plugin manifest"),J.schema!==DF)throw TypeError("Plugin manifest must use convax.plugin/8");if(!Object.prototype.hasOwnProperty.call(J,"hostApi"))throw TypeError("convax.plugin/8 must declare hostApi explicitly");let Q=G.hostApiMode==="authoring"?q4(J.hostApi):s0(J.hostApi),X=i1(J.capabilities),Y=A(J.contributes,"Plugin contributions");R(Y,["agent","canvas","capabilities","generation","llm","pet","service","skills"],"Plugin contributions");let{entry:Z,hooks:_}=a1(J),M=Y.canvas===void 0?void 0:H1(Y.canvas);l1({capabilities:X,canvas:M,entry:Z,hostApi:Q});let K=Y.agent===void 0?void 0:f1(Y.agent),D=Y.capabilities===void 0?void 0:o4(Y.capabilities),j=Y.generation===void 0?void 0:I1(Y.generation),O=Y.llm===void 0?void 0:b1(Y.llm),L=Y.pet===void 0?void 0:v1(Y.pet),k=Y.service===void 0?void 0:c1(Y.service),G0=r1(Y.skills,Q),d=J.runtime===void 0?void 0:m1(J.runtime),J0=j!==void 0||k!==void 0||O!==void 0||Boolean(D?.exports.length);if(d!==void 0!==J0){if(D?.exports.length&&d===void 0)throw TypeError("Plugin capability exports require a verified mcp-stdio runtime");throw TypeError("convax.plugin/8 runtime and executable contribution must appear together")}if(D?.exports.length&&d===void 0)throw TypeError("Plugin capability exports require a verified mcp-stdio runtime");e1(X,L,d),h1({agent:K,generation:j,selectionActions:M?.selectionActions}),o1(G0,K);let U=new Set(u1),W=X.some((V)=>U.has(V));if(M?.renderer===void 0&&!M?.selectionActions?.length&&!J0&&_===void 0&&!X.includes("generation.execute")&&!W&&L===void 0&&(D?.exports.length??0)===0&&K?.mcp===void 0)throw TypeError("convax.plugin/8 must declare a Plugin capability beyond owned Skills");return BF({capabilities:X,contributes:{...K===void 0?{}:{agent:K},...D===void 0?{}:{capabilities:D},...M===void 0?{}:{canvas:M},...j===void 0?{}:{generation:j},...O===void 0?{}:{llm:O},...L===void 0?{}:{pet:L},...k===void 0?{}:{service:k},...G0===void 0?{}:{skills:G0}},description:T(J.description,"Plugin description",2000),...Z===void 0?{}:{entry:Z},..._===void 0?{}:{hooks:_},hostApi:Q,id:HF(J.id),name:T(J.name,"Plugin name",120),...d===void 0?{}:{runtime:d},schema:DF,version:t4(J.version)})}function G2(F){return F2(F,{hostApiMode:"authoring"})}class f extends Error{code;constructor(F,G){super(G);this.name="PluginHostProtocolError",this.code=F}}class o0 extends Error{code;kind;recoverable;constructor(F){super(F.message);this.name="PluginHostRemoteError",this.code=F.code,this.kind=F.kind,this.recoverable=F.recoverable}}class m0 extends Error{reason;constructor(F){super("Plugin Host request was aborted");this.name="AbortError",this.reason=F}}var WF=0;function J2(){return WF+=1,`sdk-${Date.now().toString(36)}-${WF.toString(36)}`}function Q2(F){if(F.length<1||F.length>96||F!==F.trim()||!/^[A-Za-z0-9._-]+$/.test(F))throw TypeError("Plugin Host requestIdPrefix is invalid")}function jF(F,G){let J=F.contributes.capabilities,Q=J?.imports.required.find((Y)=>Y.id===G);if(Q)return{import:Q,requirement:"required"};let X=J?.imports.optional.find((Y)=>Y.id===G);if(X)return{import:X,requirement:"optional"};throw TypeError(`Plugin capability import is not declared: ${G}`)}function X2(F,G){let J=G.kind==="protocol"?gF(G):g4(F,G);return new o0(J)}function VF(F){let G=F.kind==="protocol"?gF(F):$1(F);return new o0(G)}function vF(F){let G=G2(F.manifest);if(G.entry===void 0||!G.hostApi.required.includes("host.context.get"))throw TypeError("Plugin Host Web client requires an entry and required host.context.get negotiation baseline");let J=F.requestIdPrefix??J2();Q2(J);let Q=new Map,X=new Set,Y,Z,_=0,M=!1,K=(U)=>{for(let W of Q.values())W.abort?.(),W.reject(U);Q.clear()},D=(U,W=!0)=>{if(M)return;M=!0,F.port.removeEventListener("message",G0),X.clear(),Y=void 0,Z=void 0,K(U);let V={protocol:u,type:"disconnect"};try{P0(V,l4,"Plugin Host disconnect"),L(V)}catch{}try{F.port.close()}catch{}if(!W)return;try{F.onFatalError?.(U)}catch{}},j=()=>{if(_>=Number.MAX_SAFE_INTEGER){let W=new f("request-id-exhausted","Plugin Host request id space is exhausted");throw D(W),W}_+=1;let U=`${J}-${_.toString(36)}`;if(!kF(U)){let W=new f("request-id-exhausted","Plugin Host request id is invalid");throw D(W),W}return U},O=(U,W)=>{P0(U,W,"Plugin Host request")},L=(U)=>{F.port.postMessage(U)},k=(U,W,V,N)=>{if(M)return Promise.reject(new f("closed","Plugin Host client is closed"));if(N?.aborted)return Promise.reject(new m0(N.reason));if(Q.size>=YF)return Promise.reject(RangeError(`Plugin Host client permits at most ${YF} in-flight requests`));try{O(U,V.maximumRequestBytes)}catch(b){return Promise.reject(b)}let E=U.id;return new Promise((b,y)=>{let Q0=N?()=>{let t=Q.get(E);if(!t)return;Q.delete(E),t.abort?.();let p={id:E,protocol:u,type:"cancel"};try{O(p,C0),L(p)}catch(s){let n0=new f("transport-failed",s instanceof Error?s.message:"Plugin Host cancel failed");y(n0),D(n0);return}y(new m0(N.reason))}:void 0,W0=Q0?()=>{N.removeEventListener("abort",Q0)}:void 0;if(Q.set(E,{abort:W0,maximumResponseBytes:V.maximumResponseBytes,parseFailure:V.parseFailure,parseResult:W,reject:y,resolve:b}),Q0)N.addEventListener("abort",Q0,{once:!0});try{L(U)}catch(t){D(new f("transport-failed",t instanceof Error?t.message:"Plugin Host transport failed"))}})};function G0(U){if(M)return;let W;try{W=P0(U.data,a4,"Plugin Host response")}catch{D(new f("invalid-envelope","Plugin Host sent a non-JSON message"));return}if(Z1(U.data)){try{for(let E of X)E(U.data)}catch{D(new f("invalid-envelope","Plugin Host command listener failed"))}return}if(!Y1(U.data)){D(new f("invalid-envelope","Plugin Host sent an invalid envelope"));return}let V=U.data,N=Q.get(V.id);if(!N){D(new f("unknown-response",`Plugin Host returned an unknown, duplicate, or late response id: ${V.id}`));return}if(W>N.maximumResponseBytes){D(new f("invalid-envelope",`Plugin Host response exceeds ${N.maximumResponseBytes} bytes for this request`));return}if(!V.ok){try{let E=N.parseFailure(V.error);Q.delete(V.id),N.abort?.(),N.reject(E)}catch(E){D(new f("invalid-result",E instanceof Error?E.message:"Plugin Host returned an invalid failure"))}return}try{let E=N.parseResult(V.result);Q.delete(V.id),N.abort?.(),N.resolve(E)}catch(E){D(new f("invalid-result",E instanceof Error?E.message:"Plugin Host returned an invalid result"))}}F.port.addEventListener("message",G0),F.port.start?.();let d=(U,W)=>{if(!GF(G.hostApi,U))return Promise.reject(TypeError(`Plugin Host API is not declared: ${U}`));let V=E4[U],N=V.params.type==="none"?void 0:W[0],E=V.params.type==="none"?W[0]:W[1],b;try{b=T4(U,N)}catch(p){return Promise.reject(p)}let Q0={id:j(),method:U,...b===void 0?{}:{params:b},protocol:u,type:"request"},W0=N4(U),t=B4;return k(Q0,(p)=>{let s=t(U,p);if(U==="host.context.get")Y=s;return s},{maximumRequestBytes:W0.request.maxBytes,maximumResponseBytes:W0.result.maxBytes,parseFailure:(p)=>{let s=X2(U,p);if(s.kind==="api"&&s.code==="stale-context")Y=void 0;return s}},E?.signal)},J0={get closed(){return M},callHostApi(U,...W){return d(U,W)},async getHostApiAvailability(U,W){if(!GF(G.hostApi,U))throw TypeError(`Plugin Host API is not declared: ${U}`);let V=!Y||W?.refresh?await J0.refreshHostApiContext(W):Y,N=p0(U);return V.hostApi.availability.find(({id:E})=>E===U)??{available:!1,contractSince:N.contractSince,id:U,reason:"unsupported-host",recoverable:!1,since:N.since}},refreshHostApiContext(U){if(Y=void 0,Z)return Z;let V=d("host.context.get",[U]).finally(()=>{if(Z===V)Z=void 0});return Z=V,Z},async requireHostApi(U,W){let V=await J0.getHostApiAvailability(U,W);if(!V.available)throw new EF(V);return V},getCapabilityAvailability(U,W){let V;try{V=jF(G,U)}catch(b){return Promise.reject(b)}let N=j();return k({capabilityId:U,id:N,protocol:u,type:"capability-availability"},(b)=>{let y=_1(b);if(y.capabilityId!==U||y.requirement!==V.requirement)throw TypeError("Plugin capability availability does not match the declared import");return y},{maximumRequestBytes:C0,maximumResponseBytes:XF,parseFailure:VF},W?.signal)},invokeCapability(U,W,V){let N;try{N=jF(G,U),QF(N.import.inputSchema,W,`Plugin capability ${U} input`)}catch(y){return Promise.reject(y)}let E=j();return k({capabilityId:U,id:E,input:W,protocol:u,type:"capability-invoke"},(y)=>{return QF(N.import.outputSchema,y,`Plugin capability ${U} output`),y},{maximumRequestBytes:C0,maximumResponseBytes:XF,parseFailure:VF},V?.signal)},onCommand(U){if(M)throw new f("closed","Plugin Host client is closed");if(X.size>=64)throw RangeError("Plugin Host command listener limit exceeded");return X.add(U),()=>{X.delete(U)}},close(){D(new f("closed","Plugin Host client was closed"),!1)}};return J0}var u0={schema:"convax.plugin/8",id:"jianying-editor",name:"剪映导入",description:"将直接连接的 Canvas 图片和视频安全导入剪映当前草稿或新草稿。",version:"3.0.0",entry:"index.html",capabilities:[],contributes:{canvas:{renderer:{create:!0,width:600,height:440}}},hostApi:{major:2,required:["canvas.inputs.list","generation.execute","host.context.get"],optional:[]}};var M2="@convax/plugin-sdk/client:createPluginHostClient";function S2(F,G={}){if(F.source!==window.parent||F.ports.length!==1||!IF(F.data)||F.data.pluginId!==u0.id)return null;return vF({manifest:u0,onFatalError:G.onFatalError,port:F.ports[0],requestIdPrefix:G.requestIdPrefix})}export{M2 as pluginSdkClientBundleMarker,S2 as acceptPluginHostConnection}; diff --git a/packages/plugins/jianying-editor/package/manifest.json b/packages/plugins/jianying-editor/package/manifest.json index 60c2d3c..62347cb 100644 --- a/packages/plugins/jianying-editor/package/manifest.json +++ b/packages/plugins/jianying-editor/package/manifest.json @@ -3,7 +3,7 @@ "id": "jianying-editor", "name": "剪映导入", "description": "将直接连接的 Canvas 图片和视频安全导入剪映当前草稿或新草稿。", - "version": "2.1.2", + "version": "3.0.0", "entry": "index.html", "capabilities": [ "canvas.connectedInputs.read", @@ -121,7 +121,7 @@ "command": "convax-jianying-editor-mcp" }, "hostApi": { - "major": 1, + "major": 2, "required": [ "canvas.inputs.list", "generation.execute", diff --git a/packages/plugins/jianying-editor/test/package.test.ts b/packages/plugins/jianying-editor/test/package.test.ts index a9cf79d..9cfc765 100644 --- a/packages/plugins/jianying-editor/test/package.test.ts +++ b/packages/plugins/jianying-editor/test/package.test.ts @@ -15,13 +15,13 @@ describe("JianYing Plugin package", () => { expect(manifest).toMatchObject({ capabilities: ["canvas.connectedInputs.read", "generation.execute"], hostApi: { - major: 1, + major: 2, optional: [], required: ["canvas.inputs.list", "generation.execute", "host.context.get"], }, id: "jianying-editor", schema: "convax.plugin/8", - version: "2.1.2", + version: "3.0.0", runtime: { command: "convax-jianying-editor-mcp", type: "mcp-stdio", @@ -92,8 +92,11 @@ describe("JianYing Plugin package", () => { "utf8", )) - expect(metadata.version).toBe("2.1.2") - expect(workspace.version).toBe("2.1.2") + expect(metadata.version).toBe("3.0.0") + expect(workspace.version).toBe("3.0.0") + expect(workspace["convax.hostCapabilityRequests"]).toEqual([ + "web-plugin-generation-input-binding", + ]) expect(metadata.companions).toEqual([ expect.objectContaining({ command: "convax-jianying-editor-mcp", @@ -127,7 +130,8 @@ describe("JianYing Plugin package", () => { expect(application).toContain("hostClient.onCommand(receiveCommand)") expect(application).toContain("hostClient.callHostApi(method, params)") expect(application).toContain("value.inputKey") - expect(application).toContain("nodeId: input.inputKey") + expect(application).toContain("inputKey: input.inputKey") + expect(application).not.toContain("nodeId: input.inputKey") expect(application).not.toContain('type: "request"') expect(application).not.toContain("postMessage") expect(application).not.toContain("new Map") diff --git a/packages/plugins/multi-angle/convax-package.json b/packages/plugins/multi-angle/convax-package.json index c3ceabd..14b3f53 100644 --- a/packages/plugins/multi-angle/convax-package.json +++ b/packages/plugins/multi-angle/convax-package.json @@ -4,6 +4,6 @@ "id": "multi-angle", "name": "多角度", "description": "通过已安装的统一图片生成工具,一次生成一张多宫格图片,每个格子展示同一主体的一个一致视角。", - "version": "0.1.3", + "version": "0.2.0", "yanked": false } diff --git a/packages/plugins/multi-angle/package.json b/packages/plugins/multi-angle/package.json index 0570e26..b7284c4 100644 --- a/packages/plugins/multi-angle/package.json +++ b/packages/plugins/multi-angle/package.json @@ -1,9 +1,10 @@ { "name": "@microvoid/convax-plugin-multi-angle", - "version": "0.1.3", + "version": "0.2.0", "private": true, "type": "module", "convax.hostCapabilityRequests": [ + "web-plugin-generation-input-binding", "web-plugin-image-input-read" ], "devDependencies": { diff --git a/packages/plugins/multi-angle/package/assets/app.js b/packages/plugins/multi-angle/package/assets/app.js index 1ae8d91..1fefd70 100644 --- a/packages/plugins/multi-angle/package/assets/app.js +++ b/packages/plugins/multi-angle/package/assets/app.js @@ -12,7 +12,12 @@ import { normalizeGenerationTools, presetById, } from "./multi-angle-model.js" -import { normalizeImageInputs, parseOpenedImageStream } from "./image-inputs.js" +import { + clearImagePreview, + decodeImageSessionPreview, + normalizeImageInputs, + withOpenedImageSession, +} from "./image-inputs.js" import { acceptPluginHostConnection } from "./plugin-host-client.js" const CONNECTIONS_CHANGED_COMMAND = "canvas.inputs.changed" @@ -62,8 +67,8 @@ let pluginState = createDefaultState() let hydrationSource = "empty" let connectedImages = [] let generationTools = [] -let sourcePreviewUrl = "" -let sourceSessionId = null +let sourcePreview = null +let sourceLoadController = null let sourceLoadSequence = 0 let refreshPromise = null let refreshQueued = false @@ -107,19 +112,26 @@ function setLoading(active, text) { setHidden(elements.loadingOverlay, !active) } -async function hostRequest(method, params, timeoutMs) { +async function hostRequest(method, params, timeoutMs, externalSignal) { if (!hostClient) throw new Error("Convax Plugin host is not connected") const requestTimeout = timeoutMs === undefined ? REQUEST_TIMEOUT : timeoutMs - if (requestTimeout === null) return hostClient.callHostApi(method, params) const controller = new AbortController() - const timeout = window.setTimeout( - () => controller.abort(new Error("插件宿主请求超时")), - requestTimeout, - ) + const forwardAbort = function () { + controller.abort(externalSignal.reason) + } + if (externalSignal?.aborted) forwardAbort() + else externalSignal?.addEventListener("abort", forwardAbort, { once: true }) + const timeout = requestTimeout === null + ? 0 + : window.setTimeout( + () => controller.abort(new Error("插件宿主请求超时")), + requestTimeout, + ) try { return await hostClient.callHostApi(method, params, { signal: controller.signal }) } finally { - window.clearTimeout(timeout) + if (timeout) window.clearTimeout(timeout) + externalSignal?.removeEventListener("abort", forwardAbort) } } @@ -204,6 +216,10 @@ async function hydrateFromHost() { const hydrated = hydratePluginState(pluginStateFromContext(context)) hydrationSource = hydrated.source pluginState = hydrated.state + await Promise.all([ + hostClient.requireHostApi("canvas.inputs.image.close"), + hostClient.requireHostApi("canvas.inputs.image.open"), + ]) renderAll() await refreshAll(true) } catch (error) { @@ -212,21 +228,19 @@ async function hydrateFromHost() { } function chooseSourceImage() { - return connectedImages.find((image) => image.id === pluginState.sourceNodeId && image.readable) + return connectedImages.find((image) => image.id === pluginState.sourceInputKey && image.readable) ?? connectedImages.find((image) => image.readable) ?? null } -async function readSelectedSource(force) { +async function readSelectedSource() { const source = chooseSourceImage() const sequence = ++sourceLoadSequence - const previousSessionId = sourceSessionId - sourceSessionId = null - sourcePreviewUrl = "" - if (previousSessionId) { - await hostRequest("canvas.inputs.close", { sessionId: previousSessionId }).catch(() => undefined) - } - if (sequence !== sourceLoadSequence) return + sourceLoadController?.abort(new Error("参考图已切换")) + const controller = new AbortController() + sourceLoadController = controller + sourcePreview = null + clearImagePreview(elements.sourceImage) if (!source) { setLoading(false) renderSource() @@ -236,19 +250,47 @@ async function readSelectedSource(force) { setLoading(true, "正在读取参考图…") renderSource() try { - const result = parseOpenedImageStream( - await hostRequest("canvas.inputs.open", { inputKey: source.id }), - ) - if (sequence !== sourceLoadSequence || pluginState.sourceNodeId !== source.id) { - await hostRequest("canvas.inputs.close", { sessionId: result.sessionId }).catch(() => undefined) + const preview = await withOpenedImageSession({ + close: (sessionId) => hostRequest( + "canvas.inputs.image.close", + { sessionId }, + 5_000, + ), + inputKey: source.id, + open: (inputKey, signal) => hostRequest( + "canvas.inputs.image.open", + { inputKey }, + undefined, + signal, + ), + signal: controller.signal, + use: (session, signal) => decodeImageSessionPreview({ + createCanvas: () => document.createElement("canvas"), + createImage: () => new Image(), + inputKey: source.id, + mediaRevision: source.mediaRevision, + pixelRatio: window.devicePixelRatio, + session, + signal, + target: elements.sourceImage, + viewport: elements.sourceStage, + }), + }) + if ( + sequence !== sourceLoadSequence || + pluginState.sourceInputKey !== source.id || + source.mediaRevision !== preview.mediaRevision + ) { return } - sourceSessionId = result.sessionId - sourcePreviewUrl = result.url + sourcePreview = preview } catch (error) { - if (sequence === sourceLoadSequence) showToast(errorMessage(error, "参考图预览失败;仍可尝试通过统一生成接口处理该节点。"), "warning") + if (sequence === sourceLoadSequence && !controller.signal.aborted) { + showToast(errorMessage(error, "参考图预览失败;仍可尝试通过统一生成接口处理该输入。"), "warning") + } } finally { if (sequence === sourceLoadSequence) { + sourceLoadController = null setLoading(false) renderSource() renderActions() @@ -265,7 +307,7 @@ async function refreshTools() { } async function refreshConnectedImages(force) { - const previousSourceId = pluginState.sourceNodeId + const previousSourceId = pluginState.sourceInputKey connectedImages = normalizeImageInputs(await hostRequest("canvas.inputs.list")) const source = chooseSourceImage() if (source?.id !== previousSourceId) { @@ -273,9 +315,10 @@ async function refreshConnectedImages(force) { ...pluginState, lastRun: null, result: null, - sourceNodeId: source?.id ?? null, + sourceInputKey: source?.id ?? null, } - sourcePreviewUrl = "" + sourcePreview = null + clearImagePreview(elements.sourceImage) } renderAll() await readSelectedSource(force) @@ -425,24 +468,28 @@ function renderSource() { option.textContent = image.name + (image.readable ? "" : "(不可读取)") elements.sourceSelect.append(option) } - if (pluginState.sourceNodeId) elements.sourceSelect.value = pluginState.sourceNodeId + if (pluginState.sourceInputKey) elements.sourceSelect.value = pluginState.sourceInputKey elements.sourceSelect.disabled = runActive setHidden(elements.sourceSelectShell, connectedImages.length === 0) const source = chooseSourceImage() - const hasPreview = Boolean(source && sourcePreviewUrl) + const hasPreview = Boolean( + source && + sourcePreview && + sourcePreview.inputKey === source.id && + sourcePreview.mediaRevision === source.mediaRevision, + ) elements.sourceStage.classList.toggle("has-image", hasPreview) setHidden(elements.emptySource, hasPreview) setHidden(elements.sourceImage, !hasPreview) setHidden(elements.sourceOverlay, !hasPreview) if (hasPreview) { - elements.sourceImage.src = sourcePreviewUrl - elements.sourceImage.alt = "多角度参考图:" + source.name - elements.sourceSize.textContent = source.width && source.height - ? String(source.width) + " × " + String(source.height) + elements.sourceImage.setAttribute("aria-label", "多角度参考图:" + source.name) + elements.sourceSize.textContent = sourcePreview.width && sourcePreview.height + ? String(sourcePreview.width) + " × " + String(sourcePreview.height) : source.mimeType ?? "IMAGE" } else { - elements.sourceImage.removeAttribute("src") + elements.sourceImage.removeAttribute("aria-label") } if (!connectedImages.length) elements.sourceHelp.textContent = "从 Canvas 图片节点连线到此节点;插件不能读取未连接的素材。" else if (!source) elements.sourceHelp.textContent = "当前连接中没有可用的 JPEG、PNG 或 WebP 图片。" @@ -605,13 +652,13 @@ async function runGeneration() { completedAt: "", failure: null, presetIds, - sourceNodeId: source.id, + sourceInputKey: source.id, startedAt, status: "running", toolId: tool.id, }, result: null, - sourceNodeId: source.id, + sourceInputKey: source.id, toolId: tool.id, } hydrationSource = "current" @@ -643,7 +690,7 @@ async function runGeneration() { presetIds, subjectType: pluginState.subjectType, }) - const request = createGenerationRequest({ prompt, sourceNodeId: source.id, toolId: tool.id }) + const request = createGenerationRequest({ prompt, sourceInputKey: source.id, toolId: tool.id }) // Generation has no client deadline. The host owns queued-job polling, // frame cancellation, stale-scope checks, managed assets and Canvas commit. const rawResult = await hostRequest("generation.execute", request, null) @@ -686,17 +733,14 @@ function bindEvents() { window.addEventListener("message", handleWindowMessage) window.addEventListener("beforeunload", function () { postStateSnapshotBestEffort() - if (sourceSessionId && hostClient) { - void hostClient.callHostApi("canvas.inputs.close", { - sessionId: sourceSessionId, - }).catch(() => { - // Host frame teardown revokes any remaining connection-bound session. - }) - sourceSessionId = null - sourcePreviewUrl = "" - } + sourceLoadController?.abort(new Error("插件页面正在关闭")) + sourceLoadController = null + sourcePreview = null + clearImagePreview(elements.sourceImage) window.clearTimeout(stateSaveTimer) window.clearTimeout(toastTimer) + // Unload cannot await the helper's explicit API close. Host connection + // teardown is the authoritative closeConnection -> revokeFrame fallback. hostClient?.close() hostClient = null }) @@ -707,9 +751,10 @@ function bindEvents() { elements.sourceSelect.addEventListener("change", function () { if (runActive) return const source = connectedImages.find((image) => image.id === elements.sourceSelect.value && image.readable) - if (!source || source.id === pluginState.sourceNodeId) return - pluginState = { ...pluginState, sourceNodeId: source.id } - sourcePreviewUrl = "" + if (!source || source.id === pluginState.sourceInputKey) return + pluginState = { ...pluginState, sourceInputKey: source.id } + sourcePreview = null + clearImagePreview(elements.sourceImage) resetRunForPlanChange() queueStateSave() renderAll() diff --git a/packages/plugins/multi-angle/package/assets/image-inputs.js b/packages/plugins/multi-angle/package/assets/image-inputs.js index 7684f83..37ae78c 100644 --- a/packages/plugins/multi-angle/package/assets/image-inputs.js +++ b/packages/plugins/multi-angle/package/assets/image-inputs.js @@ -1,9 +1,25 @@ const acceptedImageMimeTypes = new Set(["image/jpeg", "image/png", "image/webp"]) +export const MAX_PREVIEW_EDGE = 2048 +export const MAX_PREVIEW_PIXELS = 4_194_304 +export const MAX_PREVIEW_PIXEL_RATIO = 2 + function isRecord(value) { return Boolean(value) && typeof value === "object" && !Array.isArray(value) } +function safePositiveInteger(value) { + return Number.isSafeInteger(value) && value > 0 ? value : undefined +} + +function abortReason(signal) { + return signal?.reason instanceof Error ? signal.reason : new Error("图片读取已取消") +} + +function throwIfAborted(signal) { + if (signal?.aborted) throw abortReason(signal) +} + export function normalizeImageInputs(result) { if (!isRecord(result) || !Array.isArray(result.inputs)) return [] return result.inputs @@ -18,8 +34,11 @@ export function normalizeImageInputs(result) { ? input.mimeType.toLowerCase() : undefined return { - height: typeof input.height === "number" ? input.height : undefined, + height: safePositiveInteger(input.height), id: input.inputKey, + mediaRevision: typeof input.mediaRevision === "string" && input.mediaRevision + ? input.mediaRevision + : undefined, mimeType, name: typeof input.name === "string" && input.name ? input.name @@ -29,27 +48,172 @@ export function normalizeImageInputs(result) { readable: input.status !== "pending" && input.status !== "error" && (mimeType === undefined || acceptedImageMimeTypes.has(mimeType)), - width: typeof input.width === "number" ? input.width : undefined, + width: safePositiveInteger(input.width), } }) } -export function parseOpenedImageStream(result) { +export function parseOpenedImageSession(result) { + const probe = isRecord(result) && isRecord(result.probe) ? result.probe : null + const mimeType = typeof probe?.mimeType === "string" + ? probe.mimeType.toLowerCase() + : "" + const width = safePositiveInteger(probe?.width) + const height = safePositiveInteger(probe?.height) if ( !isRecord(result) || typeof result.sessionId !== "string" || !result.sessionId || typeof result.url !== "string" || !result.url.startsWith("convax-connected-media://") || - !isRecord(result.probe) || - typeof result.probe.mimeType !== "string" || - !acceptedImageMimeTypes.has(result.probe.mimeType.toLowerCase()) + probe?.kind !== "image" || + !acceptedImageMimeTypes.has(mimeType) || + !Number.isSafeInteger(probe?.size) || + probe.size < 1 || + probe.size > 16 * 1024 * 1024 || + !width || + width > 8192 || + !height || + height > 8192 || + width * height > 33_554_432 || + typeof probe.contentRevision !== "string" || + !/^[a-f0-9]{64}$/u.test(probe.contentRevision) ) { throw new Error("宿主没有返回可预览的参考图") } return { - mimeType: result.probe.mimeType.toLowerCase(), + probe: { + contentRevision: probe.contentRevision, + height, + kind: "image", + mimeType, + size: probe.size, + width, + }, sessionId: result.sessionId, url: result.url, } } + +export function computePreviewBackingSize(input) { + const sourceWidth = safePositiveInteger(input?.sourceWidth) + const sourceHeight = safePositiveInteger(input?.sourceHeight) + if (!sourceWidth || !sourceHeight) throw new Error("图片尺寸无效") + const viewportWidth = Math.max(1, Number.isFinite(input.viewportWidth) ? input.viewportWidth : sourceWidth) + const viewportHeight = Math.max(1, Number.isFinite(input.viewportHeight) ? input.viewportHeight : sourceHeight) + const pixelRatio = Math.min( + MAX_PREVIEW_PIXEL_RATIO, + Math.max(1, Number.isFinite(input.pixelRatio) ? input.pixelRatio : 1), + ) + const fitScale = Math.min(viewportWidth / sourceWidth, viewportHeight / sourceHeight) + const edgeScale = MAX_PREVIEW_EDGE / Math.max(sourceWidth, sourceHeight) + const pixelScale = Math.sqrt(MAX_PREVIEW_PIXELS / (sourceWidth * sourceHeight)) + const scale = Math.min(1, fitScale * pixelRatio, edgeScale, pixelScale) + const width = Math.max(1, Math.floor(sourceWidth * scale)) + const height = Math.max(1, Math.floor(sourceHeight * scale)) + if ( + width > sourceWidth || + height > sourceHeight || + width > MAX_PREVIEW_EDGE || + height > MAX_PREVIEW_EDGE || + width * height > MAX_PREVIEW_PIXELS + ) { + throw new Error("参考图预览尺寸超出预算") + } + return { height, pixelRatio, width } +} + +export async function withOpenedImageSession(input) { + throwIfAborted(input.signal) + let opened + let openedSessionId + let primaryError + try { + const response = await input.open(input.inputKey, input.signal) + opened = parseOpenedImageSession(response) + // The SDK validates Host results before this helper sees them. Record only a + // fully admitted session; malformed results are connection-fatal and are + // reclaimed by Host frame revocation because no session id crosses the SDK. + openedSessionId = opened.sessionId + throwIfAborted(input.signal) + const result = await input.use(opened, input.signal) + throwIfAborted(input.signal) + return result + } catch (error) { + primaryError = error + throw error + } finally { + if (openedSessionId) { + try { + await input.close(openedSessionId) + } catch (closeError) { + if (!primaryError) throw closeError + } + } + } +} + +export async function decodeImageSessionPreview(input) { + throwIfAborted(input.signal) + const image = input.createImage() + const previewCanvas = input.createCanvas() + const onAbort = function () { + image.removeAttribute("src") + } + input.signal?.addEventListener("abort", onAbort, { once: true }) + try { + image.decoding = "async" + image.src = input.session.url + await image.decode() + throwIfAborted(input.signal) + if ( + image.naturalWidth !== input.session.probe.width || + image.naturalHeight !== input.session.probe.height + ) { + throw new Error("参考图尺寸与宿主探测结果不一致") + } + const viewport = input.viewport.getBoundingClientRect() + const backing = computePreviewBackingSize({ + pixelRatio: input.pixelRatio, + sourceHeight: image.naturalHeight, + sourceWidth: image.naturalWidth, + viewportHeight: viewport.height, + viewportWidth: viewport.width, + }) + previewCanvas.width = backing.width + previewCanvas.height = backing.height + const previewContext = previewCanvas.getContext("2d", { alpha: false }) + if (!previewContext) throw new Error("浏览器不支持安全的参考图预览") + previewContext.drawImage(image, 0, 0, backing.width, backing.height) + throwIfAborted(input.signal) + + input.target.width = backing.width + input.target.height = backing.height + const targetContext = input.target.getContext("2d", { alpha: false }) + if (!targetContext) throw new Error("浏览器不支持安全的参考图预览") + targetContext.clearRect(0, 0, backing.width, backing.height) + targetContext.drawImage(previewCanvas, 0, 0) + return { + contentRevision: input.session.probe.contentRevision, + height: input.session.probe.height, + inputKey: input.inputKey, + mediaRevision: input.mediaRevision, + mimeType: input.session.probe.mimeType, + previewHeight: backing.height, + previewWidth: backing.width, + width: input.session.probe.width, + } + } finally { + input.signal?.removeEventListener("abort", onAbort) + image.removeAttribute("src") + previewCanvas.width = 1 + previewCanvas.height = 1 + } +} + +export function clearImagePreview(canvas) { + const context = canvas.getContext("2d") + context?.clearRect(0, 0, canvas.width, canvas.height) + canvas.width = 1 + canvas.height = 1 +} diff --git a/packages/plugins/multi-angle/package/assets/multi-angle-model.js b/packages/plugins/multi-angle/package/assets/multi-angle-model.js index 50d1b67..24b5117 100644 --- a/packages/plugins/multi-angle/package/assets/multi-angle-model.js +++ b/packages/plugins/multi-angle/package/assets/multi-angle-model.js @@ -1,6 +1,6 @@ export const MAX_SELECTED_PRESETS = 6 export const MIN_SELECTED_PRESETS = 2 -export const STATE_SCHEMA_VERSION = 3 +export const STATE_SCHEMA_VERSION = 4 export const ANGLE_PRESETS = Object.freeze([ { id: "front", label: "正面", shortLabel: "Front", prompt: "eye-level front view, camera centered on the subject" }, @@ -68,7 +68,7 @@ export function createDefaultState() { result: null, schemaVersion: STATE_SCHEMA_VERSION, selectedPresetIds: [...DEFAULT_PRESET_IDS], - sourceNodeId: null, + sourceInputKey: null, subjectType: "character", toolId: null, } @@ -110,15 +110,15 @@ function normalizeFailure(value) { function normalizeLastRun(value) { if (!isRecord(value)) return null const presetIds = uniquePresetIds(value.presetIds) - const sourceNodeId = safeId(value.sourceNodeId) + const sourceInputKey = safeId(value.sourceInputKey, 2048) const toolId = safeId(value.toolId, 256) - if (presetIds.length < MIN_SELECTED_PRESETS || !sourceNodeId || !toolId) return null + if (presetIds.length < MIN_SELECTED_PRESETS || !sourceInputKey || !toolId) return null if (value.status === "running") { return { completedAt: "", failure: { message: "插件页面在宫格图生成完成前关闭。宿主会保留已提交的 Canvas 结果。" }, presetIds, - sourceNodeId, + sourceInputKey, startedAt: safeText(value.startedAt, 64), status: "interrupted", toolId, @@ -129,7 +129,7 @@ function normalizeLastRun(value) { completedAt: safeText(value.completedAt, 64), failure: normalizeFailure(value.failure), presetIds, - sourceNodeId, + sourceInputKey, startedAt: safeText(value.startedAt, 64), status: value.status, toolId, @@ -145,7 +145,7 @@ function hydrateCurrentState(value) { result: normalizePersistedResult(value.result), schemaVersion: STATE_SCHEMA_VERSION, selectedPresetIds: selectedPresetIds.length ? selectedPresetIds : fallback.selectedPresetIds, - sourceNodeId: safeId(value.sourceNodeId), + sourceInputKey: safeId(value.sourceInputKey, 2048), subjectType: SUBJECT_IDS.has(value.subjectType) ? value.subjectType : fallback.subjectType, toolId: safeId(value.toolId, 256), } @@ -158,7 +158,9 @@ function migrateLegacyState(value) { ...fallback, notes: safeText(value.notes, 1000), selectedPresetIds: selectedPresetIds.length ? selectedPresetIds : fallback.selectedPresetIds, - sourceNodeId: safeId(value.sourceNodeId), + // The retired field was ambiguously named and may contain a historical + // node id. Never promote it into an API 2 opaque input capability. + sourceInputKey: null, subjectType: SUBJECT_IDS.has(value.subjectType) ? value.subjectType : fallback.subjectType, toolId: safeId(value.toolId, 256), } @@ -168,7 +170,7 @@ export function hydratePluginState(value) { if (value === null || value === undefined) return { source: "empty", state: createDefaultState() } if (!isRecord(value)) return { source: "unsupported", state: createDefaultState() } if (value.schemaVersion === STATE_SCHEMA_VERSION) return { source: "current", state: hydrateCurrentState(value) } - if (value.schemaVersion === 1 || value.schemaVersion === 2) { + if (value.schemaVersion === 1 || value.schemaVersion === 2 || value.schemaVersion === 3) { return { source: "legacy", state: migrateLegacyState(value) } } return { source: "unsupported", state: createDefaultState() } @@ -228,14 +230,14 @@ export function createMultiAngleGridPrompt(input) { } export function createGenerationRequest(input) { - const sourceNodeId = safeId(input.sourceNodeId) + const sourceInputKey = safeId(input.sourceInputKey, 2048) const toolId = safeId(input.toolId, 256) const prompt = safeText(input.prompt, 20_000).trim() - if (!sourceNodeId || !toolId || !prompt) throw new Error("生成请求无效") + if (!sourceInputKey || !toolId || !prompt) throw new Error("生成请求无效") return { output: "image", prompt, - references: [{ nodeId: sourceNodeId, role: "reference_image" }], + references: [{ inputKey: sourceInputKey, role: "reference_image" }], resultMode: "create-pending-node", toolId, } diff --git a/packages/plugins/multi-angle/package/assets/plugin-host-client.js b/packages/plugins/multi-angle/package/assets/plugin-host-client.js index a90ade2..6e3bc02 100644 --- a/packages/plugins/multi-angle/package/assets/plugin-host-client.js +++ b/packages/plugins/multi-angle/package/assets/plugin-host-client.js @@ -1 +1 @@ -var c1=/^[a-z][a-z0-9]*(?:\.[a-z][a-z0-9]*)+$/,b1=/^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/,d1=/^[a-z][A-Za-z0-9]*(?:\.[a-z][A-Za-z0-9]*)+$/,v1=/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/,m1=new Set(["web-plugin","agent-skill","companion","host"]),p1=new Set(["connection","plugin","own-node","project","canvas"]),s1=new Set(["none","read","write","execute","subscribe"]),o1=new Set(["cancelable","commit-preserving"]);function _0(G,F){if(G.trim().length===0)throw TypeError(`${F} must not be empty`)}function y0(G,F){if(!v1.test(G))throw TypeError(`${F} must be a strict semantic version`)}function D1(G,F){let J=G.split(".").map(Number),Q=F.split(".").map(Number);for(let X=0;X<3;X+=1){let Y=J[X]-Q[X];if(Y!==0)return Y}return 0}function U1(G){if(!c1.test(G.id))throw TypeError(`Plugin API id is invalid: ${G.id}`);if(G.grant!==null&&!d1.test(G.grant))throw TypeError(`Plugin API grant is invalid: ${G.grant}`);if(!p1.has(G.scope))throw TypeError(`Plugin API scope is invalid: ${G.scope}`);if(!s1.has(G.sideEffect))throw TypeError(`Plugin API sideEffect is invalid: ${G.sideEffect}`);if(!o1.has(G.completion))throw TypeError(`Plugin API completion is invalid: ${G.completion}`);let F=G.audience??["web-plugin"];if(F.length===0||new Set(F).size!==F.length||F.some((X)=>!m1.has(X)))throw TypeError(`Plugin API audience is invalid: ${G.id}`);_0(G.docs.summary,`${G.id} docs.summary`),_0(G.docs.description,`${G.id} docs.description`),_0(G.docs.request,`${G.id} docs.request`),_0(G.docs.response,`${G.id} docs.response`);let J=new Set,Q=G.errors.map((X)=>{if(!b1.test(X.code)||J.has(X.code))throw TypeError(`Plugin API error code is invalid or duplicated: ${G.id}/${X.code}`);return J.add(X.code),_0(X.description,`${G.id}/${X.code} description`),Object.freeze({...X})});return Object.freeze({...G,audience:Object.freeze([...F]),errors:Object.freeze(Q),docs:Object.freeze({...G.docs})})}function H(G){return U1(G)}function r1(G,F){return y0(G,"Plugin API release version"),Object.freeze({version:G,apis:Object.freeze([...F])})}function u1(...G){if(G.length===0)throw TypeError("Plugin API catalog requires at least one release");let F=new Set,J=[],Q;for(let X of G){if(y0(X.version,"Plugin API release version"),Q&&D1(Q,X.version)>=0)throw TypeError("Plugin API releases must be strictly increasing");Q=X.version;for(let Y of X.apis){let Z=U1(Y);if(F.has(Z.id))throw TypeError(`Plugin API id is duplicated: ${Z.id}`);F.add(Z.id),J.push(Object.freeze({...Z,since:X.version}))}}if(J.length===0)throw TypeError("Plugin API catalog must contain at least one API");return Object.freeze({schema:"convax.plugin-api-catalog/1",version:G[G.length-1].version,apis:Object.freeze(J)})}var i8=Object.freeze({assertVersion:y0,compareVersions:D1}),z=1024,I=z*z,$0={type:"none"},s={type:"boolean"},B={finite:!0,type:"number"},o={finite:!0,minimum:0,type:"integer"},E0={type:"null"},g=(G)=>({const:G}),$=(G=2048,F={})=>({controlCharacters:!1,maxLength:G,minLength:F.allowEmpty?0:1,...F.prefix?{prefix:F.prefix}:{},...F.refinement?{refinement:F.refinement}:{},type:"string"}),C=(G,F,J=0,Q)=>({items:G,maxItems:F,minItems:J,type:"array",...Q?{uniqueBy:Q}:{}}),S=(G,F)=>({additionalProperties:!1,properties:G,required:F,type:"object"}),a=(...G)=>({oneOf:G}),C0=(G=I)=>({keyMaxLength:128,maxBytes:G,maxDepth:32,type:"json-object"}),y=(G)=>({controlCharacters:!1,enum:G,maxLength:Math.max(...G.map((F)=>F.length)),minLength:1,type:"string"}),Z0=S({x:B,y:B},["x","y"]),c0=S({height:B,width:B},["height","width"]),t=S({canvasId:$(256),projectId:$(256)},["canvasId","projectId"]),P0=y(["text","image","video","audio"]),W1=y(["text","reference_image","reference_video","first_frame","last_frame","audio"]),x=(G=1000)=>C($(),G),n1=a(S({available:g(!0),catalogVersion:$(64),id:$(128),since:$(64)},["available","catalogVersion","id","since"]),S({available:g(!1),id:$(128),reason:y(["unsupported-host","not-declared","permission-denied","wrong-surface","missing-context","setup-required","disabled","recovering"]),recoverable:s,since:$(64)},["available","id","reason","recoverable"])),j1=S({data:C0(),id:$(),parentId:$(),position:Z0,revision:o,style:C0(),type:$(80)},["data","id","position","revision","type"]),t1=S({nodeId:$(),role:W1},["nodeId","role"]),i1=S({ids:x(),kinds:x(),limit:o,relatedToNodeIds:x(),text:$(2000,{allowEmpty:!0})},[]),a1=S({animated:s,id:$(),source:$(),target:$(),type:$(80)},["source","target"]),l1=S({nodeId:$(),position:Z0,size:c0},["nodeId","position"]),e1=S({componentGap:B,componentPackingScale:B,crossGap:B,isolatedPlacement:y(["left","preserve"]),mainGap:B,nodeGap:B,nodePackingScale:B,strategy:y(["component-packing","horizontal-directed-cluster","vertical-directed-cluster"])},[]),FF=a(S({edgeIds:x(),nodeIds:x(),type:g("elements.remove")},["type"]),S({direction:y(["left","center","right","top","middle","bottom"]),nodeIds:x(),type:g("nodes.align")},["direction","nodeIds","type"]),S({connection:a1,type:g("nodes.connect")},["connection","type"]),S({axis:y(["horizontal","vertical"]),nodeIds:x(),type:g("nodes.distribute")},["axis","nodeIds","type"]),S({label:$(512),nodeIds:x(),type:g("nodes.group")},["nodeIds","type"]),S({gap:B,layout:y(["grid","horizontal","vertical"]),nodeIds:x(),type:g("nodes.layout")},["nodeIds","type"]),S({delta:Z0,nodeIds:x(),type:g("nodes.move")},["delta","nodeIds","type"]),S({type:g("nodes.setGeometry"),updates:C(l1,1000)},["type","updates"]),S({nodeId:$(),type:g("nodes.ungroup")},["nodeId","type"]),S({nodeIds:x(),options:e1,type:g("canvas.auto-layout")},["type"])),GF=S({durationMs:B,height:B,inputKey:$(),kind:$(80),label:$(512),mediaRevision:$(512),mimeType:$(512),name:$(512),status:y(["error","idle","pending"]),width:B},["inputKey","kind","label"]),JF=S({acceptedInputs:C(W1,6),description:$(2000),id:$(256),kind:y(["model","operation"]),output:P0,title:$(120)},["acceptedInputs","description","id","kind","output","title"]),V1=S({id:$(),source:$(),target:$()},["id","source","target"]),QF=S({id:$(),kind:$(80),label:$(512),parentId:$(64*z,{allowEmpty:!0}),position:Z0,size:c0,type:$(64*z,{allowEmpty:!0})},["id","kind","label","position","size"]),XF=S({description:$(64*z,{allowEmpty:!0}),durationMs:B,id:$(),kind:$(80),label:$(512),mimeType:$(64*z,{allowEmpty:!0}),name:$(64*z,{allowEmpty:!0}),parentId:$(64*z,{allowEmpty:!0}),position:Z0,resource:S({kind:g("project-file"),path:$(1024)},["kind","path"]),size:c0,status:$(64*z,{allowEmpty:!0}),text:$(64*z,{allowEmpty:!0}),type:$(64*z,{allowEmpty:!0})},["id","kind","label","position","size"]),YF=S({edges:C(V1,1e4),id:$(256),nodes:C(QF,1e4),revision:o,title:$(512)},["edges","id","nodes","revision","title"]),ZF=S({description:$(8000,{allowEmpty:!0}),edges:C(V1,1e4),id:$(256),nodes:C(XF,1e4),revision:o,tags:C($(),256),title:$(512)},["edges","id","nodes","revision","title"]),_F=S({id:$(),incomingNodeIds:x(),kind:$(80),label:$(512),outgoingNodeIds:x(),parentId:$(64*z,{allowEmpty:!0}),position:Z0,text:$(64*z,{allowEmpty:!0}),type:$(64*z,{allowEmpty:!0})},["id","incomingNodeIds","kind","label","outgoingNodeIds","position"]),$F=S({canvas:S({id:$(256),name:$(512)},["id"]),hostApi:S({availability:C(n1,256,0,"id"),catalogVersion:$(64)},["availability","catalogVersion"]),node:j1,plugin:S({id:$(128),name:$(512),version:$(128)},["id","name","version"]),project:S({id:$(256),name:$(512)},["id"])},["canvas","hostApi","node","plugin","project"]),w=(G,F,J={})=>({request:{maxBytes:J.request??64*z,schema:G},result:{maxBytes:J.result??64*z,schema:F}}),F0=Object.freeze({"host.context.get":w($0,$F,{result:I}),"canvas.inputs.list":w($0,S({inputs:C(GF,256)},["inputs"]),{result:I}),"canvas.inputs.open":w(S({inputKey:$()},["inputKey"]),S({probe:S({duration:S({estimated:s,milliseconds:B},["estimated","milliseconds"]),height:B,kind:y(["audio","video"]),mediaRevision:$(128),mimeType:$(256),size:B,width:B},["duration","kind","mediaRevision","mimeType","size"]),sessionId:$(128),url:$(2048,{prefix:"convax-connected-media://"})},["probe","sessionId","url"])),"canvas.inputs.close":w(S({sessionId:$(128)},["sessionId"]),S({closed:s},["closed"])),"canvas.node.get":w($0,j1,{result:I}),"canvas.node.state.replace":w(S({state:C0(256*z)},["state"]),S({updated:g(!0)},["updated"]),{request:256*z+4*z}),"canvas.resource.image.create":w(S({dataUrl:$(24*I,{prefix:"data:image/png;base64,"}),name:$(120,{refinement:"safe-png-file-name"})},["dataUrl","name"]),S({createdNodeId:$(),revision:o},["createdNodeId","revision"]),{request:24*I+4*z}),"project.file.text.read":w(S({path:$(1024,{refinement:"portable-project-relative-path"})},["path"]),S({content:$(I,{allowEmpty:!0}),exists:s,path:$(1024,{refinement:"portable-project-relative-path"})},["content","exists","path"]),{result:I+4*z}),"agent.prompt":w(S({text:$(20000,{refinement:"trimmed"})},["text"]),S({text:$(64*z,{allowEmpty:!0})},["text"])),"generation.tools.list":w(a($0,S({output:P0},[])),S({tools:C(JF,256)},["tools"]),{result:I}),"generation.execute":w(S({output:P0,prompt:$(20000,{refinement:"trimmed"}),references:C(t1,32),resultMode:y(["create-pending-node","return"]),toolId:$(256)},["prompt"]),S({createdNodeIds:C($(),32),outputText:$(64*z,{allowEmpty:!0}),revision:o,toolId:$(256),warnings:C($(),32)},["createdNodeIds","revision","toolId","warnings"]),{result:256*z}),"projects.list":w($0,S({projects:C(S({available:s,id:$(256),name:$(512)},["available","id","name"]),1000)},["projects"]),{result:I}),"canvas.catalog.list":w(S({projectId:$(256)},["projectId"]),S({canvases:C(S({createdAt:B,id:$(256),name:$(512),updatedAt:B},["createdAt","id","name","updatedAt"]),1e4),projectId:$(256)},["canvases","projectId"]),{result:8*I}),"canvas.document.get":w(S({projection:y(["geometry","structure"]),ref:t},["ref"]),a(S({document:YF,projection:g("geometry"),ref:t,storageVersion:a(E0,$(256))},["document","projection","ref","storageVersion"]),S({document:ZF,projection:g("structure"),ref:t,storageVersion:a(E0,$(256))},["document","projection","ref","storageVersion"])),{result:8*I}),"canvas.nodes.query":w(S({query:i1,ref:t},["ref"]),S({nodes:C(_F,1000),ref:t,revision:o,storageVersion:a(E0,$(256))},["nodes","ref","revision","storageVersion"]),{request:I,result:8*I}),"canvas.transaction.execute":w(S({commands:C(FF,256,1),expectedRevision:o,ref:t,transactionId:$(128)},["commands","expectedRevision","ref","transactionId"]),S({affectedNodeIds:x(1e4),changed:s,createdNodeIds:x(1e4),ref:t,revision:o,storageVersion:$(256),summaryTruncated:s,warnings:x()},["affectedNodeIds","changed","createdNodeIds","ref","revision","storageVersion","warnings"]),{request:I,result:2*I}),"canvas.events.subscribe":w(S({ref:S({canvasId:$(256),projectId:$(256)},["projectId"])},["ref"]),S({subscriptionId:$(128)},["subscriptionId"])),"canvas.events.unsubscribe":w(S({subscriptionId:$(128)},["subscriptionId"]),S({removed:s},["removed"]))}),KF=Math.max(...Object.values(F0).map(({request:G})=>G.maxBytes)),MF=Math.max(...Object.values(F0).map(({result:G})=>G.maxBytes));function SF(G){return F0[G]}function q0(G,F){if(!G||typeof G!=="object"||Array.isArray(G))throw TypeError(`${F} must be an object`);let J=Object.getPrototypeOf(G);if(J!==Object.prototype&&J!==null)throw TypeError(`${F} must be a plain object`);return G}var DF=/^(CON|PRN|AUX|NUL|COM[1-9¹²³]|LPT[1-9¹²³]|CONIN\$|CONOUT\$)$/iu;function L1(G){for(let F of G){let J=F.codePointAt(0);if(J>=55296&&J<=57343)return!1}return!0}function s0(G){let F=G.split(".",1)[0]??"";return Boolean(G&&G!=="."&&G!==".."&&L1(G)&&!/[\\/:*?"<>|\u0000-\u001f\u007f]/u.test(G)&&!/[. ]$/u.test(G)&&!DF.test(F))}function UF(G,F){if(F===void 0)return!0;if(F==="trimmed")return G===G.trim();if(F==="safe-png-file-name")return G===G.trim()&&G.toLowerCase().endsWith(".png")&&s0(G);if(F==="portable-project-relative-path"){if(G!==G.trim()||G.includes("\\")||G.startsWith("/")||G.startsWith("//")||/^[A-Za-z]:/u.test(G)||!L1(G))return!1;let J=G.split("/");return J[0]?.toLowerCase()!==".convax"&&J.length>0&&J.every((Q)=>s0(Q))}return!1}function WF(G,F,J){let Q=new Set,X=(_,M,K)=>{if(_===null||typeof _==="string"||typeof _==="boolean")return _;if(typeof _==="number"){if(!Number.isFinite(_))throw TypeError(`${M} must contain finite JSON numbers`);return _}if(!_||typeof _!=="object"||K>=F.maxDepth||Q.has(_))throw TypeError(`${M} must be bounded acyclic JSON`);let D=Object.getPrototypeOf(_);if(!Array.isArray(_)&&D!==Object.prototype&&D!==null)throw TypeError(`${M} must contain plain JSON objects`);Q.add(_);let W;if(Array.isArray(_))W=_.map((O,V)=>X(O,`${M}[${V}]`,K+1));else{let O=Object.create(null);for(let[V,P]of Object.entries(_)){if(V.length<1||V.length>F.keyMaxLength||/[\u0000-\u001f\u007f]/u.test(V))throw TypeError(`${M} key is invalid`);O[V]=X(P,`${M}.${V}`,K+1)}W=O}return Q.delete(_),W},Y=X(q0(G,J),J,0);if(Array.isArray(Y)||!Y||typeof Y!=="object")throw TypeError(`${J} must be an object`);let Z=JSON.stringify(Y);if(new TextEncoder().encode(Z).byteLength>F.maxBytes)throw TypeError(`${J} exceeds ${F.maxBytes} bytes`);return Y}function K0(G,F,J="Plugin API value"){if("oneOf"in G){let Y=[];for(let Z of G.oneOf)try{Y.push(K0(Z,F,J))}catch{}if(Y.length!==1)throw TypeError(`${J} must match exactly one schema variant`);return Y[0]}if("const"in G){if(F!==G.const)throw TypeError(`${J} must equal ${String(G.const)}`);return F}if("type"in G&&G.type==="none"){if(F!==void 0)throw TypeError(`${J} does not accept a value`);return}if("type"in G&&G.type==="null"){if(F!==null)throw TypeError(`${J} must be null`);return null}if("type"in G&&G.type==="boolean"){if(typeof F!=="boolean")throw TypeError(`${J} must be boolean`);return F}if("type"in G&&(G.type==="number"||G.type==="integer")){if(typeof F!=="number"||!Number.isFinite(F)||G.type==="integer"&&!Number.isSafeInteger(F)||G.minimum!==void 0&&FG.maxLength||G.controlCharacters===!1&&/[\u0000-\u001f\u007f]/u.test(F)||G.enum!==void 0&&!G.enum.includes(F)||G.prefix!==void 0&&!F.startsWith(G.prefix)||!UF(F,G.refinement))throw TypeError(`${J} must satisfy its bounded string contract`);return F}if("type"in G&&G.type==="array"){if(!Array.isArray(F)||F.lengthG.maxItems)throw TypeError(`${J} must satisfy its bounded array contract`);let Y=F.map((Z,_)=>K0(G.items,Z,`${J}[${_}]`));if(G.uniqueBy!==void 0){let Z=Y.map((_)=>{let K=q0(_,`${J} unique item`)[G.uniqueBy];if(typeof K!=="string"&&typeof K!=="number")throw TypeError(`${J} unique identity is invalid`);return`${typeof K}:${String(K)}`});if(new Set(Z).size!==Z.length)throw TypeError(`${J} contains duplicate ${G.uniqueBy}`)}return Y}if("type"in G&&G.type==="json-object")return WF(F,G,J);if(!("properties"in G))throw TypeError(`${J} has an unsupported schema`);let Q=q0(F,J),X=new Set(Object.keys(G.properties));if(G.required.some((Y)=>!Object.prototype.hasOwnProperty.call(Q,Y))||Object.keys(Q).some((Y)=>!X.has(Y)))throw TypeError(`${J} contains unsupported or missing fields`);return Object.fromEntries(Object.entries(Q).map(([Y,Z])=>[Y,K0(G.properties[Y],Z,`${J}.${Y}`)]))}function k0(G,F){if("oneOf"in G){let J=G.oneOf.map((Z)=>k0(Z,F)),Q=J.filter((Z)=>Z.type==="object");if(Q.length===0&&J.some((Z)=>Z.type==="none"))return{type:"none"};if(Q.length===0)throw TypeError(`${F} is not an object schema`);let X=new Set(Q.flatMap(({required:Z,optional:_})=>[...Z,..._])),Y=[...X].filter((Z)=>Q.every((_)=>_.required.includes(Z))).sort();return{additionalProperties:!1,optional:[...X].filter((Z)=>!Y.includes(Z)).sort(),required:Y,type:"object"}}if("type"in G&&G.type==="none")return{type:"none"};if(!("properties"in G))throw TypeError(`${F} is not an object schema`);return{additionalProperties:!1,optional:Object.keys(G.properties).filter((J)=>!G.required.includes(J)).sort(),required:[...G.required].sort(),type:"object"}}var I0=Object.freeze(Object.keys(F0).sort()),jF=Object.freeze(Object.fromEntries(I0.map((G)=>{let F=F0[G],J=k0(F.result.schema,`Plugin API ${G} result`);if(J.type!=="object")throw TypeError(`Plugin API ${G} result must be an object`);return[G,{params:k0(F.request.schema,`Plugin API ${G} params`),request:F.request,response:F.result,result:J}]})));function VF(G,F){return K0(F0[G].request.schema,F,`Plugin API ${G} params`)}function LF(G,F){return K0(F0[G].result.schema,F,`Plugin API ${G} result`)}var k=[{code:"stale-context",description:"The bound Project, Canvas, node, or connection changed before the call completed.",recoverable:!0}],q=[{code:"permission-denied",description:"The installed Plugin principal does not currently hold the required grant.",recoverable:!1}],o0=[{code:"resource-unavailable",description:"The authoritative Project resource is missing, changed, or cannot be read safely.",recoverable:!0}],r0=[{code:"partial-success",description:"A user-visible Project file was published, but the requested Canvas commit did not complete; retry is unsafe.",recoverable:!1}],U0=u1(r1("1.0.0",[H({id:"host.context.get",completion:"cancelable",grant:null,scope:"connection",sideEffect:"read",errors:k,docs:{summary:"Read the bounded context attached to the current Plugin connection.",description:"Returns only renderer-safe identifiers and feature metadata for the exact live connection; it grants no additional authority.",request:"No parameters.",response:"The current Plugin, Project, Canvas, node, and negotiated Host API context when present."}}),H({id:"canvas.inputs.list",completion:"cancelable",grant:"canvas.connectedInputs.read",scope:"own-node",sideEffect:"read",errors:[...k,...q],docs:{summary:"List direct incoming inputs of the owning Plugin node.",description:"Derives pathless input metadata from authoritative direct incoming Canvas edges and never reads resource bytes.",request:"No parameters; the owning node comes from the bound connection.",response:"A bounded list of direct incoming input descriptors and opaque input keys."}}),H({id:"canvas.inputs.open",completion:"cancelable",grant:"canvas.connectedMedia.stream",scope:"own-node",sideEffect:"read",errors:[...k,...q,...o0],docs:{summary:"Open a bounded stream for one previously listed direct input.",description:"Opens host-owned access to the exact authoritative input after topology and resource identity are revalidated.",request:"`{ inputKey }`, using an opaque key returned by canvas.inputs.list.",response:"A connection-bound stream descriptor and safe media metadata.",remarks:"Call canvas.inputs.close when the stream is no longer needed."}}),H({id:"canvas.inputs.close",completion:"cancelable",grant:"canvas.connectedMedia.stream",scope:"own-node",sideEffect:"write",errors:[...k,...q],docs:{summary:"Close one connection-bound input stream.",description:"Releases a stream created by canvas.inputs.open without changing Canvas or Project state.",request:"The stream handle returned by canvas.inputs.open.",response:"An acknowledgement; closing an already closed handle is idempotent."}}),H({id:"canvas.node.get",completion:"cancelable",grant:"canvas.node.read",scope:"own-node",sideEffect:"read",errors:[...k,...q],docs:{summary:"Read the owning Plugin node projection.",description:"Returns a bounded renderer-safe projection of the exact node bound to the connection.",request:"No parameters; the owning node comes from the bound connection.",response:"The owning node identity, revision, geometry, and Plugin state projection."}}),H({id:"canvas.node.state.replace",completion:"commit-preserving",grant:"canvas.node.write",scope:"own-node",sideEffect:"write",errors:[...k,...q],docs:{summary:"Replace the owning node's bounded Plugin state.",description:"Commits only the namespaced Plugin state through the authoritative Canvas application service with revision checks.",request:"`{ state }`, where state is a bounded JSON value.",response:"`{ updated: true }` after the authoritative state replacement commits."}}),H({id:"canvas.resource.image.create",completion:"commit-preserving",grant:"canvas.image.write",scope:"own-node",sideEffect:"write",errors:[...k,...q,...r0],docs:{summary:"Create a Project-backed Canvas image through the host lifecycle.",description:"Admits bounded image content as a user-visible Project resource and commits its Canvas reference without exposing native paths.",request:"`{ dataUrl, name }`, containing a bounded validated image data URL and safe file name.",response:"The created renderer-safe image result after Project publication and Canvas commit."}}),H({id:"project.file.text.read",completion:"cancelable",grant:"project.files.read",scope:"project",sideEffect:"read",errors:[...k,...q],docs:{summary:"Read one bounded UTF-8 Project file.",description:"Reads through the scoped Project Files capability using a normalized Project-relative path and never exposes a native path.",request:"`{ path }`, using a normalized Project-relative portable path.",response:"The bounded UTF-8 file text."}}),H({id:"agent.prompt",completion:"commit-preserving",grant:"agent.prompt",scope:"connection",sideEffect:"execute",errors:[...k,...q],docs:{summary:"Submit a bounded prompt through the host Agent capability.",description:"Uses the current host-owned Agent context; it does not grant direct OpenCode, filesystem, model, or credential access.",request:"`{ text }`, containing the bounded prompt text.",response:"`{ text }`, containing the bounded host acknowledgement."}}),H({id:"generation.tools.list",completion:"cancelable",grant:"generation.execute",scope:"plugin",sideEffect:"read",errors:q,docs:{summary:"List generation tools available to the installed Plugin principal.",description:"Returns normalized tool metadata derived from active verified contributions without exposing executable paths or credentials.",request:"Optional `{ output }` modality filter; omitting params lists every admitted modality.",response:"A bounded list of available generation tools and their public input contracts."}}),H({id:"generation.execute",completion:"commit-preserving",grant:"generation.execute",scope:"plugin",sideEffect:"execute",errors:[...k,...q,...o0,...r0],docs:{summary:"Execute one selected generation tool through the shared host executor.",description:"Revalidates the active Plugin, authorized executable, inputs, cancellation, and live resource guards immediately before execution.",request:"`{ output?, prompt, references?, resultMode?, toolId? }`, validated against the selected tool.",response:"The bounded selected tool result, created node ids, authoritative revision, and warnings."}}),H({id:"projects.list",completion:"cancelable",audience:["web-plugin","companion"],grant:"projects.read",scope:"plugin",sideEffect:"read",errors:q,docs:{summary:"List Projects visible to the installed Plugin principal.",description:"Returns portable Project identities and display metadata without native paths or private Project state.",request:"No parameters.",response:"A bounded list of renderer-safe Project summaries."}}),H({id:"canvas.catalog.list",completion:"cancelable",audience:["web-plugin","companion"],grant:"canvas.catalog.read",scope:"project",sideEffect:"read",errors:[...k,...q],docs:{summary:"List Canvas catalog entries for one authorized Project.",description:"Reads the Project-owned Canvas catalog without selecting a Project or Canvas in the Workbench.",request:"`{ projectId }`, naming one explicit portable Project.",response:"A bounded list of portable Canvas catalog entries."}}),H({id:"canvas.document.get",completion:"cancelable",audience:["web-plugin","companion"],grant:"canvas.document.read",scope:"canvas",sideEffect:"read",errors:[...k,...q],docs:{summary:"Read one authorized Canvas document projection.",description:"Returns a bounded portable structure or geometry projection from Main's authoritative Canvas application service.",request:"`{ ref, projection }`, using an explicit portable Project/Canvas reference and supported projection.",response:"The requested pathless document projection and authoritative revision."}}),H({id:"canvas.nodes.query",completion:"cancelable",audience:["web-plugin","companion"],grant:"canvas.document.read",scope:"canvas",sideEffect:"read",errors:[...k,...q],docs:{summary:"Query bounded node projections in one authorized Canvas.",description:"Executes a host-defined bounded query without exposing native paths or resource bytes.",request:"`{ ref, query }`, using an explicit portable Project/Canvas reference and bounded query.",response:"Matching node projections and the authoritative Canvas revision."}}),H({id:"canvas.transaction.execute",completion:"commit-preserving",audience:["web-plugin","companion"],grant:"canvas.document.write",scope:"canvas",sideEffect:"write",errors:[...k,...q],docs:{summary:"Commit one non-empty revision-bound Canvas transaction.",description:"Validates bounded commands against one authoritative revision and persists the accepted transaction atomically.",request:"`{ ref, expectedRevision, commands, transactionId }` with a bounded non-empty command list.",response:"The committed authoritative revision and bounded command results."}}),H({id:"canvas.events.subscribe",completion:"cancelable",audience:["web-plugin","companion"],grant:"canvas.events.subscribe",scope:"canvas",sideEffect:"subscribe",errors:[...k,...q],docs:{summary:"Subscribe to bounded events for one authorized Canvas.",description:"Creates a connection-scoped subscription; events are revisioned invalidations or safe projections, never native data.",request:"`{ ref }`, using an explicit portable Project/Canvas reference.",response:"A connection-bound subscription identifier."}}),H({id:"canvas.events.unsubscribe",completion:"cancelable",audience:["web-plugin","companion"],grant:"canvas.events.subscribe",scope:"canvas",sideEffect:"subscribe",errors:[...k,...q],docs:{summary:"Close one connection-bound Canvas event subscription.",description:"Releases a subscription created by canvas.events.subscribe without changing Canvas state.",request:"The subscription identifier returned by canvas.events.subscribe.",response:"An acknowledgement; closing an already closed subscription is idempotent."}})])),u0=U0.apis.map(({id:G})=>G).sort();if(u0.length!==I0.length||u0.some((G,F)=>G!==I0[F]))throw TypeError("Plugin API Catalog and portable method contracts are incomplete or inconsistent");var NF=U0.version,M0=Number(NF.split(".")[0]),N1=new Map(U0.apis.map((G)=>[G.id,G])),OF=new Set(N1.keys());function N0(G){return typeof G==="string"&&OF.has(G)}function O1(G){return N1.get(G)}var zF=/^[a-z][a-z0-9]*(?:\.[a-z][a-z0-9]*)+$/;function AF(G){return typeof G==="object"&&G!==null&&!Array.isArray(G)}function n0(G,F){if(!Array.isArray(G))throw TypeError(`${F} must be an array`);let J=[],Q=new Set;for(let X of G){if(typeof X!=="string"||!zF.test(X))throw TypeError(`${F} contains an invalid Plugin API id: ${String(X)}`);if(Q.has(X))throw TypeError(`${F} contains a duplicate Plugin API id: ${X}`);Q.add(X),J.push(X)}return J}function RF(G){let F=b0(G),J=[],Q=[];for(let X of F.required){if(!N0(X))throw TypeError(`Plugin API declaration contains an unknown Plugin API id: ${X}`);J.push(X)}for(let X of F.optional){if(!N0(X))throw TypeError(`Plugin API declaration contains an unknown Plugin API id: ${X}`);Q.push(X)}return Object.freeze({major:M0,required:Object.freeze(J),optional:Object.freeze(Q)})}function b0(G){if(!AF(G))throw TypeError("Plugin API declaration must be an object");if(Object.keys(G).some((Z)=>Z!=="major"&&Z!=="required"&&Z!=="optional"))throw TypeError("Plugin API declaration contains an unknown field");if(G.major!==M0)throw TypeError(`Plugin API declaration major must be ${M0}`);let J=n0(G.required,"Plugin API declaration required"),Q=n0(G.optional,"Plugin API declaration optional"),X=new Set(J),Y=Q.find((Z)=>X.has(Z));if(Y)throw TypeError(`Plugin API cannot be both required and optional: ${Y}`);return Object.freeze({major:M0,required:Object.freeze(J),optional:Object.freeze(Q)})}function EF(G,F){if(G.required.includes(F))return"required";if(G.optional.includes(F))return"optional";return}function t0(G,F){return EF(G,F)!==void 0}class z1 extends Error{availability;constructor(G){super(`Plugin API ${G.id} is unavailable: ${G.reason}`);this.name="PluginApiUnavailableError",this.availability=G}}function TF(G,F){return typeof F==="string"&&O1(G).errors.some((J)=>J.code===F)}function BF(G,F){if(!F||typeof F!=="object"||Array.isArray(F))throw TypeError(`Plugin API ${G} failure must be an object`);let J=F;if(Object.keys(J).some((X)=>!["code","kind","message","recoverable"].includes(X))||!Object.prototype.hasOwnProperty.call(J,"code")||!Object.prototype.hasOwnProperty.call(J,"message")||!Object.prototype.hasOwnProperty.call(J,"recoverable")||J.kind!=="api"||!TF(G,J.code)||typeof J.message!=="string"||J.message.length<1||J.message.length>4096||typeof J.recoverable!=="boolean")throw TypeError(`Plugin API ${G} failure is invalid`);let Q=O1(G).errors.find(({code:X})=>X===J.code);if(J.recoverable!==Q.recoverable)throw TypeError(`Plugin API ${G} failure recoverability does not match the Catalog`);return Object.freeze({code:J.code,kind:"api",message:J.message,recoverable:J.recoverable})}var HF=/^[a-z][a-z0-9]*(?:\.[a-z][a-z0-9-]*)+$/,wF=/^[a-z][a-z0-9]*(?:[._-][a-z0-9]+)*$/,CF=/^[A-Za-z][A-Za-z0-9_-]{0,63}$/,PF=/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/,qF=new Set(["none","read","write","execute","subscribe"]),A1=128,kF=64,IF=8,gF=16384,xF=256;function d0(G){return typeof G==="string"&&G.length<=160&&HF.test(G)}function u(G,F){if(!G||typeof G!=="object"||Array.isArray(G))throw TypeError(`${F} must be an object`);let J=Object.getPrototypeOf(G);if(J!==Object.prototype&&J!==null)throw TypeError(`${F} must be a plain object`);return G}function d(G,F,J,Q){let X=new Set([...F,...J]);if(F.some((Y)=>!Object.prototype.hasOwnProperty.call(G,Y))||Object.keys(G).some((Y)=>!X.has(Y)))throw TypeError(`${Q} contains unsupported or missing fields`)}function i(G,F,J=2000){if(typeof G!=="string"||G.length<1||G.length>J||G!==G.trim()||/[\u0000-\u001f\u007f]/u.test(G))throw TypeError(`${F} must be a bounded, trimmed string`);return G}function j0(G,F,J){if(!Number.isSafeInteger(G)||Number(G)<0||Number(G)>J)throw TypeError(`${F} must be a bounded non-negative integer`);return Number(G)}function g0(G,F){if(typeof G!=="string"||!PF.test(G))throw TypeError(`${F} must be a strict semantic version`);return G}function fF(G,F){let J=G.split(".").map(Number),Q=F.split(".").map(Number);for(let X=0;X<3;X+=1){let Y=J[X]-Q[X];if(Y!==0)return Y}return 0}function x0(G,F,J){if(J>IF)throw TypeError(`${F} exceeds the schema depth limit`);let Q=u(G,F);if(Q.type==="null"||Q.type==="boolean")return d(Q,["type"],[],F),Object.freeze({type:Q.type});if(Q.type==="number"||Q.type==="integer"){d(Q,["type"],["minimum","maximum"],F);let{minimum:X,maximum:Y}=Q;if(X!==void 0&&(typeof X!=="number"||!Number.isFinite(X)))throw TypeError(`${F}.minimum must be finite`);if(Y!==void 0&&(typeof Y!=="number"||!Number.isFinite(Y)))throw TypeError(`${F}.maximum must be finite`);if(X!==void 0&&Y!==void 0&&X>Y)throw TypeError(`${F} minimum exceeds maximum`);return Object.freeze({type:Q.type,...X===void 0?{}:{minimum:X},...Y===void 0?{}:{maximum:Y}})}if(Q.type==="string"){if(!Object.prototype.hasOwnProperty.call(Q,"maxLength"))throw TypeError(`${F}.maxLength is required to keep values bounded`);d(Q,["type","maxLength"],["minLength","enum"],F);let X=j0(Q.maxLength,`${F}.maxLength`,gF),Y=Q.minLength===void 0?void 0:j0(Q.minLength,`${F}.minLength`,X),Z;if(Q.enum!==void 0){if(!Array.isArray(Q.enum)||Q.enum.length<1||Q.enum.length>128||Q.enum.some((_)=>typeof _!=="string"||_.length>X)||new Set(Q.enum).size!==Q.enum.length)throw TypeError(`${F}.enum must contain unique bounded strings`);Z=Object.freeze([...Q.enum])}return Object.freeze({type:"string",maxLength:X,...Y===void 0?{}:{minLength:Y},...Z===void 0?{}:{enum:Z}})}if(Q.type==="array"){d(Q,["type","items","maxItems"],["minItems"],F);let X=j0(Q.maxItems,`${F}.maxItems`,xF),Y=Q.minItems===void 0?void 0:j0(Q.minItems,`${F}.minItems`,X);return Object.freeze({type:"array",items:x0(Q.items,`${F}.items`,J+1),maxItems:X,...Y===void 0?{}:{minItems:Y}})}if(Q.type==="object"){if(d(Q,["type","properties","required","additionalProperties"],[],F),Q.additionalProperties!==!1)throw TypeError(`${F}.additionalProperties must be false`);let X=u(Q.properties,`${F}.properties`),Y=Object.keys(X);if(Y.length>kF)throw TypeError(`${F} has too many properties`);if(Y.some((_)=>!CF.test(_)))throw TypeError(`${F} contains an invalid property name`);if(!Array.isArray(Q.required)||Q.required.some((_)=>typeof _!=="string"||!Y.includes(_))||new Set(Q.required).size!==Q.required.length)throw TypeError(`${F}.required must contain unique declared properties`);let Z=Object.fromEntries(Y.sort().map((_)=>[_,x0(X[_],`${F}.properties.${_}`,J+1)]));return Object.freeze({type:"object",properties:Object.freeze(Z),required:Object.freeze([...Q.required].sort()),additionalProperties:!1})}throw TypeError(`${F}.type is unsupported`)}function O0(G,F){let J=x0(G,F,0);if(J.type!=="object")throw TypeError(`${F} must be a closed object schema`);return J}function hF(G,F){let J=u(G,F);d(J,["id","inputSchema","outputSchema","version"],[],F);let Q=i(J.id,`${F}.id`,160);if(!d0(Q))throw TypeError(`${F}.id is invalid`);let X=u(J.version,`${F}.version`);d(X,["minimum","maximumExclusive"],[],`${F}.version`);let Y=g0(X.minimum,`${F}.version.minimum`),Z=g0(X.maximumExclusive,`${F}.version.maximumExclusive`);if(fF(Y,Z)>=0)throw TypeError(`${F}.version must be a non-empty half-open interval`);return Object.freeze({id:Q,inputSchema:O0(J.inputSchema,`${F}.inputSchema`),outputSchema:O0(J.outputSchema,`${F}.outputSchema`),version:Object.freeze({minimum:Y,maximumExclusive:Z})})}function i0(G,F){if(!Array.isArray(G)||G.length>A1)throw TypeError(`${F} must be a bounded array`);let J=G.map((Q,X)=>hF(Q,`${F}[${X}]`)).sort((Q,X)=>Q.id.localeCompare(X.id));if(J.some((Q,X)=>X>0&&J[X-1].id===Q.id))throw TypeError(`${F} contains a duplicate capability id`);return Object.freeze(J)}function yF(G,F){let J=u(G,F);d(J,["id","version","operation","sideEffect","inputSchema","outputSchema","docs"],[],F);let Q=i(J.id,`${F}.id`,160);if(!d0(Q))throw TypeError(`${F}.id is invalid`);let X=i(J.operation,`${F}.operation`,128);if(!wF.test(X))throw TypeError(`${F}.operation is invalid`);if(!qF.has(J.sideEffect))throw TypeError(`${F}.sideEffect is invalid`);let Y=u(J.docs,`${F}.docs`);d(Y,["summary","request","response"],["remarks"],`${F}.docs`);let Z=Object.freeze({summary:i(Y.summary,`${F}.docs.summary`),request:i(Y.request,`${F}.docs.request`),response:i(Y.response,`${F}.docs.response`),...Y.remarks===void 0?{}:{remarks:i(Y.remarks,`${F}.docs.remarks`)}});return Object.freeze({id:Q,version:g0(J.version,`${F}.version`),operation:X,sideEffect:J.sideEffect,inputSchema:O0(J.inputSchema,`${F}.inputSchema`),outputSchema:O0(J.outputSchema,`${F}.outputSchema`),docs:Z})}function cF(G){let F=u(G,"Plugin capability declaration");if(d(F,["exports","imports"],[],"Plugin capability declaration"),!Array.isArray(F.exports)||F.exports.length>A1)throw TypeError("Plugin capability exports must be a bounded array");let J=F.exports.map((M,K)=>yF(M,`Plugin capability exports[${K}]`)).sort((M,K)=>M.id.localeCompare(K.id));if(J.some((M,K)=>K>0&&J[K-1].id===M.id))throw TypeError("Plugin capability exports contain a duplicate capability id");if(new Set(J.map((M)=>M.operation)).size!==J.length)throw TypeError("Plugin capability exports contain a duplicate provider operation");let Q=u(F.imports,"Plugin capability imports");d(Q,["required","optional"],[],"Plugin capability imports");let X=i0(Q.required,"Plugin required capability imports"),Y=i0(Q.optional,"Plugin optional capability imports"),Z=new Set(X.map(({id:M})=>M)),_=Y.find(({id:M})=>Z.has(M));if(_)throw TypeError(`Plugin capability import cannot be both required and optional: ${_.id}`);return Object.freeze({exports:Object.freeze(J),imports:Object.freeze({required:X,optional:Y})})}function f0(G,F,J,Q){if(G.type==="null"){if(F!==null)throw TypeError(`${J} must be null`);return}if(G.type==="boolean"){if(typeof F!=="boolean")throw TypeError(`${J} must be boolean`);return}if(G.type==="number"||G.type==="integer"){if(typeof F!=="number"||!Number.isFinite(F)||G.type==="integer"&&!Number.isSafeInteger(F))throw TypeError(`${J} must be a finite ${G.type==="integer"?"safe integer":"number"}`);if(G.minimum!==void 0&&FG.maximum)throw TypeError(`${J} exceeds maximum`);return}if(G.type==="string"){if(typeof F!=="string"||F.length<(G.minLength??0)||F.length>G.maxLength||G.enum!==void 0&&!G.enum.includes(F))throw TypeError(`${J} is not an admitted string`);return}if(!F||typeof F!=="object")throw TypeError(`${J} must be ${G.type}`);if(Q.has(F))throw TypeError(`${J} cannot be cyclic`);Q.add(F);try{if(G.type==="array"){if(!Array.isArray(F)||F.length<(G.minItems??0)||F.length>G.maxItems)throw TypeError(`${J} is not an admitted array`);F.forEach((Z,_)=>f0(G.items,Z,`${J}[${_}]`,Q));return}if(Array.isArray(F))throw TypeError(`${J} must be an object`);let X=Object.getPrototypeOf(F);if(X!==Object.prototype&&X!==null)throw TypeError(`${J} must be a plain object`);let Y=F;for(let Z of G.required)if(!Object.prototype.hasOwnProperty.call(Y,Z))throw TypeError(`${J}.${Z} is required`);for(let[Z,_]of Object.entries(Y)){let M=G.properties[Z];if(!M)throw TypeError(`${J} contains unsupported property: ${Z}`);f0(M,_,`${J}.${Z}`,Q)}}finally{Q.delete(F)}}function a0(G,F,J="Plugin capability value"){f0(G,F,J,new Set)}var bF=/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[A-Za-z-][0-9A-Za-z-]*)(?:\.(?:0|[1-9]\d*|\d*[A-Za-z-][0-9A-Za-z-]*))*))?(?:\+([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?$/,dF=/^(CON|PRN|AUX|NUL|COM[1-9¹²³]|LPT[1-9¹²³]|CONIN\$|CONOUT\$)$/i;function A(G,F){if(!G||typeof G!=="object"||Array.isArray(G))throw TypeError(`${F} must be an object`);let J=Object.getPrototypeOf(G);if(J!==Object.prototype&&J!==null)throw TypeError(`${F} must be a plain object`);return G}function R(G,F,J){let Q=new Set(F),X=Object.keys(G).find((Y)=>!Q.has(Y));if(X)throw TypeError(`${J} contains an unsupported field: ${X}`)}function E(G,F,J){if(typeof G!=="string"||G.length<1||G.length>J||G!==G.trim()||/[\u0000-\u001f\u007f]/u.test(G))throw TypeError(`${F} must be a bounded, trimmed string`);return G}function c(G,F,J,Q=!1){if(!Array.isArray(G)||G.length>J||Q&&G.length===0)throw TypeError(`${F} must be ${Q?"a non-empty ":"a "}bounded array with at most ${J} items`);return G}function R1(G){if(G&&typeof G==="object"&&!Object.isFrozen(G)){for(let F of Object.values(G))R1(F);Object.freeze(G)}return G}function vF(G){let F=E(G,"Plugin version",128);if(!bF.test(F))throw TypeError("Plugin version must be valid SemVer");return F}function R0(G){let F=G.split(".")[0]??"";if(!G||G.length>255||G==="."||G===".."||/[\\/:*?"<>|\u0000-\u001f\u007f]/u.test(G)||/[. ]$/u.test(G)||dF.test(F))throw TypeError(`Plugin path contains an invalid Windows filename: ${G}`);return G}function E1(G){let F=E(G,"Plugin id",80);if(!/^[a-z0-9]+(?:-[a-z0-9]+)*$/u.test(F))throw TypeError("Plugin id must use kebab-case");return R0(F),F}function X0(G,F="Plugin path"){let J=E(G,F,1024);if(J.includes("\\")||J.startsWith("/")||/^[A-Za-z]:/u.test(J)||J.startsWith("//"))throw TypeError(`${F} must be a portable relative path`);let Q=J.split("/");if(Q.some((X)=>!X||X==="."||X===".."))throw TypeError(`${F} must be a portable relative path`);return Q.forEach(R0),J}function T0(G,F,J){if(G===void 0)return;let Q=c(G,F,64).map((X)=>J(E(X,F,128)));if(new Set(Q).size!==Q.length)throw TypeError(`${F} contains duplicate values`);return Q}function Y0(G,F,J=80){let Q=E(G,F,J);if(!/^[a-z0-9]+(?:[._-][a-z0-9]+)*$/u.test(Q))throw TypeError(`${F} is invalid: ${Q}`);return Q}var l="convax.plugin-host/8",mF=KF,pF=MF,B0=1048576,l0=4194304,e0=16,sF=128,oF=64,V0=Math.ceil(mF/2),rF=/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/,uF=new Set(["not-declared","provider-missing","provider-incompatible","provider-ambiguous","self-provider","dependency-cycle","setup-required","disabled","recovering","contract-mismatch"]),T1=Object.freeze({canceled:{recoverable:!0},"contract-mismatch":{recoverable:!1},"depth-exceeded":{recoverable:!1},"duplicate-request":{recoverable:!1},"execution-failed":{recoverable:!1},"invalid-input":{recoverable:!1},"invalid-output":{recoverable:!1},overloaded:{recoverable:!0},"provider-unavailable":{recoverable:!0},"reentrant-call":{recoverable:!1}}),B1=new Set(Object.keys(T1)),H1=Object.freeze({canceled:{recoverable:!0},"internal-error":{recoverable:!1},"invalid-request":{recoverable:!1},overloaded:{recoverable:!0},"transport-closed":{recoverable:!0}}),w1=new Set(Object.keys(H1)),nF=new Set(U0.apis.flatMap((G)=>G.errors.map(({code:F})=>F)));function e(G){if(!G||typeof G!=="object"||Array.isArray(G))return;let F=Object.getPrototypeOf(G);return F===Object.prototype||F===null?G:void 0}function F1(G){let F=2;for(let J=0;J=55296&&Q<=57343){let X=G.charCodeAt(J+1);if(Q>=55296&&Q<=56319&&X>=56320&&X<=57343)F+=4,J+=1;else F+=6}else if(Q<128)F+=1;else if(Q<2048)F+=2;else F+=3}return F}function G1(G,F,J="Plugin Host message"){if(!Number.isSafeInteger(F)||F<1)throw TypeError(`${J} byte limit is invalid`);let Q=[{depth:0,value:G}],X=new WeakSet,Y=0,Z=0,_=(M)=>{if(Y+=M,Y>F)throw RangeError(`${J} exceeds ${F} bytes`)};while(Q.length>0){let M=Q.pop(),K=M.value;if(K===null){_(4);continue}if(typeof K==="string"){_(F1(K));continue}if(typeof K==="boolean"){_(K?4:5);continue}if(typeof K==="number"){if(!Number.isFinite(K))throw TypeError(`${J} must contain finite JSON numbers`);_(Object.is(K,-0)?1:String(K).length);continue}if(!K||typeof K!=="object")throw TypeError(`${J} must be a JSON value`);if(M.depth>oF||X.has(K))throw TypeError(`${J} must be a bounded acyclic JSON tree`);if(X.add(K),Array.isArray(K)){if(Z+=K.length,Z>V0)throw RangeError(`${J} exceeds ${V0} JSON entries`);if(_(2+Math.max(0,K.length-1)),Object.getOwnPropertySymbols(K).length>0)throw TypeError(`${J} arrays must not contain symbol properties`);let O=0;for(let V in K){if(!Object.prototype.hasOwnProperty.call(K,V))continue;if(!/^(0|[1-9]\d*)$/u.test(V)||Number(V)>=K.length)throw TypeError(`${J} arrays must contain only indexed entries`);let P=Object.getOwnPropertyDescriptor(K,V);if(!P?.enumerable||!("value"in P))throw TypeError(`${J} arrays must contain enumerable data properties`);O+=1,Q.push({depth:M.depth+1,value:P.value})}if(O!==K.length)throw TypeError(`${J} arrays must be dense JSON arrays`);continue}let D=Object.getPrototypeOf(K);if(D!==Object.prototype&&D!==null)throw TypeError(`${J} must contain plain JSON objects`);if(Object.getOwnPropertySymbols(K).length>0)throw TypeError(`${J} must not contain symbol properties`);_(2);let W=0;for(let O in K){if(!Object.prototype.hasOwnProperty.call(K,O))continue;let V=Object.getOwnPropertyDescriptor(K,O);if(!V?.enumerable||!("value"in V))throw TypeError(`${J} objects must contain enumerable data properties`);if(W+=1,Z+=1,Z>V0)throw RangeError(`${J} exceeds ${V0} JSON entries`);_((W===1?0:1)+F1(O)+1),Q.push({depth:M.depth+1,value:V.value})}}return Y}function r(G,F,J=[]){let Q=new Set([...F,...J]);return F.every((X)=>Object.prototype.hasOwnProperty.call(G,X))&&Object.keys(G).every((X)=>Q.has(X))}function C1(G){return typeof G==="string"&&G.length>0&&G.length<=sF&&G===G.trim()&&!/[\u0000-\u001f\u007f]/u.test(G)}function tF(G){return typeof G==="string"&&G.length>0&&G.length<=128&&G===G.trim()&&!/[\u0000-\u001f\u007f]/u.test(G)}function P1(G){let F=e(G);if(!F||!r(F,["pluginId","protocol","type"])||F.protocol!==l||F.type!=="connect")return!1;try{return E1(F.pluginId),!0}catch{return!1}}function iF(G){let F=e(G);if(!F||F.protocol!==l||F.type!=="response"||!C1(F.id))return!1;if(F.ok===!0)return r(F,["id","ok","protocol","result","type"]);if(F.ok!==!1||!r(F,["error","id","ok","protocol","type"]))return!1;let J=e(F.error);return Boolean(J&&r(J,["code","kind","message","recoverable"])&&typeof J.code==="string"&&(J.kind==="api"&&nF.has(J.code)||J.kind==="capability"&&B1.has(J.code)||J.kind==="protocol"&&w1.has(J.code))&&typeof J.message==="string"&&J.message.length>0&&J.message.length<=4096&&typeof J.recoverable==="boolean")}function aF(G){let F=e(G);return Boolean(F&&r(F,["command","protocol","type"],["params"])&&F.protocol===l&&F.type==="command"&&tF(F.command))}function lF(G){let F=e(G);if(!F||typeof F.available!=="boolean")throw TypeError("Plugin capability availability must be a closed object");let J=F.requirement;if(J!=="required"&&J!=="optional")throw TypeError("Plugin capability availability requirement is invalid");if(!d0(F.capabilityId))throw TypeError("Plugin capability availability id is invalid");if(F.available){if(!r(F,["available","capabilityId","requirement","version"])||typeof F.version!=="string"||!rF.test(F.version))throw TypeError("Available Plugin capability result is invalid");return Object.freeze({available:!0,capabilityId:F.capabilityId,requirement:J,version:F.version})}if(!r(F,["available","capabilityId","reason","recoverable","requirement"])||typeof F.reason!=="string"||!uF.has(F.reason)||typeof F.recoverable!=="boolean")throw TypeError("Unavailable Plugin capability result is invalid");return Object.freeze({available:!1,capabilityId:F.capabilityId,reason:F.reason,recoverable:F.recoverable,requirement:J})}function eF(G){let F=e(G);if(!F||!r(F,["code","kind","message","recoverable"])||F.kind!=="capability"||typeof F.code!=="string"||!B1.has(F.code)||typeof F.message!=="string"||F.message.length<1||F.message.length>4096||typeof F.recoverable!=="boolean")throw TypeError("Plugin capability failure is invalid");let J=F.code;if(F.recoverable!==T1[J].recoverable)throw TypeError("Plugin capability failure recoverability is invalid");return Object.freeze({code:J,kind:"capability",message:F.message,recoverable:F.recoverable})}function q1(G){let F=e(G);if(!F||!r(F,["code","kind","message","recoverable"])||F.kind!=="protocol"||typeof F.code!=="string"||!w1.has(F.code)||typeof F.message!=="string"||F.message.length<1||F.message.length>4096||typeof F.recoverable!=="boolean")throw TypeError("Plugin Host protocol failure is invalid");let J=F.code;if(F.recoverable!==H1[J].recoverable)throw TypeError("Plugin Host protocol failure recoverability is invalid");return Object.freeze({code:J,kind:"protocol",message:F.message,recoverable:F.recoverable})}var F8=["download","edit","open","play","refresh","settings","sparkles","upload"],k1=/^[a-z][a-z0-9]*(?:[._-][a-z0-9]+)*$/,G8=/^[a-z][a-z0-9]*(?:[._-][a-z0-9]+)*$/,J8=/^[a-z][a-z0-9]*(?:[._-][a-z0-9]+)*$/,Q8=128,J1=128,Q1=1e4;function X8(G){return Boolean(G)&&typeof G==="object"&&!Array.isArray(G)}function S0(G,F){if(!X8(G))throw TypeError(`${F} must be an object`);let J=Object.getPrototypeOf(G);if(J!==Object.prototype&&J!==null)throw TypeError(`${F} must be a plain object`);return G}function D0(G,F,J,Q){let X=new Set([...F,...J]);if(F.some((Y)=>!Object.prototype.hasOwnProperty.call(G,Y))||Object.keys(G).some((Y)=>!X.has(Y)))throw TypeError(`${Q} contains unsupported or missing fields`)}function z0(G,F,J){if(typeof G!=="string"||G.length<1||G.length>J||G!==G.trim()||/[\u0000-\u001f\u007f]/u.test(G))throw TypeError(`${F} must be a bounded, trimmed string`);return G}function A0(G,F,J,Q){let X=z0(G,F,Q);if(!J.test(X))throw TypeError(`${F} must be a stable Plugin-local id`);return X}function Y8(G,F){if(!Number.isSafeInteger(G)||Number(G)<-Q1||Number(G)>Q1)throw TypeError(`${F} must be a bounded safe integer`);return Number(G)}function Z8(G,F){let J=S0(G,F);return D0(J,["default"],["zh-CN"],F),Object.freeze({default:z0(J.default,`${F}.default`,120),...J["zh-CN"]===void 0?{}:{"zh-CN":z0(J["zh-CN"],`${F}.zh-CN`,120)}})}function _8(G){return F8.some((F)=>F===G)}function $8(G,F){let J=`Plugin UI commands[${F}]`,Q=S0(G,J);D0(Q,["id","title","target"],["icon"],J);let X=S0(Q.target,`${J}.target`);if(X.type!=="renderer-message")throw TypeError(`${J}.target.type must be renderer-message`);D0(X,["type","message"],[],`${J}.target`);let Y=Q.icon;if(Y!==void 0&&!_8(Y))throw TypeError(`${J}.icon must be a supported Host icon token`);return Object.freeze({id:A0(Q.id,`${J}.id`,k1,128),title:Z8(Q.title,`${J}.title`),target:Object.freeze({type:"renderer-message",message:z0(X.message,`${J}.target.message`,128)}),...Y===void 0?{}:{icon:Y}})}function I1(G,F,J,Q){let X=S0(G,F);return D0(X,J,Q,F),{input:X,id:A0(X.id,`${F}.id`,G8,128),command:A0(X.command,`${F}.command`,k1,128),...X.order===void 0?{}:{order:Y8(X.order,`${F}.order`)}}}function K8(G,F){let{input:J,...Q}=I1(G,`Plugin UI toolbar[${F}]`,["id","command"],["order"]);return Object.freeze(Q)}function M8(G,F){let J=`Plugin UI menus[${F}]`,Q=I1(G,J,["id","command","placement"],["group","order"]);if(Q.input.placement!=="overflow")throw TypeError(`${J}.placement must be overflow`);let X=Q.input.group===void 0?void 0:A0(Q.input.group,`${J}.group`,J8,64),{input:Y,...Z}=Q;return Object.freeze({...Z,placement:"overflow",...X===void 0?{}:{group:X}})}function H0(G,F,J){if(!Array.isArray(G)||G.length>J)throw TypeError(`${F} must be a bounded array`);return G}function w0(G,F){let J=new Set;for(let Q of G){if(J.has(Q.id))throw TypeError(`${F} contains a duplicate id: ${Q.id}`);J.add(Q.id)}}function X1(G,F){let J=new Set;for(let Q of G){if(J.has(Q.command))throw TypeError(`${F} contains a duplicate command reference: ${Q.command}`);J.add(Q.command)}}function S8(G){let F=S0(G,"Plugin Canvas UI contribution");D0(F,[],["commands","menus","toolbar"],"Plugin Canvas UI contribution");let J=Object.freeze(H0(F.commands===void 0?[]:F.commands,"Plugin UI commands",Q8).map($8)),Q=Object.freeze(H0(F.menus===void 0?[]:F.menus,"Plugin UI menus",J1).map(M8)),X=Object.freeze(H0(F.toolbar===void 0?[]:F.toolbar,"Plugin UI toolbar",J1).map(K8));w0(J,"Plugin UI commands"),w0(Q,"Plugin UI menus"),w0(X,"Plugin UI toolbar");let Y=new Set(Q.map((W)=>W.id)),Z=X.find((W)=>Y.has(W.id));if(Z)throw TypeError(`Plugin UI placements contain a duplicate id: ${Z.id}`);X1(Q,"Plugin UI menus"),X1(X,"Plugin UI toolbar");let _=new Set(J.map((W)=>W.id)),M=[...Q,...X].find((W)=>!_.has(W.command));if(M)throw TypeError(`Plugin UI placement references an unknown command: ${M.command}`);let K=new Set([...Q,...X].map((W)=>W.command)),D=J.find((W)=>!K.has(W.id));if(D)throw TypeError(`Plugin UI command has no owning-node placement: ${D.id}`);return Object.freeze({commands:J,menus:Q,toolbar:X})}var D8=["time-point","time-range","crop-region","confirmation","immediate"];function U8(G){return D8.some((F)=>F===G)}function W8(G,F){if(G==="image"||G==="video")return G;throw TypeError(`${F} target must be image or video`)}function Y1(G,F){if(!Number.isSafeInteger(G)||Number(G)<1||Number(G)>8192)throw TypeError(`${F} must be an integer between 1 and 8192`);return Number(G)}function j8(G){let F=A(G,"Canvas renderer contribution");if(R(F,["create","extensions","height","mimeTypes","nodeKinds","width"],"Canvas renderer contribution"),F.create!==void 0&&typeof F.create!=="boolean")throw TypeError("Canvas renderer create must be a boolean");let J=T0(F.extensions,"Canvas renderer extensions",(Y)=>{let Z=Y.toLowerCase();if(!/^\.[a-z0-9][a-z0-9._+-]{0,31}$/u.test(Z))throw TypeError(`Invalid Canvas renderer extension: ${Y}`);return Z}),Q=T0(F.mimeTypes,"Canvas renderer MIME types",(Y)=>{let Z=Y.toLowerCase();if(!/^[a-z0-9][a-z0-9!#$&^_.+-]*\/[a-z0-9][a-z0-9!#$&^_.+-]*$/u.test(Z))throw TypeError(`Invalid Canvas renderer MIME type: ${Y}`);return Z}),X=T0(F.nodeKinds,"Canvas renderer node kinds",(Y)=>{if(!/^[a-z][a-z0-9]*(?:[._-][a-z0-9]+)*$/u.test(Y))throw TypeError(`Invalid Canvas renderer node kind: ${Y}`);return Y});if(F.create!==!0&&!J?.length&&!Q?.length&&!X?.length)throw TypeError("Canvas renderer must be creatable or match an extension, MIME type, or node kind");return{...F.create===void 0?{}:{create:F.create},...J===void 0?{}:{extensions:J},...F.height===void 0?{}:{height:Y1(F.height,"Canvas renderer height")},...Q===void 0?{}:{mimeTypes:Q},...X===void 0?{}:{nodeKinds:X},...F.width===void 0?{}:{width:Y1(F.width,"Canvas renderer width")}}}function L0(G,F,J){let Q=A(G,F);return R(Q,["default","zh-CN"],F),{default:E(Q.default,`${F} default`,J),...Q["zh-CN"]===void 0?{}:{"zh-CN":E(Q["zh-CN"],`${F} zh-CN`,J)}}}function V8(G){let F=c(G,"Canvas selection actions",32,!0).map((J,Q)=>{let X=`Canvas selection action ${Q}`,Y=A(J,X);if(Y.action!==void 0){R(Y,["action","description","id","target","title"],X);let D=Y0(Y.id,`${X} id`);if(Y.target!=="video")throw TypeError(`${X} target must be video`);let W=A(Y.action,`${X} action`);if(R(W,["connect","type"],`${X} action`),W.type!=="materialize-own-plugin-node"||W.connect!=="selection-to-created")throw TypeError(`${X} materialization action is not supported`);return{action:{connect:"selection-to-created",type:"materialize-own-plugin-node"},description:L0(Y.description,`${X} description`,2000),id:D,target:"video",title:L0(Y.title,`${X} title`,120)}}R(Y,["description","editor","id","presentation","steps","target","title"],X);let Z=Y0(Y.id,`${X} id`),_=W8(Y.target,X);if(!U8(Y.editor))throw TypeError(`${X} editor is not supported`);let M=Y.editor;if(M==="immediate"!==(_==="image"&&Y.presentation==="cutout-scan")||Y.presentation!==void 0&&Y.presentation!=="cutout-scan")throw TypeError(`${X} immediate editor requires image target and cutout-scan presentation`);let K=c(Y.steps,`${X} steps`,16,!0).map((D,W)=>{let O=`${X} step ${W}`,V=A(D,O);return R(V,["tool"],O),{tool:Y0(V.tool,`${O} tool`)}});if(M!=="confirmation"&&K.length!==1)throw TypeError(`${X} editor requires exactly one step`);return{description:L0(Y.description,`${X} description`,2000),editor:M,id:Z,...Y.presentation===void 0?{}:{presentation:"cutout-scan"},steps:K,target:_,title:L0(Y.title,`${X} title`,120)}});if(new Set(F.map((J)=>J.id)).size!==F.length)throw TypeError("Canvas selection actions contain duplicate ids");return F}function L8(G){let F=A(G,"Canvas contributions");R(F,["commands","menus","renderer","selectionActions","toolbar"],"Canvas contributions");let J=S8({...F.commands===void 0?{}:{commands:F.commands},...F.menus===void 0?{}:{menus:F.menus},...F.toolbar===void 0?{}:{toolbar:F.toolbar}});return{...F.commands===void 0?{}:{commands:J.commands},...F.menus===void 0?{}:{menus:J.menus},...F.renderer===void 0?{}:{renderer:j8(F.renderer)},...F.selectionActions===void 0?{}:{selectionActions:V8(F.selectionActions)},...F.toolbar===void 0?{}:{toolbar:J.toolbar}}}var N8=["text","image","video","audio"],g1=["reference_image","reference_video","first_frame","last_frame","audio","text"],O8=new Set(N8),z8=new Set(g1),A8=/^[a-z][a-z0-9_]{0,63}$/;function R8(G,F){let Q=c(G,F,g1.length).map((X)=>{if(typeof X!=="string"||!z8.has(X))throw TypeError(`${F} contain an unsupported or duplicate role`);return X});if(new Set(Q).size!==Q.length)throw TypeError(`${F} contain an unsupported or duplicate role`);return Q}function E8(G){let F=A(G,"Generation contribution");if(R(F,["models","tools"],"Generation contribution"),!Object.prototype.hasOwnProperty.call(F,"models"))throw TypeError("convax.plugin/8 generation models must be declared explicitly");let J=c(F.tools,"Generation tools",64,!0).map((_,M)=>{let K=`Generation tool ${M}`,D=A(_,K);R(D,["acceptedInputs","delivery","description","id","inputBinding","output","recovery","title"],K);let W=Y0(D.id,`${K} id`);if(typeof D.output!=="string"||!O8.has(D.output))throw TypeError(`${K} output is not supported`);if(D.delivery!==void 0&&D.delivery!=="canvas"&&D.delivery!=="return")throw TypeError(`${K} delivery is not supported`);if(D.delivery==="return"&&D.output!=="text")throw TypeError(`${K} return delivery requires text output`);let O=R8(D.acceptedInputs,`${K} acceptedInputs`);if(D.inputBinding!==void 0&&D.inputBinding!=="direct-incoming")throw TypeError(`${K} input binding is not supported`);if(D.inputBinding==="direct-incoming"&&O.length===0)throw TypeError(`${K} direct-incoming input binding requires accepted inputs`);let V;if(D.recovery!==void 0){let P=A(D.recovery,`${K} recovery`);if(R(P,["mode","schema"],`${K} recovery`),P.schema!=="convax.generation-lro/1"||P.mode!=="long-running-operation")throw TypeError(`${K} recovery contract is not supported`);V={mode:"long-running-operation",schema:"convax.generation-lro/1"}}return{acceptedInputs:O,...D.delivery===void 0?{}:{delivery:D.delivery},description:E(D.description,`${K} description`,2000),id:W,...D.inputBinding===void 0?{}:{inputBinding:D.inputBinding},output:D.output,...V===void 0?{}:{recovery:V},title:E(D.title,`${K} title`,120)}});if(new Set(J.map((_)=>_.id)).size!==J.length)throw TypeError("Generation tools contain duplicate ids");let Q=c(F.models,"Generation models",J.length).map((_,M)=>{let K=`Generation model ${M}`,D=A(_,K);return R(D,["name","tool"],K),{name:E(D.name,`${K} name`,120),tool:Y0(D.tool,`${K} tool`)}});if(new Set(Q.map((_)=>_.tool)).size!==Q.length)throw TypeError("Generation models contain duplicate tool references");let X=new Set(Q.map((_)=>_.tool)),Y=J.find((_)=>_.delivery==="return"&&X.has(_.id));if(Y)throw TypeError(`Generation model cannot reference a return-delivery operation: ${Y.id}`);let Z=J.find((_)=>_.inputBinding!==void 0&&X.has(_.id));if(Z)throw TypeError(`Generation model cannot reference an input-bound operation: ${Z.id}`);return{models:Q,tools:J}}function T8(G){let F=c(G,"Agent tools",32,!0).map((J,Q)=>{let X=`Agent tool ${Q}`,Y=A(J,X);R(Y,["id","tool"],X);let Z=E(Y.id,`${X} id`,64);if(!A8.test(Z))throw TypeError(`${X} id must use lower snake_case`);return{id:Z,tool:Y0(Y.tool,`${X} generation tool`)}});if(new Set(F.map((J)=>J.id)).size!==F.length)throw TypeError("Agent tools contain duplicate ids");if(new Set(F.map((J)=>J.tool)).size!==F.length)throw TypeError("Agent tools contain duplicate generation tool references");return F}function B8(G){let F=A(G,"Agent remote MCP contribution");if(R(F,["headers","oauth","type","url"],"Agent remote MCP contribution"),F.type!=="remote")throw TypeError("Agent MCP type must be remote");let J=E(F.url,"Agent remote MCP URL",2048);try{let X=new URL(J);if(X.protocol!=="https:"||X.username!==""||X.password!==""||X.hash!=="")throw TypeError()}catch{throw TypeError("Agent remote MCP URL must be an absolute HTTPS URL without credentials or a fragment")}if(F.oauth!==void 0&&F.oauth!=="auto"&&F.oauth!=="none")throw TypeError("Agent remote MCP oauth must be auto or none");let Q;if(F.headers!==void 0){let X=A(F.headers,"Agent remote MCP headers"),Y=Object.entries(X);if(Y.length>16)throw TypeError("Agent remote MCP headers must contain at most 16 entries");let Z=new Set;Q={};for(let[_,M]of Y){if(!/^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/u.test(_))throw TypeError(`Agent remote MCP header name is invalid: ${_}`);let K=_.toLowerCase();if(Z.has(K))throw TypeError(`Agent remote MCP headers contain a duplicate name: ${_}`);if(K==="authorization"||K==="cookie"||K==="proxy-authorization")throw TypeError(`Agent remote MCP header is not allowed: ${_}`);let D=E(M,`Agent remote MCP header ${_}`,2048);if(/\{(?:env|file):/iu.test(D)||/\$\{[^}]*\}/u.test(D))throw TypeError(`Agent remote MCP header ${_} must be a literal value`);Z.add(K),Q[_]=D}}return{...Q===void 0?{}:{headers:Q},oauth:F.oauth==="none"?"none":"auto",type:"remote",url:J}}function H8(G){let F=A(G,"Agent contribution");R(F,["mcp","tools"],"Agent contribution");let J=F.tools===void 0?void 0:T8(F.tools),Q=F.mcp===void 0?void 0:B8(F.mcp);if(J===void 0&&Q===void 0)throw TypeError("Agent contribution must declare tools or mcp");return{...Q===void 0?{}:{mcp:Q},...J===void 0?{}:{tools:J}}}function w8(G){let F=new Map(G.generation?.tools.map((Q)=>[Q.id,Q])??[]),J=new Set(G.generation?.models.map((Q)=>Q.tool)??[]);for(let Q of J)if(!F.has(Q))throw TypeError(`Generation model references an unknown tool: ${Q}`);for(let Q of G.agent?.tools??[]){if(!F.has(Q.tool))throw TypeError(`Agent tool references an unknown generation tool: ${Q.tool}`);if(J.has(Q.tool))throw TypeError(`Agent tool must reference an operation, not a generation model: ${Q.tool}`)}for(let Q of G.selectionActions??[]){if(!("steps"in Q))continue;for(let X of Q.steps){let Y=F.get(X.tool);if(!Y)throw TypeError(`Canvas selection action references an unknown generation tool: ${X.tool}`);if(J.has(X.tool))throw TypeError(`Canvas selection action must reference an operation, not a generation model: ${X.tool}`);if(Y.inputBinding!==void 0)throw TypeError(`Canvas selection action cannot reference an input-bound operation: ${X.tool}`);let Z=Q.target==="image"?"reference_image":"reference_video";if(!Y.acceptedInputs.includes(Z))throw TypeError(`Canvas ${Q.target} selection action tool must accept ${Z}: ${X.tool}`);if(Y.delivery==="return"){if(Q.editor!=="confirmation")throw TypeError(`Canvas return-delivery operation requires a confirmation editor: ${X.tool}`);if(Q.steps.length!==1)throw TypeError(`Canvas return-delivery operation requires exactly one step: ${X.tool}`);if(Y.output!=="text")throw TypeError(`Canvas return-delivery operation must return text: ${X.tool}`)}else if(Q.target==="image"&&(Q.editor!=="immediate"||Q.presentation!=="cutout-scan"||Q.steps.length!==1||Y.output!=="image"))throw TypeError(`Canvas image output requires one immediate image operation with cutout-scan presentation: ${X.tool}`)}}}var x1=["authorize","reauthorize","authorization.cancel","checkout","sign_out"],C8=new Set(x1);function P8(G){let F=A(G,"Service contribution");R(F,["actions"],"Service contribution");let J=c(F.actions,"Service actions",x1.length).map((Q)=>{if(typeof Q!=="string"||!C8.has(Q))throw TypeError("Service actions contain an unsupported or duplicate action");return Q});if(new Set(J).size!==J.length)throw TypeError("Service actions contain an unsupported or duplicate action");return{actions:J}}function q8(G){let F=A(G,"LLM contribution");R(F,["modelCatalog","models","provider"],"LLM contribution");let J=A(F.provider,"LLM provider");R(J,["id","name"],"LLM provider");let Q=E(J.id,"LLM provider id",80);if(!/^[a-z0-9]+(?:-[a-z0-9]+)*$/u.test(Q))throw TypeError("LLM provider id must use kebab-case");if(F.modelCatalog!==void 0&&F.modelCatalog!=="runtime")throw TypeError("LLM model catalog must be runtime");let X=c(F.models,"LLM models",32,!0).map((Y,Z)=>{let _=`LLM model ${Z}`,M=A(Y,_);R(M,["id","name"],_);let K=E(M.id,`${_} id`,128);if(!/^~?[a-z0-9]+(?:[._/:-][a-z0-9]+)*$/u.test(K))throw TypeError(`${_} id is invalid`);return{id:K,name:E(M.name,`${_} name`,120)}});if(new Set(X.map((Y)=>Y.id)).size!==X.length)throw TypeError("LLM models contain duplicate ids");return{...F.modelCatalog===void 0?{}:{modelCatalog:"runtime"},models:X,provider:{id:Q,name:E(J.name,"LLM provider name",120)}}}function k8(G){let F=A(G,"Pet contribution");R(F,["library","overlay","protocol","settings"],"Pet contribution");let J=X0(F.library,"Pet library"),Q=X0(F.overlay,"Pet overlay"),X=X0(F.settings,"Pet settings");if(!J.toLowerCase().endsWith(".json"))throw TypeError("Pet library must be a JSON file");if(!Q.toLowerCase().endsWith(".html"))throw TypeError("Pet overlay must be an HTML file");if(!X.toLowerCase().endsWith(".html"))throw TypeError("Pet settings must be an HTML file");if(F.protocol!=="convax.pet-host/1")throw TypeError("Pet protocol must equal convax.pet-host/1");return{library:J,overlay:Q,protocol:"convax.pet-host/1",settings:X}}function I8(G){let F=A(G,"Plugin runtime");if(R(F,["args","command","type"],"Plugin runtime"),F.type!=="mcp-stdio")throw TypeError("Plugin runtime type must be mcp-stdio");let J=E(F.command,"Plugin runtime command",128);if(!/^[A-Za-z0-9][A-Za-z0-9._-]*$/u.test(J))throw TypeError("Plugin runtime command must be a bare executable name");R0(J);let Q;if(F.args!==void 0)Q=c(F.args,"Plugin runtime args",64).map((X,Y)=>{let Z=E(X,`Plugin runtime arg ${Y}`,1024);if(/[\s"'`;|&`$(){}[\]<>]/u.test(Z)||Z.includes("\\")||/(^|=)(?:\/|[A-Za-z]:)/u.test(Z)||/(^|[=/])\.{1,2}(?:\/|$)/u.test(Z))throw TypeError(`Plugin runtime arg ${Y} must be a static CLI token without code, native paths, or traversal`);return Z});return{...Q===void 0?{}:{args:Q},command:J,type:"mcp-stdio"}}var Z1=new Set(U0.apis.filter((G)=>G.audience.includes("agent-skill")).map((G)=>G.id)),g8=/^[a-z][a-z0-9_]{0,63}$/;function x8(G,F){let J=E(G,F,64);if(!/^[a-z0-9]+(?:-[a-z0-9]+)*$/u.test(J))throw TypeError(`${F} must use kebab-case`);return R0(J),J}function f8(G,F,J){let Q=A(G,F);R(Q,["optionalHostApis","pluginTools","requiredHostApis"],F);let X=b0({major:M0,required:Q.requiredHostApis??[],optional:Q.optionalHostApis??[]}),Y=new Set(J.required),Z=new Set([...J.required,...J.optional]);for(let M of X.required){if(!Y.has(M))throw TypeError(`${F} required Host API must be required by the Plugin: ${M}`);if(N0(M)&&!Z1.has(M))throw TypeError(`${F} Host API is not available to Agent Skills: ${M}`)}for(let M of X.optional){if(!Z.has(M))throw TypeError(`${F} optional Host API must be declared by the Plugin: ${M}`);if(N0(M)&&!Z1.has(M))throw TypeError(`${F} Host API is not available to Agent Skills: ${M}`)}let _;if(Q.pluginTools!==void 0){if(_=c(Q.pluginTools,`${F} pluginTools`,32,!0).map((M,K)=>{let D=E(M,`${F} pluginTools ${K}`,64);if(!g8.test(D))throw TypeError(`${F} plugin tool id must use lower snake_case: ${D}`);return D}),new Set(_).size!==_.length)throw TypeError(`${F} pluginTools contain duplicate ids`)}if(X.required.length===0&&X.optional.length===0&&_===void 0)throw TypeError(`${F} must declare at least one Host API or Plugin tool`);return{...X.optional.length===0?{}:{optionalHostApis:[...X.optional]},..._===void 0?{}:{pluginTools:_},...X.required.length===0?{}:{requiredHostApis:[...X.required]}}}function h8(G,F){if(G===void 0)return;let J=c(G,"Plugin Skill contributions",32,!0).map((Q,X)=>{let Y=`Plugin Skill contribution ${X}`,Z=A(Q,Y);R(Z,["name","path","uses"],Y);let _=x8(Z.name,`${Y} name`),M=X0(Z.path,`${Y} path`);if(M.split("/").at(-1)!==_)throw TypeError(`${Y} path must name its Skill directory: ${_}`);let K=Z.uses===void 0?void 0:f8(Z.uses,`${Y} uses`,F);return{name:_,path:M,...K===void 0?{}:{uses:K}}});if(new Set(J.map((Q)=>Q.name)).size!==J.length)throw TypeError("Plugin Skill contributions contain duplicate names");if(new Set(J.map((Q)=>Q.path.toLocaleLowerCase("en-US"))).size!==J.length)throw TypeError("Plugin Skill contributions contain duplicate paths");return J}function y8(G,F){let J=new Set(F?.tools?.map((Q)=>Q.id)??[]);for(let Q of G??[])for(let X of Q.uses?.pluginTools??[])if(!J.has(X))throw TypeError(`Plugin Skill ${Q.name} references an unknown Agent tool: ${X}`)}var _1="convax.plugin/8";var f1=["canvas.connectedImages.read","canvas.connectedInputs.read","canvas.connectedMedia.stream","canvas.node.read","canvas.node.write","canvas.image.write","project.files.read","agent.prompt","generation.execute","ui.fullscreen","projects.read","canvas.catalog.read","canvas.document.read","canvas.document.write","canvas.events.subscribe","pet.activity.read","pet.activity.open","pet.preferences.write","pet.custom.manage"],c8=["projects.read","canvas.catalog.read","canvas.document.read","canvas.document.write","canvas.events.subscribe"],h1=["pet.activity.read","pet.activity.open","pet.preferences.write","pet.custom.manage"],$1=["pet.activity.read","pet.activity.open","pet.preferences.write"],b8=new Set(f1),d8=new Set(h1);function v8(G){let F=c(G??[],"Plugin capabilities",f1.length).map((J)=>{if(typeof J!=="string"||!b8.has(J))throw TypeError("Plugin capabilities contain an unsupported or duplicate capability");return J});if(new Set(F).size!==F.length)throw TypeError("Plugin capabilities contain an unsupported or duplicate capability");return F}function m8(G){let F=G.entry===void 0?void 0:X0(G.entry,"Plugin entry");if(F!==void 0&&!F.toLowerCase().endsWith(".html"))throw TypeError("Plugin entry must be an HTML file");let J=G.hooks===void 0?void 0:X0(G.hooks,"Plugin hooks");if(J!==void 0&&!/\.(?:js|mjs)$/u.test(J))throw TypeError("Plugin hooks must be a JavaScript ESM module");return{entry:F,hooks:J}}function p8(G){let{capabilities:F,canvas:J,entry:Q,hostApi:X}=G;if(Q!==void 0!==(J?.renderer!==void 0))throw TypeError("Plugin entry and Canvas renderer must appear together");if(Q!==void 0&&!X.required.includes("host.context.get"))throw TypeError("convax.plugin/8 Web Plugins must require host.context.get");if((J?.commands!==void 0||J?.menus!==void 0||J?.toolbar!==void 0)&&J.renderer===void 0)throw TypeError("Canvas UI commands require a sandboxed Canvas renderer");if(F.includes("generation.execute")&&J?.renderer===void 0)throw TypeError("generation.execute requires a sandboxed Canvas surface");if(J&&J.renderer===void 0&&!J.selectionActions?.length&&!J.commands?.length&&!J.menus?.length&&!J.toolbar?.length)throw TypeError("Canvas contributions must declare a renderer, selection actions, or UI commands");if(J?.selectionActions?.some((Y)=>("action"in Y)&&Y.action.type==="materialize-own-plugin-node")&&J.renderer===void 0)throw TypeError("materialize-own-plugin-node requires the contributing Plugin renderer")}function s8(G,F,J){if(F===void 0)return;if(G.length<$1.length||G.length>h1.length||$1.some((Q)=>!G.includes(Q))||G.some((Q)=>!d8.has(Q)))throw TypeError("Pet capabilities must include pet.activity.read, pet.activity.open, and pet.preferences.write; pet.custom.manage is optional");if(J!==void 0)throw TypeError("Pet feature cannot declare an executable runtime")}function o8(G,F={}){let J=A(G,"Plugin manifest");if(R(J,["capabilities","contributes","description","entry","hooks","hostApi","id","name","runtime","schema","version"],"Plugin manifest"),J.schema!==_1)throw TypeError("Plugin manifest must use convax.plugin/8");if(!Object.prototype.hasOwnProperty.call(J,"hostApi"))throw TypeError("convax.plugin/8 must declare hostApi explicitly");let Q=F.hostApiMode==="authoring"?RF(J.hostApi):b0(J.hostApi),X=v8(J.capabilities),Y=A(J.contributes,"Plugin contributions");R(Y,["agent","canvas","capabilities","generation","llm","pet","service","skills"],"Plugin contributions");let{entry:Z,hooks:_}=m8(J),M=Y.canvas===void 0?void 0:L8(Y.canvas);p8({capabilities:X,canvas:M,entry:Z,hostApi:Q});let K=Y.agent===void 0?void 0:H8(Y.agent),D=Y.capabilities===void 0?void 0:cF(Y.capabilities),W=Y.generation===void 0?void 0:E8(Y.generation),O=Y.llm===void 0?void 0:q8(Y.llm),V=Y.pet===void 0?void 0:k8(Y.pet),P=Y.service===void 0?void 0:P8(Y.service),G0=h8(Y.skills,Q),v=J.runtime===void 0?void 0:I8(J.runtime),J0=W!==void 0||P!==void 0||O!==void 0||Boolean(D?.exports.length);if(v!==void 0!==J0){if(D?.exports.length&&v===void 0)throw TypeError("Plugin capability exports require a verified mcp-stdio runtime");throw TypeError("convax.plugin/8 runtime and executable contribution must appear together")}if(D?.exports.length&&v===void 0)throw TypeError("Plugin capability exports require a verified mcp-stdio runtime");s8(X,V,v),w8({agent:K,generation:W,selectionActions:M?.selectionActions}),y8(G0,K);let U=new Set(c8),j=X.some((L)=>U.has(L));if(M?.renderer===void 0&&!M?.selectionActions?.length&&!J0&&_===void 0&&!X.includes("generation.execute")&&!j&&V===void 0&&(D?.exports.length??0)===0&&K?.mcp===void 0)throw TypeError("convax.plugin/8 must declare a Plugin capability beyond owned Skills");return R1({capabilities:X,contributes:{...K===void 0?{}:{agent:K},...D===void 0?{}:{capabilities:D},...M===void 0?{}:{canvas:M},...W===void 0?{}:{generation:W},...O===void 0?{}:{llm:O},...V===void 0?{}:{pet:V},...P===void 0?{}:{service:P},...G0===void 0?{}:{skills:G0}},description:E(J.description,"Plugin description",2000),...Z===void 0?{}:{entry:Z},..._===void 0?{}:{hooks:_},hostApi:Q,id:E1(J.id),name:E(J.name,"Plugin name",120),...v===void 0?{}:{runtime:v},schema:_1,version:vF(J.version)})}function r8(G){return o8(G,{hostApiMode:"authoring"})}class f extends Error{code;constructor(G,F){super(F);this.name="PluginHostProtocolError",this.code=G}}class v0 extends Error{code;kind;recoverable;constructor(G){super(G.message);this.name="PluginHostRemoteError",this.code=G.code,this.kind=G.kind,this.recoverable=G.recoverable}}class h0 extends Error{reason;constructor(G){super("Plugin Host request was aborted");this.name="AbortError",this.reason=G}}var K1=0;function u8(){return K1+=1,`sdk-${Date.now().toString(36)}-${K1.toString(36)}`}function n8(G){if(G.length<1||G.length>96||G!==G.trim()||!/^[A-Za-z0-9._-]+$/.test(G))throw TypeError("Plugin Host requestIdPrefix is invalid")}function M1(G,F){let J=G.contributes.capabilities,Q=J?.imports.required.find((Y)=>Y.id===F);if(Q)return{import:Q,requirement:"required"};let X=J?.imports.optional.find((Y)=>Y.id===F);if(X)return{import:X,requirement:"optional"};throw TypeError(`Plugin capability import is not declared: ${F}`)}function t8(G,F){let J=F.kind==="protocol"?q1(F):BF(G,F);return new v0(J)}function S1(G){let F=G.kind==="protocol"?q1(G):eF(G);return new v0(F)}function y1(G){let F=r8(G.manifest);if(F.entry===void 0||!F.hostApi.required.includes("host.context.get"))throw TypeError("Plugin Host Web client requires an entry and required host.context.get negotiation baseline");let J=G.requestIdPrefix??u8();n8(J);let Q=new Map,X=new Set,Y,Z,_=0,M=!1,K=(U)=>{for(let j of Q.values())j.abort?.(),j.reject(U);Q.clear()},D=(U)=>{if(M)return;M=!0,G.port.removeEventListener("message",G0),X.clear(),K(U);try{G.onFatalError?.(U)}catch{}},W=()=>{if(_>=Number.MAX_SAFE_INTEGER){let j=new f("request-id-exhausted","Plugin Host request id space is exhausted");throw D(j),j}_+=1;let U=`${J}-${_.toString(36)}`;if(!C1(U)){let j=new f("request-id-exhausted","Plugin Host request id is invalid");throw D(j),j}return U},O=(U,j)=>{G1(U,j,"Plugin Host request")},V=(U)=>{G.port.postMessage(U)},P=(U,j,L,N)=>{if(M)return Promise.reject(new f("closed","Plugin Host client is closed"));if(N?.aborted)return Promise.reject(new h0(N.reason));if(Q.size>=e0)return Promise.reject(RangeError(`Plugin Host client permits at most ${e0} in-flight requests`));try{O(U,L.maximumRequestBytes)}catch(b){return Promise.reject(b)}let T=U.id;return new Promise((b,h)=>{let Q0=N?()=>{let n=Q.get(T);if(!n)return;Q.delete(T),n.abort?.();let m={id:T,protocol:l,type:"cancel"};try{O(m,B0),V(m)}catch(p){let p0=new f("transport-failed",p instanceof Error?p.message:"Plugin Host cancel failed");h(p0),D(p0);return}h(new h0(N.reason))}:void 0,W0=Q0?()=>{N.removeEventListener("abort",Q0)}:void 0;if(Q.set(T,{abort:W0,maximumResponseBytes:L.maximumResponseBytes,parseFailure:L.parseFailure,parseResult:j,reject:h,resolve:b}),Q0)N.addEventListener("abort",Q0,{once:!0});try{V(U)}catch(n){D(new f("transport-failed",n instanceof Error?n.message:"Plugin Host transport failed"))}})};function G0(U){if(M)return;let j;try{j=G1(U.data,pF,"Plugin Host response")}catch{D(new f("invalid-envelope","Plugin Host sent a non-JSON message"));return}if(aF(U.data)){try{for(let T of X)T(U.data)}catch{D(new f("invalid-envelope","Plugin Host command listener failed"))}return}if(!iF(U.data)){D(new f("invalid-envelope","Plugin Host sent an invalid envelope"));return}let L=U.data,N=Q.get(L.id);if(!N){D(new f("unknown-response",`Plugin Host returned an unknown, duplicate, or late response id: ${L.id}`));return}if(j>N.maximumResponseBytes){D(new f("invalid-envelope",`Plugin Host response exceeds ${N.maximumResponseBytes} bytes for this request`));return}if(!L.ok){try{let T=N.parseFailure(L.error);Q.delete(L.id),N.abort?.(),N.reject(T)}catch(T){D(new f("invalid-result",T instanceof Error?T.message:"Plugin Host returned an invalid failure"))}return}try{let T=N.parseResult(L.result);Q.delete(L.id),N.abort?.(),N.resolve(T)}catch(T){D(new f("invalid-result",T instanceof Error?T.message:"Plugin Host returned an invalid result"))}}G.port.addEventListener("message",G0),G.port.start?.();let v=(U,j)=>{if(!t0(F.hostApi,U))return Promise.reject(TypeError(`Plugin Host API is not declared: ${U}`));let L=jF[U],N=L.params.type==="none"?void 0:j[0],T=L.params.type==="none"?j[0]:j[1],b;try{b=VF(U,N)}catch(m){return Promise.reject(m)}let Q0={id:W(),method:U,...b===void 0?{}:{params:b},protocol:l,type:"request"},W0=SF(U),n=LF;return P(Q0,(m)=>{let p=n(U,m);if(U==="host.context.get")Y=p;return p},{maximumRequestBytes:W0.request.maxBytes,maximumResponseBytes:W0.result.maxBytes,parseFailure:(m)=>{let p=t8(U,m);if(p.kind==="api"&&p.code==="stale-context")Y=void 0;return p}},T?.signal)},J0={get closed(){return M},callHostApi(U,...j){return v(U,j)},async getHostApiAvailability(U,j){if(!t0(F.hostApi,U))throw TypeError(`Plugin Host API is not declared: ${U}`);return(!Y||j?.refresh?await J0.refreshHostApiContext(j):Y).hostApi.availability.find(({id:N})=>N===U)??{available:!1,id:U,reason:"unsupported-host",recoverable:!1}},refreshHostApiContext(U){if(Y=void 0,Z)return Z;let L=v("host.context.get",[U]).finally(()=>{if(Z===L)Z=void 0});return Z=L,Z},async requireHostApi(U,j){let L=await J0.getHostApiAvailability(U,j);if(!L.available)throw new z1(L);return L},getCapabilityAvailability(U,j){let L;try{L=M1(F,U)}catch(b){return Promise.reject(b)}let N=W();return P({capabilityId:U,id:N,protocol:l,type:"capability-availability"},(b)=>{let h=lF(b);if(h.capabilityId!==U||h.requirement!==L.requirement)throw TypeError("Plugin capability availability does not match the declared import");return h},{maximumRequestBytes:B0,maximumResponseBytes:l0,parseFailure:S1},j?.signal)},invokeCapability(U,j,L){let N;try{N=M1(F,U),a0(N.import.inputSchema,j,`Plugin capability ${U} input`)}catch(h){return Promise.reject(h)}let T=W();return P({capabilityId:U,id:T,input:j,protocol:l,type:"capability-invoke"},(h)=>{return a0(N.import.outputSchema,h,`Plugin capability ${U} output`),h},{maximumRequestBytes:B0,maximumResponseBytes:l0,parseFailure:S1},L?.signal)},onCommand(U){if(M)throw new f("closed","Plugin Host client is closed");if(X.size>=64)throw RangeError("Plugin Host command listener limit exceeded");return X.add(U),()=>{X.delete(U)}},close(){D(new f("closed","Plugin Host client was closed"))}};return J0}var m0={schema:"convax.plugin/8",id:"multi-angle",name:"多角度",description:"通过已安装的统一图片生成工具,一次生成一张多宫格图片,每个格子展示同一主体的一个一致视角。",version:"0.1.3",entry:"index.html",capabilities:[],contributes:{canvas:{renderer:{create:!0,width:1080,height:720}}},hostApi:{major:1,required:["canvas.inputs.close","canvas.inputs.list","canvas.inputs.open","canvas.node.state.replace","generation.execute","generation.tools.list","host.context.get"],optional:[]}};var G2="@convax/plugin-sdk/client:createPluginHostClient";function J2(G,F={}){if(G.source!==window.parent||G.ports.length!==1||!P1(G.data)||G.data.pluginId!==m0.id)return null;return y1({manifest:m0,onFatalError:F.onFatalError,port:G.ports[0],requestIdPrefix:F.requestIdPrefix})}export{G2 as pluginSdkClientBundleMarker,J2 as acceptPluginHostConnection}; +var m2=/^[a-z][a-z0-9]*(?:\.[a-z][a-z0-9]*)+$/,d2=/^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/,p2=/^[a-z][A-Za-z0-9]*(?:\.[a-z][A-Za-z0-9]*)+$/,s2=/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/,r2=new Set(["web-plugin","agent-skill","companion","host"]),o2=new Set(["connection","plugin","own-node","project","canvas"]),u2=new Set(["none","read","write","execute","subscribe"]),n2=new Set(["cancelable","commit-preserving"]);function _0(F,G){if(F.trim().length===0)throw TypeError(`${G} must not be empty`)}function R0(F,G){if(!s2.test(F))throw TypeError(`${G} must be a strict semantic version`)}function I0(F,G){let J=F.split(".").map(Number),Q=G.split(".").map(Number);for(let X=0;X<3;X+=1){let Y=J[X]-Q[X];if(Y!==0)return Y}return 0}function L2(F){if(!m2.test(F.id))throw TypeError(`Plugin API id is invalid: ${F.id}`);if(R0(F.contractSince,`${F.id} contractSince`),F.grant!==null&&!p2.test(F.grant))throw TypeError(`Plugin API grant is invalid: ${F.grant}`);if(!o2.has(F.scope))throw TypeError(`Plugin API scope is invalid: ${F.scope}`);if(!u2.has(F.sideEffect))throw TypeError(`Plugin API sideEffect is invalid: ${F.sideEffect}`);if(!n2.has(F.completion))throw TypeError(`Plugin API completion is invalid: ${F.completion}`);let G=F.audience??["web-plugin"];if(G.length===0||new Set(G).size!==G.length||G.some((X)=>!r2.has(X)))throw TypeError(`Plugin API audience is invalid: ${F.id}`);_0(F.docs.summary,`${F.id} docs.summary`),_0(F.docs.description,`${F.id} docs.description`),_0(F.docs.request,`${F.id} docs.request`),_0(F.docs.response,`${F.id} docs.response`);let J=new Set,Q=F.errors.map((X)=>{if(!d2.test(X.code)||J.has(X.code))throw TypeError(`Plugin API error code is invalid or duplicated: ${F.id}/${X.code}`);return J.add(X.code),_0(X.description,`${F.id}/${X.code} description`),Object.freeze({...X})});return Object.freeze({...F,audience:Object.freeze([...G]),errors:Object.freeze(Q),docs:Object.freeze({...F.docs})})}function t2(F){return L2(F)}function t0(F,G){return R0(F,"Plugin API release version"),Object.freeze({version:F,apis:Object.freeze([...G])})}function i2(...F){if(F.length===0)throw TypeError("Plugin API catalog requires at least one release");let G=new Set,J=[],Q=new Set(F.map((Y)=>Y.version)),X;for(let Y of F){if(R0(Y.version,"Plugin API release version"),X&&I0(X,Y.version)>=0)throw TypeError("Plugin API releases must be strictly increasing");X=Y.version;for(let Z of Y.apis){let _=L2(Z);if(G.has(_.id))throw TypeError(`Plugin API id is duplicated: ${_.id}`);if(I0(_.contractSince,Y.version)<0)throw TypeError(`Plugin API ${_.id} contractSince must not precede since`);if(!Q.has(_.contractSince))throw TypeError(`Plugin API ${_.id} contractSince must identify a Catalog release block`);G.add(_.id),J.push(Object.freeze({..._,since:Y.version}))}}if(J.length===0)throw TypeError("Plugin API catalog must contain at least one API");return Object.freeze({version:F[F.length-1].version,apis:Object.freeze(J)})}var Y8=Object.freeze({assertVersion:R0,compareVersions:I0}),a2="convax.plugin-api-wire-schema/3",z=1024,I=z*z,l2=16*I,i0=8192,e2=33554432,$0={type:"none"},m={type:"boolean"},B={finite:!0,type:"number"},r={finite:!0,minimum:0,type:"integer"},T0=(F)=>({finite:!0,maximum:F,minimum:1,type:"integer"}),B0={type:"null"},g=(F)=>({const:F}),$=(F=2048,G={})=>({controlCharacters:!1,maxLength:F,minLength:G.allowEmpty?0:1,...G.prefix?{prefix:G.prefix}:{},...G.refinement?{refinement:G.refinement}:{},type:"string"}),q=(F,G,J=0,Q)=>({items:F,maxItems:G,minItems:J,type:"array",...Q?{uniqueBy:Q}:{}}),S=(F,G,J)=>({additionalProperties:!1,properties:F,...J?{products:J}:{},required:G,type:"object"}),l=(...F)=>({oneOf:F}),g0=(F=I)=>({keyMaxLength:128,maxBytes:F,maxDepth:32,type:"json-object"}),h=(F)=>({controlCharacters:!1,enum:F,maxLength:Math.max(...F.map((G)=>G.length)),minLength:1,type:"string"}),Z0=S({x:B,y:B},["x","y"]),d0=S({height:B,width:B},["height","width"]),i=S({canvasId:$(256),projectId:$(256)},["canvasId","projectId"]),x0=h(["text","image","video","audio"]),N2=h(["text","reference_image","reference_video","first_frame","last_frame","audio"]),x=(F=1000)=>q($(),F),FF=l(S({available:g(!0),catalogVersion:$(64),contractSince:$(64),id:$(128),since:$(64)},["available","catalogVersion","contractSince","id","since"]),S({available:g(!1),contractSince:$(64),id:$(128),reason:h(["unsupported-host","not-declared","permission-denied","wrong-surface","missing-context","setup-required","disabled","recovering"]),recoverable:m,since:$(64)},["available","id","reason","recoverable"])),O2=S({data:g0(),id:$(),parentId:$(),position:Z0,revision:r,style:g0(),type:$(80)},["data","id","position","revision","type"]),GF=S({inputKey:$(),role:N2},["inputKey","role"]),JF=S({ids:x(),kinds:x(),limit:r,relatedToNodeIds:x(),text:$(2000,{allowEmpty:!0})},[]),QF=S({animated:m,id:$(),source:$(),target:$(),type:$(80)},["source","target"]),XF=S({nodeId:$(),position:Z0,size:d0},["nodeId","position"]),YF=S({componentGap:B,componentPackingScale:B,crossGap:B,isolatedPlacement:h(["left","preserve"]),mainGap:B,nodeGap:B,nodePackingScale:B,strategy:h(["component-packing","horizontal-directed-cluster","vertical-directed-cluster"])},[]),ZF=l(S({edgeIds:x(),nodeIds:x(),type:g("elements.remove")},["type"]),S({direction:h(["left","center","right","top","middle","bottom"]),nodeIds:x(),type:g("nodes.align")},["direction","nodeIds","type"]),S({connection:QF,type:g("nodes.connect")},["connection","type"]),S({axis:h(["horizontal","vertical"]),nodeIds:x(),type:g("nodes.distribute")},["axis","nodeIds","type"]),S({label:$(512),nodeIds:x(),type:g("nodes.group")},["nodeIds","type"]),S({gap:B,layout:h(["grid","horizontal","vertical"]),nodeIds:x(),type:g("nodes.layout")},["nodeIds","type"]),S({delta:Z0,nodeIds:x(),type:g("nodes.move")},["delta","nodeIds","type"]),S({type:g("nodes.setGeometry"),updates:q(XF,1000)},["type","updates"]),S({nodeId:$(),type:g("nodes.ungroup")},["nodeId","type"]),S({nodeIds:x(),options:YF,type:g("canvas.auto-layout")},["type"])),_F=S({durationMs:B,height:B,inputKey:$(),kind:$(80),label:$(512),mediaRevision:$(512),mimeType:$(512),name:$(512),status:h(["error","idle","pending"]),width:B},["inputKey","kind","label"]),$F=S({contentRevision:$(64,{refinement:"lowercase-sha256"}),height:T0(i0),kind:g("image"),mimeType:h(["image/jpeg","image/png","image/webp"]),size:T0(l2),width:T0(i0)},["contentRevision","height","kind","mimeType","size","width"],[{fields:["width","height"],maximum:e2}]),KF=S({acceptedInputs:q(N2,6),description:$(2000),id:$(256),kind:h(["model","operation"]),output:x0,title:$(120)},["acceptedInputs","description","id","kind","output","title"]),z2=S({id:$(),source:$(),target:$()},["id","source","target"]),MF=S({id:$(),kind:$(80),label:$(512),parentId:$(64*z,{allowEmpty:!0}),position:Z0,size:d0,type:$(64*z,{allowEmpty:!0})},["id","kind","label","position","size"]),SF=S({description:$(64*z,{allowEmpty:!0}),durationMs:B,id:$(),kind:$(80),label:$(512),mimeType:$(64*z,{allowEmpty:!0}),name:$(64*z,{allowEmpty:!0}),parentId:$(64*z,{allowEmpty:!0}),position:Z0,resource:S({kind:g("project-file"),path:$(1024)},["kind","path"]),size:d0,status:$(64*z,{allowEmpty:!0}),text:$(64*z,{allowEmpty:!0}),type:$(64*z,{allowEmpty:!0})},["id","kind","label","position","size"]),DF=S({edges:q(z2,1e4),id:$(256),nodes:q(MF,1e4),revision:r,title:$(512)},["edges","id","nodes","revision","title"]),UF=S({description:$(8000,{allowEmpty:!0}),edges:q(z2,1e4),id:$(256),nodes:q(SF,1e4),revision:r,tags:q($(),256),title:$(512)},["edges","id","nodes","revision","title"]),WF=S({id:$(),incomingNodeIds:x(),kind:$(80),label:$(512),outgoingNodeIds:x(),parentId:$(64*z,{allowEmpty:!0}),position:Z0,text:$(64*z,{allowEmpty:!0}),type:$(64*z,{allowEmpty:!0})},["id","incomingNodeIds","kind","label","outgoingNodeIds","position"]),jF=S({canvas:S({id:$(256),name:$(512)},["id"]),hostApi:S({availability:q(FF,256,0,"id"),catalogVersion:$(64)},["availability","catalogVersion"]),node:O2,plugin:S({id:$(128),name:$(512),version:$(128)},["id","name","version"]),project:S({id:$(256),name:$(512)},["id"])},["canvas","hostApi","node","plugin","project"]),H=(F,G,J={})=>({dialect:a2,request:{maxBytes:J.request??64*z,schema:F},result:{maxBytes:J.result??64*z,schema:G}}),F0=Object.freeze({"host.context.get":H($0,jF,{result:I}),"canvas.inputs.list":H($0,S({inputs:q(_F,256)},["inputs"]),{result:I}),"canvas.inputs.image.open":H(S({inputKey:$()},["inputKey"]),S({probe:$F,sessionId:$(128),url:$(2048,{prefix:"convax-connected-media://"})},["probe","sessionId","url"])),"canvas.inputs.image.close":H(S({sessionId:$(128)},["sessionId"]),S({closed:m},["closed"])),"canvas.inputs.open":H(S({inputKey:$()},["inputKey"]),S({probe:S({duration:S({estimated:m,milliseconds:B},["estimated","milliseconds"]),height:B,kind:h(["audio","video"]),mediaRevision:$(128),mimeType:$(256),size:B,width:B},["duration","kind","mediaRevision","mimeType","size"]),sessionId:$(128),url:$(2048,{prefix:"convax-connected-media://"})},["probe","sessionId","url"])),"canvas.inputs.close":H(S({sessionId:$(128)},["sessionId"]),S({closed:m},["closed"])),"canvas.node.get":H($0,O2,{result:I}),"canvas.node.state.replace":H(S({state:g0(256*z)},["state"]),S({updated:g(!0)},["updated"]),{request:256*z+4*z}),"canvas.resource.image.create":H(S({dataUrl:$(24*I,{prefix:"data:image/png;base64,"}),name:$(120,{refinement:"safe-png-file-name"})},["dataUrl","name"]),S({createdNodeId:$(),revision:r},["createdNodeId","revision"]),{request:24*I+4*z}),"project.file.text.read":H(S({path:$(1024,{refinement:"portable-project-relative-path"})},["path"]),S({content:$(I,{allowEmpty:!0}),exists:m,path:$(1024,{refinement:"portable-project-relative-path"})},["content","exists","path"]),{result:I+4*z}),"agent.prompt":H(S({text:$(20000,{refinement:"trimmed"})},["text"]),S({text:$(64*z,{allowEmpty:!0})},["text"])),"generation.tools.list":H(l($0,S({output:x0},[])),S({tools:q(KF,256)},["tools"]),{result:I}),"generation.execute":H(S({output:x0,prompt:$(20000,{refinement:"trimmed"}),references:q(GF,32),resultMode:h(["create-pending-node","return"]),toolId:$(256)},["prompt"]),S({createdNodeIds:q($(),32),outputText:$(64*z,{allowEmpty:!0}),revision:r,toolId:$(256),warnings:q($(),32)},["createdNodeIds","revision","toolId","warnings"]),{result:256*z}),"projects.list":H($0,S({projects:q(S({available:m,id:$(256),name:$(512)},["available","id","name"]),1000)},["projects"]),{result:I}),"canvas.catalog.list":H(S({projectId:$(256)},["projectId"]),S({canvases:q(S({createdAt:B,id:$(256),name:$(512),updatedAt:B},["createdAt","id","name","updatedAt"]),1e4),projectId:$(256)},["canvases","projectId"]),{result:8*I}),"canvas.document.get":H(S({projection:h(["geometry","structure"]),ref:i},["ref"]),l(S({document:DF,projection:g("geometry"),ref:i,storageVersion:l(B0,$(256))},["document","projection","ref","storageVersion"]),S({document:UF,projection:g("structure"),ref:i,storageVersion:l(B0,$(256))},["document","projection","ref","storageVersion"])),{result:8*I}),"canvas.nodes.query":H(S({query:JF,ref:i},["ref"]),S({nodes:q(WF,1000),ref:i,revision:r,storageVersion:l(B0,$(256))},["nodes","ref","revision","storageVersion"]),{request:I,result:8*I}),"canvas.transaction.execute":H(S({commands:q(ZF,256,1),expectedRevision:r,ref:i,transactionId:$(128)},["commands","expectedRevision","ref","transactionId"]),S({affectedNodeIds:x(1e4),changed:m,createdNodeIds:x(1e4),ref:i,revision:r,storageVersion:$(256),summaryTruncated:m,warnings:x()},["affectedNodeIds","changed","createdNodeIds","ref","revision","storageVersion","warnings"]),{request:I,result:2*I}),"canvas.events.subscribe":H(S({ref:S({canvasId:$(256),projectId:$(256)},["projectId"])},["ref"]),S({subscriptionId:$(128)},["subscriptionId"])),"canvas.events.unsubscribe":H(S({subscriptionId:$(128)},["subscriptionId"]),S({removed:m},["removed"]))}),VF=Math.max(...Object.values(F0).map(({request:F})=>F.maxBytes)),LF=Math.max(...Object.values(F0).map(({result:F})=>F.maxBytes));function NF(F){return F0[F]}function f0(F,G){if(!F||typeof F!=="object"||Array.isArray(F))throw TypeError(`${G} must be an object`);let J=Object.getPrototypeOf(F);if(J!==Object.prototype&&J!==null)throw TypeError(`${G} must be a plain object`);return F}var OF=/^(CON|PRN|AUX|NUL|COM[1-9¹²³]|LPT[1-9¹²³]|CONIN\$|CONOUT\$)$/iu;function A2(F){for(let G of F){let J=G.codePointAt(0);if(J>=55296&&J<=57343)return!1}return!0}function a0(F){let G=F.split(".",1)[0]??"";return Boolean(F&&F!=="."&&F!==".."&&A2(F)&&!/[\\/:*?"<>|\u0000-\u001f\u007f]/u.test(F)&&!/[. ]$/u.test(F)&&!OF.test(G))}function zF(F,G){if(G===void 0)return!0;if(G==="lowercase-sha256")return/^[a-f0-9]{64}$/u.test(F);if(G==="trimmed")return F===F.trim();if(G==="safe-png-file-name")return F===F.trim()&&F.toLowerCase().endsWith(".png")&&a0(F);if(G==="portable-project-relative-path"){if(F!==F.trim()||F.includes("\\")||F.startsWith("/")||F.startsWith("//")||/^[A-Za-z]:/u.test(F)||!A2(F))return!1;let J=F.split("/");return J[0]?.toLowerCase()!==".convax"&&J.length>0&&J.every((Q)=>a0(Q))}return!1}function AF(F,G,J){let Q=new Set,X=(_,M,K)=>{if(_===null||typeof _==="string"||typeof _==="boolean")return _;if(typeof _==="number"){if(!Number.isFinite(_))throw TypeError(`${M} must contain finite JSON numbers`);return _}if(!_||typeof _!=="object"||K>=G.maxDepth||Q.has(_))throw TypeError(`${M} must be bounded acyclic JSON`);let D=Object.getPrototypeOf(_);if(!Array.isArray(_)&&D!==Object.prototype&&D!==null)throw TypeError(`${M} must contain plain JSON objects`);Q.add(_);let j;if(Array.isArray(_))j=_.map((O,L)=>X(O,`${M}[${L}]`,K+1));else{let O=Object.create(null);for(let[L,k]of Object.entries(_)){if(L.length<1||L.length>G.keyMaxLength||/[\u0000-\u001f\u007f]/u.test(L))throw TypeError(`${M} key is invalid`);O[L]=X(k,`${M}.${L}`,K+1)}j=O}return Q.delete(_),j},Y=X(f0(F,J),J,0);if(Array.isArray(Y)||!Y||typeof Y!=="object")throw TypeError(`${J} must be an object`);let Z=JSON.stringify(Y);if(new TextEncoder().encode(Z).byteLength>G.maxBytes)throw TypeError(`${J} exceeds ${G.maxBytes} bytes`);return Y}function RF(F,G,J){for(let Q of G??[]){let X=1;for(let Y of Q.fields){let Z=F[Y];if(typeof Z!=="number"||!Number.isFinite(Z)||Z<0)throw TypeError(`${J}.${Y} must be a non-negative finite product factor`);if(Z!==0&&X>Q.maximum/Z)throw TypeError(`${J} must satisfy its numeric product limits`);X*=Z}if(X>Q.maximum)throw TypeError(`${J} must satisfy its numeric product limits`)}return F}function K0(F,G,J="Plugin API value"){if("oneOf"in F){let Z=[];for(let _ of F.oneOf)try{Z.push(K0(_,G,J))}catch{}if(Z.length!==1)throw TypeError(`${J} must match exactly one schema variant`);return Z[0]}if("const"in F){if(G!==F.const)throw TypeError(`${J} must equal ${String(F.const)}`);return G}if("type"in F&&F.type==="none"){if(G!==void 0)throw TypeError(`${J} does not accept a value`);return}if("type"in F&&F.type==="null"){if(G!==null)throw TypeError(`${J} must be null`);return null}if("type"in F&&F.type==="boolean"){if(typeof G!=="boolean")throw TypeError(`${J} must be boolean`);return G}if("type"in F&&(F.type==="number"||F.type==="integer")){if(typeof G!=="number"||!Number.isFinite(G)||F.type==="integer"&&!Number.isSafeInteger(G)||F.minimum!==void 0&&GF.maximum)throw TypeError(`${J} must be a valid ${F.type}`);return G}if("type"in F&&F.type==="string"){if(typeof G!=="string"||G.lengthF.maxLength||F.controlCharacters===!1&&/[\u0000-\u001f\u007f]/u.test(G)||F.enum!==void 0&&!F.enum.includes(G)||F.prefix!==void 0&&!G.startsWith(F.prefix)||!zF(G,F.refinement))throw TypeError(`${J} must satisfy its bounded string contract`);return G}if("type"in F&&F.type==="array"){if(!Array.isArray(G)||G.lengthF.maxItems)throw TypeError(`${J} must satisfy its bounded array contract`);let Z=G.map((_,M)=>K0(F.items,_,`${J}[${M}]`));if(F.uniqueBy!==void 0){let _=Z.map((M)=>{let D=f0(M,`${J} unique item`)[F.uniqueBy];if(typeof D!=="string"&&typeof D!=="number")throw TypeError(`${J} unique identity is invalid`);return`${typeof D}:${String(D)}`});if(new Set(_).size!==_.length)throw TypeError(`${J} contains duplicate ${F.uniqueBy}`)}return Z}if("type"in F&&F.type==="json-object")return AF(G,F,J);if(!("properties"in F))throw TypeError(`${J} has an unsupported schema`);let Q=f0(G,J),X=new Set(Object.keys(F.properties));if(F.required.some((Z)=>!Object.prototype.hasOwnProperty.call(Q,Z))||Object.keys(Q).some((Z)=>!X.has(Z)))throw TypeError(`${J} contains unsupported or missing fields`);let Y=Object.fromEntries(Object.entries(Q).map(([Z,_])=>[Z,K0(F.properties[Z],_,`${J}.${Z}`)]));return RF(Y,F.products,J)}function h0(F,G){if("oneOf"in F){let J=F.oneOf.map((Z)=>h0(Z,G)),Q=J.filter((Z)=>Z.type==="object");if(Q.length===0&&J.some((Z)=>Z.type==="none"))return{type:"none"};if(Q.length===0)throw TypeError(`${G} is not an object schema`);let X=new Set(Q.flatMap(({required:Z,optional:_})=>[...Z,..._])),Y=[...X].filter((Z)=>Q.every((_)=>_.required.includes(Z))).sort();return{additionalProperties:!1,optional:[...X].filter((Z)=>!Y.includes(Z)).sort(),required:Y,type:"object"}}if("type"in F&&F.type==="none")return{type:"none"};if(!("properties"in F))throw TypeError(`${G} is not an object schema`);return{additionalProperties:!1,optional:Object.keys(F.properties).filter((J)=>!F.required.includes(J)).sort(),required:[...F.required].sort(),type:"object"}}var y0=Object.freeze(Object.keys(F0).sort()),EF=Object.freeze(Object.fromEntries(y0.map((F)=>{let G=F0[F],J=h0(G.result.schema,`Plugin API ${F} result`);if(J.type!=="object")throw TypeError(`Plugin API ${F} result must be an object`);return[F,{dialect:G.dialect,params:h0(G.request.schema,`Plugin API ${F} params`),request:G.request,response:G.result,result:J}]})));function TF(F,G){return K0(F0[F].request.schema,G,`Plugin API ${F} params`)}function BF(F,G){return K0(F0[F].result.schema,G,`Plugin API ${F} result`)}var P=[{code:"stale-context",description:"The bound Project, Canvas, node, or connection changed before the call completed.",recoverable:!0}],C=[{code:"permission-denied",description:"The installed Plugin principal does not currently hold the required grant.",recoverable:!1}],H0=[{code:"resource-unavailable",description:"The authoritative Project resource is missing, changed, or cannot be read safely.",recoverable:!0}],l0=[{code:"partial-success",description:"A user-visible Project file was published, but the requested Canvas commit did not complete; retry is unsafe.",recoverable:!1}],w=(F)=>t2({...F,contractSince:"2.0.0"}),U0=i2(t0("1.0.0",[w({id:"host.context.get",completion:"cancelable",grant:null,scope:"connection",sideEffect:"read",errors:P,docs:{summary:"Read the bounded context attached to the current Plugin connection.",description:"Returns only renderer-safe identifiers and feature metadata for the exact live connection; it grants no additional authority.",request:"No parameters.",response:"The current Plugin, Project, Canvas, node, and negotiated Host API context when present."}}),w({id:"canvas.inputs.list",completion:"cancelable",grant:"canvas.connectedInputs.read",scope:"own-node",sideEffect:"read",errors:[...P,...C],docs:{summary:"List direct incoming inputs of the owning Plugin node.",description:"Derives pathless input metadata from authoritative direct incoming Canvas edges and never reads resource bytes.",request:"No parameters; the owning node comes from the bound connection.",response:"A bounded list of direct incoming input descriptors and opaque input keys."}}),w({id:"canvas.inputs.open",completion:"cancelable",grant:"canvas.connectedMedia.stream",scope:"own-node",sideEffect:"read",errors:[...P,...C,...H0],docs:{summary:"Open a bounded stream for one previously listed direct input.",description:"Opens host-owned access to the exact authoritative input after topology and resource identity are revalidated.",request:"`{ inputKey }`, using an opaque key returned by canvas.inputs.list.",response:"A connection-bound stream descriptor and safe media metadata.",remarks:"Call canvas.inputs.close when the stream is no longer needed."}}),w({id:"canvas.inputs.close",completion:"cancelable",grant:"canvas.connectedMedia.stream",scope:"own-node",sideEffect:"write",errors:[...P,...C],docs:{summary:"Close one connection-bound input stream.",description:"Releases a stream created by canvas.inputs.open without changing Canvas or Project state.",request:"The stream handle returned by canvas.inputs.open.",response:"An acknowledgement; closing an already closed handle is idempotent."}}),w({id:"canvas.node.get",completion:"cancelable",grant:"canvas.node.read",scope:"own-node",sideEffect:"read",errors:[...P,...C],docs:{summary:"Read the owning Plugin node projection.",description:"Returns a bounded renderer-safe projection of the exact node bound to the connection.",request:"No parameters; the owning node comes from the bound connection.",response:"The owning node identity, revision, geometry, and Plugin state projection."}}),w({id:"canvas.node.state.replace",completion:"commit-preserving",grant:"canvas.node.write",scope:"own-node",sideEffect:"write",errors:[...P,...C],docs:{summary:"Replace the owning node's bounded Plugin state.",description:"Commits only the namespaced Plugin state through the authoritative Canvas application service with revision checks.",request:"`{ state }`, where state is a bounded JSON value.",response:"`{ updated: true }` after the authoritative state replacement commits."}}),w({id:"canvas.resource.image.create",completion:"commit-preserving",grant:"canvas.image.write",scope:"own-node",sideEffect:"write",errors:[...P,...C,...l0],docs:{summary:"Create a Project-backed Canvas image through the host lifecycle.",description:"Admits bounded image content as a user-visible Project resource and commits its Canvas reference without exposing native paths.",request:"`{ dataUrl, name }`, containing a bounded validated image data URL and safe file name.",response:"The created renderer-safe image result after Project publication and Canvas commit."}}),w({id:"project.file.text.read",completion:"cancelable",grant:"project.files.read",scope:"project",sideEffect:"read",errors:[...P,...C],docs:{summary:"Read one bounded UTF-8 Project file.",description:"Reads through the scoped Project Files capability using a normalized Project-relative path and never exposes a native path.",request:"`{ path }`, using a normalized Project-relative portable path.",response:"The bounded UTF-8 file text."}}),w({id:"agent.prompt",completion:"commit-preserving",grant:"agent.prompt",scope:"connection",sideEffect:"execute",errors:[...P,...C],docs:{summary:"Submit a bounded prompt through the host Agent capability.",description:"Uses the current host-owned Agent context; it does not grant direct OpenCode, filesystem, model, or credential access.",request:"`{ text }`, containing the bounded prompt text.",response:"`{ text }`, containing the bounded host acknowledgement."}}),w({id:"generation.tools.list",completion:"cancelable",grant:"generation.execute",scope:"plugin",sideEffect:"read",errors:C,docs:{summary:"List generation tools available to the installed Plugin principal.",description:"Returns normalized tool metadata derived from active verified contributions without exposing executable paths or credentials.",request:"Optional `{ output }` modality filter; omitting params lists every admitted modality.",response:"A bounded list of available generation tools and their public input contracts."}}),w({id:"generation.execute",completion:"commit-preserving",grant:"generation.execute",scope:"plugin",sideEffect:"execute",errors:[...P,...C,...H0,...l0],docs:{summary:"Execute one selected generation tool through the shared host executor.",description:"Revalidates the active Plugin, authorized executable, inputs, cancellation, and live resource guards immediately before execution.",request:"`{ output?, prompt, references?: Array<{ inputKey, role }>, resultMode?, toolId? }`; every opaque input key must come from the current owning node's canvas.inputs.list result.",response:"The bounded selected tool result, created node ids, authoritative revision, and warnings."}}),w({id:"projects.list",completion:"cancelable",audience:["web-plugin","companion"],grant:"projects.read",scope:"plugin",sideEffect:"read",errors:C,docs:{summary:"List Projects visible to the installed Plugin principal.",description:"Returns portable Project identities and display metadata without native paths or private Project state.",request:"No parameters.",response:"A bounded list of renderer-safe Project summaries."}}),w({id:"canvas.catalog.list",completion:"cancelable",audience:["web-plugin","companion"],grant:"canvas.catalog.read",scope:"project",sideEffect:"read",errors:[...P,...C],docs:{summary:"List Canvas catalog entries for one authorized Project.",description:"Reads the Project-owned Canvas catalog without selecting a Project or Canvas in the Workbench.",request:"`{ projectId }`, naming one explicit portable Project.",response:"A bounded list of portable Canvas catalog entries."}}),w({id:"canvas.document.get",completion:"cancelable",audience:["web-plugin","companion"],grant:"canvas.document.read",scope:"canvas",sideEffect:"read",errors:[...P,...C],docs:{summary:"Read one authorized Canvas document projection.",description:"Returns a bounded portable structure or geometry projection from Main's authoritative Canvas application service.",request:"`{ ref, projection }`, using an explicit portable Project/Canvas reference and supported projection.",response:"The requested pathless document projection and authoritative revision."}}),w({id:"canvas.nodes.query",completion:"cancelable",audience:["web-plugin","companion"],grant:"canvas.document.read",scope:"canvas",sideEffect:"read",errors:[...P,...C],docs:{summary:"Query bounded node projections in one authorized Canvas.",description:"Executes a host-defined bounded query without exposing native paths or resource bytes.",request:"`{ ref, query }`, using an explicit portable Project/Canvas reference and bounded query.",response:"Matching node projections and the authoritative Canvas revision."}}),w({id:"canvas.transaction.execute",completion:"commit-preserving",audience:["web-plugin","companion"],grant:"canvas.document.write",scope:"canvas",sideEffect:"write",errors:[...P,...C],docs:{summary:"Commit one non-empty revision-bound Canvas transaction.",description:"Validates bounded commands against one authoritative revision and persists the accepted transaction atomically.",request:"`{ ref, expectedRevision, commands, transactionId }` with a bounded non-empty command list.",response:"The committed authoritative revision and bounded command results."}}),w({id:"canvas.events.subscribe",completion:"cancelable",audience:["web-plugin","companion"],grant:"canvas.events.subscribe",scope:"canvas",sideEffect:"subscribe",errors:[...P,...C],docs:{summary:"Subscribe to bounded events for one authorized Canvas.",description:"Creates a connection-scoped subscription; events are revisioned invalidations or safe projections, never native data.",request:"`{ ref }`, using an explicit portable Project/Canvas reference.",response:"A connection-bound subscription identifier."}}),w({id:"canvas.events.unsubscribe",completion:"cancelable",audience:["web-plugin","companion"],grant:"canvas.events.subscribe",scope:"canvas",sideEffect:"subscribe",errors:[...P,...C],docs:{summary:"Close one connection-bound Canvas event subscription.",description:"Releases a subscription created by canvas.events.subscribe without changing Canvas state.",request:"The subscription identifier returned by canvas.events.subscribe.",response:"An acknowledgement; closing an already closed subscription is idempotent."}})]),t0("2.0.0",[w({id:"canvas.inputs.image.open",completion:"cancelable",grant:"canvas.connectedImages.read",scope:"own-node",sideEffect:"read",errors:[...P,...C,...H0],docs:{summary:"Open one directly connected image through the owning Plugin node.",description:"Issues a revocable Host-owned session for signature-validated JPEG, PNG, or WebP content after validating the Plugin principal, owning node, direct edge, resource identity, and image limits. Every protocol read revalidates the issued principal and direct edge against current Host state.",request:"`{ inputKey }`, using an opaque image key returned by canvas.inputs.list.",response:"A connection-issued, revocable session with an opaque 128-bit bearer URL, bounded image probe, and lowercase SHA-256 content revision.",remarks:"Electron protocol GET/HEAD requests have no trusted sender or frame principal. Possession of the convax-connected-media URL therefore carries bearer authority until the Host revokes the session or its principal/edge revalidation fails; the URL must be kept secret and closed promptly. The response contains no image bytes, native path, or unrestricted URL. The Host rejects images above 16 MiB, dimensions above 8192 pixels, or more than 33,554,432 pixels."}}),w({id:"canvas.inputs.image.close",completion:"cancelable",grant:"canvas.connectedImages.read",scope:"own-node",sideEffect:"write",errors:[...P,...C],docs:{summary:"Close one revocable connected-image bearer session.",description:"Revokes a session and bearer URL created by canvas.inputs.image.open after validating the calling Plugin principal, without changing Canvas or Project state.",request:"`{ sessionId }`, using the opaque handle returned by canvas.inputs.image.open.",response:"An acknowledgement that the caller's image session is closed; repeated close calls are idempotent."}})])),e0=U0.apis.map(({id:F})=>F).sort();if(e0.length!==y0.length||e0.some((F,G)=>F!==y0[G]))throw TypeError("Plugin API Catalog and portable method contracts are incomplete or inconsistent");var HF=U0.version,M0=Number(HF.split(".")[0]),R2=new Map(U0.apis.map((F)=>[F.id,F])),wF=new Set(R2.keys());function N0(F){return typeof F==="string"&&wF.has(F)}function p0(F){return R2.get(F)}var CF=/^[a-z][a-z0-9]*(?:\.[a-z][a-z0-9]*)+$/;function PF(F){return typeof F==="object"&&F!==null&&!Array.isArray(F)}function F2(F,G){if(!Array.isArray(F))throw TypeError(`${G} must be an array`);let J=[],Q=new Set;for(let X of F){if(typeof X!=="string"||!CF.test(X))throw TypeError(`${G} contains an invalid Plugin API id: ${String(X)}`);if(Q.has(X))throw TypeError(`${G} contains a duplicate Plugin API id: ${X}`);Q.add(X),J.push(X)}return J}function qF(F){let G=s0(F),J=[],Q=[];for(let X of G.required){if(!N0(X))throw TypeError(`Plugin API declaration contains an unknown Plugin API id: ${X}`);J.push(X)}for(let X of G.optional){if(!N0(X))throw TypeError(`Plugin API declaration contains an unknown Plugin API id: ${X}`);Q.push(X)}return Object.freeze({major:M0,required:Object.freeze(J),optional:Object.freeze(Q)})}function s0(F){if(!PF(F))throw TypeError("Plugin API declaration must be an object");if(Object.keys(F).some((Z)=>Z!=="major"&&Z!=="required"&&Z!=="optional"))throw TypeError("Plugin API declaration contains an unknown field");if(F.major!==M0)throw TypeError(`Plugin API declaration major must be ${M0}`);let J=F2(F.required,"Plugin API declaration required"),Q=F2(F.optional,"Plugin API declaration optional"),X=new Set(J),Y=Q.find((Z)=>X.has(Z));if(Y)throw TypeError(`Plugin API cannot be both required and optional: ${Y}`);return Object.freeze({major:M0,required:Object.freeze(J),optional:Object.freeze(Q)})}function kF(F,G){if(F.required.includes(G))return"required";if(F.optional.includes(G))return"optional";return}function G2(F,G){return kF(F,G)!==void 0}class E2 extends Error{availability;constructor(F){super(`Plugin API ${F.id} is unavailable: ${F.reason}`);this.name="PluginApiUnavailableError",this.availability=F}}function IF(F,G){return typeof G==="string"&&p0(F).errors.some((J)=>J.code===G)}function gF(F,G){if(!G||typeof G!=="object"||Array.isArray(G))throw TypeError(`Plugin API ${F} failure must be an object`);let J=G;if(Object.keys(J).some((X)=>!["code","kind","message","recoverable"].includes(X))||!Object.prototype.hasOwnProperty.call(J,"code")||!Object.prototype.hasOwnProperty.call(J,"message")||!Object.prototype.hasOwnProperty.call(J,"recoverable")||J.kind!=="api"||!IF(F,J.code)||typeof J.message!=="string"||J.message.length<1||J.message.length>4096||typeof J.recoverable!=="boolean")throw TypeError(`Plugin API ${F} failure is invalid`);let Q=p0(F).errors.find(({code:X})=>X===J.code);if(J.recoverable!==Q.recoverable)throw TypeError(`Plugin API ${F} failure recoverability does not match the Catalog`);return Object.freeze({code:J.code,kind:"api",message:J.message,recoverable:J.recoverable})}var xF=/^[a-z][a-z0-9]*(?:\.[a-z][a-z0-9-]*)+$/,fF=/^[a-z][a-z0-9]*(?:[._-][a-z0-9]+)*$/,hF=/^[A-Za-z][A-Za-z0-9_-]{0,63}$/,yF=/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/,cF=new Set(["none","read","write","execute","subscribe"]),T2=128,bF=64,vF=8,mF=16384,dF=256;function r0(F){return typeof F==="string"&&F.length<=160&&xF.test(F)}function n(F,G){if(!F||typeof F!=="object"||Array.isArray(F))throw TypeError(`${G} must be an object`);let J=Object.getPrototypeOf(F);if(J!==Object.prototype&&J!==null)throw TypeError(`${G} must be a plain object`);return F}function v(F,G,J,Q){let X=new Set([...G,...J]);if(G.some((Y)=>!Object.prototype.hasOwnProperty.call(F,Y))||Object.keys(F).some((Y)=>!X.has(Y)))throw TypeError(`${Q} contains unsupported or missing fields`)}function a(F,G,J=2000){if(typeof F!=="string"||F.length<1||F.length>J||F!==F.trim()||/[\u0000-\u001f\u007f]/u.test(F))throw TypeError(`${G} must be a bounded, trimmed string`);return F}function j0(F,G,J){if(!Number.isSafeInteger(F)||Number(F)<0||Number(F)>J)throw TypeError(`${G} must be a bounded non-negative integer`);return Number(F)}function c0(F,G){if(typeof F!=="string"||!yF.test(F))throw TypeError(`${G} must be a strict semantic version`);return F}function pF(F,G){let J=F.split(".").map(Number),Q=G.split(".").map(Number);for(let X=0;X<3;X+=1){let Y=J[X]-Q[X];if(Y!==0)return Y}return 0}function b0(F,G,J){if(J>vF)throw TypeError(`${G} exceeds the schema depth limit`);let Q=n(F,G);if(Q.type==="null"||Q.type==="boolean")return v(Q,["type"],[],G),Object.freeze({type:Q.type});if(Q.type==="number"||Q.type==="integer"){v(Q,["type"],["minimum","maximum"],G);let{minimum:X,maximum:Y}=Q;if(X!==void 0&&(typeof X!=="number"||!Number.isFinite(X)))throw TypeError(`${G}.minimum must be finite`);if(Y!==void 0&&(typeof Y!=="number"||!Number.isFinite(Y)))throw TypeError(`${G}.maximum must be finite`);if(X!==void 0&&Y!==void 0&&X>Y)throw TypeError(`${G} minimum exceeds maximum`);return Object.freeze({type:Q.type,...X===void 0?{}:{minimum:X},...Y===void 0?{}:{maximum:Y}})}if(Q.type==="string"){if(!Object.prototype.hasOwnProperty.call(Q,"maxLength"))throw TypeError(`${G}.maxLength is required to keep values bounded`);v(Q,["type","maxLength"],["minLength","enum"],G);let X=j0(Q.maxLength,`${G}.maxLength`,mF),Y=Q.minLength===void 0?void 0:j0(Q.minLength,`${G}.minLength`,X),Z;if(Q.enum!==void 0){if(!Array.isArray(Q.enum)||Q.enum.length<1||Q.enum.length>128||Q.enum.some((_)=>typeof _!=="string"||_.length>X)||new Set(Q.enum).size!==Q.enum.length)throw TypeError(`${G}.enum must contain unique bounded strings`);Z=Object.freeze([...Q.enum])}return Object.freeze({type:"string",maxLength:X,...Y===void 0?{}:{minLength:Y},...Z===void 0?{}:{enum:Z}})}if(Q.type==="array"){v(Q,["type","items","maxItems"],["minItems"],G);let X=j0(Q.maxItems,`${G}.maxItems`,dF),Y=Q.minItems===void 0?void 0:j0(Q.minItems,`${G}.minItems`,X);return Object.freeze({type:"array",items:b0(Q.items,`${G}.items`,J+1),maxItems:X,...Y===void 0?{}:{minItems:Y}})}if(Q.type==="object"){if(v(Q,["type","properties","required","additionalProperties"],[],G),Q.additionalProperties!==!1)throw TypeError(`${G}.additionalProperties must be false`);let X=n(Q.properties,`${G}.properties`),Y=Object.keys(X);if(Y.length>bF)throw TypeError(`${G} has too many properties`);if(Y.some((_)=>!hF.test(_)))throw TypeError(`${G} contains an invalid property name`);if(!Array.isArray(Q.required)||Q.required.some((_)=>typeof _!=="string"||!Y.includes(_))||new Set(Q.required).size!==Q.required.length)throw TypeError(`${G}.required must contain unique declared properties`);let Z=Object.fromEntries(Y.sort().map((_)=>[_,b0(X[_],`${G}.properties.${_}`,J+1)]));return Object.freeze({type:"object",properties:Object.freeze(Z),required:Object.freeze([...Q.required].sort()),additionalProperties:!1})}throw TypeError(`${G}.type is unsupported`)}function O0(F,G){let J=b0(F,G,0);if(J.type!=="object")throw TypeError(`${G} must be a closed object schema`);return J}function sF(F,G){let J=n(F,G);v(J,["id","inputSchema","outputSchema","version"],[],G);let Q=a(J.id,`${G}.id`,160);if(!r0(Q))throw TypeError(`${G}.id is invalid`);let X=n(J.version,`${G}.version`);v(X,["minimum","maximumExclusive"],[],`${G}.version`);let Y=c0(X.minimum,`${G}.version.minimum`),Z=c0(X.maximumExclusive,`${G}.version.maximumExclusive`);if(pF(Y,Z)>=0)throw TypeError(`${G}.version must be a non-empty half-open interval`);return Object.freeze({id:Q,inputSchema:O0(J.inputSchema,`${G}.inputSchema`),outputSchema:O0(J.outputSchema,`${G}.outputSchema`),version:Object.freeze({minimum:Y,maximumExclusive:Z})})}function J2(F,G){if(!Array.isArray(F)||F.length>T2)throw TypeError(`${G} must be a bounded array`);let J=F.map((Q,X)=>sF(Q,`${G}[${X}]`)).sort((Q,X)=>Q.id.localeCompare(X.id));if(J.some((Q,X)=>X>0&&J[X-1].id===Q.id))throw TypeError(`${G} contains a duplicate capability id`);return Object.freeze(J)}function rF(F,G){let J=n(F,G);v(J,["id","version","operation","sideEffect","inputSchema","outputSchema","docs"],[],G);let Q=a(J.id,`${G}.id`,160);if(!r0(Q))throw TypeError(`${G}.id is invalid`);let X=a(J.operation,`${G}.operation`,128);if(!fF.test(X))throw TypeError(`${G}.operation is invalid`);if(!cF.has(J.sideEffect))throw TypeError(`${G}.sideEffect is invalid`);let Y=n(J.docs,`${G}.docs`);v(Y,["summary","request","response"],["remarks"],`${G}.docs`);let Z=Object.freeze({summary:a(Y.summary,`${G}.docs.summary`),request:a(Y.request,`${G}.docs.request`),response:a(Y.response,`${G}.docs.response`),...Y.remarks===void 0?{}:{remarks:a(Y.remarks,`${G}.docs.remarks`)}});return Object.freeze({id:Q,version:c0(J.version,`${G}.version`),operation:X,sideEffect:J.sideEffect,inputSchema:O0(J.inputSchema,`${G}.inputSchema`),outputSchema:O0(J.outputSchema,`${G}.outputSchema`),docs:Z})}function oF(F){let G=n(F,"Plugin capability declaration");if(v(G,["exports","imports"],[],"Plugin capability declaration"),!Array.isArray(G.exports)||G.exports.length>T2)throw TypeError("Plugin capability exports must be a bounded array");let J=G.exports.map((M,K)=>rF(M,`Plugin capability exports[${K}]`)).sort((M,K)=>M.id.localeCompare(K.id));if(J.some((M,K)=>K>0&&J[K-1].id===M.id))throw TypeError("Plugin capability exports contain a duplicate capability id");if(new Set(J.map((M)=>M.operation)).size!==J.length)throw TypeError("Plugin capability exports contain a duplicate provider operation");let Q=n(G.imports,"Plugin capability imports");v(Q,["required","optional"],[],"Plugin capability imports");let X=J2(Q.required,"Plugin required capability imports"),Y=J2(Q.optional,"Plugin optional capability imports"),Z=new Set(X.map(({id:M})=>M)),_=Y.find(({id:M})=>Z.has(M));if(_)throw TypeError(`Plugin capability import cannot be both required and optional: ${_.id}`);return Object.freeze({exports:Object.freeze(J),imports:Object.freeze({required:X,optional:Y})})}function v0(F,G,J,Q){if(F.type==="null"){if(G!==null)throw TypeError(`${J} must be null`);return}if(F.type==="boolean"){if(typeof G!=="boolean")throw TypeError(`${J} must be boolean`);return}if(F.type==="number"||F.type==="integer"){if(typeof G!=="number"||!Number.isFinite(G)||F.type==="integer"&&!Number.isSafeInteger(G))throw TypeError(`${J} must be a finite ${F.type==="integer"?"safe integer":"number"}`);if(F.minimum!==void 0&&GF.maximum)throw TypeError(`${J} exceeds maximum`);return}if(F.type==="string"){if(typeof G!=="string"||G.length<(F.minLength??0)||G.length>F.maxLength||F.enum!==void 0&&!F.enum.includes(G))throw TypeError(`${J} is not an admitted string`);return}if(!G||typeof G!=="object")throw TypeError(`${J} must be ${F.type}`);if(Q.has(G))throw TypeError(`${J} cannot be cyclic`);Q.add(G);try{if(F.type==="array"){if(!Array.isArray(G)||G.length<(F.minItems??0)||G.length>F.maxItems)throw TypeError(`${J} is not an admitted array`);G.forEach((Z,_)=>v0(F.items,Z,`${J}[${_}]`,Q));return}if(Array.isArray(G))throw TypeError(`${J} must be an object`);let X=Object.getPrototypeOf(G);if(X!==Object.prototype&&X!==null)throw TypeError(`${J} must be a plain object`);let Y=G;for(let Z of F.required)if(!Object.prototype.hasOwnProperty.call(Y,Z))throw TypeError(`${J}.${Z} is required`);for(let[Z,_]of Object.entries(Y)){let M=F.properties[Z];if(!M)throw TypeError(`${J} contains unsupported property: ${Z}`);v0(M,_,`${J}.${Z}`,Q)}}finally{Q.delete(G)}}function Q2(F,G,J="Plugin capability value"){v0(F,G,J,new Set)}var uF=/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[A-Za-z-][0-9A-Za-z-]*)(?:\.(?:0|[1-9]\d*|\d*[A-Za-z-][0-9A-Za-z-]*))*))?(?:\+([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?$/,nF=/^(CON|PRN|AUX|NUL|COM[1-9¹²³]|LPT[1-9¹²³]|CONIN\$|CONOUT\$)$/i;function A(F,G){if(!F||typeof F!=="object"||Array.isArray(F))throw TypeError(`${G} must be an object`);let J=Object.getPrototypeOf(F);if(J!==Object.prototype&&J!==null)throw TypeError(`${G} must be a plain object`);return F}function R(F,G,J){let Q=new Set(G),X=Object.keys(F).find((Y)=>!Q.has(Y));if(X)throw TypeError(`${J} contains an unsupported field: ${X}`)}function T(F,G,J){if(typeof F!=="string"||F.length<1||F.length>J||F!==F.trim()||/[\u0000-\u001f\u007f]/u.test(F))throw TypeError(`${G} must be a bounded, trimmed string`);return F}function c(F,G,J,Q=!1){if(!Array.isArray(F)||F.length>J||Q&&F.length===0)throw TypeError(`${G} must be ${Q?"a non-empty ":"a "}bounded array with at most ${J} items`);return F}function B2(F){if(F&&typeof F==="object"&&!Object.isFrozen(F)){for(let G of Object.values(F))B2(G);Object.freeze(F)}return F}function tF(F){let G=T(F,"Plugin version",128);if(!uF.test(G))throw TypeError("Plugin version must be valid SemVer");return G}function E0(F){let G=F.split(".")[0]??"";if(!F||F.length>255||F==="."||F===".."||/[\\/:*?"<>|\u0000-\u001f\u007f]/u.test(F)||/[. ]$/u.test(F)||nF.test(G))throw TypeError(`Plugin path contains an invalid Windows filename: ${F}`);return F}function H2(F){let G=T(F,"Plugin id",80);if(!/^[a-z0-9]+(?:-[a-z0-9]+)*$/u.test(G))throw TypeError("Plugin id must use kebab-case");return E0(G),G}function X0(F,G="Plugin path"){let J=T(F,G,1024);if(J.includes("\\")||J.startsWith("/")||/^[A-Za-z]:/u.test(J)||J.startsWith("//"))throw TypeError(`${G} must be a portable relative path`);let Q=J.split("/");if(Q.some((X)=>!X||X==="."||X===".."))throw TypeError(`${G} must be a portable relative path`);return Q.forEach(E0),J}function w0(F,G,J){if(F===void 0)return;let Q=c(F,G,64).map((X)=>J(T(X,G,128)));if(new Set(Q).size!==Q.length)throw TypeError(`${G} contains duplicate values`);return Q}function Y0(F,G,J=80){let Q=T(F,G,J);if(!/^[a-z0-9]+(?:[._-][a-z0-9]+)*$/u.test(Q))throw TypeError(`${G} is invalid: ${Q}`);return Q}var u="convax.plugin-host/8",iF=VF,aF=LF,C0=1048576,X2=4194304,lF=128,Y2=16,eF=128,F1=64,V0=Math.ceil(iF/2),G1=/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/,J1=new Set(["not-declared","provider-missing","provider-incompatible","provider-ambiguous","self-provider","dependency-cycle","setup-required","disabled","recovering","contract-mismatch"]),w2=Object.freeze({canceled:{recoverable:!0},"contract-mismatch":{recoverable:!1},"depth-exceeded":{recoverable:!1},"duplicate-request":{recoverable:!1},"execution-failed":{recoverable:!1},"invalid-input":{recoverable:!1},"invalid-output":{recoverable:!1},overloaded:{recoverable:!0},"provider-unavailable":{recoverable:!0},"reentrant-call":{recoverable:!1}}),C2=new Set(Object.keys(w2)),P2=Object.freeze({canceled:{recoverable:!0},"internal-error":{recoverable:!1},"invalid-request":{recoverable:!1},overloaded:{recoverable:!0},"transport-closed":{recoverable:!0}}),q2=new Set(Object.keys(P2)),Q1=new Set(U0.apis.flatMap((F)=>F.errors.map(({code:G})=>G)));function e(F){if(!F||typeof F!=="object"||Array.isArray(F))return;let G=Object.getPrototypeOf(F);return G===Object.prototype||G===null?F:void 0}function Z2(F){let G=2;for(let J=0;J=55296&&Q<=57343){let X=F.charCodeAt(J+1);if(Q>=55296&&Q<=56319&&X>=56320&&X<=57343)G+=4,J+=1;else G+=6}else if(Q<128)G+=1;else if(Q<2048)G+=2;else G+=3}return G}function P0(F,G,J="Plugin Host message"){if(!Number.isSafeInteger(G)||G<1)throw TypeError(`${J} byte limit is invalid`);let Q=[{depth:0,value:F}],X=new WeakSet,Y=0,Z=0,_=(M)=>{if(Y+=M,Y>G)throw RangeError(`${J} exceeds ${G} bytes`)};while(Q.length>0){let M=Q.pop(),K=M.value;if(K===null){_(4);continue}if(typeof K==="string"){_(Z2(K));continue}if(typeof K==="boolean"){_(K?4:5);continue}if(typeof K==="number"){if(!Number.isFinite(K))throw TypeError(`${J} must contain finite JSON numbers`);_(Object.is(K,-0)?1:String(K).length);continue}if(!K||typeof K!=="object")throw TypeError(`${J} must be a JSON value`);if(M.depth>F1||X.has(K))throw TypeError(`${J} must be a bounded acyclic JSON tree`);if(X.add(K),Array.isArray(K)){if(Z+=K.length,Z>V0)throw RangeError(`${J} exceeds ${V0} JSON entries`);if(_(2+Math.max(0,K.length-1)),Object.getOwnPropertySymbols(K).length>0)throw TypeError(`${J} arrays must not contain symbol properties`);let O=0;for(let L in K){if(!Object.prototype.hasOwnProperty.call(K,L))continue;if(!/^(0|[1-9]\d*)$/u.test(L)||Number(L)>=K.length)throw TypeError(`${J} arrays must contain only indexed entries`);let k=Object.getOwnPropertyDescriptor(K,L);if(!k?.enumerable||!("value"in k))throw TypeError(`${J} arrays must contain enumerable data properties`);O+=1,Q.push({depth:M.depth+1,value:k.value})}if(O!==K.length)throw TypeError(`${J} arrays must be dense JSON arrays`);continue}let D=Object.getPrototypeOf(K);if(D!==Object.prototype&&D!==null)throw TypeError(`${J} must contain plain JSON objects`);if(Object.getOwnPropertySymbols(K).length>0)throw TypeError(`${J} must not contain symbol properties`);_(2);let j=0;for(let O in K){if(!Object.prototype.hasOwnProperty.call(K,O))continue;let L=Object.getOwnPropertyDescriptor(K,O);if(!L?.enumerable||!("value"in L))throw TypeError(`${J} objects must contain enumerable data properties`);if(j+=1,Z+=1,Z>V0)throw RangeError(`${J} exceeds ${V0} JSON entries`);_((j===1?0:1)+Z2(O)+1),Q.push({depth:M.depth+1,value:L.value})}}return Y}function o(F,G,J=[]){let Q=new Set([...G,...J]);return G.every((X)=>Object.prototype.hasOwnProperty.call(F,X))&&Object.keys(F).every((X)=>Q.has(X))}function k2(F){return typeof F==="string"&&F.length>0&&F.length<=eF&&F===F.trim()&&!/[\u0000-\u001f\u007f]/u.test(F)}function X1(F){return typeof F==="string"&&F.length>0&&F.length<=128&&F===F.trim()&&!/[\u0000-\u001f\u007f]/u.test(F)}function I2(F){let G=e(F);if(!G||!o(G,["pluginId","protocol","type"])||G.protocol!==u||G.type!=="connect")return!1;try{return H2(G.pluginId),!0}catch{return!1}}function Y1(F){let G=e(F);if(!G||G.protocol!==u||G.type!=="response"||!k2(G.id))return!1;if(G.ok===!0)return o(G,["id","ok","protocol","result","type"]);if(G.ok!==!1||!o(G,["error","id","ok","protocol","type"]))return!1;let J=e(G.error);return Boolean(J&&o(J,["code","kind","message","recoverable"])&&typeof J.code==="string"&&(J.kind==="api"&&Q1.has(J.code)||J.kind==="capability"&&C2.has(J.code)||J.kind==="protocol"&&q2.has(J.code))&&typeof J.message==="string"&&J.message.length>0&&J.message.length<=4096&&typeof J.recoverable==="boolean")}function Z1(F){let G=e(F);return Boolean(G&&o(G,["command","protocol","type"],["params"])&&G.protocol===u&&G.type==="command"&&X1(G.command))}function _1(F){let G=e(F);if(!G||typeof G.available!=="boolean")throw TypeError("Plugin capability availability must be a closed object");let J=G.requirement;if(J!=="required"&&J!=="optional")throw TypeError("Plugin capability availability requirement is invalid");if(!r0(G.capabilityId))throw TypeError("Plugin capability availability id is invalid");if(G.available){if(!o(G,["available","capabilityId","requirement","version"])||typeof G.version!=="string"||!G1.test(G.version))throw TypeError("Available Plugin capability result is invalid");return Object.freeze({available:!0,capabilityId:G.capabilityId,requirement:J,version:G.version})}if(!o(G,["available","capabilityId","reason","recoverable","requirement"])||typeof G.reason!=="string"||!J1.has(G.reason)||typeof G.recoverable!=="boolean")throw TypeError("Unavailable Plugin capability result is invalid");return Object.freeze({available:!1,capabilityId:G.capabilityId,reason:G.reason,recoverable:G.recoverable,requirement:J})}function $1(F){let G=e(F);if(!G||!o(G,["code","kind","message","recoverable"])||G.kind!=="capability"||typeof G.code!=="string"||!C2.has(G.code)||typeof G.message!=="string"||G.message.length<1||G.message.length>4096||typeof G.recoverable!=="boolean")throw TypeError("Plugin capability failure is invalid");let J=G.code;if(G.recoverable!==w2[J].recoverable)throw TypeError("Plugin capability failure recoverability is invalid");return Object.freeze({code:J,kind:"capability",message:G.message,recoverable:G.recoverable})}function g2(F){let G=e(F);if(!G||!o(G,["code","kind","message","recoverable"])||G.kind!=="protocol"||typeof G.code!=="string"||!q2.has(G.code)||typeof G.message!=="string"||G.message.length<1||G.message.length>4096||typeof G.recoverable!=="boolean")throw TypeError("Plugin Host protocol failure is invalid");let J=G.code;if(G.recoverable!==P2[J].recoverable)throw TypeError("Plugin Host protocol failure recoverability is invalid");return Object.freeze({code:J,kind:"protocol",message:G.message,recoverable:G.recoverable})}var K1=["download","edit","open","play","refresh","settings","sparkles","upload"],x2=/^[a-z][a-z0-9]*(?:[._-][a-z0-9]+)*$/,M1=/^[a-z][a-z0-9]*(?:[._-][a-z0-9]+)*$/,S1=/^[a-z][a-z0-9]*(?:[._-][a-z0-9]+)*$/,D1=128,_2=128,$2=1e4;function U1(F){return Boolean(F)&&typeof F==="object"&&!Array.isArray(F)}function S0(F,G){if(!U1(F))throw TypeError(`${G} must be an object`);let J=Object.getPrototypeOf(F);if(J!==Object.prototype&&J!==null)throw TypeError(`${G} must be a plain object`);return F}function D0(F,G,J,Q){let X=new Set([...G,...J]);if(G.some((Y)=>!Object.prototype.hasOwnProperty.call(F,Y))||Object.keys(F).some((Y)=>!X.has(Y)))throw TypeError(`${Q} contains unsupported or missing fields`)}function z0(F,G,J){if(typeof F!=="string"||F.length<1||F.length>J||F!==F.trim()||/[\u0000-\u001f\u007f]/u.test(F))throw TypeError(`${G} must be a bounded, trimmed string`);return F}function A0(F,G,J,Q){let X=z0(F,G,Q);if(!J.test(X))throw TypeError(`${G} must be a stable Plugin-local id`);return X}function W1(F,G){if(!Number.isSafeInteger(F)||Number(F)<-$2||Number(F)>$2)throw TypeError(`${G} must be a bounded safe integer`);return Number(F)}function j1(F,G){let J=S0(F,G);return D0(J,["default"],["zh-CN"],G),Object.freeze({default:z0(J.default,`${G}.default`,120),...J["zh-CN"]===void 0?{}:{"zh-CN":z0(J["zh-CN"],`${G}.zh-CN`,120)}})}function V1(F){return K1.some((G)=>G===F)}function L1(F,G){let J=`Plugin UI commands[${G}]`,Q=S0(F,J);D0(Q,["id","title","target"],["icon"],J);let X=S0(Q.target,`${J}.target`);if(X.type!=="renderer-message")throw TypeError(`${J}.target.type must be renderer-message`);D0(X,["type","message"],[],`${J}.target`);let Y=Q.icon;if(Y!==void 0&&!V1(Y))throw TypeError(`${J}.icon must be a supported Host icon token`);return Object.freeze({id:A0(Q.id,`${J}.id`,x2,128),title:j1(Q.title,`${J}.title`),target:Object.freeze({type:"renderer-message",message:z0(X.message,`${J}.target.message`,128)}),...Y===void 0?{}:{icon:Y}})}function f2(F,G,J,Q){let X=S0(F,G);return D0(X,J,Q,G),{input:X,id:A0(X.id,`${G}.id`,M1,128),command:A0(X.command,`${G}.command`,x2,128),...X.order===void 0?{}:{order:W1(X.order,`${G}.order`)}}}function N1(F,G){let{input:J,...Q}=f2(F,`Plugin UI toolbar[${G}]`,["id","command"],["order"]);return Object.freeze(Q)}function O1(F,G){let J=`Plugin UI menus[${G}]`,Q=f2(F,J,["id","command","placement"],["group","order"]);if(Q.input.placement!=="overflow")throw TypeError(`${J}.placement must be overflow`);let X=Q.input.group===void 0?void 0:A0(Q.input.group,`${J}.group`,S1,64),{input:Y,...Z}=Q;return Object.freeze({...Z,placement:"overflow",...X===void 0?{}:{group:X}})}function q0(F,G,J){if(!Array.isArray(F)||F.length>J)throw TypeError(`${G} must be a bounded array`);return F}function k0(F,G){let J=new Set;for(let Q of F){if(J.has(Q.id))throw TypeError(`${G} contains a duplicate id: ${Q.id}`);J.add(Q.id)}}function K2(F,G){let J=new Set;for(let Q of F){if(J.has(Q.command))throw TypeError(`${G} contains a duplicate command reference: ${Q.command}`);J.add(Q.command)}}function z1(F){let G=S0(F,"Plugin Canvas UI contribution");D0(G,[],["commands","menus","toolbar"],"Plugin Canvas UI contribution");let J=Object.freeze(q0(G.commands===void 0?[]:G.commands,"Plugin UI commands",D1).map(L1)),Q=Object.freeze(q0(G.menus===void 0?[]:G.menus,"Plugin UI menus",_2).map(O1)),X=Object.freeze(q0(G.toolbar===void 0?[]:G.toolbar,"Plugin UI toolbar",_2).map(N1));k0(J,"Plugin UI commands"),k0(Q,"Plugin UI menus"),k0(X,"Plugin UI toolbar");let Y=new Set(Q.map((j)=>j.id)),Z=X.find((j)=>Y.has(j.id));if(Z)throw TypeError(`Plugin UI placements contain a duplicate id: ${Z.id}`);K2(Q,"Plugin UI menus"),K2(X,"Plugin UI toolbar");let _=new Set(J.map((j)=>j.id)),M=[...Q,...X].find((j)=>!_.has(j.command));if(M)throw TypeError(`Plugin UI placement references an unknown command: ${M.command}`);let K=new Set([...Q,...X].map((j)=>j.command)),D=J.find((j)=>!K.has(j.id));if(D)throw TypeError(`Plugin UI command has no owning-node placement: ${D.id}`);return Object.freeze({commands:J,menus:Q,toolbar:X})}var A1=["time-point","time-range","crop-region","confirmation","immediate"];function R1(F){return A1.some((G)=>G===F)}function E1(F,G){if(F==="image"||F==="video")return F;throw TypeError(`${G} target must be image or video`)}function M2(F,G){if(!Number.isSafeInteger(F)||Number(F)<1||Number(F)>8192)throw TypeError(`${G} must be an integer between 1 and 8192`);return Number(F)}function T1(F){let G=A(F,"Canvas renderer contribution");if(R(G,["create","extensions","height","mimeTypes","nodeKinds","width"],"Canvas renderer contribution"),G.create!==void 0&&typeof G.create!=="boolean")throw TypeError("Canvas renderer create must be a boolean");let J=w0(G.extensions,"Canvas renderer extensions",(Y)=>{let Z=Y.toLowerCase();if(!/^\.[a-z0-9][a-z0-9._+-]{0,31}$/u.test(Z))throw TypeError(`Invalid Canvas renderer extension: ${Y}`);return Z}),Q=w0(G.mimeTypes,"Canvas renderer MIME types",(Y)=>{let Z=Y.toLowerCase();if(!/^[a-z0-9][a-z0-9!#$&^_.+-]*\/[a-z0-9][a-z0-9!#$&^_.+-]*$/u.test(Z))throw TypeError(`Invalid Canvas renderer MIME type: ${Y}`);return Z}),X=w0(G.nodeKinds,"Canvas renderer node kinds",(Y)=>{if(!/^[a-z][a-z0-9]*(?:[._-][a-z0-9]+)*$/u.test(Y))throw TypeError(`Invalid Canvas renderer node kind: ${Y}`);return Y});if(G.create!==!0&&!J?.length&&!Q?.length&&!X?.length)throw TypeError("Canvas renderer must be creatable or match an extension, MIME type, or node kind");return{...G.create===void 0?{}:{create:G.create},...J===void 0?{}:{extensions:J},...G.height===void 0?{}:{height:M2(G.height,"Canvas renderer height")},...Q===void 0?{}:{mimeTypes:Q},...X===void 0?{}:{nodeKinds:X},...G.width===void 0?{}:{width:M2(G.width,"Canvas renderer width")}}}function L0(F,G,J){let Q=A(F,G);return R(Q,["default","zh-CN"],G),{default:T(Q.default,`${G} default`,J),...Q["zh-CN"]===void 0?{}:{"zh-CN":T(Q["zh-CN"],`${G} zh-CN`,J)}}}function B1(F){let G=c(F,"Canvas selection actions",32,!0).map((J,Q)=>{let X=`Canvas selection action ${Q}`,Y=A(J,X);if(Y.action!==void 0){R(Y,["action","description","id","target","title"],X);let D=Y0(Y.id,`${X} id`);if(Y.target!=="video")throw TypeError(`${X} target must be video`);let j=A(Y.action,`${X} action`);if(R(j,["connect","type"],`${X} action`),j.type!=="materialize-own-plugin-node"||j.connect!=="selection-to-created")throw TypeError(`${X} materialization action is not supported`);return{action:{connect:"selection-to-created",type:"materialize-own-plugin-node"},description:L0(Y.description,`${X} description`,2000),id:D,target:"video",title:L0(Y.title,`${X} title`,120)}}R(Y,["description","editor","id","presentation","steps","target","title"],X);let Z=Y0(Y.id,`${X} id`),_=E1(Y.target,X);if(!R1(Y.editor))throw TypeError(`${X} editor is not supported`);let M=Y.editor;if(M==="immediate"!==(_==="image"&&Y.presentation==="cutout-scan")||Y.presentation!==void 0&&Y.presentation!=="cutout-scan")throw TypeError(`${X} immediate editor requires image target and cutout-scan presentation`);let K=c(Y.steps,`${X} steps`,16,!0).map((D,j)=>{let O=`${X} step ${j}`,L=A(D,O);return R(L,["tool"],O),{tool:Y0(L.tool,`${O} tool`)}});if(M!=="confirmation"&&K.length!==1)throw TypeError(`${X} editor requires exactly one step`);return{description:L0(Y.description,`${X} description`,2000),editor:M,id:Z,...Y.presentation===void 0?{}:{presentation:"cutout-scan"},steps:K,target:_,title:L0(Y.title,`${X} title`,120)}});if(new Set(G.map((J)=>J.id)).size!==G.length)throw TypeError("Canvas selection actions contain duplicate ids");return G}function H1(F){let G=A(F,"Canvas contributions");R(G,["commands","menus","renderer","selectionActions","toolbar"],"Canvas contributions");let J=z1({...G.commands===void 0?{}:{commands:G.commands},...G.menus===void 0?{}:{menus:G.menus},...G.toolbar===void 0?{}:{toolbar:G.toolbar}});return{...G.commands===void 0?{}:{commands:J.commands},...G.menus===void 0?{}:{menus:J.menus},...G.renderer===void 0?{}:{renderer:T1(G.renderer)},...G.selectionActions===void 0?{}:{selectionActions:B1(G.selectionActions)},...G.toolbar===void 0?{}:{toolbar:J.toolbar}}}var w1=["text","image","video","audio"],h2=["reference_image","reference_video","first_frame","last_frame","audio","text"],C1=new Set(w1),P1=new Set(h2),q1=/^[a-z][a-z0-9_]{0,63}$/;function k1(F,G){let Q=c(F,G,h2.length).map((X)=>{if(typeof X!=="string"||!P1.has(X))throw TypeError(`${G} contain an unsupported or duplicate role`);return X});if(new Set(Q).size!==Q.length)throw TypeError(`${G} contain an unsupported or duplicate role`);return Q}function I1(F){let G=A(F,"Generation contribution");if(R(G,["models","tools"],"Generation contribution"),!Object.prototype.hasOwnProperty.call(G,"models"))throw TypeError("convax.plugin/8 generation models must be declared explicitly");let J=c(G.tools,"Generation tools",64,!0).map((_,M)=>{let K=`Generation tool ${M}`,D=A(_,K);R(D,["acceptedInputs","delivery","description","id","inputBinding","output","recovery","title"],K);let j=Y0(D.id,`${K} id`);if(typeof D.output!=="string"||!C1.has(D.output))throw TypeError(`${K} output is not supported`);if(D.delivery!==void 0&&D.delivery!=="canvas"&&D.delivery!=="return")throw TypeError(`${K} delivery is not supported`);if(D.delivery==="return"&&D.output!=="text")throw TypeError(`${K} return delivery requires text output`);let O=k1(D.acceptedInputs,`${K} acceptedInputs`);if(D.inputBinding!==void 0&&D.inputBinding!=="direct-incoming")throw TypeError(`${K} input binding is not supported`);if(D.inputBinding==="direct-incoming"&&O.length===0)throw TypeError(`${K} direct-incoming input binding requires accepted inputs`);let L;if(D.recovery!==void 0){let k=A(D.recovery,`${K} recovery`);if(R(k,["mode","schema"],`${K} recovery`),k.schema!=="convax.generation-lro/1"||k.mode!=="long-running-operation")throw TypeError(`${K} recovery contract is not supported`);L={mode:"long-running-operation",schema:"convax.generation-lro/1"}}return{acceptedInputs:O,...D.delivery===void 0?{}:{delivery:D.delivery},description:T(D.description,`${K} description`,2000),id:j,...D.inputBinding===void 0?{}:{inputBinding:D.inputBinding},output:D.output,...L===void 0?{}:{recovery:L},title:T(D.title,`${K} title`,120)}});if(new Set(J.map((_)=>_.id)).size!==J.length)throw TypeError("Generation tools contain duplicate ids");let Q=c(G.models,"Generation models",J.length).map((_,M)=>{let K=`Generation model ${M}`,D=A(_,K);return R(D,["name","tool"],K),{name:T(D.name,`${K} name`,120),tool:Y0(D.tool,`${K} tool`)}});if(new Set(Q.map((_)=>_.tool)).size!==Q.length)throw TypeError("Generation models contain duplicate tool references");let X=new Set(Q.map((_)=>_.tool)),Y=J.find((_)=>_.delivery==="return"&&X.has(_.id));if(Y)throw TypeError(`Generation model cannot reference a return-delivery operation: ${Y.id}`);let Z=J.find((_)=>_.inputBinding!==void 0&&X.has(_.id));if(Z)throw TypeError(`Generation model cannot reference an input-bound operation: ${Z.id}`);return{models:Q,tools:J}}function g1(F){let G=c(F,"Agent tools",32,!0).map((J,Q)=>{let X=`Agent tool ${Q}`,Y=A(J,X);R(Y,["id","tool"],X);let Z=T(Y.id,`${X} id`,64);if(!q1.test(Z))throw TypeError(`${X} id must use lower snake_case`);return{id:Z,tool:Y0(Y.tool,`${X} generation tool`)}});if(new Set(G.map((J)=>J.id)).size!==G.length)throw TypeError("Agent tools contain duplicate ids");if(new Set(G.map((J)=>J.tool)).size!==G.length)throw TypeError("Agent tools contain duplicate generation tool references");return G}function x1(F){let G=A(F,"Agent remote MCP contribution");if(R(G,["headers","oauth","type","url"],"Agent remote MCP contribution"),G.type!=="remote")throw TypeError("Agent MCP type must be remote");let J=T(G.url,"Agent remote MCP URL",2048);try{let X=new URL(J);if(X.protocol!=="https:"||X.username!==""||X.password!==""||X.hash!=="")throw TypeError()}catch{throw TypeError("Agent remote MCP URL must be an absolute HTTPS URL without credentials or a fragment")}if(G.oauth!==void 0&&G.oauth!=="auto"&&G.oauth!=="none")throw TypeError("Agent remote MCP oauth must be auto or none");let Q;if(G.headers!==void 0){let X=A(G.headers,"Agent remote MCP headers"),Y=Object.entries(X);if(Y.length>16)throw TypeError("Agent remote MCP headers must contain at most 16 entries");let Z=new Set;Q={};for(let[_,M]of Y){if(!/^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/u.test(_))throw TypeError(`Agent remote MCP header name is invalid: ${_}`);let K=_.toLowerCase();if(Z.has(K))throw TypeError(`Agent remote MCP headers contain a duplicate name: ${_}`);if(K==="authorization"||K==="cookie"||K==="proxy-authorization")throw TypeError(`Agent remote MCP header is not allowed: ${_}`);let D=T(M,`Agent remote MCP header ${_}`,2048);if(/\{(?:env|file):/iu.test(D)||/\$\{[^}]*\}/u.test(D))throw TypeError(`Agent remote MCP header ${_} must be a literal value`);Z.add(K),Q[_]=D}}return{...Q===void 0?{}:{headers:Q},oauth:G.oauth==="none"?"none":"auto",type:"remote",url:J}}function f1(F){let G=A(F,"Agent contribution");R(G,["mcp","tools"],"Agent contribution");let J=G.tools===void 0?void 0:g1(G.tools),Q=G.mcp===void 0?void 0:x1(G.mcp);if(J===void 0&&Q===void 0)throw TypeError("Agent contribution must declare tools or mcp");return{...Q===void 0?{}:{mcp:Q},...J===void 0?{}:{tools:J}}}function h1(F){let G=new Map(F.generation?.tools.map((Q)=>[Q.id,Q])??[]),J=new Set(F.generation?.models.map((Q)=>Q.tool)??[]);for(let Q of J)if(!G.has(Q))throw TypeError(`Generation model references an unknown tool: ${Q}`);for(let Q of F.agent?.tools??[]){if(!G.has(Q.tool))throw TypeError(`Agent tool references an unknown generation tool: ${Q.tool}`);if(J.has(Q.tool))throw TypeError(`Agent tool must reference an operation, not a generation model: ${Q.tool}`)}for(let Q of F.selectionActions??[]){if(!("steps"in Q))continue;for(let X of Q.steps){let Y=G.get(X.tool);if(!Y)throw TypeError(`Canvas selection action references an unknown generation tool: ${X.tool}`);if(J.has(X.tool))throw TypeError(`Canvas selection action must reference an operation, not a generation model: ${X.tool}`);if(Y.inputBinding!==void 0)throw TypeError(`Canvas selection action cannot reference an input-bound operation: ${X.tool}`);let Z=Q.target==="image"?"reference_image":"reference_video";if(!Y.acceptedInputs.includes(Z))throw TypeError(`Canvas ${Q.target} selection action tool must accept ${Z}: ${X.tool}`);if(Y.delivery==="return"){if(Q.editor!=="confirmation")throw TypeError(`Canvas return-delivery operation requires a confirmation editor: ${X.tool}`);if(Q.steps.length!==1)throw TypeError(`Canvas return-delivery operation requires exactly one step: ${X.tool}`);if(Y.output!=="text")throw TypeError(`Canvas return-delivery operation must return text: ${X.tool}`)}else if(Q.target==="image"&&(Q.editor!=="immediate"||Q.presentation!=="cutout-scan"||Q.steps.length!==1||Y.output!=="image"))throw TypeError(`Canvas image output requires one immediate image operation with cutout-scan presentation: ${X.tool}`)}}}var y2=["authorize","reauthorize","authorization.cancel","checkout","sign_out"],y1=new Set(y2);function c1(F){let G=A(F,"Service contribution");R(G,["actions"],"Service contribution");let J=c(G.actions,"Service actions",y2.length).map((Q)=>{if(typeof Q!=="string"||!y1.has(Q))throw TypeError("Service actions contain an unsupported or duplicate action");return Q});if(new Set(J).size!==J.length)throw TypeError("Service actions contain an unsupported or duplicate action");return{actions:J}}function b1(F){let G=A(F,"LLM contribution");R(G,["modelCatalog","models","provider"],"LLM contribution");let J=A(G.provider,"LLM provider");R(J,["id","name"],"LLM provider");let Q=T(J.id,"LLM provider id",80);if(!/^[a-z0-9]+(?:-[a-z0-9]+)*$/u.test(Q))throw TypeError("LLM provider id must use kebab-case");if(G.modelCatalog!==void 0&&G.modelCatalog!=="runtime")throw TypeError("LLM model catalog must be runtime");let X=c(G.models,"LLM models",32,!0).map((Y,Z)=>{let _=`LLM model ${Z}`,M=A(Y,_);R(M,["id","name"],_);let K=T(M.id,`${_} id`,128);if(!/^~?[a-z0-9]+(?:[._/:-][a-z0-9]+)*$/u.test(K))throw TypeError(`${_} id is invalid`);return{id:K,name:T(M.name,`${_} name`,120)}});if(new Set(X.map((Y)=>Y.id)).size!==X.length)throw TypeError("LLM models contain duplicate ids");return{...G.modelCatalog===void 0?{}:{modelCatalog:"runtime"},models:X,provider:{id:Q,name:T(J.name,"LLM provider name",120)}}}function v1(F){let G=A(F,"Pet contribution");R(G,["library","overlay","protocol","settings"],"Pet contribution");let J=X0(G.library,"Pet library"),Q=X0(G.overlay,"Pet overlay"),X=X0(G.settings,"Pet settings");if(!J.toLowerCase().endsWith(".json"))throw TypeError("Pet library must be a JSON file");if(!Q.toLowerCase().endsWith(".html"))throw TypeError("Pet overlay must be an HTML file");if(!X.toLowerCase().endsWith(".html"))throw TypeError("Pet settings must be an HTML file");if(G.protocol!=="convax.pet-host/1")throw TypeError("Pet protocol must equal convax.pet-host/1");return{library:J,overlay:Q,protocol:"convax.pet-host/1",settings:X}}function m1(F){let G=A(F,"Plugin runtime");if(R(G,["args","command","type"],"Plugin runtime"),G.type!=="mcp-stdio")throw TypeError("Plugin runtime type must be mcp-stdio");let J=T(G.command,"Plugin runtime command",128);if(!/^[A-Za-z0-9][A-Za-z0-9._-]*$/u.test(J))throw TypeError("Plugin runtime command must be a bare executable name");E0(J);let Q;if(G.args!==void 0)Q=c(G.args,"Plugin runtime args",64).map((X,Y)=>{let Z=T(X,`Plugin runtime arg ${Y}`,1024);if(/[\s"'`;|&`$(){}[\]<>]/u.test(Z)||Z.includes("\\")||/(^|=)(?:\/|[A-Za-z]:)/u.test(Z)||/(^|[=/])\.{1,2}(?:\/|$)/u.test(Z))throw TypeError(`Plugin runtime arg ${Y} must be a static CLI token without code, native paths, or traversal`);return Z});return{...Q===void 0?{}:{args:Q},command:J,type:"mcp-stdio"}}var S2=new Set(U0.apis.filter((F)=>F.audience.includes("agent-skill")).map((F)=>F.id)),d1=/^[a-z][a-z0-9_]{0,63}$/;function p1(F,G){let J=T(F,G,64);if(!/^[a-z0-9]+(?:-[a-z0-9]+)*$/u.test(J))throw TypeError(`${G} must use kebab-case`);return E0(J),J}function s1(F,G,J){let Q=A(F,G);R(Q,["optionalHostApis","pluginTools","requiredHostApis"],G);let X=s0({major:M0,required:Q.requiredHostApis??[],optional:Q.optionalHostApis??[]}),Y=new Set(J.required),Z=new Set([...J.required,...J.optional]);for(let M of X.required){if(!Y.has(M))throw TypeError(`${G} required Host API must be required by the Plugin: ${M}`);if(N0(M)&&!S2.has(M))throw TypeError(`${G} Host API is not available to Agent Skills: ${M}`)}for(let M of X.optional){if(!Z.has(M))throw TypeError(`${G} optional Host API must be declared by the Plugin: ${M}`);if(N0(M)&&!S2.has(M))throw TypeError(`${G} Host API is not available to Agent Skills: ${M}`)}let _;if(Q.pluginTools!==void 0){if(_=c(Q.pluginTools,`${G} pluginTools`,32,!0).map((M,K)=>{let D=T(M,`${G} pluginTools ${K}`,64);if(!d1.test(D))throw TypeError(`${G} plugin tool id must use lower snake_case: ${D}`);return D}),new Set(_).size!==_.length)throw TypeError(`${G} pluginTools contain duplicate ids`)}if(X.required.length===0&&X.optional.length===0&&_===void 0)throw TypeError(`${G} must declare at least one Host API or Plugin tool`);return{...X.optional.length===0?{}:{optionalHostApis:[...X.optional]},..._===void 0?{}:{pluginTools:_},...X.required.length===0?{}:{requiredHostApis:[...X.required]}}}function r1(F,G){if(F===void 0)return;let J=c(F,"Plugin Skill contributions",32,!0).map((Q,X)=>{let Y=`Plugin Skill contribution ${X}`,Z=A(Q,Y);R(Z,["name","path","uses"],Y);let _=p1(Z.name,`${Y} name`),M=X0(Z.path,`${Y} path`);if(M.split("/").at(-1)!==_)throw TypeError(`${Y} path must name its Skill directory: ${_}`);let K=Z.uses===void 0?void 0:s1(Z.uses,`${Y} uses`,G);return{name:_,path:M,...K===void 0?{}:{uses:K}}});if(new Set(J.map((Q)=>Q.name)).size!==J.length)throw TypeError("Plugin Skill contributions contain duplicate names");if(new Set(J.map((Q)=>Q.path.toLocaleLowerCase("en-US"))).size!==J.length)throw TypeError("Plugin Skill contributions contain duplicate paths");return J}function o1(F,G){let J=new Set(G?.tools?.map((Q)=>Q.id)??[]);for(let Q of F??[])for(let X of Q.uses?.pluginTools??[])if(!J.has(X))throw TypeError(`Plugin Skill ${Q.name} references an unknown Agent tool: ${X}`)}var D2="convax.plugin/8";var c2=["canvas.connectedImages.read","canvas.connectedInputs.read","canvas.connectedMedia.stream","canvas.node.read","canvas.node.write","canvas.image.write","project.files.read","agent.prompt","generation.execute","ui.fullscreen","projects.read","canvas.catalog.read","canvas.document.read","canvas.document.write","canvas.events.subscribe","pet.activity.read","pet.activity.open","pet.preferences.write","pet.custom.manage"],u1=["projects.read","canvas.catalog.read","canvas.document.read","canvas.document.write","canvas.events.subscribe"],b2=["pet.activity.read","pet.activity.open","pet.preferences.write","pet.custom.manage"],U2=["pet.activity.read","pet.activity.open","pet.preferences.write"],n1=new Set(c2),t1=new Set(b2);function i1(F){let G=c(F??[],"Plugin capabilities",c2.length).map((J)=>{if(typeof J!=="string"||!n1.has(J))throw TypeError("Plugin capabilities contain an unsupported or duplicate capability");return J});if(new Set(G).size!==G.length)throw TypeError("Plugin capabilities contain an unsupported or duplicate capability");return G}function a1(F){let G=F.entry===void 0?void 0:X0(F.entry,"Plugin entry");if(G!==void 0&&!G.toLowerCase().endsWith(".html"))throw TypeError("Plugin entry must be an HTML file");let J=F.hooks===void 0?void 0:X0(F.hooks,"Plugin hooks");if(J!==void 0&&!/\.(?:js|mjs)$/u.test(J))throw TypeError("Plugin hooks must be a JavaScript ESM module");return{entry:G,hooks:J}}function l1(F){let{capabilities:G,canvas:J,entry:Q,hostApi:X}=F;if(Q!==void 0!==(J?.renderer!==void 0))throw TypeError("Plugin entry and Canvas renderer must appear together");if(Q!==void 0&&!X.required.includes("host.context.get"))throw TypeError("convax.plugin/8 Web Plugins must require host.context.get");if((J?.commands!==void 0||J?.menus!==void 0||J?.toolbar!==void 0)&&J.renderer===void 0)throw TypeError("Canvas UI commands require a sandboxed Canvas renderer");if(G.includes("generation.execute")&&J?.renderer===void 0)throw TypeError("generation.execute requires a sandboxed Canvas surface");if(J&&J.renderer===void 0&&!J.selectionActions?.length&&!J.commands?.length&&!J.menus?.length&&!J.toolbar?.length)throw TypeError("Canvas contributions must declare a renderer, selection actions, or UI commands");if(J?.selectionActions?.some((Y)=>("action"in Y)&&Y.action.type==="materialize-own-plugin-node")&&J.renderer===void 0)throw TypeError("materialize-own-plugin-node requires the contributing Plugin renderer")}function e1(F,G,J){if(G===void 0)return;if(F.lengthb2.length||U2.some((Q)=>!F.includes(Q))||F.some((Q)=>!t1.has(Q)))throw TypeError("Pet capabilities must include pet.activity.read, pet.activity.open, and pet.preferences.write; pet.custom.manage is optional");if(J!==void 0)throw TypeError("Pet feature cannot declare an executable runtime")}function F8(F,G={}){let J=A(F,"Plugin manifest");if(R(J,["capabilities","contributes","description","entry","hooks","hostApi","id","name","runtime","schema","version"],"Plugin manifest"),J.schema!==D2)throw TypeError("Plugin manifest must use convax.plugin/8");if(!Object.prototype.hasOwnProperty.call(J,"hostApi"))throw TypeError("convax.plugin/8 must declare hostApi explicitly");let Q=G.hostApiMode==="authoring"?qF(J.hostApi):s0(J.hostApi),X=i1(J.capabilities),Y=A(J.contributes,"Plugin contributions");R(Y,["agent","canvas","capabilities","generation","llm","pet","service","skills"],"Plugin contributions");let{entry:Z,hooks:_}=a1(J),M=Y.canvas===void 0?void 0:H1(Y.canvas);l1({capabilities:X,canvas:M,entry:Z,hostApi:Q});let K=Y.agent===void 0?void 0:f1(Y.agent),D=Y.capabilities===void 0?void 0:oF(Y.capabilities),j=Y.generation===void 0?void 0:I1(Y.generation),O=Y.llm===void 0?void 0:b1(Y.llm),L=Y.pet===void 0?void 0:v1(Y.pet),k=Y.service===void 0?void 0:c1(Y.service),G0=r1(Y.skills,Q),d=J.runtime===void 0?void 0:m1(J.runtime),J0=j!==void 0||k!==void 0||O!==void 0||Boolean(D?.exports.length);if(d!==void 0!==J0){if(D?.exports.length&&d===void 0)throw TypeError("Plugin capability exports require a verified mcp-stdio runtime");throw TypeError("convax.plugin/8 runtime and executable contribution must appear together")}if(D?.exports.length&&d===void 0)throw TypeError("Plugin capability exports require a verified mcp-stdio runtime");e1(X,L,d),h1({agent:K,generation:j,selectionActions:M?.selectionActions}),o1(G0,K);let U=new Set(u1),W=X.some((V)=>U.has(V));if(M?.renderer===void 0&&!M?.selectionActions?.length&&!J0&&_===void 0&&!X.includes("generation.execute")&&!W&&L===void 0&&(D?.exports.length??0)===0&&K?.mcp===void 0)throw TypeError("convax.plugin/8 must declare a Plugin capability beyond owned Skills");return B2({capabilities:X,contributes:{...K===void 0?{}:{agent:K},...D===void 0?{}:{capabilities:D},...M===void 0?{}:{canvas:M},...j===void 0?{}:{generation:j},...O===void 0?{}:{llm:O},...L===void 0?{}:{pet:L},...k===void 0?{}:{service:k},...G0===void 0?{}:{skills:G0}},description:T(J.description,"Plugin description",2000),...Z===void 0?{}:{entry:Z},..._===void 0?{}:{hooks:_},hostApi:Q,id:H2(J.id),name:T(J.name,"Plugin name",120),...d===void 0?{}:{runtime:d},schema:D2,version:tF(J.version)})}function G8(F){return F8(F,{hostApiMode:"authoring"})}class f extends Error{code;constructor(F,G){super(G);this.name="PluginHostProtocolError",this.code=F}}class o0 extends Error{code;kind;recoverable;constructor(F){super(F.message);this.name="PluginHostRemoteError",this.code=F.code,this.kind=F.kind,this.recoverable=F.recoverable}}class m0 extends Error{reason;constructor(F){super("Plugin Host request was aborted");this.name="AbortError",this.reason=F}}var W2=0;function J8(){return W2+=1,`sdk-${Date.now().toString(36)}-${W2.toString(36)}`}function Q8(F){if(F.length<1||F.length>96||F!==F.trim()||!/^[A-Za-z0-9._-]+$/.test(F))throw TypeError("Plugin Host requestIdPrefix is invalid")}function j2(F,G){let J=F.contributes.capabilities,Q=J?.imports.required.find((Y)=>Y.id===G);if(Q)return{import:Q,requirement:"required"};let X=J?.imports.optional.find((Y)=>Y.id===G);if(X)return{import:X,requirement:"optional"};throw TypeError(`Plugin capability import is not declared: ${G}`)}function X8(F,G){let J=G.kind==="protocol"?g2(G):gF(F,G);return new o0(J)}function V2(F){let G=F.kind==="protocol"?g2(F):$1(F);return new o0(G)}function v2(F){let G=G8(F.manifest);if(G.entry===void 0||!G.hostApi.required.includes("host.context.get"))throw TypeError("Plugin Host Web client requires an entry and required host.context.get negotiation baseline");let J=F.requestIdPrefix??J8();Q8(J);let Q=new Map,X=new Set,Y,Z,_=0,M=!1,K=(U)=>{for(let W of Q.values())W.abort?.(),W.reject(U);Q.clear()},D=(U,W=!0)=>{if(M)return;M=!0,F.port.removeEventListener("message",G0),X.clear(),Y=void 0,Z=void 0,K(U);let V={protocol:u,type:"disconnect"};try{P0(V,lF,"Plugin Host disconnect"),L(V)}catch{}try{F.port.close()}catch{}if(!W)return;try{F.onFatalError?.(U)}catch{}},j=()=>{if(_>=Number.MAX_SAFE_INTEGER){let W=new f("request-id-exhausted","Plugin Host request id space is exhausted");throw D(W),W}_+=1;let U=`${J}-${_.toString(36)}`;if(!k2(U)){let W=new f("request-id-exhausted","Plugin Host request id is invalid");throw D(W),W}return U},O=(U,W)=>{P0(U,W,"Plugin Host request")},L=(U)=>{F.port.postMessage(U)},k=(U,W,V,N)=>{if(M)return Promise.reject(new f("closed","Plugin Host client is closed"));if(N?.aborted)return Promise.reject(new m0(N.reason));if(Q.size>=Y2)return Promise.reject(RangeError(`Plugin Host client permits at most ${Y2} in-flight requests`));try{O(U,V.maximumRequestBytes)}catch(b){return Promise.reject(b)}let E=U.id;return new Promise((b,y)=>{let Q0=N?()=>{let t=Q.get(E);if(!t)return;Q.delete(E),t.abort?.();let p={id:E,protocol:u,type:"cancel"};try{O(p,C0),L(p)}catch(s){let n0=new f("transport-failed",s instanceof Error?s.message:"Plugin Host cancel failed");y(n0),D(n0);return}y(new m0(N.reason))}:void 0,W0=Q0?()=>{N.removeEventListener("abort",Q0)}:void 0;if(Q.set(E,{abort:W0,maximumResponseBytes:V.maximumResponseBytes,parseFailure:V.parseFailure,parseResult:W,reject:y,resolve:b}),Q0)N.addEventListener("abort",Q0,{once:!0});try{L(U)}catch(t){D(new f("transport-failed",t instanceof Error?t.message:"Plugin Host transport failed"))}})};function G0(U){if(M)return;let W;try{W=P0(U.data,aF,"Plugin Host response")}catch{D(new f("invalid-envelope","Plugin Host sent a non-JSON message"));return}if(Z1(U.data)){try{for(let E of X)E(U.data)}catch{D(new f("invalid-envelope","Plugin Host command listener failed"))}return}if(!Y1(U.data)){D(new f("invalid-envelope","Plugin Host sent an invalid envelope"));return}let V=U.data,N=Q.get(V.id);if(!N){D(new f("unknown-response",`Plugin Host returned an unknown, duplicate, or late response id: ${V.id}`));return}if(W>N.maximumResponseBytes){D(new f("invalid-envelope",`Plugin Host response exceeds ${N.maximumResponseBytes} bytes for this request`));return}if(!V.ok){try{let E=N.parseFailure(V.error);Q.delete(V.id),N.abort?.(),N.reject(E)}catch(E){D(new f("invalid-result",E instanceof Error?E.message:"Plugin Host returned an invalid failure"))}return}try{let E=N.parseResult(V.result);Q.delete(V.id),N.abort?.(),N.resolve(E)}catch(E){D(new f("invalid-result",E instanceof Error?E.message:"Plugin Host returned an invalid result"))}}F.port.addEventListener("message",G0),F.port.start?.();let d=(U,W)=>{if(!G2(G.hostApi,U))return Promise.reject(TypeError(`Plugin Host API is not declared: ${U}`));let V=EF[U],N=V.params.type==="none"?void 0:W[0],E=V.params.type==="none"?W[0]:W[1],b;try{b=TF(U,N)}catch(p){return Promise.reject(p)}let Q0={id:j(),method:U,...b===void 0?{}:{params:b},protocol:u,type:"request"},W0=NF(U),t=BF;return k(Q0,(p)=>{let s=t(U,p);if(U==="host.context.get")Y=s;return s},{maximumRequestBytes:W0.request.maxBytes,maximumResponseBytes:W0.result.maxBytes,parseFailure:(p)=>{let s=X8(U,p);if(s.kind==="api"&&s.code==="stale-context")Y=void 0;return s}},E?.signal)},J0={get closed(){return M},callHostApi(U,...W){return d(U,W)},async getHostApiAvailability(U,W){if(!G2(G.hostApi,U))throw TypeError(`Plugin Host API is not declared: ${U}`);let V=!Y||W?.refresh?await J0.refreshHostApiContext(W):Y,N=p0(U);return V.hostApi.availability.find(({id:E})=>E===U)??{available:!1,contractSince:N.contractSince,id:U,reason:"unsupported-host",recoverable:!1,since:N.since}},refreshHostApiContext(U){if(Y=void 0,Z)return Z;let V=d("host.context.get",[U]).finally(()=>{if(Z===V)Z=void 0});return Z=V,Z},async requireHostApi(U,W){let V=await J0.getHostApiAvailability(U,W);if(!V.available)throw new E2(V);return V},getCapabilityAvailability(U,W){let V;try{V=j2(G,U)}catch(b){return Promise.reject(b)}let N=j();return k({capabilityId:U,id:N,protocol:u,type:"capability-availability"},(b)=>{let y=_1(b);if(y.capabilityId!==U||y.requirement!==V.requirement)throw TypeError("Plugin capability availability does not match the declared import");return y},{maximumRequestBytes:C0,maximumResponseBytes:X2,parseFailure:V2},W?.signal)},invokeCapability(U,W,V){let N;try{N=j2(G,U),Q2(N.import.inputSchema,W,`Plugin capability ${U} input`)}catch(y){return Promise.reject(y)}let E=j();return k({capabilityId:U,id:E,input:W,protocol:u,type:"capability-invoke"},(y)=>{return Q2(N.import.outputSchema,y,`Plugin capability ${U} output`),y},{maximumRequestBytes:C0,maximumResponseBytes:X2,parseFailure:V2},V?.signal)},onCommand(U){if(M)throw new f("closed","Plugin Host client is closed");if(X.size>=64)throw RangeError("Plugin Host command listener limit exceeded");return X.add(U),()=>{X.delete(U)}},close(){D(new f("closed","Plugin Host client was closed"),!1)}};return J0}var u0={schema:"convax.plugin/8",id:"multi-angle",name:"多角度",description:"通过已安装的统一图片生成工具,一次生成一张多宫格图片,每个格子展示同一主体的一个一致视角。",version:"0.2.0",entry:"index.html",capabilities:[],contributes:{canvas:{renderer:{create:!0,width:1080,height:720}}},hostApi:{major:2,required:["canvas.inputs.image.close","canvas.inputs.image.open","canvas.inputs.list","canvas.node.state.replace","generation.execute","generation.tools.list","host.context.get"],optional:[]}};var M8="@convax/plugin-sdk/client:createPluginHostClient";function S8(F,G={}){if(F.source!==window.parent||F.ports.length!==1||!I2(F.data)||F.data.pluginId!==u0.id)return null;return v2({manifest:u0,onFatalError:G.onFatalError,port:F.ports[0],requestIdPrefix:G.requestIdPrefix})}export{M8 as pluginSdkClientBundleMarker,S8 as acceptPluginHostConnection}; diff --git a/packages/plugins/multi-angle/package/assets/styles.css b/packages/plugins/multi-angle/package/assets/styles.css index 119c528..7f9a7d7 100644 --- a/packages/plugins/multi-angle/package/assets/styles.css +++ b/packages/plugins/multi-angle/package/assets/styles.css @@ -185,7 +185,7 @@ svg { linear-gradient(145deg, #121520, #0d0f17); } .source-stage.has-image { background: #08090d; } -.source-image { width: 100%; height: 100%; min-height: 276px; max-height: 350px; object-fit: contain; } +.source-image { width: auto; height: auto; max-width: 100%; max-height: 350px; image-rendering: auto; } .source-grid { position: absolute; inset: 0; diff --git a/packages/plugins/multi-angle/package/index.html b/packages/plugins/multi-angle/package/index.html index 80a2500..bd8636f 100644 --- a/packages/plugins/multi-angle/package/index.html +++ b/packages/plugins/multi-angle/package/index.html @@ -3,6 +3,7 @@ + 多角度 @@ -50,7 +51,7 @@

参考主体

- +