@yaklabs-ai/plugin-sdk 0.27.0 → 0.28.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.0"
16
+ "@bonsai/plugin-sdk": "npm:@yaklabs-ai/plugin-sdk@^0.28.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.0" },
65
+ "compatibility": { "sdk": "^0.28.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.0",
4
+ "version": "0.28.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
@@ -2312,8 +2326,23 @@ declare const KAY_PLUGIN_PROTOCOL_VERSION: "kay.plugin.v1";
2312
2326
  * `write`. `app.approvals`, its `prepare`, `finalize` and `resolveResource` are gone, and a write can
2313
2327
  * refuse in the person's words with `UriProviderError.refusalMessage`. No plugin outside this repo
2314
2328
  * declared a card, so 0.26.3 stays served. A plugin that declares a card declares ^0.27.0.
2329
+ *
2330
+ * 0.27.1 lets a manifest URI module name the exact sign-in scheme its calls use, as a tool can
2331
+ * (#14928): `authScheme`, a scheme of the module's `authService`, local or another plugin's. A
2332
+ * hosted module's code and manifest must agree on it, and the daemon reads it to find an
2333
+ * external-CLI scheme without running the module. A module that runs in the daemon is unchanged,
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.
2315
2344
  */
2316
- declare const KAY_PLUGIN_SDK_VERSION: "0.27.0";
2345
+ declare const KAY_PLUGIN_SDK_VERSION: "0.28.0";
2317
2346
 
2318
2347
  declare const KAY_PLUGIN_TARGET_NAMES: readonly ["kay.agent", "kay.app", "kay.ui"];
2319
2348
 
@@ -2691,16 +2720,12 @@ declare interface KayAgentPluginApi {
2691
2720
  */
2692
2721
  readonly auth: {
2693
2722
  /**
2694
- * The check for an `api-key` scheme the manifest marks `validates: true`. `serviceId` and
2695
- * `schemeId` are the manifest's global ids (`github.account`, `github.pat`).
2696
- */
2697
- registerValidator(serviceId: string, schemeId: string, validate: ValidatePluginApiKeyCredential): void;
2698
- /**
2699
- * The account lookup for an `oauth2` scheme whose manifest names it as where the account comes
2700
- * from (`account: "resolveAccountId"` or `"resolveAccounts"`), registering that function only.
2701
- * Refused on any other scheme.
2723
+ * Whose credential this is, for a scheme whose manifest says `account: "lookup"`. `serviceId` and
2724
+ * `schemeId` are the manifest's global ids (`github.account`, `github.pat`). On an `api-key`
2725
+ * scheme it also checks the key before it is saved, and must name exactly one account. Refused
2726
+ * on any other scheme.
2702
2727
  */
2703
- registerAccountResolver(serviceId: string, schemeId: string, resolver: PluginAccountResolver): void;
2728
+ registerAccountLookup(serviceId: string, schemeId: string, lookup: PluginAccountLookup): void;
2704
2729
  /**
2705
2730
  * Declare a delegated scheme (plugin-provided connect/refresh over opaque material) for a
2706
2731
  * service. The host maps it onto the kernel's `DelegatedAuthScheme` and drives its `connect`
@@ -3324,6 +3349,15 @@ declare const LocalContributionId: z.ZodString;
3324
3349
 
3325
3350
  declare type LocalContributionId = z.infer<typeof LocalContributionId>;
3326
3351
 
3352
+ /** One provider account a credential reaches. */
3353
+ declare interface LookedUpAccount {
3354
+ readonly accountId: string;
3355
+ readonly label?: string;
3356
+ readonly identity?: AccountIdentity;
3357
+ /** Non-secret observations the host may surface without retaining credential material. */
3358
+ readonly capabilityChecks?: readonly ApiKeyCapabilityCheck[];
3359
+ }
3360
+
3327
3361
  /** Applies a Lowercase action to the given type. */
3328
3362
  declare function Lowercase_2<Type extends TSchema>(type: Type, options?: TSchemaOptions): TLowercase<Type>;
3329
3363
 
@@ -4178,13 +4212,10 @@ export declare const PLUGIN_DISCLOSURE_CONTRACT = 2;
4178
4212
  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"];
4179
4213
 
4180
4214
  /**
4181
- * How a plugin learns which provider account a fresh OAuth token belongs to: one account, or every
4182
- * account the grant reaches. Registered with `api.auth.registerAccountResolver`.
4215
+ * Whose credential this is: every provider account it reaches, usually one. A bad credential throws.
4216
+ * Registered with `api.auth.registerAccountLookup`.
4183
4217
  */
4184
- declare interface PluginAccountResolver {
4185
- readonly resolveAccountId?: ResolvePluginAccountId;
4186
- readonly resolveAccounts?: ResolvePluginAccounts;
4187
- }
4218
+ declare type PluginAccountLookup = AccountLookup;
4188
4219
 
4189
4220
  /** The kinds of capability a plugin service can advertise (mirrors the host capability taxonomy). */
4190
4221
  declare type PluginCapabilityKind = "uri-module" | "tool" | "search-provider";
@@ -4645,28 +4676,6 @@ declare interface ResolvedCredential {
4645
4676
  readonly fields?: Readonly<Record<string, string>>;
4646
4677
  }
4647
4678
 
4648
- /**
4649
- * Derive a stable provider account id (and optional label) from a freshly connected access token,
4650
- * plus - when known - who the account belongs to.
4651
- *
4652
- * A resolver almost always calls the provider's profile endpoint to derive `accountId` at all, so
4653
- * the identity fields are already in the response: return them rather than flattening the person
4654
- * into `label`. Populating `identity` is what lets the agent know the user's handle/email for a
4655
- * connected service without asking.
4656
- */
4657
- declare type ResolvePluginAccountId = (accessToken: string) => Promise<{
4658
- readonly accountId: string;
4659
- readonly label?: string;
4660
- readonly identity?: AccountIdentity;
4661
- }>;
4662
-
4663
- /** Enumerate every provider account a fresh OAuth grant powers. */
4664
- declare type ResolvePluginAccounts = (accessToken: string) => Promise<readonly {
4665
- readonly accountId: string;
4666
- readonly label?: string;
4667
- readonly identity?: AccountIdentity;
4668
- }[]>;
4669
-
4670
4679
  /** Match remaining characters in the buffer until end. If no characters are in buffer, no match */
4671
4680
  declare function Rest<Input extends string>(input: Input): TRest<Input>;
4672
4681
 
@@ -10207,26 +10216,6 @@ declare interface Usage {
10207
10216
  };
10208
10217
  }
10209
10218
 
10210
- /** Validate freshly-entered material and resolve the provider account before persistence. */
10211
- declare type ValidateApiKeyCredential = (input: ValidateApiKeyCredentialInput) => Promise<ValidateApiKeyCredentialResult>;
10212
-
10213
- declare interface ValidateApiKeyCredentialInput {
10214
- readonly accessToken: string;
10215
- /** Every declared field; empty for a classic single-secret scheme. */
10216
- readonly fields: Readonly<Record<string, string>>;
10217
- readonly signal: AbortSignal;
10218
- }
10219
-
10220
- declare interface ValidateApiKeyCredentialResult {
10221
- readonly accountId: string;
10222
- readonly label?: string;
10223
- readonly identity?: AccountIdentity;
10224
- /** Non-secret observations the host may surface without retaining credential material. */
10225
- readonly capabilityChecks?: readonly ApiKeyCapabilityCheck[];
10226
- }
10227
-
10228
- declare type ValidatePluginApiKeyCredential = ValidateApiKeyCredential;
10229
-
10230
10219
  /**
10231
10220
  * ---
10232
10221
  * 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
@@ -2366,8 +2380,23 @@ declare const KAY_PLUGIN_PROTOCOL_VERSION: "kay.plugin.v1";
2366
2380
  * `write`. `app.approvals`, its `prepare`, `finalize` and `resolveResource` are gone, and a write can
2367
2381
  * refuse in the person's words with `UriProviderError.refusalMessage`. No plugin outside this repo
2368
2382
  * declared a card, so 0.26.3 stays served. A plugin that declares a card declares ^0.27.0.
2383
+ *
2384
+ * 0.27.1 lets a manifest URI module name the exact sign-in scheme its calls use, as a tool can
2385
+ * (#14928): `authScheme`, a scheme of the module's `authService`, local or another plugin's. A
2386
+ * hosted module's code and manifest must agree on it, and the daemon reads it to find an
2387
+ * external-CLI scheme without running the module. A module that runs in the daemon is unchanged,
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.
2369
2398
  */
2370
- declare const KAY_PLUGIN_SDK_VERSION: "0.27.0";
2399
+ declare const KAY_PLUGIN_SDK_VERSION: "0.28.0";
2371
2400
 
2372
2401
  declare const KAY_PLUGIN_TARGET_NAMES: readonly ["kay.agent", "kay.app", "kay.ui"];
2373
2402
 
@@ -2742,16 +2771,12 @@ declare interface KayAgentPluginApi {
2742
2771
  */
2743
2772
  readonly auth: {
2744
2773
  /**
2745
- * The check for an `api-key` scheme the manifest marks `validates: true`. `serviceId` and
2746
- * `schemeId` are the manifest's global ids (`github.account`, `github.pat`).
2747
- */
2748
- registerValidator(serviceId: string, schemeId: string, validate: ValidatePluginApiKeyCredential): void;
2749
- /**
2750
- * The account lookup for an `oauth2` scheme whose manifest names it as where the account comes
2751
- * from (`account: "resolveAccountId"` or `"resolveAccounts"`), registering that function only.
2752
- * Refused on any other scheme.
2774
+ * Whose credential this is, for a scheme whose manifest says `account: "lookup"`. `serviceId` and
2775
+ * `schemeId` are the manifest's global ids (`github.account`, `github.pat`). On an `api-key`
2776
+ * scheme it also checks the key before it is saved, and must name exactly one account. Refused
2777
+ * on any other scheme.
2753
2778
  */
2754
- registerAccountResolver(serviceId: string, schemeId: string, resolver: PluginAccountResolver): void;
2779
+ registerAccountLookup(serviceId: string, schemeId: string, lookup: PluginAccountLookup): void;
2755
2780
  /**
2756
2781
  * Declare a delegated scheme (plugin-provided connect/refresh over opaque material) for a
2757
2782
  * service. The host maps it onto the kernel's `DelegatedAuthScheme` and drives its `connect`
@@ -3375,6 +3400,15 @@ declare const LocalContributionId: z.ZodString;
3375
3400
 
3376
3401
  declare type LocalContributionId = z.infer<typeof LocalContributionId>;
3377
3402
 
3403
+ /** One provider account a credential reaches. */
3404
+ declare interface LookedUpAccount {
3405
+ readonly accountId: string;
3406
+ readonly label?: string;
3407
+ readonly identity?: AccountIdentity;
3408
+ /** Non-secret observations the host may surface without retaining credential material. */
3409
+ readonly capabilityChecks?: readonly ApiKeyCapabilityCheck[];
3410
+ }
3411
+
3378
3412
  /** Applies a Lowercase action to the given type. */
3379
3413
  declare function Lowercase_2<Type extends TSchema>(type: Type, options?: TSchemaOptions): TLowercase<Type>;
3380
3414
 
@@ -4196,13 +4230,10 @@ declare function Pick_2<Type extends TSchema, Indexer extends TSchema>(type: Typ
4196
4230
  declare function PickDeferred<Type extends TSchema, Indexer extends TSchema>(type: Type, indexer: Indexer, options?: TSchemaOptions): TPickDeferred<Type, Indexer>;
4197
4231
 
4198
4232
  /**
4199
- * How a plugin learns which provider account a fresh OAuth token belongs to: one account, or every
4200
- * account the grant reaches. Registered with `api.auth.registerAccountResolver`.
4233
+ * Whose credential this is: every provider account it reaches, usually one. A bad credential throws.
4234
+ * Registered with `api.auth.registerAccountLookup`.
4201
4235
  */
4202
- declare interface PluginAccountResolver {
4203
- readonly resolveAccountId?: ResolvePluginAccountId;
4204
- readonly resolveAccounts?: ResolvePluginAccounts;
4205
- }
4236
+ declare type PluginAccountLookup = AccountLookup;
4206
4237
 
4207
4238
  /** The kinds of capability a plugin service can advertise (mirrors the host capability taxonomy). */
4208
4239
  declare type PluginCapabilityKind = "uri-module" | "tool" | "search-provider";
@@ -4757,10 +4788,7 @@ declare const ResolvedPluginContractV1: z.ZodObject<{
4757
4788
  }>>;
4758
4789
  clientId: z.ZodOptional<z.ZodString>;
4759
4790
  clientSecret: z.ZodOptional<z.ZodString>;
4760
- account: z.ZodOptional<z.ZodEnum<{
4761
- resolveAccountId: "resolveAccountId";
4762
- resolveAccounts: "resolveAccounts";
4763
- }>>;
4791
+ account: z.ZodOptional<z.ZodLiteral<"lookup">>;
4764
4792
  localId: z.ZodString;
4765
4793
  globalId: z.ZodString;
4766
4794
  kind: z.ZodLiteral<"oauth2">;
@@ -4789,8 +4817,7 @@ declare const ResolvedPluginContractV1: z.ZodObject<{
4789
4817
  exchange: z.ZodLiteral<"confidential">;
4790
4818
  clientSuppliers: z.ZodTuple<[z.ZodLiteral<"kay">], null>;
4791
4819
  account: z.ZodEnum<{
4792
- resolveAccountId: "resolveAccountId";
4793
- resolveAccounts: "resolveAccounts";
4820
+ lookup: "lookup";
4794
4821
  "sign-in": "sign-in";
4795
4822
  }>;
4796
4823
  localId: z.ZodString;
@@ -4831,7 +4858,7 @@ declare const ResolvedPluginContractV1: z.ZodObject<{
4831
4858
  instructions: z.ZodString;
4832
4859
  url: z.ZodURL;
4833
4860
  }, z.core.$strict>>;
4834
- validates: z.ZodOptional<z.ZodLiteral<true>>;
4861
+ account: z.ZodOptional<z.ZodLiteral<"lookup">>;
4835
4862
  displayName: z.ZodOptional<z.ZodString>;
4836
4863
  agentHint: z.ZodOptional<z.ZodString>;
4837
4864
  summary: z.ZodOptional<z.ZodString>;
@@ -5366,6 +5393,7 @@ declare const ResolvedPluginContractV1: z.ZodObject<{
5366
5393
  schemes: z.ZodArray<z.ZodString>;
5367
5394
  displayName: z.ZodOptional<z.ZodString>;
5368
5395
  authServiceId: z.ZodOptional<z.ZodString>;
5396
+ authSchemeId: z.ZodOptional<z.ZodString>;
5369
5397
  knownResources: z.ZodOptional<z.ZodLiteral<true>>;
5370
5398
  describesOperations: z.ZodOptional<z.ZodLiteral<true>>;
5371
5399
  }, z.core.$strict>>>;
@@ -5680,28 +5708,6 @@ declare type ResolveExternalCliResult = {
5680
5708
  readonly accounts?: readonly AuthAccount[];
5681
5709
  };
5682
5710
 
5683
- /**
5684
- * Derive a stable provider account id (and optional label) from a freshly connected access token,
5685
- * plus - when known - who the account belongs to.
5686
- *
5687
- * A resolver almost always calls the provider's profile endpoint to derive `accountId` at all, so
5688
- * the identity fields are already in the response: return them rather than flattening the person
5689
- * into `label`. Populating `identity` is what lets the agent know the user's handle/email for a
5690
- * connected service without asking.
5691
- */
5692
- declare type ResolvePluginAccountId = (accessToken: string) => Promise<{
5693
- readonly accountId: string;
5694
- readonly label?: string;
5695
- readonly identity?: AccountIdentity;
5696
- }>;
5697
-
5698
- /** Enumerate every provider account a fresh OAuth grant powers. */
5699
- declare type ResolvePluginAccounts = (accessToken: string) => Promise<readonly {
5700
- readonly accountId: string;
5701
- readonly label?: string;
5702
- readonly identity?: AccountIdentity;
5703
- }[]>;
5704
-
5705
5711
  declare interface ResolveTokenFailure {
5706
5712
  readonly ok: false;
5707
5713
  readonly reason: ResolveTokenFailureReason;
@@ -11273,26 +11279,6 @@ declare interface Usage {
11273
11279
  };
11274
11280
  }
11275
11281
 
11276
- /** Validate freshly-entered material and resolve the provider account before persistence. */
11277
- declare type ValidateApiKeyCredential = (input: ValidateApiKeyCredentialInput) => Promise<ValidateApiKeyCredentialResult>;
11278
-
11279
- declare interface ValidateApiKeyCredentialInput {
11280
- readonly accessToken: string;
11281
- /** Every declared field; empty for a classic single-secret scheme. */
11282
- readonly fields: Readonly<Record<string, string>>;
11283
- readonly signal: AbortSignal;
11284
- }
11285
-
11286
- declare interface ValidateApiKeyCredentialResult {
11287
- readonly accountId: string;
11288
- readonly label?: string;
11289
- readonly identity?: AccountIdentity;
11290
- /** Non-secret observations the host may surface without retaining credential material. */
11291
- readonly capabilityChecks?: readonly ApiKeyCapabilityCheck[];
11292
- }
11293
-
11294
- declare type ValidatePluginApiKeyCredential = ValidateApiKeyCredential;
11295
-
11296
11282
  /**
11297
11283
  * ---
11298
11284
  * 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
@@ -2641,8 +2655,23 @@ declare const KAY_PLUGIN_PROTOCOL_VERSION: "kay.plugin.v1";
2641
2655
  * `write`. `app.approvals`, its `prepare`, `finalize` and `resolveResource` are gone, and a write can
2642
2656
  * refuse in the person's words with `UriProviderError.refusalMessage`. No plugin outside this repo
2643
2657
  * declared a card, so 0.26.3 stays served. A plugin that declares a card declares ^0.27.0.
2658
+ *
2659
+ * 0.27.1 lets a manifest URI module name the exact sign-in scheme its calls use, as a tool can
2660
+ * (#14928): `authScheme`, a scheme of the module's `authService`, local or another plugin's. A
2661
+ * hosted module's code and manifest must agree on it, and the daemon reads it to find an
2662
+ * external-CLI scheme without running the module. A module that runs in the daemon is unchanged,
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.
2644
2673
  */
2645
- declare const KAY_PLUGIN_SDK_VERSION: "0.27.0";
2674
+ declare const KAY_PLUGIN_SDK_VERSION: "0.28.0";
2646
2675
 
2647
2676
  declare const KAY_PLUGIN_TARGET_NAMES: readonly ["kay.agent", "kay.app", "kay.ui"];
2648
2677
 
@@ -3049,16 +3078,12 @@ export declare interface KayAgentPluginApi {
3049
3078
  */
3050
3079
  readonly auth: {
3051
3080
  /**
3052
- * The check for an `api-key` scheme the manifest marks `validates: true`. `serviceId` and
3053
- * `schemeId` are the manifest's global ids (`github.account`, `github.pat`).
3081
+ * Whose credential this is, for a scheme whose manifest says `account: "lookup"`. `serviceId` and
3082
+ * `schemeId` are the manifest's global ids (`github.account`, `github.pat`). On an `api-key`
3083
+ * scheme it also checks the key before it is saved, and must name exactly one account. Refused
3084
+ * on any other scheme.
3054
3085
  */
3055
- registerValidator(serviceId: string, schemeId: string, validate: ValidatePluginApiKeyCredential): void;
3056
- /**
3057
- * The account lookup for an `oauth2` scheme whose manifest names it as where the account comes
3058
- * from (`account: "resolveAccountId"` or `"resolveAccounts"`), registering that function only.
3059
- * Refused on any other scheme.
3060
- */
3061
- registerAccountResolver(serviceId: string, schemeId: string, resolver: PluginAccountResolver): void;
3086
+ registerAccountLookup(serviceId: string, schemeId: string, lookup: PluginAccountLookup): void;
3062
3087
  /**
3063
3088
  * Declare a delegated scheme (plugin-provided connect/refresh over opaque material) for a
3064
3089
  * service. The host maps it onto the kernel's `DelegatedAuthScheme` and drives its `connect`
@@ -3741,6 +3766,15 @@ declare const LocalContributionId: z.ZodString;
3741
3766
 
3742
3767
  declare type LocalContributionId = z.infer<typeof LocalContributionId>;
3743
3768
 
3769
+ /** One provider account a credential reaches. */
3770
+ declare interface LookedUpAccount {
3771
+ readonly accountId: string;
3772
+ readonly label?: string;
3773
+ readonly identity?: AccountIdentity;
3774
+ /** Non-secret observations the host may surface without retaining credential material. */
3775
+ readonly capabilityChecks?: readonly ApiKeyCapabilityCheck[];
3776
+ }
3777
+
3744
3778
  /** Applies a Lowercase action to the given type. */
3745
3779
  declare function Lowercase_2<Type extends TSchema>(type: Type, options?: TSchemaOptions): TLowercase<Type>;
3746
3780
 
@@ -4815,13 +4849,21 @@ declare function Pick_2<Type extends TSchema, Indexer extends TSchema>(type: Typ
4815
4849
  declare function PickDeferred<Type extends TSchema, Indexer extends TSchema>(type: Type, indexer: Indexer, options?: TSchemaOptions): TPickDeferred<Type, Indexer>;
4816
4850
 
4817
4851
  /**
4818
- * How a plugin learns which provider account a fresh OAuth token belongs to: one account, or every
4819
- * account the grant reaches. Registered with `api.auth.registerAccountResolver`.
4852
+ * One provider account a credential reaches. A lookup almost always calls the provider's profile
4853
+ * endpoint to find `accountId`, so the identity fields are already in the response: return them
4854
+ * rather than flattening the person into `label`. `identity` is what lets the agent know the user's
4855
+ * handle or email for a connected service without asking.
4820
4856
  */
4821
- export declare interface PluginAccountResolver {
4822
- readonly resolveAccountId?: ResolvePluginAccountId;
4823
- readonly resolveAccounts?: ResolvePluginAccounts;
4824
- }
4857
+ export declare type PluginAccount = LookedUpAccount;
4858
+
4859
+ /**
4860
+ * Whose credential this is: every provider account it reaches, usually one. A bad credential throws.
4861
+ * Registered with `api.auth.registerAccountLookup`.
4862
+ */
4863
+ export declare type PluginAccountLookup = AccountLookup;
4864
+
4865
+ /** What an account lookup is asked about: a fresh credential, its fields, and a cancel signal. */
4866
+ export declare type PluginAccountLookupInput = AccountLookupInput;
4825
4867
 
4826
4868
  /** Per-call options every method accepts. No construction-time credentials (see module doc) - an
4827
4869
  * `Authorization`/`Api-Key`/etc header goes here, per call, after `withResolvedAuth` resolves it. */
@@ -5727,28 +5769,6 @@ declare type ResolveExternalCliResult = {
5727
5769
  readonly accounts?: readonly AuthAccount[];
5728
5770
  };
5729
5771
 
5730
- /**
5731
- * Derive a stable provider account id (and optional label) from a freshly connected access token,
5732
- * plus - when known - who the account belongs to.
5733
- *
5734
- * A resolver almost always calls the provider's profile endpoint to derive `accountId` at all, so
5735
- * the identity fields are already in the response: return them rather than flattening the person
5736
- * into `label`. Populating `identity` is what lets the agent know the user's handle/email for a
5737
- * connected service without asking.
5738
- */
5739
- export declare type ResolvePluginAccountId = (accessToken: string) => Promise<{
5740
- readonly accountId: string;
5741
- readonly label?: string;
5742
- readonly identity?: AccountIdentity;
5743
- }>;
5744
-
5745
- /** Enumerate every provider account a fresh OAuth grant powers. */
5746
- export declare type ResolvePluginAccounts = (accessToken: string) => Promise<readonly {
5747
- readonly accountId: string;
5748
- readonly label?: string;
5749
- readonly identity?: AccountIdentity;
5750
- }[]>;
5751
-
5752
5772
  declare interface ResolveTokenFailure {
5753
5773
  readonly ok: false;
5754
5774
  readonly reason: ResolveTokenFailureReason;
@@ -11682,30 +11702,6 @@ declare interface Usage {
11682
11702
  };
11683
11703
  }
11684
11704
 
11685
- /** Validate freshly-entered material and resolve the provider account before persistence. */
11686
- declare type ValidateApiKeyCredential = (input: ValidateApiKeyCredentialInput) => Promise<ValidateApiKeyCredentialResult>;
11687
-
11688
- declare interface ValidateApiKeyCredentialInput {
11689
- readonly accessToken: string;
11690
- /** Every declared field; empty for a classic single-secret scheme. */
11691
- readonly fields: Readonly<Record<string, string>>;
11692
- readonly signal: AbortSignal;
11693
- }
11694
-
11695
- declare interface ValidateApiKeyCredentialResult {
11696
- readonly accountId: string;
11697
- readonly label?: string;
11698
- readonly identity?: AccountIdentity;
11699
- /** Non-secret observations the host may surface without retaining credential material. */
11700
- readonly capabilityChecks?: readonly ApiKeyCapabilityCheck[];
11701
- }
11702
-
11703
- export declare type ValidatePluginApiKeyCredential = ValidateApiKeyCredential;
11704
-
11705
- export declare type ValidatePluginApiKeyCredentialInput = ValidateApiKeyCredentialInput;
11706
-
11707
- export declare type ValidatePluginApiKeyCredentialResult = ValidateApiKeyCredentialResult;
11708
-
11709
11705
  /**
11710
11706
  * ---
11711
11707
  * responsibility: The one interface through which a vendored-MCP plugin's code calls a tool on its
package/dist/kay-app.d.ts CHANGED
@@ -2612,8 +2612,23 @@ declare const KAY_PLUGIN_PROTOCOL_VERSION: "kay.plugin.v1";
2612
2612
  * `write`. `app.approvals`, its `prepare`, `finalize` and `resolveResource` are gone, and a write can
2613
2613
  * refuse in the person's words with `UriProviderError.refusalMessage`. No plugin outside this repo
2614
2614
  * declared a card, so 0.26.3 stays served. A plugin that declares a card declares ^0.27.0.
2615
+ *
2616
+ * 0.27.1 lets a manifest URI module name the exact sign-in scheme its calls use, as a tool can
2617
+ * (#14928): `authScheme`, a scheme of the module's `authService`, local or another plugin's. A
2618
+ * hosted module's code and manifest must agree on it, and the daemon reads it to find an
2619
+ * external-CLI scheme without running the module. A module that runs in the daemon is unchanged,
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.
2615
2630
  */
2616
- declare const KAY_PLUGIN_SDK_VERSION: "0.27.0";
2631
+ declare const KAY_PLUGIN_SDK_VERSION: "0.28.0";
2617
2632
 
2618
2633
  declare const KAY_PLUGIN_TARGET_NAMES: readonly ["kay.agent", "kay.app", "kay.ui"];
2619
2634
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yaklabs-ai/plugin-sdk",
3
- "version": "0.27.0",
3
+ "version": "0.28.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",