@theokit/sdk 2.19.0 → 2.21.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 (89) hide show
  1. package/CHANGELOG.md +123 -0
  2. package/dist/a2a/index.cjs +611 -274
  3. package/dist/a2a/index.cjs.map +1 -1
  4. package/dist/a2a/index.js +612 -275
  5. package/dist/a2a/index.js.map +1 -1
  6. package/dist/a2a/types.d.cts +7 -0
  7. package/dist/a2a/types.d.ts +7 -0
  8. package/dist/agent-builder.d.ts +2 -1
  9. package/dist/agent-generate.d.ts +12 -0
  10. package/dist/client/index.cjs.map +1 -1
  11. package/dist/client/index.d.cts +5 -0
  12. package/dist/client/index.d.ts +5 -0
  13. package/dist/client/index.js.map +1 -1
  14. package/dist/client/theokit-client.d.cts +6 -0
  15. package/dist/client/theokit-client.d.ts +6 -0
  16. package/dist/client/types.d.cts +2 -0
  17. package/dist/client/types.d.ts +2 -0
  18. package/dist/create-skill.d.ts +29 -0
  19. package/dist/{cron-D_wK1S-0.d.cts → cron-YrmsszEN.d.cts} +110 -3
  20. package/dist/{cron-Cep07kTz.d.ts → cron-dpvtRoro.d.ts} +110 -3
  21. package/dist/cron.cjs +660 -370
  22. package/dist/cron.cjs.map +1 -1
  23. package/dist/cron.d.cts +3 -2
  24. package/dist/cron.d.ts +3 -2
  25. package/dist/cron.js +661 -371
  26. package/dist/cron.js.map +1 -1
  27. package/dist/{errors-5lj1EWgs.d.ts → errors-C4vZPqXf.d.ts} +2 -2
  28. package/dist/{errors-CE-lMBi2.d.cts → errors-DrcpYVfZ.d.cts} +2 -2
  29. package/dist/errors.d.cts +3 -2
  30. package/dist/eval.cjs +660 -370
  31. package/dist/eval.cjs.map +1 -1
  32. package/dist/eval.js +660 -370
  33. package/dist/eval.js.map +1 -1
  34. package/dist/generate-object.d.ts +19 -4
  35. package/dist/index.cjs +867 -371
  36. package/dist/index.cjs.map +1 -1
  37. package/dist/index.d.cts +274 -16
  38. package/dist/index.d.ts +274 -16
  39. package/dist/index.js +863 -373
  40. package/dist/index.js.map +1 -1
  41. package/dist/internal/agent-loop/loop-types.d.ts +2 -0
  42. package/dist/internal/agent-loop/tool-result-guard.d.ts +1 -0
  43. package/dist/internal/llm/tool-result-content.d.ts +40 -0
  44. package/dist/internal/llm/types.d.ts +6 -1
  45. package/dist/internal/persistence/conversation-storage-fs.d.cts +3 -1
  46. package/dist/internal/persistence/conversation-storage-fs.d.ts +3 -1
  47. package/dist/internal/persistence/conversation-storage-memory.d.cts +3 -1
  48. package/dist/internal/persistence/conversation-storage-memory.d.ts +3 -1
  49. package/dist/internal/persistence/session-meta.d.cts +13 -0
  50. package/dist/internal/persistence/session-meta.d.ts +13 -0
  51. package/dist/internal/runtime/model-selection.d.ts +14 -0
  52. package/dist/internal/structured-output-helpers.d.ts +1 -1
  53. package/dist/permission-engine.d.ts +32 -1
  54. package/dist/{run-BgfBWX-z.d.cts → run-BMo8yRwK.d.cts} +262 -19
  55. package/dist/{run-BgfBWX-z.d.ts → run-BMo8yRwK.d.ts} +262 -19
  56. package/dist/stream-object.d.ts +2 -1
  57. package/dist/tool-error.d.ts +30 -0
  58. package/dist/types/agent-prims.d.ts +10 -8
  59. package/dist/types/agent.d.ts +22 -1
  60. package/dist/types/content-blocks.d.ts +47 -0
  61. package/dist/types/conversation-storage.d.ts +38 -0
  62. package/dist/types/index.d.ts +1 -0
  63. package/dist/types/messages.d.ts +2 -9
  64. package/dist/types/run-events.d.ts +84 -0
  65. package/dist/types/run.d.ts +115 -1
  66. package/dist/types/session.d.ts +99 -0
  67. package/dist/types/workflow.d.ts +7 -0
  68. package/dist/workflow.cjs +7 -2
  69. package/dist/workflow.cjs.map +1 -1
  70. package/dist/workflow.d.cts +2 -0
  71. package/dist/workflow.d.ts +2 -0
  72. package/dist/workflow.js +7 -2
  73. package/dist/workflow.js.map +1 -1
  74. package/package.json +3 -23
  75. package/dist/internal/observability/context.d.cts +0 -23
  76. package/dist/internal/observability/context.d.ts +0 -23
  77. package/dist/internal/observability/index.cjs +0 -38
  78. package/dist/internal/observability/index.cjs.map +0 -1
  79. package/dist/internal/observability/index.d.cts +0 -8
  80. package/dist/internal/observability/index.d.ts +0 -8
  81. package/dist/internal/observability/index.js +0 -33
  82. package/dist/internal/observability/index.js.map +0 -1
  83. package/dist/internal/plugins/index.cjs +0 -363
  84. package/dist/internal/plugins/index.cjs.map +0 -1
  85. package/dist/internal/plugins/index.js +0 -357
  86. package/dist/internal/plugins/index.js.map +0 -1
  87. package/dist/internal/workflow/index.d.ts +0 -12
  88. package/dist/server/adapter/index.d.cts +0 -8
  89. package/dist/server/adapter/index.d.ts +0 -8
@@ -1,6 +1,8 @@
1
1
  import type { ConversationTurn } from "../../types/conversation.js";
2
2
  import type { SDKMessage } from "../../types/messages.js";
3
3
  import type { RunStatus } from "../../types/run.js";
4
+ /** SE7 — what a custom tool handler may return: a string or structured content blocks. */
5
+ export type ToolHandlerResult = string | import("../../types/content-blocks.js").ToolResultContentBlock[];
4
6
  export interface AgentLoopOutput {
5
7
  events: SDKMessage[];
6
8
  finalStatus: RunStatus;
@@ -11,6 +11,7 @@
11
11
  *
12
12
  * @internal
13
13
  */
14
+ import type { LlmContentPart } from "../llm/types.js";
14
15
  export interface ToolResultGuardOptions {
15
16
  /** Wrap tool-result content in explicit data boundaries (spotlighting). */
16
17
  delimit?: boolean;
@@ -0,0 +1,40 @@
1
+ /**
2
+ * SE7 — provider-agnostic helpers for structured tool-result content
3
+ * ({@link ToolResultContentBlock}). Named by CAPABILITY, not by provider:
4
+ *
5
+ * - `toBlockToolResultContent` — for a wire that ACCEPTS content blocks.
6
+ * - `toStringToolResultContent` — for a string-only wire (fail-fast on an image).
7
+ * - `renderToolResultContentText` — map the text parts through a fn (for the guard).
8
+ *
9
+ * @internal
10
+ */
11
+ import type { ToolResultContentBlock } from "../../types/content-blocks.js";
12
+ /**
13
+ * For a block-capable provider wire: pass a string through unchanged, or forward
14
+ * the structured blocks as-is (text + image).
15
+ *
16
+ * This is an INTENTIONAL identity: `ToolResultContentBlock` is defined to be
17
+ * exactly the on-wire content-block shape that block-capable providers accept
18
+ * for a tool result — `{ type: "text", text }` and
19
+ * `{ type: "image", source: { type: "base64", media_type, data } }`. Because the
20
+ * SDK type already IS the wire shape, no transformation is needed; this function
21
+ * names that contract at the call site (and is the single seam to add a mapping
22
+ * later, if a block-capable wire ever diverges from this shape). Do NOT add
23
+ * SDK-internal fields to `ToolResultContentBlock` without updating this seam —
24
+ * they would otherwise be forwarded verbatim onto the wire.
25
+ */
26
+ export declare function toBlockToolResultContent(content: string | ToolResultContentBlock[]): string | ToolResultContentBlock[];
27
+ /**
28
+ * For a string-only provider wire: pass a string through; flatten text-only
29
+ * blocks to a newline-joined string; **fail fast** with a typed
30
+ * {@link ConfigurationError} when an image block is present — that provider
31
+ * cannot carry an image in a tool result, and silently dropping it would hand
32
+ * the model a lie (per error-handling policy).
33
+ */
34
+ export declare function toStringToolResultContent(content: string | ToolResultContentBlock[], providerName: string): string;
35
+ /**
36
+ * Apply `fn` to the text of a tool-result content (both the string form and the
37
+ * text blocks of the structured form); image blocks pass through untouched.
38
+ * Used by the tool-result guard so redaction/delimiting still covers text.
39
+ */
40
+ export declare function renderToolResultContentText(content: string | ToolResultContentBlock[], fn: (text: string) => string): string | ToolResultContentBlock[];
@@ -19,7 +19,12 @@ export interface LlmToolCallPart {
19
19
  export interface LlmToolResultPart {
20
20
  type: "tool_result";
21
21
  toolUseId: string;
22
- content: string;
22
+ /**
23
+ * SE7 — a string (the common case) OR structured content blocks (text +
24
+ * image). Block-capable provider wires forward blocks natively; string-only
25
+ * wires flatten text and fail fast on an image (`toStringToolResultContent`).
26
+ */
27
+ content: string | import("../../types/content-blocks.js").ToolResultContentBlock[];
23
28
  isError?: boolean;
24
29
  }
25
30
  export type LlmContentPart = LlmTextPart | LlmToolCallPart | LlmToolResultPart;
@@ -16,7 +16,7 @@
16
16
  *
17
17
  * @public
18
18
  */
19
- import type { ConversationStorageAdapter, StoredMessage } from "../../types/conversation-storage.js";
19
+ import type { ConversationStorageAdapter, SessionMeta, SessionMetaPatch, StoredMessage } from "../../types/conversation-storage.js";
20
20
  export interface FileSystemConversationStorageOptions {
21
21
  /** Root directory under which `.theokit/agents/<id>/` lives. Defaults to `process.cwd()`. */
22
22
  root?: string;
@@ -39,5 +39,7 @@ export declare class FileSystemConversationStorage implements ConversationStorag
39
39
  limit?: number;
40
40
  }): Promise<readonly string[]>;
41
41
  compact(conversationId: string, maxTurns: number): Promise<void>;
42
+ getSessionMeta(conversationId: string): Promise<SessionMeta | undefined>;
43
+ setSessionMeta(conversationId: string, patch: SessionMetaPatch): Promise<void>;
42
44
  dispose(): Promise<void>;
43
45
  }
@@ -16,7 +16,7 @@
16
16
  *
17
17
  * @public
18
18
  */
19
- import type { ConversationStorageAdapter, StoredMessage } from "../../types/conversation-storage.js";
19
+ import type { ConversationStorageAdapter, SessionMeta, SessionMetaPatch, StoredMessage } from "../../types/conversation-storage.js";
20
20
  export interface FileSystemConversationStorageOptions {
21
21
  /** Root directory under which `.theokit/agents/<id>/` lives. Defaults to `process.cwd()`. */
22
22
  root?: string;
@@ -39,5 +39,7 @@ export declare class FileSystemConversationStorage implements ConversationStorag
39
39
  limit?: number;
40
40
  }): Promise<readonly string[]>;
41
41
  compact(conversationId: string, maxTurns: number): Promise<void>;
42
+ getSessionMeta(conversationId: string): Promise<SessionMeta | undefined>;
43
+ setSessionMeta(conversationId: string, patch: SessionMetaPatch): Promise<void>;
42
44
  dispose(): Promise<void>;
43
45
  }
@@ -11,7 +11,7 @@
11
11
  *
12
12
  * @public
13
13
  */
14
- import type { ConversationStorageAdapter, StoredMessage } from "../../types/conversation-storage.js";
14
+ import type { ConversationStorageAdapter, SessionMeta, SessionMetaPatch, StoredMessage } from "../../types/conversation-storage.js";
15
15
  export declare class InMemoryConversationStorage implements ConversationStorageAdapter {
16
16
  #private;
17
17
  getMessages(conversationId: string, opts?: {
@@ -26,5 +26,7 @@ export declare class InMemoryConversationStorage implements ConversationStorageA
26
26
  listConversationIds(opts?: {
27
27
  limit?: number;
28
28
  }): Promise<readonly string[]>;
29
+ getSessionMeta(conversationId: string): Promise<SessionMeta | undefined>;
30
+ setSessionMeta(conversationId: string, patch: SessionMetaPatch): Promise<void>;
29
31
  dispose(): Promise<void>;
30
32
  }
@@ -11,7 +11,7 @@
11
11
  *
12
12
  * @public
13
13
  */
14
- import type { ConversationStorageAdapter, StoredMessage } from "../../types/conversation-storage.js";
14
+ import type { ConversationStorageAdapter, SessionMeta, SessionMetaPatch, StoredMessage } from "../../types/conversation-storage.js";
15
15
  export declare class InMemoryConversationStorage implements ConversationStorageAdapter {
16
16
  #private;
17
17
  getMessages(conversationId: string, opts?: {
@@ -26,5 +26,7 @@ export declare class InMemoryConversationStorage implements ConversationStorageA
26
26
  listConversationIds(opts?: {
27
27
  limit?: number;
28
28
  }): Promise<readonly string[]>;
29
+ getSessionMeta(conversationId: string): Promise<SessionMeta | undefined>;
30
+ setSessionMeta(conversationId: string, patch: SessionMetaPatch): Promise<void>;
29
31
  dispose(): Promise<void>;
30
32
  }
@@ -0,0 +1,13 @@
1
+ /**
2
+ * SE4 — shared merge logic for {@link SessionMeta} + {@link SessionMetaPatch},
3
+ * used identically by every {@link ConversationStorageAdapter} that persists
4
+ * session metadata (FS sidecar + in-memory). Single source of truth for the
5
+ * patch semantics: an omitted field is unchanged; a `null` field CLEARS it; a
6
+ * string SETS it.
7
+ *
8
+ * @internal
9
+ */
10
+ /** Apply a patch to session metadata, returning a fresh object. */
11
+ export declare function applyMetaPatch(current: SessionMeta, patch: SessionMetaPatch): SessionMeta;
12
+ /** Read a raw parsed sidecar object into a validated {@link SessionMeta} (string fields only). */
13
+ export declare function coerceSessionMeta(raw: unknown): SessionMeta | undefined;
@@ -0,0 +1,13 @@
1
+ /**
2
+ * SE4 — shared merge logic for {@link SessionMeta} + {@link SessionMetaPatch},
3
+ * used identically by every {@link ConversationStorageAdapter} that persists
4
+ * session metadata (FS sidecar + in-memory). Single source of truth for the
5
+ * patch semantics: an omitted field is unchanged; a `null` field CLEARS it; a
6
+ * string SETS it.
7
+ *
8
+ * @internal
9
+ */
10
+ /** Apply a patch to session metadata, returning a fresh object. */
11
+ export declare function applyMetaPatch(current: SessionMeta, patch: SessionMetaPatch): SessionMeta;
12
+ /** Read a raw parsed sidecar object into a validated {@link SessionMeta} (string fields only). */
13
+ export declare function coerceSessionMeta(raw: unknown): SessionMeta | undefined;
@@ -0,0 +1,14 @@
1
+ /**
2
+ * SE8 — boundary normalizer for the model bare-string shorthand.
3
+ *
4
+ * `AgentOptions.model` and `SendOptions.model` accept `string | ModelSelection`
5
+ * (matching every peer SDK's `"provider/model"` shorthand). This is the ONE seam
6
+ * that maps a bare string to `{ id }`, so all downstream code keeps seeing a
7
+ * `ModelSelection`. `"inherit"` is an `AgentOptions`-only sentinel handled inline
8
+ * at the create seam — NOT here — so this helper stays `string | ModelSelection`.
9
+ *
10
+ * @internal
11
+ */
12
+ import type { ModelSelection } from "../../types/agent-prims.js";
13
+ /** Normalize a model selection: a bare string id → `{ id }`; object/undefined pass through. */
14
+ export declare function normalizeModel(m: string | ModelSelection | undefined): ModelSelection | undefined;
@@ -18,7 +18,7 @@ export declare function makeOutputTool(jsonSchema: Record<string, unknown>, onCa
18
18
  * model + local + tools[output] + systemPrompt + apiKey.
19
19
  */
20
20
  export declare function buildTransientAgentOptions(params: {
21
- model: ModelSelection;
21
+ model: string | ModelSelection;
22
22
  local: LocalOptions;
23
23
  outputTool: CustomTool;
24
24
  systemPrompt?: string;
@@ -8,6 +8,37 @@
8
8
  * the previous fail-open behavior with `{ defaultAction: "allow" }`.
9
9
  */
10
10
  export type PermissionAction = "allow" | "deny" | "ask";
11
+ /**
12
+ * SE1 — a per-run permission MODE that adjusts the rule-engine verdict globally.
13
+ * A PURE post-processor of the verdict (no tool-safety metadata needed, so it fits
14
+ * a bring-your-own-tools runtime). Grounded in OpenCode (plan agent = deny-all,
15
+ * `dangerously-skip-permissions`) + Codex (`AskForApproval`: `OnRequest` default,
16
+ * `Never`, `UnlessTrusted`). See {@link applyMode} for the exact table.
17
+ *
18
+ * - `default` — verdict as-is (rules decide; unmatched ⇒ `ask`, fail-closed).
19
+ * - `plan` — read-only: `allow` rules pass, everything else ⇒ `deny` (mutations blocked).
20
+ * NOTE: `plan` gates on the resolved verdict, so an engine configured with
21
+ * `{ defaultAction: "allow" }` still yields `allow` for UNMATCHED calls under
22
+ * `plan` — pair `plan` with the default fail-closed engine (`defaultAction: "ask"`)
23
+ * for full read-only behavior.
24
+ * - `acceptEdits` — auto-approve the UNMATCHED verdict, but STILL honor an explicit
25
+ * `ask` rule (a caller gates a risky tool with an ask rule). Codex `UnlessTrusted`.
26
+ * - `bypass` — everything ⇒ `allow` EXCEPT an explicit `deny` rule. Never asks.
27
+ * OpenCode `dangerously-skip-permissions` / Codex `Never`.
28
+ */
29
+ export type PermissionMode = "default" | "plan" | "acceptEdits" | "bypass";
30
+ /**
31
+ * SE1 — apply a {@link PermissionMode} to a rule-engine verdict. Pure.
32
+ *
33
+ * `explicit` is `true` when the verdict came from a rule that matched by name (and
34
+ * args), `false` when it is the fail-closed default for an unmatched call. The flag
35
+ * is load-bearing for `acceptEdits`, which auto-approves the unmatched default but
36
+ * keeps honoring an explicit `ask` rule (unlike `bypass`, which allows even that).
37
+ *
38
+ * INVARIANT (both OpenCode + Codex): an explicit `deny` is immune to EVERY
39
+ * auto-approve mode — `bypass`/`acceptEdits` never un-deny.
40
+ */
41
+ export declare function applyMode(verdict: PermissionAction, mode: PermissionMode, explicit: boolean): PermissionAction;
11
42
  /**
12
43
  * #55 — an argument matcher. A rule with `args` gates on the tool's argument
13
44
  * VALUES, not just its name: an exact string, a RegExp (tested against the
@@ -50,5 +81,5 @@ export declare class PermissionEngine {
50
81
  * argument values, so the same tool name can resolve to different actions
51
82
  * depending on what it is asked to do.
52
83
  */
53
- evaluate(toolName: string, args?: Record<string, unknown>): PermissionAction;
84
+ evaluate(toolName: string, args?: Record<string, unknown>, mode?: PermissionMode): PermissionAction;
54
85
  }
@@ -1,3 +1,53 @@
1
+ import * as zod from 'zod';
2
+
3
+ /**
4
+ * Leaf module for content-block types shared by `messages.ts` (assistant/user
5
+ * content) and `agent-prims.ts` (`CustomTool` handler results). Kept
6
+ * import-free so both can depend on it WITHOUT the `agent-prims ↔ messages`
7
+ * cycle (#7).
8
+ *
9
+ * @public
10
+ */
11
+ /**
12
+ * Plain text content block emitted by the assistant or user, or returned by a
13
+ * tool.
14
+ *
15
+ * @public
16
+ */
17
+ interface TextBlock {
18
+ type: "text";
19
+ text: string;
20
+ }
21
+ /**
22
+ * SE7 — a base64-encoded image block a tool can hand back as (part of) its
23
+ * result or its `ToolError`. `media_type` is a MIME type (e.g. `"image/png"`);
24
+ * `data` is the base64 payload without a data-URL prefix.
25
+ *
26
+ * Note: when a tool builds this from model- or user-influenced input, treat
27
+ * `media_type` as UNTRUSTED — validate/allow-list it before rendering it in a
28
+ * log or UI (it could carry newlines / control chars). The SDK only forwards it
29
+ * (JSON-serialized onto the wire) and never executes or path-joins it.
30
+ *
31
+ * @public
32
+ */
33
+ interface ImageBlock {
34
+ type: "image";
35
+ source: {
36
+ type: "base64";
37
+ media_type: string;
38
+ data: string;
39
+ };
40
+ }
41
+ /**
42
+ * SE7 — structured content a tool result may carry: text and/or images. A tool
43
+ * `handler` may return this (success) and a `ToolError` may carry it (failure).
44
+ * Block-capable provider wires forward it natively; string-only provider wires
45
+ * flatten text and fail fast on an image.
46
+ *
47
+ * @public
48
+ */
49
+ type ToolResultContentBlock = TextBlock | ImageBlock;
50
+
1
51
  /**
2
52
  * #57 — content-level defense for tool results before they reach the LLM.
3
53
  *
@@ -11,6 +61,7 @@
11
61
  *
12
62
  * @internal
13
63
  */
64
+
14
65
  interface ToolResultGuardOptions {
15
66
  /** Wrap tool-result content in explicit data boundaries (spotlighting). */
16
67
  delimit?: boolean;
@@ -18,6 +69,91 @@ interface ToolResultGuardOptions {
18
69
  redactPii?: boolean;
19
70
  }
20
71
 
72
+ /**
73
+ * SE2 — typed runtime EVENT stream, ADDITIVE to the `SDKMessage` content stream.
74
+ *
75
+ * `Run.stream()` yields `SDKMessage`s (the conversation content). `RunEvent`s are
76
+ * out-of-band runtime-OBSERVABILITY signals — the model's content is unaffected —
77
+ * delivered opt-in via `SendOptions.onRunEvent`. Discriminate on `type`. Mirrors
78
+ * the Anthropic `SDKMessage`-union approach (rate-limit, permission-denied, task
79
+ * lifecycle, compaction boundary).
80
+ *
81
+ * The union is the forward-compatible CONTRACT (discriminate exhaustively). As of
82
+ * SE2 the runtime EMITS `tool_progress` and `permission_denied` end-to-end (from
83
+ * the agent-loop tool-dispatch seam). `rate_limit`, `task_*`, and `compact_boundary`
84
+ * are part of the contract; their emission is wired incrementally as the sink is
85
+ * threaded into the LLM-client retry / task / session-compaction subsystems (they
86
+ * live below the loop). A consumer switching on `type` is future-proof either way.
87
+ *
88
+ * @public
89
+ */
90
+ type RunEvent = RunToolProgressEvent | RunRateLimitEvent | RunPermissionDeniedEvent | RunTaskStartedEvent | RunTaskUpdatedEvent | RunTaskCompletedEvent | RunCompactBoundaryEvent;
91
+ /** A tool call is being dispatched (before its result). */
92
+ interface RunToolProgressEvent {
93
+ readonly type: "tool_progress";
94
+ readonly toolName: string;
95
+ readonly toolCallId: string;
96
+ }
97
+ /** The provider returned a rate-limit (HTTP 429); the loop will back off + retry. */
98
+ interface RunRateLimitEvent {
99
+ readonly type: "rate_limit";
100
+ /** Retry attempt number (1-based) about to be delayed. */
101
+ readonly attempt: number;
102
+ /** Delay in ms before the retry, when the provider/policy supplied one. */
103
+ readonly retryAfterMs?: number;
104
+ }
105
+ /**
106
+ * A tool call was DENIED before dispatch — by the permission gate/plugin (SE1),
107
+ * an operator file-hook `preToolUse`, or the fork tool-whitelist. `source`
108
+ * discriminates which. `toolCallId` joins the event to the tool-call log.
109
+ */
110
+ interface RunPermissionDeniedEvent {
111
+ readonly type: "permission_denied";
112
+ readonly toolName: string;
113
+ readonly toolCallId: string;
114
+ /** Which layer blocked the call. */
115
+ readonly source: "plugin" | "file_hook" | "fork_whitelist";
116
+ /** The rejection message surfaced to the model. */
117
+ readonly message: string;
118
+ }
119
+ /** A background task/subagent started. */
120
+ interface RunTaskStartedEvent {
121
+ readonly type: "task_started";
122
+ readonly taskId: string;
123
+ readonly description?: string;
124
+ }
125
+ /** A background task/subagent changed state. */
126
+ interface RunTaskUpdatedEvent {
127
+ readonly type: "task_updated";
128
+ readonly taskId: string;
129
+ readonly status: string;
130
+ }
131
+ /** A background task/subagent finished. */
132
+ interface RunTaskCompletedEvent {
133
+ readonly type: "task_completed";
134
+ readonly taskId: string;
135
+ readonly status: "completed" | "failed" | "stopped";
136
+ }
137
+ /** The conversation crossed a compaction boundary (history was summarized). */
138
+ interface RunCompactBoundaryEvent {
139
+ readonly type: "compact_boundary";
140
+ readonly trigger: "manual" | "auto";
141
+ /** Token count before compaction, when known. */
142
+ readonly preTokens?: number;
143
+ }
144
+ /**
145
+ * SE2 — the opt-in sink for {@link RunEvent}s. Supplied via `SendOptions.onRunEvent`.
146
+ * Synchronous + best-effort: a throwing sink must never break the run (the emitter
147
+ * try-catches it), so keep it fast (push to a queue, don't await).
148
+ */
149
+ type RunEventSink = (event: RunEvent) => void;
150
+ /**
151
+ * SE2 — emit a {@link RunEvent} to an optional sink, swallowing any sink error so
152
+ * observability can never break the run (fail-safe, mirrors the EventBus EC-2
153
+ * contract). No-op when the sink is absent.
154
+ */
155
+ declare function emitRunEvent(sink: RunEventSink | undefined, event: RunEvent): void;
156
+
21
157
  /**
22
158
  * Type-leaf — primitives shared between `agent.ts`, `run.ts`, and
23
159
  * `messages.ts`. Extracted to break LOW type-only cycles #5 and #7
@@ -73,18 +209,20 @@ interface CustomTool {
73
209
  inputSchema: Record<string, unknown>;
74
210
  /**
75
211
  * Local handler invoked when the model emits `tool_use` for this tool.
76
- * Returns a string (becomes the `tool_result.content` surfaced back to the
77
- * model). Throws SDK converts to `tool_result` with `isError: true` and
78
- * the error `message` as content. #65 an optional 2nd `ToolContext`
79
- * argument carries the run's `AbortSignal`; single-argument handlers are
80
- * unaffected. M7the same `ctx` also carries an optional user `context`
81
- * (provided once via `SendOptions.context`), so shared config like a
82
- * `projectRoot` is read by every tool instead of baked into each factory.
212
+ * Returns a string OR structured content blocks (SE7 text + image, e.g. a
213
+ * screenshot) that become the `tool_result.content` surfaced back to the
214
+ * model. Throws SDK converts to `tool_result` with `isError: true` and the
215
+ * error `message` as content; throw a `ToolError` to carry a clean message or
216
+ * multimodal error content. #65 — an optional 2nd `ToolContext` argument
217
+ * carries the run's `AbortSignal`; single-argument handlers are unaffected. M7
218
+ * — the same `ctx` also carries an optional user `context` (provided once via
219
+ * `SendOptions.context`), so shared config like a `projectRoot` is read by
220
+ * every tool instead of baked into each factory.
83
221
  */
84
222
  handler: (input: Record<string, unknown>, ctx?: {
85
223
  signal?: AbortSignal;
86
224
  context?: unknown;
87
- }) => string | Promise<string>;
225
+ }) => string | ToolResultContentBlock[] | Promise<string | ToolResultContentBlock[]>;
88
226
  }
89
227
 
90
228
  /**
@@ -441,15 +579,6 @@ type McpHttpServerConfig = {
441
579
  */
442
580
  type McpServerConfig = McpStdioServerConfig | McpHttpServerConfig;
443
581
 
444
- /**
445
- * Plain text content block emitted by the assistant or user.
446
- *
447
- * @public
448
- */
449
- interface TextBlock {
450
- type: "text";
451
- text: string;
452
- }
453
582
  /**
454
583
  * Tool invocation block emitted by the assistant.
455
584
  *
@@ -685,6 +814,49 @@ interface RunGitInfo {
685
814
  prUrl?: string;
686
815
  }>;
687
816
  }
817
+ /**
818
+ * SE3 — provenance of the turn that produced a run: WHO triggered it. Stamped in
819
+ * the multi-agent path (Squad / a2a / handoff / background-delegation) and
820
+ * forwarded onto {@link RunResult.origin} — so consumers can attribute/route
821
+ * turns by their trigger. Metadata-only; discriminate on `kind`. Mirrors the
822
+ * Anthropic Agent SDK's `origin` shape.
823
+ *
824
+ * Encoding note (distinct from absence): an ABSENT origin (`undefined`) means the
825
+ * provenance was NOT stamped — the default for a plain `agent.send()`. The explicit
826
+ * `{ kind: "human" }` is a positive marker a HOST stamps to say "this turn is
827
+ * definitely from a human" (e.g. to distinguish a real user message from an
828
+ * un-attributed one in an audit UI). The two are not interchangeable: `undefined`
829
+ * = unknown/unstamped; `{ kind: "human" }` = explicitly human. Consumers writing an
830
+ * exhaustive `switch (origin?.kind)` therefore handle `undefined` (unstamped) and
831
+ * `"human"` (explicit) as separate, meaningful cases.
832
+ *
833
+ * @public
834
+ */
835
+ type MessageOrigin =
836
+ /** Explicitly a human-triggered turn — a positive marker a host stamps (NOT the
837
+ * same as an absent/unstamped origin, which is `undefined`). */
838
+ {
839
+ readonly kind: "human";
840
+ }
841
+ /** Another agent (a Squad peer or an a2a sender) triggered this turn. */
842
+ | {
843
+ readonly kind: "peer";
844
+ readonly from: string;
845
+ }
846
+ /** A background task's completion re-entered the agent as a follow-up turn. */
847
+ | {
848
+ readonly kind: "task-notification";
849
+ }
850
+ /** A delegating/handoff coordinator triggered this turn. `from` is the coordinator's
851
+ * id when known, omitted for an anonymous coordinator. */
852
+ | {
853
+ readonly kind: "coordinator";
854
+ readonly from?: string;
855
+ }
856
+ /** The loop's continuation driver re-sent to continue truncated work. */
857
+ | {
858
+ readonly kind: "auto-continuation";
859
+ };
688
860
  /**
689
861
  * Terminal result of a {@link Run}.
690
862
  *
@@ -697,6 +869,15 @@ interface RunResult {
697
869
  model?: ModelSelection;
698
870
  durationMs?: number;
699
871
  git?: RunGitInfo;
872
+ /**
873
+ * SE3 — provenance forwarded from {@link SendOptions.origin}: who triggered
874
+ * this turn (human / peer / task-notification / coordinator / auto-continuation).
875
+ * `undefined` means the provenance was not stamped (a plain `agent.send()`).
876
+ * Metadata-only — never affects routing.
877
+ *
878
+ * @public
879
+ */
880
+ origin?: MessageOrigin;
700
881
  /**
701
882
  * Structured error detail, populated when `status === "error"`. Surfaces
702
883
  * the diagnostic that emit-error-event pushes into the stream so callers
@@ -871,7 +1052,27 @@ interface SDKUserMessage {
871
1052
  * @public
872
1053
  */
873
1054
  interface SendOptions {
874
- model?: ModelSelection;
1055
+ /**
1056
+ * Per-send model override. SE8 — accepts a bare-string id shorthand
1057
+ * (`"openai/gpt-4o-mini"`, normalized to `{ id }`) OR a {@link ModelSelection}
1058
+ * object (use the object form to pass `params`).
1059
+ */
1060
+ model?: string | ModelSelection;
1061
+ /**
1062
+ * SE3 — provenance of this turn (who triggered it). Stamped by the multi-agent
1063
+ * path (Squad peer, a2a sender, coordinator/handoff, background task-notification)
1064
+ * and forwarded onto {@link RunResult.origin}. Metadata-only — the value never
1065
+ * changes routing or dispatch. Omit to leave the turn un-attributed; a host may
1066
+ * pass `{ kind: "human" }` to positively mark a human turn.
1067
+ */
1068
+ origin?: MessageOrigin;
1069
+ /**
1070
+ * SE2 — opt-in typed runtime-EVENT sink. Receives out-of-band `RunEvent`s
1071
+ * (permission_denied, tool_progress, rate_limit, task_*, compact_boundary) for
1072
+ * observability, ADDITIVE to the `SDKMessage` content stream. Best-effort: a
1073
+ * throwing sink never breaks the run. Discriminate on `event.type`.
1074
+ */
1075
+ onRunEvent?: RunEventSink;
875
1076
  /**
876
1077
  * Doom-loop guard config. The loop stops (with `terminal: "no_progress"`, `RunResult.stoppedByDoomLoop`)
877
1078
  * when the model repeats IDENTICAL tool calls to the hard threshold. On by default with generous
@@ -1009,5 +1210,47 @@ interface Run {
1009
1210
  /** Subscribe to status changes. Returns an unsubscribe function. */
1010
1211
  onDidChangeStatus(listener: (status: RunStatus) => void): () => void;
1011
1212
  }
1213
+ /**
1214
+ * SE9 — options for the integrated structured-output method `agent.generate`: the
1215
+ * {@link SendOptions} that drive the tool loop (phase 1) plus the required `output`
1216
+ * Zod schema and structuring knobs (phase 2). Co-located with `SendOptions` /
1217
+ * `RunResult` (which they extend/use) so the public `SDKAgent` interface does not
1218
+ * import the runtime `agent-generate` module (breaks the type cycle).
1219
+ *
1220
+ * @public
1221
+ */
1222
+ interface GenerateOptions<T extends zod.ZodType> extends SendOptions {
1223
+ /** Zod schema the final answer is coerced into (the structuring contract). */
1224
+ output: T;
1225
+ /** Retry budget on the structuring phase's parse-failures (reused from generateObject). Default 1. */
1226
+ maxRetries?: number;
1227
+ /**
1228
+ * What the STRUCTURING phase (phase 2) does when the model's output still fails
1229
+ * Zod validation after retries. Default `"throw"`. `"return-partial"` / `"return-raw"`
1230
+ * salvage the object; the salvaged/raw value is in {@link GenerateRunResult.raw}
1231
+ * (the pre-parse structuring input) — NOT the phase-1 text answer, which is in
1232
+ * `result.result`.
1233
+ */
1234
+ errorStrategy?: "throw" | "return-partial" | "return-raw";
1235
+ }
1236
+ /**
1237
+ * SE9 — result of `agent.generate`: the validated typed object plus the underlying
1238
+ * tool-loop {@link RunResult} (status / usage / model) and the raw pre-parse input.
1239
+ *
1240
+ * @public
1241
+ */
1242
+ interface GenerateRunResult<O> {
1243
+ /** The validated object — inferred type from the `output` schema. */
1244
+ object: O;
1245
+ /** The underlying tool-loop run (phase 1). */
1246
+ result: RunResult;
1247
+ /** Raw model input to the synthetic `output` tool, before the Zod parse. */
1248
+ raw: unknown;
1249
+ /** Combined token usage of the structuring phase. */
1250
+ usage: {
1251
+ inputTokens: number;
1252
+ outputTokens: number;
1253
+ };
1254
+ }
1012
1255
 
1013
- export type { ThinkingDeltaUpdate as $, AgentConversationTurn as A, SDKTaskMessage as B, CustomTool as C, DoomLoopThresholds as D, SDKThinkingMessage as E, SDKToolUseMessage as F, SDKUserMessage as G, SDKUserMessageEvent as H, InteractionUpdate as I, SendOptions as J, ShellCommand as K, ShellConversationTurn as L, ModelSelection as M, ShellOutput as N, ShellOutputDeltaUpdate as O, PartialToolCallUpdate as P, StepCompletedUpdate as Q, RunResult as R, SDKMessage as S, StepStartedUpdate as T, StreamToCompletionResult as U, SummaryCompletedUpdate as V, SummaryStartedUpdate as W, SummaryUpdate as X, TextBlock as Y, TextDeltaUpdate as Z, ThinkingCompletedUpdate as _, McpServerConfig as a, ThinkingMessage as a0, TokenDeltaUpdate as a1, TokenUsage as a2, ToolCall as a3, ToolCallCompletedUpdate as a4, ToolCallStartedUpdate as a5, ToolResult as a6, ToolResultGuardOptions as a7, ToolUseBlock as a8, TurnEndedUpdate as a9, UserMessage as aa, UserMessageAppendedUpdate as ab, Run as b, AssistantMessage as c, ConversationStep as d, ConversationTurn as e, CostBreakdown as f, CostSource as g, CostStatus as h, McpAuthConfig as i, McpHttpServerConfig as j, McpOAuthConfig as k, McpStdioServerConfig as l, ModelParameterValue as m, RunErrorDetail as n, RunGitInfo as o, RunOperation as p, RunStatus as q, RunToCompletionOptions as r, RunToCompletionResult as s, SDKAssistantMessage as t, SDKImage as u, SDKImageDimension as v, SDKObjectDelta as w, SDKRequestMessage as x, SDKStatusMessage as y, SDKSystemMessage as z };
1256
+ export { type SendOptions as $, type AgentConversationTurn as A, type RunTaskStartedEvent as B, type CustomTool as C, type DoomLoopThresholds as D, type RunTaskUpdatedEvent as E, type RunToCompletionOptions as F, type GenerateOptions as G, type RunToCompletionResult as H, type ImageBlock as I, type RunToolProgressEvent as J, type SDKAssistantMessage as K, type SDKImage as L, type ModelSelection as M, type SDKImageDimension as N, type SDKObjectDelta as O, type PartialToolCallUpdate as P, type SDKRequestMessage as Q, type RunResult as R, type SDKMessage as S, type ToolResultContentBlock as T, type SDKStatusMessage as U, type SDKSystemMessage as V, type SDKTaskMessage as W, type SDKThinkingMessage as X, type SDKToolUseMessage as Y, type SDKUserMessage as Z, type SDKUserMessageEvent as _, type McpServerConfig as a, type ShellCommand as a0, type ShellConversationTurn as a1, type ShellOutput as a2, type ShellOutputDeltaUpdate as a3, type StepCompletedUpdate as a4, type StepStartedUpdate as a5, type StreamToCompletionResult as a6, type SummaryCompletedUpdate as a7, type SummaryStartedUpdate as a8, type SummaryUpdate as a9, type TextBlock as aa, type TextDeltaUpdate as ab, type ThinkingCompletedUpdate as ac, type ThinkingDeltaUpdate as ad, type ThinkingMessage as ae, type TokenDeltaUpdate as af, type TokenUsage as ag, type ToolCall as ah, type ToolCallCompletedUpdate as ai, type ToolCallStartedUpdate as aj, type ToolResult as ak, type ToolResultGuardOptions as al, type ToolUseBlock as am, type TurnEndedUpdate as an, type UserMessage as ao, type UserMessageAppendedUpdate as ap, emitRunEvent as aq, type Run as b, type MessageOrigin as c, type AssistantMessage as d, type ConversationStep as e, type ConversationTurn as f, type CostBreakdown as g, type CostSource as h, type CostStatus as i, type GenerateRunResult as j, type InteractionUpdate as k, type McpAuthConfig as l, type McpHttpServerConfig as m, type McpOAuthConfig as n, type McpStdioServerConfig as o, type ModelParameterValue as p, type RunCompactBoundaryEvent as q, type RunErrorDetail as r, type RunEvent as s, type RunEventSink as t, type RunGitInfo as u, type RunOperation as v, type RunPermissionDeniedEvent as w, type RunRateLimitEvent as x, type RunStatus as y, type RunTaskCompletedEvent as z };