@yaklabs-ai/plugin-sdk 0.27.1 → 0.29.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.27.1"
16
+ "@bonsai/plugin-sdk": "npm:@yaklabs-ai/plugin-sdk@^0.29.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.27.1" },
65
+ "compatibility": { "sdk": "^0.29.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.27.1",
4
+ "version": "0.29.0",
5
5
  "target": "npm",
6
6
  "firstPartyLicense": "MIT",
7
7
  "bundled": [
@@ -34,6 +34,20 @@ declare interface AccountIdentity {
34
34
  readonly providerSessionId?: string;
35
35
  }
36
36
 
37
+ /**
38
+ * Whose credential this is: every provider account it reaches. One sign-in can reach several
39
+ * (Cloudflare), so the answer is always a list. A bad credential throws.
40
+ */
41
+ declare type AccountLookup = (input: AccountLookupInput) => Promise<readonly LookedUpAccount[]>;
42
+
43
+ /** What an account lookup is asked about: a fresh credential. */
44
+ declare interface AccountLookupInput {
45
+ readonly accessToken: string;
46
+ /** Every declared field of a multi-field api-key scheme; empty for anything else. */
47
+ readonly fields: Readonly<Record<string, string>>;
48
+ readonly signal: AbortSignal;
49
+ }
50
+
37
51
  /**
38
52
  * Structured, non-secret *provenance* for a connected account: which record on the provider's side
39
53
  * this credential points at. Says nothing about the human - a Notion `displayName` here is the
@@ -2318,8 +2332,23 @@ declare const KAY_PLUGIN_PROTOCOL_VERSION: "kay.plugin.v1";
2318
2332
  * hosted module's code and manifest must agree on it, and the daemon reads it to find an
2319
2333
  * external-CLI scheme without running the module. A module that runs in the daemon is unchanged,
2320
2334
  * so this is additive; a plugin whose manifest sets `authScheme` declares ^0.27.1.
2335
+ *
2336
+ * 0.28.0 makes "whose credential is this?" one call (#15714). `api.auth.registerAccountLookup`
2337
+ * replaces `registerValidator` and `registerAccountResolver`: it takes the credential, its fields and
2338
+ * a cancel signal, and returns every account the credential reaches. A manifest says `account:
2339
+ * "lookup"` on any `oauth2` or `api-key` scheme the plugin answers for, in place of `validates: true`
2340
+ * and the `"resolveAccountId"` and `"resolveAccounts"` values, and a `pkce` scheme on a client the
2341
+ * host holds may name one too. A plugin using a removed member or value stops loading until it is
2342
+ * rebuilt; a code search found none outside this repo. A plugin with a sign-in declares ^0.28.0. 0.26.3 and 0.27.1
2343
+ * stay served for a plugin that uses none of these.
2344
+ *
2345
+ * 0.29.0 replaces `servedSimulators` (`KayServedSimulators`, a lookup by adapter id) with
2346
+ * `simulator` on both targets (#14929): what the plugin's own simulator built, handed over once by
2347
+ * whichever process runs the plugin. A plugin's simulator file exports `createPluginSimulator`
2348
+ * (`KayPluginSimulatorFactory`). A clean break: only this repo's plugins read the old member, and
2349
+ * a plugin with no simulator is unaffected, so 0.28.0 stays served.
2321
2350
  */
2322
- declare const KAY_PLUGIN_SDK_VERSION: "0.27.1";
2351
+ declare const KAY_PLUGIN_SDK_VERSION: "0.29.0";
2323
2352
 
2324
2353
  declare const KAY_PLUGIN_TARGET_NAMES: readonly ["kay.agent", "kay.app", "kay.ui"];
2325
2354
 
@@ -2555,11 +2584,11 @@ declare interface KayAgentPluginApi {
2555
2584
  /** Absent unless the `knownResources` grant is requested and effectively granted. */
2556
2585
  readonly knownResources?: KayAgentKnownResources;
2557
2586
  /**
2558
- * Optional: absent unless a simulating Bonsai daemon serves this plugin a simulator (SDK 0.18.1).
2559
- * A production daemon never does. In this version only plugins the release carries are served;
2560
- * any plugin may ship a `./simulator` later. See {@link KayServedSimulators}.
2587
+ * What this plugin's own simulator built, in a simulated run only (SDK 0.29.0): absent in every
2588
+ * other, so treat absence as the normal case. Use it in place of the real backend; its shape is
2589
+ * the plugin's own, so narrow it before use. See {@link KayPluginSimulatorFactory}.
2561
2590
  */
2562
- readonly servedSimulators?: KayServedSimulators;
2591
+ readonly simulator?: unknown;
2563
2592
  /**
2564
2593
  * Present when the host composes Whiteboard. Each operation is checked against its exact
2565
2594
  * `whiteboard.<operation> {scope}` claim; handle presence is not consent.
@@ -2697,16 +2726,12 @@ declare interface KayAgentPluginApi {
2697
2726
  */
2698
2727
  readonly auth: {
2699
2728
  /**
2700
- * The check for an `api-key` scheme the manifest marks `validates: true`. `serviceId` and
2701
- * `schemeId` are the manifest's global ids (`github.account`, `github.pat`).
2729
+ * Whose credential this is, for a scheme whose manifest says `account: "lookup"`. `serviceId` and
2730
+ * `schemeId` are the manifest's global ids (`github.account`, `github.pat`). On an `api-key`
2731
+ * scheme it also checks the key before it is saved, and must name exactly one account. Refused
2732
+ * on any other scheme.
2702
2733
  */
2703
- registerValidator(serviceId: string, schemeId: string, validate: ValidatePluginApiKeyCredential): void;
2704
- /**
2705
- * The account lookup for an `oauth2` scheme whose manifest names it as where the account comes
2706
- * from (`account: "resolveAccountId"` or `"resolveAccounts"`), registering that function only.
2707
- * Refused on any other scheme.
2708
- */
2709
- registerAccountResolver(serviceId: string, schemeId: string, resolver: PluginAccountResolver): void;
2734
+ registerAccountLookup(serviceId: string, schemeId: string, lookup: PluginAccountLookup): void;
2710
2735
  /**
2711
2736
  * Declare a delegated scheme (plugin-provided connect/refresh over opaque material) for a
2712
2737
  * service. The host maps it onto the kernel's `DelegatedAuthScheme` and drives its `connect`
@@ -3203,24 +3228,6 @@ declare const KayPluginProtocolVersion: z.ZodLiteral<"kay.plugin.v1">;
3203
3228
 
3204
3229
  declare type KayPluginProtocolVersion = z.infer<typeof KayPluginProtocolVersion>;
3205
3230
 
3206
- /**
3207
- * The simulators a simulating Bonsai daemon (evals, dev, tests) serves this plugin, keyed by the
3208
- * adapter id its simulated URI connection rows name. The daemon builds each from the plugin's own
3209
- * dev-only `./simulator` subpath; the plugin never imports its simulator.
3210
- *
3211
- * The member that carries this, `servedSimulators` on both plugin APIs, is optional and absent
3212
- * unless a simulating daemon serves it. A production daemon never does, so treat absence as the
3213
- * normal case. In this version the daemon serves it only to plugins the release carries; the seam
3214
- * is not specific to them, and any plugin may ship a `./simulator` later.
3215
- */
3216
- declare interface KayServedSimulators {
3217
- /**
3218
- * What this plugin's simulator built for `adapterId`, or `undefined` when none was served for
3219
- * that id. The shape is the plugin's own simulator contract; narrow it before use.
3220
- */
3221
- get(adapterId: string): unknown;
3222
- }
3223
-
3224
3231
  /** Applies a KeyOf action to the given type. */
3225
3232
  declare function KeyOf<Type extends TSchema>(type: Type, options?: TSchemaOptions): TKeyOf_2<Type>;
3226
3233
 
@@ -3330,6 +3337,15 @@ declare const LocalContributionId: z.ZodString;
3330
3337
 
3331
3338
  declare type LocalContributionId = z.infer<typeof LocalContributionId>;
3332
3339
 
3340
+ /** One provider account a credential reaches. */
3341
+ declare interface LookedUpAccount {
3342
+ readonly accountId: string;
3343
+ readonly label?: string;
3344
+ readonly identity?: AccountIdentity;
3345
+ /** Non-secret observations the host may surface without retaining credential material. */
3346
+ readonly capabilityChecks?: readonly ApiKeyCapabilityCheck[];
3347
+ }
3348
+
3333
3349
  /** Applies a Lowercase action to the given type. */
3334
3350
  declare function Lowercase_2<Type extends TSchema>(type: Type, options?: TSchemaOptions): TLowercase<Type>;
3335
3351
 
@@ -4184,13 +4200,10 @@ export declare const PLUGIN_DISCLOSURE_CONTRACT = 2;
4184
4200
  export declare const PLUGIN_DISCLOSURE_RULES: readonly ["agent-hint-missing", "agent-hint-summary-empty", "agent-hint-flows-empty", "agent-hint-triggers-missing", "scheme-claim-missing", "help-missing", "help-malformed", "help-throws", "help-uri-malformed", "help-uri-throws", "verb-coverage-missing", "template-operation-docs-missing", "verb-docs-missing", "template-accepts-missing", "template-address-unmatchable", "template-delete-effect-missing", "template-operations-missing", "template-parameter-unknown", "template-scheme-mismatch", "clamp-summary", "clamp-flow-label", "clamp-flow-when", "clamp-flow-example", "clamp-trigger-count", "clamp-trigger-item", "clamp-help-uri", "skill-link-dangling", "skill-link-missing-scheme", "skill-twin-count-mismatch", "skill-twin-missing-declaration", "skill-twin-description-mismatch", "skill-twin-file-unreadable", "skill-twin-frontmatter-name-mismatch", "skill-twin-frontmatter-description-mismatch", "skill-twin-body-mismatch"];
4185
4201
 
4186
4202
  /**
4187
- * How a plugin learns which provider account a fresh OAuth token belongs to: one account, or every
4188
- * account the grant reaches. Registered with `api.auth.registerAccountResolver`.
4203
+ * Whose credential this is: every provider account it reaches, usually one. A bad credential throws.
4204
+ * Registered with `api.auth.registerAccountLookup`.
4189
4205
  */
4190
- declare interface PluginAccountResolver {
4191
- readonly resolveAccountId?: ResolvePluginAccountId;
4192
- readonly resolveAccounts?: ResolvePluginAccounts;
4193
- }
4206
+ declare type PluginAccountLookup = AccountLookup;
4194
4207
 
4195
4208
  /** The kinds of capability a plugin service can advertise (mirrors the host capability taxonomy). */
4196
4209
  declare type PluginCapabilityKind = "uri-module" | "tool" | "search-provider";
@@ -4651,28 +4664,6 @@ declare interface ResolvedCredential {
4651
4664
  readonly fields?: Readonly<Record<string, string>>;
4652
4665
  }
4653
4666
 
4654
- /**
4655
- * Derive a stable provider account id (and optional label) from a freshly connected access token,
4656
- * plus - when known - who the account belongs to.
4657
- *
4658
- * A resolver almost always calls the provider's profile endpoint to derive `accountId` at all, so
4659
- * the identity fields are already in the response: return them rather than flattening the person
4660
- * into `label`. Populating `identity` is what lets the agent know the user's handle/email for a
4661
- * connected service without asking.
4662
- */
4663
- declare type ResolvePluginAccountId = (accessToken: string) => Promise<{
4664
- readonly accountId: string;
4665
- readonly label?: string;
4666
- readonly identity?: AccountIdentity;
4667
- }>;
4668
-
4669
- /** Enumerate every provider account a fresh OAuth grant powers. */
4670
- declare type ResolvePluginAccounts = (accessToken: string) => Promise<readonly {
4671
- readonly accountId: string;
4672
- readonly label?: string;
4673
- readonly identity?: AccountIdentity;
4674
- }[]>;
4675
-
4676
4667
  /** Match remaining characters in the buffer until end. If no characters are in buffer, no match */
4677
4668
  declare function Rest<Input extends string>(input: Input): TRest<Input>;
4678
4669
 
@@ -10213,26 +10204,6 @@ declare interface Usage {
10213
10204
  };
10214
10205
  }
10215
10206
 
10216
- /** Validate freshly-entered material and resolve the provider account before persistence. */
10217
- declare type ValidateApiKeyCredential = (input: ValidateApiKeyCredentialInput) => Promise<ValidateApiKeyCredentialResult>;
10218
-
10219
- declare interface ValidateApiKeyCredentialInput {
10220
- readonly accessToken: string;
10221
- /** Every declared field; empty for a classic single-secret scheme. */
10222
- readonly fields: Readonly<Record<string, string>>;
10223
- readonly signal: AbortSignal;
10224
- }
10225
-
10226
- declare interface ValidateApiKeyCredentialResult {
10227
- readonly accountId: string;
10228
- readonly label?: string;
10229
- readonly identity?: AccountIdentity;
10230
- /** Non-secret observations the host may surface without retaining credential material. */
10231
- readonly capabilityChecks?: readonly ApiKeyCapabilityCheck[];
10232
- }
10233
-
10234
- declare type ValidatePluginApiKeyCredential = ValidateApiKeyCredential;
10235
-
10236
10207
  /**
10237
10208
  * ---
10238
10209
  * responsibility: The one interface through which a vendored-MCP plugin's code calls a tool on its
@@ -932,9 +932,7 @@ function collectUriModulesFromKayAgentActivate(activate) {
932
932
  registerConverter: () => {
933
933
  },
934
934
  auth: {
935
- registerValidator: () => {
936
- },
937
- registerAccountResolver: () => {
935
+ registerAccountLookup: () => {
938
936
  },
939
937
  declareDelegatedScheme: () => {
940
938
  },
@@ -34,6 +34,20 @@ declare interface AccountIdentity {
34
34
  readonly providerSessionId?: string;
35
35
  }
36
36
 
37
+ /**
38
+ * Whose credential this is: every provider account it reaches. One sign-in can reach several
39
+ * (Cloudflare), so the answer is always a list. A bad credential throws.
40
+ */
41
+ declare type AccountLookup = (input: AccountLookupInput) => Promise<readonly LookedUpAccount[]>;
42
+
43
+ /** What an account lookup is asked about: a fresh credential. */
44
+ declare interface AccountLookupInput {
45
+ readonly accessToken: string;
46
+ /** Every declared field of a multi-field api-key scheme; empty for anything else. */
47
+ readonly fields: Readonly<Record<string, string>>;
48
+ readonly signal: AbortSignal;
49
+ }
50
+
37
51
  /**
38
52
  * Structured, non-secret *provenance* for a connected account: which record on the provider's side
39
53
  * this credential points at. Says nothing about the human - a Notion `displayName` here is the
@@ -2372,8 +2386,23 @@ declare const KAY_PLUGIN_PROTOCOL_VERSION: "kay.plugin.v1";
2372
2386
  * hosted module's code and manifest must agree on it, and the daemon reads it to find an
2373
2387
  * external-CLI scheme without running the module. A module that runs in the daemon is unchanged,
2374
2388
  * so this is additive; a plugin whose manifest sets `authScheme` declares ^0.27.1.
2389
+ *
2390
+ * 0.28.0 makes "whose credential is this?" one call (#15714). `api.auth.registerAccountLookup`
2391
+ * replaces `registerValidator` and `registerAccountResolver`: it takes the credential, its fields and
2392
+ * a cancel signal, and returns every account the credential reaches. A manifest says `account:
2393
+ * "lookup"` on any `oauth2` or `api-key` scheme the plugin answers for, in place of `validates: true`
2394
+ * and the `"resolveAccountId"` and `"resolveAccounts"` values, and a `pkce` scheme on a client the
2395
+ * host holds may name one too. A plugin using a removed member or value stops loading until it is
2396
+ * rebuilt; a code search found none outside this repo. A plugin with a sign-in declares ^0.28.0. 0.26.3 and 0.27.1
2397
+ * stay served for a plugin that uses none of these.
2398
+ *
2399
+ * 0.29.0 replaces `servedSimulators` (`KayServedSimulators`, a lookup by adapter id) with
2400
+ * `simulator` on both targets (#14929): what the plugin's own simulator built, handed over once by
2401
+ * whichever process runs the plugin. A plugin's simulator file exports `createPluginSimulator`
2402
+ * (`KayPluginSimulatorFactory`). A clean break: only this repo's plugins read the old member, and
2403
+ * a plugin with no simulator is unaffected, so 0.28.0 stays served.
2375
2404
  */
2376
- declare const KAY_PLUGIN_SDK_VERSION: "0.27.1";
2405
+ declare const KAY_PLUGIN_SDK_VERSION: "0.29.0";
2377
2406
 
2378
2407
  declare const KAY_PLUGIN_TARGET_NAMES: readonly ["kay.agent", "kay.app", "kay.ui"];
2379
2408
 
@@ -2606,11 +2635,11 @@ declare interface KayAgentPluginApi {
2606
2635
  /** Absent unless the `knownResources` grant is requested and effectively granted. */
2607
2636
  readonly knownResources?: KayAgentKnownResources;
2608
2637
  /**
2609
- * Optional: absent unless a simulating Bonsai daemon serves this plugin a simulator (SDK 0.18.1).
2610
- * A production daemon never does. In this version only plugins the release carries are served;
2611
- * any plugin may ship a `./simulator` later. See {@link KayServedSimulators}.
2638
+ * What this plugin's own simulator built, in a simulated run only (SDK 0.29.0): absent in every
2639
+ * other, so treat absence as the normal case. Use it in place of the real backend; its shape is
2640
+ * the plugin's own, so narrow it before use. See {@link KayPluginSimulatorFactory}.
2612
2641
  */
2613
- readonly servedSimulators?: KayServedSimulators;
2642
+ readonly simulator?: unknown;
2614
2643
  /**
2615
2644
  * Present when the host composes Whiteboard. Each operation is checked against its exact
2616
2645
  * `whiteboard.<operation> {scope}` claim; handle presence is not consent.
@@ -2748,16 +2777,12 @@ declare interface KayAgentPluginApi {
2748
2777
  */
2749
2778
  readonly auth: {
2750
2779
  /**
2751
- * The check for an `api-key` scheme the manifest marks `validates: true`. `serviceId` and
2752
- * `schemeId` are the manifest's global ids (`github.account`, `github.pat`).
2780
+ * Whose credential this is, for a scheme whose manifest says `account: "lookup"`. `serviceId` and
2781
+ * `schemeId` are the manifest's global ids (`github.account`, `github.pat`). On an `api-key`
2782
+ * scheme it also checks the key before it is saved, and must name exactly one account. Refused
2783
+ * on any other scheme.
2753
2784
  */
2754
- registerValidator(serviceId: string, schemeId: string, validate: ValidatePluginApiKeyCredential): void;
2755
- /**
2756
- * The account lookup for an `oauth2` scheme whose manifest names it as where the account comes
2757
- * from (`account: "resolveAccountId"` or `"resolveAccounts"`), registering that function only.
2758
- * Refused on any other scheme.
2759
- */
2760
- registerAccountResolver(serviceId: string, schemeId: string, resolver: PluginAccountResolver): void;
2785
+ registerAccountLookup(serviceId: string, schemeId: string, lookup: PluginAccountLookup): void;
2761
2786
  /**
2762
2787
  * Declare a delegated scheme (plugin-provided connect/refresh over opaque material) for a
2763
2788
  * service. The host maps it onto the kernel's `DelegatedAuthScheme` and drives its `connect`
@@ -3254,24 +3279,6 @@ declare const KayPluginProtocolVersion: z.ZodLiteral<"kay.plugin.v1">;
3254
3279
 
3255
3280
  declare type KayPluginProtocolVersion = z.infer<typeof KayPluginProtocolVersion>;
3256
3281
 
3257
- /**
3258
- * The simulators a simulating Bonsai daemon (evals, dev, tests) serves this plugin, keyed by the
3259
- * adapter id its simulated URI connection rows name. The daemon builds each from the plugin's own
3260
- * dev-only `./simulator` subpath; the plugin never imports its simulator.
3261
- *
3262
- * The member that carries this, `servedSimulators` on both plugin APIs, is optional and absent
3263
- * unless a simulating daemon serves it. A production daemon never does, so treat absence as the
3264
- * normal case. In this version the daemon serves it only to plugins the release carries; the seam
3265
- * is not specific to them, and any plugin may ship a `./simulator` later.
3266
- */
3267
- declare interface KayServedSimulators {
3268
- /**
3269
- * What this plugin's simulator built for `adapterId`, or `undefined` when none was served for
3270
- * that id. The shape is the plugin's own simulator contract; narrow it before use.
3271
- */
3272
- get(adapterId: string): unknown;
3273
- }
3274
-
3275
3282
  /** Applies a KeyOf action to the given type. */
3276
3283
  declare function KeyOf<Type extends TSchema>(type: Type, options?: TSchemaOptions): TKeyOf_2<Type>;
3277
3284
 
@@ -3381,6 +3388,15 @@ declare const LocalContributionId: z.ZodString;
3381
3388
 
3382
3389
  declare type LocalContributionId = z.infer<typeof LocalContributionId>;
3383
3390
 
3391
+ /** One provider account a credential reaches. */
3392
+ declare interface LookedUpAccount {
3393
+ readonly accountId: string;
3394
+ readonly label?: string;
3395
+ readonly identity?: AccountIdentity;
3396
+ /** Non-secret observations the host may surface without retaining credential material. */
3397
+ readonly capabilityChecks?: readonly ApiKeyCapabilityCheck[];
3398
+ }
3399
+
3384
3400
  /** Applies a Lowercase action to the given type. */
3385
3401
  declare function Lowercase_2<Type extends TSchema>(type: Type, options?: TSchemaOptions): TLowercase<Type>;
3386
3402
 
@@ -4202,13 +4218,10 @@ declare function Pick_2<Type extends TSchema, Indexer extends TSchema>(type: Typ
4202
4218
  declare function PickDeferred<Type extends TSchema, Indexer extends TSchema>(type: Type, indexer: Indexer, options?: TSchemaOptions): TPickDeferred<Type, Indexer>;
4203
4219
 
4204
4220
  /**
4205
- * How a plugin learns which provider account a fresh OAuth token belongs to: one account, or every
4206
- * account the grant reaches. Registered with `api.auth.registerAccountResolver`.
4221
+ * Whose credential this is: every provider account it reaches, usually one. A bad credential throws.
4222
+ * Registered with `api.auth.registerAccountLookup`.
4207
4223
  */
4208
- declare interface PluginAccountResolver {
4209
- readonly resolveAccountId?: ResolvePluginAccountId;
4210
- readonly resolveAccounts?: ResolvePluginAccounts;
4211
- }
4224
+ declare type PluginAccountLookup = AccountLookup;
4212
4225
 
4213
4226
  /** The kinds of capability a plugin service can advertise (mirrors the host capability taxonomy). */
4214
4227
  declare type PluginCapabilityKind = "uri-module" | "tool" | "search-provider";
@@ -4763,10 +4776,7 @@ declare const ResolvedPluginContractV1: z.ZodObject<{
4763
4776
  }>>;
4764
4777
  clientId: z.ZodOptional<z.ZodString>;
4765
4778
  clientSecret: z.ZodOptional<z.ZodString>;
4766
- account: z.ZodOptional<z.ZodEnum<{
4767
- resolveAccountId: "resolveAccountId";
4768
- resolveAccounts: "resolveAccounts";
4769
- }>>;
4779
+ account: z.ZodOptional<z.ZodLiteral<"lookup">>;
4770
4780
  localId: z.ZodString;
4771
4781
  globalId: z.ZodString;
4772
4782
  kind: z.ZodLiteral<"oauth2">;
@@ -4795,8 +4805,7 @@ declare const ResolvedPluginContractV1: z.ZodObject<{
4795
4805
  exchange: z.ZodLiteral<"confidential">;
4796
4806
  clientSuppliers: z.ZodTuple<[z.ZodLiteral<"kay">], null>;
4797
4807
  account: z.ZodEnum<{
4798
- resolveAccountId: "resolveAccountId";
4799
- resolveAccounts: "resolveAccounts";
4808
+ lookup: "lookup";
4800
4809
  "sign-in": "sign-in";
4801
4810
  }>;
4802
4811
  localId: z.ZodString;
@@ -4837,7 +4846,7 @@ declare const ResolvedPluginContractV1: z.ZodObject<{
4837
4846
  instructions: z.ZodString;
4838
4847
  url: z.ZodURL;
4839
4848
  }, z.core.$strict>>;
4840
- validates: z.ZodOptional<z.ZodLiteral<true>>;
4849
+ account: z.ZodOptional<z.ZodLiteral<"lookup">>;
4841
4850
  displayName: z.ZodOptional<z.ZodString>;
4842
4851
  agentHint: z.ZodOptional<z.ZodString>;
4843
4852
  summary: z.ZodOptional<z.ZodString>;
@@ -5687,28 +5696,6 @@ declare type ResolveExternalCliResult = {
5687
5696
  readonly accounts?: readonly AuthAccount[];
5688
5697
  };
5689
5698
 
5690
- /**
5691
- * Derive a stable provider account id (and optional label) from a freshly connected access token,
5692
- * plus - when known - who the account belongs to.
5693
- *
5694
- * A resolver almost always calls the provider's profile endpoint to derive `accountId` at all, so
5695
- * the identity fields are already in the response: return them rather than flattening the person
5696
- * into `label`. Populating `identity` is what lets the agent know the user's handle/email for a
5697
- * connected service without asking.
5698
- */
5699
- declare type ResolvePluginAccountId = (accessToken: string) => Promise<{
5700
- readonly accountId: string;
5701
- readonly label?: string;
5702
- readonly identity?: AccountIdentity;
5703
- }>;
5704
-
5705
- /** Enumerate every provider account a fresh OAuth grant powers. */
5706
- declare type ResolvePluginAccounts = (accessToken: string) => Promise<readonly {
5707
- readonly accountId: string;
5708
- readonly label?: string;
5709
- readonly identity?: AccountIdentity;
5710
- }[]>;
5711
-
5712
5699
  declare interface ResolveTokenFailure {
5713
5700
  readonly ok: false;
5714
5701
  readonly reason: ResolveTokenFailureReason;
@@ -11280,26 +11267,6 @@ declare interface Usage {
11280
11267
  };
11281
11268
  }
11282
11269
 
11283
- /** Validate freshly-entered material and resolve the provider account before persistence. */
11284
- declare type ValidateApiKeyCredential = (input: ValidateApiKeyCredentialInput) => Promise<ValidateApiKeyCredentialResult>;
11285
-
11286
- declare interface ValidateApiKeyCredentialInput {
11287
- readonly accessToken: string;
11288
- /** Every declared field; empty for a classic single-secret scheme. */
11289
- readonly fields: Readonly<Record<string, string>>;
11290
- readonly signal: AbortSignal;
11291
- }
11292
-
11293
- declare interface ValidateApiKeyCredentialResult {
11294
- readonly accountId: string;
11295
- readonly label?: string;
11296
- readonly identity?: AccountIdentity;
11297
- /** Non-secret observations the host may surface without retaining credential material. */
11298
- readonly capabilityChecks?: readonly ApiKeyCapabilityCheck[];
11299
- }
11300
-
11301
- declare type ValidatePluginApiKeyCredential = ValidateApiKeyCredential;
11302
-
11303
11270
  /**
11304
11271
  * ---
11305
11272
  * responsibility: The one interface through which a vendored-MCP plugin's code calls a tool on its
@@ -35,6 +35,20 @@ export declare interface AccountIdentity {
35
35
  readonly providerSessionId?: string;
36
36
  }
37
37
 
38
+ /**
39
+ * Whose credential this is: every provider account it reaches. One sign-in can reach several
40
+ * (Cloudflare), so the answer is always a list. A bad credential throws.
41
+ */
42
+ declare type AccountLookup = (input: AccountLookupInput) => Promise<readonly LookedUpAccount[]>;
43
+
44
+ /** What an account lookup is asked about: a fresh credential. */
45
+ declare interface AccountLookupInput {
46
+ readonly accessToken: string;
47
+ /** Every declared field of a multi-field api-key scheme; empty for anything else. */
48
+ readonly fields: Readonly<Record<string, string>>;
49
+ readonly signal: AbortSignal;
50
+ }
51
+
38
52
  /**
39
53
  * Structured, non-secret *provenance* for a connected account: which record on the provider's side
40
54
  * this credential points at. Says nothing about the human - a Notion `displayName` here is the
@@ -2647,8 +2661,23 @@ declare const KAY_PLUGIN_PROTOCOL_VERSION: "kay.plugin.v1";
2647
2661
  * hosted module's code and manifest must agree on it, and the daemon reads it to find an
2648
2662
  * external-CLI scheme without running the module. A module that runs in the daemon is unchanged,
2649
2663
  * so this is additive; a plugin whose manifest sets `authScheme` declares ^0.27.1.
2664
+ *
2665
+ * 0.28.0 makes "whose credential is this?" one call (#15714). `api.auth.registerAccountLookup`
2666
+ * replaces `registerValidator` and `registerAccountResolver`: it takes the credential, its fields and
2667
+ * a cancel signal, and returns every account the credential reaches. A manifest says `account:
2668
+ * "lookup"` on any `oauth2` or `api-key` scheme the plugin answers for, in place of `validates: true`
2669
+ * and the `"resolveAccountId"` and `"resolveAccounts"` values, and a `pkce` scheme on a client the
2670
+ * host holds may name one too. A plugin using a removed member or value stops loading until it is
2671
+ * rebuilt; a code search found none outside this repo. A plugin with a sign-in declares ^0.28.0. 0.26.3 and 0.27.1
2672
+ * stay served for a plugin that uses none of these.
2673
+ *
2674
+ * 0.29.0 replaces `servedSimulators` (`KayServedSimulators`, a lookup by adapter id) with
2675
+ * `simulator` on both targets (#14929): what the plugin's own simulator built, handed over once by
2676
+ * whichever process runs the plugin. A plugin's simulator file exports `createPluginSimulator`
2677
+ * (`KayPluginSimulatorFactory`). A clean break: only this repo's plugins read the old member, and
2678
+ * a plugin with no simulator is unaffected, so 0.28.0 stays served.
2650
2679
  */
2651
- declare const KAY_PLUGIN_SDK_VERSION: "0.27.1";
2680
+ declare const KAY_PLUGIN_SDK_VERSION: "0.29.0";
2652
2681
 
2653
2682
  declare const KAY_PLUGIN_TARGET_NAMES: readonly ["kay.agent", "kay.app", "kay.ui"];
2654
2683
 
@@ -2913,11 +2942,11 @@ export declare interface KayAgentPluginApi {
2913
2942
  /** Absent unless the `knownResources` grant is requested and effectively granted. */
2914
2943
  readonly knownResources?: KayAgentKnownResources;
2915
2944
  /**
2916
- * Optional: absent unless a simulating Bonsai daemon serves this plugin a simulator (SDK 0.18.1).
2917
- * A production daemon never does. In this version only plugins the release carries are served;
2918
- * any plugin may ship a `./simulator` later. See {@link KayServedSimulators}.
2945
+ * What this plugin's own simulator built, in a simulated run only (SDK 0.29.0): absent in every
2946
+ * other, so treat absence as the normal case. Use it in place of the real backend; its shape is
2947
+ * the plugin's own, so narrow it before use. See {@link KayPluginSimulatorFactory}.
2919
2948
  */
2920
- readonly servedSimulators?: KayServedSimulators;
2949
+ readonly simulator?: unknown;
2921
2950
  /**
2922
2951
  * Present when the host composes Whiteboard. Each operation is checked against its exact
2923
2952
  * `whiteboard.<operation> {scope}` claim; handle presence is not consent.
@@ -3055,16 +3084,12 @@ export declare interface KayAgentPluginApi {
3055
3084
  */
3056
3085
  readonly auth: {
3057
3086
  /**
3058
- * The check for an `api-key` scheme the manifest marks `validates: true`. `serviceId` and
3059
- * `schemeId` are the manifest's global ids (`github.account`, `github.pat`).
3060
- */
3061
- registerValidator(serviceId: string, schemeId: string, validate: ValidatePluginApiKeyCredential): void;
3062
- /**
3063
- * The account lookup for an `oauth2` scheme whose manifest names it as where the account comes
3064
- * from (`account: "resolveAccountId"` or `"resolveAccounts"`), registering that function only.
3065
- * Refused on any other scheme.
3087
+ * Whose credential this is, for a scheme whose manifest says `account: "lookup"`. `serviceId` and
3088
+ * `schemeId` are the manifest's global ids (`github.account`, `github.pat`). On an `api-key`
3089
+ * scheme it also checks the key before it is saved, and must name exactly one account. Refused
3090
+ * on any other scheme.
3066
3091
  */
3067
- registerAccountResolver(serviceId: string, schemeId: string, resolver: PluginAccountResolver): void;
3092
+ registerAccountLookup(serviceId: string, schemeId: string, lookup: PluginAccountLookup): void;
3068
3093
  /**
3069
3094
  * Declare a delegated scheme (plugin-provided connect/refresh over opaque material) for a
3070
3095
  * service. The host maps it onto the kernel's `DelegatedAuthScheme` and drives its `connect`
@@ -3580,21 +3605,19 @@ declare const KayPluginProtocolVersion: z.ZodLiteral<"kay.plugin.v1">;
3580
3605
  declare type KayPluginProtocolVersion = z.infer<typeof KayPluginProtocolVersion>;
3581
3606
 
3582
3607
  /**
3583
- * The simulators a simulating Bonsai daemon (evals, dev, tests) serves this plugin, keyed by the
3584
- * adapter id its simulated URI connection rows name. The daemon builds each from the plugin's own
3585
- * dev-only `./simulator` subpath; the plugin never imports its simulator.
3586
- *
3587
- * The member that carries this, `servedSimulators` on both plugin APIs, is optional and absent
3588
- * unless a simulating daemon serves it. A production daemon never does, so treat absence as the
3589
- * normal case. In this version the daemon serves it only to plugins the release carries; the seam
3590
- * is not specific to them, and any plugin may ship a `./simulator` later.
3608
+ * What a plugin's dev-only simulator file exports as `createPluginSimulator`. Whichever process
3609
+ * runs the plugin calls it once and hands the result to that plugin alone, as `simulator` on both
3610
+ * plugin APIs. The result's shape is the plugin's own: nothing between the two reads it, and the
3611
+ * plugin never imports its simulator.
3591
3612
  */
3592
- export declare interface KayServedSimulators {
3593
- /**
3594
- * What this plugin's simulator built for `adapterId`, or `undefined` when none was served for
3595
- * that id. The shape is the plugin's own simulator contract; narrow it before use.
3596
- */
3597
- get(adapterId: string): unknown;
3613
+ export declare type KayPluginSimulatorFactory = (options: KayPluginSimulatorOptions) => unknown;
3614
+
3615
+ /**
3616
+ * What the launcher of a simulated run (evals, dev, tests) gives a plugin's simulator: the folder
3617
+ * its worlds live under. The simulator picks its own folders inside it.
3618
+ */
3619
+ export declare interface KayPluginSimulatorOptions {
3620
+ readonly stateRoot: string;
3598
3621
  }
3599
3622
 
3600
3623
  /** Applies a KeyOf action to the given type. */
@@ -3747,6 +3770,15 @@ declare const LocalContributionId: z.ZodString;
3747
3770
 
3748
3771
  declare type LocalContributionId = z.infer<typeof LocalContributionId>;
3749
3772
 
3773
+ /** One provider account a credential reaches. */
3774
+ declare interface LookedUpAccount {
3775
+ readonly accountId: string;
3776
+ readonly label?: string;
3777
+ readonly identity?: AccountIdentity;
3778
+ /** Non-secret observations the host may surface without retaining credential material. */
3779
+ readonly capabilityChecks?: readonly ApiKeyCapabilityCheck[];
3780
+ }
3781
+
3750
3782
  /** Applies a Lowercase action to the given type. */
3751
3783
  declare function Lowercase_2<Type extends TSchema>(type: Type, options?: TSchemaOptions): TLowercase<Type>;
3752
3784
 
@@ -4821,13 +4853,21 @@ declare function Pick_2<Type extends TSchema, Indexer extends TSchema>(type: Typ
4821
4853
  declare function PickDeferred<Type extends TSchema, Indexer extends TSchema>(type: Type, indexer: Indexer, options?: TSchemaOptions): TPickDeferred<Type, Indexer>;
4822
4854
 
4823
4855
  /**
4824
- * How a plugin learns which provider account a fresh OAuth token belongs to: one account, or every
4825
- * account the grant reaches. Registered with `api.auth.registerAccountResolver`.
4856
+ * One provider account a credential reaches. A lookup almost always calls the provider's profile
4857
+ * endpoint to find `accountId`, so the identity fields are already in the response: return them
4858
+ * rather than flattening the person into `label`. `identity` is what lets the agent know the user's
4859
+ * handle or email for a connected service without asking.
4826
4860
  */
4827
- export declare interface PluginAccountResolver {
4828
- readonly resolveAccountId?: ResolvePluginAccountId;
4829
- readonly resolveAccounts?: ResolvePluginAccounts;
4830
- }
4861
+ export declare type PluginAccount = LookedUpAccount;
4862
+
4863
+ /**
4864
+ * Whose credential this is: every provider account it reaches, usually one. A bad credential throws.
4865
+ * Registered with `api.auth.registerAccountLookup`.
4866
+ */
4867
+ export declare type PluginAccountLookup = AccountLookup;
4868
+
4869
+ /** What an account lookup is asked about: a fresh credential, its fields, and a cancel signal. */
4870
+ export declare type PluginAccountLookupInput = AccountLookupInput;
4831
4871
 
4832
4872
  /** Per-call options every method accepts. No construction-time credentials (see module doc) - an
4833
4873
  * `Authorization`/`Api-Key`/etc header goes here, per call, after `withResolvedAuth` resolves it. */
@@ -5733,28 +5773,6 @@ declare type ResolveExternalCliResult = {
5733
5773
  readonly accounts?: readonly AuthAccount[];
5734
5774
  };
5735
5775
 
5736
- /**
5737
- * Derive a stable provider account id (and optional label) from a freshly connected access token,
5738
- * plus - when known - who the account belongs to.
5739
- *
5740
- * A resolver almost always calls the provider's profile endpoint to derive `accountId` at all, so
5741
- * the identity fields are already in the response: return them rather than flattening the person
5742
- * into `label`. Populating `identity` is what lets the agent know the user's handle/email for a
5743
- * connected service without asking.
5744
- */
5745
- export declare type ResolvePluginAccountId = (accessToken: string) => Promise<{
5746
- readonly accountId: string;
5747
- readonly label?: string;
5748
- readonly identity?: AccountIdentity;
5749
- }>;
5750
-
5751
- /** Enumerate every provider account a fresh OAuth grant powers. */
5752
- export declare type ResolvePluginAccounts = (accessToken: string) => Promise<readonly {
5753
- readonly accountId: string;
5754
- readonly label?: string;
5755
- readonly identity?: AccountIdentity;
5756
- }[]>;
5757
-
5758
5776
  declare interface ResolveTokenFailure {
5759
5777
  readonly ok: false;
5760
5778
  readonly reason: ResolveTokenFailureReason;
@@ -11688,30 +11706,6 @@ declare interface Usage {
11688
11706
  };
11689
11707
  }
11690
11708
 
11691
- /** Validate freshly-entered material and resolve the provider account before persistence. */
11692
- declare type ValidateApiKeyCredential = (input: ValidateApiKeyCredentialInput) => Promise<ValidateApiKeyCredentialResult>;
11693
-
11694
- declare interface ValidateApiKeyCredentialInput {
11695
- readonly accessToken: string;
11696
- /** Every declared field; empty for a classic single-secret scheme. */
11697
- readonly fields: Readonly<Record<string, string>>;
11698
- readonly signal: AbortSignal;
11699
- }
11700
-
11701
- declare interface ValidateApiKeyCredentialResult {
11702
- readonly accountId: string;
11703
- readonly label?: string;
11704
- readonly identity?: AccountIdentity;
11705
- /** Non-secret observations the host may surface without retaining credential material. */
11706
- readonly capabilityChecks?: readonly ApiKeyCapabilityCheck[];
11707
- }
11708
-
11709
- export declare type ValidatePluginApiKeyCredential = ValidateApiKeyCredential;
11710
-
11711
- export declare type ValidatePluginApiKeyCredentialInput = ValidateApiKeyCredentialInput;
11712
-
11713
- export declare type ValidatePluginApiKeyCredentialResult = ValidateApiKeyCredentialResult;
11714
-
11715
11709
  /**
11716
11710
  * ---
11717
11711
  * responsibility: The one interface through which a vendored-MCP plugin's code calls a tool on its
package/dist/kay-app.d.ts CHANGED
@@ -2618,8 +2618,23 @@ declare const KAY_PLUGIN_PROTOCOL_VERSION: "kay.plugin.v1";
2618
2618
  * hosted module's code and manifest must agree on it, and the daemon reads it to find an
2619
2619
  * external-CLI scheme without running the module. A module that runs in the daemon is unchanged,
2620
2620
  * so this is additive; a plugin whose manifest sets `authScheme` declares ^0.27.1.
2621
+ *
2622
+ * 0.28.0 makes "whose credential is this?" one call (#15714). `api.auth.registerAccountLookup`
2623
+ * replaces `registerValidator` and `registerAccountResolver`: it takes the credential, its fields and
2624
+ * a cancel signal, and returns every account the credential reaches. A manifest says `account:
2625
+ * "lookup"` on any `oauth2` or `api-key` scheme the plugin answers for, in place of `validates: true`
2626
+ * and the `"resolveAccountId"` and `"resolveAccounts"` values, and a `pkce` scheme on a client the
2627
+ * host holds may name one too. A plugin using a removed member or value stops loading until it is
2628
+ * rebuilt; a code search found none outside this repo. A plugin with a sign-in declares ^0.28.0. 0.26.3 and 0.27.1
2629
+ * stay served for a plugin that uses none of these.
2630
+ *
2631
+ * 0.29.0 replaces `servedSimulators` (`KayServedSimulators`, a lookup by adapter id) with
2632
+ * `simulator` on both targets (#14929): what the plugin's own simulator built, handed over once by
2633
+ * whichever process runs the plugin. A plugin's simulator file exports `createPluginSimulator`
2634
+ * (`KayPluginSimulatorFactory`). A clean break: only this repo's plugins read the old member, and
2635
+ * a plugin with no simulator is unaffected, so 0.28.0 stays served.
2621
2636
  */
2622
- declare const KAY_PLUGIN_SDK_VERSION: "0.27.1";
2637
+ declare const KAY_PLUGIN_SDK_VERSION: "0.29.0";
2623
2638
 
2624
2639
  declare const KAY_PLUGIN_TARGET_NAMES: readonly ["kay.agent", "kay.app", "kay.ui"];
2625
2640
 
@@ -5144,13 +5159,11 @@ export declare interface KayAppPluginApi {
5144
5159
  /** Exact-account credential resolution for declared background-job purposes. */
5145
5160
  readonly backgroundAuth?: KayAppBackgroundAuth;
5146
5161
  /**
5147
- * Optional: absent unless a simulating Bonsai daemon serves this plugin a simulator (SDK 0.18.1).
5148
- * A production daemon never does. In this version only plugins the release carries are served;
5149
- * any plugin may ship a `./simulator` later. The `kay.app` target reads the same simulators its
5150
- * `kay.agent` part does, so a background job runs on the simulator its URI target does. See
5151
- * {@link KayServedSimulators}.
5162
+ * What this plugin's own simulator built, in a simulated run only (SDK 0.29.0): absent in every
5163
+ * other. Its shape is the plugin's own, so narrow it before use. See
5164
+ * {@link KayPluginSimulatorFactory}.
5152
5165
  */
5153
- readonly servedSimulators?: KayServedSimulators;
5166
+ readonly simulator?: unknown;
5154
5167
  /**
5155
5168
  * Read and write this plugin's OWN manifest-declared config sections (value + provenance), and
5156
5169
  * observe changes. Present whenever the host has a config store and the plugin declares at least
@@ -8526,21 +8539,19 @@ declare const KayPluginProtocolVersion: z.ZodLiteral<"kay.plugin.v1">;
8526
8539
  declare type KayPluginProtocolVersion = z.infer<typeof KayPluginProtocolVersion>;
8527
8540
 
8528
8541
  /**
8529
- * The simulators a simulating Bonsai daemon (evals, dev, tests) serves this plugin, keyed by the
8530
- * adapter id its simulated URI connection rows name. The daemon builds each from the plugin's own
8531
- * dev-only `./simulator` subpath; the plugin never imports its simulator.
8532
- *
8533
- * The member that carries this, `servedSimulators` on both plugin APIs, is optional and absent
8534
- * unless a simulating daemon serves it. A production daemon never does, so treat absence as the
8535
- * normal case. In this version the daemon serves it only to plugins the release carries; the seam
8536
- * is not specific to them, and any plugin may ship a `./simulator` later.
8542
+ * What a plugin's dev-only simulator file exports as `createPluginSimulator`. Whichever process
8543
+ * runs the plugin calls it once and hands the result to that plugin alone, as `simulator` on both
8544
+ * plugin APIs. The result's shape is the plugin's own: nothing between the two reads it, and the
8545
+ * plugin never imports its simulator.
8537
8546
  */
8538
- export declare interface KayServedSimulators {
8539
- /**
8540
- * What this plugin's simulator built for `adapterId`, or `undefined` when none was served for
8541
- * that id. The shape is the plugin's own simulator contract; narrow it before use.
8542
- */
8543
- get(adapterId: string): unknown;
8547
+ export declare type KayPluginSimulatorFactory = (options: KayPluginSimulatorOptions) => unknown;
8548
+
8549
+ /**
8550
+ * What the launcher of a simulated run (evals, dev, tests) gives a plugin's simulator: the folder
8551
+ * its worlds live under. The simulator picks its own folders inside it.
8552
+ */
8553
+ export declare interface KayPluginSimulatorOptions {
8554
+ readonly stateRoot: string;
8544
8555
  }
8545
8556
 
8546
8557
  /** Applies a KeyOf action to the given type. */
@@ -0,0 +1,4 @@
1
+ /** Normalize underscores to hyphens; return undefined unless the result is a valid Agent Skills name (at most 64 characters). */
2
+ export declare function skillInstallTargetName(sourceName: string): string | undefined;
3
+
4
+ export { }
package/dist/skills.js ADDED
@@ -0,0 +1,12 @@
1
+ // packages/plugin-sdk/dist/skills.js
2
+ var AGENT_SKILL_NAME_PATTERN = /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/;
3
+ function skillInstallTargetName(sourceName) {
4
+ const targetName = sourceName.replace(/_+/g, "-");
5
+ if (targetName.length > 64 || targetName.includes("--") || !AGENT_SKILL_NAME_PATTERN.test(targetName)) {
6
+ return void 0;
7
+ }
8
+ return targetName;
9
+ }
10
+ export {
11
+ skillInstallTargetName
12
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yaklabs-ai/plugin-sdk",
3
- "version": "0.27.1",
3
+ "version": "0.29.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",
@@ -61,6 +61,10 @@
61
61
  "types": "./dist/whiteboard.d.ts",
62
62
  "default": "./dist/whiteboard.js"
63
63
  },
64
+ "./skills": {
65
+ "types": "./dist/skills.d.ts",
66
+ "default": "./dist/skills.js"
67
+ },
64
68
  "./transcript-review": {
65
69
  "types": "./dist/transcript-review.d.ts",
66
70
  "default": "./dist/transcript-review.js"