@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 +37 -33
- package/THIRD-PARTY-INVENTORY.json +1 -1
- package/dist/disclosure.d.ts +47 -23
- package/dist/jev.d.ts +1 -1
- package/dist/kay-agent-testing.d.ts +45 -21
- package/dist/kay-agent.d.ts +50 -26
- package/dist/kay-app.d.ts +155 -58
- package/dist/kay-app.js +22 -1
- package/dist/signals.d.ts +175 -1
- package/dist/signals.js +141 -2
- package/package.json +1 -1
- package/skills/directory-plugin-authoring/SKILL.md +18 -17
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# @yaklabs-ai/plugin-sdk
|
|
2
2
|
|
|
3
|
-
The SDK for authoring a **
|
|
4
|
-
repository and add to
|
|
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.
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
|
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.
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
167
|
-
not caught that way. Keep the SDK version in step with the
|
|
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
|
|
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
|
|
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
|
|
180
|
-
root is already consented, so there is no repository to stage and no Trust
|
|
181
|
-
|
|
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 **
|
|
185
|
-
|
|
186
|
-
|
|
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
|
|
191
|
-
|
|
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
|
|
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
|
|
211
|
+
SDK remains external and is supplied by the running Bonsai app.
|
package/dist/disclosure.d.ts
CHANGED
|
@@ -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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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:
|
|
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
|
|
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
|
|
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.
|
|
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
|
|
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`.
|
|
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" (
|
|
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 —
|
|
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 (
|
|
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.
|
|
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;
|
|
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 (
|
|
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
|
|
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.
|