@yaklabs-ai/plugin-sdk 0.48.1 → 0.50.0

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
@@ -13,7 +13,7 @@ it under the name your plugin code actually imports:
13
13
  ```json
14
14
  {
15
15
  "dependencies": {
16
- "@bonsai/plugin-sdk": "npm:@yaklabs-ai/plugin-sdk@^0.48.1"
16
+ "@bonsai/plugin-sdk": "npm:@yaklabs-ai/plugin-sdk@^0.50.0"
17
17
  }
18
18
  }
19
19
  ```
@@ -62,7 +62,7 @@ Every tool the entrypoint registers is declared in the manifest too:
62
62
  "description": "Greets people by name.",
63
63
  "version": "0.1.0",
64
64
  "namespace": "widgets",
65
- "compatibility": { "sdk": "^0.48.1" },
65
+ "compatibility": { "sdk": "^0.50.0" },
66
66
  "targets": {
67
67
  "kay": {
68
68
  "agent": {
@@ -134,22 +134,24 @@ naming both versions, instead of loading it and finding no `activate`.
134
134
 
135
135
  ## Entrypoints
136
136
 
137
- | Import | What it gives you |
138
- | --------------------------------------- | ------------------------------------------------------------------------------- |
139
- | `@bonsai/plugin-sdk/kay-agent` | Tools, URI modules, search providers, auth — the per-session agent surface |
140
- | `@bonsai/plugin-sdk/kay-app` | App-lifetime surface: storage, endpoints, app-scoped URI modules |
141
- | `@bonsai/plugin-sdk/kay-agent/testing` | `invokeToolForTest`, `fauxAuthContext` — for your own `node --test` runs |
142
- | `@bonsai/plugin-sdk/disclosure` | The conformance audit Bonsai gates your plugin with — run it before you ship |
143
- | `@bonsai/plugin-sdk/time` | `Temporal` (Bonsai's own instance) and the time-zone helpers, from 0.13.6 |
144
- | `@bonsai/plugin-sdk/transcript` | The active-branch walk; the turn walk and run records from 0.13.6 |
145
- | `@bonsai/plugin-sdk/transcript-review` | The review fold: a session's spans, tool-call attempts and records, from 0.13.7 |
146
- | `@bonsai/plugin-sdk/agent-conversation` | How a session's agent-to-agent traffic groups into conversations, from 0.13.7 |
147
- | `@bonsai/plugin-sdk/app-data` | The app-data size caps, on an entry with no other import, from 0.13.7 |
148
- | `@bonsai/plugin-sdk/vendored-mcp` | The kit for a plugin built on a vendor's hosted MCP server, from 0.13.7 |
149
- | `@bonsai/plugin-sdk/system-one` | The types and error class for `api.systemOne` / `app.systemOne`, from 0.13.8 |
150
- | `@bonsai/plugin-sdk/zod` | `z` (the host's in the daemon), on an entry with no other import, from 0.13.9 |
151
-
152
- A plugin that imports these subpaths declares the current supported SDK range (`^0.19.0`).
137
+ | Import | What it gives you |
138
+ | --------------------------------------- | ---------------------------------------------------------------------------------------- |
139
+ | `@bonsai/plugin-sdk/kay-agent` | Tools, URI modules, search providers, auth — the per-session agent surface |
140
+ | `@bonsai/plugin-sdk/kay-app` | App-lifetime surface: storage, endpoints, app-scoped URI modules |
141
+ | `@bonsai/plugin-sdk/uri` | Sessionless resource caller types, revision digest and unavailable fallback, from 0.49.0 |
142
+ | `@bonsai/plugin-sdk/endpoints` | Sessionless cross-plugin endpoint caller and outcome types, from 0.50.0 |
143
+ | `@bonsai/plugin-sdk/kay-agent/testing` | `invokeToolForTest`, `fauxAuthContext` — for your own `node --test` runs |
144
+ | `@bonsai/plugin-sdk/disclosure` | The conformance audit Bonsai gates your plugin with — run it before you ship |
145
+ | `@bonsai/plugin-sdk/time` | `Temporal` (Bonsai's own instance) and the time-zone helpers, from 0.13.6 |
146
+ | `@bonsai/plugin-sdk/transcript` | The active-branch walk; the turn walk and run records from 0.13.6 |
147
+ | `@bonsai/plugin-sdk/transcript-review` | The review fold: a session's spans, tool-call attempts and records, from 0.13.7 |
148
+ | `@bonsai/plugin-sdk/agent-conversation` | How a session's agent-to-agent traffic groups into conversations, from 0.13.7 |
149
+ | `@bonsai/plugin-sdk/app-data` | The app-data size caps, on an entry with no other import, from 0.13.7 |
150
+ | `@bonsai/plugin-sdk/vendored-mcp` | The kit for a plugin built on a vendor's hosted MCP server, from 0.13.7 |
151
+ | `@bonsai/plugin-sdk/system-one` | The types and error class for `api.systemOne` / `app.systemOne`, from 0.13.8 |
152
+ | `@bonsai/plugin-sdk/zod` | `z` (the host's in the daemon), on an entry with no other import, from 0.13.9 |
153
+
154
+ A plugin that imports these subpaths declares the current supported SDK range (`^0.50.0`).
153
155
  The rows record when each subpath appeared, not retained runtime compatibility. `vendored-mcp` builds the plugin's URI module (its link cards and help); hosting the
154
156
  vendor's MCP server itself is a separate host decision: Bonsai hosts it once a person approves
155
157
  the plugin's `mcp.host-server` grant for that server's name and URL. A server that needs an OAuth
@@ -157,7 +159,7 @@ sign-in names one of the plugin's auth services in `authService`; that service m
157
159
  one `delegated` scheme, which Bonsai uses to sign the person in to the server. Bonsai declares that
158
160
  scheme at runtime; the plugin's code must not declare it again. From 0.16.2 a plugin's code can also
159
161
  call the server's tools through `api.vendoredMcp.port(<server>)`, typed by this subpath's
160
- `VendoredMcpPort` and `VendoredMcpOutcome` (declare `^0.19.0`).
162
+ `VendoredMcpPort` and `VendoredMcpOutcome` (declare `^0.50.0`).
161
163
 
162
164
  From 0.13.10 the manifest schema carries two facts Bonsai reads for its own plugins only; another
163
165
  plugin's are ignored, with a load diagnostic. An `external-cli` auth scheme's `cli` says how Bonsai
@@ -227,6 +229,20 @@ A newer floor always has a release: every change to the rule set publishes a
227
229
  version of this package as it lands, so "update and re-run" is never blocked on
228
230
  someone remembering to cut one. If the numbers differ, a newer version exists.
229
231
 
232
+ ## Sessionless calls (resources from 0.49.0, endpoints from 0.50.0)
233
+
234
+ Both backend targets expose `uri.read/list/search/write/edit/delete` and
235
+ `endpoints.invokePlugin(providerPluginId, endpointLocalId, payload, { signal })`.
236
+ URI calls return native resources, bytes and revisions. Endpoint calls return an unknown JSON
237
+ value on success or a structured failure, including `denied` when the exact grant is absent.
238
+ Provider schemas remain authoritative; declaring a dependency grants no authority.
239
+
240
+ `app.memory` and its `KayAppMemory*` types are removed. Use complete `memory://` addresses
241
+ through `app.uri`, parse returned Markdown in the consuming plugin, and retain the read's
242
+ revision (or `contentDigest` from `/uri`) for edits. The old `memory.read` and `memory.write`
243
+ grants do not authorize the replacement scheme-and-verb calls. Contracts before 0.49.0 are
244
+ refused; migrate and declare `^0.50.0`. The current host also serves the 0.49.0 resource contract.
245
+
230
246
  ## What this package is, and is not, at runtime
231
247
 
232
248
  Installing this SDK gives you **types, editor completion, and a runtime you can
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
3
  "package": "@yaklabs-ai/plugin-sdk",
4
- "version": "0.48.1",
4
+ "version": "0.50.0",
5
5
  "target": "npm",
6
6
  "firstPartyLicense": "MIT",
7
7
  "bundled": [
@@ -2448,8 +2448,16 @@ declare const KAY_PLUGIN_PROTOCOL_VERSION: "kay.plugin.v1";
2448
2448
  * 0.48.0 adds the models.complete UI capability.
2449
2449
  *
2450
2450
  * 0.48.1 adds app-tool metadata, conditional tool permissions and screen-action declarations.
2451
+ *
2452
+ * 0.49.0 adds sessionless URI calls on both backend targets. It removes app.memory and its note
2453
+ * types; callers use the resource surface instead. Previously admitted SDK contracts are no
2454
+ * longer served because they included app.memory on notebook hosts. No compatibility alias
2455
+ * restores it; callers migrate and declare ^0.49.0.
2456
+ *
2457
+ * 0.50.0 adds explicit cross-plugin endpoint calls on both backend targets. The URI-only 0.49.0
2458
+ * contract remains served.
2451
2459
  */
2452
- declare const KAY_PLUGIN_SDK_VERSION: "0.48.1";
2460
+ declare const KAY_PLUGIN_SDK_VERSION: "0.50.0";
2453
2461
 
2454
2462
  declare const KAY_PLUGIN_TARGET_NAMES: readonly ["kay.agent", "kay.app", "kay.ui"];
2455
2463
 
@@ -2462,46 +2470,9 @@ declare interface KayAgentCompiler {
2462
2470
  bundleBrowser(request: KayBrowserBundleRequest, sources: KayBrowserSources): Promise<KayBrowserBundle>;
2463
2471
  }
2464
2472
 
2465
- /**
2466
- * The plugin-facing `kay.agent` own-endpoint call: a plugin's agent part calls an endpoint its own
2467
- * `kay.app` part registered. SDK 0.17.3; a plugin that calls it declares `compatibility.sdk`
2468
- * `^0.19.0`.
2469
- *
2470
- * A plugin's two parts load as separate modules and share no memory, so this is how agent code
2471
- * reaches state its app part keeps (a worker, a database). The manifest says which endpoints the
2472
- * agent part may call: the `kay.app` target declares the endpoint with a `register` grant, and
2473
- * `permissions.byTarget["kay.agent"].endpoints` lists it with `invoke`. No other plugin's endpoint
2474
- * is nameable.
2475
- *
2476
- * An endpoint whose only `invoke` grant is the plugin's own `kay.agent` target is not reachable
2477
- * from Bonsai's surfaces (its pages and runtime clients), so an action the agent takes after the
2478
- * session's approval card cannot be taken around it.
2479
- */
2480
- /** Why an {@link KayAgentEndpoints.invoke} call produced no value. */
2481
- declare type KayAgentEndpointFailureReason =
2482
- /** The manifest grants this plugin's `kay.agent` target no `invoke` on this endpoint. */
2483
- "not-declared"
2484
- /** The plugin's `kay.app` part is not running, or registered no handler for it. */
2485
- | "unavailable"
2486
- /** The handler did not answer within the host's fixed deadline (10 seconds). It may still finish. */
2487
- | "timed-out"
2488
- /** The caller's `signal` aborted. The handler may still finish. */
2489
- | "cancelled"
2490
- /** The handler threw; `message` is its error's message. */
2491
- | "failed"
2492
- /** The request or the handler's response does not match the endpoint's declared schema. */
2493
- | "invalid";
2494
-
2495
- declare type KayAgentEndpointOutcome = {
2496
- readonly ok: true;
2497
- readonly value: unknown;
2498
- } | {
2499
- readonly ok: false;
2500
- readonly reason: KayAgentEndpointFailureReason;
2501
- readonly message: string;
2502
- };
2473
+ declare type KayAgentEndpointOutcome = PluginEndpointOutcome;
2503
2474
 
2504
- declare interface KayAgentEndpoints {
2475
+ declare interface KayAgentEndpoints extends PluginEndpointCaller {
2505
2476
  /**
2506
2477
  * Call `endpoint`, the local id this plugin's manifest declares on its `kay.app` target. Never
2507
2478
  * rejects: every failure is an outcome. Nothing is queued: when the app part is not running the
@@ -2674,7 +2645,7 @@ declare interface KayAgentNetwork {
2674
2645
  * here; the plugin never touches an `ExtensionApi`, `child_process`, credentials, or Electron.
2675
2646
  */
2676
2647
  declare interface KayAgentPluginApi {
2677
- readonly uri: {
2648
+ readonly uri: PluginUriCaller & {
2678
2649
  /** Register a whole URI module (a scheme handler that owns its address space, e.g. `drive://`). */
2679
2650
  registerModule(module: UriExtensionModule): void;
2680
2651
  };
@@ -2767,10 +2738,9 @@ declare interface KayAgentPluginApi {
2767
2738
  */
2768
2739
  readonly vendoredMcp: KayAgentVendoredMcp;
2769
2740
  /**
2770
- * Calls the endpoints this plugin's own `kay.app` part registered and the manifest grants this
2771
- * target `invoke` on, by local id. Never another plugin's. Every failure is an outcome, never a
2772
- * rejection; the host fixes a 10-second deadline. Always present; a host with no app part
2773
- * answers each call `unavailable`. See {@link KayAgentEndpoints} (SDK 0.17.3).
2741
+ * `invoke` calls this plugin's own declared app endpoint by local id. `invokePlugin` names a
2742
+ * provider plugin explicitly and checks this target's exact `endpoints.invoke` claim. Every
2743
+ * failure is an outcome; unavailable providers are never queued.
2774
2744
  */
2775
2745
  readonly endpoints: KayAgentEndpoints;
2776
2746
  /**
@@ -4412,6 +4382,28 @@ declare interface PluginDelegatedServiceEntry {
4412
4382
  /** One rule id from {@link PLUGIN_DISCLOSURE_RULES}. */
4413
4383
  export declare type PluginDisclosureRule = (typeof PLUGIN_DISCLOSURE_RULES)[number];
4414
4384
 
4385
+ /** Sessionless JSON calls to another plugin's declared, publicly reachable endpoint. */
4386
+ declare interface PluginEndpointCaller {
4387
+ /**
4388
+ * Never rejects. Both payload and result are validated against the provider's declared schemas.
4389
+ * Nothing is queued or retried. Cancellation and timeouts leave the operation's effect unknown.
4390
+ */
4391
+ invokePlugin(providerPluginId: string, endpointLocalId: string, payload: unknown, options?: {
4392
+ readonly signal?: AbortSignal;
4393
+ }): Promise<PluginEndpointOutcome>;
4394
+ }
4395
+
4396
+ declare type PluginEndpointFailureReason = "not-declared" | "unavailable" | "timed-out" | "cancelled" | "failed" | "invalid" | "denied";
4397
+
4398
+ declare type PluginEndpointOutcome = {
4399
+ readonly ok: true;
4400
+ readonly value: unknown;
4401
+ } | {
4402
+ readonly ok: false;
4403
+ readonly reason: PluginEndpointFailureReason;
4404
+ readonly message: string;
4405
+ };
4406
+
4415
4407
  declare const PluginEventPublishInput: z.ZodObject<{
4416
4408
  uri: z.ZodString;
4417
4409
  related: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>>;
@@ -4499,6 +4491,38 @@ declare const PluginToolName: z.ZodString;
4499
4491
 
4500
4492
  declare type PluginToolName = z.infer<typeof PluginToolName>;
4501
4493
 
4494
+ /**
4495
+ * Sessionless resource calls. Each call checks the calling target's exact scheme and verb grant.
4496
+ * Results retain provider bytes, metadata and revisions; provider failures retain their URI tags.
4497
+ * A cancellation or lost response does not prove a mutation was not applied.
4498
+ */
4499
+ declare interface PluginUriCaller {
4500
+ read(input: string, options?: PluginUriReadOptions): Promise<RawResource>;
4501
+ list(input: string, params?: UriListParams, options?: PluginUriCallOptions): Promise<UriListResult>;
4502
+ search(input: string, params: UriSearchParams, options?: PluginUriCallOptions): Promise<UriSearchResult>;
4503
+ write(input: string, content?: UriPayload | Uint8Array, options?: PluginUriWriteOptions): Promise<UriMutationResult | void>;
4504
+ edit(input: string, payload: UriPayload, options?: PluginUriMutationOptions): Promise<UriMutationResult>;
4505
+ delete(input: string, options?: PluginUriMutationOptions): Promise<UriMutationResult>;
4506
+ }
4507
+
4508
+ declare interface PluginUriCallOptions {
4509
+ readonly cwd?: string;
4510
+ readonly signal?: AbortSignal;
4511
+ }
4512
+
4513
+ declare interface PluginUriMutationOptions extends PluginUriCallOptions {
4514
+ readonly expectedRevision?: string;
4515
+ }
4516
+
4517
+ declare interface PluginUriReadOptions extends PluginUriCallOptions {
4518
+ readonly knownRevision?: string;
4519
+ }
4520
+
4521
+ declare interface PluginUriWriteOptions extends PluginUriMutationOptions {
4522
+ readonly sources?: readonly UriWriteSource[];
4523
+ readonly writeSource?: UriSourceDescriptor;
4524
+ }
4525
+
4502
4526
  declare const Properties: (input: string) => [unknown, string] | [];
4503
4527
 
4504
4528
  declare function PropertiesMapping(input: [unknown, unknown, unknown]): unknown;
@@ -10063,6 +10087,8 @@ declare interface UriResolveContext {
10063
10087
  * resolve a URI outside any verb call.
10064
10088
  */
10065
10089
  readonly sessionId?: string;
10090
+ /** Host-stamped calling plugin; absent for session dispatch and resolver matching. */
10091
+ readonly callerPluginId?: string;
10066
10092
  /**
10067
10093
  * WHO the dispatching session acts as, stamped by the host at the same dispatch site as
10068
10094
  * {@link UriResolveContext.sessionId} and just as un-influenceable by the caller - so a module
@@ -722,10 +722,33 @@ async function auditSkillCodegenPairFile(skill, declaration, packageDir) {
722
722
  return violations;
723
723
  }
724
724
 
725
+ // packages/plugin-sdk/dist/uri.js
726
+ function createUnavailableUriCaller(message) {
727
+ const unavailable = async () => {
728
+ throw new Error(message);
729
+ };
730
+ return {
731
+ read: unavailable,
732
+ list: unavailable,
733
+ search: unavailable,
734
+ write: unavailable,
735
+ edit: unavailable,
736
+ delete: unavailable
737
+ };
738
+ }
739
+
740
+ // packages/plugin-sdk/dist/endpoints.js
741
+ function createUnavailablePluginEndpointCaller(message) {
742
+ return {
743
+ invokePlugin: async () => ({ ok: false, reason: "unavailable", message })
744
+ };
745
+ }
746
+
725
747
  // packages/plugin-sdk/dist/kay-agent/endpoints.js
726
748
  function createUnavailableEndpoints(message) {
727
749
  return {
728
- invoke: async () => ({ ok: false, reason: "unavailable", message })
750
+ invoke: async () => ({ ok: false, reason: "unavailable", message }),
751
+ ...createUnavailablePluginEndpointCaller(message)
729
752
  };
730
753
  }
731
754
 
@@ -917,6 +940,7 @@ function collectUriModulesFromKayAgentActivate(activate) {
917
940
  const modules = [];
918
941
  const fakeApi = {
919
942
  uri: {
943
+ ...createUnavailableUriCaller("URI calls are unavailable while probing a plugin"),
920
944
  registerModule: (module) => {
921
945
  modules.push(module);
922
946
  }
@@ -0,0 +1,25 @@
1
+ export declare function createUnavailablePluginEndpointCaller(message: string): PluginEndpointCaller;
2
+
3
+ /** Sessionless JSON calls to another plugin's declared, publicly reachable endpoint. */
4
+ export declare interface PluginEndpointCaller {
5
+ /**
6
+ * Never rejects. Both payload and result are validated against the provider's declared schemas.
7
+ * Nothing is queued or retried. Cancellation and timeouts leave the operation's effect unknown.
8
+ */
9
+ invokePlugin(providerPluginId: string, endpointLocalId: string, payload: unknown, options?: {
10
+ readonly signal?: AbortSignal;
11
+ }): Promise<PluginEndpointOutcome>;
12
+ }
13
+
14
+ export declare type PluginEndpointFailureReason = "not-declared" | "unavailable" | "timed-out" | "cancelled" | "failed" | "invalid" | "denied";
15
+
16
+ export declare type PluginEndpointOutcome = {
17
+ readonly ok: true;
18
+ readonly value: unknown;
19
+ } | {
20
+ readonly ok: false;
21
+ readonly reason: PluginEndpointFailureReason;
22
+ readonly message: string;
23
+ };
24
+
25
+ export { }
@@ -0,0 +1,9 @@
1
+ // packages/plugin-sdk/dist/endpoints.js
2
+ function createUnavailablePluginEndpointCaller(message) {
3
+ return {
4
+ invokePlugin: async () => ({ ok: false, reason: "unavailable", message })
5
+ };
6
+ }
7
+ export {
8
+ createUnavailablePluginEndpointCaller
9
+ };
@@ -1196,7 +1196,7 @@ declare function FactorMapping(input: [unknown, unknown, unknown, unknown, unkno
1196
1196
  export declare function fauxAuthContext(overrides?: Partial<ExtensionAuthContext>): ExtensionAuthContext;
1197
1197
 
1198
1198
  /** The capability handles a `KayAgentPluginApi` always carries - authority is decided per call. */
1199
- export declare type FauxKayAgentCapabilities = Pick<KayAgentPluginApi, "network" | "webSession" | "process" | "whiteboard" | "interaction" | "interceptToolCall" | "implementTool" | "systemOne" | "events" | "featureFlags" | "time" | "log" | "userFiles" | "familyFolder" | "vendoredMcp" | "endpoints" | "compiler">;
1199
+ export declare type FauxKayAgentCapabilities = Pick<KayAgentPluginApi, "uri" | "network" | "webSession" | "process" | "whiteboard" | "interaction" | "interceptToolCall" | "implementTool" | "systemOne" | "events" | "featureFlags" | "time" | "log" | "userFiles" | "familyFolder" | "vendoredMcp" | "endpoints" | "compiler">;
1200
1200
 
1201
1201
  export declare function fauxKayAgentCapabilities(): FauxKayAgentCapabilities;
1202
1202
 
@@ -2502,8 +2502,16 @@ declare const KAY_PLUGIN_PROTOCOL_VERSION: "kay.plugin.v1";
2502
2502
  * 0.48.0 adds the models.complete UI capability.
2503
2503
  *
2504
2504
  * 0.48.1 adds app-tool metadata, conditional tool permissions and screen-action declarations.
2505
+ *
2506
+ * 0.49.0 adds sessionless URI calls on both backend targets. It removes app.memory and its note
2507
+ * types; callers use the resource surface instead. Previously admitted SDK contracts are no
2508
+ * longer served because they included app.memory on notebook hosts. No compatibility alias
2509
+ * restores it; callers migrate and declare ^0.49.0.
2510
+ *
2511
+ * 0.50.0 adds explicit cross-plugin endpoint calls on both backend targets. The URI-only 0.49.0
2512
+ * contract remains served.
2505
2513
  */
2506
- declare const KAY_PLUGIN_SDK_VERSION: "0.48.1";
2514
+ declare const KAY_PLUGIN_SDK_VERSION: "0.50.0";
2507
2515
 
2508
2516
  declare const KAY_PLUGIN_TARGET_NAMES: readonly ["kay.agent", "kay.app", "kay.ui"];
2509
2517
 
@@ -2513,46 +2521,9 @@ declare interface KayAgentCompiler {
2513
2521
  bundleBrowser(request: KayBrowserBundleRequest, sources: KayBrowserSources): Promise<KayBrowserBundle>;
2514
2522
  }
2515
2523
 
2516
- /**
2517
- * The plugin-facing `kay.agent` own-endpoint call: a plugin's agent part calls an endpoint its own
2518
- * `kay.app` part registered. SDK 0.17.3; a plugin that calls it declares `compatibility.sdk`
2519
- * `^0.19.0`.
2520
- *
2521
- * A plugin's two parts load as separate modules and share no memory, so this is how agent code
2522
- * reaches state its app part keeps (a worker, a database). The manifest says which endpoints the
2523
- * agent part may call: the `kay.app` target declares the endpoint with a `register` grant, and
2524
- * `permissions.byTarget["kay.agent"].endpoints` lists it with `invoke`. No other plugin's endpoint
2525
- * is nameable.
2526
- *
2527
- * An endpoint whose only `invoke` grant is the plugin's own `kay.agent` target is not reachable
2528
- * from Bonsai's surfaces (its pages and runtime clients), so an action the agent takes after the
2529
- * session's approval card cannot be taken around it.
2530
- */
2531
- /** Why an {@link KayAgentEndpoints.invoke} call produced no value. */
2532
- declare type KayAgentEndpointFailureReason =
2533
- /** The manifest grants this plugin's `kay.agent` target no `invoke` on this endpoint. */
2534
- "not-declared"
2535
- /** The plugin's `kay.app` part is not running, or registered no handler for it. */
2536
- | "unavailable"
2537
- /** The handler did not answer within the host's fixed deadline (10 seconds). It may still finish. */
2538
- | "timed-out"
2539
- /** The caller's `signal` aborted. The handler may still finish. */
2540
- | "cancelled"
2541
- /** The handler threw; `message` is its error's message. */
2542
- | "failed"
2543
- /** The request or the handler's response does not match the endpoint's declared schema. */
2544
- | "invalid";
2545
-
2546
- declare type KayAgentEndpointOutcome = {
2547
- readonly ok: true;
2548
- readonly value: unknown;
2549
- } | {
2550
- readonly ok: false;
2551
- readonly reason: KayAgentEndpointFailureReason;
2552
- readonly message: string;
2553
- };
2524
+ declare type KayAgentEndpointOutcome = PluginEndpointOutcome;
2554
2525
 
2555
- declare interface KayAgentEndpoints {
2526
+ declare interface KayAgentEndpoints extends PluginEndpointCaller {
2556
2527
  /**
2557
2528
  * Call `endpoint`, the local id this plugin's manifest declares on its `kay.app` target. Never
2558
2529
  * rejects: every failure is an outcome. Nothing is queued: when the app part is not running the
@@ -2725,7 +2696,7 @@ declare interface KayAgentNetwork {
2725
2696
  * here; the plugin never touches an `ExtensionApi`, `child_process`, credentials, or Electron.
2726
2697
  */
2727
2698
  declare interface KayAgentPluginApi {
2728
- readonly uri: {
2699
+ readonly uri: PluginUriCaller & {
2729
2700
  /** Register a whole URI module (a scheme handler that owns its address space, e.g. `drive://`). */
2730
2701
  registerModule(module: UriExtensionModule): void;
2731
2702
  };
@@ -2818,10 +2789,9 @@ declare interface KayAgentPluginApi {
2818
2789
  */
2819
2790
  readonly vendoredMcp: KayAgentVendoredMcp;
2820
2791
  /**
2821
- * Calls the endpoints this plugin's own `kay.app` part registered and the manifest grants this
2822
- * target `invoke` on, by local id. Never another plugin's. Every failure is an outcome, never a
2823
- * rejection; the host fixes a 10-second deadline. Always present; a host with no app part
2824
- * answers each call `unavailable`. See {@link KayAgentEndpoints} (SDK 0.17.3).
2792
+ * `invoke` calls this plugin's own declared app endpoint by local id. `invokePlugin` names a
2793
+ * provider plugin explicitly and checks this target's exact `endpoints.invoke` claim. Every
2794
+ * failure is an outcome; unavailable providers are never queued.
2825
2795
  */
2826
2796
  readonly endpoints: KayAgentEndpoints;
2827
2797
  /**
@@ -4427,6 +4397,28 @@ declare interface PluginDelegatedServiceEntry {
4427
4397
  readonly scheme: PluginDelegatedScheme;
4428
4398
  }
4429
4399
 
4400
+ /** Sessionless JSON calls to another plugin's declared, publicly reachable endpoint. */
4401
+ declare interface PluginEndpointCaller {
4402
+ /**
4403
+ * Never rejects. Both payload and result are validated against the provider's declared schemas.
4404
+ * Nothing is queued or retried. Cancellation and timeouts leave the operation's effect unknown.
4405
+ */
4406
+ invokePlugin(providerPluginId: string, endpointLocalId: string, payload: unknown, options?: {
4407
+ readonly signal?: AbortSignal;
4408
+ }): Promise<PluginEndpointOutcome>;
4409
+ }
4410
+
4411
+ declare type PluginEndpointFailureReason = "not-declared" | "unavailable" | "timed-out" | "cancelled" | "failed" | "invalid" | "denied";
4412
+
4413
+ declare type PluginEndpointOutcome = {
4414
+ readonly ok: true;
4415
+ readonly value: unknown;
4416
+ } | {
4417
+ readonly ok: false;
4418
+ readonly reason: PluginEndpointFailureReason;
4419
+ readonly message: string;
4420
+ };
4421
+
4430
4422
  declare const PluginEventPublishInput: z.ZodObject<{
4431
4423
  uri: z.ZodString;
4432
4424
  related: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>>;
@@ -4495,6 +4487,38 @@ declare const PluginToolName: z.ZodString;
4495
4487
 
4496
4488
  declare type PluginToolName = z.infer<typeof PluginToolName>;
4497
4489
 
4490
+ /**
4491
+ * Sessionless resource calls. Each call checks the calling target's exact scheme and verb grant.
4492
+ * Results retain provider bytes, metadata and revisions; provider failures retain their URI tags.
4493
+ * A cancellation or lost response does not prove a mutation was not applied.
4494
+ */
4495
+ declare interface PluginUriCaller {
4496
+ read(input: string, options?: PluginUriReadOptions): Promise<RawResource>;
4497
+ list(input: string, params?: UriListParams, options?: PluginUriCallOptions): Promise<UriListResult>;
4498
+ search(input: string, params: UriSearchParams, options?: PluginUriCallOptions): Promise<UriSearchResult>;
4499
+ write(input: string, content?: UriPayload | Uint8Array, options?: PluginUriWriteOptions): Promise<UriMutationResult | void>;
4500
+ edit(input: string, payload: UriPayload, options?: PluginUriMutationOptions): Promise<UriMutationResult>;
4501
+ delete(input: string, options?: PluginUriMutationOptions): Promise<UriMutationResult>;
4502
+ }
4503
+
4504
+ declare interface PluginUriCallOptions {
4505
+ readonly cwd?: string;
4506
+ readonly signal?: AbortSignal;
4507
+ }
4508
+
4509
+ declare interface PluginUriMutationOptions extends PluginUriCallOptions {
4510
+ readonly expectedRevision?: string;
4511
+ }
4512
+
4513
+ declare interface PluginUriReadOptions extends PluginUriCallOptions {
4514
+ readonly knownRevision?: string;
4515
+ }
4516
+
4517
+ declare interface PluginUriWriteOptions extends PluginUriMutationOptions {
4518
+ readonly sources?: readonly UriWriteSource[];
4519
+ readonly writeSource?: UriSourceDescriptor;
4520
+ }
4521
+
4498
4522
  /**
4499
4523
  * What a run did to a URI. The words match the automation run wire's artifact actions. When one
4500
4524
  * run both creates and updates a URI, the reader reports `created`.
@@ -11326,6 +11350,8 @@ declare interface UriResolveContext {
11326
11350
  * resolve a URI outside any verb call.
11327
11351
  */
11328
11352
  readonly sessionId?: string;
11353
+ /** Host-stamped calling plugin; absent for session dispatch and resolver matching. */
11354
+ readonly callerPluginId?: string;
11329
11355
  /**
11330
11356
  * WHO the dispatching session acts as, stamped by the host at the same dispatch site as
11331
11357
  * {@link UriResolveContext.sessionId} and just as un-influenceable by the caller - so a module
@@ -277,6 +277,16 @@ var USER_FILE_METHODS = [
277
277
  ];
278
278
  function fauxKayAgentCapabilities() {
279
279
  return {
280
+ uri: {
281
+ read: unwired("uri.read"),
282
+ list: unwired("uri.list"),
283
+ search: unwired("uri.search"),
284
+ write: unwired("uri.write"),
285
+ edit: unwired("uri.edit"),
286
+ delete: unwired("uri.delete"),
287
+ registerModule: () => {
288
+ }
289
+ },
280
290
  network: { fetch: unwired("network.fetch") },
281
291
  webSession: {
282
292
  request: unwired("webSession.request"),
@@ -348,15 +358,8 @@ function fauxKayAgentCapabilities() {
348
358
  })
349
359
  })
350
360
  },
351
- // Answers `unavailable` naming itself, keeping the real call's promise never to reject. A test
352
- // that exercises its plugin's own endpoints passes its own handle.
353
- endpoints: {
354
- invoke: async (endpoint) => ({
355
- ok: false,
356
- reason: "unavailable",
357
- message: `endpoints.invoke("${endpoint}") is not wired in this test double`
358
- })
359
- }
361
+ // Uncomposed own and foreign calls keep their outcome contract instead of rejecting.
362
+ endpoints: { invokePlugin: NOT_WIRED, invoke: NOT_WIRED }
360
363
  };
361
364
  }
362
365
  function createTestClock(startMs, options = {}) {