@yaklabs-ai/plugin-sdk 0.40.0 → 0.42.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.40.0"
16
+ "@bonsai/plugin-sdk": "npm:@yaklabs-ai/plugin-sdk@^0.42.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.40.0" },
65
+ "compatibility": { "sdk": "^0.42.0" },
66
66
  "targets": {
67
67
  "kay": {
68
68
  "agent": {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
3
  "package": "@yaklabs-ai/plugin-sdk",
4
- "version": "0.40.0",
4
+ "version": "0.42.0",
5
5
  "target": "npm",
6
6
  "firstPartyLicense": "MIT",
7
7
  "bundled": [
@@ -2414,8 +2414,15 @@ declare const KAY_PLUGIN_PROTOCOL_VERSION: "kay.plugin.v1";
2414
2414
  * feed may now declare a `store`. It removes the `cost.read`, `skills.read`, `memory.read` and
2415
2415
  * `self-improvement.read` host capabilities, so a manifest still listing one no longer parses and
2416
2416
  * lists the feed instead. A plugin that lists feeds declares ^0.40.0.
2417
+ *
2418
+ * 0.41.0 adds app.mcp.callTool for background calls to a plugin's own manifest-declared MCP
2419
+ * servers, using Bonsai's managed connection without a session or working directory (#16172).
2420
+ *
2421
+ * 0.42.0 hands background work the shared ResolvedCredential in auth.credential. Workflow
2422
+ * accounts carry auth resolution outcomes, and Poller callbacks receive only the credential.
2423
+ * Older SDK ranges are refused because their background success shape is no longer served.
2417
2424
  */
2418
- declare const KAY_PLUGIN_SDK_VERSION: "0.40.0";
2425
+ declare const KAY_PLUGIN_SDK_VERSION: "0.42.0";
2419
2426
 
2420
2427
  declare const KAY_PLUGIN_TARGET_NAMES: readonly ["kay.agent", "kay.app", "kay.ui"];
2421
2428
 
@@ -2468,8 +2468,15 @@ declare const KAY_PLUGIN_PROTOCOL_VERSION: "kay.plugin.v1";
2468
2468
  * feed may now declare a `store`. It removes the `cost.read`, `skills.read`, `memory.read` and
2469
2469
  * `self-improvement.read` host capabilities, so a manifest still listing one no longer parses and
2470
2470
  * lists the feed instead. A plugin that lists feeds declares ^0.40.0.
2471
+ *
2472
+ * 0.41.0 adds app.mcp.callTool for background calls to a plugin's own manifest-declared MCP
2473
+ * servers, using Bonsai's managed connection without a session or working directory (#16172).
2474
+ *
2475
+ * 0.42.0 hands background work the shared ResolvedCredential in auth.credential. Workflow
2476
+ * accounts carry auth resolution outcomes, and Poller callbacks receive only the credential.
2477
+ * Older SDK ranges are refused because their background success shape is no longer served.
2471
2478
  */
2472
- declare const KAY_PLUGIN_SDK_VERSION: "0.40.0";
2479
+ declare const KAY_PLUGIN_SDK_VERSION: "0.42.0";
2473
2480
 
2474
2481
  declare const KAY_PLUGIN_TARGET_NAMES: readonly ["kay.agent", "kay.app", "kay.ui"];
2475
2482
 
@@ -5793,6 +5800,7 @@ declare const ResolvedPluginContractV1: z.ZodObject<{
5793
5800
  "artifacts.read": "artifacts.read";
5794
5801
  "artifacts.preview": "artifacts.preview";
5795
5802
  "markdown.document-view": "markdown.document-view";
5803
+ "references.open": "references.open";
5796
5804
  "billing.read": "billing.read";
5797
5805
  "automations.read": "automations.read";
5798
5806
  "automations.run": "automations.run";
@@ -2743,8 +2743,15 @@ declare const KAY_PLUGIN_PROTOCOL_VERSION: "kay.plugin.v1";
2743
2743
  * feed may now declare a `store`. It removes the `cost.read`, `skills.read`, `memory.read` and
2744
2744
  * `self-improvement.read` host capabilities, so a manifest still listing one no longer parses and
2745
2745
  * lists the feed instead. A plugin that lists feeds declares ^0.40.0.
2746
+ *
2747
+ * 0.41.0 adds app.mcp.callTool for background calls to a plugin's own manifest-declared MCP
2748
+ * servers, using Bonsai's managed connection without a session or working directory (#16172).
2749
+ *
2750
+ * 0.42.0 hands background work the shared ResolvedCredential in auth.credential. Workflow
2751
+ * accounts carry auth resolution outcomes, and Poller callbacks receive only the credential.
2752
+ * Older SDK ranges are refused because their background success shape is no longer served.
2746
2753
  */
2747
- declare const KAY_PLUGIN_SDK_VERSION: "0.40.0";
2754
+ declare const KAY_PLUGIN_SDK_VERSION: "0.42.0";
2748
2755
 
2749
2756
  declare const KAY_PLUGIN_TARGET_NAMES: readonly ["kay.agent", "kay.app", "kay.ui"];
2750
2757
 
package/dist/kay-app.d.ts CHANGED
@@ -2719,8 +2719,15 @@ declare const KAY_PLUGIN_PROTOCOL_VERSION: "kay.plugin.v1";
2719
2719
  * feed may now declare a `store`. It removes the `cost.read`, `skills.read`, `memory.read` and
2720
2720
  * `self-improvement.read` host capabilities, so a manifest still listing one no longer parses and
2721
2721
  * lists the feed instead. A plugin that lists feeds declares ^0.40.0.
2722
+ *
2723
+ * 0.41.0 adds app.mcp.callTool for background calls to a plugin's own manifest-declared MCP
2724
+ * servers, using Bonsai's managed connection without a session or working directory (#16172).
2725
+ *
2726
+ * 0.42.0 hands background work the shared ResolvedCredential in auth.credential. Workflow
2727
+ * accounts carry auth resolution outcomes, and Poller callbacks receive only the credential.
2728
+ * Older SDK ranges are refused because their background success shape is no longer served.
2722
2729
  */
2723
- declare const KAY_PLUGIN_SDK_VERSION: "0.40.0";
2730
+ declare const KAY_PLUGIN_SDK_VERSION: "0.42.0";
2724
2731
 
2725
2732
  declare const KAY_PLUGIN_TARGET_NAMES: readonly ["kay.agent", "kay.app", "kay.ui"];
2726
2733
 
@@ -3929,7 +3936,7 @@ export declare interface KayAppAutomationUriChangeCondition {
3929
3936
 
3930
3937
  /** Exact-account credential resolution for a plugin's durable background jobs. */
3931
3938
  export declare interface KayAppBackgroundAuth {
3932
- resolveCredential(request: KayAppBackgroundCredentialRequest): Promise<KayAppBackgroundCredentialResult>;
3939
+ resolveCredential(request: KayAppBackgroundCredentialRequest): Promise<KayAppCredentialResolution>;
3933
3940
  }
3934
3941
 
3935
3942
  /** A credential request for durable background work bound to one known account. */
@@ -3945,21 +3952,6 @@ export declare interface KayAppBackgroundCredentialRequest {
3945
3952
  readonly jobId: string;
3946
3953
  }
3947
3954
 
3948
- /** The non-secret outcome of a durable background credential lookup. */
3949
- export declare type KayAppBackgroundCredentialResult = {
3950
- readonly status: "resolved";
3951
- readonly accessToken: string;
3952
- readonly accountId: string;
3953
- readonly scopes: readonly string[];
3954
- } | {
3955
- readonly status: "missing";
3956
- readonly reason: string;
3957
- } | {
3958
- readonly status: "requires-auth";
3959
- readonly reason: string;
3960
- readonly requiredScopes?: readonly string[];
3961
- };
3962
-
3963
3955
  /**
3964
3956
  * The `kay.app` system-prompt contract (`app.systemPrompt`): text a plugin adds to every chat's
3965
3957
  * system prompt, rendered by the daemon from a few facts about the chat and reused across chats.
@@ -4111,6 +4103,19 @@ export declare class KayAppCredentialRejectedError extends Error {
4111
4103
  readonly name = "KayAppCredentialRejectedError";
4112
4104
  }
4113
4105
 
4106
+ /** A credential for this call, or an account failure with no secret material. Never persist it. */
4107
+ export declare type KayAppCredentialResolution = {
4108
+ readonly status: "resolved";
4109
+ readonly credential: ResolvedCredential;
4110
+ } | {
4111
+ readonly status: "missing";
4112
+ readonly reason: string;
4113
+ } | {
4114
+ readonly status: "requires-auth";
4115
+ readonly reason: string;
4116
+ readonly requiredScopes?: readonly string[];
4117
+ };
4118
+
4114
4119
  export declare interface KayAppData {
4115
4120
  /**
4116
4121
  * Register the live definition behind one declared source. At most one registration per source
@@ -4356,18 +4361,17 @@ export declare interface KayAppDynamicContextSearchOptions {
4356
4361
  } | undefined;
4357
4362
  }
4358
4363
 
4359
- /**
4360
- * The app-wide endpoint bus. A plugin registers named handlers a consuming surface can invoke; the
4361
- * host routes invocations (e.g. Bonsai Desktop forwards the renderer's frame-gated call to the daemon,
4362
- * where the endpoint is single-homed). The corpus is NEVER reachable here - only what the plugin
4363
- * explicitly exposes. Both `payload` and the handler's return ride strict JSON on the wire.
4364
- */
4364
+ /** Per-invocation authority prepared from the endpoint's manifest declaration. */
4365
+ export declare interface KayAppEndpointContext {
4366
+ readonly credentials: readonly KayAppResolvedCredential[];
4367
+ readonly signal: AbortSignal;
4368
+ /** Record only a scheme from this call's credentials after its provider operation succeeds. */
4369
+ reportWorked(schemeId: string): void;
4370
+ }
4371
+
4372
+ /** The app-wide endpoint bus; payloads and returned values must be JSON. */
4365
4373
  export declare interface KayAppEndpoints {
4366
- /**
4367
- * Register a handler under `name`. Names are app-wide (open bus); a duplicate name is rejected by
4368
- * the host registry.
4369
- */
4370
- register(name: string, handler: (payload: unknown) => unknown | Promise<unknown>): void;
4374
+ register(name: string, handler: (payload: unknown, context: KayAppEndpointContext) => unknown | Promise<unknown>): void;
4371
4375
  }
4372
4376
 
4373
4377
  /**
@@ -4615,6 +4619,21 @@ export declare interface KayAppMarketplaceContributors {
4615
4619
  };
4616
4620
  }
4617
4621
 
4622
+ /** Calls tools on this plugin's manifest-declared MCP servers through Bonsai's managed connection. */
4623
+ export declare interface KayAppMcp {
4624
+ /**
4625
+ * Uses the current app-wide server set, without a session or working directory.
4626
+ * Refuses undeclared or no-longer-hosted servers. Sign-in and tool failures return typed outcomes;
4627
+ * credentials remain with the host. Like the agent-side vendored MCP API, calls can read or write
4628
+ * and do not use the agent's per-tool approval path.
4629
+ */
4630
+ callTool(input: {
4631
+ readonly server: string;
4632
+ readonly tool: string;
4633
+ readonly args: Readonly<Record<string, unknown>>;
4634
+ }): Promise<VendoredMcpOutcome>;
4635
+ }
4636
+
4618
4637
  /**
4619
4638
  * Notes through Memory's ordinary notebook operations, without a chat session. Each call checks
4620
4639
  * `memory.read` or `memory.write`; a missing notebook or refused grant rejects. Paths are note
@@ -5087,6 +5106,7 @@ export declare interface KayAppPhaseShiftSessionEvent extends KayAppSessionEvent
5087
5106
  * physical sandbox against ambient Node imports.
5088
5107
  */
5089
5108
  export declare interface KayAppPluginApi {
5109
+ readonly mcp: KayAppMcp;
5090
5110
  /** This plugin's canonical id (already validated by the host registry). */
5091
5111
  readonly id: string;
5092
5112
  /** Register app-lifetime cleanup for plugin-owned processes, sockets, watchers, or timers. */
@@ -5388,9 +5408,7 @@ export declare interface KayAppPollerOptions<Cursor extends JsonValue> {
5388
5408
  readonly poll: (input: {
5389
5409
  readonly account: KayAppAccountSummary;
5390
5410
  readonly cursor: Cursor | undefined;
5391
- readonly credential: Extract<KayAppBackgroundCredentialResult, {
5392
- readonly status: "resolved";
5393
- }>;
5411
+ readonly credential: ResolvedCredential;
5394
5412
  readonly runId: string;
5395
5413
  }) => Promise<KayAppPollResult<Cursor>>;
5396
5414
  }
@@ -5545,50 +5563,7 @@ export declare interface KayAppResolveCredentialRequest {
5545
5563
  readonly purpose: string;
5546
5564
  }
5547
5565
 
5548
- /**
5549
- * ---
5550
- * responsibility: The plugin-facing credential surface of the `kay.app` target SDK. A daemon-hosted
5551
- * plugin lists account metadata or resolves credentials for an owned or consumed auth service
5552
- * under explicit grants. Credential material is read where the work happens.
5553
- * owns:
5554
- * - {@link KayAppAuth}, {@link KayAppResolvedCredential}.
5555
- * does_not_own:
5556
- * - Acquisition, storage, refresh, or revocation. Those are the credential authority's, reached
5557
- * through the host. A plugin can only ask for material it is granted, for a purpose it declared.
5558
- * ---
5559
- *
5560
- * ## Deny-by-default
5561
- *
5562
- * `KayAppPluginApi.auth` is **present only for plugins the host grants** (`auth.operations`
5563
- * containing `"list"` or `"resolve"` in `permissions.byTarget["kay.app"]`, against an owned or consumed
5564
- * service) and `undefined` otherwise - an ungranted plugin cannot even reference the capability.
5565
- * This mirrors `KayAppPluginApi.sessions`, and it is the rule for every capability behind a grant:
5566
- * never hand a plugin an object whose grant is decorative.
5567
- *
5568
- * ## Secrets do not leave this object
5569
- *
5570
- * A resolved credential is live secret material. Never log it, never echo it into an error message,
5571
- * never put it in an event payload, never return it from an endpoint handler, and never accept it
5572
- * as a URI or config value. Read it, use it in the outbound request, drop it.
5573
- */
5574
- /**
5575
- * Live credential material for one account of one auth scheme.
5576
- *
5577
- * Shaped to match the kernel's `ResolvedCredential` so a plugin that already reads
5578
- * `ctx.auth.credential` in a URI verb reads the same thing here.
5579
- */
5580
- export declare interface KayAppResolvedCredential {
5581
- /** Bearer for OAuth schemes, the api key for api-key schemes. Host-resolved and refreshed. */
5582
- readonly accessToken: string;
5583
- readonly accountId: string;
5584
- readonly schemeId: string;
5585
- readonly scopes?: readonly string[];
5586
- /**
5587
- * Every value of a multi-field api-key credential, keyed by the scheme's declared field id
5588
- * (`accessToken` mirrors the primary field). Absent for single-secret schemes.
5589
- */
5590
- readonly fields?: Readonly<Record<string, string>>;
5591
- }
5566
+ export declare type KayAppResolvedCredential = ResolvedCredential;
5592
5567
 
5593
5568
  /** Hard limits on the routes a `tier` or `model` selection may use. */
5594
5569
  export declare interface KayAppRouteConstraints {
@@ -8126,7 +8101,7 @@ export declare interface KayAppWhiteboardTypes {
8126
8101
  */
8127
8102
  export declare interface KayAppWorkflowAccount {
8128
8103
  readonly account: KayAppAccountSummary;
8129
- readonly credential: KayAppBackgroundCredentialResult;
8104
+ readonly auth: KayAppCredentialResolution;
8130
8105
  }
8131
8106
 
8132
8107
  /**
@@ -10295,7 +10270,7 @@ export declare function requireWriteContent(payload: UriPayload | Uint8Array | u
10295
10270
  * verb (`ctx.auth.credential`), a tool (`ctx.credential`) or a search provider (`ctx.credential`).
10296
10271
  * Plain data, so it crosses a process boundary with the call; plugin code never asks for one.
10297
10272
  */
10298
- declare interface ResolvedCredential {
10273
+ export declare interface ResolvedCredential {
10299
10274
  /** Bearer for OAuth schemes, apiKey for api-key schemes. Host-resolved and refreshed. */
10300
10275
  readonly accessToken: string;
10301
10276
  readonly accountId: string;
@@ -16731,6 +16706,52 @@ declare type UserShellCommandMessage = CustomMessage<UserShellCommandDetails> &
16731
16706
  readonly display: true;
16732
16707
  };
16733
16708
 
16709
+ /**
16710
+ * ---
16711
+ * responsibility: The one interface through which a vendored-MCP plugin's code calls a tool on its
16712
+ * own vendored MCP server, so every read-through plugin and the daemon that implements the port
16713
+ * agree on the same shape by construction.
16714
+ * owns:
16715
+ * - {@link VendoredMcpPort} - what a plugin's URI module and tools call.
16716
+ * - {@link VendoredMcpOutcome} - the typed result a plugin decodes, including every failure it
16717
+ * must surface to the agent rather than swallow.
16718
+ * does_not_own:
16719
+ * - The implementation. A plugin never dials MCP itself: it takes the port from
16720
+ * `api.vendoredMcp.port(server)` (`@bonsai/plugin-sdk/kay-agent`), which the daemon binds to the
16721
+ * plugin's own hosted server over its MCP host. Plugin source stays host-free, and a plugin
16722
+ * under test substitutes a fake port.
16723
+ * - Which tool names exist. `TTool` is the plugin's own union of the vendor tools it calls; the
16724
+ * port is generic so a typo in a tool name fails typecheck inside the plugin.
16725
+ * ---
16726
+ */
16727
+ /**
16728
+ * Why a call failed, as the plugin must tell the agent. `needs-auth` carries the exact service to
16729
+ * reconnect (`serviceId`) so a plugin can name it in its error instead of returning an empty
16730
+ * result; today's plugins name their statically declared `requiresAuth` service instead, which is
16731
+ * the same service for a single-service plugin. `unknown-server` and `unknown-tool` are wiring
16732
+ * faults (a server Bonsai does not host for this plugin, or a tool name the server does not have)
16733
+ * and stay loud for the same reason: an unreachable host must never decode as "no data".
16734
+ */
16735
+ declare type VendoredMcpFailureReason = "needs-auth" | "unknown-server" | "unknown-tool" | "failed";
16736
+
16737
+ declare type VendoredMcpOutcome =
16738
+ /**
16739
+ * `value` is the tool's `structuredContent` when it sent one, else its text content parsed as
16740
+ * JSON, else that text as a string: a vendor tool that answers in prose (a transcript, a
16741
+ * markdown summary) is a result, not a failure. A route that needs a record rejects a string
16742
+ * itself, with its own message.
16743
+ */
16744
+ {
16745
+ readonly ok: true;
16746
+ readonly value: unknown;
16747
+ } | {
16748
+ readonly ok: false;
16749
+ readonly reason: VendoredMcpFailureReason;
16750
+ readonly message: string;
16751
+ /** Exact reconnect target supplied by the MCP host for an auth failure. */
16752
+ readonly serviceId?: string;
16753
+ };
16754
+
16734
16755
  /** Creates a Void type. */
16735
16756
  declare function Void(options?: TSchemaOptions): TVoid;
16736
16757
 
@@ -16898,6 +16919,9 @@ declare const WithElementList_0: (input: string, result?: unknown[]) => [unknown
16898
16919
 
16899
16920
  declare function WithElementListMapping(input: [unknown, unknown, unknown] | []): unknown;
16900
16921
 
16922
+ /** Try the call's credentials in order; only credential rejection advances to the next. */
16923
+ export declare function withEndpointCredential<T>(context: KayAppEndpointContext, use: (credential: KayAppResolvedCredential) => Promise<T>): Promise<T>;
16924
+
16901
16925
  declare function WithMapping(input: [unknown, unknown] | []): unknown;
16902
16926
 
16903
16927
  declare const WithNull: (input: string) => [unknown, string] | [];
package/dist/kay-app.js CHANGED
@@ -599,11 +599,6 @@ function payload(name, schema, options = {}) {
599
599
  };
600
600
  }
601
601
 
602
- // packages/plugin-sdk/dist/kay-app/account.js
603
- function isRetryable(result) {
604
- return result.status === "not-ready";
605
- }
606
-
607
602
  // packages/plugin-sdk/dist/kay-app/auth.js
608
603
  var KayAppCredentialRejectedError = class extends Error {
609
604
  name = "KayAppCredentialRejectedError";
@@ -626,6 +621,32 @@ async function withCredential(auth, request, use) {
626
621
  throw rejection ?? new Error(`No credential is resolvable for '${request.serviceId}'.`);
627
622
  }
628
623
 
624
+ // packages/plugin-sdk/dist/kay-app/endpoints.js
625
+ async function withEndpointCredential(context, use) {
626
+ let rejection;
627
+ for (const credential of context.credentials) {
628
+ context.signal.throwIfAborted();
629
+ try {
630
+ const result = await use(credential);
631
+ try {
632
+ context.reportWorked(credential.schemeId);
633
+ } catch {
634
+ }
635
+ return result;
636
+ } catch (error) {
637
+ if (!(error instanceof KayAppCredentialRejectedError))
638
+ throw error;
639
+ rejection = error;
640
+ }
641
+ }
642
+ throw rejection ?? new Error("No credential is resolvable for this endpoint.");
643
+ }
644
+
645
+ // packages/plugin-sdk/dist/kay-app/account.js
646
+ function isRetryable(result) {
647
+ return result.status === "not-ready";
648
+ }
649
+
629
650
  // packages/plugin-sdk/dist/kay-app/automations.js
630
651
  var KAY_APP_AUTOMATION_CONDITION_KINDS = [
631
652
  "time",
@@ -715,7 +736,7 @@ function definePoller(app, localId, options) {
715
736
  let skipped = 0;
716
737
  let failed = 0;
717
738
  let refused = 0;
718
- for (const { account, credential } of accounts) {
739
+ for (const { account, auth } of accounts) {
719
740
  const saved = previous.find((entry) => entry.schemeId === account.schemeId && entry.accountId === account.accountId);
720
741
  const name = `${account.schemeId}/${account.accountId}`;
721
742
  const keepSaved = (summary) => {
@@ -723,9 +744,9 @@ function definePoller(app, localId, options) {
723
744
  next.push(saved);
724
745
  details.push(`${name}: ${summary}`);
725
746
  };
726
- if (credential.status !== "resolved") {
747
+ if (auth.status !== "resolved") {
727
748
  skipped++;
728
- keepSaved(credential.status === "requires-auth" ? "Sign-in or required scope missing" : "Credential missing");
749
+ keepSaved(auth.status === "requires-auth" ? "Sign-in or required scope missing" : "Credential missing");
729
750
  continue;
730
751
  }
731
752
  let result;
@@ -733,7 +754,7 @@ function definePoller(app, localId, options) {
733
754
  result = await options.poll({
734
755
  account,
735
756
  cursor: structuredClone(saved?.cursor),
736
- credential,
757
+ credential: auth.credential,
737
758
  runId
738
759
  });
739
760
  } catch {
@@ -964,5 +985,6 @@ export {
964
985
  transcriptMessageText,
965
986
  transcriptMessageTexts,
966
987
  transcriptRoleLabel,
967
- withCredential
988
+ withCredential,
989
+ withEndpointCredential
968
990
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yaklabs-ai/plugin-sdk",
3
- "version": "0.40.0",
3
+ "version": "0.42.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",