mirror of
https://github.com/codewhale-hq/Codewhale.git
synced 2026-11-11 17:09:23 -10:00
docs(plugins): say how a host service is asked for, granted, shared and refused, and who approved (CW-8012)
EXTENSIONS.md gains the host services section with who may approve, the reach of each approver, that the agent's mark is a label it can remove in Full Access, and the per-kind sharing rule. The CHANGELOG line says plainly that Codewhale 0.10.2 turns plugins off on a state file in which a plugin was reviewed or turned on by this release. Co-Authored-By: Claude Fable 5.2 <[email protected]> Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
d1ea4bcecc
commit
1e2106e63a
7 files changed
+113
-5
No files matched your search
@@ -49,6 +49,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- ACP: editors can start, list, load, prompt and cancel Codewhale sessions and approve or reject tool permissions through the Runtime; prompts with image or audio blocks and relative session directories are now refused instead of ignored, and edit and read tools report the right kind. Sessions an editor drives now run the plugin tools (TypeScript and DSH, when the extension host is on) and the MCP servers configured in Codewhale; their calls show as ACP tool calls and ask through the session's permission setting, and `initialize` reports the state under `agentCapabilities._meta.codewhale`. MCP servers an editor passes in `mcpServers` and configured shell hooks still do not run in ACP sessions. A real-editor journey is not yet proved.
|
||||
- Extension host: the `sessions` and `systemPrompt` services now come from a reviewed DSH adapter instead of inline shims, and `sessions.flush` refuses an empty checkpoint ticket. Session reads and events and the `agent/pre-step` hook are still not available to plugins. (CW-7959)
|
||||
- Extension host: DSH service adapters now have one ticketed `dsh/broker` request to the core, each ticket is bound to the plugin, the service and the session, and every service (workspace, llm, network, settings, catalog, terminal and remote) refuses with a typed `not_available` until its broker lands. Nothing new is offered to plugins yet. (CW-8012)
|
||||
- **Plugin host services and who approved:** a plugin can now be granted a Codewhale host service, and only by a review that shows it. The review names each service and the plugins it is shared with, and every review records who approved it: you, the agent (in Full Access, in Auto-Review, or from a shell command carrying the agent's mark), or the command line with `--yes`; who turned the plugin on is recorded too. Plugins share one process, so a service works only while every loaded plugin of the same kind holds the same grant. A plugin the agent approved is active only in its own project and its code does not run beside the plugins you reviewed until you review it. No service is offered yet, and a plugin reviewed before this release holds no grant until it is reviewed again. Once a plugin has been reviewed or turned on in this release, Codewhale 0.10.2 and earlier cannot read the plugin state file and turn every plugin off when run on the same home folder. (CW-8012)
|
||||
- Fleet member starts are now durable: replaying an operation key after a timeout or restart returns the original worker, and GET /v1/threads/{id}/members/operations/{key} reports the outcome. A member start now answers with `state` `accepted` (200) or `unknown` (202) instead of `started` or `queued`. Verified by local HTTP tests on Linux; a real Engine restart is simulated, not exercised. (CW-7964)
|
||||
- Plugin activation now says when a requested service belongs to the Codewhale core and is not exposed to plugins yet. No plugin, provider or installed-app run exercised it; checked by the extension-host tests only.
|
||||
- Codex App Server v2 contract record (paused, not part of 0.10.3): the selected Codex v2 contract is frozen as a generated manifest in the protocol crate, with typed Rust and TypeScript shapes checked against the pinned Codex schema. It changes no wire behavior and adds no dispatch, so nothing is reachable through it yet.
|
||||
|
||||
@@ -49,6 +49,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- ACP: editors can start, list, load, prompt and cancel Codewhale sessions and approve or reject tool permissions through the Runtime; prompts with image or audio blocks and relative session directories are now refused instead of ignored, and edit and read tools report the right kind. Sessions an editor drives now run the plugin tools (TypeScript and DSH, when the extension host is on) and the MCP servers configured in Codewhale; their calls show as ACP tool calls and ask through the session's permission setting, and `initialize` reports the state under `agentCapabilities._meta.codewhale`. MCP servers an editor passes in `mcpServers` and configured shell hooks still do not run in ACP sessions. A real-editor journey is not yet proved.
|
||||
- Extension host: the `sessions` and `systemPrompt` services now come from a reviewed DSH adapter instead of inline shims, and `sessions.flush` refuses an empty checkpoint ticket. Session reads and events and the `agent/pre-step` hook are still not available to plugins. (CW-7959)
|
||||
- Extension host: DSH service adapters now have one ticketed `dsh/broker` request to the core, each ticket is bound to the plugin, the service and the session, and every service (workspace, llm, network, settings, catalog, terminal and remote) refuses with a typed `not_available` until its broker lands. Nothing new is offered to plugins yet. (CW-8012)
|
||||
- **Plugin host services and who approved:** a plugin can now be granted a Codewhale host service, and only by a review that shows it. The review names each service and the plugins it is shared with, and every review records who approved it: you, the agent (in Full Access, in Auto-Review, or from a shell command carrying the agent's mark), or the command line with `--yes`; who turned the plugin on is recorded too. Plugins share one process, so a service works only while every loaded plugin of the same kind holds the same grant. A plugin the agent approved is active only in its own project and its code does not run beside the plugins you reviewed until you review it. No service is offered yet, and a plugin reviewed before this release holds no grant until it is reviewed again. Once a plugin has been reviewed or turned on in this release, Codewhale 0.10.2 and earlier cannot read the plugin state file and turn every plugin off when run on the same home folder. (CW-8012)
|
||||
- Fleet member starts are now durable: replaying an operation key after a timeout or restart returns the original worker, and GET /v1/threads/{id}/members/operations/{key} reports the outcome. A member start now answers with `state` `accepted` (200) or `unknown` (202) instead of `started` or `queued`. Verified by local HTTP tests on Linux; a real Engine restart is simulated, not exercised. (CW-7964)
|
||||
- Plugin activation now says when a requested service belongs to the Codewhale core and is not exposed to plugins yet. No plugin, provider or installed-app run exercised it; checked by the extension-host tests only.
|
||||
- Codex App Server v2 contract record (paused, not part of 0.10.3): the selected Codex v2 contract is frozen as a generated manifest in the protocol crate, with typed Rust and TypeScript shapes checked against the pinned Codex schema. It changes no wire behavior and adds no dispatch, so nothing is reachable through it yet.
|
||||
|
||||
@@ -143,6 +143,22 @@ WebRTC traffic despite content rules, CSP, an opaque sandboxed frame and a
|
||||
restrictive Permissions-Policy; that historical result does not qualify the
|
||||
current Electron/Chromium host.
|
||||
|
||||
## Host services and grants
|
||||
|
||||
DSH services that need the core to act for a plugin (`llm`, `credentials`,
|
||||
`settings`, `terminal`, `remote`, the plugin catalog, workspace files) are
|
||||
brokered: the Rust core serves them, and only for a plugin whose review granted
|
||||
them. See [Host services](EXTENSIONS.md#host-services).
|
||||
|
||||
| Behavior | Status |
|
||||
| --- | --- |
|
||||
| A service is granted only by a review that showed it, recorded with who approved | Verified by focused plugin and Engine tests on Linux |
|
||||
| A review recorded before grants existed, or an altered or unreadable record | Grants nothing; verified by focused tests |
|
||||
| Plugins share one process: a service is given only while every loaded plugin holds the same grant | Verified by focused Engine tests |
|
||||
| Turned off, revoked or reviewed again | Grant withdrawn at once, including a call in flight; verified by focused Engine tests |
|
||||
| Services offered by this build | None. Each is switched on separately, after its own review |
|
||||
| A real plugin using a granted service end to end | Not verified |
|
||||
|
||||
## Containment
|
||||
|
||||
| Behavior | Status |
|
||||
|
||||
+79
-1
@@ -611,6 +611,80 @@ tool's text (`content`) and, when it was JSON, the parsed value
|
||||
tool asked the core to run is recorded (bounded) in your tool result's
|
||||
`core_calls` metadata, with each call's decision and outcome.
|
||||
|
||||
## Host services
|
||||
|
||||
A host service is something the core does for an extension beyond running a
|
||||
core tool: workspace files and commands, the model provider, network requests,
|
||||
settings, the plugin catalog, terminal sessions and remote pairing. Each is
|
||||
served by the core, never by the host process, and each is off until a review
|
||||
grants it. This version of Codewhale offers none of them yet: the mechanism is
|
||||
in place, and each service is switched on separately.
|
||||
|
||||
**Asking.** Name the services in the manifest. A name outside this list fails
|
||||
validation.
|
||||
|
||||
```toml
|
||||
[capabilities]
|
||||
host_services = ["network"]
|
||||
```
|
||||
|
||||
(In a `plugin.json` bundle: `extensions["net.codewhale"].capabilities.host_services`.)
|
||||
For an imported DeepSeek Harness package the importer writes this list from the
|
||||
package's own `inject` declarations. What a bundle asks for is part of its
|
||||
capability hash, so changing the list needs a new review.
|
||||
|
||||
**Granting.** Only a review grants a service, and only when the review showed
|
||||
it: the review lists each service in plain words, the reviewed plugins that
|
||||
already hold it, and any plugin that is turned on without it. Approval is bound
|
||||
to exactly that list. If it changed between showing and approving, the approval
|
||||
is refused and nothing is recorded. A review that did not show the services
|
||||
(`/plugin trust` today) records trust and grants none. A review recorded before
|
||||
this feature holds no grant.
|
||||
|
||||
**Who approved.** Every review records its approver, and every place that shows
|
||||
a plugin's trust shows it:
|
||||
|
||||
| Approver | How it happens | Reach |
|
||||
| --- | --- | --- |
|
||||
| You | the Plugins page, `/plugin trust`, or an approval card | every project |
|
||||
| The agent, in Full Access or Auto-Review | the agent's plugin tool, bound to the token of the review composed for that call and to the thread, turn and tool call that made it | only the project named in the record |
|
||||
| The agent, from a shell command | `codewhale plugins trust … --yes` run by a process that carries the agent's mark | only the project named in the record |
|
||||
| The command line | `codewhale plugins trust … --yes` without the mark: no review was shown there | every project |
|
||||
|
||||
The agent's mark is a label on the agent's shell commands, not a lock: in Full
|
||||
Access the agent can remove it, and the record then says "the command line".
|
||||
A plugin the agent approved is active only in the project its record names,
|
||||
and its code does not run in the host process of the plugins you reviewed:
|
||||
until it has a host of its own, its native code is refused with a diagnostic
|
||||
that asks you to review it. Your own review replaces the agent's record. Who
|
||||
turned a plugin on is recorded the same way, separately from who approved it.
|
||||
|
||||
**One process, one rule.** Extensions share one host process and cannot be
|
||||
isolated from each other inside it. A service is therefore given to a tool call
|
||||
only while every extension loaded in that process holds the same grant. The
|
||||
rule, and the list of plugins a review says a service is shared with, cover
|
||||
only plugins of the same kind: the plugins you reviewed are counted together,
|
||||
and a plugin the agent approved is never counted with them. If one
|
||||
does not, the service is off for all of them, and the host diagnostics name the
|
||||
extension without it. Code that was loaded cannot be unloaded, so after an
|
||||
extension is turned off, changed or fails, every service stays off until the
|
||||
host process has restarted, which Codewhale does by itself once the host is
|
||||
idle.
|
||||
|
||||
**What a refused call receives.** `REFUSED` with `data.dsh_refusal`:
|
||||
`not_granted` (the same answer whether your own review lacks the service or
|
||||
another extension's does), `limit` (this tool call used up its calls to that
|
||||
service), `ticket_refused`, `cancelled`, or the service's own typed refusal.
|
||||
Turning an extension off, revoking it or reviewing it again withdraws its grant
|
||||
at once: a call already running is dropped and its answer withheld.
|
||||
|
||||
Known limits: a grant is all of what the review showed or none of it; there is
|
||||
no per-service choice inside one review. The review record is protected by its
|
||||
private directory, not by a signature: another program running as you, outside
|
||||
the sandbox, can write it, as it can write trust itself. A change made by
|
||||
another Codewhale process reaches a running call within about 50 ms; a side
|
||||
effect a service completes inside that window is not undone.
|
||||
|
||||
## Lifecycle, diagnostics and restarts
|
||||
|
||||
Use `/plugin show <name>` for that plugin's owner state, live tool names and
|
||||
@@ -679,7 +753,11 @@ resident size at each 3-second heartbeat and kills it past the cap. Under Node
|
||||
the JavaScript heap is also limited to 256 MiB. The host has a
|
||||
32 MiB frame limit, 256 in-flight request
|
||||
limit (plus a reserved heartbeat), 128 tools per owner and 1024 per host, and
|
||||
64 commands per owner and 256 per host. Tool
|
||||
64 commands per owner and 256 per host. One tool call may make 50 core tool
|
||||
calls in all, counting those a host service makes for it, and 50 calls to each
|
||||
host service. Eight invalid tickets in a minute end the host process for every
|
||||
extension in it; a ticket whose tool call ended in the last 10 seconds is
|
||||
refused without counting. Tool
|
||||
descriptions are at most 4 KiB and schemas 64 KiB. Tool calls have a 120-second
|
||||
deadline and commands a 30-second one. The feature stays Experimental and off by default; local fixture
|
||||
tests do not establish sandbox parity, provider behavior or release readiness.
|
||||
@@ -240,6 +240,13 @@ The accept/reject behavior is deliberately loud, never silent:
|
||||
- `capabilities.network_hosts` is not a future surface: it is enforced today,
|
||||
and must exactly match the normalized host set of the bundle's remote MCP
|
||||
endpoints (so it cannot be declared without them, or omitted with them).
|
||||
- `capabilities.host_services` names the host services a bundle's native code
|
||||
asks to use (`workspace`, `llm`, `network`, `settings`, `catalog`,
|
||||
`terminal`, `remote`). It is hashed into the capability receipt only when it
|
||||
is not empty, so bundles that ask for nothing keep their review. Asking
|
||||
grants nothing: only a review that showed the services does, and this
|
||||
version offers none yet. See
|
||||
[Host services](EXTENSIONS.md#host-services).
|
||||
|
||||
A successful environment or health check is never treated as trust.
|
||||
|
||||
|
||||
@@ -208,6 +208,11 @@ lifecycle_mutation = true
|
||||
- `capabilities.network_hosts` 不属于未来才会生效的组件面:它今天就已强制执行,
|
||||
且必须与插件包远程 MCP 端点的归一化主机集合完全一致
|
||||
(有远程 MCP 端点就必须声明它,没有远程端点就不能声明)。
|
||||
- `capabilities.host_services` 列出插件包的原生代码请求使用的宿主服务
|
||||
(`workspace`、`llm`、`network`、`settings`、`catalog`、`terminal`、`remote`)。
|
||||
只有在该列表非空时才计入能力回执的哈希,因此不请求任何服务的插件包无需重新审查。
|
||||
声明本身不授予任何权限:只有展示过这些服务的审查才会授予,而当前版本尚未开放任何服务。
|
||||
参见[宿主服务](../EXTENSIONS.md#host-services)。
|
||||
|
||||
环境检查或健康检查通过,永远不等于信任。
|
||||
|
||||
|
||||
@@ -313,8 +313,8 @@
|
||||
},
|
||||
{
|
||||
"path": "docs/PLUGIN_BUNDLES.md",
|
||||
"sha256": "bc178f6e0c60792f135476ea2e301796125089c5cae164f69af906212a56b9ce",
|
||||
"content": "# Plugin bundles\n\n> 阅读简体中文版:[zh_hans/PLUGIN_BUNDLES.md](zh_hans/PLUGIN_BUNDLES.md)。\n\nCodewhale supports a deliberately small plugin-bundle boundary. The boundary\nwas drawn in v0.9.1 and is extended deliberately in v0.9.10: a bundle may\ncontribute declarative Skills, MCP configuration, Commands, Agent profiles,\nand Hooks through Codewhale's existing engines. Unsupported declarations stay\ninventoried instead of disabling a mixed bundle. Discovery alone never\nexecutes, enables, trusts, downloads, updates, or installs anything.\n\nThis document owns the bundle formats, discovery,\nvalidation, and the trust/enable/runtime contract. [PLUGINS.md](PLUGINS.md)\nowns how bits get onto and off disk — the `/plugin install`, `update`,\n`uninstall`, and `suggest` on-ramp added in v0.9.4 (#5182). Compatible Claude Code bundles use the same native adapters; their supported subset is\n[CLAUDE_PLUGIN_COMPAT.md](CLAUDE_PLUGIN_COMPAT.md).\nFor a runnable native example and explicit OpenCode/DSH data conversion, see\n[Write your first plugin](PLUGIN_AUTHORING.md).\n\n## Discovery and precedence\n\nCodewhale scans only its own roots, looking in each `<name>/` directory for a\nmanifest named `plugin.json` (the native Agent Plugins v1.0.0 format, since\nv0.9.4), `kimi.plugin.json` (the compatible Kimi Skills/MCP subset, since\nv0.9.8), `plugin.toml` (the legacy Codewhale format, still fully readable), or\n`.claude-plugin/plugin.json` (the compatible Claude subset, since v0.9.13):\n\n- User: `~/.codewhale/plugins/<name>/`\n- Workspace: `<workspace>/.codewhale/plugins/<name>/`\n\nA bundle that publishes multiple formats is read through `plugin.json` first,\nthen `kimi.plugin.json`, then the legacy `plugin.toml`, then\n`.claude-plugin/plugin.json`.\nComputer Use installs from the first-party catalog as a normal user plugin.\nIt updates independently of the Engine and requires review and enablement.\nThe native Mac helper is installed separately for permission setup and the\ncomputer-control indicator. See the [Computer Use guide](https://github.com/codewhale-hq/codewhale-cu-plugin).\n\nUser plugins take precedence over workspace plugins. Symbolic-link roots,\nmanifests, component paths, and nested component files fail closed.\nHistorical built-in snapshots and receipts remain untouched for older binaries;\nthe current Engine neither creates nor discovers a built-in Computer Use copy.\nInstall and review the catalog plugin once when upgrading from that layout.\n\nNew user and workspace bundles are always untrusted and disabled. Discovery is\nread-only and does not inspect any other application's extension or credential\ndirectories: ambient roots such as `.claude/plugins` or `.cursor/plugins` are\nnever scanned.\n\nPre-v0.9.1 `overrides.json` enablement was intentionally not imported as\ntrust; every bundle activates only through the content-hash and\n`codewhale-plugin-capabilities-v3` activation-policy review below.\n\n## Manifest\n\nAll supported encodings parse into the same internal manifest, so validation, hashing,\nreview, and runtime behavior are identical downstream. On-disk auto-migration\nbetween them is deliberately not performed; `/plugin export <name>\n<target-dir>` publishes a loaded bundle as a spec-valid Agent Plugins v1.0.0\ndirectory without modifying the installed one.\n\n### `plugin.json` (Agent Plugins v1.0.0)\n\nThe standard's manifest root is closed: `$schema`, `name`, and the optional\nwell-known fields (`version`, `description`, `author`, `homepage`,\n`repository`, `license`, `keywords`, `extensions`). An unknown root key is a\nparse error. Client-specific data lives under `extensions`, keyed by\nreverse-domain namespace: unknown vendor namespaces are ignored, never\nrejected — that is what lets a bundle authored for another client load here —\nwhile unknown keys inside Codewhale's own `extensions[\"net.codewhale\"]`\nnamespace are rejected rather than silently dropped.\n\nNames follow the standard's rule: 1–64 lowercase ASCII letters, digits, or\ninternal single `-`/`.`, starting and ending alphanumeric, never `--` or `..`.\nA `skills/` directory in the bundle root is picked up automatically; other\ncomponent locations, `capabilities`, `when`, and `display_name` ride in\n`extensions[\"net.codewhale\"]`.\n\nMCP servers cannot live in `plugin.json` (the root is closed); they live in a\nsibling `mcp.json` under `mcpServers`, with `stdio`, `streamable-http`, or\n`sse` transports (`type` may be omitted and is inferred from `command` vs\n`url`). Codewhale-only server options — timeouts, tool filters, env-backed\ncredentials, enablement — ride per-server under `extensions[\"net.codewhale\"]`.\nThe `env` names `PLUGIN_ROOT` and `PLUGIN_DATA` are reserved by the standard\nfor the host runtime and are rejected in plugin definitions.\n\n### `plugin.toml` (legacy Codewhale format)\n\n```toml\nschema_version = 1\n\n[plugin]\nname = \"example\"\nversion = \"0.1.0\Line truncated
|
||||
"sha256": "5901d95a9a294590d19cf736140986967470eea02782776f250c1bb929608b65",
|
||||
"content": "# Plugin bundles\n\n> 阅读简体中文版:[zh_hans/PLUGIN_BUNDLES.md](zh_hans/PLUGIN_BUNDLES.md)。\n\nCodewhale supports a deliberately small plugin-bundle boundary. The boundary\nwas drawn in v0.9.1 and is extended deliberately in v0.9.10: a bundle may\ncontribute declarative Skills, MCP configuration, Commands, Agent profiles,\nand Hooks through Codewhale's existing engines. Unsupported declarations stay\ninventoried instead of disabling a mixed bundle. Discovery alone never\nexecutes, enables, trusts, downloads, updates, or installs anything.\n\nThis document owns the bundle formats, discovery,\nvalidation, and the trust/enable/runtime contract. [PLUGINS.md](PLUGINS.md)\nowns how bits get onto and off disk — the `/plugin install`, `update`,\n`uninstall`, and `suggest` on-ramp added in v0.9.4 (#5182). Compatible Claude Code bundles use the same native adapters; their supported subset is\n[CLAUDE_PLUGIN_COMPAT.md](CLAUDE_PLUGIN_COMPAT.md).\nFor a runnable native example and explicit OpenCode/DSH data conversion, see\n[Write your first plugin](PLUGIN_AUTHORING.md).\n\n## Discovery and precedence\n\nCodewhale scans only its own roots, looking in each `<name>/` directory for a\nmanifest named `plugin.json` (the native Agent Plugins v1.0.0 format, since\nv0.9.4), `kimi.plugin.json` (the compatible Kimi Skills/MCP subset, since\nv0.9.8), `plugin.toml` (the legacy Codewhale format, still fully readable), or\n`.claude-plugin/plugin.json` (the compatible Claude subset, since v0.9.13):\n\n- User: `~/.codewhale/plugins/<name>/`\n- Workspace: `<workspace>/.codewhale/plugins/<name>/`\n\nA bundle that publishes multiple formats is read through `plugin.json` first,\nthen `kimi.plugin.json`, then the legacy `plugin.toml`, then\n`.claude-plugin/plugin.json`.\nComputer Use installs from the first-party catalog as a normal user plugin.\nIt updates independently of the Engine and requires review and enablement.\nThe native Mac helper is installed separately for permission setup and the\ncomputer-control indicator. See the [Computer Use guide](https://github.com/codewhale-hq/codewhale-cu-plugin).\n\nUser plugins take precedence over workspace plugins. Symbolic-link roots,\nmanifests, component paths, and nested component files fail closed.\nHistorical built-in snapshots and receipts remain untouched for older binaries;\nthe current Engine neither creates nor discovers a built-in Computer Use copy.\nInstall and review the catalog plugin once when upgrading from that layout.\n\nNew user and workspace bundles are always untrusted and disabled. Discovery is\nread-only and does not inspect any other application's extension or credential\ndirectories: ambient roots such as `.claude/plugins` or `.cursor/plugins` are\nnever scanned.\n\nPre-v0.9.1 `overrides.json` enablement was intentionally not imported as\ntrust; every bundle activates only through the content-hash and\n`codewhale-plugin-capabilities-v3` activation-policy review below.\n\n## Manifest\n\nAll supported encodings parse into the same internal manifest, so validation, hashing,\nreview, and runtime behavior are identical downstream. On-disk auto-migration\nbetween them is deliberately not performed; `/plugin export <name>\n<target-dir>` publishes a loaded bundle as a spec-valid Agent Plugins v1.0.0\ndirectory without modifying the installed one.\n\n### `plugin.json` (Agent Plugins v1.0.0)\n\nThe standard's manifest root is closed: `$schema`, `name`, and the optional\nwell-known fields (`version`, `description`, `author`, `homepage`,\n`repository`, `license`, `keywords`, `extensions`). An unknown root key is a\nparse error. Client-specific data lives under `extensions`, keyed by\nreverse-domain namespace: unknown vendor namespaces are ignored, never\nrejected — that is what lets a bundle authored for another client load here —\nwhile unknown keys inside Codewhale's own `extensions[\"net.codewhale\"]`\nnamespace are rejected rather than silently dropped.\n\nNames follow the standard's rule: 1–64 lowercase ASCII letters, digits, or\ninternal single `-`/`.`, starting and ending alphanumeric, never `--` or `..`.\nA `skills/` directory in the bundle root is picked up automatically; other\ncomponent locations, `capabilities`, `when`, and `display_name` ride in\n`extensions[\"net.codewhale\"]`.\n\nMCP servers cannot live in `plugin.json` (the root is closed); they live in a\nsibling `mcp.json` under `mcpServers`, with `stdio`, `streamable-http`, or\n`sse` transports (`type` may be omitted and is inferred from `command` vs\n`url`). Codewhale-only server options — timeouts, tool filters, env-backed\ncredentials, enablement — ride per-server under `extensions[\"net.codewhale\"]`.\nThe `env` names `PLUGIN_ROOT` and `PLUGIN_DATA` are reserved by the standard\nfor the host runtime and are rejected in plugin definitions.\n\n### `plugin.toml` (legacy Codewhale format)\n\n```toml\nschema_version = 1\n\n[plugin]\nname = \"example\"\nversion = \"0.1.0\Line truncated
|
||||
},
|
||||
{
|
||||
"path": "docs/PLUGIN_MARKETPLACE.md",
|
||||
@@ -323,8 +323,8 @@
|
||||
},
|
||||
{
|
||||
"path": "docs/EXTENSIONS.md",
|
||||
"sha256": "fee756fa0715db7c6c3e83c5fbd124b9b0faa0cb11dded91845d4c913839bc5b",
|
||||
"content": "# Writing an extension tool or command\n\nThe experimental TypeScript extension host runs reviewed plugin code in a\nshared Node process (or, as an opt-in, Bun). Rust still owns sessions, tool admission, approval and\nexecution. Extensions currently contribute tools and slash commands; they\ncannot provide an approval service, run a second agent loop or replace\nbuilt-in tools or commands.\n\n## Quick start\n\nStart with [hello-extension](examples/plugins/hello-extension/hello.mts) and its\n[plugin.json](examples/plugins/hello-extension/plugin.json). The example is\nexecuted unchanged by the host tests. It returns a greeting and does not read\nfiles or use the network.\n\n1. Explicitly enable `[features] extension_host = true` in your configuration,\n or start Codewhale with `codewhale --enable extension_host` (the flag goes\n before any subcommand).\n2. Install the example's directory using `/plugin install <local-directory>`.\n3. Run `/plugin validate hello-extension`, then `/plugin show hello-extension`.\n4. Run `/plugin enable hello-extension` to open its content/capability review.\n Read the review and personally run its exact `/plugin trust <token>` command,\n then enable the plugin. Trust alone does not execute the code.\n5. Ask Codewhale to use `hello_greet`. The tool follows the normal approval gate.\n6. Run `/hello-greet Codewhale`. The command runs when you type it, and shows\n its answer in the transcript with its origin, `extension:hello-extension`.\n\nAn authoring agent should stop after installation and validation and present\nthe review to the person. Do not trust or enable a bundle automatically.\n\n## Locations, installation and trust\n\nUser bundles live under `~/.codewhale/plugins/`; workspace bundles live under\n`<workspace>/.codewhale/plugins/`. New bundles use Agent Plugins v1.0.0\n`plugin.json`. Declare `extensions[\"net.codewhale\"].native.path` as one regular\n`.mjs`, `.js` or `.mts` file inside the bundle. Directories and other extensions\nfail validation when the host is enabled. With the flag off, native entries\nremain inventory-only.\n\nA plugin may split its code across several entries with `native.paths` (up to\n64, alone or beside `path`). They are activated in the order declared, as the\nfibers of one plugin: they share one owner, so one disable, review change or\ncrash tears all of them down together. Each entry is a separate module with its\nown `apply`, and tool and command names must be unique across them. If an entry\nfails to activate (throws, requires a service the host does not provide, or has\na registration refused), only that entry is withdrawn: entries that already\nactivated stay registered, later entries still activate, and the plugin fails\nonly when no entry activates. Listing the same file twice is one entry.\n\n## Runtime\n\n`[extension_host] runtime` selects what runs the host. Node is the default.\nBun is an opt-in: it is qualified on macOS only, and becomes the default only\nafter an explicit, recorded cutover.\n\n```toml\n[extension_host]\nruntime = \"node\" # default: Node only\n# runtime = \"bun\" # Bun only; fails rather than falling back to Node\n# runtime = \"auto\" # Bun >= 1.4.0 if one is found and starts, otherwise Node\n# bun = \"~/.bun/bin/bun\" # the only Bun tried when set\n# node = \"/opt/homebrew/bin/node\" # the only Node tried when set\n# mcp_backend = \"rust\" # temporary opt-out; default is \"host\"\n```\n\nThe default `mcp_backend = \"host\"` uses the pinned MCP SDK independently of\n`[features] extension_host`, which controls optional Native extensions. Existing\nstdio and HTTP servers use modern discovery when supported; explicitly configured\nlegacy SSE servers use their legacy handshake. Rust retains process and network\nauthority, credential resolution, catalog admission, tool approval and cancellation.\nThe SDK receives opaque session selectors and exact operation grants. Modern\nrequests carry Rust-approved protocol metadata and headers without a session id.\n\nA typed discovery refusal can admit a legacy handshake. Only an explicit HTTP\ntransport refusal during that handshake can admit legacy SSE with a fresh exact\nRust grant. Legacy HTTP retains its GET preflight and bounded OAuth refresh;\nmodern HTTP does not inherit those session or resend behaviors. Incomplete result\nflows are reported without automatically repeating the operation. Credentials,\nconfigured URLs, OAuth browser/login operations and Computer Use decision keys\nstay in Rust.\n\nBoth backends share recorded semantic MCP goldens and retain separate transport\ngoldens, including discovery, authentication and session evidence. The Host default\nrequires those fixtures and the actual broker acceptance checks, plus the platform\nisolation and measured gates in Ops CURRENT_DECISIONS §26. An explicit\n`mcp_backend = \"rust\"` remains available for one release after the qualified default\nflip, before the native protocoLine truncated
|
||||
"sha256": "43df456f3dc8dd67b905a719a3d5b9d9f18620c0031bbbaa99f4456cc33276f8",
|
||||
"content": "# Writing an extension tool or command\n\nThe experimental TypeScript extension host runs reviewed plugin code in a\nshared Node process (or, as an opt-in, Bun). Rust still owns sessions, tool admission, approval and\nexecution. Extensions currently contribute tools and slash commands; they\ncannot provide an approval service, run a second agent loop or replace\nbuilt-in tools or commands.\n\n## Quick start\n\nStart with [hello-extension](examples/plugins/hello-extension/hello.mts) and its\n[plugin.json](examples/plugins/hello-extension/plugin.json). The example is\nexecuted unchanged by the host tests. It returns a greeting and does not read\nfiles or use the network.\n\n1. Explicitly enable `[features] extension_host = true` in your configuration,\n or start Codewhale with `codewhale --enable extension_host` (the flag goes\n before any subcommand).\n2. Install the example's directory using `/plugin install <local-directory>`.\n3. Run `/plugin validate hello-extension`, then `/plugin show hello-extension`.\n4. Run `/plugin enable hello-extension` to open its content/capability review.\n Read the review and personally run its exact `/plugin trust <token>` command,\n then enable the plugin. Trust alone does not execute the code.\n5. Ask Codewhale to use `hello_greet`. The tool follows the normal approval gate.\n6. Run `/hello-greet Codewhale`. The command runs when you type it, and shows\n its answer in the transcript with its origin, `extension:hello-extension`.\n\nAn authoring agent should stop after installation and validation and present\nthe review to the person. Do not trust or enable a bundle automatically.\n\n## Locations, installation and trust\n\nUser bundles live under `~/.codewhale/plugins/`; workspace bundles live under\n`<workspace>/.codewhale/plugins/`. New bundles use Agent Plugins v1.0.0\n`plugin.json`. Declare `extensions[\"net.codewhale\"].native.path` as one regular\n`.mjs`, `.js` or `.mts` file inside the bundle. Directories and other extensions\nfail validation when the host is enabled. With the flag off, native entries\nremain inventory-only.\n\nA plugin may split its code across several entries with `native.paths` (up to\n64, alone or beside `path`). They are activated in the order declared, as the\nfibers of one plugin: they share one owner, so one disable, review change or\ncrash tears all of them down together. Each entry is a separate module with its\nown `apply`, and tool and command names must be unique across them. If an entry\nfails to activate (throws, requires a service the host does not provide, or has\na registration refused), only that entry is withdrawn: entries that already\nactivated stay registered, later entries still activate, and the plugin fails\nonly when no entry activates. Listing the same file twice is one entry.\n\n## Runtime\n\n`[extension_host] runtime` selects what runs the host. Node is the default.\nBun is an opt-in: it is qualified on macOS only, and becomes the default only\nafter an explicit, recorded cutover.\n\n```toml\n[extension_host]\nruntime = \"node\" # default: Node only\n# runtime = \"bun\" # Bun only; fails rather than falling back to Node\n# runtime = \"auto\" # Bun >= 1.4.0 if one is found and starts, otherwise Node\n# bun = \"~/.bun/bin/bun\" # the only Bun tried when set\n# node = \"/opt/homebrew/bin/node\" # the only Node tried when set\n# mcp_backend = \"rust\" # temporary opt-out; default is \"host\"\n```\n\nThe default `mcp_backend = \"host\"` uses the pinned MCP SDK independently of\n`[features] extension_host`, which controls optional Native extensions. Existing\nstdio and HTTP servers use modern discovery when supported; explicitly configured\nlegacy SSE servers use their legacy handshake. Rust retains process and network\nauthority, credential resolution, catalog admission, tool approval and cancellation.\nThe SDK receives opaque session selectors and exact operation grants. Modern\nrequests carry Rust-approved protocol metadata and headers without a session id.\n\nA typed discovery refusal can admit a legacy handshake. Only an explicit HTTP\ntransport refusal during that handshake can admit legacy SSE with a fresh exact\nRust grant. Legacy HTTP retains its GET preflight and bounded OAuth refresh;\nmodern HTTP does not inherit those session or resend behaviors. Incomplete result\nflows are reported without automatically repeating the operation. Credentials,\nconfigured URLs, OAuth browser/login operations and Computer Use decision keys\nstay in Rust.\n\nBoth backends share recorded semantic MCP goldens and retain separate transport\ngoldens, including discovery, authentication and session evidence. The Host default\nrequires those fixtures and the actual broker acceptance checks, plus the platform\nisolation and measured gates in Ops CURRENT_DECISIONS §26. An explicit\n`mcp_backend = \"rust\"` remains available for one release after the qualified default\nflip, before the native protocoLine truncated
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
Reference in new issue
Block a user