返回 DeepSeek-Reasonix
EXTENSIONS.md
根目录 / docs / EXTENSIONS.md
1 # Reasonix Extensions
2
3 Extensions let a plugin package change what Reasonix does at runtime —
4 rewrite input, intercept tool calls, replace the system prompt, contribute
5 streaming model providers, publish structured UI, and ship prompts and
6 themes — using a stable, versioned contract.
7
8 Two kinds of plugin capabilities exist:
9
10 - **Declarative** (any plugin package): skills, agents, commands, prompts,
11 hooks, MCP servers, and themes. These are files and configuration; they
12 run with the host's normal permissions.
13 - **Code runtime** (Manifest v1 `runtime` block): a sidecar process speaking
14 the Extension Protocol. Code extensions are **full trust** — see the
15 security section below before installing one.
16
17 ## Installing and managing
18
19 Extensions install exactly like any plugin package:
20
21 ```bash
22 reasonix plugin install git:github.com/owner/extension --dry-run # preview
23 reasonix plugin install git:github.com/owner/extension --yes # install
24 reasonix plugin show <name> # details
25 reasonix plugin doctor <name> # validate
26 ```
27
28 For a plugin with a `runtime` block, the preview and `show` output include a
29 **FULL TRUST** block: the runtime command, the events it intercepts, the
30 replacement slots it owns, and its provider/UI capabilities. Installing,
31 updating, replacing, or `--link`ing is the authorization — there is no
32 second confirmation, and `--link` keeps trusting changed content. Only
33 install runtimes you trust completely.
34
35 ## What extensions can do
36
37 - **Interceptors** — observe and rule on 17 hook points (input, tool calls,
38 permission decisions, provider requests/responses, compaction, session
39 lifecycle, frontend events). An interceptor can `continue`, `block` with a
40 user-visible reason, or `replace` the payload; the host re-validates every
41 replacement.
42 - **Replacement strategies** — single-owner slots (`system_prompt`,
43 `context`, `provider_request`, `provider_response`, `compaction`,
44 `session_policy`, `permission`, `frontend_events`, `tool:<name>`,
45 `provider:<ref>`). One owner per slot across all installed plugins; a
46 collision fails the runtime build with both sources named.
47 - **Streaming providers** — new models appear as
48 `plugin/<plugin>/<provider>/<model>` in the model picker, streamed with
49 the same text/reasoning/tool-call/usage semantics as built-in providers.
50 The ref works everywhere a built-in ref does: `default_model`, `--model`,
51 the CLI/Desktop/ACP pickers, and mid-session model switches — including on
52 the very first boot.
53 - **Structured UI** — status entries, cards, forms, and notifications
54 rendered natively in the CLI transcript, the Desktop app, and ACP clients
55 (with text fallbacks), plus `/<plugin>:<action>` actions in the slash
56 menu, the Desktop command palette, and ACP's discoverable commands.
57 - **Prompts and themes** — `/<plugin>:<name>` prompt templates and
58 read-only plugin themes (`plugin:<plugin>:<theme>`) in Desktop Settings.
59
60 ## Runtime reload
61
62 Changing an installed extension (install, update, enable/disable, or
63 `--link` content changes) never mutates a running turn. Reloading is one
64 fail-atomic operation through every interactive frontend — CLI `/reload`,
65 Desktop **Reload Runtime** (command palette), Serve `/reload`, and the ACP
66 vendor method `_reasonix.io/session/reloadExtensions`:
67
68 1. If a turn or background work is running, CLI/Desktop/ACP queue exactly one
69 reload; Serve rejects the request so the browser can retry once idle.
70 2. When idle, Reasonix starts new sidecars and builds a new runtime
71 snapshot.
72 3. On full success it swaps atomically, carrying over the session path,
73 transcript, approval grants, and goal/recovery state.
74 4. If the new build fails, the old runtime keeps working untouched.
75 5. Only after the swap are the old sidecars retired.
76
77 Each turn pins one runtime generation for the whole turn, tool batch, and
78 compaction — extension changes apply to the *next* turn, and a no-op reload
79 leaves the provider prompt-cache prefix byte-identical.
80
81 ## Performance and prompt cache
82
83 With no code runtime installed, the Agent takes the existing nil-dispatcher
84 path: no sidecar process, JSON encoding, RPC, or event queue is involved.
85 When runtimes are installed, Reasonix initializes at most four sidecars at once
86 inside one shared 30-second generation startup budget. A stalled optional
87 runtime therefore cannot multiply boot or reload time by the number of installed
88 packages. Packages that do not start inside that budget degrade or fail according
89 to their `runtime.required` setting.
90 Enabled synchronous interceptors are deliberately on the matching hot path and
91 run serially, so their RPC and handler latency is additive; keep input, tool,
92 permission, and provider interceptors small and deterministic. Observation
93 events use a bounded non-blocking queue and are dropped with a warning under
94 backpressure instead of stalling the turn.
95
96 An observation-only extension does not change the provider-visible cache
97 prefix. A stable system-prompt or tool replacement creates one intentional
98 cold prefix after install/reload and remains cacheable afterwards. A strategy
99 that injects timestamps, random values, session IDs, or other per-turn data
100 into the system prompt, tool schemas, context prefix, or provider request can
101 destroy cache reuse; dynamic data should stay in the current turn tail when
102 possible. Maintainers can measure host overhead with:
103
104 ```bash
105 go test ./internal/extension/... -run '^$' -bench 'Extension|Dispatch' -benchmem
106 ```
107
108 ## Developing an extension
109
110 Start with the complete
111 [`starterextension`](../sdk/go/examples/starterextension/README.md) package.
112 It keeps the manifest, Sidecar source, cross-platform build commands, linked
113 installation, and first observable intercept in one directory. The normal
114 development loop is:
115
116 1. Add `apiVersion: "reasonix.io/plugin/v1"` to `reasonix-plugin.json` and
117 declare `contributes` and (optionally) `runtime` — see
118 [Plugin Packages](./PLUGIN_PACKAGES.md#manifest-v1-extensions).
119 2. Implement the Sidecar. The [Go SDK](../sdk/go/README.md) (standard library
120 only) handles transport, handshake, sequencing, content references, and
121 shutdown; the [wire contract](./EXTENSION_PROTOCOL.md) and
122 [generated method index](./EXTENSION_PROTOCOL.generated.md) are the
123 language-neutral references.
124 3. Build the runtime binary, preview its trust and capabilities with
125 `reasonix plugin install /path/to/plugin --dry-run`, then install it with
126 `--link --yes`.
127 4. Validate with `reasonix plugin doctor <name>`, run `/reload` while idle,
128 and exercise the contributed intercept, Provider, UI action, or resource.
129
130 SDK releases use immutable `sdk/go/vX.Y.Z` tags. The first public version is
131 `sdk/go/v1.0.0`; until that tag exists, use the starter from a source checkout
132 instead of relying on an unversioned module.
133
134 ## Compatibility
135
136 - Manifests without `apiVersion` parse exactly as before.
137 - Older Reasonix versions ignore extension-only state: the per-session
138 `<session>.extensions.json` sidecar file, `plugin/...` model refs (they
139 simply resolve as unavailable models), and the `extension_surface` /
140 `extension_status` event kinds (older frontends drop unknown kinds; ACP
141 clients without `reasonix.extensionSurface` get text fallbacks).
142 - `plugin-packages.json` keeps its existing schema; an enabled installed
143 runtime *is* the trust record.
144
145 ## Security model
146
147 A code extension runs outside the Reasonix sandbox with the unfiltered
148 inherited environment. It can read the full session and environment, bypass
149 permissions and workspace restrictions, and operate the machine directly;
150 its `permission.decision` "allow" overrides a host deny. In return the host
151 enforces:
152
153 - only plugins installed through the plugin flow can start a runtime —
154 project configuration can never declare one;
155 - the handshake rejects any capability beyond the manifest;
156 - replacements are re-validated against each point's DTO and schema;
157 - sidecar diagnostics, structured UI, interceptor reasons, and provider errors
158 are credential-redacted by the host before they reach the UI, logs, or error
159 surfaces; ordinary provider/model content is preserved as product data;
160 - a crashed sidecar fails its own operations explicitly — Reasonix never
161 silently falls back to another model or strategy.
162
162 lines MARKDOWN