@opengeni/runtime 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/dist/chunk-2PO56VAL.js +3478 -0
  2. package/dist/chunk-2PO56VAL.js.map +1 -0
  3. package/dist/index.d.ts +912 -0
  4. package/dist/index.js +3663 -0
  5. package/dist/index.js.map +1 -0
  6. package/dist/sandbox/index.d.ts +1738 -0
  7. package/dist/sandbox/index.js +187 -0
  8. package/dist/sandbox/index.js.map +1 -0
  9. package/package.json +49 -0
  10. package/src/bundled_hashicorp_terraform_skills/LICENSE +373 -0
  11. package/src/bundled_hashicorp_terraform_skills/README.md +18 -0
  12. package/src/bundled_hashicorp_terraform_skills/UPSTREAM_GIT_SHA +1 -0
  13. package/src/bundled_hashicorp_terraform_skills/azure-verified-modules/SKILL.md +613 -0
  14. package/src/bundled_hashicorp_terraform_skills/checkov/SKILL.md +43 -0
  15. package/src/bundled_hashicorp_terraform_skills/refactor-module/SKILL.md +538 -0
  16. package/src/bundled_hashicorp_terraform_skills/social-media-marketing/SKILL.md +35 -0
  17. package/src/bundled_hashicorp_terraform_skills/terraform-search-import/SKILL.md +372 -0
  18. package/src/bundled_hashicorp_terraform_skills/terraform-search-import/references/MANUAL-IMPORT.md +113 -0
  19. package/src/bundled_hashicorp_terraform_skills/terraform-search-import/scripts/list_resources.sh +38 -0
  20. package/src/bundled_hashicorp_terraform_skills/terraform-stacks/SKILL.md +480 -0
  21. package/src/bundled_hashicorp_terraform_skills/terraform-stacks/references/api-monitoring.md +543 -0
  22. package/src/bundled_hashicorp_terraform_skills/terraform-stacks/references/component-blocks.md +476 -0
  23. package/src/bundled_hashicorp_terraform_skills/terraform-stacks/references/deployment-blocks.md +391 -0
  24. package/src/bundled_hashicorp_terraform_skills/terraform-stacks/references/examples.md +1529 -0
  25. package/src/bundled_hashicorp_terraform_skills/terraform-stacks/references/linked-stacks.md +187 -0
  26. package/src/bundled_hashicorp_terraform_skills/terraform-stacks/references/troubleshooting.md +671 -0
  27. package/src/bundled_hashicorp_terraform_skills/terraform-style-guide/SKILL.md +353 -0
  28. package/src/bundled_hashicorp_terraform_skills/terraform-test/SKILL.md +451 -0
  29. package/src/bundled_hashicorp_terraform_skills/terraform-test/references/CI_CD.md +80 -0
  30. package/src/bundled_hashicorp_terraform_skills/terraform-test/references/EXAMPLES.md +314 -0
  31. package/src/bundled_hashicorp_terraform_skills/terraform-test/references/MOCK_PROVIDERS.md +171 -0
  32. package/src/codex-tool-search.ts +267 -0
  33. package/src/context-compaction.ts +538 -0
  34. package/src/history-sanitizer.ts +719 -0
  35. package/src/index.ts +3299 -0
  36. package/src/sandbox/capabilities.ts +69 -0
  37. package/src/sandbox/channel-a.ts +1031 -0
  38. package/src/sandbox/display-stack.ts +231 -0
  39. package/src/sandbox/errors.ts +34 -0
  40. package/src/sandbox/index.ts +832 -0
  41. package/src/sandbox/providers/blaxel.ts +35 -0
  42. package/src/sandbox/providers/cloudflare.ts +24 -0
  43. package/src/sandbox/providers/daytona.ts +34 -0
  44. package/src/sandbox/providers/docker.ts +17 -0
  45. package/src/sandbox/providers/e2b.ts +36 -0
  46. package/src/sandbox/providers/index.ts +107 -0
  47. package/src/sandbox/providers/local.ts +13 -0
  48. package/src/sandbox/providers/modal.ts +55 -0
  49. package/src/sandbox/providers/none.ts +13 -0
  50. package/src/sandbox/providers/runloop.ts +32 -0
  51. package/src/sandbox/providers/selfhosted.ts +96 -0
  52. package/src/sandbox/providers/types.ts +38 -0
  53. package/src/sandbox/providers/vercel.ts +29 -0
  54. package/src/sandbox/recording.ts +286 -0
  55. package/src/sandbox/routing/backend-resolver.ts +189 -0
  56. package/src/sandbox/routing/routing-session.ts +455 -0
  57. package/src/sandbox/select.ts +371 -0
  58. package/src/sandbox/selfhosted/capabilities.ts +255 -0
  59. package/src/sandbox/selfhosted/control-rpc.ts +351 -0
  60. package/src/sandbox/selfhosted/session.ts +930 -0
  61. package/src/sandbox/selfhosted/testing.ts +230 -0
  62. package/src/sandbox/stream-port.ts +185 -0
  63. package/src/sandbox/stream-token.ts +90 -0
  64. package/src/sandbox/terminal-server.ts +203 -0
  65. package/src/sandbox-computer.ts +835 -0
@@ -0,0 +1,912 @@
1
+ import * as _openai_agents from '@openai/agents';
2
+ import { Tool, Computer, AgentInputItem, Model, MCPServer, ModelProvider, Agent, RunState, CallModelInputFilter, RunStreamEvent } from '@openai/agents';
3
+ export { MaxTurnsExceededError, OpenAIChatCompletionsModel, OpenAIResponsesModel } from '@openai/agents';
4
+ import { ContextCompactionMode, Settings, ResolvedModelProvider, ConfiguredModel, ModelProviderApi } from '@opengeni/config';
5
+ export { collectSandboxEnvironment, parseExposedPorts } from '@opengeni/config';
6
+ import { ReasoningEffort, SessionEventType, ResourceRef, ToolRef, Permission } from '@opengeni/contracts';
7
+ export { CAPABILITY_DESCRIPTORS, CapabilityDescriptor, DESKTOP_STREAM_PORT, StreamTokenPayload, StreamTokenPayload as StreamTokenPayloadType, TERMINAL_STREAM_PORT } from '@opengeni/contracts';
8
+ import { Capability, SandboxSessionLike, SandboxSessionState, Manifest, Capabilities, LocalDirLazySkillSource, SandboxClient } from '@openai/agents/sandbox';
9
+ import OpenAI from 'openai';
10
+ export { ActiveBackendResolverDeps, ActiveBackendUnresolvableError, ActivePointer, ChannelAConflictError, ChannelAEmitter, ChannelAExecArgs, ChannelAExecResult, ChannelANotFoundError, ChannelASession, ChannelAUnsupportedError, ChannelAValidationError, ControlRpc, DEFAULT_DESKTOP_GEOMETRY, DISPLAY_STACK_TIMEOUT_MS, DesktopGeometry, DisplayStackError, DisplayStackUnsupportedError, EnsureDisplayStackOptions, EnsureDisplayStackResult, EnsureTerminalServerOptions, EnsureTerminalServerResult, EstablishedSandboxSession, ExposeStreamPortInput, ExposeStreamPortResult, ExposedPortEndpoint, FinalizeRecordingResult, MintStreamTokenInput, MockAgentResponder, MockAgentResponderOptions, MockExecHandler, NatsControlRpc, NatsRequestConnection, NegotiationContext, NumstatEntry, PROVIDER_REGISTRY, ProviderConstructionContext, ProviderRegistration, RecordingCodec, RecordingContentType, RecordingError, RecordingProcess, RecordingUnavailableError, ResolvedActiveBackend, RoutableBackendSession, RoutableSandbox, RoutingSandboxSession, RoutingSandboxSessionDeps, RoutingTransitionEvent, RoutingUnsupportedError, SELFHOSTED_DEFAULT_TIMEOUT_MS, SELFHOSTED_RECONNECT_WINDOW_MS, SELFHOSTED_RELAY_STREAM_PATH, STREAM_PORT, STREAM_TOKEN_DEFAULT_TTL_SECONDS, SandboxChannelAService, SandboxChannelAServiceOptions, SandboxConfigError, SandboxProviderUnavailableError, SelfhostedApplyDiff, SelfhostedControlError, SelfhostedEditor, SelfhostedEnrollment, SelfhostedExecArgs, SelfhostedExecResult, SelfhostedImageOutput, SelfhostedLivenessState, SelfhostedNegotiationInput, SelfhostedRelayConfig, SelfhostedSandboxClient, SelfhostedSession, SelfhostedSessionBuild, SelfhostedSessionDeps, SelfhostedSessionState, SelfhostedUnavailableReason, StartRecordingInput, StreamPortUnavailableError, TERMINAL_SERVER_TIMEOUT_MS, TerminalServerError, TerminalServerUnsupportedError, agentErrorToControlError, assertDescriptorRegistryInvariants, assertProviderRegistryInvariants, assertSafeRelPath, backendSupportsOs, buildDisplayStackScript, buildSelfhostedBackendSession, buildStreamUrl, buildTerminalServerScript, contentTypeForCodec, createSandboxClient, createSandboxClientForBackend, decodeModalSnapshotId, deletePriorPersistedSnapshot, deleteRecordingArtifacts, deserializeSandboxSessionStateEnvelope, desktopCapableBackend, ensureDisplayStack, ensureTerminalServer, establishSandboxSessionFromEnvelope, exposeStreamPort, extForCodec, isExecSessionLostBanner, isProviderSandboxNotFoundError, isSelfhostedProviderNotFoundError, isWorkspaceEscapeError, makeActiveBackendResolver, mintStreamToken, negotiateCapabilities, negotiateSelfhostedCapabilities, offlineAgentError, offlineControlResponse, parseExecBannerSessionId, parseNumstatZ, parsePorcelainV2, parseUnifiedPatch, readRecordingBytes, readWorkspaceArchiveFromEnvelopeSessionState, recordingStorageKey, restoredSandboxSessionStateFromEntry, sandboxStateEntryFromRunState, selectBackend, selfhostedLiveness, serializeEstablishedSandboxEnvelope, setSelfhostedApplyDiff, startRecording, stopRecording, stripExecBanner, subjectFor, tearDownDisplayStack, tearDownTerminalServer, timeoutAgentError, timeoutControlResponse, verifyStreamToken } from './sandbox/index.js';
11
+ import '@opengeni/agent-proto';
12
+
13
+ type ComputerButton = "left" | "right" | "wheel" | "back" | "forward";
14
+ type SandboxComputerOptions = {
15
+ display?: string;
16
+ dimensions?: [number, number];
17
+ runAs?: string;
18
+ typeDelayMs?: number;
19
+ readOnly?: boolean;
20
+ screenshotTmpDir?: string;
21
+ };
22
+ /** No exec/execCommand on the session, or the display is not up. */
23
+ declare class ComputerUnavailableError extends Error {
24
+ constructor(message: string);
25
+ }
26
+ /** A write action attempted while readOnly. */
27
+ declare class ComputerReadOnlyError extends Error {
28
+ constructor();
29
+ }
30
+ /** A nonzero xdotool/scrot exit, OR a command that did not finish before the
31
+ * yield window (F3 — "still running" is a failure, not a silent success). */
32
+ declare class ComputerActionError extends Error {
33
+ cmd: string;
34
+ exitCode: number;
35
+ stderr: string;
36
+ constructor(cmd: string, exitCode: number, stderr: string);
37
+ }
38
+ /**
39
+ * The Computer the agent drives. Every action issues ONE shell line through the
40
+ * externally-owned session (exec ?? execCommand, F1), prefixed with the display.
41
+ * screenshot() scrots to a /tmp file and reads the RAW bytes by running
42
+ * `base64 <path>` over the SAME command primitive and stripping the banner — NOT
43
+ * `session.readFile` (Modal's readFile path-validates against /workspace and rejects
44
+ * /tmp with "escapes the workspace root", which would yield an empty frame and 400
45
+ * the model). The base64-over-exec path is /tmp-readable and binary-safe.
46
+ */
47
+ declare class SandboxComputer implements Computer {
48
+ readonly environment: "ubuntu";
49
+ readonly dimensions: [number, number];
50
+ private session;
51
+ private readonly display;
52
+ private readonly runAs?;
53
+ private readonly typeDelayMs;
54
+ private readonly readOnly;
55
+ private readonly tmp;
56
+ constructor(session: SandboxSessionLike, opts?: SandboxComputerOptions);
57
+ /** Rebind to a freshly resumed-by-id session after a box rollover / re-establish. */
58
+ rebind(session: SandboxSessionLike): void;
59
+ private x;
60
+ private guardWrite;
61
+ private shq;
62
+ screenshot(): Promise<string>;
63
+ private readScreenshotBytes;
64
+ click(xp: number, yp: number, button: ComputerButton): Promise<void>;
65
+ doubleClick(xp: number, yp: number): Promise<void>;
66
+ move(xp: number, yp: number): Promise<void>;
67
+ scroll(xp: number, yp: number, sx: number, sy: number): Promise<void>;
68
+ type(text: string): Promise<void>;
69
+ keypress(keys: string[]): Promise<void>;
70
+ drag(path: [number, number][]): Promise<void>;
71
+ wait(): Promise<void>;
72
+ }
73
+ type ComputerUseArgs = {
74
+ dimensions?: [number, number];
75
+ readOnly?: boolean;
76
+ display?: string;
77
+ needsApproval?: boolean | ((ctx: unknown, action: unknown) => boolean | Promise<boolean>);
78
+ imageFunctionResults?: boolean;
79
+ };
80
+ declare function computerUse(args?: ComputerUseArgs): ComputerUseCapability;
81
+ /**
82
+ * A `Capability` subclass merged into the agent's tool set by SandboxAgent
83
+ * (`tools = [...agent.tools, ...capability.tools()]`). `bind(session)` hands it
84
+ * the LIVE externally-owned session, so the agent's actions and the viewers'
85
+ * pixels are one display.
86
+ *
87
+ * `tools()` is TRANSPORT-AWARE, mirroring the SDK's `filesystem()` capability
88
+ * (which branches its `view_image` / `apply_patch` on
89
+ * `supportsStructuredToolOutputTransport(this._modelInstance)`):
90
+ * • structured transport (the Responses/OpenAI backend) → the single HOSTED
91
+ * `computer_use_preview` tool over a Computer bound to the session (unchanged).
92
+ * • text transport (codex / ChatGPT backend — or an unbound model) → a set of
93
+ * FUNCTION tools ({@link computerFunctionTools}) that route to the SAME Computer,
94
+ * because the codex backend rejects the hosted computer tool type.
95
+ * The bound model instance is captured by the SDK's `bind().bindRunAs().bindModel()`
96
+ * chain (base `Capability._modelInstance`); the codex path in index.ts neutralizes
97
+ * `bindModel` so `_modelInstance` stays undefined here → the function tools win.
98
+ */
99
+ declare class ComputerUseCapability extends Capability {
100
+ private args;
101
+ readonly type = "computer-use";
102
+ constructor(args?: ComputerUseArgs);
103
+ tools(): Tool<unknown>[];
104
+ }
105
+
106
+ /**
107
+ * Read-path sanitizer for replayed conversation history (issue: orphaned
108
+ * tool outputs brick a session).
109
+ *
110
+ * Conversation truth is persisted as a flat list of SDK history items in
111
+ * `session_history_items` and replayed verbatim into the model on every turn.
112
+ * The OpenAI Responses API rejects the whole request (HTTP 400) when that list
113
+ * violates its tool-call pairing rules — most destructively:
114
+ *
115
+ * `400 No tool call found for function call output with call_id <X>`
116
+ *
117
+ * when a `function_call_result` (a.k.a. function_call_output) has no matching
118
+ * `function_call` earlier in the list. Because the corrupt item is replayed on
119
+ * every subsequent turn, one orphaned output permanently bricks the session
120
+ * across revival — it stays dead until the row is hand-deleted.
121
+ *
122
+ * This module is the reliability net: before history items are sent to the
123
+ * model they pass through `sanitizeHistoryItemsForModel`, which removes any
124
+ * item that would make the request invalid. It mirrors the SDK's own
125
+ * `dropOrphanToolCalls` continuation logic (which only runs over the SDK's
126
+ * in-memory `state.history`, not over rows we reload from the database) so a
127
+ * reloaded history is shaped exactly like a freshly-generated one.
128
+ *
129
+ * It is a pure function over plain JSON item shapes (no SDK import, no I/O) so
130
+ * it is cheap to unit-test exhaustively. It NEVER mutates its input items and
131
+ * NEVER touches the stored rows — only the in-memory copy sent to the model is
132
+ * filtered, keeping the persisted audit trail intact.
133
+ */
134
+ /** A history item is any JSON object; we only inspect a few discriminator fields. */
135
+ type HistoryItem = Record<string, unknown>;
136
+ /**
137
+ * Sanitize a replayed history item list into a sequence the Responses API
138
+ * accepts. Pure: returns a new array of the same item references in order,
139
+ * with invalid items omitted. Valid histories come back byte-identical
140
+ * (same references, same order).
141
+ *
142
+ * Rules, each motivated by a concrete 400 the API raises:
143
+ *
144
+ * 1. Drop every tool-call RESULT whose matching tool CALL does not appear
145
+ * earlier in the list. This is the session-bricking orphan: a
146
+ * `function_call_result` with no preceding `function_call` of the same
147
+ * `call_id`. ("No tool call found for function call output…")
148
+ *
149
+ * 2. Drop every tool CALL that has no matching RESULT anywhere after it.
150
+ * The Responses API requires each tool call to be settled by its output
151
+ * before the conversation can continue; a dangling call left in replayed
152
+ * history 400s with "No tool output found for function call…". Dropping
153
+ * the dangling call (rather than synthesizing a fake output) is what the
154
+ * SDK itself does for in-memory continuation, so a reloaded history is
155
+ * shaped identically. The matching result, if it later exists, is kept;
156
+ * only genuinely unpaired calls are removed.
157
+ *
158
+ * 3. Drop any `reasoning` item that immediately precedes (across a run of
159
+ * reasoning items) a dropped tool call. The Responses API ties an
160
+ * encrypted reasoning item to the tool call it produced; a reasoning item
161
+ * orphaned by rule 2 trips "Item 'rs_…' of type 'reasoning' was provided
162
+ * without its required following item". Mirrors the SDK's
163
+ * `dropReasoningItemsPrecedingDroppedCalls`.
164
+ *
165
+ * A `call_id` is paired only when BOTH a call and a result of the matching
166
+ * types exist with that id, the call appearing before the result. Calls and
167
+ * results that satisfy that survive untouched.
168
+ */
169
+ declare function sanitizeHistoryItemsForModel<T extends HistoryItem>(items: readonly T[]): T[];
170
+ /**
171
+ * Drop the account/org-bound `reasoning.encrypted_content` blob from a single
172
+ * history item, preserving everything else (the visible chain-of-thought text in
173
+ * `summary`/`content`, and every non-reasoning field). Pure + non-mutating: when
174
+ * there is nothing to strip the SAME reference is returned (so the common,
175
+ * same-account path stays byte-identical); otherwise a shallow clone is returned.
176
+ *
177
+ * WHY. A codex-subscription turn round-trips `reasoning.encrypted_content` — an
178
+ * opaque blob minted by the ChatGPT/Codex backend that is bound to the account
179
+ * (org) that produced it. After a manual switch from codex account A to B, the
180
+ * carried history items still hold A-minted blobs; replaying them into a turn
181
+ * running on B is rejected (400). The blob is purely a chain-of-thought
182
+ * continuity optimization — dropping it costs at most one turn of lost CoT
183
+ * continuity and never any message content.
184
+ *
185
+ * USED FOR `compaction` items only on the history-items read path: a foreign
186
+ * `compaction` summary carries account-bound `encrypted_content` but its summary
187
+ * is real conversation content that must be preserved, so we strip only the blob
188
+ * (we do NOT drop the whole item). Foreign `reasoning` items are instead dropped
189
+ * WHOLESALE by the caller (id + blob), because the Responses backend validates
190
+ * the foreign `rs_…` id and rejects a reasoning item that has a foreign id and no
191
+ * encrypted_content (so blanking the blob alone is not enough — see
192
+ * {@link applyCodexHistoryStrip}).
193
+ *
194
+ * The SDK's Responses converter reads the blob via `providerData.encryptedContent`
195
+ * (camel) or `providerData.encrypted_content` (snake); persisted rows use the
196
+ * snake form, but we delete both casings defensively. We also clear a top-level
197
+ * `encrypted_content` (the `compaction`-item shape) belt-and-braces — that blob
198
+ * is likewise source-bound. Only `reasoning` and `compaction` items are touched;
199
+ * messages, tool calls, and tool outputs pass through untouched by reference.
200
+ */
201
+ declare function stripReasoningEncryptedContent<T extends HistoryItem>(item: T): T;
202
+ /**
203
+ * Neutralize the account/org-bound identity of EVERY `reasoning` item embedded
204
+ * in a serialized RunState JSON string, returning the re-serialized string. Pure:
205
+ * a parse failure or a no-op returns the SAME string reference (so an unchanged
206
+ * or non-codex run-state replays byte-for-byte).
207
+ *
208
+ * WHY (HOLE C — the run-state REPLAY paths). The approval-decision resume and the
209
+ * items-mode run-state fallback replay the serialized RunState blob verbatim. That
210
+ * blob round-trips `reasoning.encrypted_content` minted by the ChatGPT/Codex
211
+ * backend (bound to the freezing account/org — a foreign account 400s it) AND the
212
+ * foreign `rs_…` reasoning ids the Responses backend validates (rejected once the
213
+ * blob is gone). Unlike `session_history_items`, the blob carries NO per-item
214
+ * producer tag, so foreign-ness cannot be decided per item; the worker instead
215
+ * records the FREEZING codex account on the run-state row and calls this only when
216
+ * the resuming turn's codex account DIFFERS from it. When the accounts differ we
217
+ * conservatively neutralize every reasoning item: delete its provider id and its
218
+ * `encrypted_content` (both casings, in `providerData`). The visible reasoning
219
+ * `content`/`summary` and every message / tool-call / tool-output item are left
220
+ * intact (message and tool content are never account-bound).
221
+ *
222
+ * A reasoning item with no id and no encrypted_content is exactly the shape the
223
+ * production Azure path already sends (see `stripProviderItemIdsFilter`), so it
224
+ * deserializes and replays cleanly. Reasoning items live in several places in the
225
+ * blob — `originalInput` (when an array), each `modelResponses[].output`,
226
+ * `lastModelResponse.output`, and the `generatedItems` wrappers (`reasoning_item`
227
+ * → `rawItem`) — and we scrub all of them. `compaction` items are deliberately
228
+ * left untouched: their `encrypted_content` is a protocol-REQUIRED field whose
229
+ * removal would fail the SDK's run-state schema validation on deserialize.
230
+ */
231
+ declare function stripReasoningIdentityFromSerializedRunState(serialized: string): string;
232
+ /**
233
+ * Neutralize tool_search items IN PLACE in a serialized RunState blob for a
234
+ * cross-account codex resume — the run-state sibling of
235
+ * `applyCodexHistoryStrip`'s tool_search rule, but COUNT-PRESERVING (HOLE E: the
236
+ * blob path's reconcile watermark counts the blob's history length, so items
237
+ * must never be removed — only mutated, exactly like the reasoning
238
+ * neutralization above).
239
+ *
240
+ * The hazard: on deserialize, the SDK re-runs the registered CLIENT tool_search
241
+ * execute callback per frozen pair (`rehydrateToolSearchRuntimeTools`) and
242
+ * THROWS a UserError when the re-run's runtime-tool keys mismatch the serialized
243
+ * expectation — which is exactly what happens when the RESUMING account's
244
+ * connector pool differs from the FREEZING account's. The SDK skips that
245
+ * rehydration entirely for `execution === 'server'` calls, so flipping the
246
+ * frozen pairs' `execution` to `"server"` in place defuses the throw without
247
+ * touching counts, ids, pairing, or content. The flipped shape is wire-safe:
248
+ * LIVE-VERIFIED against /codex/responses — a replayed server-execution pair is
249
+ * accepted (200) and its disclosure still holds. The account-bound `tsc_…` id is
250
+ * separately stripped by the codex transport normalizer (all input item ids).
251
+ *
252
+ * Walks the same blob locations as {@link stripReasoningIdentityFromSerializedRunState}:
253
+ * `originalInput` (array form), `generatedItems` (SDK run-item wrappers — the
254
+ * raw shape under `rawItem`), every `modelResponses[].output`, and
255
+ * `lastModelResponse.output`. Returns the input string unchanged when nothing
256
+ * matched.
257
+ */
258
+ declare function neutralizeToolSearchItemsInSerializedRunState(serialized: string): string;
259
+
260
+ /**
261
+ * Client-side conversation context compaction (the Azure path).
262
+ *
263
+ * OpenGeni runs long-lived agent sessions whose conversation truth
264
+ * (`session_history_items`) grows unbounded. On the OpenAI platform the
265
+ * Responses API compacts server-side (the SDK's `compaction()` capability). On
266
+ * Azure that capability 400s (`unsupported_parameter`), so the session
267
+ * eventually overflows the model context window and hard-fails every turn.
268
+ *
269
+ * This module is the Azure-safe replacement. It is built from two pure pieces
270
+ * plus one impure step the caller wires in:
271
+ *
272
+ * 1. `planCompaction` — given the active history items, the last turn's actual
273
+ * input-token count, and the token budget, decide WHETHER to compact and,
274
+ * if so, WHERE the orphan-safe cut boundary is (the prefix to summarize vs
275
+ * the recent tail to keep verbatim). Pure, exhaustively testable.
276
+ * 2. (caller) summarize the prefix into ONE plain user `message` item via a
277
+ * model call — see `buildCompactionMessages` / `SUMMARY_PREFIX`.
278
+ * 3. `applyCompaction` shape — the storage write the caller performs:
279
+ * supersede the prefix rows, insert the summary at the boundary position.
280
+ *
281
+ * Design constraints (non-negotiable):
282
+ * - The summary is a PLAIN user message, NOT the SDK `compaction` item type
283
+ * (that requires server-minted `encrypted_content`; a hand-rolled one risks
284
+ * an Azure 400).
285
+ * - ORPHAN SAFETY: the cut lands only at a clean turn boundary (start of a
286
+ * user message). No tool call_id may straddle the cut — for every
287
+ * `function_call` dropped, its `function_call_result` is also dropped, and
288
+ * vice versa. Reasoning items drop/keep with their whole turn.
289
+ * - SINGLE LIVE SUMMARY: each compaction folds the prior summary forward
290
+ * (summarize [prior summary] + [items since]); prior summaries are excluded
291
+ * from re-collection so drift stays bounded.
292
+ */
293
+ type CompactionItem = Record<string, unknown>;
294
+ /**
295
+ * Marker stored on the synthetic summary item so it can be recognized on the
296
+ * next compaction (to fold it forward) and excluded from re-summarization. It
297
+ * lives in the item JSON, not a DB column, so it survives verbatim replay.
298
+ */
299
+ declare const COMPACTION_SUMMARY_MARKER = "opengeni_context_summary";
300
+ /**
301
+ * Bridge text prepended to the summary body in the synthetic user message. It
302
+ * tells the model the preceding conversation was compacted and that durable
303
+ * facts live in the notebook — so it treats the summary as a working-memory
304
+ * pointer, not the whole truth.
305
+ */
306
+ declare const SUMMARY_PREFIX: string;
307
+ /** A user-authored `message` item is the only legal turn boundary. */
308
+ declare function isUserMessage(item: unknown): boolean;
309
+ /** True for our synthetic compaction summary item. */
310
+ declare function isCompactionSummary(item: unknown): boolean;
311
+ /**
312
+ * Rough token estimate for an item: char/4 over its serialized text. Used only
313
+ * for the tail-budget walk; the trigger decision uses the real last-turn input
314
+ * token count, falling back to this when that is unavailable.
315
+ */
316
+ declare function estimateItemTokens(item: CompactionItem): number;
317
+ declare function estimateTokens(items: readonly CompactionItem[]): number;
318
+ /**
319
+ * Walk backwards from the end of `items` keeping whole turns until the kept
320
+ * tail would exceed `keepRecentTokens`, and return the index of the first kept
321
+ * item. The returned index is always the start of a user message (a clean turn
322
+ * boundary), so the prefix [0, index) never splits a tool-call pair.
323
+ *
324
+ * Returns `items.length` when nothing fits within the budget yet a boundary is
325
+ * required (degenerate); callers treat an index of 0 or length as "no useful
326
+ * cut".
327
+ */
328
+ declare function findKeepBoundary(items: readonly CompactionItem[], keepRecentTokens: number): number;
329
+ /**
330
+ * READ-PATH BUDGET GUARD (last-resort backstop).
331
+ *
332
+ * Pre-turn compaction is best-effort: it can no-op (summarizer model call
333
+ * fails, "client" mode off, a fresh user message arrives after a turn already
334
+ * ballooned the history) and STILL leave an assembled input that exceeds the
335
+ * model context window. The #61 orphan sanitizer is purely structural — it has
336
+ * NO size awareness — so without this guard an over-budget input is sent and
337
+ * 400s every turn, re-bricking the session.
338
+ *
339
+ * `enforceInputBudget` drops the OLDEST history at a clean turn boundary until
340
+ * the estimated input fits `maxTokens`, ALWAYS keeping the most recent turn(s).
341
+ * It is orphan-safe by construction: it only ever cuts at the start of a user
342
+ * message (via `findKeepBoundary`), so no tool-call pair is split. It is a
343
+ * crude data-loss fallback (no summary is generated) that exists solely so a
344
+ * single over-budget assembled input is never put on the wire — real context
345
+ * preservation is the summarizing pre-turn path; this is the airbag.
346
+ *
347
+ * Pure: returns a new array (same item references, in order) with an oldest
348
+ * prefix omitted, or the input unchanged when it already fits. The provided
349
+ * `trailingTokens` accounts for the un-stored part of the assembled input (the
350
+ * new user/continuation message + fixed system/tool overhead) so the cap is
351
+ * measured against the WHOLE request, not just the stored history.
352
+ */
353
+ declare function enforceInputBudget<T extends CompactionItem>(items: readonly T[], maxTokens: number, trailingTokens?: number): {
354
+ items: T[];
355
+ trimmed: boolean;
356
+ droppedCount: number;
357
+ estimatedTokens: number;
358
+ };
359
+ type CompactionPlan = {
360
+ /** Whether a compaction should run this turn. */
361
+ shouldCompact: boolean;
362
+ /** Why not, when shouldCompact is false (for logs/tests). */
363
+ reason: "below_threshold" | "no_boundary" | "nothing_to_summarize" | "compact";
364
+ /**
365
+ * The signal-token count the trigger decision was made on:
366
+ * max(actual last-turn input tokens, char/4 estimate of the active items).
367
+ * Recorded for logging / metrics and so a caller can reason about pressure.
368
+ */
369
+ signalTokens: number;
370
+ /**
371
+ * True when the signal reached hardFraction*B — the session is at/over the
372
+ * hard ceiling and compaction was forced even if the recorded last-turn count
373
+ * was stale-low. The boundary walk is run with a SHRUNK keep-recent budget in
374
+ * this case so an over-budget history always yields a non-empty prefix to
375
+ * summarize (the everything-is-"recent" deadlock can't strand it un-compacted).
376
+ */
377
+ hardForced: boolean;
378
+ /** Index (into the active items) where the kept tail begins. */
379
+ boundaryIndex: number;
380
+ /**
381
+ * The prefix items to summarize: active[0, boundaryIndex), EXCLUDING any
382
+ * prior compaction summary (which is folded forward via `priorSummaryItem`).
383
+ */
384
+ prefixItems: CompactionItem[];
385
+ /** The prior live summary item folded into this compaction, if any. */
386
+ priorSummaryItem: CompactionItem | null;
387
+ /** Items kept verbatim: active[boundaryIndex, end). */
388
+ tailItems: CompactionItem[];
389
+ };
390
+ type PlanCompactionInput = {
391
+ /** Active history items in position order (already excludes superseded rows). */
392
+ items: readonly CompactionItem[];
393
+ /**
394
+ * Actual input tokens reported for the last model call of the previous turn.
395
+ * Null/undefined falls back to a char/4 estimate over `items`.
396
+ */
397
+ lastInputTokens?: number | null;
398
+ /** Usable input budget B = window - reserved output. */
399
+ inputBudgetTokens: number;
400
+ softFraction: number;
401
+ hardFraction: number;
402
+ keepRecentTokens: number;
403
+ /**
404
+ * Operator-forced compaction (the /compact command): bypass the soft-limit
405
+ * token trigger and compact now if there is anything to summarize. The
406
+ * boundary / nothing-to-summarize guards still apply — force never invents a
407
+ * cut that would orphan a tool-call pair or summarize an empty prefix.
408
+ */
409
+ force?: boolean;
410
+ };
411
+ /**
412
+ * Decide whether and where to compact. Pure.
413
+ *
414
+ * Trigger: signal tokens >= softFraction*B (soft) or hardFraction*B (hard).
415
+ * Signal = MAX(actual last-turn input tokens, char/4 estimate of the active
416
+ * items). The max — not "trust the recorded count, estimate only when it's
417
+ * null" — is the self-heal fix: `sessions.last_input_tokens` is written ONLY
418
+ * when a model response reports usage, so a turn that OVERFLOWS on its first
419
+ * model call records NOTHING and the column keeps a STALE-POSITIVE value from
420
+ * the last good turn (e.g. ~600k). Trusting that stale-low number let an
421
+ * actually-over-budget history (>1.05M) slip under the soft limit and overflow
422
+ * again, re-bricking with no self-heal. Taking the max means a bloated history
423
+ * triggers compaction regardless of a stale recorded count.
424
+ *
425
+ * Hard force (hardFraction*B): at/over the hard ceiling we compact even if the
426
+ * recorded count was stale-low, AND we run the boundary walk with a shrunk
427
+ * keep-recent budget so an over-budget history always yields a non-empty prefix
428
+ * — otherwise a history where the whole thing reads as "recent" (tail within
429
+ * keepRecentTokens) would find no prefix and strand the session over budget.
430
+ *
431
+ * Boundary: the earliest user-message boundary whose kept tail fits the
432
+ * (possibly shrunk) keep-recent budget. The prefix before it (minus any prior
433
+ * summary, which is folded forward) is what gets summarized.
434
+ */
435
+ declare function planCompaction(input: PlanCompactionInput): CompactionPlan;
436
+ /** Extract the plain-text body of the prior summary item, if any. */
437
+ declare function compactionSummaryText(item: CompactionItem | null): string;
438
+ /**
439
+ * Build the synthetic summary item (a plain user message) to insert at the
440
+ * boundary. `summaryBody` is the model-generated working-memory bridge.
441
+ */
442
+ declare function buildSummaryItem(summaryBody: string): CompactionItem;
443
+ /**
444
+ * Instruction prompt for the summarizer model call. Leans on OpenGeni's durable
445
+ * structured memory (the notebook) so the summary stays a light working-memory
446
+ * bridge, never a place secret values get copied.
447
+ */
448
+ declare const SUMMARY_INSTRUCTIONS: string;
449
+ /**
450
+ * Render the prefix items into a transcript the summarizer reads. Keeps it
451
+ * bounded by truncating individual items; the model call itself is what
452
+ * produces the compact result.
453
+ */
454
+ declare function renderPrefixTranscript(items: readonly CompactionItem[], priorSummaryText: string): string;
455
+ /**
456
+ * The summarizer model call payload: a system instruction plus the rendered
457
+ * prefix transcript. The caller turns this into a single model request (no
458
+ * tools, no streaming) and feeds the text result into `buildSummaryItem`.
459
+ */
460
+ declare function buildCompactionMessages(plan: CompactionPlan): {
461
+ system: string;
462
+ user: string;
463
+ };
464
+
465
+ type NormalizedRuntimeEvent = {
466
+ type: SessionEventType;
467
+ payload: unknown;
468
+ };
469
+ type ModelResponseUsage = {
470
+ responseId?: string;
471
+ usage: {
472
+ inputTokens?: number;
473
+ outputTokens?: number;
474
+ totalTokens?: number;
475
+ inputTokensDetails?: Record<string, number> | Array<Record<string, number>>;
476
+ };
477
+ };
478
+ declare function ensureReadableStreamFrom(): void;
479
+ type AgentSegmentInput = {
480
+ kind: "message";
481
+ text: string;
482
+ serializedRunState?: string | null;
483
+ historyItems?: AgentInputItem[] | null;
484
+ sandboxEnvelope?: Record<string, unknown> | null;
485
+ } | {
486
+ kind: "approval";
487
+ serializedRunState: string;
488
+ approvalId: string;
489
+ decision: "approve" | "reject";
490
+ message?: string;
491
+ };
492
+ type PreparedAgentInput = {
493
+ input: string | AgentInputItem[] | RunState<any, any>;
494
+ sandboxSessionState?: SandboxSessionState;
495
+ serializedRunStateForSandbox?: string;
496
+ };
497
+ type SandboxFileDownload = {
498
+ fileId: string;
499
+ mountPath: string;
500
+ filename: string;
501
+ url?: string;
502
+ content?: Uint8Array;
503
+ expiresAt?: Date | string;
504
+ sizeBytes?: number;
505
+ };
506
+ type OpenGeniRuntime = {
507
+ configure: (settings: Settings) => void;
508
+ resolveTurnModel: (settings: Settings, modelId: string) => ReturnType<typeof resolveTurnModel>;
509
+ buildAgent: (settings: Settings, resources: ResourceRef[], options?: BuildAgentOptions) => Agent<any, any>;
510
+ prepareTools: (settings: Settings, tools: ToolRef[], options?: PrepareToolsOptions) => Promise<PreparedAgentTools>;
511
+ prepareInput: (agent: Agent<any, any>, input: AgentSegmentInput, options?: PrepareInputOptions) => Promise<PreparedAgentInput>;
512
+ runStream: (agent: Agent<any, any>, input: PreparedAgentInput, settings: Settings, options?: RunAgentStreamOptions) => Promise<Awaited<ReturnType<typeof runAgentStream>>>;
513
+ serializeApprovals: (interruptions: unknown[]) => unknown[];
514
+ };
515
+ type ProductionRuntimeOverrides = {
516
+ model?: Model;
517
+ sandboxClient?: unknown;
518
+ };
519
+ declare function createProductionAgentRuntime(overrides?: ProductionRuntimeOverrides): OpenGeniRuntime;
520
+ /**
521
+ * Build an OpenAI client from settings for the configured provider. Mirrors the
522
+ * client construction in configureOpenAI so a direct API call (the compaction
523
+ * summarizer) uses the same Azure/OpenAI auth and base URL. Returns null when
524
+ * the OpenAI-platform path has only a key (the SDK default client is used via
525
+ * setDefaultOpenAIKey there); the caller then constructs a key-only client.
526
+ */
527
+ declare function buildOpenAIClientFromSettings(settings: Settings): OpenAI;
528
+ declare function buildProviderClient(provider: ResolvedModelProvider, settings: Settings): OpenAI;
529
+ /**
530
+ * Bind a model id to a provider's OpenAI client as an @openai/agents `Model`
531
+ * instance, choosing the wire API by the provider's declared `api`: the "chat"
532
+ * providers (e.g. Fireworks) get an OpenAIChatCompletionsModel that speaks
533
+ * /v1/chat/completions, the "responses" providers (built-in OpenAI/Azure) get
534
+ * an OpenAIResponsesModel that speaks /v1/responses. Passing this Model into
535
+ * the agent is what routes a turn to its provider without mutating the global
536
+ * default client.
537
+ */
538
+ declare function buildModelInstance(provider: ResolvedModelProvider, client: OpenAI, modelId: string): Model;
539
+ /**
540
+ * Resolved per-turn model routing: the provider that serves `modelId`, its
541
+ * (cached) OpenAI client, the provider-bound `Model` instance, and the
542
+ * configured-model shape (label/api/contextWindow/reasoningEffort/hostedWebSearch).
543
+ * Returns null when the model is not in the registry — the caller then falls
544
+ * back to the legacy global-client path (settings.openaiModel + the default
545
+ * client configured by configureOpenAI), preserved byte-for-byte.
546
+ */
547
+ declare function resolveTurnModel(settings: Settings, modelId: string): {
548
+ provider: ResolvedModelProvider;
549
+ client: OpenAI;
550
+ model: Model;
551
+ configured: ConfiguredModel;
552
+ } | null;
553
+ /**
554
+ * Routes a model *name* to its provider-bound Model (Fireworks chat model for a
555
+ * registry model id, the built-in OpenAI/Azure responses model otherwise) via
556
+ * `resolveTurnModel`. This is the load-bearing piece for the sandbox path:
557
+ * passing a Model *instance* as `agent.model` only survives the in-process
558
+ * (`sandboxBackend: "none"`) run — on the SandboxAgent/Modal path the instance
559
+ * is dropped and the model *name* is re-resolved through the run's
560
+ * `modelProvider` (or the global default). Without this router that re-resolution
561
+ * hits the default client (e.g. Azure) and a registry model 404s
562
+ * ("deployment does not exist"); with it the name resolves back to the right
563
+ * provider. Installed both as the run-scoped `Runner.config.modelProvider` (every
564
+ * run in runAgentStream goes through `runScopedRunner(settings)`, built from the
565
+ * per-turn settings) and as the process default (see configureOpenAI). The
566
+ * run-scoped instance is the load-bearing one: a `Runner` resolves string model
567
+ * names against ITS OWN modelProvider, not the lazy global default, so each
568
+ * concurrent turn routes codex/registry names against its own settings and a
569
+ * foreign turn's setDefaultModelProvider can never clobber this turn's routing.
570
+ * The process default remains only as a boot-time fallback. Falls back to the
571
+ * SDK default provider for a model that is in no provider's allow-list.
572
+ */
573
+ declare class MultiProviderModelProvider implements ModelProvider {
574
+ private readonly settings;
575
+ private fallback;
576
+ constructor(settings: Settings);
577
+ getModel(modelName?: string): Promise<Model>;
578
+ }
579
+ /**
580
+ * A `codex/<slug>` turn reached the model router but the workspace has no active
581
+ * Codex subscription connected (the worker overlay never injected the synthetic
582
+ * provider, so resolveTurnModel returned nothing). Thrown instead of silently
583
+ * routing the id to the built-in Azure/OpenAI client — that produced an opaque
584
+ * "DeploymentNotFound" 404. The message is user-actionable (connect/reconnect)
585
+ * and carries no status/code, so agentRunFailurePayload surfaces it verbatim as
586
+ * a non-retryable turn.failed the session UI shows.
587
+ */
588
+ declare class CodexSubscriptionUnavailableError extends Error {
589
+ constructor(modelName: string);
590
+ }
591
+ declare function configureOpenAI(settings: Settings): void;
592
+ /**
593
+ * Run the compaction summarizer as one plain, tool-less, non-streaming model
594
+ * call against the resolved provider. `system`/`user` come from
595
+ * buildCompactionMessages. Returns the trimmed summary text, or null on any
596
+ * failure (the caller treats a failed summarize as "skip compaction this turn"
597
+ * — never fatal). The call deliberately does NOT request reasoning encryption,
598
+ * tools, or server-side compaction; it is a self-contained summarize.
599
+ *
600
+ * Provider-aware: the summary always runs on the SAME provider that serves the
601
+ * turn (registry providers can't summarize through OpenAI/Azure, and vice
602
+ * versa). `api: "chat"` providers (Fireworks) speak /v1/chat/completions, where
603
+ * the summary is choices[0].message.content; `api: "responses"` (the default,
604
+ * built-in OpenAI/Azure) speaks /v1/responses as before. When no client/api is
605
+ * supplied it falls back to the built-in OpenAI/Azure Responses path so the
606
+ * legacy global-client callers are byte-for-byte unchanged. store:false is set
607
+ * only on the OpenAI-platform Responses path (Azure rejects it; chat ignores it).
608
+ */
609
+ declare function summarizeForCompaction(settings: Settings, messages: {
610
+ system: string;
611
+ user: string;
612
+ }, options?: {
613
+ client?: OpenAI;
614
+ api?: ModelProviderApi;
615
+ maxOutputTokens?: number;
616
+ model?: string;
617
+ }): Promise<string | null>;
618
+ /**
619
+ * Pull the assistant text out of a Responses API result, shape-tolerant. Only
620
+ * `role === "assistant"` message items contribute: a provider whose Responses
621
+ * endpoint echoes the user input back as an output `message` item (Fireworks'
622
+ * beta /v1/responses does exactly this — see docs/model-providers.md) would
623
+ * otherwise corrupt the summary with the prompt it was given. The OpenAI/Azure
624
+ * Responses API only emits assistant messages, so this guard is a no-op there.
625
+ */
626
+ declare function extractResponseOutputText(response: unknown): string;
627
+ type BuildAgentOptions = {
628
+ model?: Model;
629
+ reasoningEffort?: ReasoningEffort;
630
+ compactionMode?: ContextCompactionMode;
631
+ hostedWebSearch?: boolean;
632
+ encryptedReasoning?: boolean;
633
+ contextWindowTokens?: number;
634
+ structuredToolTransport?: boolean;
635
+ codexConnectorNamespaces?: ReadonlySet<string>;
636
+ sandboxEnvironment?: Record<string, string>;
637
+ activeSandboxBackend?: Settings["sandboxBackend"];
638
+ fileResourceDownloads?: SandboxFileDownload[];
639
+ mcpServers?: MCPServer[];
640
+ workspaceEnvironment?: WorkspaceEnvironmentContext;
641
+ gitTokenSeed?: string;
642
+ genesisTitleHint?: boolean;
643
+ instructionsTemplate?: string;
644
+ packSkills?: PackSkill[];
645
+ };
646
+ type PackSkillFile = {
647
+ path: string;
648
+ content: string;
649
+ };
650
+ type PackSkill = {
651
+ name: string;
652
+ description?: string | null;
653
+ files: PackSkillFile[];
654
+ };
655
+ /**
656
+ * Operator-facing metadata for the workspace environment attached to a run.
657
+ * Surfaced verbatim in the agent instructions: the description is where
658
+ * operators document how the exported credentials are meant to be used
659
+ * (e.g. which variable holds a deploy key and how to clone with it), so an
660
+ * agent must not have to rediscover that by enumerating `env` and guessing.
661
+ * Only metadata belongs here — never variable values.
662
+ */
663
+ type WorkspaceEnvironmentContext = {
664
+ name: string;
665
+ description?: string | null;
666
+ variableNames?: string[];
667
+ };
668
+ declare function workspaceEnvironmentInstructions(environment: WorkspaceEnvironmentContext): string[];
669
+ /**
670
+ * The non-bypassable CORE of the agent instructions: the goal-loop ownership
671
+ * line (which names the opengeni__goal_* tools and is what keeps a long-running
672
+ * session driving itself) followed by the dynamic workspace-environment block.
673
+ * Returned as ordered lines so the caller joins them with the rest of the
674
+ * instructions by " ", exactly as the historical preamble did.
675
+ *
676
+ * This is the slice a white-labelled persona template must never be able to
677
+ * drop: composeAgentInstructions() substitutes it at the persona template's
678
+ * {{core}} marker, and appends it when the marker is absent.
679
+ */
680
+ declare function coreInstructions(workspaceEnvironment?: WorkspaceEnvironmentContext): string[];
681
+ /**
682
+ * Composes the final agent instructions from a (possibly white-labelled)
683
+ * persona template and the non-bypassable CORE. The CORE is substituted at the
684
+ * template's {{core}} marker; if the template omits the marker, the CORE is
685
+ * appended after it instead (the non-bypassable fail-safe). The substitution
686
+ * and the append both join by " ", so the DEFAULT_AGENT_INSTRUCTIONS template
687
+ * with an empty environment reproduces the historical preamble byte-for-byte.
688
+ */
689
+ declare function composeAgentInstructions(template: string, workspaceEnvironment?: WorkspaceEnvironmentContext): string;
690
+ declare function buildOpenGeniAgent(settings: Settings, resources: ResourceRef[], options?: BuildAgentOptions): Agent<any, any>;
691
+ /**
692
+ * Build the SandboxAgent capability set provider-aware.
693
+ *
694
+ * The SDK's `Capabilities.default()` force-includes `compaction()`, whose
695
+ * sampling params emit `context_management:[{type:'compaction', …}]` to the
696
+ * Responses transport. The OpenAI platform honors that (server-side compaction);
697
+ * AZURE rejects it with `400 unsupported_parameter` — which is exactly the live
698
+ * production failure on Azure today. So we MUST NOT attach the compaction
699
+ * capability on the Azure / client / off paths.
700
+ *
701
+ * We rebuild the base set explicitly (`filesystem()`, `shell()`, the same
702
+ * factories the SDK default uses) and add `compaction()` ONLY on the server
703
+ * path, with an explicit `StaticCompactionPolicy(threshold)` so gpt-5.5 — which
704
+ * is absent from the SDK's hardcoded context-window map and would otherwise hit
705
+ * the wrong 240k fallback — gets the correct threshold. The SDK has no
706
+ * window-registration API, so an explicit threshold is the only way to fix it.
707
+ *
708
+ * The resolved compaction mode and the effective context window are now passed
709
+ * IN (the multi-provider caller resolves them per provider/model) rather than
710
+ * re-derived from settings here. Both default to the settings-derived value so
711
+ * callers that don't route per-model (and the existing tests) keep today's exact
712
+ * behaviour; the effective window only changes the server-path threshold when a
713
+ * resolved model declares its own contextWindowTokens.
714
+ */
715
+ declare function buildAgentCapabilities(settings: Settings, packSkills: PackSkill[], options?: {
716
+ compactionMode?: ContextCompactionMode;
717
+ contextWindowTokens?: number;
718
+ structuredToolTransport?: boolean;
719
+ }): ReturnType<typeof Capabilities.default>;
720
+ declare function sandboxRunAs(_settings: Settings): string | undefined;
721
+ type PreparedAgentTools = {
722
+ mcpServers: MCPServer[];
723
+ close: () => Promise<void>;
724
+ codexConnectorNamespaces: Set<string>;
725
+ };
726
+ type PrepareToolsOptions = {
727
+ accountId?: string;
728
+ workspaceId?: string;
729
+ sessionId?: string;
730
+ subjectId?: string;
731
+ subjectLabel?: string;
732
+ firstPartyPermissions?: Permission[];
733
+ };
734
+ declare function prepareAgentTools(settings: Settings, tools: ToolRef[], options?: PrepareToolsOptions): Promise<PreparedAgentTools>;
735
+ declare function prefixedMcpToolName(registryId: string, toolName: string): string;
736
+ type PrepareInputOptions = {
737
+ sandboxClient?: unknown;
738
+ /**
739
+ * Usable input-token budget B (window - reserved output). When set, the
740
+ * assembled history is passed through `enforceInputBudget` so a single
741
+ * over-budget input can never be sent — the last-resort backstop behind the
742
+ * best-effort pre-turn compaction. Omitted (undefined) disables the guard
743
+ * (no behaviour change for callers that don't opt in).
744
+ */
745
+ inputBudgetTokens?: number;
746
+ };
747
+ declare function prepareRunInput(agent: Agent<any, any>, input: AgentSegmentInput, options?: PrepareInputOptions): Promise<PreparedAgentInput>;
748
+ type RunAgentStreamOptions = {
749
+ sandboxClient?: unknown;
750
+ sandboxEnvironment?: Record<string, string>;
751
+ onRuntimeEvent?: (event: NormalizedRuntimeEvent) => Promise<void> | void;
752
+ ownedSandbox?: {
753
+ client: unknown;
754
+ session: unknown;
755
+ sessionState?: unknown;
756
+ setupSession?: unknown;
757
+ };
758
+ callModelInputFilter?: CallModelInputFilter;
759
+ };
760
+ declare const GENESIS_TITLE_DIRECTIVE = "This is the first turn of a new session. Before responding to the user, call the opengeni__set_session_title tool with a concise 3-7 word title that summarizes what this session is about, then address the user's request normally.";
761
+ /**
762
+ * callModelInputFilter that removes provider-assigned item ids (rs_/msg_/fc_…)
763
+ * from every input item immediately before each model call. Responses-API
764
+ * requests that carry item ids are resolved against the provider's stored
765
+ * responses, and that store is not durable enough to anchor long runs on: a
766
+ * response that streamed successfully can be missing from the store on the
767
+ * very next call, which then fails with 400 "Item with id ... not found"
768
+ * (observed live on Azure OpenAI mid-turn). All item content — including the
769
+ * encrypted reasoning payload carried in providerData when
770
+ * `openaiReasoningEncryptedContent` is on — is sent inline, so the ids add
771
+ * fragility without adding information. Pairing fields (`call_id`/`callId`)
772
+ * are separate properties and stay untouched; items are cloned, never mutated.
773
+ */
774
+ declare const stripProviderItemIdsFilter: CallModelInputFilter;
775
+ /**
776
+ * callModelInputFilter that normalizes every `computer_call` carrying BOTH
777
+ * `action` and `actions` down to EXACTLY ONE (keeps `actions`, drops `action`).
778
+ * The Azure computer-use endpoint rejects a request whose computer_call has
779
+ * both with `400 Computer call input must include exactly one of `action` or
780
+ * `actions``; and (live-proven against gpt-5.5's GA computer tool) it also
781
+ * rejects the `action`-only form, accepting ONLY the batched plural `actions`.
782
+ * The SDK 0.11.6 schema allows both, so a freshly-emitted
783
+ * screenshot call carries the redundant pair. This filter runs before EVERY
784
+ * model call — the turn-start history replay AND every mid-turn follow-up — so
785
+ * it covers the just-emitted (non-replayed) computer_call on the same turn,
786
+ * which the turn-start `prepareRunInput` sanitizer never sees. Items are cloned,
787
+ * never mutated.
788
+ */
789
+ declare const normalizeComputerCallsFilter: CallModelInputFilter;
790
+ /**
791
+ * The model-input filter applied before every model call. The computer_call
792
+ * action/actions normalizer is ALWAYS on (the Azure endpoint 400s without it);
793
+ * the provider-item-id strip is layered on top when the configured policy
794
+ * selects it.
795
+ */
796
+ declare function callModelInputFilterForSettings(settings: Settings): CallModelInputFilter | undefined;
797
+ declare function runAgentStream(agent: Agent<any, any>, input: PreparedAgentInput | string | RunState<any, any>, settings: Settings, overrides?: RunAgentStreamOptions): Promise<_openai_agents.StreamedRunResult<any, Agent<any, any>>>;
798
+
799
+ /**
800
+ * Detects the agents SDK per-segment turn cap. The cap is a pacing valve, not
801
+ * a session failure: callers should end the segment gracefully (idle) so an
802
+ * active goal's continuation loop -- or a follow-up user message -- resumes
803
+ * the work. When the SDK attached the run state at the moment the cap hit,
804
+ * the serialized form is returned so the resumed turn keeps full context.
805
+ */
806
+ declare function maxTurnsExceededRunState(error: unknown): {
807
+ serializedRunState: string | null;
808
+ } | null;
809
+ /**
810
+ * Serialized run state attached to any agents SDK error, when present.
811
+ * Provider failures usually surface as raw API errors without state; callers
812
+ * must treat a null here as "resume from the previous snapshot" rather than
813
+ * an error.
814
+ */
815
+ declare function agentsErrorRunState(error: unknown): string | null;
816
+ declare function withManifestRefreshOnResume(client: SandboxClient, targetManifest: Manifest | undefined): SandboxClient;
817
+ declare function applyMissingManifestEntries(session: SandboxSessionLike, targetManifest: Manifest): Promise<void>;
818
+ declare function withSandboxFileDownloads(client: SandboxClient, downloads: SandboxFileDownload[], context?: Pick<SandboxLifecycleHookContext, "onRuntimeEvent" | "runAs">): SandboxClient;
819
+ declare function materializeSandboxFileDownloads(session: SandboxSessionLike, downloads: SandboxFileDownload[], context?: Pick<SandboxLifecycleHookContext, "onRuntimeEvent" | "runAs">): Promise<void>;
820
+ declare function sandboxFileDownloadsForAgent(agent: unknown): SandboxFileDownload[];
821
+ /**
822
+ * Compact a tool-call output for the `agent.toolCall.output` SESSION EVENT so it
823
+ * never carries a raw binary payload. The codex-path `computer_screenshot` function
824
+ * tool returns a structured `{type:'image', image:{data: Uint8Array, mediaType}}`;
825
+ * captured verbatim its `Uint8Array` JSON-serializes as an object-of-numbers (~12.7MB
826
+ * per screenshot in session_events — ~10x the base64 form). This mirrors the desktop
827
+ * screenshot to the SAME compact `data:<mediaType>;base64,…` STRING the HOSTED
828
+ * `computer_call` event already carries (agents-core sets its output to that data-URL),
829
+ * so both computer-use transports emit one representation. The full data-URL is kept
830
+ * (not truncated) because the web timeline RENDERS the screenshot from this event
831
+ * payload — packages/react/src/timeline/tool-renderers.tsx ComputerCallRenderer
832
+ * (`out.startsWith("data:image")` → <ScreenshotFigure src={out}/>) and ViewImageRenderer.
833
+ * Non-image outputs (text strings, MCP `{isError,content}` objects, hosted computer_call
834
+ * data-URL strings) pass through unchanged.
835
+ */
836
+ declare function normalizeToolOutputForEvent(output: unknown): unknown;
837
+ declare function normalizeSdkEvent(event: RunStreamEvent): NormalizedRuntimeEvent[];
838
+ declare function modelResponseUsageFromSdkEvent(event: RunStreamEvent): ModelResponseUsage | null;
839
+ declare function serializeApprovals(interruptions: unknown[]): unknown[];
840
+ declare function buildManifest(settings: Settings, resources: ResourceRef[], environment?: Record<string, string>, fileResourceDownloads?: SandboxFileDownload[]): Manifest;
841
+ type SandboxLifecycleHookPhase = "beforeAgentStart";
842
+ type SandboxLifecycleHookContext = {
843
+ environment: Record<string, string>;
844
+ onRuntimeEvent?: (event: NormalizedRuntimeEvent) => Promise<void> | void;
845
+ runAs?: string;
846
+ gitTokenSeed?: string;
847
+ };
848
+ type SandboxLifecycleHook = {
849
+ id: string;
850
+ phase: SandboxLifecycleHookPhase;
851
+ shouldRun?: (context: SandboxLifecycleHookContext) => boolean;
852
+ run: (session: SandboxSessionLike, context: SandboxLifecycleHookContext) => Promise<void>;
853
+ };
854
+ declare function sandboxLifecycleHooksForIds(ids: string[]): SandboxLifecycleHook[];
855
+ /**
856
+ * Run the beforeAgentStart lifecycle hooks directly against an already-live box.
857
+ *
858
+ * The create/resume decoration (withSandboxLifecycleHooks) is structurally blind to
859
+ * the PROVIDED-session path: when runStream hands the SDK a live `session`
860
+ * (runOptions.sandbox.session — the lease-owned box resolved by the turn activity),
861
+ * SandboxRuntimeManager uses it as-is and never calls client.create/resume, so a
862
+ * wrapper around those methods never fires. Callers on that path invoke this
863
+ * before starting the run so the box still gets its beforeAgentStart preparation
864
+ * (repository clone + B1 askpass/token-file seed, azure-cli-login).
865
+ */
866
+ declare function runBeforeAgentStartHooks(session: SandboxSessionLike, hooks: SandboxLifecycleHook[], context: SandboxLifecycleHookContext): Promise<void>;
867
+ declare function withSandboxLifecycleHooks(client: SandboxClient, hooks: SandboxLifecycleHook[], context: SandboxLifecycleHookContext): SandboxClient;
868
+ /**
869
+ * Whether the platform should seed a repository resource by `git clone` inside
870
+ * the sandbox before the agent starts.
871
+ *
872
+ * SAFETY GATE (selfhosted/bring-your-own machine): the clone hook writes into
873
+ * `posixPath.join("/workspace", mountPath)`, which a selfhosted agent rewrites
874
+ * to a path under its REAL launch directory — so a platform-initiated clone
875
+ * lands on the user's actual disk. A connected machine already owns its
876
+ * filesystem; the platform must NEVER clone onto it. We therefore key the
877
+ * decision off the EFFECTIVE/active backend, not just the session's HOME backend
878
+ * (`settings.sandboxBackend`): a session can run on the cloud default while its
879
+ * active sandbox has been swapped to a connected machine (active_sandbox_id → a
880
+ * selfhosted lease), in which case the agent actually executes on the user's
881
+ * machine even though the home backend is e.g. "modal". `activeSandboxBackend`
882
+ * defaults to the home backend, so a session whose HOME backend is "selfhosted"
883
+ * is gated with no caller change, and every cloud path is byte-for-byte
884
+ * unchanged.
885
+ */
886
+ declare function repositoryUsesSandboxClone(settings: Settings, resource: Extract<ResourceRef, {
887
+ kind: "repository";
888
+ }>, activeSandboxBackend?: Settings["sandboxBackend"]): boolean;
889
+ declare function repositoryCloneCommand(resources: Extract<ResourceRef, {
890
+ kind: "repository";
891
+ }>[]): string;
892
+ declare function runRepositoryCloneHook(session: SandboxSessionLike, resources: Extract<ResourceRef, {
893
+ kind: "repository";
894
+ }>[], context?: SandboxLifecycleHookContext): Promise<void>;
895
+ declare function azureCliLoginCommand(): string;
896
+ declare function sandboxCommandExitCode(result: unknown): number | null;
897
+ declare function sandboxCommandOutput(result: unknown): string;
898
+ declare function sandboxCommandStillRunning(result: unknown): boolean;
899
+ declare function runAzureCliLoginHook(session: SandboxSessionLike, context?: SandboxLifecycleHookContext): Promise<void>;
900
+ declare function azureOpenAIDefaultQuery(settings: Pick<Settings, "azureOpenaiApiVersion">, baseURL: string): Record<string, string> | undefined;
901
+ /**
902
+ * The skill source fed to the SDK Skills capability. Without pack skills this
903
+ * is the plain bundled local-dir source, byte-for-byte the pre-pack behavior.
904
+ * With pack skills it becomes a single in-memory dir source combining bundled
905
+ * skill directories (as local_dir entries the SDK materializes lazily) with
906
+ * pack skill directories built from manifest-carried file content — one skill
907
+ * index, one `## Skills` instruction section, lazy `load_skill` for all of
908
+ * them. A pack skill shadows a bundled skill with the same directory name.
909
+ */
910
+ declare function lazySkillSourceWithPackSkills(packSkills: PackSkill[]): LocalDirLazySkillSource;
911
+
912
+ export { type AgentSegmentInput, type BuildAgentOptions, COMPACTION_SUMMARY_MARKER, CodexSubscriptionUnavailableError, type CompactionItem, type CompactionPlan, ComputerActionError, ComputerReadOnlyError, ComputerUnavailableError, type ComputerUseArgs, ComputerUseCapability, GENESIS_TITLE_DIRECTIVE, type HistoryItem, type ModelResponseUsage, MultiProviderModelProvider, type NormalizedRuntimeEvent, type OpenGeniRuntime, type PackSkill, type PackSkillFile, type PlanCompactionInput, type PrepareInputOptions, type PrepareToolsOptions, type PreparedAgentInput, type PreparedAgentTools, type ProductionRuntimeOverrides, type RunAgentStreamOptions, SUMMARY_INSTRUCTIONS, SUMMARY_PREFIX, SandboxComputer, type SandboxComputerOptions, type SandboxFileDownload, type SandboxLifecycleHook, type SandboxLifecycleHookContext, type SandboxLifecycleHookPhase, type WorkspaceEnvironmentContext, agentsErrorRunState, applyMissingManifestEntries, azureCliLoginCommand, azureOpenAIDefaultQuery, buildAgentCapabilities, buildCompactionMessages, buildManifest, buildModelInstance, buildOpenAIClientFromSettings, buildOpenGeniAgent, buildProviderClient, buildSummaryItem, callModelInputFilterForSettings, compactionSummaryText, composeAgentInstructions, computerUse, configureOpenAI, coreInstructions, createProductionAgentRuntime, enforceInputBudget, ensureReadableStreamFrom, estimateItemTokens, estimateTokens, extractResponseOutputText, findKeepBoundary, isCompactionSummary, isUserMessage, lazySkillSourceWithPackSkills, materializeSandboxFileDownloads, maxTurnsExceededRunState, modelResponseUsageFromSdkEvent, neutralizeToolSearchItemsInSerializedRunState, normalizeComputerCallsFilter, normalizeSdkEvent, normalizeToolOutputForEvent, planCompaction, prefixedMcpToolName, prepareAgentTools, prepareRunInput, renderPrefixTranscript, repositoryCloneCommand, repositoryUsesSandboxClone, resolveTurnModel, runAgentStream, runAzureCliLoginHook, runBeforeAgentStartHooks, runRepositoryCloneHook, sandboxCommandExitCode, sandboxCommandOutput, sandboxCommandStillRunning, sandboxFileDownloadsForAgent, sandboxLifecycleHooksForIds, sandboxRunAs, sanitizeHistoryItemsForModel, serializeApprovals, stripProviderItemIdsFilter, stripReasoningEncryptedContent, stripReasoningIdentityFromSerializedRunState, summarizeForCompaction, withManifestRefreshOnResume, withSandboxFileDownloads, withSandboxLifecycleHooks, workspaceEnvironmentInstructions };