@yaklabs-ai/plugin-sdk 0.13.0 → 0.13.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # @yaklabs-ai/plugin-sdk
2
2
 
3
- The SDK for authoring a **Kay directory plugin** — a plugin you write in a
4
- repository and add to Kay through an approved plugin repository source.
3
+ The SDK for authoring a **Bonsai directory plugin** — a plugin you write in a
4
+ repository and add to Bonsai through an approved plugin repository source.
5
5
 
6
6
  Published to the public npm registry under the MIT licence.
7
7
 
@@ -13,13 +13,13 @@ it under the name your plugin code actually imports:
13
13
  ```json
14
14
  {
15
15
  "dependencies": {
16
- "@kay/plugin-sdk": "npm:@yaklabs-ai/plugin-sdk@^0.13.0"
16
+ "@kay/plugin-sdk": "npm:@yaklabs-ai/plugin-sdk@^0.13.1"
17
17
  }
18
18
  }
19
19
  ```
20
20
 
21
21
  **The alias is not cosmetic.** The package is published as
22
- `@yaklabs-ai/plugin-sdk`, but Kay's daemon resolves the specifier
22
+ `@yaklabs-ai/plugin-sdk`, but Bonsai's daemon resolves the specifier
23
23
  `@kay/plugin-sdk` when it loads your entrypoint, so that is the name your source
24
24
  must import. The alias installs the published package at
25
25
  `node_modules/@kay/plugin-sdk`, satisfying both.
@@ -79,22 +79,22 @@ export default activate;
79
79
 
80
80
  ## Entrypoints
81
81
 
82
- | Import | What it gives you |
83
- | ----------------------------------- | -------------------------------------------------------------------------- |
84
- | `@kay/plugin-sdk/kay-agent` | Tools, URI modules, search providers, auth — the per-session agent surface |
85
- | `@kay/plugin-sdk/kay-app` | App-lifetime surface: storage, endpoints, app-scoped URI modules |
86
- | `@kay/plugin-sdk/kay-agent/testing` | `invokeToolForTest`, `fauxAuthContext` — for your own `node --test` runs |
87
- | `@kay/plugin-sdk/disclosure` | The conformance audit Kay gates your plugin with — run it before you ship |
82
+ | Import | What it gives you |
83
+ | ----------------------------------- | ---------------------------------------------------------------------------- |
84
+ | `@kay/plugin-sdk/kay-agent` | Tools, URI modules, search providers, auth — the per-session agent surface |
85
+ | `@kay/plugin-sdk/kay-app` | App-lifetime surface: storage, endpoints, app-scoped URI modules |
86
+ | `@kay/plugin-sdk/kay-agent/testing` | `invokeToolForTest`, `fauxAuthContext` — for your own `node --test` runs |
87
+ | `@kay/plugin-sdk/disclosure` | The conformance audit Bonsai gates your plugin with — run it before you ship |
88
88
 
89
- `kay-agent/host` is intentionally not published; it is Kay's own loading
89
+ `kay-agent/host` is intentionally not published; it is Bonsai's own loading
90
90
  machinery, not an authoring API.
91
91
 
92
92
  ## Check yourself against the gate that can reject you
93
93
 
94
- Kay runs `auditPluginDisclosure` against your `kay.agent` target **at load,
94
+ Bonsai runs `auditPluginDisclosure` against your `kay.agent` target **at load,
95
95
  fail-closed**: one violation and the whole target fails — no tools, no URI
96
96
  modules, no skills. It is the same function this entrypoint exports, so the
97
- run below is the run Kay does.
97
+ run below is the run Bonsai does.
98
98
 
99
99
  ```ts
100
100
  import {
@@ -128,7 +128,7 @@ Pass the loader's inputs, not a subset — the audit judges what it is given:
128
128
  - `commandBoundSkillIds` — the `localId` of every skill bound to a declared
129
129
  command (`contributes.commands[].handler.kind === "skill"`). Omit it when
130
130
  you have such commands and you will see `skill-link-missing-scheme`
131
- violations Kay itself would not report.
131
+ violations Bonsai itself would not report.
132
132
 
133
133
  `auditSkillCodegenPairs({ declaredSkills, exportedSkills, packageDir })` is the
134
134
  companion check for a bundled-skill plugin. It compares the decoded YAML
@@ -138,7 +138,7 @@ Both return violations rather than asserting, so any runner works. Both read fro
138
138
  and call your own `help()`, so run them in Node, and keep `activate` free of
139
139
  side effects: the probe calls it.
140
140
 
141
- `PLUGIN_DISCLOSURE_CONTRACT` names the floor this SDK enforces. Kay's load
141
+ `PLUGIN_DISCLOSURE_CONTRACT` names the floor this SDK enforces. Bonsai's load
142
142
  failure names the floor **it** enforces. Different numbers mean the rules
143
143
  moved, not your code — update this package and re-run.
144
144
 
@@ -149,47 +149,51 @@ someone remembering to cut one. If the numbers differ, a newer version exists.
149
149
  ## What this package is, and is not, at runtime
150
150
 
151
151
  Installing this SDK gives you **types, editor completion, and a runtime you can
152
- execute in your own tests**. It is not what runs inside Kay.
152
+ execute in your own tests**. It is not what runs inside Bonsai.
153
153
 
154
154
  When the daemon loads your plugin, chord bundles its declared target and keeps
155
155
  `@kay/plugin-sdk/*` as a host external. Those imports resolve to the SDK
156
- **bundled with the Kay app**. The host's copy always wins. That is deliberate —
156
+ **bundled with the Bonsai app**. The host's copy always wins. That is deliberate —
157
157
  one implementation, the one the daemon is built against — but it has a
158
158
  consequence worth stating plainly:
159
159
 
160
- > If your installed SDK is newer than your Kay app, code that typechecks against
160
+ > If your installed SDK is newer than your Bonsai app, code that typechecks against
161
161
  > a newly-added API can still fail at load time, because the running host does
162
162
  > not have it.
163
163
 
164
164
  Importing an entire subpath the host does not know about fails loudly and
165
165
  specifically (a `target-load` diagnostic naming the subpath, shown on the
166
- Plugins page). A _symbol_ that exists here but not in the host's older copy is
167
- not caught that way. Keep the SDK version in step with the Kay app you run.
166
+ App Store on the app's detail page). A _symbol_ that exists here but not in the host's older copy is
167
+ not caught that way. Keep the SDK version in step with the Bonsai app you run.
168
168
 
169
169
  The same skew applies to the conformance floor, and in the direction that
170
- bites: if your Kay app is **newer** than this package, it can enforce a rule
170
+ bites: if your Bonsai app is **newer** than this package, it can enforce a rule
171
171
  your copy of the audit does not know about, so a green local run is not a
172
172
  promise the host will load you. That is why the load failure names its
173
173
  contract number — compare it against `PLUGIN_DISCLOSURE_CONTRACT` here, and if
174
174
  they differ, update before you debug your code.
175
175
 
176
- ## Install the plugin in Kay
176
+ ## Install the plugin in Bonsai
177
177
 
178
178
  The fastest route is the local plugin root. Put the plugin directory in
179
- `~/.kay/plugins/<your-plugin>/` and turn it on in **Settings → Plugins**. That
180
- root is already consented, so there is no repository to stage and no Trust step,
181
- and your edits load without restarting Kay.
179
+ `~/.kay/plugins/<your-plugin>/` and enable it in **App Store → Installed**.
180
+ That root is already consented, so there is no repository to stage and no Trust
181
+ step. Commit your edits to load them without restarting Bonsai; uncommitted edits
182
+ never execute.
182
183
 
183
184
  To share a plugin with someone who does not have your files, commit it to a Git
184
- repository and have them add it under **Settings → Plugins → Plugin sources →
185
- Add repository source**. They stage the source, Trust it, and enable the plugin;
186
- Trust and activation are separate gates.
185
+ repository and have them add it under **App Store → Sources → Add source**.
186
+ They stage and Trust the source, then add the plugin: **Get** in
187
+ **App Store → Browse** for a marketplace catalog, or **Turn on** on the
188
+ source's page under **App Store → Sources** for a plain Git repository.
189
+ Either action installs and enables that plugin; source Trust does not install
190
+ every item it contains.
187
191
 
188
192
  A plugin executes as a trusted in-process Node module with the daemon's own
189
193
  authority. **The SDK does not provide a sandbox.** Putting code in the local
190
- plugin root is itself the decision to run it, with no prompt in between — so
191
- treat that directory exactly as carefully as you would Trust an unfamiliar
192
- repository.
194
+ plugin root makes it discoverable without a source Trust prompt; enabling its install
195
+ row is still required. Treat that directory exactly as carefully as you would
196
+ Trust an unfamiliar repository.
193
197
 
194
198
  ## Requirements
195
199
 
@@ -200,8 +204,8 @@ checkout script is not the standalone path. The SDK's `kay-app` declarations
200
204
  use `node:sqlite`, which TypeScript cannot resolve without the Node 24
201
205
  typings.
202
206
 
203
- When Kay loads your plugin, chord bundles the declared entrypoint and its
207
+ When Bonsai loads your plugin, chord bundles the declared entrypoint and its
204
208
  relative imports. Multi-file entrypoints are supported, and TypeScript syntax
205
209
  that native stripping cannot execute, such as enums, namespaces, constructor
206
210
  parameter properties, and decorators, is compiled into the bundle. The host
207
- SDK remains external and is supplied by the running Kay app.
211
+ SDK remains external and is supplied by the running Bonsai app.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
3
  "package": "@yaklabs-ai/plugin-sdk",
4
- "version": "0.13.0",
4
+ "version": "0.13.1",
5
5
  "target": "npm",
6
6
  "firstPartyLicense": "MIT",
7
7
  "bundled": [
@@ -20,7 +20,7 @@ declare interface AccountIdentity {
20
20
  readonly displayName?: string;
21
21
  /** Absolute URL of the account's avatar. */
22
22
  readonly avatarUrl?: string;
23
- /** Issuer-asserted beta-tester flag; only Kay's product-account service sets it. */
23
+ /** Issuer-asserted beta-tester flag; only Bonsai's product-account service sets it. */
24
24
  readonly betaTester?: boolean;
25
25
  readonly activeOrganizationId?: string;
26
26
  readonly organizationSelectionState?: "selected" | "unresolved";
@@ -28,7 +28,7 @@ declare interface AccountIdentity {
28
28
  /**
29
29
  * Provider-native session id claim (WorkOS's `sid`), needed to call the provider's own
30
30
  * session-revocation endpoint at sign-out (`POST /user_management/sessions/revoke`, not yet
31
- * wired — see `docs/kay-account-auth.md`'s "Sign-out guarantee" section). Only Kay's WorkOS
31
+ * wired — see `docs/kay-account-auth.md`'s "Sign-out guarantee" section). Only Bonsai's WorkOS
32
32
  * product-account exchange/refresh sets it; every other provider leaves it absent.
33
33
  */
34
34
  readonly providerSessionId?: string;
@@ -164,7 +164,7 @@ declare interface ApiKeyAuthSchemeField {
164
164
  readonly label: string;
165
165
  }
166
166
 
167
- /** Provider-owned instructions for creating a credential outside Kay. */
167
+ /** Provider-owned instructions for creating a credential outside Bonsai. */
168
168
  declare interface ApiKeyAuthSchemeSetup {
169
169
  readonly instructions: string;
170
170
  /** Absolute HTTPS page where the user can create or manage the credential. */
@@ -755,7 +755,7 @@ declare interface InteractionCandidate {
755
755
  declare type InteractionCandidateKind = "click" | "fill" | "select" | "scroll" | "wait" | "activate" | "press";
756
756
 
757
757
  declare interface InteractionDriver {
758
- /** Unique in the session. `builtin:` is reserved for Kay's own drivers. */
758
+ /** Unique in the session. `builtin:` is reserved for Bonsai's own drivers. */
759
759
  readonly id: string;
760
760
  /** Human-readable name the agent sees beside the driver's targets. */
761
761
  readonly label: string;
@@ -778,7 +778,7 @@ declare interface InteractionDriver {
778
778
  }
779
779
 
780
780
  /**
781
- * The Interaction driver contract: what a plugin implements to let Kay's agent drive something
781
+ * The Interaction driver contract: what a plugin implements to let Bonsai's agent drive something
782
782
  * on the user's machine (a browser, an app, a remote screen) through the harness-owned
783
783
  * Interaction engine.
784
784
  *
@@ -791,7 +791,7 @@ declare interface InteractionDriver {
791
791
  * every tool work on every driver.
792
792
  *
793
793
  * Shape mirrors `SearchProvider` behind `web_search`: one tool set owned by the harness, many
794
- * backends registered per session, the `builtin:` id namespace reserved for Kay's own.
794
+ * backends registered per session, the `builtin:` id namespace reserved for Bonsai's own.
795
795
  */
796
796
  /** "Browser Interaction" drives web pages; "Computer Use Interaction" drives native apps. */
797
797
  declare type InteractionDriverKind = "browser" | "computer-use";
@@ -850,7 +850,7 @@ declare interface InteractionRegion {
850
850
  }
851
851
 
852
852
  /**
853
- * One surface Kay ships, in the driver contract's own shape, so a plugin's driver is the surface
853
+ * One surface Bonsai ships, in the driver contract's own shape, so a plugin's driver is the surface
854
854
  * plus an identity: `{ id, label, kind, ...api.interaction.desktop }`. Each call is checked
855
855
  * against the plugin's `interaction.surface {surface}` grant, and then against the session's
856
856
  * permissions exactly as the agent's `interaction_*` tools are: an act is judged as the plugin
@@ -972,7 +972,7 @@ declare interface JevScoreQuestion {
972
972
  * Those are host-side (`@kay/agent-runtime`'s `kay/jev/`).
973
973
  * ---
974
974
  *
975
- * The vocabulary is Kay's own (SDK 0.12.0). Before it, `use` received TypeSafe's `TypeSafeClient`
975
+ * The vocabulary is Bonsai's own (SDK 0.12.0). Before it, `use` received TypeSafe's `TypeSafeClient`
976
976
  * and plugins coded against a vendor's types. It follows pi's classifier contract, which the host
977
977
  * runs Jev through: a yes/no question is `bool` and answers a `probability`, every instruction and
978
978
  * criterion is text, and the state is a JSON object.
@@ -1004,7 +1004,7 @@ declare const JsonValue_2: z.ZodType<JsonValue_2>;
1004
1004
 
1005
1005
  declare type JsonValue_3 = null | boolean | number | string | readonly JsonValue_3[] | JsonObject;
1006
1006
 
1007
- /** A plugin's Kay agent activation — receives only the brokered {@link KayAgentPluginApi}. */
1007
+ /** A plugin's Bonsai agent activation — receives only the brokered {@link KayAgentPluginApi}. */
1008
1008
  declare type KayAgentActivate = (api: KayAgentPluginApi) => void;
1009
1009
 
1010
1010
  /**
@@ -1043,7 +1043,7 @@ declare interface KayAgentInteractionSurfaces {
1043
1043
  readonly browserPane: InteractionSurface;
1044
1044
  /**
1045
1045
  * The user's desktop through the platform's accessibility APIs: native apps as targets
1046
- * (`app://<bundle id>`), their windows' controls as elements. On macOS Kay drives it with its
1046
+ * (`app://<bundle id>`), their windows' controls as elements. On macOS Bonsai drives it with its
1047
1047
  * bundled accessibility worker under the app's Accessibility permission; on a platform with no
1048
1048
  * backend it reports itself unavailable.
1049
1049
  */
@@ -1200,7 +1200,7 @@ declare interface KayAgentPluginApi {
1200
1200
  */
1201
1201
  readonly process: KayAgentProcess;
1202
1202
  /**
1203
- * Always present; the interaction surfaces Kay ships (its browser pane, and the desktop through
1203
+ * Always present; the interaction surfaces Bonsai ships (its browser pane, and the desktop through
1204
1204
  * the platform accessibility APIs), each call checked against `interaction.surface {surface}`
1205
1205
  * and the session's permissions (see {@link InteractionSurface}).
1206
1206
  * Wrap one in an {@link InteractionDriver} and register it with
@@ -1799,7 +1799,7 @@ declare type ModelPromptCache = Partial<Record<Exclude<CacheRetention, "none">,
1799
1799
  declare type ModelThinkingLevel = "off" | ThinkingLevel;
1800
1800
 
1801
1801
  /**
1802
- * Who may supply the OAuth client for a scheme: Kay's embedded client, or one the user pastes in
1802
+ * Who may supply the OAuth client for a scheme: Bonsai's embedded client, or one the user pastes in
1803
1803
  * (BYOOC). An UNORDERED SET — list order carries no meaning (nothing reads it as a preference).
1804
1804
  */
1805
1805
  declare type OAuthClientSupplier = "kay" | "user";
@@ -1812,7 +1812,7 @@ declare interface OAuthRedirectResult {
1812
1812
 
1813
1813
  /**
1814
1814
  * The two client-supply axes, structured so the illegal cell is unrepresentable: a `confidential`
1815
- * exchange's secret may only ever be Kay's (held by the host's broker, never pasted by a
1815
+ * exchange's secret may only ever be Bonsai's (held by the host's broker, never pasted by a
1816
1816
  * customer), so `confidential` types `clientSuppliers` as `readonly ["kay"]` — `confidential ×
1817
1817
  * user` is a compile-time impossibility in v1, not a runtime refusal. `pkce`'s `clientSuppliers`
1818
1818
  * is a non-empty set; {@link createOAuthPkceAuthScheme} dedupes it and refuses empty.
@@ -1995,7 +1995,7 @@ declare interface OpenRouterRouting {
1995
1995
  * {@link PLUGIN_DISCLOSURE_RULES} changes, and never for anything else.
1996
1996
  *
1997
1997
  * Two readers, and the second is why a number beats a changelog entry. A plugin author compares it
1998
- * against the Kay build they target. The daemon's loader NAMES it in the
1998
+ * against the Bonsai build they target. The daemon's loader NAMES it in the
1999
1999
  * `disclosure-conformance-failed` diagnostic, so a plugin that passed its own suite against an
2000
2000
  * older SDK and then failed at load says "this host enforces contract N, you audited against
2001
2001
  * something older" instead of leaving the author to guess whether their code or their SDK moved.
@@ -2084,7 +2084,7 @@ declare interface PluginDelegatedScheme {
2084
2084
  readonly connect: (ctx: PluginDelegatedConnectContext) => Promise<PluginDelegatedConnectResult>;
2085
2085
  /**
2086
2086
  * Mint fresh material from the current (expiring) material, including the `data` the last
2087
- * connect or refresh returned. Kay calls this only inside its credential authority, which holds
2087
+ * connect or refresh returned. Bonsai calls this only inside its credential authority, which holds
2088
2088
  * the refresh lease and saves the result; this hook performs the exchange and nothing else.
2089
2089
  * Returned `data` replaces the stored `data`; omitted `data` keeps it. Returned `expiresAt`
2090
2090
  * replaces the stored expiry; omitted `expiresAt` means the new material does not expire.
@@ -2161,7 +2161,7 @@ declare type PluginOAuthPkceScheme = PluginOAuthSchemeClientAxes & {
2161
2161
  readonly summary?: string;
2162
2162
  readonly authorizationUrl: string;
2163
2163
  readonly tokenUrl: string;
2164
- /** The Kay-supplied embedded client id; omit for a `confidential` scheme or a `pkce` scheme
2164
+ /** The Bonsai-supplied embedded client id; omit for a `confidential` scheme or a `pkce` scheme
2165
2165
  * the host ships no client for. */
2166
2166
  readonly clientId?: string;
2167
2167
  /**
@@ -2791,6 +2791,14 @@ declare interface ToolDefinition<TParams extends ToolParametersWire = ToolParame
2791
2791
  * explicit Stop.
2792
2792
  */
2793
2793
  durationClass?: "fast" | "long";
2794
+ /**
2795
+ * Set only for a tool whose rerun with the same arguments is harmless, such
2796
+ * as one keyed on its own call: after a crash cuts a call off, a pi-durable
2797
+ * session may rerun it with its recorded arguments (without `before_tool`)
2798
+ * instead of ending it as an interrupted error. Absent: never rerun. Ignored
2799
+ * on pi 0.99.1.
2800
+ */
2801
+ replaySafe?: true;
2794
2802
  /**
2795
2803
  * Optional capability⇄scheme binding. When present this tool is auth-gated: discoverable when
2796
2804
  * unauthed, callable once the binding is satisfied. The SDK's {@link withResolvedAuth}
@@ -2874,9 +2882,9 @@ declare type ToolParametersWire = unknown;
2874
2882
  *
2875
2883
  * The host is trusted to supply honest values; a declared `kind` of `read` moves a call below
2876
2884
  * the protected-path hard-deny (which only fires for non-read kinds), so a tool that could
2877
- * touch protected config must NOT declare `read`. Kay's embedded-experience tools never touch
2885
+ * touch protected config must NOT declare `read`. Bonsai's embedded-experience tools never touch
2878
2886
  * `configDir`, so this is safe for them. `read` is also what every capability surface reports as
2879
- * "read-only" (Kay's Permissions page groups and defaults on it), so it is a claim about what the
2887
+ * "read-only" (Bonsai's Permissions page groups and defaults on it), so it is a claim about what the
2880
2888
  * tool DOES — never a way to buy silence. A tool that should raise no ask on its own account
2881
2889
  * declares {@link ToolPermissionHint.quiet} and keeps its honest `kind`.
2882
2890
  */
@@ -2917,7 +2925,7 @@ declare interface ToolPermissionHint {
2917
2925
  * because the same tool can read on one input and execute on another, which a static `kind`
2918
2926
  * cannot express.
2919
2927
  *
2920
- * Exemplar — Kay's `mcp` proxy tool, one tool spanning every server: `search`/`describe` derive
2928
+ * Exemplar — Bonsai's `mcp` proxy tool, one tool spanning every server: `search`/`describe` derive
2921
2929
  * `{ kind: "read" }` (metadata lookups), while `call` derives
2922
2930
  * `{ kind: "execute", ruleKey: "mcp:<server>::<tool>", scheme: "<server>" }`, so a
2923
2931
  * `{ scheme: "<server>" }` rule gates a whole server and a `{ ruleKey: "mcp:<server>::<tool>" }`
@@ -2958,7 +2966,7 @@ declare interface ToolPermissionHint {
2958
2966
  * really had — not that the result is always stricter than the target's. How much gate is left
2959
2967
  * on such a call is exactly how much the CARRIER carries: an `execute` carrier is stricter than
2960
2968
  * a `read` target and equal to a `mutate`/`destructive` one outside allow mode, while a
2961
- * {@link quiet} carrier (Kay's own `call_tool`) contributes no mode default at all, so the
2969
+ * {@link quiet} carrier (Bonsai's own `call_tool`) contributes no mode default at all, so the
2962
2970
  * fallback leaves nothing but the carrier's rules and the protected-path deny — and the carrier
2963
2971
  * names no path, so that deny has nothing to fire on. This is why a carrier must refuse a target
2964
2972
  * that is itself a carrier: no chain long or circular enough to reach the fallback can be built,
@@ -2982,7 +2990,7 @@ declare interface ToolPermissionHint {
2982
2990
  * whose only effect is invoking the target the gate is already classifying beside it: the
2983
2991
  * target's kind, rules, resources and the protected-path deny all still decide, so a proxied
2984
2992
  * call is gated exactly like the direct one — no more, and no ask the direct call would never
2985
- * have raised. Kay's `call_tool` declares `{ kind: "execute", quiet: true }` (owner ruling,
2993
+ * have raised. Bonsai's `call_tool` declares `{ kind: "execute", quiet: true }` (owner ruling,
2986
2994
  * 2026-08-18): honest about everything it can reach, silent on its own account.
2987
2995
  *
2988
2996
  * Quiet is not ungated, but it IS nearly all the gate a lone carrier has. On a call that
@@ -3172,13 +3180,19 @@ declare interface UriExtensionModule extends Omit<UriModule, "verbs"> {
3172
3180
  readonly permissionDefaults?: UriPermissionDefaults;
3173
3181
  /** Requires a resolved URI connection before any verb handler runs. */
3174
3182
  readonly requiresConnection?: boolean;
3175
- /** Pure route-aware permission facts; may only strengthen the verb default. */
3183
+ /** Pure route-aware permission facts; see {@link UriExtensionOperationPermissionPolicy}. */
3176
3184
  readonly permission?: UriExtensionOperationPermissionPolicy;
3177
3185
  /** False rejects generic write-tool `source` copies before source fetch. */
3178
3186
  readonly acceptsSourceCopy?: boolean;
3179
3187
  }
3180
3188
 
3181
3189
  declare interface UriExtensionOperationPermissionPolicy {
3190
+ /**
3191
+ * Classify one canonical route, purely. `write`/`edit`/`delete` may only be made stricter
3192
+ * than the verb default; `help`/`read`/`list`/`search` must stay `"read"` (a `ruleKey` is
3193
+ * allowed), because the kernel reruns a crash-interrupted read without asking again. Any
3194
+ * other answer, or a throw, fails the call closed.
3195
+ */
3182
3196
  classifyOperation(request: {
3183
3197
  readonly operation: UriOperation;
3184
3198
  readonly uri: string;
@@ -3406,7 +3420,15 @@ declare interface UriModule {
3406
3420
  normalize?(input: string, ctx: UriResolveContext): UriNormalizeResult | undefined;
3407
3421
  describe?(input: string, ctx: UriDescribeContext): UriResourceDescription | undefined;
3408
3422
  locate?(input: string, ctx: UriLocateContext): Promise<UriLocateResult>;
3423
+ /**
3424
+ * `read`, `help`, `list` and `search` observe; they never change the resource or anything
3425
+ * outside the host. Repeating one with the same input must be harmless: the kernel reruns a
3426
+ * call of these verbs that a crash cut off, with the same input, without asking the user
3427
+ * again. Idempotent bookkeeping (a cache fill, an index of what was read, a usage count) is
3428
+ * fine; a send, a mark-as-read or a create is not, and belongs on a mutating verb.
3429
+ */
3409
3430
  read(input: string, ctx: UriResolveContext): Promise<RawResource>;
3431
+ /** Observes only; see {@link read}. */
3410
3432
  help?(input: string, ctx: UriResolveContext): Promise<UriHelp>;
3411
3433
  write?(input: string, content: UriPayload, ctx: UriResolveContext): Promise<UriMutationResult | void>;
3412
3434
  /** Opt-in structured write with one or more host-resolved resources delivered beside the content. */
@@ -3429,7 +3451,9 @@ declare interface UriModule {
3429
3451
  */
3430
3452
  writeBytes?(input: string, bytes: Uint8Array, source: UriSourceDescriptor, ctx: UriResolveContext): Promise<UriMutationResult | void>;
3431
3453
  edit?(input: string, patch: UriPayload, ctx: UriResolveContext): Promise<UriMutationResult>;
3454
+ /** Observes only; see {@link read}. */
3432
3455
  list?(input: string, params: UriListParams, ctx: UriResolveContext): Promise<UriListResult>;
3456
+ /** Observes only; see {@link read}. */
3433
3457
  search?(input: string, params: UriSearchParams, ctx: UriResolveContext): Promise<UriSearchResult>;
3434
3458
  delete?(input: string, ctx: UriResolveContext): Promise<UriMutationResult>;
3435
3459
  toMarkdown?(input: UriMarkdownRenderInput, ctx: UriResolveContext): string | undefined;
@@ -3647,7 +3671,7 @@ declare interface UriResolveContext {
3647
3671
  * {@link UriResolveContext.sessionId} and just as un-influenceable by the caller — so a module
3648
3672
  * writing to a store it owns can record the actor without the agent being able to choose one.
3649
3673
  *
3650
- * Free text minted by the host's own runtime (Kay's form is `user`, `subagent`,
3674
+ * Free text minted by the host's own runtime (Bonsai's form is `user`, `subagent`,
3651
3675
  * `system/<surface>`, `followup/<surface>`) rather than a closed union: the surface half is the
3652
3676
  * host's vocabulary, and a second enumeration of it here would drift from the first.
3653
3677
  *
package/dist/jev.d.ts CHANGED
@@ -138,7 +138,7 @@ export declare interface JevScoreQuestion {
138
138
  * Those are host-side (`@kay/agent-runtime`'s `kay/jev/`).
139
139
  * ---
140
140
  *
141
- * The vocabulary is Kay's own (SDK 0.12.0). Before it, `use` received TypeSafe's `TypeSafeClient`
141
+ * The vocabulary is Bonsai's own (SDK 0.12.0). Before it, `use` received TypeSafe's `TypeSafeClient`
142
142
  * and plugins coded against a vendor's types. It follows pi's classifier contract, which the host
143
143
  * runs Jev through: a yes/no question is `bool` and answers a `probability`, every instruction and
144
144
  * criterion is text, and the state is a JSON object.