@yaklabs-ai/plugin-sdk 0.15.3 → 0.26.3

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.
@@ -1,7 +1,7 @@
1
1
  import { z } from 'zod';
2
2
 
3
3
  /**
4
- * Who a connected account *belongs to* — the human, as the provider reports them. Derived at connect
4
+ * Who a connected account *belongs to* - the human, as the provider reports them. Derived at connect
5
5
  * time by a scheme's `resolveAccountId` hook from the provider's own profile endpoint, and surfaced
6
6
  * to the agent so it never has to ask "what is your email?" for a service the user already
7
7
  * connected.
@@ -9,7 +9,7 @@ import { z } from 'zod';
9
9
  * Distinct from {@link AccountProvenance}: an account can be firmly identified
10
10
  * (`externalId`/`provider`) while nothing is known about its owner, and a workspace's name is not a
11
11
  * person's name. Field-for-field the same shape the credential authority persists, so identity
12
- * crosses the daemon⇄kernel boundary without a lossy projection.
12
+ * crosses the daemon<->kernel boundary without a lossy projection.
13
13
  */
14
14
  declare interface AccountIdentity {
15
15
  /** Provider handle (GitHub `login`, Slack `user`). */
@@ -28,7 +28,7 @@ declare interface AccountIdentity {
28
28
  /**
29
29
  * Provider-native session id claim (WorkOS's `sid`), needed to call the provider's own
30
30
  * session-revocation endpoint at sign-out (`POST /user_management/sessions/revoke`, not yet
31
- * wired — see `docs/kay-account-auth.md`'s "Sign-out guarantee" section). Only Bonsai's WorkOS
31
+ * wired - see `docs/kay-account-auth.md`'s "Sign-out guarantee" section). Only Bonsai's WorkOS
32
32
  * product-account exchange/refresh sets it; every other provider leaves it absent.
33
33
  */
34
34
  readonly providerSessionId?: string;
@@ -36,7 +36,7 @@ declare interface AccountIdentity {
36
36
 
37
37
  /**
38
38
  * Structured, non-secret *provenance* for a connected account: which record on the provider's side
39
- * this credential points at. Says nothing about the human — a Notion `displayName` here is the
39
+ * this credential points at. Says nothing about the human - a Notion `displayName` here is the
40
40
  * workspace name, a Slack one is the team name. To describe the person, see {@link AccountIdentity}.
41
41
  */
42
42
  declare interface AccountProvenance {
@@ -50,6 +50,17 @@ declare interface AccountProvenance {
50
50
  readonly raw?: Readonly<Record<string, unknown>>;
51
51
  }
52
52
 
53
+ declare const AdapterPlacement: z.ZodEnum<{
54
+ "local-only": "local-only";
55
+ anywhere: "anywhere";
56
+ }>;
57
+
58
+ declare type AdapterPlacement = z.infer<typeof AdapterPlacement>;
59
+
60
+ declare const AdapterSelectionKey: z.ZodString;
61
+
62
+ declare type AdapterSelectionKey = z.infer<typeof AdapterSelectionKey>;
63
+
53
64
  /** Applies an AddImmutable action to a type. */
54
65
  declare function AddImmutable<Type extends TSchema>(type: Type, options?: TSchemaOptions): TAddImmutable<Type>;
55
66
 
@@ -146,21 +157,6 @@ declare function Any(options?: TSchemaOptions): TAny;
146
157
 
147
158
  declare type Api = KnownApi | (string & {});
148
159
 
149
- /** One labeled secret input of a multi-field api-key scheme. */
150
- declare interface ApiKeyAuthSchemeField {
151
- /** Stable key — the `fields` Record key on the stored material and resolved credential. */
152
- readonly id: string;
153
- /** Per-field prompt copy, e.g. "Access Client ID". */
154
- readonly label: string;
155
- }
156
-
157
- /** Provider-owned instructions for creating a credential outside Bonsai. */
158
- declare interface ApiKeyAuthSchemeSetup {
159
- readonly instructions: string;
160
- /** Absolute HTTPS page where the user can create or manage the credential. */
161
- readonly url: string;
162
- }
163
-
164
160
  /** One non-secret capability observation made while validating a credential. */
165
161
  declare interface ApiKeyCapabilityCheck {
166
162
  /** Stable service capability id the scheme checked. */
@@ -178,13 +174,17 @@ declare function _Array_<Type extends TSchema>(items: Type, options?: TArrayOpti
178
174
  /** Extracts options from a TArray. */
179
175
  declare function ArrayOptions(type: TArray): TArrayOptions;
180
176
 
177
+ declare const ArtifactGenerationId: z.core.$ZodBranded<z.ZodString, "ArtifactGenerationId", "out">;
178
+
179
+ declare type ArtifactGenerationId = z.infer<typeof ArtifactGenerationId>;
180
+
181
181
  /**
182
182
  * Performs an Object assign using the Left and Right object types. We track this operation as it
183
183
  * creates a new GC handle per assignment.
184
184
  */
185
185
  declare function Assign<Left extends ObjectLike, Right extends ObjectLike>(left: Left, right: Right): TAssign<Left, Right>;
186
186
 
187
- /** A connected account under one `(serviceId, schemeId)` — the multi-account unit. */
187
+ /** A connected account under one `(serviceId, schemeId)` - the multi-account unit. */
188
188
  declare interface AuthAccount {
189
189
  readonly accountId: string;
190
190
  readonly displayName: string;
@@ -199,12 +199,66 @@ declare interface AuthAccount {
199
199
  /**
200
200
  * Trust-lost marker carried through from `StoredCredentialSummary.needsReconnect`
201
201
  * (kay#7852): the account's credential is dead (revoked or terminally unrefreshable) and the
202
- * user must reconnect it. The account stays listed — with this flag — so the agent can see it
202
+ * user must reconnect it. The account stays listed - with this flag - so the agent can see it
203
203
  * and point the user at a reconnect; token resolution for it still fails closed.
204
204
  */
205
205
  readonly needsReconnect?: boolean;
206
206
  }
207
207
 
208
+ declare namespace authoringCommonSchemas {
209
+ export {
210
+ hostWithinDomain,
211
+ urlHostWithinDomain,
212
+ refineWebSessionScopeConfined,
213
+ KAY_PLUGIN_PROTOCOL_VERSION,
214
+ KAY_PLUGIN_PROTOCOL_PACKAGE_NAME,
215
+ KAY_PLUGIN_SDK_VERSION,
216
+ KAY_PLUGIN_COMPATIBLE_SDK_VERSIONS,
217
+ KAY_PLUGIN_TARGET_NAMES,
218
+ KayPluginProtocolVersion,
219
+ PluginTargetName,
220
+ KAY_EVENT_PUBLISHER_ID,
221
+ NonEmptyString,
222
+ PluginId,
223
+ PluginNamespace,
224
+ LocalContributionId,
225
+ GlobalContributionId,
226
+ PluginToolName,
227
+ AuthServiceReference,
228
+ AuthSchemeReference,
229
+ AdapterSelectionKey,
230
+ AdapterPlacement,
231
+ UriScheme,
232
+ MimeTypeString,
233
+ FileExtensionToken,
234
+ CliBinaryName,
235
+ CliAuthEnvVarName,
236
+ PackageAssetPath,
237
+ PluginSourceClass,
238
+ ArtifactGenerationId,
239
+ HttpsUrl,
240
+ RegistrableDomain,
241
+ GitHostName,
242
+ GitBasicAuthUser,
243
+ HttpStatusCode,
244
+ SignedInStatusCode,
245
+ JsonPointer,
246
+ TargetEntrypoint,
247
+ canonicalCommonSchemas,
248
+ JsonObject,
249
+ JsonSchema_2 as JsonSchema,
250
+ JsonValue_2 as JsonValue
251
+ }
252
+ }
253
+
254
+ declare const AuthSchemeReference: z.ZodString;
255
+
256
+ declare type AuthSchemeReference = z.infer<typeof AuthSchemeReference>;
257
+
258
+ declare const AuthServiceReference: z.ZodString;
259
+
260
+ declare type AuthServiceReference = z.infer<typeof AuthServiceReference>;
261
+
208
262
  declare interface Availability {
209
263
  readonly available: boolean;
210
264
  readonly reason?: string;
@@ -256,7 +310,7 @@ declare type BackgroundTaskRun = (ctx: BackgroundTaskRunContext) => Promise<stri
256
310
  declare interface BackgroundTaskRunContext {
257
311
  readonly taskId: string;
258
312
  readonly signal: AbortSignal;
259
- /** `this: void` — task bodies destructure this reporter off the context. */
313
+ /** `this: void` - task bodies destructure this reporter off the context. */
260
314
  reportProgress(this: void, text: string, details?: Record<string, unknown>): void;
261
315
  }
262
316
 
@@ -320,6 +374,47 @@ declare function Call<Target extends TSchema, Arguments extends TSchema[]>(targe
320
374
 
321
375
  declare function CallConstruct<Target extends TSchema, Arguments extends TSchema[]>(target: Target, arguments_: [...Arguments]): TCallConstruct<Target, Arguments>;
322
376
 
377
+ declare const canonicalCommonSchemas: {
378
+ NonEmptyString: z.ZodString;
379
+ PluginId: z.ZodString;
380
+ PluginNamespace: z.ZodString;
381
+ LocalContributionId: z.ZodString;
382
+ GlobalContributionId: z.ZodString;
383
+ PluginToolName: z.ZodString;
384
+ AuthServiceReference: z.ZodString;
385
+ AuthSchemeReference: z.ZodString;
386
+ AdapterSelectionKey: z.ZodString;
387
+ AdapterPlacement: z.ZodEnum<{
388
+ "local-only": "local-only";
389
+ anywhere: "anywhere";
390
+ }>;
391
+ UriScheme: z.ZodString;
392
+ MimeTypeString: z.ZodString;
393
+ FileExtensionToken: z.ZodString;
394
+ CliBinaryName: z.ZodString;
395
+ CliAuthEnvVarName: z.ZodString;
396
+ PackageAssetPath: z.ZodString;
397
+ PluginSourceClass: z.ZodEnum<{
398
+ bundled: "bundled";
399
+ "org-shared": "org-shared";
400
+ "user-local": "user-local";
401
+ "verified-marketplace": "verified-marketplace";
402
+ freeform: "freeform";
403
+ }>;
404
+ ArtifactGenerationId: z.core.$ZodBranded<z.ZodString, "ArtifactGenerationId", "out">;
405
+ HttpsUrl: z.ZodURL;
406
+ RegistrableDomain: z.ZodString;
407
+ GitHostName: z.ZodString;
408
+ GitBasicAuthUser: z.ZodString;
409
+ HttpStatusCode: z.ZodNumber;
410
+ SignedInStatusCode: z.ZodNumber;
411
+ JsonPointer: z.ZodString;
412
+ TargetEntrypoint: z.ZodObject<{
413
+ module: z.ZodString;
414
+ export: z.ZodOptional<z.ZodString>;
415
+ }, z.core.$strict>;
416
+ };
417
+
323
418
  /** Applies a Capitalize action to the given type. */
324
419
  declare function Capitalize_2<Type extends TSchema>(type: Type, options?: TSchemaOptions): TCapitalize<Type>;
325
420
 
@@ -353,6 +448,14 @@ declare namespace Char {
353
448
  }
354
449
  }
355
450
 
451
+ declare const CliAuthEnvVarName: z.ZodString;
452
+
453
+ declare type CliAuthEnvVarName = z.infer<typeof CliAuthEnvVarName>;
454
+
455
+ declare const CliBinaryName: z.ZodString;
456
+
457
+ declare type CliBinaryName = z.infer<typeof CliBinaryName>;
458
+
356
459
  /**
357
460
  * Returns a Clone of the given value. This function is similar to structuredClone()
358
461
  * but also supports deep cloning instances of Map, Set and TypeArray.
@@ -414,7 +517,13 @@ declare interface ContentConverter {
414
517
  */
415
518
  readonly description?: string;
416
519
  matches(probe: ContentProbe): boolean;
417
- convert(bytes: Uint8Array, probe: ContentProbe, ctx: ConvertContext): Promise<ConversionResult>;
520
+ /**
521
+ * Converts the file `matches` claimed. Resolves `undefined` to decline it after all: the read
522
+ * pipeline then tries the next converter that claimed it, as if this one had not. A converter
523
+ * that answers elsewhere (the plugin host's stand-in, which learns only there which converter
524
+ * takes the file) declines this way; one that decides in `matches` never needs to.
525
+ */
526
+ convert(bytes: Uint8Array, probe: ContentProbe, ctx: ConvertContext): Promise<ConversionResult | undefined>;
418
527
  }
419
528
 
420
529
  /**
@@ -438,7 +547,7 @@ declare interface ContentProbe {
438
547
 
439
548
  /**
440
549
  * The convert return shape. `content` is the agent-facing
441
- * {@link ModelContent} — text and/or image blocks — and is
550
+ * {@link ModelContent} - text and/or image blocks - and is
442
551
  * the field the read pipeline consumes (finalize windows/truncates TEXT blocks and
443
552
  * passes IMAGE blocks through unchanged). `contentType`/`artifacts`/`structure`/
444
553
  * `notes` are reserved metadata that no consumer renders yet. The converter does
@@ -615,7 +724,7 @@ declare function Deferred<Action extends string, Types extends TSchema[]>(action
615
724
  * What `service_connect` hands a delegated scheme's {@link DelegatedAuthScheme.connect}: the
616
725
  * scope being connected plus the host's browser-redirect capability when one is configured.
617
726
  * `authorize`/`redirectUri` wrap the host `OAuthRedirectTransport` (`@herd/herd-agent`)
618
- * — both absent when the host has none; the scheme decides whether it needs them.
727
+ * - both absent when the host has none; the scheme decides whether it needs them.
619
728
  */
620
729
  declare interface DelegatedConnectContext {
621
730
  readonly serviceId: string;
@@ -648,7 +757,7 @@ declare interface DelegatedConnectResult {
648
757
  /**
649
758
  * Token material minted by a delegated scheme's extension-provided flow. Core reads only
650
759
  * `accessToken`/`expiresAt` (resolution + proactive refresh); `data` is an opaque blob the
651
- * scheme round-trips through `refresh` (refresh token, DCR client info, …) — never read by core.
760
+ * scheme round-trips through `refresh` (refresh token, DCR client info, ...) - never read by core.
652
761
  */
653
762
  declare interface DelegatedSecretMaterial {
654
763
  readonly kind: "delegated";
@@ -674,7 +783,7 @@ declare function DependentOptions(type: TDependent): TSchemaOptions;
674
783
  * can derive per-call via {@link ToolPermissionHint.deriveClassification}. Every field is
675
784
  * optional: a present field overrides the static hint for that call; an absent field falls back
676
785
  * to the static hint (then to the fail-closed default). `resources` stays a separate deriver
677
- * ({@link ToolPermissionHint.deriveResources}) — these are the fields that decide which rule a
786
+ * ({@link ToolPermissionHint.deriveResources}) - these are the fields that decide which rule a
678
787
  * call matches, not the paths it touches.
679
788
  */
680
789
  declare interface DerivedToolClassification {
@@ -683,6 +792,13 @@ declare interface DerivedToolClassification {
683
792
  readonly scheme?: string;
684
793
  }
685
794
 
795
+ /**
796
+ * The definition the host builds for the tool `contract` describes under `localId`, running
797
+ * `execute`: name, parameters, auth binding and permission all come from the manifest, as in a
798
+ * session.
799
+ */
800
+ export declare function describedToolForTest(contract: ResolvedPluginContractV1, localId: string, execute: KayAgentToolExecute): ToolDefinition;
801
+
686
802
  declare const Digit: TDigit;
687
803
 
688
804
  /** Discards multiple property keys from the given object value */
@@ -834,18 +950,19 @@ declare function ExtendsTrue<Inferred extends TProperties>(inferred: TProperties
834
950
  declare function ExtendsUnion<Inferred extends TProperties>(inferred: TProperties): TExtendsUnion<Inferred>;
835
951
 
836
952
  /**
837
- * The execute-time auth surface the SDK wrappers read off `ctx.auth`. Slice 3 attaches a
838
- * concrete implementation (vault + pkce refresh + active-account store) to ExtensionContext;
839
- * defining the contract here lets the wrappers compile and be unit-tested against a double.
953
+ * The auth resolver: the host resolves a capability's credential through it before calling the
954
+ * capability, and an extension's event handlers read it off `ctx.auth`. Tools, URI verbs and search
955
+ * providers never see it; they receive the {@link ResolvedCredential} the host resolved.
840
956
  */
841
957
  declare interface ExtensionAuthContext {
842
958
  /**
843
959
  * Resolve a live token for a service and an account: the explicit `accountId` when given, else
844
- * the session-active account. `schemeId` is a preference, not an address — an explicit account
960
+ * the session-active account. `schemeId` is a preference, not an address - an explicit account
845
961
  * resolves against its OWN backing scheme even when a different scheme is named/bound, and an
846
962
  * absent `schemeId` resolves service-level across the injectable schemes. Refreshes oauth near
847
963
  * expiry under the hood. Returns an actionable {@link ResolveTokenFailure} (never throws) when
848
- * there is no connection or the account is ambiguous, so wrappers can short-circuit gracefully.
964
+ * there is no connection or the account is ambiguous, which the host answers with instead of
965
+ * calling the capability.
849
966
  */
850
967
  readonly resolveToken: (input: {
851
968
  readonly serviceId: string;
@@ -854,7 +971,7 @@ declare interface ExtensionAuthContext {
854
971
  /**
855
972
  * The invoking capability's `requiresAuth.requiredScopes`, threaded down to the vault load so a
856
973
  * grant-enforcing vault can refuse a plugin whose granted scopes don't cover them. The
857
- * caller identity itself is not a per-call argument — it is fixed by the owner-scoped context
974
+ * caller identity itself is not a per-call argument - it is fixed by the owner-scoped context
858
975
  * (see `CreateExtensionAuthContextInput.callerId`).
859
976
  */
860
977
  readonly requiredScopes?: readonly string[];
@@ -906,7 +1023,7 @@ declare interface ExtensionBackgroundTasksApi {
906
1023
 
907
1024
  /**
908
1025
  * Host-provided, per-extension writable data root surfaced on {@link ToolContext.paths}. Isolation is
909
- * the DIRECTORY itself — exactly like the per-extension SQLite db files keyed by extension id: the host
1026
+ * the DIRECTORY itself - exactly like the per-extension SQLite db files keyed by extension id: the host
910
1027
  * provisions a distinct path per owning extension, the extension owns everything inside it. The kernel
911
1028
  * never decides *where* this lives; it carries an opaque host-resolved path and exposes it, so an
912
1029
  * extension can read/write files (caches, scratch state, downloads) under a sanctioned root without the
@@ -1051,18 +1168,22 @@ declare function FactorMapping(input: [unknown, unknown, unknown, unknown, unkno
1051
1168
  * A default-permissive {@link ExtensionAuthContext} double: every method resolves
1052
1169
  * to a benign "not connected" outcome unless overridden. Kernel test fixtures that
1053
1170
  * need real account-selection semantics (active/sole/ambiguous account picking) or
1054
- * call-recording pass their own `resolveToken`/`listAccounts`/etc via `overrides` —
1171
+ * call-recording pass their own `resolveToken`/`listAccounts`/etc via `overrides` -
1055
1172
  * this owns only the four-method boilerplate shell that four kernel test files
1056
1173
  * used to hand-roll independently (see `extensions-auth-sdk.test.ts`'s `stubAuth`,
1057
1174
  * the double this was derived from).
1058
1175
  */
1059
1176
  export declare function fauxAuthContext(overrides?: Partial<ExtensionAuthContext>): ExtensionAuthContext;
1060
1177
 
1061
- /** The capability handles a `KayAgentPluginApi` always carries — authority is decided per call. */
1062
- export declare type FauxKayAgentCapabilities = Pick<KayAgentPluginApi, "network" | "webSession" | "process" | "whiteboard" | "interaction" | "interceptToolCall" | "systemOne" | "events" | "time" | "userFiles" | "familyFolder">;
1178
+ /** The capability handles a `KayAgentPluginApi` always carries - authority is decided per call. */
1179
+ export declare type FauxKayAgentCapabilities = Pick<KayAgentPluginApi, "network" | "webSession" | "process" | "whiteboard" | "interaction" | "interceptToolCall" | "implementTool" | "systemOne" | "events" | "time" | "log" | "userFiles" | "familyFolder" | "vendoredMcp" | "endpoints" | "compiler">;
1063
1180
 
1064
1181
  export declare function fauxKayAgentCapabilities(): FauxKayAgentCapabilities;
1065
1182
 
1183
+ declare const FileExtensionToken: z.ZodString;
1184
+
1185
+ declare type FileExtensionToken = z.infer<typeof FileExtensionToken>;
1186
+
1066
1187
  declare type ForecastInterval = "step" | "minute" | "hour" | "day" | "week" | "month" | "quarter" | "year";
1067
1188
 
1068
1189
  /** Creates a Function type. */
@@ -1126,6 +1247,36 @@ declare const GenericType: (input: string) => [unknown, string] | [];
1126
1247
 
1127
1248
  declare function GenericTypeMapping(input: [unknown, unknown, unknown]): unknown;
1128
1249
 
1250
+ declare const GitBasicAuthUser: z.ZodString;
1251
+
1252
+ declare type GitBasicAuthUser = z.infer<typeof GitBasicAuthUser>;
1253
+
1254
+ declare const GitHostName: z.ZodString;
1255
+
1256
+ declare type GitHostName = z.infer<typeof GitHostName>;
1257
+
1258
+ declare const GlobalContributionId: z.ZodString;
1259
+
1260
+ declare type GlobalContributionId = z.infer<typeof GlobalContributionId>;
1261
+
1262
+ /**
1263
+ * The cookie suffix rule shared by every web-session boundary: whether `host`
1264
+ * is `domain` or a subdomain of it. Coined ONCE here - the manifest's scope
1265
+ * confinement, the resolved/wire re-checks, and the desktop probe's
1266
+ * redirect-landing classification must all agree on it, or a login bounce
1267
+ * inside the declared scope could read as "unknown" on one side of a seam and
1268
+ * "signed-out" on the other.
1269
+ */
1270
+ declare function hostWithinDomain(host: string, domain: string): boolean;
1271
+
1272
+ declare const HttpStatusCode: z.ZodNumber;
1273
+
1274
+ declare type HttpStatusCode = z.infer<typeof HttpStatusCode>;
1275
+
1276
+ declare const HttpsUrl: z.ZodURL;
1277
+
1278
+ declare type HttpsUrl = z.infer<typeof HttpsUrl>;
1279
+
1129
1280
  declare const Hyphen = "-";
1130
1281
 
1131
1282
  /** Matches if next is an Ident */
@@ -1134,13 +1285,6 @@ declare function Ident<Input extends string>(input: Input): TIdent<Input>;
1134
1285
  /** Creates an Identifier. */
1135
1286
  declare function Identifier<Name extends string>(name: Name): TIdentifier<Name>;
1136
1287
 
1137
- /**
1138
- * Whether a scheme acts *as the user* (the fully-built PKCE path) or *on behalf of the user
1139
- * as an app* (a declared seam — see {@link OAuthPkceAuthScheme.mintToken}). It's a property of
1140
- * the scheme, not the call, so the resolver knows the identity without per-call ambiguity.
1141
- */
1142
- declare type IdentityMode = "as-user" | "on-behalf-of-app";
1143
-
1144
1288
  declare interface ImageContent {
1145
1289
  type: "image";
1146
1290
  data: string;
@@ -1270,6 +1414,12 @@ declare interface InteractionCandidate {
1270
1414
  readonly checked?: string | undefined;
1271
1415
  readonly selected?: string | undefined;
1272
1416
  readonly expanded?: string | undefined;
1417
+ /**
1418
+ * What a page driver found the element to be in the DOM, not what the page calls it: `link` is an
1419
+ * anchor that navigates to another http(s) page; `widget` is an element that is no form control.
1420
+ * Absent means unknown, and the engine then treats the element as any other.
1421
+ */
1422
+ readonly look?: "link" | "widget" | undefined;
1273
1423
  readonly delta?: number | undefined;
1274
1424
  /** Where an element outside the visible area sits; absent means on screen. */
1275
1425
  readonly position?: "above" | "below" | "beside" | undefined;
@@ -1445,18 +1595,18 @@ declare class InvalidLiteralValue extends Error {
1445
1595
 
1446
1596
  /**
1447
1597
  * Invoke a plugin tool definition's `execute` in a test, owning the **one sanctioned cast** past
1448
- * `ToolExecutionAwareParams<unknown>` — the phantom-wire-shaped type every `ToolDefinition`'s
1598
+ * `ToolExecutionAwareParams<unknown>` - the phantom-wire-shaped type every `ToolDefinition`'s
1449
1599
  * `execute` resolves to once auth-gated by `withResolvedAuth` (whose synthesized `execute` does not
1450
1600
  * go through `defineTool`'s `PluginToolDefinition` -> `InferToolInput` mapping, so there is no
1451
- * zod-inferred params type to type-check `params` against at the call site — see decision 002's
1601
+ * zod-inferred params type to type-check `params` against at the call site - see decision 002's
1452
1602
  * problem statement). `tool` is typed `ToolDefinition<any, TDetails>`, the same
1453
1603
  * accept-any-params-shape idiom the kernel itself uses for generic tool-definition plumbing
1454
- * (`core/tools/execution-policy.ts`, `core/tools/tool-definition-wrapper.ts`) — the `any` is this
1604
+ * (`core/tools/execution-policy.ts`, `core/tools/tool-definition-wrapper.ts`) - the `any` is this
1455
1605
  * function's entire reason to exist, not a shortcut taken to avoid one.
1456
1606
  *
1457
- * Fixes `toolCallId` to `"test-call"`, `signal` to `undefined`, and `onUpdate` to `undefined` —
1607
+ * Fixes `toolCallId` to `"test-call"`, `signal` to `undefined`, and `onUpdate` to `undefined` -
1458
1608
  * the values every fixture invocation wants and no fal-style test had a reason to vary. Pass a
1459
- * `ctx` (with `auth: fauxAuthContext(...)` for an auth-gated tool) to exercise anything beyond the
1609
+ * `ctx` (with a `credential` for an auth-gated tool) to exercise anything beyond the
1460
1610
  * happy-path default.
1461
1611
  */
1462
1612
  export declare function invokeToolForTest<TDetails = unknown>(tool: ToolDefinition<any, TDetails>, params: Record<string, unknown>, ctx?: ToolContext): Promise<AgentToolResult<TDetails>>;
@@ -1620,10 +1770,22 @@ declare function IsUnsafe(value: unknown): value is TUnsafe;
1620
1770
  /** Returns true if the given value is TVoid. */
1621
1771
  declare function IsVoid(value: unknown): value is TVoid;
1622
1772
 
1773
+ declare const JsonObject: z.ZodRecord<z.ZodString, z.ZodType<JsonValue_2, unknown, z.core.$ZodTypeInternals<JsonValue_2, unknown>>>;
1774
+
1775
+ declare type JsonObject = z.infer<typeof JsonObject>;
1776
+
1777
+ declare const JsonPointer: z.ZodString;
1778
+
1779
+ declare type JsonPointer = z.infer<typeof JsonPointer>;
1780
+
1623
1781
  declare type JsonPrimitive = string | number | boolean | null;
1624
1782
 
1625
1783
  declare type JsonSchema = Record<string, unknown>;
1626
1784
 
1785
+ declare const JsonSchema_2: z.ZodRecord<z.ZodString, z.ZodType<JsonValue_2, unknown, z.core.$ZodTypeInternals<JsonValue_2, unknown>>>;
1786
+
1787
+ declare type JsonSchema_2 = z.infer<typeof JsonSchema_2>;
1788
+
1627
1789
  declare type JsonValue = JsonPrimitive | {
1628
1790
  readonly [key: string]: JsonValue;
1629
1791
  } | readonly JsonValue[];
@@ -1638,6 +1800,627 @@ declare type JsonValue_3 = null | boolean | number | string | JsonValue_3[] | {
1638
1800
  [key: string]: JsonValue_3;
1639
1801
  };
1640
1802
 
1803
+ /**
1804
+ * The publisher id Bonsai's own subsystems publish declared events under (skill
1805
+ * changes, wallet notices, automation failures). A notification rule matches a
1806
+ * declared event by (publisher id, event local id), so no plugin may take this
1807
+ * id or it could publish events that Bonsai's default rules read as Bonsai's own.
1808
+ */
1809
+ declare const KAY_EVENT_PUBLISHER_ID: "kay";
1810
+
1811
+ /** Released SDK contracts still implemented by the host, alongside its current SDK. */
1812
+ declare const KAY_PLUGIN_COMPATIBLE_SDK_VERSIONS: readonly string[];
1813
+
1814
+ declare const KAY_PLUGIN_PROTOCOL_PACKAGE_NAME: "@bonsai/plugin-protocol";
1815
+
1816
+ declare const KAY_PLUGIN_PROTOCOL_VERSION: "kay.plugin.v1";
1817
+
1818
+ /**
1819
+ * The plugin SDK version this host ships, and the number a plugin's
1820
+ * `compatibility.sdk` range is matched against.
1821
+ *
1822
+ * -- Why this is the compatibility axis, and the app version is not ----------
1823
+ * A plugin never bundles the SDK: the host injects its own `@bonsai/plugin-sdk`
1824
+ * dist at import time. So the SDK surface a plugin was written against is the
1825
+ * thing that can break under it, and the Bonsai app version is only correlated
1826
+ * with that - it moves for reasons a plugin cannot observe.
1827
+ *
1828
+ * -- Two lines, deliberately, not one ----------------------------------------
1829
+ * This continues the published `@yaklabs-ai/plugin-sdk` line, currently in 0.x.
1830
+ * `KAY_UI_SDK_VERSION` in `@bonsai/protocol` is a SEPARATE line at its own number,
1831
+ * and the two are never compared: a `kay.ui` app package declares against the
1832
+ * UI SDK, a plugin manifest declares `compatibility.sdk` against this one, and
1833
+ * no manifest field takes both. Unifying them would have to publish the plugin
1834
+ * SDK at the UI line's 1.x, claiming a stability this surface does not have -
1835
+ * 0.x says "breaking minors" honestly, which is the truth pre-product.
1836
+ *
1837
+ * -- Bumping it --------------------------------------------------------------
1838
+ * A protocol or SDK surface break bumps this constant IN THE SAME PR, and
1839
+ * `scripts/check-sdk-release-due.mjs` then reports a release due at the new
1840
+ * number. The constant is the declared version, not a derived one: the release
1841
+ * publishes exactly what is written here.
1842
+ *
1843
+ * An ADDITION takes the patch slot, not the minor. Under 0.x npm's caret makes
1844
+ * the minor the breaking slot, so a minor bump refuses
1845
+ * (`sdk-range-unsatisfied`) every plugin still declaring the previous one - a
1846
+ * fleet-wide break, never the price of one new entrypoint. 0.7.1 carried the
1847
+ * additive `@bonsai/plugin-sdk/phase-shift` surface that way, while `^0.7.0`
1848
+ * plugins kept loading.
1849
+ *
1850
+ * 0.8.0 IS that fleet-wide break, deliberately, and it spends the one break on
1851
+ * two changes at once.
1852
+ *
1853
+ * FIRST, a plugin no longer declares the capabilities it wants, because the
1854
+ * CALL is the ask. Every capability ask left `permissions.byTarget` (an
1855
+ * installed manifest that still carries one is stripped with a
1856
+ * `retired-permission-ask` diagnostic, never refused - the same law
1857
+ * `RETIRED_COMPATIBILITY_KEYS` follows), every brokered capability object is
1858
+ * unconditionally present on the SDK surface (presence is no longer a grant
1859
+ * signal to feature-detect), and authority is one exact claim checked against
1860
+ * the user's grant ledger at the call.
1861
+ *
1862
+ * SECOND, `app.hindsight` (`KayAppHindsight` - lane registration, the lane
1863
+ * event, the lane context, and the followup DTOs) is DELETED, along with the
1864
+ * daemon-side lane dispatcher it registered onto. Its replacement is two
1865
+ * generic doors a plugin composes itself, `app.sessionEvents.subscribe` and
1866
+ * `app.agents.run`, and their authority is two claims in the same ledger
1867
+ * (`session-events.subscribe`, `agents.run`). There is no shim, because a shim
1868
+ * would have to fake a dispatcher that no longer exists.
1869
+ *
1870
+ * Either half alone breaks a `^0.7` plugin: the TYPE surface it compiles
1871
+ * against moved under it - the ask keys are gone from the manifest type, the
1872
+ * capability objects are required rather than optional, and the hindsight door
1873
+ * is gone - which is what the minor bump signals. A plugin declaring `^0.7` is
1874
+ * refused (`sdk-range-unsatisfied`) rather than loaded against a contract it
1875
+ * was not written to.
1876
+ *
1877
+ * 0.8.1 takes the PATCH slot under the addition rule above: `api.withJev`
1878
+ * (`@bonsai/plugin-sdk/jev`) - Jev typed-decision inference with a required
1879
+ * fallback - is one new member on an api a plugin RECEIVES. A `^0.8.0` plugin
1880
+ * keeps loading and keeps compiling; it simply never reaches for the member.
1881
+ * The member is non-optional for the same reason 0.8.0 made every brokered
1882
+ * capability unconditional: presence is not a grant signal, and an optional one
1883
+ * would invite the feature-detect branch that skips the required fallback.
1884
+ *
1885
+ * 0.8.2 adds the received Whiteboard handles, type contributions, and session
1886
+ * app-data readers. Existing 0.8 plugins keep loading without using them.
1887
+ *
1888
+ * 0.8.3 adds the recorded Jev signal reads, `app.signals.list` and
1889
+ * `app.signals.listDetectors`, behind the new `signals.read` claim. It is also
1890
+ * the first number that guarantees `app.signals.observe`, which reached hosts
1891
+ * still advertising 0.8.2. A plugin that reads signals declares `^0.8.3`, so an
1892
+ * older host refuses it at load instead of failing at the call. 0.8.3's
1893
+ * `observe` also answers `invalid`, recording nothing, for a detector id,
1894
+ * version, question name, choice label, or source id outside the recorded-name
1895
+ * grammar (`invalidObservation` in `@bonsai/plugin-sdk/signals`): names a reader
1896
+ * could not later address, filter on, or copy back. A 0.8.2 host recorded such
1897
+ * names, so a plugin moving to 0.8.3 checks its names against that grammar.
1898
+ *
1899
+ * 0.8.4 adds `api.events` on `kay.agent` (publish a declared event from agent
1900
+ * code, host-stamped with the session) and the `kay.app` manifest key
1901
+ * `notificationRules` (default notification rules for a plugin's own events).
1902
+ * Both are additions: a `^0.8` plugin keeps loading. The manifest key is new
1903
+ * schema, so an older host refuses a manifest that uses it at parse. `api.events`
1904
+ * carries no such schema backstop - it is a call, not a manifest field - so a
1905
+ * plugin that calls it, or declares `notificationRules`, declares `^0.8.4`: a
1906
+ * host still advertising 0.8.3 (signals only, landed separately) refuses it at
1907
+ * load instead of failing at the call.
1908
+ *
1909
+ * 0.8.5 republishes `@yaklabs-ai/plugin-sdk` to include the `./jev` and
1910
+ * `./signals` entrypoints: the workspace package has exported them since 0.8.1
1911
+ * (`jev`) and 0.8.3 (`signals`), but `scripts/build-publishable-packages.mjs`'s
1912
+ * hand-maintained `entrypoints` allowlist had omitted both. This packages
1913
+ * EXISTING apis; the type contract does not change. It still takes the patch
1914
+ * slot: nothing a `^0.8.1`/`^0.8.3` plugin already compiles against changes
1915
+ * shape, and the fix is which bytes reach npm, not what the contract promises.
1916
+ *
1917
+ * 0.9.0 adds timer_cancelled and requires workflow descriptions and summary
1918
+ * returns. This is an authoring-type break only: the host retains the 0.8
1919
+ * runtime contracts.
1920
+ *
1921
+ * 0.9.1 adds bounded corpus invocation reads (`app.corpus.listResourceInvocations`).
1922
+ * Existing received APIs are unchanged, so this is additive only.
1923
+ *
1924
+ * 0.10.0 removes the `spawn-session` variant from `KayAppAutomationEffectInput`
1925
+ * (and its daemon-facing mirror, `KayAutomationEffectInput`): an agent or
1926
+ * plugin can no longer create a spawn-session automation binding (owner
1927
+ * ruling, 2026-09-28) - durable recurring agent work is a plugin workflow
1928
+ * (`app.workflows.define` + `ctx.runAgent`) or a direct `session/run`. A
1929
+ * binding created before this version, or by daemon-internal code, still
1930
+ * stores and reads the effect fine (`KayAppAutomationEffect` keeps it); only
1931
+ * the create-time input type is narrower. Mostly an authoring-type break -
1932
+ * 0.9.0 and 0.9.1 stay in the runtime-contract retention list below, so a
1933
+ * plugin still running bytecode compiled against either keeps loading and
1934
+ * working - except for the one call this ruling actually closes:
1935
+ * `app.automations.create` with a `spawn-session` effect now throws
1936
+ * explicitly at the call site instead of being accepted, for any plugin
1937
+ * regardless of its declared SDK range.
1938
+ *
1939
+ * 0.11.0 adds `producedResources` to `KayAppAutomationRunDetail` (every URI a
1940
+ * run wrote, edited or declared, as one list deduplicated by URI) and the
1941
+ * `produced-resource-unnamed` member to `KayAppProvenanceGapCode`. An
1942
+ * authoring-type break only: code that builds a run detail must supply the
1943
+ * new list, and an exhaustive switch over gap codes must handle the new one.
1944
+ * 0.10.0 stays in the runtime-contract retention list below, because a plugin
1945
+ * compiled against it reads the same run detail and simply ignores the list.
1946
+ *
1947
+ * 0.11.1 adds read-only skill metadata (`app.skills`: `list`, `read`, `history`),
1948
+ * checked per call against the new `skills.read` claim. Additive: a plugin
1949
+ * compiled against 0.11.0 never reads the member. A plugin that calls it
1950
+ * declares `^0.11.1`, so an older host refuses it at load instead of the call
1951
+ * failing.
1952
+ *
1953
+ * 0.12.0 replaces the vendor client `api.withJev` hands its callback. `use`
1954
+ * now receives Bonsai's own `JevClient` (`@bonsai/plugin-sdk/jev`): one method,
1955
+ * `classify({state, questions})`, in Bonsai's question and answer vocabulary
1956
+ * (yes/no is `bool` answering `probability`; instructions and criteria are
1957
+ * text; the state is a JSON object), rejecting with a classified
1958
+ * `JevCallError`. TypeSafe's `TypeSafeClient`, `SystemOneRequest`,
1959
+ * `SystemOneResult`, `Questions`, and the `NoulResponse`/`ChoiceResponse`/
1960
+ * `ScoreResponse` re-exports are gone, and the SDK no longer depends on
1961
+ * `@typesafe-ai/sdk`. `app.signals.observe` takes the same questions, answers
1962
+ * `invalid` for a state that is not a JSON object, and its reads type stored
1963
+ * answers as `KayAppSignalAnswer` (a `JevAnswer`, or a yes/no answer recorded
1964
+ * before 0.12.0 as `{type: "noul", noul}`).
1965
+ *
1966
+ * A clean break with no shim, and deliberately NOT a load refusal: every
1967
+ * earlier release stays in the retention list below. `withJev`'s contract was
1968
+ * always that `use` may fail and the fallback then runs, so a plugin compiled
1969
+ * against 0.11 that calls `jev.systemOne` throws inside `use` and runs its
1970
+ * fallback on this host. This fallback guarantee does not cover `signals.observe`:
1971
+ * old text/array states now return `invalid`; old object states with `noul`
1972
+ * questions can classify but receive `bool` answers, so reading `.noul` yields
1973
+ * undefined. Stored pre-0.12 answers retain `noul`. Retention allows activation,
1974
+ * not vocabulary compatibility: old plugins must migrate both surfaces.
1975
+ *
1976
+ * 0.12.1 adds `app.time` (`KayAppTime`): `snapshot()` returns the daemon's clock and the time
1977
+ * zone the user is in, as `{ nowMs, zone, zoneSource }`, where `zoneSource: "utc-fallback"` marks a
1978
+ * zone the host does not know. The member is always present and ungated, like `app.paths`.
1979
+ * Additive: a plugin compiled against 0.12.0 never reads it. A plugin that calls it declares
1980
+ * `^0.12.1`, so an older host refuses a directory or repository plugin at load instead of the
1981
+ * call failing. That check needs a host that knows its own version, and it never runs for a
1982
+ * bundled plugin, which ships with the SDK it calls.
1983
+ *
1984
+ * 0.12.2 adds the `ui-action` session event (`KayAppUiActionSessionEvent`), a fourth member of the
1985
+ * `KayAppSessionEvent` union: the daemon publishes it once per accepted answer to a card the agent
1986
+ * drew with `ui_render` (pressing Send on a drafted message, submitting a form), carrying the
1987
+ * projected entry's id and the answered call's id and no payload. A typed message still publishes
1988
+ * only `human-message`. Additive: a plugin compiled against 0.12.1 never subscribes to it, and
1989
+ * code that narrows the union by `type` meets one more member, as it must for any future one. A
1990
+ * plugin that subscribes to it declares `^0.12.2`, so an older host refuses a directory or
1991
+ * repository plugin at load instead of the subscription never firing. That check never runs for a
1992
+ * bundled plugin, which ships with the SDK it calls.
1993
+ *
1994
+ * 0.12.3 adds the `page` reference open kind (`{ kind: "page", pageId }` on a
1995
+ * `referencePresentations` entry), and lets a presentation name a `kay.app` URI module as well as a
1996
+ * `kay.agent` one. A plugin's own `scheme://` references then pill with its icon and the module's
1997
+ * `describe` title, and a click opens the plugin's own registered page with the reference URI as
1998
+ * the page's `objectId`. Additive: a `^0.12.2` plugin keeps loading. The value is new schema, so an
1999
+ * older host refuses the whole manifest at parse (`manifest-schema-invalid`), before any range
2000
+ * check runs. A plugin that declares it still declares `^0.12.3`, so the install-time version
2001
+ * checks name the mismatch instead of a schema error.
2002
+ *
2003
+ * 0.12.4 adds `app.repos` (`KayAppRepos`): `resolve(folder)` answers which git checkout encloses a
2004
+ * folder (repo root, primary checkout, common dir, remotes, origin), and `linkedWorktrees(commonDir)`
2005
+ * lists git's linked-worktree registry, both read by the host asynchronously under a time limit and
2006
+ * answering `unknown` rather than throwing. Always present and ungated, like `app.paths`. Additive:
2007
+ * a plugin compiled against 0.12.3 never reads it. A plugin that calls it declares `^0.12.4`, so an
2008
+ * older host refuses a directory or repository plugin at load instead of the call failing.
2009
+ *
2010
+ * 0.12.5 adds `userFiles` (`KayAppUserFiles`) on both `app` and the `kay.agent` api: stat, read,
2011
+ * list, walk, realpath, write, mkdir and rename in user folders, run by the host on its own worker
2012
+ * threads under a deadline and answering a typed result rather than throwing. Always present and
2013
+ * ungated, like `app.paths`. Additive: a plugin compiled against 0.12.4 never reads it. A plugin
2014
+ * that calls it declares `^0.12.5`, so an older host refuses a directory or repository plugin at
2015
+ * load instead of the call failing.
2016
+ *
2017
+ * 0.13.0 adds `@bonsai/plugin-sdk/fs`, Bonsai's own `node:fs/promises`: the same functions, arguments,
2018
+ * return types and errors, with every call run on the host's user-files workers under a deadline
2019
+ * (`ERR_KAY_FS_DEADLINE` and siblings when the host gives up or does not try), plus
2020
+ * `writeFileAtomic` and `withTimeout`. With no host installed it is Node's own module. It adds
2021
+ * `api.familyFolder` (`KayAgentFamilyFolder`), whose `path()` answers the plugin's folder in its
2022
+ * session family's Whiteboard, and makes it a required member of `KayAgentPluginApi`. It removes
2023
+ * the `kay.agent` api's `filesystem` broker, the `filesystem.read` / `filesystem.write`
2024
+ * permissions it was gated by, the `{ root: "filesystem", selector }` URI backing and the URI
2025
+ * module `verbs` that went with it: plugins use `@bonsai/plugin-sdk/fs`, `userFiles` or
2026
+ * `familyFolder` instead. No plugin used them. Stored grants naming the retired permissions are
2027
+ * ignored, not refused. For the api surface this is a clean break with no shim and deliberately
2028
+ * NOT a load refusal, like 0.12.0: every earlier release stays in the retention list, so a
2029
+ * plugin compiled against 0.12.x that reads `api.filesystem` gets `undefined` at the call. The
2030
+ * manifest is different: a manifest that still declares URI-module `verbs` or
2031
+ * `filesystemBacking: { root: "filesystem" }` fails to parse and is refused at load (no plugin
2032
+ * declared either). A plugin that imports
2033
+ * `@bonsai/plugin-sdk/fs` or calls `familyFolder` declares `^0.13.0`, so an older host refuses a
2034
+ * directory or repository plugin at load.
2035
+ *
2036
+ * 0.13.1 adds the signal engine to `@bonsai/plugin-sdk/signals`: `SignalDefinition`,
2037
+ * `createSignalEngine` and `signalAnswersPass` (a plugin declares its Jev signals as data and the
2038
+ * engine evaluates them, upstreams first, through `app.signals.observe`), plus `signalDigest`.
2039
+ * `observe` gains three optional input fields, `subject`, `after` and `reuse`, and an observation
2040
+ * and a read signal carry the stored `subject` and `upstreamId` back. Additive: a plugin compiled
2041
+ * against 0.13.0 never sends or reads them. A plugin that imports the engine declares `^0.13.1`,
2042
+ * so an older host refuses a directory or repository plugin at load.
2043
+ *
2044
+ * 0.13.2 adds `app.tools` (`KayAppTools`): `describe(sessionId, refs)` returns, for each tool name
2045
+ * or address a live session can use, the text the agent sees for it, where it comes from, and
2046
+ * whether it is one of Bonsai's own (`ownedByBonsai`). Checked per call against the new
2047
+ * `tools.describe` claim. It also adds the manifest's top-level `ownedByBonsai` flag, honoured only
2048
+ * for a plugin that ships with Bonsai. Additive: a plugin compiled against 0.13.1 never reads the
2049
+ * member. A plugin that calls it declares `^0.13.2`, so an older host refuses a directory or
2050
+ * repository plugin at load. The flag is new schema, so an older host refuses a manifest that sets
2051
+ * it at parse, like 0.12.3's page open kind.
2052
+ *
2053
+ * 0.13.3 adds `app.usage` (`KayAppUsage`, `createUnavailableUsage`): `uriActivity({ prefix })`
2054
+ * returns read and change activity for resources under one of the plugin's OWN registered URI
2055
+ * schemes, checked per call (any other prefix answers `refused`). It also adds
2056
+ * `KayAppAgentDefinition.maintains`, the URI schemes a registered agent definition's runs maintain;
2057
+ * reads by such a run and its session family are not counted. Additive: a plugin compiled against
2058
+ * 0.13.2 never reads the member or sets the field. A plugin that calls `app.usage` or declares
2059
+ * `maintains` declares `^0.13.3`, so an older host refuses a directory or repository plugin at
2060
+ * load; an older host's strict definition schema would refuse a definition that sets `maintains`.
2061
+ *
2062
+ * 0.13.4 caps reads through `@bonsai/plugin-sdk/fs`: a whole-file `readFile` (a file handle's too)
2063
+ * and a single `read` reject past 64 MiB with `EFBIG` instead of copying the bytes into the daemon.
2064
+ * No API changes: a plugin compiled against 0.13.3 runs unchanged unless it reads more than 64 MiB
2065
+ * in one call, and such a plugin reads in bounded chunks (a file handle's `read`,
2066
+ * `createReadStream`, `readLines`), which work on every 0.13 host. File calls sent to a host worker
2067
+ * that fail are also logged to the daemon log as `runtime.user-files.*` events.
2068
+ *
2069
+ * 0.13.5 loads a `kay.agent` or `kay.app` entrypoint's default export when the manifest's
2070
+ * `entrypoint.export` names none, the way Pi writes extensions; a module with no default export
2071
+ * still loads from a named `activate`. A plugin whose entrypoint has only a default
2072
+ * export declares `^0.13.5`, so an older host, which reads only `activate`, refuses it at load
2073
+ * instead of failing to find the export. It also renamed three published types with no aliases,
2074
+ * a break in the authoring types that shipped in this patch: `kay-app`'s `SessionTreeEntry`
2075
+ * became `TranscriptEntry`, and `transcript`'s `TranscriptEntry` and `TranscriptSourceEntry`
2076
+ * became `TranscriptEntryLike` and `TranscriptSourceEntryLike`.
2077
+ *
2078
+ * 0.13.6 publishes the pure contracts Bonsai's own plugins took from its internal libraries, so a
2079
+ * plugin needs less beside the SDK. A new `@bonsai/plugin-sdk/time` carries `Temporal` (the
2080
+ * host's own instance, like `z`), `canonicalZone`, `isValidZone` and `sameZone`, and the time
2081
+ * door's types. `kay-app` adds
2082
+ * the `JsonSchema` and `JsonValue` schemas, `PluginAgentDefinitionPermissionRule`,
2083
+ * `KAY_APP_DATA_SNAPSHOT_MAX_BYTES`, and the URI types `UriHelp`, `RawResource`, `UriPayload`,
2084
+ * `UriListParams`, `UriListResult`, `UriSearchParams` and `UriSearchResult`. `kay-agent` adds
2085
+ * `compileUriClaim`, `kay-agent/testing` adds `createTestClock`, and `transcript` adds the turn walk
2086
+ * (`turnSegments`), the run records and the work-block and work-headline helpers. Additive: a
2087
+ * plugin compiled against 0.13.5 never imports them. A plugin that imports one declares `^0.13.6`,
2088
+ * so an older host refuses a directory or repository plugin at load instead of the import failing.
2089
+ *
2090
+ * 0.13.7 adds four subpaths. `@bonsai/plugin-sdk/vendored-mcp` re-exports
2091
+ * `@bonsai/vendored-mcp-integration` (`createVendoredMcpUriModule` and its descriptor types; not
2092
+ * the MCP read-port types). `transcript-review` and `agent-conversation` re-export the session
2093
+ * folds Bonsai's own Sessions and Hindsight plugins share. `app-data` carries the app-data size
2094
+ * caps on an entry with no other import, for code a `kay.ui` page also loads. The protocol it
2095
+ * ships also carries three new capability-claim slugs (`mcp.host-server`, `prompt.resident`,
2096
+ * `skills.declared-source`). Additive: a plugin compiled against 0.13.6 never imports the new
2097
+ * subpaths, and its manifest parses unchanged. A plugin that imports one declares `^0.13.7`, so
2098
+ * an older host refuses a directory or repository plugin at load instead of the import failing.
2099
+ *
2100
+ * 0.13.8 takes the PATCH slot under the addition rule, as `api.withJev` did in 0.8.1: one new
2101
+ * member on the api a plugin RECEIVES, `api.systemOne` / `app.systemOne` (`@bonsai/plugin-sdk/
2102
+ * system-one`), the System One client for `decide` and `extract` on Jev, Clef, Clef Flash and
2103
+ * Clairic. It is non-optional for the same reason `withJev` is, and a host with no System One
2104
+ * binds a client that throws `not-served`. `withJev` stays for every compatible plugin. A
2105
+ * plugin that calls `systemOne` declares `^0.13.8`, so an older host refuses it at load instead
2106
+ * of the member being absent.
2107
+ *
2108
+ * 0.13.9 adds `@bonsai/plugin-sdk/zod`: the host's `z` on an entry with no other import, for
2109
+ * code a `kay.ui` page also loads (`kay-agent` exports the same `z`). Additive: a plugin compiled
2110
+ * against 0.13.8 never imports it. A plugin that imports it declares `^0.13.9`, so an older host
2111
+ * refuses a directory or repository plugin at load instead of the import failing.
2112
+ *
2113
+ * 0.13.10 adds two optional manifest fields. An `external-cli` auth scheme's `cli` says how the host
2114
+ * connects it (the binary, its probe and sign-in argv, the hints, the install command), which the
2115
+ * host read from its own tables before. An auth grant's `frontDoor` names the product a person
2116
+ * connects a shared identity through (`gmail` over `google.account`), with an optional file picker.
2117
+ * Additive: a manifest without them parses unchanged. A plugin that declares one declares
2118
+ * `^0.13.10`, so an older host refuses it at load with that reason rather than a schema error.
2119
+ *
2120
+ * 0.14.0 removes `withJev`: `api.withJev` on `kay.agent`, `app.withJev` on `kay.app`, the
2121
+ * `@bonsai/plugin-sdk/jev` subpath and every `Jev*` type it exported. A plugin uses `api.systemOne`
2122
+ * / `app.systemOne` (`@bonsai/plugin-sdk/system-one`) instead. The `jev.use` capability claim is
2123
+ * renamed `systemOne.use`, and stored grants are rewritten to the new slug. The signals subpath
2124
+ * types its own surface now: observe options by `KayAppSignalObserveOptions`, state by
2125
+ * `KayAppSignalState`, and questions and answers by `DecideQuestions` and `DecideAnswer`. For the
2126
+ * api surface this is a clean break with no shim and deliberately NOT a load refusal, like 0.13.0:
2127
+ * every earlier release stays in the retention list, so a plugin compiled against 0.13.x that
2128
+ * reads `api.withJev` gets `undefined` at the call, and one that imports a value from
2129
+ * `@bonsai/plugin-sdk/jev` fails at load. No plugin used either.
2130
+ *
2131
+ * 0.14.1 adds the owned-service `kay.app` auth list operation and `listAccounts`.
2132
+ * Existing resolve-only `has` callers retain account bounds and now probe metadata without
2133
+ * resolving credentials. Plugins using list declare `^0.14.1` so older hosts refuse at load.
2134
+ *
2135
+ * 0.15.0 replaces plugin-event publish arguments and requires resource URI declarations.
2136
+ * Pre-0.15 SDK contracts are no longer retained: their publishers cannot satisfy this contract.
2137
+ *
2138
+ * 0.15.1 adds plugin-event automation conditions and public event-identity run matches.
2139
+ * The host retains 0.15.0; plugins using the new condition declare ^0.15.1.
2140
+ *
2141
+ * 0.15.2 lets a plugin workflow start on the plugin's own events (a `plugin-event` trigger, with
2142
+ * the event handed to the run as `ctx.match`) and declare `concurrency`. The host retains 0.15.0
2143
+ * and 0.15.1; a plugin using either declares ^0.15.2, so an older host refuses it at load instead
2144
+ * of `define` throwing inside activation.
2145
+ *
2146
+ * 0.15.3 adds `owner: "user"` to `app.automations.create`, with the `spawn-session` effect it
2147
+ * allows: an automation the user owns, which outlives the calling session. Additive; plugins
2148
+ * using it declare ^0.15.3 so an older host, which would ignore the field and make the calling
2149
+ * session the owner, refuses them at load.
2150
+ *
2151
+ * 0.16.0 adds declared app-lifetime approval types and their brokered registration API.
2152
+ * Plugins using approval types declare ^0.16.0; the host retains the 0.15 contracts.
2153
+ *
2154
+ * 0.16.1 adds `api.log` on both targets: a logger whose lines land in Bonsai's own log under the
2155
+ * plugin's id. Additive; plugins calling it declare ^0.16.1 so an older host, which has no
2156
+ * `api.log`, refuses them at load instead of activation throwing.
2157
+ *
2158
+ * 0.16.2 adds `api.vendoredMcp` on `kay.agent`: a port to a vendored MCP server the plugin declares,
2159
+ * bound to that plugin, with its `VendoredMcpPort` / `VendoredMcpOutcome` types on
2160
+ * `@bonsai/plugin-sdk/vendored-mcp`. Additive; plugins calling it declare ^0.16.2 so an older host,
2161
+ * which has no `api.vendoredMcp`, refuses them at load instead of activation throwing.
2162
+ *
2163
+ * 0.16.3 adds `app.sessionEvents.subscribeSessionDeleted`: a notice for every deleted session, so
2164
+ * a plugin can delete what it derived from it. Additive; plugins calling it declare ^0.16.3.
2165
+ *
2166
+ * 0.17.0 consolidates `app.corpus` into the always-present `app.sessions`. Read methods retain
2167
+ * the `corpus.read` claim; control methods retain their own claims and are absent on read-only
2168
+ * hosts. The summary helper takes `sessions` and stored-session DTOs use session names. The host
2169
+ * no longer implements earlier runtime contracts, so declared 0.15/0.16 ranges are refused.
2170
+ *
2171
+ * 0.17.1 adds `app.skills.diff` and `app.skills.revision` under `skills.read`, `uncommitted` on a
2172
+ * history result, refs by app-inventory row id, and `app.skills.writeFile`, `install` and `delete`
2173
+ * under the new `skills.write` claim. Additive; plugins calling them declare ^0.17.1.
2174
+ *
2175
+ * 0.17.2 adds `app.account.activeOrganization()` (ungated) and `app.account.refreshBilling()`
2176
+ * (under the `account.assert` grant), and an optional `refresh()` on an app-data source definition.
2177
+ * Additive; plugins using them declare ^0.17.2.
2178
+ *
2179
+ * 0.17.3 adds `app.sealing` on `kay.app` (encrypt small values under a key only the plugin's id
2180
+ * can use; the daemon holds it) and `api.endpoints` on `kay.agent` (call an endpoint the plugin's
2181
+ * own `kay.app` part registered, by local id). Additive; plugins calling either declare ^0.17.3 so
2182
+ * an older host, which has neither member, refuses them at load instead of activation throwing.
2183
+ *
2184
+ * 0.17.4 adds the optional `app.sessions.readCost(sessionId)` (a stored session's spend, models,
2185
+ * and providers, under the same `corpus.read` grant as the other session reads). Additive.
2186
+ *
2187
+ * 0.17.5 adds `app.modelSelection.registerPolicy` on `kay.app`, a private method under the
2188
+ * `model-selection.register` claim (only plugins Bonsai ships). Additive; a host without it leaves
2189
+ * `app.modelSelection` undefined.
2190
+ *
2191
+ * 0.17.6 renames the stored-session read claim `corpus.read` to `sessions.read`, next to
2192
+ * `sessions.run`, `sessions.create` and `sessions.update`; stored grants are rewritten to the new
2193
+ * slug. The manifest's `contributes.corpusConsumers` becomes `contributes.sessionReaders` (kind
2194
+ * `sessionReader`), a clean break: no plugin outside this repo declares it.
2195
+ *
2196
+ * 0.18.0 adds the calls hindsight moved onto (#14533): `app.sessions.annotate` and
2197
+ * `app.sessions.compact` (claims `sessions.annotate`, `sessions.compact`), the session-state read,
2198
+ * `app.models.listTiers({ provider })`, `app.usage.skillInvocations`, an optional `cause` on
2199
+ * `app.models.complete` and `app.systemOne.decide`, `app.skills.registerSuggestionExplainer`, and
2200
+ * the private `app.soul` (claim `soul.write`). Additive; plugins calling them declare ^0.18.0.
2201
+ *
2202
+ * 0.18.1 adds `servedSimulators` on both targets (`KayServedSimulators`): the simulators a
2203
+ * simulating Bonsai daemon (evals, dev, tests) serves a plugin, keyed by adapter id. Optional and
2204
+ * absent unless such a daemon serves it, so no plugin needs it to load; additive, so it takes the
2205
+ * patch slot. A plugin need not declare a range to read it: an older host serves none, the same as
2206
+ * a production daemon, and code that reads it already runs without it. It also deletes the other
2207
+ * route a plugin could get a simulator by: a per-dispatch handle on a URI call's `ctx.auth`, and
2208
+ * the type that `@bonsai/plugin-sdk/kay-agent` exported for it. Only Slack read it. It entered the
2209
+ * source after 0.17.3's bump, and no SDK since 0.15.3 has been published, so no released contract
2210
+ * loses a member and the removal does not spend the minor slot.
2211
+ *
2212
+ * 0.18.2 adds the marketplace calls the kay plugin moved onto (#14530):
2213
+ * `app.skills.sourceContributors`, `app.skills.shareDestinations` and `app.skills.prepareShare`
2214
+ * under `skills.read`, `app.skills.setMarketplaceAdded` under `skills.write`, and two private
2215
+ * methods, `app.skills.confirmShare` (claim `skills.share`) and `app.plugins.setEnabled` (claim
2216
+ * `plugins.set-enabled`). Additive; plugins calling them declare ^0.18.2.
2217
+ *
2218
+ * 0.18.3 adds `app.systemPrompt.register` on `kay.app`, a private method under the
2219
+ * `system-prompt.register` claim (only plugins Bonsai ships): text a plugin adds to every chat's
2220
+ * system prompt, rendered by the daemon and reused across chats. Additive; a host without it leaves
2221
+ * `app.systemPrompt` undefined.
2222
+ *
2223
+ * 0.18.4 adds `api.compiler.bundleBrowser` on `kay.agent` (#14896): the host compiles
2224
+ * caller-supplied bytes with caller-owned import resolution, without filesystem or network
2225
+ * fallback. Additive and ungated; plugins calling it declare ^0.18.4.
2226
+ *
2227
+ * 0.19.0 makes the host resolve the credential of a tool or search provider that declares
2228
+ * `requiresAuth` before calling it, as it already did for URI verbs (#15102). The credential
2229
+ * arrives on the call as `ctx.credential` (`ResolvedCredential`, the one type all three share,
2230
+ * replacing `ResolvedAuth` and `UriResolvedCredential`); tools and search providers no longer
2231
+ * receive the `ctx.auth` resolver. `defineAuthedTool`, `withResolvedAuth` and
2232
+ * `withResolvedSearchProvider` keep their shapes and read the credential off the call. A plugin
2233
+ * built against an earlier SDK carries wrappers that ask `ctx.auth`, so the host no longer
2234
+ * implements earlier runtime contracts and declared 0.17/0.18 ranges are refused.
2235
+ *
2236
+ * 0.19.1 adds `app.memory` note operations and `app.skills.propose` for pending suggestions.
2237
+ *
2238
+ * 0.19.2 adds the optional `app.sessions.readPage` (one bounded page of a stored transcript, or a
2239
+ * typed reason there is none) and `app.sessions.listSessionPage` (a page of the session index, or
2240
+ * rows by id), both under `sessions.read`; `app.knowledgeSearch` on `kay.app` under the `kay.app`
2241
+ * `knowledgeSearch` grant; and re-exports the record-kind helpers (`storedTranscriptKindOf`,
2242
+ * `parseStoredTranscriptKindFilter`) the daemon's reader numbers records with. Additive and
2243
+ * optional, so it takes the patch slot; plugins calling them feature-detect.
2244
+ *
2245
+ * 0.20.0 removes the unused activation-free advertisement helpers and their types from
2246
+ * `kay-agent` (#15160). No plugin used them, so 0.19.x stays served rather than refused, as with
2247
+ * 0.14.0; a 0.19.x plugin that imported one would now fail at load.
2248
+ *
2249
+ * 0.20.1 deletes `preflight.acceptsPayloadlessWrite` from URI modules (#15164). A `write` call
2250
+ * with neither `content` nor `source` now reaches the module's `write` with `content: undefined`,
2251
+ * and the module decides: a route that takes no body (a folder create) proceeds, and one that
2252
+ * needs a body refuses, naming what is missing. Only gdrive and microsoft declared the member,
2253
+ * and no SDK since 0.15.3 has been published, so the removal does not spend the minor slot.
2254
+ *
2255
+ * 0.20.2 lets a `kay.agent` manifest describe a tool whole (#15152): `parameters` (and with it a
2256
+ * required `description`), an `authService`/`authScheme` binding, and a `permission` (kind, rule
2257
+ * key, and the string arguments that name its resources). The host builds the tool from that entry,
2258
+ * and code supplies only the call through `api.implementTool(localId, execute)`. A plugin that runs
2259
+ * in the plugin host must describe its tools this way, because the daemon never loads its code.
2260
+ * Additive for every other plugin, so it takes the patch slot; plugins describing a tool declare
2261
+ * ^0.20.2.
2262
+ *
2263
+ * 0.21.0 makes sign-in manifest data (#15151). The host builds every auth service and scheme from
2264
+ * the manifest's `auth.services`, which gains OAuth endpoints, a public `clientId`, api-key
2265
+ * `inputLabel`/`fields`/`setup`/`validates` and a service `summary`. `api.auth` keeps only the
2266
+ * functions: `registerValidator` and `registerAccountResolver` replace `advertiseService` and the
2267
+ * `declare{OAuthPkce,ApiKey,ExternalCli}Scheme` calls. 0.19.x and 0.20.x stay served, as with
2268
+ * 0.20.0: most plugins declare no sign-in in code and are unaffected. One that does stops working
2269
+ * until it is rebuilt against 0.21: a manifest `oauth2` scheme without the now-required endpoints
2270
+ * is refused at load, and an activation that calls a removed member throws, so the plugin loses
2271
+ * its tools and URI modules too.
2272
+ *
2273
+ * 0.21.1 lets a URI module's `read` return its index form on `RawResource.observation`, from the
2274
+ * same fetch as the content, and deletes what steered the old second read (#15163): `observes`
2275
+ * on URI modules, `format: "observation"` on the read context, and `owns` on knowledge sources.
2276
+ * A plugin that still declares `owns` or `observes` loads, and the member is ignored. One that
2277
+ * omits `owns` needs this host, since an older one requires it. No SDK since 0.15.3 has been
2278
+ * published, so the removals take the patch slot, as in 0.20.1. It also adds `knownResourcesView`,
2279
+ * which marks a list or search rendered from the known-resources ledger so the host does not
2280
+ * record it back.
2281
+ *
2282
+ * 0.21.2 adds same-plugin informational tooltip apps to reference presentations, matched by
2283
+ * canonical resource URI patterns, and context-only apps excluded from standalone navigation.
2284
+ * Plugins declaring either require ^0.21.2.
2285
+ *
2286
+ * 0.22.0 deletes URI-module members the daemon used to call in a plugin's code (#15150):
2287
+ * `authActions.classifyOperation` (sign-in actions come from `authActions.rules`), `preflight` (the
2288
+ * verb rejects a bad call when it runs), `permission`, and `toMarkdown` (a verb's result carries
2289
+ * its own `markdown`); `@bonsai/plugin-sdk/kay-agent` stops re-exporting
2290
+ * `UriOperationPreflightPolicy`. A `kay.app` module also loses `matches`, `normalize` and
2291
+ * `describe`: it routes, spells and links its addresses through its claims' `normalizeTo`, `title`
2292
+ * and `sourceUrl`. The host drops these members from a 0.20.x or 0.21.x module rather than calling
2293
+ * them, and a module already claims every scheme it declares, so both stay served.
2294
+ *
2295
+ * 0.22.1 renames `RawResource.observation` to `observations`, a list (#15168), so one read can
2296
+ * index several documents: a Gmail thread read indexes each of its messages. A module that still
2297
+ * returns `observation` loads, and its read is not indexed. No SDK since 0.15.3 has been
2298
+ * published, so the rename takes the patch slot, as in 0.21.1. Plugins that return observations
2299
+ * and declare a floor require ^0.22.1.
2300
+ *
2301
+ * 0.22.2 lets a converter decline a file its `matches` claimed (#15153): `convert` may resolve
2302
+ * `undefined`, and the read pipeline tries the next converter that claimed the file. A plugin
2303
+ * whose converters only convert is unaffected; one that declines requires ^0.22.2, since an older
2304
+ * host reads the result's `content`. Additive, so it takes the patch slot.
2305
+ *
2306
+ * 0.23.0 trims the message approval type (#15154): `prepare` returns a promise, so the host can
2307
+ * call it across a process boundary; `tighten` is gone (no plugin set it, and an unknown member
2308
+ * is ignored); `resolveResource` is optional, for a provider that keeps no saved draft. A 0.22
2309
+ * plugin's synchronous `prepare` is still read correctly, because the host awaits what it
2310
+ * returns, so 0.22.x stays served.
2311
+ *
2312
+ * 0.23.0 also deletes `definePoller`'s `resolveCredential` option (#15154): the helper asks
2313
+ * `app.backgroundAuth` itself, and `requiredScopes` on a background credential request becomes
2314
+ * optional. Omitted, the host asks for the first scope of the manifest's `background-job` grant
2315
+ * (`allowedScopes`) that the account holds, and answers `requires-auth` when it holds none. A
2316
+ * 0.22.x plugin that passes `resolveCredential` still loads; the option is ignored, so its poller
2317
+ * needs a `background-job` grant whose `allowedScopes` the host can choose from.
2318
+ *
2319
+ * 0.23.0 also deletes `timezone` from a cron schedule (#15394): every schedule, a workflow trigger's
2320
+ * and an automation's, runs in the computer's current time zone and follows it when it changes.
2321
+ * A `define` or create that still passes `timezone` is refused, so a 0.22.x plugin that pins a
2322
+ * cron zone stops loading its workflow until it drops the field; every other 0.22.x plugin is
2323
+ * unaffected and stays served. Plugins that declare a cron trigger declare ^0.23.0, since an
2324
+ * older host requires the zone.
2325
+ *
2326
+ * 0.24.0 lets the daemon build a hosted plugin's URI module from its manifest alone (#15141).
2327
+ * The module facts gain `verbs.searchable`; resolved modules carry `displayName` and
2328
+ * `authServiceId`. Asana and Figma use their services' single auth scheme.
2329
+ *
2330
+ * 0.25.0 unifies URI writes (#15402): `write(input, content, sources, ctx)` receives an
2331
+ * empty sources array for ordinary writes. Modules that accept files declare
2332
+ * `acceptsWriteSources: true` in their manifest. Earlier SDK contracts are no longer served.
2333
+ *
2334
+ * 0.26.0 folds `writeBytes` into `write` (#15433): a binary `source` copy reaches `write` as a
2335
+ * `Uint8Array` content, named and typed by `ctx.writeSource`, and only for a module that declares
2336
+ * `acceptsBytes: true` in its manifest. A module that still defines `writeBytes` never receives
2337
+ * bytes. Earlier SDK contracts are no longer served.
2338
+ *
2339
+ * 0.26.1 turns the revision check into a conditional `read` (#15423). `ctx.knownRevision` carries
2340
+ * the revision the session holds, and a module that has verified the source has not moved returns
2341
+ * `{ content: "", unchanged: true, metadata: { revision } }` with no body. The module's `revision`
2342
+ * member is gone (the host drops a leftover one), so is `fallback` and `locate` (the host's own
2343
+ * modules keep them), and so is the manifest's `filesystemBacking`, which no plugin declared.
2344
+ * Additive for a plugin that never used them. A plugin that answers `unchanged` declares ^0.26.1.
2345
+ *
2346
+ * 0.26.2 lets a hosted URI module describe its calls for the approval card (#15423): a manifest
2347
+ * URI module sets `describesOperations: true` when its code defines `describeOperation`, and the
2348
+ * daemon calls the plugin host for it. `amendOperation` is gone: the host applies an "Allow with
2349
+ * edits" answer itself, replacing top-level string properties of the payload, so a preview field
2350
+ * is editable only when the payload is an object with that key as a string. `labelResource` is
2351
+ * gone: a verb's result carries the transcript row's name as `label`. The SDK stops re-exporting
2352
+ * `UriOperationAmendment`, `UriResourceLabelRequest` and `UriPreviewEdit`. The host ignores a
2353
+ * leftover `amendOperation` or `labelResource`, so this is additive for a plugin that never sets
2354
+ * the flag; a plugin whose manifest sets `describesOperations` declares ^0.26.2.
2355
+ *
2356
+ * 0.26.3 gives a plugin's own sign-in back what #15151 left behind (#15195). Every `oauth2` sign-in a
2357
+ * plugin runs says where its account comes from: `account` is `"resolveAccountId"`,
2358
+ * `"resolveAccounts"` or, on a hosted (`confidential`) sign-in whose broker names the account,
2359
+ * `"sign-in"`, so each account a person signs in with is saved apart. `api.auth.registerAccountResolver`
2360
+ * registers the named function on any such scheme, its own client's included, and the SDK refuses a
2361
+ * plugin whose lookup and manifest disagree. An own-client (`pkce`) scheme may carry the
2362
+ * `clientSecret` that goes with its `clientId`. A plugin with an `oauth2` sign-in declares ^0.26.3.
2363
+ */
2364
+ declare const KAY_PLUGIN_SDK_VERSION: "0.26.3";
2365
+
2366
+ declare const KAY_PLUGIN_TARGET_NAMES: readonly ["kay.agent", "kay.app", "kay.ui"];
2367
+
2368
+ /** Browser compilation over caller-supplied bytes, without filesystem or network authority. */
2369
+ declare interface KayAgentCompiler {
2370
+ /** Rejects on compilation or source callback failure, and when the host composed no compiler. */
2371
+ bundleBrowser(request: KayBrowserBundleRequest, sources: KayBrowserSources): Promise<KayBrowserBundle>;
2372
+ }
2373
+
2374
+ /**
2375
+ * The plugin-facing `kay.agent` own-endpoint call: a plugin's agent part calls an endpoint its own
2376
+ * `kay.app` part registered. SDK 0.17.3; a plugin that calls it declares `compatibility.sdk`
2377
+ * `^0.19.0`.
2378
+ *
2379
+ * A plugin's two parts load as separate modules and share no memory, so this is how agent code
2380
+ * reaches state its app part keeps (a worker, a database). The manifest says which endpoints the
2381
+ * agent part may call: the `kay.app` target declares the endpoint with a `register` grant, and
2382
+ * `permissions.byTarget["kay.agent"].endpoints` lists it with `invoke`. No other plugin's endpoint
2383
+ * is nameable.
2384
+ *
2385
+ * An endpoint whose only `invoke` grant is the plugin's own `kay.agent` target is not reachable
2386
+ * from Bonsai's surfaces (its pages and runtime clients), so an action the agent takes after the
2387
+ * session's approval card cannot be taken around it.
2388
+ */
2389
+ /** Why an {@link KayAgentEndpoints.invoke} call produced no value. */
2390
+ declare type KayAgentEndpointFailureReason =
2391
+ /** The manifest grants this plugin's `kay.agent` target no `invoke` on this endpoint. */
2392
+ "not-declared"
2393
+ /** The plugin's `kay.app` part is not running, or registered no handler for it. */
2394
+ | "unavailable"
2395
+ /** The handler did not answer within the host's fixed deadline (10 seconds). It may still finish. */
2396
+ | "timed-out"
2397
+ /** The caller's `signal` aborted. The handler may still finish. */
2398
+ | "cancelled"
2399
+ /** The handler threw; `message` is its error's message. */
2400
+ | "failed"
2401
+ /** The request or the handler's response does not match the endpoint's declared schema. */
2402
+ | "invalid";
2403
+
2404
+ declare type KayAgentEndpointOutcome = {
2405
+ readonly ok: true;
2406
+ readonly value: unknown;
2407
+ } | {
2408
+ readonly ok: false;
2409
+ readonly reason: KayAgentEndpointFailureReason;
2410
+ readonly message: string;
2411
+ };
2412
+
2413
+ declare interface KayAgentEndpoints {
2414
+ /**
2415
+ * Call `endpoint`, the local id this plugin's manifest declares on its `kay.app` target. Never
2416
+ * rejects: every failure is an outcome. Nothing is queued: when the app part is not running the
2417
+ * answer is `unavailable` at once.
2418
+ */
2419
+ invoke(endpoint: string, payload: unknown, options?: {
2420
+ readonly signal?: AbortSignal;
2421
+ }): Promise<KayAgentEndpointOutcome>;
2422
+ }
2423
+
1641
2424
  /**
1642
2425
  * Publishes the plugin's declared events from agent code. See {@link KayAgentPluginApi.events}.
1643
2426
  */
@@ -1681,7 +2464,7 @@ declare interface KayAgentInteractionSurfaces {
1681
2464
  readonly desktop: InteractionSurface;
1682
2465
  }
1683
2466
 
1684
- /** One knowledge-index hit — a reference and within-list rank score, never a snippet. */
2467
+ /** One knowledge-index hit - a reference and within-list rank score, never a snippet. */
1685
2468
  declare interface KayAgentKnowledgeHit {
1686
2469
  readonly uri: string;
1687
2470
  /** Comparable only with other hits returned by this search call. */
@@ -1691,7 +2474,7 @@ declare interface KayAgentKnowledgeHit {
1691
2474
  /**
1692
2475
  * Query the daemon's shared knowledge index, scoped to this plugin's own declared `kay.agent`
1693
2476
  * schemes. Deny-by-default: `api.knowledgeSearch` is absent unless the manifest requests the
1694
- * `knowledgeSearch` grant AND the host effectively grants it — a plugin must feature-detect the
2477
+ * `knowledgeSearch` grant AND the host effectively grants it - a plugin must feature-detect the
1695
2478
  * capability. (It is WIRING, so absence is still the signal here, unlike the claim-checked
1696
2479
  * capabilities around it.) The host pre-scopes every call to the
1697
2480
  * plugin's OWN declared URI schemes; a caller-supplied `uriPrefixes` outside that scope is dropped
@@ -1707,7 +2490,7 @@ declare type KayAgentKnowledgeSearch = (query: string, opts?: {
1707
2490
  /**
1708
2491
  * One row of the daemon's known-resources ledger: a resource the host has
1709
2492
  * observed flowing through one of this plugin's own URI modules (or recorded
1710
- * through a host-side grant flow). Metadata facts, never content — content
2493
+ * through a host-side grant flow). Metadata facts, never content - content
1711
2494
  * understanding stays with the knowledge index.
1712
2495
  */
1713
2496
  declare interface KayAgentKnownResource {
@@ -1722,7 +2505,7 @@ declare interface KayAgentKnownResource {
1722
2505
  readonly seenVia: KayAgentKnownResourceSeenVia;
1723
2506
  /**
1724
2507
  * Durable grant provenance (`picked` for a Drive-picker grant). Unlike `seenVia`, a later
1725
- * ordinary sighting never erases it — the row permanently remembers it entered the corpus
2508
+ * ordinary sighting never erases it - the row permanently remembers it entered the corpus
1726
2509
  * through an explicit user grant.
1727
2510
  */
1728
2511
  readonly grantedVia?: string;
@@ -1741,12 +2524,12 @@ declare interface KayAgentKnownResource {
1741
2524
  * (the host-recorded memory that `contributes.uriModules[].knownResources`
1742
2525
  * opts a module's traffic into). Deny-by-default: `api.knownResources` is
1743
2526
  * absent unless the manifest requests the `knownResources` grant AND the host
1744
- * effectively grants it — feature-detect it exactly like
2527
+ * effectively grants it - feature-detect it exactly like
1745
2528
  * {@link KayAgentKnowledgeSearch}, the other WIRING capability. Every call is host-scoped to the plugin's
1746
2529
  * OWN declared module ids; there is no way to widen it. Read-only by design:
1747
2530
  * rows are created only by the host's recording wrap and host-side grant
1748
2531
  * writers, so a plugin can render its memory but never invent it. The ledger
1749
- * is a cache of CLAIMS, not an authority — a returned row proves the resource
2532
+ * is a cache of CLAIMS, not an authority - a returned row proves the resource
1750
2533
  * was once seen, never that it is still reachable.
1751
2534
  */
1752
2535
  declare interface KayAgentKnownResources {
@@ -1776,7 +2559,7 @@ declare interface KayAgentKnownResources {
1776
2559
  * How a known-resource row was MOST RECENTLY seen: one of the recording
1777
2560
  * wrap's verbs, or a host-side grant writer's `granted:<label>` (e.g. a
1778
2561
  * Drive picker completion writing `granted:picked`). The closed template
1779
- * union keeps the contract honest without enumerating grant labels — a
2562
+ * union keeps the contract honest without enumerating grant labels - a
1780
2563
  * plain-string widening here would silently admit junk provenance.
1781
2564
  */
1782
2565
  declare type KayAgentKnownResourceSeenVia = "read" | "list" | "search" | `granted:${string}`;
@@ -1785,7 +2568,7 @@ declare type KayAgentKnownResourceSeenVia = "read" | "list" | "search" | `grante
1785
2568
  * Claim-checked outbound HTTP. The handle is always present; authority is the CALL, not the handle.
1786
2569
  *
1787
2570
  * The signature is `fetch`'s on purpose: a plugin that already speaks `fetch` changes the object it
1788
- * calls, not the code around it. What differs is invisible from here — the host builds an exact
2571
+ * calls, not the code around it. What differs is invisible from here - the host builds an exact
1789
2572
  * `network.connect {connect}` claim from the live URL (and again from each redirect hop), checks it
1790
2573
  * against the user's grant ledger, and rejects with a {@link KayAgentCapabilityError} rather than
1791
2574
  * performing the request. There is no `allowedHosts` to read: a plugin cannot enumerate its own
@@ -1810,13 +2593,19 @@ declare interface KayAgentPluginApi {
1810
2593
  readonly knowledgeSearch?: KayAgentKnowledgeSearch;
1811
2594
  /** Absent unless the `knownResources` grant is requested and effectively granted. */
1812
2595
  readonly knownResources?: KayAgentKnownResources;
2596
+ /**
2597
+ * Optional: absent unless a simulating Bonsai daemon serves this plugin a simulator (SDK 0.18.1).
2598
+ * A production daemon never does. In this version only plugins the release carries are served;
2599
+ * any plugin may ship a `./simulator` later. See {@link KayServedSimulators}.
2600
+ */
2601
+ readonly servedSimulators?: KayServedSimulators;
1813
2602
  /**
1814
2603
  * Present when the host composes Whiteboard. Each operation is checked against its exact
1815
2604
  * `whiteboard.<operation> {scope}` claim; handle presence is not consent.
1816
2605
  */
1817
2606
  readonly whiteboard?: KayAgentWhiteboard;
1818
2607
  /**
1819
- * Always present; each request — and each redirect hop — is checked against
2608
+ * Always present; each request - and each redirect hop - is checked against
1820
2609
  * `network.connect {connect}` for the host it is about to reach.
1821
2610
  */
1822
2611
  readonly network: KayAgentNetwork;
@@ -1847,6 +2636,8 @@ declare interface KayAgentPluginApi {
1847
2636
  * (SDK 0.13.8).
1848
2637
  */
1849
2638
  readonly systemOne: SystemOneClient;
2639
+ /** Always present and ungated; compiles only caller-supplied bytes. SDK 0.18.4. */
2640
+ readonly compiler: KayAgentCompiler;
1850
2641
  /**
1851
2642
  * The daemon's clock and the time zone the user is in, read together on each `snapshot()` call.
1852
2643
  * Always present and ungated: it confers no authority, since a plugin runs in the daemon's
@@ -1869,18 +2660,50 @@ declare interface KayAgentPluginApi {
1869
2660
  */
1870
2661
  readonly events: KayAgentEvents;
1871
2662
  /**
1872
- * Register a tool (a named function the agent can call). Parallel to the kernel's `registerTool`.
1873
- * To auth-gate a tool, build the definition with {@link withResolvedAuth}: it stamps the
1874
- * `requiresAuth` binding onto the definition and resolves a live token from the kernel-injected
1875
- * `ctx.auth` before the body runs — the same wrapper the built-in service tools use. A definition
1876
- * with no `requiresAuth` is an ordinary always-on tool.
2663
+ * A logger whose lines land in Bonsai's own log under this plugin's id, filed on this
2664
+ * activation's session. Always present and ungated, like {@link time}. Use it instead of
2665
+ * `console`; see {@link KayPluginLog}.
2666
+ */
2667
+ readonly log: KayPluginLog;
2668
+ /**
2669
+ * Calls tools on the vendored MCP servers this plugin declares (`kay.app`
2670
+ * `contributes.mcpServers`), signed in through the plugin's own auth service. A port reaches
2671
+ * only this plugin's own server, and only while Bonsai hosts it for this plugin under its
2672
+ * `mcp.host-server` grant; it never reaches another plugin's server or one the user configured.
2673
+ * It calls any tool the server has, writes included. Always present; a host with no MCP host
2674
+ * answers each call `failed`. Types: `@bonsai/plugin-sdk/vendored-mcp` (SDK 0.16.2).
2675
+ */
2676
+ readonly vendoredMcp: KayAgentVendoredMcp;
2677
+ /**
2678
+ * Calls the endpoints this plugin's own `kay.app` part registered and the manifest grants this
2679
+ * target `invoke` on, by local id. Never another plugin's. Every failure is an outcome, never a
2680
+ * rejection; the host fixes a 10-second deadline. Always present; a host with no app part
2681
+ * answers each call `unavailable`. See {@link KayAgentEndpoints} (SDK 0.17.3).
2682
+ */
2683
+ readonly endpoints: KayAgentEndpoints;
2684
+ /**
2685
+ * Supply the `execute` of a tool kay-plugin.json describes (its entry declares `parameters`),
2686
+ * by the entry's `localId`. The host builds the rest of the tool - name, label, description,
2687
+ * parameters, auth binding and permission - from that entry. Build `execute` with
2688
+ * {@link toolExecute}. For a tool declaring `authService`, a session resolves the credential
2689
+ * onto `ctx.credential` before each call (for the account its `accountId` argument names, when
2690
+ * the tool declares one) and never calls `execute` without one; outside a session it may be
2691
+ * absent (SDK 0.20.2).
2692
+ */
2693
+ implementTool(localId: string, execute: KayAgentToolExecute): void;
2694
+ /**
2695
+ * Register a whole tool definition, for a declared tool whose entry has no `parameters` because
2696
+ * part of its policy is code. Such a plugin cannot run in the plugin host; prefer
2697
+ * {@link implementTool}. To auth-gate one, build the definition with {@link withResolvedAuth}
2698
+ * (or `defineAuthedTool`).
1877
2699
  */
1878
2700
  registerTool(definition: ToolDefinition): void;
1879
2701
  /**
1880
2702
  * Register a web search provider (a backend behind the single `web_search` tool). Parallel to the
1881
- * kernel's `registerSearchProvider`. An own-credential provider carries its `requiresAuth` binding —
1882
- * build it with {@link withResolvedSearchProvider}, which stamps the binding and resolves the token
1883
- * from `ctx.auth`. A provider without a binding reuses inference credentials or needs none.
2703
+ * kernel's `registerSearchProvider`. An own-credential provider carries its `requiresAuth` binding -
2704
+ * build it with {@link withResolvedSearchProvider}, which stamps the binding; the host resolves the
2705
+ * credential before each call and hands it to the body. A provider without a binding reuses
2706
+ * inference credentials or needs none.
1884
2707
  */
1885
2708
  registerSearchProvider(provider: SearchProvider): void;
1886
2709
  /**
@@ -1899,23 +2722,34 @@ declare interface KayAgentPluginApi {
1899
2722
  registerConverter(converter: ContentConverter): void;
1900
2723
  /**
1901
2724
  * Always present; the registration is checked against `tool-interception.register`. Register
1902
- * a tool-call interceptor — the neutral around-execution seam over EVERY tool call in the session
2725
+ * a tool-call interceptor - the neutral around-execution seam over EVERY tool call in the session
1903
2726
  * (any layer's tools, subagent sessions included): observe a call, delegate to the real tool via
1904
2727
  * `next()`, or return a substitute result so the real tool never runs. Materially higher
1905
2728
  * privilege than `registerTool` (which owns only its own tool), which is why the registration is
1906
- * a claim of its own. The permission gate still runs before execution — an interceptor can
2729
+ * a claim of its own. The permission gate still runs before execution - an interceptor can
1907
2730
  * substitute results, never widen what is callable.
1908
2731
  */
1909
2732
  interceptToolCall(interceptor: ToolCallInterceptor): void;
2733
+ /**
2734
+ * Sign-in. The plugin's manifest (`auth.services`) declares every service and scheme and the
2735
+ * facts the host shows and runs; plugin code registers only the functions a scheme needs.
2736
+ */
1910
2737
  readonly auth: {
1911
- advertiseService(descriptor: PluginServiceDescriptor): void;
1912
- declareOAuthPkceScheme(serviceId: string, scheme: PluginOAuthPkceScheme): void;
1913
- declareApiKeyScheme(serviceId: string, scheme: PluginApiKeyScheme): void;
1914
- declareExternalCliScheme(serviceId: string, scheme: PluginExternalCliScheme): void;
2738
+ /**
2739
+ * The check for an `api-key` scheme the manifest marks `validates: true`. `serviceId` and
2740
+ * `schemeId` are the manifest's global ids (`github.account`, `github.pat`).
2741
+ */
2742
+ registerValidator(serviceId: string, schemeId: string, validate: ValidatePluginApiKeyCredential): void;
2743
+ /**
2744
+ * The account lookup for an `oauth2` scheme whose manifest names it as where the account comes
2745
+ * from (`account: "resolveAccountId"` or `"resolveAccounts"`), registering that function only.
2746
+ * Refused on any other scheme.
2747
+ */
2748
+ registerAccountResolver(serviceId: string, schemeId: string, resolver: PluginAccountResolver): void;
1915
2749
  /**
1916
2750
  * Declare a delegated scheme (plugin-provided connect/refresh over opaque material) for a
1917
- * service. Mirrors the other three declarations; the host maps it onto the kernel's
1918
- * `DelegatedAuthScheme` and drives its `connect` from `service_connect`.
2751
+ * service. The host maps it onto the kernel's `DelegatedAuthScheme` and drives its `connect`
2752
+ * from `service_connect`.
1919
2753
  */
1920
2754
  declareDelegatedScheme(serviceId: string, scheme: PluginDelegatedScheme): void;
1921
2755
  /**
@@ -1935,7 +2769,7 @@ declare interface KayAgentPluginApi {
1935
2769
  * {@link KayAgentProcessRunResult.exitCode} always means the command itself failed, never that
1936
2770
  * permission did. Two DIFFERENT things reject, and a caller should handle both: a refusal rejects
1937
2771
  * with {@link KayAgentCapabilityError}, and cancelling through
1938
- * {@link KayAgentProcessRunRequest.signal} rejects with an `AbortError` carrying a fixed message —
2772
+ * {@link KayAgentProcessRunRequest.signal} rejects with an `AbortError` carrying a fixed message -
1939
2773
  * the host terminates the child and settles its output first, and deliberately does not echo back
1940
2774
  * the `reason` you aborted with. A user cancelling a run is not a crash. A timeout is NOT a
1941
2775
  * rejection: it resolves with exit code 124. The termination bound covers the DIRECT child only: a
@@ -1959,12 +2793,12 @@ declare interface KayAgentProcessRunRequest {
1959
2793
  readonly command: string;
1960
2794
  readonly argvClass: string;
1961
2795
  readonly args: readonly string[];
1962
- /** Abort the run; the host kills the DIRECT child and rejects — a forked descendant may outlive it (#6153). */
2796
+ /** Abort the run; the host kills the DIRECT child and rejects - a forked descendant may outlive it (#6153). */
1963
2797
  readonly signal?: AbortSignal;
1964
2798
  }
1965
2799
 
1966
2800
  /**
1967
- * A finished run. `stdout`/`stderr` are decoded text, and the host CAPS them — a truncation flag is
2801
+ * A finished run. `stdout`/`stderr` are decoded text, and the host CAPS them - a truncation flag is
1968
2802
  * set rather than the output silently ending, so a plugin parsing the stream can tell "the command
1969
2803
  * printed this" apart from "the command printed more than we kept".
1970
2804
  */
@@ -1976,6 +2810,28 @@ declare interface KayAgentProcessRunResult {
1976
2810
  readonly stderrTruncated?: boolean;
1977
2811
  }
1978
2812
 
2813
+ /** The `execute` a plugin supplies for a tool its manifest describes. */
2814
+ declare type KayAgentToolExecute = ToolDefinition["execute"];
2815
+
2816
+ /**
2817
+ * Calls tools on the plugin's own vendored MCP servers. See {@link KayAgentPluginApi.vendoredMcp}.
2818
+ */
2819
+ declare interface KayAgentVendoredMcp {
2820
+ /**
2821
+ * The port to `server`, a name this plugin declares in its `kay.app` target's
2822
+ * `contributes.mcpServers`. Throws when the plugin declares no server of that name. A declared
2823
+ * server that Bonsai does not host for this plugin still returns a port; each call then answers
2824
+ * `unknown-server`. Its message names the plugin that holds the name, or else lists the possible
2825
+ * reasons (no approved `mcp.host-server` grant, a sign-in the server cannot use, or a name that
2826
+ * a plugin Bonsai ships or another installed plugin also claims) and points at the plugin's load
2827
+ * diagnostic.
2828
+ *
2829
+ * A port reaches this plugin's own server only. To use another plugin's data, declare that
2830
+ * plugin in the manifest's `dependencies.plugins`; a later SDK surface reaches it.
2831
+ */
2832
+ port<TTool extends string = string>(server: string): VendoredMcpPort<TTool>;
2833
+ }
2834
+
1979
2835
  /**
1980
2836
  * Authenticated requests through the host's embedded-browser partition. The host confines every
1981
2837
  * call to the exact origin/path rows declared in the plugin manifest (segment-bounded), never
@@ -2094,7 +2950,7 @@ declare interface KayAgentWhiteboardUpdateInput {
2094
2950
  /**
2095
2951
  * `app.time` / `api.time`: host facts about time. Added to `kay.app` in SDK 0.12.1 and to
2096
2952
  * `kay.agent` with the calendar zone-of-record work: a plugin that calls it declares
2097
- * `compatibility.sdk` `^0.12.1`, so an older Bonsai refuses a directory or repository plugin at
2953
+ * `compatibility.sdk` `^0.19.0`, so an older Bonsai refuses a directory or repository plugin at
2098
2954
  * load instead of the call failing.
2099
2955
  */
2100
2956
  declare interface KayAppTime {
@@ -2104,9 +2960,7 @@ declare interface KayAppTime {
2104
2960
  * Every call asks the host again and returns a new object; nothing is cached. Call it where you
2105
2961
  * need the value (inside a tool, a handler or a workflow step), not inside `activate()`: a value
2106
2962
  * read there is as old as the activation, and the host can run a bundled plugin's `activate()`
2107
- * against a recording api that has no `time`, so a read there throws. The exception is a
2108
- * directory plugin that declares a workflow with a cron `timezone`: `workflows.define` is legal
2109
- * only during `activate()`, so it reads the zone there, and the schedule then keeps that zone.
2963
+ * against a recording api that has no `time`, so a read there throws.
2110
2964
  * Keep the result for as long as you use it, and not across a long wait (a sleep, a timer, a
2111
2965
  * queued run): the zone can change while you wait. On a daemon that runs on the user's machine,
2112
2966
  * a change of the process's `TZ` shows in the next call. A `TZ` that names a zone wins over the
@@ -2197,7 +3051,7 @@ declare interface KayAppUserFileListing {
2197
3051
  * File I/O in user folders, run by the host off the daemon's main thread. Every path is absolute.
2198
3052
  * No method rejects; each answers a {@link KayAppUserFilesResult}. This is not a sandbox: it does
2199
3053
  * not limit which paths a plugin may touch. Added in SDK 0.12.5: a plugin that calls it declares
2200
- * `compatibility.sdk` `^0.12.5`, so an older Bonsai refuses a directory or repository plugin at
3054
+ * `compatibility.sdk` `^0.19.0`, so an older Bonsai refuses a directory or repository plugin at
2201
3055
  * load instead of the call failing.
2202
3056
  */
2203
3057
  declare interface KayAppUserFiles {
@@ -2293,6 +3147,119 @@ declare interface KayAppUserFileWalkEntry {
2293
3147
  readonly kind: KayAppUserFileKind;
2294
3148
  }
2295
3149
 
3150
+ declare interface KayBrowserBundle {
3151
+ readonly outputs: readonly {
3152
+ readonly path: string;
3153
+ readonly text: string;
3154
+ }[];
3155
+ readonly warnings: readonly string[];
3156
+ }
3157
+
3158
+ declare interface KayBrowserBundleRequest {
3159
+ readonly entry: {
3160
+ readonly path: string;
3161
+ } | {
3162
+ readonly path: string;
3163
+ readonly contents: string;
3164
+ readonly loader: "js" | "css";
3165
+ };
3166
+ readonly target: string;
3167
+ readonly format: "iife" | "esm";
3168
+ readonly charset: "ascii" | "utf8";
3169
+ readonly minifyWhitespace: boolean;
3170
+ readonly legalComments: "none" | "inline";
3171
+ }
3172
+
3173
+ /** Import edges the host reports to a browser bundle's source resolver. */
3174
+ declare type KayBrowserImportKind = "entry-point" | "import-statement" | "require-call" | "dynamic-import" | "require-resolve" | "import-rule" | "composes-from" | "url-token";
3175
+
3176
+ /** All imports and bytes come from these callbacks; the host performs no fallback I/O. */
3177
+ declare interface KayBrowserSources {
3178
+ resolve(request: {
3179
+ readonly path: string;
3180
+ readonly importer: string;
3181
+ readonly kind: KayBrowserImportKind;
3182
+ }): Promise<{
3183
+ readonly path: string;
3184
+ readonly external?: boolean;
3185
+ readonly suffix?: string;
3186
+ }>;
3187
+ load(request: {
3188
+ readonly path: string;
3189
+ }): Promise<{
3190
+ readonly contents: string | Uint8Array;
3191
+ readonly loader: "js" | "css" | "json" | "dataurl";
3192
+ }>;
3193
+ }
3194
+
3195
+ /**
3196
+ * Each method writes one line. `name` is a stable event name (`sync-failed`), the same for every
3197
+ * line of one kind, so the line can be found by name; put what varies in `message` and
3198
+ * `attributes`. A call never throws, and it keeps working after the plugin is disabled.
3199
+ */
3200
+ declare interface KayPluginLog {
3201
+ debug(name: string, message: string, details?: KayPluginLogDetails): void;
3202
+ info(name: string, message: string, details?: KayPluginLogDetails): void;
3203
+ warn(name: string, message: string, details?: KayPluginLogDetails): void;
3204
+ error(name: string, message: string, details?: KayPluginLogDetails): void;
3205
+ /** A logger that adds these attributes to every line it writes, after the line's own. */
3206
+ child(attributes: KayPluginLogAttributes): KayPluginLog;
3207
+ }
3208
+
3209
+ /**
3210
+ * The plugin-facing log contract: a logger each plugin gets as `api.log`, whose lines land in
3211
+ * Bonsai's own log beside the daemon's.
3212
+ *
3213
+ * Ungated and always present, like `api.time`. It confers no authority: a line is written under the
3214
+ * plugin's own id, which the host stamps and the plugin cannot set, and a plugin can already print
3215
+ * to the console. The host records each line as `<pluginId>.<name>`, files it on a session's log
3216
+ * when it knows the session, and keeps an error's stack, so a built-in plugin's failure reaches
3217
+ * Error Tracking. Lines from a plugin the user added stay on the user's machine.
3218
+ *
3219
+ * This is a leaf module. It lives beside both target SDKs (rather than inside `kay-app`) so the
3220
+ * `kay.agent` SDK can expose the same logger without importing the `kay.app` surface.
3221
+ */
3222
+ /**
3223
+ * Metadata only: ids, closed values, counts. Never session content. The host drops any value that
3224
+ * is not a string, a boolean or a finite number.
3225
+ */
3226
+ declare type KayPluginLogAttributes = Readonly<Record<string, string | number | boolean>>;
3227
+
3228
+ declare interface KayPluginLogDetails {
3229
+ /** The error object. The host keeps its message, its stack and its `cause` chain. */
3230
+ readonly error?: unknown;
3231
+ /**
3232
+ * The session this line is about. Defaults to the session of the call the plugin is handling,
3233
+ * when the host knows it (a tool call or a URI read); the line then lands on that session's
3234
+ * `kay-log://events`. Pass it from an endpoint, a session-event handler or a timer. Work a call
3235
+ * starts (a timer, a subscription) keeps that call's session unless a line names another.
3236
+ */
3237
+ readonly sessionId?: string;
3238
+ readonly attributes?: KayPluginLogAttributes;
3239
+ }
3240
+
3241
+ declare const KayPluginProtocolVersion: z.ZodLiteral<"kay.plugin.v1">;
3242
+
3243
+ declare type KayPluginProtocolVersion = z.infer<typeof KayPluginProtocolVersion>;
3244
+
3245
+ /**
3246
+ * The simulators a simulating Bonsai daemon (evals, dev, tests) serves this plugin, keyed by the
3247
+ * adapter id its simulated URI connection rows name. The daemon builds each from the plugin's own
3248
+ * dev-only `./simulator` subpath; the plugin never imports its simulator.
3249
+ *
3250
+ * The member that carries this, `servedSimulators` on both plugin APIs, is optional and absent
3251
+ * unless a simulating daemon serves it. A production daemon never does, so treat absence as the
3252
+ * normal case. In this version the daemon serves it only to plugins the release carries; the seam
3253
+ * is not specific to them, and any plugin may ship a `./simulator` later.
3254
+ */
3255
+ declare interface KayServedSimulators {
3256
+ /**
3257
+ * What this plugin's simulator built for `adapterId`, or `undefined` when none was served for
3258
+ * that id. The shape is the plugin's own simulator contract; narrow it before use.
3259
+ */
3260
+ get(adapterId: string): unknown;
3261
+ }
3262
+
2296
3263
  /** Applies a KeyOf action to the given type. */
2297
3264
  declare function KeyOf<Type extends TSchema>(type: Type, options?: TSchemaOptions): TKeyOf_2<Type>;
2298
3265
 
@@ -2398,6 +3365,10 @@ declare function LiteralStringMapping(input: string): unknown;
2398
3365
 
2399
3366
  declare function LiteralTypeName<Value extends TLiteralValue>(value: Value): TLiteralTypeName<Value>;
2400
3367
 
3368
+ declare const LocalContributionId: z.ZodString;
3369
+
3370
+ declare type LocalContributionId = z.infer<typeof LocalContributionId>;
3371
+
2401
3372
  /** Applies a Lowercase action to the given type. */
2402
3373
  declare function Lowercase_2<Type extends TSchema>(type: Type, options?: TSchemaOptions): TLowercase<Type>;
2403
3374
 
@@ -2471,7 +3442,7 @@ declare type MidTurnCompactionRequest = {
2471
3442
  * Settles exactly once and never rejects, including abort and teardown paths.
2472
3443
  *
2473
3444
  * NEVER `await` this inside `execute`. The only thing that settles it is
2474
- * post-run compaction, and that cannot begin until this tool call returns —
3445
+ * post-run compaction, and that cannot begin until this tool call returns -
2475
3446
  * so awaiting it here hangs the run behind itself, which is the exact
2476
3447
  * deadlock this capability replaced. Attach a callback and return.
2477
3448
  */
@@ -2481,6 +3452,10 @@ declare type MidTurnCompactionRequest = {
2481
3452
  readonly reason: "already-pending" | "maintenance-in-flight";
2482
3453
  };
2483
3454
 
3455
+ declare const MimeTypeString: z.ZodString;
3456
+
3457
+ declare type MimeTypeString = z.infer<typeof MimeTypeString>;
3458
+
2484
3459
  /** Compatibility settings for the Mistral chat API. */
2485
3460
  declare interface MistralConversationsCompat extends Static<typeof MistralConversationsCompatSchema> {
2486
3461
  }
@@ -2516,7 +3491,7 @@ declare interface Model<TApi extends Api> extends BaseModel<TApi> {
2516
3491
  }
2517
3492
 
2518
3493
  /**
2519
- * The canonical model-facing content type — the single source of truth for what
3494
+ * The canonical model-facing content type - the single source of truth for what
2520
3495
  * a `read`/`finalize` boundary emits and what an {@link AgentToolResult.content}
2521
3496
  * carries (it IS the same `(TextContent | ImageContent)` union). When pi-ai later
2522
3497
  * adds audio, this one alias widens and every consumer follows.
@@ -2601,6 +3576,8 @@ declare const NeverPattern = "(?!)";
2601
3576
 
2602
3577
  declare const NewLine = "\n";
2603
3578
 
3579
+ declare const NonEmptyString: z.ZodString;
3580
+
2604
3581
  /** Applies a NonNullable action to the given type. */
2605
3582
  declare function NonNullable_2<Type extends TSchema>(type: Type, options?: TSchemaOptions): TNonNullable<Type>;
2606
3583
 
@@ -2622,33 +3599,12 @@ declare const NumberKey = "^-?(?:0|[1-9][0-9]*)(?:\\.[0-9]+)?$";
2622
3599
 
2623
3600
  declare const NumberPattern = "-?(?:0|[1-9][0-9]*)(?:\\.[0-9]+)?";
2624
3601
 
2625
- /**
2626
- * Who may supply the OAuth client for a scheme: Bonsai's embedded client, or one the user pastes in
2627
- * (BYOOC). An UNORDERED SET — list order carries no meaning (nothing reads it as a preference).
2628
- */
2629
- declare type OAuthClientSupplier = "kay" | "user";
2630
-
2631
3602
  /** What the provider hands back at the redirect URI after the user approves. */
2632
3603
  declare interface OAuthRedirectResult {
2633
3604
  readonly code: string;
2634
3605
  readonly state: string;
2635
3606
  }
2636
3607
 
2637
- /**
2638
- * The two client-supply axes, structured so the illegal cell is unrepresentable: a `confidential`
2639
- * exchange's secret may only ever be Bonsai's (held by the host's broker, never pasted by a
2640
- * customer), so `confidential` types `clientSuppliers` as `readonly ["kay"]` — `confidential ×
2641
- * user` is a compile-time impossibility in v1, not a runtime refusal. `pkce`'s `clientSuppliers`
2642
- * is a non-empty set; {@link createOAuthPkceAuthScheme} dedupes it and refuses empty.
2643
- */
2644
- declare type OAuthSchemeClientAxes = {
2645
- readonly exchange: "pkce";
2646
- readonly clientSuppliers: readonly OAuthClientSupplier[];
2647
- } | {
2648
- readonly exchange: "confidential";
2649
- readonly clientSuppliers: readonly ["kay"];
2650
- };
2651
-
2652
3608
  /** Creates an Object type. */
2653
3609
  declare function _Object_<Properties extends TProperties>(properties: Properties, options?: TObjectOptions): TObject<Properties>;
2654
3610
 
@@ -2667,6 +3623,79 @@ declare type ObjectLike_4 = Record<PropertyKey, any>;
2667
3623
  /** Extracts options from a TObject. */
2668
3624
  declare function ObjectOptions(type: TObject): TObjectOptions;
2669
3625
 
3626
+ /**
3627
+ * A source-native read of one URI, shaped for downstream indexing rather than
3628
+ * direct model consumption. A module's read returns it in
3629
+ * `RawResource.observations`, built from the same fetch as the content, once
3630
+ * per document it wants indexed; absence means "not indexed".
3631
+ *
3632
+ * Gone signal: the index retires a doc when a read throws `UriNotFoundError`
3633
+ * or an error whose `.status === 404`. A module whose vendor signals "gone"
3634
+ * differently (HTTP 410, a 200-body `{ok:false}`/`archived:true`, a
3635
+ * 403/404-ambiguous lost-access response) must translate that into one of
3636
+ * those two shapes itself; losing access to a resource counts as gone too.
3637
+ * A read that cannot build a complete observation (a secondary fetch failed)
3638
+ * returns none rather than a partial one.
3639
+ *
3640
+ * Account-qualified identity: a module whose read can resolve against more
3641
+ * than one connected account (the account selector is stripped before route
3642
+ * parsing, so two accounts reading the same opaque provider id would
3643
+ * otherwise collide on one doc key) must fold `ctx.auth.credential.accountId`
3644
+ * into `uri` - e.g. `gmail://@<accountId>/threads/<threadId>` - never the
3645
+ * user-renamable connection/selector label. `ctx.auth.credential` is the
3646
+ * reliable source of the resolved account at a `requiresAuth` module's
3647
+ * `read()`: it is always populated once auth resolution runs (an
3648
+ * `authContext`-style check already throws first when no credential
3649
+ * resolved). `ctx.connection` may ALSO be populated by dispatch - a
3650
+ * connection-required module receives it whenever the host has a tracked
3651
+ * connection for the account - so do not assume it is absent; a module that
3652
+ * wants the human-facing label rather than the account id reads
3653
+ * `ctx.connection?.displayName`.
3654
+ *
3655
+ * `accountId` is guaranteed stable only for the life of the stored credential
3656
+ * record, not necessarily across a disconnect/reconnect of the same
3657
+ * real-world provider account. A scheme that mints an opaque id at connect
3658
+ * time (the default for an api-key or delegated scheme, absent a
3659
+ * provider-derived override) gets a fresh id on every connect; a scheme that
3660
+ * instead derives the id from provider data (an oauth2-pkce scheme supplying
3661
+ * `resolveAccountId`, e.g. reading an OIDC `sub`) keeps the same id across
3662
+ * reconnect. A module on a scheme without a provider-stable id has two honest
3663
+ * choices: derive its own stable identity from provider data at read time
3664
+ * (call the provider's own account/"who am I" endpoint with the resolved
3665
+ * credential and fold THAT into `uri` instead of `accountId`), or
3666
+ * account-qualify with `accountId` knowing a disconnect/reconnect of the same
3667
+ * real-world account re-keys its documents under a new id rather than
3668
+ * updating them in place - nothing on the host side reconciles the old and
3669
+ * new keys.
3670
+ */
3671
+ declare interface ObservationMaterial {
3672
+ /** Canonical URI of the observed resource - may differ from the input URI. */
3673
+ readonly uri: string;
3674
+ /** Scheme-prefixed content type, e.g. `"github.pr"`, `"gmail.thread"`, `"wikipedia.article"`. */
3675
+ readonly kind: string;
3676
+ readonly title?: string;
3677
+ /** Source-native seams: one element per message/comment/section, in source order. */
3678
+ readonly text?: readonly string[];
3679
+ /** ISO-8601 creation time; provenance only - not persisted by the store yet. */
3680
+ readonly createdAt?: string;
3681
+ /** ISO-8601 last-update time; provenance only - not persisted by the store yet. */
3682
+ readonly updatedAt?: string;
3683
+ /** Source-native revision/version marker, when the source exposes one. */
3684
+ readonly version?: string;
3685
+ /**
3686
+ * How long this resource stays worth semantically searching, measured from
3687
+ * the LAST time it was observed - not from when it was first indexed. Every
3688
+ * observation of an unchanged resource pushes the deadline out again, so a
3689
+ * thread that keeps getting read keeps living and a quiet one ages out.
3690
+ *
3691
+ * Retention is opt-in per resource: absent means the index keeps the
3692
+ * resource until its source says it is gone. A route declares this only
3693
+ * when staleness is real for that shape - a chat thread or an inbox
3694
+ * conversation goes cold, a durable note the user wrote does not.
3695
+ */
3696
+ readonly retainForMs?: number;
3697
+ }
3698
+
2670
3699
  /** Applies a Omit action using the given types. */
2671
3700
  declare function Omit_2<Type extends TSchema, Indexer extends PropertyKey[]>(type: Type, indexer: readonly [...Indexer], options?: TSchemaOptions): TOmit<Type, TKeysToIndexer<Indexer>>;
2672
3701
 
@@ -2789,6 +3818,10 @@ declare const OptionalSemiColon: (input: string) => [unknown, string] | [];
2789
3818
 
2790
3819
  declare function OptionalSemiColonMapping(input: [unknown] | []): unknown;
2791
3820
 
3821
+ declare const PackageAssetPath: z.ZodString;
3822
+
3823
+ declare type PackageAssetPath = z.infer<typeof PackageAssetPath>;
3824
+
2792
3825
  /** Creates a Parameter type. */
2793
3826
  declare function Parameter<Name extends string, Extends extends TSchema, Equals extends TSchema>(name: Name, extends_: Extends, equals: Equals): TParameter<Name, Extends, Equals>;
2794
3827
 
@@ -3156,32 +4189,15 @@ declare function Pick_2<Type extends TSchema, Indexer extends TSchema>(type: Typ
3156
4189
  /** Creates a deferred Pick action. */
3157
4190
  declare function PickDeferred<Type extends TSchema, Indexer extends TSchema>(type: Type, indexer: Indexer, options?: TSchemaOptions): TPickDeferred<Type, Indexer>;
3158
4191
 
3159
- declare interface PluginApiKeyScheme {
3160
- readonly id: string;
3161
- /** Human-facing flow name; distinguish the key's purpose when sibling flows exist. */
3162
- readonly displayName: string;
3163
- /** What this flow unlocks and when to choose it over another. */
3164
- readonly agentHint?: PluginSchemeAgentHint;
3165
- /** What this flow unlocks, for the person: one plain sentence, no identifiers or URIs. */
3166
- readonly summary?: string;
3167
- readonly inputLabel: string;
3168
- /**
3169
- * Two or more labeled inputs for an irreducibly multi-part secret (e.g. a Cloudflare Access
3170
- * service token's client-id + client-secret pair). The connect prompt collects one value per
3171
- * field; handlers read them from `ctx.auth.credential.fields`, keyed by field id. Index 0 is
3172
- * the primary field (mirrored as `accessToken`). Absent means the classic single-secret prompt;
3173
- * when present, ids must be unique and non-empty and there must be at least two entries — the
3174
- * kernel rejects an invalid declaration at activation.
3175
- */
3176
- readonly fields?: readonly PluginApiKeySchemeField[];
3177
- readonly setup?: PluginApiKeySchemeSetup;
3178
- readonly validate?: ValidatePluginApiKeyCredential;
4192
+ /**
4193
+ * How a plugin learns which provider account a fresh OAuth token belongs to: one account, or every
4194
+ * account the grant reaches. Registered with `api.auth.registerAccountResolver`.
4195
+ */
4196
+ declare interface PluginAccountResolver {
4197
+ readonly resolveAccountId?: ResolvePluginAccountId;
4198
+ readonly resolveAccounts?: ResolvePluginAccounts;
3179
4199
  }
3180
4200
 
3181
- declare type PluginApiKeySchemeField = ApiKeyAuthSchemeField;
3182
-
3183
- declare type PluginApiKeySchemeSetup = ApiKeyAuthSchemeSetup;
3184
-
3185
4201
  /** The kinds of capability a plugin service can advertise (mirrors the host capability taxonomy). */
3186
4202
  declare type PluginCapabilityKind = "uri-module" | "tool" | "search-provider";
3187
4203
 
@@ -3198,12 +4214,12 @@ declare interface PluginDelegatedRevokeContext {
3198
4214
  }
3199
4215
 
3200
4216
  /**
3201
- * A protocol-agnostic scheme whose connect/refresh choreography the plugin provides — the host owns
4217
+ * A protocol-agnostic scheme whose connect/refresh choreography the plugin provides - the host owns
3202
4218
  * only vault persistence, gating, and single-flight refresh over the opaque material. Use this when
3203
4219
  * the auth dance is not a fixed OAuth-PKCE shape the host can drive itself (e.g. a runtime-discovered
3204
- * authorization server: 401 sniff → RFC 9728/8414 discovery → RFC 7591 dynamic client registration →
4220
+ * authorization server: 401 sniff -> RFC 9728/8414 discovery -> RFC 7591 dynamic client registration ->
3205
4221
  * PKCE). `connect` receives the host's browser-redirect capability (`ctx.redirectUri`/`ctx.authorize`)
3206
- * when one is configured, and both are absent when the host has none — the scheme decides whether it
4222
+ * when one is configured, and both are absent when the host has none - the scheme decides whether it
3207
4223
  * needs them and fails its connect with an actionable message if it does and they are missing.
3208
4224
  */
3209
4225
  declare interface PluginDelegatedScheme {
@@ -3253,83 +4269,18 @@ declare const PluginEventPublishInput: z.ZodObject<{
3253
4269
  poller: z.ZodOptional<z.ZodString>;
3254
4270
  runId: z.ZodOptional<z.ZodString>;
3255
4271
  }, z.core.$strict>>;
3256
- payload: z.ZodOptional<z.ZodType<JsonValue_2, unknown, z.core.$ZodTypeInternals<JsonValue_2, unknown>>>;
4272
+ payload: z.ZodOptional<z.ZodType<authoringCommonSchemas.JsonValue, unknown, z.core.$ZodTypeInternals<authoringCommonSchemas.JsonValue, unknown>>>;
3257
4273
  }, z.core.$strict>;
3258
4274
 
3259
4275
  declare type PluginEventPublishInput = z.infer<typeof PluginEventPublishInput>;
3260
4276
 
3261
- /**
3262
- * An external-CLI readiness scheme the plugin declares: a non-injectable marker for a
3263
- * host-probed local binary (e.g. `osascript`, `gh`). Connecting runs `binary probeArgs`
3264
- * through the host's bounded spawn — success mints a readiness record, never token
3265
- * material. Verb handlers gated on such a scheme receive `ctx.auth.externalCli`, a
3266
- * host-owned runner pinned to the declared binary; the plugin itself never spawns.
3267
- * The manifest twin must declare the binary under `permissions.byTarget["agent.harness"].process`.
3268
- */
3269
- declare interface PluginExternalCliScheme {
3270
- readonly id: string;
3271
- readonly displayName: string;
3272
- /** What this flow unlocks and when to choose it over another. */
3273
- readonly agentHint?: PluginSchemeAgentHint;
3274
- /** What this flow unlocks, for the person: one plain sentence, no identifiers or URIs. */
3275
- readonly summary?: string;
3276
- /** The local binary the host probes and runs (bare name resolved on PATH, or absolute). */
3277
- readonly binary: string;
3278
- /** Argv for the readiness probe; exit 0 means connected. */
3279
- readonly probeArgs: readonly string[];
3280
- /** Optional argv whose stdout is recorded as the CLI version on connect. */
3281
- readonly versionArgs?: readonly string[];
3282
- /** Probe/run timeout; the host default applies when absent. */
3283
- readonly timeoutMs?: number;
3284
- /** Actionable copy when the binary is missing (install path, platform requirement). */
3285
- readonly installHint: string;
3286
- /** Actionable copy when the probe fails (login step, OS permission grant). */
3287
- readonly loginHint: string;
3288
- }
4277
+ declare const PluginId: z.ZodString;
3289
4278
 
3290
- /**
3291
- * An OAuth2-PKCE scheme the plugin declares. The host owns acquisition, refresh, and broker
3292
- * routing; the plugin supplies only public metadata plus an optional account-id resolver.
3293
- *
3294
- * Intersects {@link PluginOAuthSchemeClientAxes} (BYOOC — bring-your-own-OAuth-client):
3295
- * `clientId`/`clientSecret` are optional and mean ONLY "the Kay-supplied embedded client" —
3296
- * present iff `exchange: "pkce"` and the host ships one. A `confidential` scheme never carries
3297
- * them; that secret lives with the host's broker, never with the plugin.
3298
- */
3299
- declare type PluginOAuthPkceScheme = PluginOAuthSchemeClientAxes & {
3300
- readonly id: string;
3301
- readonly displayName: string;
3302
- /** What this flow unlocks and when to choose it over another. */
3303
- readonly agentHint?: PluginSchemeAgentHint;
3304
- /** What this flow unlocks, for the person: one plain sentence, no identifiers or URIs. */
3305
- readonly summary?: string;
3306
- readonly authorizationUrl: string;
3307
- readonly tokenUrl: string;
3308
- /** The Bonsai-supplied embedded client id; omit for a `confidential` scheme or a `pkce` scheme
3309
- * the host ships no client for. */
3310
- readonly clientId?: string;
3311
- /**
3312
- * An embedded, **non-confidential** client secret for a broker-free PKCE scheme — the case where a
3313
- * desktop-app OAuth client requires `client_secret` at the token endpoint but the secret is public
3314
- * by design (e.g. Google installed-app clients). Omit for brokered schemes, where the confidential
3315
- * secret lives in the broker and never reaches the plugin. A scheme is broker-free purely by virtue
3316
- * of its `id` not being in the host's brokered-scheme map; supplying this never routes it anywhere.
3317
- */
3318
- readonly clientSecret?: string;
3319
- readonly scopes: readonly string[];
3320
- /** Extra params merged into the authorize query. */
3321
- readonly extraAuthorizeParams?: Readonly<Record<string, string>>;
3322
- readonly resolveAccountId?: ResolvePluginAccountId;
3323
- /**
3324
- * Enumerate every provider account a fresh OAuth grant powers. Present only for providers whose
3325
- * consent can grant multiple accounts; the host commits one account binding per result while
3326
- * keeping one shared token lifecycle.
3327
- */
3328
- readonly resolveAccounts?: ResolvePluginAccounts;
3329
- };
4279
+ declare type PluginId = z.infer<typeof PluginId>;
3330
4280
 
3331
- /** BYOOC — the herd canonical client-axes union, aliased (never copied) for plugin authors. */
3332
- declare type PluginOAuthSchemeClientAxes = OAuthSchemeClientAxes;
4281
+ declare const PluginNamespace: z.ZodString;
4282
+
4283
+ declare type PluginNamespace = z.infer<typeof PluginNamespace>;
3333
4284
 
3334
4285
  /** What one connection flow unlocks and when an agent should choose it; grants no authority. */
3335
4286
  declare type PluginSchemeAgentHint = string;
@@ -3341,7 +4292,7 @@ declare interface PluginServiceCapability {
3341
4292
  readonly summary: string;
3342
4293
  }
3343
4294
 
3344
- /** A service the plugin owns — advertised for discovery and used to gate auth-backed contributions. */
4295
+ /** A service the plugin owns - advertised for discovery and used to gate auth-backed contributions. */
3345
4296
  declare interface PluginServiceDescriptor {
3346
4297
  readonly id: string;
3347
4298
  readonly display: string;
@@ -3349,6 +4300,28 @@ declare interface PluginServiceDescriptor {
3349
4300
  readonly capabilities: readonly PluginServiceCapability[];
3350
4301
  }
3351
4302
 
4303
+ declare const PluginSourceClass: z.ZodEnum<{
4304
+ bundled: "bundled";
4305
+ "org-shared": "org-shared";
4306
+ "user-local": "user-local";
4307
+ "verified-marketplace": "verified-marketplace";
4308
+ freeform: "freeform";
4309
+ }>;
4310
+
4311
+ declare type PluginSourceClass = z.infer<typeof PluginSourceClass>;
4312
+
4313
+ declare const PluginTargetName: z.ZodEnum<{
4314
+ "kay.agent": "kay.agent";
4315
+ "kay.app": "kay.app";
4316
+ "kay.ui": "kay.ui";
4317
+ }>;
4318
+
4319
+ declare type PluginTargetName = z.infer<typeof PluginTargetName>;
4320
+
4321
+ declare const PluginToolName: z.ZodString;
4322
+
4323
+ declare type PluginToolName = z.infer<typeof PluginToolName>;
4324
+
3352
4325
  /**
3353
4326
  * What a run did to a URI. The words match the automation run wire's artifact actions. When one
3354
4327
  * run both creates and updates a URI, the reader reports `created`.
@@ -3357,7 +4330,7 @@ declare type ProducedResourceAction = "created" | "updated";
3357
4330
 
3358
4331
  /** One URI a tool call created or updated as a side effect. */
3359
4332
  declare interface ProducedResourceDeclaration {
3360
- /** A `scheme://…` URI or an absolute local file path, compared as an exact string. */
4333
+ /** A `scheme://...` URI or an absolute local file path, compared as an exact string. */
3361
4334
  readonly uri: string;
3362
4335
  readonly action: ProducedResourceAction;
3363
4336
  }
@@ -3454,7 +4427,7 @@ declare type ProviderId = KnownProvider | string;
3454
4427
  declare interface ProxiedToolCall {
3455
4428
  /** The registered tool the carrier will invoke. */
3456
4429
  readonly toolName: string;
3457
- /** The input that tool will be invoked with — what the gate must classify. */
4430
+ /** The input that tool will be invoked with - what the gate must classify. */
3458
4431
  readonly input: Record<string, unknown>;
3459
4432
  }
3460
4433
 
@@ -3464,6 +4437,28 @@ declare interface RawResource {
3464
4437
  readonly mimeType: string;
3465
4438
  readonly metadata?: RawResourceMetadata;
3466
4439
  readonly selector?: SelectorDisposition;
4440
+ /**
4441
+ * The indexable forms of this resource, built from the same fetch as
4442
+ * `content`: one per document the read wants indexed (a thread read offers
4443
+ * one per message). Absent or empty means nothing is indexed. The read tool
4444
+ * takes them off before the cache and the model; other host reads
4445
+ * (out-of-band host reads) return them untouched.
4446
+ */
4447
+ readonly observations?: readonly ObservationMaterial[];
4448
+ /** How long the host may cache this result; see {@link UriCachePolicy.ttlMs}. */
4449
+ readonly cachePolicy?: Pick<UriCachePolicy, "ttlMs">;
4450
+ /**
4451
+ * A short name for the resource this call touched, for the transcript row; absent shows the
4452
+ * address. Render-only: the host stamps it on the tool result's `details`, never in `content`.
4453
+ */
4454
+ readonly label?: UriResourceLabel;
4455
+ /**
4456
+ * Answer to a `read` called with `ctx.knownRevision`: the module checked the source's current
4457
+ * revision and it equals `knownRevision`, so `content` is empty and `metadata.revision` equals
4458
+ * `knownRevision`. Set it only when that check was made and matched; a module that cannot
4459
+ * check cheaply, or that found a different revision, returns the full resource without it.
4460
+ */
4461
+ readonly unchanged?: true;
3467
4462
  }
3468
4463
 
3469
4464
  declare interface RawResourceCacheControl {
@@ -3507,7 +4502,7 @@ declare interface RawResourceMetadata {
3507
4502
  readonly resourceIdentity?: RawResourceIdentity;
3508
4503
  /**
3509
4504
  * The resource's stable public address when `uri` reports something more
3510
- * specific than the address a consumer names it by — a retained revision
4505
+ * specific than the address a consumer names it by - a retained revision
3511
4506
  * (`skill://<id>/@revision/<version>`) served for a `skill://<source>/<name>`
3512
4507
  * read. Present only when the two differ. Consumers that attribute by name
3513
4508
  * (the read tool's `skillName` detail, and everything keyed off it) read
@@ -3582,6 +4577,29 @@ declare function Refine<Type extends TSchema, Value = Static<Type>>(type: Type,
3582
4577
  /** Applies a Refine check to the given type. */
3583
4578
  declare function RefineAdd<Type extends TSchema>(type: Type, refinement: TRefinement<Type>): TRefineAdd<Type>;
3584
4579
 
4580
+ /**
4581
+ * The web-session scope-confinement refinement, coined ONCE and shared by both
4582
+ * web-session boundaries: `loginUrl` and `probe.url` must each fall within a
4583
+ * declared `cookieDomains` entry. The manifest boundary
4584
+ * (`PluginWebSessionDeclaration`) enforces it because those URLs are
4585
+ * authenticated-navigation/request primitives a third-party manifest hands the
4586
+ * host; the resolved/wire boundary (`ResolvedPluginWebSession`) re-runs the SAME
4587
+ * check rather than trust it survived resolution (its parse is the surface's
4588
+ * only validation against a skewed daemon). Two copies of the check itself would
4589
+ * be one edit away from disagreeing across those hops.
4590
+ */
4591
+ declare function refineWebSessionScopeConfined(webSession: {
4592
+ readonly cookieDomains: readonly string[];
4593
+ readonly loginUrl: string;
4594
+ readonly probe: {
4595
+ readonly url: string;
4596
+ };
4597
+ }, ctx: z.RefinementCtx): void;
4598
+
4599
+ declare const RegistrableDomain: z.ZodString;
4600
+
4601
+ declare type RegistrableDomain = z.infer<typeof RegistrableDomain>;
4602
+
3585
4603
  /** Applies an RemoveImmutable action to a type. */
3586
4604
  declare function RemoveImmutable<Type extends TSchema>(type: Type, options?: TSchemaOptions): TRemoveImmutable<Type>;
3587
4605
 
@@ -3612,7 +4630,7 @@ declare function RequiredDeferred<Type extends TSchema>(type: Type, options?: TS
3612
4630
  declare type RequiredKeys<Properties extends TProperties, Result extends PropertyKey = keyof Omit<Properties, ReadonlyOptionalKeys<Properties> | ReadonlyKeys<Properties> | OptionalKeys<Properties>>> = Result;
3613
4631
 
3614
4632
  /**
3615
- * The capability⇄service auth binding. A registration carrying this is gated on `serviceId`'s
4633
+ * The capability<->service auth binding. A registration carrying this is gated on `serviceId`'s
3616
4634
  * connectivity; the runtime answers "is this capability authorized?" from this plus vault state.
3617
4635
  */
3618
4636
  declare interface RequiresAuth {
@@ -3620,7 +4638,7 @@ declare interface RequiresAuth {
3620
4638
  /**
3621
4639
  * Optional scheme preference. Absent means the binding is service-level: any injectable scheme
3622
4640
  * of the service satisfies it, and resolution picks each account's own backing scheme. Present,
3623
- * it names the scheme resolution tries first — an account connected under a sibling injectable
4641
+ * it names the scheme resolution tries first - an account connected under a sibling injectable
3624
4642
  * scheme still satisfies the binding and resolves against its own scheme. A non-injectable
3625
4643
  * capability (`external-cli`) MUST name its scheme: it is a scheme-exact island.
3626
4644
  */
@@ -3628,7 +4646,7 @@ declare interface RequiresAuth {
3628
4646
  /**
3629
4647
  * The scopes this capability needs to do its job. Threaded through `resolveToken` into the
3630
4648
  * vault load so a grant-enforcing vault (the daemon's authority-backed vault) can refuse a
3631
- * plugin whose granted scopes don't cover them (`scopesCovered`) — per call, per plugin. Absent
4649
+ * plugin whose granted scopes don't cover them (`scopesCovered`) - per call, per plugin. Absent
3632
4650
  * means the capability declares no scope requirement (the single-user local path never checks
3633
4651
  * scopes; it is a daemon per-plugin enforcement input). Also read by the scope-aware half of
3634
4652
  * `isBindingSatisfied` when the host supplies a granted-scopes reader.
@@ -3640,11 +4658,11 @@ declare interface RequiresAuth {
3640
4658
  */
3641
4659
  readonly scopeRequirement?: ScopeRequirement;
3642
4660
  /**
3643
- * The service id to NAME in connect guidance when this capability is gated — a host-composed
4661
+ * The service id to NAME in connect guidance when this capability is gated - a host-composed
3644
4662
  * FRONT DOOR whose `service_connect` grants exactly what this binding needs (e.g. Gmail's
3645
4663
  * modules resolve under the shared `google.account` credential but connect via the `gmail`
3646
4664
  * front door, which expands only Gmail's scopes onto it). Guidance only: credential resolution
3647
- * still keys on `(serviceId, schemeId)`. Absent, guidance names `serviceId` — which for a
4665
+ * still keys on `(serviceId, schemeId)`. Absent, guidance names `serviceId` - which for a
3648
4666
  * scoped binding on a shared multi-product credential would send the agent to a connect that
3649
4667
  * classifies resolved and no-ops, never granting the missing scopes.
3650
4668
  */
@@ -3652,22 +4670,931 @@ declare interface RequiresAuth {
3652
4670
  }
3653
4671
 
3654
4672
  /**
3655
- * What the resolver hands a tool body: a live token for a concrete account + identity.
3656
- * `accessToken` is `apiKey` for an api-key scheme or the (refreshed) bearer for oauth.
4673
+ * The credential the host resolved for one call to plugin code that declares `requiresAuth`: a URI
4674
+ * verb (`ctx.auth.credential`), a tool (`ctx.credential`) or a search provider (`ctx.credential`).
4675
+ * Plain data, so it crosses a process boundary with the call; plugin code never asks for one.
3657
4676
  */
3658
- declare interface ResolvedAuth {
4677
+ declare interface ResolvedCredential {
4678
+ /** Bearer for OAuth schemes, apiKey for api-key schemes. Host-resolved and refreshed. */
3659
4679
  readonly accessToken: string;
3660
- readonly account: AuthAccount;
3661
- readonly identityMode: IdentityMode;
4680
+ readonly accountId: string;
3662
4681
  readonly schemeId: string;
3663
4682
  readonly scopes?: readonly string[];
3664
4683
  /**
3665
- * Every value of a multi-field api-key credential, keyed by the scheme's field id;
3666
- * `accessToken` mirrors the primary (first) field. Absent for single-secret schemes.
4684
+ * Every value of a multi-field api-key credential, keyed by the scheme's declared field id
4685
+ * (`accessToken` mirrors the primary field). Absent for single-secret schemes.
3667
4686
  */
3668
4687
  readonly fields?: Readonly<Record<string, string>>;
3669
4688
  }
3670
4689
 
4690
+ declare const ResolvedPluginContractV1: z.ZodObject<{
4691
+ protocol: z.ZodLiteral<"kay.plugin.v1">;
4692
+ pluginId: z.ZodString;
4693
+ namespace: z.ZodString;
4694
+ contributions: z.ZodArray<z.ZodObject<{
4695
+ target: z.ZodEnum<{
4696
+ "kay.agent": "kay.agent";
4697
+ "kay.app": "kay.app";
4698
+ "kay.ui": "kay.ui";
4699
+ }>;
4700
+ kind: z.ZodEnum<{
4701
+ tool: "tool";
4702
+ resource: "resource";
4703
+ endpoint: "endpoint";
4704
+ storage: "storage";
4705
+ command: "command";
4706
+ authService: "authService";
4707
+ app: "app";
4708
+ uriModule: "uriModule";
4709
+ configSection: "configSection";
4710
+ skill: "skill";
4711
+ converter: "converter";
4712
+ artifactUriModule: "artifactUriModule";
4713
+ cliBinding: "cliBinding";
4714
+ searchProvider: "searchProvider";
4715
+ interactionDriver: "interactionDriver";
4716
+ entityResolver: "entityResolver";
4717
+ agentRenderer: "agentRenderer";
4718
+ eventDefinition: "eventDefinition";
4719
+ eventSubscription: "eventSubscription";
4720
+ appDataSource: "appDataSource";
4721
+ whiteboardType: "whiteboardType";
4722
+ approvalType: "approvalType";
4723
+ contextContributor: "contextContributor";
4724
+ transcriptionProvider: "transcriptionProvider";
4725
+ deviceDelegation: "deviceDelegation";
4726
+ sessionReader: "sessionReader";
4727
+ mcpServer: "mcpServer";
4728
+ uiCommand: "uiCommand";
4729
+ uiSlot: "uiSlot";
4730
+ settingsPanel: "settingsPanel";
4731
+ resultRenderer: "resultRenderer";
4732
+ referencePresentation: "referencePresentation";
4733
+ view: "view";
4734
+ theme: "theme";
4735
+ }>;
4736
+ localId: z.ZodString;
4737
+ globalId: z.ZodString;
4738
+ }, z.core.$strict>>;
4739
+ consumesAuthServices: z.ZodArray<z.ZodString>;
4740
+ explicitDependencies: z.ZodArray<z.ZodString>;
4741
+ authServices: z.ZodArray<z.ZodObject<{
4742
+ localId: z.ZodString;
4743
+ globalId: z.ZodString;
4744
+ displayName: z.ZodString;
4745
+ summary: z.ZodOptional<z.ZodString>;
4746
+ schemes: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodDiscriminatedUnion<[z.ZodObject<{
4747
+ exchange: z.ZodLiteral<"pkce">;
4748
+ clientSuppliers: z.ZodArray<z.ZodEnum<{
4749
+ user: "user";
4750
+ kay: "kay";
4751
+ }>>;
4752
+ clientId: z.ZodOptional<z.ZodString>;
4753
+ clientSecret: z.ZodOptional<z.ZodString>;
4754
+ account: z.ZodOptional<z.ZodEnum<{
4755
+ resolveAccountId: "resolveAccountId";
4756
+ resolveAccounts: "resolveAccounts";
4757
+ }>>;
4758
+ localId: z.ZodString;
4759
+ globalId: z.ZodString;
4760
+ kind: z.ZodLiteral<"oauth2">;
4761
+ scopes: z.ZodOptional<z.ZodArray<z.ZodString>>;
4762
+ authorizationUrl: z.ZodURL;
4763
+ tokenUrl: z.ZodURL;
4764
+ extraAuthorizeParams: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
4765
+ displayName: z.ZodOptional<z.ZodString>;
4766
+ agentHint: z.ZodOptional<z.ZodString>;
4767
+ summary: z.ZodOptional<z.ZodString>;
4768
+ provisioning: z.ZodOptional<z.ZodArray<z.ZodObject<{
4769
+ id: z.ZodString;
4770
+ displayName: z.ZodString;
4771
+ description: z.ZodString;
4772
+ remediationUrl: z.ZodOptional<z.ZodURL>;
4773
+ probe: z.ZodObject<{
4774
+ url: z.ZodURL;
4775
+ method: z.ZodEnum<{
4776
+ GET: "GET";
4777
+ }>;
4778
+ verdictStatuses: z.ZodArray<z.ZodNumber>;
4779
+ nonEmptyArrayAt: z.ZodOptional<z.ZodString>;
4780
+ }, z.core.$strict>;
4781
+ }, z.core.$strict>>>;
4782
+ }, z.core.$strict>, z.ZodObject<{
4783
+ exchange: z.ZodLiteral<"confidential">;
4784
+ clientSuppliers: z.ZodTuple<[z.ZodLiteral<"kay">], null>;
4785
+ account: z.ZodEnum<{
4786
+ resolveAccountId: "resolveAccountId";
4787
+ resolveAccounts: "resolveAccounts";
4788
+ "sign-in": "sign-in";
4789
+ }>;
4790
+ localId: z.ZodString;
4791
+ globalId: z.ZodString;
4792
+ kind: z.ZodLiteral<"oauth2">;
4793
+ scopes: z.ZodOptional<z.ZodArray<z.ZodString>>;
4794
+ authorizationUrl: z.ZodURL;
4795
+ tokenUrl: z.ZodURL;
4796
+ extraAuthorizeParams: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
4797
+ displayName: z.ZodOptional<z.ZodString>;
4798
+ agentHint: z.ZodOptional<z.ZodString>;
4799
+ summary: z.ZodOptional<z.ZodString>;
4800
+ provisioning: z.ZodOptional<z.ZodArray<z.ZodObject<{
4801
+ id: z.ZodString;
4802
+ displayName: z.ZodString;
4803
+ description: z.ZodString;
4804
+ remediationUrl: z.ZodOptional<z.ZodURL>;
4805
+ probe: z.ZodObject<{
4806
+ url: z.ZodURL;
4807
+ method: z.ZodEnum<{
4808
+ GET: "GET";
4809
+ }>;
4810
+ verdictStatuses: z.ZodArray<z.ZodNumber>;
4811
+ nonEmptyArrayAt: z.ZodOptional<z.ZodString>;
4812
+ }, z.core.$strict>;
4813
+ }, z.core.$strict>>>;
4814
+ }, z.core.$strict>], "exchange">, z.ZodObject<{
4815
+ localId: z.ZodString;
4816
+ globalId: z.ZodString;
4817
+ kind: z.ZodLiteral<"api-key">;
4818
+ scopes: z.ZodOptional<z.ZodArray<z.ZodString>>;
4819
+ inputLabel: z.ZodString;
4820
+ fields: z.ZodOptional<z.ZodArray<z.ZodObject<{
4821
+ id: z.ZodString;
4822
+ label: z.ZodString;
4823
+ }, z.core.$strict>>>;
4824
+ setup: z.ZodOptional<z.ZodObject<{
4825
+ instructions: z.ZodString;
4826
+ url: z.ZodURL;
4827
+ }, z.core.$strict>>;
4828
+ validates: z.ZodOptional<z.ZodLiteral<true>>;
4829
+ displayName: z.ZodOptional<z.ZodString>;
4830
+ agentHint: z.ZodOptional<z.ZodString>;
4831
+ summary: z.ZodOptional<z.ZodString>;
4832
+ provisioning: z.ZodOptional<z.ZodArray<z.ZodObject<{
4833
+ id: z.ZodString;
4834
+ displayName: z.ZodString;
4835
+ description: z.ZodString;
4836
+ remediationUrl: z.ZodOptional<z.ZodURL>;
4837
+ probe: z.ZodObject<{
4838
+ url: z.ZodURL;
4839
+ method: z.ZodEnum<{
4840
+ GET: "GET";
4841
+ }>;
4842
+ verdictStatuses: z.ZodArray<z.ZodNumber>;
4843
+ nonEmptyArrayAt: z.ZodOptional<z.ZodString>;
4844
+ }, z.core.$strict>;
4845
+ }, z.core.$strict>>>;
4846
+ }, z.core.$strict>, z.ZodObject<{
4847
+ localId: z.ZodString;
4848
+ globalId: z.ZodString;
4849
+ kind: z.ZodLiteral<"delegated">;
4850
+ scopes: z.ZodOptional<z.ZodArray<z.ZodString>>;
4851
+ displayName: z.ZodOptional<z.ZodString>;
4852
+ agentHint: z.ZodOptional<z.ZodString>;
4853
+ summary: z.ZodOptional<z.ZodString>;
4854
+ }, z.core.$strict>, z.ZodObject<{
4855
+ localId: z.ZodString;
4856
+ globalId: z.ZodString;
4857
+ kind: z.ZodLiteral<"external-cli">;
4858
+ scopes: z.ZodOptional<z.ZodArray<z.ZodString>>;
4859
+ cli: z.ZodOptional<z.ZodObject<{
4860
+ binary: z.ZodString;
4861
+ probe: z.ZodObject<{
4862
+ args: z.ZodArray<z.ZodString>;
4863
+ timeoutMs: z.ZodOptional<z.ZodNumber>;
4864
+ signedOutMarker: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>;
4865
+ }, z.core.$strict>;
4866
+ login: z.ZodOptional<z.ZodObject<{
4867
+ args: z.ZodArray<z.ZodString>;
4868
+ timeoutMs: z.ZodOptional<z.ZodNumber>;
4869
+ pasteCode: z.ZodOptional<z.ZodObject<{
4870
+ args: z.ZodArray<z.ZodString>;
4871
+ label: z.ZodString;
4872
+ }, z.core.$strict>>;
4873
+ }, z.core.$strict>>;
4874
+ install: z.ZodOptional<z.ZodObject<{
4875
+ command: z.ZodString;
4876
+ args: z.ZodArray<z.ZodString>;
4877
+ }, z.core.$strict>>;
4878
+ hints: z.ZodObject<{
4879
+ install: z.ZodString;
4880
+ login: z.ZodString;
4881
+ }, z.core.$strict>;
4882
+ }, z.core.$strict>>;
4883
+ displayName: z.ZodOptional<z.ZodString>;
4884
+ agentHint: z.ZodOptional<z.ZodString>;
4885
+ summary: z.ZodOptional<z.ZodString>;
4886
+ }, z.core.$strict>], "kind">>;
4887
+ purposes: z.ZodArray<z.ZodString>;
4888
+ webSession: z.ZodOptional<z.ZodObject<{
4889
+ importance: z.ZodEnum<{
4890
+ required: "required";
4891
+ recommended: "recommended";
4892
+ }>;
4893
+ loginUrl: z.ZodURL;
4894
+ cookieDomains: z.ZodArray<z.ZodString>;
4895
+ probe: z.ZodObject<{
4896
+ url: z.ZodURL;
4897
+ method: z.ZodEnum<{
4898
+ GET: "GET";
4899
+ POST: "POST";
4900
+ }>;
4901
+ signedInStatuses: z.ZodArray<z.ZodNumber>;
4902
+ }, z.core.$strict>;
4903
+ oauthVenue: z.ZodEnum<{
4904
+ external: "external";
4905
+ embedded: "embedded";
4906
+ }>;
4907
+ }, z.core.$strict>>;
4908
+ }, z.core.$strict>>;
4909
+ grants: z.ZodOptional<z.ZodObject<{
4910
+ byTarget: z.ZodObject<{
4911
+ "kay.agent": z.ZodOptional<z.ZodObject<{
4912
+ auth: z.ZodOptional<z.ZodArray<z.ZodObject<{
4913
+ operations: z.ZodArray<z.ZodEnum<{
4914
+ status: "status";
4915
+ list: "list";
4916
+ connect: "connect";
4917
+ disconnect: "disconnect";
4918
+ resolve: "resolve";
4919
+ }>>;
4920
+ purposes: z.ZodOptional<z.ZodArray<z.ZodString>>;
4921
+ allowedScopes: z.ZodOptional<z.ZodArray<z.ZodString>>;
4922
+ requiredScopes: z.ZodOptional<z.ZodArray<z.ZodString>>;
4923
+ connectScopes: z.ZodOptional<z.ZodArray<z.ZodString>>;
4924
+ scopeRequirement: z.ZodOptional<z.ZodObject<{
4925
+ purpose: z.ZodString;
4926
+ alternatives: z.ZodArray<z.ZodObject<{
4927
+ allOf: z.ZodArray<z.ZodObject<{
4928
+ scope: z.ZodString;
4929
+ reason: z.ZodExactOptional<z.ZodString>;
4930
+ }, z.core.$strict>>;
4931
+ }, z.core.$strict>>;
4932
+ }, z.core.$strict>>;
4933
+ scopeDefinitions: z.ZodOptional<z.ZodArray<z.ZodObject<{
4934
+ id: z.ZodString;
4935
+ label: z.ZodString;
4936
+ description: z.ZodString;
4937
+ documentationUrl: z.ZodOptional<z.ZodURL>;
4938
+ }, z.core.$strict>>>;
4939
+ frontDoor: z.ZodOptional<z.ZodObject<{
4940
+ id: z.ZodString;
4941
+ displayName: z.ZodString;
4942
+ resourcePicker: z.ZodOptional<z.ZodObject<{
4943
+ effect: z.ZodEnum<{
4944
+ selection: "selection";
4945
+ "resource-grant": "resource-grant";
4946
+ }>;
4947
+ mimeTypes: z.ZodOptional<z.ZodArray<z.ZodString>>;
4948
+ successNote: z.ZodOptional<z.ZodString>;
4949
+ }, z.core.$strict>>;
4950
+ }, z.core.$strict>>;
4951
+ service: z.ZodString;
4952
+ schemes: z.ZodOptional<z.ZodArray<z.ZodString>>;
4953
+ accountSelectors: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
4954
+ kind: z.ZodLiteral<"active">;
4955
+ }, z.core.$strict>, z.ZodObject<{
4956
+ kind: z.ZodLiteral<"account-id">;
4957
+ accountId: z.ZodString;
4958
+ }, z.core.$strict>, z.ZodObject<{
4959
+ kind: z.ZodLiteral<"record-id">;
4960
+ recordId: z.ZodString;
4961
+ }, z.core.$strict>], "kind">>;
4962
+ }, z.core.$strict>>>;
4963
+ storage: z.ZodOptional<z.ZodArray<z.ZodObject<{
4964
+ kind: z.ZodEnum<{
4965
+ sqlite: "sqlite";
4966
+ dataDir: "dataDir";
4967
+ }>;
4968
+ operations: z.ZodArray<z.ZodEnum<{
4969
+ open: "open";
4970
+ read: "read";
4971
+ write: "write";
4972
+ }>>;
4973
+ }, z.core.$strict>>>;
4974
+ events: z.ZodOptional<z.ZodArray<z.ZodObject<{
4975
+ event: z.ZodString;
4976
+ operations: z.ZodArray<z.ZodEnum<{
4977
+ subscribe: "subscribe";
4978
+ publish: "publish";
4979
+ }>>;
4980
+ }, z.core.$strict>>>;
4981
+ endpoints: z.ZodOptional<z.ZodArray<z.ZodObject<{
4982
+ operations: z.ZodArray<z.ZodEnum<{
4983
+ register: "register";
4984
+ invoke: "invoke";
4985
+ }>>;
4986
+ endpoint: z.ZodString;
4987
+ }, z.core.$strict>>>;
4988
+ webSession: z.ZodOptional<z.ZodArray<z.ZodObject<{
4989
+ origin: z.ZodString;
4990
+ pathPrefixes: z.ZodArray<z.ZodString>;
4991
+ csrf: z.ZodOptional<z.ZodObject<{
4992
+ sourceUrl: z.ZodURL;
4993
+ selector: z.ZodString;
4994
+ attribute: z.ZodString;
4995
+ header: z.ZodString;
4996
+ bodyField: z.ZodOptional<z.ZodString>;
4997
+ }, z.core.$strict>>;
4998
+ }, z.core.$strict>>>;
4999
+ knowledgeSearch: z.ZodOptional<z.ZodArray<z.ZodObject<{
5000
+ scope: z.ZodLiteral<"own-schemes">;
5001
+ }, z.core.$strict>>>;
5002
+ knownResources: z.ZodOptional<z.ZodArray<z.ZodObject<{
5003
+ scope: z.ZodLiteral<"own-modules">;
5004
+ }, z.core.$strict>>>;
5005
+ }, z.core.$strict>>;
5006
+ "kay.app": z.ZodOptional<z.ZodObject<{
5007
+ auth: z.ZodOptional<z.ZodArray<z.ZodObject<{
5008
+ operations: z.ZodArray<z.ZodEnum<{
5009
+ status: "status";
5010
+ list: "list";
5011
+ connect: "connect";
5012
+ disconnect: "disconnect";
5013
+ resolve: "resolve";
5014
+ }>>;
5015
+ purposes: z.ZodOptional<z.ZodArray<z.ZodString>>;
5016
+ allowedScopes: z.ZodOptional<z.ZodArray<z.ZodString>>;
5017
+ requiredScopes: z.ZodOptional<z.ZodArray<z.ZodString>>;
5018
+ connectScopes: z.ZodOptional<z.ZodArray<z.ZodString>>;
5019
+ scopeRequirement: z.ZodOptional<z.ZodObject<{
5020
+ purpose: z.ZodString;
5021
+ alternatives: z.ZodArray<z.ZodObject<{
5022
+ allOf: z.ZodArray<z.ZodObject<{
5023
+ scope: z.ZodString;
5024
+ reason: z.ZodExactOptional<z.ZodString>;
5025
+ }, z.core.$strict>>;
5026
+ }, z.core.$strict>>;
5027
+ }, z.core.$strict>>;
5028
+ scopeDefinitions: z.ZodOptional<z.ZodArray<z.ZodObject<{
5029
+ id: z.ZodString;
5030
+ label: z.ZodString;
5031
+ description: z.ZodString;
5032
+ documentationUrl: z.ZodOptional<z.ZodURL>;
5033
+ }, z.core.$strict>>>;
5034
+ frontDoor: z.ZodOptional<z.ZodObject<{
5035
+ id: z.ZodString;
5036
+ displayName: z.ZodString;
5037
+ resourcePicker: z.ZodOptional<z.ZodObject<{
5038
+ effect: z.ZodEnum<{
5039
+ selection: "selection";
5040
+ "resource-grant": "resource-grant";
5041
+ }>;
5042
+ mimeTypes: z.ZodOptional<z.ZodArray<z.ZodString>>;
5043
+ successNote: z.ZodOptional<z.ZodString>;
5044
+ }, z.core.$strict>>;
5045
+ }, z.core.$strict>>;
5046
+ service: z.ZodString;
5047
+ schemes: z.ZodOptional<z.ZodArray<z.ZodString>>;
5048
+ accountSelectors: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
5049
+ kind: z.ZodLiteral<"active">;
5050
+ }, z.core.$strict>, z.ZodObject<{
5051
+ kind: z.ZodLiteral<"account-id">;
5052
+ accountId: z.ZodString;
5053
+ }, z.core.$strict>, z.ZodObject<{
5054
+ kind: z.ZodLiteral<"record-id">;
5055
+ recordId: z.ZodString;
5056
+ }, z.core.$strict>], "kind">>;
5057
+ }, z.core.$strict>>>;
5058
+ storage: z.ZodOptional<z.ZodArray<z.ZodObject<{
5059
+ kind: z.ZodEnum<{
5060
+ sqlite: "sqlite";
5061
+ dataDir: "dataDir";
5062
+ }>;
5063
+ operations: z.ZodArray<z.ZodEnum<{
5064
+ open: "open";
5065
+ read: "read";
5066
+ write: "write";
5067
+ }>>;
5068
+ }, z.core.$strict>>>;
5069
+ events: z.ZodOptional<z.ZodArray<z.ZodObject<{
5070
+ event: z.ZodString;
5071
+ operations: z.ZodArray<z.ZodEnum<{
5072
+ subscribe: "subscribe";
5073
+ publish: "publish";
5074
+ }>>;
5075
+ }, z.core.$strict>>>;
5076
+ endpoints: z.ZodOptional<z.ZodArray<z.ZodObject<{
5077
+ operations: z.ZodArray<z.ZodEnum<{
5078
+ register: "register";
5079
+ invoke: "invoke";
5080
+ }>>;
5081
+ endpoint: z.ZodString;
5082
+ }, z.core.$strict>>>;
5083
+ webSession: z.ZodOptional<z.ZodArray<z.ZodObject<{
5084
+ origin: z.ZodString;
5085
+ pathPrefixes: z.ZodArray<z.ZodString>;
5086
+ csrf: z.ZodOptional<z.ZodObject<{
5087
+ sourceUrl: z.ZodURL;
5088
+ selector: z.ZodString;
5089
+ attribute: z.ZodString;
5090
+ header: z.ZodString;
5091
+ bodyField: z.ZodOptional<z.ZodString>;
5092
+ }, z.core.$strict>>;
5093
+ }, z.core.$strict>>>;
5094
+ knowledgeSearch: z.ZodOptional<z.ZodArray<z.ZodObject<{
5095
+ scope: z.ZodLiteral<"own-schemes">;
5096
+ }, z.core.$strict>>>;
5097
+ knownResources: z.ZodOptional<z.ZodArray<z.ZodObject<{
5098
+ scope: z.ZodLiteral<"own-modules">;
5099
+ }, z.core.$strict>>>;
5100
+ }, z.core.$strict>>;
5101
+ "kay.ui": z.ZodOptional<z.ZodObject<{
5102
+ auth: z.ZodOptional<z.ZodArray<z.ZodObject<{
5103
+ operations: z.ZodArray<z.ZodEnum<{
5104
+ status: "status";
5105
+ list: "list";
5106
+ connect: "connect";
5107
+ disconnect: "disconnect";
5108
+ resolve: "resolve";
5109
+ }>>;
5110
+ purposes: z.ZodOptional<z.ZodArray<z.ZodString>>;
5111
+ allowedScopes: z.ZodOptional<z.ZodArray<z.ZodString>>;
5112
+ requiredScopes: z.ZodOptional<z.ZodArray<z.ZodString>>;
5113
+ connectScopes: z.ZodOptional<z.ZodArray<z.ZodString>>;
5114
+ scopeRequirement: z.ZodOptional<z.ZodObject<{
5115
+ purpose: z.ZodString;
5116
+ alternatives: z.ZodArray<z.ZodObject<{
5117
+ allOf: z.ZodArray<z.ZodObject<{
5118
+ scope: z.ZodString;
5119
+ reason: z.ZodExactOptional<z.ZodString>;
5120
+ }, z.core.$strict>>;
5121
+ }, z.core.$strict>>;
5122
+ }, z.core.$strict>>;
5123
+ scopeDefinitions: z.ZodOptional<z.ZodArray<z.ZodObject<{
5124
+ id: z.ZodString;
5125
+ label: z.ZodString;
5126
+ description: z.ZodString;
5127
+ documentationUrl: z.ZodOptional<z.ZodURL>;
5128
+ }, z.core.$strict>>>;
5129
+ frontDoor: z.ZodOptional<z.ZodObject<{
5130
+ id: z.ZodString;
5131
+ displayName: z.ZodString;
5132
+ resourcePicker: z.ZodOptional<z.ZodObject<{
5133
+ effect: z.ZodEnum<{
5134
+ selection: "selection";
5135
+ "resource-grant": "resource-grant";
5136
+ }>;
5137
+ mimeTypes: z.ZodOptional<z.ZodArray<z.ZodString>>;
5138
+ successNote: z.ZodOptional<z.ZodString>;
5139
+ }, z.core.$strict>>;
5140
+ }, z.core.$strict>>;
5141
+ service: z.ZodString;
5142
+ schemes: z.ZodOptional<z.ZodArray<z.ZodString>>;
5143
+ accountSelectors: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
5144
+ kind: z.ZodLiteral<"active">;
5145
+ }, z.core.$strict>, z.ZodObject<{
5146
+ kind: z.ZodLiteral<"account-id">;
5147
+ accountId: z.ZodString;
5148
+ }, z.core.$strict>, z.ZodObject<{
5149
+ kind: z.ZodLiteral<"record-id">;
5150
+ recordId: z.ZodString;
5151
+ }, z.core.$strict>], "kind">>;
5152
+ }, z.core.$strict>>>;
5153
+ storage: z.ZodOptional<z.ZodArray<z.ZodObject<{
5154
+ kind: z.ZodEnum<{
5155
+ sqlite: "sqlite";
5156
+ dataDir: "dataDir";
5157
+ }>;
5158
+ operations: z.ZodArray<z.ZodEnum<{
5159
+ open: "open";
5160
+ read: "read";
5161
+ write: "write";
5162
+ }>>;
5163
+ }, z.core.$strict>>>;
5164
+ events: z.ZodOptional<z.ZodArray<z.ZodObject<{
5165
+ event: z.ZodString;
5166
+ operations: z.ZodArray<z.ZodEnum<{
5167
+ subscribe: "subscribe";
5168
+ publish: "publish";
5169
+ }>>;
5170
+ }, z.core.$strict>>>;
5171
+ endpoints: z.ZodOptional<z.ZodArray<z.ZodObject<{
5172
+ operations: z.ZodArray<z.ZodEnum<{
5173
+ register: "register";
5174
+ invoke: "invoke";
5175
+ }>>;
5176
+ endpoint: z.ZodString;
5177
+ }, z.core.$strict>>>;
5178
+ webSession: z.ZodOptional<z.ZodArray<z.ZodObject<{
5179
+ origin: z.ZodString;
5180
+ pathPrefixes: z.ZodArray<z.ZodString>;
5181
+ csrf: z.ZodOptional<z.ZodObject<{
5182
+ sourceUrl: z.ZodURL;
5183
+ selector: z.ZodString;
5184
+ attribute: z.ZodString;
5185
+ header: z.ZodString;
5186
+ bodyField: z.ZodOptional<z.ZodString>;
5187
+ }, z.core.$strict>>;
5188
+ }, z.core.$strict>>>;
5189
+ knowledgeSearch: z.ZodOptional<z.ZodArray<z.ZodObject<{
5190
+ scope: z.ZodLiteral<"own-schemes">;
5191
+ }, z.core.$strict>>>;
5192
+ knownResources: z.ZodOptional<z.ZodArray<z.ZodObject<{
5193
+ scope: z.ZodLiteral<"own-modules">;
5194
+ }, z.core.$strict>>>;
5195
+ }, z.core.$strict>>;
5196
+ }, z.core.$strict>;
5197
+ }, z.core.$strict>>;
5198
+ kayAgentUriModules: z.ZodOptional<z.ZodArray<z.ZodObject<{
5199
+ claims: z.ZodExactOptional<z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
5200
+ kind: z.ZodLiteral<"scheme">;
5201
+ scheme: z.ZodString;
5202
+ }, z.core.$strict>, z.ZodObject<{
5203
+ kind: z.ZodLiteral<"uriPattern">;
5204
+ pattern: z.ZodObject<{
5205
+ protocol: z.ZodExactOptional<z.ZodString>;
5206
+ hostname: z.ZodExactOptional<z.ZodString>;
5207
+ pathname: z.ZodExactOptional<z.ZodString>;
5208
+ search: z.ZodExactOptional<z.ZodString>;
5209
+ }, z.core.$strict>;
5210
+ normalizeTo: z.ZodExactOptional<z.ZodString>;
5211
+ route: z.ZodExactOptional<z.ZodString>;
5212
+ sourceUrl: z.ZodExactOptional<z.ZodString>;
5213
+ title: z.ZodExactOptional<z.ZodString>;
5214
+ examples: z.ZodExactOptional<z.ZodArray<z.ZodString>>;
5215
+ }, z.core.$strict>, z.ZodObject<{
5216
+ kind: z.ZodLiteral<"urlPattern">;
5217
+ pattern: z.ZodObject<{
5218
+ protocol: z.ZodExactOptional<z.ZodString>;
5219
+ hostname: z.ZodExactOptional<z.ZodString>;
5220
+ pathname: z.ZodExactOptional<z.ZodString>;
5221
+ search: z.ZodExactOptional<z.ZodString>;
5222
+ }, z.core.$strict>;
5223
+ normalizeTo: z.ZodExactOptional<z.ZodString>;
5224
+ route: z.ZodExactOptional<z.ZodString>;
5225
+ examples: z.ZodExactOptional<z.ZodArray<z.ZodString>>;
5226
+ }, z.core.$strict>], "kind">>>;
5227
+ templates: z.ZodExactOptional<z.ZodArray<z.ZodObject<{
5228
+ uri: z.ZodString;
5229
+ description: z.ZodString;
5230
+ operations: z.ZodExactOptional<z.ZodArray<z.ZodEnum<{
5231
+ search: "search";
5232
+ delete: "delete";
5233
+ list: "list";
5234
+ read: "read";
5235
+ write: "write";
5236
+ help: "help";
5237
+ edit: "edit";
5238
+ }>>>;
5239
+ operationDocs: z.ZodExactOptional<z.ZodRecord<z.ZodEnum<{
5240
+ search: "search";
5241
+ delete: "delete";
5242
+ list: "list";
5243
+ read: "read";
5244
+ write: "write";
5245
+ help: "help";
5246
+ edit: "edit";
5247
+ }> & z.core.$partial, z.ZodString>>;
5248
+ operationDefaults: z.ZodExactOptional<z.ZodRecord<z.ZodEnum<{
5249
+ search: "search";
5250
+ delete: "delete";
5251
+ list: "list";
5252
+ read: "read";
5253
+ write: "write";
5254
+ help: "help";
5255
+ edit: "edit";
5256
+ }> & z.core.$partial, z.ZodEnum<{
5257
+ never: "never";
5258
+ allow: "allow";
5259
+ ask: "ask";
5260
+ }>>>;
5261
+ }, z.core.$strict>>>;
5262
+ verbs: z.ZodExactOptional<z.ZodObject<{
5263
+ readable: z.ZodBoolean;
5264
+ writable: z.ZodBoolean;
5265
+ editable: z.ZodBoolean;
5266
+ deletable: z.ZodExactOptional<z.ZodBoolean>;
5267
+ listable: z.ZodBoolean;
5268
+ searchable: z.ZodExactOptional<z.ZodBoolean>;
5269
+ }, z.core.$strict>>;
5270
+ verbDocs: z.ZodExactOptional<z.ZodObject<{
5271
+ read: z.ZodExactOptional<z.ZodString>;
5272
+ list: z.ZodExactOptional<z.ZodString>;
5273
+ search: z.ZodExactOptional<z.ZodString>;
5274
+ write: z.ZodExactOptional<z.ZodString>;
5275
+ edit: z.ZodExactOptional<z.ZodString>;
5276
+ delete: z.ZodExactOptional<z.ZodString>;
5277
+ }, z.core.$strict>>;
5278
+ permissionDefaults: z.ZodExactOptional<z.ZodObject<{
5279
+ read: z.ZodExactOptional<z.ZodEnum<{
5280
+ never: "never";
5281
+ allow: "allow";
5282
+ ask: "ask";
5283
+ }>>;
5284
+ write: z.ZodExactOptional<z.ZodEnum<{
5285
+ never: "never";
5286
+ allow: "allow";
5287
+ ask: "ask";
5288
+ }>>;
5289
+ edit: z.ZodExactOptional<z.ZodEnum<{
5290
+ never: "never";
5291
+ allow: "allow";
5292
+ ask: "ask";
5293
+ }>>;
5294
+ delete: z.ZodExactOptional<z.ZodEnum<{
5295
+ never: "never";
5296
+ allow: "allow";
5297
+ ask: "ask";
5298
+ }>>;
5299
+ }, z.core.$strict>>;
5300
+ authActions: z.ZodExactOptional<z.ZodObject<{
5301
+ actions: z.ZodRecord<z.ZodString, z.ZodObject<{
5302
+ purpose: z.ZodString;
5303
+ alternatives: z.ZodArray<z.ZodObject<{
5304
+ allOf: z.ZodArray<z.ZodObject<{
5305
+ scope: z.ZodString;
5306
+ reason: z.ZodExactOptional<z.ZodString>;
5307
+ }, z.core.$strict>>;
5308
+ }, z.core.$strict>>;
5309
+ }, z.core.$strict>>;
5310
+ rules: z.ZodArray<z.ZodUnion<readonly [z.ZodObject<{
5311
+ action: z.ZodString;
5312
+ operations: z.ZodExactOptional<z.ZodArray<z.ZodEnum<{
5313
+ search: "search";
5314
+ delete: "delete";
5315
+ list: "list";
5316
+ read: "read";
5317
+ write: "write";
5318
+ help: "help";
5319
+ edit: "edit";
5320
+ }>>>;
5321
+ routes: z.ZodExactOptional<z.ZodArray<z.ZodString>>;
5322
+ query: z.ZodExactOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
5323
+ }, z.core.$strict>, z.ZodObject<{
5324
+ public: z.ZodLiteral<true>;
5325
+ operations: z.ZodExactOptional<z.ZodArray<z.ZodEnum<{
5326
+ search: "search";
5327
+ delete: "delete";
5328
+ list: "list";
5329
+ read: "read";
5330
+ write: "write";
5331
+ help: "help";
5332
+ edit: "edit";
5333
+ }>>>;
5334
+ routes: z.ZodExactOptional<z.ZodArray<z.ZodString>>;
5335
+ query: z.ZodExactOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
5336
+ }, z.core.$strict>]>>;
5337
+ }, z.core.$strict>>;
5338
+ requiresConnection: z.ZodExactOptional<z.ZodLiteral<true>>;
5339
+ acceptsSourceCopy: z.ZodExactOptional<z.ZodLiteral<false>>;
5340
+ acceptsWriteSources: z.ZodExactOptional<z.ZodLiteral<true>>;
5341
+ acceptsBytes: z.ZodExactOptional<z.ZodLiteral<true>>;
5342
+ ownsLineSelectors: z.ZodExactOptional<z.ZodLiteral<true>>;
5343
+ description: z.ZodExactOptional<z.ZodString>;
5344
+ agentHint: z.ZodExactOptional<z.ZodObject<{
5345
+ summary: z.ZodString;
5346
+ commonFlows: z.ZodExactOptional<z.ZodArray<z.ZodObject<{
5347
+ label: z.ZodString;
5348
+ when: z.ZodExactOptional<z.ZodString>;
5349
+ example: z.ZodString;
5350
+ }, z.core.$strict>>>;
5351
+ helpUri: z.ZodExactOptional<z.ZodString>;
5352
+ triggers: z.ZodExactOptional<z.ZodObject<{
5353
+ keywords: z.ZodExactOptional<z.ZodArray<z.ZodString>>;
5354
+ patterns: z.ZodExactOptional<z.ZodArray<z.ZodString>>;
5355
+ }, z.core.$strict>>;
5356
+ skills: z.ZodExactOptional<z.ZodArray<z.ZodString>>;
5357
+ }, z.core.$strict>>;
5358
+ localId: z.ZodString;
5359
+ globalId: z.ZodString;
5360
+ schemes: z.ZodArray<z.ZodString>;
5361
+ displayName: z.ZodOptional<z.ZodString>;
5362
+ authServiceId: z.ZodOptional<z.ZodString>;
5363
+ knownResources: z.ZodOptional<z.ZodLiteral<true>>;
5364
+ describesOperations: z.ZodOptional<z.ZodLiteral<true>>;
5365
+ }, z.core.$strict>>>;
5366
+ kayAgentArtifactUriModules: z.ZodOptional<z.ZodArray<z.ZodObject<{
5367
+ localId: z.ZodString;
5368
+ globalId: z.ZodString;
5369
+ scheme: z.ZodString;
5370
+ editable: z.ZodBoolean;
5371
+ listable: z.ZodBoolean;
5372
+ deletable: z.ZodBoolean;
5373
+ appendable: z.ZodBoolean;
5374
+ storageScope: z.ZodEnum<{
5375
+ session: "session";
5376
+ family: "family";
5377
+ }>;
5378
+ }, z.core.$strict>>>;
5379
+ kayAgentEntityResolvers: z.ZodOptional<z.ZodArray<z.ZodObject<{
5380
+ localId: z.ZodString;
5381
+ globalId: z.ZodString;
5382
+ displayName: z.ZodOptional<z.ZodString>;
5383
+ uriModule: z.ZodString;
5384
+ entityTypes: z.ZodArray<z.ZodString>;
5385
+ uriHint: z.ZodString;
5386
+ }, z.core.$strict>>>;
5387
+ kayAgentGitHostClaims: z.ZodOptional<z.ZodArray<z.ZodObject<{
5388
+ host: z.ZodString;
5389
+ authServiceId: z.ZodString;
5390
+ authSchemeIds: z.ZodArray<z.ZodString>;
5391
+ authServiceDisplayName: z.ZodString;
5392
+ basicAuthUser: z.ZodString;
5393
+ }, z.core.$strict>>>;
5394
+ kayAgentTools: z.ZodOptional<z.ZodArray<z.ZodObject<{
5395
+ displayName: z.ZodOptional<z.ZodString>;
5396
+ description: z.ZodOptional<z.ZodString>;
5397
+ parameters: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodType<authoringCommonSchemas.JsonValue, unknown, z.core.$ZodTypeInternals<authoringCommonSchemas.JsonValue, unknown>>>>;
5398
+ requiresAuth: z.ZodOptional<z.ZodObject<{
5399
+ serviceId: z.ZodString;
5400
+ schemeId: z.ZodOptional<z.ZodString>;
5401
+ }, z.core.$strict>>;
5402
+ permission: z.ZodOptional<z.ZodObject<{
5403
+ kind: z.ZodEnum<{
5404
+ read: "read";
5405
+ mutate: "mutate";
5406
+ destructive: "destructive";
5407
+ execute: "execute";
5408
+ }>;
5409
+ ruleKey: z.ZodOptional<z.ZodString>;
5410
+ resourceArgs: z.ZodOptional<z.ZodArray<z.ZodString>>;
5411
+ }, z.core.$strict>>;
5412
+ localId: z.ZodString;
5413
+ globalId: z.ZodString;
5414
+ toolName: z.ZodString;
5415
+ }, z.core.$strict>>>;
5416
+ kayAppTools: z.ZodOptional<z.ZodArray<z.ZodObject<{
5417
+ localId: z.ZodString;
5418
+ globalId: z.ZodString;
5419
+ toolName: z.ZodString;
5420
+ }, z.core.$strict>>>;
5421
+ kayAppApprovalTypes: z.ZodOptional<z.ZodArray<z.ZodObject<{
5422
+ localId: z.ZodString;
5423
+ globalId: z.ZodString;
5424
+ kind: z.ZodEnum<{
5425
+ message: "message";
5426
+ change: "change";
5427
+ action: "action";
5428
+ access: "access";
5429
+ }>;
5430
+ }, z.core.$strict>>>;
5431
+ kayAppDataSources: z.ZodOptional<z.ZodArray<z.ZodObject<{
5432
+ localId: z.ZodString;
5433
+ globalId: z.ZodString;
5434
+ scope: z.ZodEnum<{
5435
+ session: "session";
5436
+ runtime: "runtime";
5437
+ account: "account";
5438
+ }>;
5439
+ snapshot: z.ZodObject<{
5440
+ version: z.ZodNumber;
5441
+ schema: z.ZodRecord<z.ZodString, z.ZodUnknown>;
5442
+ }, z.core.$strict>;
5443
+ change: z.ZodObject<{
5444
+ version: z.ZodNumber;
5445
+ schema: z.ZodRecord<z.ZodString, z.ZodUnknown>;
5446
+ semantics: z.ZodOptional<z.ZodDiscriminatedUnion<[z.ZodObject<{
5447
+ kind: z.ZodLiteral<"incremental">;
5448
+ }, z.core.$strict>, z.ZodObject<{
5449
+ kind: z.ZodLiteral<"snapshot-replacement">;
5450
+ maxEncodedBytes: z.ZodNumber;
5451
+ rationale: z.ZodString;
5452
+ }, z.core.$strict>], "kind">>;
5453
+ }, z.core.$strict>;
5454
+ read: z.ZodOptional<z.ZodObject<{
5455
+ request: z.ZodObject<{
5456
+ version: z.ZodNumber;
5457
+ schema: z.ZodRecord<z.ZodString, z.ZodType<authoringCommonSchemas.JsonValue, unknown, z.core.$ZodTypeInternals<authoringCommonSchemas.JsonValue, unknown>>>;
5458
+ }, z.core.$strict>;
5459
+ result: z.ZodObject<{
5460
+ version: z.ZodNumber;
5461
+ schema: z.ZodRecord<z.ZodString, z.ZodType<authoringCommonSchemas.JsonValue, unknown, z.core.$ZodTypeInternals<authoringCommonSchemas.JsonValue, unknown>>>;
5462
+ }, z.core.$strict>;
5463
+ }, z.core.$strict>>;
5464
+ }, z.core.$strict>>>;
5465
+ kayAppWhiteboardTypes: z.ZodOptional<z.ZodArray<z.ZodObject<{
5466
+ localId: z.ZodString;
5467
+ globalId: z.ZodString;
5468
+ displayName: z.ZodString;
5469
+ schemaVersion: z.ZodNumber;
5470
+ storage: z.ZodDiscriminatedUnion<[z.ZodObject<{
5471
+ kind: z.ZodLiteral<"json">;
5472
+ }, z.core.$strict>, z.ZodObject<{
5473
+ kind: z.ZodLiteral<"payload">;
5474
+ }, z.core.$strict>, z.ZodObject<{
5475
+ kind: z.ZodLiteral<"markdown">;
5476
+ bodyField: z.ZodString;
5477
+ }, z.core.$strict>], "kind">;
5478
+ valueSchema: z.ZodRecord<z.ZodString, z.ZodType<authoringCommonSchemas.JsonValue, unknown, z.core.$ZodTypeInternals<authoringCommonSchemas.JsonValue, unknown>>>;
5479
+ presentation: z.ZodOptional<z.ZodObject<{
5480
+ app: z.ZodString;
5481
+ }, z.core.$strict>>;
5482
+ }, z.core.$strict>>>;
5483
+ kayAppMcpServers: z.ZodOptional<z.ZodArray<z.ZodObject<{
5484
+ name: z.ZodString;
5485
+ pluginId: z.ZodString;
5486
+ url: z.ZodString;
5487
+ auth: z.ZodEnum<{
5488
+ oauth: "oauth";
5489
+ "api-key": "api-key";
5490
+ none: "none";
5491
+ }>;
5492
+ authServiceId: z.ZodOptional<z.ZodString>;
5493
+ }, z.core.$strict>>>;
5494
+ kayAgentConverters: z.ZodOptional<z.ZodArray<z.ZodObject<{
5495
+ localId: z.ZodString;
5496
+ globalId: z.ZodString;
5497
+ description: z.ZodOptional<z.ZodString>;
5498
+ mimeTypes: z.ZodArray<z.ZodString>;
5499
+ extensions: z.ZodOptional<z.ZodArray<z.ZodString>>;
5500
+ }, z.core.$strict>>>;
5501
+ referencePresentations: z.ZodOptional<z.ZodArray<z.ZodObject<{
5502
+ localId: z.ZodString;
5503
+ globalId: z.ZodString;
5504
+ uriModule: z.ZodString;
5505
+ resourceKind: z.ZodString;
5506
+ open: z.ZodDiscriminatedUnion<[z.ZodObject<{
5507
+ kind: z.ZodLiteral<"working-document">;
5508
+ }, z.core.$strict>, z.ZodObject<{
5509
+ kind: z.ZodLiteral<"browser-pane">;
5510
+ }, z.core.$strict>, z.ZodObject<{
5511
+ kind: z.ZodLiteral<"page">;
5512
+ pageId: z.ZodString;
5513
+ }, z.core.$strict>], "kind">;
5514
+ variants: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
5515
+ resourceKind: z.ZodString;
5516
+ presentationPluginId: z.ZodOptional<z.ZodString>;
5517
+ }, z.core.$strict>>>;
5518
+ claims: z.ZodOptional<z.ZodArray<z.ZodObject<{
5519
+ kind: z.ZodLiteral<"urlPattern">;
5520
+ pattern: z.ZodObject<{
5521
+ hostname: z.ZodString;
5522
+ pathname: z.ZodOptional<z.ZodString>;
5523
+ search: z.ZodOptional<z.ZodString>;
5524
+ protocol: z.ZodEnum<{
5525
+ http: "http";
5526
+ https: "https";
5527
+ }>;
5528
+ }, z.core.$strict>;
5529
+ brandIcon: z.ZodOptional<z.ZodString>;
5530
+ }, z.core.$strict>>>;
5531
+ tooltip: z.ZodOptional<z.ZodObject<{
5532
+ app: z.ZodString;
5533
+ pattern: z.ZodObject<{
5534
+ protocol: z.ZodString;
5535
+ hostname: z.ZodString;
5536
+ pathname: z.ZodOptional<z.ZodString>;
5537
+ search: z.ZodOptional<z.ZodString>;
5538
+ }, z.core.$strict>;
5539
+ }, z.core.$strict>>;
5540
+ }, z.core.$strict>>>;
5541
+ kayUiApps: z.ZodOptional<z.ZodArray<z.ZodObject<{
5542
+ localId: z.ZodString;
5543
+ globalId: z.ZodString;
5544
+ displayName: z.ZodString;
5545
+ contextOnly: z.ZodOptional<z.ZodLiteral<true>>;
5546
+ activityRail: z.ZodOptional<z.ZodObject<{
5547
+ section: z.ZodOptional<z.ZodEnum<{
5548
+ primary: "primary";
5549
+ plugins: "plugins";
5550
+ }>>;
5551
+ order: z.ZodOptional<z.ZodNumber>;
5552
+ icon: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
5553
+ svg: z.ZodString;
5554
+ }, z.core.$strict>]>>;
5555
+ }, z.core.$strict>>;
5556
+ description: z.ZodOptional<z.ZodString>;
5557
+ icon: z.ZodOptional<z.ZodString>;
5558
+ runtime: z.ZodLiteral<"kay.react-app.v1">;
5559
+ sdk: z.ZodObject<{
5560
+ range: z.ZodString;
5561
+ }, z.core.$strict>;
5562
+ entrypoint: z.ZodObject<{
5563
+ module: z.ZodString;
5564
+ export: z.ZodOptional<z.ZodString>;
5565
+ }, z.core.$strict>;
5566
+ styles: z.ZodOptional<z.ZodArray<z.ZodString>>;
5567
+ assets: z.ZodOptional<z.ZodArray<z.ZodString>>;
5568
+ capabilities: z.ZodOptional<z.ZodObject<{
5569
+ endpoints: z.ZodOptional<z.ZodArray<z.ZodObject<{
5570
+ localId: z.ZodString;
5571
+ globalId: z.ZodString;
5572
+ }, z.core.$strict>>>;
5573
+ host: z.ZodOptional<z.ZodArray<z.ZodEnum<{
5574
+ "sessions.create": "sessions.create";
5575
+ "memory.read": "memory.read";
5576
+ "skills.read": "skills.read";
5577
+ "automations.run": "automations.run";
5578
+ "artifacts.read": "artifacts.read";
5579
+ "navigation.open-session": "navigation.open-session";
5580
+ "artifacts.preview": "artifacts.preview";
5581
+ "cost.read": "cost.read";
5582
+ "billing.read": "billing.read";
5583
+ "context.read": "context.read";
5584
+ "usage.read": "usage.read";
5585
+ "self-improvement.read": "self-improvement.read";
5586
+ "automations.read": "automations.read";
5587
+ "shared-artifacts.read": "shared-artifacts.read";
5588
+ "workspace.place-pane": "workspace.place-pane";
5589
+ "workspace.pane-header": "workspace.pane-header";
5590
+ "workspace.arrange": "workspace.arrange";
5591
+ }>>>;
5592
+ }, z.core.$strict>>;
5593
+ }, z.core.$strict>>>;
5594
+ }, z.core.$strict>;
5595
+
5596
+ declare type ResolvedPluginContractV1 = z.infer<typeof ResolvedPluginContractV1>;
5597
+
3671
5598
  declare type ResolveExternalCliFailureReason = "not-external-cli" | "no-connection" | "account-ambiguous" | "account-not-found" | "not-authorized" | "host-unavailable";
3672
5599
 
3673
5600
  declare type ResolveExternalCliResult = {
@@ -3683,7 +5610,7 @@ declare type ResolveExternalCliResult = {
3683
5610
 
3684
5611
  /**
3685
5612
  * Derive a stable provider account id (and optional label) from a freshly connected access token,
3686
- * plus — when known — who the account belongs to.
5613
+ * plus - when known - who the account belongs to.
3687
5614
  *
3688
5615
  * A resolver almost always calls the provider's profile endpoint to derive `accountId` at all, so
3689
5616
  * the identity fields are already in the response: return them rather than flattening the person
@@ -3706,7 +5633,7 @@ declare type ResolvePluginAccounts = (accessToken: string) => Promise<readonly {
3706
5633
  declare interface ResolveTokenFailure {
3707
5634
  readonly ok: false;
3708
5635
  readonly reason: ResolveTokenFailureReason;
3709
- /** Actionable text the wrapper surfaces verbatim to the agent. */
5636
+ /** Actionable text the host surfaces verbatim to the agent. */
3710
5637
  readonly message: string;
3711
5638
  /** When ambiguous, the candidate accounts so the agent can pick one. */
3712
5639
  readonly accounts?: readonly AuthAccount[];
@@ -3719,7 +5646,7 @@ declare type ResolveTokenResult = ResolveTokenSuccess | ResolveTokenFailure;
3719
5646
 
3720
5647
  declare interface ResolveTokenSuccess {
3721
5648
  readonly ok: true;
3722
- readonly auth: ResolvedAuth;
5649
+ readonly credential: ResolvedCredential;
3723
5650
  }
3724
5651
 
3725
5652
  /** Match remaining characters in the buffer until end. If no characters are in buffer, no match */
@@ -3735,7 +5662,7 @@ declare function ReturnType_2<Type extends TSchema>(type: Type, options?: TSchem
3735
5662
  declare function ReturnTypeDeferred<Type extends TSchema>(type: Type, options?: TSchemaOptions): TReturnTypeDeferred<Type>;
3736
5663
 
3737
5664
  /** Observed cause of a failed request or interrupted run. */
3738
- declare const RUN_FAILURE_REASONS: readonly ["auth", "cancelled", "content_blocked", "context_overflow", "invalid_request", "model_disabled", "model_unavailable", "network", "organization_unavailable", "overloaded", "quota_exhausted", "rate_limit", "runtime_interrupted", "safeguard_block", "seat_unpaid", "server_error", "sign_in_required", "stream_interrupted", "timeout", "unknown"];
5665
+ declare const RUN_FAILURE_REASONS: readonly ["account_unreachable", "auth", "cancelled", "content_blocked", "context_overflow", "final_output_missing", "invalid_request", "model_disabled", "model_unavailable", "network", "organization_unavailable", "overloaded", "quota_exhausted", "rate_limit", "runtime_interrupted", "safeguard_block", "seat_unpaid", "server_error", "sign_in_required", "stream_interrupted", "timeout", "unknown"];
3739
5666
 
3740
5667
  declare type RunFailureReason = (typeof RUN_FAILURE_REASONS)[number];
3741
5668
 
@@ -4161,7 +6088,7 @@ declare interface SearchParams {
4161
6088
  readonly query: string;
4162
6089
  /**
4163
6090
  * Pure time filter narrowing results to a window. Providers MUST treat this as
4164
- * a time filter only — never as a signal to change topic scope, content domain,
6091
+ * a time filter only - never as a signal to change topic scope, content domain,
4165
6092
  * or ranking (oh-my-pi's Tavily `topic=news` coupling silently dropped docs).
4166
6093
  * Providers without temporal filtering MUST ignore it silently.
4167
6094
  */
@@ -4175,7 +6102,7 @@ declare interface SearchParams {
4175
6102
  /**
4176
6103
  * A web search backend behind the single `web_search` tool. Directly analogous
4177
6104
  * to a `UriModule` behind `read`/`write`: registered through `ExtensionApi`,
4178
- * merged per session, dispatched by the registry. Stateless and shareable —
6105
+ * merged per session, dispatched by the registry. Stateless and shareable -
4179
6106
  * per-call context (the abort signal and the {@link SearchProviderContext}) is
4180
6107
  * threaded into `search` and `isAvailable`.
4181
6108
  */
@@ -4191,17 +6118,18 @@ declare abstract class SearchProvider {
4191
6118
  */
4192
6119
  abstract readonly providerId: string;
4193
6120
  /**
4194
- * The capability⇄scheme binding when this provider resolves its OWN credential through the
6121
+ * The capability<->scheme binding when this provider resolves its OWN credential through the
4195
6122
  * service-extension auth system (stamped by {@link withResolvedSearchProvider}). `undefined`
4196
- * for providers that reuse inference credentials (the builtins) or need no auth. The runner
4197
- * reads it to surface the provider in `auth_status` as gated-until-connected, parallel to a
4198
- * tool's or URI module's `requiresAuth`.
6123
+ * for providers that reuse inference credentials (the builtins) or need no auth. When set, the
6124
+ * host resolves the credential onto {@link SearchProviderContext.credential} before it asks or
6125
+ * calls the provider, and `auth_status` lists the provider as gated-until-connected, parallel to
6126
+ * a tool's or URI module's `requiresAuth`.
4199
6127
  */
4200
6128
  readonly requiresAuth?: RequiresAuth;
4201
6129
  /**
4202
- * Cheap availability check (typically: does a usable credential resolve?). An own-credential
4203
- * provider returns `false` until its auth scheme has a connected account, so the chain skips
4204
- * it gracefully — the gating counterpart to a tool/module's discoverable-but-disallowed state.
6130
+ * Cheap availability check. The host never asks a provider with `requiresAuth` whose credential
6131
+ * did not resolve: it is unavailable, so the chain skips it - the gating counterpart to a
6132
+ * tool/module's discoverable-but-disallowed state.
4205
6133
  */
4206
6134
  abstract isAvailable(ctx?: SearchProviderContext): Promise<boolean> | boolean;
4207
6135
  /** Run the search. Throw {@link SearchProviderError} on a provider failure. */
@@ -4210,15 +6138,16 @@ declare abstract class SearchProvider {
4210
6138
 
4211
6139
  /**
4212
6140
  * Per-call context threaded into a provider's {@link SearchProvider.isAvailable} and
4213
- * {@link SearchProvider.search}. Carries the execute-time auth surface — the SAME
4214
- * `ctx.auth` a tool or URI module receives — scoped to the provider's OWNING extension,
4215
- * so a provider that declares its own credential (an api-key/oauth scheme via the
4216
- * service-extension auth system) can resolve a token. `auth` is absent for builtins
4217
- * (no owning extension; they reuse inference credentials through the host model execution capability)
4218
- * and outside a live session.
6141
+ * {@link SearchProvider.search}.
4219
6142
  */
4220
6143
  declare interface SearchProviderContext {
4221
- readonly auth?: ExtensionAuthContext;
6144
+ /**
6145
+ * The credential the host resolved for a provider that declares
6146
+ * {@link SearchProvider.requiresAuth}, for the session-active account. The host neither asks
6147
+ * nor calls such a provider when none resolves. Absent for a provider without `requiresAuth`
6148
+ * (builtins reuse inference credentials through the host model execution capability).
6149
+ */
6150
+ readonly credential?: ResolvedCredential;
4222
6151
  }
4223
6152
 
4224
6153
  /** Registry id of a search provider, e.g. `builtin:anthropic`. Open-ended for extensions. */
@@ -4277,19 +6206,19 @@ declare type SelectorDisposition = {
4277
6206
  * rebuilds it on each `AgentSession.reroot` (`@herd/herd-agent`) (the only event that
4278
6207
  * moves `cwd`), then evaluates every tool's predicate against it exactly once per change.
4279
6208
  *
4280
- * **CLOSED-CONTEXT INVARIANT (load-bearing — do not violate when extending this type).** This object
4281
- * carries ONLY primary facts that are *independent of tool availability* — `cwd`, `repoRoot`, and the
6209
+ * **CLOSED-CONTEXT INVARIANT (load-bearing - do not violate when extending this type).** This object
6210
+ * carries ONLY primary facts that are *independent of tool availability* - `cwd`, `repoRoot`, and the
4282
6211
  * planned `mode`/`platform`. It MUST NEVER carry the tool list, the active/effective set, or anything
4283
6212
  * else derived from availability. If a predicate's input could depend on another predicate's output,
4284
6213
  * evaluation would have to reach a fixpoint and could cycle. Because the context is closed, the kernel
4285
6214
  * evaluates each predicate ONCE per context change (one pass, no fixpoint) and caches the result. Keep
4286
6215
  * every future field in this same closed class so the single-pass guarantee survives.
4287
6216
  *
4288
- * Predicates reading this MUST be **pure and synchronous** — same context in ⇒ same answer out, no I/O,
6217
+ * Predicates reading this MUST be **pure and synchronous** - same context in => same answer out, no I/O,
4289
6218
  * no side effects. The host resolves the VCS facts (`repoRoot`); the predicate only inspects them.
4290
6219
  */
4291
6220
  declare interface SessionContext {
4292
- /** The session's current working directory (the live, re-rootable cwd — not the launch dir). */
6221
+ /** The session's current working directory (the live, re-rootable cwd - not the launch dir). */
4293
6222
  readonly cwd: string;
4294
6223
  /**
4295
6224
  * The enclosing VCS repository root for {@link cwd}, or `null` when `cwd` is not inside a repo.
@@ -4299,6 +6228,10 @@ declare interface SessionContext {
4299
6228
  readonly repoRoot: string | null;
4300
6229
  }
4301
6230
 
6231
+ declare const SignedInStatusCode: z.ZodNumber;
6232
+
6233
+ declare type SignedInStatusCode = z.infer<typeof SignedInStatusCode>;
6234
+
4302
6235
  /** Matches from Start and End capturing everything in-between. Start and End are consumed. */
4303
6236
  declare function Span<Start extends string, End extends string, MultiLine extends boolean, Input extends string>(start: Start, end: End, multiLine: MultiLine, input: Input): TSpan<Start, End, MultiLine, Input>;
4304
6237
 
@@ -4411,12 +6344,25 @@ declare const StringPattern = ".*";
4411
6344
  /** Creates a Symbol type. */
4412
6345
  declare function Symbol_2(options?: TSchemaOptions): TSymbol;
4413
6346
 
6347
+ /** Structurally the plugin SDK's `KayAppSessionEventCause`: only the fields the host reads. */
6348
+ declare interface SystemOneCallCause {
6349
+ readonly kind?: "session-event" | "backfill";
6350
+ readonly handler: string;
6351
+ readonly sourceSessionId: string;
6352
+ }
6353
+
4414
6354
  declare interface SystemOneCallOptions {
4415
6355
  readonly signal?: AbortSignal;
4416
6356
  /** Bounds the whole call, retries included. */
4417
6357
  readonly timeoutMs?: number;
4418
6358
  /** What the call is for, carried to the host's usage accounting. Never sent to a provider. */
4419
6359
  readonly purpose?: string;
6360
+ /**
6361
+ * The session event a plugin's call answers, so the host charges the call to that session.
6362
+ * The host checks the plugin is handling that session's event right now. Never sent to a
6363
+ * provider.
6364
+ */
6365
+ readonly cause?: SystemOneCallCause;
4420
6366
  }
4421
6367
 
4422
6368
  declare interface SystemOneClient {
@@ -4870,6 +6816,13 @@ declare type TApplyReadonly<Readonly extends TModifierOperation, Type extends T.
4870
6816
 
4871
6817
  declare type TApplyReverse<Types extends TSchema[], Reversed extends boolean> = Reversed extends true ? TReverse<Types> : Types;
4872
6818
 
6819
+ declare const TargetEntrypoint: z.ZodObject<{
6820
+ module: z.ZodString;
6821
+ export: z.ZodOptional<z.ZodString>;
6822
+ }, z.core.$strict>;
6823
+
6824
+ declare type TargetEntrypoint = z.infer<typeof TargetEntrypoint>;
6825
+
4873
6826
  /** Represents an Array type. */
4874
6827
  declare interface TArray<Type extends TSchema = TSchema> extends TSchema {
4875
6828
  '~kind': 'Array';
@@ -6645,7 +8598,7 @@ declare type TOmitInstantiate<Context extends TProperties, State extends TState,
6645
8598
  * classification (the engine records the rejection on an unexplained failure),
6646
8599
  * and a stored record with one reads as none.
6647
8600
  */
6648
- declare const TOOL_CALL_FAILURE_CODES: readonly ["tool.invalid_input", "tool.blocked", "tool.cancelled", "tool.timeout", "tool.not_found", "tool.unavailable", "tool.execution_failed", "provider.http", "provider.api", "provider.transport", "uri.not_found", "uri.unsupported_operation", "uri.not_connected", "uri.auth_unavailable", "permission.denied", "edit.empty_edits", "edit.text_not_found", "edit.text_not_unique", "edit.empty_old_text", "edit.overlapping_edits", "edit.no_change"];
8601
+ declare const TOOL_CALL_FAILURE_CODES: readonly ["tool.invalid_input", "tool.blocked", "tool.cancelled", "tool.timeout", "tool.not_found", "tool.unavailable", "tool.execution_failed", "tool.auth_unavailable", "tool.replies_owed", "provider.http", "provider.api", "provider.transport", "uri.not_found", "uri.unsupported_operation", "uri.not_connected", "uri.auth_unavailable", "permission.denied", "edit.empty_edits", "edit.text_not_found", "edit.text_not_unique", "edit.empty_old_text", "edit.overlapping_edits", "edit.no_change"];
6649
8602
 
6650
8603
  /**
6651
8604
  * ---
@@ -6663,14 +8616,14 @@ declare type ToolActionKind = "read" | "mutate" | "destructive" | "execute";
6663
8616
  * A tool's declarative availability gate. `when` is the authoritative predicate the kernel evaluates
6664
8617
  * against the live {@link SessionContext} to decide whether the tool is offered to the model here;
6665
8618
  * `description` is the always-shown, human-readable "why" a UI renders next to a tool the predicate
6666
- * disables (e.g. greyed on the new-session page). The predicate runs in the main process only — a
8619
+ * disables (e.g. greyed on the new-session page). The predicate runs in the main process only - a
6667
8620
  * renderer receives just the resolved `available: boolean` plus this `description`.
6668
8621
  *
6669
8622
  * `when` MUST be pure and synchronous (see {@link SessionContext}); a throw is caught by the kernel,
6670
- * treated as "unavailable", and surfaced as a session diagnostic — it never crashes the tool sync.
8623
+ * treated as "unavailable", and surfaced as a session diagnostic - it never crashes the tool sync.
6671
8624
  */
6672
8625
  declare interface ToolAvailability {
6673
- /** Pure, synchronous gate. `true` ⇒ the tool may be offered in this context; `false` ⇒ withheld. */
8626
+ /** Pure, synchronous gate. `true` => the tool may be offered in this context; `false` => withheld. */
6674
8627
  when(ctx: SessionContext): boolean;
6675
8628
  /** Human-readable reason the tool is/isn't available, always shown in UI. */
6676
8629
  description: string;
@@ -6698,6 +8651,7 @@ declare const toolCallFailureCauseSchema: z.ZodObject<{
6698
8651
  "not-found": "not-found";
6699
8652
  permission: "permission";
6700
8653
  unavailable: "unavailable";
8654
+ waiting: "waiting";
6701
8655
  }>;
6702
8656
  retryable: z.ZodBoolean;
6703
8657
  action: z.ZodEnum<{
@@ -6706,6 +8660,7 @@ declare const toolCallFailureCauseSchema: z.ZodObject<{
6706
8660
  retry: "retry";
6707
8661
  "correct-input": "correct-input";
6708
8662
  connect: "connect";
8663
+ wait: "wait";
6709
8664
  }>;
6710
8665
  details: z.ZodOptional<z.ZodObject<{
6711
8666
  moduleId: z.ZodOptional<z.ZodString>;
@@ -6714,6 +8669,7 @@ declare const toolCallFailureCauseSchema: z.ZodObject<{
6714
8669
  uri: z.ZodOptional<z.ZodString>;
6715
8670
  path: z.ZodOptional<z.ZodString>;
6716
8671
  validationField: z.ZodOptional<z.ZodString>;
8672
+ validationRule: z.ZodOptional<z.ZodString>;
6717
8673
  errorName: z.ZodOptional<z.ZodString>;
6718
8674
  errorCode: z.ZodOptional<z.ZodString>;
6719
8675
  providerCode: z.ZodOptional<z.ZodString>;
@@ -6728,14 +8684,14 @@ declare type ToolCallFailureCode = (typeof TOOL_CALL_FAILURE_CODES)[number];
6728
8684
 
6729
8685
  /**
6730
8686
  * The neutral around-execution hook: return `next()`'s result (possibly transformed) to run the
6731
- * real tool, or return a result without calling `next()` to substitute one — the tool then never
8687
+ * real tool, or return a result without calling `next()` to substitute one - the tool then never
6732
8688
  * executes. Every downstream consumer (the model, the session log, result clamps, failure
6733
8689
  * attribution) sees whatever is returned exactly as if the tool produced it. Throwing surfaces to
6734
8690
  * the caller as a tool failure, classified like any other.
6735
8691
  *
6736
8692
  * Interceptors compose as middleware: each receives a `next` that runs the REST of the chain, the
6737
8693
  * innermost `next` being the tool itself. `next` may be called at most the caller's own logic
6738
- * demands (zero to short-circuit, once to delegate, more to retry) — the kernel does not police
8694
+ * demands (zero to short-circuit, once to delegate, more to retry) - the kernel does not police
6739
8695
  * arity.
6740
8696
  */
6741
8697
  declare type ToolCallInterceptor = (call: ToolCallInvocation, next: () => Promise<AgentToolResult<unknown>>) => Promise<AgentToolResult<unknown>>;
@@ -6744,7 +8700,7 @@ declare type ToolCallInterceptor = (call: ToolCallInvocation, next: () => Promis
6744
8700
  declare interface ToolCallInvocation {
6745
8701
  readonly toolCallId: string;
6746
8702
  readonly toolName: string;
6747
- /** The call's arguments, already through `prepareArguments` — the shape `execute` receives. */
8703
+ /** The call's arguments, already through `prepareArguments` - the shape `execute` receives. */
6748
8704
  readonly params: unknown;
6749
8705
  readonly signal: AbortSignal | undefined;
6750
8706
  /**
@@ -6763,7 +8719,7 @@ declare interface ToolCallInvocation {
6763
8719
 
6764
8720
  /**
6765
8721
  * The model the call's result is about to be shown to, as the session holds it at execution
6766
- * time: identity plus pi's `input` list — the SAME field pi's adapters read when they build the
8722
+ * time: identity plus pi's `input` list - the SAME field pi's adapters read when they build the
6767
8723
  * next request, so a capability policy keyed on it agrees with what the provider will accept.
6768
8724
  * Absent when the wrap was built without a resolver; a policy must then treat the capability
6769
8725
  * as unknown, not as absent.
@@ -6798,7 +8754,7 @@ declare type ToolCallPermissionVerdict = {
6798
8754
  * What a tool call ADDRESSES, resolved by the session before execution from facts it already
6799
8755
  * holds for auth scoping: a URI verb's matched module (and the extension that registered it), or
6800
8756
  * an extension-contributed tool's owner. `ownerExtensionId` is absent for builtin/app-owned
6801
- * modules and tools — the session owns those, no extension does. A host policy that keys on
8757
+ * modules and tools - the session owns those, no extension does. A host policy that keys on
6802
8758
  * "which integration is this call about" reads this instead of re-parsing `params`.
6803
8759
  */
6804
8760
  declare type ToolCallTarget = {
@@ -6816,15 +8772,15 @@ declare interface ToolContext {
6816
8772
  readonly cwd: string;
6817
8773
  readonly model: Model<any> | undefined;
6818
8774
  /**
6819
- * The execute-time auth resolver the SDK tool wrapper (`withResolvedAuth`) reads to resolve a
6820
- * live token for the active (or per-call-overridden) account. Present when the session is bound
6821
- * to an `ExtensionAuthRuntime` (`@herd/herd-agent`); absent in always-on contexts
6822
- * (the wrapper short-circuits with an actionable message when undefined).
8775
+ * The credential the host resolved for this call, for a tool that declares
8776
+ * {@link ToolDefinition.requiresAuth}: the account named by the call's `accountId` argument, else
8777
+ * the session-active one. The host does not call the tool when none resolves. Absent for a tool
8778
+ * without `requiresAuth`, and outside a live session.
6823
8779
  */
6824
- readonly auth?: ExtensionAuthContext;
8780
+ readonly credential?: ResolvedCredential;
6825
8781
  /**
6826
8782
  * Detached work whose result should re-enter the conversation as a new turn (each completion calls
6827
- * `nextTurn()` and appears in the Background tasks panel). Not for fire-and-forget side effects —
8783
+ * `nextTurn()` and appears in the Background tasks panel). Not for fire-and-forget side effects -
6828
8784
  * use `ExtensionContext.runEffect`. Absent when the host wires no background-task manager.
6829
8785
  */
6830
8786
  readonly backgroundTasks?: ExtensionBackgroundTasksApi;
@@ -6846,9 +8802,9 @@ declare interface ToolContext {
6846
8802
  /**
6847
8803
  * Re-root the session into `newCwd` mid-run, recomposing the cwd-scoped substrate (builtin tools,
6848
8804
  * the capability registry, the system-prompt project line) in place so subsequent tool calls operate
6849
- * there — the conversation continues uninterrupted. This is the agent self-reroot seam: the
8805
+ * there - the conversation continues uninterrupted. This is the agent self-reroot seam: the
6850
8806
  * motivating caller is an app tool (e.g. `isolate_worktree`) that does its git ops then calls
6851
- * `ctx.reroot(worktreePath)` from inside its own `execute`. Safe mid-run — it never gates on idle.
8807
+ * `ctx.reroot(worktreePath)` from inside its own `execute`. Safe mid-run - it never gates on idle.
6852
8808
  * Present only with a live session (absent in session-less inventory/standalone contexts, like
6853
8809
  * {@link auth}). `reason` labels the transition for observability (e.g. `"worktree-isolation"`).
6854
8810
  */
@@ -6889,12 +8845,12 @@ declare interface ToolDefinition<TParams extends ToolParametersWire = ToolParame
6889
8845
  executionMode?: ToolExecutionMode;
6890
8846
  /**
6891
8847
  * How long a single execution may legitimately stay silent (#3785).
6892
- * - `"fast"` (the default when omitted): the execution is bounded — if it
8848
+ * - `"fast"` (the default when omitted): the execution is bounded - if it
6893
8849
  * neither settles nor loses the abort race within the fast-tool deadline
6894
8850
  * (120s), the kernel fails the call with a timeout error the model can
6895
8851
  * react to. Right for local reads/writes and short network calls, which
6896
8852
  * finish in seconds or are stuck.
6897
- * - `"long"`: no deadline — a build under a shell, a parent parked on a
8853
+ * - `"long"`: no deadline - a build under a shell, a parent parked on a
6898
8854
  * child task. The abort race still applies: a user Stop always wins,
6899
8855
  * whether or not the tool honors its `signal`.
6900
8856
  * Declare `"long"` only when unbounded silent execution is genuinely part
@@ -6911,29 +8867,29 @@ declare interface ToolDefinition<TParams extends ToolParametersWire = ToolParame
6911
8867
  */
6912
8868
  replaySafe?: true;
6913
8869
  /**
6914
- * Optional capability⇄scheme binding. When present this tool is auth-gated: discoverable when
6915
- * unauthed, callable once the binding is satisfied. The SDK's `withResolvedAuth`
6916
- * stamps this; absent means an ordinary always-on tool (additive — nothing changes for existing
6917
- * tools that omit it).
8870
+ * Optional capability<->scheme binding. When present this tool is auth-gated: discoverable when
8871
+ * unauthed, callable once the binding is satisfied, and the host resolves its credential onto
8872
+ * {@link ToolContext.credential} before each call. The SDK's `withResolvedAuth` stamps this; absent
8873
+ * means an ordinary always-on tool.
6918
8874
  */
6919
8875
  requiresAuth?: RequiresAuth;
6920
8876
  /**
6921
8877
  * Optional declarative availability gate ({@link ToolAvailability}). When present, the kernel
6922
8878
  * evaluates `availability.when` against the live {@link SessionContext} once per context change
6923
8879
  * (session start + each reroot) and withholds the tool from the model-visible set wherever it
6924
- * returns `false`. Backward-compatible: **absent ⇒ always available**. Orthogonal to
6925
- * mode-disallowed sets and to auth/permission gates — availability answers only "does this tool
8880
+ * returns `false`. Backward-compatible: **absent => always available**. Orthogonal to
8881
+ * mode-disallowed sets and to auth/permission gates - availability answers only "does this tool
6926
8882
  * apply in this context", and composes with the others at the same chokepoint.
6927
8883
  */
6928
8884
  availability?: ToolAvailability;
6929
8885
  /**
6930
8886
  * Optional declarative permission classification ({@link ToolPermissionHint}). Consulted by
6931
8887
  * the permission gate ONLY for tools the classifier does not otherwise recognize (extension/app
6932
- * tools), letting a tool relax the fail-closed `execute` fallback (a pure staging tool → `read`),
8888
+ * tools), letting a tool relax the fail-closed `execute` fallback (a pure staging tool -> `read`),
6933
8889
  * declare its provider `scheme`, derive the `resources` a call touches (a browser
6934
8890
  * navigation's target origin) so per-provider and per-origin rules can gate it.
6935
8891
  * Because it lives on the definition it is
6936
- * provenance-bound. Backward-compatible: **absent ⇒ the classifier's default (`execute`, no
8892
+ * provenance-bound. Backward-compatible: **absent => the classifier's default (`execute`, no
6937
8893
  * scheme)**.
6938
8894
  */
6939
8895
  permission?: ToolPermissionHint;
@@ -6987,7 +8943,7 @@ declare type ToolParametersWire = unknown;
6987
8943
  * definition (the same shape of author-declared, kernel-read fact as `requiresAuth` and
6988
8944
  * `availability`). Consulted ONLY when the classifier does not otherwise recognize the tool
6989
8945
  * (never overrides `read`/`bash`/URI builtins), so a tool can relax the fail-closed
6990
- * `execute` fallback (e.g. a pure staging tool → `read`) or scope itself for per-provider and
8946
+ * `execute` fallback (e.g. a pure staging tool -> `read`) or scope itself for per-provider and
6991
8947
  * per-origin rules. Because it lives on the registered definition, it is provenance-bound: a
6992
8948
  * tool named the same as another carries its OWN hint, never inherits a first-party one.
6993
8949
  *
@@ -6996,7 +8952,7 @@ declare type ToolParametersWire = unknown;
6996
8952
  * touch protected config must NOT declare `read`. Bonsai's embedded-experience tools never touch
6997
8953
  * `configDir`, so this is safe for them. `read` is also what every capability surface reports as
6998
8954
  * "read-only" (Bonsai's Permissions page groups and defaults on it), so it is a claim about what the
6999
- * tool DOES — never a way to buy silence. A tool that should raise no ask on its own account
8955
+ * tool DOES - never a way to buy silence. A tool that should raise no ask on its own account
7000
8956
  * declares {@link ToolPermissionHint.quiet} and keeps its honest `kind`.
7001
8957
  */
7002
8958
  declare interface ToolPermissionHint {
@@ -7013,8 +8969,8 @@ declare interface ToolPermissionHint {
7013
8969
  readonly ruleKey?: string;
7014
8970
  /**
7015
8971
  * Overrides the ask rail's default human-response window for THIS tool's asks, in ms.
7016
- * A UX window declaration, not authority: it cannot loosen or tighten what is asked —
7017
- * kind/ruleKey/scheme/rules/mode all decide that exactly as they would without it —
8972
+ * A UX window declaration, not authority: it cannot loosen or tighten what is asked -
8973
+ * kind/ruleKey/scheme/rules/mode all decide that exactly as they would without it -
7018
8974
  * only how long the prompt waits before it lapses unanswered (`expired`, which the gate
7019
8975
  * already treats as `unanswered`, never `denied`). Bounded use case: a suggestion-shaped
7020
8976
  * tool whose silence means "continue" (e.g. `suggest_compaction`'s 15s ask, chosen to
@@ -7025,26 +8981,26 @@ declare interface ToolPermissionHint {
7025
8981
  /**
7026
8982
  * Derives the resources a call touches from its validated input (e.g. the target origin of
7027
8983
  * a browser navigation). Pure and total; a throw is treated as "no resources" and the call
7028
- * falls back to the plain classification (fail-closed — never crashes the gate).
8984
+ * falls back to the plain classification (fail-closed - never crashes the gate).
7029
8985
  */
7030
8986
  readonly deriveResources?: (input: Record<string, unknown>) => readonly string[];
7031
8987
  /**
7032
8988
  * Derives a call's classification (`kind`/`ruleKey`/`scheme`) from its validated input, where
7033
8989
  * the static fields above fix them for every call. This is the generalization of
7034
- * {@link deriveResources} (input → resources) to the rule-matching triple, and of the kernel's
8990
+ * {@link deriveResources} (input -> resources) to the rule-matching triple, and of the kernel's
7035
8991
  * built-in `deriveBashRuleKey` (a bash call's argv sharpens its key) to an author-declared tool.
7036
8992
  *
7037
8993
  * Returns a partial: each present field OVERRIDES the static hint for this call; each absent
7038
8994
  * field (or a wholly `undefined` return) falls back to the static hint, then the fail-closed
7039
8995
  * default. Pure and total; a throw is treated as "no refinement" and the call falls back to the
7040
- * static hint (fail-closed — never crashes the gate).
8996
+ * static hint (fail-closed - never crashes the gate).
7041
8997
  *
7042
8998
  * It grants no authority the static fields don't already grant: it computes the same
7043
8999
  * kind/ruleKey/scheme the tool could hard-code, per call rather than once. `kind` here matters
7044
9000
  * because the same tool can read on one input and execute on another, which a static `kind`
7045
9001
  * cannot express.
7046
9002
  *
7047
- * Exemplar — Bonsai's `mcp` proxy tool, one tool spanning every server: `search`/`describe` derive
9003
+ * Exemplar - Bonsai's `mcp` proxy tool, one tool spanning every server: `search`/`describe` derive
7048
9004
  * `{ kind: "read" }` (metadata lookups), while `call` derives
7049
9005
  * `{ kind: "execute", ruleKey: "mcp:<server>::<tool>", scheme: "<server>" }`, so a
7050
9006
  * `{ scheme: "<server>" }` rule gates a whole server and a `{ ruleKey: "mcp:<server>::<tool>" }`
@@ -7061,7 +9017,7 @@ declare interface ToolPermissionHint {
7061
9017
  * deriver is a pure function of its own input and cannot see the target's hint, its service
7062
9018
  * scheme, or the kernel's own recognition of names like `bash` and the URI verbs. Resolution
7063
9019
  * re-enters classification under the target's identity, so a proxied call matches EXACTLY the
7064
- * rules its direct form would — same kind, same ruleKey, same scheme.
9020
+ * rules its direct form would - same kind, same ruleKey, same scheme.
7065
9021
  *
7066
9022
  * A hop ADDS the target's rules; it never SUBTRACTS the carrier's. The carrier's own
7067
9023
  * classification rides along (`ToolActionPreflight.carrier`) and the controller takes the
@@ -7071,22 +9027,22 @@ declare interface ToolPermissionHint {
7071
9027
  * alone could not.
7072
9028
  *
7073
9029
  * Not consulted at all when the CARRIER is a tool the kernel classifies itself (`bash`, the URI
7074
- * verbs, the read tools) — the same invariant that governs the rest of this hint. A proxy may
9030
+ * verbs, the read tools) - the same invariant that governs the rest of this hint. A proxy may
7075
9031
  * still freely TARGET one of them.
7076
9032
  *
7077
9033
  * Pure and total. EVERY abnormal outcome falls back to the carrier's own classification, never
7078
9034
  * to an intermediate link: a throw, a malformed return, a blank target name, a non-object input,
7079
9035
  * a cycle, or a chain longer than 4 hops. (Falling back to an intermediate would itself be a
7080
- * bypass — a crafted 5-link chain could present hop 4's benign classification for a call whose
9036
+ * bypass - a crafted 5-link chain could present hop 4's benign classification for a call whose
7081
9037
  * real target is `bash rm -rf /`.) Only a chain terminating normally, at a tool declaring no
7082
9038
  * further proxy, hops at all.
7083
9039
  *
7084
- * "Fail-closed" here means the carrier's own classification applies — the identity the call
7085
- * really had — not that the result is always stricter than the target's. How much gate is left
9040
+ * "Fail-closed" here means the carrier's own classification applies - the identity the call
9041
+ * really had - not that the result is always stricter than the target's. How much gate is left
7086
9042
  * on such a call is exactly how much the CARRIER carries: an `execute` carrier is stricter than
7087
9043
  * a `read` target and equal to a `mutate`/`destructive` one outside allow mode, while a
7088
9044
  * {@link quiet} carrier (Bonsai's own `call_tool`) contributes no mode default at all, so the
7089
- * fallback leaves nothing but the carrier's rules and the protected-path deny — and the carrier
9045
+ * fallback leaves nothing but the carrier's rules and the protected-path deny - and the carrier
7090
9046
  * names no path, so that deny has nothing to fire on. This is why a carrier must refuse a target
7091
9047
  * that is itself a carrier: no chain long or circular enough to reach the fallback can be built,
7092
9048
  * which is the only thing that keeps the fallback from being toothless. Fail-closed is a
@@ -7097,24 +9053,24 @@ declare interface ToolPermissionHint {
7097
9053
  * Declares that this tool's identity contributes its RULES to the gate but not its MODE
7098
9054
  * DEFAULT. A rule about it still applies in full (a deny denies, an ask asks, an allow
7099
9055
  * allows) and the protected-path hard-deny still fires; what is withheld is the verdict the
7100
- * MODE would reach from `kind` alone — default/ask mode's "anything but a read asks".
9056
+ * MODE would reach from `kind` alone - default/ask mode's "anything but a read asks".
7101
9057
  *
7102
9058
  * It is a statement about this identity's CONTRIBUTION, never about what the call does.
7103
9059
  * `kind` stays the honest declaration of the strongest effect a call can have, and a quiet
7104
- * tool declares it exactly as loudly as a noisy one — which is the whole point: buying
9060
+ * tool declares it exactly as loudly as a noisy one - which is the whole point: buying
7105
9061
  * silence with `kind: "read"` instead moves the call below the protected-path hard-deny and
7106
9062
  * reports the tool as read-only on every capability surface.
7107
9063
  *
7108
9064
  * It exists for a PROXY CARRIER ({@link deriveProxiedCall}), and is honest only for a tool
7109
9065
  * whose only effect is invoking the target the gate is already classifying beside it: the
7110
9066
  * target's kind, rules, resources and the protected-path deny all still decide, so a proxied
7111
- * call is gated exactly like the direct one — no more, and no ask the direct call would never
9067
+ * call is gated exactly like the direct one - no more, and no ask the direct call would never
7112
9068
  * have raised. Bonsai's `call_tool` declares `{ kind: "execute", quiet: true }` (owner ruling,
7113
9069
  * 2026-08-18): honest about everything it can reach, silent on its own account.
7114
9070
  *
7115
9071
  * Quiet is not ungated, but it IS nearly all the gate a lone carrier has. On a call that
7116
9072
  * classifies as the carrier because no hop resolved (a cycle, an over-long chain), a quiet
7117
- * carrier leaves only its own rules — see {@link deriveProxiedCall}'s fail-closed paragraph
9073
+ * carrier leaves only its own rules - see {@link deriveProxiedCall}'s fail-closed paragraph
7118
9074
  * for why a carrier must therefore refuse a carrier as a target.
7119
9075
  */
7120
9076
  readonly quiet?: boolean;
@@ -8317,32 +10273,43 @@ declare interface UriAgentHint {
8317
10273
  readonly triggers?: UriHintTriggers;
8318
10274
  /**
8319
10275
  * Skill invocation names (flat `localId`s, e.g. `"gmail-email-triage"`) that hold this module's
8320
- * deeper workflow judgment — the name a `read skill://<name>` dispatch resolves, not a display
10276
+ * deeper workflow judgment - the name a `read skill://<name>` dispatch resolves, not a display
8321
10277
  * title or a path. Point here only at skills that actually exist in the composed skill roster;
8322
10278
  * a dangling name sends the agent to a `skill://` read for nothing.
8323
10279
  */
8324
10280
  readonly skills?: readonly string[];
8325
10281
  }
8326
10282
 
8327
- declare type UriAuthActionClassification = {
8328
- readonly kind: "action";
8329
- readonly actionId: string;
8330
- } | {
8331
- readonly kind: "public";
8332
- };
8333
-
8334
10283
  /**
8335
- * Finite authorization actions plus the pure route classifier that selects one before dispatch.
8336
- * An exception, an unknown action id, or `undefined` classification fails closed in the host.
10284
+ * Finite authorization actions plus the rules that select one before dispatch. A call no rule
10285
+ * matches, or a rule naming an action that is not in `actions`, fails closed in the host.
8337
10286
  */
8338
10287
  declare interface UriAuthActionPolicy {
8339
10288
  readonly actions: Readonly<Record<string, ScopeRequirement>>;
8340
- classifyOperation(request: {
8341
- readonly operation: UriOperation;
8342
- readonly uri: string;
8343
- }): UriAuthActionClassification | undefined;
10289
+ /** Absent matches no call, so every call fails closed. */
10290
+ readonly rules?: readonly UriAuthActionRule[];
8344
10291
  }
8345
10292
 
10293
+ /**
10294
+ * One row of a module's sign-in action rules: which calls need which action. A row matches a call
10295
+ * when every condition it names holds; a condition it leaves out matches anything. The first
10296
+ * matching row decides, so a row with no conditions at the end means "everything else".
10297
+ */
10298
+ declare type UriAuthActionRule = {
10299
+ /** The verbs this row covers. */
10300
+ readonly operations?: readonly UriOperation[];
10301
+ /** The claim `route` ids this row covers, matched against the call's address. */
10302
+ readonly routes?: readonly string[];
10303
+ /** Query parameters the address must carry with exactly these values (`{ permanent: "true" }`). */
10304
+ readonly query?: Readonly<Record<string, string>>;
10305
+ } & ({
10306
+ /** The {@link UriAuthActionPolicy.actions} entry the call needs. */
10307
+ readonly action: string;
10308
+ } | {
10309
+ /** The call needs no credential. */
10310
+ readonly public: true;
10311
+ });
10312
+
8346
10313
  declare interface UriAuthRef {
8347
10314
  readonly serviceId: string;
8348
10315
  readonly schemeId: string;
@@ -8364,7 +10331,7 @@ declare interface UriAuthRequirement {
8364
10331
  */
8365
10332
  readonly requiredScopes?: readonly string[];
8366
10333
  /**
8367
- * The service id connect guidance should NAME when this module is gated — a host-composed
10334
+ * The service id connect guidance should NAME when this module is gated - a host-composed
8368
10335
  * front door whose connect grants exactly this module's scopes (e.g. `gmail` expanding onto
8369
10336
  * the shared `google.account` credential). Guidance only; resolution keys on
8370
10337
  * `(serviceId, schemeId)`. Absent, guidance names `serviceId`.
@@ -8410,6 +10377,21 @@ declare type UriCachePolicyResolver = (operation: UriOperation, cacheUri: string
8410
10377
 
8411
10378
  declare type UriClaim = UriSchemeClaim | UriPatternClaim | UrlPatternClaim;
8412
10379
 
10380
+ /**
10381
+ * A URL with `:name` placeholders for the claim's captures. Each capture is escaped for where it
10382
+ * lands: lowercased in the host, one path segment (a `:name*` capture keeps its `/`), or a query
10383
+ * or fragment value. `{transform(...)}` runs one named, built-in transform over the text inside
10384
+ * it, captures pasted in unescaped, and escapes the output for where it lands:
10385
+ *
10386
+ * - `base64`: unpadded base64 of the UTF-8 text (`{base64(:id :calendar)}`).
10387
+ * - `slackTimestamp`: a Slack archive message token as the API's timestamp
10388
+ * (`p1783350000000100` becomes `1783350000.000100`).
10389
+ *
10390
+ * A transform that cannot read its input fills nothing. A claim whose `normalizeTo` fills nothing
10391
+ * does not match; a `sourceUrl` that fills nothing paints no link.
10392
+ */
10393
+ declare type UriClaimTemplate = string;
10394
+
8413
10395
  declare interface UriCommonFlow {
8414
10396
  readonly label: string;
8415
10397
  readonly when?: string;
@@ -8459,41 +10441,28 @@ declare interface UriExample {
8459
10441
  readonly operation?: UriOperation;
8460
10442
  }
8461
10443
 
8462
- declare interface UriExtensionModule extends Omit<UriModule, "verbs"> {
10444
+ /**
10445
+ * A plugin's URI module. Its claims route, spell and describe its addresses, so it has no
10446
+ * `matches`, `normalize` or `describe`. It also has no `fallback` (a plugin's addresses are always
10447
+ * claimed) and no `locate` (a plugin has no file on disk for the daemon to open).
10448
+ */
10449
+ declare interface UriExtensionModule extends Omit<UriModule, "verbs" | "normalize" | "matches" | "describe" | "fallback" | "locate"> {
8463
10450
  readonly verbs: UriVerbSupport;
8464
10451
  /** Human-facing per-verb effect docs; see {@link UriVerbDocs}. */
8465
10452
  readonly verbDocs?: UriVerbDocs;
8466
10453
  /**
8467
10454
  * Plugin-declared default permission per verb group. A verb group set to `"ask"`
8468
- * compiles into a defaults-level ask rule — the user is prompted by default but can
10455
+ * compiles into a defaults-level ask rule - the user is prompted by default but can
8469
10456
  * override with an explicit allow. Undeclared = `"allow"` (fail-open).
8470
10457
  * See {@link UriPermissionDefaults}.
8471
10458
  */
8472
10459
  readonly permissionDefaults?: UriPermissionDefaults;
8473
10460
  /** Requires a resolved URI connection before any verb handler runs. */
8474
10461
  readonly requiresConnection?: boolean;
8475
- /** Pure route-aware permission facts; see {@link UriExtensionOperationPermissionPolicy}. */
8476
- readonly permission?: UriExtensionOperationPermissionPolicy;
8477
10462
  /** False rejects generic write-tool `source` copies before source fetch. */
8478
10463
  readonly acceptsSourceCopy?: boolean;
8479
10464
  }
8480
10465
 
8481
- declare interface UriExtensionOperationPermissionPolicy {
8482
- /**
8483
- * Classify one canonical route, purely. `write`/`edit`/`delete` may only be made stricter
8484
- * than the verb default; `help`/`read`/`list`/`search` must stay `"read"` (a `ruleKey` is
8485
- * allowed), because the kernel reruns a crash-interrupted read without asking again. Any
8486
- * other answer, or a throw, fails the call closed.
8487
- */
8488
- classifyOperation(request: {
8489
- readonly operation: UriOperation;
8490
- readonly uri: string;
8491
- }): {
8492
- readonly kind: "read" | "mutate" | "destructive" | "execute";
8493
- readonly ruleKey?: string;
8494
- } | undefined;
8495
- }
8496
-
8497
10466
  declare interface UriExternalCliRunner {
8498
10467
  readonly run: (request: UriExternalCliRunRequest) => Promise<UriExternalCliRunResult>;
8499
10468
  }
@@ -8528,6 +10497,8 @@ declare interface UriHelp {
8528
10497
  * than text the module's author wrote. Absent: the module's own text.
8529
10498
  */
8530
10499
  readonly thirdPartyContent?: true;
10500
+ /** The module's own markdown for this result, shown instead of the host's default rendering. */
10501
+ readonly markdown?: string;
8531
10502
  }
8532
10503
 
8533
10504
  declare interface UriHintTriggers {
@@ -8567,6 +10538,12 @@ declare interface UriListResult {
8567
10538
  readonly items: readonly UriListItem[];
8568
10539
  readonly nextCursor?: string;
8569
10540
  readonly metadata?: UriListMetadata;
10541
+ /** How long the host may cache this result; see {@link UriCachePolicy.ttlMs}. */
10542
+ readonly cachePolicy?: Pick<UriCachePolicy, "ttlMs">;
10543
+ /** The module's own markdown for this result, shown instead of the host's default rendering. */
10544
+ readonly markdown?: string;
10545
+ /** The touched resource's name for the transcript row, as on `RawResource.label`. */
10546
+ readonly label?: UriResourceLabel;
8570
10547
  }
8571
10548
 
8572
10549
  declare type UriLocateContext = Pick<UriResolveContext, "cwd" | "signal" | "connection" | "sessionId" | "paths"> & {
@@ -8584,31 +10561,13 @@ declare type UriLocateResult = {
8584
10561
  readonly kind: "not-disk-backed";
8585
10562
  };
8586
10563
 
8587
- declare type UriMarkdownRenderInput = {
8588
- readonly operation: "help";
8589
- readonly uri: string;
8590
- readonly result: UriHelp;
8591
- } | {
8592
- readonly operation: "list";
8593
- readonly uri: string;
8594
- readonly result: UriListResult;
8595
- } | {
8596
- readonly operation: "search";
8597
- readonly uri: string;
8598
- readonly result: UriSearchResult;
8599
- } | {
8600
- readonly operation: Extract<UriOperation, "write" | "edit" | "delete">;
8601
- readonly uri: string;
8602
- readonly result: UriMutationResult;
8603
- };
8604
-
8605
10564
  declare interface UriModule {
8606
10565
  readonly id: string;
8607
10566
  /**
8608
10567
  * Explicit human-readable name for catalog/display purposes (the plugin
8609
10568
  * manifest's `contributes.uriModules[].displayName`, threaded through by
8610
- * hand since there is no automatic manifest→runtime-module composition
8611
- * step). Falls back to a mechanical id-derived title when absent — see
10569
+ * hand since there is no automatic manifest->runtime-module composition
10570
+ * step). Falls back to a mechanical id-derived title when absent - see
8612
10571
  * `uriCatalogTitle`.
8613
10572
  */
8614
10573
  readonly title?: string;
@@ -8628,14 +10587,26 @@ declare interface UriModule {
8628
10587
  * calls `parseLineSelector` itself and reports what it did through `RawResource.selector`.
8629
10588
  */
8630
10589
  readonly ownsLineSelectors?: boolean;
10590
+ /** Opt in to host-resolved supplementary sources; absent means unsupported. */
10591
+ readonly acceptsWriteSources?: boolean;
10592
+ /**
10593
+ * Opt in to raw bytes as `write`'s content; absent means text and JSON only. The `write`
10594
+ * tool's `source` copy leg is the only producer: a provider's binary resource (an attachment,
10595
+ * an image, a PDF) reaches a module that declares this as a `Uint8Array`, never decoded into
10596
+ * the model's context, and a binary copy to any other module is refused before it runs.
10597
+ */
10598
+ readonly acceptsBytes?: boolean;
8631
10599
  readonly claims?: readonly UriClaim[];
10600
+ /**
10601
+ * The routes the module's scheme-root `help` lists, as data, so a host can list them without
10602
+ * calling `help`.
10603
+ */
10604
+ readonly templates?: readonly UriTemplate[];
8632
10605
  /** Migration-only prompt summary until structured help/catalog coverage replaces prose. */
8633
10606
  readonly description?: string;
8634
10607
  readonly agentHint?: UriAgentHint;
8635
10608
  readonly requiresAuth?: UriAuthRequirement;
8636
10609
  readonly authActions?: UriAuthActionPolicy;
8637
- /** Pure route/payload validation applied before a consequential permission ask. */
8638
- readonly preflight?: UriOperationPreflightPolicy;
8639
10610
  /**
8640
10611
  * Structured facts for approval surfaces, or `undefined` when unavailable.
8641
10612
  * A one-line description must name the whole consequence; `preview` instead
@@ -8645,120 +10616,46 @@ declare interface UriModule {
8645
10616
  * of covered payload fields and query parameters. Unknown fields cost the summary.
8646
10617
  * The host owns framing, the whole-quote fit (no elision) and display-safety admission.
8647
10618
  *
8648
- * Unlike preflight, this hook is async and may do I/O. Resolve names through `ctx`,
10619
+ * This hook is async and may do I/O. Resolve names through `ctx`,
8649
10620
  * the same dispatch context used by execution, never an ambient or cached account. A name
8650
10621
  * the module resolved under that account may be cached for a bounded time, keyed by that
8651
10622
  * account's identity and never answered to another account or after a failed lookup.
8652
- * The host calls it once before raising the ask, enforces the short `ctx.signal`
8653
- * deadline and discards late answers. A throw yields no summary and a module-attributed
8654
- * diagnostic; declining costs a click into the app, never an under-described approval.
8655
- */
8656
- describeOperation?(request: {
8657
- readonly operation: UriOperation;
8658
- readonly uri: string;
8659
- readonly payload: unknown;
8660
- }, ctx: UriResolveContext): Promise<UriOperationDescription | undefined>;
8661
- /**
8662
- * Rebuild a call from the person's "Allow with edits" answer: the same payload
8663
- * {@link describeOperation} was given, with the values the person typed into the preview's
8664
- * `editable` fields put in their place. Implement it beside any preview that marks a field
8665
- * `editable`; without it the host drops every editable marker from that module's previews, so
8666
- * a field is never offered for editing that cannot be honoured.
8667
- *
8668
- * Pure and fast: it must not send, write or otherwise act, and it should not do I/O (it gets
8669
- * the dispatch context `ctx` only so a name can be resolved the way `describeOperation` does).
8670
- * Return the COMPLETE amended payload in the shape the module's own handler reads. Validate it
8671
- * with the handler's own schema, so an amended call is exactly as valid as one the model made.
8672
- * Decline by returning `undefined` or throwing; either denies the call with nothing done.
8673
- *
8674
- * The host calls it once, after the person allowed the call, never for a denial, and only for
8675
- * a `write` whose payload this module described. The kernel passes the `edits` through
8676
- * unchanged. Bonsai's daemon has already refused, before the ask settled, a key that is not an
8677
- * `editable` field of the preview it showed, a repeated key, a blank value and a value past the
8678
- * field's `maxLength`, but another host may not, so refuse each of those here yourself (return
8679
- * `undefined`).
10623
+ * The host calls it once before raising the ask and waits for the answer, with no deadline;
10624
+ * `ctx.signal` fires when the host stops waiting (the session closes, or a caller gives up),
10625
+ * and a late answer is discarded. A throw yields no
10626
+ * summary and a module-attributed diagnostic; declining costs a click into the app, never an
10627
+ * under-described approval.
8680
10628
  *
8681
- * The host then holds the amended call to what the person was shown, in two steps, and runs it
8682
- * only if both pass. It classifies the amended call again and requires the same tool, rule key,
8683
- * kind, resources, scheme and target address, so an edit cannot reach a different route. It then
8684
- * calls {@link describeOperation} on the amended call and requires that preview to read exactly
8685
- * as the one the person saw, apart from the values of the fields they edited: the same title, the
8686
- * same fields in the same order, each with the same label, key, `editable` marker and
10629
+ * "Allow with edits": a field marked `editable` may be rewritten by the person on the card.
10630
+ * The host rebuilds the call itself (see the field's `editable`), then holds the rebuilt call to
10631
+ * what the person was shown, in two steps, and runs it only if both pass. It classifies the
10632
+ * rebuilt call again and requires the same tool, rule key, kind, resources, scheme and target
10633
+ * address. It then calls this hook on the rebuilt call and requires that preview to read exactly
10634
+ * as the one the person saw, apart from the values of the fields they edited: the same title,
10635
+ * the same fields in the same order, each with the same label, key, `editable` marker and
8687
10636
  * `maxLength`, and every read-only field with the same value. Anything else refuses the call
8688
- * with nothing done: a mismatch, and also a describer that is missing, declines, throws or
8689
- * overruns its deadline. The `description` line is not compared.
8690
- *
8691
- * So rebuild from the original payload and change only the fields you offered. A recipient, a
8692
- * thread or an attachment list that an amendment changed is caught by the second step, but only
8693
- * where the preview shows it: put whatever says where a call goes, or what it does beyond its
10637
+ * with nothing done: a mismatch, and also an answer of `undefined` or a throw. The `description`
10638
+ * line is not compared. So put whatever says where a call goes, or what it does beyond its
8694
10639
  * editable fields, in the preview's `title` or a field, never only in its `description`, and
8695
10640
  * keep recipients, destinations and thread bindings out of `editable` fields.
8696
10641
  */
8697
- amendOperation?(request: {
10642
+ describeOperation?(request: {
8698
10643
  readonly operation: UriOperation;
8699
10644
  readonly uri: string;
8700
10645
  readonly payload: unknown;
8701
- readonly edits: readonly UriPreviewEdit[];
8702
- }, ctx: UriResolveContext): Promise<UriOperationAmendment | undefined>;
8703
- /**
8704
- * A short, render-only name for the resource a settled call on `request.uri` touched, which the
8705
- * host stamps on the tool result's `details` so a transcript row can name it where it would
8706
- * otherwise print the address (`#lane-analytics` and `thread`, not a channel id). Answer
8707
- * `undefined` for any address you cannot honestly name.
8708
- *
8709
- * Called once per successful URI verb call, AFTER the verb handler has returned, with the same
8710
- * dispatch context. Resolve names through `ctx` and nothing else, and prefer a cache your own
8711
- * verb handlers warm, keyed by the executing account: a name one account saw is never answered
8712
- * to another, and a failed, blank or aborted lookup is never cached. The host bounds the wait
8713
- * (a finished result is held at most a quarter of a second), gives `ctx.signal` a hard deadline,
8714
- * and drops a late, thrown or refused answer without failing the call; a throw is reported as a
8715
- * module-attributed diagnostic. The label is a label, never an identity: the address remains the
8716
- * click target, hover text and accessible name. It is UI-only, so it never enters the tool
8717
- * result's content and no telemetry reads it.
8718
- *
8719
- * Unlike `describeOperation` this is not an approval surface: it carries no consequence, no
8720
- * quote and no coverage claim, and nothing may gate a permission on it.
8721
- */
8722
- labelResource?(request: UriResourceLabelRequest, ctx: UriResolveContext): Promise<UriResourceLabel | undefined>;
8723
- /**
8724
- * Per-resource observability: does a `format: "observation"` read of THIS
8725
- * uri render source-native material ({@link UriResolveContext.format})?
8726
- * Route-parse only — cheap, side-effect-free, no I/O, no auth (the same
8727
- * discipline as `matches`); a throw is treated as `false`. Returning true
8728
- * is the resource's contract that its observation read returns an
8729
- * observation render and that failures under that format throw typed,
8730
- * status-bearing errors rather than resolving a friendly fallback page.
8731
- * The kernel stamps the answer onto the resource's access events, which is
8732
- * what ambient index consumers replay on — so "PRs are observable" is
8733
- * declared here, route by route, never module-wide. Absent means no read
8734
- * of this module is observable. A vendor's own gone-vocabulary (HTTP 410,
8735
- * a 200-body "ok:false"/"archived:true"/"status:cancelled", or a
8736
- * 403/404-ambiguous lost-access response) is this module's job to
8737
- * translate into `UriNotFoundError` or a `status: 404` error under the
8738
- * observation format — the fold that retires a doc never learns vendor
8739
- * vocabulary (see `ObservationMaterial`'s doc comment).
8740
- */
8741
- observes?(uri: string): boolean;
8742
- /**
8743
- * Head-only revision probe: the resource's CURRENT source-native revision
8744
- * without fetching its body, or `undefined` when that cannot be known
8745
- * cheaply. The host calls it before a repeat `read` of an address the
8746
- * session already holds, with `ctx.expectedRevision` set to the revision
8747
- * that read reported (`RawResourceMetadata.revision`); a value equal to it
8748
- * means "unchanged" and the fetch is skipped, anything else falls through
8749
- * to the ordinary read. A module whose read revision embeds more than the
8750
- * head can know (a content digest beside a stat stamp) may answer relative
8751
- * to `expectedRevision` — return it when the cheap part matches, `undefined`
8752
- * when it does not — but must never return a value it has not verified.
8753
- * `undefined` is always safe: it costs one fetch, never a wrong answer.
8754
- * Must be cheaper than the read (a metadata request, a `stat`); a throw is
8755
- * treated as `undefined`.
8756
- */
8757
- revision?(uri: string, ctx: UriResolveContext): Promise<string | undefined>;
10646
+ }, ctx: UriResolveContext): Promise<UriOperationDescription | undefined>;
8758
10647
  readonly getCachePolicy?: UriCachePolicyResolver;
8759
- /** Retained matching escape hatch; future dispatch should prefer compiled claims. */
8760
- matches(input: string, ctx: UriResolveContext): boolean;
10648
+ /**
10649
+ * Code matching, for the host's own modules whose addresses no claim can describe (a bare file
10650
+ * path). A plugin module has none; it routes through its `claims` alone.
10651
+ */
10652
+ matches?(input: string, ctx: UriResolveContext): boolean;
10653
+ /** The official spelling, for the host's own modules; a plugin's comes from its claims' `normalizeTo`. */
8761
10654
  normalize?(input: string, ctx: UriResolveContext): UriNormalizeResult | undefined;
10655
+ /**
10656
+ * The pill's title and link, for the host's own modules only; a plugin module has none, and its
10657
+ * pill comes from its claims' `title` and `sourceUrl`.
10658
+ */
8762
10659
  describe?(input: string, ctx: UriDescribeContext): UriResourceDescription | undefined;
8763
10660
  locate?(input: string, ctx: UriLocateContext): Promise<UriLocateResult>;
8764
10661
  /**
@@ -8771,33 +10668,21 @@ declare interface UriModule {
8771
10668
  read(input: string, ctx: UriResolveContext): Promise<RawResource>;
8772
10669
  /** Observes only; see {@link read}. */
8773
10670
  help?(input: string, ctx: UriResolveContext): Promise<UriHelp>;
8774
- write?(input: string, content: UriPayload, ctx: UriResolveContext): Promise<UriMutationResult | void>;
8775
- /** Opt-in structured write with one or more host-resolved resources delivered beside the content. */
8776
- writeWithSources?(input: string, content: UriPayload, sources: readonly UriWriteSource[], ctx: UriResolveContext): Promise<UriMutationResult | void>;
8777
- /**
8778
- * Opt-in byte sink: write RAW BYTES to this address, no UTF-8 round trip.
8779
- * `UriPayload` is text/JSON by contract, so a module that can store bytes
8780
- * declares it here instead of stretching `write`. The only caller today is
8781
- * the `write` tool's `source` copy leg, which is how a provider's binary
8782
- * resource — a Gmail attachment, an image, a PDF, a zip — reaches a
8783
- * byte-capable destination without ever being decoded into the model's
8784
- * context. A module that omits it is text-only, and a binary copy targeting
8785
- * it is refused with an error naming a byte-capable destination.
8786
- *
8787
- * `source` describes what the bytes are: a filesystem-backed sink can ignore
8788
- * it (the target path already carries the name), while a remote provider
8789
- * sink needs it to name and type the stored file. It sits before `ctx` so a
8790
- * forwarding wrapper that fails to thread it is a compile error, not a
8791
- * silent drop.
10671
+ /**
10672
+ * `sources` is empty for ordinary writes; populated only with `acceptsWriteSources: true`.
10673
+ * `content` is a `Uint8Array` only with `acceptsBytes: true`, and then `ctx.writeSource`
10674
+ * names and types it. It is `undefined` when the call carried neither `content` nor `source`.
10675
+ * The module decides what that means: a route that takes no body (a folder
10676
+ * create) proceeds, and a route that needs one refuses with an error naming
10677
+ * what is missing. Never treat it as empty content.
8792
10678
  */
8793
- writeBytes?(input: string, bytes: Uint8Array, source: UriSourceDescriptor, ctx: UriResolveContext): Promise<UriMutationResult | void>;
10679
+ write?(input: string, content: UriPayload | Uint8Array | undefined, sources: readonly UriWriteSource[], ctx: UriResolveContext): Promise<UriMutationResult | void>;
8794
10680
  edit?(input: string, patch: UriPayload, ctx: UriResolveContext): Promise<UriMutationResult>;
8795
10681
  /** Observes only; see {@link read}. */
8796
10682
  list?(input: string, params: UriListParams, ctx: UriResolveContext): Promise<UriListResult>;
8797
10683
  /** Observes only; see {@link read}. */
8798
10684
  search?(input: string, params: UriSearchParams, ctx: UriResolveContext): Promise<UriSearchResult>;
8799
10685
  delete?(input: string, ctx: UriResolveContext): Promise<UriMutationResult>;
8800
- toMarkdown?(input: UriMarkdownRenderInput, ctx: UriResolveContext): string | undefined;
8801
10686
  }
8802
10687
 
8803
10688
  /** Authoritative lifecycle facts for a successful record-like URI mutation. */
@@ -8823,6 +10708,12 @@ declare interface UriMutationResult {
8823
10708
  readonly receipt?: UriMutationReceipt;
8824
10709
  /** Opaque source-native revision after this successful mutation. */
8825
10710
  readonly revision?: string;
10711
+ /** Cached reads this mutation made stale; see {@link UriCachePolicy.invalidate}. */
10712
+ readonly cachePolicy?: Pick<UriCachePolicy, "invalidate">;
10713
+ /** The module's own markdown for this result, shown instead of the host's default rendering. */
10714
+ readonly markdown?: string;
10715
+ /** The touched resource's name for the transcript row, as on `RawResource.label`. */
10716
+ readonly label?: UriResourceLabel;
8826
10717
  }
8827
10718
 
8828
10719
  declare interface UriNodeCapability {
@@ -8843,11 +10734,6 @@ declare interface UriNormalizeResult {
8843
10734
 
8844
10735
  declare type UriOperation = "help" | "read" | "write" | "edit" | "list" | "search" | "delete";
8845
10736
 
8846
- /** The call {@link UriModule.amendOperation} rebuilt: the whole payload, in the shape the module reads. */
8847
- declare interface UriOperationAmendment {
8848
- readonly payload: unknown;
8849
- }
8850
-
8851
10737
  declare interface UriOperationDescription {
8852
10738
  /** Static verb phrase authored by the module. Never interpolated from input. */
8853
10739
  readonly action: string;
@@ -8870,9 +10756,11 @@ declare interface UriOperationDescription {
8870
10756
  */
8871
10757
  readonly key?: string;
8872
10758
  /**
8873
- * `true` offers this field to the person for editing on the approval card. Offer it only
8874
- * when the module implements {@link UriModule.amendOperation} for this call and can honour
8875
- * any value within `maxLength`; the host drops the offer otherwise. Absent means read-only.
10759
+ * `true` offers this field to the person for editing on the approval card. The host applies
10760
+ * an edit itself: it copies the payload and replaces the value of the top-level string
10761
+ * property named `key`. So offer a field only when the payload is an object, `key` is one
10762
+ * of its string properties, and the module would send any value within `maxLength` as it
10763
+ * sends the model's; the host drops the offer otherwise. Absent means read-only.
8876
10764
  */
8877
10765
  readonly editable?: true;
8878
10766
  /** Longest edited value, in UTF-16 code units. Meaningful only with `editable`. */
@@ -8890,56 +10778,6 @@ declare interface UriOperationDescription {
8890
10778
  };
8891
10779
  }
8892
10780
 
8893
- /**
8894
- * Pure, route-aware validation that runs before permission policy can surface an ask.
8895
- *
8896
- * This is deliberately narrower than execution: it receives only the canonical URI,
8897
- * operation, and operation payload, performs no I/O, and returns a user-actionable
8898
- * rejection for calls that the module already knows cannot succeed. The handler must
8899
- * still validate again when it executes because approval is not an authority boundary.
8900
- */
8901
- declare interface UriOperationPreflightPolicy {
8902
- /**
8903
- * The rejection half. Optional since kay#7684: a module whose only preflight
8904
- * fact is affirmative (`acceptsPayloadlessWrite`) must not have to stub a
8905
- * validator that never rejects.
8906
- */
8907
- validateOperation?(request: {
8908
- readonly operation: UriOperation;
8909
- readonly uri: string;
8910
- readonly payload: unknown;
8911
- }): string | undefined;
8912
- /**
8913
- * Route-level affirmative: may a `write` to this URI carry NO payload at all
8914
- * — neither `content` nor `source`? (The canonical case is folder creation,
8915
- * e.g. `?type=folder`.) The write tool's generic shape rule requires exactly
8916
- * one payload form; a route answers `true` here when a payloadless write is
8917
- * meaningful FOR THAT ROUTE, and the rule then admits the call.
8918
- *
8919
- * This exists because an empty body is not always sendable: on some
8920
- * model/provider paths a top-level empty-string argument (`content: ""`)
8921
- * never reaches the host — the key arrives absent, indistinguishable from an
8922
- * omitted argument (kay#7684). A contract that can only be invoked with an
8923
- * empty string is unreachable on those paths, so a route whose write is
8924
- * meaningful with no body must declare it and let the caller omit the
8925
- * payload instead.
8926
- *
8927
- * Pure and side-effect-free like {@link validateOperation}: route-parse
8928
- * only, no I/O. A throw NEVER admits the write, but the two consult paths
8929
- * disagree on purpose about what happens next: pre-ask (permission
8930
- * resolution, which must never crash the gate) answers no and records a
8931
- * module-attributed diagnostic; at execute time the write tool asks only
8932
- * when the call genuinely carries no payload, and a throw there is the
8933
- * module's own bug surfacing as the call's error — louder than a misleading
8934
- * \"provide exactly one of content or source\" the model could never
8935
- * satisfy. Absent means no route of this module accepts a payloadless
8936
- * write.
8937
- */
8938
- acceptsPayloadlessWrite?(request: {
8939
- readonly uri: string;
8940
- }): boolean;
8941
- }
8942
-
8943
10781
  declare interface UriParameter {
8944
10782
  readonly name: string;
8945
10783
  readonly in: "uri" | "query" | "selector";
@@ -8949,29 +10787,60 @@ declare interface UriParameter {
8949
10787
  readonly examples?: readonly unknown[];
8950
10788
  }
8951
10789
 
10790
+ /**
10791
+ * A claim on a module's own custom-scheme addresses. The pattern matches with or without an
10792
+ * account prefix: `gcal://@work/events/x` is matched as `gcal://events/x`, and the prefix is put
10793
+ * back on the official spelling, so one claim covers both spellings.
10794
+ */
8952
10795
  declare interface UriPatternClaim {
8953
10796
  readonly kind: "uriPattern";
8954
10797
  readonly pattern: UriPatternInit;
8955
10798
  /**
8956
- * Canonical spelling rebuilt from the captures. When the template keeps the
8957
- * input's scheme (the module's own addressing), the input's query string is
10799
+ * Canonical spelling rebuilt from the captures (see {@link UriClaimTemplate}). When the template
10800
+ * keeps the input's scheme (the module's own addressing), the input's query string is
8958
10801
  * carried over verbatim so a route flag such as `?permanent=true` survives
8959
10802
  * canonicalization (kay#7859); a template that re-targets to another scheme
8960
10803
  * (a projection to a web link) drops it, as does a pattern that consumed the
8961
10804
  * query itself or a template that spells its own.
8962
10805
  */
8963
- readonly normalizeTo?: string;
10806
+ readonly normalizeTo?: UriClaimTemplate;
10807
+ /**
10808
+ * Names the route this claim matches, so data keyed by route (a module's sign-in action rules)
10809
+ * can say which addresses it means. Several claims may name the same route.
10810
+ */
10811
+ readonly route?: string;
10812
+ /**
10813
+ * The web page a matched address opens, filled from the captures (see
10814
+ * {@link UriClaimTemplate}). The host matches an address's official spelling and paints its
10815
+ * reference with the source URL of the first matching claim that declares one.
10816
+ */
10817
+ readonly sourceUrl?: UriClaimTemplate;
10818
+ /**
10819
+ * The name a matched address's reference shows: literal text, with each `:name` replaced by
10820
+ * that capture as decoded (`"Flow :flow"`, or a fixed `"BFS"`). The first matching claim that
10821
+ * declares one names the address.
10822
+ */
10823
+ readonly title?: string;
8964
10824
  readonly examples?: readonly string[];
8965
10825
  }
8966
10826
 
8967
10827
  declare interface UriPatternInit {
8968
10828
  readonly protocol?: string;
10829
+ /**
10830
+ * Dot-delimited host pattern. A pattern that is one capture (`:owner`) takes the whole host,
10831
+ * dots included, as a `github://some.org/repo` owner must.
10832
+ */
8969
10833
  readonly hostname?: string;
8970
10834
  /**
8971
10835
  * Slash-delimited path pattern. A final capture may use `:name*` to consume
8972
- * the remaining path segments, preserving `/` in the captured value.
10836
+ * the remaining path segments, preserving `/` in the captured value. Unless the pattern itself
10837
+ * ends in `/`, an input path ending in one `/` matches as if the slash were absent, so
10838
+ * `threads/t1/` is `threads/t1` (captures and official spelling included) and a lone `/` after a
10839
+ * host is the empty path; a doubled `//` is never dropped, nor the root path of an address with
10840
+ * no host (`bfs:///`).
8973
10841
  */
8974
10842
  readonly pathname?: string;
10843
+ /** `&`-delimited query pattern; `""` matches only an address with no query. */
8975
10844
  readonly search?: string;
8976
10845
  }
8977
10846
 
@@ -8990,7 +10859,7 @@ declare interface UriPayloadContract {
8990
10859
 
8991
10860
  /**
8992
10861
  * The three-state permission vocabulary a plugin declares for its default permissions.
8993
- * Maps to `PermissionRule.effect`: `allow` → allow, `ask` → ask, `never` → deny.
10862
+ * Maps to `PermissionRule.effect`: `allow` -> allow, `ask` -> ask, `never` -> deny.
8994
10863
  */
8995
10864
  declare type UriPermissionDefault = "allow" | "ask" | "never";
8996
10865
 
@@ -9008,19 +10877,6 @@ declare interface UriPermissionDefaults {
9008
10877
  readonly delete?: UriPermissionDefault;
9009
10878
  }
9010
10879
 
9011
- /**
9012
- * One change a person made to an `editable` field of a call's action preview ("Allow with
9013
- * edits"): the field's `key` and the value they want it to hold. Values are message content, so
9014
- * a module must not log or persist them.
9015
- */
9016
- declare interface UriPreviewEdit {
9017
- readonly key: string;
9018
- readonly value: string;
9019
- }
9020
-
9021
- /** The read shape a caller may request via {@link UriResolveContext.format}. */
9022
- declare type UriReadFormat = "observation";
9023
-
9024
10880
  declare interface UriResolveContext {
9025
10881
  readonly cwd: string;
9026
10882
  readonly signal?: AbortSignal;
@@ -9029,8 +10885,8 @@ declare interface UriResolveContext {
9029
10885
  readonly auth?: UriResolvedAuth;
9030
10886
  /**
9031
10887
  * Id of the session dispatching this call, stamped by the host at the dispatch site.
9032
- * It never originates from anything the caller can influence — no verb argument, no write
9033
- * body — so a module may treat it as trustworthy caller identity and stamp it onto writes.
10888
+ * It never originates from anything the caller can influence - no verb argument, no write
10889
+ * body - so a module may treat it as trustworthy caller identity and stamp it onto writes.
9034
10890
  *
9035
10891
  * Absent when no session owns the dispatch: registry matching and permission pre-checks
9036
10892
  * resolve a URI outside any verb call.
@@ -9038,14 +10894,14 @@ declare interface UriResolveContext {
9038
10894
  readonly sessionId?: string;
9039
10895
  /**
9040
10896
  * WHO the dispatching session acts as, stamped by the host at the same dispatch site as
9041
- * {@link UriResolveContext.sessionId} and just as un-influenceable by the caller — so a module
10897
+ * {@link UriResolveContext.sessionId} and just as un-influenceable by the caller - so a module
9042
10898
  * writing to a store it owns can record the actor without the agent being able to choose one.
9043
10899
  *
9044
10900
  * Free text minted by the host's own runtime (Bonsai's form is `user`, `subagent`,
9045
10901
  * `system/<surface>`, `followup/<surface>`) rather than a closed union: the surface half is the
9046
10902
  * host's vocabulary, and a second enumeration of it here would drift from the first.
9047
10903
  *
9048
- * Absent whenever the host has nothing to say — no session owns the dispatch, or the session
10904
+ * Absent whenever the host has nothing to say - no session owns the dispatch, or the session
9049
10905
  * predates the host recording an origin. A module must then omit the actor rather than assume
9050
10906
  * one; an invented actor written into a durable artifact can never be walked back.
9051
10907
  */
@@ -9061,7 +10917,7 @@ declare interface UriResolveContext {
9061
10917
  readonly origin: "model" | "host";
9062
10918
  /**
9063
10919
  * The daemon-assigned id of the run driving this invocation, when the host's own execution
9064
- * frame carried one. Absent means the frame carried none — never a reason to guess one: a
10920
+ * frame carried one. Absent means the frame carried none - never a reason to guess one: a
9065
10921
  * module recording this onto a durable artifact must treat absence as unresolved provenance,
9066
10922
  * not as "no run was active".
9067
10923
  */
@@ -9070,39 +10926,33 @@ declare interface UriResolveContext {
9070
10926
  readonly toolName?: string;
9071
10927
  };
9072
10928
  /**
9073
- * An OPAQUE, host-captured context for the mutation this dispatch is about to make —
10929
+ * An OPAQUE, host-captured context for the mutation this dispatch is about to make -
9074
10930
  * the artifact-provenance counterpart of `sessionId`/`actor`, and stamped at the same
9075
10931
  * un-influenceable dispatch site.
9076
10932
  *
9077
10933
  * The host composes it from facts a caller cannot supply: which session is acting, the
9078
10934
  * run driving it, the tool invocation, and whatever the host resolved about how that
9079
- * session came to exist. The kernel treats it as an uninterpreted JSON value — it never
10935
+ * session came to exist. The kernel treats it as an uninterpreted JSON value - it never
9080
10936
  * reads a field, only checks that the value is lossless JSON before it crosses the
9081
- * dispatch boundary — so this layer stays ignorant of any one product's provenance
10937
+ * dispatch boundary - so this layer stays ignorant of any one product's provenance
9082
10938
  * semantics. A module that owns a durable artifact carries it to its store and validates
9083
10939
  * it against its OWN schema at the point it persists, where the target revision is known.
9084
10940
  *
9085
10941
  * Absent means the host captured nothing for this dispatch (a read, a host with no
9086
- * capture resolver, or a capture that failed) — never a claim that there was nothing to
10942
+ * capture resolver, or a capture that failed) - never a claim that there was nothing to
9087
10943
  * capture. Present only on mutating dispatches (`write`/`edit`/`delete`); reads never pay
9088
10944
  * for it.
9089
10945
  */
9090
10946
  readonly captureContext?: Readonly<Record<string, unknown>>;
9091
10947
  /**
9092
- * Requested read shape. A module may ignore this and return its normal read; honoring
9093
- * it means returning an `ObservationMaterial` via `observationResource(...)` instead.
9094
- * Opt-in only — there is no advertisement surface or capability flag.
9095
- */
9096
- readonly format?: UriReadFormat;
9097
- /**
9098
- * Host-provided writable data root for the OWNING extension of the module handling this call —
10948
+ * Host-provided writable data root for the OWNING extension of the module handling this call -
9099
10949
  * structurally identical to the per-extension `paths` a tool/handler context already receives, so
9100
10950
  * a module authored against both surfaces reads `ctx.paths?.dataDir` uniformly. Lets a URI module
9101
10951
  * own durable local state (a JSON store, a small file tree) instead of the host constructing and
9102
10952
  * injecting it. Host-populated after dispatch selects a module and keyed to that module's owner;
9103
10953
  * always absent during matching, and absent for modules with no owning extension (builtins) or a
9104
10954
  * host that wires no per-module data dir. Unlike a tool context, the host only NAMES this path for
9105
- * a URI module and does NOT pre-create the directory — create it on first write and tolerate its
10955
+ * a URI module and does NOT pre-create the directory - create it on first write and tolerate its
9106
10956
  * absence on read.
9107
10957
  */
9108
10958
  readonly paths?: {
@@ -9117,6 +10967,15 @@ declare interface UriResolveContext {
9117
10967
  * proceeds as before.
9118
10968
  */
9119
10969
  readonly expectedRevision?: string;
10970
+ /**
10971
+ * The revision this session already holds for the address a `read` is about to fetch: the
10972
+ * `RawResourceMetadata.revision` its last read reported. Set only on a repeat `read`, never
10973
+ * on a mutation (`expectedRevision` is the mutation witness). A module with a cheap
10974
+ * current-revision check (a metadata request, a `stat`) may compare first and, when it has
10975
+ * verified the two are equal, answer {@link RawResource.unchanged} with no body. A module
10976
+ * with no such check ignores it and reads in full, which is always correct.
10977
+ */
10978
+ readonly knownRevision?: string;
9120
10979
  /** Host marks a mediated session that enforces its private revision witness ledger. */
9121
10980
  readonly requiresRevisionWitness?: boolean;
9122
10981
  /** Host-derived descriptor for a top-level copied resource; absent for inline writes. */
@@ -9126,26 +10985,13 @@ declare interface UriResolveContext {
9126
10985
  declare interface UriResolvedAuth {
9127
10986
  readonly connection?: UriConnection;
9128
10987
  /** Present only for verb handlers of a module declaring `requiresAuth`; absent during matching. */
9129
- readonly credential?: UriResolvedCredential;
10988
+ readonly credential?: ResolvedCredential;
9130
10989
  /** Present for handlers gated by a non-injectable external-CLI readiness scheme. */
9131
10990
  readonly externalCli?: UriExternalCliRunner;
9132
10991
  /** Opaque host metadata; not a credential channel. */
9133
10992
  readonly metadata?: Record<string, unknown>;
9134
10993
  }
9135
10994
 
9136
- declare interface UriResolvedCredential {
9137
- /** Bearer for OAuth schemes, apiKey for api-key schemes. Host-resolved and refreshed. */
9138
- readonly accessToken: string;
9139
- readonly accountId: string;
9140
- readonly schemeId: string;
9141
- readonly scopes?: readonly string[];
9142
- /**
9143
- * Every value of a multi-field api-key credential, keyed by the scheme's declared field id
9144
- * (`accessToken` mirrors the primary field). Absent for single-secret schemes.
9145
- */
9146
- readonly fields?: Readonly<Record<string, string>>;
9147
- }
9148
-
9149
10995
  declare interface UriResourceDescription {
9150
10996
  readonly uri: string;
9151
10997
  /** Absent when the caller should retain its existing label. */
@@ -9165,12 +11011,9 @@ declare interface UriResourceLabel {
9165
11011
  readonly section?: string;
9166
11012
  }
9167
11013
 
9168
- /** The call a module is asked to label. */
9169
- declare interface UriResourceLabelRequest {
9170
- readonly operation: UriOperation;
9171
- /** The dispatch address: selector-stripped, the exact form the module's verb handler received. */
9172
- readonly uri: string;
9173
- }
11014
+ declare const UriScheme: z.ZodString;
11015
+
11016
+ declare type UriScheme = z.infer<typeof UriScheme>;
9174
11017
 
9175
11018
  declare interface UriSchemeClaim {
9176
11019
  readonly kind: "scheme";
@@ -9205,15 +11048,21 @@ declare interface UriSearchResult {
9205
11048
  * so the caller knows the matches may be partial.
9206
11049
  */
9207
11050
  readonly metadata?: UriListMetadata;
11051
+ /** How long the host may cache this result; see {@link UriCachePolicy.ttlMs}. */
11052
+ readonly cachePolicy?: Pick<UriCachePolicy, "ttlMs">;
11053
+ /** The module's own markdown for this result, shown instead of the host's default rendering. */
11054
+ readonly markdown?: string;
11055
+ /** The touched resource's name for the transcript row, as on `RawResource.label`. */
11056
+ readonly label?: UriResourceLabel;
9208
11057
  }
9209
11058
 
9210
11059
  /**
9211
11060
  * What a copied resource IS, minus its bytes: the identity half of a mediated
9212
11061
  * source. The host derives it once (filename inferred from the source address,
9213
11062
  * `mimeType` carried from the source module's own `RawResource.mimeType`) and
9214
- * delivers it on both byte-bearing write hooks — inside each `UriWriteSource`,
9215
- * and as the standalone third argument to `writeBytes` — so a remote sink can
9216
- * name and type what it stores without re-deriving either from raw bytes.
11063
+ * delivers it inside each `UriWriteSource`, and on `ctx.writeSource` for a
11064
+ * `source` copy - so a remote sink can name and type what it stores without
11065
+ * re-deriving either from raw bytes.
9217
11066
  */
9218
11067
  declare interface UriSourceDescriptor {
9219
11068
  readonly uri: string;
@@ -9228,11 +11077,11 @@ declare interface UriTemplate {
9228
11077
  /**
9229
11078
  * Per-operation effect docs for this route, keyed by operation. A route
9230
11079
  * whose shared {@link description} spans several verbs ("Read, edit, or
9231
- * trash a thread") is ambiguous for any surface that groups by verb — a
11080
+ * trash a thread") is ambiguous for any surface that groups by verb - a
9232
11081
  * permission view must not describe `read` with a sentence that mentions
9233
11082
  * trashing. Each entry says what THAT operation concretely does at THIS
9234
11083
  * route; operations without an entry fall back to the shared description.
9235
- * Additive and optional — existing templates are unaffected.
11084
+ * Additive and optional - existing templates are unaffected.
9236
11085
  */
9237
11086
  readonly operationDocs?: Partial<Record<UriOperation, string>>;
9238
11087
  /**
@@ -9272,13 +11121,13 @@ declare interface UriValidationMessage {
9272
11121
 
9273
11122
  /**
9274
11123
  * Author-declared, human-facing documentation of what each supported verb
9275
- * CONCRETELY does against the provider — the capability half of a module's
11124
+ * CONCRETELY does against the provider - the capability half of a module's
9276
11125
  * boolean verb-support declaration. Written for a permission/capability
9277
11126
  * surface ("what am I allowing?"), not for the model: one plain sentence per
9278
11127
  * verb naming the real-world effect ("Sends mail, creates/updates drafts,
9279
11128
  * applies label changes"), never wire mechanics or URI shapes. Verbs the
9280
11129
  * module does not support are omitted; at runtime a supported verb with no
9281
- * entry simply renders undocumented (fail-open metadata) — but for a plugin's
11130
+ * entry simply renders undocumented (fail-open metadata) - but for a plugin's
9282
11131
  * `kay.agent` URI modules, `auditPluginDisclosure` (`@bonsai/plugin-sdk/
9283
11132
  * disclosure`) enforces coverage of every supported verb at authoring/load
9284
11133
  * time.
@@ -9286,7 +11135,7 @@ declare interface UriValidationMessage {
9286
11135
  * Lives here in the protocol layer (beside {@link UriTemplate.operationDocs},
9287
11136
  * its per-route sibling) so both `@herd/uri-extensions`' `UriExtensionModule`
9288
11137
  * and herd-agent's kernel `UriModule` can carry it without inverting the
9289
- * `@herd/uri` ← `@herd/uri-extensions` dependency.
11138
+ * `@herd/uri` <- `@herd/uri-extensions` dependency.
9290
11139
  */
9291
11140
  declare interface UriVerbDocs {
9292
11141
  /** What a `read` of this address space returns (also covers `help`). */
@@ -9309,6 +11158,7 @@ declare interface UriVerbSupport {
9309
11158
  readonly editable: boolean;
9310
11159
  readonly deletable?: boolean;
9311
11160
  readonly listable: boolean;
11161
+ readonly searchable?: boolean;
9312
11162
  }
9313
11163
 
9314
11164
  /** A mediated resource supplied beside structured write content without entering model context. */
@@ -9316,10 +11166,15 @@ declare interface UriWriteSource extends UriSourceDescriptor {
9316
11166
  readonly content: string | Uint8Array;
9317
11167
  }
9318
11168
 
11169
+ /** {@link hostWithinDomain} over a URL's hostname; an unparseable URL is never within. */
11170
+ declare function urlHostWithinDomain(url: string, domain: string): boolean;
11171
+
11172
+ /** A claim on a public web link (`http` or `https`), usually folded onto the module's own scheme. */
9319
11173
  declare interface UrlPatternClaim {
9320
11174
  readonly kind: "urlPattern";
9321
11175
  readonly pattern: UriPatternInit;
9322
- readonly normalizeTo?: string;
11176
+ readonly normalizeTo?: UriClaimTemplate;
11177
+ readonly route?: string;
9323
11178
  readonly examples?: readonly string[];
9324
11179
  }
9325
11180
 
@@ -9366,6 +11221,66 @@ declare interface ValidateApiKeyCredentialResult {
9366
11221
 
9367
11222
  declare type ValidatePluginApiKeyCredential = ValidateApiKeyCredential;
9368
11223
 
11224
+ /**
11225
+ * ---
11226
+ * responsibility: The one interface through which a vendored-MCP plugin's code calls a tool on its
11227
+ * own vendored MCP server, so every read-through plugin and the daemon that implements the port
11228
+ * agree on the same shape by construction.
11229
+ * owns:
11230
+ * - {@link VendoredMcpPort} - what a plugin's URI module and tools call.
11231
+ * - {@link VendoredMcpOutcome} - the typed result a plugin decodes, including every failure it
11232
+ * must surface to the agent rather than swallow.
11233
+ * does_not_own:
11234
+ * - The implementation. A plugin never dials MCP itself: it takes the port from
11235
+ * `api.vendoredMcp.port(server)` (`@bonsai/plugin-sdk/kay-agent`), which the daemon binds to the
11236
+ * plugin's own hosted server over its MCP host. Plugin source stays host-free, and a plugin
11237
+ * under test substitutes a fake port.
11238
+ * - Which tool names exist. `TTool` is the plugin's own union of the vendor tools it calls; the
11239
+ * port is generic so a typo in a tool name fails typecheck inside the plugin.
11240
+ * ---
11241
+ */
11242
+ /**
11243
+ * Why a call failed, as the plugin must tell the agent. `needs-auth` carries the exact service to
11244
+ * reconnect (`serviceId`) so a plugin can name it in its error instead of returning an empty
11245
+ * result; today's plugins name their statically declared `requiresAuth` service instead, which is
11246
+ * the same service for a single-service plugin. `unknown-server` and `unknown-tool` are wiring
11247
+ * faults (a server Bonsai does not host for this plugin, or a tool name the server does not have)
11248
+ * and stay loud for the same reason: an unreachable host must never decode as "no data".
11249
+ */
11250
+ declare type VendoredMcpFailureReason = "needs-auth" | "unknown-server" | "unknown-tool" | "failed";
11251
+
11252
+ declare type VendoredMcpOutcome =
11253
+ /**
11254
+ * `value` is the tool's `structuredContent` when it sent one, else its text content parsed as
11255
+ * JSON, else that text as a string: a vendor tool that answers in prose (a transcript, a
11256
+ * markdown summary) is a result, not a failure. A route that needs a record rejects a string
11257
+ * itself, with its own message.
11258
+ */
11259
+ {
11260
+ readonly ok: true;
11261
+ readonly value: unknown;
11262
+ } | {
11263
+ readonly ok: false;
11264
+ readonly reason: VendoredMcpFailureReason;
11265
+ readonly message: string;
11266
+ /** Exact reconnect target supplied by the MCP host for an auth failure. */
11267
+ readonly serviceId?: string;
11268
+ };
11269
+
11270
+ /**
11271
+ * One vendored MCP server, as the plugin that declares it calls it. `invoke` calls any tool the
11272
+ * server has, whether it reads or writes. The port checks no permission of its own: a call is as
11273
+ * permitted as the plugin tool or URI verb that makes it.
11274
+ */
11275
+ declare interface VendoredMcpPort<TTool extends string = string> {
11276
+ invoke(input: {
11277
+ /** The session's working directory; the host resolves the server binding per cwd. */
11278
+ readonly cwd: string;
11279
+ readonly tool: TTool;
11280
+ readonly args: Readonly<Record<string, unknown>>;
11281
+ }): Promise<VendoredMcpOutcome>;
11282
+ }
11283
+
9369
11284
  /** Creates a Void type. */
9370
11285
  declare function Void(options?: TSchemaOptions): TVoid;
9371
11286
 
@@ -9400,8 +11315,8 @@ declare const WhiteboardEntryInfo: z.ZodObject<{
9400
11315
  authorSessionId: z.ZodNullable<z.ZodString>;
9401
11316
  }, z.core.$strict>>;
9402
11317
  state: z.ZodEnum<{
9403
- available: "available";
9404
11318
  unavailable: "unavailable";
11319
+ available: "available";
9405
11320
  "unsupported-version": "unsupported-version";
9406
11321
  invalid: "invalid";
9407
11322
  }>;
@@ -9422,8 +11337,8 @@ declare const WhiteboardEntryInspection: z.ZodObject<{
9422
11337
  authorSessionId: z.ZodNullable<z.ZodString>;
9423
11338
  }, z.core.$strict>>;
9424
11339
  state: z.ZodEnum<{
9425
- available: "available";
9426
11340
  unavailable: "unavailable";
11341
+ available: "available";
9427
11342
  "unsupported-version": "unsupported-version";
9428
11343
  invalid: "invalid";
9429
11344
  }>;