@yaklabs-ai/plugin-sdk 0.49.0 → 0.51.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.49.0"
16
+ "@bonsai/plugin-sdk": "npm:@yaklabs-ai/plugin-sdk@^0.51.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.49.0" },
65
+ "compatibility": { "sdk": "^0.51.0" },
66
66
  "targets": {
67
67
  "kay": {
68
68
  "agent": {
@@ -139,6 +139,7 @@ naming both versions, instead of loading it and finding no `activate`.
139
139
  | `@bonsai/plugin-sdk/kay-agent` | Tools, URI modules, search providers, auth — the per-session agent surface |
140
140
  | `@bonsai/plugin-sdk/kay-app` | App-lifetime surface: storage, endpoints, app-scoped URI modules |
141
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 |
142
143
  | `@bonsai/plugin-sdk/kay-agent/testing` | `invokeToolForTest`, `fauxAuthContext` — for your own `node --test` runs |
143
144
  | `@bonsai/plugin-sdk/disclosure` | The conformance audit Bonsai gates your plugin with — run it before you ship |
144
145
  | `@bonsai/plugin-sdk/time` | `Temporal` (Bonsai's own instance) and the time-zone helpers, from 0.13.6 |
@@ -150,7 +151,7 @@ naming both versions, instead of loading it and finding no `activate`.
150
151
  | `@bonsai/plugin-sdk/system-one` | The types and error class for `api.systemOne` / `app.systemOne`, from 0.13.8 |
151
152
  | `@bonsai/plugin-sdk/zod` | `z` (the host's in the daemon), on an entry with no other import, from 0.13.9 |
152
153
 
153
- A plugin that imports these subpaths declares the current supported SDK range (`^0.49.0`).
154
+ A plugin that imports these subpaths declares the current supported SDK range (`^0.51.0`).
154
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
155
156
  vendor's MCP server itself is a separate host decision: Bonsai hosts it once a person approves
156
157
  the plugin's `mcp.host-server` grant for that server's name and URL. A server that needs an OAuth
@@ -158,7 +159,7 @@ sign-in names one of the plugin's auth services in `authService`; that service m
158
159
  one `delegated` scheme, which Bonsai uses to sign the person in to the server. Bonsai declares that
159
160
  scheme at runtime; the plugin's code must not declare it again. From 0.16.2 a plugin's code can also
160
161
  call the server's tools through `api.vendoredMcp.port(<server>)`, typed by this subpath's
161
- `VendoredMcpPort` and `VendoredMcpOutcome` (declare `^0.49.0`).
162
+ `VendoredMcpPort` and `VendoredMcpOutcome` (declare `^0.51.0`).
162
163
 
163
164
  From 0.13.10 the manifest schema carries two facts Bonsai reads for its own plugins only; another
164
165
  plugin's are ignored, with a load diagnostic. An `external-cli` auth scheme's `cli` says how Bonsai
@@ -228,18 +229,19 @@ A newer floor always has a release: every change to the rule set publishes a
228
229
  version of this package as it lands, so "update and re-run" is never blocked on
229
230
  someone remembering to cut one. If the numbers differ, a newer version exists.
230
231
 
231
- ## Sessionless calls (0.49.0)
232
+ ## Sessionless calls (resources from 0.49.0, endpoints from 0.50.0)
232
233
 
233
- Both backend targets expose `uri.read/list/search/write/edit/delete`. Calls return native
234
- resources, bytes and revisions. Exact `uri.call` grants name the canonical scheme and verb;
235
- declaring a dependency grants no authority. Declared cross-plugin endpoint calls are deferred
236
- to the next slice of #15758.
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.
237
239
 
238
240
  `app.memory` and its `KayAppMemory*` types are removed. Use complete `memory://` addresses
239
241
  through `app.uri`, parse returned Markdown in the consuming plugin, and retain the read's
240
242
  revision (or `contentDigest` from `/uri`) for edits. The old `memory.read` and `memory.write`
241
- grants do not authorize the replacement scheme-and-verb calls. Earlier SDK contracts are
242
- refused; migrate and declare `^0.49.0`.
243
+ grants do not authorize the replacement scheme-and-verb calls. Contracts before 0.49.0 are
244
+ refused; migrate and declare `^0.51.0`. The current host also serves the 0.49.0 resource contract.
243
245
 
244
246
  ## What this package is, and is not, at runtime
245
247
 
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
3
  "package": "@yaklabs-ai/plugin-sdk",
4
- "version": "0.49.0",
4
+ "version": "0.51.0",
5
5
  "target": "npm",
6
6
  "firstPartyLicense": "MIT",
7
7
  "bundled": [
@@ -2453,8 +2453,13 @@ declare const KAY_PLUGIN_PROTOCOL_VERSION: "kay.plugin.v1";
2453
2453
  * types; callers use the resource surface instead. Previously admitted SDK contracts are no
2454
2454
  * longer served because they included app.memory on notebook hosts. No compatibility alias
2455
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.
2459
+ *
2460
+ * 0.51.0 adds flag-dependent title, icon and panel presence on rail entries.
2456
2461
  */
2457
- declare const KAY_PLUGIN_SDK_VERSION: "0.49.0";
2462
+ declare const KAY_PLUGIN_SDK_VERSION: "0.51.0";
2458
2463
 
2459
2464
  declare const KAY_PLUGIN_TARGET_NAMES: readonly ["kay.agent", "kay.app", "kay.ui"];
2460
2465
 
@@ -2467,46 +2472,9 @@ declare interface KayAgentCompiler {
2467
2472
  bundleBrowser(request: KayBrowserBundleRequest, sources: KayBrowserSources): Promise<KayBrowserBundle>;
2468
2473
  }
2469
2474
 
2470
- /**
2471
- * The plugin-facing `kay.agent` own-endpoint call: a plugin's agent part calls an endpoint its own
2472
- * `kay.app` part registered. SDK 0.17.3; a plugin that calls it declares `compatibility.sdk`
2473
- * `^0.19.0`.
2474
- *
2475
- * A plugin's two parts load as separate modules and share no memory, so this is how agent code
2476
- * reaches state its app part keeps (a worker, a database). The manifest says which endpoints the
2477
- * agent part may call: the `kay.app` target declares the endpoint with a `register` grant, and
2478
- * `permissions.byTarget["kay.agent"].endpoints` lists it with `invoke`. No other plugin's endpoint
2479
- * is nameable.
2480
- *
2481
- * An endpoint whose only `invoke` grant is the plugin's own `kay.agent` target is not reachable
2482
- * from Bonsai's surfaces (its pages and runtime clients), so an action the agent takes after the
2483
- * session's approval card cannot be taken around it.
2484
- */
2485
- /** Why an {@link KayAgentEndpoints.invoke} call produced no value. */
2486
- declare type KayAgentEndpointFailureReason =
2487
- /** The manifest grants this plugin's `kay.agent` target no `invoke` on this endpoint. */
2488
- "not-declared"
2489
- /** The plugin's `kay.app` part is not running, or registered no handler for it. */
2490
- | "unavailable"
2491
- /** The handler did not answer within the host's fixed deadline (10 seconds). It may still finish. */
2492
- | "timed-out"
2493
- /** The caller's `signal` aborted. The handler may still finish. */
2494
- | "cancelled"
2495
- /** The handler threw; `message` is its error's message. */
2496
- | "failed"
2497
- /** The request or the handler's response does not match the endpoint's declared schema. */
2498
- | "invalid";
2499
-
2500
- declare type KayAgentEndpointOutcome = {
2501
- readonly ok: true;
2502
- readonly value: unknown;
2503
- } | {
2504
- readonly ok: false;
2505
- readonly reason: KayAgentEndpointFailureReason;
2506
- readonly message: string;
2507
- };
2475
+ declare type KayAgentEndpointOutcome = PluginEndpointOutcome;
2508
2476
 
2509
- declare interface KayAgentEndpoints {
2477
+ declare interface KayAgentEndpoints extends PluginEndpointCaller {
2510
2478
  /**
2511
2479
  * Call `endpoint`, the local id this plugin's manifest declares on its `kay.app` target. Never
2512
2480
  * rejects: every failure is an outcome. Nothing is queued: when the app part is not running the
@@ -2772,10 +2740,9 @@ declare interface KayAgentPluginApi {
2772
2740
  */
2773
2741
  readonly vendoredMcp: KayAgentVendoredMcp;
2774
2742
  /**
2775
- * Calls the endpoints this plugin's own `kay.app` part registered and the manifest grants this
2776
- * target `invoke` on, by local id. Never another plugin's. Every failure is an outcome, never a
2777
- * rejection; the host fixes a 10-second deadline. Always present; a host with no app part
2778
- * answers each call `unavailable`. See {@link KayAgentEndpoints} (SDK 0.17.3).
2743
+ * `invoke` calls this plugin's own declared app endpoint by local id. `invokePlugin` names a
2744
+ * provider plugin explicitly and checks this target's exact `endpoints.invoke` claim. Every
2745
+ * failure is an outcome; unavailable providers are never queued.
2779
2746
  */
2780
2747
  readonly endpoints: KayAgentEndpoints;
2781
2748
  /**
@@ -4417,6 +4384,28 @@ declare interface PluginDelegatedServiceEntry {
4417
4384
  /** One rule id from {@link PLUGIN_DISCLOSURE_RULES}. */
4418
4385
  export declare type PluginDisclosureRule = (typeof PLUGIN_DISCLOSURE_RULES)[number];
4419
4386
 
4387
+ /** Sessionless JSON calls to another plugin's declared, publicly reachable endpoint. */
4388
+ declare interface PluginEndpointCaller {
4389
+ /**
4390
+ * Never rejects. Both payload and result are validated against the provider's declared schemas.
4391
+ * Nothing is queued or retried. Cancellation and timeouts leave the operation's effect unknown.
4392
+ */
4393
+ invokePlugin(providerPluginId: string, endpointLocalId: string, payload: unknown, options?: {
4394
+ readonly signal?: AbortSignal;
4395
+ }): Promise<PluginEndpointOutcome>;
4396
+ }
4397
+
4398
+ declare type PluginEndpointFailureReason = "not-declared" | "unavailable" | "timed-out" | "cancelled" | "failed" | "invalid" | "denied";
4399
+
4400
+ declare type PluginEndpointOutcome = {
4401
+ readonly ok: true;
4402
+ readonly value: unknown;
4403
+ } | {
4404
+ readonly ok: false;
4405
+ readonly reason: PluginEndpointFailureReason;
4406
+ readonly message: string;
4407
+ };
4408
+
4420
4409
  declare const PluginEventPublishInput: z.ZodObject<{
4421
4410
  uri: z.ZodString;
4422
4411
  related: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>>;
@@ -737,10 +737,18 @@ function createUnavailableUriCaller(message) {
737
737
  };
738
738
  }
739
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
+
740
747
  // packages/plugin-sdk/dist/kay-agent/endpoints.js
741
748
  function createUnavailableEndpoints(message) {
742
749
  return {
743
- invoke: async () => ({ ok: false, reason: "unavailable", message })
750
+ invoke: async () => ({ ok: false, reason: "unavailable", message }),
751
+ ...createUnavailablePluginEndpointCaller(message)
744
752
  };
745
753
  }
746
754
 
@@ -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
+ };
@@ -2507,8 +2507,13 @@ declare const KAY_PLUGIN_PROTOCOL_VERSION: "kay.plugin.v1";
2507
2507
  * types; callers use the resource surface instead. Previously admitted SDK contracts are no
2508
2508
  * longer served because they included app.memory on notebook hosts. No compatibility alias
2509
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.
2513
+ *
2514
+ * 0.51.0 adds flag-dependent title, icon and panel presence on rail entries.
2510
2515
  */
2511
- declare const KAY_PLUGIN_SDK_VERSION: "0.49.0";
2516
+ declare const KAY_PLUGIN_SDK_VERSION: "0.51.0";
2512
2517
 
2513
2518
  declare const KAY_PLUGIN_TARGET_NAMES: readonly ["kay.agent", "kay.app", "kay.ui"];
2514
2519
 
@@ -2518,46 +2523,9 @@ declare interface KayAgentCompiler {
2518
2523
  bundleBrowser(request: KayBrowserBundleRequest, sources: KayBrowserSources): Promise<KayBrowserBundle>;
2519
2524
  }
2520
2525
 
2521
- /**
2522
- * The plugin-facing `kay.agent` own-endpoint call: a plugin's agent part calls an endpoint its own
2523
- * `kay.app` part registered. SDK 0.17.3; a plugin that calls it declares `compatibility.sdk`
2524
- * `^0.19.0`.
2525
- *
2526
- * A plugin's two parts load as separate modules and share no memory, so this is how agent code
2527
- * reaches state its app part keeps (a worker, a database). The manifest says which endpoints the
2528
- * agent part may call: the `kay.app` target declares the endpoint with a `register` grant, and
2529
- * `permissions.byTarget["kay.agent"].endpoints` lists it with `invoke`. No other plugin's endpoint
2530
- * is nameable.
2531
- *
2532
- * An endpoint whose only `invoke` grant is the plugin's own `kay.agent` target is not reachable
2533
- * from Bonsai's surfaces (its pages and runtime clients), so an action the agent takes after the
2534
- * session's approval card cannot be taken around it.
2535
- */
2536
- /** Why an {@link KayAgentEndpoints.invoke} call produced no value. */
2537
- declare type KayAgentEndpointFailureReason =
2538
- /** The manifest grants this plugin's `kay.agent` target no `invoke` on this endpoint. */
2539
- "not-declared"
2540
- /** The plugin's `kay.app` part is not running, or registered no handler for it. */
2541
- | "unavailable"
2542
- /** The handler did not answer within the host's fixed deadline (10 seconds). It may still finish. */
2543
- | "timed-out"
2544
- /** The caller's `signal` aborted. The handler may still finish. */
2545
- | "cancelled"
2546
- /** The handler threw; `message` is its error's message. */
2547
- | "failed"
2548
- /** The request or the handler's response does not match the endpoint's declared schema. */
2549
- | "invalid";
2550
-
2551
- declare type KayAgentEndpointOutcome = {
2552
- readonly ok: true;
2553
- readonly value: unknown;
2554
- } | {
2555
- readonly ok: false;
2556
- readonly reason: KayAgentEndpointFailureReason;
2557
- readonly message: string;
2558
- };
2526
+ declare type KayAgentEndpointOutcome = PluginEndpointOutcome;
2559
2527
 
2560
- declare interface KayAgentEndpoints {
2528
+ declare interface KayAgentEndpoints extends PluginEndpointCaller {
2561
2529
  /**
2562
2530
  * Call `endpoint`, the local id this plugin's manifest declares on its `kay.app` target. Never
2563
2531
  * rejects: every failure is an outcome. Nothing is queued: when the app part is not running the
@@ -2823,10 +2791,9 @@ declare interface KayAgentPluginApi {
2823
2791
  */
2824
2792
  readonly vendoredMcp: KayAgentVendoredMcp;
2825
2793
  /**
2826
- * Calls the endpoints this plugin's own `kay.app` part registered and the manifest grants this
2827
- * target `invoke` on, by local id. Never another plugin's. Every failure is an outcome, never a
2828
- * rejection; the host fixes a 10-second deadline. Always present; a host with no app part
2829
- * answers each call `unavailable`. See {@link KayAgentEndpoints} (SDK 0.17.3).
2794
+ * `invoke` calls this plugin's own declared app endpoint by local id. `invokePlugin` names a
2795
+ * provider plugin explicitly and checks this target's exact `endpoints.invoke` claim. Every
2796
+ * failure is an outcome; unavailable providers are never queued.
2830
2797
  */
2831
2798
  readonly endpoints: KayAgentEndpoints;
2832
2799
  /**
@@ -4432,6 +4399,28 @@ declare interface PluginDelegatedServiceEntry {
4432
4399
  readonly scheme: PluginDelegatedScheme;
4433
4400
  }
4434
4401
 
4402
+ /** Sessionless JSON calls to another plugin's declared, publicly reachable endpoint. */
4403
+ declare interface PluginEndpointCaller {
4404
+ /**
4405
+ * Never rejects. Both payload and result are validated against the provider's declared schemas.
4406
+ * Nothing is queued or retried. Cancellation and timeouts leave the operation's effect unknown.
4407
+ */
4408
+ invokePlugin(providerPluginId: string, endpointLocalId: string, payload: unknown, options?: {
4409
+ readonly signal?: AbortSignal;
4410
+ }): Promise<PluginEndpointOutcome>;
4411
+ }
4412
+
4413
+ declare type PluginEndpointFailureReason = "not-declared" | "unavailable" | "timed-out" | "cancelled" | "failed" | "invalid" | "denied";
4414
+
4415
+ declare type PluginEndpointOutcome = {
4416
+ readonly ok: true;
4417
+ readonly value: unknown;
4418
+ } | {
4419
+ readonly ok: false;
4420
+ readonly reason: PluginEndpointFailureReason;
4421
+ readonly message: string;
4422
+ };
4423
+
4435
4424
  declare const PluginEventPublishInput: z.ZodObject<{
4436
4425
  uri: z.ZodString;
4437
4426
  related: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>>;
@@ -358,15 +358,8 @@ function fauxKayAgentCapabilities() {
358
358
  })
359
359
  })
360
360
  },
361
- // Answers `unavailable` naming itself, keeping the real call's promise never to reject. A test
362
- // that exercises its plugin's own endpoints passes its own handle.
363
- endpoints: {
364
- invoke: async (endpoint) => ({
365
- ok: false,
366
- reason: "unavailable",
367
- message: `endpoints.invoke("${endpoint}") is not wired in this test double`
368
- })
369
- }
361
+ // Uncomposed own and foreign calls keep their outcome contract instead of rejecting.
362
+ endpoints: { invokePlugin: NOT_WIRED, invoke: NOT_WIRED }
370
363
  };
371
364
  }
372
365
  function createTestClock(startMs, options = {}) {
@@ -813,6 +813,8 @@ export declare function createUnavailableCompiler(message: string): KayAgentComp
813
813
  */
814
814
  export declare function createUnavailableEndpoints(message: string): KayAgentEndpoints;
815
815
 
816
+ export declare function createUnavailablePluginEndpointCaller(message: string): PluginEndpointCaller;
817
+
816
818
  export declare function createUnavailableUriCaller(message: string): PluginUriCaller;
817
819
 
818
820
  /** What the module holds at mutation time: a provider revision, the current content, or both. */
@@ -2784,8 +2786,13 @@ declare const KAY_PLUGIN_PROTOCOL_VERSION: "kay.plugin.v1";
2784
2786
  * types; callers use the resource surface instead. Previously admitted SDK contracts are no
2785
2787
  * longer served because they included app.memory on notebook hosts. No compatibility alias
2786
2788
  * restores it; callers migrate and declare ^0.49.0.
2789
+ *
2790
+ * 0.50.0 adds explicit cross-plugin endpoint calls on both backend targets. The URI-only 0.49.0
2791
+ * contract remains served.
2792
+ *
2793
+ * 0.51.0 adds flag-dependent title, icon and panel presence on rail entries.
2787
2794
  */
2788
- declare const KAY_PLUGIN_SDK_VERSION: "0.49.0";
2795
+ declare const KAY_PLUGIN_SDK_VERSION: "0.51.0";
2789
2796
 
2790
2797
  declare const KAY_PLUGIN_TARGET_NAMES: readonly ["kay.agent", "kay.app", "kay.ui"];
2791
2798
 
@@ -2819,46 +2826,11 @@ export declare interface KayAgentCompiler {
2819
2826
  bundleBrowser(request: KayBrowserBundleRequest, sources: KayBrowserSources): Promise<KayBrowserBundle>;
2820
2827
  }
2821
2828
 
2822
- /**
2823
- * The plugin-facing `kay.agent` own-endpoint call: a plugin's agent part calls an endpoint its own
2824
- * `kay.app` part registered. SDK 0.17.3; a plugin that calls it declares `compatibility.sdk`
2825
- * `^0.19.0`.
2826
- *
2827
- * A plugin's two parts load as separate modules and share no memory, so this is how agent code
2828
- * reaches state its app part keeps (a worker, a database). The manifest says which endpoints the
2829
- * agent part may call: the `kay.app` target declares the endpoint with a `register` grant, and
2830
- * `permissions.byTarget["kay.agent"].endpoints` lists it with `invoke`. No other plugin's endpoint
2831
- * is nameable.
2832
- *
2833
- * An endpoint whose only `invoke` grant is the plugin's own `kay.agent` target is not reachable
2834
- * from Bonsai's surfaces (its pages and runtime clients), so an action the agent takes after the
2835
- * session's approval card cannot be taken around it.
2836
- */
2837
- /** Why an {@link KayAgentEndpoints.invoke} call produced no value. */
2838
- export declare type KayAgentEndpointFailureReason =
2839
- /** The manifest grants this plugin's `kay.agent` target no `invoke` on this endpoint. */
2840
- "not-declared"
2841
- /** The plugin's `kay.app` part is not running, or registered no handler for it. */
2842
- | "unavailable"
2843
- /** The handler did not answer within the host's fixed deadline (10 seconds). It may still finish. */
2844
- | "timed-out"
2845
- /** The caller's `signal` aborted. The handler may still finish. */
2846
- | "cancelled"
2847
- /** The handler threw; `message` is its error's message. */
2848
- | "failed"
2849
- /** The request or the handler's response does not match the endpoint's declared schema. */
2850
- | "invalid";
2851
-
2852
- export declare type KayAgentEndpointOutcome = {
2853
- readonly ok: true;
2854
- readonly value: unknown;
2855
- } | {
2856
- readonly ok: false;
2857
- readonly reason: KayAgentEndpointFailureReason;
2858
- readonly message: string;
2859
- };
2829
+ export declare type KayAgentEndpointFailureReason = PluginEndpointFailureReason;
2860
2830
 
2861
- export declare interface KayAgentEndpoints {
2831
+ export declare type KayAgentEndpointOutcome = PluginEndpointOutcome;
2832
+
2833
+ export declare interface KayAgentEndpoints extends PluginEndpointCaller {
2862
2834
  /**
2863
2835
  * Call `endpoint`, the local id this plugin's manifest declares on its `kay.app` target. Never
2864
2836
  * rejects: every failure is an outcome. Nothing is queued: when the app part is not running the
@@ -3132,10 +3104,9 @@ export declare interface KayAgentPluginApi {
3132
3104
  */
3133
3105
  readonly vendoredMcp: KayAgentVendoredMcp;
3134
3106
  /**
3135
- * Calls the endpoints this plugin's own `kay.app` part registered and the manifest grants this
3136
- * target `invoke` on, by local id. Never another plugin's. Every failure is an outcome, never a
3137
- * rejection; the host fixes a 10-second deadline. Always present; a host with no app part
3138
- * answers each call `unavailable`. See {@link KayAgentEndpoints} (SDK 0.17.3).
3107
+ * `invoke` calls this plugin's own declared app endpoint by local id. `invokePlugin` names a
3108
+ * provider plugin explicitly and checks this target's exact `endpoints.invoke` claim. Every
3109
+ * failure is an outcome; unavailable providers are never queued.
3139
3110
  */
3140
3111
  readonly endpoints: KayAgentEndpoints;
3141
3112
  /**
@@ -5128,6 +5099,16 @@ declare const PluginCapabilityRefusalV1: z.ZodObject<{
5128
5099
  delete: "delete";
5129
5100
  }>;
5130
5101
  }, z.core.$strict>;
5102
+ }, z.core.$strict>, z.ZodObject<{
5103
+ target: z.ZodEnum<{
5104
+ "kay.agent": "kay.agent";
5105
+ "kay.app": "kay.app";
5106
+ }>;
5107
+ slug: z.ZodLiteral<"endpoints.invoke">;
5108
+ envelope: z.ZodObject<{
5109
+ pluginId: z.ZodString;
5110
+ endpointId: z.ZodString;
5111
+ }, z.core.$strict>;
5131
5112
  }, z.core.$strict>, z.ZodObject<{
5132
5113
  target: z.ZodLiteral<"kay.app">;
5133
5114
  slug: z.ZodLiteral<"skills.read">;
@@ -5456,6 +5437,28 @@ export declare interface PluginDelegatedServiceEntry {
5456
5437
  readonly scheme: PluginDelegatedScheme;
5457
5438
  }
5458
5439
 
5440
+ /** Sessionless JSON calls to another plugin's declared, publicly reachable endpoint. */
5441
+ export declare interface PluginEndpointCaller {
5442
+ /**
5443
+ * Never rejects. Both payload and result are validated against the provider's declared schemas.
5444
+ * Nothing is queued or retried. Cancellation and timeouts leave the operation's effect unknown.
5445
+ */
5446
+ invokePlugin(providerPluginId: string, endpointLocalId: string, payload: unknown, options?: {
5447
+ readonly signal?: AbortSignal;
5448
+ }): Promise<PluginEndpointOutcome>;
5449
+ }
5450
+
5451
+ export declare type PluginEndpointFailureReason = "not-declared" | "unavailable" | "timed-out" | "cancelled" | "failed" | "invalid" | "denied";
5452
+
5453
+ export declare type PluginEndpointOutcome = {
5454
+ readonly ok: true;
5455
+ readonly value: unknown;
5456
+ } | {
5457
+ readonly ok: false;
5458
+ readonly reason: PluginEndpointFailureReason;
5459
+ readonly message: string;
5460
+ };
5461
+
5459
5462
  export declare const PluginEventEnvelope: z.ZodObject<{
5460
5463
  id: z.ZodString;
5461
5464
  localId: z.ZodString;
package/dist/kay-agent.js CHANGED
@@ -997,6 +997,13 @@ function createUnavailableUriCaller(message) {
997
997
  };
998
998
  }
999
999
 
1000
+ // packages/plugin-sdk/dist/endpoints.js
1001
+ function createUnavailablePluginEndpointCaller(message) {
1002
+ return {
1003
+ invokePlugin: async () => ({ ok: false, reason: "unavailable", message })
1004
+ };
1005
+ }
1006
+
1000
1007
  // packages/herd-uri-extensions/dist/limits.js
1001
1008
  var MAX_BYTES = 50 * 1024 * 1024;
1002
1009
  var MAX_OUTPUT_CHARS = 5e5;
@@ -1492,7 +1499,8 @@ function createUnavailableCompiler(message) {
1492
1499
  // packages/plugin-sdk/dist/kay-agent/endpoints.js
1493
1500
  function createUnavailableEndpoints(message) {
1494
1501
  return {
1495
- invoke: async () => ({ ok: false, reason: "unavailable", message })
1502
+ invoke: async () => ({ ok: false, reason: "unavailable", message }),
1503
+ ...createUnavailablePluginEndpointCaller(message)
1496
1504
  };
1497
1505
  }
1498
1506
 
@@ -1731,6 +1739,7 @@ export {
1731
1739
  createOsascriptRunner,
1732
1740
  createUnavailableCompiler,
1733
1741
  createUnavailableEndpoints,
1742
+ createUnavailablePluginEndpointCaller,
1734
1743
  createUnavailableUriCaller,
1735
1744
  declareProducedResources,
1736
1745
  defineAuthedTool,
package/dist/kay-app.d.ts CHANGED
@@ -952,6 +952,8 @@ export declare function createFallbackOnlySignals(): KayAppSignals;
952
952
  */
953
953
  export declare function createKayPluginLog(write: (line: KayPluginLogLine) => void, bound?: KayPluginLogAttributes): KayPluginLog;
954
954
 
955
+ export declare function createUnavailablePluginEndpointCaller(message: string): PluginEndpointCaller;
956
+
955
957
  /**
956
958
  * A `KayAppSealing` that answers `unavailable` to every call: what a host with no vault binds, so
957
959
  * `app.sealing` stays present on every host.
@@ -2900,8 +2902,13 @@ declare const KAY_PLUGIN_PROTOCOL_VERSION: "kay.plugin.v1";
2900
2902
  * types; callers use the resource surface instead. Previously admitted SDK contracts are no
2901
2903
  * longer served because they included app.memory on notebook hosts. No compatibility alias
2902
2904
  * restores it; callers migrate and declare ^0.49.0.
2905
+ *
2906
+ * 0.50.0 adds explicit cross-plugin endpoint calls on both backend targets. The URI-only 0.49.0
2907
+ * contract remains served.
2908
+ *
2909
+ * 0.51.0 adds flag-dependent title, icon and panel presence on rail entries.
2903
2910
  */
2904
- declare const KAY_PLUGIN_SDK_VERSION: "0.49.0";
2911
+ declare const KAY_PLUGIN_SDK_VERSION: "0.51.0";
2905
2912
 
2906
2913
  declare const KAY_PLUGIN_TARGET_NAMES: readonly ["kay.agent", "kay.app", "kay.ui"];
2907
2914
 
@@ -4572,12 +4579,14 @@ export declare interface KayAppDynamicContextSearchOptions {
4572
4579
  export declare interface KayAppEndpointContext {
4573
4580
  readonly credentials: readonly KayAppResolvedCredential[];
4574
4581
  readonly signal: AbortSignal;
4582
+ /** Host-stamped origin of a sessionless cross-plugin call; absent for other callers. */
4583
+ readonly callerPluginId?: string;
4575
4584
  /** Record only a scheme from this call's credentials after its provider operation succeeds. */
4576
4585
  reportWorked(schemeId: string): void;
4577
4586
  }
4578
4587
 
4579
4588
  /** The app-wide endpoint bus; payloads and returned values must be JSON. */
4580
- export declare interface KayAppEndpoints {
4589
+ export declare interface KayAppEndpoints extends PluginEndpointCaller {
4581
4590
  register(name: string, handler: (payload: unknown, context: KayAppEndpointContext) => unknown | Promise<unknown>): void;
4582
4591
  }
4583
4592
 
@@ -5497,9 +5506,9 @@ export declare interface KayAppPluginApi {
5497
5506
  */
5498
5507
  readonly sealing: KayAppSealing;
5499
5508
  /**
5500
- * The app-wide endpoint bus (register handlers a consuming surface invokes). An endpoint whose
5501
- * only `invoke` grant is this plugin's own `kay.agent` target is reachable only from that target
5502
- * (`api.endpoints.invoke`), never from a surface.
5509
+ * Register this plugin's app handlers or call another plugin's declared endpoint with
5510
+ * `invokePlugin`. Foreign calls require this target's exact `endpoints.invoke` claim and
5511
+ * cannot reach an endpoint restricted to its owner's agent target.
5503
5512
  */
5504
5513
  readonly endpoints: KayAppEndpoints;
5505
5514
  /** Publish one event declared by this plugin's `kay.app` manifest target. */
@@ -9974,6 +9983,28 @@ declare type PluginCardSubmitResult<T> = {
9974
9983
  readonly ok: false;
9975
9984
  }>;
9976
9985
 
9986
+ /** Sessionless JSON calls to another plugin's declared, publicly reachable endpoint. */
9987
+ export declare interface PluginEndpointCaller {
9988
+ /**
9989
+ * Never rejects. Both payload and result are validated against the provider's declared schemas.
9990
+ * Nothing is queued or retried. Cancellation and timeouts leave the operation's effect unknown.
9991
+ */
9992
+ invokePlugin(providerPluginId: string, endpointLocalId: string, payload: unknown, options?: {
9993
+ readonly signal?: AbortSignal;
9994
+ }): Promise<PluginEndpointOutcome>;
9995
+ }
9996
+
9997
+ export declare type PluginEndpointFailureReason = "not-declared" | "unavailable" | "timed-out" | "cancelled" | "failed" | "invalid" | "denied";
9998
+
9999
+ export declare type PluginEndpointOutcome = {
10000
+ readonly ok: true;
10001
+ readonly value: unknown;
10002
+ } | {
10003
+ readonly ok: false;
10004
+ readonly reason: PluginEndpointFailureReason;
10005
+ readonly message: string;
10006
+ };
10007
+
9977
10008
  export declare const PluginEventEnvelope: z.ZodObject<{
9978
10009
  id: z.ZodString;
9979
10010
  localId: z.ZodString;
package/dist/kay-app.js CHANGED
@@ -308,6 +308,13 @@ function createUnavailableUriCaller(message) {
308
308
  };
309
309
  }
310
310
 
311
+ // packages/plugin-sdk/dist/endpoints.js
312
+ function createUnavailablePluginEndpointCaller(message) {
313
+ return {
314
+ invokePlugin: async () => ({ ok: false, reason: "unavailable", message })
315
+ };
316
+ }
317
+
311
318
  // packages/plugin-protocol/dist/plugin-signal-limits.js
312
319
  var PLUGIN_EVENT_REFUSED_ERROR_NAME = "PluginEventRefusedError";
313
320
  var PLUGIN_SIGNAL_KINDS = [
@@ -1106,6 +1113,7 @@ export {
1106
1113
  createConsoleKayPluginLog,
1107
1114
  createFallbackOnlySignals,
1108
1115
  createKayPluginLog,
1116
+ createUnavailablePluginEndpointCaller,
1109
1117
  createUnavailableSealing,
1110
1118
  createUnavailableSkills,
1111
1119
  createUnavailableTools,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yaklabs-ai/plugin-sdk",
3
- "version": "0.49.0",
3
+ "version": "0.51.0",
4
4
  "description": "The Kay plugin SDK — types and helpers for authoring a Kay directory plugin.",
5
5
  "author": "YakLabs",
6
6
  "type": "module",
@@ -21,6 +21,10 @@
21
21
  "types": "./dist/uri.d.ts",
22
22
  "default": "./dist/uri.js"
23
23
  },
24
+ "./endpoints": {
25
+ "types": "./dist/endpoints.d.ts",
26
+ "default": "./dist/endpoints.js"
27
+ },
24
28
  "./kay-app/session-summary": {
25
29
  "types": "./dist/kay-app-session-summary.d.ts",
26
30
  "default": "./dist/kay-app-session-summary.js"