@openclaw/codex 2026.6.8 → 2026.6.9
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/{notification-correlation-BGoG0N90.js → app-server-policy-BPTiVNsW.js} +15 -74
- package/dist/attempt-notifications-7oZeRa71.js +249 -0
- package/dist/{client-DovmVtbr.js → client-CLrtWgrD.js} +24 -2
- package/dist/{client-factory-C71Xdb6z.js → client-factory-Bm6HsGob.js} +3 -2
- package/dist/{command-handlers-DHecBkuc.js → command-handlers-BaqM9s9b.js} +17 -13
- package/dist/{compact-GEKusemL.js → compact-aQJ0ZKhe.js} +5 -5
- package/dist/{computer-use-D1qxvTE_.js → computer-use-BmuwYrW6.js} +3 -3
- package/dist/{config-DJXpBkGf.js → config-CszD0vP3.js} +176 -25
- package/dist/{conversation-binding-CbnMilVW.js → conversation-binding-DbG2ZJQY.js} +166 -58
- package/dist/doctor-contract-api.js +37 -3
- package/dist/harness.js +6 -6
- package/dist/index.js +108 -27
- package/dist/media-understanding-provider-Dmfg4tH_.js +463 -0
- package/dist/media-understanding-provider.js +1 -355
- package/dist/{models-DRKnOpzF.js → models-CAmfBWRl.js} +2 -2
- package/dist/{plugin-app-cache-key-kIqpGTQj.js → plugin-app-cache-key-vaZ_8Usz.js} +17 -6
- package/dist/prompt-overlay.js +2 -6
- package/dist/{protocol-oeJQu4rs.js → protocol-dh-ETiNd.js} +4 -1
- package/dist/{protocol-validators-B48C6S9O.js → protocol-validators-B19q5BIX.js} +210 -16
- package/dist/{provider-C5P6352f.js → provider-B-OHpbD3.js} +4 -4
- package/dist/{native-hook-relay-C3i3FYtc.js → provider-capabilities-ByR82ytL.js} +803 -78
- package/dist/provider.js +1 -1
- package/dist/{request-BxZ40QKY.js → request-Dcd452Nk.js} +2 -2
- package/dist/{run-attempt-D_q-VrpR.js → run-attempt-DYt00Jxz.js} +519 -789
- package/dist/{sandbox-guard-C-Yv9uwY.js → sandbox-guard-3tnjhjFb.js} +37 -10
- package/dist/{session-binding-ElbcSq2o.js → session-binding-HOuPt-E0.js} +27 -8
- package/dist/{shared-client-jFMumCOe.js → shared-client-Dtx5i7Ez.js} +4 -4
- package/dist/{side-question-DqKLfWMB.js → side-question-h01W1aCe.js} +106 -42
- package/dist/{thread-lifecycle-cban34w3.js → thread-lifecycle-DQyii5vp.js} +948 -616
- package/dist/web-search-contract-api.js +10 -0
- package/dist/web-search-provider.runtime-BWG_oqLf.js +74 -0
- package/dist/web-search-provider.shared-BrZmlqyR.js +32 -0
- package/npm-shrinkwrap.json +2 -2
- package/openclaw.plugin.json +140 -6
- package/package.json +4 -4
|
@@ -1,34 +1,33 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { a as
|
|
3
|
-
import { t as
|
|
4
|
-
import {
|
|
5
|
-
import { a as
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import { n as
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import { t as defaultLeasedCodexAppServerClientFactory } from "./client-factory-
|
|
13
|
-
import {
|
|
14
|
-
import { t as ensureCodexComputerUse } from "./computer-use-
|
|
1
|
+
import { n as isJsonObject, t as flattenCodexDynamicToolFunctions } from "./protocol-dh-ETiNd.js";
|
|
2
|
+
import { A as resolveCodexContextEngineProjectionReserveTokens, D as fitCodexProjectedContextForTurnStart, E as resolveCodexDynamicToolsLoadingForRuntime, H as readCodexNotificationTurnId, M as buildCodexPluginThreadConfigInputFingerprint, N as mergeCodexThreadConfigs, O as projectContextEngineAssemblyForCodex, P as shouldBuildCodexPluginThreadConfig, R as defaultCodexAppInventoryCache, V as readCodexNotificationThreadId, _ as resolveCodexWebSearchPlan, a as buildDeveloperInstructions, b as sanitizeCodexHistoryImagePayloads, c as codexDynamicToolsFingerprint, f as resolveCodexAppServerThreadModelSelection, h as startOrResumeThread, i as buildContextEngineBinding, j as buildCodexPluginThreadConfig, k as resolveCodexContextEngineProjectionMaxChars, l as isContextEngineBindingCompatible, n as areCodexDynamicToolFingerprintsCompatible, o as buildTurnCollaborationMode, s as buildTurnStartParams, v as isCodexAppServerProfilerEnabled, z as describeCodexNotificationCorrelation } from "./thread-lifecycle-DQyii5vp.js";
|
|
3
|
+
import { C as readNotificationItemId, E as updateActiveTurnItemIds, S as readCodexNotificationItem, T as shouldDisarmAssistantCompletionIdleWatch, _ as isReasoningItemCompletionNotification, a as isCodexNotificationOutsideActiveRun, b as isTerminalTurnStatus, c as isCurrentThreadOptionalTurnRequestParams, d as isNativeResponseStreamDeltaNotification, f as isNativeToolProgressNotification, g as isRawToolOutputCompletionNotification, h as isRawReasoningCompletionNotification, i as isAssistantCompletionReleaseNotification, l as isCurrentThreadTurnRequestParams, m as isRawAssistantProgressNotification, n as describeNotificationActivity, o as isCodexTurnAbortMarkerNotification, p as isPendingOpenClawDynamicToolCompletionNotification, r as isAssistantCommentaryCompletionNotification, s as isCurrentApprovalTurnRequestParams, t as codexExecutionToolName, u as isFileChangePatchUpdatedNotification, v as isReasoningProgressNotification, w as readRawResponseToolCallId, x as isTurnNotification, y as isRetryableErrorNotification } from "./attempt-notifications-7oZeRa71.js";
|
|
4
|
+
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-CszD0vP3.js";
|
|
5
|
+
import { a as readCodexDynamicToolCallParams, c as readCodexTurn, i as assertCodexTurnStartResponse } from "./protocol-validators-B19q5BIX.js";
|
|
6
|
+
import { i as formatCodexUsageLimitErrorMessage, o as resolveCodexUsageLimitResetAtMs, s as shouldRefreshCodexRateLimitsForUsageLimitMessage } from "./provider-B-OHpbD3.js";
|
|
7
|
+
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-CLrtWgrD.js";
|
|
8
|
+
import { i as isCodexAppServerNativeAuthProfile, l as writeCodexAppServerBinding, n as clearCodexAppServerBinding, o as readCodexAppServerBinding, r as clearCodexAppServerBindingForThread } from "./session-binding-HOuPt-E0.js";
|
|
9
|
+
import { n as buildCodexPluginAppCacheKey, r as CODEX_CONTROL_METHODS, t as buildCodexAppServerRuntimeFingerprint } from "./plugin-app-cache-key-vaZ_8Usz.js";
|
|
10
|
+
import { a as formatCodexDisplayText, n as resolveCodexAppServerForOpenClawToolPolicy, t as resolveCodexAppServerForModelProvider } from "./app-server-policy-BPTiVNsW.js";
|
|
11
|
+
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-Dtx5i7Ez.js";
|
|
12
|
+
import { t as defaultLeasedCodexAppServerClientFactory } from "./client-factory-Bm6HsGob.js";
|
|
13
|
+
import { A as CODEX_POST_REASONING_REPLY_IDLE_TIMEOUT_MS, C as resolveCodexMessageToolProvider, D as shouldWarnCodexDynamicToolBuildStageSummary, E as shouldRequireCodexSandboxExecServerEnvironment, F as resolveCodexTurnTerminalIdleTimeoutMs, I as withCodexStartupTimeout, M as resolveCodexStartupTimeoutMs, N as resolveCodexTurnAssistantCompletionIdleTimeoutMs, P as resolveCodexTurnCompletionIdleTimeoutMs, S as resolveCodexExternalSandboxPolicyForOpenClawSandbox, T as shouldEnableCodexAppServerNativeToolSurface, _ as createCodexDynamicToolBuildStageTracker, a as buildCodexNativeHookRelayConfig, b as resolveCodexAppServerExecutionCwd, c as resolveCodexNativeHookRelayEvents, d as handleCodexAppServerElicitationRequest, f as createCodexDynamicToolBridge, g as buildDynamicTools, h as emitDynamicToolTerminalDiagnostic, i as CODEX_NATIVE_HOOK_RELAY_TTL_GRACE_MS, j as resolveCodexPostToolRawAssistantCompletionIdleTimeoutMs, k as handleCodexAppServerApprovalRequest, l as resolveCodexNativeHookRelayTtlMs, m as emitDynamicToolStartedDiagnostic, o as buildCodexNativeHookRelayDisabledConfig, p as emitDynamicToolErrorDiagnostic, s as createCodexNativeHookRelay, t as resolveCodexProviderWebSearchSupport, u as scheduleCodexNativeHookRelayUnregister, v as disableCodexPluginThreadConfig, w as resolveCodexSandboxEnvironmentSelection, x as resolveCodexAppServerHookChannelId, y as formatCodexDynamicToolBuildStageSummary } from "./provider-capabilities-ByR82ytL.js";
|
|
14
|
+
import { t as ensureCodexComputerUse } from "./computer-use-BmuwYrW6.js";
|
|
15
15
|
import { n as rememberCodexRateLimits, t as readRecentCodexRateLimits } from "./rate-limit-cache-C7qmZ0Jh.js";
|
|
16
|
+
import fs from "node:fs/promises";
|
|
17
|
+
import path, { posix } from "node:path";
|
|
16
18
|
import { asDateTimestampMs, parseStrictNonNegativeInteger, resolveTimerTimeoutMs } from "openclaw/plugin-sdk/number-runtime";
|
|
19
|
+
import { asFiniteNumber, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
17
20
|
import { createHash, randomUUID } from "node:crypto";
|
|
18
21
|
import fsSync from "node:fs";
|
|
19
|
-
import path, { posix } from "node:path";
|
|
20
22
|
import { markAuthProfileBlockedUntil, resolveAgentDir, resolveAgentWorkspaceDir } from "openclaw/plugin-sdk/agent-runtime";
|
|
21
23
|
import { loadExecApprovals } from "openclaw/plugin-sdk/exec-approvals-runtime";
|
|
22
|
-
import {
|
|
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";
|
|
24
|
+
import { CODEX_APP_SERVER_CONTEXT_ENGINE_HOST, TOOL_PROGRESS_OUTPUT_MAX_CHARS, acquireSessionWriteLock, appendSessionTranscriptMessage, assembleHarnessContextEngine, assertContextEngineHostSupport, awaitAgentHarnessAgentEndHook, bootstrapHarnessContextEngine, buildBootstrapContextForFiles, buildHarnessContextEngineRuntimeContext, buildHarnessContextEngineRuntimeContextFromUsage, classifyAgentHarnessTerminalOutcome, clearActiveEmbeddedRun, embeddedAgentLog, emitAgentEvent, emitSessionTranscriptUpdate, finalizeHarnessContextEngineTurn, formatErrorMessage, formatToolAggregate, formatToolProgressOutput, getAgentHarnessHookRunner, getBeforeToolCallPolicyDiagnosticState, inferToolMetaFromArgs, isActiveHarnessContextEngine, loadCodexBundleMcpThreadConfig, normalizeUsage, resolveAgentHarnessBeforePromptBuildResult, resolveBootstrapFilesForRun, resolveContextEngineOwnerPluginId, 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";
|
|
24
25
|
import { buildMemorySystemPromptAddition } from "openclaw/plugin-sdk/core";
|
|
25
26
|
import { spawn } from "node:child_process";
|
|
26
27
|
import { once } from "node:events";
|
|
27
28
|
import { WebSocketServer } from "ws";
|
|
28
29
|
import { redactSensitiveFieldValue, redactToolPayloadText } from "openclaw/plugin-sdk/logging-core";
|
|
29
|
-
import fs from "node:fs/promises";
|
|
30
30
|
import { createDiagnosticTraceContextFromActiveScope, emitTrustedDiagnosticEvent, emitTrustedDiagnosticEventWithPrivateData, freezeDiagnosticTraceContext, hasPendingInternalDiagnosticEvent, onInternalDiagnosticEvent, resolveDiagnosticModelContentCapturePolicy } from "openclaw/plugin-sdk/diagnostic-runtime";
|
|
31
|
-
import { isToolAllowed } from "openclaw/plugin-sdk/sandbox";
|
|
32
31
|
import { appendRegularFile, pathExists } from "openclaw/plugin-sdk/security-runtime";
|
|
33
32
|
import { MESSAGE_TOOL_DELIVERY_HINTS } from "openclaw/plugin-sdk/message-tool-delivery-hints";
|
|
34
33
|
import { buildSessionContext, migrateSessionEntries, parseSessionEntries } from "openclaw/plugin-sdk/agent-sessions";
|
|
@@ -39,12 +38,42 @@ import { saveMediaBuffer } from "openclaw/plugin-sdk/media-store";
|
|
|
39
38
|
import { createAgentHarnessTaskRuntime, deliverAgentHarnessTaskCompletion, isDurableAgentHarnessCompletionDelivery } from "openclaw/plugin-sdk/agent-harness-task-runtime";
|
|
40
39
|
//#region extensions/codex/src/app-server/attempt-client-cleanup.ts
|
|
41
40
|
/**
|
|
42
|
-
* Best-effort cleanup helpers for
|
|
41
|
+
* Best-effort cleanup helpers for Codex app-server startup attempts and turns.
|
|
43
42
|
*/
|
|
44
43
|
/** Timeout for best-effort app-server turn interruption during cleanup. */
|
|
45
44
|
const CODEX_APP_SERVER_INTERRUPT_TIMEOUT_MS = 5e3;
|
|
46
45
|
/** Timeout for best-effort thread unsubscribe during cleanup. */
|
|
47
46
|
const CODEX_APP_SERVER_UNSUBSCRIBE_TIMEOUT_MS = 5e3;
|
|
47
|
+
async function closeClientAndWaitIfAvailable(client) {
|
|
48
|
+
const closeable = client;
|
|
49
|
+
if (typeof closeable.closeAndWait === "function") {
|
|
50
|
+
await closeable.closeAndWait();
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
closeable.close?.();
|
|
54
|
+
}
|
|
55
|
+
async function closeCodexStartupClientBestEffort(client) {
|
|
56
|
+
if (!client) return;
|
|
57
|
+
const unclaimedSharedClient = clearSharedCodexAppServerClientIfCurrentAndUnclaimed(client);
|
|
58
|
+
if (unclaimedSharedClient.closed) {
|
|
59
|
+
await closeClientAndWaitIfAvailable(client);
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
if (unclaimedSharedClient.found) {
|
|
63
|
+
if (retireSharedCodexAppServerClientIfCurrent(client)?.closed) await closeClientAndWaitIfAvailable(client);
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
const retiredSharedClient = retireSharedCodexAppServerClientIfCurrent(client);
|
|
67
|
+
if (retiredSharedClient) {
|
|
68
|
+
if (retiredSharedClient.closed) await closeClientAndWaitIfAvailable(client);
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
if (clearSharedCodexAppServerClientIfCurrent(client)) {
|
|
72
|
+
await closeClientAndWaitIfAvailable(client);
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
await closeClientAndWaitIfAvailable(client);
|
|
76
|
+
}
|
|
48
77
|
/** Sends a turn interrupt without blocking abort cleanup on app-server errors. */
|
|
49
78
|
function interruptCodexTurnBestEffort(client, params) {
|
|
50
79
|
const requestOptions = params.timeoutMs && Number.isFinite(params.timeoutMs) && params.timeoutMs > 0 ? { timeoutMs: params.timeoutMs } : void 0;
|
|
@@ -293,7 +322,7 @@ async function buildCodexWorkspaceBootstrapContext(params) {
|
|
|
293
322
|
* report for a Codex run.
|
|
294
323
|
*/
|
|
295
324
|
function buildCodexSystemPromptReport(params) {
|
|
296
|
-
const toolEntries = params.tools.map(buildCodexToolReportEntry);
|
|
325
|
+
const toolEntries = flattenCodexDynamicToolFunctions(params.tools).map(buildCodexToolReportEntry);
|
|
297
326
|
const schemaChars = toolEntries.reduce((sum, tool) => sum + tool.schemaChars, 0);
|
|
298
327
|
const skillsPrompt = params.skillsPrompt.trim();
|
|
299
328
|
const bootstrapMaxChars = readPositiveNumber(params.attempt.config?.agents?.defaults?.bootstrapMaxChars);
|
|
@@ -389,7 +418,7 @@ function stableJsonHash(value) {
|
|
|
389
418
|
function buildCodexBootstrapInjectionStats(params) {
|
|
390
419
|
const injectedIndex = indexCodexContextFileContent(params.injectedFiles);
|
|
391
420
|
const developerInstructionIndex = indexCodexContextFileContent(params.developerInstructionFiles ?? []);
|
|
392
|
-
const memoryToolRoutedPaths = new Set((params.memoryToolRoutedBootstrapFiles ?? []).map((file) => readNonEmptyString$1(file.path)).filter(isNonEmptyString$
|
|
421
|
+
const memoryToolRoutedPaths = new Set((params.memoryToolRoutedBootstrapFiles ?? []).map((file) => readNonEmptyString$1(file.path)).filter(isNonEmptyString$1).map(normalizeCodexContextFilePath));
|
|
393
422
|
return params.bootstrapFiles.map((file) => {
|
|
394
423
|
const fileName = readNonEmptyString$1(file.name);
|
|
395
424
|
const pathValue = readNonEmptyString$1(file.path) ?? fileName ?? "";
|
|
@@ -459,7 +488,7 @@ function buildCodexOpenClawPromptContext(params) {
|
|
|
459
488
|
"## OpenClaw Workspace Context",
|
|
460
489
|
"",
|
|
461
490
|
params.workspacePromptContext.trim()
|
|
462
|
-
].join("\n") : void 0].filter(isNonEmptyString$
|
|
491
|
+
].join("\n") : void 0].filter(isNonEmptyString$1);
|
|
463
492
|
if (sections.length === 0) return;
|
|
464
493
|
return [
|
|
465
494
|
"OpenClaw runtime context for this turn:",
|
|
@@ -619,7 +648,7 @@ function renderCodexWorkspaceMemoryCollaborationInstructions(params) {
|
|
|
619
648
|
}) : void 0, renderCodexWorkspaceMemoryReference({
|
|
620
649
|
files: params.files,
|
|
621
650
|
toolNames: params.toolNames
|
|
622
|
-
})].filter(isNonEmptyString$
|
|
651
|
+
})].filter(isNonEmptyString$1);
|
|
623
652
|
return sections.length > 0 ? sections.join("\n\n") : void 0;
|
|
624
653
|
}
|
|
625
654
|
function renderCodexMemoryRecallInstructions(params) {
|
|
@@ -628,7 +657,7 @@ function renderCodexMemoryRecallInstructions(params) {
|
|
|
628
657
|
citationsMode: params.citationsMode
|
|
629
658
|
});
|
|
630
659
|
if (!memoryPrompt) return;
|
|
631
|
-
return [memoryPrompt, renderCodexMemoryToolSearchBridge(params.toolNames)].filter(isNonEmptyString$
|
|
660
|
+
return [memoryPrompt, renderCodexMemoryToolSearchBridge(params.toolNames)].filter(isNonEmptyString$1).join("\n").trim();
|
|
632
661
|
}
|
|
633
662
|
function renderCodexMemoryToolSearchBridge(toolNames) {
|
|
634
663
|
const memoryToolNames = toolNames.map((name) => normalizeCodexDynamicToolName(name)).filter((name) => CODEX_MEMORY_TOOL_NAMES.has(name)).toSorted();
|
|
@@ -637,7 +666,7 @@ function renderCodexMemoryToolSearchBridge(toolNames) {
|
|
|
637
666
|
}
|
|
638
667
|
/** Lists available memory tool names understood by Codex workspace memory routing. */
|
|
639
668
|
function getCodexWorkspaceMemoryToolNames(tools) {
|
|
640
|
-
const availableToolNames = new Set(tools.map((tool) => normalizeCodexDynamicToolName(tool.name)));
|
|
669
|
+
const availableToolNames = new Set(flattenCodexDynamicToolFunctions(tools).map((tool) => normalizeCodexDynamicToolName(tool.name)));
|
|
641
670
|
return Array.from(CODEX_MEMORY_TOOL_NAMES).filter((name) => availableToolNames.has(name));
|
|
642
671
|
}
|
|
643
672
|
function canRouteCodexWorkspaceMemoryThroughTools(params) {
|
|
@@ -714,7 +743,7 @@ function getCodexContextFileBasename(filePath) {
|
|
|
714
743
|
function normalizeCodexDynamicToolName(name) {
|
|
715
744
|
return name.trim().toLowerCase();
|
|
716
745
|
}
|
|
717
|
-
function isNonEmptyString$
|
|
746
|
+
function isNonEmptyString$1(value) {
|
|
718
747
|
return typeof value === "string" && value.length > 0;
|
|
719
748
|
}
|
|
720
749
|
//#endregion
|
|
@@ -843,236 +872,6 @@ function classifyCodexModelCallFailureKind(params) {
|
|
|
843
872
|
return errorMessage.includes("aborted") ? "aborted" : void 0;
|
|
844
873
|
}
|
|
845
874
|
//#endregion
|
|
846
|
-
//#region extensions/codex/src/app-server/attempt-notifications.ts
|
|
847
|
-
/**
|
|
848
|
-
* Predicates and readers for Codex app-server notification envelopes.
|
|
849
|
-
*/
|
|
850
|
-
const CODEX_TURN_ABORT_MARKER_START = "<turn_aborted>";
|
|
851
|
-
const CODEX_TURN_ABORT_MARKER_END = "</turn_aborted>";
|
|
852
|
-
const CODEX_INTERRUPTED_USER_GUIDANCE = "The user interrupted the previous turn on purpose. Any running unified exec processes may still be running in the background. If any tools/commands were aborted, they may have partially executed.";
|
|
853
|
-
const CODEX_INTERRUPTED_DEVELOPER_GUIDANCE = "The previous turn was interrupted on purpose. Any running unified exec processes may still be running in the background. If any tools/commands were aborted, they may have partially executed.";
|
|
854
|
-
/** Builds compact activity metadata for watchdog and diagnostic updates. */
|
|
855
|
-
function describeNotificationActivity(notification) {
|
|
856
|
-
if (!isJsonObject(notification.params)) return { lastNotificationMethod: notification.method };
|
|
857
|
-
if (notification.method !== "rawResponseItem/completed") return { lastNotificationMethod: notification.method };
|
|
858
|
-
const item = isJsonObject(notification.params.item) ? notification.params.item : void 0;
|
|
859
|
-
if (!item) return { lastNotificationMethod: notification.method };
|
|
860
|
-
return {
|
|
861
|
-
lastNotificationMethod: notification.method,
|
|
862
|
-
lastNotificationItemId: readString$6(item, "id"),
|
|
863
|
-
lastNotificationItemType: readString$6(item, "type"),
|
|
864
|
-
lastNotificationItemRole: readString$6(item, "role"),
|
|
865
|
-
lastAssistantTextPreview: readRawAssistantTextPreview(item)
|
|
866
|
-
};
|
|
867
|
-
}
|
|
868
|
-
/** Tracks active app-server item ids from item start/completion notifications. */
|
|
869
|
-
function updateActiveTurnItemIds(notification, activeItemIds) {
|
|
870
|
-
if (notification.method !== "item/started" && notification.method !== "item/completed") return;
|
|
871
|
-
const itemId = readNotificationItemId(notification);
|
|
872
|
-
if (!itemId) return;
|
|
873
|
-
if (notification.method === "item/started") {
|
|
874
|
-
activeItemIds.add(itemId);
|
|
875
|
-
return;
|
|
876
|
-
}
|
|
877
|
-
activeItemIds.delete(itemId);
|
|
878
|
-
}
|
|
879
|
-
function isCompletedAssistantNotification(notification) {
|
|
880
|
-
if (!isJsonObject(notification.params)) return false;
|
|
881
|
-
if (notification.method !== "item/completed") return false;
|
|
882
|
-
const item = isJsonObject(notification.params.item) ? notification.params.item : void 0;
|
|
883
|
-
return Boolean(item && readString$6(item, "type") === "agentMessage" && readString$6(item, "phase") !== "commentary");
|
|
884
|
-
}
|
|
885
|
-
/** Returns true for completed app-server reasoning items. */
|
|
886
|
-
function isReasoningItemCompletionNotification(notification) {
|
|
887
|
-
if (!isJsonObject(notification.params) || notification.method !== "item/completed") return false;
|
|
888
|
-
const item = isJsonObject(notification.params.item) ? notification.params.item : void 0;
|
|
889
|
-
return item ? readString$6(item, "type") === "reasoning" : false;
|
|
890
|
-
}
|
|
891
|
-
/** Returns true for completed assistant commentary items. */
|
|
892
|
-
function isAssistantCommentaryCompletionNotification(notification) {
|
|
893
|
-
if (!isJsonObject(notification.params) || notification.method !== "item/completed") return false;
|
|
894
|
-
const item = isJsonObject(notification.params.item) ? notification.params.item : void 0;
|
|
895
|
-
return Boolean(item && readString$6(item, "type") === "agentMessage" && readString$6(item, "phase") === "commentary");
|
|
896
|
-
}
|
|
897
|
-
/** Returns true for completed raw response reasoning items. */
|
|
898
|
-
function isRawReasoningCompletionNotification(notification) {
|
|
899
|
-
if (!isJsonObject(notification.params) || notification.method !== "rawResponseItem/completed") return false;
|
|
900
|
-
const item = isJsonObject(notification.params.item) ? notification.params.item : void 0;
|
|
901
|
-
return item ? readString$6(item, "type") === "reasoning" : false;
|
|
902
|
-
}
|
|
903
|
-
/** Returns true for streamed app-server reasoning progress. */
|
|
904
|
-
function isReasoningProgressNotification(notification) {
|
|
905
|
-
return notification.method === "item/reasoning/textDelta" || notification.method === "item/reasoning/summaryTextDelta" || notification.method === "item/reasoning/summaryPartAdded";
|
|
906
|
-
}
|
|
907
|
-
/** Returns true when assistant completion can release the short idle watch. */
|
|
908
|
-
function isAssistantCompletionReleaseNotification(notification, turnCrossedToolHandoff) {
|
|
909
|
-
if (isCompletedAssistantNotification(notification)) return true;
|
|
910
|
-
return !turnCrossedToolHandoff && isRawAssistantCompletionNotification(notification);
|
|
911
|
-
}
|
|
912
|
-
/** Returns true when a notification proves assistant output is still active. */
|
|
913
|
-
function shouldDisarmAssistantCompletionIdleWatch(notification) {
|
|
914
|
-
if (!isJsonObject(notification.params)) return false;
|
|
915
|
-
if (notification.method === "item/started") return true;
|
|
916
|
-
if (notification.method === "item/agentMessage/delta") return true;
|
|
917
|
-
return false;
|
|
918
|
-
}
|
|
919
|
-
/** Reads an item id from supported notification envelope shapes. */
|
|
920
|
-
function readNotificationItemId(notification) {
|
|
921
|
-
if (!isJsonObject(notification.params)) return;
|
|
922
|
-
const item = isJsonObject(notification.params.item) ? notification.params.item : void 0;
|
|
923
|
-
return (item ? readString$6(item, "id") : void 0) ?? readString$6(notification.params, "itemId") ?? readString$6(notification.params, "id");
|
|
924
|
-
}
|
|
925
|
-
/** Detects completion for an OpenClaw dynamic tool result still awaited by Codex. */
|
|
926
|
-
function isPendingOpenClawDynamicToolCompletionNotification(notification, pendingOpenClawDynamicToolCompletionIds) {
|
|
927
|
-
if (notification.method !== "item/completed" || !isJsonObject(notification.params)) return false;
|
|
928
|
-
const itemId = readNotificationItemId(notification);
|
|
929
|
-
if (!itemId || !pendingOpenClawDynamicToolCompletionIds.has(itemId)) return false;
|
|
930
|
-
const item = isJsonObject(notification.params.item) ? notification.params.item : void 0;
|
|
931
|
-
const itemType = item ? readString$6(item, "type") : void 0;
|
|
932
|
-
return itemType === void 0 || itemType === "dynamicToolCall";
|
|
933
|
-
}
|
|
934
|
-
/** Returns true for raw response tool-output completion notifications. */
|
|
935
|
-
function isRawToolOutputCompletionNotification(notification) {
|
|
936
|
-
if (notification.method !== "rawResponseItem/completed" || !isJsonObject(notification.params)) return false;
|
|
937
|
-
const item = isJsonObject(notification.params.item) ? notification.params.item : void 0;
|
|
938
|
-
return item ? readString$6(item, "type") === "custom_tool_call_output" : false;
|
|
939
|
-
}
|
|
940
|
-
/** Returns true for progress on Codex-native tool item types. */
|
|
941
|
-
function isNativeToolProgressNotification(notification) {
|
|
942
|
-
if (notification.method !== "item/started" && notification.method !== "item/completed" && notification.method !== "item/updated") return false;
|
|
943
|
-
if (!isJsonObject(notification.params)) return false;
|
|
944
|
-
const item = isJsonObject(notification.params.item) ? notification.params.item : void 0;
|
|
945
|
-
switch (item ? readString$6(item, "type") : void 0) {
|
|
946
|
-
case "commandExecution":
|
|
947
|
-
case "fileChange":
|
|
948
|
-
case "mcpToolCall":
|
|
949
|
-
case "webSearch": return true;
|
|
950
|
-
default: return false;
|
|
951
|
-
}
|
|
952
|
-
}
|
|
953
|
-
/** Returns true for raw native response stream delta events. */
|
|
954
|
-
function isNativeResponseStreamDeltaNotification(notification) {
|
|
955
|
-
return notification.method.startsWith("response.") && notification.method.endsWith(".delta");
|
|
956
|
-
}
|
|
957
|
-
/** Returns true for file-change patch update notifications. */
|
|
958
|
-
function isFileChangePatchUpdatedNotification(notification) {
|
|
959
|
-
return notification.method === "item/fileChange/patchUpdated" && isJsonObject(notification.params);
|
|
960
|
-
}
|
|
961
|
-
/** Returns true for raw assistant message progress with readable text. */
|
|
962
|
-
function isRawAssistantProgressNotification(notification) {
|
|
963
|
-
if (notification.method !== "rawResponseItem/completed" || !isJsonObject(notification.params)) return false;
|
|
964
|
-
const item = isJsonObject(notification.params.item) ? notification.params.item : void 0;
|
|
965
|
-
return Boolean(item && readString$6(item, "type") === "message" && readString$6(item, "role") === "assistant" && readRawAssistantTextPreview(item));
|
|
966
|
-
}
|
|
967
|
-
/** Returns true for raw assistant completion outside commentary phase. */
|
|
968
|
-
function isRawAssistantCompletionNotification(notification) {
|
|
969
|
-
if (!isRawAssistantProgressNotification(notification) || !isJsonObject(notification.params)) return false;
|
|
970
|
-
const item = isJsonObject(notification.params.item) ? notification.params.item : void 0;
|
|
971
|
-
return Boolean(item && readString$6(item, "phase") !== "commentary");
|
|
972
|
-
}
|
|
973
|
-
function readRawAssistantTextPreview(item) {
|
|
974
|
-
if (readString$6(item, "role") !== "assistant" || !Array.isArray(item.content)) return;
|
|
975
|
-
const text = item.content.flatMap((content) => {
|
|
976
|
-
if (!isJsonObject(content)) return [];
|
|
977
|
-
const contentText = readString$6(content, "text");
|
|
978
|
-
return contentText ? [contentText] : [];
|
|
979
|
-
}).join("\n").trim();
|
|
980
|
-
if (!text) return;
|
|
981
|
-
return text.length > 240 ? `${text.slice(0, 237)}...` : text;
|
|
982
|
-
}
|
|
983
|
-
/** Returns true when notification params correlate to a specific thread/turn. */
|
|
984
|
-
function isTurnNotification(value, threadId, turnId) {
|
|
985
|
-
return isCodexNotificationForTurn(value, threadId, turnId);
|
|
986
|
-
}
|
|
987
|
-
/** Returns true when a correlated notification belongs to another active run. */
|
|
988
|
-
function isCodexNotificationOutsideActiveRun(correlation) {
|
|
989
|
-
if (!Boolean(correlation.threadId || correlation.nestedTurnThreadId)) return false;
|
|
990
|
-
if (!correlation.matchesActiveThread) return true;
|
|
991
|
-
return Boolean(correlation.turnId || correlation.nestedTurnId) && correlation.matchesActiveTurn === false;
|
|
992
|
-
}
|
|
993
|
-
/** Checks request params that must contain the current thread and turn ids. */
|
|
994
|
-
function isCurrentThreadTurnRequestParams(value, threadId, turnId) {
|
|
995
|
-
if (!isJsonObject(value)) return false;
|
|
996
|
-
return readString$6(value, "threadId") === threadId && readString$6(value, "turnId") === turnId;
|
|
997
|
-
}
|
|
998
|
-
/** Checks approval request params, accepting `conversationId` as thread id. */
|
|
999
|
-
function isCurrentApprovalTurnRequestParams(value, threadId, turnId) {
|
|
1000
|
-
if (!isJsonObject(value)) return false;
|
|
1001
|
-
return (readString$6(value, "threadId") ?? readString$6(value, "conversationId")) === threadId && readString$6(value, "turnId") === turnId;
|
|
1002
|
-
}
|
|
1003
|
-
/** Checks request params where `turnId` may be omitted or null for the thread. */
|
|
1004
|
-
function isCurrentThreadOptionalTurnRequestParams(value, threadId, turnId) {
|
|
1005
|
-
if (!isJsonObject(value) || readString$6(value, "threadId") !== threadId) return false;
|
|
1006
|
-
const requestTurnId = value.turnId;
|
|
1007
|
-
return requestTurnId === null || requestTurnId === void 0 || requestTurnId === turnId;
|
|
1008
|
-
}
|
|
1009
|
-
/** Returns true for app-server error notifications that will retry. */
|
|
1010
|
-
function isRetryableErrorNotification(value) {
|
|
1011
|
-
if (!isJsonObject(value)) return false;
|
|
1012
|
-
return readBoolean$1(value, "willRetry") === true || readBoolean$1(value, "will_retry") === true;
|
|
1013
|
-
}
|
|
1014
|
-
/** Returns true for terminal app-server thread status strings. */
|
|
1015
|
-
function isTerminalTurnStatus(status) {
|
|
1016
|
-
return status === "completed" || status === "interrupted" || status === "failed";
|
|
1017
|
-
}
|
|
1018
|
-
/**
|
|
1019
|
-
* Detects Codex's synthetic interrupted-turn marker while ignoring the current
|
|
1020
|
-
* user prompt echoed through raw response events.
|
|
1021
|
-
*/
|
|
1022
|
-
function isCodexTurnAbortMarkerNotification(notification, options = {}) {
|
|
1023
|
-
if (notification.method !== "rawResponseItem/completed" || !isJsonObject(notification.params)) return false;
|
|
1024
|
-
const item = notification.params.item;
|
|
1025
|
-
const role = isJsonObject(item) ? readString$6(item, "role") : void 0;
|
|
1026
|
-
if (!isJsonObject(item) || role !== "user" && role !== "developer") return false;
|
|
1027
|
-
const text = extractRawResponseItemText(item).trim();
|
|
1028
|
-
const currentPromptTexts = [options.currentPromptText, ...options.currentPromptTexts ?? []].filter(isNonEmptyString$1).map((prompt) => prompt.trim());
|
|
1029
|
-
if (role === "user" && currentPromptTexts.includes(text)) return false;
|
|
1030
|
-
const markerBody = readCodexTurnAbortMarkerBody(text);
|
|
1031
|
-
return markerBody === CODEX_INTERRUPTED_USER_GUIDANCE || markerBody === CODEX_INTERRUPTED_DEVELOPER_GUIDANCE;
|
|
1032
|
-
}
|
|
1033
|
-
function readCodexTurnAbortMarkerBody(text) {
|
|
1034
|
-
if (!text.startsWith(CODEX_TURN_ABORT_MARKER_START) || !text.endsWith(CODEX_TURN_ABORT_MARKER_END)) return;
|
|
1035
|
-
return text.slice(14, -15).trim();
|
|
1036
|
-
}
|
|
1037
|
-
function extractRawResponseItemText(item) {
|
|
1038
|
-
const content = item.content;
|
|
1039
|
-
if (!Array.isArray(content)) return "";
|
|
1040
|
-
return content.flatMap((entry) => {
|
|
1041
|
-
if (!isJsonObject(entry)) return [];
|
|
1042
|
-
const type = readString$6(entry, "type");
|
|
1043
|
-
if (type !== "input_text" && type !== "text") return [];
|
|
1044
|
-
const text = readString$6(entry, "text");
|
|
1045
|
-
return text ? [text] : [];
|
|
1046
|
-
}).join("");
|
|
1047
|
-
}
|
|
1048
|
-
function readString$6(record, key) {
|
|
1049
|
-
const value = record[key];
|
|
1050
|
-
return typeof value === "string" ? value : void 0;
|
|
1051
|
-
}
|
|
1052
|
-
function readBoolean$1(record, key) {
|
|
1053
|
-
return asBoolean(record[key]);
|
|
1054
|
-
}
|
|
1055
|
-
/** Reads a typed Codex item from notification params when id/type are present. */
|
|
1056
|
-
function readCodexNotificationItem(params) {
|
|
1057
|
-
if (!isJsonObject(params) || !isJsonObject(params.item)) return;
|
|
1058
|
-
const item = params.item;
|
|
1059
|
-
return typeof item.id === "string" && typeof item.type === "string" ? item : void 0;
|
|
1060
|
-
}
|
|
1061
|
-
/** Maps Codex item types to the tool name shown in execution progress. */
|
|
1062
|
-
function codexExecutionToolName(item) {
|
|
1063
|
-
if (item.type === "dynamicToolCall" && typeof item.tool === "string") return item.tool;
|
|
1064
|
-
if (item.type === "mcpToolCall" && typeof item.tool === "string") {
|
|
1065
|
-
const server = typeof item.server === "string" && item.server ? item.server : void 0;
|
|
1066
|
-
return server ? `${server}.${item.tool}` : item.tool;
|
|
1067
|
-
}
|
|
1068
|
-
if (item.type === "commandExecution") return "bash";
|
|
1069
|
-
if (item.type === "fileChange") return "apply_patch";
|
|
1070
|
-
if (item.type === "webSearch") return "web_search";
|
|
1071
|
-
}
|
|
1072
|
-
function isNonEmptyString$1(value) {
|
|
1073
|
-
return typeof value === "string" && value.length > 0;
|
|
1074
|
-
}
|
|
1075
|
-
//#endregion
|
|
1076
875
|
//#region extensions/codex/src/app-server/attempt-notification-state.ts
|
|
1077
876
|
/**
|
|
1078
877
|
* State machine for Codex app-server turn notifications and idle-watch updates.
|
|
@@ -1224,6 +1023,7 @@ function buildCodexTurnStartFailureResult(params) {
|
|
|
1224
1023
|
assistantTexts: [],
|
|
1225
1024
|
toolMetas: [],
|
|
1226
1025
|
lastAssistant: void 0,
|
|
1026
|
+
currentAttemptAssistant: void 0,
|
|
1227
1027
|
didSendViaMessagingTool: false,
|
|
1228
1028
|
messagingToolSentTexts: [],
|
|
1229
1029
|
messagingToolSentMediaUrls: [],
|
|
@@ -1249,396 +1049,6 @@ function isInvalidCodexImagePayloadError(message) {
|
|
|
1249
1049
|
return /\b(?:invalid|malformed)\b[\s\S]{0,120}\b(?:image|image url|base64)\b/iu.test(normalizedMessage) || /\b(?:image|image url|base64)\b[\s\S]{0,120}\b(?:invalid|malformed)\b/iu.test(normalizedMessage);
|
|
1250
1050
|
}
|
|
1251
1051
|
//#endregion
|
|
1252
|
-
//#region extensions/codex/src/app-server/dynamic-tool-build.ts
|
|
1253
|
-
/**
|
|
1254
|
-
* Builds the Codex app-server dynamic tool list for one turn, including
|
|
1255
|
-
* OpenClaw-owned tools, Codex native-tool fallback rules, sandbox shell shims,
|
|
1256
|
-
* and provider allowlist normalization.
|
|
1257
|
-
*/
|
|
1258
|
-
const CODEX_NATIVE_SANDBOX_TOOL_REQUIREMENTS = [
|
|
1259
|
-
"exec",
|
|
1260
|
-
"process",
|
|
1261
|
-
"read",
|
|
1262
|
-
"write",
|
|
1263
|
-
"edit",
|
|
1264
|
-
"apply_patch"
|
|
1265
|
-
];
|
|
1266
|
-
const CODEX_MEMORY_FLUSH_DYNAMIC_TOOL_ALLOW = new Set(["read", "write"]);
|
|
1267
|
-
/** Splits sandbox and run session keys so tool calls can bind to both scopes when needed. */
|
|
1268
|
-
function resolveOpenClawCodingToolsSessionKeys(params, sandboxSessionKey) {
|
|
1269
|
-
return {
|
|
1270
|
-
sessionKey: sandboxSessionKey,
|
|
1271
|
-
runSessionKey: params.sessionKey && params.sessionKey !== sandboxSessionKey ? params.sessionKey : void 0
|
|
1272
|
-
};
|
|
1273
|
-
}
|
|
1274
|
-
/** Resolves the channel id that hook events should target for this Codex app-server turn. */
|
|
1275
|
-
function resolveCodexAppServerHookChannelId(params, sandboxSessionKey) {
|
|
1276
|
-
return buildAgentHookContextChannelFields({
|
|
1277
|
-
sessionKey: sandboxSessionKey,
|
|
1278
|
-
messageChannel: params.messageChannel,
|
|
1279
|
-
messageProvider: params.messageProvider,
|
|
1280
|
-
currentChannelId: params.currentChannelId,
|
|
1281
|
-
messageTo: params.messageTo
|
|
1282
|
-
}).channelId;
|
|
1283
|
-
}
|
|
1284
|
-
const CODEX_DYNAMIC_TOOL_BUILD_WARN_TOTAL_MS = 1e3;
|
|
1285
|
-
const CODEX_DYNAMIC_TOOL_BUILD_WARN_STAGE_MS = 500;
|
|
1286
|
-
/** Creates cheap optional timing instrumentation for the dynamic-tool hot path. */
|
|
1287
|
-
function createCodexDynamicToolBuildStageTracker(options = {}) {
|
|
1288
|
-
if (!options.enabled) return {
|
|
1289
|
-
mark() {},
|
|
1290
|
-
snapshot() {
|
|
1291
|
-
return {
|
|
1292
|
-
totalMs: 0,
|
|
1293
|
-
stages: []
|
|
1294
|
-
};
|
|
1295
|
-
}
|
|
1296
|
-
};
|
|
1297
|
-
const startedAt = Date.now();
|
|
1298
|
-
let previousAt = startedAt;
|
|
1299
|
-
const stages = [];
|
|
1300
|
-
const toMs = (value) => Math.max(0, Math.round(value));
|
|
1301
|
-
return {
|
|
1302
|
-
mark(name) {
|
|
1303
|
-
const currentAt = Date.now();
|
|
1304
|
-
stages.push({
|
|
1305
|
-
name,
|
|
1306
|
-
durationMs: toMs(currentAt - previousAt),
|
|
1307
|
-
elapsedMs: toMs(currentAt - startedAt)
|
|
1308
|
-
});
|
|
1309
|
-
previousAt = currentAt;
|
|
1310
|
-
},
|
|
1311
|
-
snapshot() {
|
|
1312
|
-
return {
|
|
1313
|
-
totalMs: toMs(Date.now() - startedAt),
|
|
1314
|
-
stages: stages.slice()
|
|
1315
|
-
};
|
|
1316
|
-
}
|
|
1317
|
-
};
|
|
1318
|
-
}
|
|
1319
|
-
/** Returns true when dynamic-tool construction is slow enough to warrant a warning log. */
|
|
1320
|
-
function shouldWarnCodexDynamicToolBuildStageSummary(summary) {
|
|
1321
|
-
return summary.totalMs >= CODEX_DYNAMIC_TOOL_BUILD_WARN_TOTAL_MS || summary.stages.some((stage) => stage.durationMs >= CODEX_DYNAMIC_TOOL_BUILD_WARN_STAGE_MS);
|
|
1322
|
-
}
|
|
1323
|
-
/** Formats per-stage timings into the compact form used by Codex app-server logs. */
|
|
1324
|
-
function formatCodexDynamicToolBuildStageSummary(summary) {
|
|
1325
|
-
return summary.stages.length > 0 ? summary.stages.map((stage) => `${stage.name}:${stage.durationMs}ms@${stage.elapsedMs}ms`).join(",") : "none";
|
|
1326
|
-
}
|
|
1327
|
-
/** Builds, filters, and normalizes Codex-compatible runtime tools for a single turn. */
|
|
1328
|
-
async function buildDynamicTools(input) {
|
|
1329
|
-
const { params } = input;
|
|
1330
|
-
if (params.disableTools || !supportsModelTools(params.model)) return [];
|
|
1331
|
-
const toolBuildStages = createCodexDynamicToolBuildStageTracker({ enabled: input.profilerEnabled });
|
|
1332
|
-
const modelHasVision = params.model.input?.includes("image") ?? false;
|
|
1333
|
-
const agentDir = params.agentDir ?? resolveAgentDir(params.config ?? {}, input.sessionAgentId);
|
|
1334
|
-
const createOpenClawCodingTools = (await import("openclaw/plugin-sdk/agent-harness")).createOpenClawCodingTools;
|
|
1335
|
-
toolBuildStages.mark("load-agent-harness-tools");
|
|
1336
|
-
const sessionKeys = resolveOpenClawCodingToolsSessionKeys(params, input.sandboxSessionKey);
|
|
1337
|
-
const allTools = createOpenClawCodingTools({
|
|
1338
|
-
agentId: input.sessionAgentId,
|
|
1339
|
-
...buildEmbeddedAttemptToolRunContext(params),
|
|
1340
|
-
exec: {
|
|
1341
|
-
...params.execOverrides,
|
|
1342
|
-
config: params.config,
|
|
1343
|
-
elevated: params.bashElevated
|
|
1344
|
-
},
|
|
1345
|
-
sandbox: input.sandbox,
|
|
1346
|
-
messageProvider: params.messageChannel ?? params.messageProvider,
|
|
1347
|
-
agentAccountId: params.agentAccountId,
|
|
1348
|
-
messageTo: params.messageTo,
|
|
1349
|
-
messageThreadId: params.messageThreadId,
|
|
1350
|
-
groupId: params.groupId,
|
|
1351
|
-
groupChannel: params.groupChannel,
|
|
1352
|
-
groupSpace: params.groupSpace,
|
|
1353
|
-
spawnedBy: params.spawnedBy,
|
|
1354
|
-
senderId: params.senderId,
|
|
1355
|
-
senderName: params.senderName,
|
|
1356
|
-
senderUsername: params.senderUsername,
|
|
1357
|
-
senderE164: params.senderE164,
|
|
1358
|
-
allowGatewaySubagentBinding: params.allowGatewaySubagentBinding || isForcedPrivateQaCodexRuntime(),
|
|
1359
|
-
...sessionKeys,
|
|
1360
|
-
sessionId: params.sessionId,
|
|
1361
|
-
runId: params.runId,
|
|
1362
|
-
agentDir,
|
|
1363
|
-
cwd: input.effectiveCwd ?? input.effectiveWorkspace,
|
|
1364
|
-
workspaceDir: input.effectiveWorkspace,
|
|
1365
|
-
spawnWorkspaceDir: input.effectiveCwd && input.effectiveCwd !== input.effectiveWorkspace ? input.resolvedWorkspace : resolveAttemptSpawnWorkspaceDir({
|
|
1366
|
-
sandbox: input.sandbox,
|
|
1367
|
-
resolvedWorkspace: input.resolvedWorkspace
|
|
1368
|
-
}),
|
|
1369
|
-
config: params.config,
|
|
1370
|
-
authProfileStore: params.toolAuthProfileStore ?? params.authProfileStore,
|
|
1371
|
-
abortSignal: input.runAbortController.signal,
|
|
1372
|
-
emitBeforeToolCallDiagnostics: false,
|
|
1373
|
-
modelProvider: params.model.provider,
|
|
1374
|
-
modelId: params.modelId,
|
|
1375
|
-
modelCompat: params.model.compat && typeof params.model.compat === "object" ? params.model.compat : void 0,
|
|
1376
|
-
modelApi: params.model.api,
|
|
1377
|
-
modelContextWindowTokens: params.model.contextWindow,
|
|
1378
|
-
modelAuthMode: resolveModelAuthMode(params.model.provider, params.config, params.toolAuthProfileStore ?? params.authProfileStore, { workspaceDir: input.effectiveWorkspace }),
|
|
1379
|
-
suppressManagedWebSearch: false,
|
|
1380
|
-
currentChannelId: params.currentChannelId,
|
|
1381
|
-
hookChannelId: resolveCodexAppServerHookChannelId(params, input.sandboxSessionKey),
|
|
1382
|
-
currentThreadTs: params.currentThreadTs,
|
|
1383
|
-
currentMessageId: params.currentMessageId,
|
|
1384
|
-
replyToMode: params.replyToMode,
|
|
1385
|
-
hasRepliedRef: params.hasRepliedRef,
|
|
1386
|
-
modelHasVision,
|
|
1387
|
-
requireExplicitMessageTarget: params.requireExplicitMessageTarget ?? isSubagentSessionKey(params.sessionKey),
|
|
1388
|
-
sourceReplyDeliveryMode: params.sourceReplyDeliveryMode,
|
|
1389
|
-
disableMessageTool: params.disableMessageTool,
|
|
1390
|
-
forceMessageTool: shouldForceMessageTool(params),
|
|
1391
|
-
enableHeartbeatTool: params.trigger === "heartbeat" || input.forceHeartbeatTool === true,
|
|
1392
|
-
forceHeartbeatTool: params.trigger === "heartbeat" || input.forceHeartbeatTool === true,
|
|
1393
|
-
onYield: (message) => {
|
|
1394
|
-
input.onYieldDetected();
|
|
1395
|
-
input.onCodexAppServerEvent?.({
|
|
1396
|
-
stream: "codex_app_server.tool",
|
|
1397
|
-
data: {
|
|
1398
|
-
name: "sessions_yield",
|
|
1399
|
-
message
|
|
1400
|
-
}
|
|
1401
|
-
});
|
|
1402
|
-
},
|
|
1403
|
-
recordToolPrepStage: (name) => {
|
|
1404
|
-
toolBuildStages.mark(name);
|
|
1405
|
-
}
|
|
1406
|
-
});
|
|
1407
|
-
toolBuildStages.mark("create-openclaw-coding-tools");
|
|
1408
|
-
const preNormalizationDiagnostics = [];
|
|
1409
|
-
const readableAllToolProjection = filterProviderNormalizableTools(allTools);
|
|
1410
|
-
preNormalizationDiagnostics.push(...readableAllToolProjection.diagnostics);
|
|
1411
|
-
const readableAllTools = [...readableAllToolProjection.tools];
|
|
1412
|
-
const codexFilteredTools = addNodeShellDynamicToolsIfNeeded(addSandboxShellDynamicToolsIfAvailable(isCodexMemoryFlushRun(params) ? filterCodexMemoryFlushDynamicTools(readableAllTools) : filterCodexDynamicTools(readableAllTools, input.pluginConfig), readableAllTools, input), readableAllTools, input);
|
|
1413
|
-
toolBuildStages.mark("codex-filtering");
|
|
1414
|
-
const visionFilteredTools = filterToolsForVisionInputs(codexFilteredTools, {
|
|
1415
|
-
modelHasVision,
|
|
1416
|
-
hasInboundImages: (params.images?.length ?? 0) > 0
|
|
1417
|
-
});
|
|
1418
|
-
toolBuildStages.mark("vision-filtering");
|
|
1419
|
-
const filteredTools = filterCodexDynamicToolsForAllowlist(visionFilteredTools, includeForcedCodexDynamicToolAllow(params.toolsAllow, params));
|
|
1420
|
-
toolBuildStages.mark("allowlist-filter");
|
|
1421
|
-
const normalizedTools = normalizeAgentRuntimeTools({
|
|
1422
|
-
runtimePlan: input.ignoreRuntimePlan ? void 0 : params.runtimePlan,
|
|
1423
|
-
tools: filteredTools,
|
|
1424
|
-
provider: params.provider,
|
|
1425
|
-
config: params.config,
|
|
1426
|
-
workspaceDir: input.effectiveWorkspace,
|
|
1427
|
-
env: process.env,
|
|
1428
|
-
modelId: params.modelId,
|
|
1429
|
-
modelApi: params.model.api,
|
|
1430
|
-
model: params.model,
|
|
1431
|
-
onPreNormalizationSchemaDiagnostics: (diagnostics) => preNormalizationDiagnostics.push(...diagnostics)
|
|
1432
|
-
});
|
|
1433
|
-
toolBuildStages.mark("runtime-normalization");
|
|
1434
|
-
if (preNormalizationDiagnostics.length > 0) embeddedAgentLog.warn(`codex app-server quarantined ${preNormalizationDiagnostics.length} unsupported runtime tool schema${preNormalizationDiagnostics.length === 1 ? "" : "s"} before dynamic tool registration`, {
|
|
1435
|
-
runId: params.runId,
|
|
1436
|
-
sessionId: params.sessionId,
|
|
1437
|
-
diagnostics: preNormalizationDiagnostics.map((diagnostic) => ({
|
|
1438
|
-
index: diagnostic.toolIndex,
|
|
1439
|
-
tool: diagnostic.toolName,
|
|
1440
|
-
violations: diagnostic.violations.slice(0, 12),
|
|
1441
|
-
violationCount: diagnostic.violations.length
|
|
1442
|
-
}))
|
|
1443
|
-
});
|
|
1444
|
-
const summary = toolBuildStages.snapshot();
|
|
1445
|
-
if (shouldWarnCodexDynamicToolBuildStageSummary(summary)) {
|
|
1446
|
-
const phase = input.forceHeartbeatTool ? "registered-tools" : "runtime-tools";
|
|
1447
|
-
embeddedAgentLog.warn(`codex app-server dynamic tool build timings runId=${params.runId} sessionId=${params.sessionId} phase=${phase} totalMs=${summary.totalMs} stages=${formatCodexDynamicToolBuildStageSummary(summary)}`, {
|
|
1448
|
-
runId: params.runId,
|
|
1449
|
-
sessionId: params.sessionId,
|
|
1450
|
-
phase,
|
|
1451
|
-
totalMs: summary.totalMs,
|
|
1452
|
-
stages: summary.stages,
|
|
1453
|
-
allToolCount: readableAllTools.length,
|
|
1454
|
-
codexFilteredToolCount: codexFilteredTools.length,
|
|
1455
|
-
visionFilteredToolCount: visionFilteredTools.length,
|
|
1456
|
-
filteredToolCount: filteredTools.length,
|
|
1457
|
-
normalizedToolCount: normalizedTools.length,
|
|
1458
|
-
forceHeartbeatTool: input.forceHeartbeatTool === true,
|
|
1459
|
-
ignoreRuntimePlan: input.ignoreRuntimePlan === true,
|
|
1460
|
-
nativeToolSurfaceEnabled: input.nativeToolSurfaceEnabled === true
|
|
1461
|
-
});
|
|
1462
|
-
}
|
|
1463
|
-
return normalizedTools;
|
|
1464
|
-
}
|
|
1465
|
-
/** Preserves delivery-critical tools when a narrow allowlist would otherwise hide them. */
|
|
1466
|
-
function includeForcedCodexDynamicToolAllow(toolsAllow, params) {
|
|
1467
|
-
if (toolsAllow === void 0 || hasWildcardCodexToolsAllow(toolsAllow)) return toolsAllow;
|
|
1468
|
-
const forcedToolNames = shouldForceMessageTool(params) ? ["message"] : [];
|
|
1469
|
-
if (forcedToolNames.length === 0) return toolsAllow;
|
|
1470
|
-
if (toolsAllow.length === 0) return forcedToolNames;
|
|
1471
|
-
const normalized = new Set(toolsAllow.map((name) => normalizeCodexDynamicToolName$1(name)));
|
|
1472
|
-
const missingToolNames = forcedToolNames.filter((toolName) => !normalized.has(normalizeCodexDynamicToolName$1(toolName)));
|
|
1473
|
-
return missingToolNames.length === 0 ? toolsAllow : [...toolsAllow, ...missingToolNames];
|
|
1474
|
-
}
|
|
1475
|
-
/** Decides whether Codex native code mode can own shell/file tools for this turn. */
|
|
1476
|
-
function shouldEnableCodexAppServerNativeToolSurface(params, sandbox, options = {}) {
|
|
1477
|
-
if (isCodexMemoryFlushRun(params)) return false;
|
|
1478
|
-
if (isCodexNativeExecutionBlockedByNodeExecHost(params, {
|
|
1479
|
-
agentId: options.agentId,
|
|
1480
|
-
runtimeSessionKey: options.runtimeSessionKey,
|
|
1481
|
-
sandbox
|
|
1482
|
-
})) return false;
|
|
1483
|
-
const toolsAllow = includeForcedCodexDynamicToolAllow(params.toolsAllow, params);
|
|
1484
|
-
if (toolsAllow === void 0) return canCodexAppServerNativeToolSurfaceHonorSandbox(sandbox, options);
|
|
1485
|
-
return hasWildcardCodexToolsAllow(toolsAllow) && canCodexAppServerNativeToolSurfaceHonorSandbox(sandbox, options);
|
|
1486
|
-
}
|
|
1487
|
-
/** Returns true when OpenClaw policy requires the Node-owned exec/process tools instead. */
|
|
1488
|
-
function isCodexNativeExecutionBlockedByNodeExecHost(params, options = {}) {
|
|
1489
|
-
return !resolveCodexNativeExecutionPolicy({
|
|
1490
|
-
config: params.config,
|
|
1491
|
-
sessionKey: resolveCodexRuntimePolicySessionKey(params, options.runtimeSessionKey),
|
|
1492
|
-
sessionId: params.sessionId,
|
|
1493
|
-
agentId: options.agentId,
|
|
1494
|
-
execOverrides: params.execOverrides,
|
|
1495
|
-
sandboxAvailable: options.sandbox?.enabled,
|
|
1496
|
-
readRuntimeSessionEntry: true
|
|
1497
|
-
}).nativeToolSurfaceAllowed;
|
|
1498
|
-
}
|
|
1499
|
-
function resolveCodexRuntimePolicySessionKey(params, runtimeSessionKey) {
|
|
1500
|
-
return runtimeSessionKey?.trim() || params.sandboxSessionKey?.trim() || params.sessionKey?.trim() || params.sessionId;
|
|
1501
|
-
}
|
|
1502
|
-
function canCodexAppServerNativeToolSurfaceHonorSandbox(sandbox, options = {}) {
|
|
1503
|
-
if (!sandbox?.enabled) return true;
|
|
1504
|
-
if (options.sandboxExecServerEnabled === true && sandbox.backend && canSandboxToolPolicyExposeCodexNativeToolSurface(sandbox)) return true;
|
|
1505
|
-
return false;
|
|
1506
|
-
}
|
|
1507
|
-
function canSandboxToolPolicyExposeCodexNativeToolSurface(sandbox) {
|
|
1508
|
-
return CODEX_NATIVE_SANDBOX_TOOL_REQUIREMENTS.every((toolName) => isToolAllowed(sandbox.tools, toolName));
|
|
1509
|
-
}
|
|
1510
|
-
function isCodexMemoryFlushRun(params) {
|
|
1511
|
-
return params?.trigger === "memory" && Boolean(params.memoryFlushWritePath?.trim());
|
|
1512
|
-
}
|
|
1513
|
-
function filterCodexMemoryFlushDynamicTools(tools) {
|
|
1514
|
-
return tools.filter((tool) => CODEX_MEMORY_FLUSH_DYNAMIC_TOOL_ALLOW.has(normalizeCodexDynamicToolName$1(tool.name)));
|
|
1515
|
-
}
|
|
1516
|
-
/** Requires a Codex sandbox environment only when native tools must run inside OpenClaw sandboxing. */
|
|
1517
|
-
function shouldRequireCodexSandboxExecServerEnvironment(params) {
|
|
1518
|
-
return Boolean(params.sandbox?.enabled && params.nativeToolSurfaceEnabled && params.sandboxExecServerEnabled);
|
|
1519
|
-
}
|
|
1520
|
-
/** Selects the sandbox exec-server environment passed through the Codex app-server protocol. */
|
|
1521
|
-
function resolveCodexSandboxEnvironmentSelection(environment, nativeToolSurfaceEnabled) {
|
|
1522
|
-
return environment && nativeToolSurfaceEnabled ? [environment] : void 0;
|
|
1523
|
-
}
|
|
1524
|
-
/** Chooses the cwd visible to Codex native execution after sandbox exec-server setup. */
|
|
1525
|
-
function resolveCodexAppServerExecutionCwd(params) {
|
|
1526
|
-
return params.environment && params.nativeToolSurfaceEnabled ? params.environment.cwd : params.effectiveCwd;
|
|
1527
|
-
}
|
|
1528
|
-
/** Converts OpenClaw sandbox networking into Codex's external-sandbox policy shape. */
|
|
1529
|
-
function resolveCodexExternalSandboxPolicyForOpenClawSandbox(sandbox) {
|
|
1530
|
-
return {
|
|
1531
|
-
type: "externalSandbox",
|
|
1532
|
-
networkAccess: codexNetworkAccessForOpenClawSandbox(sandbox) ? "enabled" : "restricted"
|
|
1533
|
-
};
|
|
1534
|
-
}
|
|
1535
|
-
function codexNetworkAccessForOpenClawSandbox(sandbox) {
|
|
1536
|
-
if (sandbox?.backendId !== "docker") return true;
|
|
1537
|
-
const network = sandbox?.docker?.network?.trim().toLowerCase();
|
|
1538
|
-
return Boolean(network && network !== "none");
|
|
1539
|
-
}
|
|
1540
|
-
/** Returns a Codex config copy with app-server Codex plugin loading disabled for thread tools. */
|
|
1541
|
-
function disableCodexPluginThreadConfig(pluginConfig) {
|
|
1542
|
-
const config = readCodexPluginConfig(pluginConfig);
|
|
1543
|
-
return {
|
|
1544
|
-
...config,
|
|
1545
|
-
codexPlugins: {
|
|
1546
|
-
...config.codexPlugins,
|
|
1547
|
-
enabled: false
|
|
1548
|
-
}
|
|
1549
|
-
};
|
|
1550
|
-
}
|
|
1551
|
-
/** Adds sandbox_exec/process aliases when native Code Mode cannot directly honor the sandbox. */
|
|
1552
|
-
function addSandboxShellDynamicToolsIfAvailable(filteredTools, allTools, input) {
|
|
1553
|
-
if (!shouldExposeSandboxExecDynamicTool(input) || isSandboxShellDynamicToolExcluded(input.pluginConfig)) return filteredTools;
|
|
1554
|
-
const execTool = allTools.find((tool) => normalizeCodexDynamicToolName$1(tool.name) === "exec");
|
|
1555
|
-
const processTool = allTools.find((tool) => normalizeCodexDynamicToolName$1(tool.name) === "process");
|
|
1556
|
-
if (!execTool || !processTool) return filteredTools;
|
|
1557
|
-
const sandboxExecTool = {
|
|
1558
|
-
...execTool,
|
|
1559
|
-
name: "sandbox_exec",
|
|
1560
|
-
description: "Run a shell command through OpenClaw's configured sandbox backend for this session. Use when OpenClaw sandboxing is active or when a command must execute in the sandbox backend, such as an SSH-backed sandbox or Docker container-path bind layout. Use Codex's native shell only when no OpenClaw sandbox is active and native Code Mode is available.",
|
|
1561
|
-
execute: async (toolCallId, args, signal, onUpdate) => {
|
|
1562
|
-
const result = await execTool.execute(toolCallId, args, signal, onUpdate);
|
|
1563
|
-
return {
|
|
1564
|
-
...result,
|
|
1565
|
-
content: result.content.map((item) => item.type === "text" ? Object.assign({}, item, { text: item.text.replace("Use process (list/poll/log/write/send-keys/submit/paste/kill/clear/remove) for follow-up.", "Use sandbox_process (list/poll/log/write/send-keys/submit/paste/kill/clear/remove) for follow-up.") }) : item)
|
|
1566
|
-
};
|
|
1567
|
-
}
|
|
1568
|
-
};
|
|
1569
|
-
const sandboxProcessTool = {
|
|
1570
|
-
...processTool,
|
|
1571
|
-
name: "sandbox_process",
|
|
1572
|
-
description: "Manage sandbox_exec sessions that were started through OpenClaw's configured sandbox backend for this session: list, poll, log, write, send-keys, submit, paste, kill, clear, or remove. Use only for sandbox_exec follow-up; use Codex's native shell session handling only when no OpenClaw sandbox is active and native Code Mode is available."
|
|
1573
|
-
};
|
|
1574
|
-
return [
|
|
1575
|
-
...filteredTools,
|
|
1576
|
-
sandboxExecTool,
|
|
1577
|
-
sandboxProcessTool
|
|
1578
|
-
];
|
|
1579
|
-
}
|
|
1580
|
-
function shouldExposeSandboxExecDynamicTool(input) {
|
|
1581
|
-
if (isCodexMemoryFlushRun(input.params)) return false;
|
|
1582
|
-
if (isCodexNativeExecutionBlockedByNodeExecHost(input.params, {
|
|
1583
|
-
agentId: input.sessionAgentId,
|
|
1584
|
-
runtimeSessionKey: input.sandboxSessionKey,
|
|
1585
|
-
sandbox: input.sandbox
|
|
1586
|
-
})) return false;
|
|
1587
|
-
const backendId = input.sandbox?.enabled ? input.sandbox.backendId.trim().toLowerCase() : "";
|
|
1588
|
-
return Boolean(backendId && input.nativeToolSurfaceEnabled === false);
|
|
1589
|
-
}
|
|
1590
|
-
function isCodexDynamicToolExcluded(config, names) {
|
|
1591
|
-
const normalizedNames = new Set(names.map((name) => normalizeCodexDynamicToolName$1(name)));
|
|
1592
|
-
return (config.codexDynamicToolsExclude ?? []).some((name) => {
|
|
1593
|
-
const normalized = normalizeCodexDynamicToolName$1(name);
|
|
1594
|
-
return normalizedNames.has(normalized);
|
|
1595
|
-
});
|
|
1596
|
-
}
|
|
1597
|
-
function isSandboxShellDynamicToolExcluded(config) {
|
|
1598
|
-
return isCodexDynamicToolExcluded(config, [
|
|
1599
|
-
"exec",
|
|
1600
|
-
"sandbox_exec",
|
|
1601
|
-
"process",
|
|
1602
|
-
"sandbox_process"
|
|
1603
|
-
]);
|
|
1604
|
-
}
|
|
1605
|
-
function addNodeShellDynamicToolsIfNeeded(filteredTools, allTools, input) {
|
|
1606
|
-
if (isCodexMemoryFlushRun(input.params) || !isCodexNativeExecutionBlockedByNodeExecHost(input.params, {
|
|
1607
|
-
agentId: input.sessionAgentId,
|
|
1608
|
-
runtimeSessionKey: input.sandboxSessionKey,
|
|
1609
|
-
sandbox: input.sandbox
|
|
1610
|
-
})) return filteredTools;
|
|
1611
|
-
let next = filteredTools;
|
|
1612
|
-
for (const toolName of ["exec", "process"]) {
|
|
1613
|
-
if (isCodexDynamicToolExcluded(input.pluginConfig, [toolName])) continue;
|
|
1614
|
-
if (next.some((tool) => normalizeCodexDynamicToolName$1(tool.name) === toolName)) continue;
|
|
1615
|
-
const tool = allTools.find((candidate) => normalizeCodexDynamicToolName$1(candidate.name) === toolName);
|
|
1616
|
-
if (!tool) continue;
|
|
1617
|
-
if (next === filteredTools) next = [...filteredTools];
|
|
1618
|
-
next.push(tool);
|
|
1619
|
-
}
|
|
1620
|
-
return next;
|
|
1621
|
-
}
|
|
1622
|
-
/** Applies a normalized tool allowlist while preserving sandbox shell aliases for exec/process. */
|
|
1623
|
-
function filterCodexDynamicToolsForAllowlist(tools, toolsAllow) {
|
|
1624
|
-
if (!toolsAllow) return tools;
|
|
1625
|
-
if (toolsAllow.length === 0) return [];
|
|
1626
|
-
if (hasWildcardCodexToolsAllow(toolsAllow)) return tools;
|
|
1627
|
-
const allowSet = new Set(toolsAllow.map((name) => normalizeCodexDynamicToolName$1(name)).filter(Boolean));
|
|
1628
|
-
return tools.filter((tool) => {
|
|
1629
|
-
const normalized = normalizeCodexDynamicToolName$1(tool.name);
|
|
1630
|
-
return allowSet.has(normalized) || normalized === "sandbox_exec" && allowSet.has("exec") || normalized === "sandbox_process" && (allowSet.has("exec") || allowSet.has("process"));
|
|
1631
|
-
});
|
|
1632
|
-
}
|
|
1633
|
-
/** Detects the wildcard allowlist marker after Codex tool-name normalization. */
|
|
1634
|
-
function hasWildcardCodexToolsAllow(toolsAllow) {
|
|
1635
|
-
return toolsAllow.some((name) => normalizeCodexDynamicToolName$1(name) === "*");
|
|
1636
|
-
}
|
|
1637
|
-
/** Forces message delivery through the message tool when the source channel requires it. */
|
|
1638
|
-
function shouldForceMessageTool(params) {
|
|
1639
|
-
return params.disableMessageTool !== true && params.sourceReplyDeliveryMode === "message_tool_only";
|
|
1640
|
-
}
|
|
1641
|
-
//#endregion
|
|
1642
1052
|
//#region extensions/codex/src/app-server/sandbox-exec-server/json-rpc.ts
|
|
1643
1053
|
/** JSON-RPC error code used when a sandbox exec-server method is unknown. */
|
|
1644
1054
|
const JSON_RPC_NOT_FOUND = -32004;
|
|
@@ -3039,39 +2449,17 @@ async function startCodexAttemptThread(params) {
|
|
|
3039
2449
|
await releaseStartupResourcesOnTimeout?.();
|
|
3040
2450
|
releaseSharedClientLease?.();
|
|
3041
2451
|
releaseSharedClientLease = void 0;
|
|
3042
|
-
await
|
|
2452
|
+
await closeCodexStartupClientBestEffort(startupClientForAbandonedRequestCleanup);
|
|
3043
2453
|
startupClientForAbandonedRequestCleanup = void 0;
|
|
3044
2454
|
},
|
|
3045
2455
|
operation: async () => {
|
|
3046
2456
|
const threadConfig = mergeCodexThreadConfigs(params.bundleMcpThreadConfig?.configPatch);
|
|
3047
2457
|
const pluginThreadConfigRequired = !params.nativeToolSurfaceEnabled || shouldBuildCodexPluginThreadConfig(params.pluginConfig);
|
|
3048
2458
|
const pluginThreadConfigPluginConfig = params.nativeToolSurfaceEnabled ? params.pluginConfig : disableCodexPluginThreadConfig(params.pluginConfig);
|
|
3049
|
-
const pluginAppCacheKey = buildCodexPluginAppCacheKey({
|
|
3050
|
-
appServer: params.appServer,
|
|
3051
|
-
agentDir: params.agentDir,
|
|
3052
|
-
authProfileId: params.startupAuthProfileId,
|
|
3053
|
-
accountId: params.startupAuthAccountCacheKey,
|
|
3054
|
-
envApiKeyFingerprint: params.startupEnvApiKeyCacheKey
|
|
3055
|
-
});
|
|
3056
|
-
const pluginThreadConfigInputFingerprint = pluginThreadConfigRequired ? buildCodexPluginThreadConfigInputFingerprint({
|
|
3057
|
-
pluginConfig: pluginThreadConfigPluginConfig,
|
|
3058
|
-
appCacheKey: pluginAppCacheKey
|
|
3059
|
-
}) : void 0;
|
|
3060
2459
|
const resolvedPluginPolicy = pluginThreadConfigRequired ? resolveCodexPluginsPolicy(pluginThreadConfigPluginConfig) : void 0;
|
|
3061
2460
|
const computerUseMcpElicitationDelegationRequired = params.computerUseConfig.enabled;
|
|
3062
2461
|
const mcpElicitationDelegationRequired = resolvedPluginPolicy?.enabled === true || computerUseMcpElicitationDelegationRequired;
|
|
3063
2462
|
const enabledPluginConfigKeys = resolvedPluginPolicy ? resolvedPluginPolicy.pluginPolicies.filter((plugin) => plugin.enabled).map((plugin) => plugin.configKey).toSorted() : void 0;
|
|
3064
|
-
const attemptParams = params.buildAttemptParams();
|
|
3065
|
-
embeddedAgentLog.debug("codex plugin thread config eligibility", buildCodexPluginThreadConfigEligibilityLogData({
|
|
3066
|
-
sessionId: attemptParams.sessionId,
|
|
3067
|
-
sessionKey: attemptParams.sessionKey ?? "",
|
|
3068
|
-
pluginThreadConfigRequired,
|
|
3069
|
-
resolvedPluginPolicy,
|
|
3070
|
-
enabledPluginConfigKeys,
|
|
3071
|
-
pluginAppCacheKey,
|
|
3072
|
-
startupAuthProfileId: params.startupAuthProfileId,
|
|
3073
|
-
appServer: params.appServer
|
|
3074
|
-
}));
|
|
3075
2463
|
pluginAppServer = mcpElicitationDelegationRequired ? {
|
|
3076
2464
|
...params.appServer,
|
|
3077
2465
|
approvalPolicy: withMcpElicitationsApprovalPolicy(params.appServer.approvalPolicy)
|
|
@@ -3086,7 +2474,7 @@ async function startCodexAttemptThread(params) {
|
|
|
3086
2474
|
startupClient = await params.attemptClientFactory(params.appServer.start, params.startupAuthProfileId, params.agentDir, params.config, {
|
|
3087
2475
|
onStartedClient: (client) => {
|
|
3088
2476
|
startupClientForAbandonedRequestCleanup = client;
|
|
3089
|
-
if (startupAbandoned || startupAbandonController.signal.aborted)
|
|
2477
|
+
if (startupAbandoned || startupAbandonController.signal.aborted) closeCodexStartupClientBestEffort(client);
|
|
3090
2478
|
},
|
|
3091
2479
|
abandonSignal: startupAbandonController.signal
|
|
3092
2480
|
});
|
|
@@ -3108,6 +2496,36 @@ async function startCodexAttemptThread(params) {
|
|
|
3108
2496
|
timeoutMs: params.appServer.requestTimeoutMs,
|
|
3109
2497
|
signal: startupAbandonController.signal
|
|
3110
2498
|
});
|
|
2499
|
+
const startupRuntimeIdentity = activeStartupClient.getRuntimeIdentity();
|
|
2500
|
+
const pluginAppCacheKey = buildCodexPluginAppCacheKey({
|
|
2501
|
+
appServer: params.appServer,
|
|
2502
|
+
agentDir: params.agentDir,
|
|
2503
|
+
authProfileId: params.startupAuthProfileId,
|
|
2504
|
+
accountId: params.startupAuthAccountCacheKey,
|
|
2505
|
+
envApiKeyFingerprint: params.startupEnvApiKeyCacheKey,
|
|
2506
|
+
appServerVersion: activeStartupClient.getServerVersion(),
|
|
2507
|
+
runtimeIdentity: startupRuntimeIdentity
|
|
2508
|
+
});
|
|
2509
|
+
const appServerRuntimeFingerprint = buildCodexAppServerRuntimeFingerprint({
|
|
2510
|
+
appServer: params.appServer,
|
|
2511
|
+
appServerVersion: activeStartupClient.getServerVersion(),
|
|
2512
|
+
runtimeIdentity: startupRuntimeIdentity
|
|
2513
|
+
});
|
|
2514
|
+
const pluginThreadConfigInputFingerprint = pluginThreadConfigRequired ? buildCodexPluginThreadConfigInputFingerprint({
|
|
2515
|
+
pluginConfig: pluginThreadConfigPluginConfig,
|
|
2516
|
+
appCacheKey: pluginAppCacheKey
|
|
2517
|
+
}) : void 0;
|
|
2518
|
+
const attemptParams = params.buildAttemptParams();
|
|
2519
|
+
embeddedAgentLog.debug("codex plugin thread config eligibility", buildCodexPluginThreadConfigEligibilityLogData({
|
|
2520
|
+
sessionId: attemptParams.sessionId,
|
|
2521
|
+
sessionKey: attemptParams.sessionKey ?? "",
|
|
2522
|
+
pluginThreadConfigRequired,
|
|
2523
|
+
resolvedPluginPolicy,
|
|
2524
|
+
enabledPluginConfigKeys,
|
|
2525
|
+
pluginAppCacheKey,
|
|
2526
|
+
startupAuthProfileId: params.startupAuthProfileId,
|
|
2527
|
+
appServer: params.appServer
|
|
2528
|
+
}));
|
|
3111
2529
|
let startupSandboxEnvironment;
|
|
3112
2530
|
let startupSandboxEnvironmentAcquired = false;
|
|
3113
2531
|
const releaseStartupSandboxEnvironment = async () => {
|
|
@@ -3142,8 +2560,10 @@ async function startCodexAttemptThread(params) {
|
|
|
3142
2560
|
const startupEnvironmentSelection = resolveCodexSandboxEnvironmentSelection(startupSandboxEnvironment, params.nativeToolSurfaceEnabled);
|
|
3143
2561
|
const startupExecutionCwd = resolveCodexAppServerExecutionCwd({
|
|
3144
2562
|
effectiveCwd: params.effectiveCwd,
|
|
2563
|
+
localWorkspaceRoot: params.effectiveWorkspace,
|
|
3145
2564
|
environment: startupSandboxEnvironment,
|
|
3146
|
-
nativeToolSurfaceEnabled: params.nativeToolSurfaceEnabled
|
|
2565
|
+
nativeToolSurfaceEnabled: params.nativeToolSurfaceEnabled,
|
|
2566
|
+
remoteWorkspaceRoot: params.appServer.remoteWorkspaceRoot
|
|
3147
2567
|
});
|
|
3148
2568
|
const startupSandboxPolicy = startupSandboxEnvironment ? resolveCodexExternalSandboxPolicyForOpenClawSandbox(params.sandbox) : void 0;
|
|
3149
2569
|
const buildThreadLifecycleParams = (signal) => ({
|
|
@@ -3152,6 +2572,8 @@ async function startCodexAttemptThread(params) {
|
|
|
3152
2572
|
agentId: params.sessionAgentId,
|
|
3153
2573
|
cwd: startupExecutionCwd,
|
|
3154
2574
|
dynamicTools: params.dynamicTools,
|
|
2575
|
+
persistentWebSearchAllowed: params.persistentWebSearchAllowed,
|
|
2576
|
+
webSearchAllowed: params.webSearchAllowed,
|
|
3155
2577
|
appServer: pluginAppServer,
|
|
3156
2578
|
developerInstructions: params.developerInstructions,
|
|
3157
2579
|
config: threadConfig,
|
|
@@ -3159,11 +2581,13 @@ async function startCodexAttemptThread(params) {
|
|
|
3159
2581
|
buildFinalConfigPatch: params.buildFinalConfigPatch,
|
|
3160
2582
|
nativeHookRelayGeneration: params.nativeHookRelayGeneration,
|
|
3161
2583
|
nativeCodeModeEnabled: params.nativeToolSurfaceEnabled,
|
|
2584
|
+
nativeProviderWebSearchSupport: params.nativeProviderWebSearchSupport,
|
|
3162
2585
|
nativeCodeModeOnlyEnabled: params.appServer.codeModeOnly,
|
|
3163
2586
|
userMcpServersEnabled: params.nativeToolSurfaceEnabled,
|
|
3164
2587
|
mcpServersFingerprint: params.bundleMcpThreadConfig.fingerprint,
|
|
3165
2588
|
mcpServersFingerprintEvaluated: params.bundleMcpThreadConfig.evaluated,
|
|
3166
2589
|
environmentSelection: startupEnvironmentSelection,
|
|
2590
|
+
appServerRuntimeFingerprint,
|
|
3167
2591
|
contextEngineProjection: params.contextEngineProjection,
|
|
3168
2592
|
signal,
|
|
3169
2593
|
pluginThreadConfig: pluginThreadConfigRequired ? {
|
|
@@ -3213,13 +2637,13 @@ async function startCodexAttemptThread(params) {
|
|
|
3213
2637
|
startupClientLease?.();
|
|
3214
2638
|
if (startupAbandoned || params.signal.aborted) {
|
|
3215
2639
|
if (startupClientForAbandonedRequestCleanup === startupClient) startupClientForAbandonedRequestCleanup = void 0;
|
|
3216
|
-
await
|
|
2640
|
+
await closeCodexStartupClientBestEffort(startupClient);
|
|
3217
2641
|
} else if (shouldClearSharedClientAfterStartupRace(startupAttemptError) || shouldClearSharedClientAfterStartupFailure({
|
|
3218
2642
|
error: startupAttemptError,
|
|
3219
2643
|
spawnedBy: params.spawnedBy
|
|
3220
2644
|
})) {
|
|
3221
2645
|
if (startupClientForAbandonedRequestCleanup === startupClient) startupClientForAbandonedRequestCleanup = void 0;
|
|
3222
|
-
await
|
|
2646
|
+
await closeCodexStartupClientBestEffort(startupClient);
|
|
3223
2647
|
}
|
|
3224
2648
|
}
|
|
3225
2649
|
}
|
|
@@ -3262,7 +2686,7 @@ async function startCodexAttemptThread(params) {
|
|
|
3262
2686
|
if (params.signal.aborted || shouldClearSharedClientAfterStartupAbandon(error)) {
|
|
3263
2687
|
releaseSharedClientLease?.();
|
|
3264
2688
|
releaseSharedClientLease = void 0;
|
|
3265
|
-
await
|
|
2689
|
+
await closeCodexStartupClientBestEffort(startupClientForAbandonedRequestCleanup);
|
|
3266
2690
|
startupClientForAbandonedRequestCleanup = void 0;
|
|
3267
2691
|
} else if (shouldClearSharedClientAfterStartupRace(error) || shouldClearSharedClientAfterStartupFailure({
|
|
3268
2692
|
error,
|
|
@@ -3270,7 +2694,7 @@ async function startCodexAttemptThread(params) {
|
|
|
3270
2694
|
})) {
|
|
3271
2695
|
releaseSharedClientLease?.();
|
|
3272
2696
|
releaseSharedClientLease = void 0;
|
|
3273
|
-
await
|
|
2697
|
+
await closeCodexStartupClientBestEffort(startupClientForAbandonedRequestCleanup);
|
|
3274
2698
|
startupClientForAbandonedRequestCleanup = void 0;
|
|
3275
2699
|
}
|
|
3276
2700
|
throw error;
|
|
@@ -3278,58 +2702,6 @@ async function startCodexAttemptThread(params) {
|
|
|
3278
2702
|
params.signal.removeEventListener("abort", abandonStartupAcquire);
|
|
3279
2703
|
}
|
|
3280
2704
|
}
|
|
3281
|
-
async function closeAbandonedStartupClient(client) {
|
|
3282
|
-
if (!client) return;
|
|
3283
|
-
const unclaimedSharedClient = clearSharedCodexAppServerClientIfCurrentAndUnclaimed(client);
|
|
3284
|
-
if (unclaimedSharedClient.closed) {
|
|
3285
|
-
await closeClientAndWaitIfAvailable(client);
|
|
3286
|
-
return;
|
|
3287
|
-
}
|
|
3288
|
-
if (unclaimedSharedClient.found) {
|
|
3289
|
-
if (retireSharedCodexAppServerClientIfCurrent(client)?.closed) await closeClientAndWaitIfAvailable(client);
|
|
3290
|
-
return;
|
|
3291
|
-
}
|
|
3292
|
-
const retiredSharedClient = retireSharedCodexAppServerClientIfCurrent(client);
|
|
3293
|
-
if (retiredSharedClient) {
|
|
3294
|
-
if (retiredSharedClient.closed) await closeClientAndWaitIfAvailable(client);
|
|
3295
|
-
return;
|
|
3296
|
-
}
|
|
3297
|
-
if (clearSharedCodexAppServerClientIfCurrent(client)) {
|
|
3298
|
-
await closeClientAndWaitIfAvailable(client);
|
|
3299
|
-
return;
|
|
3300
|
-
}
|
|
3301
|
-
await closeClientAndWaitIfAvailable(client);
|
|
3302
|
-
}
|
|
3303
|
-
async function closeClientAndWaitIfAvailable(client) {
|
|
3304
|
-
const closeable = client;
|
|
3305
|
-
if (typeof closeable.closeAndWait === "function") {
|
|
3306
|
-
await closeable.closeAndWait();
|
|
3307
|
-
return;
|
|
3308
|
-
}
|
|
3309
|
-
closeable.close?.();
|
|
3310
|
-
}
|
|
3311
|
-
async function evictFailedStartupClient(client) {
|
|
3312
|
-
if (!client) return;
|
|
3313
|
-
const unclaimedSharedClient = clearSharedCodexAppServerClientIfCurrentAndUnclaimed(client);
|
|
3314
|
-
if (unclaimedSharedClient.closed) {
|
|
3315
|
-
await closeClientAndWaitIfAvailable(client);
|
|
3316
|
-
return;
|
|
3317
|
-
}
|
|
3318
|
-
if (unclaimedSharedClient.found) {
|
|
3319
|
-
if (retireSharedCodexAppServerClientIfCurrent(client)?.closed) await closeClientAndWaitIfAvailable(client);
|
|
3320
|
-
return;
|
|
3321
|
-
}
|
|
3322
|
-
const retiredSharedClient = retireSharedCodexAppServerClientIfCurrent(client);
|
|
3323
|
-
if (retiredSharedClient) {
|
|
3324
|
-
if (retiredSharedClient.closed) await closeClientAndWaitIfAvailable(client);
|
|
3325
|
-
return;
|
|
3326
|
-
}
|
|
3327
|
-
if (clearSharedCodexAppServerClientIfCurrent(client)) {
|
|
3328
|
-
await closeClientAndWaitIfAvailable(client);
|
|
3329
|
-
return;
|
|
3330
|
-
}
|
|
3331
|
-
await closeClientAndWaitIfAvailable(client);
|
|
3332
|
-
}
|
|
3333
2705
|
function shouldClearSharedClientAfterStartupAbandon(error) {
|
|
3334
2706
|
return error instanceof Error && (error.message === "codex app-server startup timed out" || error.message === "codex app-server startup aborted");
|
|
3335
2707
|
}
|
|
@@ -3857,6 +3229,7 @@ async function handleDynamicToolCallWithTimeout(params) {
|
|
|
3857
3229
|
};
|
|
3858
3230
|
if (params.signal.aborted) {
|
|
3859
3231
|
const message = "OpenClaw dynamic tool call aborted before execution.";
|
|
3232
|
+
params.onFallbackSelected?.();
|
|
3860
3233
|
notifyFailedToolResult(message);
|
|
3861
3234
|
return failedDynamicToolResponse(message);
|
|
3862
3235
|
}
|
|
@@ -3866,6 +3239,7 @@ async function handleDynamicToolCallWithTimeout(params) {
|
|
|
3866
3239
|
let resolveAbort;
|
|
3867
3240
|
const abortFromRun = () => {
|
|
3868
3241
|
const message = "OpenClaw dynamic tool call aborted.";
|
|
3242
|
+
params.onFallbackSelected?.();
|
|
3869
3243
|
controller.abort(params.signal.reason ?? /* @__PURE__ */ new Error(message));
|
|
3870
3244
|
notifyFailedToolResult(message);
|
|
3871
3245
|
resolveAbort?.(failedDynamicToolResponse(message, { sideEffectEvidence: true }));
|
|
@@ -3881,6 +3255,7 @@ async function handleDynamicToolCallWithTimeout(params) {
|
|
|
3881
3255
|
call: params.call,
|
|
3882
3256
|
timeoutMs
|
|
3883
3257
|
});
|
|
3258
|
+
params.onFallbackSelected?.();
|
|
3884
3259
|
controller.abort(new Error(timeoutDetails.responseMessage));
|
|
3885
3260
|
params.onTimeout?.();
|
|
3886
3261
|
embeddedAgentLog.warn("codex dynamic tool call timed out", {
|
|
@@ -3898,7 +3273,8 @@ async function handleDynamicToolCallWithTimeout(params) {
|
|
|
3898
3273
|
const response = await Promise.race([
|
|
3899
3274
|
params.toolBridge.handleToolCall(params.call, {
|
|
3900
3275
|
signal: controller.signal,
|
|
3901
|
-
onAgentToolResult: notifyAgentToolResult
|
|
3276
|
+
onAgentToolResult: notifyAgentToolResult,
|
|
3277
|
+
toolCallOrdinal: params.toolCallOrdinal
|
|
3902
3278
|
}),
|
|
3903
3279
|
abortPromise,
|
|
3904
3280
|
timeoutPromise
|
|
@@ -4406,6 +3782,7 @@ var CodexAppServerEventProjector = class {
|
|
|
4406
3782
|
this.assistantItemOrder = [];
|
|
4407
3783
|
this.assistantPhaseByItem = /* @__PURE__ */ new Map();
|
|
4408
3784
|
this.lastCommentaryProgressTextByItem = /* @__PURE__ */ new Map();
|
|
3785
|
+
this.pendingRawCommentaryEchoes = 0;
|
|
4409
3786
|
this.reasoningTextByGroup = /* @__PURE__ */ new Map();
|
|
4410
3787
|
this.reasoningItemOrder = /* @__PURE__ */ new Map();
|
|
4411
3788
|
this.planTextByItem = /* @__PURE__ */ new Map();
|
|
@@ -4421,6 +3798,8 @@ var CodexAppServerEventProjector = class {
|
|
|
4421
3798
|
this.toolResultOutputDeltaState = /* @__PURE__ */ new Map();
|
|
4422
3799
|
this.toolResultOutputTextByItem = /* @__PURE__ */ new Map();
|
|
4423
3800
|
this.toolMetas = /* @__PURE__ */ new Map();
|
|
3801
|
+
this.terminalPresentationClearedItemIds = /* @__PURE__ */ new Set();
|
|
3802
|
+
this.nativeToolOutcomeOrdinals = /* @__PURE__ */ new Map();
|
|
4424
3803
|
this.sideEffectingToolItemIds = /* @__PURE__ */ new Set();
|
|
4425
3804
|
this.sideEffectingDynamicToolCallIds = /* @__PURE__ */ new Set();
|
|
4426
3805
|
this.toolTranscriptMessages = [];
|
|
@@ -4453,6 +3832,12 @@ var CodexAppServerEventProjector = class {
|
|
|
4453
3832
|
const finalItem = this.resolveFinalAssistantTextItem();
|
|
4454
3833
|
return finalItem !== void 0 && this.completedItemIds.has(finalItem.itemId);
|
|
4455
3834
|
}
|
|
3835
|
+
/** Resolves the shared model-order position for a native tool item. */
|
|
3836
|
+
recordNativeToolOutcome(item) {
|
|
3837
|
+
if (!item || this.nativeToolOutcomeOrdinals.has(item.id) || !shouldClearTerminalPresentationForNativeItem(item)) return;
|
|
3838
|
+
const ordinal = this.params.allocateToolOutcomeOrdinal?.(item.id);
|
|
3839
|
+
if (ordinal !== void 0) this.nativeToolOutcomeOrdinals.set(item.id, ordinal);
|
|
3840
|
+
}
|
|
4456
3841
|
async handleNotification(notification) {
|
|
4457
3842
|
const params = isJsonObject(notification.params) ? notification.params : void 0;
|
|
4458
3843
|
if (!params) return;
|
|
@@ -4527,6 +3912,7 @@ var CodexAppServerEventProjector = class {
|
|
|
4527
3912
|
recordPromptError: legacyFailClosed && !hasDeliverableAssistantOnCompletedTurn
|
|
4528
3913
|
});
|
|
4529
3914
|
const lastAssistant = assistantTexts.length > 0 ? this.createAssistantMessage(assistantTexts.join("\n\n")) : void 0;
|
|
3915
|
+
const currentAttemptAssistant = this.createCurrentAttemptAssistantMessage();
|
|
4530
3916
|
const turnId = this.turnId;
|
|
4531
3917
|
const messagesSnapshot = this.params.suppressNextUserMessagePersistence ? [] : [attachCodexMirrorIdentity(buildCodexUserPromptMessage(this.params), `${turnId}:prompt`)];
|
|
4532
3918
|
if (reasoningText) messagesSnapshot.push(attachCodexMirrorIdentity(this.createAssistantMirrorMessage("Codex reasoning", reasoningText), `${turnId}:reasoning`));
|
|
@@ -4561,6 +3947,7 @@ var CodexAppServerEventProjector = class {
|
|
|
4561
3947
|
assistantTexts,
|
|
4562
3948
|
toolMetas,
|
|
4563
3949
|
lastAssistant,
|
|
3950
|
+
currentAttemptAssistant,
|
|
4564
3951
|
...this.lastNativeToolError ? { lastToolError: this.lastNativeToolError } : {},
|
|
4565
3952
|
didSendViaMessagingTool: toolTelemetry.didSendViaMessagingTool,
|
|
4566
3953
|
messagingToolSentTexts: toolTelemetry.messagingToolSentTexts,
|
|
@@ -4596,6 +3983,7 @@ var CodexAppServerEventProjector = class {
|
|
|
4596
3983
|
});
|
|
4597
3984
|
}
|
|
4598
3985
|
recordDynamicToolResult(params) {
|
|
3986
|
+
const resultText = collectDynamicToolContentText(params.contentItems);
|
|
4599
3987
|
if (params.asyncStarted === true) {
|
|
4600
3988
|
const existing = this.toolMetas.get(params.callId);
|
|
4601
3989
|
this.toolMetas.set(params.callId, {
|
|
@@ -4607,10 +3995,15 @@ var CodexAppServerEventProjector = class {
|
|
|
4607
3995
|
this.recordToolTranscriptResult({
|
|
4608
3996
|
id: params.callId,
|
|
4609
3997
|
name: params.tool,
|
|
4610
|
-
text:
|
|
3998
|
+
text: resultText,
|
|
4611
3999
|
isError: !params.success
|
|
4612
4000
|
});
|
|
4613
|
-
if (
|
|
4001
|
+
if (!params.success && params.terminalType === "blocked") this.lastNativeToolError = {
|
|
4002
|
+
toolName: params.tool,
|
|
4003
|
+
error: resultText || "codex dynamic tool blocked"
|
|
4004
|
+
};
|
|
4005
|
+
else if (params.success && this.lastNativeToolError && !this.lastNativeToolError.mutatingAction) this.lastNativeToolError = void 0;
|
|
4006
|
+
if (params.sideEffectEvidence === true) this.sideEffectingDynamicToolCallIds.add(params.callId);
|
|
4614
4007
|
}
|
|
4615
4008
|
markTimedOut() {
|
|
4616
4009
|
this.aborted = true;
|
|
@@ -4695,6 +4088,7 @@ var CodexAppServerEventProjector = class {
|
|
|
4695
4088
|
const itemId = item?.id ?? readString$5(params, "itemId") ?? readString$5(params, "id");
|
|
4696
4089
|
this.rememberAssistantPhase(item);
|
|
4697
4090
|
if (itemId) this.activeItemIds.add(itemId);
|
|
4091
|
+
this.recordNativeToolOutcome(item);
|
|
4698
4092
|
if (item?.type === "contextCompaction" && itemId) {
|
|
4699
4093
|
this.activeCompactionItemIds.add(itemId);
|
|
4700
4094
|
await runAgentHarnessBeforeCompactionHook({
|
|
@@ -4744,19 +4138,24 @@ var CodexAppServerEventProjector = class {
|
|
|
4744
4138
|
}
|
|
4745
4139
|
async handleItemCompleted(params) {
|
|
4746
4140
|
const item = readItem(params.item);
|
|
4141
|
+
this.recordNativeToolOutcome(item);
|
|
4142
|
+
this.clearTerminalPresentationForNativeItem(item);
|
|
4747
4143
|
const itemId = item?.id ?? readString$5(params, "itemId") ?? readString$5(params, "id");
|
|
4748
4144
|
if (itemId) {
|
|
4749
4145
|
this.activeItemIds.delete(itemId);
|
|
4750
4146
|
this.completedItemIds.add(itemId);
|
|
4751
4147
|
}
|
|
4752
4148
|
this.rememberAssistantPhase(item);
|
|
4753
|
-
if (item?.type === "agentMessage" && typeof item.text === "string"
|
|
4149
|
+
if (item?.type === "agentMessage" && typeof item.text === "string") {
|
|
4754
4150
|
this.rememberAssistantItem(item.id);
|
|
4755
4151
|
this.assistantTextByItem.set(item.id, item.text);
|
|
4756
|
-
if (this.isCommentaryAssistantItem(item.id))
|
|
4757
|
-
|
|
4758
|
-
|
|
4759
|
-
|
|
4152
|
+
if (item.text && this.isCommentaryAssistantItem(item.id)) {
|
|
4153
|
+
this.emitCommentaryProgress({
|
|
4154
|
+
itemId: item.id,
|
|
4155
|
+
text: item.text
|
|
4156
|
+
});
|
|
4157
|
+
this.pendingRawCommentaryEchoes += 1;
|
|
4158
|
+
}
|
|
4760
4159
|
}
|
|
4761
4160
|
this.recordNativeGeneratedMedia(item);
|
|
4762
4161
|
if (item?.type === "plan" && typeof item.text === "string" && item.text) {
|
|
@@ -4883,9 +4282,19 @@ var CodexAppServerEventProjector = class {
|
|
|
4883
4282
|
}) ?? turn.error?.message ?? "codex app-server turn failed";
|
|
4884
4283
|
this.promptErrorSource = "prompt";
|
|
4885
4284
|
}
|
|
4886
|
-
|
|
4285
|
+
const turnItems = turn.items ?? [];
|
|
4286
|
+
for (let index = turnItems.length - 1; index >= 0; index -= 1) {
|
|
4287
|
+
const item = turnItems[index];
|
|
4288
|
+
if (!item || !this.isCurrentTurnSnapshotItem(item)) continue;
|
|
4289
|
+
if (item?.type === "dynamicToolCall") break;
|
|
4290
|
+
if (shouldClearTerminalPresentationForNativeItem(item)) {
|
|
4291
|
+
this.clearTerminalPresentationForNativeItem(item);
|
|
4292
|
+
break;
|
|
4293
|
+
}
|
|
4294
|
+
}
|
|
4295
|
+
for (const item of turnItems) {
|
|
4887
4296
|
this.rememberAssistantPhase(item);
|
|
4888
|
-
if (item.type === "agentMessage" && typeof item.text === "string"
|
|
4297
|
+
if (item.type === "agentMessage" && typeof item.text === "string") {
|
|
4889
4298
|
this.rememberAssistantItem(item.id);
|
|
4890
4299
|
this.assistantTextByItem.set(item.id, item.text);
|
|
4891
4300
|
}
|
|
@@ -4976,10 +4385,14 @@ var CodexAppServerEventProjector = class {
|
|
|
4976
4385
|
if (!item) return;
|
|
4977
4386
|
await this.recordRawGeneratedImageMedia(item);
|
|
4978
4387
|
if (readString$5(item, "role") !== "assistant") return;
|
|
4388
|
+
const phase = readString$5(item, "phase");
|
|
4389
|
+
if (phase === "commentary" && this.pendingRawCommentaryEchoes > 0) {
|
|
4390
|
+
this.pendingRawCommentaryEchoes -= 1;
|
|
4391
|
+
return;
|
|
4392
|
+
}
|
|
4979
4393
|
const text = extractRawAssistantText(item);
|
|
4980
4394
|
if (!text) return;
|
|
4981
4395
|
const itemId = readString$5(item, "id") ?? `raw-assistant-${this.assistantItemOrder.length + 1}`;
|
|
4982
|
-
const phase = readString$5(item, "phase");
|
|
4983
4396
|
if (phase) this.assistantPhaseByItem.set(itemId, phase);
|
|
4984
4397
|
this.rememberAssistantItem(itemId);
|
|
4985
4398
|
this.assistantTextByItem.set(itemId, text);
|
|
@@ -5162,6 +4575,19 @@ var CodexAppServerEventProjector = class {
|
|
|
5162
4575
|
});
|
|
5163
4576
|
if (params.phase === "result") this.emitAfterToolCallObservation(item);
|
|
5164
4577
|
}
|
|
4578
|
+
clearTerminalPresentationForNativeItem(item) {
|
|
4579
|
+
if (!item || this.terminalPresentationClearedItemIds.has(item.id) || !shouldClearTerminalPresentationForNativeItem(item)) return;
|
|
4580
|
+
const toolCallOrdinal = this.nativeToolOutcomeOrdinals.get(item.id);
|
|
4581
|
+
this.terminalPresentationClearedItemIds.add(item.id);
|
|
4582
|
+
this.params.onToolOutcome?.({
|
|
4583
|
+
toolName: itemName(item) ?? item.type,
|
|
4584
|
+
argsHash: "",
|
|
4585
|
+
resultHash: "",
|
|
4586
|
+
...toolCallOrdinal !== void 0 ? { toolCallOrdinal } : {},
|
|
4587
|
+
terminalPresentation: void 0,
|
|
4588
|
+
presentationOnly: true
|
|
4589
|
+
});
|
|
4590
|
+
}
|
|
5165
4591
|
recordNativeToolError(params) {
|
|
5166
4592
|
if (!isNonSuccessItemStatus(params.status)) {
|
|
5167
4593
|
if (!this.lastNativeToolError) return;
|
|
@@ -5333,6 +4759,8 @@ var CodexAppServerEventProjector = class {
|
|
|
5333
4759
|
}
|
|
5334
4760
|
recordToolMeta(item) {
|
|
5335
4761
|
if (!item) return;
|
|
4762
|
+
if (isSideEffectingNativeToolItem(item)) this.sideEffectingToolItemIds.add(item.id);
|
|
4763
|
+
else this.sideEffectingToolItemIds.delete(item.id);
|
|
5336
4764
|
const toolName = itemName(item);
|
|
5337
4765
|
if (!toolName) return;
|
|
5338
4766
|
const meta = itemMeta(item, this.toolProgressDetailMode());
|
|
@@ -5342,8 +4770,6 @@ var CodexAppServerEventProjector = class {
|
|
|
5342
4770
|
...meta ? { meta } : {},
|
|
5343
4771
|
...existing?.asyncStarted ? { asyncStarted: true } : {}
|
|
5344
4772
|
});
|
|
5345
|
-
if (isSideEffectingNativeToolItem(item)) this.sideEffectingToolItemIds.add(item.id);
|
|
5346
|
-
else this.sideEffectingToolItemIds.delete(item.id);
|
|
5347
4773
|
}
|
|
5348
4774
|
recordNativeToolTranscriptCall(item) {
|
|
5349
4775
|
if (!item || !shouldRecordNativeToolTranscript(item)) return;
|
|
@@ -5545,6 +4971,16 @@ var CodexAppServerEventProjector = class {
|
|
|
5545
4971
|
if (!itemId || this.assistantItemOrder.includes(itemId)) return;
|
|
5546
4972
|
this.assistantItemOrder.push(itemId);
|
|
5547
4973
|
}
|
|
4974
|
+
createCurrentAttemptAssistantMessage() {
|
|
4975
|
+
for (let i = this.assistantItemOrder.length - 1; i >= 0; i -= 1) {
|
|
4976
|
+
const itemId = this.assistantItemOrder[i];
|
|
4977
|
+
if (!itemId || this.isCommentaryAssistantItem(itemId) || !this.assistantTextByItem.has(itemId)) continue;
|
|
4978
|
+
const text = this.assistantTextByItem.get(itemId) ?? "";
|
|
4979
|
+
const normalizedText = text.trim();
|
|
4980
|
+
if (normalizedText && this.toolProgressTexts.has(normalizedText)) continue;
|
|
4981
|
+
return this.createAssistantMessage(text);
|
|
4982
|
+
}
|
|
4983
|
+
}
|
|
5548
4984
|
async readMirroredSessionMessages() {
|
|
5549
4985
|
return await readCodexMirroredSessionHistoryMessages(this.params.sessionFile) ?? [];
|
|
5550
4986
|
}
|
|
@@ -5869,7 +5305,20 @@ function shouldRecordNativeToolTranscript(item) {
|
|
|
5869
5305
|
return shouldSynthesizeToolProgressForItem(item) && item.type !== "webSearch";
|
|
5870
5306
|
}
|
|
5871
5307
|
function isMutatingNativeToolItem(item) {
|
|
5872
|
-
|
|
5308
|
+
if (item.type === "commandExecution") return true;
|
|
5309
|
+
return item.type === "fileChange" || item.type === "collabAgentToolCall" || item.type === "imageGeneration";
|
|
5310
|
+
}
|
|
5311
|
+
function shouldClearTerminalPresentationForNativeItem(item) {
|
|
5312
|
+
switch (item.type) {
|
|
5313
|
+
case "collabAgentToolCall":
|
|
5314
|
+
case "commandExecution":
|
|
5315
|
+
case "fileChange":
|
|
5316
|
+
case "imageGeneration":
|
|
5317
|
+
case "imageView":
|
|
5318
|
+
case "mcpToolCall":
|
|
5319
|
+
case "webSearch": return true;
|
|
5320
|
+
default: return false;
|
|
5321
|
+
}
|
|
5873
5322
|
}
|
|
5874
5323
|
function nativeToolActionFingerprint(item) {
|
|
5875
5324
|
if (item.type === "commandExecution" && typeof item.command === "string") return JSON.stringify({
|
|
@@ -6199,8 +5648,18 @@ var CodexNativeSubagentTaskMirror = class {
|
|
|
6199
5648
|
this.mirroredThreadIds = /* @__PURE__ */ new Set();
|
|
6200
5649
|
this.failedMirrorThreadIds = /* @__PURE__ */ new Set();
|
|
6201
5650
|
this.terminalRunIds = /* @__PURE__ */ new Set();
|
|
5651
|
+
this.authoritativeRunIds = /* @__PURE__ */ new Set();
|
|
5652
|
+
this.expectedAuthoritativeRunIds = /* @__PURE__ */ new Set();
|
|
6202
5653
|
this.now = params.now ?? Date.now;
|
|
6203
5654
|
}
|
|
5655
|
+
markAuthoritativeCompletion(childThreadId) {
|
|
5656
|
+
const runId = codexNativeSubagentRunId(childThreadId);
|
|
5657
|
+
this.authoritativeRunIds.add(runId);
|
|
5658
|
+
this.terminalRunIds.add(runId);
|
|
5659
|
+
}
|
|
5660
|
+
markAuthoritativeCompletionExpected(childThreadId) {
|
|
5661
|
+
this.expectedAuthoritativeRunIds.add(codexNativeSubagentRunId(childThreadId));
|
|
5662
|
+
}
|
|
6204
5663
|
handleNotification(notification) {
|
|
6205
5664
|
const params = isJsonObject(notification.params) ? notification.params : void 0;
|
|
6206
5665
|
if (!params) return;
|
|
@@ -6246,6 +5705,7 @@ var CodexNativeSubagentTaskMirror = class {
|
|
|
6246
5705
|
}
|
|
6247
5706
|
this.failedMirrorThreadIds.delete(threadId);
|
|
6248
5707
|
this.terminalRunIds.delete(runId);
|
|
5708
|
+
this.authoritativeRunIds.delete(runId);
|
|
6249
5709
|
this.applyStatus(threadId, thread.status);
|
|
6250
5710
|
}
|
|
6251
5711
|
handleThreadStatusChanged(params) {
|
|
@@ -6258,6 +5718,7 @@ var CodexNativeSubagentTaskMirror = class {
|
|
|
6258
5718
|
const statusType = status?.type;
|
|
6259
5719
|
if (!statusType) return;
|
|
6260
5720
|
const runId = codexNativeSubagentRunId(threadId);
|
|
5721
|
+
if (this.authoritativeRunIds.has(runId)) return;
|
|
6261
5722
|
if (this.terminalRunIds.has(runId) && statusType !== "systemError") return;
|
|
6262
5723
|
const eventAt = this.now();
|
|
6263
5724
|
if (statusType === "active") {
|
|
@@ -6270,13 +5731,10 @@ var CodexNativeSubagentTaskMirror = class {
|
|
|
6270
5731
|
}
|
|
6271
5732
|
if (statusType === "idle") {
|
|
6272
5733
|
this.terminalRunIds.add(runId);
|
|
6273
|
-
this.runtime.
|
|
5734
|
+
this.runtime.recordTaskRunProgressByRunId({
|
|
6274
5735
|
runId,
|
|
6275
|
-
status: "succeeded",
|
|
6276
|
-
endedAt: eventAt,
|
|
6277
5736
|
lastEventAt: eventAt,
|
|
6278
|
-
progressSummary: "Codex native subagent is idle."
|
|
6279
|
-
terminalSummary: "Codex native subagent finished."
|
|
5737
|
+
progressSummary: "Codex native subagent is idle."
|
|
6280
5738
|
});
|
|
6281
5739
|
return;
|
|
6282
5740
|
}
|
|
@@ -6353,12 +5811,14 @@ var CodexNativeSubagentTaskMirror = class {
|
|
|
6353
5811
|
}
|
|
6354
5812
|
this.failedMirrorThreadIds.delete(normalizedThreadId);
|
|
6355
5813
|
this.terminalRunIds.delete(runId);
|
|
5814
|
+
this.authoritativeRunIds.delete(runId);
|
|
6356
5815
|
}
|
|
6357
5816
|
applyCollabAgentStatus(threadId, status, message) {
|
|
6358
5817
|
if (!this.mirroredThreadIds.has(threadId) && this.failedMirrorThreadIds.has(threadId)) return;
|
|
6359
5818
|
const normalizedStatus = normalizeAgentStateStatus(status);
|
|
6360
5819
|
if (!normalizedStatus) return;
|
|
6361
5820
|
const runId = codexNativeSubagentRunId(threadId);
|
|
5821
|
+
if (this.authoritativeRunIds.has(runId)) return;
|
|
6362
5822
|
if (this.terminalRunIds.has(runId) && isNonTerminalAgentStateStatus(normalizedStatus)) return;
|
|
6363
5823
|
const eventAt = this.now();
|
|
6364
5824
|
if (normalizedStatus === "pendingInit" || normalizedStatus === "running") {
|
|
@@ -6371,13 +5831,19 @@ var CodexNativeSubagentTaskMirror = class {
|
|
|
6371
5831
|
}
|
|
6372
5832
|
if (normalizedStatus === "completed") {
|
|
6373
5833
|
this.terminalRunIds.add(runId);
|
|
6374
|
-
|
|
5834
|
+
const summary = trimOptional(message) ?? "Codex native subagent completed.";
|
|
5835
|
+
if (this.expectedAuthoritativeRunIds.has(runId)) this.runtime.recordTaskRunProgressByRunId({
|
|
5836
|
+
runId,
|
|
5837
|
+
lastEventAt: eventAt,
|
|
5838
|
+
progressSummary: summary
|
|
5839
|
+
});
|
|
5840
|
+
else this.runtime.finalizeTaskRunByRunId({
|
|
6375
5841
|
runId,
|
|
6376
5842
|
status: "succeeded",
|
|
6377
5843
|
endedAt: eventAt,
|
|
6378
5844
|
lastEventAt: eventAt,
|
|
6379
|
-
progressSummary:
|
|
6380
|
-
terminalSummary:
|
|
5845
|
+
progressSummary: summary,
|
|
5846
|
+
terminalSummary: summary
|
|
6381
5847
|
});
|
|
6382
5848
|
return;
|
|
6383
5849
|
}
|
|
@@ -6608,6 +6074,8 @@ var CodexNativeSubagentMonitor = class {
|
|
|
6608
6074
|
error: formatErrorMessage(error)
|
|
6609
6075
|
});
|
|
6610
6076
|
}
|
|
6077
|
+
this.captureChildAssistantMessage(notification);
|
|
6078
|
+
await this.handleChildTurnCompletion(notification);
|
|
6611
6079
|
await this.handleCompletionNotification(notification);
|
|
6612
6080
|
}
|
|
6613
6081
|
ensureParentTaskRuntime(state) {
|
|
@@ -6661,7 +6129,7 @@ var CodexNativeSubagentMonitor = class {
|
|
|
6661
6129
|
for (const nativeCompletion of completions) {
|
|
6662
6130
|
const childThreadId = this.resolveChildThreadIdForAgentPath(state.parentThreadId, nativeCompletion.agentPath);
|
|
6663
6131
|
const childState = childThreadId ? this.childStates.get(childThreadId) : void 0;
|
|
6664
|
-
if (!childState || childState.parentThreadId !== state.parentThreadId) {
|
|
6132
|
+
if (!childState || childState.parentThreadId !== state.parentThreadId || childState.transcriptTerminal) {
|
|
6665
6133
|
embeddedAgentLog.warn("Ignoring Codex native subagent completion for unknown child thread", {
|
|
6666
6134
|
parentThreadId: state.parentThreadId,
|
|
6667
6135
|
agentPath: nativeCompletion.agentPath
|
|
@@ -6669,16 +6137,86 @@ var CodexNativeSubagentMonitor = class {
|
|
|
6669
6137
|
continue;
|
|
6670
6138
|
}
|
|
6671
6139
|
const completion = toThreadCompletion(nativeCompletion, childState.childThreadId);
|
|
6672
|
-
|
|
6673
|
-
|
|
6674
|
-
|
|
6675
|
-
|
|
6676
|
-
|
|
6677
|
-
|
|
6678
|
-
|
|
6140
|
+
await this.processChildCompletion(state, childState, completion);
|
|
6141
|
+
}
|
|
6142
|
+
}
|
|
6143
|
+
captureChildAssistantMessage(notification) {
|
|
6144
|
+
const params = isJsonObject(notification.params) ? notification.params : void 0;
|
|
6145
|
+
const childThreadId = readString$2(params, "threadId")?.trim();
|
|
6146
|
+
const childState = childThreadId ? this.childStates.get(childThreadId) : void 0;
|
|
6147
|
+
if (!childState || childState.transcriptTerminal) return;
|
|
6148
|
+
if (notification.method === "item/agentMessage/delta") {
|
|
6149
|
+
const turnId = readString$2(params, "turnId");
|
|
6150
|
+
const itemId = readString$2(params, "itemId");
|
|
6151
|
+
const delta = readString$2(params, "delta");
|
|
6152
|
+
if (turnId && itemId && delta) this.recordChildAssistantMessage(childState, turnId, itemId, delta);
|
|
6153
|
+
return;
|
|
6154
|
+
}
|
|
6155
|
+
if (notification.method !== "item/started" && notification.method !== "item/completed") return;
|
|
6156
|
+
const turnId = readString$2(params, "turnId");
|
|
6157
|
+
const item = isJsonObject(params?.item) ? params.item : void 0;
|
|
6158
|
+
this.captureChildAssistantMessageItem(childState, turnId, item);
|
|
6159
|
+
}
|
|
6160
|
+
captureChildAssistantMessageItem(childState, turnId, item) {
|
|
6161
|
+
if (readString$2(item, "type") !== "agentMessage") return;
|
|
6162
|
+
const itemId = readString$2(item, "id");
|
|
6163
|
+
if (!turnId || !itemId) return;
|
|
6164
|
+
const assistantMessages = this.getChildAssistantMessages(childState, turnId);
|
|
6165
|
+
if (readString$2(item, "phase") === "commentary") assistantMessages.commentaryIds.add(itemId);
|
|
6166
|
+
else assistantMessages.finalMessageIds.add(itemId);
|
|
6167
|
+
const text = readString$2(item, "text");
|
|
6168
|
+
if (text) this.recordChildAssistantMessage(childState, turnId, itemId, text, { replace: true });
|
|
6169
|
+
}
|
|
6170
|
+
captureChildTurnAssistantMessages(childState, turn) {
|
|
6171
|
+
const turnId = readString$2(turn, "id");
|
|
6172
|
+
if (!turnId || !Array.isArray(turn.items)) return;
|
|
6173
|
+
for (const item of turn.items) this.captureChildAssistantMessageItem(childState, turnId, isJsonObject(item) ? item : void 0);
|
|
6174
|
+
}
|
|
6175
|
+
recordChildAssistantMessage(childState, turnId, itemId, text, options = {}) {
|
|
6176
|
+
const assistantMessages = this.getChildAssistantMessages(childState, turnId);
|
|
6177
|
+
if (!assistantMessages.texts.has(itemId)) assistantMessages.order.push(itemId);
|
|
6178
|
+
const existing = assistantMessages.texts.get(itemId) ?? "";
|
|
6179
|
+
assistantMessages.texts.set(itemId, options.replace ? text : `${existing}${text}`);
|
|
6180
|
+
}
|
|
6181
|
+
getChildAssistantMessages(childState, turnId) {
|
|
6182
|
+
const existing = childState.assistantMessagesByTurn.get(turnId);
|
|
6183
|
+
if (existing) return existing;
|
|
6184
|
+
const assistantMessages = {
|
|
6185
|
+
texts: /* @__PURE__ */ new Map(),
|
|
6186
|
+
order: [],
|
|
6187
|
+
commentaryIds: /* @__PURE__ */ new Set(),
|
|
6188
|
+
finalMessageIds: /* @__PURE__ */ new Set()
|
|
6189
|
+
};
|
|
6190
|
+
childState.assistantMessagesByTurn.set(turnId, assistantMessages);
|
|
6191
|
+
return assistantMessages;
|
|
6192
|
+
}
|
|
6193
|
+
async handleChildTurnCompletion(notification) {
|
|
6194
|
+
if (notification.method !== "turn/completed") return;
|
|
6195
|
+
const params = isJsonObject(notification.params) ? notification.params : void 0;
|
|
6196
|
+
const childThreadId = readString$2(params, "threadId")?.trim();
|
|
6197
|
+
const childState = childThreadId ? this.childStates.get(childThreadId) : void 0;
|
|
6198
|
+
const state = childState ? this.parentStates.get(childState.parentThreadId) : void 0;
|
|
6199
|
+
const turn = isJsonObject(params?.turn) ? params.turn : void 0;
|
|
6200
|
+
if (childState && turn && readString$2(turn, "status") === "interrupted") {
|
|
6201
|
+
const turnId = readString$2(turn, "id");
|
|
6202
|
+
if (turnId) childState.assistantMessagesByTurn.delete(turnId);
|
|
6203
|
+
return;
|
|
6204
|
+
}
|
|
6205
|
+
if (childState && turn) this.captureChildTurnAssistantMessages(childState, turn);
|
|
6206
|
+
const completion = childState && turn ? toChildTurnCompletion(childState, turn) : void 0;
|
|
6207
|
+
if (!state || !childState || childState.transcriptTerminal || !completion) return;
|
|
6208
|
+
await this.processChildCompletion(state, childState, completion);
|
|
6209
|
+
}
|
|
6210
|
+
async processChildCompletion(state, childState, completion) {
|
|
6211
|
+
if (shouldWaitForTranscriptCompletion(completion, this.codexHome)) {
|
|
6212
|
+
const eventAt = Date.now();
|
|
6213
|
+
if (!await this.reconcileChildTranscript(childState.childThreadId)) {
|
|
6214
|
+
this.scheduleTranscriptPoll(childState);
|
|
6215
|
+
this.scheduleNoFinalCompletionFallback(state, childState, completion, eventAt);
|
|
6679
6216
|
}
|
|
6680
|
-
|
|
6217
|
+
return;
|
|
6681
6218
|
}
|
|
6219
|
+
await this.processCompletion(state, completion);
|
|
6682
6220
|
}
|
|
6683
6221
|
async reconcileChildTranscript(childThreadId, options = {}) {
|
|
6684
6222
|
const childState = this.childStates.get(childThreadId.trim());
|
|
@@ -6803,6 +6341,7 @@ var CodexNativeSubagentMonitor = class {
|
|
|
6803
6341
|
finalizeCompletionTask(completion, eventAt) {
|
|
6804
6342
|
const taskRuntime = this.getTaskRuntimeForChild(completion.childThreadId);
|
|
6805
6343
|
if (!taskRuntime) return;
|
|
6344
|
+
this.getMirrorForChild(completion.childThreadId)?.markAuthoritativeCompletion(completion.childThreadId);
|
|
6806
6345
|
taskRuntime.finalizeTaskRunByRunId({
|
|
6807
6346
|
runId: codexNativeSubagentRunId(completion.childThreadId),
|
|
6808
6347
|
status: completion.status,
|
|
@@ -6817,6 +6356,10 @@ var CodexNativeSubagentMonitor = class {
|
|
|
6817
6356
|
const childState = this.childStates.get(childThreadId.trim());
|
|
6818
6357
|
return (childState ? this.parentStates.get(childState.parentThreadId) : void 0)?.taskRuntime;
|
|
6819
6358
|
}
|
|
6359
|
+
getMirrorForChild(childThreadId) {
|
|
6360
|
+
const childState = this.childStates.get(childThreadId.trim());
|
|
6361
|
+
return (childState ? this.parentStates.get(childState.parentThreadId) : void 0)?.mirror;
|
|
6362
|
+
}
|
|
6820
6363
|
registerChildThread(parentThreadId, childThreadId, options = {}) {
|
|
6821
6364
|
const normalizedParentThreadId = parentThreadId.trim();
|
|
6822
6365
|
const normalizedChildThreadId = childThreadId.trim();
|
|
@@ -6824,12 +6367,15 @@ var CodexNativeSubagentMonitor = class {
|
|
|
6824
6367
|
this.childThreadParents.set(normalizedChildThreadId, normalizedParentThreadId);
|
|
6825
6368
|
this.childThreadIdsByAgentPath.set(buildParentAgentPathKey(normalizedParentThreadId, normalizedChildThreadId), normalizedChildThreadId);
|
|
6826
6369
|
const agentPath = normalizeOptionalString(options.agentPath);
|
|
6370
|
+
const state = this.parentStates.get(normalizedParentThreadId);
|
|
6371
|
+
if (state?.mirror && (this.codexHome || agentPath)) state.mirror.markAuthoritativeCompletionExpected(normalizedChildThreadId);
|
|
6827
6372
|
if (agentPath) this.childThreadIdsByAgentPath.set(buildParentAgentPathKey(normalizedParentThreadId, agentPath), normalizedChildThreadId);
|
|
6828
6373
|
let childState = this.childStates.get(normalizedChildThreadId);
|
|
6829
6374
|
if (!childState) {
|
|
6830
6375
|
childState = {
|
|
6831
6376
|
childThreadId: normalizedChildThreadId,
|
|
6832
6377
|
parentThreadId: normalizedParentThreadId,
|
|
6378
|
+
assistantMessagesByTurn: /* @__PURE__ */ new Map(),
|
|
6833
6379
|
transcriptPollAttempt: 0,
|
|
6834
6380
|
transcriptTerminal: false,
|
|
6835
6381
|
completionDeliveryAttempt: 0
|
|
@@ -7025,6 +6571,40 @@ function buildCompletionDedupeKey(parentThreadId, completion) {
|
|
|
7025
6571
|
const hash = createHash("sha256").update(completion.result).digest("hex").slice(0, 16);
|
|
7026
6572
|
return `${parentThreadId}:${completion.childThreadId}:${completion.status}:${hash}`;
|
|
7027
6573
|
}
|
|
6574
|
+
function toChildTurnCompletion(childState, turn) {
|
|
6575
|
+
const status = readString$2(turn, "status");
|
|
6576
|
+
if (status === "completed") {
|
|
6577
|
+
const turnId = readString$2(turn, "id");
|
|
6578
|
+
const result = turnId ? lastChildAssistantMessage(childState, turnId) : void 0;
|
|
6579
|
+
return {
|
|
6580
|
+
childThreadId: childState.childThreadId,
|
|
6581
|
+
status: "succeeded",
|
|
6582
|
+
statusLabel: result ? "turn_completed" : "completed_without_final_message",
|
|
6583
|
+
result: result ?? "Codex native subagent completed without a final assistant message."
|
|
6584
|
+
};
|
|
6585
|
+
}
|
|
6586
|
+
if (status === "failed") return {
|
|
6587
|
+
childThreadId: childState.childThreadId,
|
|
6588
|
+
status: "failed",
|
|
6589
|
+
statusLabel: "turn_failed",
|
|
6590
|
+
result: readTurnErrorMessage(turn) ?? "Codex native subagent failed."
|
|
6591
|
+
};
|
|
6592
|
+
}
|
|
6593
|
+
function lastChildAssistantMessage(childState, turnId) {
|
|
6594
|
+
const assistantMessages = childState.assistantMessagesByTurn.get(turnId);
|
|
6595
|
+
if (!assistantMessages) return;
|
|
6596
|
+
for (let index = assistantMessages.order.length - 1; index >= 0; index -= 1) {
|
|
6597
|
+
const itemId = assistantMessages.order[index];
|
|
6598
|
+
if (assistantMessages.finalMessageIds.has(itemId) && !assistantMessages.commentaryIds.has(itemId)) {
|
|
6599
|
+
const text = normalizeOptionalString(assistantMessages.texts.get(itemId));
|
|
6600
|
+
if (text) return text;
|
|
6601
|
+
}
|
|
6602
|
+
}
|
|
6603
|
+
}
|
|
6604
|
+
function readTurnErrorMessage(turn) {
|
|
6605
|
+
const error = isJsonObject(turn.error) ? turn.error : void 0;
|
|
6606
|
+
return normalizeOptionalString(readString$2(error, "message")) ?? normalizeOptionalString(isJsonObject(error?.codexErrorInfo) ? readString$2(error.codexErrorInfo, "message") : void 0);
|
|
6607
|
+
}
|
|
7028
6608
|
function buildParentAgentPathKey(parentThreadId, agentPath) {
|
|
7029
6609
|
return `${parentThreadId}\0${agentPath}`;
|
|
7030
6610
|
}
|
|
@@ -7620,7 +7200,7 @@ function resolveContainedPath(baseDir, fileName) {
|
|
|
7620
7200
|
}
|
|
7621
7201
|
function toTrajectoryToolDefinitions(tools) {
|
|
7622
7202
|
if (!tools || tools.length === 0) return;
|
|
7623
|
-
return tools.flatMap((tool) => {
|
|
7203
|
+
return flattenCodexDynamicToolFunctions(tools).flatMap((tool) => {
|
|
7624
7204
|
const name = tool.name?.trim();
|
|
7625
7205
|
if (!name) return [];
|
|
7626
7206
|
return [{
|
|
@@ -8264,18 +7844,12 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
8264
7844
|
});
|
|
8265
7845
|
const startupEnvApiKeyCacheKey = startupAuthProfileId ? void 0 : resolveCodexAppServerFallbackApiKeyCacheKey({ startOptions: appServer.start });
|
|
8266
7846
|
preDynamicStartupStages.mark("auth-cache");
|
|
8267
|
-
const nodeExecBlocksNativeExecution = isCodexNativeExecutionBlockedByNodeExecHost(params, {
|
|
8268
|
-
agentId: sessionAgentId,
|
|
8269
|
-
runtimeSessionKey: sandboxSessionKey,
|
|
8270
|
-
sandbox
|
|
8271
|
-
});
|
|
8272
|
-
preDynamicStartupStages.mark("native-exec-policy");
|
|
8273
7847
|
const bundleMcpThreadConfig = await loadCodexBundleMcpThreadConfig({
|
|
8274
7848
|
workspaceDir: effectiveWorkspace,
|
|
8275
7849
|
cfg: params.config,
|
|
8276
7850
|
toolsEnabled: supportsModelTools(params.model),
|
|
8277
7851
|
disableTools: params.disableTools,
|
|
8278
|
-
toolsAllow:
|
|
7852
|
+
toolsAllow: params.toolsAllow
|
|
8279
7853
|
});
|
|
8280
7854
|
preDynamicStartupStages.mark("bundle-mcp");
|
|
8281
7855
|
const sandboxExecServerEnabled = isCodexSandboxExecServerEnabled(pluginConfig);
|
|
@@ -8285,6 +7859,28 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
8285
7859
|
sandboxExecServerEnabled
|
|
8286
7860
|
});
|
|
8287
7861
|
preDynamicStartupStages.mark("native-tool-surface");
|
|
7862
|
+
const nativeProviderWebSearchSupport = resolveCodexWebSearchPlan({
|
|
7863
|
+
config: params.config,
|
|
7864
|
+
disableTools: params.disableTools,
|
|
7865
|
+
nativeToolSurfaceEnabled
|
|
7866
|
+
}).kind === "native-hosted" ? await resolveCodexProviderWebSearchSupport({
|
|
7867
|
+
clientFactory: attemptClientFactory,
|
|
7868
|
+
appServer,
|
|
7869
|
+
authProfileId: startupAuthProfileId,
|
|
7870
|
+
agentDir,
|
|
7871
|
+
config: params.config,
|
|
7872
|
+
modelProviderOverride: resolveCodexAppServerThreadModelSelection({
|
|
7873
|
+
provider: params.provider,
|
|
7874
|
+
model: params.modelId,
|
|
7875
|
+
binding: startupBinding,
|
|
7876
|
+
authProfileId: startupAuthProfileId,
|
|
7877
|
+
authProfileStore: params.authProfileStore,
|
|
7878
|
+
agentDir,
|
|
7879
|
+
config: params.config
|
|
7880
|
+
}).modelProvider,
|
|
7881
|
+
signal: runAbortController.signal
|
|
7882
|
+
}) : "unsupported";
|
|
7883
|
+
preDynamicStartupStages.mark("provider-capabilities");
|
|
8288
7884
|
for (const diagnostic of bundleMcpThreadConfig.diagnostics) embeddedAgentLog.warn(`bundle-mcp: ${diagnostic.pluginId}: ${diagnostic.message}`);
|
|
8289
7885
|
if (activeContextEngine) assertContextEngineHostSupport({
|
|
8290
7886
|
contextEngine: activeContextEngine,
|
|
@@ -8305,14 +7901,36 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
8305
7901
|
nativeToolSurfaceEnabled
|
|
8306
7902
|
});
|
|
8307
7903
|
let yieldDetected = false;
|
|
7904
|
+
const toolOutcomeOrdinals = /* @__PURE__ */ new Map();
|
|
7905
|
+
const suppressedDynamicToolOutcomeOrdinals = /* @__PURE__ */ new Set();
|
|
7906
|
+
const onCodexToolOutcome = params.onToolOutcome ? (observation) => {
|
|
7907
|
+
if (observation.toolCallOrdinal !== void 0 && suppressedDynamicToolOutcomeOrdinals.has(observation.toolCallOrdinal)) return;
|
|
7908
|
+
params.onToolOutcome?.(observation);
|
|
7909
|
+
} : void 0;
|
|
7910
|
+
const baseAllocateToolOutcomeOrdinal = params.allocateToolOutcomeOrdinal;
|
|
7911
|
+
const allocateCodexToolOutcomeOrdinal = baseAllocateToolOutcomeOrdinal ? (toolCallId) => {
|
|
7912
|
+
const reservedOrdinal = toolCallId ? toolOutcomeOrdinals.get(toolCallId) : void 0;
|
|
7913
|
+
if (reservedOrdinal !== void 0) return reservedOrdinal;
|
|
7914
|
+
const ordinal = baseAllocateToolOutcomeOrdinal(toolCallId);
|
|
7915
|
+
if (toolCallId) toolOutcomeOrdinals.set(toolCallId, ordinal);
|
|
7916
|
+
return ordinal;
|
|
7917
|
+
} : void 0;
|
|
7918
|
+
const dynamicToolParams = allocateCodexToolOutcomeOrdinal || onCodexToolOutcome ? {
|
|
7919
|
+
...params,
|
|
7920
|
+
...allocateCodexToolOutcomeOrdinal ? { allocateToolOutcomeOrdinal: allocateCodexToolOutcomeOrdinal } : {},
|
|
7921
|
+
...onCodexToolOutcome ? { onToolOutcome: onCodexToolOutcome } : {}
|
|
7922
|
+
} : params;
|
|
7923
|
+
let persistentWebSearchAllowed;
|
|
7924
|
+
let webSearchAllowed = false;
|
|
8308
7925
|
const tools = await buildDynamicTools({
|
|
8309
|
-
params,
|
|
7926
|
+
params: dynamicToolParams,
|
|
8310
7927
|
resolvedWorkspace,
|
|
8311
7928
|
effectiveWorkspace,
|
|
8312
7929
|
effectiveCwd,
|
|
8313
7930
|
sandboxSessionKey,
|
|
8314
7931
|
sandbox,
|
|
8315
7932
|
nativeToolSurfaceEnabled,
|
|
7933
|
+
nativeProviderWebSearchSupport,
|
|
8316
7934
|
runAbortController,
|
|
8317
7935
|
sessionAgentId,
|
|
8318
7936
|
pluginConfig,
|
|
@@ -8320,23 +7938,31 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
8320
7938
|
onYieldDetected: () => {
|
|
8321
7939
|
yieldDetected = true;
|
|
8322
7940
|
},
|
|
8323
|
-
onCodexAppServerEvent: (event) => emitCodexAppServerEvent(params, event)
|
|
7941
|
+
onCodexAppServerEvent: (event) => emitCodexAppServerEvent(params, event),
|
|
7942
|
+
onPersistentWebSearchPolicyResolved: (allowed) => {
|
|
7943
|
+
persistentWebSearchAllowed = allowed;
|
|
7944
|
+
},
|
|
7945
|
+
onWebSearchPolicyResolved: (allowed) => {
|
|
7946
|
+
webSearchAllowed = allowed;
|
|
7947
|
+
}
|
|
8324
7948
|
});
|
|
8325
7949
|
const toolBridge = createCodexDynamicToolBridge({
|
|
8326
7950
|
tools,
|
|
8327
7951
|
registeredTools: await buildDynamicTools({
|
|
8328
|
-
params,
|
|
7952
|
+
params: dynamicToolParams,
|
|
8329
7953
|
resolvedWorkspace,
|
|
8330
7954
|
effectiveWorkspace,
|
|
8331
7955
|
effectiveCwd,
|
|
8332
7956
|
sandboxSessionKey,
|
|
8333
7957
|
sandbox,
|
|
8334
7958
|
nativeToolSurfaceEnabled,
|
|
7959
|
+
nativeProviderWebSearchSupport,
|
|
8335
7960
|
runAbortController,
|
|
8336
7961
|
sessionAgentId,
|
|
8337
7962
|
pluginConfig,
|
|
8338
7963
|
profilerEnabled,
|
|
8339
7964
|
forceHeartbeatTool: true,
|
|
7965
|
+
ignoreDisableMessageTool: true,
|
|
8340
7966
|
ignoreRuntimePlan: true,
|
|
8341
7967
|
onYieldDetected: () => {
|
|
8342
7968
|
yieldDetected = true;
|
|
@@ -8344,15 +7970,23 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
8344
7970
|
onCodexAppServerEvent: (event) => emitCodexAppServerEvent(params, event)
|
|
8345
7971
|
}),
|
|
8346
7972
|
signal: runAbortController.signal,
|
|
8347
|
-
loading:
|
|
8348
|
-
directToolNames:
|
|
7973
|
+
loading: resolveCodexDynamicToolsLoadingForRuntime(pluginConfig, params.modelId, { connectionClass: appServer.connectionClass }),
|
|
7974
|
+
directToolNames: resolveCodexDynamicToolDirectNames(params),
|
|
8349
7975
|
hookContext: {
|
|
8350
7976
|
agentId: sessionAgentId,
|
|
8351
7977
|
config: params.config,
|
|
8352
7978
|
sessionId: params.sessionId,
|
|
8353
7979
|
sessionKey: sandboxSessionKey,
|
|
8354
7980
|
runId: params.runId,
|
|
8355
|
-
channelId: hookChannelId
|
|
7981
|
+
channelId: hookChannelId,
|
|
7982
|
+
currentChannelProvider: resolveCodexMessageToolProvider(params),
|
|
7983
|
+
currentChannelId: params.currentChannelId,
|
|
7984
|
+
currentMessagingTarget: params.currentMessagingTarget,
|
|
7985
|
+
currentThreadId: params.currentThreadTs,
|
|
7986
|
+
replyToMode: params.replyToMode,
|
|
7987
|
+
hasRepliedRef: params.hasRepliedRef,
|
|
7988
|
+
onToolOutcome: onCodexToolOutcome,
|
|
7989
|
+
allocateToolOutcomeOrdinal: allocateCodexToolOutcomeOrdinal
|
|
8356
7990
|
}
|
|
8357
7991
|
});
|
|
8358
7992
|
const hadSessionFile = await pathExists(activeSessionFile);
|
|
@@ -8392,6 +8026,12 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
8392
8026
|
sessionKey: contextSessionKey,
|
|
8393
8027
|
sessionFile: activeSessionFile,
|
|
8394
8028
|
runtimeContext: buildActiveContextEngineRuntimeContext(),
|
|
8029
|
+
contextEngineHostSupport: CODEX_APP_SERVER_CONTEXT_ENGINE_HOST,
|
|
8030
|
+
providerId: params.provider,
|
|
8031
|
+
requestedModelId: params.requestedModelId,
|
|
8032
|
+
modelId: params.modelId,
|
|
8033
|
+
fallbackReason: params.fallbackReason,
|
|
8034
|
+
degradedReason: params.degradedReason,
|
|
8395
8035
|
runMaintenance: runHarnessContextEngineMaintenance,
|
|
8396
8036
|
config: params.config,
|
|
8397
8037
|
warn: (message) => embeddedAgentLog.warn(message)
|
|
@@ -8416,8 +8056,13 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
8416
8056
|
skillsPrompt: params.skillsSnapshot?.prompt
|
|
8417
8057
|
});
|
|
8418
8058
|
let promptText = params.prompt;
|
|
8059
|
+
let promptContextRange;
|
|
8419
8060
|
let developerInstructions = baseDeveloperInstructions;
|
|
8420
8061
|
let prePromptMessageCount = historyMessages.length;
|
|
8062
|
+
const codexContextProjectionMaxChars = resolveCodexContextEngineProjectionMaxChars({
|
|
8063
|
+
contextTokenBudget: params.contextTokenBudget,
|
|
8064
|
+
reserveTokens: resolveCodexContextEngineProjectionReserveTokens({ config: params.config })
|
|
8065
|
+
});
|
|
8421
8066
|
let contextEngineProjection;
|
|
8422
8067
|
let precomputedStaleBindingContinuityProjectionApplied = false;
|
|
8423
8068
|
let staleBindingContinuityForcedFreshStart = false;
|
|
@@ -8426,9 +8071,11 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
8426
8071
|
const projection = projectContextEngineAssemblyForCodex({
|
|
8427
8072
|
assembledMessages: historyMessages,
|
|
8428
8073
|
originalHistoryMessages: historyMessages,
|
|
8429
|
-
prompt: params.prompt
|
|
8074
|
+
prompt: params.prompt,
|
|
8075
|
+
maxRenderedContextChars: codexContextProjectionMaxChars
|
|
8430
8076
|
});
|
|
8431
8077
|
promptText = projection.promptText;
|
|
8078
|
+
promptContextRange = projection.promptContextRange;
|
|
8432
8079
|
prePromptMessageCount = projection.prePromptMessageCount;
|
|
8433
8080
|
};
|
|
8434
8081
|
const applyActiveContextEngineProjection = async (decisionStartupBinding) => {
|
|
@@ -8439,9 +8086,14 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
8439
8086
|
sessionKey: contextSessionKey,
|
|
8440
8087
|
messages: historyMessages,
|
|
8441
8088
|
tokenBudget: params.contextTokenBudget,
|
|
8442
|
-
availableTools: new Set(toolBridge.availableSpecs.map((tool) => tool.name).filter(isNonEmptyString)),
|
|
8089
|
+
availableTools: new Set(flattenCodexDynamicToolFunctions(toolBridge.availableSpecs).map((tool) => tool.name).filter(isNonEmptyString)),
|
|
8443
8090
|
citationsMode: params.config?.memory?.citations,
|
|
8444
8091
|
modelId: params.modelId,
|
|
8092
|
+
contextEngineHostSupport: CODEX_APP_SERVER_CONTEXT_ENGINE_HOST,
|
|
8093
|
+
providerId: params.provider,
|
|
8094
|
+
requestedModelId: params.requestedModelId,
|
|
8095
|
+
fallbackReason: params.fallbackReason,
|
|
8096
|
+
degradedReason: params.degradedReason,
|
|
8445
8097
|
prompt: params.prompt
|
|
8446
8098
|
});
|
|
8447
8099
|
if (!assembled) throw new Error("context engine assemble returned no result");
|
|
@@ -8451,10 +8103,7 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
8451
8103
|
originalHistoryMessages: historyMessages,
|
|
8452
8104
|
prompt: params.prompt,
|
|
8453
8105
|
systemPromptAddition: assembled.systemPromptAddition,
|
|
8454
|
-
maxRenderedContextChars:
|
|
8455
|
-
contextTokenBudget: params.contextTokenBudget,
|
|
8456
|
-
reserveTokens: resolveCodexContextEngineProjectionReserveTokens({ config: params.config })
|
|
8457
|
-
}),
|
|
8106
|
+
maxRenderedContextChars: codexContextProjectionMaxChars,
|
|
8458
8107
|
toolPayloadMode: contextEngineProjection ? "preserve" : "elide"
|
|
8459
8108
|
});
|
|
8460
8109
|
const projectionDecision = contextEngineProjection ? resolveContextEngineBootstrapProjectionDecision({
|
|
@@ -8484,6 +8133,7 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
8484
8133
|
developerInstructionAdditionChars: projection.developerInstructionAddition?.length ?? 0
|
|
8485
8134
|
});
|
|
8486
8135
|
promptText = projectionDecision.project ? projection.promptText : params.prompt;
|
|
8136
|
+
promptContextRange = projectionDecision.project ? projection.promptContextRange : void 0;
|
|
8487
8137
|
developerInstructions = joinPresentSections(baseDeveloperInstructions, projection.developerInstructionAddition);
|
|
8488
8138
|
prePromptMessageCount = projection.prePromptMessageCount;
|
|
8489
8139
|
};
|
|
@@ -8499,8 +8149,23 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
8499
8149
|
messages: codexModelInputHistoryMessages,
|
|
8500
8150
|
ctx: hookContext
|
|
8501
8151
|
});
|
|
8152
|
+
const resolveShiftedPromptContextRange = (prompt, turnPromptText) => {
|
|
8153
|
+
if (!promptContextRange || !prompt.endsWith(promptText) || !turnPromptText.endsWith(prompt)) return;
|
|
8154
|
+
const promptTextOffset = prompt.length - promptText.length;
|
|
8155
|
+
const turnPromptOffset = turnPromptText.length - prompt.length + promptTextOffset;
|
|
8156
|
+
return {
|
|
8157
|
+
start: turnPromptOffset + promptContextRange.start,
|
|
8158
|
+
end: turnPromptOffset + promptContextRange.end
|
|
8159
|
+
};
|
|
8160
|
+
};
|
|
8502
8161
|
let promptBuild = await buildPromptFromCurrentInputs();
|
|
8503
|
-
const decorateCodexTurnPromptText = (prompt) =>
|
|
8162
|
+
const decorateCodexTurnPromptText = (prompt) => {
|
|
8163
|
+
const turnPromptText = prependCodexOpenClawPromptContext(prompt, openClawPromptContext, { preservePromptWithoutContext: params.bootstrapContextMode === "lightweight" && params.bootstrapContextRunKind === "cron" });
|
|
8164
|
+
return fitCodexProjectedContextForTurnStart({
|
|
8165
|
+
promptText: turnPromptText,
|
|
8166
|
+
contextRange: resolveShiftedPromptContextRange(prompt, turnPromptText)
|
|
8167
|
+
});
|
|
8168
|
+
};
|
|
8504
8169
|
let codexTurnPromptText = decorateCodexTurnPromptText(promptBuild.prompt);
|
|
8505
8170
|
const buildCodexTurnCollaborationDeveloperInstructions = () => buildTurnCollaborationMode(params, {
|
|
8506
8171
|
turnScopedDeveloperInstructions: workspaceBootstrapContext.turnScopedDeveloperInstructions,
|
|
@@ -8542,9 +8207,11 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
8542
8207
|
const projection = projectContextEngineAssemblyForCodex({
|
|
8543
8208
|
assembledMessages: newerVisibleMessages,
|
|
8544
8209
|
originalHistoryMessages: historyMessages,
|
|
8545
|
-
prompt: params.prompt
|
|
8210
|
+
prompt: params.prompt,
|
|
8211
|
+
maxRenderedContextChars: codexContextProjectionMaxChars
|
|
8546
8212
|
});
|
|
8547
8213
|
promptText = projection.promptText;
|
|
8214
|
+
promptContextRange = projection.promptContextRange;
|
|
8548
8215
|
prePromptMessageCount = projection.prePromptMessageCount;
|
|
8549
8216
|
return true;
|
|
8550
8217
|
};
|
|
@@ -8593,6 +8260,7 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
8593
8260
|
if (startupBinding?.threadId) return;
|
|
8594
8261
|
inactiveThreadBootstrapBindingForcedFreshStart = hadInactiveThreadBootstrapBinding;
|
|
8595
8262
|
staleBindingContinuityForcedFreshStart = precomputedStaleBindingContinuityProjectionApplied && !inactiveThreadBootstrapBindingForcedFreshStart;
|
|
8263
|
+
if (staleBindingContinuityForcedFreshStart) applyFreshThreadContinuityProjection();
|
|
8596
8264
|
if (activeContextEngine) {
|
|
8597
8265
|
contextEngineProjection = void 0;
|
|
8598
8266
|
try {
|
|
@@ -8635,12 +8303,35 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
8635
8303
|
};
|
|
8636
8304
|
let nativeHookRelay;
|
|
8637
8305
|
let releaseSharedClientLease;
|
|
8306
|
+
let sharedCodexClientRetiredForOneShotCleanup = false;
|
|
8638
8307
|
const releaseSharedClientLeaseOnce = () => {
|
|
8639
8308
|
const release = releaseSharedClientLease;
|
|
8640
8309
|
if (!release) return;
|
|
8641
8310
|
releaseSharedClientLease = void 0;
|
|
8642
8311
|
release();
|
|
8643
8312
|
};
|
|
8313
|
+
const retireSharedCodexClientForOneShotCleanup = async () => {
|
|
8314
|
+
if (params.cleanupBundleMcpOnRunEnd !== true) return;
|
|
8315
|
+
if (sharedCodexClientRetiredForOneShotCleanup) return;
|
|
8316
|
+
sharedCodexClientRetiredForOneShotCleanup = true;
|
|
8317
|
+
const retired = retireSharedCodexAppServerClientIfCurrent(client);
|
|
8318
|
+
embeddedAgentLog.info("codex app-server one-shot cleanup retired shared client", {
|
|
8319
|
+
runId: params.runId,
|
|
8320
|
+
sessionId: params.sessionId,
|
|
8321
|
+
sessionKey: params.sessionKey,
|
|
8322
|
+
activeLeases: retired?.activeLeases ?? null,
|
|
8323
|
+
closed: retired?.closed ?? false,
|
|
8324
|
+
matchedSharedClient: Boolean(retired)
|
|
8325
|
+
});
|
|
8326
|
+
if (retired?.closed) await client.closeAndWait({
|
|
8327
|
+
exitTimeoutMs: 2e3,
|
|
8328
|
+
forceKillDelayMs: 250
|
|
8329
|
+
});
|
|
8330
|
+
};
|
|
8331
|
+
const releaseSharedClientLeaseAndRetireOneShotClient = async () => {
|
|
8332
|
+
releaseSharedClientLeaseOnce();
|
|
8333
|
+
await retireSharedCodexClientForOneShotCleanup();
|
|
8334
|
+
};
|
|
8644
8335
|
let sandboxExecEnvironmentAcquired = false;
|
|
8645
8336
|
const releaseSandboxExecEnvironment = async () => {
|
|
8646
8337
|
if (sandboxExecEnvironmentAcquired) {
|
|
@@ -8703,10 +8394,13 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
8703
8394
|
effectiveWorkspace,
|
|
8704
8395
|
effectiveCwd,
|
|
8705
8396
|
dynamicTools: toolBridge.specs,
|
|
8397
|
+
persistentWebSearchAllowed,
|
|
8398
|
+
webSearchAllowed,
|
|
8706
8399
|
developerInstructions: promptBuild.developerInstructions,
|
|
8707
8400
|
buildFinalConfigPatch: buildNativeHookRelayFinalConfigPatch,
|
|
8708
8401
|
bundleMcpThreadConfig,
|
|
8709
8402
|
nativeToolSurfaceEnabled,
|
|
8403
|
+
nativeProviderWebSearchSupport,
|
|
8710
8404
|
sandboxExecServerEnabled,
|
|
8711
8405
|
sandbox,
|
|
8712
8406
|
contextEngineProjection,
|
|
@@ -8745,7 +8439,7 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
8745
8439
|
threadId: thread.threadId,
|
|
8746
8440
|
authProfileId: startupAuthProfileId,
|
|
8747
8441
|
workspaceDir: effectiveWorkspace,
|
|
8748
|
-
toolCount: toolBridge.specs.length
|
|
8442
|
+
toolCount: flattenCodexDynamicToolFunctions(toolBridge.specs).length
|
|
8749
8443
|
});
|
|
8750
8444
|
recordCodexTrajectoryContext(trajectoryRecorder, {
|
|
8751
8445
|
attempt: params,
|
|
@@ -8932,7 +8626,8 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
8932
8626
|
data: {
|
|
8933
8627
|
startedAt: attemptStartedAt,
|
|
8934
8628
|
endedAt: Date.now(),
|
|
8935
|
-
...data
|
|
8629
|
+
...data,
|
|
8630
|
+
...params.deferTerminalLifecycle ?? params.deferTerminalLifecycleEnd ? { phase: "finishing" } : {}
|
|
8936
8631
|
}
|
|
8937
8632
|
});
|
|
8938
8633
|
lifecycleTerminalEmitted = true;
|
|
@@ -9055,7 +8750,14 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
9055
8750
|
if (isTerminalTurnNotificationForTurn(notification, turnId)) terminalTurnNotificationQueued = true;
|
|
9056
8751
|
const isNativeResponseStreamDelta = isNativeResponseStreamDeltaNotification(notification);
|
|
9057
8752
|
const nativeResponseStreamDeltaMatchesActiveTurn = isNativeResponseStreamDelta && (correlation.matchesActiveTurn === true || isUnscopedCodexNotification(correlation) && canAttributeUnscopedNativeResponseDeltaToThisTurn(client));
|
|
9058
|
-
|
|
8753
|
+
const notificationMatchesActiveTurn = correlation.matchesActiveTurn === true || !isNativeResponseStreamDelta && correlation.matchesActiveTurn !== false || nativeResponseStreamDeltaMatchesActiveTurn;
|
|
8754
|
+
if (correlation.matchesActiveTurn === true) {
|
|
8755
|
+
const modelToolCallId = readRawResponseToolCallId(notification);
|
|
8756
|
+
if (modelToolCallId) allocateCodexToolOutcomeOrdinal?.(modelToolCallId);
|
|
8757
|
+
const nativeItem = readCodexNotificationItem(notification.params);
|
|
8758
|
+
if (nativeItem?.type === "webSearch") projector.recordNativeToolOutcome(nativeItem);
|
|
8759
|
+
}
|
|
8760
|
+
if (notificationMatchesActiveTurn) turnWatches.noteNotificationReceived(notification.method, isNativeResponseStreamDelta ? {
|
|
9059
8761
|
attemptProgress: true,
|
|
9060
8762
|
...turnCrossedToolHandoff ? { attemptTimeoutMs: postToolRawAssistantCompletionIdleTimeoutMs } : {},
|
|
9061
8763
|
details: { lastNotificationMethod: notification.method }
|
|
@@ -9063,13 +8765,14 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
9063
8765
|
notificationQueue = notificationQueue.then(() => handleNotification(notification), () => handleNotification(notification));
|
|
9064
8766
|
return notificationQueue;
|
|
9065
8767
|
};
|
|
8768
|
+
const nativeSubagentCodexHome = appServer.start.transport === "stdio" ? appServer.start.env?.CODEX_HOME ?? resolveCodexAppServerHomeDir(agentDir) : void 0;
|
|
9066
8769
|
registerCodexNativeSubagentMonitor({
|
|
9067
8770
|
client,
|
|
9068
8771
|
parentThreadId: thread.threadId,
|
|
9069
8772
|
requesterSessionKey: params.sessionKey,
|
|
9070
8773
|
taskRuntimeScope: params.agentHarnessTaskRuntimeScope,
|
|
9071
8774
|
agentId: params.agentId,
|
|
9072
|
-
codexHome:
|
|
8775
|
+
codexHome: nativeSubagentCodexHome
|
|
9073
8776
|
});
|
|
9074
8777
|
const notificationCleanup = client.addNotificationHandler(enqueueNotification);
|
|
9075
8778
|
const requestCleanup = client.addRequestHandler(async (request) => {
|
|
@@ -9141,6 +8844,7 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
9141
8844
|
}
|
|
9142
8845
|
const call = readDynamicToolCallParams(request.params);
|
|
9143
8846
|
if (!call || call.threadId !== thread.threadId || call.turnId !== turnId) return;
|
|
8847
|
+
const toolCallOrdinal = allocateCodexToolOutcomeOrdinal?.(call.callId);
|
|
9144
8848
|
armCompletionWatchOnResponse = true;
|
|
9145
8849
|
markCurrentTurnRequestProgress();
|
|
9146
8850
|
turnCrossedToolHandoff = true;
|
|
@@ -9204,7 +8908,11 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
9204
8908
|
toolBridge,
|
|
9205
8909
|
signal: runAbortController.signal,
|
|
9206
8910
|
timeoutMs: dynamicToolTimeoutMs,
|
|
8911
|
+
toolCallOrdinal,
|
|
9207
8912
|
onAgentToolResult: params.onAgentToolResult,
|
|
8913
|
+
onFallbackSelected: () => {
|
|
8914
|
+
if (toolCallOrdinal !== void 0) suppressedDynamicToolOutcomeOrdinals.add(toolCallOrdinal);
|
|
8915
|
+
},
|
|
9208
8916
|
onTimeout: () => {
|
|
9209
8917
|
trajectoryRecorder?.recordEvent("tool.timeout", {
|
|
9210
8918
|
threadId: call.threadId,
|
|
@@ -9216,6 +8924,17 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
9216
8924
|
}
|
|
9217
8925
|
});
|
|
9218
8926
|
const protocolResponse = toCodexDynamicToolProtocolResponse(response);
|
|
8927
|
+
if (!protocolResponse.success && toolCallOrdinal !== void 0) {
|
|
8928
|
+
suppressedDynamicToolOutcomeOrdinals.add(toolCallOrdinal);
|
|
8929
|
+
params.onToolOutcome?.({
|
|
8930
|
+
toolName: call.tool,
|
|
8931
|
+
argsHash: "",
|
|
8932
|
+
resultHash: "",
|
|
8933
|
+
toolCallOrdinal,
|
|
8934
|
+
terminalPresentation: void 0,
|
|
8935
|
+
presentationOnly: true
|
|
8936
|
+
});
|
|
8937
|
+
}
|
|
9219
8938
|
const toolDurationMs = Math.max(0, Date.now() - toolStartedAt);
|
|
9220
8939
|
trajectoryRecorder?.recordEvent("tool.result", {
|
|
9221
8940
|
threadId: call.threadId,
|
|
@@ -9289,6 +9008,7 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
9289
9008
|
});
|
|
9290
9009
|
throw error;
|
|
9291
9010
|
} finally {
|
|
9011
|
+
toolOutcomeOrdinals.delete(call.callId);
|
|
9292
9012
|
unsubscribeToolDiagnosticObserver();
|
|
9293
9013
|
}
|
|
9294
9014
|
} finally {
|
|
@@ -9564,7 +9284,7 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
9564
9284
|
}
|
|
9565
9285
|
});
|
|
9566
9286
|
params.abortSignal?.removeEventListener("abort", abortFromUpstream);
|
|
9567
|
-
|
|
9287
|
+
await releaseSharedClientLeaseAndRetireOneShotClient();
|
|
9568
9288
|
if (usageLimitError) {
|
|
9569
9289
|
await markCodexAuthProfileBlockedFromRateLimits({
|
|
9570
9290
|
params,
|
|
@@ -9582,7 +9302,7 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
9582
9302
|
}
|
|
9583
9303
|
}
|
|
9584
9304
|
if (!turn) {
|
|
9585
|
-
|
|
9305
|
+
await releaseSharedClientLeaseAndRetireOneShotClient();
|
|
9586
9306
|
throw new Error("codex app-server turn/start failed without an error");
|
|
9587
9307
|
}
|
|
9588
9308
|
turnIdRef.current = turn.turn.id;
|
|
@@ -9600,7 +9320,7 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
9600
9320
|
prompt: codexTurnPromptText,
|
|
9601
9321
|
imagesCount: params.images?.length ?? 0
|
|
9602
9322
|
});
|
|
9603
|
-
projectorRef.current = new CodexAppServerEventProjector(
|
|
9323
|
+
projectorRef.current = new CodexAppServerEventProjector(dynamicToolParams, thread.threadId, activeTurnId, {
|
|
9604
9324
|
nativePostToolUseRelayEnabled: nativeHookRelay?.allowedEvents.includes("post_tool_use") === true && nativeHookRelay.shouldRelayEvent("post_tool_use"),
|
|
9605
9325
|
trajectoryRecorder
|
|
9606
9326
|
});
|
|
@@ -9815,6 +9535,12 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
9815
9535
|
lastCallUsage: result.attemptUsage,
|
|
9816
9536
|
promptCache: result.promptCache
|
|
9817
9537
|
}),
|
|
9538
|
+
contextEngineHostSupport: CODEX_APP_SERVER_CONTEXT_ENGINE_HOST,
|
|
9539
|
+
providerId: params.provider,
|
|
9540
|
+
requestedModelId: params.requestedModelId,
|
|
9541
|
+
modelId: params.modelId,
|
|
9542
|
+
fallbackReason: params.fallbackReason,
|
|
9543
|
+
degradedReason: params.degradedReason,
|
|
9818
9544
|
runMaintenance: runHarnessContextEngineMaintenance,
|
|
9819
9545
|
config: params.config,
|
|
9820
9546
|
warn: (message) => embeddedAgentLog.warn(message),
|
|
@@ -9906,7 +9632,7 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
9906
9632
|
notificationCleanup();
|
|
9907
9633
|
requestCleanup();
|
|
9908
9634
|
closeCleanup?.();
|
|
9909
|
-
|
|
9635
|
+
await releaseSharedClientLeaseAndRetireOneShotClient();
|
|
9910
9636
|
if (nativeHookRelay) if (shouldDelayNativeHookRelayUnregister) scheduleCodexNativeHookRelayUnregister({
|
|
9911
9637
|
relay: nativeHookRelay,
|
|
9912
9638
|
hookTimeoutSec: options.nativeHookRelay?.hookTimeoutSec
|
|
@@ -10036,5 +9762,9 @@ function handleApprovalRequest(params) {
|
|
|
10036
9762
|
signal: params.signal
|
|
10037
9763
|
});
|
|
10038
9764
|
}
|
|
9765
|
+
function resolveCodexDynamicToolDirectNames(params) {
|
|
9766
|
+
if (params.sourceReplyDeliveryMode !== "message_tool_only") return [];
|
|
9767
|
+
return ["message"];
|
|
9768
|
+
}
|
|
10039
9769
|
//#endregion
|
|
10040
9770
|
export { runCodexAppServerAttempt };
|