@yaklabs-ai/plugin-sdk 0.8.5 → 0.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -13,7 +13,7 @@ it under the name your plugin code actually imports:
13
13
  ```json
14
14
  {
15
15
  "dependencies": {
16
- "@kay/plugin-sdk": "npm:@yaklabs-ai/plugin-sdk@^0.8.5"
16
+ "@kay/plugin-sdk": "npm:@yaklabs-ai/plugin-sdk@^0.9.1"
17
17
  }
18
18
  }
19
19
  ```
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
3
  "package": "@yaklabs-ai/plugin-sdk",
4
- "version": "0.8.5",
4
+ "version": "0.9.1",
5
5
  "target": "npm",
6
6
  "firstPartyLicense": "MIT",
7
7
  "bundled": [
@@ -2700,6 +2700,24 @@ declare interface UriModule {
2700
2700
  readonly authActions?: UriAuthActionPolicy;
2701
2701
  /** Pure route/payload validation applied before a consequential permission ask. */
2702
2702
  readonly preflight?: UriOperationPreflightPolicy;
2703
+ /**
2704
+ * Structured facts naming the WHOLE consequence of this call, or `undefined` when
2705
+ * the route cannot honestly be described on a one-line approval surface. The module
2706
+ * owns the static action phrase, target resolution, payload decoding and declaration
2707
+ * of covered payload fields and query parameters. Unknown fields cost the summary.
2708
+ * The host owns framing, the whole-quote fit (no elision) and display-safety admission.
2709
+ *
2710
+ * Unlike preflight, this hook is async and may do I/O. Resolve names through `ctx`,
2711
+ * the same dispatch context used by execution, never an ambient or cached account.
2712
+ * The host calls it once before raising the ask, enforces the short `ctx.signal`
2713
+ * deadline and discards late answers. A throw yields no summary and a module-attributed
2714
+ * diagnostic; declining costs a click into the app, never an under-described approval.
2715
+ */
2716
+ describeOperation?(request: {
2717
+ readonly operation: UriOperation;
2718
+ readonly uri: string;
2719
+ readonly payload: unknown;
2720
+ }, ctx: UriResolveContext): Promise<UriOperationDescription | undefined>;
2703
2721
  /**
2704
2722
  * Per-resource observability: does a `format: "observation"` read of THIS
2705
2723
  * uri render source-native material ({@link UriResolveContext.format})?
@@ -2813,6 +2831,22 @@ declare interface UriNormalizeResult {
2813
2831
 
2814
2832
  declare type UriOperation = "help" | "read" | "write" | "edit" | "list" | "search" | "delete";
2815
2833
 
2834
+ declare interface UriOperationDescription {
2835
+ /** Static verb phrase authored by the module. Never interpolated from input. */
2836
+ readonly action: string;
2837
+ /** Human name resolved through the connection that will execute the call. */
2838
+ readonly target: string;
2839
+ /** Model-authored content; the host flattens, budgets, elides and bounds it. */
2840
+ readonly quote?: string;
2841
+ /** What this description accounts for; the host refuses undeclared input. */
2842
+ readonly accounts: {
2843
+ /** The payload actually read by the module, after its own decoding. */
2844
+ readonly payload: unknown;
2845
+ readonly payloadFields: readonly string[];
2846
+ readonly queryParams?: readonly string[];
2847
+ };
2848
+ }
2849
+
2816
2850
  /**
2817
2851
  * Pure, route-aware validation that runs before permission policy can surface an ask.
2818
2852
  *
@@ -2563,6 +2563,24 @@ declare interface UriModule {
2563
2563
  readonly authActions?: UriAuthActionPolicy;
2564
2564
  /** Pure route/payload validation applied before a consequential permission ask. */
2565
2565
  readonly preflight?: UriOperationPreflightPolicy;
2566
+ /**
2567
+ * Structured facts naming the WHOLE consequence of this call, or `undefined` when
2568
+ * the route cannot honestly be described on a one-line approval surface. The module
2569
+ * owns the static action phrase, target resolution, payload decoding and declaration
2570
+ * of covered payload fields and query parameters. Unknown fields cost the summary.
2571
+ * The host owns framing, the whole-quote fit (no elision) and display-safety admission.
2572
+ *
2573
+ * Unlike preflight, this hook is async and may do I/O. Resolve names through `ctx`,
2574
+ * the same dispatch context used by execution, never an ambient or cached account.
2575
+ * The host calls it once before raising the ask, enforces the short `ctx.signal`
2576
+ * deadline and discards late answers. A throw yields no summary and a module-attributed
2577
+ * diagnostic; declining costs a click into the app, never an under-described approval.
2578
+ */
2579
+ describeOperation?(request: {
2580
+ readonly operation: UriOperation;
2581
+ readonly uri: string;
2582
+ readonly payload: unknown;
2583
+ }, ctx: UriResolveContext): Promise<UriOperationDescription | undefined>;
2566
2584
  /**
2567
2585
  * Per-resource observability: does a `format: "observation"` read of THIS
2568
2586
  * uri render source-native material ({@link UriResolveContext.format})?
@@ -2676,6 +2694,22 @@ declare interface UriNormalizeResult {
2676
2694
 
2677
2695
  declare type UriOperation = "help" | "read" | "write" | "edit" | "list" | "search" | "delete";
2678
2696
 
2697
+ declare interface UriOperationDescription {
2698
+ /** Static verb phrase authored by the module. Never interpolated from input. */
2699
+ readonly action: string;
2700
+ /** Human name resolved through the connection that will execute the call. */
2701
+ readonly target: string;
2702
+ /** Model-authored content; the host flattens, budgets, elides and bounds it. */
2703
+ readonly quote?: string;
2704
+ /** What this description accounts for; the host refuses undeclared input. */
2705
+ readonly accounts: {
2706
+ /** The payload actually read by the module, after its own decoding. */
2707
+ readonly payload: unknown;
2708
+ readonly payloadFields: readonly string[];
2709
+ readonly queryParams?: readonly string[];
2710
+ };
2711
+ }
2712
+
2679
2713
  /**
2680
2714
  * Pure, route-aware validation that runs before permission policy can surface an ask.
2681
2715
  *
@@ -4323,6 +4323,24 @@ export declare interface UriModule {
4323
4323
  readonly authActions?: UriAuthActionPolicy;
4324
4324
  /** Pure route/payload validation applied before a consequential permission ask. */
4325
4325
  readonly preflight?: UriOperationPreflightPolicy;
4326
+ /**
4327
+ * Structured facts naming the WHOLE consequence of this call, or `undefined` when
4328
+ * the route cannot honestly be described on a one-line approval surface. The module
4329
+ * owns the static action phrase, target resolution, payload decoding and declaration
4330
+ * of covered payload fields and query parameters. Unknown fields cost the summary.
4331
+ * The host owns framing, the whole-quote fit (no elision) and display-safety admission.
4332
+ *
4333
+ * Unlike preflight, this hook is async and may do I/O. Resolve names through `ctx`,
4334
+ * the same dispatch context used by execution, never an ambient or cached account.
4335
+ * The host calls it once before raising the ask, enforces the short `ctx.signal`
4336
+ * deadline and discards late answers. A throw yields no summary and a module-attributed
4337
+ * diagnostic; declining costs a click into the app, never an under-described approval.
4338
+ */
4339
+ describeOperation?(request: {
4340
+ readonly operation: UriOperation;
4341
+ readonly uri: string;
4342
+ readonly payload: unknown;
4343
+ }, ctx: UriResolveContext): Promise<UriOperationDescription | undefined>;
4326
4344
  /**
4327
4345
  * Per-resource observability: does a `format: "observation"` read of THIS
4328
4346
  * uri render source-native material ({@link UriResolveContext.format})?
@@ -4453,6 +4471,22 @@ export declare class UriNotFoundError extends UriError {
4453
4471
 
4454
4472
  export declare type UriOperation = "help" | "read" | "write" | "edit" | "list" | "search" | "delete";
4455
4473
 
4474
+ export declare interface UriOperationDescription {
4475
+ /** Static verb phrase authored by the module. Never interpolated from input. */
4476
+ readonly action: string;
4477
+ /** Human name resolved through the connection that will execute the call. */
4478
+ readonly target: string;
4479
+ /** Model-authored content; the host flattens, budgets, elides and bounds it. */
4480
+ readonly quote?: string;
4481
+ /** What this description accounts for; the host refuses undeclared input. */
4482
+ readonly accounts: {
4483
+ /** The payload actually read by the module, after its own decoding. */
4484
+ readonly payload: unknown;
4485
+ readonly payloadFields: readonly string[];
4486
+ readonly queryParams?: readonly string[];
4487
+ };
4488
+ }
4489
+
4456
4490
  /**
4457
4491
  * Pure, route-aware validation that runs before permission policy can surface an ask.
4458
4492
  *
package/dist/kay-app.d.ts CHANGED
@@ -299,6 +299,93 @@ declare type ConstrainedSamplingConfig = {
299
299
  variants: GrammarVariants;
300
300
  };
301
301
 
302
+ export declare interface CorpusResourceInvocation {
303
+ readonly eventId: string;
304
+ /** Envelope recording time, never a run/message/incident identifier. */
305
+ readonly at: string;
306
+ readonly kind: CorpusResourceKind;
307
+ readonly sessionId: string;
308
+ /** Falls back to sessionId for legacy events without a recorded root. */
309
+ readonly rootSessionId: string;
310
+ readonly name: string;
311
+ readonly sourceId?: string;
312
+ /** Absent on unresolved legacy rows; names/aliases are not a substitute. */
313
+ readonly resourceId?: string;
314
+ readonly version?: string;
315
+ readonly variantId?: string;
316
+ readonly rootProvenance: SessionProvenanceRecord;
317
+ /** Current index hints, not the session's historical context at invocation. */
318
+ readonly currentContext: {
319
+ readonly cwd: string;
320
+ readonly projectId?: string;
321
+ };
322
+ }
323
+
324
+ /** Exclusive keyset position; preserve timestamp precision when returning it. */
325
+ export declare const CorpusResourceInvocationCursor: z.ZodObject<{
326
+ at: z.ZodISODateTime;
327
+ eventId: z.ZodString;
328
+ }, z.core.$strict>;
329
+
330
+ export declare type CorpusResourceInvocationCursor = z.infer<typeof CorpusResourceInvocationCursor>;
331
+
332
+ export declare interface CorpusResourceInvocationExclusion {
333
+ readonly eventId: string;
334
+ readonly sessionId: string;
335
+ readonly rootSessionId: string;
336
+ readonly reason: "session-missing" | "root-missing" | "root-provenance-unverified" | "root-creator-filtered";
337
+ }
338
+
339
+ export declare type CorpusResourceInvocationPage = {
340
+ readonly state: "available";
341
+ readonly items: readonly CorpusResourceInvocation[];
342
+ /** Absent only when this recording-time window is exhausted. */
343
+ readonly next?: CorpusResourceInvocationCursor;
344
+ /** Telemetry import succeeded; exclusions still describe missing or filtered index facts. */
345
+ readonly coverage: {
346
+ readonly scanned: number;
347
+ readonly exclusions: readonly CorpusResourceInvocationExclusion[];
348
+ };
349
+ } | {
350
+ readonly state: "unavailable";
351
+ readonly reason: "not-wired" | "telemetry-unavailable" | "telemetry-incomplete" | "index-unavailable" | "invalid-record";
352
+ readonly message: string;
353
+ };
354
+
355
+ /** Half-open recording-time window. Limits bound scanned rows, including exclusions. */
356
+ export declare const CorpusResourceInvocationQuery: z.ZodObject<{
357
+ kind: z.ZodEnum<{
358
+ skill: "skill";
359
+ "context-file": "context-file";
360
+ "prompt-command": "prompt-command";
361
+ }>;
362
+ since: z.ZodISODateTime;
363
+ until: z.ZodISODateTime;
364
+ after: z.ZodOptional<z.ZodObject<{
365
+ at: z.ZodISODateTime;
366
+ eventId: z.ZodString;
367
+ }, z.core.$strict>>;
368
+ limit: z.ZodOptional<z.ZodNumber>;
369
+ rootCreatedByKind: z.ZodOptional<z.ZodEnum<{
370
+ human: "human";
371
+ agent: "agent";
372
+ plugin: "plugin";
373
+ trigger: "trigger";
374
+ daemon: "daemon";
375
+ }>>;
376
+ }, z.core.$strict>;
377
+
378
+ export declare type CorpusResourceInvocationQuery = z.infer<typeof CorpusResourceInvocationQuery>;
379
+
380
+ /** Roster invocation facts, not evidence that a read completed successfully. */
381
+ export declare const CorpusResourceKind: z.ZodEnum<{
382
+ skill: "skill";
383
+ "context-file": "context-file";
384
+ "prompt-command": "prompt-command";
385
+ }>;
386
+
387
+ export declare type CorpusResourceKind = z.infer<typeof CorpusResourceKind>;
388
+
302
389
  /**
303
390
  * The `signals` a host with no Jev lane or no signals store binds: `observe` never touches the
304
391
  * network, answers `invalid` for an input that breaks the recorded-name grammar exactly as a
@@ -1083,18 +1170,15 @@ export declare interface KayAppAutomationArtifactItem {
1083
1170
  readonly moduleId: string;
1084
1171
  /**
1085
1172
  * The authoring session. Required on the wire, and load-bearing rather than
1086
- * decorative: it is the identity a reverse `explainArtifactRevision` call
1087
- * resolves back to, and the session an `app:artifact:output` uri must be
1173
+ * decorative: it is the session an `app:artifact:output` uri must be
1088
1174
  * resolved against to open at all.
1089
1175
  */
1090
1176
  readonly sessionId: string;
1091
1177
  /** Collapsed by precedence: `deleted` > `created` > `updated`. */
1092
1178
  readonly action: "created" | "updated" | "deleted";
1093
1179
  /**
1094
- * One real revision of the group, carrying the action above, so a reverse
1095
- * `explainArtifactRevision` read still resolves from this row. Not
1096
- * necessarily the newest: the projection stores no ordering for the several
1097
- * revisions of one target.
1180
+ * One real revision of the group, carrying the action above. Not
1181
+ * necessarily the newest revision of the target.
1098
1182
  */
1099
1183
  readonly revision: string;
1100
1184
  /** How many revisions this row collapsed. Always at least 1. */
@@ -1238,7 +1322,7 @@ export declare type KayAppAutomationEffectInput = {
1238
1322
  * widening of it: an external resource has no revision, no Kay uri module, and
1239
1323
  * nothing on this machine to re-read.
1240
1324
  *
1241
- * `kind` mirrors the projection's closed external-resource vocabulary and names
1325
+ * `kind` is the run-detail wire's closed external-resource vocabulary and names
1242
1326
  * the host as well as the thing. There is deliberately no `offBranch`: an
1243
1327
  * abandoned transcript branch does not un-open a pull request, so branch
1244
1328
  * membership is never consulted for these facts.
@@ -1361,6 +1445,7 @@ export declare interface KayAppAutomationRunOptions {
1361
1445
 
1362
1446
  export declare type KayAppAutomationRunOutcome = {
1363
1447
  readonly status: "succeeded";
1448
+ readonly summary?: KayAppRunSummary | undefined;
1364
1449
  readonly daemonRunId?: string | undefined;
1365
1450
  /** Present on a script run: which source this run actually executed. */
1366
1451
  readonly script?: {
@@ -1369,11 +1454,12 @@ export declare type KayAppAutomationRunOutcome = {
1369
1454
  } | undefined;
1370
1455
  } | {
1371
1456
  readonly status: "failed";
1457
+ readonly summary?: KayAppRunSummary | undefined;
1372
1458
  readonly reason: "executor_failed" | "permission_denied" | "surface_unavailable" | "target_gone";
1373
1459
  readonly message?: string | undefined;
1374
1460
  } | {
1375
1461
  readonly status: "skipped";
1376
- readonly reason: "already_running" | "binding_inactive" | "circuit_breaker" | "concurrency_capped" | "guard_not_satisfied" | "missed_window";
1462
+ readonly reason: "already_running" | "binding_inactive" | "circuit_breaker" | "concurrency_capped" | "guard_not_satisfied" | "missed_window" | "timer_cancelled";
1377
1463
  } | {
1378
1464
  readonly status: "abandoned";
1379
1465
  readonly reason: "daemon_restart";
@@ -1407,6 +1493,7 @@ export declare interface KayAppAutomations {
1407
1493
  get(id: string, ctx: KayAppAutomationContext): Promise<KayAppAutomationBinding | undefined>;
1408
1494
  create(input: {
1409
1495
  readonly name: string;
1496
+ readonly description?: string;
1410
1497
  readonly condition: KayAppAutomationConditionInput;
1411
1498
  readonly effect: KayAppAutomationEffectInput;
1412
1499
  readonly enabled?: boolean;
@@ -1468,13 +1555,13 @@ export declare interface KayAppAutomations {
1468
1555
  readonly nextCursor?: string;
1469
1556
  }>;
1470
1557
  /**
1471
- * One run's provenance detail (RFC Release 2): the sessions that run drove
1472
- * (direct and child, shared-run marked) and the Git-backed artifact
1473
- * revisions those sessions produced, with explicit projection coverage and
1474
- * gaps. A PUBLIC read like {@link listRuns}: it resolves the binding's
1475
- * actual owner rather than the caller's. Null when no retained run matches
1476
- * `bindingId` + `runId`. Coverage reports `rebuilding`/`partial` honestly
1477
- * while the projection catches up — it never blocks or fabricates.
1558
+ * One run's detail (RFC Release 2): the sessions that run drove (direct and
1559
+ * child, shared-run marked), the artifacts, external resources and skill
1560
+ * suggestions those sessions produced, and explicit coverage and gaps. A
1561
+ * PUBLIC read like {@link listRuns}: it resolves the binding's actual owner
1562
+ * rather than the caller's. Null when no retained run matches `bindingId` +
1563
+ * `runId`. Coverage reports `partial` honestly when some of the run's work
1564
+ * cannot be read — it never blocks or fabricates.
1478
1565
  */
1479
1566
  getRun(bindingId: string, runId: string, ctx: KayAppAutomationContext, options?: KayAppAutomationRunDetailOptions): Promise<KayAppAutomationRunDetail | null>;
1480
1567
  }
@@ -1495,6 +1582,8 @@ export declare type KayAppAutomationScriptRef = {
1495
1582
 
1496
1583
  /** A receipt-attributed skill candidate, with live status only for that exact revision. */
1497
1584
  export declare type KayAppAutomationSuggestionItem = {
1585
+ /** Only literal 1 proves physical addressing; other historical values remain uninterpreted. */
1586
+ readonly locatorVersion?: unknown;
1498
1587
  readonly sourceId: string;
1499
1588
  readonly skillName: string;
1500
1589
  readonly suggestionId: string;
@@ -1613,10 +1702,15 @@ export declare interface KayAppConfig {
1613
1702
  * path of the winning file. A JSON-safe twin of the runtime's `KayConfigValueOrigin`
1614
1703
  * (`@kay/product-catalog`) — this SDK cannot import that package, so the shape is re-declared
1615
1704
  * here and an assignability test in `@kay/agent-runtime` pins the two together. The level union
1616
- * is the closed, protocol-owned fold precedence stack (`learned < global < project`).
1705
+ * is the closed, protocol-owned fold precedence stack (`baseline < learned < global < project`).
1706
+ * `"baseline"` names a host-composed, in-memory, build/channel-scoped default with no file
1707
+ * behind it (`KayConfigStoreOptions.baselineDefaults`) — a plugin can still be handed one as a
1708
+ * winner for a FIELD within its own declared section that neither it nor the user ever set
1709
+ * (e.g. hindsight's `handlers.signals`, defaulted on by the host for this release channel), so
1710
+ * `path` for that level is a synthetic label, never a real file path.
1617
1711
  */
1618
1712
  export declare interface KayAppConfigOrigin {
1619
- readonly level: "learned" | "global" | "project";
1713
+ readonly level: "baseline" | "learned" | "global" | "project";
1620
1714
  readonly path: string;
1621
1715
  }
1622
1716
 
@@ -1677,14 +1771,31 @@ export declare interface KayAppContextContributor {
1677
1771
  * Raw read access to every stored session's transcript. Always present on
1678
1772
  * {@link KayAppPluginApi}; each read is checked against the `corpus.read` claim, and refused
1679
1773
  * unless the user has granted it. Data is raw and un-redacted — the plugin filters to what it
1680
- * needs. Both reads are async iterables so a corpus pass never loads the whole corpus into memory
1681
- * at once (the bound is one session at a time).
1774
+ * needs. Invocation queries are bounded pages. Transcript reads materialize a whole session
1775
+ * before yielding; the iterable does not promise per-entry streaming or an allocation bound.
1682
1776
  */
1683
1777
  export declare interface KayAppCorpus {
1778
+ /** Page invocation leads under the live grant; inspect exclusions even on available empty pages. */
1779
+ listResourceInvocations(query: CorpusResourceInvocationQuery): Promise<CorpusResourceInvocationPage>;
1684
1780
  /** Enumerate every stored session, newest-first. */
1685
1781
  listSessions(): AsyncIterable<KayAppCorpusSession>;
1686
- /** Stream one session's full entry log oldest→newest; an unknown id yields nothing. */
1782
+ /**
1783
+ * Yield one session's full entry log oldest→newest; an unknown id yields nothing. Treat the
1784
+ * entries as read-only: for a session the daemon holds in memory they are its live objects.
1785
+ */
1687
1786
  readEntries(sessionId: string): AsyncIterable<SessionTreeEntry>;
1787
+ /**
1788
+ * Read one bounded physical JSONL page. The host resolves `sessionId` to its authoritative
1789
+ * indexed path and validates the opaque cursor before opening it. When `throughEntryId` is
1790
+ * supplied, the cursor stops at that entry's transaction line; a V4 line may carry later
1791
+ * entries, which are returned for the caller to filter and are replayed on the next page.
1792
+ */
1793
+ readEntryBatch?(sessionId: string, options?: {
1794
+ readonly cursor?: JsonValue_4;
1795
+ readonly throughEntryId?: string;
1796
+ /** Host-only cancellation for the bounded physical read. */
1797
+ readonly signal?: AbortSignal;
1798
+ }): Promise<KayAppCorpusEntryBatch>;
1688
1799
  /**
1689
1800
  * Read a cheap transcript change marker without loading the entry log. Unknown or deleted
1690
1801
  * sessions yield `undefined`.
@@ -1692,6 +1803,20 @@ export declare interface KayAppCorpus {
1692
1803
  readSessionSourceMark(sessionId: string): Promise<KayAppCorpusSourceMark | undefined>;
1693
1804
  }
1694
1805
 
1806
+ /** One bounded physical page from the host's incremental JSONL reader. */
1807
+ export declare interface KayAppCorpusEntryBatch {
1808
+ readonly entries: readonly SessionTreeEntry[];
1809
+ /** Opaque JSON cursor after the physical page; only the host may interpret it or open its path. */
1810
+ readonly cursor: JsonValue_4;
1811
+ /** Opaque cursor at the physical page start, for a partial logical chunk. */
1812
+ readonly pageStartCursor?: JsonValue_4;
1813
+ readonly mode: "replace" | "append";
1814
+ readonly status: "complete" | "more" | "awaiting-append" | "record-too-large";
1815
+ /** Present when a caller supplied `throughEntryId`. */
1816
+ readonly anchorFound?: boolean;
1817
+ readonly malformedRecords: number;
1818
+ }
1819
+
1695
1820
  /** One stored session, as the granted corpus enumerates them. Keyed by its stable `sessionId`. */
1696
1821
  export declare interface KayAppCorpusSession {
1697
1822
  readonly sessionId: string;
@@ -1954,6 +2079,13 @@ export declare interface KayAppEndpoints {
1954
2079
  register(name: string, handler: (payload: unknown) => unknown | Promise<unknown>): void;
1955
2080
  }
1956
2081
 
2082
+ /** A real human carrier projected into the source session's transcript. */
2083
+ export declare interface KayAppHumanMessageSessionEvent extends KayAppSessionEventBase {
2084
+ readonly type: "human-message";
2085
+ /** Exact prior persisted boundary captured by the host at projection time; `null` means empty history. */
2086
+ readonly throughEntryId: string | null;
2087
+ }
2088
+
1957
2089
  /**
1958
2090
  * A provider's nominated image model, resolved now: what a session on one of that
1959
2091
  * provider's text-only models spawns to read images. `resolved` absent = nothing
@@ -2452,9 +2584,9 @@ export declare interface KayAppPluginEvents {
2452
2584
  export declare type KayAppProcessingSpeed = "standard" | "fast";
2453
2585
 
2454
2586
  /**
2455
- * A gap reason on the run-detail wire. Adapter-determined codes come from the
2456
- * projection's stored gap vocabulary; the remaining four are derived at query
2457
- * time from current evidence and checkpoint coverage.
2587
+ * A gap reason on the run-detail wire: something about the run's work the
2588
+ * daemon could not establish from its session transcripts. The vocabulary is
2589
+ * closed; a daemon may emit only some of these codes.
2458
2590
  */
2459
2591
  export declare type KayAppProvenanceGapCode = "legacy-run-id-missing" | "mutation-revision-missing" | "partial-git-provenance" | "git-session-stamp-missing"
2460
2592
  /** A run created something off this machine that the transcript cannot name. */
@@ -2537,6 +2669,14 @@ export declare interface KayAppResolvedCredential {
2537
2669
  readonly fields?: Readonly<Record<string, string>>;
2538
2670
  }
2539
2671
 
2672
+ export declare interface KayAppRunSummary {
2673
+ /** One plain-text line, at most 100 characters. */
2674
+ readonly headline: string;
2675
+ /** Optional plain-text explanation, at most 600 characters. */
2676
+ readonly details?: string | undefined;
2677
+ readonly author: "automation" | "kay";
2678
+ }
2679
+
2540
2680
  /**
2541
2681
  * The session provenance vocabulary, as the plugin protocol declares it. These used to be spelled
2542
2682
  * out here because the canonical schemas lived in `@kay/agent-runtime-protocol`, which this
@@ -2568,17 +2708,16 @@ export declare type KayAppSessionCreator = SessionCreator;
2568
2708
 
2569
2709
  export declare type KayAppSessionDefiner = SessionDefiner;
2570
2710
 
2571
- export declare type KayAppSessionEvent = KayAppTurnSettledSessionEvent | KayAppPhaseShiftSessionEvent;
2711
+ export declare type KayAppSessionEvent = KayAppHumanMessageSessionEvent | KayAppTurnSettledSessionEvent | KayAppPhaseShiftSessionEvent;
2572
2712
 
2573
2713
  declare interface KayAppSessionEventBase {
2574
2714
  readonly sessionId: string;
2575
2715
  /**
2576
- * The event's own anchor entry: the settled turn's own last entry, or the phase-shift
2577
- * observation's `observationEntryId`. A handler bounds its OWN corpus read using this id (via
2578
- * whatever packet-building helpers the plugin already owns); the door hands out no
2579
- * `readEntries()` closure, and re-validating what was read against the CURRENT branch — a
2580
- * rewind can race between publish and read — is the handler's own job, exactly as
2581
- * `resolveClosedPhase` already does today for the phase extractor.
2716
+ * The event's own anchor entry: the projected human carrier, the settled turn's own last
2717
+ * entry, or the phase-shift observation's `observationEntryId`. A handler bounds its OWN logical
2718
+ * corpus interval using this id (via whatever packet-building helpers the plugin already owns);
2719
+ * the door hands out no `readEntries()` closure, and re-validating what was read against the
2720
+ * CURRENT branch — a rewind can race between publish and read — is the handler's own job.
2582
2721
  */
2583
2722
  readonly entryId: string;
2584
2723
  /** ISO-8601 publish time. */
@@ -2615,6 +2754,8 @@ export declare type KayAppSessionEventCause = {
2615
2754
  * substitute a run id resolved another way.
2616
2755
  */
2617
2756
  readonly runId?: string;
2757
+ /** Exact prior persisted boundary for a projected human-message event; null means empty history. */
2758
+ readonly throughEntryId?: string | null;
2618
2759
  };
2619
2760
  /**
2620
2761
  * Exact-match dedupe key. The host REFUSES a second run carrying the same key outright (a
@@ -2677,12 +2818,12 @@ export declare interface KayAppSessionEventsSubscribeOptions {
2677
2818
  }
2678
2819
 
2679
2820
  /**
2680
- * A closed, extensible union: today's two root events a lane could fire on
2681
- * (`turn-settled`) and react to (`phase-shift`), collapsed onto one subscribable set now that
2682
- * there is no dispatcher chaining one lane's completion into another's `when`. Adding a third
2683
- * type is additive, never breaking.
2821
+ * A closed, extensible union: a projected human message, a settled turn, or an accepted
2822
+ * phase-shift observation. They share one subscribable set now that there is no dispatcher
2823
+ * chaining one job's completion into another's `when`. Adding a fourth type is additive, never
2824
+ * breaking.
2684
2825
  */
2685
- export declare type KayAppSessionEventType = "turn-settled" | "phase-shift";
2826
+ export declare type KayAppSessionEventType = "human-message" | "turn-settled" | "phase-shift";
2686
2827
 
2687
2828
  export declare type KayAppSessionIntent = SessionIntent;
2688
2829
 
@@ -3006,8 +3147,9 @@ export declare interface KayAppSignalDetector {
3006
3147
  * - `classified`: Jev answered; `answers`, `model`, and `usage` are the vendor's verbatim
3007
3148
  * response, and `stored` says whether the row landed in the durable store.
3008
3149
  * - `unavailable`: Jev could not answer (no key, refused grant, timeout, vendor error, or a
3009
- * malformed response). `reason` names the host's classification; no row is written, so the
3010
- * same input can be observed again later without a conflict.
3150
+ * malformed response), or the host has no signals store at all (`reason: "no-store"`).
3151
+ * `reason` names the host's classification; no row is written, so the same input can be
3152
+ * observed again later without a conflict.
3011
3153
  * - `invalid`: the input breaks the recorded-name grammar (see {@link invalidObservation}), and
3012
3154
  * `reason` says which name and why. The caller's mistake, not the environment's: Jev is never
3013
3155
  * called, no row is written, and the same input is refused again. `detector` and `source`
@@ -3030,7 +3172,11 @@ export declare interface KayAppSignalObservation {
3030
3172
  } | undefined;
3031
3173
  readonly tookMs?: number | undefined;
3032
3174
  readonly reason?: string | undefined;
3033
- /** True when the row landed in the durable store; false when the host composed no store. */
3175
+ /**
3176
+ * True when the row landed in the durable store; false when a composed store's own write
3177
+ * failed after Jev already answered (rare -- a host with no store at all instead answers
3178
+ * `unavailable` with reason `"no-store"`, never reaching `classified`).
3179
+ */
3034
3180
  readonly stored: boolean;
3035
3181
  /** True when this call returned an already-stored row instead of running inference. */
3036
3182
  readonly deduplicated: boolean;
@@ -3531,10 +3677,22 @@ export declare interface KayAppWorkflowContext {
3531
3677
 
3532
3678
  export declare interface KayAppWorkflowDefinition {
3533
3679
  readonly name: string;
3680
+ /** Plain-text purpose, at most 280 characters. */
3681
+ readonly description: string;
3682
+ readonly instructions?: readonly KayAppWorkflowInstruction[];
3683
+ readonly perRunNote?: string;
3534
3684
  readonly trigger: Extract<KayAppAutomationConditionInput, {
3535
3685
  readonly kind: "time";
3536
3686
  }>;
3537
- readonly run: (context: KayAppWorkflowContext) => void | Promise<void>;
3687
+ readonly run: (context: KayAppWorkflowContext) => Promise<{
3688
+ readonly summary: KayAppRunSummary;
3689
+ }>;
3690
+ }
3691
+
3692
+ /** Fail a workflow while retaining its own explanation beside this attempt. */
3693
+ export declare class KayAppWorkflowFailure extends Error {
3694
+ readonly summary: KayAppRunSummary;
3695
+ constructor(summary: Omit<KayAppRunSummary, "author">, options?: ErrorOptions);
3538
3696
  }
3539
3697
 
3540
3698
  export declare interface KayAppWorkflowInspection {
@@ -3548,6 +3706,20 @@ export declare interface KayAppWorkflowInspectOptions {
3548
3706
  readonly limit?: number;
3549
3707
  }
3550
3708
 
3709
+ export declare type KayAppWorkflowInstruction = {
3710
+ readonly label: string;
3711
+ readonly kind: "prompt";
3712
+ readonly text: string;
3713
+ } | {
3714
+ readonly label: string;
3715
+ readonly kind: "agent";
3716
+ readonly agent: KayAppAgentDefinitionRef;
3717
+ } | {
3718
+ readonly label: string;
3719
+ readonly kind: "script";
3720
+ readonly ref: KayAppAutomationScriptRef;
3721
+ };
3722
+
3551
3723
  export declare interface KayAppWorkflows {
3552
3724
  define(localId: string, definition: KayAppWorkflowDefinition): void;
3553
3725
  inspect(localId: string, options?: KayAppWorkflowInspectOptions): Promise<KayAppWorkflowInspection>;
@@ -4454,9 +4626,11 @@ declare const SessionCausedByEvent: z.ZodObject<{
4454
4626
  type: z.ZodEnum<{
4455
4627
  "turn-settled": "turn-settled";
4456
4628
  "phase-shift": "phase-shift";
4629
+ "human-message": "human-message";
4457
4630
  }>;
4458
4631
  entryId: z.ZodString;
4459
4632
  runId: z.ZodOptional<z.ZodString>;
4633
+ throughEntryId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
4460
4634
  }, z.core.$strict>>;
4461
4635
  dedupeKey: z.ZodOptional<z.ZodString>;
4462
4636
  }, z.core.$strict>;
@@ -4650,9 +4824,11 @@ declare const SessionProvenanceRecord: z.ZodObject<{
4650
4824
  type: z.ZodEnum<{
4651
4825
  "turn-settled": "turn-settled";
4652
4826
  "phase-shift": "phase-shift";
4827
+ "human-message": "human-message";
4653
4828
  }>;
4654
4829
  entryId: z.ZodString;
4655
4830
  runId: z.ZodOptional<z.ZodString>;
4831
+ throughEntryId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
4656
4832
  }, z.core.$strict>>;
4657
4833
  dedupeKey: z.ZodOptional<z.ZodString>;
4658
4834
  }, z.core.$strict>>;
@@ -5412,6 +5588,17 @@ export declare interface UriModule {
5412
5588
  readonly permission?: UriOperationPermissionPolicy;
5413
5589
  /** Pure route/payload validation applied before a consequential permission ask. */
5414
5590
  readonly preflight?: UriOperationPreflightPolicy;
5591
+ /**
5592
+ * Supply structured action facts and explicit input coverage for a one-line approval.
5593
+ * The host composes and admits the line; see the protocol's UriModule contract.
5594
+ * Names must be resolved through this call's dispatch context. The host enforces
5595
+ * `ctx.signal`'s deadline and treats a throw or late answer as no summary.
5596
+ */
5597
+ describeOperation?(request: {
5598
+ readonly operation: UriOperation;
5599
+ readonly uri: string;
5600
+ readonly payload: unknown;
5601
+ }, ctx: UriResolveContext): Promise<UriOperationDescription | undefined>;
5415
5602
  /**
5416
5603
  * Set false when the generic write tool must reject `source` copies before
5417
5604
  * fetching the source. Inline `content` writes remain available.
@@ -5584,6 +5771,22 @@ export declare class UriNotFoundError extends UriError {
5584
5771
 
5585
5772
  declare type UriOperation = "help" | "read" | "write" | "edit" | "list" | "search" | "delete";
5586
5773
 
5774
+ declare interface UriOperationDescription {
5775
+ /** Static verb phrase authored by the module. Never interpolated from input. */
5776
+ readonly action: string;
5777
+ /** Human name resolved through the connection that will execute the call. */
5778
+ readonly target: string;
5779
+ /** Model-authored content; the host flattens, budgets, elides and bounds it. */
5780
+ readonly quote?: string;
5781
+ /** What this description accounts for; the host refuses undeclared input. */
5782
+ readonly accounts: {
5783
+ /** The payload actually read by the module, after its own decoding. */
5784
+ readonly payload: unknown;
5785
+ readonly payloadFields: readonly string[];
5786
+ readonly queryParams?: readonly string[];
5787
+ };
5788
+ }
5789
+
5587
5790
  declare interface UriOperationPermissionClassification {
5588
5791
  /**
5589
5792
  * The operation's real effect. The permission classifier only accepts a
package/dist/kay-app.js CHANGED
@@ -387,6 +387,16 @@ function transcriptRoleLabel(role) {
387
387
  return role === "user" ? "User" : "Assistant";
388
388
  }
389
389
 
390
+ // packages/plugin-sdk/dist/kay-app/workflows.js
391
+ var KayAppWorkflowFailure = class extends Error {
392
+ summary;
393
+ constructor(summary, options) {
394
+ super(summary.details ?? summary.headline, options);
395
+ this.name = "KayAppWorkflowFailure";
396
+ this.summary = { ...summary, author: "automation" };
397
+ }
398
+ };
399
+
390
400
  // packages/plugin-protocol/dist/app-data.js
391
401
  var KAY_APP_DATA_SNAPSHOT_MAX_BYTES = 16 * 1024 * 1024;
392
402
  var KAY_APP_DATA_CHANGE_MAX_BYTES = 256 * 1024;
@@ -406,6 +416,7 @@ var KAY_APP_AUTOMATION_CONDITION_KINDS = [
406
416
  export {
407
417
  KAY_APP_AUTOMATION_CONDITION_KINDS,
408
418
  KAY_APP_DATA_CHANGE_MAX_BYTES,
419
+ KayAppWorkflowFailure,
409
420
  MAX_CHOICE_LABELS,
410
421
  SIGNAL_TIME_MAX_MS,
411
422
  UriConflictError,
package/dist/signals.d.ts CHANGED
@@ -67,8 +67,9 @@ export declare interface KayAppSignalDetector {
67
67
  * - `classified`: Jev answered; `answers`, `model`, and `usage` are the vendor's verbatim
68
68
  * response, and `stored` says whether the row landed in the durable store.
69
69
  * - `unavailable`: Jev could not answer (no key, refused grant, timeout, vendor error, or a
70
- * malformed response). `reason` names the host's classification; no row is written, so the
71
- * same input can be observed again later without a conflict.
70
+ * malformed response), or the host has no signals store at all (`reason: "no-store"`).
71
+ * `reason` names the host's classification; no row is written, so the same input can be
72
+ * observed again later without a conflict.
72
73
  * - `invalid`: the input breaks the recorded-name grammar (see {@link invalidObservation}), and
73
74
  * `reason` says which name and why. The caller's mistake, not the environment's: Jev is never
74
75
  * called, no row is written, and the same input is refused again. `detector` and `source`
@@ -91,7 +92,11 @@ export declare interface KayAppSignalObservation {
91
92
  } | undefined;
92
93
  readonly tookMs?: number | undefined;
93
94
  readonly reason?: string | undefined;
94
- /** True when the row landed in the durable store; false when the host composed no store. */
95
+ /**
96
+ * True when the row landed in the durable store; false when a composed store's own write
97
+ * failed after Jev already answered (rare -- a host with no store at all instead answers
98
+ * `unavailable` with reason `"no-store"`, never reaching `classified`).
99
+ */
95
100
  readonly stored: boolean;
96
101
  /** True when this call returned an already-stored row instead of running inference. */
97
102
  readonly deduplicated: boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yaklabs-ai/plugin-sdk",
3
- "version": "0.8.5",
3
+ "version": "0.9.1",
4
4
  "description": "The Kay plugin SDK — types and helpers for authoring a Kay directory plugin.",
5
5
  "author": "YakLabs",
6
6
  "type": "module",