@claxedo/agent-runtime-contract 0.8.0 → 0.10.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.
Files changed (65) hide show
  1. package/README.md +27 -9
  2. package/dist/agent-runtime-event.d.ts +975 -0
  3. package/dist/availability.d.ts +3 -4
  4. package/dist/background-work.d.ts +10 -0
  5. package/dist/claims.d.ts +2 -0
  6. package/dist/connections.d.ts +66 -1
  7. package/dist/content.d.ts +72 -15
  8. package/dist/credential-broker-errors.d.ts +4 -0
  9. package/dist/custom-provider-headers.d.ts +12 -0
  10. package/dist/d1-bookmarks.d.ts +39 -0
  11. package/dist/daemon-ownership-snapshot.d.ts +40 -0
  12. package/dist/diagnostics.d.ts +24 -0
  13. package/dist/elicitation-pattern-worker.d.ts +6 -0
  14. package/dist/elicitation-pattern-worker.mjs +17 -0
  15. package/dist/elicitation-validation.d.ts +23 -0
  16. package/dist/elicitation.d.ts +51 -0
  17. package/dist/errors.d.ts +8 -1
  18. package/dist/event-cursor.d.ts +19 -0
  19. package/dist/events.d.ts +146 -216
  20. package/dist/files.d.ts +2 -0
  21. package/dist/first-turn-error.d.ts +12 -0
  22. package/dist/goals.d.ts +28 -0
  23. package/dist/harness-permission-modes.d.ts +76 -0
  24. package/dist/harness-table.d.ts +66 -4
  25. package/dist/harnesses.d.ts +19 -1
  26. package/dist/ids.d.ts +4 -0
  27. package/dist/index.d.ts +46 -1
  28. package/dist/index.mjs +2814 -95
  29. package/dist/mcp-app.d.ts +24 -0
  30. package/dist/message-page.d.ts +101 -0
  31. package/dist/permissions.d.ts +47 -0
  32. package/dist/pi-providers.d.ts +36 -0
  33. package/dist/prompt-title.d.ts +2 -0
  34. package/dist/provider-projection.d.ts +166 -0
  35. package/dist/raw-harness-event.d.ts +7 -0
  36. package/dist/recovery/actions.d.ts +20 -0
  37. package/dist/recovery/budgets.d.ts +16 -0
  38. package/dist/recovery/facts.d.ts +37 -0
  39. package/dist/recovery/operations.d.ts +66 -0
  40. package/dist/recovery/outcomes.d.ts +48 -0
  41. package/dist/recovery/payload-line.d.ts +19 -0
  42. package/dist/recovery/postconditions.d.ts +18 -0
  43. package/dist/recovery/requests.d.ts +44 -0
  44. package/dist/recovery/targets.d.ts +55 -0
  45. package/dist/recovery/validation.d.ts +9 -0
  46. package/dist/runtime-content.d.ts +34 -0
  47. package/dist/session-handoff.d.ts +4 -0
  48. package/dist/session-titles.d.ts +14 -0
  49. package/dist/sessions.d.ts +183 -5
  50. package/dist/stream-heartbeat.d.ts +11 -0
  51. package/dist/subagents.d.ts +92 -0
  52. package/dist/tool-header.d.ts +13 -0
  53. package/dist/tool-names.d.ts +5 -0
  54. package/dist/transcript-notice.d.ts +28 -0
  55. package/dist/turn-account.d.ts +26 -0
  56. package/dist/turn-error-classes.d.ts +10 -0
  57. package/dist/turn-fold.d.ts +111 -0
  58. package/dist/turn-fold.mjs +414 -0
  59. package/dist/turn-message-ids.d.ts +16 -0
  60. package/dist/turn-outline.d.ts +37 -0
  61. package/dist/turn-page.d.ts +58 -0
  62. package/dist/usage-streams.d.ts +19 -0
  63. package/dist/vendor-body.d.ts +31 -0
  64. package/dist/vendor-providers.d.ts +11 -0
  65. package/package.json +17 -3
@@ -24,9 +24,9 @@ export type AgentRuntimeStatus = {
24
24
  type: "busy";
25
25
  } | {
26
26
  type: "retry";
27
- attempt: number;
28
27
  message: string;
29
- next: number;
28
+ attempt?: number;
29
+ next?: number;
30
30
  action?: {
31
31
  reason: string;
32
32
  provider: string;
@@ -36,7 +36,6 @@ export type AgentRuntimeStatus = {
36
36
  link?: string;
37
37
  };
38
38
  } | {
39
- type: "recovering";
40
- kind: "process_restart";
39
+ type: "interrupted";
41
40
  message: string;
42
41
  };
@@ -0,0 +1,10 @@
1
+ /** Work a harness runs for a session outside any turn, counted by kind. A task the harness marks ambient is not activity and is not counted. */
2
+ export type BackgroundWork = {
3
+ agents: number;
4
+ shells: number;
5
+ other: number;
6
+ };
7
+ export declare const NO_BACKGROUND_WORK: BackgroundWork;
8
+ export declare function backgroundWorkActive(work: BackgroundWork): boolean;
9
+ export declare function sameBackgroundWork(a: BackgroundWork, b: BackgroundWork): boolean;
10
+ export declare function parseBackgroundWork(value: unknown): BackgroundWork | undefined;
package/dist/claims.d.ts CHANGED
@@ -20,6 +20,8 @@
20
20
  * credential without an email is ordinary.
21
21
  */
22
22
  export declare function emailFromClaims(input: Record<string, unknown> | undefined): string | undefined;
23
+ /** When a JWT stops being accepted, from its own `exp`, in epoch milliseconds; nothing when the value is not a JWT or names none. */
24
+ export declare function expiryFromJwt(token: string | undefined): number | undefined;
23
25
  /**
24
26
  * The ChatGPT account a login document names.
25
27
  *
@@ -1,6 +1,40 @@
1
1
  import type { AgentCapabilities, ModelSelection } from "./capabilities";
2
- export type ConnectionReadiness = "ready" | "unavailable" | "disabled";
2
+ export type ConnectionReadiness = "configured" | "ready" | "unavailable" | "disabled";
3
+ /** Ready proves the ACP handshake, not subscription authentication or session admission. */
4
+ export type ConnectionRuntimeState = "configured" | "connecting" | "ready" | "auth-required" | "disconnected" | "failed";
5
+ export type ConnectionRuntimeObservation = {
6
+ generation: string;
7
+ role: "execution" | "discovery";
8
+ state: Exclude<ConnectionRuntimeState, "configured">;
9
+ observedAt: number;
10
+ reason?: string;
11
+ };
12
+ export type ConnectionRuntimeStatus = {
13
+ state: ConnectionRuntimeState;
14
+ processes: ConnectionRuntimeObservation[];
15
+ };
16
+ /** A harness's health as the runtime reads it, for the runtime or for one session. */
17
+ export type AgentRuntimeHealth = {
18
+ status: "ok" | "degraded" | "unavailable";
19
+ reason?: string;
20
+ message?: string;
21
+ sessions?: Array<{
22
+ id: string;
23
+ status?: string | null;
24
+ message?: string | null;
25
+ }>;
26
+ };
3
27
  export type HarnessConnectionCapabilities = Omit<AgentCapabilities, "harness" | "modelSelection">;
28
+ /** An operator-configured connection as the control plane stores it; `config` is readable only by its provider. */
29
+ export type HarnessConnectionDescriptor<TConfig = unknown> = {
30
+ connectionId: string;
31
+ providerKey: string;
32
+ configRevision: number;
33
+ enabled: boolean;
34
+ config: TConfig;
35
+ /** Opaque host-persistence references. Raw secret values never enter config. */
36
+ secretRefs?: Readonly<Record<string, string>>;
37
+ };
4
38
  /** Public discovery metadata. Provider configuration and credentials stay on the host. */
5
39
  export type HarnessConnectionRef = {
6
40
  connectionId: string;
@@ -19,3 +53,34 @@ export type HarnessConnectionsCatalog = {
19
53
  };
20
54
  export declare function decodeHarnessConnectionsCatalog(value: unknown): HarnessConnectionsCatalog;
21
55
  export declare function decodeModelSelection(value: unknown): ModelSelection;
56
+ export type ConnectionSecretLease = {
57
+ /** Provider-named secret values, resolved only at the trusted runtime boundary. */
58
+ secrets: Readonly<Record<string, string>>;
59
+ /** Non-secret version or expiry token that keys the transport generation. */
60
+ secretLeaseGeneration: string;
61
+ };
62
+ /**
63
+ * The proof the operation that needs a connection was admitted under. A remote
64
+ * secret lease is requested with it, so a background turn proves itself with
65
+ * its own turn lease rather than with whichever request happens to be running.
66
+ */
67
+ export type ConnectionSecretAuthority = {
68
+ kind: "request";
69
+ credential: string;
70
+ } | {
71
+ kind: "turn";
72
+ lease: string;
73
+ };
74
+ export type ConnectionSecretOwner = {
75
+ kind: "machine-owner";
76
+ } | {
77
+ kind: "person";
78
+ userId: string;
79
+ };
80
+ export type ConnectionSecretResolver = (input: {
81
+ descriptor: HarnessConnectionDescriptor;
82
+ directory: string;
83
+ authority?: ConnectionSecretAuthority;
84
+ /** The session owner whose accounts the connection spends, whoever sent the turn. */
85
+ owner: ConnectionSecretOwner;
86
+ }) => Promise<ConnectionSecretLease> | ConnectionSecretLease;
package/dist/content.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import type { AgentMessageAuthor } from "./sessions";
2
+ import { type TranscriptNotice } from "./transcript-notice";
2
3
  /** Token accounting, reported identically by assistant messages and step-finish parts. */
3
4
  export type AgentTokenUsage = {
4
5
  total?: number;
@@ -42,8 +43,10 @@ export type AgentUserMessage = {
42
43
  body?: string;
43
44
  diffs: AgentSnapshotFileDiff[];
44
45
  };
45
- agent: string;
46
- model: AgentModelRef;
46
+ /** Present only when the prompt named an engine agent; a harness with no agent concept sends none. */
47
+ agent?: string;
48
+ /** Absent when the connection owns model selection. */
49
+ model?: AgentModelRef;
47
50
  system?: string;
48
51
  tools?: Record<string, boolean>;
49
52
  claxedo?: {
@@ -60,10 +63,10 @@ export type AgentAssistantMessage = {
60
63
  };
61
64
  error?: AgentMessageError;
62
65
  parentID: string;
63
- modelID: string;
64
- providerID: string;
66
+ modelID?: string;
67
+ providerID?: string;
65
68
  mode: string;
66
- agent: string;
69
+ agent?: string;
67
70
  path: {
68
71
  cwd: string;
69
72
  root: string;
@@ -113,6 +116,13 @@ export type AgentMessage = {
113
116
  info: AgentMessageInfo;
114
117
  parts: AgentContentPart[];
115
118
  harnessPayload?: unknown;
119
+ /**
120
+ * The turn the runtime projected this message in, named by the assistant
121
+ * message id that turn's start opened. A prompt steered into a running turn
122
+ * and every reply after it carry that turn's id; a message no turn holds has
123
+ * none.
124
+ */
125
+ turnId?: string;
116
126
  };
117
127
  type AgentPartBase<Type extends string> = {
118
128
  id: string;
@@ -120,6 +130,10 @@ type AgentPartBase<Type extends string> = {
120
130
  messageID: string;
121
131
  type: Type;
122
132
  };
133
+ /** The harness withdrew the response this content belongs to; the content is kept, not erased. */
134
+ export type AgentPartRetraction = {
135
+ reason: string;
136
+ };
123
137
  export type AgentTextPart = AgentPartBase<"text"> & {
124
138
  text: string;
125
139
  synthetic?: boolean;
@@ -129,6 +143,7 @@ export type AgentTextPart = AgentPartBase<"text"> & {
129
143
  end?: number;
130
144
  };
131
145
  metadata?: Record<string, unknown>;
146
+ retracted?: AgentPartRetraction;
132
147
  };
133
148
  export type AgentReasoningPart = AgentPartBase<"reasoning"> & {
134
149
  text: string;
@@ -137,6 +152,7 @@ export type AgentReasoningPart = AgentPartBase<"reasoning"> & {
137
152
  end?: number;
138
153
  };
139
154
  metadata?: Record<string, unknown>;
155
+ retracted?: AgentPartRetraction;
140
156
  };
141
157
  export type AgentFilePartSourceText = {
142
158
  value: string;
@@ -180,6 +196,9 @@ export type AgentFilePartSource = AgentFileSource | AgentSymbolSource | AgentRes
180
196
  * image was instead of rendering a broken one.
181
197
  */
182
198
  export type AgentFileLocation = {
199
+ kind: "tool-file";
200
+ path: string;
201
+ } | {
183
202
  kind: "workspace-file";
184
203
  path: string;
185
204
  } | {
@@ -193,15 +212,15 @@ export type AgentFilePart = AgentPartBase<"file"> & {
193
212
  location?: AgentFileLocation;
194
213
  source?: AgentFilePartSource;
195
214
  };
196
- export type AgentTextPartInput = Omit<AgentTextPart, "id" | "sessionID" | "messageID"> & {
197
- id?: string;
198
- };
199
- export type AgentFilePartInput = Omit<AgentFilePart, "id" | "sessionID" | "messageID"> & {
200
- id?: string;
201
- };
202
- export type AgentAgentPartInput = Omit<AgentAgentPart, "id" | "sessionID" | "messageID"> & {
203
- id?: string;
204
- };
215
+ export type AgentTextPartInput = Omit<AgentTextPart, "id" | "sessionID" | "messageID">;
216
+ export type AgentFilePartInput = Omit<AgentFilePart, "id" | "sessionID" | "messageID">;
217
+ export type AgentAgentPartInput = Omit<AgentAgentPart, "id" | "sessionID" | "messageID">;
218
+ /**
219
+ * A prompt part's id, minted by the runtime from its message id. Part ids are
220
+ * one primary key across every session a runtime stores, so an id the client
221
+ * chose could name another session's part.
222
+ */
223
+ export declare function promptPartId(messageId: string, index: number): string;
205
224
  export type AgentToolState = {
206
225
  status: "pending";
207
226
  input: Record<string, unknown>;
@@ -241,6 +260,9 @@ export type AgentToolPart = AgentPartBase<"tool"> & {
241
260
  tool: string;
242
261
  state: AgentToolState;
243
262
  metadata?: Record<string, unknown>;
263
+ /** A read sent only what the collapsed row draws (`toolPartHeader`); the whole part is read when the row opens. */
264
+ headerOnly?: true;
265
+ retracted?: AgentPartRetraction;
244
266
  };
245
267
  /**
246
268
  * Whether a tool name spawns a subagent. Every harness spelling — Claude's `Agent`,
@@ -311,7 +333,13 @@ export type AgentHandoffPart = AgentPartBase<"handoff"> & {
311
333
  connection?: unknown;
312
334
  };
313
335
  };
314
- export type AgentContentPart = AgentTextPart | AgentReasoningPart | AgentFilePart | AgentToolPart | AgentSubtaskPart | AgentStepStartPart | AgentStepFinishPart | AgentSnapshotPart | AgentPatchPart | AgentAgentPart | AgentRetryPart | AgentCompactionPart | AgentHandoffPart;
336
+ export type AgentNoticePart = AgentPartBase<"notice"> & {
337
+ notice: TranscriptNotice;
338
+ time: {
339
+ created: number;
340
+ };
341
+ };
342
+ export type AgentContentPart = AgentTextPart | AgentReasoningPart | AgentFilePart | AgentToolPart | AgentSubtaskPart | AgentStepStartPart | AgentStepFinishPart | AgentSnapshotPart | AgentPatchPart | AgentAgentPart | AgentRetryPart | AgentCompactionPart | AgentHandoffPart | AgentNoticePart;
315
343
  export type AgentPromptResponse = {
316
344
  info: AgentAssistantMessage;
317
345
  parts: AgentContentPart[];
@@ -335,6 +363,9 @@ export type AgentQuestionInfo = {
335
363
  custom?: boolean;
336
364
  };
337
365
  export type AgentQuestionAnswer = string[];
366
+ export type AgentPermissionReply = "once" | "always" | "reject" | {
367
+ optionId: string;
368
+ };
338
369
  export type AgentPermission = {
339
370
  id: string;
340
371
  sessionID: string;
@@ -344,6 +375,11 @@ export type AgentPermission = {
344
375
  };
345
376
  title?: string;
346
377
  permission: string;
378
+ options?: {
379
+ id: string;
380
+ label: string;
381
+ description?: string;
382
+ }[];
347
383
  patterns: string[];
348
384
  always: string[];
349
385
  metadata: Record<string, unknown>;
@@ -366,10 +402,25 @@ export type AgentCommand = {
366
402
  name: string;
367
403
  content?: string;
368
404
  description?: string;
405
+ input?: {
406
+ hint: string;
407
+ } | null;
408
+ source?: "command" | "mcp" | "skill";
369
409
  harnessPayload?: unknown;
370
410
  };
411
+ /** A user's command as configuration carries it: its name and the prompt text it expands to. */
412
+ export type SavedCommand = {
413
+ name: string;
414
+ content: string;
415
+ };
416
+ export type RuntimeCommand = AgentCommand & ((SavedCommand & {
417
+ origin: "saved";
418
+ }) | {
419
+ origin: "transport";
420
+ });
371
421
  export type AgentAgent = {
372
422
  name: string;
423
+ id?: string;
373
424
  description?: string;
374
425
  mode?: string;
375
426
  harnessPayload?: unknown;
@@ -387,6 +438,8 @@ export type AgentConfigOption = {
387
438
  description?: string;
388
439
  value?: unknown;
389
440
  connected?: boolean;
441
+ /** The full model id an alias row runs (`haiku` runs `claude-haiku-4-5-20251001`). */
442
+ resolvedModel?: string;
390
443
  harnessPayload?: unknown;
391
444
  }>;
392
445
  harnessPayload?: unknown;
@@ -408,4 +461,8 @@ export declare function isAgentMessageInfo(value: unknown): value is AgentMessag
408
461
  export declare function isAgentMessage(value: unknown): value is AgentMessage;
409
462
  /** The message `value` holds, or `undefined` when it is not one. */
410
463
  export declare function parseAgentMessage(value: unknown): AgentMessage | undefined;
464
+ /** Is `value` a todo as the runtime reports it? */
465
+ export declare function isAgentTodo(value: unknown): value is AgentTodo;
466
+ /** Is `value` one file's entry in a session's diff summary? */
467
+ export declare function isAgentSnapshotFileDiff(value: unknown): value is AgentSnapshotFileDiff;
411
468
  export {};
@@ -66,6 +66,10 @@ export declare const CREDENTIAL_BROKER_ERRORS: {
66
66
  readonly fault: "harness";
67
67
  readonly message: "The credential broker answers loopback callers only";
68
68
  };
69
+ readonly runtime_token_rate_limited: {
70
+ readonly fault: "harness";
71
+ readonly message: "Too many requests without a verifiable runtime token from this client";
72
+ };
69
73
  };
70
74
  export type CredentialBrokerErrorCode = keyof typeof CREDENTIAL_BROKER_ERRORS;
71
75
  /**
@@ -0,0 +1,12 @@
1
+ /**
2
+ * The request headers an operator-declared provider may carry beside its
3
+ * credential: routing and attribution metadata only. Anything else is either a
4
+ * credential or unknown, and an unknown header is refused rather than trusted,
5
+ * because its value travels in the runtime snapshot and the engine's config in
6
+ * the clear. The stored credential reaches the provider through the broker at
7
+ * the header the provider declares for it, never as one of these.
8
+ */
9
+ export declare const CUSTOM_PROVIDER_METADATA_HEADERS: readonly ["HTTP-Referer", "X-Title", "OpenAI-Organization", "OpenAI-Project"];
10
+ export declare function isCustomProviderMetadataHeader(name: string): boolean;
11
+ /** Whether the broker can write a custom provider's stored key into this header: never a metadata header, never one the connection owns. */
12
+ export declare function isCustomProviderCredentialHeader(name: string): boolean;
@@ -0,0 +1,39 @@
1
+ /**
2
+ * How the hosted control plane's clients carry D1 bookmarks between requests.
3
+ *
4
+ * A bookmark names a version of one of the control plane's databases; a read
5
+ * that starts from it is answered by a replica at least that new
6
+ * (developers.cloudflare.com/d1/best-practices/read-replication/). The control
7
+ * plane hands bookmarks out on its answers and on the live-sync notices of
8
+ * the writes they announce; a client returns the newest it holds per
9
+ * database, the browser as cookies and a client without a cookie jar in
10
+ * `D1_BOOKMARKS_HEADER`, written as `auth=<bookmark>, control=<bookmark>`.
11
+ */
12
+ export type D1BookmarkName = "auth" | "control";
13
+ export declare const D1_BOOKMARKS_HEADER = "x-claxedo-d1-bookmarks";
14
+ /** Followed by the database's name; `__Host-` keeps the cookie on the exact origin, over HTTPS, at path `/`. */
15
+ export declare const D1_BOOKMARK_COOKIE_PREFIX = "__Host-claxedo.d1-";
16
+ /**
17
+ * Long enough to outlast replica lag, short enough that no bookmark outlives
18
+ * the database it names: resetting staging recreates the control-plane
19
+ * database, whose versions start again below any bookmark a client still holds.
20
+ */
21
+ export declare const D1_BOOKMARK_MAX_AGE_SECONDS = 300;
22
+ /** The cookie that carries `name`'s bookmark; scripts may read and raise it, since it says only which version a reader has seen. */
23
+ export declare function d1BookmarkCookie(name: D1BookmarkName, bookmark: string): string;
24
+ export declare function isD1Bookmark(value: unknown): value is string;
25
+ /** D1 bookmarks "are lexicographically sortable", oldest first (developers.cloudflare.com/d1/reference/time-travel/). */
26
+ export declare function newerD1Bookmark(held: string | undefined, next: string): string;
27
+ export declare function readD1Bookmarks(header: string): [D1BookmarkName, string][];
28
+ export declare function writeD1Bookmarks(entries: Iterable<readonly [D1BookmarkName, string]>): string;
29
+ /** The bookmark a live-sync frame announces, past the write it rings for. */
30
+ export declare function announcedD1Bookmark(frame: unknown): string | undefined;
31
+ /**
32
+ * Raises the control-plane bookmark a browser's cookie jar (`document`)
33
+ * sends with every request to `bookmark`, so the re-reads a notice sets off
34
+ * are answered by a replica that holds the change it announces. The jar is
35
+ * every tab's, so a newer bookmark is never lowered.
36
+ */
37
+ export declare function raiseD1BookmarkCookie(jar: {
38
+ cookie: string;
39
+ }, bookmark: string): void;
@@ -0,0 +1,40 @@
1
+ /**
2
+ * The redacted ownership view a machine owner rewrites beside its discovery
3
+ * record each time what it owns changes, and never otherwise: `changedAt` is
4
+ * when that last happened, not a heartbeat. Whether the view is still current
5
+ * is whether its writer is still alive, which a reader establishes from the
6
+ * writer's process identity rather than from the file's age.
7
+ *
8
+ * The file name lives here because the writer and the reader are in different
9
+ * products with a boundary between them: the launcher that reads this file
10
+ * cannot import the daemon that writes it, and a filename agreed twice is a
11
+ * filename that drifts once.
12
+ */
13
+ export declare const DAEMON_OWNERSHIP_SNAPSHOT_FILE = "local-daemon-ownership.json";
14
+ /** Readers and writers must resolve the same file even when their data roots have trailing separators. */
15
+ export declare function daemonOwnershipSnapshotPath(dataRoot: string): string;
16
+ /** One owner row as the snapshot carries it: ids, states and generations, never a command. */
17
+ export type DaemonOwnershipRow = {
18
+ id: string;
19
+ kind: string;
20
+ generation: string;
21
+ state: string;
22
+ pins: boolean;
23
+ detail?: string;
24
+ };
25
+ /**
26
+ * What a launcher may rely on in a snapshot it did not write.
27
+ *
28
+ * Both sides validate through this rather than each declaring the shape: the
29
+ * writer is a daemon and the reader is the launcher that cannot import it, so
30
+ * two declarations would be two chances to drift.
31
+ */
32
+ export declare function isDaemonOwnershipSnapshot(value: unknown): value is {
33
+ machineId: string;
34
+ generation: string;
35
+ pid: number;
36
+ revision: string;
37
+ changedAt: number;
38
+ residencyPins: number;
39
+ owners: DaemonOwnershipRow[];
40
+ };
@@ -0,0 +1,24 @@
1
+ /** The declared severities, as the single source for both the type and the parser. */
2
+ declare const RUNTIME_DIAGNOSTIC_SEVERITIES: readonly ["debug", "info", "warn", "error"];
3
+ export type RuntimeDiagnosticSeverity = (typeof RUNTIME_DIAGNOSTIC_SEVERITIES)[number];
4
+ export type RuntimeDiagnostic = {
5
+ code: string;
6
+ message: string;
7
+ severity: RuntimeDiagnosticSeverity;
8
+ source?: string;
9
+ method?: string;
10
+ raw?: unknown;
11
+ details?: Record<string, unknown>;
12
+ };
13
+ export declare function runtimeDiagnostic(input: {
14
+ code: string;
15
+ message: string;
16
+ severity?: RuntimeDiagnosticSeverity;
17
+ source?: string;
18
+ method?: string;
19
+ raw?: unknown;
20
+ details?: Record<string, unknown>;
21
+ }): RuntimeDiagnostic;
22
+ /** Parses an unknown payload into diagnostics, dropping rows that carry no code or message. */
23
+ export declare function normalizeDiagnostics(input: unknown): RuntimeDiagnostic[];
24
+ export {};
@@ -0,0 +1,6 @@
1
+ import type { ElicitationPatternCheck } from "./elicitation-validation";
2
+ /** Worker-only evaluator. Self-contained so Node can serialize trusted code without a worker asset. */
3
+ export declare function evaluateNativeElicitationPatterns(checks: ElicitationPatternCheck[]): {
4
+ code: "invalid_schema" | "invalid_answer";
5
+ message: string;
6
+ } | null;
@@ -0,0 +1,17 @@
1
+ // src/elicitation-pattern-worker.ts
2
+ function evaluateNativeElicitationPatterns(checks) {
3
+ for (const check of checks) {
4
+ let pattern;
5
+ try {
6
+ pattern = new RegExp(check.pattern, "u");
7
+ } catch {
8
+ return { code: "invalid_schema", message: `Invalid pattern for ${check.field}` };
9
+ }
10
+ if (check.value !== undefined && !pattern.test(check.value))
11
+ return { code: "invalid_answer", message: `Invalid value for ${check.field}` };
12
+ }
13
+ return null;
14
+ }
15
+ export {
16
+ evaluateNativeElicitationPatterns
17
+ };
@@ -0,0 +1,23 @@
1
+ import { type ElicitationContent, type ElicitationSchema } from "./elicitation";
2
+ export type ElicitationValidationCode = "invalid_answer" | "invalid_schema" | "validation_timeout" | "validation_unavailable" | "validation_busy" | "validation_cancelled";
3
+ export declare class ElicitationValidationError extends Error {
4
+ readonly code: ElicitationValidationCode;
5
+ constructor(code: ElicitationValidationCode, message: string);
6
+ }
7
+ /** Consent links are displayed without fetching or accepting embedded credentials. */
8
+ export declare function validateElicitationUrl(value: string): void;
9
+ export type ElicitationPatternCheck = {
10
+ field: string;
11
+ pattern: string;
12
+ value?: string;
13
+ };
14
+ export type ElicitationPatternEvaluator = (checks: ElicitationPatternCheck[], signal?: AbortSignal) => Promise<void>;
15
+ export declare const ELICITATION_PATTERN_LIMITS: {
16
+ readonly fields: 64;
17
+ readonly pattern: 4096;
18
+ readonly value: 65536;
19
+ readonly total: 262144;
20
+ };
21
+ export declare function elicitationPatternChecks(schema: ElicitationSchema, content?: ElicitationContent): ElicitationPatternCheck[];
22
+ /** Complete response validation; the evaluator must isolate native regex work. */
23
+ export declare function validateElicitationResponse(schema: ElicitationSchema, value: unknown, evaluate: ElicitationPatternEvaluator, signal?: AbortSignal): Promise<ElicitationContent>;
@@ -0,0 +1,51 @@
1
+ export type ElicitationChoice = {
2
+ const: string;
3
+ title?: string;
4
+ description?: string;
5
+ };
6
+ export type ElicitationContent = Record<string, string | number | boolean | string[]>;
7
+ export type ElicitationField = {
8
+ type: "string" | "number" | "integer" | "boolean" | "array";
9
+ title?: string;
10
+ description?: string;
11
+ default?: unknown;
12
+ enum?: string[];
13
+ oneOf?: ElicitationChoice[];
14
+ items?: {
15
+ type?: "string";
16
+ enum?: string[];
17
+ anyOf?: ElicitationChoice[];
18
+ };
19
+ minLength?: number;
20
+ maxLength?: number;
21
+ minimum?: number;
22
+ maximum?: number;
23
+ minItems?: number;
24
+ maxItems?: number;
25
+ format?: string;
26
+ /** Native ECMAScript constraint evaluated by the asynchronous response validator. */
27
+ pattern?: string | null;
28
+ };
29
+ export type ElicitationSchema = {
30
+ type: "object";
31
+ properties: Record<string, ElicitationField>;
32
+ required?: string[];
33
+ title?: string;
34
+ description?: string;
35
+ _meta?: Record<string, unknown>;
36
+ };
37
+ export type AgentElicitation = {
38
+ agentName: string;
39
+ message: string;
40
+ } & ({
41
+ mode: "form";
42
+ requestedSchema: ElicitationSchema;
43
+ } | {
44
+ mode: "url";
45
+ url: string;
46
+ elicitationId: string;
47
+ });
48
+ export declare function elicitationChoices(field: ElicitationField): ElicitationChoice[] | undefined;
49
+ export declare function readElicitationSchema(input: unknown): ElicitationSchema;
50
+ /** Primitive constraints. Use validateElicitationResponse for complete validation including patterns. */
51
+ export declare function validateElicitationContent(schema: ElicitationSchema, value: unknown): asserts value is ElicitationContent;
package/dist/errors.d.ts CHANGED
@@ -40,4 +40,11 @@ export declare class AgentRuntimeContractError extends Error {
40
40
  readonly detail: AgentRuntimeError;
41
41
  constructor(detail: AgentRuntimeError);
42
42
  }
43
- export declare function assertAgentExecutionBinding(binding: Readonly<AgentExecutionBinding>, expected?: AgentExecutionBindingExpectation): AgentExecutionBinding;
43
+ /** The binding is complete: workspace-scoped and every field a non-empty string. */
44
+ export declare function requireAgentExecutionBinding(binding: Readonly<AgentExecutionBinding>): AgentExecutionBinding;
45
+ /**
46
+ * The binding is complete AND matches the expectation this caller independently
47
+ * holds. `expected` has no default: an expectation copied from the binding
48
+ * itself compares every field to itself and proves nothing.
49
+ */
50
+ export declare function assertAgentExecutionBinding(binding: Readonly<AgentExecutionBinding>, expected: AgentExecutionBindingExpectation): AgentExecutionBinding;
@@ -0,0 +1,19 @@
1
+ /**
2
+ * The position in a runtime's event feed a response was taken at, so a reader
3
+ * can tell whether the live stream it holds covers everything a read did not
4
+ * include. A read answers the position its snapshot is good up to; an event
5
+ * stream answers the position it starts after. The stream covers the read
6
+ * when both come from the same feed and the stream starts no later than the
7
+ * read: nothing then fell between the two.
8
+ *
9
+ * `feed` identifies one runtime process's numbering; a position from another
10
+ * feed is not comparable, so a reader treats the pair as uncovered.
11
+ */
12
+ export declare const EVENT_CURSOR_HEADER = "X-Event-Cursor";
13
+ export type EventCursor = {
14
+ readonly feed: string;
15
+ readonly at: number;
16
+ };
17
+ export declare function formatEventCursor(cursor: EventCursor): string;
18
+ export declare function parseEventCursor(value: string | null | undefined): EventCursor | undefined;
19
+ export declare function eventCursorCovers(streamSince: EventCursor | undefined, readAt: EventCursor | undefined): boolean;