@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.
- package/dist/chunk-2PO56VAL.js +3478 -0
- package/dist/chunk-2PO56VAL.js.map +1 -0
- package/dist/index.d.ts +912 -0
- package/dist/index.js +3663 -0
- package/dist/index.js.map +1 -0
- package/dist/sandbox/index.d.ts +1738 -0
- package/dist/sandbox/index.js +187 -0
- package/dist/sandbox/index.js.map +1 -0
- package/package.json +49 -0
- package/src/bundled_hashicorp_terraform_skills/LICENSE +373 -0
- package/src/bundled_hashicorp_terraform_skills/README.md +18 -0
- package/src/bundled_hashicorp_terraform_skills/UPSTREAM_GIT_SHA +1 -0
- package/src/bundled_hashicorp_terraform_skills/azure-verified-modules/SKILL.md +613 -0
- package/src/bundled_hashicorp_terraform_skills/checkov/SKILL.md +43 -0
- package/src/bundled_hashicorp_terraform_skills/refactor-module/SKILL.md +538 -0
- package/src/bundled_hashicorp_terraform_skills/social-media-marketing/SKILL.md +35 -0
- package/src/bundled_hashicorp_terraform_skills/terraform-search-import/SKILL.md +372 -0
- package/src/bundled_hashicorp_terraform_skills/terraform-search-import/references/MANUAL-IMPORT.md +113 -0
- package/src/bundled_hashicorp_terraform_skills/terraform-search-import/scripts/list_resources.sh +38 -0
- package/src/bundled_hashicorp_terraform_skills/terraform-stacks/SKILL.md +480 -0
- package/src/bundled_hashicorp_terraform_skills/terraform-stacks/references/api-monitoring.md +543 -0
- package/src/bundled_hashicorp_terraform_skills/terraform-stacks/references/component-blocks.md +476 -0
- package/src/bundled_hashicorp_terraform_skills/terraform-stacks/references/deployment-blocks.md +391 -0
- package/src/bundled_hashicorp_terraform_skills/terraform-stacks/references/examples.md +1529 -0
- package/src/bundled_hashicorp_terraform_skills/terraform-stacks/references/linked-stacks.md +187 -0
- package/src/bundled_hashicorp_terraform_skills/terraform-stacks/references/troubleshooting.md +671 -0
- package/src/bundled_hashicorp_terraform_skills/terraform-style-guide/SKILL.md +353 -0
- package/src/bundled_hashicorp_terraform_skills/terraform-test/SKILL.md +451 -0
- package/src/bundled_hashicorp_terraform_skills/terraform-test/references/CI_CD.md +80 -0
- package/src/bundled_hashicorp_terraform_skills/terraform-test/references/EXAMPLES.md +314 -0
- package/src/bundled_hashicorp_terraform_skills/terraform-test/references/MOCK_PROVIDERS.md +171 -0
- package/src/codex-tool-search.ts +267 -0
- package/src/context-compaction.ts +538 -0
- package/src/history-sanitizer.ts +719 -0
- package/src/index.ts +3299 -0
- package/src/sandbox/capabilities.ts +69 -0
- package/src/sandbox/channel-a.ts +1031 -0
- package/src/sandbox/display-stack.ts +231 -0
- package/src/sandbox/errors.ts +34 -0
- package/src/sandbox/index.ts +832 -0
- package/src/sandbox/providers/blaxel.ts +35 -0
- package/src/sandbox/providers/cloudflare.ts +24 -0
- package/src/sandbox/providers/daytona.ts +34 -0
- package/src/sandbox/providers/docker.ts +17 -0
- package/src/sandbox/providers/e2b.ts +36 -0
- package/src/sandbox/providers/index.ts +107 -0
- package/src/sandbox/providers/local.ts +13 -0
- package/src/sandbox/providers/modal.ts +55 -0
- package/src/sandbox/providers/none.ts +13 -0
- package/src/sandbox/providers/runloop.ts +32 -0
- package/src/sandbox/providers/selfhosted.ts +96 -0
- package/src/sandbox/providers/types.ts +38 -0
- package/src/sandbox/providers/vercel.ts +29 -0
- package/src/sandbox/recording.ts +286 -0
- package/src/sandbox/routing/backend-resolver.ts +189 -0
- package/src/sandbox/routing/routing-session.ts +455 -0
- package/src/sandbox/select.ts +371 -0
- package/src/sandbox/selfhosted/capabilities.ts +255 -0
- package/src/sandbox/selfhosted/control-rpc.ts +351 -0
- package/src/sandbox/selfhosted/session.ts +930 -0
- package/src/sandbox/selfhosted/testing.ts +230 -0
- package/src/sandbox/stream-port.ts +185 -0
- package/src/sandbox/stream-token.ts +90 -0
- package/src/sandbox/terminal-server.ts +203 -0
- package/src/sandbox-computer.ts +835 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/history-sanitizer.ts","../src/codex-tool-search.ts","../src/context-compaction.ts","../src/sandbox-computer.ts"],"sourcesContent":["import type { ConfiguredModel, ContextCompactionMode, ModelProviderApi, ResolvedModelProvider, Settings } from \"@opengeni/config\";\nimport { AGENT_INSTRUCTIONS_CORE_PLACEHOLDER, collectSandboxEnvironment, contextServerCompactThreshold, firstPartyMcpBaseUrl, parseExposedPorts, resolveContextCompactionMode, resolveModelProvider, sandboxLifecycleHookIds } from \"@opengeni/config\";\nimport { CAPABILITY_DESCRIPTORS, isClearedRunStateBlob, signDelegatedAccessToken, type Permission, type ReasoningEffort, type ResourceRef, type SessionEventType, type ToolRef } from \"@opengeni/contracts\";\nimport {\n Agent,\n AgentsError,\n connectMcpServers,\n OpenAIProvider,\n setDefaultModelProvider,\n MaxTurnsExceededError,\n MCPServerStreamableHttp,\n // Provider-bound Model instances. Both are re-exported from\n // @openai/agents-openai via `export * from '@openai/agents-openai'` in\n // @openai/agents' index (0.11.6), so the multi-provider routing imports them\n // from the same entrypoint as the rest of the SDK rather than reaching into\n // the openai subpackage. OpenAIChatCompletionsModel speaks /v1/chat/completions\n // (the registry \"chat\" wire API, e.g. Fireworks); OpenAIResponsesModel speaks\n // /v1/responses (the built-in OpenAI/Azure \"responses\" wire API). Both bind a\n // model id to a specific OpenAI client, which is what routes a turn to its\n // provider without touching the global default client.\n OpenAIChatCompletionsModel,\n OpenAIResponsesModel,\n RunState,\n isOpenAIResponsesRawModelStreamEvent,\n run,\n Runner,\n setDefaultOpenAIClient,\n setDefaultOpenAIKey,\n setOpenAIResponsesTransport,\n // Hosted web_search tool factory. Re-exported from @openai/agents-openai via\n // `export * from '@openai/agents-openai'` in @openai/agents' index (0.11.6);\n // it returns a { type: 'hosted_tool', providerData: { type: 'web_search' } }\n // descriptor the OpenAI Responses model serializes into request.tools[].\n webSearchTool,\n // The SDK's V4A-diff applier — the apply_patch host the filesystem capability's\n // editor uses. The agent-loop-free sandbox leaf cannot import it (it lives behind\n // the `@openai/agents` root the leaf forbids), so the barrel imports it here and\n // injects it into the selfhosted session's `createEditor` via setSelfhostedApplyDiff\n // (below, right after the leaf re-export). This lets a selfhosted active backend\n // apply file edits over its NATS fs ops using the SDK's exact diff semantics.\n applyDiff,\n type AgentInputItem,\n type CallModelInputFilter,\n type MCPServer,\n type Model,\n type ModelProvider,\n type RunStreamEvent,\n} from \"@openai/agents\";\nimport {\n localDirLazySkillSource,\n} from \"@openai/agents/sandbox/local\";\nimport {\n Capabilities,\n Manifest,\n SandboxAgent,\n StaticCompactionPolicy,\n azureBlobMount,\n compaction,\n dir,\n file,\n filesystem,\n gitRepo,\n inContainerMountStrategy,\n localDir,\n s3Mount,\n shell,\n skills,\n type Dir,\n type Entry,\n type LocalDirLazySkillSource,\n type SandboxClient,\n type SandboxSessionLike,\n type SandboxSessionState,\n type SandboxRunConfig,\n type SkillIndexEntry,\n} from \"@openai/agents/sandbox\";\nimport { ModalCloudBucketMountStrategy } from \"@openai/agents-extensions/sandbox/modal\";\nimport OpenAI from \"openai\";\nimport { CODEX_APPS_MCP_SERVER_ID, CODEX_MODEL_ID_PREFIX, CODEX_ORIGINATOR, codexAppsSanitizingFetch, codexRequestStorage, codexSubscriptionFetch } from \"@opengeni/codex\";\nimport { cpSync, existsSync, mkdirSync, readdirSync, renameSync, rmSync } from \"node:fs\";\nimport { dirname, isAbsolute, join, posix as posixPath, relative } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nimport { computerCallNormalizingFetch, normalizeComputerCallActions, sanitizeHistoryItemsForModel } from \"./history-sanitizer\";\nimport { installCodexToolSearch } from \"./codex-tool-search\";\nimport { enforceInputBudget, estimateItemTokens } from \"./context-compaction\";\nimport {\n createSandboxClient,\n deserializeSandboxSessionStateEnvelope,\n desktopCapableBackend,\n restoredSandboxSessionStateFromEntry,\n setSelfhostedApplyDiff,\n} from \"./sandbox\";\nimport { computerUse } from \"./sandbox-computer\";\n\n// P4.3 computer-use surface (the agent's :0 driver). Re-exported from the barrel\n// so callers (the worker, live proofs) reach SandboxComputer/ComputerUseCapability\n// alongside the rest of the runtime. NOT part of the agent-loop-free leaf (it\n// imports computerTool from the @openai/agents root).\nexport {\n SandboxComputer,\n ComputerUseCapability,\n computerUse,\n ComputerUnavailableError,\n ComputerReadOnlyError,\n ComputerActionError,\n type SandboxComputerOptions,\n type ComputerUseArgs,\n} from \"./sandbox-computer\";\n\n// The agent-loop-free sandbox leaf (createSandboxClient + resume/recovery\n// helpers + the config-owned env/port re-exports). Re-exported verbatim so the\n// barrel surface is unchanged for apps/worker while @opengeni/runtime/sandbox\n// stays importable by the API without the agent loop.\nexport * from \"./sandbox\";\n\n// Inject the SDK's V4A `applyDiff` into the selfhosted session's apply_patch editor\n// at module load. The leaf can't import `applyDiff` (agent-loop root), so the\n// barrel — which already imports `@openai/agents` — wires it once. A selfhosted\n// active backend can now apply file edits over its NATS fs ops with the SDK's exact\n// diff semantics; without this, `createEditor()` throws a clear \"not injected\" error\n// rather than mis-editing. Runs at import time, before any turn binds a capability.\nsetSelfhostedApplyDiff(applyDiff as unknown as (input: string, diff: string, mode?: \"default\" | \"create\") => string);\n\nexport { sanitizeHistoryItemsForModel, stripReasoningEncryptedContent, stripReasoningIdentityFromSerializedRunState, neutralizeToolSearchItemsInSerializedRunState } from \"./history-sanitizer\";\nexport type { HistoryItem } from \"./history-sanitizer\";\n\n// The provider-bound Model classes used by buildModelInstance/resolveTurnModel.\n// Re-exported so callers (and routing tests) can assert which wire API a\n// resolved turn was bound to — OpenAIChatCompletionsModel for registry \"chat\"\n// providers (Fireworks), OpenAIResponsesModel for the built-in \"responses\" path\n// — without reaching into @openai/agents directly.\nexport { OpenAIChatCompletionsModel, OpenAIResponsesModel } from \"@openai/agents\";\n\nexport {\n planCompaction,\n enforceInputBudget,\n buildSummaryItem,\n buildCompactionMessages,\n isCompactionSummary,\n isUserMessage,\n findKeepBoundary,\n estimateTokens,\n estimateItemTokens,\n compactionSummaryText,\n renderPrefixTranscript,\n COMPACTION_SUMMARY_MARKER,\n SUMMARY_PREFIX,\n SUMMARY_INSTRUCTIONS,\n} from \"./context-compaction\";\nexport type { CompactionItem, CompactionPlan, PlanCompactionInput } from \"./context-compaction\";\n\nensureReadableStreamFrom();\n\nconst SANDBOX_LIFECYCLE_COMMAND_TIMEOUT_MS = 120_000;\n\nexport type NormalizedRuntimeEvent = {\n type: SessionEventType;\n payload: unknown;\n};\n\nexport type ModelResponseUsage = {\n responseId?: string;\n usage: {\n inputTokens?: number;\n outputTokens?: number;\n totalTokens?: number;\n inputTokensDetails?: Record<string, number> | Array<Record<string, number>>;\n };\n};\n\ntype RuntimeMcpTool = Awaited<ReturnType<MCPServer[\"listTools\"]>>[number];\n\nexport function ensureReadableStreamFrom(): void {\n const ctor = globalThis.ReadableStream as (typeof ReadableStream & {\n from?: <T>(source: Iterable<T> | AsyncIterable<T>) => ReadableStream<T>;\n }) | undefined;\n if (!ctor || typeof ctor.from === \"function\") {\n return;\n }\n Object.defineProperty(ctor, \"from\", {\n configurable: true,\n writable: true,\n value<T>(source: Iterable<T> | AsyncIterable<T>): ReadableStream<T> {\n const iterator = isAsyncIterable(source)\n ? source[Symbol.asyncIterator]()\n : source[Symbol.iterator]();\n return new ReadableStream<T>({\n async pull(controller) {\n const next = await iterator.next();\n if (next.done) {\n controller.close();\n } else {\n controller.enqueue(next.value);\n }\n },\n async cancel() {\n await iterator.return?.();\n },\n });\n },\n });\n}\n\nexport type AgentSegmentInput =\n | {\n kind: \"message\";\n text: string;\n serializedRunState?: string | null;\n // Items-mode conversation truth (issue #35): when provided, turn input is\n // built from these verbatim AgentInputItems and the stored sandbox\n // envelope — no RunState deserialization, no SDK-version coupling.\n historyItems?: AgentInputItem[] | null;\n sandboxEnvelope?: Record<string, unknown> | null;\n }\n | { kind: \"approval\"; serializedRunState: string; approvalId: string; decision: \"approve\" | \"reject\"; message?: string };\n\nexport type PreparedAgentInput = {\n input: string | AgentInputItem[] | RunState<any, any>;\n sandboxSessionState?: SandboxSessionState;\n serializedRunStateForSandbox?: string;\n};\n\nexport type SandboxFileDownload = {\n fileId: string;\n mountPath: string;\n filename: string;\n url?: string;\n content?: Uint8Array;\n expiresAt?: Date | string;\n sizeBytes?: number;\n};\n\nexport type OpenGeniRuntime = {\n configure: (settings: Settings) => void;\n // Multi-provider per-turn model routing. Returns the resolved provider, its\n // (cached) client, the provider-bound Model instance, and the configured-model\n // shape; null when the turn's model is not in the registry, so the caller\n // falls back to the legacy global-client path (settings.openaiModel).\n resolveTurnModel: (settings: Settings, modelId: string) => ReturnType<typeof resolveTurnModel>;\n buildAgent: (settings: Settings, resources: ResourceRef[], options?: BuildAgentOptions) => Agent<any, any>;\n prepareTools: (settings: Settings, tools: ToolRef[], options?: PrepareToolsOptions) => Promise<PreparedAgentTools>;\n prepareInput: (agent: Agent<any, any>, input: AgentSegmentInput, options?: PrepareInputOptions) => Promise<PreparedAgentInput>;\n runStream: (agent: Agent<any, any>, input: PreparedAgentInput, settings: Settings, options?: RunAgentStreamOptions) => Promise<Awaited<ReturnType<typeof runAgentStream>>>;\n serializeApprovals: (interruptions: unknown[]) => unknown[];\n};\n\nexport type ProductionRuntimeOverrides = {\n model?: Model;\n sandboxClient?: unknown;\n};\n\nexport function createProductionAgentRuntime(overrides: ProductionRuntimeOverrides = {}): OpenGeniRuntime {\n return {\n configure: configureOpenAI,\n // A test/override model shadows the registry routing entirely (the scripted\n // model used in worker tests is not in any provider's allow-list), so when\n // one is supplied resolveTurnModel reports \"no resolution\" and the caller\n // keeps the legacy global-client path with the override model.\n resolveTurnModel: (settings, modelId) => (overrides.model ? null : resolveTurnModel(settings, modelId)),\n buildAgent: (settings, resources, options) => buildOpenGeniAgent(settings, resources, {\n ...options,\n ...(overrides.model ? { model: overrides.model } : {}),\n }),\n prepareTools: prepareAgentTools,\n prepareInput: prepareRunInput,\n runStream: async (agent, input, settings, options) => await runAgentStream(agent, input, settings, {\n ...options,\n sandboxClient: overrides.sandboxClient,\n }),\n serializeApprovals,\n };\n}\n\n/**\n * Build an OpenAI client from settings for the configured provider. Mirrors the\n * client construction in configureOpenAI so a direct API call (the compaction\n * summarizer) uses the same Azure/OpenAI auth and base URL. Returns null when\n * the OpenAI-platform path has only a key (the SDK default client is used via\n * setDefaultOpenAIKey there); the caller then constructs a key-only client.\n */\nexport function buildOpenAIClientFromSettings(settings: Settings): OpenAI {\n if (settings.openaiProvider === \"azure\") {\n const baseURL = settings.azureOpenaiBaseUrl ?? azureDeploymentBaseUrl(settings);\n const apiKey = settings.azureOpenaiApiKey ?? settings.azureOpenaiAdToken ?? \"azure-ad-token\";\n return new OpenAI({\n apiKey,\n baseURL,\n maxRetries: settings.openaiMaxRetries,\n defaultQuery: azureOpenAIDefaultQuery(settings, baseURL),\n defaultHeaders: settings.azureOpenaiAdToken && !settings.azureOpenaiApiKey\n ? { Authorization: `Bearer ${settings.azureOpenaiAdToken}` }\n : undefined,\n // Rewrite every outbound /responses computer_call to the ACTIONS-ONLY shape\n // the GA Azure computer tool (gpt-5.5) accepts. This is the lowest reachable\n // seam — below the SDK responses converter, which always re-synthesizes BOTH\n // `action` and `actions` (rejected 400 \"exactly one of action or actions\").\n // See computerCallNormalizingFetch / rewriteComputerCallsToActionsOnly.\n fetch: computerCallNormalizingFetch(globalThis.fetch),\n });\n }\n return new OpenAI({\n apiKey: settings.openaiApiKey ?? process.env.OPENAI_API_KEY,\n ...(settings.openaiBaseUrl ? { baseURL: settings.openaiBaseUrl } : {}),\n maxRetries: settings.openaiMaxRetries,\n });\n}\n\n/**\n * One OpenAI client per resolved provider id, built lazily and cached for the\n * process. The built-in openai/azure provider reuses\n * buildOpenAIClientFromSettings verbatim (so its Azure AD/api-version/base-URL\n * construction stays byte-for-byte identical to configureOpenAI); a registry\n * provider gets a plain client pointed at its base URL with its resolved key,\n * the shared maxRetries budget, and its declared defaultQuery/defaultHeaders.\n * Caching by provider.id keeps concurrent multi-provider turns sharing one\n * connection pool per provider rather than reconstructing a client per turn.\n */\nconst providerClientCache = new Map<string, OpenAI>();\n\nexport function buildProviderClient(provider: ResolvedModelProvider, settings: Settings): OpenAI {\n const cached = providerClientCache.get(provider.id);\n if (cached) {\n return cached;\n }\n const client = provider.builtin\n ? buildOpenAIClientFromSettings(settings)\n : provider.kind === \"codex-subscription\"\n // Codex subscription: the static apiKey is a placeholder — the real per-request\n // bearer + ChatGPT-Account-ID, the /responses->/codex/responses rewrite, and the\n // body normalization are all injected by codexSubscriptionFetch, which reads the\n // per-workspace token from codexRequestStorage (AsyncLocalStorage) at call time.\n // The provider id is constant (\"codex-subscription\"), so one cached client serves\n // every workspace without baking a token into it.\n ? new OpenAI({\n apiKey: provider.apiKey ?? \"codex-subscription\",\n ...(provider.baseUrl ? { baseURL: provider.baseUrl } : {}),\n maxRetries: settings.openaiMaxRetries,\n fetch: codexSubscriptionFetch(globalThis.fetch),\n })\n // ResolvedModelProvider.apiKey is already the resolved key (configuredProviders\n // ran resolveProviderApiKey at config time, collapsing apiKey/apiKeyEnv), so it\n // is passed straight through here rather than re-resolved.\n : new OpenAI({\n ...(provider.apiKey ? { apiKey: provider.apiKey } : {}),\n ...(provider.baseUrl ? { baseURL: provider.baseUrl } : {}),\n maxRetries: settings.openaiMaxRetries,\n ...(provider.defaultQuery ? { defaultQuery: provider.defaultQuery } : {}),\n ...(provider.defaultHeaders ? { defaultHeaders: provider.defaultHeaders } : {}),\n });\n providerClientCache.set(provider.id, client);\n return client;\n}\n\n/**\n * Bind a model id to a provider's OpenAI client as an @openai/agents `Model`\n * instance, choosing the wire API by the provider's declared `api`: the \"chat\"\n * providers (e.g. Fireworks) get an OpenAIChatCompletionsModel that speaks\n * /v1/chat/completions, the \"responses\" providers (built-in OpenAI/Azure) get\n * an OpenAIResponsesModel that speaks /v1/responses. Passing this Model into\n * the agent is what routes a turn to its provider without mutating the global\n * default client.\n */\nexport function buildModelInstance(provider: ResolvedModelProvider, client: OpenAI, modelId: string): Model {\n return provider.api === \"chat\"\n ? new OpenAIChatCompletionsModel(client, modelId)\n : new OpenAIResponsesModel(client, modelId);\n}\n\n/**\n * Resolved per-turn model routing: the provider that serves `modelId`, its\n * (cached) OpenAI client, the provider-bound `Model` instance, and the\n * configured-model shape (label/api/contextWindow/reasoningEffort/hostedWebSearch).\n * Returns null when the model is not in the registry — the caller then falls\n * back to the legacy global-client path (settings.openaiModel + the default\n * client configured by configureOpenAI), preserved byte-for-byte.\n */\nexport function resolveTurnModel(\n settings: Settings,\n modelId: string,\n): { provider: ResolvedModelProvider; client: OpenAI; model: Model; configured: ConfiguredModel } | null {\n const resolved = resolveModelProvider(settings, modelId);\n if (!resolved) {\n return null;\n }\n const client = buildProviderClient(resolved.provider, settings);\n return {\n provider: resolved.provider,\n client,\n model: buildModelInstance(resolved.provider, client, resolved.model.id),\n configured: resolved.model,\n };\n}\n\n/**\n * Routes a model *name* to its provider-bound Model (Fireworks chat model for a\n * registry model id, the built-in OpenAI/Azure responses model otherwise) via\n * `resolveTurnModel`. This is the load-bearing piece for the sandbox path:\n * passing a Model *instance* as `agent.model` only survives the in-process\n * (`sandboxBackend: \"none\"`) run — on the SandboxAgent/Modal path the instance\n * is dropped and the model *name* is re-resolved through the run's\n * `modelProvider` (or the global default). Without this router that re-resolution\n * hits the default client (e.g. Azure) and a registry model 404s\n * (\"deployment does not exist\"); with it the name resolves back to the right\n * provider. Installed both as the run-scoped `Runner.config.modelProvider` (every\n * run in runAgentStream goes through `runScopedRunner(settings)`, built from the\n * per-turn settings) and as the process default (see configureOpenAI). The\n * run-scoped instance is the load-bearing one: a `Runner` resolves string model\n * names against ITS OWN modelProvider, not the lazy global default, so each\n * concurrent turn routes codex/registry names against its own settings and a\n * foreign turn's setDefaultModelProvider can never clobber this turn's routing.\n * The process default remains only as a boot-time fallback. Falls back to the\n * SDK default provider for a model that is in no provider's allow-list.\n */\nexport class MultiProviderModelProvider implements ModelProvider {\n private fallback: OpenAIProvider | undefined;\n\n constructor(private readonly settings: Settings) {}\n\n async getModel(modelName?: string): Promise<Model> {\n if (modelName) {\n const resolved = resolveTurnModel(this.settings, modelName);\n if (resolved) {\n // Fail-loud floor (defense in depth): a `codex/<slug>` id must only ever\n // resolve through the synthetic codex-subscription provider (which installs\n // fetch: codexSubscriptionFetch + the per-workspace bearer). If a future\n // settings path re-introduces a built-in/registry shadow that binds a\n // `codex/` id to any other provider kind, that would silently ship the id\n // to Azure/OpenAI as a deployment name (DeploymentNotFound 404). Refuse it\n // here so codex can never reach a non-codex client on ANY backend; the\n // primary fix (config configuredModels) keeps this a no-op in practice.\n if (modelName.startsWith(CODEX_MODEL_ID_PREFIX) && resolved.provider.kind !== \"codex-subscription\") {\n throw new CodexSubscriptionUnavailableError(modelName);\n }\n return resolved.model;\n }\n // A `codex/<slug>` id only resolves when the per-workspace worker overlay\n // (settingsWithCodexCredential) has injected the synthetic codex-subscription\n // provider — which it does ONLY for a workspace with an *active* connected\n // Codex subscription. If it did not resolve, the subscription is not\n // connected for this workspace, so the codex provider is absent. Falling\n // through to the built-in OpenAIProvider below would ship `codex/<slug>` to\n // the global default (Azure) client as a deployment name and surface a\n // misleading \"DeploymentNotFound\" 404. Throw a clear, user-actionable error\n // instead; it propagates through the worker's agentRunFailurePayload as the\n // turn.failed message the session UI shows. Mirrors the codex-prefix\n // awareness of assertConfiguredModel at apps/api/src/domain/sessions.ts.\n if (modelName.startsWith(CODEX_MODEL_ID_PREFIX)) {\n throw new CodexSubscriptionUnavailableError(modelName);\n }\n }\n // A non-codex model in no provider's allow-list falls back to the SDK's\n // default OpenAIProvider, which uses the global default client/key\n // configureOpenAI set up (the built-in OpenAI/Azure provider).\n this.fallback ??= new OpenAIProvider();\n return this.fallback.getModel(modelName);\n }\n}\n\n/**\n * A `codex/<slug>` turn reached the model router but the workspace has no active\n * Codex subscription connected (the worker overlay never injected the synthetic\n * provider, so resolveTurnModel returned nothing). Thrown instead of silently\n * routing the id to the built-in Azure/OpenAI client — that produced an opaque\n * \"DeploymentNotFound\" 404. The message is user-actionable (connect/reconnect)\n * and carries no status/code, so agentRunFailurePayload surfaces it verbatim as\n * a non-retryable turn.failed the session UI shows.\n */\nexport class CodexSubscriptionUnavailableError extends Error {\n constructor(modelName: string) {\n super(\n `Codex subscription model \"${modelName}\" is unavailable: no active Codex subscription is connected for this workspace. `\n + `Connect (or reconnect) your ChatGPT/Codex subscription in Settings, then retry.`,\n );\n this.name = \"CodexSubscriptionUnavailableError\";\n }\n}\n\nexport function configureOpenAI(settings: Settings): void {\n setOpenAIResponsesTransport(settings.openaiResponsesTransport);\n // Install the registry-aware router as the process default model provider so a\n // model name re-resolved on the SandboxAgent/Modal path (where a Model instance\n // does not survive) routes to its provider instead of the built-in client.\n // Built before the default-client calls below so it captures the same settings.\n const router = new MultiProviderModelProvider(settings);\n if (settings.openaiProvider === \"azure\") {\n setDefaultOpenAIClient(buildOpenAIClientFromSettings(settings));\n setDefaultModelProvider(router);\n return;\n }\n if (settings.openaiApiKey) {\n setDefaultOpenAIKey(settings.openaiApiKey);\n }\n if (settings.openaiBaseUrl) {\n setDefaultOpenAIClient(buildOpenAIClientFromSettings(settings));\n }\n setDefaultModelProvider(router);\n}\n\n/**\n * Run the compaction summarizer as one plain, tool-less, non-streaming model\n * call against the resolved provider. `system`/`user` come from\n * buildCompactionMessages. Returns the trimmed summary text, or null on any\n * failure (the caller treats a failed summarize as \"skip compaction this turn\"\n * — never fatal). The call deliberately does NOT request reasoning encryption,\n * tools, or server-side compaction; it is a self-contained summarize.\n *\n * Provider-aware: the summary always runs on the SAME provider that serves the\n * turn (registry providers can't summarize through OpenAI/Azure, and vice\n * versa). `api: \"chat\"` providers (Fireworks) speak /v1/chat/completions, where\n * the summary is choices[0].message.content; `api: \"responses\"` (the default,\n * built-in OpenAI/Azure) speaks /v1/responses as before. When no client/api is\n * supplied it falls back to the built-in OpenAI/Azure Responses path so the\n * legacy global-client callers are byte-for-byte unchanged. store:false is set\n * only on the OpenAI-platform Responses path (Azure rejects it; chat ignores it).\n */\nexport async function summarizeForCompaction(\n settings: Settings,\n messages: { system: string; user: string },\n options: { client?: OpenAI; api?: ModelProviderApi; maxOutputTokens?: number; model?: string } = {},\n): Promise<string | null> {\n const client = options.client ?? buildOpenAIClientFromSettings(settings);\n const api = options.api ?? \"responses\";\n const model = options.model ?? settings.openaiModel;\n const maxTokens = options.maxOutputTokens ?? settings.contextSummaryMaxTokens;\n try {\n if (api === \"chat\") {\n const completion = await client.chat.completions.create({\n model,\n max_tokens: maxTokens,\n messages: [\n { role: \"system\", content: messages.system },\n { role: \"user\", content: messages.user },\n ],\n } as any);\n const text = (completion as { choices?: Array<{ message?: { content?: unknown } }> }).choices?.[0]?.message?.content;\n const trimmed = typeof text === \"string\" ? text.trim() : \"\";\n return trimmed.length > 0 ? trimmed : null;\n }\n const response = await client.responses.create({\n model,\n // store:false is the OpenAI-platform-only storeless precondition; Azure\n // rejects it. The summarizer's resolved client is OpenAI/Azure on the\n // built-in path (api \"responses\"), so gate it on the built-in provider.\n ...(settings.openaiProvider === \"azure\" ? {} : { store: false }),\n max_output_tokens: maxTokens,\n input: [\n { role: \"system\", content: messages.system },\n { role: \"user\", content: messages.user },\n ],\n } as any);\n const text = extractResponseOutputText(response);\n const trimmed = text.trim();\n return trimmed.length > 0 ? trimmed : null;\n } catch (error) {\n console.error(\"context compaction summarize failed (compaction skipped this turn)\", error);\n return null;\n }\n}\n\n/**\n * Pull the assistant text out of a Responses API result, shape-tolerant. Only\n * `role === \"assistant\"` message items contribute: a provider whose Responses\n * endpoint echoes the user input back as an output `message` item (Fireworks'\n * beta /v1/responses does exactly this — see docs/model-providers.md) would\n * otherwise corrupt the summary with the prompt it was given. The OpenAI/Azure\n * Responses API only emits assistant messages, so this guard is a no-op there.\n */\nexport function extractResponseOutputText(response: unknown): string {\n if (!response || typeof response !== \"object\") {\n return \"\";\n }\n const direct = (response as { output_text?: unknown }).output_text;\n if (typeof direct === \"string\") {\n return direct;\n }\n const output = (response as { output?: unknown }).output;\n if (!Array.isArray(output)) {\n return \"\";\n }\n const parts: string[] = [];\n for (const item of output) {\n if (!item || typeof item !== \"object\") {\n continue;\n }\n if ((item as { type?: unknown }).type !== \"message\") {\n continue;\n }\n // Read assistant messages only; skip any input-echo (role \"user\"/\"system\").\n if ((item as { role?: unknown }).role !== \"assistant\") {\n continue;\n }\n const content = (item as { content?: unknown }).content;\n if (!Array.isArray(content)) {\n continue;\n }\n for (const part of content) {\n if (part && typeof part === \"object\" && typeof (part as { text?: unknown }).text === \"string\") {\n parts.push((part as { text: string }).text);\n }\n }\n }\n return parts.join(\"\");\n}\n\nexport type BuildAgentOptions = {\n model?: Model;\n reasoningEffort?: ReasoningEffort;\n // Per-turn gating overrides for the multi-provider path. Each defaults to\n // today's settings-derived behaviour when omitted, so the legacy\n // global-client callers (no model resolution) are byte-for-byte unchanged.\n //\n // - compactionMode: the resolved context-compaction path. Drives whether the\n // sandbox `compaction()` capability is attached AND whether `store: false`\n // is set (the OpenAI-platform-only storeless precondition). Registry\n // providers resolve to \"client\", so neither is applied to them.\n // Default: resolveContextCompactionMode(settings).\n // - hostedWebSearch: attach the hosted web_search tool. Only the providers\n // that actually execute it (built-in OpenAI/Azure; a registry model that\n // opts in) should get it — Fireworks accepts the param but no-ops it, which\n // would hand the agent a dead tool. Default: settings.webSearchEnabled.\n // - encryptedReasoning: round-trip reasoning.encrypted_content via\n // providerData.include. Only the Responses API carries it; the chat wire\n // API has no such field, so registry \"chat\" providers turn it off.\n // Default: settings.openaiReasoningEncryptedContent.\n // - contextWindowTokens: the model's effective window, used to derive the\n // server-path compaction threshold. A registry model can declare its own\n // (e.g. GLM 5.2's 1,048,576). Default: settings.contextWindowTokens.\n // - structuredToolTransport: whether the backend supports the Responses\n // STRUCTURED/HOSTED sandbox-tool transport — the hosted `apply_patch` tool\n // type and structured `view_image` output. The SDK's sandbox capabilities\n // pick hosted-vs-function purely from the bound model instance's constructor\n // name (supportsApplyPatchTransport / supportsStructuredToolOutputTransport).\n // Our codex turns run the OpenAIResponsesModel — which the SDK reads as\n // hosted-capable — but route it to the ChatGPT/Codex backend, which REJECTS\n // the hosted `apply_patch` type (\"Unsupported tool type: apply_patch\",\n // verified live). Set false for that backend so filesystem emits the\n // function `apply_patch` + text `view_image` variants it accepts. Default\n // true (let the SDK decide from the model instance) — non-codex paths are\n // byte-for-byte unchanged.\n compactionMode?: ContextCompactionMode;\n hostedWebSearch?: boolean;\n encryptedReasoning?: boolean;\n contextWindowTokens?: number;\n structuredToolTransport?: boolean;\n // The LIVE, by-reference connector-namespace Set from prepareAgentTools\n // (codexConnectorNamespaces): fills during each turn's codex_apps tools/list,\n // read per model call by the codex tool_search description so the model sees\n // the account's ACTUALLY-connected sources (codex-rs parity). Only meaningful\n // on the codex tool-search path.\n codexConnectorNamespaces?: ReadonlySet<string>;\n sandboxEnvironment?: Record<string, string>;\n // The EFFECTIVE/active compute backend for this turn. `settings.sandboxBackend`\n // is the session's HOME backend (the default cloud group box it was created\n // with); when a session has swapped its active sandbox to a connected machine\n // (active_sandbox_id → a selfhosted lease, while the home backend stays the\n // cloud default), the worker passes that machine's backend here so\n // filesystem-touching lifecycle hooks key off where the agent ACTUALLY runs,\n // not where it was created. The one such hook today is the repository clone\n // (sandboxRepositoryCloneHooks): a bring-your-own machine owns its real disk,\n // so the platform must NEVER `git clone` onto it. Defaults to\n // settings.sandboxBackend, so the legacy cloud paths are byte-for-byte\n // unchanged and a session whose HOME backend is \"selfhosted\" is gated with no\n // caller change.\n activeSandboxBackend?: Settings[\"sandboxBackend\"];\n fileResourceDownloads?: SandboxFileDownload[];\n mcpServers?: MCPServer[];\n workspaceEnvironment?: WorkspaceEnvironmentContext;\n // TOKEN-BROKER (B1): the run-scoped GitHub App installation token, minted ONCE\n // per turn by the worker (sandboxEnvironmentForRun's `gitToken`). Threaded here\n // OFF-MANIFEST — it is NOT part of sandboxEnvironment (the manifest env), so the\n // token VALUE never triggers the SDK's provided-session env-delta guard even\n // though it rotates every turn. buildAgent stashes it alongside the agent's\n // repository-clone hooks; runStream forwards it into the clone hook context, which\n // seeds it to the box's token FILE before the clone runs. Omitted on the\n // selfhosted path (the machine uses its own git creds) — a NO-OP there.\n gitTokenSeed?: string;\n // Genesis turn only: append a one-shot instruction to the agent's system\n // prompt telling it to title the session via opengeni__set_session_title\n // before responding. Delivered through the instructions channel (where the\n // model actually obeys), appended AFTER the non-bypassable core so a\n // white-label persona template can't drop it.\n genesisTitleHint?: boolean;\n // Per-call agent persona override (the white-label surface). Resolved by the\n // caller as session > workspace > deployment default; when omitted the\n // runtime falls back to settings.agentInstructionsTemplate. The runtime\n // substitutes the non-bypassable CORE at AGENT_INSTRUCTIONS_CORE_PLACEHOLDER\n // (or appends it when the template omits the marker), so an override can\n // restyle the persona but never drop the goal-loop contract or environment\n // block.\n instructionsTemplate?: string;\n // Skills delivered by enabled capability packs. They join the bundled\n // skills in the sandbox skill index (mounted under .agents/) so\n // skills/<name> references resolve like any other indexed skill.\n packSkills?: PackSkill[];\n};\n\nexport type PackSkillFile = {\n // Relative POSIX path inside the skill directory, e.g. \"SKILL.md\" or\n // \"references/runbook.md\".\n path: string;\n content: string;\n};\n\nexport type PackSkill = {\n name: string;\n description?: string | null;\n files: PackSkillFile[];\n};\n\n/**\n * Operator-facing metadata for the workspace environment attached to a run.\n * Surfaced verbatim in the agent instructions: the description is where\n * operators document how the exported credentials are meant to be used\n * (e.g. which variable holds a deploy key and how to clone with it), so an\n * agent must not have to rediscover that by enumerating `env` and guessing.\n * Only metadata belongs here — never variable values.\n */\nexport type WorkspaceEnvironmentContext = {\n name: string;\n description?: string | null;\n variableNames?: string[];\n};\n\nexport function workspaceEnvironmentInstructions(environment: WorkspaceEnvironmentContext): string[] {\n const lines = [\n `A workspace environment named \"${environment.name}\" is attached to this session; its variables are exported in the sandbox shell environment.`,\n ];\n const variableNames = (environment.variableNames ?? []).filter((name) => name.length > 0);\n if (variableNames.length > 0) {\n lines.push(`Exported environment variables: ${[...variableNames].sort().join(\", \")}.`);\n }\n const description = environment.description?.trim();\n if (description) {\n lines.push(`Environment notes from the operator: ${description}`);\n }\n return lines;\n}\n\n/**\n * The non-bypassable CORE of the agent instructions: the goal-loop ownership\n * line (which names the opengeni__goal_* tools and is what keeps a long-running\n * session driving itself) followed by the dynamic workspace-environment block.\n * Returned as ordered lines so the caller joins them with the rest of the\n * instructions by \" \", exactly as the historical preamble did.\n *\n * This is the slice a white-labelled persona template must never be able to\n * drop: composeAgentInstructions() substitutes it at the persona template's\n * {{core}} marker, and appends it when the marker is absent.\n */\nexport function coreInstructions(workspaceEnvironment?: WorkspaceEnvironmentContext): string[] {\n return [\n \"If the session has a goal, you own it: keep working until you call opengeni__goal_complete with concrete evidence or opengeni__goal_pause with a rationale; revise it with opengeni__goal_update; create one with opengeni__goal_set when given a long-running objective.\",\n ...(workspaceEnvironment ? workspaceEnvironmentInstructions(workspaceEnvironment) : []),\n ];\n}\n\n/**\n * Composes the final agent instructions from a (possibly white-labelled)\n * persona template and the non-bypassable CORE. The CORE is substituted at the\n * template's {{core}} marker; if the template omits the marker, the CORE is\n * appended after it instead (the non-bypassable fail-safe). The substitution\n * and the append both join by \" \", so the DEFAULT_AGENT_INSTRUCTIONS template\n * with an empty environment reproduces the historical preamble byte-for-byte.\n */\nexport function composeAgentInstructions(template: string, workspaceEnvironment?: WorkspaceEnvironmentContext): string {\n const core = coreInstructions(workspaceEnvironment).join(\" \");\n if (template.includes(AGENT_INSTRUCTIONS_CORE_PLACEHOLDER)) {\n return template.split(AGENT_INSTRUCTIONS_CORE_PLACEHOLDER).join(core);\n }\n return core ? `${template} ${core}` : template;\n}\n\nconst agentFileDownloads = new WeakMap<object, SandboxFileDownload[]>();\nconst agentRepositoryCloneHooks = new WeakMap<object, SandboxLifecycleHook[]>();\n// TOKEN-BROKER (B1): the per-turn git token seed, stashed alongside the agent's\n// repository-clone hooks (a parallel map keyed by the agent). Kept OFF the\n// manifest/defaultManifest so the rotating value never rides the SDK's provided-\n// session env; runStream reads it to build the clone hook context. Absent when\n// no repo is attached / on the selfhosted path.\nconst agentGitTokenSeed = new WeakMap<object, string>();\n// The EFFECTIVE backend the turn resolved for this agent (undefined -> the home\n// backend). Read by runStream's owned branch to keep platform box-setup hooks off\n// connected machines (a user's real computer).\nconst agentActiveSandboxBackend = new WeakMap<object, Settings[\"sandboxBackend\"]>();\n\nexport function buildOpenGeniAgent(settings: Settings, resources: ResourceRef[], options: BuildAgentOptions = {}): Agent<any, any> {\n // Resolved per-turn gating. Each override defaults to today's settings-derived\n // behaviour, so the legacy global-client callers (no resolved model) build the\n // exact same agent as before; the multi-provider worker path passes the\n // resolved provider's mode/api/window/web-search instead.\n const compactionMode = options.compactionMode ?? resolveContextCompactionMode(settings);\n const hostedWebSearch = options.hostedWebSearch ?? settings.webSearchEnabled;\n const encryptedReasoning = options.encryptedReasoning ?? settings.openaiReasoningEncryptedContent;\n const contextWindowTokens = options.contextWindowTokens ?? settings.contextWindowTokens;\n // Native hosted tools attached to every constructed agent. webSearchEnabled\n // is ON by default and provider-unconditional on the built-in path (the live\n // Azure Responses path executes the hosted web_search tool); a registry model\n // only gets it when it opts in (resolved via options.hostedWebSearch), since\n // a provider that no-ops the param would hand the agent a dead tool. The SDK\n // merges this explicit `tools` array with the MCP-server tools\n // (Agent.getAllTools = [...mcpTools, ...tools]) and, on the SandboxAgent path,\n // with the sandbox capability tools (prepareSandboxAgent: tools =\n // [...agent.tools, ...capability.tools()]), so hosted web_search coexists with\n // both rather than overriding them.\n const hostedTools = hostedWebSearch ? [webSearchTool()] : [];\n const baseConfig = {\n name: \"OpenGeni Agent\",\n model: options.model ?? settings.openaiModel,\n // White-label persona composition. The effective template is the per-call\n // override (options.instructionsTemplate, resolved by the caller as\n // session > workspace) falling back to the deployment default\n // (settings.agentInstructionsTemplate, default DEFAULT_AGENT_INSTRUCTIONS).\n // composeAgentInstructions substitutes the non-bypassable CORE (goal-loop\n // ownership + workspace-environment block) at the {{core}} marker, or\n // appends it when the template omits the marker. With the default template\n // and no environment this is byte-identical to the historical preamble.\n instructions: options.genesisTitleHint\n ? `${composeAgentInstructions(options.instructionsTemplate ?? settings.agentInstructionsTemplate, options.workspaceEnvironment)} ${GENESIS_TITLE_DIRECTIVE}`\n : composeAgentInstructions(options.instructionsTemplate ?? settings.agentInstructionsTemplate, options.workspaceEnvironment),\n modelSettings: {\n reasoning: { effort: options.reasoningEffort ?? settings.openaiReasoningEffort, summary: \"detailed\" },\n // Server-side compaction (OpenAI platform) requires store=false: the\n // server emits an opaque ENCRYPTED 'compaction' item that round-trips in\n // the request rather than being anchored to a stored response. OpenGeni\n // already runs storeless (provider item ids stripped, encrypted reasoning\n // round-tripped), so this is consistent with the existing design and\n // only set where the server compaction capability is attached. Gated on\n // the RESOLVED compaction mode (registry providers resolve to \"client\",\n // so they never carry store:false).\n ...(compactionMode === \"server\" ? { store: false } : {}),\n // Round-trip the encrypted reasoning payload with every call so chains\n // of thought survive without provider-side response storage (which is\n // what stripped provider item ids opt us out of — see\n // stripProviderItemIds). providerData.include replaces any\n // tool-derived include entries; OpenGeni's tools are MCP/sandbox\n // function tools, which contribute none. Gated on the resolved\n // encryptedReasoning flag: the chat wire API has no encrypted_content\n // field, so registry \"chat\" providers turn it off.\n ...(encryptedReasoning\n ? { providerData: { include: [\"reasoning.encrypted_content\"] } }\n : {}),\n },\n // Explicit hosted tools (web_search when enabled). Threaded into BOTH the\n // `new Agent(baseConfig)` path (sandboxBackend === \"none\") and the\n // `new SandboxAgent({ ...baseConfig, ... })` path via the shared baseConfig\n // spread; the SDK concatenates these with MCP and sandbox capability tools.\n ...(hostedTools.length ? { tools: hostedTools } : {}),\n ...(options.mcpServers?.length ? { mcpServers: options.mcpServers } : {}),\n } as const;\n\n if (settings.sandboxBackend === \"none\") {\n const agent = new Agent(baseConfig);\n maybeInstallCodexToolSearch(agent, settings, options);\n return agent;\n }\n\n const runAs = sandboxRunAs(settings);\n const agent = new SandboxAgent({\n ...baseConfig,\n defaultManifest: buildManifest(settings, resources, options.sandboxEnvironment, options.fileResourceDownloads),\n ...(runAs ? { runAs } : {}),\n capabilities: buildAgentCapabilities(settings, options.packSkills ?? [], {\n compactionMode,\n contextWindowTokens,\n ...(options.structuredToolTransport !== undefined ? { structuredToolTransport: options.structuredToolTransport } : {}),\n }),\n });\n agentFileDownloads.set(agent, normalizeSandboxFileDownloads(options.fileResourceDownloads ?? []).filter((download) => !download.content));\n agentRepositoryCloneHooks.set(agent, sandboxRepositoryCloneHooks(settings, resources, options.activeSandboxBackend));\n // Stash the EFFECTIVE backend so runStream's owned branch can skip the direct\n // beforeAgentStart hook run on a connected machine: the box there is the user's\n // REAL computer — the platform must not run setup (az login) against it. The\n // clone hooks are already excluded for selfhosted at construction (above); this\n // keeps the built-in hooks equally out.\n if (options.activeSandboxBackend) {\n agentActiveSandboxBackend.set(agent, options.activeSandboxBackend);\n }\n // TOKEN-BROKER (B1): stash the per-turn seed off-manifest so runStream can seed the\n // clone hook without the token ever touching defaultManifest / sandboxEnvironment.\n if (options.gitTokenSeed) {\n agentGitTokenSeed.set(agent, options.gitTokenSeed);\n }\n maybeInstallCodexToolSearch(agent, settings, options);\n return agent;\n}\n\n/**\n * Enable Codex-CLI-style progressive connector disclosure on a codex turn when the\n * flag is on. Gated on `structuredToolTransport === false` — the same signal that\n * identifies a codex-subscription turn (the ChatGPT backend that rejects hosted\n * tools) — so no non-codex turn is ever touched. On qualifying turns it wraps\n * `getAllTools` (clone-survivingly — see {@link installCodexToolSearch}) to defer\n * codex_apps schemas + add the client tool_search tool, whose description renders\n * the live connector namespaces threaded from prepareAgentTools.\n */\nfunction maybeInstallCodexToolSearch(agent: Agent<any, any>, settings: Settings, options: BuildAgentOptions): void {\n if (settings.codexToolSearchEnabled && options.structuredToolTransport === false) {\n installCodexToolSearch(\n agent as unknown as Parameters<typeof installCodexToolSearch>[0],\n options.codexConnectorNamespaces ?? new Set<string>(),\n );\n }\n}\n\n/**\n * Force a sandbox capability to emit its FUNCTION-transport tool variants instead\n * of the hosted ones, by dropping the model instance the SDK's transport\n * detection keys off. See {@link buildAgentCapabilities} for why (codex routes the\n * OpenAIResponsesModel to the ChatGPT backend, which rejects the hosted\n * `apply_patch` AND `computer_use_preview` tool types). The SDK reads\n * hosted-vs-function ONLY from `_modelInstance` (set via `bindModel`); overriding\n * `bindModel` to discard the instance leaves `_modelInstance` undefined, so\n * `supportsApplyPatchTransport` / `supportsStructuredToolOutputTransport` return\n * false and `tools()` emits the function variants — `apply_patch` + text\n * `view_image` for filesystem, and the `computer_*` function tools + text\n * `computer_screenshot` for computer-use. `bindModel` still returns the capability\n * so the SDK's bind chain (`.bind().bindRunAs().bindModel()`) is preserved.\n */\nfunction neutralizeStructuredToolTransport(capability: ReturnType<typeof filesystem> | ReturnType<typeof computerUse>): void {\n // Use `this` (NOT a captured reference to `capability`): the SandboxAgent binds\n // via `cap.clone().bind(session).bindRunAs(runAs).bindModel(model, instance)` and\n // runs tools() on the object the CHAIN returns. Capability.clone() copies this\n // override onto the fresh per-run instance, so bindModel must operate on and\n // RETURN `this` (the clone) — a version that mutated/returned the ORIGINAL\n // capability leaves the clone (which .bind() set `_session` on) out of the chain,\n // so tools() runs on the unbound original and throws \"Filesystem capability is\n // not bound to a SandboxSession\". Dropping the model instance is all we need:\n // supportsApplyPatchTransport(undefined) is false → the function apply_patch.\n const forceFunctionTransport = function (this: Record<string, unknown>): unknown {\n this._modelInstance = undefined;\n return this;\n };\n (capability as unknown as { bindModel: typeof forceFunctionTransport }).bindModel = forceFunctionTransport;\n}\n\n/**\n * Build the SandboxAgent capability set provider-aware.\n *\n * The SDK's `Capabilities.default()` force-includes `compaction()`, whose\n * sampling params emit `context_management:[{type:'compaction', …}]` to the\n * Responses transport. The OpenAI platform honors that (server-side compaction);\n * AZURE rejects it with `400 unsupported_parameter` — which is exactly the live\n * production failure on Azure today. So we MUST NOT attach the compaction\n * capability on the Azure / client / off paths.\n *\n * We rebuild the base set explicitly (`filesystem()`, `shell()`, the same\n * factories the SDK default uses) and add `compaction()` ONLY on the server\n * path, with an explicit `StaticCompactionPolicy(threshold)` so gpt-5.5 — which\n * is absent from the SDK's hardcoded context-window map and would otherwise hit\n * the wrong 240k fallback — gets the correct threshold. The SDK has no\n * window-registration API, so an explicit threshold is the only way to fix it.\n *\n * The resolved compaction mode and the effective context window are now passed\n * IN (the multi-provider caller resolves them per provider/model) rather than\n * re-derived from settings here. Both default to the settings-derived value so\n * callers that don't route per-model (and the existing tests) keep today's exact\n * behaviour; the effective window only changes the server-path threshold when a\n * resolved model declares its own contextWindowTokens.\n */\nexport function buildAgentCapabilities(\n settings: Settings,\n packSkills: PackSkill[],\n options: { compactionMode?: ContextCompactionMode; contextWindowTokens?: number; structuredToolTransport?: boolean } = {},\n): ReturnType<typeof Capabilities.default> {\n const mode = options.compactionMode ?? resolveContextCompactionMode(settings);\n const contextWindowTokens = options.contextWindowTokens ?? settings.contextWindowTokens;\n // The `filesystem()` capability picks hosted-vs-function tool variants from the\n // bound model instance (supportsApplyPatchTransport / structured tool output).\n // When the caller declares the backend does NOT support that structured/hosted\n // transport (codex → the ChatGPT backend rejects the hosted `apply_patch` type),\n // neutralize this capability's model binding so tools() falls to the function\n // `apply_patch` + text `view_image` variants the backend accepts — the SDK\n // handles their function_call round-trip natively, so no reimplementation.\n // Scoped to filesystem: shell() (always function tools) and compaction() (a\n // sampling param, dropped by the codex normalizer) are untouched.\n const filesystemCapability = filesystem();\n if (options.structuredToolTransport === false) {\n neutralizeStructuredToolTransport(filesystemCapability);\n }\n const caps: ReturnType<typeof Capabilities.default> = [filesystemCapability, shell()];\n if (mode === \"server\") {\n caps.push(compaction({ policy: new StaticCompactionPolicy(contextServerCompactThreshold({ ...settings, contextWindowTokens })) }));\n }\n caps.push(skills({ lazyFrom: lazySkillSourceWithPackSkills(packSkills) }));\n // P4.3 computer-use: the agent drives the SAME :0 humans watch (xdotool/XTEST +\n // scrot), but only when the desktop tier is ON, computer-use is enabled, and the\n // backend is one whose image carries the X stack (descriptorgate — honest about\n // which backends are desktop-capable today; headless/dev backends never get the\n // tool, so a misconfigured non-desktop box can't register a tool that always\n // fails). The capability's tools() bind to the live externally-owned session at\n // run time (the SandboxAgent merge); xdotool drives :0 regardless of whether any\n // viewer is attached, so no pixel-tunnel dependency.\n if (\n settings.computerUseEnabled\n && settings.sandboxDesktopEnabled\n && desktopCapableBackend(settings.sandboxBackend)\n ) {\n // computer-use is now transport-aware, exactly like filesystem: its `tools()`\n // emits the HOSTED `computer_use_preview` tool on the structured transport and a\n // set of FUNCTION `computer_*` tools on the text transport. The ChatGPT/Codex\n // backend rejects hosted tool types (only function/custom/web_search accepted),\n // so on the codex path (structuredToolTransport === false) we neutralize the\n // capability's model binding — the SAME trick used for filesystem above — so\n // `tools()` sees no model instance and emits the function tools the backend can\n // call, instead of suppressing the desktop tier entirely.\n const computerCapability = computerUse({\n dimensions: [settings.streamResolutionWidth, settings.streamResolutionHeight],\n readOnly: settings.computerUseReadOnly,\n // On the codex path the function tools deliver screenshots as a real image the\n // model can see. The ChatGPT/Codex backend rejects HOSTED tool types but DOES\n // accept `input_image` content items inside a `function_call_output` (proven by\n // openai/codex codex-rs, whose view_image tool ships exactly that shape) — so a\n // structured image tool result is seen, where a text data-URL would be unreadable.\n ...(options.structuredToolTransport === false ? { imageFunctionResults: true } : {}),\n });\n if (options.structuredToolTransport === false) {\n neutralizeStructuredToolTransport(computerCapability);\n }\n caps.push(computerCapability as unknown as ReturnType<typeof Capabilities.default>[number]);\n }\n return caps;\n}\n\nexport function sandboxRunAs(_settings: Settings): string | undefined {\n return undefined;\n}\n\nexport type PreparedAgentTools = {\n mcpServers: MCPServer[];\n close: () => Promise<void>;\n // P4 (Part B.1): the live, by-reference Set of ORIGINAL-dotted connector\n // namespaces the codex_apps transport saw across this turn's tools/list calls.\n // Accumulates as the agent lists tools during the run, so the worker reads it\n // AFTER the turn (in its finally) to cache the serving account's connector set.\n // Empty when this turn has no codex_apps server (or it never listed any\n // namespaced tool) — the worker only persists a non-empty set.\n codexConnectorNamespaces: Set<string>;\n};\n\nexport type PrepareToolsOptions = {\n accountId?: string;\n workspaceId?: string;\n // Worker-asserted session scope for first-party MCP calls; enables\n // session-scoped tools such as goal management on the API side.\n sessionId?: string;\n subjectId?: string;\n subjectLabel?: string;\n // Overrides the fixed first-party MCP permission set for this session's\n // delegated token (manager-style sessions). The caller is responsible for\n // having validated the set against the session creator's grant.\n firstPartyPermissions?: Permission[];\n};\n\nexport async function prepareAgentTools(settings: Settings, tools: ToolRef[], options: PrepareToolsOptions = {}): Promise<PreparedAgentTools> {\n // P4 (Part B.1): one Set per prepareTools call, shared by reference into the\n // codex_apps sanitizing fetch so every tools/list this turn accumulates the\n // account's connector namespaces. Surfaced on PreparedAgentTools for the worker.\n const codexConnectorNamespaces = new Set<string>();\n if (tools.length === 0) {\n return { mcpServers: [], close: async () => {}, codexConnectorNamespaces };\n }\n const registry = new Map(settings.mcpServers.map((server) => [server.id, server]));\n const servers = await Promise.all(tools.map(async (tool) => {\n const config = registry.get(tool.id);\n if (!config) {\n throw new Error(`Unknown MCP server id: ${tool.id}`);\n }\n const url = firstPartyMcpServerUrlForRun(settings, config, options.workspaceId) ?? config.url;\n const server = new PrefixedMcpServer(new MCPServerStreamableHttp({\n url,\n name: config.name ?? config.id,\n cacheToolsList: config.cacheToolsList,\n // codex_apps returns connector tools with empty `outputSchema: {}` that the\n // MCP SDK's strict Tool schema rejects (fails the turn during tools/list);\n // sanitize the response on the wire before validation. The namespace Set\n // also captures each tool's original connector namespace (P4 Part B.1).\n ...(isCodexAppsMcpServer(config) ? { fetch: codexAppsSanitizingFetch(globalThis.fetch, codexConnectorNamespaces) } : {}),\n ...await mcpServerRequestInit(settings, config, options),\n ...(config.timeoutMs ? {\n timeout: config.timeoutMs,\n clientSessionTimeoutSeconds: Math.ceil(config.timeoutMs / 1000),\n } : {}),\n }), config.id, config.allowedTools);\n // A server is connected BEST-EFFORT (a connect / tools-list failure drops\n // it instead of failing the turn) in two cases:\n // - codex_apps: connector availability is RUNTIME-DISCOVERED — the\n // device-code login may lack the connector scopes, and the backend can\n // reject the bearer at the initialize/tools-list handshake, so a 401/403\n // (or a missing/failed token) drops the server.\n // - an AUTO-ATTACHED workspace-default capability MCP (ToolRef.optional):\n // the caller never explicitly requested it, so a broken/expired\n // capability credential must SKIP the server with a warning, never kill\n // the turn before the model runs. An EXPLICITLY-requested tool omits\n // `optional` and stays strict (below), preserving the fail-loud contract.\n const optional = tool.optional === true;\n return { server, bestEffort: isCodexAppsMcpServer(config) || optional, optional };\n }));\n const requiredServers = servers.filter((entry) => !entry.bestEffort).map((entry) => entry.server);\n const bestEffortServers = servers.filter((entry) => entry.bestEffort).map((entry) => entry.server);\n // Names of the OPTIONAL capability servers (not codex_apps) so a drop is\n // surfaced as a warning; codex_apps keeps its historically-quiet drop (a\n // not-logged-in ChatGPT plan is a normal, non-noteworthy state).\n const optionalServerNames = new Set(\n servers.filter((entry) => entry.optional).map((entry) => entry.server.name),\n );\n const connectedRequired = await connectMcpServers(requiredServers, {\n connectInParallel: true,\n strict: true,\n });\n const connectedBestEffort = bestEffortServers.length\n ? await connectMcpServers(bestEffortServers, {\n connectInParallel: true,\n strict: false,\n })\n : null;\n if (connectedBestEffort) {\n for (const failed of connectedBestEffort.failed) {\n if (!optionalServerNames.has(failed.name)) {\n continue;\n }\n const error = connectedBestEffort.errors.get(failed);\n console.warn(\n `[mcp] optional capability server \"${failed.name}\" failed to connect/list tools; skipping it for this turn`,\n error instanceof Error ? error.message : error,\n );\n }\n }\n return {\n mcpServers: [...connectedRequired.active, ...(connectedBestEffort?.active ?? [])],\n close: async () => {\n await connectedRequired.close();\n if (connectedBestEffort) {\n await connectedBestEffort.close();\n }\n },\n codexConnectorNamespaces,\n };\n}\n\nasync function mcpServerRequestInit(settings: Settings, config: Settings[\"mcpServers\"][number], options: PrepareToolsOptions): Promise<{ requestInit: { headers: Record<string, string> } } | {}> {\n // codex_apps is checked FIRST so the static-headers path can never apply to\n // it: its refreshing ChatGPT/Codex bearer is resolved per-connect from the\n // codex ALS, never from a baked `config.headers` value.\n if (isCodexAppsMcpServer(config)) {\n return await codexAppsMcpRequestInit(settings);\n }\n if (isFirstPartyMcpServer(settings, config)) {\n return await firstPartyMcpRequestInit(settings, config, options);\n }\n // Third-party MCP servers get their configured credential headers (for\n // example workspace-enabled capability MCP credentials) and nothing else —\n // never OpenGeni's own access key or delegated tokens.\n if (config.headers && Object.keys(config.headers).length > 0) {\n return { requestInit: { headers: { ...config.headers } } };\n }\n return {};\n}\n\nasync function firstPartyMcpRequestInit(settings: Settings, config: Settings[\"mcpServers\"][number], options: PrepareToolsOptions): Promise<{ requestInit: { headers: Record<string, string> } } | {}> {\n if (!isFirstPartyMcpServer(settings, config)) {\n return {};\n }\n const headers: Record<string, string> = {};\n if (settings.authRequired && settings.accessKey) {\n headers[\"x-opengeni-access-key\"] = settings.accessKey;\n }\n if (settings.delegationSecret && options.accountId && options.workspaceId) {\n headers.authorization = `Bearer ${await signDelegatedAccessToken(settings.delegationSecret, {\n accountId: options.accountId,\n workspaceId: options.workspaceId,\n subjectId: options.subjectId ?? \"worker:first-party-mcp\",\n ...(options.subjectLabel ? { subjectLabel: options.subjectLabel } : {}),\n permissions: options.firstPartyPermissions ?? firstPartyMcpPermissions,\n ...(options.sessionId ? { sessionId: options.sessionId } : {}),\n exp: Math.floor(Date.now() / 1000) + 60 * 60,\n })}`;\n }\n if (Object.keys(headers).length === 0) {\n return {};\n }\n return {\n requestInit: {\n headers,\n },\n };\n}\n\n/**\n * Builds the connect-time auth headers for the codex_apps connectors MCP. The\n * bearer is resolved from codexRequestStorage — the SAME refreshing token source\n * the model fetch uses (proactive refresh + single-flight + db persist) — so the\n * token is valid at connect. A missing store (non-codex turn, or prepareTools\n * ran outside the ALS) or a token failure (needs_relogin) returns {} so the\n * best-effort connect drops the server rather than crashing the turn.\n */\nasync function codexAppsMcpRequestInit(settings: Settings): Promise<{ requestInit: { headers: Record<string, string> } } | {}> {\n const ctx = codexRequestStorage.getStore();\n if (!ctx) {\n return {};\n }\n let token;\n try {\n token = await ctx.getToken();\n } catch {\n return {};\n }\n const headers: Record<string, string> = {\n authorization: `Bearer ${token.accessToken}`,\n // The ChatGPT backend sits behind Cloudflare, which 403s requests bearing a\n // default runtime User-Agent (confirmed live: an HTML bot-block page, NOT an\n // auth failure). Send the codex client identity — the same originator/version/\n // User-Agent the model fetch uses — so the MCP connect handshake passes the edge.\n originator: CODEX_ORIGINATOR,\n \"user-agent\": `${CODEX_ORIGINATOR}/${ctx.clientVersion}`,\n version: ctx.clientVersion,\n };\n if (token.chatgptAccountId) {\n headers[\"chatgpt-account-id\"] = token.chatgptAccountId;\n }\n if (settings.codexProductSku) {\n headers[\"X-OpenAI-Product-Sku\"] = settings.codexProductSku;\n }\n return { requestInit: { headers } };\n}\n\n// The first-party MCP permission set signed into a worker's delegated token\n// when the session does not specify its own. POWERFUL BY DEFAULT: it carries\n// every permission that unlocks a first-party tool — session orchestration\n// (sessions:*), workspace environments (environments:*), and GitHub\n// (github:use) — so agents are fully capable out of the box. A user DEMOTES a\n// specific session by setting a narrower session.firstPartyMcpPermissions (the\n// create-session permission picker), which the worker uses instead. Account-\n// level scopes (billing/account/members/api_keys/workspace:admin) are\n// intentionally excluded: they gate no first-party tool and are not agent\n// capabilities. (A finer-grained capability model comes later.)\nconst firstPartyMcpPermissions: Permission[] = [\n \"workspace:read\",\n \"files:read\",\n \"documents:search\",\n \"scheduled_tasks:manage\",\n \"scheduled_tasks:run\",\n \"goals:manage\",\n \"sessions:read\",\n \"sessions:create\",\n \"sessions:control\",\n \"environments:use\",\n \"environments:manage\",\n \"github:use\",\n];\n\n// codex_apps is third-party-by-trust (the external ChatGPT connectors backend)\n// but needs DYNAMIC auth, so it is its own category — deliberately NOT folded\n// into the first-party allowlist, which would wrongly sign an OpenGeni delegated\n// token to chatgpt.com.\nfunction isCodexAppsMcpServer(config: Settings[\"mcpServers\"][number]): boolean {\n return config.id === CODEX_APPS_MCP_SERVER_ID;\n}\n\nfunction isFirstPartyMcpServer(settings: Settings, config: Settings[\"mcpServers\"][number]): boolean {\n if (![\"opengeni\", \"files\", \"docs\"].includes(config.id)) {\n return false;\n }\n if (config.url.includes(\"{workspaceId}\")) {\n return true;\n }\n const url = normalizeUrl(config.url);\n if (!url) {\n return false;\n }\n return firstPartyMcpUrls(settings).some((candidate) => candidate === url);\n}\n\nfunction firstPartyMcpServerUrlForRun(settings: Settings, config: Settings[\"mcpServers\"][number], workspaceId: string | undefined): string | null {\n if (!workspaceId || ![\"opengeni\", \"files\", \"docs\"].includes(config.id)) {\n return null;\n }\n if (config.url.includes(\"{workspaceId}\")) {\n return config.url.replaceAll(\"{workspaceId}\", workspaceId);\n }\n if (!isFirstPartyMcpServer(settings, config)) {\n return null;\n }\n const rawBase = settings.opengeniMcpUrl?.includes(\"{workspaceId}\")\n ? settings.opengeniMcpUrl.replaceAll(\"{workspaceId}\", workspaceId)\n : settings.opengeniMcpUrl\n ? scopedMcpUrlFromConfiguredBase(settings.opengeniMcpUrl, workspaceId)\n // unset → the shared loopback default (a `{workspaceId}` template owned by\n // @opengeni/config's firstPartyMcpBaseUrl), scoped to this run's workspace.\n : firstPartyMcpBaseUrl(settings).replaceAll(\"{workspaceId}\", workspaceId);\n const url = new URL(rawBase);\n if (config.id === \"docs\") {\n url.pathname = `${url.pathname.replace(/\\/+$/, \"\")}/docs`;\n }\n return url.toString();\n}\n\nfunction scopedMcpUrlFromConfiguredBase(raw: string, workspaceId: string): string {\n const url = new URL(raw);\n url.pathname = `/v1/workspaces/${workspaceId}/mcp`;\n url.search = \"\";\n url.hash = \"\";\n return url.toString();\n}\n\nfunction firstPartyMcpUrls(settings: Settings): string[] {\n // Route the unset case through the shared loopback default so the literal\n // lives in exactly one place (@opengeni/config's firstPartyMcpBaseUrl).\n const base = normalizeUrl(settings.opengeniMcpUrl ?? firstPartyMcpBaseUrl(settings));\n if (!base) {\n return [];\n }\n const docs = new URL(base);\n docs.pathname = `${docs.pathname.replace(/\\/+$/, \"\")}/docs`;\n return [base, normalizeUrl(docs.toString())].filter((value): value is string => Boolean(value));\n}\n\nfunction normalizeUrl(raw: string): string | null {\n try {\n const url = new URL(raw);\n url.hash = \"\";\n url.pathname = url.pathname.replace(/\\/+$/, \"\");\n return url.toString();\n } catch {\n return null;\n }\n}\n\nexport function prefixedMcpToolName(registryId: string, toolName: string): string {\n return `${registryId}__${toolName}`;\n}\n\nclass PrefixedMcpServer implements MCPServer {\n readonly cacheToolsList: boolean;\n readonly name: string;\n readonly prefix: string;\n private readonly allowedTools: Set<string> | undefined;\n\n constructor(private readonly inner: MCPServer, registryId: string, allowedTools?: string[]) {\n this.name = registryId;\n this.prefix = prefixedMcpToolName(registryId, \"\");\n this.cacheToolsList = inner.cacheToolsList;\n this.allowedTools = allowedTools ? new Set(allowedTools) : undefined;\n }\n\n connect(): Promise<void> {\n return this.inner.connect();\n }\n\n close(): Promise<void> {\n return this.inner.close();\n }\n\n async listTools(): Promise<RuntimeMcpTool[]> {\n const tools = await this.inner.listTools();\n return tools\n .filter((tool) => this.isAllowed(tool.name))\n .map((tool) => ({ ...tool, name: prefixedMcpToolName(this.name, tool.name) }));\n }\n\n async callTool(toolName: string, args: Record<string, unknown> | null, meta?: Record<string, unknown> | null): Promise<any> {\n const unprefixed = this.unprefixToolName(toolName);\n if (!this.isAllowed(unprefixed)) {\n throw new Error(`MCP tool ${unprefixed} is not allowed for server ${this.name}`);\n }\n return await this.inner.callTool(unprefixed, args, meta);\n }\n\n invalidateToolsCache(): Promise<void> {\n return this.inner.invalidateToolsCache();\n }\n\n async listResources(params?: Record<string, unknown>): Promise<any> {\n const resourcesServer = this.inner as MCPServer & { listResources?: (params?: Record<string, unknown>) => Promise<any> };\n if (!resourcesServer.listResources) {\n throw new Error(`MCP server ${this.name} does not support resources`);\n }\n return await resourcesServer.listResources(params);\n }\n\n async listResourceTemplates(params?: Record<string, unknown>): Promise<any> {\n const resourcesServer = this.inner as MCPServer & { listResourceTemplates?: (params?: Record<string, unknown>) => Promise<any> };\n if (!resourcesServer.listResourceTemplates) {\n throw new Error(`MCP server ${this.name} does not support resource templates`);\n }\n return await resourcesServer.listResourceTemplates(params);\n }\n\n async readResource(uri: string): Promise<any> {\n const resourcesServer = this.inner as MCPServer & { readResource?: (uri: string) => Promise<any> };\n if (!resourcesServer.readResource) {\n throw new Error(`MCP server ${this.name} does not support resource reads`);\n }\n return await resourcesServer.readResource(uri);\n }\n\n private isAllowed(toolName: string): boolean {\n return !this.allowedTools || this.allowedTools.has(toolName);\n }\n\n private unprefixToolName(toolName: string): string {\n if (!toolName.startsWith(this.prefix)) {\n throw new Error(`MCP tool ${toolName} is missing expected ${this.name} prefix`);\n }\n return toolName.slice(this.prefix.length);\n }\n}\n\n// createSandboxClient (+ withDockerNetwork / connectDockerNetwork) moved to the\n// agent-loop-free leaf ./sandbox; re-exported via `export * from \"./sandbox\"`.\n\nexport type PrepareInputOptions = {\n sandboxClient?: unknown;\n /**\n * Usable input-token budget B (window - reserved output). When set, the\n * assembled history is passed through `enforceInputBudget` so a single\n * over-budget input can never be sent — the last-resort backstop behind the\n * best-effort pre-turn compaction. Omitted (undefined) disables the guard\n * (no behaviour change for callers that don't opt in).\n */\n inputBudgetTokens?: number;\n};\n\n/**\n * Apply the read-path budget guard to an assembled model input: drop the oldest\n * history at a clean turn boundary until the request fits B. Orphan-safe (only\n * cuts at user-message boundaries) and only active when a budget is supplied.\n * The trailing user message is counted against the budget but never dropped.\n */\nfunction guardAssembledInput(\n history: AgentInputItem[],\n trailing: AgentInputItem,\n inputBudgetTokens: number | undefined,\n): AgentInputItem[] {\n if (typeof inputBudgetTokens !== \"number\" || inputBudgetTokens <= 0) {\n return [...history, trailing];\n }\n const trailingTokens = estimateItemTokens(trailing as unknown as Record<string, unknown>);\n const guarded = enforceInputBudget(\n history as unknown as Array<Record<string, unknown>>,\n inputBudgetTokens,\n trailingTokens,\n );\n if (guarded.trimmed) {\n console.warn(\n `read-path budget guard trimmed ${guarded.droppedCount} oldest history item(s) to fit input budget (${inputBudgetTokens} tokens); the over-budget input was NOT sent`,\n );\n }\n return [...(guarded.items as unknown as AgentInputItem[]), trailing];\n}\n\nexport async function prepareRunInput(agent: Agent<any, any>, input: AgentSegmentInput, options: PrepareInputOptions = {}): Promise<PreparedAgentInput> {\n if (input.kind === \"message\") {\n if (input.historyItems && input.historyItems.length > 0) {\n // Items mode: conversation truth comes from the database, the sandbox\n // recovery descriptor from its own store. The RunState blob is not\n // touched at all on this path.\n const sandboxSessionState = input.sandboxEnvelope\n ? await restoredSandboxSessionStateFromEntry(input.sandboxEnvelope, options.sandboxClient)\n : undefined;\n // Replayed conversation truth is reloaded verbatim from the database, so\n // it can contain a tool-call pairing the Responses API rejects (most\n // destructively an orphaned function_call_result with no matching\n // function_call — which 400s every turn and bricks the session until the\n // row is hand-deleted). Sanitize the in-memory copy before it reaches the\n // model so existing corruption self-heals and a future write-path race is\n // non-fatal; the stored rows are never touched.\n const sanitizedHistory = sanitizeHistoryItemsForModel(\n input.historyItems as unknown as Array<Record<string, unknown>>,\n ) as unknown as AgentInputItem[];\n return {\n // Read-path budget guard: even after the orphan sanitizer, an assembled\n // input can exceed the model window (pre-turn compaction is best-effort\n // and can no-op). Trim the oldest history at a clean turn boundary so an\n // over-budget request is never sent. No-op when no budget is supplied.\n input: guardAssembledInput(\n sanitizedHistory,\n {\n type: \"message\",\n role: \"user\",\n content: input.text,\n } as AgentInputItem,\n options.inputBudgetTokens,\n ),\n ...(sandboxSessionState ? { sandboxSessionState } : {}),\n };\n }\n // No prior state, or a cleared sentinel: start fresh. The clear sentinel\n // ({@link CLEARED_RUN_STATE_BLOB}) is not a real serialized run state — it\n // carries no $schemaVersion, so RunState.fromString would throw on it. In\n // run_state history mode this message path is the one that reads the blob\n // after a /clear, so recognizing the sentinel here is what keeps the next\n // turn working (a fresh, empty context) instead of bricking on deserialize.\n if (!input.serializedRunState || isClearedRunStateBlob(input.serializedRunState)) {\n return { input: input.text };\n }\n const state = await RunState.fromString(agent, input.serializedRunState);\n const sandboxSessionState = await restoredSandboxSessionState(state, options.sandboxClient);\n // state.history already runs the SDK's own orphan-tool-call pruning, but\n // applying the same sanitizer keeps the legacy run-state resume path under\n // one invariant with the items path and is defensive against a corrupt blob.\n const sanitizedHistory = sanitizeHistoryItemsForModel(\n state.history as unknown as Array<Record<string, unknown>>,\n ) as unknown as AgentInputItem[];\n return {\n // Read-path budget guard (see the items path above): keep an over-budget\n // resumed history off the wire by trimming the oldest turns when a budget\n // is supplied.\n input: guardAssembledInput(\n sanitizedHistory,\n {\n type: \"message\",\n role: \"user\",\n content: input.text,\n } as AgentInputItem,\n options.inputBudgetTokens,\n ),\n ...(sandboxSessionState ? { sandboxSessionState } : {}),\n serializedRunStateForSandbox: input.serializedRunState,\n };\n }\n // An approval can only be resumed against a real saved run state. If the\n // latest blob is the cleared sentinel the awaiting turn was wiped (the API\n // refuses clear in requires_action, so this is a defensive guard) — fail with\n // an honest message instead of the cryptic SDK \"missing schema version\".\n if (isClearedRunStateBlob(input.serializedRunState)) {\n throw new Error(\"Cannot resume an approval: the session context was cleared, so the awaiting run state no longer exists.\");\n }\n const state = await RunState.fromString(agent, input.serializedRunState);\n const interruptions = state.getInterruptions();\n const target = interruptions.find((item: any) => approvalIdentifier(item) === input.approvalId);\n if (!target) {\n throw new Error(`Approval not found in saved run state: ${input.approvalId}`);\n }\n if (input.decision === \"approve\") {\n state.approve(target as any);\n } else {\n state.reject(target as any, input.message ? { message: input.message } : undefined);\n }\n return { input: state };\n}\n\nexport type RunAgentStreamOptions = {\n sandboxClient?: unknown;\n sandboxEnvironment?: Record<string, string>;\n onRuntimeEvent?: (event: NormalizedRuntimeEvent) => Promise<void> | void;\n // OWNERSHIP INVERSION (P1.2): an externally-owned, already-live sandbox\n // session resolved by the per-turn resume-by-id path. When present,\n // runAgentStream does NOT build (or resume, or discard) a client — it threads\n // these straight into runOptions.sandbox as a NON-OWNED session. The SDK\n // registers a provided session non-owned (manager.js) and NEVER reaps it on a\n // normal finish (proven by spikes/sdk-keystone) — that is the keystone: the\n // one box survives across turns. Mutually exclusive with the per-run\n // createSandboxClient path (the owned branch takes precedence when both set).\n // Agent-dependent decorators (file-downloads, lifecycle/repo-clone hooks) are\n // re-applied around the resumed client here; the live `session`/`sessionState`\n // carry the box, so no create()/resume() is re-invoked inside run().\n ownedSandbox?: {\n client: unknown; // built by the per-turn resume path (the raw provider client)\n session: unknown; // SandboxSessionLike — the live, NON-OWNED handle (never reaped)\n sessionState?: unknown; // SandboxSessionState the box was resumed from\n // The UN-PROXIED established box for platform setup (lifecycle hooks + file\n // resource materialization). `session` may be the mid-turn routing proxy whose\n // every exec re-reads the active pointer — platform-initiated setup must NOT\n // follow a swap onto a connected machine (the user's real computer), so it\n // runs against this pinned handle instead. Absent -> falls back to `session`.\n setupSession?: unknown;\n };\n // A per-turn model-input filter chained AFTER the provider-item-id strip.\n // Used by the genesis-title injection to prepend a hidden, NON-PERSISTED\n // directive: a callModelInputFilter mutates only `modelData.input` for each\n // model call and never touches `state.history`/`originalInput`, so the\n // reconcile dual-write never sees it.\n callModelInputFilter?: CallModelInputFilter;\n};\n\n// One-shot directive appended to the agent's system prompt on the genesis turn\n// (see buildOpenGeniAgent's genesisTitleHint). Delivered through the\n// authoritative instructions channel so the model reliably obeys; references\n// the prefixed tool name the agent actually sees (opengeni__set_session_title).\n// Appended after the non-bypassable core so a white-label persona can't drop it.\nexport const GENESIS_TITLE_DIRECTIVE =\n \"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.\";\n\n/**\n * callModelInputFilter that removes provider-assigned item ids (rs_/msg_/fc_…)\n * from every input item immediately before each model call. Responses-API\n * requests that carry item ids are resolved against the provider's stored\n * responses, and that store is not durable enough to anchor long runs on: a\n * response that streamed successfully can be missing from the store on the\n * very next call, which then fails with 400 \"Item with id ... not found\"\n * (observed live on Azure OpenAI mid-turn). All item content — including the\n * encrypted reasoning payload carried in providerData when\n * `openaiReasoningEncryptedContent` is on — is sent inline, so the ids add\n * fragility without adding information. Pairing fields (`call_id`/`callId`)\n * are separate properties and stay untouched; items are cloned, never mutated.\n */\nexport const stripProviderItemIdsFilter: CallModelInputFilter = ({ modelData }) => ({\n ...modelData,\n input: modelData.input.map((item) => {\n if (item && typeof item === \"object\" && \"id\" in item) {\n const { id: _id, ...rest } = item as Record<string, unknown>;\n return rest as AgentInputItem;\n }\n return item;\n }),\n});\n\n/**\n * callModelInputFilter that normalizes every `computer_call` carrying BOTH\n * `action` and `actions` down to EXACTLY ONE (keeps `actions`, drops `action`).\n * The Azure computer-use endpoint rejects a request whose computer_call has\n * both with `400 Computer call input must include exactly one of `action` or\n * `actions``; and (live-proven against gpt-5.5's GA computer tool) it also\n * rejects the `action`-only form, accepting ONLY the batched plural `actions`.\n * The SDK 0.11.6 schema allows both, so a freshly-emitted\n * screenshot call carries the redundant pair. This filter runs before EVERY\n * model call — the turn-start history replay AND every mid-turn follow-up — so\n * it covers the just-emitted (non-replayed) computer_call on the same turn,\n * which the turn-start `prepareRunInput` sanitizer never sees. Items are cloned,\n * never mutated.\n */\nexport const normalizeComputerCallsFilter: CallModelInputFilter = ({ modelData }) => ({\n ...modelData,\n input: normalizeComputerCallActions(\n modelData.input as unknown as Array<Record<string, unknown>>,\n ) as unknown as AgentInputItem[],\n});\n\n/**\n * Compose a list of callModelInputFilters into one, applied left-to-right so\n * each sees the prior filter's output.\n */\nfunction composeCallModelInputFilters(filters: CallModelInputFilter[]): CallModelInputFilter {\n return async (args) => {\n let modelData = args.modelData;\n for (const filter of filters) {\n modelData = await filter({ ...args, modelData });\n }\n return modelData;\n };\n}\n\n/**\n * The model-input filter applied before every model call. The computer_call\n * action/actions normalizer is ALWAYS on (the Azure endpoint 400s without it);\n * the provider-item-id strip is layered on top when the configured policy\n * selects it.\n */\nexport function callModelInputFilterForSettings(settings: Settings): CallModelInputFilter | undefined {\n const filters: CallModelInputFilter[] = [normalizeComputerCallsFilter];\n if (settings.openaiProviderItemIds === \"strip\") {\n filters.push(stripProviderItemIdsFilter);\n }\n return composeCallModelInputFilters(filters);\n}\n\nexport async function runAgentStream(agent: Agent<any, any>, input: PreparedAgentInput | string | RunState<any, any>, settings: Settings, overrides: RunAgentStreamOptions = {}) {\n const prepared: PreparedAgentInput = typeof input === \"string\" || input instanceof RunState ? { input } : input;\n const environment = overrides.sandboxEnvironment ?? collectSandboxEnvironment(settings);\n\n // OWNED PATH (P1.2 ownership inversion): the per-turn resume path injected a\n // live, externally-owned box. We thread the live `session` straight into\n // runOptions.sandbox so the SDK registers it NON-OWNED and never reaps it on\n // a normal finish (the keystone). We re-apply ONLY the agent-dependent\n // decorators (file-downloads + lifecycle/repo-clone hooks) around the resumed\n // client — the manifest-refresh-on-resume wrap is a no-op when a live\n // `session` is supplied (resume is not re-invoked). This branch is reached\n // ONLY when sandboxOwnershipEnabled gated the activity into resolving a box;\n // with the flag off the activity never sets `ownedSandbox` and this whole\n // block is skipped (byte-for-byte the legacy path).\n if (overrides.ownedSandbox) {\n const { client: ownedClient, session, sessionState } = overrides.ownedSandbox;\n // Platform setup (hooks + file materialization) execs against the UN-PROXIED\n // established box when the caller pinned one — never through the routing proxy,\n // whose per-op pointer re-read could land these execs on a machine swapped in\n // mid-turn.\n const setupSession = (overrides.ownedSandbox.setupSession ?? session) as SandboxSessionLike;\n const runAs = sandboxRunAs(settings);\n const fileDownloads = sandboxFileDownloadsForAgent(agent);\n const resourceClient = fileDownloads.length > 0\n ? withSandboxFileDownloads(ownedClient as SandboxClient, fileDownloads, {\n ...(overrides.onRuntimeEvent ? { onRuntimeEvent: overrides.onRuntimeEvent } : {}),\n ...(runAs ? { runAs } : {}),\n })\n : (ownedClient as SandboxClient);\n // TOKEN-BROKER (B1): the per-turn git token seed, forwarded OFF-MANIFEST so the\n // repository-clone hook seeds it to the box's token file before the clone.\n const ownedGitTokenSeed = gitTokenSeedForAgent(agent);\n const ownedHooks = [\n ...sandboxLifecycleHooksForIds(sandboxLifecycleHookIds(settings)),\n ...sandboxRepositoryCloneHooksForAgent(agent),\n ];\n const ownedHookContext: SandboxLifecycleHookContext = {\n environment,\n ...(overrides.onRuntimeEvent ? { onRuntimeEvent: overrides.onRuntimeEvent } : {}),\n ...(runAs ? { runAs } : {}),\n ...(ownedGitTokenSeed ? { gitTokenSeed: ownedGitTokenSeed } : {}),\n };\n // OWNED-PATH HOOKS: the SDK NEVER calls client.create/resume when handed a live\n // provided session (SandboxRuntimeManager uses `sandboxConfig.session` directly),\n // so the withSandboxLifecycleHooks decoration below can never fire on this branch —\n // it only wraps create/resume. Run the beforeAgentStart hooks directly against the\n // provided box, once per turn, BEFORE the run starts: this is what executes the\n // repository-clone hook (which also seeds the B1 askpass + token file) and the\n // azure-cli-login hook on lease-owned boxes. Re-running on a warm box is safe by\n // construction: clone skips when the target is already materialized, the token\n // seed OVERWRITES the file (the desired per-turn refresh), and az login is\n // idempotent. A turn resumed after preemption re-enters here and re-seeds the\n // freshly minted token — which is exactly what a >1h-old warm box needs.\n // EXCEPT on a connected machine (effective backend \"selfhosted\"): the box is the\n // user's REAL computer — the platform must not run setup against it (the clone\n // hooks are already empty there; this keeps az login off it too).\n if (agentActiveSandboxBackend.get(agent) !== \"selfhosted\") {\n await runBeforeAgentStartHooks(setupSession, ownedHooks, ownedHookContext);\n // FILE RESOURCES: withSandboxFileDownloads below has the IDENTICAL provided-\n // session blind spot (it too wraps only create/resume), so signed-URL file\n // materialization must also run directly against the pinned box. The download\n // command is idempotent (skips an existing file) and atomic (tmp + rename),\n // so the per-turn re-run is safe; the turn re-signs URLs each run, so a\n // re-warmed box always gets fresh links.\n if (fileDownloads.length > 0) {\n await materializeSandboxFileDownloads(setupSession, fileDownloads, {\n ...(overrides.onRuntimeEvent ? { onRuntimeEvent: overrides.onRuntimeEvent } : {}),\n ...(runAs ? { runAs } : {}),\n });\n }\n }\n // Keep the decoration as a safety net for any session the SDK does create/resume\n // through the client during this run (it is inert for the provided session).\n const decoratedClient = withSandboxLifecycleHooks(resourceClient, ownedHooks, ownedHookContext);\n const ownedFilter = composeCallModelInputFilters(\n [callModelInputFilterForSettings(settings), overrides.callModelInputFilter].filter(\n (f): f is CallModelInputFilter => Boolean(f),\n ),\n );\n const ownedRunOptions: Parameters<typeof run>[2] = {\n stream: true,\n maxTurns: settings.agentMaxModelCallsPerTurn,\n callModelInputFilter: ownedFilter,\n };\n ownedRunOptions.sandbox = {\n client: decoratedClient,\n session,\n ...(sessionState ? { sessionState } : {}),\n } as SandboxRunConfig;\n return await runScopedRunner(settings).run(agent, prepared.input, ownedRunOptions);\n }\n\n const rawClient = overrides.sandboxClient ?? createSandboxClient(settings, environment);\n const refreshedClient = rawClient\n ? withManifestRefreshOnResume(rawClient as SandboxClient, (agent as { defaultManifest?: Manifest }).defaultManifest)\n : undefined;\n const runAs = sandboxRunAs(settings);\n const fileDownloads = sandboxFileDownloadsForAgent(agent);\n const resourceClient = refreshedClient && fileDownloads.length > 0\n ? withSandboxFileDownloads(refreshedClient, fileDownloads, {\n ...(overrides.onRuntimeEvent ? { onRuntimeEvent: overrides.onRuntimeEvent } : {}),\n ...(runAs ? { runAs } : {}),\n })\n : refreshedClient;\n // TOKEN-BROKER (B1): the per-turn git token seed, forwarded OFF-MANIFEST so the\n // repository-clone hook seeds it to the box's token file before the clone.\n const gitTokenSeed = gitTokenSeedForAgent(agent);\n const client = resourceClient\n ? withSandboxLifecycleHooks(resourceClient, [\n ...sandboxLifecycleHooksForIds(sandboxLifecycleHookIds(settings)),\n ...sandboxRepositoryCloneHooksForAgent(agent),\n ], {\n environment,\n ...(overrides.onRuntimeEvent ? { onRuntimeEvent: overrides.onRuntimeEvent } : {}),\n ...(runAs ? { runAs } : {}),\n ...(gitTokenSeed ? { gitTokenSeed } : {}),\n })\n : undefined;\n const sandboxSessionState = prepared.sandboxSessionState\n ?? (prepared.serializedRunStateForSandbox && client\n ? await restoredSandboxSessionState(await RunState.fromString(agent, prepared.serializedRunStateForSandbox), client)\n : undefined);\n // Strip provider item ids first, then apply any per-turn filter (genesis\n // title directive). Composed left-to-right so the directive lands on the\n // already-id-stripped input. A callModelInputFilter only shapes the per-call\n // model input, never the persisted run-state history.\n const callModelInputFilter = composeCallModelInputFilters(\n [callModelInputFilterForSettings(settings), overrides.callModelInputFilter].filter(\n (f): f is CallModelInputFilter => Boolean(f),\n ),\n );\n const runOptions: Parameters<typeof run>[2] = {\n stream: true,\n maxTurns: settings.agentMaxModelCallsPerTurn,\n // Strip provider-assigned item ids from every model call (turn-start\n // history replay AND mid-turn follow-ups) so requests never depend on the\n // provider's server-side response store. A stored response can vanish\n // between two calls of the same turn, failing the run with 400 \"Item with\n // id 'rs_…' not found\"; with the ids gone the request is self-contained.\n callModelInputFilter,\n };\n void settings.disableOpenaiTracing;\n if (client) {\n runOptions.sandbox = {\n client,\n ...(sandboxSessionState ? { sessionState: sandboxSessionState } : {}),\n } as SandboxRunConfig;\n }\n return await runScopedRunner(settings).run(agent, prepared.input, runOptions);\n}\n\n/**\n * A per-run `Runner` whose `modelProvider` is built from THIS turn's settings.\n *\n * The standalone `run()` uses a process-global default Runner whose modelProvider\n * is the lazy global default (whatever the last `configureOpenAI` /\n * `setDefaultModelProvider` installed). The worker runs ~100 activities\n * concurrently in one process, so a concurrently-starting turn for a DIFFERENT\n * workspace can overwrite that global between this turn's `configure` and a\n * per-call `getModel()` during the stream — leaving the global router with no\n * codex provider and throwing CodexSubscriptionUnavailableError on a\n * `codex/<slug>` name re-resolution (the SandboxAgent/Modal path drops the Model\n * instance and re-resolves by NAME). Pinning a run-scoped Runner makes the\n * mutable global irrelevant to correctness: each concurrent turn resolves names\n * against its OWN settings (which carry the codex-subscription provider via\n * withCodexProvider for an active workspace, and the registry providers). The\n * Runner inherits the SDK's default config for everything else, identical to the\n * default runner. setDefaultModelProvider remains only as a boot-time fallback.\n */\nfunction runScopedRunner(settings: Settings): Runner {\n return new Runner({ modelProvider: new MultiProviderModelProvider(settings) });\n}\n\nexport { MaxTurnsExceededError } from \"@openai/agents\";\n\n/**\n * Detects the agents SDK per-segment turn cap. The cap is a pacing valve, not\n * a session failure: callers should end the segment gracefully (idle) so an\n * active goal's continuation loop -- or a follow-up user message -- resumes\n * the work. When the SDK attached the run state at the moment the cap hit,\n * the serialized form is returned so the resumed turn keeps full context.\n */\nexport function maxTurnsExceededRunState(error: unknown): { serializedRunState: string | null } | null {\n if (!(error instanceof MaxTurnsExceededError)) {\n return null;\n }\n try {\n return { serializedRunState: error.state ? error.state.toString() : null };\n } catch {\n return { serializedRunState: null };\n }\n}\n\n/**\n * Serialized run state attached to any agents SDK error, when present.\n * Provider failures usually surface as raw API errors without state; callers\n * must treat a null here as \"resume from the previous snapshot\" rather than\n * an error.\n */\nexport function agentsErrorRunState(error: unknown): string | null {\n if (!(error instanceof AgentsError) || !error.state) {\n return null;\n }\n try {\n return error.state.toString();\n } catch {\n return null;\n }\n}\n\nexport function withManifestRefreshOnResume(client: SandboxClient, targetManifest: Manifest | undefined): SandboxClient {\n if (!targetManifest || !client.resume) {\n return client;\n }\n return {\n backendId: client.backendId,\n ...(client.supportsDefaultOptions !== undefined ? { supportsDefaultOptions: client.supportsDefaultOptions } : {}),\n ...(client.create ? { create: async (...args: any[]) => await (client.create as any)(...args) } : {}),\n resume: async (state: SandboxSessionState) => {\n const session = await client.resume!(state);\n await applyMissingManifestEntries(session, targetManifest);\n return session;\n },\n ...(client.delete ? { delete: async (state: SandboxSessionState) => await client.delete!(state) } : {}),\n ...(client.serializeSessionState ? { serializeSessionState: async (state: SandboxSessionState, options) => await client.serializeSessionState!(state, options) } : {}),\n ...(client.canPersistOwnedSessionState ? { canPersistOwnedSessionState: async (state: SandboxSessionState) => await client.canPersistOwnedSessionState!(state) } : {}),\n ...(client.canReusePreservedOwnedSession ? { canReusePreservedOwnedSession: async (state: SandboxSessionState) => await client.canReusePreservedOwnedSession!(state) } : {}),\n ...(client.deserializeSessionState ? { deserializeSessionState: async (state: Record<string, unknown>) => await client.deserializeSessionState!(state) } : {}),\n };\n}\n\nexport async function applyMissingManifestEntries(session: SandboxSessionLike, targetManifest: Manifest): Promise<void> {\n const currentManifestValue = (session as { state?: { manifest?: Manifest | { root?: string; entries?: Record<string, any>; environment?: Record<string, any> } } }).state?.manifest;\n const currentManifest = currentManifestValue ? ensureManifest(currentManifestValue) : undefined;\n const target = ensureManifest(targetManifest);\n if (!currentManifest) {\n if (Object.keys(target.entries).length === 0) {\n return;\n }\n throw new Error(\"Resumed sandbox session cannot apply new manifest entries because current manifest state is unavailable\");\n }\n if (!session.applyManifest && !session.materializeEntry) {\n if (Object.keys(target.entries).length === 0) {\n return;\n }\n throw new Error(\"Resumed sandbox session cannot apply new manifest entries because it does not support applyManifest() or materializeEntry()\");\n }\n if (Object.keys(target.entries).length === 0) {\n return;\n }\n if (currentManifest.root !== target.root) {\n throw new Error(\"Cannot apply per-turn resources to a sandbox with a different manifest root\");\n }\n const entries: Record<string, any> = {};\n for (const [path, entry] of Object.entries(target.entries)) {\n const existing = (currentManifest.entries as Record<string, unknown>)[path];\n if (existing === undefined) {\n entries[path] = entry;\n continue;\n }\n if (stableJson(existing) !== stableJson(entry)) {\n throw new Error(`Cannot replace existing sandbox manifest entry: ${path}`);\n }\n }\n const environmentChanged = stableJson(currentManifest.environment) !== stableJson(target.environment);\n if (environmentChanged && !session.applyManifest) {\n throw new Error(\"Resumed sandbox session cannot refresh manifest environment because it does not support applyManifest()\");\n }\n if (Object.keys(entries).length === 0 && !environmentChanged) {\n return;\n }\n // Carry path grants through manifest rebuilds: since @openai/agents 0.11.0\n // they gate local source materialization, and run states saved before the\n // upgrade have manifests without grants.\n const extraPathGrants = mergePathGrants(currentManifest.extraPathGrants, target.extraPathGrants);\n const delta = new Manifest({\n root: currentManifest.root,\n entries,\n environment: target.environment,\n ...(extraPathGrants.length ? { extraPathGrants } : {}),\n });\n if (session.applyManifest) {\n await session.applyManifest(delta);\n } else {\n for (const [path, entry] of Object.entries(entries)) {\n await session.materializeEntry!({ path, entry });\n }\n }\n (session as { state?: { manifest?: Manifest } }).state!.manifest = new Manifest({\n root: currentManifest.root,\n environment: environmentChanged ? target.environment : currentManifest.environment,\n entries: {\n ...currentManifest.entries,\n ...entries,\n },\n ...(extraPathGrants.length ? { extraPathGrants } : {}),\n });\n}\n\nfunction mergePathGrants(\n current: Manifest[\"extraPathGrants\"] | undefined,\n target: Manifest[\"extraPathGrants\"] | undefined,\n): Manifest[\"extraPathGrants\"] {\n const merged = new Map<string, Manifest[\"extraPathGrants\"][number]>();\n for (const grant of [...(current ?? []), ...(target ?? [])]) {\n merged.set(grant.path, grant);\n }\n return [...merged.values()];\n}\n\nexport function withSandboxFileDownloads(\n client: SandboxClient,\n downloads: SandboxFileDownload[],\n context: Pick<SandboxLifecycleHookContext, \"onRuntimeEvent\" | \"runAs\"> = {},\n): SandboxClient {\n const normalizedDownloads = normalizeSandboxFileDownloads(downloads);\n if (normalizedDownloads.length === 0) {\n return client;\n }\n const completed = new WeakSet<object>();\n const wrapSession = async <T extends SandboxSessionLike>(session: T): Promise<T> => {\n if (typeof session === \"object\" && session !== null && !completed.has(session)) {\n await materializeSandboxFileDownloads(session, normalizedDownloads, context);\n completed.add(session);\n }\n return session;\n };\n return {\n backendId: client.backendId,\n ...(client.supportsDefaultOptions !== undefined ? { supportsDefaultOptions: client.supportsDefaultOptions } : {}),\n ...(client.create ? { create: async (...args: any[]) => await wrapSession(await (client.create as any)(...args)) } : {}),\n ...(client.resume ? { resume: async (state: SandboxSessionState) => await wrapSession(await client.resume!(state)) } : {}),\n ...(client.delete ? { delete: async (state: SandboxSessionState) => await client.delete!(state) } : {}),\n ...(client.serializeSessionState ? { serializeSessionState: async (state: SandboxSessionState, options) => await client.serializeSessionState!(state, options) } : {}),\n ...(client.canPersistOwnedSessionState ? { canPersistOwnedSessionState: async (state: SandboxSessionState) => await client.canPersistOwnedSessionState!(state) } : {}),\n ...(client.canReusePreservedOwnedSession ? { canReusePreservedOwnedSession: async (state: SandboxSessionState) => await client.canReusePreservedOwnedSession!(state) } : {}),\n ...(client.deserializeSessionState ? { deserializeSessionState: async (state: Record<string, unknown>) => await client.deserializeSessionState!(state) } : {}),\n };\n}\n\nexport async function materializeSandboxFileDownloads(\n session: SandboxSessionLike,\n downloads: SandboxFileDownload[],\n context: Pick<SandboxLifecycleHookContext, \"onRuntimeEvent\" | \"runAs\"> = {},\n): Promise<void> {\n const normalizedDownloads = normalizeSandboxFileDownloads(downloads);\n if (normalizedDownloads.length === 0) {\n return;\n }\n if (!session.exec && !session.execCommand) {\n throw new Error(\"Sandbox file download materialization requires command execution support\");\n }\n for (const download of normalizedDownloads) {\n const targetPath = sandboxDownloadTargetPath(download);\n const payload = {\n fileId: download.fileId,\n path: targetPath,\n sizeBytes: download.sizeBytes ?? null,\n expiresAt: download.expiresAt ? new Date(download.expiresAt).toISOString() : null,\n };\n await context.onRuntimeEvent?.({ type: \"sandbox.operation.started\", payload: { name: \"file-resource-download\", ...payload } });\n try {\n const result = session.exec\n ? await session.exec({\n cmd: sandboxFileDownloadCommand(download, targetPath),\n workdir: \"/workspace\",\n ...(context.runAs ? { runAs: context.runAs } : {}),\n yieldTimeMs: SANDBOX_LIFECYCLE_COMMAND_TIMEOUT_MS,\n maxOutputTokens: 20_000,\n })\n : await session.execCommand!({\n cmd: sandboxFileDownloadCommand(download, targetPath),\n workdir: \"/workspace\",\n ...(context.runAs ? { runAs: context.runAs } : {}),\n yieldTimeMs: SANDBOX_LIFECYCLE_COMMAND_TIMEOUT_MS,\n maxOutputTokens: 20_000,\n });\n assertSandboxCommandSucceeded(result, `Sandbox file resource download ${download.fileId}`);\n await context.onRuntimeEvent?.({ type: \"sandbox.operation.completed\", payload: { name: \"file-resource-download\", ...payload } });\n } catch (error) {\n await context.onRuntimeEvent?.({\n type: \"sandbox.operation.failed\",\n payload: {\n name: \"file-resource-download\",\n ...payload,\n error: error instanceof Error ? error.message : String(error),\n },\n });\n throw error;\n }\n }\n}\n\nexport function sandboxFileDownloadsForAgent(agent: unknown): SandboxFileDownload[] {\n return typeof agent === \"object\" && agent !== null\n ? [...(agentFileDownloads.get(agent) ?? [])]\n : [];\n}\n\nfunction ensureManifest(manifest: Manifest | { root?: string; entries?: Record<string, any>; environment?: Record<string, any>; extraPathGrants?: any[] }): Manifest {\n if (manifest instanceof Manifest && typeof manifest.mountTargetsForMaterialization === \"function\") {\n return manifest;\n }\n return new Manifest({\n ...(manifest.root ? { root: manifest.root } : {}),\n entries: manifest.entries ?? {},\n environment: manifest.environment ?? {},\n ...(manifest.extraPathGrants?.length ? { extraPathGrants: manifest.extraPathGrants } : {}),\n });\n}\n\n/** Coerce the various binary shapes a tool-output image `data` field can take into\n * a Uint8Array. Handles a live `Uint8Array`, a plain number[] , and the\n * object-of-numbers (`{\"0\":137,\"1\":80,…}`) that a `Uint8Array` degrades into after\n * a JSON round-trip — the exact 10x-bloat shape this normalizer exists to kill. */\nfunction toImageBytes(data: unknown): Uint8Array | null {\n if (data instanceof Uint8Array) {\n return data;\n }\n if (Array.isArray(data)) {\n return data.every((n) => typeof n === \"number\") ? Uint8Array.from(data as number[]) : null;\n }\n if (data && typeof data === \"object\") {\n const values = Object.values(data as Record<string, unknown>);\n if (values.length > 0 && values.every((n) => typeof n === \"number\")) {\n return Uint8Array.from(values as number[]);\n }\n }\n return null;\n}\n\n/** Compact a structured image tool output — the SDK's `{type:'image', image:{data,mediaType}}`\n * shape (produced by the codex-path `computer_screenshot` function tool) OR the already-\n * normalized protocol `{type:'input_image', image:'data:…'}` item — into a `data:<mt>;base64,…`\n * string. Returns null when `value` is not an image output. */\nfunction structuredImageToDataUrl(value: unknown): string | null {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) {\n return null;\n }\n const v = value as { type?: unknown; image?: unknown };\n if (v.type === \"input_image\") {\n // Protocol item: `image` is already a `data:…` (or plain URL) string.\n return typeof v.image === \"string\" && v.image.length > 0 ? v.image : null;\n }\n if (v.type !== \"image\" || !v.image || typeof v.image !== \"object\") {\n return null;\n }\n const image = v.image as { data?: unknown; mediaType?: unknown; url?: unknown };\n if (typeof image.url === \"string\" && image.url.length > 0) {\n return image.url;\n }\n const mediaType = typeof image.mediaType === \"string\" && image.mediaType.length > 0 ? image.mediaType : \"image/png\";\n if (typeof image.data === \"string\") {\n return image.data.startsWith(\"data:\") ? image.data : `data:${mediaType};base64,${image.data}`;\n }\n const bytes = toImageBytes(image.data);\n return bytes ? `data:${mediaType};base64,${Buffer.from(bytes).toString(\"base64\")}` : null;\n}\n\n/**\n * Compact a tool-call output for the `agent.toolCall.output` SESSION EVENT so it\n * never carries a raw binary payload. The codex-path `computer_screenshot` function\n * tool returns a structured `{type:'image', image:{data: Uint8Array, mediaType}}`;\n * captured verbatim its `Uint8Array` JSON-serializes as an object-of-numbers (~12.7MB\n * per screenshot in session_events — ~10x the base64 form). This mirrors the desktop\n * screenshot to the SAME compact `data:<mediaType>;base64,…` STRING the HOSTED\n * `computer_call` event already carries (agents-core sets its output to that data-URL),\n * so both computer-use transports emit one representation. The full data-URL is kept\n * (not truncated) because the web timeline RENDERS the screenshot from this event\n * payload — packages/react/src/timeline/tool-renderers.tsx ComputerCallRenderer\n * (`out.startsWith(\"data:image\")` → <ScreenshotFigure src={out}/>) and ViewImageRenderer.\n * Non-image outputs (text strings, MCP `{isError,content}` objects, hosted computer_call\n * data-URL strings) pass through unchanged.\n */\nexport function normalizeToolOutputForEvent(output: unknown): unknown {\n const single = structuredImageToDataUrl(output);\n if (single !== null) {\n return single;\n }\n if (Array.isArray(output)) {\n const normalized = output.map((el) => structuredImageToDataUrl(el) ?? el);\n // A lone image content item unwraps to the bare data-URL string the timeline\n // image renderers expect; a mixed/multi array keeps its (now-compact) shape.\n if (normalized.length === 1 && typeof normalized[0] === \"string\") {\n return normalized[0];\n }\n return normalized;\n }\n return output;\n}\n\nexport function normalizeSdkEvent(event: RunStreamEvent): NormalizedRuntimeEvent[] {\n const out: NormalizedRuntimeEvent[] = [];\n if (event.type === \"raw_model_stream_event\") {\n const data = (event as any).data;\n if (data?.type === \"output_text_delta\" && typeof data.delta === \"string\") {\n out.push({ type: \"agent.message.delta\", payload: { text: data.delta } });\n return out;\n }\n }\n if (isOpenAIResponsesRawModelStreamEvent(event)) {\n const raw = (event as any).data?.event;\n if (raw?.type === \"response.reasoning_summary_text.delta\" && typeof raw.delta === \"string\") {\n out.push({ type: \"agent.reasoning.delta\", payload: { text: raw.delta } });\n }\n return out;\n }\n if (event.type === \"agent_updated_stream_event\") {\n out.push({ type: \"agent.updated\", payload: { agent: (event as any).agent?.name ?? null } });\n return out;\n }\n if (event.type !== \"run_item_stream_event\") {\n return out;\n }\n const item = (event as any).item;\n if (!item) {\n return out;\n }\n if (item.type === \"tool_call_item\") {\n const raw = item.rawItem ?? {};\n out.push({\n type: \"agent.toolCall.created\",\n payload: {\n id: raw.callId ?? raw.id ?? item.id ?? null,\n name: raw.name ?? raw.type ?? \"tool\",\n arguments: raw.arguments ?? raw.input ?? null,\n raw,\n },\n });\n } else if (item.type === \"tool_call_output_item\") {\n out.push({\n type: \"agent.toolCall.output\",\n payload: {\n id: item.rawItem?.callId ?? item.id ?? null,\n // Compact any structured/binary image output to a data-URL string so a\n // screenshot never bloats session_events ~10x as an object-of-numbers.\n output: normalizeToolOutputForEvent(item.output),\n },\n });\n } else if (item.type === \"tool_search_call_item\") {\n // Progressive connector disclosure: surface the model's tool search as a\n // regular tool-call event so the session stream shows the step (parity with\n // the Codex CLI, which renders its searches). Arguments may be an object\n // (the live wire shape) or a string.\n const raw = item.rawItem ?? {};\n out.push({\n type: \"agent.toolCall.created\",\n payload: {\n id: raw.call_id ?? raw.callId ?? raw.id ?? item.id ?? null,\n name: \"tool_search\",\n arguments: raw.arguments ?? null,\n raw,\n },\n });\n } else if (item.type === \"tool_search_output_item\") {\n const raw = item.rawItem ?? {};\n const disclosed = Array.isArray(raw.tools)\n ? raw.tools.map((tool: { name?: unknown }) => (typeof tool?.name === \"string\" ? tool.name : \"\")).filter(Boolean)\n : [];\n out.push({\n type: \"agent.toolCall.output\",\n payload: {\n id: raw.call_id ?? raw.callId ?? item.id ?? null,\n output: { type: \"text\", text: disclosed.length > 0 ? `Disclosed tools: ${disclosed.join(\", \")}` : \"No matching tools found.\" },\n },\n });\n } else if (item.type === \"message_output_item\") {\n const text = typeof item.text === \"string\" ? item.text : undefined;\n if (text) {\n out.push({ type: \"agent.message.completed\", payload: { text } });\n }\n }\n return out;\n}\n\nexport function modelResponseUsageFromSdkEvent(event: RunStreamEvent): ModelResponseUsage | null {\n const response = modelResponseFromSdkEvent(event);\n const usage = usageFromResponse(response);\n if (!usage) {\n return null;\n }\n const responseId = typeof response?.id === \"string\"\n ? response.id\n : typeof response?.responseId === \"string\"\n ? response.responseId\n : undefined;\n return {\n ...(responseId ? { responseId } : {}),\n usage,\n };\n}\n\nfunction modelResponseFromSdkEvent(event: RunStreamEvent): any {\n if (event.type === \"raw_model_stream_event\") {\n const data = (event as any).data;\n if (data?.type === \"response_done\") {\n return data.response;\n }\n }\n if (isOpenAIResponsesRawModelStreamEvent(event)) {\n const raw = (event as any).data?.event;\n if (raw?.type === \"response.completed\") {\n return raw.response;\n }\n }\n return null;\n}\n\nfunction usageFromResponse(response: any): ModelResponseUsage[\"usage\"] | null {\n const raw = response?.usage;\n if (!raw || typeof raw !== \"object\") {\n return null;\n }\n const usage = {\n ...numberProp(raw, \"inputTokens\", \"inputTokens\", \"input_tokens\"),\n ...numberProp(raw, \"outputTokens\", \"outputTokens\", \"output_tokens\"),\n ...numberProp(raw, \"totalTokens\", \"totalTokens\", \"total_tokens\"),\n ...inputTokenDetailsProp(raw),\n };\n return Object.keys(usage).length > 0 ? usage : null;\n}\n\nfunction numberProp(raw: Record<string, unknown>, outputKey: \"inputTokens\" | \"outputTokens\" | \"totalTokens\", camel: string, snake: string): Partial<ModelResponseUsage[\"usage\"]> {\n const value = raw[camel] ?? raw[snake];\n return typeof value === \"number\" && Number.isFinite(value) ? { [outputKey]: value } : {};\n}\n\nfunction inputTokenDetailsProp(raw: Record<string, unknown>): Partial<ModelResponseUsage[\"usage\"]> {\n const details = raw.inputTokensDetails ?? raw.input_tokens_details;\n if (!details || typeof details !== \"object\") {\n return {};\n }\n return { inputTokensDetails: details as Record<string, number> | Array<Record<string, number>> };\n}\n\nexport function serializeApprovals(interruptions: unknown[]): unknown[] {\n return interruptions.map((item: any) => {\n if (typeof item?.toJSON === \"function\") {\n return item.toJSON();\n }\n return {\n id: approvalIdentifier(item),\n name: item?.name ?? item?.rawItem?.name ?? \"tool\",\n arguments: item?.arguments ?? item?.rawItem?.arguments ?? null,\n raw: item,\n };\n });\n}\n\nexport function buildManifest(\n settings: Settings,\n resources: ResourceRef[],\n environment = collectSandboxEnvironment(settings),\n fileResourceDownloads: SandboxFileDownload[] = [],\n): Manifest {\n const entries: Record<string, any> = {};\n const downloadsByFileId = new Map(normalizeSandboxFileDownloads(fileResourceDownloads).map((download) => [download.fileId, download]));\n for (const resource of resources) {\n if (resource.kind === \"repository\") {\n const url = new URL(resource.uri);\n const host = url.hostname.toLowerCase();\n const repo = url.pathname.replace(/^\\/+|\\/+$/g, \"\").replace(/\\.git$/, \"\");\n const mountPath = normalizeManifestPath(resource.mountPath ?? `repos/${repo}`);\n if (repositoryUsesSandboxClone(settings, resource)) {\n entries[mountPath] = dir();\n continue;\n }\n entries[mountPath] = gitRepo({\n host,\n repo,\n ref: resource.ref,\n ...(resource.subpath ? { subpath: normalizeManifestPath(resource.subpath) } : {}),\n });\n continue;\n }\n if (resource.kind === \"file\") {\n const mountPath = normalizeManifestPath(resource.mountPath ?? `files/${resource.fileId}`);\n const download = downloadsByFileId.get(resource.fileId);\n entries[mountPath] = download\n ? sandboxDownloadDirectory(download, mountPath)\n : objectStorageFileMount(settings, `files/${resource.fileId}/original`);\n }\n }\n // No extraPathGrants here: remote sandbox clients (Modal) reject manifests\n // that carry them at create/apply time, which broke every Modal session.\n // The lazy bundled-skills source no longer needs a grant because\n // bundledSkillsDir() stages the skills inside the process working directory\n // whenever the packaged copy lives outside it.\n return new Manifest({\n root: \"/workspace\",\n entries,\n environment,\n });\n}\n\nfunction sandboxDownloadDirectory(download: SandboxFileDownload, mountPath: string): any {\n if (download.mountPath !== mountPath) {\n throw new Error(`File download materialization path mismatch for ${download.fileId}: expected ${mountPath}, got ${download.mountPath}`);\n }\n assertSafeSandboxFilename(download.filename, download.fileId);\n if (download.content) {\n return dir({\n children: {\n [download.filename]: file({ content: download.content }),\n },\n });\n }\n return dir();\n}\n\nfunction objectStorageFileMount(settings: Settings, prefix: string): any {\n // Descriptor-driven: a nativeBucketMount backend (modal) mounts via the\n // provider's own bucket-mount strategy and cannot mount Azure Blob entries —\n // it needs pre-signed downloads instead. Reading the descriptor (not a\n // hard-coded backend name) keeps this honest as providers are added.\n const nativeBucketMount = CAPABILITY_DESCRIPTORS[settings.sandboxBackend].nativeBucketMount;\n if (settings.objectStorageBackend === \"azure-blob\") {\n if (nativeBucketMount) {\n throw new Error(\"Modal sandbox Azure Blob file resources require pre-signed download materialization because the current OpenAI Agents SDK Modal client does not support Azure Blob mount entries.\");\n }\n const config = azureBlobMountConfig(settings);\n return azureBlobMount({\n container: config.container,\n prefix,\n accountName: config.accountName,\n accountKey: config.accountKey,\n endpointUrl: config.endpointUrl,\n readOnly: true,\n mountStrategy: inContainerMountStrategy({ pattern: { type: \"rclone\", mode: \"fuse\" } }),\n });\n }\n if (settings.objectStorageBackend === \"aws-s3\" || settings.objectStorageBackend === \"gcs\") {\n throw new Error(`${settings.objectStorageBackend} file resources require pre-signed download materialization`);\n }\n const config = s3CompatibleMountConfig(settings);\n return s3Mount({\n bucket: config.bucket,\n prefix,\n endpointUrl: config.endpointUrl,\n region: config.region,\n s3Provider: config.s3Provider,\n accessKeyId: config.accessKeyId,\n secretAccessKey: config.secretAccessKey,\n readOnly: true,\n mountStrategy: nativeBucketMount\n ? new ModalCloudBucketMountStrategy()\n : inContainerMountStrategy({ pattern: { type: \"rclone\", mode: \"fuse\" } }),\n });\n}\n\nfunction s3CompatibleMountConfig(settings: Settings): {\n bucket: string;\n endpointUrl: string;\n region: string;\n s3Provider: string;\n accessKeyId: string;\n secretAccessKey: string;\n} {\n const endpointUrl = settings.objectStorageSandboxEndpoint ?? settings.objectStorageEndpoint;\n if (!endpointUrl || !settings.objectStorageAccessKeyId || !settings.objectStorageSecretAccessKey) {\n throw new Error(\"File resources require configured S3-compatible object storage\");\n }\n return {\n bucket: settings.objectStorageBucket,\n endpointUrl,\n region: settings.objectStorageRegion,\n s3Provider: settings.objectStorageS3Provider,\n accessKeyId: settings.objectStorageAccessKeyId,\n secretAccessKey: settings.objectStorageSecretAccessKey,\n };\n}\n\nfunction azureBlobMountConfig(settings: Settings): {\n container: string;\n accountName: string;\n accountKey: string;\n endpointUrl?: string;\n} {\n const parsed = settings.objectStorageAzureConnectionString\n ? parseAzureConnectionString(settings.objectStorageAzureConnectionString)\n : {};\n const accountName = settings.objectStorageAzureAccountName ?? parsed.AccountName;\n const accountKey = settings.objectStorageAzureAccountKey ?? parsed.AccountKey;\n if (!accountName || !accountKey) {\n throw new Error(\"File resources require Azure Blob account name and account key\");\n }\n const endpointUrl = azureBlobManifestEndpoint(settings.objectStorageAzureEndpoint ?? parsed.BlobEndpoint, accountName);\n return {\n container: settings.objectStorageBucket,\n accountName,\n accountKey,\n ...(endpointUrl ? { endpointUrl } : {}),\n };\n}\n\nfunction azureBlobManifestEndpoint(endpoint: string | undefined, accountName: string): string | undefined {\n if (!endpoint) {\n return undefined;\n }\n const normalized = endpoint.replace(/\\/+$/, \"\");\n const standardAccountEndpoint = `https://${accountName}.blob.core.windows.net`;\n return normalized === standardAccountEndpoint ? undefined : normalized;\n}\n\nfunction parseAzureConnectionString(value: string): Record<string, string> {\n return Object.fromEntries(value.split(\";\")\n .map((part) => part.trim())\n .filter(Boolean)\n .map((part) => {\n const index = part.indexOf(\"=\");\n return index === -1 ? [part, \"\"] : [part.slice(0, index), part.slice(index + 1)];\n }));\n}\n\nfunction normalizeManifestPath(path: string): string {\n const normalized = path.replace(/^\\/+|\\/+$/g, \"\");\n if (!normalized || normalized.includes(\"..\")) {\n throw new Error(`Invalid sandbox resource path: ${path}`);\n }\n return normalized;\n}\n\nfunction normalizeSandboxFileDownloads(downloads: SandboxFileDownload[]): SandboxFileDownload[] {\n return downloads.map((download) => {\n const mountPath = normalizeManifestPath(download.mountPath);\n assertSafeSandboxFilename(download.filename, download.fileId);\n if (!download.content && !download.url?.trim()) {\n throw new Error(`File download materialization requires content or a URL for ${download.fileId}`);\n }\n return {\n ...download,\n mountPath,\n };\n });\n}\n\nfunction assertSafeSandboxFilename(filename: string, fileId: string): void {\n if (!filename || filename.includes(\"/\") || filename.includes(\"\\\\\") || filename === \".\" || filename === \"..\" || filename.includes(\"..\")) {\n throw new Error(`Invalid sandbox file name for ${fileId}: ${filename}`);\n }\n}\n\nfunction sandboxDownloadTargetPath(download: SandboxFileDownload): string {\n return posixPath.join(\"/workspace\", download.mountPath, download.filename);\n}\n\nfunction sandboxFileDownloadCommand(download: SandboxFileDownload, targetPath: string): string {\n if (!download.url) {\n throw new Error(`File download materialization URL is empty for ${download.fileId}`);\n }\n const targetDir = posixPath.dirname(targetPath);\n const tmpPath = `${targetPath}.opengeni-download-$$`;\n return [\n \"set -euo pipefail\",\n `mkdir -p -- ${shellQuote(targetDir)}`,\n `if [ ! -f ${shellQuote(targetPath)} ]; then`,\n ` tmp=${shellQuote(tmpPath)}`,\n \" cleanup() { rm -f -- \\\"$tmp\\\"; }\",\n \" trap cleanup EXIT\",\n ` curl --fail --location --silent --show-error --retry 3 --retry-delay 1 --output \"$tmp\" ${shellQuote(download.url)}`,\n ` mv -- \"$tmp\" ${shellQuote(targetPath)}`,\n \" trap - EXIT\",\n \"fi\",\n `chmod a-w -- ${shellQuote(targetPath)} 2>/dev/null || true`,\n ].join(\"\\n\");\n}\n\nfunction shellQuote(value: string): string {\n return `'${value.replace(/'/g, \"'\\\\''\")}'`;\n}\n\nasync function restoredSandboxSessionState(state: RunState<any, any>, client: unknown): Promise<SandboxSessionState | undefined> {\n if (!client) {\n return undefined;\n }\n const sandboxState = (state as any)._sandbox;\n const entry = sandboxState?.sessionsByAgent?.[sandboxState.currentAgentKey]\n ?? (sandboxState?.currentAgentKey && sandboxState?.sessionState\n ? {\n backendId: sandboxState.backendId,\n currentAgentKey: sandboxState.currentAgentKey,\n currentAgentName: sandboxState.currentAgentName,\n sessionState: sandboxState.sessionState,\n }\n : undefined);\n if (!entry) {\n return undefined;\n }\n if ((client as SandboxClient).backendId !== entry.backendId) {\n throw new Error(\"RunState sandbox backend does not match the configured sandbox client\");\n }\n return await deserializeSandboxSessionStateEnvelope(client as SandboxClient, entry.sessionState);\n}\n\n// sandboxStateEntryFromRunState + restoredSandboxSessionStateFromEntry +\n// deserializeSandboxSessionStateEnvelope moved to the agent-loop-free leaf\n// ./sandbox; re-exported via `export * from \"./sandbox\"`. The private\n// restoredSandboxSessionState above (which takes an agent-loop RunState) calls\n// the moved deserializeSandboxSessionStateEnvelope, imported from ./sandbox.\n\nexport type SandboxLifecycleHookPhase = \"beforeAgentStart\";\n\nexport type SandboxLifecycleHookContext = {\n environment: Record<string, string>;\n onRuntimeEvent?: (event: NormalizedRuntimeEvent) => Promise<void> | void;\n runAs?: string;\n // TOKEN-BROKER (B1): the run-scoped GitHub token to seed into the box's token\n // FILE before the repository clone runs. Threaded OFF-MANIFEST — it rides ONLY\n // the clone exec's per-call env (OPENGENI_GIT_TOKEN_SEED), NEVER the box/agent\n // manifest env (validateNoEnvironmentDelta must never see a rotating value).\n gitTokenSeed?: string;\n};\n\nexport type SandboxLifecycleHook = {\n id: string;\n phase: SandboxLifecycleHookPhase;\n shouldRun?: (context: SandboxLifecycleHookContext) => boolean;\n run: (session: SandboxSessionLike, context: SandboxLifecycleHookContext) => Promise<void>;\n};\n\nconst builtInSandboxLifecycleHooks: Record<string, SandboxLifecycleHook> = {\n \"azure-cli-login\": {\n id: \"azure-cli-login\",\n phase: \"beforeAgentStart\",\n shouldRun: ({ environment }) => hasAzureServicePrincipal(environment),\n run: runAzureCliLoginHook,\n },\n};\n\nexport function sandboxLifecycleHooksForIds(ids: string[]): SandboxLifecycleHook[] {\n return ids.map((id) => {\n const hook = builtInSandboxLifecycleHooks[id];\n if (!hook) {\n throw new Error(`Unknown sandbox lifecycle hook ${id}`);\n }\n return hook;\n });\n}\n\nfunction applicableBeforeAgentStartHooks(\n hooks: SandboxLifecycleHook[],\n context: SandboxLifecycleHookContext,\n): SandboxLifecycleHook[] {\n return hooks.filter((hook) => hook.phase === \"beforeAgentStart\" && (hook.shouldRun?.(context) ?? true));\n}\n\n/**\n * Run the beforeAgentStart lifecycle hooks directly against an already-live box.\n *\n * The create/resume decoration (withSandboxLifecycleHooks) is structurally blind to\n * the PROVIDED-session path: when runStream hands the SDK a live `session`\n * (runOptions.sandbox.session — the lease-owned box resolved by the turn activity),\n * SandboxRuntimeManager uses it as-is and never calls client.create/resume, so a\n * wrapper around those methods never fires. Callers on that path invoke this\n * before starting the run so the box still gets its beforeAgentStart preparation\n * (repository clone + B1 askpass/token-file seed, azure-cli-login).\n */\nexport async function runBeforeAgentStartHooks(\n session: SandboxSessionLike,\n hooks: SandboxLifecycleHook[],\n context: SandboxLifecycleHookContext,\n): Promise<void> {\n for (const hook of applicableBeforeAgentStartHooks(hooks, context)) {\n await hook.run(session, context);\n }\n}\n\nexport function withSandboxLifecycleHooks(\n client: SandboxClient,\n hooks: SandboxLifecycleHook[],\n context: SandboxLifecycleHookContext,\n): SandboxClient {\n const beforeAgentStartHooks = applicableBeforeAgentStartHooks(hooks, context);\n if (beforeAgentStartHooks.length === 0) {\n return client;\n }\n const seen = new WeakSet<object>();\n const wrapSession = async <T extends SandboxSessionLike>(session: T): Promise<T> => {\n if (typeof session === \"object\" && session !== null && !seen.has(session)) {\n for (const hook of beforeAgentStartHooks) {\n await hook.run(session, context);\n }\n seen.add(session);\n }\n return session;\n };\n const wrapped: SandboxClient = {\n backendId: client.backendId,\n ...(client.supportsDefaultOptions !== undefined ? { supportsDefaultOptions: client.supportsDefaultOptions } : {}),\n ...(client.create ? { create: async (...args: any[]) => await wrapSession(await (client.create as any)(...args)) } : {}),\n ...(client.resume ? { resume: async (state: SandboxSessionState) => await wrapSession(await client.resume!(state)) } : {}),\n ...(client.delete ? { delete: async (state: SandboxSessionState) => await client.delete!(state) } : {}),\n ...(client.serializeSessionState ? { serializeSessionState: async (state: SandboxSessionState, options) => await client.serializeSessionState!(state, options) } : {}),\n ...(client.canPersistOwnedSessionState ? { canPersistOwnedSessionState: async (state: SandboxSessionState) => await client.canPersistOwnedSessionState!(state) } : {}),\n ...(client.canReusePreservedOwnedSession ? { canReusePreservedOwnedSession: async (state: SandboxSessionState) => await client.canReusePreservedOwnedSession!(state) } : {}),\n ...(client.deserializeSessionState ? { deserializeSessionState: async (state: Record<string, unknown>) => await client.deserializeSessionState!(state) } : {}),\n };\n return wrapped;\n}\n\nfunction sandboxRepositoryCloneHooksForAgent(agent: Agent<any, any>): SandboxLifecycleHook[] {\n return agentRepositoryCloneHooks.get(agent) ?? [];\n}\n\n// TOKEN-BROKER (B1): the per-turn git token seed stashed for this agent (undefined\n// when no repo is attached / on the selfhosted path). Read into the clone hook\n// context at runStream so the token is seeded off-manifest.\nfunction gitTokenSeedForAgent(agent: Agent<any, any>): string | undefined {\n return agentGitTokenSeed.get(agent);\n}\n\nfunction sandboxRepositoryCloneHooks(\n settings: Settings,\n resources: ResourceRef[],\n activeSandboxBackend: Settings[\"sandboxBackend\"] = settings.sandboxBackend,\n): SandboxLifecycleHook[] {\n const repositories = resources.filter((resource): resource is Extract<ResourceRef, { kind: \"repository\" }> => (\n resource.kind === \"repository\" && repositoryUsesSandboxClone(settings, resource, activeSandboxBackend)\n ));\n if (repositories.length === 0) {\n return [];\n }\n return [{\n id: \"repository-clone\",\n phase: \"beforeAgentStart\",\n run: async (session, context) => {\n await runRepositoryCloneHook(session, repositories, context);\n },\n }];\n}\n\n/**\n * Whether the platform should seed a repository resource by `git clone` inside\n * the sandbox before the agent starts.\n *\n * SAFETY GATE (selfhosted/bring-your-own machine): the clone hook writes into\n * `posixPath.join(\"/workspace\", mountPath)`, which a selfhosted agent rewrites\n * to a path under its REAL launch directory — so a platform-initiated clone\n * lands on the user's actual disk. A connected machine already owns its\n * filesystem; the platform must NEVER clone onto it. We therefore key the\n * decision off the EFFECTIVE/active backend, not just the session's HOME backend\n * (`settings.sandboxBackend`): a session can run on the cloud default while its\n * active sandbox has been swapped to a connected machine (active_sandbox_id → a\n * selfhosted lease), in which case the agent actually executes on the user's\n * machine even though the home backend is e.g. \"modal\". `activeSandboxBackend`\n * defaults to the home backend, so a session whose HOME backend is \"selfhosted\"\n * is gated with no caller change, and every cloud path is byte-for-byte\n * unchanged.\n */\nexport function repositoryUsesSandboxClone(\n settings: Settings,\n resource: Extract<ResourceRef, { kind: \"repository\" }>,\n activeSandboxBackend: Settings[\"sandboxBackend\"] = settings.sandboxBackend,\n): boolean {\n if (activeSandboxBackend === \"selfhosted\") {\n return false;\n }\n return settings.sandboxBackend === \"modal\" || Boolean(resource.githubInstallationId && resource.githubRepositoryId);\n}\n\nexport function repositoryCloneCommand(resources: Extract<ResourceRef, { kind: \"repository\" }>[]): string {\n const commands = [\n \"set -eu\",\n \"export HOME=\\\"${HOME:-/workspace}\\\"\",\n \"export GIT_TERMINAL_PROMPT=\\\"${GIT_TERMINAL_PROMPT:-0}\\\"\",\n // TOKEN-BROKER (B1/B2): seed the run-scoped GitHub token into the STABLE token FILE\n // AND provision the git-askpass helper into the box AT SETUP (runtime) BEFORE any\n // clone runs, so GIT_ASKPASS points at a per-box, user-writable script that reads\n // that file for the fetch below. Provisioning the askpass here (rather than relying\n // on a baked image script at /usr/local/bin/opengeni-git-askpass) removes the\n // image-rebuild rollout gate: the askpass is correct on ANY box image, including\n // pre-existing warm boxes on their next turn's clone hook, and no product image has\n // to carry it. The seed rides the per-exec env (OPENGENI_GIT_TOKEN_SEED) — NEVER the\n // box/agent manifest (validateNoEnvironmentDelta must not see a rotating value), so\n // this whole block is a no-op when the seed is absent (e.g. the selfhosted path,\n // which uses its own git creds). The token file lives at $OPENGENI_GIT_TOKEN_FILE\n // (stable, from the shared base) with a $HOME/.opengeni/git-token fallback.\n // $GIT_ASKPASS is on the box manifest env (set by\n // sandboxEnvironmentForRun to $HOME/.opengeni/askpass), so it is available to this\n // exec; the askpass script we write is byte-identical to docker/opengeni-git-askpass\n // and is written via a QUOTED heredoc (<<'ASKPASS_EOF') so NOTHING inside it expands\n // ($1, $HOME, ${OPENGENI_GIT_TOKEN_FILE:-...}, and the literal \\n in printf all land\n // verbatim), then chmod 0755 so git can exec it.\n //\n // ATOMIC REWRITE: this block now re-runs at the start of EVERY turn on a warm box\n // that other turn holders may be actively using — an in-flight `git fetch` from a\n // concurrent turn can invoke the askpass (which cats the token file) at any moment.\n // Both files are therefore written to a pid-suffixed temp under umask 077 and\n // renamed into place: rename is atomic, concurrent readers keep the old inode, and\n // the token is never observable world-readable (no post-hoc chmod window).\n \"if [ -n \\\"${OPENGENI_GIT_TOKEN_SEED:-}\\\" ]; then\",\n \" seed_umask=\\\"$(umask)\\\"\",\n \" umask 077\",\n \" git_token_file=\\\"${OPENGENI_GIT_TOKEN_FILE:-$HOME/.opengeni/git-token}\\\"\",\n \" mkdir -p \\\"$(dirname \\\"$git_token_file\\\")\\\"\",\n \" printf '%s' \\\"$OPENGENI_GIT_TOKEN_SEED\\\" > \\\"$git_token_file.tmp.$$\\\"\",\n \" mv -f \\\"$git_token_file.tmp.$$\\\" \\\"$git_token_file\\\"\",\n \" git_askpass=\\\"${GIT_ASKPASS:-$HOME/.opengeni/askpass}\\\"\",\n \" mkdir -p \\\"$(dirname \\\"$git_askpass\\\")\\\"\",\n \" cat > \\\"$git_askpass.tmp.$$\\\" <<'ASKPASS_EOF'\",\n \"#!/usr/bin/env sh\",\n \"case \\\"$1\\\" in\",\n \" *Username*) printf '%s\\\\n' \\\"x-access-token\\\" ;;\",\n \" *Password*) cat \\\"${OPENGENI_GIT_TOKEN_FILE:-$HOME/.opengeni/git-token}\\\" 2>/dev/null || printf '\\\\n' ;;\",\n \" *) printf '\\\\n' ;;\",\n \"esac\",\n \"ASKPASS_EOF\",\n \" chmod 0755 \\\"$git_askpass.tmp.$$\\\"\",\n \" mv -f \\\"$git_askpass.tmp.$$\\\" \\\"$git_askpass\\\"\",\n \" umask \\\"$seed_umask\\\"\",\n \"fi\",\n \"ensure_git() {\",\n \" if command -v git >/dev/null 2>&1; then\",\n \" return 0\",\n \" fi\",\n \" if command -v apt-get >/dev/null 2>&1; then\",\n \" export DEBIAN_FRONTEND=noninteractive\",\n \" apt-get update >/dev/null\",\n \" apt-get install -y --no-install-recommends ca-certificates git >/dev/null\",\n \" rm -rf /var/lib/apt/lists/*\",\n \" command -v git >/dev/null 2>&1 && return 0\",\n \" fi\",\n \" echo \\\"git is not installed in the sandbox and could not be bootstrapped\\\" >&2\",\n \" exit 127\",\n \"}\",\n \"ensure_git\",\n \"clone_repository() {\",\n \" target=\\\"$1\\\"\",\n \" uri=\\\"$2\\\"\",\n \" ref=\\\"$3\\\"\",\n \" subpath=\\\"$4\\\"\",\n \" if [ -e \\\"$target\\\" ] && { [ -f \\\"$target\\\" ] || [ -n \\\"$(find \\\"$target\\\" -mindepth 1 -maxdepth 1 -print -quit 2>/dev/null)\\\" ]; }; then\",\n // This hook re-runs every turn on a long-lived box, so \\\"non-empty\\\" alone is not\n // proof of a completed materialization: an interrupted clone (worker crash /\n // lifecycle timeout mid-mv/cp) leaves a partial tree that would otherwise pass\n // this check forever. A full-repo target must actually BE a work tree to be\n // skipped; a partial one is wiped and rebuilt (nothing legitimate writes under\n // the mount path before the repo exists). Subpath extracts are not git repos —\n // for those the plain non-empty check stands (no stronger signal available).\n \" if [ -n \\\"$subpath\\\" ] || git -C \\\"$target\\\" rev-parse --is-inside-work-tree >/dev/null 2>&1; then\",\n \" echo \\\"Repository resource already present at $target\\\"\",\n \" return 0\",\n \" fi\",\n \" echo \\\"Re-materializing partial repository resource at $target\\\" >&2\",\n \" find \\\"$target\\\" -mindepth 1 -maxdepth 1 -exec rm -rf {} +\",\n \" fi\",\n \" mkdir -p \\\"$(dirname \\\"$target\\\")\\\"\",\n \" tmp=\\\"${target}.tmp.$$\\\"\",\n \" rm -rf \\\"$tmp\\\"\",\n // Fetch failures must not leak the pid-suffixed tmp clone beside the mount\n // (set -eu would exit before any cleanup).\n \" if ! { git init \\\"$tmp\\\" >/dev/null && git -C \\\"$tmp\\\" remote add origin \\\"$uri\\\" && git -C \\\"$tmp\\\" fetch --depth 1 --no-tags --filter=blob:none origin \\\"$ref\\\" && git -C \\\"$tmp\\\" checkout --detach FETCH_HEAD >/dev/null; }; then\",\n \" rm -rf \\\"$tmp\\\"\",\n \" echo \\\"Repository resource fetch failed for $target\\\" >&2\",\n \" exit 1\",\n \" fi\",\n \" if [ -n \\\"$subpath\\\" ]; then\",\n \" if [ ! -e \\\"$tmp/$subpath\\\" ]; then\",\n \" echo \\\"Repository subpath not found: $subpath\\\" >&2\",\n \" rm -rf \\\"$tmp\\\"\",\n \" exit 1\",\n \" fi\",\n \" if [ -d \\\"$tmp/$subpath\\\" ]; then\",\n \" mkdir -p \\\"$target\\\"\",\n \" cp -a \\\"$tmp/$subpath/.\\\" \\\"$target/\\\"\",\n \" else\",\n \" rmdir \\\"$target\\\" 2>/dev/null || true\",\n \" cp -a \\\"$tmp/$subpath\\\" \\\"$target\\\"\",\n \" fi\",\n \" rm -rf \\\"$tmp\\\"\",\n \" else\",\n \" rmdir \\\"$target\\\" 2>/dev/null || true\",\n // Two concurrent turn holders can race this install: without the existence\n // re-check the loser's un-flagged `mv` would nest its tmp clone INSIDE the\n // winner's tree as <name>.tmp.<pid>. If the winner produced a valid work tree,\n // accept it; a non-empty non-repo survivor here is a mount point the manifest\n // re-filled — install into it by content copy instead of rename.\n \" if [ -e \\\"$target\\\" ]; then\",\n \" if git -C \\\"$target\\\" rev-parse --is-inside-work-tree >/dev/null 2>&1; then\",\n \" rm -rf \\\"$tmp\\\"\",\n \" echo \\\"Repository resource already present at $target\\\"\",\n \" return 0\",\n \" fi\",\n \" cp -a \\\"$tmp/.\\\" \\\"$target/\\\"\",\n \" rm -rf \\\"$tmp\\\"\",\n \" else\",\n \" mv \\\"$tmp\\\" \\\"$target\\\"\",\n \" fi\",\n \" git -C \\\"$target\\\" rev-parse --is-inside-work-tree >/dev/null\",\n \" fi\",\n \" if [ ! -e \\\"$target\\\" ]; then\",\n \" echo \\\"Repository resource was not materialized at $target\\\" >&2\",\n \" exit 1\",\n \" fi\",\n \" echo \\\"Repository resource ready at $target\\\"\",\n \"}\",\n ];\n for (const resource of resources) {\n const url = new URL(resource.uri);\n const repo = url.pathname.replace(/^\\/+|\\/+$/g, \"\").replace(/\\.git$/, \"\");\n const mountPath = normalizeManifestPath(resource.mountPath ?? `repos/${repo}`);\n commands.push([\n \"clone_repository\",\n shellQuote(posixPath.join(\"/workspace\", mountPath)),\n shellQuote(resource.uri),\n shellQuote(resource.ref),\n shellQuote(resource.subpath ? normalizeManifestPath(resource.subpath) : \"\"),\n ].join(\" \"));\n }\n return commands.join(\"\\n\");\n}\n\nexport async function runRepositoryCloneHook(\n session: SandboxSessionLike,\n resources: Extract<ResourceRef, { kind: \"repository\" }>[],\n context: SandboxLifecycleHookContext = { environment: {} },\n): Promise<void> {\n const payload = { name: \"repository-clone\", repositoryCount: resources.length };\n await context.onRuntimeEvent?.({ type: \"sandbox.operation.started\", payload });\n try {\n // TOKEN-BROKER (B1): thread the run-scoped GitHub token PER-EXEC, never on the\n // manifest. The SDK's ExecCommandArgs has no `environment` field (exec inherits\n // the box's manifest env), so we can't hand the seed through an exec option — and\n // we MUST NOT put it on the manifest (validateNoEnvironmentDelta would see a\n // rotating value). We therefore inline it as an ephemeral `export` prefix on THIS\n // exec's command text only: it lives in the command, not the box/agent manifest,\n // and never persists. The clone command's gated seed block then writes it to the\n // token FILE before the fetch, so GIT_ASKPASS reads it. Absent seed (e.g. the\n // selfhosted path) -> no prefix, the clone runs byte-for-byte as before.\n const command = context.gitTokenSeed\n ? `export OPENGENI_GIT_TOKEN_SEED=${shellQuote(context.gitTokenSeed)}\\n${repositoryCloneCommand(resources)}`\n : repositoryCloneCommand(resources);\n if (session.exec) {\n const result = await session.exec({\n cmd: command,\n workdir: \"/workspace\",\n ...(context.runAs ? { runAs: context.runAs } : {}),\n yieldTimeMs: SANDBOX_LIFECYCLE_COMMAND_TIMEOUT_MS,\n maxOutputTokens: 20_000,\n });\n assertSandboxCommandSucceeded(result, \"Repository clone hook\");\n } else if (session.execCommand) {\n const result = await session.execCommand({\n cmd: command,\n workdir: \"/workspace\",\n ...(context.runAs ? { runAs: context.runAs } : {}),\n yieldTimeMs: SANDBOX_LIFECYCLE_COMMAND_TIMEOUT_MS,\n maxOutputTokens: 20_000,\n });\n assertSandboxCommandSucceeded(result, \"Repository clone hook\");\n } else {\n throw new Error(\"Sandbox session does not support command execution\");\n }\n await context.onRuntimeEvent?.({ type: \"sandbox.operation.completed\", payload });\n } catch (error) {\n await context.onRuntimeEvent?.({\n type: \"sandbox.operation.failed\",\n payload: {\n ...payload,\n error: error instanceof Error ? error.message : String(error),\n },\n });\n throw error;\n }\n}\n\nexport function azureCliLoginCommand(): string {\n return [\n \"export HOME=\\\"${HOME:-/workspace}\\\"\",\n \"mkdir -p \\\"$HOME/.azure\\\"\",\n \"CLIENT_ID=\\\"${AZURE_CLIENT_ID:-${ARM_CLIENT_ID:-}}\\\"\",\n \"CLIENT_SECRET=\\\"${AZURE_CLIENT_SECRET:-${ARM_CLIENT_SECRET:-}}\\\"\",\n \"TENANT_ID=\\\"${AZURE_TENANT_ID:-${ARM_TENANT_ID:-}}\\\"\",\n \"SUBSCRIPTION_ID=\\\"${AZURE_SUBSCRIPTION_ID:-${ARM_SUBSCRIPTION_ID:-}}\\\"\",\n \"if [ -n \\\"$CLIENT_ID\\\" ] && [ -n \\\"$CLIENT_SECRET\\\" ] && [ -n \\\"$TENANT_ID\\\" ]; then\",\n \" command -v az >/dev/null 2>&1 || { echo \\\"Azure CLI is not installed in the sandbox\\\" >&2; exit 127; }\",\n \" az account show --only-show-errors >/dev/null 2>&1 || az login --service-principal --username \\\"$CLIENT_ID\\\" --password \\\"$CLIENT_SECRET\\\" --tenant \\\"$TENANT_ID\\\" --allow-no-subscriptions --only-show-errors --output none\",\n // if/fi, NOT `[ -n ] && az`: this line ends the credentialed if-body, so with a\n // no-subscription SP (an explicitly supported config — the login above passes\n // --allow-no-subscriptions) the bare `[ -n ]` would exit the whole script 1 and\n // fail the turn.\n \" if [ -n \\\"$SUBSCRIPTION_ID\\\" ]; then az account set --subscription \\\"$SUBSCRIPTION_ID\\\" --only-show-errors; fi\",\n \"fi\",\n ].join(\"\\n\");\n}\n\nexport function sandboxCommandExitCode(result: unknown): number | null {\n if (typeof result === \"string\") {\n const match = result.match(/Process exited with code (-?\\d+)/);\n return match ? Number(match[1]) : null;\n }\n if (!result || typeof result !== \"object\") {\n return null;\n }\n const candidate = result as {\n exitCode?: unknown;\n exit_code?: unknown;\n code?: unknown;\n status?: unknown;\n };\n for (const value of [candidate.exitCode, candidate.exit_code, candidate.code, candidate.status]) {\n if (typeof value === \"number\") {\n return value;\n }\n }\n return null;\n}\n\nexport function sandboxCommandOutput(result: unknown): string {\n if (!result || typeof result !== \"object\") {\n return \"\";\n }\n const candidate = result as {\n output?: unknown;\n stdout?: unknown;\n stderr?: unknown;\n };\n return [candidate.output, candidate.stderr, candidate.stdout]\n .filter((value): value is string => typeof value === \"string\" && value.length > 0)\n .join(\"\\n\");\n}\n\nfunction assertSandboxCommandSucceeded(result: unknown, operation: string): void {\n const output = sandboxCommandOutput(result);\n if (sandboxCommandStillRunning(result)) {\n throw new Error(`${operation} did not finish before the lifecycle command timeout${output ? `:\\n${output}` : \"\"}`);\n }\n const exitCode = sandboxCommandExitCode(result);\n if (exitCode !== null && exitCode !== 0) {\n throw new Error(output || `${operation} failed with exit code ${exitCode}`);\n }\n if (exitCode === null) {\n throw new Error(output || `${operation} did not return a command exit code`);\n }\n}\n\nexport function sandboxCommandStillRunning(result: unknown): boolean {\n if (typeof result === \"string\") {\n return /Process running with session ID \\d+/u.test(result);\n }\n if (!result || typeof result !== \"object\") {\n return false;\n }\n const candidate = result as { sessionId?: unknown; session_id?: unknown };\n return typeof candidate.sessionId === \"number\" || typeof candidate.session_id === \"number\";\n}\n\nfunction hasAzureServicePrincipal(environment: Record<string, string>): boolean {\n const clientId = environment.AZURE_CLIENT_ID || environment.ARM_CLIENT_ID;\n const clientSecret = environment.AZURE_CLIENT_SECRET || environment.ARM_CLIENT_SECRET;\n const tenantId = environment.AZURE_TENANT_ID || environment.ARM_TENANT_ID;\n return Boolean(clientId && clientSecret && tenantId);\n}\n\nexport async function runAzureCliLoginHook(\n session: SandboxSessionLike,\n context: SandboxLifecycleHookContext = { environment: {} },\n): Promise<void> {\n const payload = { name: \"azure-cli-login\", command: \"az login --service-principal\" };\n await context.onRuntimeEvent?.({ type: \"sandbox.operation.started\", payload });\n try {\n if (session.exec) {\n const result = await session.exec({\n cmd: azureCliLoginCommand(),\n workdir: \"/workspace\",\n ...(context.runAs ? { runAs: context.runAs } : {}),\n yieldTimeMs: SANDBOX_LIFECYCLE_COMMAND_TIMEOUT_MS,\n maxOutputTokens: 20_000,\n });\n assertSandboxCommandSucceeded(result, \"Azure CLI login hook\");\n } else if (session.execCommand) {\n const result = await session.execCommand({\n cmd: azureCliLoginCommand(),\n workdir: \"/workspace\",\n ...(context.runAs ? { runAs: context.runAs } : {}),\n yieldTimeMs: SANDBOX_LIFECYCLE_COMMAND_TIMEOUT_MS,\n maxOutputTokens: 20_000,\n });\n assertSandboxCommandSucceeded(result, \"Azure CLI login hook\");\n } else {\n throw new Error(\"Sandbox session does not support command execution\");\n }\n await context.onRuntimeEvent?.({ type: \"sandbox.operation.completed\", payload });\n } catch (error) {\n await context.onRuntimeEvent?.({\n type: \"sandbox.operation.failed\",\n payload: {\n ...payload,\n error: error instanceof Error ? error.message : String(error),\n },\n });\n throw error;\n }\n}\n\nfunction azureDeploymentBaseUrl(settings: Settings): string {\n const endpoint = settings.azureOpenaiEndpoint?.replace(/\\/+$/, \"\");\n if (!endpoint || !settings.azureOpenaiDeployment) {\n throw new Error(\"Azure OpenAI endpoint/deployment settings are incomplete\");\n }\n return `${endpoint}/openai/deployments/${settings.azureOpenaiDeployment}`;\n}\n\nexport function azureOpenAIDefaultQuery(\n settings: Pick<Settings, \"azureOpenaiApiVersion\">,\n baseURL: string,\n): Record<string, string> | undefined {\n if (!settings.azureOpenaiApiVersion) return undefined;\n const normalized = baseURL.replace(/\\/+$/, \"\").toLowerCase();\n if (normalized.endsWith(\"/openai/v1\")) {\n return undefined;\n }\n return { \"api-version\": settings.azureOpenaiApiVersion };\n}\n\n// Since @openai/agents 0.11.0 local sandbox sources (including the lazy\n// bundled-skills source) must stay within the SDK process working directory:\n// reads outside it require manifest.extraPathGrants, and remote sandbox\n// clients such as Modal reject manifests that carry extra path grants. The\n// packaged skills live inside the runtime package — outside the worker's cwd\n// in production — so stage a copy under the working directory once per\n// process instead of granting the packaged path.\nlet stagedBundledSkillsDir: string | null = null;\n\nfunction bundledSkillsDir(): string {\n const moduleDir = dirname(fileURLToPath(import.meta.url));\n const packaged = [\n join(moduleDir, \"bundled_hashicorp_terraform_skills\"),\n join(moduleDir, \"..\", \"src\", \"bundled_hashicorp_terraform_skills\"),\n ].find((candidate) => existsSync(candidate)) ?? join(moduleDir, \"bundled_hashicorp_terraform_skills\");\n if (isPathWithin(process.cwd(), packaged)) {\n return packaged;\n }\n if (!stagedBundledSkillsDir) {\n stagedBundledSkillsDir = stageBundledSkills(packaged, join(process.cwd(), \".opengeni\", \"bundled_hashicorp_terraform_skills\"));\n }\n return stagedBundledSkillsDir;\n}\n\nfunction stageBundledSkills(packaged: string, target: string): string {\n const tmp = `${target}.tmp-${process.pid}`;\n rmSync(tmp, { recursive: true, force: true });\n mkdirSync(dirname(tmp), { recursive: true });\n cpSync(packaged, tmp, { recursive: true });\n rmSync(target, { recursive: true, force: true });\n try {\n renameSync(tmp, target);\n } catch (error) {\n // Another process staged the same content between our rm and rename.\n rmSync(tmp, { recursive: true, force: true });\n if (!existsSync(target)) {\n throw error;\n }\n }\n return target;\n}\n\nfunction isPathWithin(root: string, candidate: string): boolean {\n const relativePath = relative(root, candidate);\n return relativePath === \"\" || (!relativePath.startsWith(\"..\") && !isAbsolute(relativePath));\n}\n\n/**\n * The skill source fed to the SDK Skills capability. Without pack skills this\n * is the plain bundled local-dir source, byte-for-byte the pre-pack behavior.\n * With pack skills it becomes a single in-memory dir source combining bundled\n * skill directories (as local_dir entries the SDK materializes lazily) with\n * pack skill directories built from manifest-carried file content — one skill\n * index, one `## Skills` instruction section, lazy `load_skill` for all of\n * them. A pack skill shadows a bundled skill with the same directory name.\n */\nexport function lazySkillSourceWithPackSkills(packSkills: PackSkill[]): LocalDirLazySkillSource {\n const bundledDir = bundledSkillsDir();\n const bundled = localDirLazySkillSource({ src: bundledDir });\n if (packSkills.length === 0) {\n return bundled;\n }\n const children: Record<string, Entry> = {};\n for (const name of bundledSkillDirNames(bundledDir)) {\n children[name] = localDir({ src: join(bundledDir, name) });\n }\n const packIndex: SkillIndexEntry[] = [];\n const packNames = new Set<string>();\n const packNameKeys = new Set<string>();\n for (const skill of packSkills) {\n assertSafePackSkillName(skill.name);\n if (packNameKeys.has(skill.name.toLowerCase())) {\n throw new Error(`Duplicate pack skill name: ${skill.name}`);\n }\n packNameKeys.add(skill.name.toLowerCase());\n packNames.add(skill.name);\n children[skill.name] = packSkillDirEntry(skill);\n packIndex.push({ name: skill.name, description: packSkillDescription(skill), path: skill.name });\n }\n return {\n source: dir({ children }),\n getIndex: (manifest, skillsPath) => [\n ...(bundled.getIndex?.(manifest, skillsPath) ?? []).filter((entry) => !packNames.has(entry.path ?? entry.name)),\n ...packIndex,\n ],\n };\n}\n\nfunction bundledSkillDirNames(root: string): string[] {\n return readdirSync(root, { withFileTypes: true })\n .filter((entry) => entry.isDirectory() && existsSync(join(root, entry.name, \"SKILL.md\")))\n .map((entry) => entry.name)\n .sort();\n}\n\ntype PackSkillDirNode = {\n dirs: Map<string, PackSkillDirNode>;\n files: Map<string, string>;\n};\n\nfunction packSkillDirEntry(skill: PackSkill): Dir {\n const root: PackSkillDirNode = { dirs: new Map(), files: new Map() };\n for (const skillFile of skill.files) {\n const segments = packSkillPathSegments(skill.name, skillFile.path);\n let node = root;\n for (const segment of segments.slice(0, -1)) {\n if (node.files.has(segment)) {\n throw new Error(`Pack skill ${skill.name} uses ${segment} as both a file and a directory`);\n }\n let next = node.dirs.get(segment);\n if (!next) {\n next = { dirs: new Map(), files: new Map() };\n node.dirs.set(segment, next);\n }\n node = next;\n }\n const filename = segments[segments.length - 1]!;\n if (node.dirs.has(filename) || node.files.has(filename)) {\n throw new Error(`Duplicate pack skill file path in ${skill.name}: ${skillFile.path}`);\n }\n node.files.set(filename, skillFile.content);\n }\n if (!root.files.has(\"SKILL.md\")) {\n throw new Error(`Pack skill ${skill.name} is missing a top-level SKILL.md file`);\n }\n return packSkillDirFromNode(root);\n}\n\nfunction packSkillDirFromNode(node: PackSkillDirNode): Dir {\n const children: Record<string, Entry> = {};\n for (const [name, child] of node.dirs) {\n children[name] = packSkillDirFromNode(child);\n }\n for (const [name, content] of node.files) {\n children[name] = file({ content });\n }\n return dir({ children });\n}\n\nfunction assertSafePackSkillName(name: string): void {\n if (packSkillPathSegments(name, name).length !== 1) {\n throw new Error(`Invalid pack skill name: ${name}`);\n }\n}\n\nfunction packSkillPathSegments(skillName: string, path: string): string[] {\n const segments = path.split(\"/\");\n if (path.startsWith(\"/\") || path.includes(\"\\\\\") || segments.some((segment) => segment.length === 0 || segment === \".\" || segment === \"..\")) {\n throw new Error(`Invalid pack skill file path for ${skillName}: ${path}`);\n }\n return segments;\n}\n\nfunction packSkillDescription(skill: PackSkill): string {\n const explicit = skill.description?.trim();\n if (explicit) {\n return explicit;\n }\n const markdown = skill.files.find((skillFile) => skillFile.path === \"SKILL.md\")?.content ?? \"\";\n return skillFrontmatterDescription(markdown) ?? \"No description provided.\";\n}\n\nfunction skillFrontmatterDescription(markdown: string): string | null {\n const lines = markdown.split(/\\r?\\n/);\n if (lines[0]?.trim() !== \"---\") {\n return null;\n }\n const end = lines.findIndex((line, index) => index > 0 && line.trim() === \"---\");\n if (end === -1) {\n return null;\n }\n const collected: string[] = [];\n let inDescription = false;\n for (const line of lines.slice(1, end)) {\n const match = line.match(/^description:\\s*(.*)$/);\n if (match) {\n const inline = match[1]!.trim();\n if (inline && inline !== \">-\" && inline !== \">\" && inline !== \"|\" && inline !== \"|-\") {\n return unquoteFrontmatterValue(inline);\n }\n inDescription = true;\n continue;\n }\n if (inDescription) {\n if (/^\\s+\\S/.test(line)) {\n collected.push(line.trim());\n continue;\n }\n break;\n }\n }\n const blockValue = collected.join(\" \").trim();\n return blockValue ? blockValue : null;\n}\n\nfunction unquoteFrontmatterValue(value: string): string {\n if (value.length >= 2 && value[0] === value[value.length - 1] && (value[0] === '\"' || value[0] === \"'\")) {\n return value.slice(1, -1);\n }\n return value;\n}\n\nfunction stringValue(value: unknown): string | undefined {\n return typeof value === \"string\" && value.trim() ? value.trim() : undefined;\n}\n\nfunction isAsyncIterable<T>(source: Iterable<T> | AsyncIterable<T>): source is AsyncIterable<T> {\n return typeof (source as AsyncIterable<T>)[Symbol.asyncIterator] === \"function\";\n}\n\nfunction stableJson(value: unknown): string {\n return JSON.stringify(sortJson(value));\n}\n\nfunction sortJson(value: unknown): unknown {\n if (Array.isArray(value)) {\n return value.map(sortJson);\n }\n if (value && typeof value === \"object\") {\n return Object.fromEntries(Object.entries(value).sort(([a], [b]) => a.localeCompare(b)).map(([key, nested]) => [key, sortJson(nested)]));\n }\n return value;\n}\n\nfunction approvalIdentifier(item: any): string {\n return String(item?.rawItem?.callId ?? item?.rawItem?.id ?? item?.id ?? item?.name ?? \"approval\");\n}\n","/**\n * Read-path sanitizer for replayed conversation history (issue: orphaned\n * tool outputs brick a session).\n *\n * Conversation truth is persisted as a flat list of SDK history items in\n * `session_history_items` and replayed verbatim into the model on every turn.\n * The OpenAI Responses API rejects the whole request (HTTP 400) when that list\n * violates its tool-call pairing rules — most destructively:\n *\n * `400 No tool call found for function call output with call_id <X>`\n *\n * when a `function_call_result` (a.k.a. function_call_output) has no matching\n * `function_call` earlier in the list. Because the corrupt item is replayed on\n * every subsequent turn, one orphaned output permanently bricks the session\n * across revival — it stays dead until the row is hand-deleted.\n *\n * This module is the reliability net: before history items are sent to the\n * model they pass through `sanitizeHistoryItemsForModel`, which removes any\n * item that would make the request invalid. It mirrors the SDK's own\n * `dropOrphanToolCalls` continuation logic (which only runs over the SDK's\n * in-memory `state.history`, not over rows we reload from the database) so a\n * reloaded history is shaped exactly like a freshly-generated one.\n *\n * It is a pure function over plain JSON item shapes (no SDK import, no I/O) so\n * it is cheap to unit-test exhaustively. It NEVER mutates its input items and\n * NEVER touches the stored rows — only the in-memory copy sent to the model is\n * filtered, keeping the persisted audit trail intact.\n */\n\n/** A history item is any JSON object; we only inspect a few discriminator fields. */\nexport type HistoryItem = Record<string, unknown>;\n\n/**\n * Tool-call item types and the result-item type that settles them. Kept in\n * sync with the SDK's `TOOL_CALL_RESULT_TYPE_BY_CALL_TYPE`; `function_call` is\n * the one observed live, the rest are included so the same pairing logic holds\n * for every tool-call kind the SDK can emit.\n */\nconst RESULT_TYPE_BY_CALL_TYPE: Record<string, string> = {\n function_call: \"function_call_result\",\n computer_call: \"computer_call_result\",\n shell_call: \"shell_call_output\",\n apply_patch_call: \"apply_patch_call_output\",\n // Progressive connector disclosure (codex tool_search): a replayed\n // `tool_search_call` must be settled by its `tool_search_output` exactly like a\n // function call — an unpaired one 400s the store:false replay. The SDK pairs\n // these OUTSIDE its own TOOL_CALL_RESULT_TYPE_BY_CALL_TYPE (sessionPersistence's\n // hasToolSearchCallId), so we mirror the semantics here; the correlation id can\n // additionally ride providerData (see callIdOf).\n tool_search_call: \"tool_search_output\",\n};\n\nconst RESULT_TYPES = new Set(Object.values(RESULT_TYPE_BY_CALL_TYPE));\n\nfunction itemType(item: unknown): string | undefined {\n if (!item || typeof item !== \"object\") {\n return undefined;\n }\n const type = (item as { type?: unknown }).type;\n return typeof type === \"string\" ? type : undefined;\n}\n\n/**\n * Correlation id for a tool call / result. The SDK's canonical history shape\n * uses camelCase `callId`; the raw Responses wire shape uses snake_case\n * `call_id`. Persisted rows are the SDK shape, but we accept either so a row\n * written by any code path (or hand-repaired) still correlates.\n */\nfunction callIdOf(item: unknown): string | undefined {\n if (!item || typeof item !== \"object\") {\n return undefined;\n }\n const record = item as { callId?: unknown; call_id?: unknown; providerData?: unknown };\n if (typeof record.callId === \"string\" && record.callId.length > 0) {\n return record.callId;\n }\n if (typeof record.call_id === \"string\" && record.call_id.length > 0) {\n return record.call_id;\n }\n // tool_search items may carry their correlation id ONLY in providerData\n // (mirrors the SDK's getToolSearchProviderCallId: providerData.call_id ??\n // providerData.callId ?? call_id ?? callId). Harmless for other item kinds —\n // their ids never live there.\n const provider = record.providerData as { call_id?: unknown; callId?: unknown } | null | undefined;\n if (provider && typeof provider === \"object\") {\n if (typeof provider.call_id === \"string\" && provider.call_id.length > 0) {\n return provider.call_id;\n }\n if (typeof provider.callId === \"string\" && provider.callId.length > 0) {\n return provider.callId;\n }\n }\n return undefined;\n}\n\n/**\n * Sanitize a replayed history item list into a sequence the Responses API\n * accepts. Pure: returns a new array of the same item references in order,\n * with invalid items omitted. Valid histories come back byte-identical\n * (same references, same order).\n *\n * Rules, each motivated by a concrete 400 the API raises:\n *\n * 1. Drop every tool-call RESULT whose matching tool CALL does not appear\n * earlier in the list. This is the session-bricking orphan: a\n * `function_call_result` with no preceding `function_call` of the same\n * `call_id`. (\"No tool call found for function call output…\")\n *\n * 2. Drop every tool CALL that has no matching RESULT anywhere after it.\n * The Responses API requires each tool call to be settled by its output\n * before the conversation can continue; a dangling call left in replayed\n * history 400s with \"No tool output found for function call…\". Dropping\n * the dangling call (rather than synthesizing a fake output) is what the\n * SDK itself does for in-memory continuation, so a reloaded history is\n * shaped identically. The matching result, if it later exists, is kept;\n * only genuinely unpaired calls are removed.\n *\n * 3. Drop any `reasoning` item that immediately precedes (across a run of\n * reasoning items) a dropped tool call. The Responses API ties an\n * encrypted reasoning item to the tool call it produced; a reasoning item\n * orphaned by rule 2 trips \"Item 'rs_…' of type 'reasoning' was provided\n * without its required following item\". Mirrors the SDK's\n * `dropReasoningItemsPrecedingDroppedCalls`.\n *\n * A `call_id` is paired only when BOTH a call and a result of the matching\n * types exist with that id, the call appearing before the result. Calls and\n * results that satisfy that survive untouched.\n */\nexport function sanitizeHistoryItemsForModel<T extends HistoryItem>(items: readonly T[]): T[] {\n if (items.length === 0) {\n return [];\n }\n\n // Pre-scan: for every (call-type, call_id) record the index of a RESULT that\n // appears strictly after the call. A call is valid only when such a result\n // exists; a result is valid only when its call appears strictly before it.\n // We resolve pairs in order so ordering is enforced both ways (a result that\n // precedes its call is an orphan, and a call whose only result precedes it is\n // dangling).\n const dropped = new Set<number>();\n\n // For each result-type, the call_ids of CALLs we have seen so far that are\n // still waiting to be settled by a following result.\n const openCallIdsByResultType = new Map<string, Set<string>>();\n\n items.forEach((item, index) => {\n const type = itemType(item);\n const callId = callIdOf(item);\n if (!type || !callId) {\n return;\n }\n const callResultType = RESULT_TYPE_BY_CALL_TYPE[type];\n if (callResultType) {\n const open = openCallIdsByResultType.get(callResultType) ?? new Set<string>();\n open.add(callId);\n openCallIdsByResultType.set(callResultType, open);\n return;\n }\n if (RESULT_TYPES.has(type)) {\n const open = openCallIdsByResultType.get(type);\n if (open && open.has(callId)) {\n // Settles a call we have already seen — keep both, close the call.\n open.delete(callId);\n } else {\n // Rule 1: result whose call is absent or appears later — the orphan.\n dropped.add(index);\n }\n }\n });\n\n // Rule 2: any call still open after the full scan has no result after it —\n // a dangling call the API rejects. Drop those calls. We re-walk to find the\n // indices of the still-open call_ids (the last unmatched call per id).\n const stillOpen = new Map<string, Set<string>>();\n for (const [resultType, open] of openCallIdsByResultType) {\n if (open.size > 0) {\n stillOpen.set(resultType, new Set(open));\n }\n }\n if (stillOpen.size > 0) {\n for (let index = items.length - 1; index >= 0; index -= 1) {\n const item = items[index];\n const type = itemType(item);\n const callId = callIdOf(item);\n if (!type || !callId) {\n continue;\n }\n const resultType = RESULT_TYPE_BY_CALL_TYPE[type];\n if (!resultType) {\n continue;\n }\n const open = stillOpen.get(resultType);\n if (open && open.has(callId)) {\n dropped.add(index);\n open.delete(callId);\n }\n }\n }\n\n if (dropped.size > 0) {\n // Rule 3: drop reasoning items stranded by a dropped tool call. A reasoning\n // item is stranded when the next non-reasoning item after it is dropped.\n for (let index = 0; index < items.length; index += 1) {\n if (dropped.has(index) || itemType(items[index]) !== \"reasoning\") {\n continue;\n }\n for (let next = index + 1; next < items.length; next += 1) {\n if (itemType(items[next]) === \"reasoning\") {\n continue;\n }\n if (dropped.has(next)) {\n dropped.add(index);\n }\n break;\n }\n }\n }\n\n if (dropped.size === 0) {\n return items.slice();\n }\n return items.filter((_item, index) => !dropped.has(index));\n}\n\n/**\n * Drop the account/org-bound `reasoning.encrypted_content` blob from a single\n * history item, preserving everything else (the visible chain-of-thought text in\n * `summary`/`content`, and every non-reasoning field). Pure + non-mutating: when\n * there is nothing to strip the SAME reference is returned (so the common,\n * same-account path stays byte-identical); otherwise a shallow clone is returned.\n *\n * WHY. A codex-subscription turn round-trips `reasoning.encrypted_content` — an\n * opaque blob minted by the ChatGPT/Codex backend that is bound to the account\n * (org) that produced it. After a manual switch from codex account A to B, the\n * carried history items still hold A-minted blobs; replaying them into a turn\n * running on B is rejected (400). The blob is purely a chain-of-thought\n * continuity optimization — dropping it costs at most one turn of lost CoT\n * continuity and never any message content.\n *\n * USED FOR `compaction` items only on the history-items read path: a foreign\n * `compaction` summary carries account-bound `encrypted_content` but its summary\n * is real conversation content that must be preserved, so we strip only the blob\n * (we do NOT drop the whole item). Foreign `reasoning` items are instead dropped\n * WHOLESALE by the caller (id + blob), because the Responses backend validates\n * the foreign `rs_…` id and rejects a reasoning item that has a foreign id and no\n * encrypted_content (so blanking the blob alone is not enough — see\n * {@link applyCodexHistoryStrip}).\n *\n * The SDK's Responses converter reads the blob via `providerData.encryptedContent`\n * (camel) or `providerData.encrypted_content` (snake); persisted rows use the\n * snake form, but we delete both casings defensively. We also clear a top-level\n * `encrypted_content` (the `compaction`-item shape) belt-and-braces — that blob\n * is likewise source-bound. Only `reasoning` and `compaction` items are touched;\n * messages, tool calls, and tool outputs pass through untouched by reference.\n */\nexport function stripReasoningEncryptedContent<T extends HistoryItem>(item: T): T {\n const type = itemType(item);\n if (type !== \"reasoning\" && type !== \"compaction\") {\n return item;\n }\n const record = item as Record<string, unknown>;\n const providerData = record.providerData;\n const providerHasBlob = !!providerData && typeof providerData === \"object\"\n && (\"encryptedContent\" in (providerData as Record<string, unknown>)\n || \"encrypted_content\" in (providerData as Record<string, unknown>));\n const topLevelHasBlob = \"encrypted_content\" in record;\n if (!providerHasBlob && !topLevelHasBlob) {\n // Nothing encrypted to strip — return the same reference (byte-identical).\n return item;\n }\n const clone: Record<string, unknown> = { ...record };\n if (providerHasBlob) {\n const providerClone = { ...(providerData as Record<string, unknown>) };\n delete providerClone.encryptedContent;\n delete providerClone.encrypted_content;\n clone.providerData = providerClone;\n }\n if (topLevelHasBlob) {\n delete clone.encrypted_content;\n }\n return clone as unknown as T;\n}\n\n/**\n * Neutralize the account/org-bound identity of EVERY `reasoning` item embedded\n * in a serialized RunState JSON string, returning the re-serialized string. Pure:\n * a parse failure or a no-op returns the SAME string reference (so an unchanged\n * or non-codex run-state replays byte-for-byte).\n *\n * WHY (HOLE C — the run-state REPLAY paths). The approval-decision resume and the\n * items-mode run-state fallback replay the serialized RunState blob verbatim. That\n * blob round-trips `reasoning.encrypted_content` minted by the ChatGPT/Codex\n * backend (bound to the freezing account/org — a foreign account 400s it) AND the\n * foreign `rs_…` reasoning ids the Responses backend validates (rejected once the\n * blob is gone). Unlike `session_history_items`, the blob carries NO per-item\n * producer tag, so foreign-ness cannot be decided per item; the worker instead\n * records the FREEZING codex account on the run-state row and calls this only when\n * the resuming turn's codex account DIFFERS from it. When the accounts differ we\n * conservatively neutralize every reasoning item: delete its provider id and its\n * `encrypted_content` (both casings, in `providerData`). The visible reasoning\n * `content`/`summary` and every message / tool-call / tool-output item are left\n * intact (message and tool content are never account-bound).\n *\n * A reasoning item with no id and no encrypted_content is exactly the shape the\n * production Azure path already sends (see `stripProviderItemIdsFilter`), so it\n * deserializes and replays cleanly. Reasoning items live in several places in the\n * blob — `originalInput` (when an array), each `modelResponses[].output`,\n * `lastModelResponse.output`, and the `generatedItems` wrappers (`reasoning_item`\n * → `rawItem`) — and we scrub all of them. `compaction` items are deliberately\n * left untouched: their `encrypted_content` is a protocol-REQUIRED field whose\n * removal would fail the SDK's run-state schema validation on deserialize.\n */\nexport function stripReasoningIdentityFromSerializedRunState(serialized: string): string {\n let parsed: unknown;\n try {\n parsed = JSON.parse(serialized);\n } catch {\n // Not JSON (e.g. a cleared-state sentinel handled elsewhere): forward as-is.\n return serialized;\n }\n if (!parsed || typeof parsed !== \"object\") {\n return serialized;\n }\n let changed = false;\n const scrubReasoning = (candidate: unknown): void => {\n if (!candidate || typeof candidate !== \"object\") {\n return;\n }\n const record = candidate as Record<string, unknown>;\n if (record.type !== \"reasoning\") {\n return;\n }\n if (\"id\" in record) {\n delete record.id;\n changed = true;\n }\n const providerData = record.providerData;\n if (providerData && typeof providerData === \"object\") {\n const provider = providerData as Record<string, unknown>;\n if (\"encryptedContent\" in provider) {\n delete provider.encryptedContent;\n changed = true;\n }\n if (\"encrypted_content\" in provider) {\n delete provider.encrypted_content;\n changed = true;\n }\n }\n if (\"encrypted_content\" in record) {\n delete record.encrypted_content;\n changed = true;\n }\n };\n const scrubItemArray = (arr: unknown): void => {\n if (Array.isArray(arr)) {\n for (const item of arr) {\n scrubReasoning(item);\n }\n }\n };\n const root = parsed as Record<string, unknown>;\n // 1. originalInput is either a string (no items) or an array of protocol items.\n scrubItemArray(root.originalInput);\n // 2. generatedItems are SDK run-item wrappers; a `reasoning_item` carries the\n // protocol reasoning shape under `rawItem`.\n if (Array.isArray(root.generatedItems)) {\n for (const wrapper of root.generatedItems) {\n if (wrapper && typeof wrapper === \"object\" && \"rawItem\" in (wrapper as Record<string, unknown>)) {\n scrubReasoning((wrapper as Record<string, unknown>).rawItem);\n }\n }\n }\n // 3. modelResponses[].output and lastModelResponse.output hold protocol items.\n const scrubResponseOutput = (response: unknown): void => {\n if (response && typeof response === \"object\") {\n scrubItemArray((response as Record<string, unknown>).output);\n }\n };\n if (Array.isArray(root.modelResponses)) {\n for (const response of root.modelResponses) {\n scrubResponseOutput(response);\n }\n }\n scrubResponseOutput(root.lastModelResponse);\n if (!changed) {\n return serialized;\n }\n return JSON.stringify(parsed);\n}\n\n/**\n * Neutralize tool_search items IN PLACE in a serialized RunState blob for a\n * cross-account codex resume — the run-state sibling of\n * `applyCodexHistoryStrip`'s tool_search rule, but COUNT-PRESERVING (HOLE E: the\n * blob path's reconcile watermark counts the blob's history length, so items\n * must never be removed — only mutated, exactly like the reasoning\n * neutralization above).\n *\n * The hazard: on deserialize, the SDK re-runs the registered CLIENT tool_search\n * execute callback per frozen pair (`rehydrateToolSearchRuntimeTools`) and\n * THROWS a UserError when the re-run's runtime-tool keys mismatch the serialized\n * expectation — which is exactly what happens when the RESUMING account's\n * connector pool differs from the FREEZING account's. The SDK skips that\n * rehydration entirely for `execution === 'server'` calls, so flipping the\n * frozen pairs' `execution` to `\"server\"` in place defuses the throw without\n * touching counts, ids, pairing, or content. The flipped shape is wire-safe:\n * LIVE-VERIFIED against /codex/responses — a replayed server-execution pair is\n * accepted (200) and its disclosure still holds. The account-bound `tsc_…` id is\n * separately stripped by the codex transport normalizer (all input item ids).\n *\n * Walks the same blob locations as {@link stripReasoningIdentityFromSerializedRunState}:\n * `originalInput` (array form), `generatedItems` (SDK run-item wrappers — the\n * raw shape under `rawItem`), every `modelResponses[].output`, and\n * `lastModelResponse.output`. Returns the input string unchanged when nothing\n * matched.\n */\nexport function neutralizeToolSearchItemsInSerializedRunState(serialized: string): string {\n let parsed: unknown;\n try {\n parsed = JSON.parse(serialized);\n } catch {\n return serialized;\n }\n if (!parsed || typeof parsed !== \"object\") {\n return serialized;\n }\n let changed = false;\n const neutralize = (candidate: unknown): void => {\n if (!candidate || typeof candidate !== \"object\") {\n return;\n }\n const record = candidate as Record<string, unknown>;\n if (record.type !== \"tool_search_call\" && record.type !== \"tool_search_output\") {\n return;\n }\n if (record.execution !== \"server\") {\n record.execution = \"server\";\n changed = true;\n }\n };\n const neutralizeArray = (arr: unknown): void => {\n if (Array.isArray(arr)) {\n for (const item of arr) {\n neutralize(item);\n }\n }\n };\n const root = parsed as Record<string, unknown>;\n neutralizeArray(root.originalInput);\n if (Array.isArray(root.generatedItems)) {\n for (const wrapper of root.generatedItems) {\n if (wrapper && typeof wrapper === \"object\" && \"rawItem\" in (wrapper as Record<string, unknown>)) {\n neutralize((wrapper as Record<string, unknown>).rawItem);\n }\n }\n }\n const neutralizeResponseOutput = (response: unknown): void => {\n if (response && typeof response === \"object\") {\n neutralizeArray((response as Record<string, unknown>).output);\n }\n };\n if (Array.isArray(root.modelResponses)) {\n for (const response of root.modelResponses) {\n neutralizeResponseOutput(response);\n }\n }\n neutralizeResponseOutput(root.lastModelResponse);\n if (!changed) {\n return serialized;\n }\n return JSON.stringify(parsed);\n}\n\n/**\n * Normalize `computer_call` items so each carries EXACTLY ONE of the two\n * mutually-exclusive action fields the provider accepts.\n *\n * The OpenAI Agents SDK 0.11.6 `computer_call` schema (protocol.mjs) carries\n * BOTH the legacy singular `action` and the GA batched `actions`, each\n * `.optional()`, and only requires \"at least one\" (its superRefine errors only\n * when both are absent). The Azure computer-use endpoint is stricter: it\n * requires EXACTLY one and rejects the whole request with\n *\n * `400 Computer call input must include exactly one of `action` or `actions`.`\n *\n * when an emitted `computer_call` carries both (observed live: a screenshot\n * call carrying `action:{type:\"screenshot\"}` AND `actions:[{type:\"screenshot\"}]`).\n *\n * Which singular do we keep? LIVE-PROVEN against the deployed Azure deployment\n * (gpt-5.5-2026-04-24): for gpt-5.5 the SDK serializes the GA computer tool as\n * `{type:\"computer\"}` (not the legacy `computer_use_preview`), and that GA tool\n * accepts ONLY the batched plural `actions`. Probing all three shapes:\n * - `action`-only -> 400 \"exactly one of action or actions\" (STILL rejected)\n * - `actions`-only -> passes the action/actions structural validation\n * - both -> 400 \"exactly one …\"\n * The \"exactly one\" wording is misleading: only the `actions`-only form is\n * accepted by the GA tool. So when both are present we KEEP `actions` (the GA\n * batched plural) and DROP `action`. Calls that already carry exactly one field\n * — or the legacy `action`-only form — pass through untouched (this transform's\n * sole job is to resolve the both-present conflict, not to rewrite singulars).\n *\n * Pure and non-mutating: only the conflicting item(s) are cloned; every other\n * item passes through by reference (byte-identical). Unlike\n * {@link sanitizeHistoryItemsForModel} (which only *filters* items), this is a\n * read-path *transform* of a single item's shape.\n */\nexport function normalizeComputerCallActions<T extends HistoryItem>(items: readonly T[]): T[] {\n let changed = false;\n const out = items.map((item) => {\n if (itemType(item) !== \"computer_call\") {\n return item;\n }\n const record = item as Record<string, unknown>;\n const hasAction = record.action !== undefined && record.action !== null;\n const hasActions = Array.isArray(record.actions) && (record.actions as unknown[]).length > 0;\n if (hasAction && hasActions) {\n changed = true;\n const { action: _droppedAction, ...rest } = record;\n return rest as unknown as T;\n }\n return item;\n });\n return changed ? out : items.slice();\n}\n\n/**\n * Rewrite EVERY `computer_call` item in a serialized Responses request body to\n * the ACTIONS-ONLY shape the GA Azure computer tool accepts, mutating the parsed\n * JSON object in place and returning whether anything changed.\n *\n * WHY THIS LIVES AT THE WIRE LEVEL (not the input-item filter). The input-item\n * normalizer above ({@link normalizeComputerCallActions}, wired as a\n * callModelInputFilter) runs BEFORE the SDK's responses converter\n * (`convertAgentItemToResponsesInput`). That converter then re-derives the wire\n * payload from the item: when `actions` is present it emits BOTH\n * `{action: ..., actions: [...]}`, and when only `action` is present it emits\n * `action`-only. It can NEVER emit actions-only. Probed live against the\n * deployed Azure gpt-5.5-2026-04-24 GA computer tool (`{type:\"computer\"}`):\n * - `action`-only -> 400 \"Computer call input must include exactly one of\n * `action` or `actions`.\" (rejected)\n * - both -> 400 same message (rejected)\n * - `actions`-only -> passes the action/actions structural validation\n * So neither the input-filter nor the converter can produce an accepted body.\n * The ONLY seam that sees — and can rewrite — the final serialized JSON is a\n * custom `fetch` on the OpenAI client (it runs after the converter and after\n * `responses.create` serialization). This function is that rewriter's core.\n *\n * It collapses each computer_call to actions-only: it prefers an existing\n * non-empty `actions` array, else wraps the singular `action` into\n * `actions:[action]`, then deletes `action`. A computer_call with neither field\n * is left untouched (nothing to derive; let the provider report it).\n *\n * Mutates `body` in place (the caller has already JSON.parsed a private copy of\n * the request body). Returns `true` iff at least one computer_call was changed.\n */\nexport function rewriteComputerCallsToActionsOnly(body: unknown): boolean {\n if (!body || typeof body !== \"object\") {\n return false;\n }\n const input = (body as Record<string, unknown>).input;\n if (!Array.isArray(input)) {\n return false;\n }\n let changed = false;\n for (const item of input) {\n if (!item || typeof item !== \"object\") {\n continue;\n }\n const record = item as Record<string, unknown>;\n if (record.type !== \"computer_call\") {\n continue;\n }\n const existingActions = Array.isArray(record.actions) && (record.actions as unknown[]).length > 0\n ? (record.actions as unknown[])\n : undefined;\n const actions = existingActions ?? (\n record.action !== undefined && record.action !== null ? [record.action] : undefined\n );\n if (actions === undefined) {\n // Neither action nor actions present: nothing to normalize.\n continue;\n }\n const hadAction = \"action\" in record;\n const actionsAlreadyExact = existingActions !== undefined && !hadAction;\n if (actionsAlreadyExact) {\n // Already actions-only with a non-empty array — leave byte-identical.\n continue;\n }\n delete record.action;\n record.actions = actions;\n changed = true;\n }\n return changed;\n}\n\n/**\n * The 1×1 transparent PNG placeholder used by the SDK for tool-approval-rejection\n * screenshots (`TOOL_APPROVAL_REJECTION_SCREENSHOT_DATA_URL` in agents-core\n * `toolExecution.mjs`). We reuse the exact same constant as a backstop for the\n * action-timeout 400: when an action times out the SDK's catch sets output='' and\n * builds `{type:\"computer_call_output\",output:{type:\"computer_screenshot\",image_url:\"\"}}`.\n * Azure rejects `image_url:\"\"` with \"400 Invalid input[N].output.image_url\". This\n * placeholder is a valid data URI the provider accepts, so the turn continues and\n * the model receives the next real screenshot on its following step.\n */\nconst EMPTY_IMAGE_URL_PLACEHOLDER =\n \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR4nGP4z8DwHwAFAAH/iZk9HQAAAABJRU5ErkJggg==\";\n\n/**\n * Backstop for the action-timeout 400: walk the `input` array of a serialized\n * Responses request body and replace any `computer_call_output` item whose\n * `output.image_url` is an empty string, null, undefined, or otherwise not a\n * non-empty string with the 1×1 transparent PNG placeholder data URI.\n *\n * WHY THIS IS NEEDED. When a computer ACTION (click/type/scroll/drag) times out\n * at the 15-second yield window `SandboxComputer.x()` throws `ComputerActionError`.\n * The agents-core SDK `toolExecution.mjs` catch block sets `output = ''` and then\n * builds the wire item:\n *\n * `{type:\"computer_call_output\", output:{type:\"computer_screenshot\", image_url:\"\"}}`\n *\n * Azure rejects the whole request with:\n *\n * `400 Invalid 'input[N].output.image_url'. Expected a valid URL, but got a\n * value with an invalid format.`\n *\n * Our screenshot() fail-loud guard (which throws on empty frames) only runs when\n * the SDK calls screenshot() on a SUCCESS path — not on this action-error catch\n * path that sets output='' directly. This wire-level rewrite is the only seam that\n * catches both paths regardless of how the empty image_url was produced. It runs\n * in the same `computerCallNormalizingFetch` wrapper, so a single parse/rewrite\n * pass covers both the action/actions-only rewrite and this placeholder injection.\n *\n * Mutates `body` in place (the caller has already JSON.parsed a private copy).\n * Returns `true` iff at least one image_url was replaced.\n */\nexport function rewriteEmptyComputerCallOutputImageUrls(body: unknown): boolean {\n if (!body || typeof body !== \"object\") {\n return false;\n }\n const input = (body as Record<string, unknown>).input;\n if (!Array.isArray(input)) {\n return false;\n }\n let changed = false;\n for (const item of input) {\n if (!item || typeof item !== \"object\") {\n continue;\n }\n const record = item as Record<string, unknown>;\n if (record.type !== \"computer_call_output\") {\n continue;\n }\n const output = record.output;\n if (!output || typeof output !== \"object\") {\n continue;\n }\n const out = output as Record<string, unknown>;\n const imageUrl = out.image_url;\n // Replace the image_url when it is not a non-empty string (covers: \"\", null, undefined, missing).\n if (typeof imageUrl !== \"string\" || imageUrl.length === 0) {\n out.image_url = EMPTY_IMAGE_URL_PLACEHOLDER;\n changed = true;\n }\n }\n return changed;\n}\n\n/**\n * Wrap a `fetch` so every outbound OpenAI Responses request body that contains a\n * `computer_call` is rewritten to the ACTIONS-ONLY shape (see\n * {@link rewriteComputerCallsToActionsOnly}) before it reaches the network, AND\n * any `computer_call_output` item with an empty/missing `output.image_url` is\n * patched with the 1×1 transparent PNG placeholder (see\n * {@link rewriteEmptyComputerCallOutputImageUrls}).\n *\n * Installed as the `fetch:` option on the Azure OpenAI client, this is the\n * lowest reachable seam — below the agents-core input filter and below the SDK's\n * responses converter — so it neutralizes the converter's both-fields synthesis\n * regardless of what the input item carried, and backstops the action-timeout\n * empty image_url regardless of how it was produced.\n *\n * Surgical and cheap: it only parses the body when it is a string that contains\n * the prefix `\"computer_call` (matching both `\"computer_call\"` action items and\n * `\"computer_call_output\"` result items). Every other request — non-computer-use\n * turns, streaming SSE responses, non-string bodies — forwards untouched, the\n * SAME `init` reference, so streaming and other providers are unaffected. A JSON\n * parse failure or a no-op rewrite also forwards the original `init` unchanged.\n *\n * Typed structurally (the `(input, init) => Promise<Response>` call signature)\n * rather than as the DOM `typeof fetch` so it omits the `preconnect` static the\n * global type carries; this matches the OpenAI SDK's `Fetch` option, which only\n * needs the call signature. The wiring site passes it as the client `fetch:`.\n */\ntype FetchLike = (\n input: Parameters<typeof fetch>[0],\n init?: Parameters<typeof fetch>[1],\n) => Promise<Response>;\n\nexport function computerCallNormalizingFetch(base: FetchLike): FetchLike {\n return (input, init) => {\n // Match any request that mentions either `computer_call` (the action call) or\n // `computer_call_output` (the output/result item). Both strings begin with\n // `\"computer_call` so a single prefix-substring check covers both.\n if (init && typeof init.body === \"string\" && init.body.includes(\"\\\"computer_call\")) {\n try {\n const parsed = JSON.parse(init.body) as unknown;\n const changed1 = rewriteComputerCallsToActionsOnly(parsed);\n const changed2 = rewriteEmptyComputerCallOutputImageUrls(parsed);\n if (changed1 || changed2) {\n return base(input, { ...init, body: JSON.stringify(parsed) });\n }\n } catch {\n // Non-JSON or parse failure: forward the request unchanged.\n }\n }\n return base(input, init);\n };\n}\n","// Progressive connector disclosure for the ChatGPT/Codex backend — parity with\n// how the Codex CLI surfaces its ~217 `codex_apps` connector tools WITHOUT paying\n// their schemas in every turn's context.\n//\n// WHY. OpenGeni connects the codex_apps MCP server as a CLIENT and the SDK\n// materializes EVERY connector tool as a `function` tool in request.tools[] on\n// every codex turn (~217 tools ≈ tens of thousands of context tokens). The Codex\n// CLI instead uses the backend's NATIVE tool-search: the model gets one compact\n// search tool + all connector tools flagged `defer_loading:true` (schemas dropped\n// from model context), searches by capability, and only the matched tools are\n// disclosed back and become callable.\n//\n// PROVEN LIVE (Phase 0 probe against /codex/responses on gpt-5.5): the backend\n// HONORS `defer_loading:true` on function tools — 50 fat tools dropped input_tokens\n// 6766 → 108 — AND makes a tool callable purely because a prior `tool_search_output`\n// disclosed it (V3). The model emits `tool_search_call` on our slug.\n//\n// HOW. We wrap the agent's `getAllTools` (codex turns only, flag-gated): tag every\n// `codex_apps__*` function tool `deferLoading = true` (converTool then serializes\n// `defer_loading:true`, dropping the schema from context) and append one\n// client-executed `toolSearchTool`. The SDK routes a `tool_search_call` to our\n// executor (ClientToolSearchExecutor), which BM25-ranks the deferred pool and\n// returns the matched tools BY REFERENCE — the SDK emits the `tool_search_output`\n// that discloses them; the subsequent `function_call` resolves through the normal\n// PrefixedMcpServer.callTool path (auth + name-sanitize + structuredContent inline\n// all unchanged). Invocation is untouched; only the wire tool-set shrinks.\n\nimport { toolSearchTool, type Tool } from \"@openai/agents\";\n\n/** The prefix OpenGeni's PrefixedMcpServer stamps on codex_apps connector tools. */\nexport const CODEX_APPS_TOOL_PREFIX = \"codex_apps__\";\nconst DEFAULT_SEARCH_LIMIT = 8;\nconst MAX_SEARCH_LIMIT = 20;\n\n/** True for a materialized codex_apps connector function tool. */\nexport function isCodexAppsFunctionTool(tool: unknown): tool is Tool & { name: string; deferLoading?: boolean } {\n return (\n !!tool\n && typeof tool === \"object\"\n && (tool as { type?: unknown }).type === \"function\"\n && typeof (tool as { name?: unknown }).name === \"string\"\n && (tool as { name: string }).name.startsWith(CODEX_APPS_TOOL_PREFIX)\n );\n}\n\n// Minimal English stopword set: query phrasings like \"send an email to someone\"\n// should match on capability words, not drown in glue words (parity with\n// codex-rs, whose search normalizes tokens server-side).\nconst STOPWORDS = new Set([\n \"a\", \"an\", \"the\", \"and\", \"or\", \"of\", \"to\", \"in\", \"on\", \"for\", \"with\", \"by\", \"at\",\n \"is\", \"are\", \"be\", \"do\", \"does\", \"my\", \"me\", \"your\", \"you\", \"it\", \"its\", \"this\",\n \"that\", \"from\", \"as\", \"up\", \"out\", \"all\", \"some\", \"any\", \"can\", \"will\", \"would\",\n \"should\", \"want\", \"need\", \"please\", \"user\", \"users\",\n]);\n\n/** Light suffix stemmer so \"emails\"/\"email\", \"creating\"/\"create\" co-match (min-stem guards, no over-stripping). */\nfunction stem(token: string): string {\n if (token.length > 5 && token.endsWith(\"ing\")) return token.slice(0, -3);\n if (token.length > 4 && token.endsWith(\"ed\")) return token.slice(0, -2);\n if (token.length > 4 && token.endsWith(\"es\")) return token.slice(0, -2);\n if (token.length > 3 && token.endsWith(\"s\") && !token.endsWith(\"ss\")) return token.slice(0, -1);\n return token;\n}\n\n/** Split snake_case/camelCase/dotted text into stemmed lowercase word tokens (len ≥ 2, stopwords removed). */\nfunction tokenize(text: string): string[] {\n return text\n .replace(/([a-z0-9])([A-Z])/g, \"$1 $2\")\n .toLowerCase()\n .split(/[^a-z0-9]+/)\n .filter((t) => t.length > 1 && !STOPWORDS.has(t))\n .map(stem);\n}\n\n/** The searchable text of a connector tool: name (weighted ×2) + description + param names. */\nfunction toolSearchText(tool: Tool): string {\n const raw = (tool as { name?: string }).name ?? \"\";\n const name = raw.startsWith(CODEX_APPS_TOOL_PREFIX) ? raw.slice(CODEX_APPS_TOOL_PREFIX.length) : raw;\n const description = typeof (tool as { description?: unknown }).description === \"string\" ? (tool as { description: string }).description : \"\";\n const params = (tool as { parameters?: { properties?: Record<string, unknown> } }).parameters?.properties;\n const paramNames = params && typeof params === \"object\" ? Object.keys(params).join(\" \") : \"\";\n return `${name} ${name} ${description} ${paramNames}`;\n}\n\n/**\n * Rank connector tools against a plain-language query with BM25 (Okapi, k1=1.5,\n * b=0.75) over tokenized name+description+params. Returns the top `limit` tools\n * with a positive score, most-relevant first. An empty or no-match query returns\n * [] — matching codex-rs, whose search returns empty rather than arbitrary tools;\n * disclosing unrelated (and thereby CALLABLE) tools on a miss feeds the model\n * noise. The SDK normalizes an empty executor result into an empty\n * tool_search_output, which the model reads as \"nothing matched — rephrase\".\n */\nexport function bm25RankTools(tools: Tool[], query: string, limit: number): Tool[] {\n const qTokens = Array.from(new Set(tokenize(query)));\n if (tools.length === 0 || qTokens.length === 0) return [];\n\n const docs = tools.map((tool) => {\n const tokens = tokenize(toolSearchText(tool));\n const tf = new Map<string, number>();\n for (const t of tokens) tf.set(t, (tf.get(t) ?? 0) + 1);\n return { tool, len: tokens.length, tf };\n });\n const N = docs.length;\n const avgdl = Math.max(1, docs.reduce((s, d) => s + d.len, 0) / N);\n const df = new Map<string, number>();\n for (const d of docs) for (const t of d.tf.keys()) df.set(t, (df.get(t) ?? 0) + 1);\n\n const k1 = 1.5;\n const b = 0.75;\n const scored = docs.map((d) => {\n let score = 0;\n for (const qt of qTokens) {\n const n = df.get(qt);\n const f = d.tf.get(qt);\n if (!n || !f) continue;\n const idf = Math.log(1 + (N - n + 0.5) / (n + 0.5));\n score += idf * ((f * (k1 + 1)) / (f + k1 * (1 - b + (b * d.len) / avgdl)));\n }\n return { tool: d.tool, score };\n });\n const hits = scored.filter((s) => s.score > 0).sort((a, b2) => b2.score - a.score);\n return hits.slice(0, limit).map((s) => s.tool); // no hits ⇒ [] (codex-rs parity; see doc)\n}\n\n/** Parse `{query, limit}` from a tool_search_call's arguments (string or object). */\nfunction parseSearchArgs(raw: unknown): { query: string; limit: number } {\n let obj: Record<string, unknown> = {};\n try {\n obj = typeof raw === \"string\" ? (raw.length ? JSON.parse(raw) : {}) : (raw && typeof raw === \"object\" ? (raw as Record<string, unknown>) : {});\n } catch {\n obj = {};\n }\n const query = typeof obj.query === \"string\" ? obj.query : \"\";\n const limitRaw = typeof obj.limit === \"number\" && Number.isFinite(obj.limit) ? obj.limit : DEFAULT_SEARCH_LIMIT;\n return { query, limit: Math.max(1, Math.min(MAX_SEARCH_LIMIT, Math.round(limitRaw))) };\n}\n\n/**\n * Render the search tool's description from the account's ACTUALLY-connected\n * sources — codex-rs parity (its create_tool_search_tool builds \"You have access\n * to tools from the following sources:\\n- <name>\" from the live enabled-source\n * list). With defer_loading stripping every connector schema (and name) from\n * model context, this description is the model's ONLY signal of which apps\n * exist, so a hardcoded list would both advertise absent connectors and hide\n * present ones.\n */\nexport function renderSearchToolDescription(connectorNamespaces: ReadonlySet<string>): string {\n const base =\n \"Search the user's connected app tools by capability. \"\n + \"Describe in plain language WHAT you need to do (for example: \\\"send an email\\\", \\\"create a calendar event\\\") \"\n + \"rather than guessing exact tool names. Returns the matching connector tools, which then become callable.\";\n const sources = Array.from(connectorNamespaces).filter((n) => typeof n === \"string\" && n.length > 0).sort();\n if (sources.length === 0) {\n return `${base}\\nConnected sources: none currently available.`;\n }\n return `${base}\\nYou have access to tools from the following sources:\\n${sources.map((s) => `- ${s}`).join(\"\\n\")}`;\n}\n\nconst SEARCH_TOOL_PARAMETERS = {\n type: \"object\",\n properties: {\n query: { type: \"string\", description: \"Plain-language description of the capability you need.\" },\n limit: { type: \"number\", description: \"Maximum number of tools to return (default 8).\" },\n },\n required: [\"query\"],\n additionalProperties: false,\n} as const;\n\n/**\n * The client tool-search executor: BM25 over the deferred codex_apps pool from the\n * turn's live `availableTools`, returning matched tools BY REFERENCE (the only legal\n * return — the SDK emits the disclosing `tool_search_output` and flips the loaded\n * gate; returning copies would throw). Stateless — reads the pool per call.\n */\nfunction codexToolSearchExecutor(args: { availableTools?: Tool[]; toolCall?: { arguments?: unknown } }): Tool[] {\n const deferred = (args.availableTools ?? []).filter(isCodexAppsFunctionTool);\n if (deferred.length === 0) return [];\n const { query, limit } = parseSearchArgs(args.toolCall?.arguments);\n return bm25RankTools(deferred, query, limit);\n}\n\nconst NO_NAMESPACES: ReadonlySet<string> = new Set();\n\n/** Build the client-executed tool_search tool that discloses codex_apps connectors on demand. */\nexport function buildCodexToolSearchTool(connectorNamespaces: ReadonlySet<string> = NO_NAMESPACES): Tool {\n return toolSearchTool({\n execution: \"client\",\n description: renderSearchToolDescription(connectorNamespaces),\n parameters: SEARCH_TOOL_PARAMETERS as unknown as Record<string, unknown>,\n execute: codexToolSearchExecutor as never,\n }) as unknown as Tool;\n}\n\n/** True for the built-in tool_search tool (so we never add a second one). */\nfunction isToolSearchTool(tool: unknown): boolean {\n const t = tool as { name?: unknown; providerData?: { type?: unknown } } | null;\n return !!t && (t.name === \"tool_search\" || t.providerData?.type === \"tool_search\");\n}\n\n/**\n * The transform applied to a turn's resolved tool list: tag every codex_apps\n * connector function tool `deferLoading = true`, and — unless one is already\n * present — append the client tool_search tool. Pure (mutates the passed tools +\n * returns the possibly-extended array); the SDK's `getTools` gate requires a\n * tool_search whenever a deferred tool is present, which appending here satisfies\n * in the same request.\n *\n * The search tool is appended UNCONDITIONALLY (even when the turn has no\n * codex_apps tools, e.g. the best-effort codex_apps connect was dropped this\n * turn): a prior turn's history may carry tool_search_call/output items, and\n * replaying those without a tool_search tool in the request risks a backend\n * reject; a search over an empty pool simply discloses nothing. The description\n * reflects the LIVE connector namespaces, so an empty turn reads\n * \"none currently available\".\n */\nexport function applyCodexToolSearch(tools: Tool[], connectorNamespaces: ReadonlySet<string> = NO_NAMESPACES): Tool[] {\n for (const tool of tools) {\n if (isCodexAppsFunctionTool(tool) && (tool as { deferLoading?: boolean }).deferLoading !== true) {\n (tool as { deferLoading?: boolean }).deferLoading = true;\n }\n }\n if (tools.some(isToolSearchTool)) {\n return tools;\n }\n return [...tools, buildCodexToolSearchTool(connectorNamespaces)];\n}\n\ntype CloneCapableAgent = {\n getAllTools: (runContext: unknown) => Promise<Tool[]>;\n clone?: (config: unknown) => CloneCapableAgent;\n};\n\n/**\n * Install progressive connector disclosure on a codex-path agent by wrapping\n * `getAllTools` so every per-model-call tool resolution runs\n * {@link applyCodexToolSearch}. Idempotent-per-call (re-tags each\n * freshly-materialized MCP tool under cacheToolsList:false). Gated by the caller\n * (flag + codex path).\n *\n * CLONE SURVIVAL (the part that makes this work on the REAL sandbox path): the\n * SDK's sandbox runtime routes EVERY model call through\n * `prepareSandboxAgent → agent.clone(...)` (agentPreparation.js), and\n * `SandboxAgent.clone` constructs a FRESH agent from a fixed field list — an\n * instance-own `getAllTools` override is NOT copied, so patching only this\n * instance would silently no-op the whole feature on sandbox turns (the run\n * loop resolves tools on the CLONE). We therefore also wrap `clone` to\n * RE-INSTALL onto every clone, recursively — covering clone-of-clone and the\n * RunState resume paths. `connectorNamespaces` is the LIVE, by-reference Set the\n * codex_apps sanitizing transport fills during each turn's tools/list\n * (prepareAgentTools), so by the time the wrapper post-processes getAllTools the\n * current turn's connector sources are known.\n */\nexport function installCodexToolSearch(agent: CloneCapableAgent, connectorNamespaces: ReadonlySet<string> = NO_NAMESPACES): void {\n const originalGetAllTools = agent.getAllTools.bind(agent);\n agent.getAllTools = (async (runContext: unknown) =>\n applyCodexToolSearch(await originalGetAllTools(runContext), connectorNamespaces)) as typeof agent.getAllTools;\n const originalClone = agent.clone?.bind(agent);\n if (originalClone) {\n const cloneWithToolSearch: NonNullable<CloneCapableAgent[\"clone\"]> = (config: unknown) => {\n const cloned = originalClone(config);\n installCodexToolSearch(cloned, connectorNamespaces);\n return cloned;\n };\n agent.clone = cloneWithToolSearch;\n }\n}\n","/**\n * Client-side conversation context compaction (the Azure path).\n *\n * OpenGeni runs long-lived agent sessions whose conversation truth\n * (`session_history_items`) grows unbounded. On the OpenAI platform the\n * Responses API compacts server-side (the SDK's `compaction()` capability). On\n * Azure that capability 400s (`unsupported_parameter`), so the session\n * eventually overflows the model context window and hard-fails every turn.\n *\n * This module is the Azure-safe replacement. It is built from two pure pieces\n * plus one impure step the caller wires in:\n *\n * 1. `planCompaction` — given the active history items, the last turn's actual\n * input-token count, and the token budget, decide WHETHER to compact and,\n * if so, WHERE the orphan-safe cut boundary is (the prefix to summarize vs\n * the recent tail to keep verbatim). Pure, exhaustively testable.\n * 2. (caller) summarize the prefix into ONE plain user `message` item via a\n * model call — see `buildCompactionMessages` / `SUMMARY_PREFIX`.\n * 3. `applyCompaction` shape — the storage write the caller performs:\n * supersede the prefix rows, insert the summary at the boundary position.\n *\n * Design constraints (non-negotiable):\n * - The summary is a PLAIN user message, NOT the SDK `compaction` item type\n * (that requires server-minted `encrypted_content`; a hand-rolled one risks\n * an Azure 400).\n * - ORPHAN SAFETY: the cut lands only at a clean turn boundary (start of a\n * user message). No tool call_id may straddle the cut — for every\n * `function_call` dropped, its `function_call_result` is also dropped, and\n * vice versa. Reasoning items drop/keep with their whole turn.\n * - SINGLE LIVE SUMMARY: each compaction folds the prior summary forward\n * (summarize [prior summary] + [items since]); prior summaries are excluded\n * from re-collection so drift stays bounded.\n */\n\nexport type CompactionItem = Record<string, unknown>;\n\n/**\n * Marker stored on the synthetic summary item so it can be recognized on the\n * next compaction (to fold it forward) and excluded from re-summarization. It\n * lives in the item JSON, not a DB column, so it survives verbatim replay.\n */\nexport const COMPACTION_SUMMARY_MARKER = \"opengeni_context_summary\";\n\n/**\n * Bridge text prepended to the summary body in the synthetic user message. It\n * tells the model the preceding conversation was compacted and that durable\n * facts live in the notebook — so it treats the summary as a working-memory\n * pointer, not the whole truth.\n */\nexport const SUMMARY_PREFIX = [\n \"[CONTEXT CHECKPOINT] The earlier part of this conversation was automatically compacted to stay within the model context window.\",\n \"Durable facts already live in the workspace notebook / document bases (via MCP) — the summary below is a light working-memory bridge, not a full transcript.\",\n \"Trust it for current objective, decisions, blockers, deployed/infra state, and next steps; re-read the notebook for anything authoritative.\",\n \"\",\n \"SUMMARY:\",\n].join(\"\\n\");\n\nconst RESULT_TYPE_BY_CALL_TYPE: Record<string, string> = {\n function_call: \"function_call_result\",\n computer_call: \"computer_call_result\",\n shell_call: \"shell_call_output\",\n apply_patch_call: \"apply_patch_call_output\",\n};\nconst RESULT_TYPES = new Set(Object.values(RESULT_TYPE_BY_CALL_TYPE));\n\nfunction itemType(item: unknown): string | undefined {\n if (!item || typeof item !== \"object\") {\n return undefined;\n }\n const type = (item as { type?: unknown }).type;\n return typeof type === \"string\" ? type : undefined;\n}\n\nfunction itemRole(item: unknown): string | undefined {\n if (!item || typeof item !== \"object\") {\n return undefined;\n }\n const role = (item as { role?: unknown }).role;\n return typeof role === \"string\" ? role : undefined;\n}\n\n/** A user-authored `message` item is the only legal turn boundary. */\nexport function isUserMessage(item: unknown): boolean {\n return itemType(item) === \"message\" && itemRole(item) === \"user\";\n}\n\n/** True for our synthetic compaction summary item. */\nexport function isCompactionSummary(item: unknown): boolean {\n return (\n isUserMessage(item) &&\n (item as Record<string, unknown>)[COMPACTION_SUMMARY_MARKER] === true\n );\n}\n\n/**\n * Rough token estimate for an item: char/4 over its serialized text. Used only\n * for the tail-budget walk; the trigger decision uses the real last-turn input\n * token count, falling back to this when that is unavailable.\n */\nexport function estimateItemTokens(item: CompactionItem): number {\n let text: string;\n try {\n text = JSON.stringify(item);\n } catch {\n text = String(item);\n }\n return Math.ceil(text.length / 4);\n}\n\nexport function estimateTokens(items: readonly CompactionItem[]): number {\n let total = 0;\n for (const item of items) {\n total += estimateItemTokens(item);\n }\n return total;\n}\n\n/**\n * Walk backwards from the end of `items` keeping whole turns until the kept\n * tail would exceed `keepRecentTokens`, and return the index of the first kept\n * item. The returned index is always the start of a user message (a clean turn\n * boundary), so the prefix [0, index) never splits a tool-call pair.\n *\n * Returns `items.length` when nothing fits within the budget yet a boundary is\n * required (degenerate); callers treat an index of 0 or length as \"no useful\n * cut\".\n */\nexport function findKeepBoundary(items: readonly CompactionItem[], keepRecentTokens: number): number {\n // Indices that begin a user message (candidate boundaries). The first item is\n // a boundary even if it is not a user message, so a cut at 0 is meaningful.\n const boundaries: number[] = [];\n for (let i = 0; i < items.length; i += 1) {\n if (isUserMessage(items[i])) {\n boundaries.push(i);\n }\n }\n if (boundaries.length === 0) {\n // No user-message boundary at all — cannot cut safely.\n return 0;\n }\n // keepRecentTokens is a CAP on how much recent history is kept verbatim. We\n // keep as much as fits: the EARLIEST user-message boundary whose tail\n // [boundary, end) is still within the cap. Walking earliest -> latest, the\n // first boundary that fits is that earliest one (tails only shrink as the\n // boundary moves later). If even the last boundary's tail exceeds the cap we\n // fall back to it (keep at least the final turn).\n for (let b = 0; b < boundaries.length; b += 1) {\n const boundary = boundaries[b]!;\n if (estimateTokens(items.slice(boundary)) <= keepRecentTokens) {\n return boundary;\n }\n }\n return boundaries[boundaries.length - 1]!;\n}\n\n/**\n * READ-PATH BUDGET GUARD (last-resort backstop).\n *\n * Pre-turn compaction is best-effort: it can no-op (summarizer model call\n * fails, \"client\" mode off, a fresh user message arrives after a turn already\n * ballooned the history) and STILL leave an assembled input that exceeds the\n * model context window. The #61 orphan sanitizer is purely structural — it has\n * NO size awareness — so without this guard an over-budget input is sent and\n * 400s every turn, re-bricking the session.\n *\n * `enforceInputBudget` drops the OLDEST history at a clean turn boundary until\n * the estimated input fits `maxTokens`, ALWAYS keeping the most recent turn(s).\n * It is orphan-safe by construction: it only ever cuts at the start of a user\n * message (via `findKeepBoundary`), so no tool-call pair is split. It is a\n * crude data-loss fallback (no summary is generated) that exists solely so a\n * single over-budget assembled input is never put on the wire — real context\n * preservation is the summarizing pre-turn path; this is the airbag.\n *\n * Pure: returns a new array (same item references, in order) with an oldest\n * prefix omitted, or the input unchanged when it already fits. The provided\n * `trailingTokens` accounts for the un-stored part of the assembled input (the\n * new user/continuation message + fixed system/tool overhead) so the cap is\n * measured against the WHOLE request, not just the stored history.\n */\nexport function enforceInputBudget<T extends CompactionItem>(\n items: readonly T[],\n maxTokens: number,\n trailingTokens = 0,\n): { items: T[]; trimmed: boolean; droppedCount: number; estimatedTokens: number } {\n const total = estimateTokens(items) + Math.max(0, trailingTokens);\n if (items.length === 0 || total <= maxTokens) {\n return { items: items.slice(), trimmed: false, droppedCount: 0, estimatedTokens: total };\n }\n // Budget left for the stored history once the fixed trailing cost is paid.\n const historyBudget = Math.max(0, maxTokens - Math.max(0, trailingTokens));\n // Find the EARLIEST user-message boundary whose tail fits historyBudget; that\n // boundary's prefix is the oldest history we drop. findKeepBoundary already\n // returns a clean turn boundary (start of a user message), so the cut is\n // orphan-safe. A boundary of 0 means nothing could be dropped safely (no\n // earlier boundary) — we leave the input as-is rather than orphan a pair.\n const boundary = findKeepBoundary(items, historyBudget);\n if (boundary <= 0) {\n return { items: items.slice(), trimmed: false, droppedCount: 0, estimatedTokens: total };\n }\n const kept = items.slice(boundary);\n return {\n items: kept,\n trimmed: true,\n droppedCount: boundary,\n estimatedTokens: estimateTokens(kept) + Math.max(0, trailingTokens),\n };\n}\n\nexport type CompactionPlan = {\n /** Whether a compaction should run this turn. */\n shouldCompact: boolean;\n /** Why not, when shouldCompact is false (for logs/tests). */\n reason: \"below_threshold\" | \"no_boundary\" | \"nothing_to_summarize\" | \"compact\";\n /**\n * The signal-token count the trigger decision was made on:\n * max(actual last-turn input tokens, char/4 estimate of the active items).\n * Recorded for logging / metrics and so a caller can reason about pressure.\n */\n signalTokens: number;\n /**\n * True when the signal reached hardFraction*B — the session is at/over the\n * hard ceiling and compaction was forced even if the recorded last-turn count\n * was stale-low. The boundary walk is run with a SHRUNK keep-recent budget in\n * this case so an over-budget history always yields a non-empty prefix to\n * summarize (the everything-is-\"recent\" deadlock can't strand it un-compacted).\n */\n hardForced: boolean;\n /** Index (into the active items) where the kept tail begins. */\n boundaryIndex: number;\n /**\n * The prefix items to summarize: active[0, boundaryIndex), EXCLUDING any\n * prior compaction summary (which is folded forward via `priorSummaryItem`).\n */\n prefixItems: CompactionItem[];\n /** The prior live summary item folded into this compaction, if any. */\n priorSummaryItem: CompactionItem | null;\n /** Items kept verbatim: active[boundaryIndex, end). */\n tailItems: CompactionItem[];\n};\n\nexport type PlanCompactionInput = {\n /** Active history items in position order (already excludes superseded rows). */\n items: readonly CompactionItem[];\n /**\n * Actual input tokens reported for the last model call of the previous turn.\n * Null/undefined falls back to a char/4 estimate over `items`.\n */\n lastInputTokens?: number | null;\n /** Usable input budget B = window - reserved output. */\n inputBudgetTokens: number;\n softFraction: number;\n hardFraction: number;\n keepRecentTokens: number;\n /**\n * Operator-forced compaction (the /compact command): bypass the soft-limit\n * token trigger and compact now if there is anything to summarize. The\n * boundary / nothing-to-summarize guards still apply — force never invents a\n * cut that would orphan a tool-call pair or summarize an empty prefix.\n */\n force?: boolean;\n};\n\n/**\n * Decide whether and where to compact. Pure.\n *\n * Trigger: signal tokens >= softFraction*B (soft) or hardFraction*B (hard).\n * Signal = MAX(actual last-turn input tokens, char/4 estimate of the active\n * items). The max — not \"trust the recorded count, estimate only when it's\n * null\" — is the self-heal fix: `sessions.last_input_tokens` is written ONLY\n * when a model response reports usage, so a turn that OVERFLOWS on its first\n * model call records NOTHING and the column keeps a STALE-POSITIVE value from\n * the last good turn (e.g. ~600k). Trusting that stale-low number let an\n * actually-over-budget history (>1.05M) slip under the soft limit and overflow\n * again, re-bricking with no self-heal. Taking the max means a bloated history\n * triggers compaction regardless of a stale recorded count.\n *\n * Hard force (hardFraction*B): at/over the hard ceiling we compact even if the\n * recorded count was stale-low, AND we run the boundary walk with a shrunk\n * keep-recent budget so an over-budget history always yields a non-empty prefix\n * — otherwise a history where the whole thing reads as \"recent\" (tail within\n * keepRecentTokens) would find no prefix and strand the session over budget.\n *\n * Boundary: the earliest user-message boundary whose kept tail fits the\n * (possibly shrunk) keep-recent budget. The prefix before it (minus any prior\n * summary, which is folded forward) is what gets summarized.\n */\nexport function planCompaction(input: PlanCompactionInput): CompactionPlan {\n const softLimit = Math.floor(input.inputBudgetTokens * input.softFraction);\n const hardLimit = Math.floor(input.inputBudgetTokens * input.hardFraction);\n // Signal = MAX(recorded last-turn input tokens, estimate of the actual\n // history). See the doc comment: the max is what defeats the stale-positive\n // re-brick — a bloated history wins over a stale-low recorded count.\n const recorded =\n typeof input.lastInputTokens === \"number\" && input.lastInputTokens > 0\n ? input.lastInputTokens\n : 0;\n const signalTokens = Math.max(recorded, estimateTokens(input.items));\n const hardForced = signalTokens >= hardLimit;\n\n const empty: CompactionPlan = {\n shouldCompact: false,\n reason: \"below_threshold\",\n signalTokens,\n hardForced,\n boundaryIndex: input.items.length,\n prefixItems: [],\n priorSummaryItem: null,\n tailItems: [...input.items],\n };\n\n // force (operator /compact) bypasses the budget trigger; the structural\n // guards below still run, so a forced compaction with nothing to summarize is\n // still a no-op. A hard-forced compaction is, like soft, gated by those\n // guards but additionally shrinks the keep-recent budget (below) so it can\n // actually find a prefix when the whole history is over budget.\n if (!input.force && signalTokens < softLimit) {\n return empty;\n }\n\n // Under hard pressure, cap the verbatim tail well below B so the boundary walk\n // is forced to leave a summarizable prefix even when last_input_tokens was\n // stale-low and the history exceeds the window. We keep at most HALF the\n // configured keep-recent budget (and never more than a quarter of B) — enough\n // recent context to stay coherent, little enough that a real prefix always\n // remains to compact. Soft compactions keep the full configured budget.\n const effectiveKeepRecent = hardForced\n ? Math.min(\n Math.floor(input.keepRecentTokens / 2),\n Math.floor(input.inputBudgetTokens / 4),\n )\n : input.keepRecentTokens;\n\n const boundaryIndex = findKeepBoundary(input.items, effectiveKeepRecent);\n if (boundaryIndex <= 0) {\n // No prefix to summarize (cut at the very start) — nothing to do.\n return { ...empty, reason: \"no_boundary\", boundaryIndex };\n }\n\n const prefix = input.items.slice(0, boundaryIndex);\n const tailItems = input.items.slice(boundaryIndex);\n\n // Fold the prior live summary forward: pull it out of the prefix so it is not\n // re-summarized verbatim, and hand it to the summarizer as prior context.\n let priorSummaryItem: CompactionItem | null = null;\n const prefixItems: CompactionItem[] = [];\n for (const item of prefix) {\n if (isCompactionSummary(item)) {\n priorSummaryItem = item;\n continue;\n }\n prefixItems.push(item);\n }\n\n // Nothing real to summarize. This fires both when the prefix is genuinely\n // empty AND when the prefix contains ONLY a prior summary (boundary landed\n // immediately after it): folding a summary forward over zero new items would\n // burn a summarizer call to re-wrap identical content, emit a spurious\n // compaction event, and — if the next turn is still above the soft threshold\n // — loop. The single live summary already sits at the boundary, so leaving it\n // in place is correct.\n if (prefixItems.length === 0) {\n return { ...empty, reason: \"nothing_to_summarize\", boundaryIndex };\n }\n\n return {\n shouldCompact: true,\n reason: \"compact\",\n signalTokens,\n hardForced,\n boundaryIndex,\n prefixItems,\n priorSummaryItem,\n tailItems,\n };\n}\n\n/** Extract the plain-text body of the prior summary item, if any. */\nexport function compactionSummaryText(item: CompactionItem | null): string {\n if (!item) {\n return \"\";\n }\n const content = (item as { content?: unknown }).content;\n if (typeof content === \"string\") {\n return stripSummaryPrefix(content);\n }\n if (Array.isArray(content)) {\n const text = content\n .map((part) => {\n if (part && typeof part === \"object\") {\n const t = (part as { text?: unknown }).text;\n return typeof t === \"string\" ? t : \"\";\n }\n return \"\";\n })\n .join(\"\");\n return stripSummaryPrefix(text);\n }\n return \"\";\n}\n\nfunction stripSummaryPrefix(text: string): string {\n const marker = \"SUMMARY:\";\n const idx = text.indexOf(marker);\n return idx >= 0 ? text.slice(idx + marker.length) : text;\n}\n\n/**\n * Build the synthetic summary item (a plain user message) to insert at the\n * boundary. `summaryBody` is the model-generated working-memory bridge.\n */\nexport function buildSummaryItem(summaryBody: string): CompactionItem {\n return {\n type: \"message\",\n role: \"user\",\n content: `${SUMMARY_PREFIX}${summaryBody}`,\n [COMPACTION_SUMMARY_MARKER]: true,\n };\n}\n\n/**\n * Instruction prompt for the summarizer model call. Leans on OpenGeni's durable\n * structured memory (the notebook) so the summary stays a light working-memory\n * bridge, never a place secret values get copied.\n */\nexport const SUMMARY_INSTRUCTIONS = [\n \"You are compacting the earlier part of a long-running agent conversation into a compact working-memory checkpoint so the agent can continue past the model's context limit.\",\n \"Durable facts already live in the workspace notebook and document bases (via MCP). Do NOT re-derive or copy those; summarize POINTERS, not contents.\",\n \"Capture, concisely and factually:\",\n \"- The current objective and the key decisions made so far.\",\n \"- Open blockers and anything in-progress.\",\n \"- Deployed / infrastructure state that has changed (what exists now).\",\n \"- Environment and credential facts BY REFERENCE ONLY — name the env var keys, secret names, or notebook/document ids; NEVER copy a secret value, token, key, or password.\",\n \"- Concrete next steps.\",\n \"Say explicitly that durable facts are in the notebook and that this summary lists pointers, not contents.\",\n \"Output only the summary body — no preamble, no markdown headers, plain prose or terse bullets.\",\n].join(\"\\n\");\n\n/**\n * Render the prefix items into a transcript the summarizer reads. Keeps it\n * bounded by truncating individual items; the model call itself is what\n * produces the compact result.\n */\nexport function renderPrefixTranscript(items: readonly CompactionItem[], priorSummaryText: string): string {\n const lines: string[] = [];\n if (priorSummaryText.trim().length > 0) {\n lines.push(\"PRIOR CHECKPOINT SUMMARY (fold this forward; it already replaced even older history):\");\n lines.push(priorSummaryText.trim());\n lines.push(\"\");\n lines.push(\"CONVERSATION SINCE THAT CHECKPOINT:\");\n } else {\n lines.push(\"CONVERSATION TO SUMMARIZE:\");\n }\n for (const item of items) {\n lines.push(renderItem(item));\n }\n return lines.join(\"\\n\");\n}\n\nfunction renderItem(item: CompactionItem): string {\n const type = itemType(item) ?? \"unknown\";\n if (type === \"message\") {\n const role = itemRole(item) ?? \"assistant\";\n return `[${role}] ${truncate(messageText(item), 4000)}`;\n }\n if (type === \"reasoning\") {\n return \"[reasoning] (omitted)\";\n }\n if (RESULT_TYPES.has(type)) {\n return `[tool_result] ${truncate(resultText(item), 2000)}`;\n }\n if (RESULT_TYPE_BY_CALL_TYPE[type]) {\n return `[tool_call ${type}] ${truncate(callText(item), 1000)}`;\n }\n return `[${type}] ${truncate(safeStringify(item), 1000)}`;\n}\n\nfunction messageText(item: CompactionItem): string {\n const content = (item as { content?: unknown }).content;\n if (typeof content === \"string\") {\n return content;\n }\n if (Array.isArray(content)) {\n return content\n .map((part) => {\n if (part && typeof part === \"object\") {\n const t = (part as { text?: unknown }).text;\n return typeof t === \"string\" ? t : \"\";\n }\n return \"\";\n })\n .join(\"\");\n }\n return \"\";\n}\n\nfunction resultText(item: CompactionItem): string {\n const output = (item as { output?: unknown }).output;\n if (typeof output === \"string\") {\n return output;\n }\n return safeStringify(output ?? item);\n}\n\nfunction callText(item: CompactionItem): string {\n const name = (item as { name?: unknown }).name;\n const args = (item as { arguments?: unknown }).arguments;\n const namePart = typeof name === \"string\" ? name : \"\";\n const argPart = typeof args === \"string\" ? args : safeStringify(args ?? {});\n return `${namePart} ${argPart}`.trim();\n}\n\nfunction safeStringify(value: unknown): string {\n try {\n return JSON.stringify(value);\n } catch {\n return String(value);\n }\n}\n\nfunction truncate(text: string, max: number): string {\n if (text.length <= max) {\n return text;\n }\n return `${text.slice(0, max)}… (${text.length - max} more chars)`;\n}\n\n/**\n * The summarizer model call payload: a system instruction plus the rendered\n * prefix transcript. The caller turns this into a single model request (no\n * tools, no streaming) and feeds the text result into `buildSummaryItem`.\n */\nexport function buildCompactionMessages(plan: CompactionPlan): { system: string; user: string } {\n const priorText = compactionSummaryText(plan.priorSummaryItem);\n return {\n system: SUMMARY_INSTRUCTIONS,\n user: renderPrefixTranscript(plan.prefixItems, priorText),\n };\n}\n","// packages/runtime/src/sandbox-computer.ts — the agent computer-use surface (P4.3).\n//\n// A `Computer` impl backed by xdotool (mouse/keyboard/move/click/type/key) +\n// scrot (screenshots), issued through the SAME externally-owned `session` the\n// human watches over Channel B. The agent and the human share ONE :0 display —\n// zero projection: ffmpeg reads exactly the pixels xdotool draws. Exposed to the\n// Agents SDK as a `computerTool` carried by `ComputerUseCapability`, pushed into\n// `buildAgentCapabilities` when `computerUseEnabled && desktopCapableBackend`.\n//\n// This file lives OUTSIDE the @opengeni/runtime/sandbox agent-loop-free leaf\n// (it imports `computerTool` from the @openai/agents root, which the leaf forbids)\n// and is wired into the agent-loop barrel (packages/runtime/src/index.ts).\n//\n// ── Adversarial-review fixes folded in (module 05 §Adversarial) ──────────────\n// F1 exec is OPTIONAL on every provider (Modal has only execCommand) — the\n// primitive dual-paths `session.exec ?? session.execCommand`.\n// F2 execCommand returns a FORMATTED STRING with a metadata preamble, not raw\n// stdout — screenshots read the PNG by running `base64 <path>` over the SAME\n// command primitive and stripping the banner (NOT `session.readFile`: Modal's\n// readFile path-validates against the /workspace root and THROWS\n// \"Sandbox path /tmp/…png escapes the workspace root\", so the /tmp scrot can\n// never be read → empty frame → `image_url: ''` → model 400). This mirrors\n// recording.ts/channel-a fsReadViaExec. Exit codes come from the established\n// `sandboxCommandExitCode` parser, not a `.exitCode` field.\n// F3 exec/execCommand YIELDS (does not wait) — `sandboxCommandStillRunning` is\n// treated as a retriable failure, and the input commands complete well under\n// the yield window.\n// F4 import paths: `computerTool`/`Computer` from `@openai/agents` (root, via\n// the agents-core star re-export); `Capability`/`requireBoundSession` from\n// `@openai/agents/sandbox`. `Button` is NOT exported — the union is inlined.\n// F5 scroll deltas are model PIXELS (often hundreds) — divided by a notch step\n// and clamped, NOT used as literal wheel-click `--repeat` counts.\n\nimport { computerTool, tool, type Computer, type Tool } from \"@openai/agents\";\nimport { Capability, type SandboxSessionLike } from \"@openai/agents/sandbox\";\nimport { KeyAction, PointerAction, PointerButton, type DesktopInputRequest } from \"@opengeni/agent-proto\";\n\nimport { sandboxCommandExitCode, sandboxCommandOutput, sandboxCommandStillRunning } from \"./index\";\n// `stripExecBanner` is the SAME pure helper recording.ts uses to recover the raw\n// command body from Modal's execCommand banner (\"…Output:\\n<body>\"). Imported from\n// the agent-loop-free leaf (importing a pure parser FROM the leaf is allowed — the\n// leaf boundary only forbids the leaf importing the agent loop, not the reverse).\nimport { stripExecBanner } from \"./sandbox\";\n\n// `requireBoundSession` lives in @openai/agents-core/sandbox/capabilities/base\n// but is NOT re-exported from the public @openai/agents/sandbox barrel, so we\n// inline the trivial bound-session guard (parity with the SDK's own helper).\nfunction requireBoundSession(capabilityType: string, session?: SandboxSessionLike): SandboxSessionLike {\n if (!session) {\n throw new ComputerUnavailableError(`capability \"${capabilityType}\" used before bind(session)`);\n }\n return session;\n}\n\n// `Button` is intentionally NOT imported (it is not a public export, F4) — the\n// union is inlined and kept in lockstep with @openai/agents-core/computer.d.ts.\ntype ComputerButton = \"left\" | \"right\" | \"wheel\" | \"back\" | \"forward\";\n\nconst DEFAULT_DISPLAY = \":0\";\nconst DEFAULT_DIMENSIONS: [number, number] = [1280, 800];\n// Commands must complete well under this (F3): xdotool/scrot of a 1280x800 PNG is\n// sub-second; the wait gives headroom on a cold gVisor box without masking a wedge.\nconst ACTION_YIELD_MS = 15_000;\n// Model scroll deltas are pixels (F5); one wheel \"notch\" ≈ this many pixels. e2b\n// uses a similar divisor. Clamp keeps a runaway delta from spamming the wheel.\nconst SCROLL_NOTCH_PIXELS = 100;\nconst SCROLL_MAX_CLICKS = 15;\n// screenshot() never hands the model an empty image_url (the SDK turns \"\" into\n// `image_url: ''`, which the model API 400s). A cold/not-yet-painting :0 can yield\n// a zero-byte frame on the first scrot; bounded retries with a short pause let a\n// momentarily-unpainted-but-live display self-heal before we FAIL LOUD.\nconst SCREENSHOT_MAX_ATTEMPTS = 3;\nconst SCREENSHOT_RETRY_DELAY_MS = 400;\n\nexport type SandboxComputerOptions = {\n display?: string; // \":0\"\n dimensions?: [number, number]; // must match the Xvfb geometry\n runAs?: string; // provider runAs (modal/docker: \"sandbox\"); undefined otherwise\n typeDelayMs?: number; // xdotool type --delay (default 12ms)\n readOnly?: boolean; // when true, every WRITE action throws ComputerReadOnlyError\n screenshotTmpDir?: string; // \"/tmp\"\n};\n\n// X keysym map for keypress(): model key names → xdotool keysyms.\nconst KEYSYM: Record<string, string> = {\n ctrl: \"ctrl\", control: \"ctrl\", alt: \"alt\", option: \"alt\", shift: \"shift\",\n cmd: \"super\", meta: \"super\", win: \"super\", super: \"super\",\n enter: \"Return\", return: \"Return\", tab: \"Tab\", esc: \"Escape\", escape: \"Escape\",\n backspace: \"BackSpace\", delete: \"Delete\", space: \"space\",\n up: \"Up\", down: \"Down\", left: \"Left\", right: \"Right\",\n pageup: \"Prior\", pagedown: \"Next\", home: \"Home\", end: \"End\",\n};\nfunction toKeysym(k: string): string {\n const low = k.toLowerCase();\n if (KEYSYM[low]) return KEYSYM[low];\n if (/^f([1-9]|1[0-2])$/.test(low)) return low.toUpperCase();\n return low.length === 1 ? low : k;\n}\nconst BUTTON_NUM: Record<ComputerButton, number> = { left: 1, wheel: 2, right: 3, back: 8, forward: 9 };\n\n// The structural slice of a provider session computer-use drives. exec and\n// execCommand are optional because the SDK's SandboxSessionLike leaves them\n// optional (Modal implements execCommand, not exec — F1). readFile is intentionally\n// NOT in this type: screenshots read the /tmp PNG via `base64 <path>` over\n// exec/execCommand (readFile path-validates against /workspace and rejects /tmp).\ntype ExecResultLike = { output?: string; stdout?: string; stderr?: string; exitCode?: number | null; sessionId?: number };\ntype ComputerSession = {\n exec?: (args: { cmd: string; runAs?: string; yieldTimeMs?: number; maxOutputTokens?: number }) => Promise<ExecResultLike>;\n execCommand?: (args: { cmd: string; runAs?: string; yieldTimeMs?: number; maxOutputTokens?: number }) => Promise<string>;\n};\n\n/** No exec/execCommand on the session, or the display is not up. */\nexport class ComputerUnavailableError extends Error {\n constructor(message: string) { super(message); this.name = \"ComputerUnavailableError\"; }\n}\n/** A write action attempted while readOnly. */\nexport class ComputerReadOnlyError extends Error {\n constructor() { super(\"computer-use is read-only — write actions are disabled\"); this.name = \"ComputerReadOnlyError\"; }\n}\n/** A nonzero xdotool/scrot exit, OR a command that did not finish before the\n * yield window (F3 — \"still running\" is a failure, not a silent success). */\nexport class ComputerActionError extends Error {\n constructor(public cmd: string, public exitCode: number, public stderr: string) {\n super(`computer action failed (${exitCode}): ${cmd}${stderr ? `\\n${stderr}` : \"\"}`);\n this.name = \"ComputerActionError\";\n }\n}\n\n/**\n * The Computer the agent drives. Every action issues ONE shell line through the\n * externally-owned session (exec ?? execCommand, F1), prefixed with the display.\n * screenshot() scrots to a /tmp file and reads the RAW bytes by running\n * `base64 <path>` over the SAME command primitive and stripping the banner — NOT\n * `session.readFile` (Modal's readFile path-validates against /workspace and rejects\n * /tmp with \"escapes the workspace root\", which would yield an empty frame and 400\n * the model). The base64-over-exec path is /tmp-readable and binary-safe.\n */\nexport class SandboxComputer implements Computer {\n readonly environment = \"ubuntu\" as const;\n readonly dimensions: [number, number];\n private session: ComputerSession;\n private readonly display: string;\n private readonly runAs?: string;\n private readonly typeDelayMs: number;\n private readonly readOnly: boolean;\n private readonly tmp: string;\n\n constructor(session: SandboxSessionLike, opts: SandboxComputerOptions = {}) {\n this.session = session as unknown as ComputerSession;\n this.display = opts.display ?? DEFAULT_DISPLAY;\n this.dimensions = opts.dimensions ?? DEFAULT_DIMENSIONS;\n if (opts.runAs !== undefined) {\n this.runAs = opts.runAs;\n }\n this.typeDelayMs = opts.typeDelayMs ?? 12;\n this.readOnly = opts.readOnly ?? false;\n this.tmp = opts.screenshotTmpDir ?? \"/tmp\";\n }\n\n /** Rebind to a freshly resumed-by-id session after a box rollover / re-establish. */\n rebind(session: SandboxSessionLike) { this.session = session as unknown as ComputerSession; }\n\n // The single command primitive. Dual-paths exec/execCommand (F1), then uses the\n // established string-aware parsers (F2/F3): exitCode from the preamble, and\n // \"still running\" → a retriable failure. Returns the command OUTPUT body.\n private async x(cmd: string): Promise<string> {\n const args = {\n cmd: `DISPLAY=${this.display} ${cmd}`,\n ...(this.runAs ? { runAs: this.runAs } : {}),\n yieldTimeMs: ACTION_YIELD_MS,\n maxOutputTokens: 4_000,\n };\n let result: ExecResultLike | string;\n if (typeof this.session.exec === \"function\") {\n result = await this.session.exec(args);\n } else if (typeof this.session.execCommand === \"function\") {\n result = await this.session.execCommand(args);\n } else {\n throw new ComputerUnavailableError(\"session cannot run commands (no exec/execCommand)\");\n }\n const output = sandboxCommandOutput(result);\n if (sandboxCommandStillRunning(result)) {\n // F3: the command exceeded the yield window. WARN AND RETURN rather than\n // throw. Throwing here causes the SDK's catch in `_runComputerActionAndScreenshot`\n // to set output='' and build `{image_url:\"\"}` → Azure 400. By returning\n // instead, the SDK proceeds past the action loop and calls computer.screenshot()\n // so the model gets the REAL current frame for its next step.\n //\n // screenshot()'s FAIL-LOUD + retry contract is preserved: if scrot itself\n // times out (very unlikely at 15 s), x() returns here, readScreenshotBytes\n // produces empty bytes, and the retry loop eventually throws. The wire-level\n // backstop in computerCallNormalizingFetch is also in place as a second net.\n console.warn(\n `[SandboxComputer] action command did not finish before the ${ACTION_YIELD_MS}ms yield window — proceeding to screenshot: ${cmd}`,\n );\n return output;\n }\n const exitCode = sandboxCommandExitCode(result);\n if (exitCode !== null && exitCode !== 0) {\n throw new ComputerActionError(cmd, exitCode, output);\n }\n return output;\n }\n\n private guardWrite() {\n if (this.readOnly) throw new ComputerReadOnlyError();\n }\n private shq(s: string): string {\n return `'${s.replace(/'/g, `'\\\\''`)}'`;\n }\n\n async screenshot(): Promise<string> {\n // F2: scrot to a /tmp file, then read the RAW PNG bytes by running `base64\n // <path>` over the SAME command primitive (exec ?? execCommand) and stripping\n // the banner — NOT `session.readFile`. On Modal, readFile path-validates the\n // path against the /workspace root and THROWS for /tmp (\"Sandbox path\n // /tmp/og-shot-*.png escapes the workspace root\"), so the scrot could never be\n // read → empty frame → `image_url: ''` → the model 400s. The base64-over-exec\n // mechanism (mirroring recording.ts readRecordingBytes + channel-a\n // fsReadViaExec) is /tmp-readable and binary-safe. We do NOT use execCommand's\n // body via the `this.x()` parser — that drops the execCommand string body; the\n // banner is stripped explicitly here so the base64 payload survives intact.\n //\n // CRITICAL CONTRACT: this NEVER returns an empty string. The Agents SDK builds\n // the model-facing image as `data:image/png;base64,${output}` — so an empty\n // `output` becomes `image_url: ''`, which the model API rejects with\n // \"400 Invalid input[N].output.image_url, expected a valid URL\" and kills the\n // turn. An empty/failed frame is therefore a THROW (a clear action failure the\n // SDK surfaces), never a silent \"\". We also self-heal a transient cold-display\n // frame: bounded retries with a short wait between attempts, so a :0 that is up\n // but momentarily not painting (XFCE/dbus still warming) recovers without\n // failing the turn.\n let lastError: unknown;\n for (let attempt = 0; attempt < SCREENSHOT_MAX_ATTEMPTS; attempt++) {\n if (attempt > 0) {\n await new Promise((r) => setTimeout(r, SCREENSHOT_RETRY_DELAY_MS));\n }\n const f = `${this.tmp}/og-shot-${Date.now()}-${Math.random().toString(36).slice(2)}.png`;\n try {\n await this.x(`scrot --pointer --overwrite ${f}`);\n const bytes = await this.readScreenshotBytes(f);\n if (bytes.length === 0) {\n // A cold/not-yet-painting :0 yields a zero-byte frame. Retry rather than\n // hand the model an empty image_url; throw on the final attempt.\n throw new ComputerUnavailableError(\"scrot produced an empty screenshot (display not up?)\");\n }\n return Buffer.from(bytes).toString(\"base64\");\n } catch (error) {\n lastError = error;\n } finally {\n // Best-effort cleanup on every attempt (success OR failure); never mask the\n // screenshot result.\n await this.x(`rm -f ${f}`).catch(() => undefined);\n }\n }\n // Exhausted retries: FAIL LOUD. A clear throw is the only acceptable outcome —\n // returning \"\" here would surface to the model as an invalid empty image_url.\n if (lastError instanceof Error) {\n throw lastError;\n }\n throw new ComputerUnavailableError(\"scrot produced an empty screenshot (display not up?)\");\n }\n\n // Read the screenshot PNG bytes by base64-ing the absolute /tmp path through the\n // SAME command primitive (exec ?? execCommand) — NOT `session.readFile` (Modal\n // path-validates against /workspace and rejects /tmp) and NOT `this.x()` (its\n // `sandboxCommandOutput` parser drops the execCommand STRING body, returning \"\"\n // — only the exec-object path has a structured body). We capture the RAW result,\n // strip the execCommand banner (\"…Output:\\n<base64>\"), strip whitespace, and\n // decode. Binary-safe: base64 of the scrot is plain ASCII over stdout, no\n // truncation (maxOutputTokens:null), mirroring recording.ts readRecordingBytes.\n private async readScreenshotBytes(path: string): Promise<Uint8Array> {\n const args = {\n cmd: `DISPLAY=${this.display} base64 ${path}`,\n ...(this.runAs ? { runAs: this.runAs } : {}),\n yieldTimeMs: ACTION_YIELD_MS,\n // null disables the provider's output truncation so a full-screen PNG's\n // base64 is never clipped (the SDK's truncateOutput passes through on null).\n maxOutputTokens: null as unknown as number,\n };\n let raw: string;\n if (typeof this.session.exec === \"function\") {\n // The exec-object path exposes a structured stdout/output body.\n raw = sandboxCommandOutput(await this.session.exec(args));\n } else if (typeof this.session.execCommand === \"function\") {\n // execCommand returns the formatted STRING — strip the banner to recover the\n // base64 body (sandboxCommandOutput would drop it for the string form).\n raw = stripExecBanner(await this.session.execCommand(args));\n } else {\n throw new ComputerUnavailableError(\"session cannot run commands (no exec/execCommand) — screenshots unavailable\");\n }\n const b64 = raw.replace(/\\s+/g, \"\");\n if (b64.length === 0) return new Uint8Array();\n return Uint8Array.from(Buffer.from(b64, \"base64\"));\n }\n\n async click(xp: number, yp: number, button: ComputerButton) {\n this.guardWrite();\n await this.x(`xdotool mousemove --sync ${xp} ${yp} click ${BUTTON_NUM[button] ?? 1}`);\n }\n async doubleClick(xp: number, yp: number) {\n this.guardWrite();\n await this.x(`xdotool mousemove --sync ${xp} ${yp} click --repeat 2 --delay 60 1`);\n }\n async move(xp: number, yp: number) {\n this.guardWrite();\n await this.x(`xdotool mousemove --sync ${xp} ${yp}`);\n }\n async scroll(xp: number, yp: number, sx: number, sy: number) {\n this.guardWrite();\n // F5: model deltas are PIXELS — convert to wheel notches, clamp.\n const notches = (px: number): number => Math.min(SCROLL_MAX_CLICKS, Math.max(0, Math.round(Math.abs(px) / SCROLL_NOTCH_PIXELS)));\n const vBtn = sy < 0 ? 4 : 5;\n const hBtn = sx < 0 ? 6 : 7;\n const vN = notches(sy);\n const hN = notches(sx);\n let cmd = `xdotool mousemove --sync ${xp} ${yp}`;\n if (vN) cmd += ` click --repeat ${vN} ${vBtn}`;\n if (hN) cmd += ` click --repeat ${hN} ${hBtn}`;\n await this.x(cmd);\n }\n async type(text: string) {\n this.guardWrite();\n await this.x(`xdotool type --delay ${this.typeDelayMs} -- ${this.shq(text)}`);\n }\n async keypress(keys: string[]) {\n this.guardWrite();\n const combo = keys.map(toKeysym).join(\"+\");\n await this.x(`xdotool key -- ${this.shq(combo)}`);\n }\n async drag(path: [number, number][]) {\n this.guardWrite();\n if (path.length === 0) return;\n const [sx0, sy0] = path[0]!;\n let cmd = `xdotool mousemove --sync ${sx0} ${sy0} mousedown 1`;\n for (const [px, py] of path.slice(1)) cmd += ` mousemove --sync ${px} ${py}`;\n cmd += ` mouseup 1`;\n await this.x(cmd);\n }\n async wait() {\n await new Promise((r) => setTimeout(r, 1000));\n }\n}\n\n// ── The native-desktop computer (self-hosted / macOS) ────────────────────────\n//\n// `SandboxComputer` drives the desktop by shelling out to xdotool/scrot over the\n// session's `exec` — which needs those X utilities installed in the box image and\n// only works under X11. A SELF-HOSTED machine (macOS OR bring-your-own Linux) has\n// neither guarantee, so it drives the desktop NATIVELY over the control plane: the\n// Rust agent injects input via CGEvent (macOS) / XTEST (Linux) and captures via\n// ScreenCaptureKit / x11, exposed as the two `SelfhostedSession` ops below. No\n// xdotool/scrot dependency; works on macOS.\n\n/** The structural slice of a self-hosted session the native computer drives — the\n * two control-plane ops added in session.ts. Kept structural (NOT an import of\n * `SelfhostedSession`) so this agent-loop file never hard-couples to the sandbox\n * leaf; the duck-typed `isNativeDesktopSession` probe (below) selects on it. */\nexport type NativeDesktopSession = {\n desktopInput(event: DesktopInputRequest[\"event\"]): Promise<void>;\n screenshot(): Promise<{ png: Uint8Array; width: number; height: number }>;\n};\n\n/** Model `Button` → wire `PointerButton`. The proto has no back/forward button, so\n * those degrade to UNSPECIFIED (the agent ignores an unmapped button rather than\n * mis-clicking). A total record so indexing is exhaustive. */\nconst POINTER_BUTTON: Record<ComputerButton, PointerButton> = {\n left: PointerButton.POINTER_BUTTON_LEFT,\n right: PointerButton.POINTER_BUTTON_RIGHT,\n wheel: PointerButton.POINTER_BUTTON_MIDDLE,\n back: PointerButton.POINTER_BUTTON_UNSPECIFIED,\n forward: PointerButton.POINTER_BUTTON_UNSPECIFIED,\n};\n\nexport type NativeDesktopComputerOptions = {\n dimensions?: [number, number]; // the display geometry (must match the capture size)\n environment?: NonNullable<Computer[\"environment\"]>; // \"ubuntu\" (default) | \"mac\" | ...; model uses it for OS key conventions\n readOnly?: boolean; // when true, every WRITE action throws ComputerReadOnlyError\n};\n\n/**\n * A `Computer` that drives a SELF-HOSTED machine's OWN desktop NATIVELY over the\n * control plane (`desktopInput` inject + `screenshot` capture on the bound\n * `SelfhostedSession`) instead of xdotool/scrot over `exec`. Consent + epoch are\n * enforced AGENT-side, so an unconsented inject surfaces the session's mapped\n * control error.\n *\n * screenshot() returns raw base64 with NO data-URL prefix — the EXACT contract of\n * `SandboxComputer.screenshot`: the Agents SDK wraps it as\n * `data:image/png;base64,${output}`, so an empty string would become\n * `image_url: ''` and 400 the model turn. An empty PNG therefore THROWS\n * `ComputerUnavailableError` (mirroring SandboxComputer's empty-guard) — the model\n * never receives an empty image_url.\n */\nexport class NativeDesktopComputer implements Computer {\n readonly environment: NonNullable<Computer[\"environment\"]>;\n readonly dimensions: [number, number];\n private session: NativeDesktopSession;\n private readonly readOnly: boolean;\n\n constructor(session: NativeDesktopSession, opts: NativeDesktopComputerOptions = {}) {\n this.session = session;\n this.dimensions = opts.dimensions ?? DEFAULT_DIMENSIONS;\n // Default \"ubuntu\" (self-hosted Linux is the near-term target); a macOS session\n // should pass \"mac\" so the model uses ⌘-based shortcuts — see the coordinate TODO.\n this.environment = opts.environment ?? \"ubuntu\";\n this.readOnly = opts.readOnly ?? false;\n }\n\n /** Rebind to a freshly resumed-by-id session after a box rollover / re-establish. */\n rebind(session: NativeDesktopSession) { this.session = session; }\n\n private guardWrite() {\n if (this.readOnly) throw new ComputerReadOnlyError();\n }\n\n private async pointer(x: number, y: number, action: PointerAction, button: PointerButton): Promise<void> {\n // COORDINATE SEAM — TODO(verify e2e on macOS): the model computes x/y against the\n // pixels of the screenshot it just saw, and the agent's macOS CGEvent inject\n // treats x/y as raw screen coordinates. On a Retina Mac, ScreenCaptureKit may\n // capture at 2× the logical POINT space while CGEvent expects logical points — a\n // potential 2× mismatch between the coords the model derives and the coords the\n // inject applies. This MUST be measured on a real Retina Mac (compare the\n // screenshot's reported width/height against the logical display bounds) before\n // any DPR scaling is added. Do NOT add scaling speculatively. Self-hosted Linux\n // (XTEST/x11) is 1:1 and unaffected.\n await this.session.desktopInput({ $case: \"pointer\", pointer: { x, y, action, button } });\n }\n\n async screenshot(): Promise<string> {\n // CRITICAL CONTRACT (mirrors SandboxComputer.screenshot): NEVER return \"\". The\n // Agents SDK builds the model image as `data:image/png;base64,${output}`; an\n // empty output → `image_url: ''` → the model API 400s and kills the turn. A\n // missing/empty frame is therefore a THROW, never a silent \"\". Native capture\n // (ScreenCaptureKit / x11) does not have the cold-scrot warm-up the xdotool path\n // retries around, so a single capture + a hard empty-guard is sufficient.\n const { png } = await this.session.screenshot();\n if (png.length === 0) {\n throw new ComputerUnavailableError(\"native desktop screenshot returned an empty frame (display not up?)\");\n }\n return Buffer.from(png).toString(\"base64\");\n }\n\n async click(x: number, y: number, button: ComputerButton) {\n this.guardWrite();\n await this.pointer(x, y, PointerAction.POINTER_ACTION_CLICK, POINTER_BUTTON[button] ?? PointerButton.POINTER_BUTTON_LEFT);\n }\n async doubleClick(x: number, y: number) {\n this.guardWrite();\n await this.pointer(x, y, PointerAction.POINTER_ACTION_DOUBLE_CLICK, PointerButton.POINTER_BUTTON_LEFT);\n }\n async move(x: number, y: number) {\n this.guardWrite();\n await this.pointer(x, y, PointerAction.POINTER_ACTION_MOVE, PointerButton.POINTER_BUTTON_UNSPECIFIED);\n }\n async scroll(x: number, y: number, sx: number, sy: number) {\n this.guardWrite();\n // The model's scroll deltas are PIXELS — forward them straight to the agent as a\n // ScrollEvent{x,y,deltaX,deltaY} and let the native inject translate to wheel\n // events per platform. No xdotool \"notch\" quantization here (that is an\n // xdotool-specific artifact); the agent owns the platform-appropriate scaling.\n await this.session.desktopInput({ $case: \"scroll\", scroll: { x, y, deltaX: sx, deltaY: sy } });\n }\n async type(text: string) {\n this.guardWrite();\n // A literal text burst: isText:true tells the agent to type the string verbatim\n // (Unicode-aware) rather than interpret it as a key name.\n await this.session.desktopInput({ $case: \"key\", key: { key: text, isText: true, action: KeyAction.KEY_ACTION_PRESS } });\n }\n async keypress(keys: string[]) {\n this.guardWrite();\n // A chord (\"ctrl+c\") as ONE non-text KeyEvent (isText:false ⇒ interpret as key\n // names). We send the model's PLATFORM-INDEPENDENT key names joined with \"+\" —\n // NOT xdotool X keysyms (SandboxComputer's toKeysym maps to \"Return\"/\"super\"/\n // \"Prior\", which are X-specific and wrong for the macOS CGEvent path). The agent\n // owns the per-platform key-name → keycode mapping (the KeyEvent.key contract).\n await this.session.desktopInput({ $case: \"key\", key: { key: keys.join(\"+\"), isText: false, action: KeyAction.KEY_ACTION_PRESS } });\n }\n async drag(path: [number, number][]) {\n this.guardWrite();\n if (path.length === 0) return;\n // Press at the start, move through each waypoint with the button held, release at\n // the last point. The agent tracks button state across the DOWN → MOVE… → UP.\n const [sx, sy] = path[0]!;\n await this.pointer(sx, sy, PointerAction.POINTER_ACTION_DOWN, PointerButton.POINTER_BUTTON_LEFT);\n for (const [px, py] of path.slice(1)) {\n await this.pointer(px, py, PointerAction.POINTER_ACTION_MOVE, PointerButton.POINTER_BUTTON_LEFT);\n }\n const [ex, ey] = path[path.length - 1]!;\n await this.pointer(ex, ey, PointerAction.POINTER_ACTION_UP, PointerButton.POINTER_BUTTON_LEFT);\n }\n async wait() {\n await new Promise((r) => setTimeout(r, 1000));\n }\n}\n\n/**\n * Backend-aware SELECTION discriminator: a SELF-HOSTED session exposes the two\n * native control-plane ops (`desktopInput` + `screenshot`); a MODAL session does\n * not (it drives the desktop via xdotool/scrot over `exec`). Duck-typing on those\n * two methods keeps this file from hard-importing `SelfhostedSession` (avoiding an\n * agent-loop ↔ sandbox-leaf import coupling) and is future-proof: any backend that\n * grows native inject/capture is picked up automatically.\n */\nexport function isNativeDesktopSession(session: SandboxSessionLike): session is SandboxSessionLike & NativeDesktopSession {\n const s = session as Partial<NativeDesktopSession>;\n return typeof s.desktopInput === \"function\" && typeof s.screenshot === \"function\";\n}\n\n// ── Function-transport (codex / text backend) computer tools ─────────────────\n//\n// The SDK emits computer-use ONLY as the HOSTED `computer_use_preview` tool, which\n// the codex / ChatGPT backend rejects (it accepts only function/custom/web_search\n// tool types) — so on codex the hosted tool is unusable and the agent has nothing\n// to drive the desktop with. We mirror EXACTLY how the SDK's filesystem capability\n// degrades `view_image` for the text transport: when the bound model does NOT\n// support the structured tool-output transport, emit a set of FUNCTION tools that\n// route to the SAME bound `Computer`, and hand the model the screen by rendering\n// the screenshot image-output as a text-transport data URL — the identical two-step\n// `imageOutputFromBytes` → `renderImageForTextTransport` the SDK's text `view_image`\n// uses. Those three helpers are NOT public exports of `@openai/agents` /\n// `@openai/agents/sandbox` (they live in the SDK's private capabilities/transport +\n// shared/media modules, unreachable via the package `exports` map), so — mirroring\n// selfhosted/session.ts's local `sniffImageMediaType` — the three tiny pure helpers\n// are reimplemented here in lockstep with the SDK.\n\n/** The SDK's tool-output image shape (@openai/agents-core shared/media `ToolOutputImage`). */\ntype ToolOutputImage = { type: \"image\"; image: { data: Uint8Array; mediaType: string } };\n\n/** Magic-byte image sniff, in lockstep with the SDK's `sniffImageMediaType`\n * (shared/media). Screenshots are always PNG (scrot / ScreenCaptureKit / x11), so\n * an unrecognized header defaults to image/png rather than failing the frame. */\nfunction sniffScreenshotMediaType(bytes: Uint8Array): string {\n if (bytes[0] === 0x89 && bytes[1] === 0x50 && bytes[2] === 0x4e && bytes[3] === 0x47) return \"image/png\";\n if (bytes[0] === 0xff && bytes[1] === 0xd8 && bytes[2] === 0xff) return \"image/jpeg\";\n if (bytes[0] === 0x47 && bytes[1] === 0x49 && bytes[2] === 0x46 && bytes[3] === 0x38) return \"image/gif\";\n if (\n bytes[0] === 0x52 && bytes[1] === 0x49 && bytes[2] === 0x46 && bytes[3] === 0x46 &&\n bytes[8] === 0x57 && bytes[9] === 0x45 && bytes[10] === 0x42 && bytes[11] === 0x50\n ) return \"image/webp\";\n return \"image/png\";\n}\n\n/** Build the SDK `ToolOutputImage` from raw screenshot bytes — the structured shape\n * the SDK's `imageOutputFromBytes` produces (`{type:'image', image:{data,mediaType}}`). */\nfunction imageOutputFromScreenshotBytes(bytes: Uint8Array): ToolOutputImage {\n return { type: \"image\", image: { data: Uint8Array.from(bytes), mediaType: sniffScreenshotMediaType(bytes) } };\n}\n\n/** Render an image tool-output as a text-transport string, in lockstep with the\n * SDK's private `renderImageForTextTransport` (capabilities/filesystem). Our image\n * output always carries `data` as bytes, so it becomes a `data:<mediaType>;base64,…`\n * URL — the exact form the text-backend `view_image` hands the model. */\nfunction renderImageForTextTransport(output: ToolOutputImage | string): string {\n if (typeof output === \"string\") return output;\n const { image } = output;\n const mediaType = typeof image.mediaType === \"string\" ? image.mediaType : \"application/octet-stream\";\n return `data:${mediaType};base64,${Buffer.from(image.data).toString(\"base64\")}`;\n}\n\n/** Whether the bound model supports the structured tool-output transport, in\n * lockstep with the SDK's private `supportsStructuredToolOutputTransport`\n * (capabilities/transport): a ChatCompletions-family model — and an UNBOUND model\n * (undefined) — does NOT, so it gets the function tools; every other model keeps\n * the hosted `computer_use_preview` tool. The codex neutralize trick in index.ts\n * drops `_modelInstance`, so this returns false there and the function tools win. */\nfunction supportsStructuredToolOutputTransport(modelInstance: unknown): boolean {\n if (!modelInstance) return false;\n const constructorName =\n typeof modelInstance === \"object\" && modelInstance && typeof (modelInstance as { constructor?: unknown }).constructor === \"function\"\n ? ((modelInstance as { constructor: { name?: string } }).constructor.name ?? \"\")\n : \"\";\n return !constructorName.includes(\"ChatCompletions\");\n}\n\nconst COMPUTER_READ_ONLY_MESSAGE =\n \"computer-use is read-only for this session — click, double_click, move, scroll, type, keypress, and drag are disabled. Call computer_screenshot to observe the desktop.\";\n\n// The two coordinate properties every pointer tool shares. Raw JSON schema (NOT\n// zod: zod is not a @opengeni/runtime dependency) with `strict:false`, mirroring the\n// SDK's own `apply_patch` function-tool schema style.\nconst COORD_PROPS = {\n x: { type: \"integer\", description: \"X coordinate in the pixels of the most recent computer_screenshot\" },\n y: { type: \"integer\", description: \"Y coordinate in the pixels of the most recent computer_screenshot\" },\n} as const;\n\nfunction objectSchema(properties: Record<string, unknown>, required: string[]): Record<string, unknown> {\n return { type: \"object\", properties, required, additionalProperties: false };\n}\n\n/**\n * The FUNCTION-transport computer tools for the codex / text backend, each routing\n * to the SAME bound `Computer` the hosted `computer_use_preview` tool would drive.\n * `computer_screenshot` hands the model the desktop two ways, selected by\n * `imageFunctionResults`:\n * • false (chat-completions providers, the default) → the text-transport\n * `data:image/png;base64,…` URL (imageOutputFromBytes → renderImageForTextTransport,\n * the SDK's text `view_image` path) — those backends can't read structured image\n * tool results.\n * • true (the codex/ChatGPT backend) → the structured `{type:'image'}` tool output,\n * which agents-core normalizes into an `input_image` content item inside the\n * function_call_output — the codex /responses backend accepts and SEES it (a text\n * data-URL there is just unreadable text). See index.ts for why it's on there.\n * Write tools return a concise confirmation; when read-only they return\n * {@link COMPUTER_READ_ONLY_MESSAGE} instead of throwing, and any action error is\n * returned as a string so a failed action never kills the turn. Exported so it can be\n * unit-tested against a fake `Computer`.\n */\nexport function computerFunctionTools(\n computer: Computer,\n readOnly: boolean,\n needsApproval?: ComputerUseArgs[\"needsApproval\"],\n imageFunctionResults = false,\n): Tool<unknown>[] {\n const approval = needsApproval !== undefined ? { needsApproval: needsApproval as never } : {};\n // Perform a WRITE action, surfacing read-only / failures as a model-readable\n // string rather than an uncaught throw (an uncaught throw becomes a tool error\n // the backend may 400 on, or kills the step).\n const write = async (confirmation: string, action: () => void | Promise<void>): Promise<string> => {\n if (readOnly) return COMPUTER_READ_ONLY_MESSAGE;\n try {\n await action();\n return confirmation;\n } catch (error) {\n if (error instanceof ComputerReadOnlyError) return COMPUTER_READ_ONLY_MESSAGE;\n return `computer action failed: ${error instanceof Error ? error.message : String(error)}`;\n }\n };\n\n return [\n tool({\n name: \"computer_screenshot\",\n description:\n \"Capture the current desktop and return it as an image. Call this FIRST and again after each action — all coordinates for click/move/scroll/drag are pixels of the most recent screenshot.\",\n parameters: objectSchema({}, []) as never,\n strict: false,\n execute: async () => {\n // screenshot() returns raw base64 PNG and NEVER an empty string (it throws\n // instead), so the model can't receive an empty image_url.\n const b64 = await computer.screenshot();\n const bytes = Uint8Array.from(Buffer.from(b64, \"base64\"));\n const image = imageOutputFromScreenshotBytes(bytes);\n // On the codex backend return the structured image output so the model SEES\n // the desktop (agents-core normalizes {type:'image'} → an input_image data-URL\n // content item in the function_call_output); chat-completions providers get\n // the text data-URL string they expect.\n return imageFunctionResults ? image : renderImageForTextTransport(image);\n },\n }),\n tool({\n name: \"computer_click\",\n description:\n \"Click the mouse at (x, y). `button` is one of left|right|wheel|back|forward (default left). Take a computer_screenshot first to find coordinates.\",\n parameters: objectSchema(\n { ...COORD_PROPS, button: { type: \"string\", enum: [\"left\", \"right\", \"wheel\", \"back\", \"forward\"], description: \"Mouse button; defaults to left\" } },\n [\"x\", \"y\"],\n ) as never,\n strict: false,\n ...approval,\n execute: async (input) => {\n const { x, y, button } = input as { x: number; y: number; button?: ComputerButton };\n return write(`clicked ${button ?? \"left\"} at (${x}, ${y})`, () => computer.click(x, y, button ?? \"left\"));\n },\n }),\n tool({\n name: \"computer_double_click\",\n description: \"Double-click the left mouse button at (x, y). Take a computer_screenshot first to find coordinates.\",\n parameters: objectSchema({ ...COORD_PROPS }, [\"x\", \"y\"]) as never,\n strict: false,\n ...approval,\n execute: async (input) => {\n const { x, y } = input as { x: number; y: number };\n return write(`double-clicked at (${x}, ${y})`, () => computer.doubleClick(x, y));\n },\n }),\n tool({\n name: \"computer_move\",\n description: \"Move the mouse cursor to (x, y) without clicking.\",\n parameters: objectSchema({ ...COORD_PROPS }, [\"x\", \"y\"]) as never,\n strict: false,\n ...approval,\n execute: async (input) => {\n const { x, y } = input as { x: number; y: number };\n return write(`moved to (${x}, ${y})`, () => computer.move(x, y));\n },\n }),\n tool({\n name: \"computer_scroll\",\n description:\n \"Scroll at (x, y) by scroll_x / scroll_y pixels (positive scroll_y scrolls down, negative up; positive scroll_x scrolls right).\",\n parameters: objectSchema(\n {\n ...COORD_PROPS,\n scroll_x: { type: \"integer\", description: \"Horizontal scroll amount in pixels (positive = right)\" },\n scroll_y: { type: \"integer\", description: \"Vertical scroll amount in pixels (positive = down)\" },\n },\n [\"x\", \"y\", \"scroll_x\", \"scroll_y\"],\n ) as never,\n strict: false,\n ...approval,\n execute: async (input) => {\n const { x, y, scroll_x, scroll_y } = input as { x: number; y: number; scroll_x: number; scroll_y: number };\n return write(`scrolled (${scroll_x}, ${scroll_y}) at (${x}, ${y})`, () => computer.scroll(x, y, scroll_x, scroll_y));\n },\n }),\n tool({\n name: \"computer_type\",\n description: \"Type a literal text string at the current keyboard focus. Click the target field first.\",\n parameters: objectSchema({ text: { type: \"string\", description: \"The literal text to type\" } }, [\"text\"]) as never,\n strict: false,\n ...approval,\n execute: async (input) => {\n const { text } = input as { text: string };\n return write(`typed ${text.length} character(s)`, () => computer.type(text));\n },\n }),\n tool({\n name: \"computer_keypress\",\n description:\n 'Press a key or chord. `keys` is an ordered list pressed together, e.g. [\"ctrl\",\"c\"] or [\"Enter\"]. Use key names (ctrl, alt, shift, cmd, enter, tab, esc, arrows…), not characters.',\n parameters: objectSchema(\n { keys: { type: \"array\", items: { type: \"string\" }, description: \"Keys pressed together as a chord\" } },\n [\"keys\"],\n ) as never,\n strict: false,\n ...approval,\n execute: async (input) => {\n const { keys } = input as { keys: string[] };\n return write(`pressed ${keys.join(\"+\")}`, () => computer.keypress(keys));\n },\n }),\n tool({\n name: \"computer_drag\",\n description:\n \"Drag the left mouse button along a path of points. `path` is an ordered list of {x, y} pixels; the button is pressed at the first point, moved through each, and released at the last.\",\n parameters: objectSchema(\n {\n path: {\n type: \"array\",\n description: \"Ordered list of points to drag through\",\n items: {\n type: \"object\",\n properties: { x: { type: \"integer\" }, y: { type: \"integer\" } },\n required: [\"x\", \"y\"],\n additionalProperties: false,\n },\n },\n },\n [\"path\"],\n ) as never,\n strict: false,\n ...approval,\n execute: async (input) => {\n const { path } = input as { path: Array<{ x: number; y: number }> };\n const points = path.map((p) => [p.x, p.y] as [number, number]);\n return write(`dragged through ${points.length} point(s)`, () => computer.drag(points));\n },\n }),\n ] as unknown as Tool<unknown>[];\n}\n\n// ── The capability (the SDK seam) ────────────────────────────────────────────\n\nexport type ComputerUseArgs = {\n dimensions?: [number, number];\n readOnly?: boolean;\n display?: string;\n needsApproval?: boolean | ((ctx: unknown, action: unknown) => boolean | Promise<boolean>);\n // Deliver screenshots from the FUNCTION tools as a REAL image the model can see\n // (a structured `{type:'image'}` tool output → agents-core normalizes it to an\n // `input_image` content item inside the function_call_output) instead of the text\n // data-URL string. Only the codex/ChatGPT backend can read structured image tool\n // results; chat-completions providers cannot, so this stays OFF (text rendering)\n // by default and is turned on only on the codex path (see index.ts).\n imageFunctionResults?: boolean;\n};\n\nexport function computerUse(args: ComputerUseArgs = {}): ComputerUseCapability {\n return new ComputerUseCapability(args);\n}\n\n/**\n * A `Capability` subclass merged into the agent's tool set by SandboxAgent\n * (`tools = [...agent.tools, ...capability.tools()]`). `bind(session)` hands it\n * the LIVE externally-owned session, so the agent's actions and the viewers'\n * pixels are one display.\n *\n * `tools()` is TRANSPORT-AWARE, mirroring the SDK's `filesystem()` capability\n * (which branches its `view_image` / `apply_patch` on\n * `supportsStructuredToolOutputTransport(this._modelInstance)`):\n * • structured transport (the Responses/OpenAI backend) → the single HOSTED\n * `computer_use_preview` tool over a Computer bound to the session (unchanged).\n * • text transport (codex / ChatGPT backend — or an unbound model) → a set of\n * FUNCTION tools ({@link computerFunctionTools}) that route to the SAME Computer,\n * because the codex backend rejects the hosted computer tool type.\n * The bound model instance is captured by the SDK's `bind().bindRunAs().bindModel()`\n * chain (base `Capability._modelInstance`); the codex path in index.ts neutralizes\n * `bindModel` so `_modelInstance` stays undefined here → the function tools win.\n */\nexport class ComputerUseCapability extends Capability {\n readonly type = \"computer-use\";\n constructor(private args: ComputerUseArgs = {}) { super(); }\n\n override tools(): Tool<unknown>[] {\n const session = requireBoundSession(\"computer-use\", this._session);\n // Backend-aware: a SELF-HOSTED session (macOS OR bring-your-own Linux) drives the\n // desktop NATIVELY (CGEvent/XTEST inject + ScreenCaptureKit/x11 capture over the\n // control plane) — no xdotool/scrot on the user's machine required. Everything\n // else (Modal) keeps the xdotool/scrot-over-exec SandboxComputer. See\n // `isNativeDesktopSession` for the duck-typed discriminator.\n const computer: Computer = isNativeDesktopSession(session)\n ? new NativeDesktopComputer(session, {\n ...(this.args.dimensions ? { dimensions: this.args.dimensions } : {}),\n ...(this.args.readOnly !== undefined ? { readOnly: this.args.readOnly } : {}),\n })\n : new SandboxComputer(session, {\n ...(this.args.dimensions ? { dimensions: this.args.dimensions } : {}),\n ...(this.args.readOnly !== undefined ? { readOnly: this.args.readOnly } : {}),\n ...(this.args.display ? { display: this.args.display } : {}),\n // The SDK base exposes the bound runAs as a protected field.\n ...(typeof this._runAs === \"string\" ? { runAs: this._runAs } : {}),\n });\n // Structured transport keeps the HOSTED computer tool (unchanged); the codex /\n // text backend gets the FUNCTION tools it can actually call.\n if (supportsStructuredToolOutputTransport(this._modelInstance)) {\n return [\n computerTool({\n computer,\n ...(this.args.needsApproval !== undefined ? { needsApproval: this.args.needsApproval as never } : {}),\n }) as unknown as Tool<unknown>,\n ];\n }\n return computerFunctionTools(computer, this.args.readOnly ?? false, this.args.needsApproval, this.args.imageFunctionResults ?? false);\n }\n}\n"],"mappings":"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","names":["collectSandboxEnvironment","CAPABILITY_DESCRIPTORS","tool","RESULT_TYPE_BY_CALL_TYPE","RESULT_TYPES","itemType","OpenAIChatCompletionsModel","OpenAIResponsesModel","MaxTurnsExceededError","text","trimmed","agent","tool","sandboxSessionState","sanitizedHistory","state","collectSandboxEnvironment","runAs","fileDownloads","resourceClient","CAPABILITY_DESCRIPTORS","config"]}
|