@openclaw/codex 2026.6.5 → 2026.6.6-beta.1
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/{client-kMCtlApt.js → client-DovmVtbr.js} +3 -10
- package/dist/{client-factory-Bt49r45B.js → client-factory-XajDuvQ1.js} +1 -1
- package/dist/{command-handlers-DMn2M7W7.js → command-handlers-DIUFKqaF.js} +11 -9
- package/dist/{compact-CwnPeYnM.js → compact-BWiNkDSs.js} +96 -9
- package/dist/{computer-use-ClweWaMz.js → computer-use-D3pi5csE.js} +3 -2
- package/dist/{config-BT6SLiE6.js → config-DJXpBkGf.js} +214 -13
- package/dist/{conversation-binding-CzpvaBs1.js → conversation-binding-CMwrZrt7.js} +190 -65
- package/dist/harness.js +12 -5
- package/dist/index.js +11 -10
- package/dist/media-understanding-provider.js +6 -6
- package/dist/{models-DXorTaja.js → models-CQGfP7nG.js} +2 -2
- package/dist/{native-hook-relay-DHwz_ICg.js → native-hook-relay-CmUUO3Eu.js} +160 -4
- package/dist/notification-correlation-D-MYfJwV.js +382 -0
- package/dist/{request-D64BfplD.js → plugin-app-cache-key-NpzxEcSR.js} +4 -36
- package/dist/protocol-oeJQu4rs.js +9 -0
- package/dist/{protocol-validators-CIpP8IJ2.js → protocol-validators-B48C6S9O.js} +2296 -2273
- package/dist/provider-Cs6kWhDQ.js +584 -0
- package/dist/provider.js +1 -164
- package/dist/request-Dq0LUOqZ.js +36 -0
- package/dist/{run-attempt-BWdNnok4.js → run-attempt-DG9p9ReO.js} +374 -65
- package/dist/{session-binding-BgTv_YGm.js → session-binding-ElbcSq2o.js} +107 -44
- package/dist/{shared-client-xytpSKD0.js → shared-client-CflavQ_i.js} +3 -3
- package/dist/{side-question-BnvBQPqW.js → side-question-Ctu2VXAG.js} +82 -26
- package/dist/{thread-lifecycle-BJsazZ8j.js → thread-lifecycle-Cq1-IfZB.js} +115 -34
- package/npm-shrinkwrap.json +30 -30
- package/package.json +5 -5
- package/dist/notification-correlation-o8quHmTK.js +0 -656
|
@@ -1,59 +1,40 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { a as readCodexDynamicToolCallParams, c as readCodexTurn, i as assertCodexTurnStartResponse } from "./protocol-validators-
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { a as
|
|
6
|
-
import { n as
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
1
|
+
import { _ as withMcpElicitationsApprovalPolicy, a as isCodexAppServerApprovalPolicyAllowedByRequirements, d as resolveCodexAppServerRuntimeOptions, f as resolveCodexComputerUseConfig, g as shouldAutoApproveCodexAppServerApprovals, h as resolveOpenClawExecPolicyForCodexAppServer, m as resolveCodexPluginsPolicy, p as resolveCodexModelBackedReviewerPolicyContext, s as isCodexSandboxExecServerEnabled, u as readCodexPluginConfig } from "./config-DJXpBkGf.js";
|
|
2
|
+
import { a as readCodexDynamicToolCallParams, c as readCodexTurn, i as assertCodexTurnStartResponse } from "./protocol-validators-B48C6S9O.js";
|
|
3
|
+
import { t as isJsonObject } from "./protocol-oeJQu4rs.js";
|
|
4
|
+
import { i as formatCodexUsageLimitErrorMessage, o as resolveCodexUsageLimitResetAtMs, s as shouldRefreshCodexRateLimitsForUsageLimitMessage } from "./provider-Cs6kWhDQ.js";
|
|
5
|
+
import { a as isCodexAppServerConnectionClosedError, i as isCodexAppServerApprovalRequest, n as CodexAppServerRpcError, r as compareCodexAppServerVersions, s as MIN_CODEX_SANDBOX_EXEC_SERVER_APP_SERVER_VERSION } from "./client-DovmVtbr.js";
|
|
6
|
+
import { C as defaultCodexAppInventoryCache, D as filterCodexDynamicTools, M as projectContextEngineAssemblyForCodex, N as resolveCodexContextEngineProjectionMaxChars, O as isForcedPrivateQaCodexRuntime, P as resolveCodexContextEngineProjectionReserveTokens, T as sanitizeCodexHistoryImagePayloads, _ as buildCodexPluginThreadConfigInputFingerprint, a as buildDeveloperInstructions, c as codexDynamicToolsFingerprint, g as buildCodexPluginThreadConfig, h as isCodexAppServerProfilerEnabled, i as buildContextEngineBinding, j as resolveCodexDynamicToolsLoadingForModel, k as normalizeCodexDynamicToolName$1, l as isContextEngineBindingCompatible, m as startOrResumeThread, n as areCodexDynamicToolFingerprintsCompatible, o as buildTurnCollaborationMode, s as buildTurnStartParams, v as mergeCodexThreadConfigs, y as shouldBuildCodexPluginThreadConfig } from "./thread-lifecycle-Cq1-IfZB.js";
|
|
7
|
+
import { i as isCodexAppServerNativeAuthProfile, l as writeCodexAppServerBinding, n as clearCodexAppServerBinding, o as readCodexAppServerBinding, r as clearCodexAppServerBindingForThread } from "./session-binding-ElbcSq2o.js";
|
|
8
|
+
import { n as CODEX_CONTROL_METHODS, t as buildCodexPluginAppCacheKey } from "./plugin-app-cache-key-NpzxEcSR.js";
|
|
9
|
+
import { a as resolveCodexAppServerForModelProvider, i as readCodexNotificationTurnId, l as formatCodexDisplayText, n as isCodexNotificationForTurn, o as resolveCodexAppServerForOpenClawToolPolicy, r as readCodexNotificationThreadId, t as describeCodexNotificationCorrelation } from "./notification-correlation-D-MYfJwV.js";
|
|
10
|
+
import { d as resolveCodexAppServerAuthAccountCacheKey, f as resolveCodexAppServerAuthProfileId, h as resolveCodexAppServerHomeDir, m as resolveCodexAppServerFallbackApiKeyCacheKey, n as clearSharedCodexAppServerClientIfCurrentAndUnclaimed, o as releaseLeasedSharedCodexAppServerClient, p as resolveCodexAppServerAuthProfileIdForAgent, s as retireSharedCodexAppServerClientIfCurrent, t as clearSharedCodexAppServerClientIfCurrent, u as refreshCodexAppServerAuthTokens } from "./shared-client-CflavQ_i.js";
|
|
9
11
|
import { i as resolveCodexNativeExecutionPolicy } from "./sandbox-guard-C-Yv9uwY.js";
|
|
10
|
-
import { t as defaultLeasedCodexAppServerClientFactory } from "./client-factory-
|
|
11
|
-
import { S as withCodexStartupTimeout, _ as resolveCodexPostToolRawAssistantCompletionIdleTimeoutMs, a as createCodexNativeHookRelay, b as resolveCodexTurnCompletionIdleTimeoutMs, c as scheduleCodexNativeHookRelayUnregister, d as emitDynamicToolErrorDiagnostic, f as emitDynamicToolStartedDiagnostic, g as CODEX_POST_REASONING_REPLY_IDLE_TIMEOUT_MS, h as handleCodexAppServerApprovalRequest, i as buildCodexNativeHookRelayDisabledConfig, l as handleCodexAppServerElicitationRequest, m as filterToolsForVisionInputs, n as CODEX_NATIVE_HOOK_RELAY_TTL_GRACE_MS, o as resolveCodexNativeHookRelayEvents, p as emitDynamicToolTerminalDiagnostic, r as buildCodexNativeHookRelayConfig, s as resolveCodexNativeHookRelayTtlMs, u as createCodexDynamicToolBridge, v as resolveCodexStartupTimeoutMs, x as resolveCodexTurnTerminalIdleTimeoutMs, y as resolveCodexTurnAssistantCompletionIdleTimeoutMs } from "./native-hook-relay-
|
|
12
|
-
import { t as ensureCodexComputerUse } from "./computer-use-
|
|
12
|
+
import { t as defaultLeasedCodexAppServerClientFactory } from "./client-factory-XajDuvQ1.js";
|
|
13
|
+
import { S as withCodexStartupTimeout, _ as resolveCodexPostToolRawAssistantCompletionIdleTimeoutMs, a as createCodexNativeHookRelay, b as resolveCodexTurnCompletionIdleTimeoutMs, c as scheduleCodexNativeHookRelayUnregister, d as emitDynamicToolErrorDiagnostic, f as emitDynamicToolStartedDiagnostic, g as CODEX_POST_REASONING_REPLY_IDLE_TIMEOUT_MS, h as handleCodexAppServerApprovalRequest, i as buildCodexNativeHookRelayDisabledConfig, l as handleCodexAppServerElicitationRequest, m as filterToolsForVisionInputs, n as CODEX_NATIVE_HOOK_RELAY_TTL_GRACE_MS, o as resolveCodexNativeHookRelayEvents, p as emitDynamicToolTerminalDiagnostic, r as buildCodexNativeHookRelayConfig, s as resolveCodexNativeHookRelayTtlMs, u as createCodexDynamicToolBridge, v as resolveCodexStartupTimeoutMs, x as resolveCodexTurnTerminalIdleTimeoutMs, y as resolveCodexTurnAssistantCompletionIdleTimeoutMs } from "./native-hook-relay-CmUUO3Eu.js";
|
|
14
|
+
import { t as ensureCodexComputerUse } from "./computer-use-D3pi5csE.js";
|
|
13
15
|
import { n as rememberCodexRateLimits, t as readRecentCodexRateLimits } from "./rate-limit-cache-C7qmZ0Jh.js";
|
|
14
16
|
import { asDateTimestampMs, parseStrictNonNegativeInteger, resolveTimerTimeoutMs } from "openclaw/plugin-sdk/number-runtime";
|
|
15
17
|
import { createHash, randomUUID } from "node:crypto";
|
|
16
18
|
import fsSync from "node:fs";
|
|
19
|
+
import path, { posix } from "node:path";
|
|
20
|
+
import { markAuthProfileBlockedUntil, resolveAgentDir, resolveAgentWorkspaceDir } from "openclaw/plugin-sdk/agent-runtime";
|
|
17
21
|
import { loadExecApprovals } from "openclaw/plugin-sdk/exec-approvals-runtime";
|
|
18
22
|
import { asBoolean, asFiniteNumber, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
19
|
-
import { CODEX_APP_SERVER_CONTEXT_ENGINE_HOST, TOOL_PROGRESS_OUTPUT_MAX_CHARS, acquireSessionWriteLock, appendSessionTranscriptMessage, assembleHarnessContextEngine, assertContextEngineHostSupport, awaitAgentHarnessAgentEndHook, bootstrapHarnessContextEngine, buildAgentHookContextChannelFields, buildBootstrapContextForFiles, buildEmbeddedAttemptToolRunContext, buildHarnessContextEngineRuntimeContext, buildHarnessContextEngineRuntimeContextFromUsage, classifyAgentHarnessTerminalOutcome, clearActiveEmbeddedRun, embeddedAgentLog, emitAgentEvent, emitSessionTranscriptUpdate, filterProviderNormalizableTools, finalizeHarnessContextEngineTurn, formatErrorMessage, formatToolAggregate, formatToolProgressOutput, getAgentHarnessHookRunner, getBeforeToolCallPolicyDiagnosticState, inferToolMetaFromArgs, isActiveHarnessContextEngine, isSubagentSessionKey, loadCodexBundleMcpThreadConfig, normalizeAgentRuntimeTools, normalizeUsage, resolveAgentHarnessBeforePromptBuildResult, resolveAttemptSpawnWorkspaceDir, resolveBootstrapFilesForRun, resolveContextEngineOwnerPluginId, resolveModelAuthMode, resolveSandboxContext, resolveSessionAgentIds, resolveSessionWriteLockOptions, resolveUserPath, runAgentCleanupStep, runAgentHarnessAfterCompactionHook, runAgentHarnessAfterToolCallHook, runAgentHarnessAgentEndHook, runAgentHarnessBeforeCompactionHook, runAgentHarnessBeforeMessageWriteHook, runAgentHarnessLlmInputHook, runAgentHarnessLlmOutputHook, runHarnessContextEngineMaintenance, setActiveEmbeddedRun, supportsModelTools } from "openclaw/plugin-sdk/agent-harness-runtime";
|
|
23
|
+
import { CODEX_APP_SERVER_CONTEXT_ENGINE_HOST, TOOL_PROGRESS_OUTPUT_MAX_CHARS, acquireSessionWriteLock, appendSessionTranscriptMessage, assembleHarnessContextEngine, assertContextEngineHostSupport, awaitAgentHarnessAgentEndHook, bootstrapHarnessContextEngine, buildAgentHookContextChannelFields, buildBootstrapContextForFiles, buildEmbeddedAttemptToolRunContext, buildHarnessContextEngineRuntimeContext, buildHarnessContextEngineRuntimeContextFromUsage, classifyAgentHarnessTerminalOutcome, clearActiveEmbeddedRun, embeddedAgentLog, emitAgentEvent, emitSessionTranscriptUpdate, filterProviderNormalizableTools, finalizeHarnessContextEngineTurn, formatErrorMessage, formatToolAggregate, formatToolProgressOutput, getAgentHarnessHookRunner, getBeforeToolCallPolicyDiagnosticState, inferToolMetaFromArgs, isActiveHarnessContextEngine, isSubagentSessionKey, loadCodexBundleMcpThreadConfig, normalizeAgentRuntimeTools, normalizeUsage, resolveAgentHarnessBeforePromptBuildResult, resolveAttemptSpawnWorkspaceDir, resolveBootstrapFilesForRun, resolveContextEngineOwnerPluginId, resolveModelAuthMode, resolveSandboxContext, resolveSessionAgentIds as resolveSessionAgentIds$1, resolveSessionWriteLockOptions, resolveUserPath, runAgentCleanupStep, runAgentHarnessAfterCompactionHook, runAgentHarnessAfterToolCallHook, runAgentHarnessAgentEndHook, runAgentHarnessBeforeCompactionHook, runAgentHarnessBeforeMessageWriteHook, runAgentHarnessLlmInputHook, runAgentHarnessLlmOutputHook, runHarnessContextEngineMaintenance, setActiveEmbeddedRun, supportsModelTools } from "openclaw/plugin-sdk/agent-harness-runtime";
|
|
20
24
|
import { spawn } from "node:child_process";
|
|
21
25
|
import { once } from "node:events";
|
|
22
26
|
import { WebSocketServer } from "ws";
|
|
23
27
|
import { redactSensitiveFieldValue, redactToolPayloadText } from "openclaw/plugin-sdk/logging-core";
|
|
24
28
|
import fs from "node:fs/promises";
|
|
25
|
-
import path, { posix } from "node:path";
|
|
26
29
|
import { createDiagnosticTraceContextFromActiveScope, emitTrustedDiagnosticEvent, emitTrustedDiagnosticEventWithPrivateData, freezeDiagnosticTraceContext, hasPendingInternalDiagnosticEvent, onInternalDiagnosticEvent, resolveDiagnosticModelContentCapturePolicy } from "openclaw/plugin-sdk/diagnostic-runtime";
|
|
27
|
-
import { markAuthProfileBlockedUntil, resolveAgentDir as resolveAgentDir$1, resolveAgentWorkspaceDir } from "openclaw/plugin-sdk/agent-runtime";
|
|
28
30
|
import { isToolAllowed } from "openclaw/plugin-sdk/sandbox";
|
|
29
31
|
import { appendRegularFile, pathExists } from "openclaw/plugin-sdk/security-runtime";
|
|
30
32
|
import { buildSessionContext, migrateSessionEntries, parseSessionEntries } from "openclaw/plugin-sdk/agent-sessions";
|
|
31
33
|
import { isIP } from "node:net";
|
|
34
|
+
import { SsrFBlockedError, isBlockedHostnameOrIp } from "openclaw/plugin-sdk/ssrf-runtime";
|
|
32
35
|
import { generatedImageAssetFromBase64 } from "openclaw/plugin-sdk/image-generation";
|
|
33
36
|
import { saveMediaBuffer } from "openclaw/plugin-sdk/media-store";
|
|
34
37
|
import { createAgentHarnessTaskRuntime, deliverAgentHarnessTaskCompletion, isDurableAgentHarnessCompletionDelivery } from "openclaw/plugin-sdk/agent-harness-task-runtime";
|
|
35
|
-
//#region extensions/codex/src/app-server/app-server-policy.ts
|
|
36
|
-
/**
|
|
37
|
-
* Promotes implicit `never` approval policy to `untrusted` only when runtime
|
|
38
|
-
* requirements allow OpenClaw to handle tool approvals.
|
|
39
|
-
*/
|
|
40
|
-
function resolveCodexAppServerForOpenClawToolPolicy(params) {
|
|
41
|
-
if (!params.shouldPromote || !params.canUseUntrustedApprovalPolicy || params.appServer.approvalPolicy !== "never") return params.appServer;
|
|
42
|
-
const explicitMode = params.execPolicy?.mode === "full" || params.pluginConfig.appServer?.mode !== void 0 || isCodexAppServerPolicyMode(params.env.OPENCLAW_CODEX_APP_SERVER_MODE);
|
|
43
|
-
const explicitApprovalPolicy = params.pluginConfig.appServer?.approvalPolicy !== void 0 || isCodexAppServerApprovalPolicy(params.env.OPENCLAW_CODEX_APP_SERVER_APPROVAL_POLICY) || params.appServer.approvalPolicySource === "requirements";
|
|
44
|
-
if (explicitMode || explicitApprovalPolicy) return params.appServer;
|
|
45
|
-
return {
|
|
46
|
-
...params.appServer,
|
|
47
|
-
approvalPolicy: "untrusted"
|
|
48
|
-
};
|
|
49
|
-
}
|
|
50
|
-
function isCodexAppServerPolicyMode(value) {
|
|
51
|
-
return value === "guardian" || value === "yolo";
|
|
52
|
-
}
|
|
53
|
-
function isCodexAppServerApprovalPolicy(value) {
|
|
54
|
-
return value === "never" || value === "on-request" || value === "on-failure" || value === "untrusted";
|
|
55
|
-
}
|
|
56
|
-
//#endregion
|
|
57
38
|
//#region extensions/codex/src/app-server/attempt-client-cleanup.ts
|
|
58
39
|
/**
|
|
59
40
|
* Best-effort cleanup helpers for timed-out or aborted Codex app-server turns.
|
|
@@ -1323,7 +1304,7 @@ async function buildDynamicTools(input) {
|
|
|
1323
1304
|
if (params.disableTools || !supportsModelTools(params.model)) return [];
|
|
1324
1305
|
const toolBuildStages = createCodexDynamicToolBuildStageTracker({ enabled: input.profilerEnabled });
|
|
1325
1306
|
const modelHasVision = params.model.input?.includes("image") ?? false;
|
|
1326
|
-
const agentDir = params.agentDir ?? resolveAgentDir
|
|
1307
|
+
const agentDir = params.agentDir ?? resolveAgentDir(params.config ?? {}, input.sessionAgentId);
|
|
1327
1308
|
const createOpenClawCodingTools = (await import("openclaw/plugin-sdk/agent-harness")).createOpenClawCodingTools;
|
|
1328
1309
|
toolBuildStages.mark("load-agent-harness-tools");
|
|
1329
1310
|
const sessionKeys = resolveOpenClawCodingToolsSessionKeys(params, input.sandboxSessionKey);
|
|
@@ -2122,9 +2103,11 @@ const SANDBOX_HTTP_STREAM_LINE_MAX_CHARS = 256 * 1024;
|
|
|
2122
2103
|
async function httpRequest(execServer, socket, params) {
|
|
2123
2104
|
const record = requireObject(params, "http/request params");
|
|
2124
2105
|
const requestId = requireString(record.requestId, "requestId");
|
|
2106
|
+
const url = requireString(record.url, "url");
|
|
2107
|
+
assertSandboxHttpRequestTargetAllowed(url);
|
|
2125
2108
|
const request = {
|
|
2126
2109
|
method: requireString(record.method, "method"),
|
|
2127
|
-
url
|
|
2110
|
+
url,
|
|
2128
2111
|
headers: readHttpHeaders(record.headers),
|
|
2129
2112
|
bodyBase64: typeof record.bodyBase64 === "string" ? record.bodyBase64 : void 0,
|
|
2130
2113
|
timeoutMs: typeof record.timeoutMs === "number" && record.timeoutMs > 0 ? Math.floor(record.timeoutMs) : void 0,
|
|
@@ -2136,6 +2119,16 @@ async function httpRequest(execServer, socket, params) {
|
|
|
2136
2119
|
streamResponse: false
|
|
2137
2120
|
});
|
|
2138
2121
|
}
|
|
2122
|
+
function assertSandboxHttpRequestTargetAllowed(url) {
|
|
2123
|
+
let parsed;
|
|
2124
|
+
try {
|
|
2125
|
+
parsed = new URL(url);
|
|
2126
|
+
} catch {
|
|
2127
|
+
throw new SsrFBlockedError("Invalid URL supplied to sandbox http/request");
|
|
2128
|
+
}
|
|
2129
|
+
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") throw new SsrFBlockedError(`Blocked non-HTTP(S) protocol in sandbox http/request: ${parsed.protocol}`);
|
|
2130
|
+
if (isBlockedHostnameOrIp(parsed.hostname)) throw new SsrFBlockedError(`Blocked hostname or private/internal IP in sandbox http/request: ${parsed.hostname}`);
|
|
2131
|
+
}
|
|
2139
2132
|
async function runSandboxHttpRequest(execServer, params) {
|
|
2140
2133
|
const result = await requireBackend(execServer).runShellCommand({
|
|
2141
2134
|
script: SANDBOX_HTTP_REQUEST_SCRIPT,
|
|
@@ -2284,6 +2277,8 @@ trap 'rm -f "$tmp"' EXIT
|
|
|
2284
2277
|
cat > "$tmp" <<'PY'
|
|
2285
2278
|
import base64
|
|
2286
2279
|
import json
|
|
2280
|
+
import ipaddress
|
|
2281
|
+
import socket
|
|
2287
2282
|
import sys
|
|
2288
2283
|
import urllib.error
|
|
2289
2284
|
import urllib.parse
|
|
@@ -2295,6 +2290,127 @@ def emit(payload):
|
|
|
2295
2290
|
def response_headers(response):
|
|
2296
2291
|
return [{"name": name, "value": value} for name, value in response.headers.items()]
|
|
2297
2292
|
|
|
2293
|
+
BLOCKED_HOSTNAMES = {
|
|
2294
|
+
"localhost",
|
|
2295
|
+
"localhost.localdomain",
|
|
2296
|
+
"metadata.google.internal",
|
|
2297
|
+
}
|
|
2298
|
+
CLOUD_METADATA_IP_ADDRESSES = {
|
|
2299
|
+
"100.100.100.200",
|
|
2300
|
+
"fd00:ec2::254",
|
|
2301
|
+
}
|
|
2302
|
+
BLOCKED_IPV4_NETWORKS = tuple(
|
|
2303
|
+
ipaddress.ip_network(network)
|
|
2304
|
+
for network in (
|
|
2305
|
+
"100.64.0.0/10",
|
|
2306
|
+
"198.18.0.0/15",
|
|
2307
|
+
)
|
|
2308
|
+
)
|
|
2309
|
+
BLOCKED_IPV6_NETWORKS = tuple(
|
|
2310
|
+
ipaddress.ip_network(network)
|
|
2311
|
+
for network in (
|
|
2312
|
+
"100::/64",
|
|
2313
|
+
"2001:2::/48",
|
|
2314
|
+
"2001:20::/28",
|
|
2315
|
+
"2001:db8::/32",
|
|
2316
|
+
"fec0::/10",
|
|
2317
|
+
)
|
|
2318
|
+
)
|
|
2319
|
+
PINNED_ADDRESSES = {}
|
|
2320
|
+
|
|
2321
|
+
def normalize_hostname(hostname):
|
|
2322
|
+
return (hostname or "").strip("[]").rstrip(".").lower()
|
|
2323
|
+
|
|
2324
|
+
def is_blocked_hostname(hostname):
|
|
2325
|
+
normalized = normalize_hostname(hostname)
|
|
2326
|
+
return (
|
|
2327
|
+
normalized in BLOCKED_HOSTNAMES
|
|
2328
|
+
or normalized.endswith(".localhost")
|
|
2329
|
+
or normalized.endswith(".local")
|
|
2330
|
+
or normalized.endswith(".internal")
|
|
2331
|
+
)
|
|
2332
|
+
|
|
2333
|
+
def is_blocked_ip(address):
|
|
2334
|
+
try:
|
|
2335
|
+
parsed = ipaddress.ip_address(address)
|
|
2336
|
+
except ValueError:
|
|
2337
|
+
return False
|
|
2338
|
+
embedded_ipv4 = extract_embedded_ipv4(parsed)
|
|
2339
|
+
if embedded_ipv4 is not None and is_blocked_ip(str(embedded_ipv4)):
|
|
2340
|
+
return True
|
|
2341
|
+
if str(parsed).lower() in CLOUD_METADATA_IP_ADDRESSES:
|
|
2342
|
+
return True
|
|
2343
|
+
if isinstance(parsed, ipaddress.IPv4Address):
|
|
2344
|
+
if any(parsed in network for network in BLOCKED_IPV4_NETWORKS):
|
|
2345
|
+
return True
|
|
2346
|
+
else:
|
|
2347
|
+
if any(parsed in network for network in BLOCKED_IPV6_NETWORKS):
|
|
2348
|
+
return True
|
|
2349
|
+
return (
|
|
2350
|
+
parsed.is_loopback
|
|
2351
|
+
or parsed.is_private
|
|
2352
|
+
or parsed.is_link_local
|
|
2353
|
+
or parsed.is_multicast
|
|
2354
|
+
or parsed.is_reserved
|
|
2355
|
+
or parsed.is_unspecified
|
|
2356
|
+
)
|
|
2357
|
+
|
|
2358
|
+
def ipv4_from_int(value):
|
|
2359
|
+
return ipaddress.IPv4Address(value & 0xffffffff)
|
|
2360
|
+
|
|
2361
|
+
def extract_embedded_ipv4(address):
|
|
2362
|
+
if not isinstance(address, ipaddress.IPv6Address):
|
|
2363
|
+
return None
|
|
2364
|
+
if address.ipv4_mapped is not None:
|
|
2365
|
+
return address.ipv4_mapped
|
|
2366
|
+
value = int(address)
|
|
2367
|
+
hextets = [(value >> shift) & 0xffff for shift in range(112, -1, -16)]
|
|
2368
|
+
if hextets[:6] == [0, 0, 0, 0, 0, 0]:
|
|
2369
|
+
return ipv4_from_int(value)
|
|
2370
|
+
if hextets[:6] == [0x64, 0xff9b, 0, 0, 0, 0]:
|
|
2371
|
+
return ipv4_from_int(value)
|
|
2372
|
+
if hextets[:6] == [0x64, 0xff9b, 1, 0, 0, 0]:
|
|
2373
|
+
return ipv4_from_int(value)
|
|
2374
|
+
if hextets[0] == 0x2002:
|
|
2375
|
+
return ipv4_from_int((hextets[1] << 16) | hextets[2])
|
|
2376
|
+
if hextets[0] == 0x2001 and hextets[1] == 0:
|
|
2377
|
+
return ipv4_from_int(((hextets[6] << 16) | hextets[7]) ^ 0xffffffff)
|
|
2378
|
+
if (hextets[4] & 0xfcff) == 0 and hextets[5] == 0x5efe:
|
|
2379
|
+
return ipv4_from_int((hextets[6] << 16) | hextets[7])
|
|
2380
|
+
return None
|
|
2381
|
+
|
|
2382
|
+
def assert_url_allowed(url):
|
|
2383
|
+
parsed = urllib.parse.urlparse(url)
|
|
2384
|
+
if parsed.scheme not in ("http", "https"):
|
|
2385
|
+
raise ValueError("http/request only supports http and https URLs")
|
|
2386
|
+
hostname = normalize_hostname(parsed.hostname)
|
|
2387
|
+
if not hostname or is_blocked_hostname(hostname) or is_blocked_ip(hostname):
|
|
2388
|
+
raise ValueError("Blocked hostname or private/internal/special-use IP address")
|
|
2389
|
+
try:
|
|
2390
|
+
results = socket.getaddrinfo(hostname, parsed.port, proto=socket.IPPROTO_TCP)
|
|
2391
|
+
except socket.gaierror as error:
|
|
2392
|
+
raise ValueError(f"Unable to resolve hostname: {hostname}") from error
|
|
2393
|
+
addresses = {entry[4][0] for entry in results if entry[4]}
|
|
2394
|
+
if not addresses or any(is_blocked_ip(address) for address in addresses):
|
|
2395
|
+
raise ValueError("Blocked: resolves to private/internal/special-use IP address")
|
|
2396
|
+
PINNED_ADDRESSES[hostname] = sorted(addresses)
|
|
2397
|
+
|
|
2398
|
+
class GuardedRedirectHandler(urllib.request.HTTPRedirectHandler):
|
|
2399
|
+
def redirect_request(self, req, fp, code, msg, headers, newurl):
|
|
2400
|
+
assert_url_allowed(newurl)
|
|
2401
|
+
return super().redirect_request(req, fp, code, msg, headers, newurl)
|
|
2402
|
+
|
|
2403
|
+
def pinned_getaddrinfo(original_getaddrinfo):
|
|
2404
|
+
def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0):
|
|
2405
|
+
pinned = PINNED_ADDRESSES.get(normalize_hostname(host))
|
|
2406
|
+
if not pinned:
|
|
2407
|
+
return original_getaddrinfo(host, port, family, type, proto, flags)
|
|
2408
|
+
results = []
|
|
2409
|
+
for address in pinned:
|
|
2410
|
+
results.extend(original_getaddrinfo(address, port, family, type, proto, flags))
|
|
2411
|
+
return results
|
|
2412
|
+
return getaddrinfo
|
|
2413
|
+
|
|
2298
2414
|
def handle_response(input_data, response):
|
|
2299
2415
|
headers = response_headers(response)
|
|
2300
2416
|
status = int(getattr(response, "status", getattr(response, "code", 0)))
|
|
@@ -2324,9 +2440,7 @@ def handle_response(input_data, response):
|
|
|
2324
2440
|
def main():
|
|
2325
2441
|
input_data = json.load(sys.stdin)
|
|
2326
2442
|
url = str(input_data.get("url", ""))
|
|
2327
|
-
|
|
2328
|
-
if parsed.scheme not in ("http", "https"):
|
|
2329
|
-
raise ValueError("http/request only supports http and https URLs")
|
|
2443
|
+
assert_url_allowed(url)
|
|
2330
2444
|
body_base64 = input_data.get("bodyBase64")
|
|
2331
2445
|
data = base64.b64decode(body_base64) if isinstance(body_base64, str) else None
|
|
2332
2446
|
request = urllib.request.Request(
|
|
@@ -2340,11 +2454,16 @@ def main():
|
|
|
2340
2454
|
timeout = None
|
|
2341
2455
|
if isinstance(timeout_ms, (int, float)) and timeout_ms > 0:
|
|
2342
2456
|
timeout = timeout_ms / 1000
|
|
2457
|
+
opener = urllib.request.build_opener(urllib.request.ProxyHandler({}), GuardedRedirectHandler)
|
|
2458
|
+
original_getaddrinfo = socket.getaddrinfo
|
|
2459
|
+
socket.getaddrinfo = pinned_getaddrinfo(original_getaddrinfo)
|
|
2343
2460
|
try:
|
|
2344
|
-
with
|
|
2461
|
+
with opener.open(request, timeout=timeout) as response:
|
|
2345
2462
|
handle_response(input_data, response)
|
|
2346
2463
|
except urllib.error.HTTPError as response:
|
|
2347
2464
|
handle_response(input_data, response)
|
|
2465
|
+
finally:
|
|
2466
|
+
socket.getaddrinfo = original_getaddrinfo
|
|
2348
2467
|
|
|
2349
2468
|
if __name__ == "__main__":
|
|
2350
2469
|
main()
|
|
@@ -7798,6 +7917,7 @@ function readRequestId(record) {
|
|
|
7798
7917
|
//#region extensions/codex/src/app-server/run-attempt.ts
|
|
7799
7918
|
const CODEX_NATIVE_HOOK_RELAY_RENEW_INTERVAL_MS = 6e4;
|
|
7800
7919
|
const CODEX_APP_SERVER_PROJECTED_CHARS_PER_TOKEN = 4;
|
|
7920
|
+
const CODEX_APP_SERVER_ACTIVE_NATIVE_TURN_WAIT_TIMEOUT_MS = 3e4;
|
|
7801
7921
|
const ensuredCodexWorkspaceDirs = /* @__PURE__ */ new Set();
|
|
7802
7922
|
function estimateCodexAppServerProjectedTurnTokens(params) {
|
|
7803
7923
|
const inputChars = params.prompt.length + (params.developerInstructions?.length ?? 0);
|
|
@@ -7836,6 +7956,43 @@ function emitCodexAppServerEvent(params, event) {
|
|
|
7836
7956
|
embeddedAgentLog.debug("codex app-server agent event handler threw", { error });
|
|
7837
7957
|
}
|
|
7838
7958
|
}
|
|
7959
|
+
function toTranscriptToolResult(response) {
|
|
7960
|
+
const sanitized = sanitizeCodexToolResponse(response);
|
|
7961
|
+
const contentItems = Array.isArray(sanitized.contentItems) ? sanitized.contentItems : [];
|
|
7962
|
+
const result = {
|
|
7963
|
+
...sanitized,
|
|
7964
|
+
content: contentItems.map(toTranscriptToolResultContentItem)
|
|
7965
|
+
};
|
|
7966
|
+
delete result.contentItems;
|
|
7967
|
+
delete result.success;
|
|
7968
|
+
return result;
|
|
7969
|
+
}
|
|
7970
|
+
function toTranscriptToolResultContentItem(item) {
|
|
7971
|
+
if (!item || typeof item !== "object") return {
|
|
7972
|
+
type: "text",
|
|
7973
|
+
text: ""
|
|
7974
|
+
};
|
|
7975
|
+
const record = item;
|
|
7976
|
+
if (record.type === "inputText") return {
|
|
7977
|
+
type: "text",
|
|
7978
|
+
text: typeof record.text === "string" ? record.text : ""
|
|
7979
|
+
};
|
|
7980
|
+
if (record.type === "inputImage") return typeof record.imageUrl === "string" ? {
|
|
7981
|
+
type: "image",
|
|
7982
|
+
url: record.imageUrl
|
|
7983
|
+
} : {
|
|
7984
|
+
type: "text",
|
|
7985
|
+
text: formatUnsupportedCodexDynamicToolOutput(record.type)
|
|
7986
|
+
};
|
|
7987
|
+
return {
|
|
7988
|
+
type: "text",
|
|
7989
|
+
text: formatUnsupportedCodexDynamicToolOutput(record.type)
|
|
7990
|
+
};
|
|
7991
|
+
}
|
|
7992
|
+
function formatUnsupportedCodexDynamicToolOutput(type) {
|
|
7993
|
+
const rawType = typeof type === "string" ? type.replace(/\s+/g, " ").trim() : "";
|
|
7994
|
+
return `[Unsupported Codex dynamic tool output: ${rawType ? rawType.slice(0, 80) : "unknown"}${rawType.length > 80 ? "..." : ""}]`;
|
|
7995
|
+
}
|
|
7839
7996
|
function shouldAwaitCodexAgentEndHook(params) {
|
|
7840
7997
|
return !params.messageChannel && !params.messageProvider;
|
|
7841
7998
|
}
|
|
@@ -7856,7 +8013,7 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
7856
8013
|
const attemptClientFactory = options.clientFactory ?? defaultLeasedCodexAppServerClientFactory;
|
|
7857
8014
|
const pluginConfig = readCodexPluginConfig(options.pluginConfig);
|
|
7858
8015
|
const computerUseConfig = resolveCodexComputerUseConfig({ pluginConfig });
|
|
7859
|
-
const { sessionAgentId } = resolveSessionAgentIds({
|
|
8016
|
+
const { sessionAgentId } = resolveSessionAgentIds$1({
|
|
7860
8017
|
sessionKey: params.sessionKey,
|
|
7861
8018
|
config: params.config,
|
|
7862
8019
|
agentId: params.agentId
|
|
@@ -7880,9 +8037,44 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
7880
8037
|
config: params.config,
|
|
7881
8038
|
agentId: sessionAgentId
|
|
7882
8039
|
});
|
|
7883
|
-
const
|
|
8040
|
+
const agentDir = params.agentDir ?? resolveAgentDir(params.config ?? {}, sessionAgentId);
|
|
8041
|
+
preDynamicStartupStages.mark("session-agent");
|
|
8042
|
+
const activeContextEngine = isActiveHarnessContextEngine(params.contextEngine) ? params.contextEngine : void 0;
|
|
8043
|
+
const isInactiveThreadBootstrapBinding = (binding) => !activeContextEngine && binding?.contextEngine?.projection?.mode === "thread_bootstrap";
|
|
8044
|
+
let startupBinding = await readCodexAppServerBinding(params.sessionFile);
|
|
8045
|
+
preDynamicStartupStages.mark("read-binding");
|
|
8046
|
+
const startupBindingAuthProfileId = startupBinding?.authProfileId;
|
|
8047
|
+
const initialStartupBindingHadInactiveThreadBootstrap = isInactiveThreadBootstrapBinding(startupBinding);
|
|
8048
|
+
const startupAuthProfileCandidate = params.runtimePlan?.auth.forwardedAuthProfileId ?? params.authProfileId ?? startupBinding?.authProfileId ?? startupBindingAuthProfileId;
|
|
8049
|
+
const startupAuthProfileId = params.authProfileStore ? resolveCodexAppServerAuthProfileId({
|
|
8050
|
+
authProfileId: startupAuthProfileCandidate,
|
|
8051
|
+
store: params.authProfileStore,
|
|
8052
|
+
config: params.config
|
|
8053
|
+
}) : resolveCodexAppServerAuthProfileIdForAgent({
|
|
8054
|
+
authProfileId: startupAuthProfileCandidate,
|
|
8055
|
+
agentDir,
|
|
8056
|
+
config: params.config
|
|
8057
|
+
});
|
|
8058
|
+
let reviewerPolicyContext = resolveCodexModelBackedReviewerPolicyContext({
|
|
8059
|
+
provider: params.provider,
|
|
8060
|
+
model: params.modelId,
|
|
8061
|
+
bindingModelProvider: startupBinding?.modelProvider,
|
|
8062
|
+
bindingModel: startupBinding?.model,
|
|
8063
|
+
nativeAuthProfile: isCodexAppServerNativeAuthProfile({
|
|
8064
|
+
authProfileId: startupAuthProfileId,
|
|
8065
|
+
authProfileStore: params.authProfileStore,
|
|
8066
|
+
agentDir,
|
|
8067
|
+
config: params.config
|
|
8068
|
+
})
|
|
8069
|
+
});
|
|
8070
|
+
preDynamicStartupStages.mark("auth-profile");
|
|
8071
|
+
let configuredAppServer = resolveCodexAppServerRuntimeOptions({
|
|
7884
8072
|
pluginConfig,
|
|
7885
8073
|
execPolicy,
|
|
8074
|
+
modelProvider: reviewerPolicyContext.modelProvider,
|
|
8075
|
+
model: reviewerPolicyContext.model,
|
|
8076
|
+
config: params.config,
|
|
8077
|
+
agentDir,
|
|
7886
8078
|
openClawSandboxActive: sandbox?.enabled === true
|
|
7887
8079
|
});
|
|
7888
8080
|
const effectiveWorkspace = sandbox?.enabled ? sandbox.workspaceAccess === "rw" ? resolvedWorkspace : sandbox.workspaceDir : resolvedWorkspace;
|
|
@@ -7891,7 +8083,7 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
7891
8083
|
const effectiveCwd = sandbox?.enabled ? effectiveWorkspace : requestedCwd ?? effectiveWorkspace;
|
|
7892
8084
|
await ensureCodexWorkspaceDirOnce(effectiveWorkspace);
|
|
7893
8085
|
preDynamicStartupStages.mark("effective-workspace");
|
|
7894
|
-
|
|
8086
|
+
let policyAppServer = resolveCodexAppServerForOpenClawToolPolicy({
|
|
7895
8087
|
appServer: configuredAppServer,
|
|
7896
8088
|
pluginConfig,
|
|
7897
8089
|
env: process.env,
|
|
@@ -7899,6 +8091,14 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
7899
8091
|
execPolicy,
|
|
7900
8092
|
canUseUntrustedApprovalPolicy: configuredAppServer.start.transport !== "stdio" || isCodexAppServerApprovalPolicyAllowedByRequirements("untrusted")
|
|
7901
8093
|
});
|
|
8094
|
+
let appServer = resolveCodexAppServerForModelProvider({
|
|
8095
|
+
appServer: policyAppServer,
|
|
8096
|
+
provider: reviewerPolicyContext.modelProvider,
|
|
8097
|
+
model: reviewerPolicyContext.model,
|
|
8098
|
+
config: params.config,
|
|
8099
|
+
env: process.env,
|
|
8100
|
+
agentDir
|
|
8101
|
+
});
|
|
7902
8102
|
if (configuredAppServer.approvalPolicy === "never" && appServer.approvalPolicy === "untrusted") embeddedAgentLog.info("codex app-server approval policy promoted for OpenClaw tool policy", {
|
|
7903
8103
|
from: "never",
|
|
7904
8104
|
to: "untrusted",
|
|
@@ -7907,7 +8107,7 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
7907
8107
|
});
|
|
7908
8108
|
preDynamicStartupStages.mark("app-server-policy");
|
|
7909
8109
|
let pluginAppServer = appServer;
|
|
7910
|
-
|
|
8110
|
+
let nativeHookRelayEvents = resolveCodexNativeHookRelayEvents({
|
|
7911
8111
|
configuredEvents: options.nativeHookRelay?.events,
|
|
7912
8112
|
appServer
|
|
7913
8113
|
});
|
|
@@ -7918,14 +8118,6 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
7918
8118
|
};
|
|
7919
8119
|
if (params.abortSignal?.aborted) abortFromUpstream();
|
|
7920
8120
|
else params.abortSignal?.addEventListener("abort", abortFromUpstream, { once: true });
|
|
7921
|
-
const agentDir = params.agentDir ?? resolveAgentDir$1(params.config ?? {}, sessionAgentId);
|
|
7922
|
-
preDynamicStartupStages.mark("session-agent");
|
|
7923
|
-
const activeContextEngine = isActiveHarnessContextEngine(params.contextEngine) ? params.contextEngine : void 0;
|
|
7924
|
-
const isInactiveThreadBootstrapBinding = (binding) => !activeContextEngine && binding?.contextEngine?.projection?.mode === "thread_bootstrap";
|
|
7925
|
-
let startupBinding = await readCodexAppServerBinding(params.sessionFile);
|
|
7926
|
-
preDynamicStartupStages.mark("read-binding");
|
|
7927
|
-
const startupBindingAuthProfileId = startupBinding?.authProfileId;
|
|
7928
|
-
const initialStartupBindingHadInactiveThreadBootstrap = isInactiveThreadBootstrapBinding(startupBinding);
|
|
7929
8121
|
startupBinding = await rotateOversizedCodexAppServerStartupBinding({
|
|
7930
8122
|
binding: startupBinding,
|
|
7931
8123
|
sessionFile: params.sessionFile,
|
|
@@ -7936,17 +8128,48 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
7936
8128
|
});
|
|
7937
8129
|
const initialInactiveThreadBootstrapBindingForcedFreshStart = initialStartupBindingHadInactiveThreadBootstrap && !startupBinding?.threadId;
|
|
7938
8130
|
preDynamicStartupStages.mark("rotate-binding");
|
|
7939
|
-
|
|
7940
|
-
|
|
7941
|
-
|
|
7942
|
-
|
|
7943
|
-
|
|
7944
|
-
|
|
7945
|
-
|
|
8131
|
+
reviewerPolicyContext = resolveCodexModelBackedReviewerPolicyContext({
|
|
8132
|
+
provider: params.provider,
|
|
8133
|
+
model: params.modelId,
|
|
8134
|
+
bindingModelProvider: startupBinding?.modelProvider,
|
|
8135
|
+
bindingModel: startupBinding?.model,
|
|
8136
|
+
nativeAuthProfile: isCodexAppServerNativeAuthProfile({
|
|
8137
|
+
authProfileId: startupAuthProfileId,
|
|
8138
|
+
authProfileStore: params.authProfileStore,
|
|
8139
|
+
agentDir,
|
|
8140
|
+
config: params.config
|
|
8141
|
+
})
|
|
8142
|
+
});
|
|
8143
|
+
configuredAppServer = resolveCodexAppServerRuntimeOptions({
|
|
8144
|
+
pluginConfig,
|
|
8145
|
+
execPolicy,
|
|
8146
|
+
modelProvider: reviewerPolicyContext.modelProvider,
|
|
8147
|
+
model: reviewerPolicyContext.model,
|
|
8148
|
+
config: params.config,
|
|
7946
8149
|
agentDir,
|
|
7947
|
-
|
|
8150
|
+
openClawSandboxActive: sandbox?.enabled === true
|
|
8151
|
+
});
|
|
8152
|
+
policyAppServer = resolveCodexAppServerForOpenClawToolPolicy({
|
|
8153
|
+
appServer: configuredAppServer,
|
|
8154
|
+
pluginConfig,
|
|
8155
|
+
env: process.env,
|
|
8156
|
+
shouldPromote: beforeToolCallPolicy.hasBeforeToolCallHook || beforeToolCallPolicy.trustedToolPolicies.length > 0,
|
|
8157
|
+
execPolicy,
|
|
8158
|
+
canUseUntrustedApprovalPolicy: configuredAppServer.start.transport !== "stdio" || isCodexAppServerApprovalPolicyAllowedByRequirements("untrusted")
|
|
8159
|
+
});
|
|
8160
|
+
appServer = resolveCodexAppServerForModelProvider({
|
|
8161
|
+
appServer: policyAppServer,
|
|
8162
|
+
provider: reviewerPolicyContext.modelProvider,
|
|
8163
|
+
model: reviewerPolicyContext.model,
|
|
8164
|
+
config: params.config,
|
|
8165
|
+
env: process.env,
|
|
8166
|
+
agentDir
|
|
8167
|
+
});
|
|
8168
|
+
pluginAppServer = appServer;
|
|
8169
|
+
nativeHookRelayEvents = resolveCodexNativeHookRelayEvents({
|
|
8170
|
+
configuredEvents: options.nativeHookRelay?.events,
|
|
8171
|
+
appServer
|
|
7948
8172
|
});
|
|
7949
|
-
preDynamicStartupStages.mark("auth-profile");
|
|
7950
8173
|
const runtimeParams = {
|
|
7951
8174
|
...params,
|
|
7952
8175
|
sessionKey: contextSessionKey,
|
|
@@ -8709,6 +8932,32 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
8709
8932
|
}
|
|
8710
8933
|
}
|
|
8711
8934
|
};
|
|
8935
|
+
let activeNativeTurnCompletionWaiter;
|
|
8936
|
+
const waitForActiveNativeTurnCompletion = async (turnIds) => {
|
|
8937
|
+
const turnIdSet = turnIds?.length ? new Set(turnIds) : void 0;
|
|
8938
|
+
const matchesCompletion = (notification) => isCodexThreadTurnCompletedNotification(notification, thread.threadId, turnIdSet);
|
|
8939
|
+
if (pendingNotifications.some((notification) => matchesCompletion(notification))) return true;
|
|
8940
|
+
return await new Promise((resolve) => {
|
|
8941
|
+
let settled = false;
|
|
8942
|
+
const timeoutRef = {};
|
|
8943
|
+
const finish = (completedNativeTurn) => {
|
|
8944
|
+
if (settled) return;
|
|
8945
|
+
settled = true;
|
|
8946
|
+
if (timeoutRef.current) clearTimeout(timeoutRef.current);
|
|
8947
|
+
runAbortController.signal.removeEventListener("abort", abortListener);
|
|
8948
|
+
if (activeNativeTurnCompletionWaiter?.resolve === finishComplete) activeNativeTurnCompletionWaiter = void 0;
|
|
8949
|
+
resolve(completedNativeTurn);
|
|
8950
|
+
};
|
|
8951
|
+
const finishComplete = () => finish(true);
|
|
8952
|
+
const abortListener = () => finish(false);
|
|
8953
|
+
timeoutRef.current = setTimeout(() => finish(false), Math.min(appServer.requestTimeoutMs, CODEX_APP_SERVER_ACTIVE_NATIVE_TURN_WAIT_TIMEOUT_MS));
|
|
8954
|
+
activeNativeTurnCompletionWaiter = {
|
|
8955
|
+
matches: matchesCompletion,
|
|
8956
|
+
resolve: finishComplete
|
|
8957
|
+
};
|
|
8958
|
+
runAbortController.signal.addEventListener("abort", abortListener, { once: true });
|
|
8959
|
+
});
|
|
8960
|
+
};
|
|
8712
8961
|
const enqueueNotification = (notification) => {
|
|
8713
8962
|
const projector = projectorRef.current;
|
|
8714
8963
|
const turnId = turnIdRef.current;
|
|
@@ -8720,6 +8969,9 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
8720
8969
|
embeddedAgentLog.trace("codex app-server raw notification received", correlation);
|
|
8721
8970
|
if (notification.method === "turn/completed" && correlation.matchesActiveTurn === false) if (correlation.matchesActiveThread) embeddedAgentLog.warn("codex app-server turn/completed did not match active turn", correlation);
|
|
8722
8971
|
else embeddedAgentLog.debug("codex app-server turn/completed ignored for other subscribed thread", correlation);
|
|
8972
|
+
if (notification.method === "turn/completed" && correlation.matchesActiveThread) {
|
|
8973
|
+
if (activeNativeTurnCompletionWaiter?.matches(notification)) activeNativeTurnCompletionWaiter.resolve();
|
|
8974
|
+
}
|
|
8723
8975
|
if (isCodexNotificationOutsideActiveRun(correlation)) return Promise.resolve();
|
|
8724
8976
|
if (!projector || !turnId) {
|
|
8725
8977
|
userInputBridge?.handleNotification(notification);
|
|
@@ -8804,6 +9056,9 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
8804
9056
|
threadId: thread.threadId,
|
|
8805
9057
|
turnId,
|
|
8806
9058
|
nativeHookRelay,
|
|
9059
|
+
execPolicy,
|
|
9060
|
+
execReviewerAgentId: sessionAgentId,
|
|
9061
|
+
internalExecAutoReview: appServer.approvalsReviewer === "user",
|
|
8807
9062
|
autoApprove: shouldAutoApproveCodexAppServerApprovals(appServer),
|
|
8808
9063
|
signal: runAbortController.signal
|
|
8809
9064
|
});
|
|
@@ -8914,7 +9169,7 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
8914
9169
|
toolCallId: call.callId,
|
|
8915
9170
|
...toolMeta ? { meta: toolMeta } : {},
|
|
8916
9171
|
isError: !protocolResponse.success,
|
|
8917
|
-
result:
|
|
9172
|
+
result: toTranscriptToolResult(progressResponse)
|
|
8918
9173
|
}
|
|
8919
9174
|
});
|
|
8920
9175
|
}
|
|
@@ -9028,6 +9283,8 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
9028
9283
|
promptText: codexTurnPromptText,
|
|
9029
9284
|
sandboxPolicy: codexSandboxPolicy,
|
|
9030
9285
|
environmentSelection: codexEnvironmentSelection,
|
|
9286
|
+
model: thread.model,
|
|
9287
|
+
modelProvider: thread.modelProvider,
|
|
9031
9288
|
turnScopedDeveloperInstructions: workspaceBootstrapContext.turnScopedDeveloperInstructions,
|
|
9032
9289
|
skillsCollaborationInstructions,
|
|
9033
9290
|
memoryCollaborationInstructions: workspaceBootstrapContext.memoryCollaborationInstructions,
|
|
@@ -9041,6 +9298,25 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
9041
9298
|
throwIfTurnStartAcceptedAfterAbort();
|
|
9042
9299
|
return startedTurn;
|
|
9043
9300
|
};
|
|
9301
|
+
const activeNativeTurnIds = thread.lifecycle.action === "resumed" ? thread.lifecycle.activeTurnIds ?? [] : [];
|
|
9302
|
+
if (activeNativeTurnIds.length > 0) {
|
|
9303
|
+
embeddedAgentLog.info("codex app-server resumed thread has active native turn; waiting before turn/start", {
|
|
9304
|
+
threadId: thread.threadId,
|
|
9305
|
+
activeTurnIds: activeNativeTurnIds
|
|
9306
|
+
});
|
|
9307
|
+
emitCodexAppServerEvent(params, {
|
|
9308
|
+
stream: "codex_app_server.lifecycle",
|
|
9309
|
+
data: {
|
|
9310
|
+
phase: "turn_start_waiting_for_native_turn",
|
|
9311
|
+
threadId: thread.threadId,
|
|
9312
|
+
activeTurnIds: activeNativeTurnIds
|
|
9313
|
+
}
|
|
9314
|
+
});
|
|
9315
|
+
if (!await waitForActiveNativeTurnCompletion(activeNativeTurnIds) && !runAbortController.signal.aborted) embeddedAgentLog.warn("codex app-server active native turn did not complete before turn/start wait timed out", {
|
|
9316
|
+
threadId: thread.threadId,
|
|
9317
|
+
activeTurnIds: activeNativeTurnIds
|
|
9318
|
+
});
|
|
9319
|
+
}
|
|
9044
9320
|
try {
|
|
9045
9321
|
codexModelCallDiagnostics.emitStarted();
|
|
9046
9322
|
runAgentHarnessLlmInputHook({
|
|
@@ -9058,7 +9334,24 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
9058
9334
|
turn = await startCodexTurn();
|
|
9059
9335
|
} catch (error) {
|
|
9060
9336
|
let turnStartError = error;
|
|
9061
|
-
if (
|
|
9337
|
+
if (isCodexActiveCompactTurnError(turnStartError)) {
|
|
9338
|
+
embeddedAgentLog.info("codex app-server turn/start blocked by active compact turn; waiting to retry", { threadId: thread.threadId });
|
|
9339
|
+
if (await waitForActiveNativeTurnCompletion() && !runAbortController.signal.aborted) {
|
|
9340
|
+
emitCodexAppServerEvent(params, {
|
|
9341
|
+
stream: "codex_app_server.lifecycle",
|
|
9342
|
+
data: {
|
|
9343
|
+
phase: "turn_start_retry_after_compact",
|
|
9344
|
+
threadId: thread.threadId
|
|
9345
|
+
}
|
|
9346
|
+
});
|
|
9347
|
+
try {
|
|
9348
|
+
turn = await startCodexTurn();
|
|
9349
|
+
} catch (retryError) {
|
|
9350
|
+
turnStartError = retryError;
|
|
9351
|
+
}
|
|
9352
|
+
}
|
|
9353
|
+
}
|
|
9354
|
+
if (turn === void 0 && shouldUseFreshCodexThreadAfterContextEngineOverflow({
|
|
9062
9355
|
error: turnStartError,
|
|
9063
9356
|
contextEngineActive: Boolean(activeContextEngine),
|
|
9064
9357
|
thread
|
|
@@ -9598,6 +9891,19 @@ function isCodexContextWindowError(error) {
|
|
|
9598
9891
|
const message = formatErrorMessage(error);
|
|
9599
9892
|
return /ran out of room in the model'?s context window/iu.test(message) || /context window/iu.test(message) || /context length/iu.test(message) || /maximum context/iu.test(message) || /too many tokens/iu.test(message);
|
|
9600
9893
|
}
|
|
9894
|
+
function isCodexActiveCompactTurnError(error) {
|
|
9895
|
+
if (!(error instanceof CodexAppServerRpcError)) return false;
|
|
9896
|
+
const data = isJsonObject(error.data) ? error.data : void 0;
|
|
9897
|
+
const codexErrorInfo = isJsonObject(data?.codexErrorInfo) ? data.codexErrorInfo : void 0;
|
|
9898
|
+
return (isJsonObject(codexErrorInfo?.activeTurnNotSteerable) ? codexErrorInfo.activeTurnNotSteerable : void 0)?.turnKind === "compact";
|
|
9899
|
+
}
|
|
9900
|
+
function isCodexThreadTurnCompletedNotification(notification, threadId, turnIds) {
|
|
9901
|
+
if (notification.method !== "turn/completed") return false;
|
|
9902
|
+
const correlation = describeCodexNotificationCorrelation(notification, { threadId });
|
|
9903
|
+
if (!correlation.matchesActiveThread) return false;
|
|
9904
|
+
const turnId = correlation.turnId ?? correlation.nestedTurnId;
|
|
9905
|
+
return !turnIds || turnId !== void 0 && turnIds.has(turnId);
|
|
9906
|
+
}
|
|
9601
9907
|
function joinPresentSections(...sections) {
|
|
9602
9908
|
return sections.filter((section) => Boolean(section?.trim())).join("\n\n");
|
|
9603
9909
|
}
|
|
@@ -9648,6 +9954,9 @@ function handleApprovalRequest(params) {
|
|
|
9648
9954
|
threadId: params.threadId,
|
|
9649
9955
|
turnId: params.turnId,
|
|
9650
9956
|
nativeHookRelay: params.nativeHookRelay,
|
|
9957
|
+
execPolicy: params.execPolicy,
|
|
9958
|
+
execReviewerAgentId: params.execReviewerAgentId,
|
|
9959
|
+
internalExecAutoReview: params.internalExecAutoReview,
|
|
9651
9960
|
autoApprove: params.autoApprove,
|
|
9652
9961
|
signal: params.signal
|
|
9653
9962
|
});
|