@theokit/sdk 4.19.1 → 4.19.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cron-Bhdyjl0B.d.ts +2582 -0
- package/dist/cron-M2Xz7lq2.d.cts +2582 -0
- package/dist/cron.cjs +40 -20
- package/dist/cron.cjs.map +1 -1
- package/dist/cron.d.cts +3 -0
- package/dist/cron.d.ts +3 -0
- package/dist/cron.js +40 -20
- package/dist/cron.js.map +1 -1
- package/dist/errors-CG2RpeW-.d.ts +516 -0
- package/dist/errors-gE8612p9.d.cts +516 -0
- package/dist/errors.d.cts +3 -0
- package/dist/eval.cjs +40 -20
- package/dist/eval.cjs.map +1 -1
- package/dist/eval.js +40 -20
- package/dist/eval.js.map +1 -1
- package/dist/goal-loop.d.ts +35 -0
- package/dist/index.cjs +160 -142
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2309 -0
- package/dist/index.d.ts +2309 -0
- package/dist/index.js +160 -142
- package/dist/index.js.map +1 -1
- package/dist/internal/persistence/index.cjs +3 -1
- package/dist/internal/persistence/index.cjs.map +1 -1
- package/dist/internal/persistence/index.js +3 -1
- package/dist/internal/persistence/index.js.map +1 -1
- package/dist/internal/runtime/lifecycle/run-until.d.ts +1 -1
- package/dist/persistence.cjs +3 -1
- package/dist/persistence.cjs.map +1 -1
- package/dist/persistence.js +3 -1
- package/dist/persistence.js.map +1 -1
- package/dist/provider-catalog.json +1295 -0
- package/dist/run-DFM1H2jW.d.cts +1589 -0
- package/dist/run-DFM1H2jW.d.ts +1589 -0
- package/package.json +1 -1
|
@@ -0,0 +1,1589 @@
|
|
|
1
|
+
import * as zod from 'zod';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* `PermissionEngine` — first-match permission rules for tool invocations.
|
|
5
|
+
*
|
|
6
|
+
* Evaluates a tool name (and optional arguments, #55) against an ordered list
|
|
7
|
+
* of rules. First matching rule wins; when no rule matches the `defaultAction`
|
|
8
|
+
* is returned. #55 — the default is now `"ask"` (FAIL-CLOSED): a permission
|
|
9
|
+
* engine that cannot positively allow must not silently allow. Opt back into
|
|
10
|
+
* the previous fail-open behavior with `{ defaultAction: "allow" }`.
|
|
11
|
+
*/
|
|
12
|
+
type PermissionAction = "allow" | "deny" | "ask";
|
|
13
|
+
/**
|
|
14
|
+
* SE1 — a per-run permission MODE that adjusts the rule-engine verdict globally.
|
|
15
|
+
* A PURE post-processor of the verdict (no tool-safety metadata needed, so it fits
|
|
16
|
+
* a bring-your-own-tools runtime). Grounded in a peer project (plan agent = deny-all,
|
|
17
|
+
* `dangerously-skip-permissions`) + Codex (`AskForApproval`: `OnRequest` default,
|
|
18
|
+
* `Never`, `UnlessTrusted`). See {@link applyMode} for the exact table.
|
|
19
|
+
*
|
|
20
|
+
* - `default` — verdict as-is (rules decide; unmatched ⇒ `ask`, fail-closed).
|
|
21
|
+
* - `plan` — read-only: `allow` rules pass, everything else ⇒ `deny` (mutations blocked).
|
|
22
|
+
* NOTE: `plan` gates on the resolved verdict, so an engine configured with
|
|
23
|
+
* `{ defaultAction: "allow" }` still yields `allow` for UNMATCHED calls under
|
|
24
|
+
* `plan` — pair `plan` with the default fail-closed engine (`defaultAction: "ask"`)
|
|
25
|
+
* for full read-only behavior.
|
|
26
|
+
* - `acceptEdits` — auto-approve the UNMATCHED verdict, but STILL honor an explicit
|
|
27
|
+
* `ask` rule (a caller gates a risky tool with an ask rule). Codex `UnlessTrusted`.
|
|
28
|
+
* - `bypass` (alias `bypassPermissions`, the Anthropic-exact name) — everything ⇒
|
|
29
|
+
* `allow` EXCEPT an explicit `deny` rule. Never asks. a peer project
|
|
30
|
+
* `dangerously-skip-permissions` / Codex `Never` / Anthropic `bypassPermissions`.
|
|
31
|
+
*/
|
|
32
|
+
type PermissionMode = "default" | "plan" | "acceptEdits" | "bypass" | "bypassPermissions";
|
|
33
|
+
/**
|
|
34
|
+
* SE1 — apply a {@link PermissionMode} to a rule-engine verdict. Pure.
|
|
35
|
+
*
|
|
36
|
+
* `explicit` is `true` when the verdict came from a rule that matched by name (and
|
|
37
|
+
* args), `false` when it is the fail-closed default for an unmatched call. The flag
|
|
38
|
+
* is load-bearing for `acceptEdits`, which auto-approves the unmatched default but
|
|
39
|
+
* keeps honoring an explicit `ask` rule (unlike `bypass`, which allows even that).
|
|
40
|
+
*
|
|
41
|
+
* INVARIANT (both a peer project + Codex): an explicit `deny` is immune to EVERY
|
|
42
|
+
* auto-approve mode — `bypass`/`acceptEdits` never un-deny.
|
|
43
|
+
*/
|
|
44
|
+
declare function applyMode(verdict: PermissionAction, mode: PermissionMode, explicit: boolean): PermissionAction;
|
|
45
|
+
/**
|
|
46
|
+
* #55 — an argument matcher. A rule with `args` gates on the tool's argument
|
|
47
|
+
* VALUES, not just its name: an exact string, a RegExp (tested against the
|
|
48
|
+
* stringified value), or a predicate. Every declared arg must match for the
|
|
49
|
+
* rule to apply — so `{ tool: "shell", args: { command: /rm\s+-rf/ } }` denies
|
|
50
|
+
* a destructive shell call while leaving `ls` to fall through.
|
|
51
|
+
*/
|
|
52
|
+
type ArgMatcher = string | RegExp | ((value: unknown) => boolean);
|
|
53
|
+
interface PermissionRule {
|
|
54
|
+
/** Tool name (exact string) or pattern (RegExp). */
|
|
55
|
+
tool: string | RegExp;
|
|
56
|
+
/**
|
|
57
|
+
* #55 — optional per-argument matchers. When present, the rule matches only
|
|
58
|
+
* if the tool name matches AND every declared arg predicate matches the
|
|
59
|
+
* corresponding call argument. A missing/undefined arg fails its predicate
|
|
60
|
+
* (the rule does not match) — never throws.
|
|
61
|
+
*/
|
|
62
|
+
args?: Record<string, ArgMatcher>;
|
|
63
|
+
/** Action to take when rule matches. */
|
|
64
|
+
action: PermissionAction;
|
|
65
|
+
}
|
|
66
|
+
/** Options for {@link PermissionEngine}. */
|
|
67
|
+
interface PermissionEngineOptions {
|
|
68
|
+
/**
|
|
69
|
+
* Action when no rule matches. #55 — default is now `"ask"` (fail-closed): a
|
|
70
|
+
* permission engine that cannot positively allow must not silently allow.
|
|
71
|
+
* Pass `"allow"` to restore the previous fail-open behavior.
|
|
72
|
+
*/
|
|
73
|
+
readonly defaultAction?: PermissionAction;
|
|
74
|
+
}
|
|
75
|
+
declare class PermissionEngine {
|
|
76
|
+
#private;
|
|
77
|
+
private readonly rules;
|
|
78
|
+
private readonly defaultAction;
|
|
79
|
+
constructor(rules: PermissionRule[], options?: PermissionEngineOptions);
|
|
80
|
+
/**
|
|
81
|
+
* Evaluate a tool name (and optional arguments) against the rules. First
|
|
82
|
+
* match wins; falls back to the configured `defaultAction` (default `"ask"`,
|
|
83
|
+
* fail-closed) when no rule matches. #55 — a rule with `args` gates on the
|
|
84
|
+
* argument values, so the same tool name can resolve to different actions
|
|
85
|
+
* depending on what it is asked to do.
|
|
86
|
+
*/
|
|
87
|
+
evaluate(toolName: string, args?: Record<string, unknown>, mode?: PermissionMode): PermissionAction;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* SE2 — typed runtime EVENT stream, ADDITIVE to the `SDKMessage` content stream.
|
|
92
|
+
*
|
|
93
|
+
* `Run.stream()` yields `SDKMessage`s (the conversation content). `RunEvent`s are
|
|
94
|
+
* out-of-band runtime-OBSERVABILITY signals — the model's content is unaffected —
|
|
95
|
+
* delivered opt-in via `SendOptions.onRunEvent`. Discriminate on `type`. Mirrors
|
|
96
|
+
* the Anthropic `SDKMessage`-union approach (rate-limit, permission-denied, task
|
|
97
|
+
* lifecycle, compaction boundary).
|
|
98
|
+
*
|
|
99
|
+
* The union is the forward-compatible CONTRACT (discriminate exhaustively). The
|
|
100
|
+
* runtime EMITS every variant end-to-end: `tool_progress` + `permission_denied`
|
|
101
|
+
* (agent-loop tool-dispatch seam), `rate_limit` (pool-aware LLM client 429 retry),
|
|
102
|
+
* `compact_boundary` (session auto-compaction), and `task_*` (opt-in bridge from a
|
|
103
|
+
* `Task.submit({ onRunEvent })` task's lifecycle). A consumer switching on `type`
|
|
104
|
+
* sees the real signal.
|
|
105
|
+
*
|
|
106
|
+
* @public
|
|
107
|
+
*/
|
|
108
|
+
type RunEvent = RunToolProgressEvent | RunRateLimitEvent | RunPermissionDeniedEvent | RunTaskStartedEvent | RunTaskUpdatedEvent | RunTaskCompletedEvent | RunCompactBoundaryEvent | RunTripwireEvent | RunCompletionCheckEvent;
|
|
109
|
+
/**
|
|
110
|
+
* SE24 — a guardrail processor called `abort()`; the run stops with a tripwire.
|
|
111
|
+
* Delivered via {@link SendOptions.onRunEvent} (mirrors the `RunResult.tripwire`
|
|
112
|
+
* surfaced on `wait()`).
|
|
113
|
+
*/
|
|
114
|
+
interface RunTripwireEvent {
|
|
115
|
+
readonly type: "tripwire";
|
|
116
|
+
readonly reason: string;
|
|
117
|
+
readonly processorId: string;
|
|
118
|
+
}
|
|
119
|
+
/** A tool call is being dispatched (before its result). */
|
|
120
|
+
interface RunToolProgressEvent {
|
|
121
|
+
readonly type: "tool_progress";
|
|
122
|
+
readonly toolName: string;
|
|
123
|
+
readonly toolCallId: string;
|
|
124
|
+
}
|
|
125
|
+
/** The provider returned a rate-limit (HTTP 429); the loop will back off + retry. */
|
|
126
|
+
interface RunRateLimitEvent {
|
|
127
|
+
readonly type: "rate_limit";
|
|
128
|
+
/** Retry attempt number (1-based) about to be delayed. */
|
|
129
|
+
readonly attempt: number;
|
|
130
|
+
/** Delay in ms before the retry, when the provider/policy supplied one. */
|
|
131
|
+
readonly retryAfterMs?: number;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* A tool call was DENIED before dispatch — by the permission gate/plugin (SE1),
|
|
135
|
+
* an operator file-hook `preToolUse`, or the fork tool-whitelist. `source`
|
|
136
|
+
* discriminates which. `toolCallId` joins the event to the tool-call log.
|
|
137
|
+
*/
|
|
138
|
+
interface RunPermissionDeniedEvent {
|
|
139
|
+
readonly type: "permission_denied";
|
|
140
|
+
readonly toolName: string;
|
|
141
|
+
readonly toolCallId: string;
|
|
142
|
+
/** Which layer blocked the call. */
|
|
143
|
+
readonly source: "plugin" | "file_hook" | "fork_whitelist";
|
|
144
|
+
/** The rejection message surfaced to the model. */
|
|
145
|
+
readonly message: string;
|
|
146
|
+
}
|
|
147
|
+
/** A background task/subagent started. */
|
|
148
|
+
interface RunTaskStartedEvent {
|
|
149
|
+
readonly type: "task_started";
|
|
150
|
+
readonly taskId: string;
|
|
151
|
+
readonly description?: string;
|
|
152
|
+
}
|
|
153
|
+
/** A background task/subagent changed state. */
|
|
154
|
+
interface RunTaskUpdatedEvent {
|
|
155
|
+
readonly type: "task_updated";
|
|
156
|
+
readonly taskId: string;
|
|
157
|
+
readonly status: string;
|
|
158
|
+
}
|
|
159
|
+
/** A background task/subagent finished. */
|
|
160
|
+
interface RunTaskCompletedEvent {
|
|
161
|
+
readonly type: "task_completed";
|
|
162
|
+
readonly taskId: string;
|
|
163
|
+
readonly status: "completed" | "failed" | "stopped";
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* SE34 — the per-send completion check (`isTaskComplete`) produced a verdict.
|
|
167
|
+
* Emitted once, after a finished run's reply is judged against
|
|
168
|
+
* {@link SendOptions.completionCheck}. Distinct from `task_completed` (which is
|
|
169
|
+
* background-task/subagent lifecycle). Mirrors {@link RunResult.completionCheck}.
|
|
170
|
+
*/
|
|
171
|
+
interface RunCompletionCheckEvent {
|
|
172
|
+
readonly type: "completion_check";
|
|
173
|
+
readonly complete: boolean;
|
|
174
|
+
readonly reason: string;
|
|
175
|
+
}
|
|
176
|
+
/** The conversation crossed a compaction boundary (history was summarized). */
|
|
177
|
+
interface RunCompactBoundaryEvent {
|
|
178
|
+
readonly type: "compact_boundary";
|
|
179
|
+
readonly trigger: "manual" | "auto";
|
|
180
|
+
/** Token count before compaction, when known. */
|
|
181
|
+
readonly preTokens?: number;
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* SE2 — the opt-in sink for {@link RunEvent}s. Supplied via `SendOptions.onRunEvent`.
|
|
185
|
+
* Synchronous + best-effort: a throwing sink must never break the run (the emitter
|
|
186
|
+
* try-catches it), so keep it fast (push to a queue, don't await).
|
|
187
|
+
*/
|
|
188
|
+
type RunEventSink = (event: RunEvent) => void;
|
|
189
|
+
/**
|
|
190
|
+
* SE2 — emit a {@link RunEvent} to an optional sink, swallowing any sink error so
|
|
191
|
+
* observability can never break the run (fail-safe, mirrors the EventBus EC-2
|
|
192
|
+
* contract). No-op when the sink is absent.
|
|
193
|
+
*/
|
|
194
|
+
declare function emitRunEvent(sink: RunEventSink | undefined, event: RunEvent): void;
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* SE24 — guardrail processor pipeline. A `Processor` inspects/transforms/blocks
|
|
198
|
+
* the user message (input) or the model's final text (output). Processors run in
|
|
199
|
+
* order; each may rewrite its payload, `abort(reason)` to stop the run (surfaced
|
|
200
|
+
* as {@link RunResult.tripwire} + a `tripwire` run-event), or `warn()` to report
|
|
201
|
+
* a non-blocking violation. The pipeline is provider-agnostic and carries NO LLM
|
|
202
|
+
* — an LLM-classifier processor is the consumer's (delegated, see the guardrails
|
|
203
|
+
* ADR). Mirrors a peer framework's `inputProcessors` / `outputProcessors`.
|
|
204
|
+
*
|
|
205
|
+
* @public
|
|
206
|
+
*/
|
|
207
|
+
/**
|
|
208
|
+
* A policy violation surfaced to a processor's {@link Processor.onViolation}
|
|
209
|
+
* callback — on `abort()` (blocking) AND on `warn()` (non-blocking).
|
|
210
|
+
*
|
|
211
|
+
* @public
|
|
212
|
+
*/
|
|
213
|
+
interface ProcessorViolation {
|
|
214
|
+
processorId: string;
|
|
215
|
+
message: string;
|
|
216
|
+
detail?: unknown;
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Controls available to a processor while it runs: `abort()` stops the run with
|
|
220
|
+
* a tripwire; `warn()` reports a non-blocking violation and continues.
|
|
221
|
+
*
|
|
222
|
+
* @public
|
|
223
|
+
*/
|
|
224
|
+
interface ProcessorControls {
|
|
225
|
+
/** Stop the run immediately with a tripwire. Throws — code after it never runs. */
|
|
226
|
+
abort(reason: string): never;
|
|
227
|
+
/** Report a non-blocking violation (fires `onViolation`); the run continues. */
|
|
228
|
+
warn(message: string, detail?: unknown): void;
|
|
229
|
+
}
|
|
230
|
+
/** Context passed to {@link Processor.processInput}. @public */
|
|
231
|
+
interface InputProcessorContext extends ProcessorControls {
|
|
232
|
+
/** The user message text for this send. */
|
|
233
|
+
message: string;
|
|
234
|
+
agentId: string;
|
|
235
|
+
}
|
|
236
|
+
/** Context passed to {@link Processor.processOutput}. @public */
|
|
237
|
+
interface OutputProcessorContext extends ProcessorControls {
|
|
238
|
+
/** The model's final assistant text for this run. */
|
|
239
|
+
text: string;
|
|
240
|
+
agentId: string;
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* A guardrail processor. Provide `processInput` (runs before the LLM) and/or
|
|
244
|
+
* `processOutput` (runs on the final text). A processor's `strategy` (block /
|
|
245
|
+
* rewrite / redact / warn) is expressed via the {@link ProcessorControls}:
|
|
246
|
+
* return the transformed payload to rewrite/redact, `abort()` to block, `warn()`
|
|
247
|
+
* to report without blocking. The core ships no strategy enum — strategies are a
|
|
248
|
+
* processor-level convention over these primitives.
|
|
249
|
+
*
|
|
250
|
+
* @public
|
|
251
|
+
*/
|
|
252
|
+
interface Processor {
|
|
253
|
+
/** Stable id — surfaced on {@link ProcessorViolation} and {@link RunResult.tripwire}. */
|
|
254
|
+
id: string;
|
|
255
|
+
/**
|
|
256
|
+
* Transform or block the user message before it reaches the model. Return the
|
|
257
|
+
* (possibly rewritten) text; returning nothing (void) preserves the message
|
|
258
|
+
* unchanged. May be `async`.
|
|
259
|
+
*/
|
|
260
|
+
processInput?(ctx: InputProcessorContext): string | Promise<string> | void;
|
|
261
|
+
/**
|
|
262
|
+
* Transform or block the model's final text before it reaches the caller.
|
|
263
|
+
* Return the (possibly redacted) text; returning nothing (void) preserves the
|
|
264
|
+
* text unchanged. May be `async`.
|
|
265
|
+
*/
|
|
266
|
+
processOutput?(ctx: OutputProcessorContext): string | Promise<string> | void;
|
|
267
|
+
/** Fires on `abort()` and `warn()`. Errors thrown here are swallowed (never break the pipeline). */
|
|
268
|
+
onViolation?(violation: ProcessorViolation): void;
|
|
269
|
+
}
|
|
270
|
+
/**
|
|
271
|
+
* The tripwire detail attached to {@link RunResult.tripwire} when a processor
|
|
272
|
+
* aborts, and carried by the `tripwire` run-event.
|
|
273
|
+
*
|
|
274
|
+
* @public
|
|
275
|
+
*/
|
|
276
|
+
interface ProcessorTripwire {
|
|
277
|
+
reason: string;
|
|
278
|
+
processorId: string;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* Leaf module for content-block types shared by `messages.ts` (assistant/user
|
|
283
|
+
* content) and `agent-prims.ts` (`CustomTool` handler results). Kept
|
|
284
|
+
* import-free so both can depend on it WITHOUT the `agent-prims ↔ messages`
|
|
285
|
+
* cycle (#7).
|
|
286
|
+
*
|
|
287
|
+
* @public
|
|
288
|
+
*/
|
|
289
|
+
/**
|
|
290
|
+
* Plain text content block emitted by the assistant or user, or returned by a
|
|
291
|
+
* tool.
|
|
292
|
+
*
|
|
293
|
+
* @public
|
|
294
|
+
*/
|
|
295
|
+
interface TextBlock {
|
|
296
|
+
type: "text";
|
|
297
|
+
text: string;
|
|
298
|
+
}
|
|
299
|
+
/**
|
|
300
|
+
* SE7 — a base64-encoded image block a tool can hand back as (part of) its
|
|
301
|
+
* result or its `ToolError`. `media_type` is a MIME type (e.g. `"image/png"`);
|
|
302
|
+
* `data` is the base64 payload without a data-URL prefix.
|
|
303
|
+
*
|
|
304
|
+
* Note: when a tool builds this from model- or user-influenced input, treat
|
|
305
|
+
* `media_type` as UNTRUSTED — validate/allow-list it before rendering it in a
|
|
306
|
+
* log or UI (it could carry newlines / control chars). The SDK only forwards it
|
|
307
|
+
* (JSON-serialized onto the wire) and never executes or path-joins it.
|
|
308
|
+
*
|
|
309
|
+
* @public
|
|
310
|
+
*/
|
|
311
|
+
interface ImageBlock {
|
|
312
|
+
type: "image";
|
|
313
|
+
source: {
|
|
314
|
+
type: "base64";
|
|
315
|
+
media_type: string;
|
|
316
|
+
data: string;
|
|
317
|
+
};
|
|
318
|
+
}
|
|
319
|
+
/**
|
|
320
|
+
* SE7 — structured content a tool result may carry: text and/or images. A tool
|
|
321
|
+
* `handler` may return this (success) and a `ToolError` may carry it (failure).
|
|
322
|
+
* Block-capable provider wires forward it natively; string-only provider wires
|
|
323
|
+
* flatten text and fail fast on an image.
|
|
324
|
+
*
|
|
325
|
+
* @public
|
|
326
|
+
*/
|
|
327
|
+
type ToolResultContentBlock = TextBlock | ImageBlock;
|
|
328
|
+
|
|
329
|
+
/**
|
|
330
|
+
* Type-leaf — primitives shared between `agent.ts`, `run.ts`, and
|
|
331
|
+
* `messages.ts`. Extracted to break LOW type-only cycles #5 and #7
|
|
332
|
+
* (audit `architecture-output/final_report.md`) per plan
|
|
333
|
+
* arch-review-fixes-2026-06-06 § Phase 4 / T4.1 (D438).
|
|
334
|
+
*
|
|
335
|
+
* Public surface unchanged — `types/agent.ts` re-exports these from this
|
|
336
|
+
* leaf so `import type { ModelSelection, CustomTool } from "@theokit/sdk"`
|
|
337
|
+
* keeps resolving.
|
|
338
|
+
*
|
|
339
|
+
* @public
|
|
340
|
+
*/
|
|
341
|
+
/**
|
|
342
|
+
* One slot in a {@link ModelSelection.params} array.
|
|
343
|
+
*
|
|
344
|
+
* @public
|
|
345
|
+
*/
|
|
346
|
+
interface ModelParameterValue {
|
|
347
|
+
id: string;
|
|
348
|
+
value: string;
|
|
349
|
+
}
|
|
350
|
+
/**
|
|
351
|
+
* Identifies a model plus optional per-model parameters (e.g. reasoning effort).
|
|
352
|
+
*
|
|
353
|
+
* Use `Theokit.models.list()` to discover valid ids and parameter definitions.
|
|
354
|
+
*
|
|
355
|
+
* @public
|
|
356
|
+
*/
|
|
357
|
+
interface ModelSelection {
|
|
358
|
+
id: string;
|
|
359
|
+
params?: ModelParameterValue[];
|
|
360
|
+
}
|
|
361
|
+
/**
|
|
362
|
+
* SE12 — a read-only, text-only projection of one turn of the run's conversation,
|
|
363
|
+
* exposed to a tool handler via `ctx.messages`. Content is flattened to text; tool
|
|
364
|
+
* calls / results and non-text parts are dropped, and turns that project to empty
|
|
365
|
+
* text are omitted. Consumed by `defineSubAgent`'s `messageFilter` to forward
|
|
366
|
+
* (a subset of) the supervisor transcript to a subagent.
|
|
367
|
+
*
|
|
368
|
+
* `role` includes `"system"` for type-completeness with the wire message shape,
|
|
369
|
+
* but the system prompt travels on a separate request field — a `"system"` entry
|
|
370
|
+
* does NOT appear in the current projection.
|
|
371
|
+
*
|
|
372
|
+
* @public
|
|
373
|
+
*/
|
|
374
|
+
interface ToolContextMessage {
|
|
375
|
+
role: "system" | "user" | "assistant";
|
|
376
|
+
content: string;
|
|
377
|
+
}
|
|
378
|
+
/**
|
|
379
|
+
* Local function tool declared per-agent via {@link AgentOptions.tools}. The
|
|
380
|
+
* handler runs in-process; no MCP server is involved. The SDK serializes
|
|
381
|
+
* `name`, `description`, and `inputSchema` into the model's tool catalog.
|
|
382
|
+
*
|
|
383
|
+
* Handlers MUST be re-passed on `Agent.resume()` because closures cannot be
|
|
384
|
+
* persisted. The tool catalog (name + description + schema) is NOT serialized.
|
|
385
|
+
*
|
|
386
|
+
* @public
|
|
387
|
+
*/
|
|
388
|
+
interface CustomTool {
|
|
389
|
+
/**
|
|
390
|
+
* Tool name surfaced to the LLM. Must match `^[a-zA-Z][a-zA-Z0-9_-]{0,63}$`
|
|
391
|
+
* and must not collide with `shell`, `memory_search`, `memory_get`, or any
|
|
392
|
+
* `mcp_*` prefix (reserved for the SDK's built-in tools).
|
|
393
|
+
*/
|
|
394
|
+
name: string;
|
|
395
|
+
/** Description surfaced to the LLM. Required — drives tool-selection accuracy. */
|
|
396
|
+
description: string;
|
|
397
|
+
/** JSON Schema (Draft-7 subset) describing the `input` argument. Must be `type: "object"`. */
|
|
398
|
+
inputSchema: Record<string, unknown>;
|
|
399
|
+
/**
|
|
400
|
+
* Local handler invoked when the model emits `tool_use` for this tool.
|
|
401
|
+
* Returns a string OR structured content blocks (SE7 — text + image, e.g. a
|
|
402
|
+
* screenshot) that become the `tool_result.content` surfaced back to the
|
|
403
|
+
* model. Throws → SDK converts to `tool_result` with `isError: true` and the
|
|
404
|
+
* error `message` as content; throw a `ToolError` to carry a clean message or
|
|
405
|
+
* multimodal error content. #65 — an optional 2nd `ToolContext` argument
|
|
406
|
+
* carries the run's `AbortSignal`; single-argument handlers are unaffected. M7
|
|
407
|
+
* — the same `ctx` also carries an optional user `context` (provided once via
|
|
408
|
+
* `SendOptions.context`), so shared config like a `projectRoot` is read by
|
|
409
|
+
* every tool instead of baked into each factory. SE12 — `ctx.messages` is a
|
|
410
|
+
* read-only, text-only projection of the current turn's transcript (see
|
|
411
|
+
* {@link ToolContextMessage}); `defineSubAgent`'s `messageFilter` consumes it.
|
|
412
|
+
* #119 — `ctx.threadId` is the run's session identity (the key passed to
|
|
413
|
+
* `Agent.getOrCreate(sessionId, …)`, or the agent's own id), so a stateful tool
|
|
414
|
+
* shared across sessions can scope its state per session instead of leaking it.
|
|
415
|
+
*/
|
|
416
|
+
handler: (input: Record<string, unknown>, ctx?: {
|
|
417
|
+
signal?: AbortSignal;
|
|
418
|
+
context?: unknown;
|
|
419
|
+
messages?: readonly ToolContextMessage[];
|
|
420
|
+
threadId?: string;
|
|
421
|
+
}) => string | ToolResultContentBlock[] | Promise<string | ToolResultContentBlock[]>;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
/**
|
|
425
|
+
* Type-leaf — base message types shared between `conversation.ts` and
|
|
426
|
+
* `updates.ts`. Extracted to break LOW type-only cycle #6 (audit
|
|
427
|
+
* `architecture-output/final_report.md`) per plan arch-review-fixes-2026-06-06
|
|
428
|
+
* § Phase 4 / T4.1 (D438).
|
|
429
|
+
*
|
|
430
|
+
* Public surface unchanged — `types/conversation.ts` re-exports `UserMessage`
|
|
431
|
+
* from this leaf so `import type { UserMessage } from "@theokit/sdk"` keeps
|
|
432
|
+
* resolving.
|
|
433
|
+
*
|
|
434
|
+
* @public
|
|
435
|
+
*/
|
|
436
|
+
/**
|
|
437
|
+
* User-authored message in a conversation history.
|
|
438
|
+
*
|
|
439
|
+
* @public
|
|
440
|
+
*/
|
|
441
|
+
interface UserMessage {
|
|
442
|
+
text: string;
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
/**
|
|
446
|
+
* Single tool call event. The internal `args` and `result` shapes are NOT stable.
|
|
447
|
+
*
|
|
448
|
+
* @public
|
|
449
|
+
*/
|
|
450
|
+
interface ToolCall {
|
|
451
|
+
callId: string;
|
|
452
|
+
name: string;
|
|
453
|
+
args?: unknown;
|
|
454
|
+
result?: unknown;
|
|
455
|
+
}
|
|
456
|
+
/**
|
|
457
|
+
* Incremental text token from the assistant.
|
|
458
|
+
*
|
|
459
|
+
* @public
|
|
460
|
+
*/
|
|
461
|
+
interface TextDeltaUpdate {
|
|
462
|
+
type: "text-delta";
|
|
463
|
+
text: string;
|
|
464
|
+
}
|
|
465
|
+
/**
|
|
466
|
+
* Incremental reasoning token.
|
|
467
|
+
*
|
|
468
|
+
* @public
|
|
469
|
+
*/
|
|
470
|
+
interface ThinkingDeltaUpdate {
|
|
471
|
+
type: "thinking-delta";
|
|
472
|
+
text: string;
|
|
473
|
+
}
|
|
474
|
+
/**
|
|
475
|
+
* Emitted when a reasoning block completes.
|
|
476
|
+
*
|
|
477
|
+
* @public
|
|
478
|
+
*/
|
|
479
|
+
interface ThinkingCompletedUpdate {
|
|
480
|
+
type: "thinking-completed";
|
|
481
|
+
thinkingDurationMs: number;
|
|
482
|
+
}
|
|
483
|
+
/**
|
|
484
|
+
* Tool call started — args committed.
|
|
485
|
+
*
|
|
486
|
+
* @public
|
|
487
|
+
*/
|
|
488
|
+
interface ToolCallStartedUpdate {
|
|
489
|
+
type: "tool-call-started";
|
|
490
|
+
callId: string;
|
|
491
|
+
toolCall: ToolCall;
|
|
492
|
+
modelCallId: string;
|
|
493
|
+
}
|
|
494
|
+
/**
|
|
495
|
+
* Tool call arguments streaming in incrementally.
|
|
496
|
+
*
|
|
497
|
+
* @public
|
|
498
|
+
*/
|
|
499
|
+
interface PartialToolCallUpdate {
|
|
500
|
+
type: "partial-tool-call";
|
|
501
|
+
callId: string;
|
|
502
|
+
toolCall: ToolCall;
|
|
503
|
+
modelCallId: string;
|
|
504
|
+
}
|
|
505
|
+
/**
|
|
506
|
+
* Tool call completed.
|
|
507
|
+
*
|
|
508
|
+
* @public
|
|
509
|
+
*/
|
|
510
|
+
interface ToolCallCompletedUpdate {
|
|
511
|
+
type: "tool-call-completed";
|
|
512
|
+
callId: string;
|
|
513
|
+
toolCall: ToolCall;
|
|
514
|
+
modelCallId: string;
|
|
515
|
+
}
|
|
516
|
+
/**
|
|
517
|
+
* Token count delta for usage tracking.
|
|
518
|
+
*
|
|
519
|
+
* @public
|
|
520
|
+
*/
|
|
521
|
+
interface TokenDeltaUpdate {
|
|
522
|
+
type: "token-delta";
|
|
523
|
+
tokens: number;
|
|
524
|
+
}
|
|
525
|
+
/**
|
|
526
|
+
* Conversation step started.
|
|
527
|
+
*
|
|
528
|
+
* @public
|
|
529
|
+
*/
|
|
530
|
+
interface StepStartedUpdate {
|
|
531
|
+
type: "step-started";
|
|
532
|
+
stepId: number;
|
|
533
|
+
}
|
|
534
|
+
/**
|
|
535
|
+
* Conversation step completed.
|
|
536
|
+
*
|
|
537
|
+
* @public
|
|
538
|
+
*/
|
|
539
|
+
interface StepCompletedUpdate {
|
|
540
|
+
type: "step-completed";
|
|
541
|
+
stepId: number;
|
|
542
|
+
stepDurationMs: number;
|
|
543
|
+
}
|
|
544
|
+
/**
|
|
545
|
+
* Turn ended with usage summary.
|
|
546
|
+
*
|
|
547
|
+
* @public
|
|
548
|
+
*/
|
|
549
|
+
interface TurnEndedUpdate {
|
|
550
|
+
type: "turn-ended";
|
|
551
|
+
usage?: {
|
|
552
|
+
inputTokens: number;
|
|
553
|
+
outputTokens: number;
|
|
554
|
+
cacheReadTokens: number;
|
|
555
|
+
cacheWriteTokens: number;
|
|
556
|
+
};
|
|
557
|
+
}
|
|
558
|
+
/**
|
|
559
|
+
* User message appended to the conversation.
|
|
560
|
+
*
|
|
561
|
+
* @public
|
|
562
|
+
*/
|
|
563
|
+
interface UserMessageAppendedUpdate {
|
|
564
|
+
type: "user-message-appended";
|
|
565
|
+
userMessage: UserMessage;
|
|
566
|
+
}
|
|
567
|
+
/** @public */
|
|
568
|
+
interface SummaryUpdate {
|
|
569
|
+
type: "summary";
|
|
570
|
+
summary: string;
|
|
571
|
+
}
|
|
572
|
+
/** @public */
|
|
573
|
+
interface SummaryStartedUpdate {
|
|
574
|
+
type: "summary-started";
|
|
575
|
+
}
|
|
576
|
+
/** @public */
|
|
577
|
+
interface SummaryCompletedUpdate {
|
|
578
|
+
type: "summary-completed";
|
|
579
|
+
}
|
|
580
|
+
/** @public */
|
|
581
|
+
interface ShellOutputDeltaUpdate {
|
|
582
|
+
type: "shell-output-delta";
|
|
583
|
+
event: Record<string, unknown>;
|
|
584
|
+
}
|
|
585
|
+
/**
|
|
586
|
+
* Lowest-level raw update from a run. Pass `onDelta` to `agent.send()` to
|
|
587
|
+
* consume these. Finer-grained than `SDKMessage` events.
|
|
588
|
+
*
|
|
589
|
+
* @public
|
|
590
|
+
*/
|
|
591
|
+
type InteractionUpdate = TextDeltaUpdate | ThinkingDeltaUpdate | ThinkingCompletedUpdate | ToolCallStartedUpdate | ToolCallCompletedUpdate | PartialToolCallUpdate | TokenDeltaUpdate | StepStartedUpdate | StepCompletedUpdate | TurnEndedUpdate | UserMessageAppendedUpdate | SummaryUpdate | SummaryStartedUpdate | SummaryCompletedUpdate | ShellOutputDeltaUpdate;
|
|
592
|
+
|
|
593
|
+
/**
|
|
594
|
+
* Plain assistant message in a conversation history.
|
|
595
|
+
*
|
|
596
|
+
* @public
|
|
597
|
+
*/
|
|
598
|
+
interface AssistantMessage {
|
|
599
|
+
text: string;
|
|
600
|
+
}
|
|
601
|
+
/**
|
|
602
|
+
* Reasoning step in a conversation history.
|
|
603
|
+
*
|
|
604
|
+
* @public
|
|
605
|
+
*/
|
|
606
|
+
interface ThinkingMessage {
|
|
607
|
+
text: string;
|
|
608
|
+
thinkingDurationMs?: number;
|
|
609
|
+
}
|
|
610
|
+
/**
|
|
611
|
+
* Shell command executed during a run.
|
|
612
|
+
*
|
|
613
|
+
* @public
|
|
614
|
+
*/
|
|
615
|
+
interface ShellCommand {
|
|
616
|
+
command: string;
|
|
617
|
+
workingDirectory?: string;
|
|
618
|
+
}
|
|
619
|
+
/**
|
|
620
|
+
* Output of a shell command.
|
|
621
|
+
*
|
|
622
|
+
* @public
|
|
623
|
+
*/
|
|
624
|
+
interface ShellOutput {
|
|
625
|
+
stdout: string;
|
|
626
|
+
stderr: string;
|
|
627
|
+
exitCode: number;
|
|
628
|
+
}
|
|
629
|
+
/**
|
|
630
|
+
* Single step inside an agent turn.
|
|
631
|
+
*
|
|
632
|
+
* @public
|
|
633
|
+
*/
|
|
634
|
+
/**
|
|
635
|
+
* Result of a tool invocation. Pairs with the preceding `toolCall` step
|
|
636
|
+
* by `callId`. `isError: true` when the tool returned a failure result.
|
|
637
|
+
*
|
|
638
|
+
* T2.3 — added so `Run.conversation()` surfaces the full interaction
|
|
639
|
+
* including tool results (parity with OpenAI Agents `RunResult.new_items`).
|
|
640
|
+
*
|
|
641
|
+
* @public
|
|
642
|
+
*/
|
|
643
|
+
interface ToolResult {
|
|
644
|
+
callId: string;
|
|
645
|
+
name: string;
|
|
646
|
+
result: string;
|
|
647
|
+
isError: boolean;
|
|
648
|
+
}
|
|
649
|
+
type ConversationStep = {
|
|
650
|
+
type: "assistantMessage";
|
|
651
|
+
message: AssistantMessage;
|
|
652
|
+
} | {
|
|
653
|
+
type: "toolCall";
|
|
654
|
+
message: ToolCall;
|
|
655
|
+
} | {
|
|
656
|
+
type: "toolResult";
|
|
657
|
+
message: ToolResult;
|
|
658
|
+
} | {
|
|
659
|
+
type: "thinkingMessage";
|
|
660
|
+
message: ThinkingMessage;
|
|
661
|
+
};
|
|
662
|
+
/**
|
|
663
|
+
* Agent turn: user message + assistant/tool/thinking steps.
|
|
664
|
+
*
|
|
665
|
+
* @public
|
|
666
|
+
*/
|
|
667
|
+
interface AgentConversationTurn {
|
|
668
|
+
userMessage?: UserMessage;
|
|
669
|
+
steps: ConversationStep[];
|
|
670
|
+
}
|
|
671
|
+
/**
|
|
672
|
+
* Shell turn: a command and its output.
|
|
673
|
+
*
|
|
674
|
+
* @public
|
|
675
|
+
*/
|
|
676
|
+
interface ShellConversationTurn {
|
|
677
|
+
shellCommand?: ShellCommand;
|
|
678
|
+
shellOutput?: ShellOutput;
|
|
679
|
+
}
|
|
680
|
+
/**
|
|
681
|
+
* Structured per-turn view of a run.
|
|
682
|
+
*
|
|
683
|
+
* @public
|
|
684
|
+
*/
|
|
685
|
+
type ConversationTurn = {
|
|
686
|
+
type: "agentConversationTurn";
|
|
687
|
+
turn: AgentConversationTurn;
|
|
688
|
+
} | {
|
|
689
|
+
type: "shellConversationTurn";
|
|
690
|
+
turn: ShellConversationTurn;
|
|
691
|
+
};
|
|
692
|
+
|
|
693
|
+
/**
|
|
694
|
+
* Child-process environment policy contract (#54).
|
|
695
|
+
*
|
|
696
|
+
* The DIP-correct home for the `EnvPolicy` contract type: the domain `types/`
|
|
697
|
+
* layer owns the contract, and the application-layer implementation
|
|
698
|
+
* (`internal/runtime/lifecycle/env-policy.ts`) re-exports it for back-compat
|
|
699
|
+
* while owning the runtime logic (`resolveChildEnv`, secret patterns, …).
|
|
700
|
+
*
|
|
701
|
+
* Modes:
|
|
702
|
+
* - `inherit-scrubbed` (DEFAULT) — inherit all parent vars EXCEPT secret-like
|
|
703
|
+
* names (`*KEY*`, `*SECRET*`, `*TOKEN*`, `*PASSWORD*`, `*_AUTH*`). Non-breaking:
|
|
704
|
+
* existing spawns keep every non-secret var; only secrets stop leaking.
|
|
705
|
+
* - `core` — inherit ONLY a safe base allowlist (PATH/HOME/…); strongest scrub.
|
|
706
|
+
* - `all` — explicit opt-out: inherit everything, secrets included.
|
|
707
|
+
*
|
|
708
|
+
* @public
|
|
709
|
+
*/
|
|
710
|
+
type EnvPolicy = "inherit-scrubbed" | "core" | "all";
|
|
711
|
+
|
|
712
|
+
/**
|
|
713
|
+
* MCP server configuration accepted by `Agent.create()` and `agent.send()`.
|
|
714
|
+
*
|
|
715
|
+
* @public
|
|
716
|
+
*/
|
|
717
|
+
type McpStdioServerConfig = {
|
|
718
|
+
type?: "stdio";
|
|
719
|
+
command: string;
|
|
720
|
+
args?: string[];
|
|
721
|
+
env?: Record<string, string>;
|
|
722
|
+
/** Local agents only. Cloud rejects this field. */
|
|
723
|
+
cwd?: string;
|
|
724
|
+
/**
|
|
725
|
+
* #59 — per-request timeout in ms. A request that gets no reply within this
|
|
726
|
+
* window rejects with a typed `NetworkError` (`code: "mcp_timeout"`) instead
|
|
727
|
+
* of hanging the agent loop forever. Default 30_000.
|
|
728
|
+
*/
|
|
729
|
+
requestTimeoutMs?: number;
|
|
730
|
+
/**
|
|
731
|
+
* #54 — env inherit/scrub policy for the spawned MCP server process. Defaults
|
|
732
|
+
* to `"inherit-scrubbed"` (drop secret-like host vars: `*KEY*`/`*SECRET*`/
|
|
733
|
+
* `*TOKEN*`/`*PASSWORD*`/`*_AUTH*`/…) so a third-party MCP server binary cannot
|
|
734
|
+
* exfiltrate host secrets via the environment. `env` above is merged AFTER the
|
|
735
|
+
* policy and always wins. Pass `"all"` to restore full inheritance.
|
|
736
|
+
*/
|
|
737
|
+
envPolicy?: EnvPolicy;
|
|
738
|
+
};
|
|
739
|
+
/**
|
|
740
|
+
* OAuth-style auth bundle for HTTP/SSE MCP servers.
|
|
741
|
+
*
|
|
742
|
+
* @public
|
|
743
|
+
*/
|
|
744
|
+
interface McpAuthConfig {
|
|
745
|
+
CLIENT_ID: string;
|
|
746
|
+
CLIENT_SECRET?: string;
|
|
747
|
+
scopes?: string[];
|
|
748
|
+
/**
|
|
749
|
+
* OAuth 2.1 PKCE flow configuration (ADR D41, v1.2+). When present, the
|
|
750
|
+
* SDK runs the PKCE flow on first use and stores tokens via keychain or
|
|
751
|
+
* file. Without this, the SDK relies on `CLIENT_SECRET` + manual headers.
|
|
752
|
+
*/
|
|
753
|
+
oauth?: McpOAuthConfig;
|
|
754
|
+
}
|
|
755
|
+
/**
|
|
756
|
+
* OAuth 2.1 PKCE flow descriptor. See ADR D41.
|
|
757
|
+
*
|
|
758
|
+
* @public
|
|
759
|
+
*/
|
|
760
|
+
interface McpOAuthConfig {
|
|
761
|
+
/** Authorization endpoint (e.g. https://api.notion.com/v1/oauth/authorize). */
|
|
762
|
+
authorizationEndpoint: string;
|
|
763
|
+
/** Token endpoint (e.g. https://api.notion.com/v1/oauth/token). */
|
|
764
|
+
tokenEndpoint: string;
|
|
765
|
+
/** Where the OAuth `code` is received. */
|
|
766
|
+
redirectMode: "manual" | "localhost";
|
|
767
|
+
/** Localhost callback port (0 = random free port, default). */
|
|
768
|
+
localhostPort?: number;
|
|
769
|
+
/** Flow timeout in ms (default 300_000 = 5min). */
|
|
770
|
+
timeoutMs?: number;
|
|
771
|
+
}
|
|
772
|
+
/**
|
|
773
|
+
* HTTP or SSE MCP server.
|
|
774
|
+
*
|
|
775
|
+
* @public
|
|
776
|
+
*/
|
|
777
|
+
type McpHttpServerConfig = {
|
|
778
|
+
type?: "http" | "sse";
|
|
779
|
+
url: string;
|
|
780
|
+
/** Passed through. `Authorization` works here. */
|
|
781
|
+
headers?: Record<string, string>;
|
|
782
|
+
auth?: McpAuthConfig;
|
|
783
|
+
/**
|
|
784
|
+
* #59 — per-request timeout in ms, enforced via `AbortSignal.timeout`. A
|
|
785
|
+
* fetch that does not respond within this window rejects with a typed
|
|
786
|
+
* `NetworkError` (`code: "mcp_timeout"`). Default 30_000.
|
|
787
|
+
*/
|
|
788
|
+
requestTimeoutMs?: number;
|
|
789
|
+
};
|
|
790
|
+
/**
|
|
791
|
+
* Union of MCP server configs.
|
|
792
|
+
*
|
|
793
|
+
* @public
|
|
794
|
+
*/
|
|
795
|
+
type McpServerConfig = McpStdioServerConfig | McpHttpServerConfig;
|
|
796
|
+
|
|
797
|
+
/**
|
|
798
|
+
* Tool invocation block emitted by the assistant.
|
|
799
|
+
*
|
|
800
|
+
* @public
|
|
801
|
+
*/
|
|
802
|
+
interface ToolUseBlock {
|
|
803
|
+
type: "tool_use";
|
|
804
|
+
id: string;
|
|
805
|
+
name: string;
|
|
806
|
+
/** Tool args are not part of the stable schema. Treat as unknown and parse defensively. */
|
|
807
|
+
input: unknown;
|
|
808
|
+
}
|
|
809
|
+
/**
|
|
810
|
+
* Init metadata. Emitted once at the start of a run.
|
|
811
|
+
*
|
|
812
|
+
* @public
|
|
813
|
+
*/
|
|
814
|
+
interface SDKSystemMessage {
|
|
815
|
+
type: "system";
|
|
816
|
+
subtype?: "init";
|
|
817
|
+
agent_id: string;
|
|
818
|
+
run_id: string;
|
|
819
|
+
model?: ModelSelection;
|
|
820
|
+
tools?: string[];
|
|
821
|
+
}
|
|
822
|
+
/**
|
|
823
|
+
* Echo of the user prompt for this run.
|
|
824
|
+
*
|
|
825
|
+
* @public
|
|
826
|
+
*/
|
|
827
|
+
interface SDKUserMessageEvent {
|
|
828
|
+
type: "user";
|
|
829
|
+
agent_id: string;
|
|
830
|
+
run_id: string;
|
|
831
|
+
message: {
|
|
832
|
+
role: "user";
|
|
833
|
+
content: TextBlock[];
|
|
834
|
+
};
|
|
835
|
+
}
|
|
836
|
+
/**
|
|
837
|
+
* Model text output for this run.
|
|
838
|
+
*
|
|
839
|
+
* @public
|
|
840
|
+
*/
|
|
841
|
+
interface SDKAssistantMessage {
|
|
842
|
+
type: "assistant";
|
|
843
|
+
agent_id: string;
|
|
844
|
+
run_id: string;
|
|
845
|
+
message: {
|
|
846
|
+
role: "assistant";
|
|
847
|
+
content: Array<TextBlock | ToolUseBlock>;
|
|
848
|
+
};
|
|
849
|
+
}
|
|
850
|
+
/**
|
|
851
|
+
* Reasoning content.
|
|
852
|
+
*
|
|
853
|
+
* @public
|
|
854
|
+
*/
|
|
855
|
+
interface SDKThinkingMessage {
|
|
856
|
+
type: "thinking";
|
|
857
|
+
agent_id: string;
|
|
858
|
+
run_id: string;
|
|
859
|
+
text: string;
|
|
860
|
+
thinking_duration_ms?: number;
|
|
861
|
+
}
|
|
862
|
+
/**
|
|
863
|
+
* Tool invocation lifecycle event. Emitted at start with `args`, then again on
|
|
864
|
+
* completion with `result`.
|
|
865
|
+
*
|
|
866
|
+
* Tool `args` and `result` are NOT part of the stable schema — treat as unknown.
|
|
867
|
+
*
|
|
868
|
+
* @public
|
|
869
|
+
*/
|
|
870
|
+
interface SDKToolUseMessage {
|
|
871
|
+
type: "tool_call";
|
|
872
|
+
agent_id: string;
|
|
873
|
+
run_id: string;
|
|
874
|
+
call_id: string;
|
|
875
|
+
name: string;
|
|
876
|
+
status: "running" | "completed" | "error";
|
|
877
|
+
args?: unknown;
|
|
878
|
+
result?: unknown;
|
|
879
|
+
truncated?: {
|
|
880
|
+
args?: boolean;
|
|
881
|
+
result?: boolean;
|
|
882
|
+
};
|
|
883
|
+
}
|
|
884
|
+
/**
|
|
885
|
+
* Cloud run lifecycle transitions.
|
|
886
|
+
*
|
|
887
|
+
* @public
|
|
888
|
+
*/
|
|
889
|
+
interface SDKStatusMessage {
|
|
890
|
+
type: "status";
|
|
891
|
+
agent_id: string;
|
|
892
|
+
run_id: string;
|
|
893
|
+
status: "CREATING" | "RUNNING" | "FINISHED" | "ERROR" | "CANCELLED" | "EXPIRED";
|
|
894
|
+
message?: string;
|
|
895
|
+
}
|
|
896
|
+
/**
|
|
897
|
+
* Task-level milestones and summaries.
|
|
898
|
+
*
|
|
899
|
+
* @public
|
|
900
|
+
*/
|
|
901
|
+
interface SDKTaskMessage {
|
|
902
|
+
type: "task";
|
|
903
|
+
agent_id: string;
|
|
904
|
+
run_id: string;
|
|
905
|
+
status?: string;
|
|
906
|
+
text?: string;
|
|
907
|
+
}
|
|
908
|
+
/**
|
|
909
|
+
* Awaiting user input or approval.
|
|
910
|
+
*
|
|
911
|
+
* @public
|
|
912
|
+
*/
|
|
913
|
+
interface SDKRequestMessage {
|
|
914
|
+
type: "request";
|
|
915
|
+
agent_id: string;
|
|
916
|
+
run_id: string;
|
|
917
|
+
request_id: string;
|
|
918
|
+
}
|
|
919
|
+
/**
|
|
920
|
+
* Partial object emitted during `Agent.streamObject<T>` streaming (ADR D45).
|
|
921
|
+
* `partial` is `DeepPartial<z.infer<T>>` at the typed iterator level but
|
|
922
|
+
* erased to `unknown` here because SDKMessage union is non-generic.
|
|
923
|
+
*
|
|
924
|
+
* @public
|
|
925
|
+
*/
|
|
926
|
+
interface SDKObjectDelta {
|
|
927
|
+
type: "object_delta";
|
|
928
|
+
agent_id: string;
|
|
929
|
+
run_id: string;
|
|
930
|
+
partial: unknown;
|
|
931
|
+
attempt: number;
|
|
932
|
+
}
|
|
933
|
+
/**
|
|
934
|
+
* Discriminated union of all stream events. Discriminate on `type`.
|
|
935
|
+
*
|
|
936
|
+
* All events include `agent_id` and `run_id`.
|
|
937
|
+
*
|
|
938
|
+
* @public
|
|
939
|
+
*/
|
|
940
|
+
type SDKMessage = SDKSystemMessage | SDKUserMessageEvent | SDKAssistantMessage | SDKThinkingMessage | SDKToolUseMessage | SDKStatusMessage | SDKTaskMessage | SDKRequestMessage | SDKObjectDelta;
|
|
941
|
+
|
|
942
|
+
/**
|
|
943
|
+
* Public type contract for token usage + cost tracking (ADRs D376-D379).
|
|
944
|
+
*
|
|
945
|
+
* Surfaces via `RunResult.usage` + `RunResult.cost` after every Run.
|
|
946
|
+
* Re-exported through the package barrel; consumers import from
|
|
947
|
+
* `@theokit/sdk`.
|
|
948
|
+
*
|
|
949
|
+
* @public
|
|
950
|
+
*/
|
|
951
|
+
/**
|
|
952
|
+
* Token usage observed during a Run. 5 closed buckets (D376) cover
|
|
953
|
+
* 100% of providers in 2026: OpenAI Chat / OpenAI Responses (o-series
|
|
954
|
+
* with reasoning) / Anthropic Messages (with prompt caching).
|
|
955
|
+
*
|
|
956
|
+
* `totalTokens` is derived (`inputTokens + outputTokens`); EC-10
|
|
957
|
+
* invariant: SDK must never emit `totalTokens !== inputTokens + outputTokens`.
|
|
958
|
+
*
|
|
959
|
+
* `requests[]` is the per-request breakdown (mirror a peer SDK)
|
|
960
|
+
* — populated only when the run made > 1 LLM call.
|
|
961
|
+
*/
|
|
962
|
+
interface TokenUsage {
|
|
963
|
+
readonly inputTokens: number;
|
|
964
|
+
readonly outputTokens: number;
|
|
965
|
+
readonly cacheReadTokens?: number;
|
|
966
|
+
readonly cacheWriteTokens?: number;
|
|
967
|
+
readonly reasoningTokens?: number;
|
|
968
|
+
readonly totalTokens: number;
|
|
969
|
+
/** Per-request breakdown; absent when the run made a single LLM call. */
|
|
970
|
+
readonly requests?: ReadonlyArray<Omit<TokenUsage, "requests">>;
|
|
971
|
+
}
|
|
972
|
+
/**
|
|
973
|
+
* Cost confidence level (D377).
|
|
974
|
+
* - `actual`: returned by a provider billing API (e.g. OpenRouter `/generation`).
|
|
975
|
+
* - `estimated`: computed from bundled pricing snapshot.
|
|
976
|
+
* - `included`: subscription-included route (Codex CLI, Claude Pro).
|
|
977
|
+
* - `unknown`: pricing data unavailable; `amountUsd` is undefined.
|
|
978
|
+
*/
|
|
979
|
+
type CostStatus = "actual" | "estimated" | "included" | "unknown";
|
|
980
|
+
/** Source of the cost figure for caller-side audit. */
|
|
981
|
+
type CostSource = "openrouter_api" | "litellm_snapshot" | "user_override" | "subscription_included" | "unknown";
|
|
982
|
+
/**
|
|
983
|
+
* Cost breakdown attached to `RunResult.cost`. When `status === "unknown"`,
|
|
984
|
+
* `amountUsd` is `undefined` — DO NOT default to 0 (mentira). UI exibe
|
|
985
|
+
* `n/a` para unknown, `~$1.23` para estimated, `$1.23` para actual.
|
|
986
|
+
*/
|
|
987
|
+
interface CostBreakdown {
|
|
988
|
+
readonly amountUsd: number | undefined;
|
|
989
|
+
readonly status: CostStatus;
|
|
990
|
+
readonly currency: "USD";
|
|
991
|
+
readonly source: CostSource;
|
|
992
|
+
readonly pricingVersion: string | undefined;
|
|
993
|
+
readonly notes?: ReadonlyArray<string>;
|
|
994
|
+
/** Per-bucket detail (in USD) for caller analytics. */
|
|
995
|
+
readonly detail?: {
|
|
996
|
+
readonly input?: number;
|
|
997
|
+
readonly output?: number;
|
|
998
|
+
readonly cacheRead?: number;
|
|
999
|
+
readonly cacheWrite?: number;
|
|
1000
|
+
readonly reasoning?: number;
|
|
1001
|
+
};
|
|
1002
|
+
}
|
|
1003
|
+
|
|
1004
|
+
/**
|
|
1005
|
+
* Options for the tool-result guard (spotlighting + PII redaction on tool
|
|
1006
|
+
* output). Contract type owned by `types/` (SE45 / D435) — the implementation
|
|
1007
|
+
* lives in `internal/agent-loop/tool-result-guard.ts`, which re-exports this.
|
|
1008
|
+
*
|
|
1009
|
+
* @public
|
|
1010
|
+
*/
|
|
1011
|
+
interface ToolResultGuardOptions {
|
|
1012
|
+
/** Wrap tool-result content in explicit data boundaries (spotlighting). */
|
|
1013
|
+
delimit?: boolean;
|
|
1014
|
+
/** Redact common PII patterns (email, phone) in tool-result content. */
|
|
1015
|
+
redactPii?: boolean;
|
|
1016
|
+
}
|
|
1017
|
+
/**
|
|
1018
|
+
* Lifecycle status of a {@link Run}.
|
|
1019
|
+
*
|
|
1020
|
+
* @public
|
|
1021
|
+
*/
|
|
1022
|
+
type RunStatus = "running" | "finished" | "error" | "cancelled";
|
|
1023
|
+
/**
|
|
1024
|
+
* Operations that may or may not be supported on a given {@link Run}, or on
|
|
1025
|
+
* its parent agent.
|
|
1026
|
+
*
|
|
1027
|
+
* Runtime-specific availability — query at runtime with `run.supports(op)` and
|
|
1028
|
+
* read the human reason via `run.unsupportedReason(op)`.
|
|
1029
|
+
*
|
|
1030
|
+
* @public
|
|
1031
|
+
*/
|
|
1032
|
+
type RunOperation = "stream" | "wait" | "cancel" | "conversation" | "listArtifacts" | "downloadArtifact" | "runUntil" | "runToCompletion" | "streamToCompletion" | "fork" | "usePersonality" | "workflow";
|
|
1033
|
+
/**
|
|
1034
|
+
* Git metadata attached to cloud runs.
|
|
1035
|
+
*
|
|
1036
|
+
* @public
|
|
1037
|
+
*/
|
|
1038
|
+
interface RunGitInfo {
|
|
1039
|
+
branches: Array<{
|
|
1040
|
+
repoUrl: string;
|
|
1041
|
+
branch?: string;
|
|
1042
|
+
prUrl?: string;
|
|
1043
|
+
}>;
|
|
1044
|
+
}
|
|
1045
|
+
/**
|
|
1046
|
+
* SE3 — provenance of the turn that produced a run: WHO triggered it. Stamped in
|
|
1047
|
+
* the multi-agent path (Squad / a2a / handoff / background-delegation) and
|
|
1048
|
+
* forwarded onto {@link RunResult.origin} — so consumers can attribute/route
|
|
1049
|
+
* turns by their trigger. Metadata-only; discriminate on `kind`. Mirrors the
|
|
1050
|
+
* Anthropic Agent SDK's `origin` shape.
|
|
1051
|
+
*
|
|
1052
|
+
* Encoding note (distinct from absence): an ABSENT origin (`undefined`) means the
|
|
1053
|
+
* provenance was NOT stamped — the default for a plain `agent.send()`. The explicit
|
|
1054
|
+
* `{ kind: "human" }` is a positive marker a HOST stamps to say "this turn is
|
|
1055
|
+
* definitely from a human" (e.g. to distinguish a real user message from an
|
|
1056
|
+
* un-attributed one in an audit UI). The two are not interchangeable: `undefined`
|
|
1057
|
+
* = unknown/unstamped; `{ kind: "human" }` = explicitly human. Consumers writing an
|
|
1058
|
+
* exhaustive `switch (origin?.kind)` therefore handle `undefined` (unstamped) and
|
|
1059
|
+
* `"human"` (explicit) as separate, meaningful cases.
|
|
1060
|
+
*
|
|
1061
|
+
* @public
|
|
1062
|
+
*/
|
|
1063
|
+
/**
|
|
1064
|
+
* SE3 — provenance of a turn (metadata-only; never changes routing/dispatch).
|
|
1065
|
+
* Producers: `peer` (Squad step / a2a envelope), `coordinator` (subagent
|
|
1066
|
+
* delegation), `auto-continuation` (the run-to-completion / stream-to-completion
|
|
1067
|
+
* driver's continuation rounds) are stamped BY the SDK. `human` and
|
|
1068
|
+
* `task-notification` are positive markers a HOST stamps (e.g. re-sending an
|
|
1069
|
+
* agent after a background task completed). Absent origin ⇒ `undefined`.
|
|
1070
|
+
*
|
|
1071
|
+
* @public
|
|
1072
|
+
*/
|
|
1073
|
+
type MessageOrigin =
|
|
1074
|
+
/** Explicitly a human-triggered turn — a positive marker a host stamps (NOT the
|
|
1075
|
+
* same as an absent/unstamped origin, which is `undefined`). */
|
|
1076
|
+
{
|
|
1077
|
+
readonly kind: "human";
|
|
1078
|
+
}
|
|
1079
|
+
/** Another agent (a Squad peer or an a2a sender) triggered this turn. */
|
|
1080
|
+
| {
|
|
1081
|
+
readonly kind: "peer";
|
|
1082
|
+
readonly from: string;
|
|
1083
|
+
}
|
|
1084
|
+
/** A background task's completion re-entered the agent as a follow-up turn. */
|
|
1085
|
+
| {
|
|
1086
|
+
readonly kind: "task-notification";
|
|
1087
|
+
}
|
|
1088
|
+
/** A delegating/handoff coordinator triggered this turn. `from` is the coordinator's
|
|
1089
|
+
* id when known, omitted for an anonymous coordinator. */
|
|
1090
|
+
| {
|
|
1091
|
+
readonly kind: "coordinator";
|
|
1092
|
+
readonly from?: string;
|
|
1093
|
+
}
|
|
1094
|
+
/** The loop's continuation driver re-sent to continue truncated work. */
|
|
1095
|
+
| {
|
|
1096
|
+
readonly kind: "auto-continuation";
|
|
1097
|
+
};
|
|
1098
|
+
/**
|
|
1099
|
+
* Terminal result of a {@link Run}.
|
|
1100
|
+
*
|
|
1101
|
+
* @public
|
|
1102
|
+
*/
|
|
1103
|
+
interface RunResult {
|
|
1104
|
+
id: string;
|
|
1105
|
+
status: "finished" | "error" | "cancelled";
|
|
1106
|
+
result?: string;
|
|
1107
|
+
/**
|
|
1108
|
+
* SE24 — set when a guardrail processor called `abort()`. The run stops
|
|
1109
|
+
* (`status: "cancelled"`) and `tripwire` carries the blocking reason +
|
|
1110
|
+
* processor id. `undefined` on every non-guardrail outcome. A
|
|
1111
|
+
* `throwOnError: true` agent resolves normally on a tripwire (status is
|
|
1112
|
+
* `"cancelled"`, not `"error"`). On an OUTPUT block the model already ran, so
|
|
1113
|
+
* `usage`/`cost` survive (billing) while `result` is suppressed; an INPUT
|
|
1114
|
+
* block never reaches the model, so `usage` is absent.
|
|
1115
|
+
*
|
|
1116
|
+
* @public
|
|
1117
|
+
*/
|
|
1118
|
+
tripwire?: ProcessorTripwire;
|
|
1119
|
+
model?: ModelSelection;
|
|
1120
|
+
durationMs?: number;
|
|
1121
|
+
git?: RunGitInfo;
|
|
1122
|
+
/**
|
|
1123
|
+
* SE3 — provenance forwarded from {@link SendOptions.origin}: who triggered
|
|
1124
|
+
* this turn (human / peer / task-notification / coordinator / auto-continuation).
|
|
1125
|
+
* `undefined` means the provenance was not stamped (a plain `agent.send()`).
|
|
1126
|
+
* Metadata-only — never affects routing.
|
|
1127
|
+
*
|
|
1128
|
+
* @public
|
|
1129
|
+
*/
|
|
1130
|
+
origin?: MessageOrigin;
|
|
1131
|
+
/**
|
|
1132
|
+
* Structured error detail, populated when `status === "error"`. Surfaces
|
|
1133
|
+
* the diagnostic that emit-error-event pushes into the stream so callers
|
|
1134
|
+
* that don't drain `run.stream()` still get the cause via `run.wait()`.
|
|
1135
|
+
*
|
|
1136
|
+
* For successful runs (`status: "finished"`) this is undefined.
|
|
1137
|
+
*
|
|
1138
|
+
* @public
|
|
1139
|
+
*/
|
|
1140
|
+
error?: RunErrorDetail;
|
|
1141
|
+
/**
|
|
1142
|
+
* Token usage observed for this run (ADR D376). Populated in every
|
|
1143
|
+
* status where ≥1 LLM call completed — including partial-failure
|
|
1144
|
+
* runs (EC-5). `undefined` only when zero LLM calls executed (e.g.,
|
|
1145
|
+
* abort before send).
|
|
1146
|
+
*
|
|
1147
|
+
* @public
|
|
1148
|
+
*/
|
|
1149
|
+
usage?: TokenUsage;
|
|
1150
|
+
/**
|
|
1151
|
+
* Estimated/actual USD cost for this run (ADR D377). Always paired
|
|
1152
|
+
* with `usage` when populated. `cost.status` tells caller how to
|
|
1153
|
+
* trust the figure.
|
|
1154
|
+
*
|
|
1155
|
+
* @public
|
|
1156
|
+
*/
|
|
1157
|
+
cost?: CostBreakdown;
|
|
1158
|
+
/**
|
|
1159
|
+
* M1-2: `true` when the run stopped because the agent loop hit its iteration
|
|
1160
|
+
* ceiling (`SendOptions.maxIterations` or the default of 8) while the model
|
|
1161
|
+
* still wanted to call tools — i.e. the work was silently truncated rather
|
|
1162
|
+
* than finished. `undefined`/absent on a clean finish. A continuation driver
|
|
1163
|
+
* (or a careful caller) inspects this to decide whether to send again.
|
|
1164
|
+
*
|
|
1165
|
+
* @public
|
|
1166
|
+
*/
|
|
1167
|
+
stoppedAtIterationLimit?: boolean;
|
|
1168
|
+
/**
|
|
1169
|
+
* `true` when the run stopped because the **doom-loop guard** detected the model repeating
|
|
1170
|
+
* IDENTICAL tool calls (same name + same input) to the hard threshold — making no progress (e.g.
|
|
1171
|
+
* a tool that keeps failing and is retried unchanged). `undefined`/absent otherwise. Through the
|
|
1172
|
+
* continuation driver this surfaces as `terminal: "no_progress"` (a controlled stop, NOT a
|
|
1173
|
+
* truncation to re-send). Tune or disable via {@link SendOptions.doomLoop}.
|
|
1174
|
+
*
|
|
1175
|
+
* @public
|
|
1176
|
+
*/
|
|
1177
|
+
stoppedByDoomLoop?: boolean;
|
|
1178
|
+
/**
|
|
1179
|
+
* SE34 — the per-send completion verdict, populated when
|
|
1180
|
+
* {@link SendOptions.completionCheck} was set AND the run finished. Absent on
|
|
1181
|
+
* non-finished runs and when no completion check was requested. Reuses the
|
|
1182
|
+
* shipped LLM-as-judge (same one `runUntil` drives). @public
|
|
1183
|
+
*/
|
|
1184
|
+
completionCheck?: CompletionCheckResult;
|
|
1185
|
+
}
|
|
1186
|
+
/**
|
|
1187
|
+
* Doom-loop guard thresholds (see {@link SendOptions.doomLoop}). Both are counts of CONSECUTIVE
|
|
1188
|
+
* identical tool calls: `softThreshold` injects a one-time guidance nudge; `hardThreshold` stops.
|
|
1189
|
+
*
|
|
1190
|
+
* @public
|
|
1191
|
+
*/
|
|
1192
|
+
interface DoomLoopThresholds {
|
|
1193
|
+
/** Consecutive-identical count at which a one-time guidance nudge is injected. Default 3. */
|
|
1194
|
+
softThreshold?: number;
|
|
1195
|
+
/** Consecutive-identical count at which the run stops (`no_progress`). Default 5. */
|
|
1196
|
+
hardThreshold?: number;
|
|
1197
|
+
}
|
|
1198
|
+
/**
|
|
1199
|
+
* Options for {@link SDKAgent.runToCompletion} (M1 Phase 3 — continuation driver).
|
|
1200
|
+
*
|
|
1201
|
+
* @public
|
|
1202
|
+
*/
|
|
1203
|
+
interface RunToCompletionOptions {
|
|
1204
|
+
/**
|
|
1205
|
+
* Maximum number of continuation rounds (re-sends) before giving up with
|
|
1206
|
+
* `terminal: "step_limit"`. Default 5. A hard ceiling that prevents a
|
|
1207
|
+
* runaway loop when the model keeps truncating.
|
|
1208
|
+
*/
|
|
1209
|
+
maxRounds?: number;
|
|
1210
|
+
/**
|
|
1211
|
+
* The short prompt re-sent after a truncated round to make the (stateful)
|
|
1212
|
+
* agent resume. Defaults to a generic "continue" instruction. The original
|
|
1213
|
+
* conversation is preserved by the agent's session, so this need not repeat
|
|
1214
|
+
* the task.
|
|
1215
|
+
*/
|
|
1216
|
+
continuationPrompt?: string;
|
|
1217
|
+
/** Called once per truncated round that triggers a re-send (for metrics/logging). */
|
|
1218
|
+
onTruncated?: (event: {
|
|
1219
|
+
round: number;
|
|
1220
|
+
}) => void | Promise<void>;
|
|
1221
|
+
/** Abort signal; checked between rounds — once aborted, no further round starts. */
|
|
1222
|
+
signal?: AbortSignal;
|
|
1223
|
+
/** Per-send options forwarded to each underlying `send()` (e.g. `maxIterations`). */
|
|
1224
|
+
sendOptions?: SendOptions;
|
|
1225
|
+
}
|
|
1226
|
+
/**
|
|
1227
|
+
* Result of {@link SDKAgent.runToCompletion}.
|
|
1228
|
+
*
|
|
1229
|
+
* @public
|
|
1230
|
+
*/
|
|
1231
|
+
interface RunToCompletionResult {
|
|
1232
|
+
/**
|
|
1233
|
+
* Why the driver stopped:
|
|
1234
|
+
* - `"done"` — a round finished without truncating (the model is done).
|
|
1235
|
+
* - `"step_limit"` — `maxRounds` exhausted (or aborted) while still truncating.
|
|
1236
|
+
* - `"no_progress"` — two consecutive rounds produced empty output.
|
|
1237
|
+
*/
|
|
1238
|
+
terminal: "done" | "step_limit" | "no_progress";
|
|
1239
|
+
/**
|
|
1240
|
+
* Index of the final round. Round 0 is the initial `send`; rounds ≥ 1 are
|
|
1241
|
+
* continuation re-sends. So `terminal: "done"` with `rounds: 0` means the
|
|
1242
|
+
* first send finished without truncating; `rounds: N` means N continuation
|
|
1243
|
+
* re-sends happened. For `step_limit`, `rounds` equals `maxRounds`.
|
|
1244
|
+
*/
|
|
1245
|
+
rounds: number;
|
|
1246
|
+
/** The `RunResult` of the final round. */
|
|
1247
|
+
lastResult: RunResult;
|
|
1248
|
+
/** Token usage summed across all rounds; `undefined` when no round reported usage. */
|
|
1249
|
+
usage?: TokenUsage;
|
|
1250
|
+
}
|
|
1251
|
+
/**
|
|
1252
|
+
* Result of {@link SDKAgent.streamToCompletion} (V3-4 — the STREAMING continuation
|
|
1253
|
+
* driver). Same shape + terminal semantics as {@link RunToCompletionResult}; it is
|
|
1254
|
+
* the generator's RETURN value (read it via a manual `gen.next()` loop — a plain
|
|
1255
|
+
* `for await...of` consumes the yielded `SDKMessage`s but discards this return value).
|
|
1256
|
+
*
|
|
1257
|
+
* @public
|
|
1258
|
+
*/
|
|
1259
|
+
type StreamToCompletionResult = RunToCompletionResult;
|
|
1260
|
+
/**
|
|
1261
|
+
* Structured error attached to a {@link RunResult} when the underlying run
|
|
1262
|
+
* transitioned to `"error"` status. `message` is always present; `code` is
|
|
1263
|
+
* a stable identifier suitable for branching (e.g. `"llm_4xx"`,
|
|
1264
|
+
* `"tool_dispatch_failed"`, `"mcp_init_failed"`); `cause` is the raw error
|
|
1265
|
+
* for further inspection when available.
|
|
1266
|
+
*
|
|
1267
|
+
* @public
|
|
1268
|
+
*/
|
|
1269
|
+
interface RunErrorDetail {
|
|
1270
|
+
message: string;
|
|
1271
|
+
code?: string;
|
|
1272
|
+
cause?: unknown;
|
|
1273
|
+
}
|
|
1274
|
+
/**
|
|
1275
|
+
* Dimensions of an inline image attachment.
|
|
1276
|
+
*
|
|
1277
|
+
* @public
|
|
1278
|
+
*/
|
|
1279
|
+
interface SDKImageDimension {
|
|
1280
|
+
width: number;
|
|
1281
|
+
height: number;
|
|
1282
|
+
}
|
|
1283
|
+
/**
|
|
1284
|
+
* Either a remote URL or inline base64 payload.
|
|
1285
|
+
*
|
|
1286
|
+
* @public
|
|
1287
|
+
*/
|
|
1288
|
+
type SDKImage = {
|
|
1289
|
+
url: string;
|
|
1290
|
+
dimension?: SDKImageDimension;
|
|
1291
|
+
} | {
|
|
1292
|
+
data: string;
|
|
1293
|
+
mimeType: string;
|
|
1294
|
+
dimension?: SDKImageDimension;
|
|
1295
|
+
};
|
|
1296
|
+
/**
|
|
1297
|
+
* Structured form of `agent.send()`'s message argument. Use it to send images
|
|
1298
|
+
* alongside text.
|
|
1299
|
+
*
|
|
1300
|
+
* @public
|
|
1301
|
+
*/
|
|
1302
|
+
interface SDKUserMessage {
|
|
1303
|
+
text: string;
|
|
1304
|
+
images?: SDKImage[];
|
|
1305
|
+
}
|
|
1306
|
+
/**
|
|
1307
|
+
* Per-send overrides and callbacks.
|
|
1308
|
+
*
|
|
1309
|
+
* @public
|
|
1310
|
+
*/
|
|
1311
|
+
interface SendOptions {
|
|
1312
|
+
/**
|
|
1313
|
+
* Per-send model override. SE8 — accepts a bare-string id shorthand
|
|
1314
|
+
* (`"openai/gpt-4o-mini"`, normalized to `{ id }`) OR a {@link ModelSelection}
|
|
1315
|
+
* object (use the object form to pass `params`).
|
|
1316
|
+
*/
|
|
1317
|
+
model?: string | ModelSelection;
|
|
1318
|
+
/**
|
|
1319
|
+
* SE3 — provenance of this turn (who triggered it). Stamped by the multi-agent
|
|
1320
|
+
* path (Squad peer, a2a sender, coordinator/handoff, background task-notification)
|
|
1321
|
+
* and forwarded onto {@link RunResult.origin}. Metadata-only — the value never
|
|
1322
|
+
* changes routing or dispatch. Omit to leave the turn un-attributed; a host may
|
|
1323
|
+
* pass `{ kind: "human" }` to positively mark a human turn.
|
|
1324
|
+
*/
|
|
1325
|
+
origin?: MessageOrigin;
|
|
1326
|
+
/**
|
|
1327
|
+
* SE2 — opt-in typed runtime-EVENT sink. Receives out-of-band `RunEvent`s
|
|
1328
|
+
* (permission_denied, tool_progress, rate_limit, task_*, compact_boundary) for
|
|
1329
|
+
* observability, ADDITIVE to the `SDKMessage` content stream. Best-effort: a
|
|
1330
|
+
* throwing sink never breaks the run. Discriminate on `event.type`.
|
|
1331
|
+
*/
|
|
1332
|
+
onRunEvent?: RunEventSink;
|
|
1333
|
+
/**
|
|
1334
|
+
* Doom-loop guard config. The loop stops (with `terminal: "no_progress"`, `RunResult.stoppedByDoomLoop`)
|
|
1335
|
+
* when the model repeats IDENTICAL tool calls to the hard threshold. On by default with generous
|
|
1336
|
+
* thresholds (soft 3 / hard 5). Set `false` to disable, or an object to tune the thresholds.
|
|
1337
|
+
*/
|
|
1338
|
+
doomLoop?: false | DoomLoopThresholds;
|
|
1339
|
+
/**
|
|
1340
|
+
* Per-call system prompt override. Wins over `AgentOptions.systemPrompt`.
|
|
1341
|
+
* String only — for dynamic resolvers, configure on `AgentOptions`. An
|
|
1342
|
+
* empty string is honoured (it explicitly clears the system context).
|
|
1343
|
+
*/
|
|
1344
|
+
systemPrompt?: string;
|
|
1345
|
+
/** Fully replaces creation-time servers for this run (not merged). */
|
|
1346
|
+
mcpServers?: Record<string, McpServerConfig>;
|
|
1347
|
+
/**
|
|
1348
|
+
* Per-call inline custom tools. Fully replaces `AgentOptions.tools` for
|
|
1349
|
+
* this run (not merged). Local runtime only — cloud agents reject any
|
|
1350
|
+
* non-empty per-call tools array with the same error code as creation
|
|
1351
|
+
* (`cloud_custom_tools_rejected`). Semantics:
|
|
1352
|
+
* - `undefined` → fall back to `AgentOptions.tools`
|
|
1353
|
+
* - `[]` → explicitly clear (no custom tools for this run)
|
|
1354
|
+
* - `[t1, t2]` → use exactly these tools for this run
|
|
1355
|
+
*/
|
|
1356
|
+
tools?: CustomTool[];
|
|
1357
|
+
/**
|
|
1358
|
+
* The set of repo-relative file paths in scope for THIS send (local runtime).
|
|
1359
|
+
* Declares "which files am I working on" so path-scoped rule files
|
|
1360
|
+
* (`.theokit/rules/*.md` with `paths:`/`globs:`, and `.cursor/rules/*.mdc`
|
|
1361
|
+
* globs) activate when a pattern matches one of these paths. `alwaysApply`
|
|
1362
|
+
* rules load regardless. Omit ⇒ only unconditional rules load (the create-time
|
|
1363
|
+
* snapshot is untouched). Matching is glob-based (`**`, `*`, `?`).
|
|
1364
|
+
*/
|
|
1365
|
+
contextPaths?: readonly string[];
|
|
1366
|
+
/**
|
|
1367
|
+
* SE1 — the permission mode for THIS run, threaded to a registered
|
|
1368
|
+
* `PermissionPlugin`'s pre-tool gate. Precedence: this per-send value wins over
|
|
1369
|
+
* `AgentOptions.permissionMode` (creation-time default). Modes: `default` (rules
|
|
1370
|
+
* decide; unmatched ⇒ fail-closed ask), `plan` (read-only — allow rules pass,
|
|
1371
|
+
* everything else denied), `acceptEdits` (auto-approve unmatched, honor explicit
|
|
1372
|
+
* ask rules), `bypass` / `bypassPermissions` (allow all except an explicit deny).
|
|
1373
|
+
* Absent ⇒ the plugin's own construction-time mode applies. Local runtime.
|
|
1374
|
+
*/
|
|
1375
|
+
permissionMode?: PermissionMode;
|
|
1376
|
+
onStep?: (args: {
|
|
1377
|
+
step: ConversationStep;
|
|
1378
|
+
}) => void | Promise<void>;
|
|
1379
|
+
onDelta?: (args: {
|
|
1380
|
+
update: InteractionUpdate;
|
|
1381
|
+
}) => void | Promise<void>;
|
|
1382
|
+
/**
|
|
1383
|
+
* Per-call tool gate (OpenAI/OpenRouter `tool_choice`). `"none"` forces a text answer even when
|
|
1384
|
+
* the agent has tools registered — used by an agent loop to force a closing summary at its step
|
|
1385
|
+
* ceiling (a cached agent's tools cannot be un-registered, so the gate is per-send). `"required"`
|
|
1386
|
+
* forces a tool call; `"auto"` (or omitted) is the default. Local runtime; OpenAI-compat providers.
|
|
1387
|
+
*/
|
|
1388
|
+
toolChoice?: "auto" | "none" | "required";
|
|
1389
|
+
/**
|
|
1390
|
+
* SE18 — per-send runtime tool subset (**local runtime only**; cloud agents
|
|
1391
|
+
* ignore it). When set, only tools whose name is in this list may be called for
|
|
1392
|
+
* this send; a call to any other registered tool is vetoed at dispatch (the same
|
|
1393
|
+
* `withToolWhitelist` path `Agent.fork`'s `allowedTools` uses — NOT
|
|
1394
|
+
* `PermissionEngine`). Composes with `toolChoice`: `activeTools` narrows the set,
|
|
1395
|
+
* `toolChoice` gates calling within it. Absent ⇒ the full toolset is available.
|
|
1396
|
+
*
|
|
1397
|
+
* Matching is EXACT against the tool's registered name — the same name the
|
|
1398
|
+
* dispatch sees after tool-name repair (mirrors `Agent.fork`'s `allowedTools`;
|
|
1399
|
+
* it is NOT lowercased for you, so a mixed-case registered tool needs its exact
|
|
1400
|
+
* registered name here). An empty list (`[]`) vetoes EVERY tool (fail-closed —
|
|
1401
|
+
* "restrict to the empty set"); pass `undefined` (or omit) for no restriction.
|
|
1402
|
+
* A subagent invoked within this send inherits the whitelist via async-context
|
|
1403
|
+
* propagation unless it declares its own tool scope.
|
|
1404
|
+
*/
|
|
1405
|
+
activeTools?: string[];
|
|
1406
|
+
/** Local agents only. Expire a stuck active run before starting this message. */
|
|
1407
|
+
local?: {
|
|
1408
|
+
force?: boolean;
|
|
1409
|
+
};
|
|
1410
|
+
/**
|
|
1411
|
+
* Optional `AbortSignal` propagated to memory adapter `pre_user_send`
|
|
1412
|
+
* hooks (EC-H). Note: the LLM HTTP call itself is NOT cancellable
|
|
1413
|
+
* mid-stream — same constraint as `Agent.batch` (ADR D140).
|
|
1414
|
+
*
|
|
1415
|
+
* @public
|
|
1416
|
+
*/
|
|
1417
|
+
signal?: AbortSignal;
|
|
1418
|
+
/**
|
|
1419
|
+
* M7 — an opaque user `context` forwarded to every tool handler's `ctx.context`
|
|
1420
|
+
* for this run. Set shared config (e.g. `projectRoot`) once here instead of
|
|
1421
|
+
* baking it into each tool factory (mirrors a framework `experimental_context`,
|
|
1422
|
+
* a peer framework `RuntimeContext`, a peer SDK `RunContext`).
|
|
1423
|
+
*
|
|
1424
|
+
* @public
|
|
1425
|
+
*/
|
|
1426
|
+
context?: unknown;
|
|
1427
|
+
/**
|
|
1428
|
+
* #58 — per-tool execution timeout in ms. Each tool call is bounded by this
|
|
1429
|
+
* deadline (merged with `signal`); a hung tool yields a typed timeout result
|
|
1430
|
+
* (exit 124) instead of wedging the run. Undefined = no per-tool timeout.
|
|
1431
|
+
*
|
|
1432
|
+
* @public
|
|
1433
|
+
*/
|
|
1434
|
+
perToolTimeoutMs?: number;
|
|
1435
|
+
/**
|
|
1436
|
+
* #57 — opt-in tool-result content guard applied before tool output reaches
|
|
1437
|
+
* the LLM. `{ delimit: true }` frames untrusted tool output as data
|
|
1438
|
+
* (prompt-injection mitigation); `{ redactPii: true }` redacts email/phone.
|
|
1439
|
+
* Undefined = no guard.
|
|
1440
|
+
*
|
|
1441
|
+
* @public
|
|
1442
|
+
*/
|
|
1443
|
+
toolResultGuard?: ToolResultGuardOptions;
|
|
1444
|
+
/**
|
|
1445
|
+
* Opt-in task wrapping (ADRs D363, D374). When truthy, the entire
|
|
1446
|
+
* run is registered as a `Task` in the SDK's observable registry —
|
|
1447
|
+
* caller can list / inspect / cancel / subscribe via the `Task`
|
|
1448
|
+
* namespace. Default behavior (no `task` option) is byte-identical
|
|
1449
|
+
* to v1.1 (no Task overhead).
|
|
1450
|
+
*
|
|
1451
|
+
* Accepts:
|
|
1452
|
+
* - `true` — auto-generate task id; no extra metadata.
|
|
1453
|
+
* - `{ id, meta }` — user-supplied id (D368 grammar enforced) and/or
|
|
1454
|
+
* metadata attached to the handle's `meta` field.
|
|
1455
|
+
*
|
|
1456
|
+
* The work-fn `signal` is **merged** with `options.signal` (whichever
|
|
1457
|
+
* aborts first wins). Local agents only — CloudAgent throws
|
|
1458
|
+
* `UnsupportedTaskOperationError` (D370).
|
|
1459
|
+
*
|
|
1460
|
+
* @public
|
|
1461
|
+
*/
|
|
1462
|
+
task?: true | {
|
|
1463
|
+
id?: string;
|
|
1464
|
+
meta?: Record<string, unknown>;
|
|
1465
|
+
};
|
|
1466
|
+
/**
|
|
1467
|
+
* Per-send ceiling on the agent loop's tool-calling turns (M1-2). Raises (or
|
|
1468
|
+
* lowers) the default cap of 8 for this single send — useful when one heavy
|
|
1469
|
+
* task needs more rounds than the agent's default. Must be a positive
|
|
1470
|
+
* integer; invalid values throw `ConfigurationError` at the boundary. When
|
|
1471
|
+
* unset, the loop uses the default of 8.
|
|
1472
|
+
*
|
|
1473
|
+
* @public
|
|
1474
|
+
*/
|
|
1475
|
+
maxIterations?: number;
|
|
1476
|
+
/**
|
|
1477
|
+
* SE34 — per-send completion check (`isTaskComplete`). After this single
|
|
1478
|
+
* `send()` reaches a terminal `finished` state, the shipped LLM-as-judge
|
|
1479
|
+
* scores the final reply against `criteria` and surfaces the verdict on
|
|
1480
|
+
* {@link RunResult.completionCheck} + a `completion_check` run-event. This is
|
|
1481
|
+
* the finer-grained, single-`send()` gate (contrast `runUntil`, which judges
|
|
1482
|
+
* the FULL response BETWEEN sends). Opt-in — absent ⇒ the send is byte-identical
|
|
1483
|
+
* to today (no extra judge call). Non-finished runs skip the check. The judge
|
|
1484
|
+
* runs when `wait()` is called on the returned `Run`; a stream-only consumer
|
|
1485
|
+
* must call `wait()` to trigger the verdict + the `completion_check` event.
|
|
1486
|
+
*
|
|
1487
|
+
* @public
|
|
1488
|
+
*/
|
|
1489
|
+
completionCheck?: CompletionCheck;
|
|
1490
|
+
}
|
|
1491
|
+
/**
|
|
1492
|
+
* SE34 — the per-send completion criterion (see {@link SendOptions.completionCheck}).
|
|
1493
|
+
*
|
|
1494
|
+
* @public
|
|
1495
|
+
*/
|
|
1496
|
+
interface CompletionCheck {
|
|
1497
|
+
/** What "complete" means for this send — fed to the judge as the goal. */
|
|
1498
|
+
criteria: string;
|
|
1499
|
+
/** Judge model identifier. Default `"openai/gpt-4o-mini"`. */
|
|
1500
|
+
judgeModel?: string;
|
|
1501
|
+
/** Override env for the judge auxiliary agent. Default `OPENROUTER_API_KEY`. */
|
|
1502
|
+
apiKey?: string;
|
|
1503
|
+
}
|
|
1504
|
+
/**
|
|
1505
|
+
* SE34 — the resolved per-send completion verdict (see {@link RunResult.completionCheck}).
|
|
1506
|
+
*
|
|
1507
|
+
* @public
|
|
1508
|
+
*/
|
|
1509
|
+
interface CompletionCheckResult {
|
|
1510
|
+
/** `true` when the judge ruled the send's reply satisfies the criteria. */
|
|
1511
|
+
complete: boolean;
|
|
1512
|
+
/** The judge's stated reason. */
|
|
1513
|
+
reason: string;
|
|
1514
|
+
/** `true` when the judge output could not be parsed — fail-safe `complete: false`. */
|
|
1515
|
+
parseFailed: boolean;
|
|
1516
|
+
}
|
|
1517
|
+
/**
|
|
1518
|
+
* Handle to a single prompt submission.
|
|
1519
|
+
*
|
|
1520
|
+
* @public
|
|
1521
|
+
*/
|
|
1522
|
+
interface Run {
|
|
1523
|
+
readonly id: string;
|
|
1524
|
+
readonly agentId: string;
|
|
1525
|
+
readonly status: RunStatus;
|
|
1526
|
+
readonly result?: string;
|
|
1527
|
+
readonly model?: ModelSelection;
|
|
1528
|
+
readonly durationMs?: number;
|
|
1529
|
+
readonly git?: RunGitInfo;
|
|
1530
|
+
readonly createdAt?: number;
|
|
1531
|
+
/** AsyncGenerator of normalized stream events. Discriminate on `event.type`. */
|
|
1532
|
+
stream(): AsyncGenerator<SDKMessage, void>;
|
|
1533
|
+
/** Resolves to the terminal {@link RunResult}. */
|
|
1534
|
+
wait(): Promise<RunResult>;
|
|
1535
|
+
/** Move status to `"cancelled"`, abort the stream, stop in-flight tool calls. */
|
|
1536
|
+
cancel(): Promise<void>;
|
|
1537
|
+
/** Structured per-turn view of the conversation. */
|
|
1538
|
+
conversation(): Promise<ConversationTurn[]>;
|
|
1539
|
+
/** Whether the given operation is available on this run's runtime. */
|
|
1540
|
+
supports(operation: RunOperation): boolean;
|
|
1541
|
+
/** Human-readable reason that `supports(operation)` returned `false`. */
|
|
1542
|
+
unsupportedReason(operation: RunOperation): string | undefined;
|
|
1543
|
+
/** Subscribe to status changes. Returns an unsubscribe function. */
|
|
1544
|
+
onDidChangeStatus(listener: (status: RunStatus) => void): () => void;
|
|
1545
|
+
}
|
|
1546
|
+
/**
|
|
1547
|
+
* SE9 — options for the integrated structured-output method `agent.generate`: the
|
|
1548
|
+
* {@link SendOptions} that drive the tool loop (phase 1) plus the required `output`
|
|
1549
|
+
* Zod schema and structuring knobs (phase 2). Co-located with `SendOptions` /
|
|
1550
|
+
* `RunResult` (which they extend/use) so the public `SDKAgent` interface does not
|
|
1551
|
+
* import the runtime `agent-generate` module (breaks the type cycle).
|
|
1552
|
+
*
|
|
1553
|
+
* @public
|
|
1554
|
+
*/
|
|
1555
|
+
interface GenerateOptions<T extends zod.ZodType> extends SendOptions {
|
|
1556
|
+
/** Zod schema the final answer is coerced into (the structuring contract). */
|
|
1557
|
+
output: T;
|
|
1558
|
+
/** Retry budget on the structuring phase's parse-failures (reused from generateObject). Default 1. */
|
|
1559
|
+
maxRetries?: number;
|
|
1560
|
+
/**
|
|
1561
|
+
* What the STRUCTURING phase (phase 2) does when the model's output still fails
|
|
1562
|
+
* Zod validation after retries. Default `"throw"`. `"return-partial"` / `"return-raw"`
|
|
1563
|
+
* salvage the object; the salvaged/raw value is in {@link GenerateRunResult.raw}
|
|
1564
|
+
* (the pre-parse structuring input) — NOT the phase-1 text answer, which is in
|
|
1565
|
+
* `result.result`.
|
|
1566
|
+
*/
|
|
1567
|
+
errorStrategy?: "throw" | "return-partial" | "return-raw";
|
|
1568
|
+
}
|
|
1569
|
+
/**
|
|
1570
|
+
* SE9 — result of `agent.generate`: the validated typed object plus the underlying
|
|
1571
|
+
* tool-loop {@link RunResult} (status / usage / model) and the raw pre-parse input.
|
|
1572
|
+
*
|
|
1573
|
+
* @public
|
|
1574
|
+
*/
|
|
1575
|
+
interface GenerateRunResult<O> {
|
|
1576
|
+
/** The validated object — inferred type from the `output` schema. */
|
|
1577
|
+
object: O;
|
|
1578
|
+
/** The underlying tool-loop run (phase 1). */
|
|
1579
|
+
result: RunResult;
|
|
1580
|
+
/** Raw model input to the synthetic `output` tool, before the Zod parse. */
|
|
1581
|
+
raw: unknown;
|
|
1582
|
+
/** Combined token usage of the structuring phase. */
|
|
1583
|
+
usage: {
|
|
1584
|
+
inputTokens: number;
|
|
1585
|
+
outputTokens: number;
|
|
1586
|
+
};
|
|
1587
|
+
}
|
|
1588
|
+
|
|
1589
|
+
export { type RunToCompletionResult as $, type AgentConversationTurn as A, type ProcessorControls as B, type CustomTool as C, type DoomLoopThresholds as D, type ProcessorTripwire as E, type ProcessorViolation as F, type GenerateOptions as G, type RunCompactBoundaryEvent as H, type ImageBlock as I, type RunCompletionCheckEvent as J, type RunErrorDetail as K, type RunEvent as L, type ModelSelection as M, type RunGitInfo as N, type OutputProcessorContext as O, type Processor as P, type RunOperation as Q, type RunResult as R, type SDKMessage as S, type ToolResultContentBlock as T, type RunPermissionDeniedEvent as U, type RunRateLimitEvent as V, type RunStatus as W, type RunTaskCompletedEvent as X, type RunTaskStartedEvent as Y, type RunTaskUpdatedEvent as Z, type RunToCompletionOptions as _, type McpServerConfig as a, type RunToolProgressEvent as a0, type RunTripwireEvent as a1, type SDKAssistantMessage as a2, type SDKImage as a3, type SDKImageDimension as a4, type SDKObjectDelta as a5, type SDKRequestMessage as a6, type SDKStatusMessage as a7, type SDKSystemMessage as a8, type SDKTaskMessage as a9, type ToolResult as aA, type ToolResultGuardOptions as aB, type ToolUseBlock as aC, type TurnEndedUpdate as aD, type UserMessage as aE, type UserMessageAppendedUpdate as aF, applyMode as aG, emitRunEvent as aH, type SDKThinkingMessage as aa, type SDKToolUseMessage as ab, type SDKUserMessage as ac, type SDKUserMessageEvent as ad, type SendOptions as ae, type ShellCommand as af, type ShellConversationTurn as ag, type ShellOutput as ah, type ShellOutputDeltaUpdate as ai, type StepCompletedUpdate as aj, type StepStartedUpdate as ak, type StreamToCompletionResult as al, type SummaryCompletedUpdate as am, type SummaryStartedUpdate as an, type SummaryUpdate as ao, type TextBlock as ap, type TextDeltaUpdate as aq, type ThinkingCompletedUpdate as ar, type ThinkingDeltaUpdate as as, type ThinkingMessage as at, type TokenDeltaUpdate as au, type TokenUsage as av, type ToolCall as aw, type ToolCallCompletedUpdate as ax, type ToolCallStartedUpdate as ay, type ToolContextMessage as az, type Run as b, type PermissionMode as c, PermissionEngine as d, type RunEventSink as e, type AssistantMessage as f, type CompletionCheck as g, type CompletionCheckResult as h, type ConversationStep as i, type ConversationTurn as j, type CostBreakdown as k, type CostSource as l, type CostStatus as m, type GenerateRunResult as n, type InputProcessorContext as o, type InteractionUpdate as p, type McpAuthConfig as q, type McpHttpServerConfig as r, type McpOAuthConfig as s, type McpStdioServerConfig as t, type MessageOrigin as u, type ModelParameterValue as v, type PartialToolCallUpdate as w, type PermissionAction as x, type PermissionEngineOptions as y, type PermissionRule as z };
|