@yaklabs-ai/plugin-sdk 0.14.0 → 0.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/kay-app.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { pathToFileURL } from 'node:url';
1
2
  import type { StatementSync } from 'node:sqlite';
2
3
  import { z } from 'zod';
3
4
 
@@ -78,6 +79,8 @@ export declare interface AgentToolResult<T = JsonValue_2 | undefined> {
78
79
  * error, but `details` and `structuredContent` are kept for the UI and programmatic callers.
79
80
  */
80
81
  isError?: boolean;
82
+ /** Classification for an `isError` result; the host validates it and stamps identity and attribution. */
83
+ failure?: ToolCallFailure;
81
84
  /**
82
85
  * Hint that the agent should stop after the current tool batch.
83
86
  * Early termination only happens when every finalized tool result in the batch sets this to true.
@@ -296,6 +299,12 @@ declare interface BackgroundTaskAdoptOptions {
296
299
  readonly ownerId?: string;
297
300
  readonly inspect?: BackgroundTaskInspector;
298
301
  readonly meta?: Readonly<Record<string, unknown>>;
302
+ /**
303
+ * The task's owner waits for its result: the work was meant to finish and report back (a build,
304
+ * a test run). Absent or false: nothing waits on it (a dev server, a watcher). The kernel only
305
+ * carries this fact on the task's snapshot; what waiting means is the host's to decide.
306
+ */
307
+ readonly awaitsResult?: boolean;
299
308
  /** Scoped settlement hook for the task created by this adoption only. */
300
309
  readonly onSettled?: (completion: BackgroundTaskCompletion) => void;
301
310
  }
@@ -370,6 +379,8 @@ declare interface BackgroundTaskSnapshot {
370
379
  readonly startedAtMs: number;
371
380
  readonly updatedAtMs: number;
372
381
  readonly meta?: Readonly<Record<string, unknown>>;
382
+ /** The owner waits for this task's result; see `BackgroundTaskAdoptOptions.awaitsResult`. */
383
+ readonly awaitsResult?: boolean;
373
384
  }
374
385
 
375
386
  declare type BackgroundTaskStatus = "queued" | "running" | "completed" | "failed" | "cancelled";
@@ -843,7 +854,7 @@ declare interface DecideChoiceQuestion<L extends string = string> {
843
854
  /** What a question asks: text, or a JSON object the client sends as its JSON text. */
844
855
  declare type DecideInstructions = string | object;
845
856
 
846
- declare type DecideModelId = "jev" | "clef" | "clef-flash";
857
+ declare type DecideModelId = "jev" | "clef" | "clef-flash" | "gpt-6-luna";
847
858
 
848
859
  declare type DecideQuestion = DecideBoolQuestion | DecideChoiceQuestion | DecideScoreQuestion;
849
860
 
@@ -851,10 +862,10 @@ declare type DecideQuestion = DecideBoolQuestion | DecideChoiceQuestion | Decide
851
862
  declare type DecideQuestions = Readonly<Record<string, DecideQuestion>>;
852
863
 
853
864
  declare interface DecideRequest<Q extends DecideQuestions = DecideQuestions> {
854
- /** Defaults to `jev`. */
855
- readonly model?: DecideModelId;
865
+ readonly model: DecideModelId;
856
866
  readonly state: DecideState;
857
867
  readonly questions: Q;
868
+ readonly image?: SystemOneImage;
858
869
  }
859
870
 
860
871
  declare interface DecideScoreAnswer {
@@ -1235,7 +1246,10 @@ declare interface ExtensionAuthContext {
1235
1246
 
1236
1247
  /** Optional extension-facing APIs for background task orchestration. */
1237
1248
  declare interface ExtensionBackgroundTasksApi {
1238
- adopt(taskKind: BackgroundTaskKind, label: string, run: BackgroundTaskRun, options?: BackgroundTaskAdoptOptions): string;
1249
+ adopt(taskKind: BackgroundTaskKind, label: string, run: BackgroundTaskRun, options?: BackgroundTaskAdoptOptions & {
1250
+ readonly awaitsResult?: false;
1251
+ }): string;
1252
+ adopt(taskKind: BackgroundTaskKind, label: string, run: BackgroundTaskRun, options: BackgroundTaskAdoptOptions): string | Promise<string>;
1239
1253
  list(): readonly BackgroundTaskSnapshot[];
1240
1254
  get(taskId: string): BackgroundTaskSnapshot | undefined;
1241
1255
  }
@@ -2093,6 +2107,26 @@ export declare interface KayAppAccountProfileUpdate {
2093
2107
  readonly displayName: string;
2094
2108
  }
2095
2109
 
2110
+ /**
2111
+ * Service/scheme IDs are local when owned, globally qualified when consumed.
2112
+ * Omitting scheme searches all admitted schemes.
2113
+ */
2114
+ export declare interface KayAppAccountRequest {
2115
+ readonly serviceId: string;
2116
+ readonly schemeId?: string;
2117
+ }
2118
+
2119
+ /** Stored account state, without resolving or refreshing its credential. */
2120
+ export declare interface KayAppAccountSummary {
2121
+ readonly accountId: string;
2122
+ /** Global scheme ID, matching a resolved credential's schemeId. */
2123
+ readonly schemeId: string;
2124
+ readonly label?: string;
2125
+ readonly scopes?: readonly string[];
2126
+ /** Last recorded health; unknown means no health observation was stored. */
2127
+ readonly status: "ok" | "needs_reauth" | "refresh_failed" | "revoked" | "unknown";
2128
+ }
2129
+
2096
2130
  /**
2097
2131
  * A plugin's `kay.app` activation — receives only the brokered {@link KayAppPluginApi}. Runs ONCE at
2098
2132
  * host start, fully awaited before any session starts.
@@ -2343,22 +2377,25 @@ export declare interface KayAppAssistantMessageSessionEvent extends KayAppSessio
2343
2377
 
2344
2378
  /** The brokered credential capability. Present only when granted. */
2345
2379
  export declare interface KayAppAuth {
2380
+ /** Resolve a granted credential for a declared purpose. */
2381
+ resolve(request: KayAppResolveCredentialRequest): Promise<KayAppResolvedCredential>;
2346
2382
  /**
2347
- * Resolve the credential for a declared, granted service+scheme. Rejects when the grant is absent,
2348
- * the account is not connected, or the purpose is not one the service declared.
2383
+ * Enumerate an owned or consumed service under an explicit list grant in
2384
+ * permissions.byTarget["kay.app"].auth. Consumption or resolve alone does not allow listing;
2385
+ * shared-identity services also require auth.shared-identity authorization.
2386
+ * Includes accounts needing repair within admitted schemes, without broadening resolve grants.
2387
+ * Never resolves, decrypts secret material, refreshes, or calls a provider. Invalid or
2388
+ * unauthorized requests reject; an authorized service with no accounts returns an empty list.
2349
2389
  */
2350
- resolve(request: KayAppResolveCredentialRequest): Promise<KayAppResolvedCredential>;
2390
+ listAccounts(request: KayAppAccountRequest): Promise<readonly KayAppAccountSummary[]>;
2351
2391
  /**
2352
- * Whether a credential is currently resolvable. Intended for availability-style probes a
2353
- * settings screen calls repeatedly.
2354
- *
2355
- * Answers `false` rather than throwing when nothing is connected, and never returns material to
2356
- * the caller. It does NOT yet answer without resolving: today it runs the full resolve internally
2357
- * and discards the result, so it can decrypt a secret — and, for a refreshable scheme, take the
2358
- * network — to produce a boolean. Do not read this as a cheap probe. Tracked in #1048; the fix is
2359
- * a `list`-scoped grant plus `listAccounts`, which answers from record metadata alone.
2392
+ * Stored availability, not proof that a provider request will authenticate. False for no
2393
+ * matching account or only revoked/needs-reauth accounts. Uses explicit list permission for
2394
+ * owned or consumed services when present, otherwise resolve permission within its account
2395
+ * bounds. Never resolves, decrypts secrets, refreshes, or calls a provider.
2396
+ * Storage and authorization failures reject.
2360
2397
  */
2361
- has(request: Omit<KayAppResolveCredentialRequest, "purpose">): Promise<boolean>;
2398
+ has(request: KayAppAccountRequest): Promise<boolean>;
2362
2399
  }
2363
2400
 
2364
2401
  /**
@@ -3863,11 +3900,11 @@ export declare interface KayAppPluginApi {
3863
3900
  */
3864
3901
  readonly sessionEvents: KayAppSessionEvents;
3865
3902
  /**
3866
- * Grant-gated time-triggered workflow registration. PRESENT ONLY for a plugin holding the
3867
- * `workflows.define` claim in the user's grant ledger — no manifest request and no source-class
3868
- * gate; `undefined` otherwise. Same deny-by-default rule as {@link corpus}: an ungranted plugin
3869
- * cannot even reference the capability, so guard with `if (app.workflows === undefined) return;`
3870
- * rather than assuming it is there.
3903
+ * Grant-gated time-triggered workflow registration. Present for a plugin the host has a workflow
3904
+ * namespace for; `undefined` otherwise. The first `define` asks for the `workflows.define` claim
3905
+ * in the user's grant ledger — no manifest request and no source-class gate — and it is decided
3906
+ * once `activate()` resolves: an ungranted plugin does not start until the user allows it. A
3907
+ * plugin that defines no workflow is never asked.
3871
3908
  */
3872
3909
  readonly workflows?: KayAppWorkflows;
3873
3910
  /**
@@ -3887,7 +3924,7 @@ export declare interface KayAppPluginApi {
3887
3924
  readonly permissions?: KayAppPermissions;
3888
3925
  /**
3889
3926
  * Credential resolution for an auth service this plugin declares. PRESENT ONLY for plugins whose
3890
- * manifest wires `auth.operations: ["resolve"]` on this target (deny-by-default); `undefined`
3927
+ * manifest wires `auth.operations` including `"list"` or `"resolve"` on this target (deny-by-default); `undefined`
3891
3928
  * otherwise. Auth is manifest WIRING (the host binds the credential vault before any code runs),
3892
3929
  * so its presence is declaration-driven, unlike the claim-checked capabilities above.
3893
3930
  */
@@ -3973,12 +4010,7 @@ export declare interface KayAppPluginApi {
3973
4010
  }
3974
4011
 
3975
4012
  export declare interface KayAppPluginEvents {
3976
- publish(localId: string, payload: unknown, options?: {
3977
- readonly subject?: {
3978
- readonly kind: string;
3979
- readonly id?: string;
3980
- };
3981
- }): void;
4013
+ publish(localId: string, input: PluginEventPublishInput): void;
3982
4014
  }
3983
4015
 
3984
4016
  export declare type KayAppProcessingSpeed = "standard" | "fast";
@@ -4111,12 +4143,12 @@ export declare interface KayAppRepos {
4111
4143
 
4112
4144
  /** What the plugin is asking for, and what it intends to do with it. */
4113
4145
  export declare interface KayAppResolveCredentialRequest {
4114
- /** An auth service this plugin's own manifest declares, by its LOCAL id. */
4146
+ /** A granted service: local ID when owned, globally qualified ID when consumed. */
4115
4147
  readonly serviceId: string;
4116
- /** Exact scheme to require; omit to resolve the service's sole connected scheme. */
4148
+ /** Local scheme ID when owned, globally qualified when consumed; omit for the sole connected scheme. */
4117
4149
  readonly schemeId?: string;
4118
4150
  /**
4119
- * One of the `purposes` the declared service lists. The host pins the resolved grant to it, so a
4151
+ * One of the service's `purposes` admitted by the manifest grant. The host pins the grant to it, so a
4120
4152
  * credential taken for `"transcription"` cannot be replayed for anything else.
4121
4153
  */
4122
4154
  readonly purpose: string;
@@ -4125,8 +4157,8 @@ export declare interface KayAppResolveCredentialRequest {
4125
4157
  /**
4126
4158
  * ---
4127
4159
  * responsibility: The plugin-facing credential surface of the `kay.app` target SDK. A daemon-hosted
4128
- * plugin resolves the credential for an auth service **it declared in its own manifest**, so a
4129
- * cloud adapter's secret is read where the work happens and never crosses a process boundary.
4160
+ * plugin lists account metadata or resolves credentials for an owned or consumed auth service
4161
+ * under explicit grants. Credential material is read where the work happens.
4130
4162
  * owns:
4131
4163
  * - {@link KayAppAuth}, {@link KayAppResolvedCredential}.
4132
4164
  * does_not_own:
@@ -4137,8 +4169,8 @@ export declare interface KayAppResolveCredentialRequest {
4137
4169
  * ## Deny-by-default
4138
4170
  *
4139
4171
  * `KayAppPluginApi.auth` is **present only for plugins the host grants** (`auth.operations`
4140
- * containing `"resolve"` in `permissions.byTarget["kay.app"]`, against a service the manifest
4141
- * declares) and `undefined` otherwise — an ungranted plugin cannot even reference the capability.
4172
+ * containing `"list"` or `"resolve"` in `permissions.byTarget["kay.app"]`, against an owned or consumed
4173
+ * service) and `undefined` otherwise — an ungranted plugin cannot even reference the capability.
4142
4174
  * This mirrors `KayAppPluginApi.corpus`, and it is the rule for every capability behind a grant:
4143
4175
  * never hand a plugin an object whose grant is decorative.
4144
4176
  *
@@ -5952,6 +5984,8 @@ export declare interface KayAppWhiteboardTypes {
5952
5984
  * different process. Anything you need later belongs in a step's return value.
5953
5985
  */
5954
5986
  export declare interface KayAppWorkflowContext {
5987
+ /** State from the last successful run; undefined until a run saves it. */
5988
+ readonly state: JsonValue | undefined;
5955
5989
  readonly automationId: string;
5956
5990
  readonly runId: string;
5957
5991
  readonly match: Extract<KayAppAutomationMatch, {
@@ -6024,6 +6058,8 @@ export declare interface KayAppWorkflowDefinition {
6024
6058
  readonly kind: "time";
6025
6059
  }>;
6026
6060
  readonly run: (context: KayAppWorkflowContext) => Promise<{
6061
+ /** Replacement JSON state, at most 64 KiB; omission keeps the previous value. */
6062
+ readonly state?: JsonValue | undefined;
6027
6063
  readonly summary: KayAppRunSummary;
6028
6064
  readonly produced?: KayAppRunProduced;
6029
6065
  readonly effect?: KayAppRunEffect;
@@ -7134,6 +7170,8 @@ declare function Partial_2<Type extends TSchema>(type: Type, options?: TSchemaOp
7134
7170
  /** Creates a deferred Partial action. */
7135
7171
  declare function PartialDeferred<Type extends TSchema>(type: Type, options?: TSchemaOptions): TPartialDeferred<Type>;
7136
7172
 
7173
+ export { pathToFileURL }
7174
+
7137
7175
  declare const Pattern: (input: string) => [unknown, string] | [];
7138
7176
 
7139
7177
  declare const PatternBase: (input: string) => [unknown, string] | [];
@@ -7294,6 +7332,42 @@ export declare const PluginAgentDefinitionPermissionRule: z.ZodObject<{
7294
7332
 
7295
7333
  export declare type PluginAgentDefinitionPermissionRule = z.infer<typeof PluginAgentDefinitionPermissionRule>;
7296
7334
 
7335
+ export declare const PluginEventEnvelope: z.ZodObject<{
7336
+ id: z.ZodString;
7337
+ localId: z.ZodString;
7338
+ type: z.ZodString;
7339
+ version: z.ZodNumber;
7340
+ uri: z.ZodString;
7341
+ related: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>>;
7342
+ key: z.ZodOptional<z.ZodString>;
7343
+ occurredAt: z.ZodISODateTime;
7344
+ publishedAt: z.ZodISODateTime;
7345
+ source: z.ZodObject<{
7346
+ poller: z.ZodOptional<z.ZodString>;
7347
+ runId: z.ZodOptional<z.ZodString>;
7348
+ layer: z.ZodLiteral<"runtime">;
7349
+ pluginId: z.ZodString;
7350
+ sessionId: z.ZodOptional<z.ZodString>;
7351
+ }, z.core.$strict>;
7352
+ payload: z.ZodOptional<z.ZodType<JsonValue, unknown, z.core.$ZodTypeInternals<JsonValue, unknown>>>;
7353
+ }, z.core.$strict>;
7354
+
7355
+ export declare type PluginEventEnvelope = z.infer<typeof PluginEventEnvelope>;
7356
+
7357
+ export declare const PluginEventPublishInput: z.ZodObject<{
7358
+ uri: z.ZodString;
7359
+ related: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>>;
7360
+ key: z.ZodOptional<z.ZodString>;
7361
+ occurredAt: z.ZodOptional<z.ZodISODateTime>;
7362
+ source: z.ZodOptional<z.ZodObject<{
7363
+ poller: z.ZodOptional<z.ZodString>;
7364
+ runId: z.ZodOptional<z.ZodString>;
7365
+ }, z.core.$strict>>;
7366
+ payload: z.ZodOptional<z.ZodType<JsonValue, unknown, z.core.$ZodTypeInternals<JsonValue, unknown>>>;
7367
+ }, z.core.$strict>;
7368
+
7369
+ export declare type PluginEventPublishInput = z.infer<typeof PluginEventPublishInput>;
7370
+
7297
7371
  declare const Properties: (input: string) => [unknown, string] | [];
7298
7372
 
7299
7373
  declare function PropertiesMapping(input: [unknown, unknown, unknown]): unknown;
@@ -8590,7 +8664,7 @@ declare interface SystemOneClient {
8590
8664
  decide<const Q extends DecideQuestions>(request: DecideRequest<Q>, options?: SystemOneCallOptions): Promise<Decision<Q>>;
8591
8665
  extract<const F extends ExtractFields>(request: ExtractRequest<F>, options?: SystemOneCallOptions): Promise<Extraction<F>>;
8592
8666
  /** Whether some provider in the current order can serve `(kind, model)`. Never rejects. */
8593
- availability(kind: SystemOneKind, model?: SystemOneModelId): Promise<Availability>;
8667
+ availability(kind: SystemOneKind, model: SystemOneModelId): Promise<Availability>;
8594
8668
  }
8595
8669
 
8596
8670
  /**
@@ -8625,6 +8699,12 @@ declare type SystemOneFailureCause = {
8625
8699
  readonly kind: "invalid-answer";
8626
8700
  };
8627
8701
 
8702
+ /** One PNG attachment. `data` is padded base64, without a data-URL prefix. */
8703
+ declare interface SystemOneImage {
8704
+ readonly mimeType: "image/png";
8705
+ readonly data: string;
8706
+ }
8707
+
8628
8708
  /**
8629
8709
  * ---
8630
8710
  * responsibility: The data shapes of the System One surface: models, the decide and extract
@@ -10818,6 +10898,14 @@ declare interface Tool<TParameters extends TSchema = TSchema> {
10818
10898
  constrainedSampling?: false | ConstrainedSamplingConfig;
10819
10899
  }
10820
10900
 
10901
+ /**
10902
+ * The closed vocabulary of tool call failure codes. The engine and the tools
10903
+ * mint only these; a returned failure with a code outside it is not a
10904
+ * classification (the engine records the rejection on an unexplained failure),
10905
+ * and a stored record with one reads as none.
10906
+ */
10907
+ 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"];
10908
+
10821
10909
  /**
10822
10910
  * ---
10823
10911
  * responsibility: The declarative permission classification a tool carries on its definition
@@ -10862,6 +10950,56 @@ declare interface ToolCall {
10862
10950
  argumentsError?: string;
10863
10951
  }
10864
10952
 
10953
+ /**
10954
+ * The lane's classification of why one tool invocation failed: a searchable
10955
+ * machine code and the cause the tool or engine classified at execution.
10956
+ */
10957
+ declare interface ToolCallFailure extends ToolCallFailureCause {
10958
+ readonly code: ToolCallFailureCode;
10959
+ }
10960
+
10961
+ declare type ToolCallFailureCause = z.infer<typeof toolCallFailureCauseSchema>;
10962
+
10963
+ declare const toolCallFailureCauseSchema: z.ZodObject<{
10964
+ category: z.ZodEnum<{
10965
+ cancelled: "cancelled";
10966
+ timeout: "timeout";
10967
+ unknown: "unknown";
10968
+ provider: "provider";
10969
+ "invalid-input": "invalid-input";
10970
+ "not-connected": "not-connected";
10971
+ "unsupported-operation": "unsupported-operation";
10972
+ "not-found": "not-found";
10973
+ permission: "permission";
10974
+ unavailable: "unavailable";
10975
+ }>;
10976
+ retryable: z.ZodBoolean;
10977
+ action: z.ZodEnum<{
10978
+ unknown: "unknown";
10979
+ none: "none";
10980
+ retry: "retry";
10981
+ "correct-input": "correct-input";
10982
+ connect: "connect";
10983
+ }>;
10984
+ details: z.ZodOptional<z.ZodObject<{
10985
+ moduleId: z.ZodOptional<z.ZodString>;
10986
+ toolOwnerId: z.ZodOptional<z.ZodString>;
10987
+ operation: z.ZodOptional<z.ZodString>;
10988
+ uri: z.ZodOptional<z.ZodString>;
10989
+ path: z.ZodOptional<z.ZodString>;
10990
+ validationField: z.ZodOptional<z.ZodString>;
10991
+ errorName: z.ZodOptional<z.ZodString>;
10992
+ errorCode: z.ZodOptional<z.ZodString>;
10993
+ providerCode: z.ZodOptional<z.ZodString>;
10994
+ status: z.ZodOptional<z.ZodNumber>;
10995
+ editIndex: z.ZodOptional<z.ZodNumber>;
10996
+ occurrences: z.ZodOptional<z.ZodNumber>;
10997
+ retryAfterMs: z.ZodOptional<z.ZodNumber>;
10998
+ }, z.core.$strict>>;
10999
+ }, z.core.$strict>;
11000
+
11001
+ declare type ToolCallFailureCode = (typeof TOOL_CALL_FAILURE_CODES)[number];
11002
+
10865
11003
  /** A call to judge with {@link ToolContext.checkToolCallPermission}. */
10866
11004
  declare interface ToolCallPermissionCheck {
10867
11005
  readonly toolName: string;
package/dist/kay-app.js CHANGED
@@ -163,6 +163,9 @@ function invalidObservation(input) {
163
163
  };
164
164
  }
165
165
 
166
+ // packages/plugin-sdk/dist/kay-app/index.js
167
+ import { pathToFileURL } from "node:url";
168
+
166
169
  // packages/herd-uri/dist/errors.js
167
170
  var UriError = class extends Error {
168
171
  };
@@ -537,6 +540,7 @@ export {
537
540
  invalidObservation,
538
541
  isRetryable,
539
542
  parseLineSelector,
543
+ pathToFileURL,
540
544
  payload,
541
545
  transcriptMessageText,
542
546
  transcriptMessageTexts,
@@ -42,7 +42,7 @@ export declare interface DecideChoiceQuestion<L extends string = string> {
42
42
  /** What a question asks: text, or a JSON object the client sends as its JSON text. */
43
43
  export declare type DecideInstructions = string | object;
44
44
 
45
- export declare type DecideModelId = "jev" | "clef" | "clef-flash";
45
+ export declare type DecideModelId = "jev" | "clef" | "clef-flash" | "gpt-6-luna";
46
46
 
47
47
  export declare type DecideQuestion = DecideBoolQuestion | DecideChoiceQuestion | DecideScoreQuestion;
48
48
 
@@ -50,10 +50,10 @@ export declare type DecideQuestion = DecideBoolQuestion | DecideChoiceQuestion |
50
50
  export declare type DecideQuestions = Readonly<Record<string, DecideQuestion>>;
51
51
 
52
52
  export declare interface DecideRequest<Q extends DecideQuestions = DecideQuestions> {
53
- /** Defaults to `jev`. */
54
- readonly model?: DecideModelId;
53
+ readonly model: DecideModelId;
55
54
  readonly state: DecideState;
56
55
  readonly questions: Q;
56
+ readonly image?: SystemOneImage;
57
57
  }
58
58
 
59
59
  export declare interface DecideScoreAnswer {
@@ -243,7 +243,7 @@ export declare interface SystemOneClient {
243
243
  decide<const Q extends DecideQuestions>(request: DecideRequest<Q>, options?: SystemOneCallOptions): Promise<Decision<Q>>;
244
244
  extract<const F extends ExtractFields>(request: ExtractRequest<F>, options?: SystemOneCallOptions): Promise<Extraction<F>>;
245
245
  /** Whether some provider in the current order can serve `(kind, model)`. Never rejects. */
246
- availability(kind: SystemOneKind, model?: SystemOneModelId): Promise<SystemOneAvailability>;
246
+ availability(kind: SystemOneKind, model: SystemOneModelId): Promise<SystemOneAvailability>;
247
247
  }
248
248
 
249
249
  /**
@@ -297,6 +297,12 @@ export declare type SystemOneFailureCause = {
297
297
  readonly kind: "invalid-answer";
298
298
  };
299
299
 
300
+ /** One PNG attachment. `data` is padded base64, without a data-URL prefix. */
301
+ export declare interface SystemOneImage {
302
+ readonly mimeType: "image/png";
303
+ readonly data: string;
304
+ }
305
+
300
306
  /**
301
307
  * ---
302
308
  * responsibility: The data shapes of the System One surface: models, the decide and extract
@@ -23,20 +23,6 @@ function isSystemOneError(error) {
23
23
  return error instanceof SystemOneError;
24
24
  }
25
25
 
26
- // packages/system-one/dist/models.js
27
- var DEFAULT_DECIDE_MODEL = "jev";
28
- var SYSTEM_ONE_LIMITS = {
29
- /** The serialized request body, in bytes. */
30
- maxBodyBytes: 64 * 1024,
31
- maxQuestions: 64,
32
- maxFields: 32,
33
- minChoiceOptions: 2,
34
- maxChoiceOptions: 255,
35
- minScoreLevels: 2,
36
- maxScoreLevels: 10,
37
- maxForecastHorizon: 64
38
- };
39
-
40
26
  // packages/system-one/dist/unavailable.js
41
27
  var NOT_SERVED = {
42
28
  available: false,
@@ -48,7 +34,7 @@ function createUnavailableSystemOneClient() {
48
34
  decide(request) {
49
35
  return Promise.reject(new SystemOneError({
50
36
  kind: "decide",
51
- model: request.model ?? DEFAULT_DECIDE_MODEL,
37
+ model: request.model,
52
38
  cause: { kind: "not-served" }
53
39
  }));
54
40
  },
@@ -62,6 +48,22 @@ function createUnavailableSystemOneClient() {
62
48
  availability: () => Promise.resolve(NOT_SERVED)
63
49
  };
64
50
  }
51
+
52
+ // packages/system-one/dist/models.js
53
+ var SYSTEM_ONE_LIMITS = {
54
+ /** The serialized state and questions, in bytes; images have a separate budget. */
55
+ maxBodyBytes: 64 * 1024,
56
+ maxImageBytes: 4 * 1024 * 1024,
57
+ maxImagePixels: 16e6,
58
+ maxImageBodyBytes: 6 * 1024 * 1024,
59
+ maxQuestions: 64,
60
+ maxFields: 32,
61
+ minChoiceOptions: 2,
62
+ maxChoiceOptions: 255,
63
+ minScoreLevels: 2,
64
+ maxScoreLevels: 10,
65
+ maxForecastHorizon: 64
66
+ };
65
67
  export {
66
68
  SystemOneError,
67
69
  createUnavailableSystemOneClient,
@@ -1,5 +1,7 @@
1
1
  import { z } from 'zod';
2
2
 
3
+ export declare const ATTACHMENTS_CUSTOM_TYPE = "attachments";
4
+
3
5
  /**
4
6
  * The ids on a session's active branch: the leaf chain walked parent-ward from
5
7
  * the tip, which a trailing `leaf` marker moves. Empty for an empty log.
@@ -43,6 +45,36 @@ export declare function matchesWorkBlock(coverage: WorkBlockCoverage, toolResult
43
45
  */
44
46
  export declare const NON_ACTIVITY_TOOL_NAMES: readonly string[];
45
47
 
48
+ /**
49
+ * What a run did to a URI. The words match the automation run wire's artifact actions. When one
50
+ * run both creates and updates a URI, the reader reports `created`.
51
+ */
52
+ declare type ProducedResourceAction = "created" | "updated";
53
+
54
+ /** One URI a tool call created or updated as a side effect. */
55
+ declare interface ProducedResourceDeclaration {
56
+ /** A `scheme://…` URI or an absolute local file path, compared as an exact string. */
57
+ readonly uri: string;
58
+ readonly action: ProducedResourceAction;
59
+ }
60
+
61
+ /**
62
+ * One tool result's declarations. `absent` covers every result that makes no claim, including a
63
+ * non-object `details` and an empty list. `malformed` means a claim was made that cannot be
64
+ * trusted; the reader reports a gap for it instead of keeping the parts that look valid.
65
+ */
66
+ declare type ProducedResourceDeclarationsRead = {
67
+ readonly kind: "absent";
68
+ } | {
69
+ readonly kind: "malformed";
70
+ } | {
71
+ readonly kind: "declared";
72
+ readonly resources: readonly ProducedResourceDeclaration[];
73
+ };
74
+
75
+ /** Read the declarations that one persisted tool result's `details` carries. */
76
+ export declare function readProducedResourceDeclarations(details: unknown): ProducedResourceDeclarationsRead;
77
+
46
78
  /**
47
79
  * The daemon's own run-start record. A run's entries begin here, before the
48
80
  * user message that opened it.
@@ -94,7 +94,47 @@ var NON_ACTIVITY_TOOL_NAMES = [
94
94
  ];
95
95
  var WORK_HEADLINE_MIN_CHARS = 12;
96
96
  var WORK_HEADLINE_MAX_CHARS = 90;
97
+
98
+ // packages/herd-transcript/dist/context-messages.js
99
+ var ATTACHMENTS_CUSTOM_TYPE = "attachments";
100
+
101
+ // packages/herd-uri/dist/produced-resources.js
102
+ var PRODUCED_RESOURCES_DETAILS_KEY = "producedResources";
103
+ var ABSENT = { kind: "absent" };
104
+ var MALFORMED = { kind: "malformed" };
105
+ var SCHEME_URI = /^[a-z][a-z0-9+.-]*:\/\/./;
106
+ var WINDOWS_ABSOLUTE_PATH = /^[A-Za-z]:[\\/]./;
107
+ function isProducedResourceUri(value) {
108
+ if (typeof value !== "string" || value.trim() !== value)
109
+ return false;
110
+ return SCHEME_URI.test(value) || value.startsWith("/") && value.length > 1 || WINDOWS_ABSOLUTE_PATH.test(value);
111
+ }
112
+ function isProducedResourceDeclaration(value) {
113
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
114
+ return false;
115
+ }
116
+ const keys = Object.keys(value);
117
+ if (keys.length !== 2 || !keys.includes("uri") || !keys.includes("action")) {
118
+ return false;
119
+ }
120
+ const record = value;
121
+ return isProducedResourceUri(record.uri) && (record.action === "created" || record.action === "updated");
122
+ }
123
+ function readProducedResourceDeclarations(details) {
124
+ if (typeof details !== "object" || details === null || Array.isArray(details) || !Object.hasOwn(details, PRODUCED_RESOURCES_DETAILS_KEY)) {
125
+ return ABSENT;
126
+ }
127
+ const claimed = details[PRODUCED_RESOURCES_DETAILS_KEY];
128
+ if (!Array.isArray(claimed))
129
+ return MALFORMED;
130
+ if (claimed.length === 0)
131
+ return ABSENT;
132
+ if (!claimed.every(isProducedResourceDeclaration))
133
+ return MALFORMED;
134
+ return { kind: "declared", resources: claimed };
135
+ }
97
136
  export {
137
+ ATTACHMENTS_CUSTOM_TYPE,
98
138
  NON_ACTIVITY_TOOL_NAMES,
99
139
  RUN_STARTED_CUSTOM_TYPE,
100
140
  RUN_TERMINAL_CUSTOM_TYPE,
@@ -105,6 +145,7 @@ export {
105
145
  branchEntryIds,
106
146
  customEntriesFromEntries,
107
147
  matchesWorkBlock,
148
+ readProducedResourceDeclarations,
108
149
  turnSegments,
109
150
  workBlockCoverage,
110
151
  workBlockKey
@@ -22,8 +22,8 @@
22
22
  * This module's `read` is a pure projection of the URI it was handed — no network, no credential.
23
23
  * Declaring `requiresAuth` anyway would not be a harmless formality: an auth-gated module whose
24
24
  * binding is unsatisfied has its public-web `urlPattern` claims suppressed and its `matches()`
25
- * wrapped to decline `http(s)` (`agent-session.ts` `_suppressPublicUrlClaims`, and
26
- * `authSuppressedCatalogModule` for discovery). A pasted Supabase link would therefore stay
25
+ * wrapped to decline `http(s)` (herd-agent's `uri-catalog-projection.ts`: `suppressPublicUrlClaims`,
26
+ * and `authSuppressedCatalogModule` for discovery). A pasted Supabase link would therefore stay
27
27
  * unbranded for every user who has not yet connected Supabase — which is exactly the user the
28
28
  * branded pill is for. The vendor's MCP tools remain gated on their own, by the MCP host.
29
29
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yaklabs-ai/plugin-sdk",
3
- "version": "0.14.0",
3
+ "version": "0.15.0",
4
4
  "description": "The Kay plugin SDK — types and helpers for authoring a Kay directory plugin.",
5
5
  "author": "YakLabs",
6
6
  "type": "module",
@@ -289,10 +289,10 @@ on the plugin's row (or on the plugin source's row, when the whole source found
289
289
 
290
290
  A directory plugin does not request workflows in its manifest. During `kay.app` activation, call
291
291
  `app.workflows.define(localId, { name, trigger, run })` to put a durable, daemon-scheduled row on
292
- the Automations page. The host raises the `workflows.define` claim for every `kay.app` plugin; a
293
- bundled install holds every grant, while a directory plugin needs the user to add that grant to its
294
- `installs` row. Source class no longer decides workflow authority, and the capability is ABSENT
295
- rather than refused when ungranted, so guard on `app.workflows === undefined`.
292
+ the Automations page. The first `define` raises the `workflows.define` claim, decided once
293
+ `activate()` resolves; a bundled install holds every grant, while a directory plugin needs the user
294
+ to add that grant to its `installs` row, and until then it does not start. Source class no longer
295
+ decides workflow authority. `app.workflows` is absent only for a plugin with no workflow namespace.
296
296
 
297
297
  The product-agent procedure is the builtin skill `create-workflow`
298
298
  (`packages/agent-runtime/src/kay/builtin-skills/`), and the API reference is the "Durable Workflows