@tangle-network/sandbox 0.0.0-develop.20260514223840.b2abd84

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.
@@ -0,0 +1,642 @@
1
+ import { Response, ResponseCreateParamsBase, ResponseOutputItem, ResponseStreamEvent, ResponseUsage } from "openai/resources/responses/responses";
2
+ import { ChatCompletionChunk, ChatCompletionMessageParam, ChatCompletionTool } from "openai/resources/chat/completions/completions";
3
+ import { Completion } from "openai/resources/completions";
4
+ import { EmbeddingCreateParams } from "openai/resources/embeddings";
5
+
6
+ //#region src/openai/hooks.d.ts
7
+ /**
8
+ * Tool-call hook surface.
9
+ *
10
+ * Every tool dispatched by the Run executor flows through an ordered
11
+ * `HookChain`. Hooks observe the call (`beforeToolCall`) and the result
12
+ * (`afterToolCall`) and may allow, rewrite, block, override, or
13
+ * terminate. The chain composes built-in hooks (audit-log, egress
14
+ * policy, cost cap, rate limit, destructive-action guard, screenshot
15
+ * redaction) with partner-supplied hooks. The route layer wires the
16
+ * chain into the Run state machine in `runs.ts`.
17
+ *
18
+ * Semantics:
19
+ * - `beforeToolCall`: `allow` → next hook; `rewrite` → mutates the
20
+ * args carried into subsequent hooks and the executor; `block` →
21
+ * short-circuits the chain and is surfaced as an error tool result.
22
+ * - `afterToolCall`: `pass` → next hook; `override` → mutates the
23
+ * result carried into subsequent hooks and the response; `terminate`
24
+ * → short-circuits and ends the run with the supplied reason.
25
+ */
26
+ interface ToolCallContext {
27
+ runId: string;
28
+ threadId?: string;
29
+ partnerId: string;
30
+ toolName: string;
31
+ args: unknown;
32
+ callId: string;
33
+ timestamp: number;
34
+ }
35
+ interface ToolResult {
36
+ content: unknown;
37
+ isError?: boolean;
38
+ details?: Record<string, unknown>;
39
+ }
40
+ type BeforeHookOutcome = {
41
+ action: "allow";
42
+ } | {
43
+ action: "block";
44
+ reason: string;
45
+ } | {
46
+ action: "rewrite";
47
+ args: unknown;
48
+ };
49
+ type AfterHookOutcome = {
50
+ action: "pass";
51
+ } | {
52
+ action: "override";
53
+ result: ToolResult;
54
+ } | {
55
+ action: "terminate";
56
+ reason: string;
57
+ };
58
+ interface HookSurface {
59
+ beforeToolCall?(ctx: ToolCallContext): Promise<BeforeHookOutcome>;
60
+ afterToolCall?(ctx: ToolCallContext, result: ToolResult): Promise<AfterHookOutcome>;
61
+ }
62
+ /**
63
+ * Sequential hook composer. Hooks run in registration order; `block` and
64
+ * `terminate` short-circuit. `rewrite` and `override` thread their
65
+ * mutated payloads through to the remaining hooks so subsequent hooks
66
+ * observe the rewritten args / overridden result.
67
+ */
68
+ declare class HookChain {
69
+ private readonly hooks;
70
+ constructor(hooks?: HookSurface[]);
71
+ /** Number of hooks in the chain. */
72
+ get size(): number;
73
+ /**
74
+ * Run every `beforeToolCall` in registration order. Returns the first
75
+ * non-`allow` outcome (block/rewrite), or `allow` if the chain ran
76
+ * clean. `rewrite` outcomes are threaded forward so later hooks see
77
+ * the mutated args.
78
+ */
79
+ runBefore(ctx: ToolCallContext): Promise<BeforeHookOutcome>;
80
+ /**
81
+ * Run every `afterToolCall` in registration order. Returns the first
82
+ * `terminate` outcome immediately. `override` outcomes are threaded
83
+ * forward so later hooks see the mutated result; the final result is
84
+ * surfaced as the last `override`, or `pass` if no hook overrode.
85
+ */
86
+ runAfter(ctx: ToolCallContext, result: ToolResult): Promise<AfterHookOutcome>;
87
+ }
88
+ interface AuditEvent {
89
+ phase: "before" | "after";
90
+ runId: string;
91
+ threadId?: string;
92
+ partnerId: string;
93
+ toolName: string;
94
+ callId: string;
95
+ timestamp: number;
96
+ args?: unknown;
97
+ result?: ToolResult;
98
+ }
99
+ interface AuditLogOptions {
100
+ sink?: (event: AuditEvent) => Promise<void> | void;
101
+ }
102
+ /**
103
+ * Emits a structured `AuditEvent` for every tool call (before + after).
104
+ * Default sink is `console.info`. The route layer swaps the sink for
105
+ * the eval-runs DuckDB writer.
106
+ */
107
+ declare function auditLogHook(opts?: AuditLogOptions): HookSurface;
108
+ interface EgressPolicyOptions {
109
+ allowList?: string[];
110
+ denyList?: string[];
111
+ allowFn?: (ctx: ToolCallContext) => Promise<boolean>;
112
+ }
113
+ /**
114
+ * Best-effort allow/deny filter for tool-call URLs.
115
+ *
116
+ * Block tool calls that look network-ish (toolName matches the network
117
+ * regex OR args contain url-like fields) when the resolved host hits
118
+ * the deny list. The allow list is treated as an explicit allowance —
119
+ * when set, only listed hosts pass; unmatched hosts are blocked.
120
+ * `allowFn` overrides both lists when present.
121
+ *
122
+ * **What this hook does NOT catch.** It inspects URL-shaped strings in
123
+ * the tool-call arguments only. The following bypass it silently:
124
+ *
125
+ * - URLs encoded as base64 / hex / `Buffer.from(...)` literals
126
+ * - URLs assembled at execution time from string fragments
127
+ * - URLs reached via redirects, DNS rebinding, or proxy hosts that
128
+ * match the allow list but forward to denied destinations
129
+ * - Network calls made by spawned subprocesses, generated code, or
130
+ * tools whose argument schema does not name a URL field
131
+ *
132
+ * Treat this hook as a UX guardrail (clearer error messages,
133
+ * short-circuiting obvious mistakes) on top of a real egress boundary
134
+ * — not as one. When egress containment is a security requirement
135
+ * (exfil prevention, data residency), enforce it at the runtime
136
+ * sandbox layer (egress firewall, CNI policy, outbound proxy with
137
+ * mTLS) where the agent cannot evade it.
138
+ */
139
+ declare function egressPolicyHook(opts?: EgressPolicyOptions): HookSurface;
140
+ interface CostCapOptions {
141
+ ceiling: number;
142
+ getCurrentCost?: (partnerId: string) => Promise<number>;
143
+ }
144
+ /**
145
+ * Terminates the run when the partner's accumulated cost is at or
146
+ * above `ceiling`. The cost lookup is injected so any usage ledger can
147
+ * back it.
148
+ */
149
+ declare function costCapHook(opts: CostCapOptions): HookSurface;
150
+ interface ActionRateLimitOptions {
151
+ perSecondPerSession: number;
152
+ /** Optional clock injection for tests. Defaults to `Date.now`. */
153
+ now?: () => number;
154
+ }
155
+ /**
156
+ * Token-bucket rate limiter scoped per session id (`runId`) over
157
+ * `computer-use:*` tool calls. Excess calls are blocked with a clear
158
+ * reason. Non-`computer-use` tools pass through untouched.
159
+ */
160
+ declare function actionRateLimitHook(opts: ActionRateLimitOptions): HookSurface;
161
+ interface RedactionRegion {
162
+ x: number;
163
+ y: number;
164
+ w: number;
165
+ h: number;
166
+ }
167
+ interface ScreenshotRedactionOptions {
168
+ regions?: RedactionRegion[];
169
+ /** Optional logger for the no-sharp warning path. Defaults to `console.warn`. */
170
+ warn?: (msg: string) => void;
171
+ }
172
+ /**
173
+ * Applied AFTER `computer-use:screenshot`. v1 ships without the
174
+ * `sharp` dependency: when regions are configured, we surface a warning
175
+ * exactly once per process and pass the screenshot through untouched.
176
+ * Pixel-blur lands in a follow-up that introduces `sharp` deliberately.
177
+ */
178
+ declare function screenshotRedactionHook(opts?: ScreenshotRedactionOptions): HookSurface;
179
+ interface DestructiveActionGuardOptions {
180
+ denyPatterns: RegExp[];
181
+ }
182
+ /**
183
+ * Block before-execute when a `computer-use:type` text or
184
+ * `computer-use:click` label matches any deny pattern. Mitigates
185
+ * destructive-action sequences (e.g. "delete account", "wire transfer")
186
+ * before they hit the OS.
187
+ */
188
+ declare function destructiveActionGuardHook(opts: DestructiveActionGuardOptions): HookSurface;
189
+ //#endregion
190
+ //#region src/openai/types.d.ts
191
+ /**
192
+ * Internal types for the OpenAI translator core.
193
+ *
194
+ * The translator is a pure function layer between OpenAI's wire formats
195
+ * (chat.completions, completions, responses, embeddings) and the Tangle
196
+ * sandbox run input/output. Types defined here are SDK-internal — public
197
+ * OpenAI shapes are imported from `openai/resources/...` directly so the
198
+ * translator's outputs satisfy the upstream type system at compile time.
199
+ */
200
+ /**
201
+ * A Tangle SSE event as emitted by the sandbox runtime. The event union is
202
+ * intentionally open at the data level — every concrete Tangle event has a
203
+ * known `type` plus a payload whose shape depends on the type. Translators
204
+ * narrow on `type` and read the fields they need.
205
+ *
206
+ * Event types currently emitted by the runtime:
207
+ * - `start` — handshake, no payload of interest.
208
+ * - `execution.started` — run has begun, no payload of interest.
209
+ * - `status` — signal frames (build_passed, tests_failed, etc.).
210
+ * - `token` — incremental text token.
211
+ * - `message.part.updated` — provider-native part updates (text deltas,
212
+ * tool state transitions, reasoning blocks).
213
+ * - `raw` — provider-native passthrough, including
214
+ * `tool-invocation` and `computer-use` payloads.
215
+ * - `session.updated` — session metadata, no payload of interest.
216
+ * - `error` — terminal error frame.
217
+ * - `done` — terminal completion frame, optionally with usage.
218
+ */
219
+ interface TangleSSEEvent {
220
+ type: string;
221
+ [key: string]: unknown;
222
+ }
223
+ /**
224
+ * A single multimodal part on a user/assistant turn. Mirrors the structural
225
+ * shape of OpenAI's `ChatCompletionContentPart` so we can pass it through
226
+ * unchanged to providers that accept the OpenAI shape natively, while still
227
+ * letting non-vision providers reject at the capability layer.
228
+ */
229
+ type MultimodalPart = {
230
+ type: "text";
231
+ text: string;
232
+ } | {
233
+ type: "image_url";
234
+ image_url: {
235
+ url: string;
236
+ detail?: "auto" | "low" | "high";
237
+ };
238
+ } | {
239
+ type: "input_audio";
240
+ input_audio: {
241
+ data: string;
242
+ format: "wav" | "mp3";
243
+ };
244
+ };
245
+ /**
246
+ * One reconstructed prior turn for the sandbox run input. The translator
247
+ * collapses an OpenAI-shape message thread (system / user / assistant /
248
+ * tool) into an ordered list of prior turns plus a single trailing task.
249
+ */
250
+ interface PriorTurn {
251
+ /** Final assistant text on this turn, if any. Tool-only turns omit this. */
252
+ assistantText?: string;
253
+ /** Tool calls the assistant emitted on this turn. */
254
+ toolCalls?: PriorToolCall[];
255
+ /** Tool results threaded back from the user side, keyed to `toolCalls[i].id`. */
256
+ toolResults?: PriorToolResult[];
257
+ /** User-side multimodal content for the turn, when the user sent parts. */
258
+ userParts?: MultimodalPart[];
259
+ }
260
+ interface PriorToolCall {
261
+ id: string;
262
+ name: string;
263
+ /** JSON-stringified arguments as emitted by the model. */
264
+ arguments: string;
265
+ }
266
+ interface PriorToolResult {
267
+ /** Matches the `toolCalls[i].id` from the assistant turn. */
268
+ toolCallId: string;
269
+ /** Tool output as a string (OpenAI tool messages carry a string body). */
270
+ content: string;
271
+ }
272
+ /**
273
+ * Shape of a tool descriptor preserved from the OpenAI request. The
274
+ * translator does not interpret tool schemas — it forwards them so the
275
+ * provider receives the same schema the caller authored.
276
+ */
277
+ interface SandboxToolSpec {
278
+ type: "function";
279
+ function: {
280
+ name: string;
281
+ description?: string;
282
+ parameters?: Record<string, unknown> | null;
283
+ strict?: boolean | null;
284
+ };
285
+ }
286
+ /**
287
+ * Resolved input handed to the sandbox run executor. The fields are
288
+ * provider-agnostic; the executor materializes them into whatever shape
289
+ * the chosen provider expects.
290
+ */
291
+ interface SandboxRunInput {
292
+ /** Provider id stripped of the `tangle/` prefix (e.g. `claude-code`). */
293
+ provider: string;
294
+ /** Optional variant after the provider id (e.g. `sonnet` for `tangle/opencode/sonnet`). */
295
+ variant?: string;
296
+ /** Concatenated system / developer instructions. */
297
+ instructions?: string;
298
+ /** Trailing user task — the message the agent acts on. */
299
+ task: string;
300
+ /** Multimodal parts attached to the trailing user task, when present. */
301
+ taskParts?: MultimodalPart[];
302
+ /** Reconstructed history before `task`, ordered oldest → newest. */
303
+ priorTurns?: PriorTurn[];
304
+ /** Forwarded tool descriptors (function tools only at this layer). */
305
+ tools?: SandboxToolSpec[];
306
+ /** Capability hints derived from the request (e.g. computer_use). */
307
+ capabilities?: string[];
308
+ /** True when any user message contained non-text parts. */
309
+ multimodal?: boolean;
310
+ }
311
+ /**
312
+ * Mutable per-stream context threaded through the chunk translators. The
313
+ * translator is a pure function over (event, ctx); the context tracks
314
+ * cross-event state that must persist for the lifetime of one stream
315
+ * (chunk index, tool-call buffering, the synthetic message id).
316
+ */
317
+ interface TranslatorContext {
318
+ /** Stable id assigned to the run; used as the `id` on every chunk. */
319
+ runId: string;
320
+ /** Model id echoed back on every chunk (caller-supplied, e.g. `tangle/claude-code`). */
321
+ modelId: string;
322
+ /** Monotonic chunk index — each emitted chunk increments. */
323
+ chunkIndex: number;
324
+ /** Tool calls observed during the stream, keyed by call id. */
325
+ toolCallBuffer: Map<string, BufferedToolCall>;
326
+ /** Unix timestamp (seconds) when the stream was opened. */
327
+ createdAt: number;
328
+ }
329
+ interface BufferedToolCall {
330
+ /** Position in the order tool calls were observed. */
331
+ index: number;
332
+ id: string;
333
+ name: string;
334
+ /** JSON-stringified arguments. */
335
+ arguments: string;
336
+ }
337
+ /**
338
+ * Construct a fresh translator context. The factory is deliberately tiny
339
+ * — call sites that need to override fields can do so via the partial.
340
+ */
341
+ declare function createTranslatorContext(init: Pick<TranslatorContext, "runId" | "modelId"> & Partial<TranslatorContext>): TranslatorContext;
342
+ //#endregion
343
+ //#region src/openai/translate/responses.d.ts
344
+ /**
345
+ * Persistence interface for `previous_response_id` chains. The route layer
346
+ * supplies a concrete impl (DuckDB-backed in production, in-memory in
347
+ * tests). The translator is store-agnostic.
348
+ */
349
+ interface ResponseStore {
350
+ /** Look up the prior turns recorded under a previous response id. */
351
+ getPriorTurns(responseId: string): Promise<PriorTurn[] | null>;
352
+ /** Persist the prior turns produced by a response. */
353
+ putPriorTurns(responseId: string, priorTurns: PriorTurn[]): Promise<void>;
354
+ }
355
+ /**
356
+ * Resolve a `previous_response_id` into the prior-turns prefix that
357
+ * gets prepended to the new request. Throws when the id is supplied but
358
+ * unknown — silently dropping it would corrupt conversation continuity.
359
+ */
360
+ declare function resolvePreviousResponseId(prevId: string | undefined, store: ResponseStore): Promise<{
361
+ priorTurns: PriorTurn[];
362
+ }>;
363
+ /**
364
+ * Aggregate a Tangle SSE event sequence into the Responses-API output[]
365
+ * array plus a usage envelope. This is the non-streaming path: callers
366
+ * collect every event, hand them all in, and get back a settled response
367
+ * payload ready to return as JSON.
368
+ */
369
+ declare function assembleResponseOutput(events: TangleSSEEvent[]): {
370
+ output: ResponseOutputItem[];
371
+ usage: ResponseUsage;
372
+ };
373
+ /**
374
+ * Fold every usage frame in a Tangle event sequence into a single
375
+ * ResponseUsage envelope. Multiple `done` events are tolerated (e.g.
376
+ * during retries) by summing.
377
+ */
378
+ declare function usageFromEvents(events: TangleSSEEvent[]): ResponseUsage;
379
+ declare class ResponsesValidationError extends Error {
380
+ readonly type = "invalid_request_error";
381
+ readonly code: string;
382
+ readonly param: string | undefined;
383
+ constructor(message: string, code: string, param?: string);
384
+ }
385
+ /**
386
+ * Reject Responses requests that ask for tool types Tangle cannot
387
+ * service. Function tools, the OpenAI computer-use preview tool, and
388
+ * the code interpreter (every Tangle sandbox can run code) are
389
+ * accepted; web_search and file_search are explicitly rejected with
390
+ * the OpenAI error shape.
391
+ */
392
+ declare function validateResponsesRequest(req: ResponseCreateParamsBase): void;
393
+ /**
394
+ * Build a settled `Response` shell from an aggregated output + usage.
395
+ * Caller fills in the runtime-specific fields (id, model, created_at,
396
+ * status, instructions, etc.) to avoid having to re-derive them inside
397
+ * the translator.
398
+ */
399
+ declare function buildResponseShell(args: {
400
+ id: string;
401
+ model: string;
402
+ createdAt: number;
403
+ output: ResponseOutputItem[];
404
+ usage: ResponseUsage;
405
+ instructions?: string | null;
406
+ previousResponseId?: string | null;
407
+ }): Response;
408
+ //#endregion
409
+ //#region src/openai/responses-store.d.ts
410
+ declare class InMemoryResponseStore implements ResponseStore {
411
+ private readonly chains;
412
+ getPriorTurns(responseId: string): Promise<PriorTurn[] | null>;
413
+ putPriorTurns(responseId: string, priorTurns: PriorTurn[]): Promise<void>;
414
+ /** Convenience accessor for tests / debug; not part of `ResponseStore`. */
415
+ size(): number;
416
+ /** Drop a chain. */
417
+ delete(responseId: string): boolean;
418
+ /** Drop everything. Useful between test cases. */
419
+ clear(): void;
420
+ }
421
+ //#endregion
422
+ //#region src/openai/runs.d.ts
423
+ /**
424
+ * Tangle-internal run events surfaced to consumers of `Run.events()`.
425
+ * The low-level `runEvents()` iterator emits the raw sandbox event
426
+ * frames (`TangleSSEEvent`) directly; the high-level state machine
427
+ * wraps each frame in a typed envelope plus emits its own
428
+ * status-transition and tool-dispatch events for consumers that don't
429
+ * want to parse SSE shapes themselves.
430
+ */
431
+ type RunEvent = {
432
+ type: "status";
433
+ status: RunStatus;
434
+ previous: RunStatus | null;
435
+ } | {
436
+ type: "stream";
437
+ event: TangleSSEEvent;
438
+ } | {
439
+ type: "tool_call";
440
+ ctx: ToolCallContext;
441
+ } | {
442
+ type: "tool_result";
443
+ ctx: ToolCallContext;
444
+ result: ToolResult;
445
+ } | {
446
+ type: "tool_blocked";
447
+ ctx: ToolCallContext;
448
+ reason: string;
449
+ } | {
450
+ type: "requires_action";
451
+ pendingCallIds: string[];
452
+ } | {
453
+ type: "completed";
454
+ } | {
455
+ type: "failed";
456
+ reason: string;
457
+ } | {
458
+ type: "cancelled";
459
+ reason?: string;
460
+ };
461
+ type RunStatus = "queued" | "in_progress" | "requires_action" | "completed" | "failed" | "cancelled" | "expired";
462
+ /**
463
+ * Minimal interface the low-level `runEvents()` consumes. The route
464
+ * layer adapts the concrete `SandboxClient` SSE stream onto this
465
+ * surface so the Run executor stays decoupled from any specific HTTP
466
+ * shape. `cancel()` is best-effort — the source should stop producing
467
+ * events as soon as it observes a cancellation.
468
+ */
469
+ interface RunEventSource {
470
+ open(threadId: string | undefined, runId: string): AsyncIterable<TangleSSEEvent>;
471
+ /** Optional: append a steer message and re-open the stream for the same run. */
472
+ steer?(threadId: string | undefined, runId: string, message: {
473
+ role: "user";
474
+ content: string;
475
+ }): Promise<void>;
476
+ /** Optional: submit tool outputs and resume from `requires_action`. */
477
+ submitToolOutputs?(threadId: string | undefined, runId: string, outputs: ToolOutput[]): Promise<void>;
478
+ /** Optional: server-side cancel hint. */
479
+ cancel?(threadId: string | undefined, runId: string): Promise<void>;
480
+ }
481
+ interface ToolOutput {
482
+ toolCallId: string;
483
+ output: ToolResult;
484
+ }
485
+ /**
486
+ * Pure async iterator over the underlying source. No state, no
487
+ * buffering. Iteration ends when the source closes or yields a
488
+ * terminal frame; the iterator itself does not classify frames.
489
+ */
490
+ declare function runEvents(threadId: string | undefined, runId: string, source: RunEventSource): AsyncIterable<TangleSSEEvent>;
491
+ interface RunOptions {
492
+ id: string;
493
+ threadId?: string;
494
+ partnerId: string;
495
+ source: RunEventSource;
496
+ hooks?: HookChain;
497
+ /** Caller-supplied tool executor. Required when the underlying stream
498
+ * does not auto-execute tools server-side (the typical Tangle path). */
499
+ executeTool?: (ctx: ToolCallContext) => Promise<ToolResult>;
500
+ onStatusChange?: (status: RunStatus, previous: RunStatus | null) => void;
501
+ }
502
+ /**
503
+ * High-level `Run`. Drives the underlying `RunEventSource`, manages
504
+ * status transitions, dispatches tool calls through the hook chain,
505
+ * and surfaces a typed `RunEvent` stream to consumers.
506
+ */
507
+ declare class Run {
508
+ readonly id: string;
509
+ readonly threadId: string | undefined;
510
+ readonly partnerId: string;
511
+ private _status;
512
+ private readonly source;
513
+ private readonly hooks;
514
+ private readonly executeTool;
515
+ private readonly onStatusChange;
516
+ private readonly queue;
517
+ private startPromise;
518
+ private pendingCalls;
519
+ private cancelRequested;
520
+ constructor(opts: RunOptions);
521
+ get status(): RunStatus;
522
+ /**
523
+ * Subscribe to typed events. May only be consumed once per Run.
524
+ *
525
+ * The single-consumer constraint is permanent for the lifetime of
526
+ * the Run instance, including AFTER the run completes — calling
527
+ * `events()` a second time always throws, even if the first
528
+ * consumer drained the iterator to completion. This is intentional:
529
+ * the queue is a one-shot stream, not a re-readable buffer, and
530
+ * events are dropped after delivery to avoid unbounded retention.
531
+ * Callers that need to revisit terminal state should keep a handle
532
+ * to the original iterator's drained values, or use the Run's
533
+ * status/result accessors.
534
+ */
535
+ events(): AsyncIterable<RunEvent>;
536
+ /**
537
+ * Drive the underlying stream to completion. Idempotent: subsequent
538
+ * calls return the same in-flight promise.
539
+ */
540
+ start(): Promise<void>;
541
+ /**
542
+ * Cancel an in-flight run. Sets status to `cancelled` and closes
543
+ * the event queue. Tries the source-level cancel hint as a
544
+ * best-effort heads-up to the upstream stream.
545
+ */
546
+ cancel(reason?: string): Promise<void>;
547
+ /**
548
+ * Append a user message to the thread and restart the stream. The
549
+ * source's `steer` hook is invoked when present; otherwise we throw
550
+ * because a stateless source cannot honor a steer.
551
+ */
552
+ steer(message: {
553
+ role: "user";
554
+ content: string;
555
+ }): Promise<void>;
556
+ /**
557
+ * Resume a `requires_action` run by submitting tool outputs. The
558
+ * outputs are forwarded to the source so the upstream agent can
559
+ * continue. Status transitions back to `in_progress`.
560
+ */
561
+ submitToolOutputs(outputs: ToolOutput[]): Promise<void>;
562
+ /** Externally drive the run into the `expired` terminal status. */
563
+ expire(): void;
564
+ private transition;
565
+ private driveStream;
566
+ private handleToolCall;
567
+ }
568
+ //#endregion
569
+ //#region src/openai/translate/chunks.d.ts
570
+ declare function sandboxEventToChatChunk(event: TangleSSEEvent, ctx: TranslatorContext): ChatCompletionChunk | null;
571
+ declare function sandboxEventToCompletionChunk(event: TangleSSEEvent, ctx: TranslatorContext): Completion | null;
572
+ declare function sandboxEventToResponsesEvent(event: TangleSSEEvent, ctx: TranslatorContext): ResponseStreamEvent | null;
573
+ //#endregion
574
+ //#region src/openai/translate/embeddings.d.ts
575
+ type NormalizedEmbeddingInput = {
576
+ kind: "text";
577
+ values: string[];
578
+ } | {
579
+ kind: "tokens";
580
+ values: number[][];
581
+ };
582
+ interface NormalizedEmbeddingRequest {
583
+ model: string;
584
+ input: NormalizedEmbeddingInput;
585
+ dimensions?: number;
586
+ encodingFormat: "float" | "base64";
587
+ user?: string;
588
+ }
589
+ /**
590
+ * Error shape used for rejecting embedding requests. The route layer
591
+ * lifts these into OpenAI's `{ error: { type, code, message } }` body.
592
+ */
593
+ declare class EmbeddingValidationError extends Error {
594
+ readonly type = "invalid_request_error";
595
+ readonly code: string;
596
+ readonly param: string | undefined;
597
+ constructor(message: string, code: string, param?: string);
598
+ }
599
+ /**
600
+ * Validate and normalize an embedding request. Throws
601
+ * `EmbeddingValidationError` on any rejection.
602
+ */
603
+ declare function validateEmbeddingRequest(req: EmbeddingCreateParams): NormalizedEmbeddingRequest;
604
+ //#endregion
605
+ //#region src/openai/translate/finish-reason.d.ts
606
+ /**
607
+ * Map a Tangle outcome string + tool-call presence to an OpenAI
608
+ * `finish_reason`. Shared across chat / completions / responses
609
+ * translators so all three surfaces report the same termination reason
610
+ * for the same underlying outcome.
611
+ *
612
+ * Inputs:
613
+ * - `outcome` is the Tangle terminal status (`success`, `failure`,
614
+ * `length_exceeded`, `content_filtered`, `error`, `cancelled`, ...).
615
+ * - `hasToolCall` is true when the run emitted at least one tool call
616
+ * before terminating.
617
+ *
618
+ * Mapping:
619
+ * - `success` + tool_call → `tool_calls` (model handed control back).
620
+ * - `success` → `stop`.
621
+ * - `length_exceeded` → `length`.
622
+ * - `content_filtered` → `content_filter`.
623
+ * - everything else → `stop` (route layer surfaces the error).
624
+ */
625
+ type OpenAIFinishReason = "stop" | "length" | "tool_calls" | "content_filter";
626
+ declare function outcomeToFinishReason(outcome: string, hasToolCall: boolean): OpenAIFinishReason;
627
+ //#endregion
628
+ //#region src/openai/translate/messages.d.ts
629
+ /**
630
+ * Translate an OpenAI chat-shape message thread into a SandboxRunInput.
631
+ *
632
+ * @param messages Ordered messages as the OpenAI client would send them.
633
+ * @param tools Optional function tool descriptors to forward unchanged.
634
+ * @param model Caller-supplied model id (`tangle/<provider>[/<variant>]`).
635
+ *
636
+ * @throws when the resolved provider id is empty, when the message thread
637
+ * lacks any user message, or when an `assistant` `tool_calls` item
638
+ * is malformed (missing id/name/arguments).
639
+ */
640
+ declare function openaiMessagesToSandboxInput(messages: ChatCompletionMessageParam[], tools: ChatCompletionTool[] | undefined, model: string): SandboxRunInput;
641
+ //#endregion
642
+ export { type ActionRateLimitOptions, type AfterHookOutcome, type AuditEvent, type AuditLogOptions, type BeforeHookOutcome, type BufferedToolCall, type CostCapOptions, type DestructiveActionGuardOptions, type EgressPolicyOptions, EmbeddingValidationError, HookChain, type HookSurface, InMemoryResponseStore, type MultimodalPart, type NormalizedEmbeddingInput, type NormalizedEmbeddingRequest, type OpenAIFinishReason, type PriorToolCall, type PriorToolResult, type PriorTurn, type RedactionRegion, type ResponseStore, ResponsesValidationError, Run, type RunEvent, type RunEventSource, type RunOptions, type RunStatus, type SandboxRunInput, type SandboxToolSpec, type ScreenshotRedactionOptions, type TangleSSEEvent, type ToolCallContext, type ToolOutput, type ToolResult, type TranslatorContext, actionRateLimitHook, assembleResponseOutput, auditLogHook, buildResponseShell, costCapHook, createTranslatorContext, destructiveActionGuardHook, egressPolicyHook, openaiMessagesToSandboxInput, outcomeToFinishReason, resolvePreviousResponseId, runEvents, sandboxEventToChatChunk, sandboxEventToCompletionChunk, sandboxEventToResponsesEvent, screenshotRedactionHook, usageFromEvents, validateEmbeddingRequest, validateResponsesRequest };