@openclaw/codex 2026.6.8 → 2026.6.9-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{notification-correlation-BGoG0N90.js → app-server-policy-KpyUye2D.js} +15 -74
- package/dist/attempt-notifications-Meja3TX6.js +249 -0
- package/dist/{client-factory-C71Xdb6z.js → client-factory-CPuoOOx6.js} +3 -2
- package/dist/{client-DovmVtbr.js → client-m7XiCQpO.js} +24 -2
- package/dist/{command-handlers-DHecBkuc.js → command-handlers-CqS0Kv3Z.js} +17 -13
- package/dist/{compact-GEKusemL.js → compact-CMVlldii.js} +5 -5
- package/dist/{computer-use-D1qxvTE_.js → computer-use-qLm7Gf35.js} +3 -3
- package/dist/{config-DJXpBkGf.js → config-BksX0T33.js} +160 -20
- package/dist/{conversation-binding-CbnMilVW.js → conversation-binding-DBof5w9J.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-CiwPkR58.js +463 -0
- package/dist/media-understanding-provider.js +1 -355
- package/dist/{models-DRKnOpzF.js → models-BsyV1Psm.js} +2 -2
- package/dist/{plugin-app-cache-key-kIqpGTQj.js → plugin-app-cache-key-CN9zBiCG.js} +17 -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/{native-hook-relay-C3i3FYtc.js → provider-capabilities-BOvTfMhF.js} +803 -78
- package/dist/{provider-C5P6352f.js → provider-qJygHQx4.js} +4 -4
- package/dist/provider.js +1 -1
- package/dist/{request-BxZ40QKY.js → request-DTIEyUrA.js} +2 -2
- package/dist/{run-attempt-D_q-VrpR.js → run-attempt-DRhB6bTc.js} +421 -774
- package/dist/{sandbox-guard-C-Yv9uwY.js → sandbox-guard-3tnjhjFb.js} +37 -10
- package/dist/{session-binding-ElbcSq2o.js → session-binding-BRUi8y6E.js} +27 -8
- package/dist/{shared-client-jFMumCOe.js → shared-client-Bg5d7VV9.js} +4 -4
- package/dist/{side-question-DqKLfWMB.js → side-question-BdYL4kj1.js} +106 -42
- package/dist/{thread-lifecycle-cban34w3.js → thread-lifecycle-CbJqqnEw.js} +912 -616
- package/dist/web-search-contract-api.js +10 -0
- package/dist/web-search-provider.runtime-DrpQ8Cyd.js +74 -0
- package/dist/web-search-provider.shared-BrZmlqyR.js +32 -0
- package/npm-shrinkwrap.json +2 -2
- package/openclaw.plugin.json +129 -4
- 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 buildCodexPluginThreadConfig, B as readCodexNotificationThreadId, D as projectContextEngineAssemblyForCodex, E as resolveCodexDynamicToolsLoadingForRuntime, L as defaultCodexAppInventoryCache, M as mergeCodexThreadConfigs, N as shouldBuildCodexPluginThreadConfig, O as resolveCodexContextEngineProjectionMaxChars, R as describeCodexNotificationCorrelation, V as readCodexNotificationTurnId, _ as resolveCodexWebSearchPlan, a as buildDeveloperInstructions, b as sanitizeCodexHistoryImagePayloads, c as codexDynamicToolsFingerprint, f as resolveCodexAppServerThreadModelSelection, h as startOrResumeThread, i as buildContextEngineBinding, j as buildCodexPluginThreadConfigInputFingerprint, k as resolveCodexContextEngineProjectionReserveTokens, l as isContextEngineBindingCompatible, n as areCodexDynamicToolFingerprintsCompatible, o as buildTurnCollaborationMode, s as buildTurnStartParams, v as isCodexAppServerProfilerEnabled } from "./thread-lifecycle-CbJqqnEw.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-Meja3TX6.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-BksX0T33.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-qJygHQx4.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-m7XiCQpO.js";
|
|
8
|
+
import { i as isCodexAppServerNativeAuthProfile, l as writeCodexAppServerBinding, n as clearCodexAppServerBinding, o as readCodexAppServerBinding, r as clearCodexAppServerBindingForThread } from "./session-binding-BRUi8y6E.js";
|
|
9
|
+
import { n as buildCodexPluginAppCacheKey, r as CODEX_CONTROL_METHODS, t as buildCodexAppServerRuntimeFingerprint } from "./plugin-app-cache-key-CN9zBiCG.js";
|
|
10
|
+
import { a as formatCodexDisplayText, n as resolveCodexAppServerForOpenClawToolPolicy, t as resolveCodexAppServerForModelProvider } from "./app-server-policy-KpyUye2D.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-Bg5d7VV9.js";
|
|
12
|
+
import { t as defaultLeasedCodexAppServerClientFactory } from "./client-factory-CPuoOOx6.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-BOvTfMhF.js";
|
|
14
|
+
import { t as ensureCodexComputerUse } from "./computer-use-qLm7Gf35.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
|
|
@@ -6680,6 +6148,26 @@ var CodexNativeSubagentMonitor = class {
|
|
|
6680
6148
|
await this.processCompletion(state, completion);
|
|
6681
6149
|
}
|
|
6682
6150
|
}
|
|
6151
|
+
captureChildAssistantMessage(notification) {
|
|
6152
|
+
if (notification.method !== "item/completed") return;
|
|
6153
|
+
const params = isJsonObject(notification.params) ? notification.params : void 0;
|
|
6154
|
+
const childThreadId = readString$2(params, "threadId")?.trim();
|
|
6155
|
+
const childState = childThreadId ? this.childStates.get(childThreadId) : void 0;
|
|
6156
|
+
const item = isJsonObject(params?.item) ? params.item : void 0;
|
|
6157
|
+
const text = readString$2(item, "type") === "agentMessage" ? normalizeOptionalString(readString$2(item, "text")) : void 0;
|
|
6158
|
+
if (childState && text) childState.lastAssistantMessage = text;
|
|
6159
|
+
}
|
|
6160
|
+
async handleChildTurnCompletion(notification) {
|
|
6161
|
+
if (notification.method !== "turn/completed") return;
|
|
6162
|
+
const params = isJsonObject(notification.params) ? notification.params : void 0;
|
|
6163
|
+
const childThreadId = readString$2(params, "threadId")?.trim();
|
|
6164
|
+
const childState = childThreadId ? this.childStates.get(childThreadId) : void 0;
|
|
6165
|
+
const state = childState ? this.parentStates.get(childState.parentThreadId) : void 0;
|
|
6166
|
+
const turn = isJsonObject(params?.turn) ? params.turn : void 0;
|
|
6167
|
+
const completion = childState && turn ? toChildTurnCompletion(childState, turn) : void 0;
|
|
6168
|
+
if (!state || !childState || childState.transcriptTerminal || !completion) return;
|
|
6169
|
+
await this.processCompletion(state, completion);
|
|
6170
|
+
}
|
|
6683
6171
|
async reconcileChildTranscript(childThreadId, options = {}) {
|
|
6684
6172
|
const childState = this.childStates.get(childThreadId.trim());
|
|
6685
6173
|
const state = childState ? this.parentStates.get(childState.parentThreadId) : void 0;
|
|
@@ -6803,6 +6291,7 @@ var CodexNativeSubagentMonitor = class {
|
|
|
6803
6291
|
finalizeCompletionTask(completion, eventAt) {
|
|
6804
6292
|
const taskRuntime = this.getTaskRuntimeForChild(completion.childThreadId);
|
|
6805
6293
|
if (!taskRuntime) return;
|
|
6294
|
+
this.getMirrorForChild(completion.childThreadId)?.markAuthoritativeCompletion(completion.childThreadId);
|
|
6806
6295
|
taskRuntime.finalizeTaskRunByRunId({
|
|
6807
6296
|
runId: codexNativeSubagentRunId(completion.childThreadId),
|
|
6808
6297
|
status: completion.status,
|
|
@@ -6817,6 +6306,10 @@ var CodexNativeSubagentMonitor = class {
|
|
|
6817
6306
|
const childState = this.childStates.get(childThreadId.trim());
|
|
6818
6307
|
return (childState ? this.parentStates.get(childState.parentThreadId) : void 0)?.taskRuntime;
|
|
6819
6308
|
}
|
|
6309
|
+
getMirrorForChild(childThreadId) {
|
|
6310
|
+
const childState = this.childStates.get(childThreadId.trim());
|
|
6311
|
+
return (childState ? this.parentStates.get(childState.parentThreadId) : void 0)?.mirror;
|
|
6312
|
+
}
|
|
6820
6313
|
registerChildThread(parentThreadId, childThreadId, options = {}) {
|
|
6821
6314
|
const normalizedParentThreadId = parentThreadId.trim();
|
|
6822
6315
|
const normalizedChildThreadId = childThreadId.trim();
|
|
@@ -6824,6 +6317,8 @@ var CodexNativeSubagentMonitor = class {
|
|
|
6824
6317
|
this.childThreadParents.set(normalizedChildThreadId, normalizedParentThreadId);
|
|
6825
6318
|
this.childThreadIdsByAgentPath.set(buildParentAgentPathKey(normalizedParentThreadId, normalizedChildThreadId), normalizedChildThreadId);
|
|
6826
6319
|
const agentPath = normalizeOptionalString(options.agentPath);
|
|
6320
|
+
const state = this.parentStates.get(normalizedParentThreadId);
|
|
6321
|
+
if (state?.mirror && (this.codexHome || agentPath)) state.mirror.markAuthoritativeCompletionExpected(normalizedChildThreadId);
|
|
6827
6322
|
if (agentPath) this.childThreadIdsByAgentPath.set(buildParentAgentPathKey(normalizedParentThreadId, agentPath), normalizedChildThreadId);
|
|
6828
6323
|
let childState = this.childStates.get(normalizedChildThreadId);
|
|
6829
6324
|
if (!childState) {
|
|
@@ -7025,6 +6520,31 @@ function buildCompletionDedupeKey(parentThreadId, completion) {
|
|
|
7025
6520
|
const hash = createHash("sha256").update(completion.result).digest("hex").slice(0, 16);
|
|
7026
6521
|
return `${parentThreadId}:${completion.childThreadId}:${completion.status}:${hash}`;
|
|
7027
6522
|
}
|
|
6523
|
+
function toChildTurnCompletion(childState, turn) {
|
|
6524
|
+
const status = readString$2(turn, "status");
|
|
6525
|
+
if (status === "completed") return {
|
|
6526
|
+
childThreadId: childState.childThreadId,
|
|
6527
|
+
status: "succeeded",
|
|
6528
|
+
statusLabel: "turn_completed",
|
|
6529
|
+
result: childState.lastAssistantMessage ?? "Codex native subagent completed without a final assistant message."
|
|
6530
|
+
};
|
|
6531
|
+
if (status === "interrupted") return {
|
|
6532
|
+
childThreadId: childState.childThreadId,
|
|
6533
|
+
status: "cancelled",
|
|
6534
|
+
statusLabel: "turn_interrupted",
|
|
6535
|
+
result: "Codex native subagent was interrupted."
|
|
6536
|
+
};
|
|
6537
|
+
if (status === "failed") return {
|
|
6538
|
+
childThreadId: childState.childThreadId,
|
|
6539
|
+
status: "failed",
|
|
6540
|
+
statusLabel: "turn_failed",
|
|
6541
|
+
result: readTurnErrorMessage(turn) ?? "Codex native subagent failed."
|
|
6542
|
+
};
|
|
6543
|
+
}
|
|
6544
|
+
function readTurnErrorMessage(turn) {
|
|
6545
|
+
const error = isJsonObject(turn.error) ? turn.error : void 0;
|
|
6546
|
+
return normalizeOptionalString(readString$2(error, "message")) ?? normalizeOptionalString(isJsonObject(error?.codexErrorInfo) ? readString$2(error.codexErrorInfo, "message") : void 0);
|
|
6547
|
+
}
|
|
7028
6548
|
function buildParentAgentPathKey(parentThreadId, agentPath) {
|
|
7029
6549
|
return `${parentThreadId}\0${agentPath}`;
|
|
7030
6550
|
}
|
|
@@ -7620,7 +7140,7 @@ function resolveContainedPath(baseDir, fileName) {
|
|
|
7620
7140
|
}
|
|
7621
7141
|
function toTrajectoryToolDefinitions(tools) {
|
|
7622
7142
|
if (!tools || tools.length === 0) return;
|
|
7623
|
-
return tools.flatMap((tool) => {
|
|
7143
|
+
return flattenCodexDynamicToolFunctions(tools).flatMap((tool) => {
|
|
7624
7144
|
const name = tool.name?.trim();
|
|
7625
7145
|
if (!name) return [];
|
|
7626
7146
|
return [{
|
|
@@ -8264,18 +7784,12 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
8264
7784
|
});
|
|
8265
7785
|
const startupEnvApiKeyCacheKey = startupAuthProfileId ? void 0 : resolveCodexAppServerFallbackApiKeyCacheKey({ startOptions: appServer.start });
|
|
8266
7786
|
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
7787
|
const bundleMcpThreadConfig = await loadCodexBundleMcpThreadConfig({
|
|
8274
7788
|
workspaceDir: effectiveWorkspace,
|
|
8275
7789
|
cfg: params.config,
|
|
8276
7790
|
toolsEnabled: supportsModelTools(params.model),
|
|
8277
7791
|
disableTools: params.disableTools,
|
|
8278
|
-
toolsAllow:
|
|
7792
|
+
toolsAllow: params.toolsAllow
|
|
8279
7793
|
});
|
|
8280
7794
|
preDynamicStartupStages.mark("bundle-mcp");
|
|
8281
7795
|
const sandboxExecServerEnabled = isCodexSandboxExecServerEnabled(pluginConfig);
|
|
@@ -8285,6 +7799,28 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
8285
7799
|
sandboxExecServerEnabled
|
|
8286
7800
|
});
|
|
8287
7801
|
preDynamicStartupStages.mark("native-tool-surface");
|
|
7802
|
+
const nativeProviderWebSearchSupport = resolveCodexWebSearchPlan({
|
|
7803
|
+
config: params.config,
|
|
7804
|
+
disableTools: params.disableTools,
|
|
7805
|
+
nativeToolSurfaceEnabled
|
|
7806
|
+
}).kind === "native-hosted" ? await resolveCodexProviderWebSearchSupport({
|
|
7807
|
+
clientFactory: attemptClientFactory,
|
|
7808
|
+
appServer,
|
|
7809
|
+
authProfileId: startupAuthProfileId,
|
|
7810
|
+
agentDir,
|
|
7811
|
+
config: params.config,
|
|
7812
|
+
modelProviderOverride: resolveCodexAppServerThreadModelSelection({
|
|
7813
|
+
provider: params.provider,
|
|
7814
|
+
model: params.modelId,
|
|
7815
|
+
binding: startupBinding,
|
|
7816
|
+
authProfileId: startupAuthProfileId,
|
|
7817
|
+
authProfileStore: params.authProfileStore,
|
|
7818
|
+
agentDir,
|
|
7819
|
+
config: params.config
|
|
7820
|
+
}).modelProvider,
|
|
7821
|
+
signal: runAbortController.signal
|
|
7822
|
+
}) : "unsupported";
|
|
7823
|
+
preDynamicStartupStages.mark("provider-capabilities");
|
|
8288
7824
|
for (const diagnostic of bundleMcpThreadConfig.diagnostics) embeddedAgentLog.warn(`bundle-mcp: ${diagnostic.pluginId}: ${diagnostic.message}`);
|
|
8289
7825
|
if (activeContextEngine) assertContextEngineHostSupport({
|
|
8290
7826
|
contextEngine: activeContextEngine,
|
|
@@ -8305,14 +7841,36 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
8305
7841
|
nativeToolSurfaceEnabled
|
|
8306
7842
|
});
|
|
8307
7843
|
let yieldDetected = false;
|
|
7844
|
+
const toolOutcomeOrdinals = /* @__PURE__ */ new Map();
|
|
7845
|
+
const suppressedDynamicToolOutcomeOrdinals = /* @__PURE__ */ new Set();
|
|
7846
|
+
const onCodexToolOutcome = params.onToolOutcome ? (observation) => {
|
|
7847
|
+
if (observation.toolCallOrdinal !== void 0 && suppressedDynamicToolOutcomeOrdinals.has(observation.toolCallOrdinal)) return;
|
|
7848
|
+
params.onToolOutcome?.(observation);
|
|
7849
|
+
} : void 0;
|
|
7850
|
+
const baseAllocateToolOutcomeOrdinal = params.allocateToolOutcomeOrdinal;
|
|
7851
|
+
const allocateCodexToolOutcomeOrdinal = baseAllocateToolOutcomeOrdinal ? (toolCallId) => {
|
|
7852
|
+
const reservedOrdinal = toolCallId ? toolOutcomeOrdinals.get(toolCallId) : void 0;
|
|
7853
|
+
if (reservedOrdinal !== void 0) return reservedOrdinal;
|
|
7854
|
+
const ordinal = baseAllocateToolOutcomeOrdinal(toolCallId);
|
|
7855
|
+
if (toolCallId) toolOutcomeOrdinals.set(toolCallId, ordinal);
|
|
7856
|
+
return ordinal;
|
|
7857
|
+
} : void 0;
|
|
7858
|
+
const dynamicToolParams = allocateCodexToolOutcomeOrdinal || onCodexToolOutcome ? {
|
|
7859
|
+
...params,
|
|
7860
|
+
...allocateCodexToolOutcomeOrdinal ? { allocateToolOutcomeOrdinal: allocateCodexToolOutcomeOrdinal } : {},
|
|
7861
|
+
...onCodexToolOutcome ? { onToolOutcome: onCodexToolOutcome } : {}
|
|
7862
|
+
} : params;
|
|
7863
|
+
let persistentWebSearchAllowed;
|
|
7864
|
+
let webSearchAllowed = false;
|
|
8308
7865
|
const tools = await buildDynamicTools({
|
|
8309
|
-
params,
|
|
7866
|
+
params: dynamicToolParams,
|
|
8310
7867
|
resolvedWorkspace,
|
|
8311
7868
|
effectiveWorkspace,
|
|
8312
7869
|
effectiveCwd,
|
|
8313
7870
|
sandboxSessionKey,
|
|
8314
7871
|
sandbox,
|
|
8315
7872
|
nativeToolSurfaceEnabled,
|
|
7873
|
+
nativeProviderWebSearchSupport,
|
|
8316
7874
|
runAbortController,
|
|
8317
7875
|
sessionAgentId,
|
|
8318
7876
|
pluginConfig,
|
|
@@ -8320,23 +7878,31 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
8320
7878
|
onYieldDetected: () => {
|
|
8321
7879
|
yieldDetected = true;
|
|
8322
7880
|
},
|
|
8323
|
-
onCodexAppServerEvent: (event) => emitCodexAppServerEvent(params, event)
|
|
7881
|
+
onCodexAppServerEvent: (event) => emitCodexAppServerEvent(params, event),
|
|
7882
|
+
onPersistentWebSearchPolicyResolved: (allowed) => {
|
|
7883
|
+
persistentWebSearchAllowed = allowed;
|
|
7884
|
+
},
|
|
7885
|
+
onWebSearchPolicyResolved: (allowed) => {
|
|
7886
|
+
webSearchAllowed = allowed;
|
|
7887
|
+
}
|
|
8324
7888
|
});
|
|
8325
7889
|
const toolBridge = createCodexDynamicToolBridge({
|
|
8326
7890
|
tools,
|
|
8327
7891
|
registeredTools: await buildDynamicTools({
|
|
8328
|
-
params,
|
|
7892
|
+
params: dynamicToolParams,
|
|
8329
7893
|
resolvedWorkspace,
|
|
8330
7894
|
effectiveWorkspace,
|
|
8331
7895
|
effectiveCwd,
|
|
8332
7896
|
sandboxSessionKey,
|
|
8333
7897
|
sandbox,
|
|
8334
7898
|
nativeToolSurfaceEnabled,
|
|
7899
|
+
nativeProviderWebSearchSupport,
|
|
8335
7900
|
runAbortController,
|
|
8336
7901
|
sessionAgentId,
|
|
8337
7902
|
pluginConfig,
|
|
8338
7903
|
profilerEnabled,
|
|
8339
7904
|
forceHeartbeatTool: true,
|
|
7905
|
+
ignoreDisableMessageTool: true,
|
|
8340
7906
|
ignoreRuntimePlan: true,
|
|
8341
7907
|
onYieldDetected: () => {
|
|
8342
7908
|
yieldDetected = true;
|
|
@@ -8344,15 +7910,23 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
8344
7910
|
onCodexAppServerEvent: (event) => emitCodexAppServerEvent(params, event)
|
|
8345
7911
|
}),
|
|
8346
7912
|
signal: runAbortController.signal,
|
|
8347
|
-
loading:
|
|
8348
|
-
directToolNames:
|
|
7913
|
+
loading: resolveCodexDynamicToolsLoadingForRuntime(pluginConfig, params.modelId, { connectionClass: appServer.connectionClass }),
|
|
7914
|
+
directToolNames: resolveCodexDynamicToolDirectNames(params),
|
|
8349
7915
|
hookContext: {
|
|
8350
7916
|
agentId: sessionAgentId,
|
|
8351
7917
|
config: params.config,
|
|
8352
7918
|
sessionId: params.sessionId,
|
|
8353
7919
|
sessionKey: sandboxSessionKey,
|
|
8354
7920
|
runId: params.runId,
|
|
8355
|
-
channelId: hookChannelId
|
|
7921
|
+
channelId: hookChannelId,
|
|
7922
|
+
currentChannelProvider: resolveCodexMessageToolProvider(params),
|
|
7923
|
+
currentChannelId: params.currentChannelId,
|
|
7924
|
+
currentMessagingTarget: params.currentMessagingTarget,
|
|
7925
|
+
currentThreadId: params.currentThreadTs,
|
|
7926
|
+
replyToMode: params.replyToMode,
|
|
7927
|
+
hasRepliedRef: params.hasRepliedRef,
|
|
7928
|
+
onToolOutcome: onCodexToolOutcome,
|
|
7929
|
+
allocateToolOutcomeOrdinal: allocateCodexToolOutcomeOrdinal
|
|
8356
7930
|
}
|
|
8357
7931
|
});
|
|
8358
7932
|
const hadSessionFile = await pathExists(activeSessionFile);
|
|
@@ -8392,6 +7966,12 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
8392
7966
|
sessionKey: contextSessionKey,
|
|
8393
7967
|
sessionFile: activeSessionFile,
|
|
8394
7968
|
runtimeContext: buildActiveContextEngineRuntimeContext(),
|
|
7969
|
+
contextEngineHostSupport: CODEX_APP_SERVER_CONTEXT_ENGINE_HOST,
|
|
7970
|
+
providerId: params.provider,
|
|
7971
|
+
requestedModelId: params.requestedModelId,
|
|
7972
|
+
modelId: params.modelId,
|
|
7973
|
+
fallbackReason: params.fallbackReason,
|
|
7974
|
+
degradedReason: params.degradedReason,
|
|
8395
7975
|
runMaintenance: runHarnessContextEngineMaintenance,
|
|
8396
7976
|
config: params.config,
|
|
8397
7977
|
warn: (message) => embeddedAgentLog.warn(message)
|
|
@@ -8439,9 +8019,14 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
8439
8019
|
sessionKey: contextSessionKey,
|
|
8440
8020
|
messages: historyMessages,
|
|
8441
8021
|
tokenBudget: params.contextTokenBudget,
|
|
8442
|
-
availableTools: new Set(toolBridge.availableSpecs.map((tool) => tool.name).filter(isNonEmptyString)),
|
|
8022
|
+
availableTools: new Set(flattenCodexDynamicToolFunctions(toolBridge.availableSpecs).map((tool) => tool.name).filter(isNonEmptyString)),
|
|
8443
8023
|
citationsMode: params.config?.memory?.citations,
|
|
8444
8024
|
modelId: params.modelId,
|
|
8025
|
+
contextEngineHostSupport: CODEX_APP_SERVER_CONTEXT_ENGINE_HOST,
|
|
8026
|
+
providerId: params.provider,
|
|
8027
|
+
requestedModelId: params.requestedModelId,
|
|
8028
|
+
fallbackReason: params.fallbackReason,
|
|
8029
|
+
degradedReason: params.degradedReason,
|
|
8445
8030
|
prompt: params.prompt
|
|
8446
8031
|
});
|
|
8447
8032
|
if (!assembled) throw new Error("context engine assemble returned no result");
|
|
@@ -8635,12 +8220,35 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
8635
8220
|
};
|
|
8636
8221
|
let nativeHookRelay;
|
|
8637
8222
|
let releaseSharedClientLease;
|
|
8223
|
+
let sharedCodexClientRetiredForOneShotCleanup = false;
|
|
8638
8224
|
const releaseSharedClientLeaseOnce = () => {
|
|
8639
8225
|
const release = releaseSharedClientLease;
|
|
8640
8226
|
if (!release) return;
|
|
8641
8227
|
releaseSharedClientLease = void 0;
|
|
8642
8228
|
release();
|
|
8643
8229
|
};
|
|
8230
|
+
const retireSharedCodexClientForOneShotCleanup = async () => {
|
|
8231
|
+
if (params.cleanupBundleMcpOnRunEnd !== true) return;
|
|
8232
|
+
if (sharedCodexClientRetiredForOneShotCleanup) return;
|
|
8233
|
+
sharedCodexClientRetiredForOneShotCleanup = true;
|
|
8234
|
+
const retired = retireSharedCodexAppServerClientIfCurrent(client);
|
|
8235
|
+
embeddedAgentLog.info("codex app-server one-shot cleanup retired shared client", {
|
|
8236
|
+
runId: params.runId,
|
|
8237
|
+
sessionId: params.sessionId,
|
|
8238
|
+
sessionKey: params.sessionKey,
|
|
8239
|
+
activeLeases: retired?.activeLeases ?? null,
|
|
8240
|
+
closed: retired?.closed ?? false,
|
|
8241
|
+
matchedSharedClient: Boolean(retired)
|
|
8242
|
+
});
|
|
8243
|
+
if (retired?.closed) await client.closeAndWait({
|
|
8244
|
+
exitTimeoutMs: 2e3,
|
|
8245
|
+
forceKillDelayMs: 250
|
|
8246
|
+
});
|
|
8247
|
+
};
|
|
8248
|
+
const releaseSharedClientLeaseAndRetireOneShotClient = async () => {
|
|
8249
|
+
releaseSharedClientLeaseOnce();
|
|
8250
|
+
await retireSharedCodexClientForOneShotCleanup();
|
|
8251
|
+
};
|
|
8644
8252
|
let sandboxExecEnvironmentAcquired = false;
|
|
8645
8253
|
const releaseSandboxExecEnvironment = async () => {
|
|
8646
8254
|
if (sandboxExecEnvironmentAcquired) {
|
|
@@ -8703,10 +8311,13 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
8703
8311
|
effectiveWorkspace,
|
|
8704
8312
|
effectiveCwd,
|
|
8705
8313
|
dynamicTools: toolBridge.specs,
|
|
8314
|
+
persistentWebSearchAllowed,
|
|
8315
|
+
webSearchAllowed,
|
|
8706
8316
|
developerInstructions: promptBuild.developerInstructions,
|
|
8707
8317
|
buildFinalConfigPatch: buildNativeHookRelayFinalConfigPatch,
|
|
8708
8318
|
bundleMcpThreadConfig,
|
|
8709
8319
|
nativeToolSurfaceEnabled,
|
|
8320
|
+
nativeProviderWebSearchSupport,
|
|
8710
8321
|
sandboxExecServerEnabled,
|
|
8711
8322
|
sandbox,
|
|
8712
8323
|
contextEngineProjection,
|
|
@@ -8745,7 +8356,7 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
8745
8356
|
threadId: thread.threadId,
|
|
8746
8357
|
authProfileId: startupAuthProfileId,
|
|
8747
8358
|
workspaceDir: effectiveWorkspace,
|
|
8748
|
-
toolCount: toolBridge.specs.length
|
|
8359
|
+
toolCount: flattenCodexDynamicToolFunctions(toolBridge.specs).length
|
|
8749
8360
|
});
|
|
8750
8361
|
recordCodexTrajectoryContext(trajectoryRecorder, {
|
|
8751
8362
|
attempt: params,
|
|
@@ -8932,7 +8543,8 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
8932
8543
|
data: {
|
|
8933
8544
|
startedAt: attemptStartedAt,
|
|
8934
8545
|
endedAt: Date.now(),
|
|
8935
|
-
...data
|
|
8546
|
+
...data,
|
|
8547
|
+
...params.deferTerminalLifecycle ?? params.deferTerminalLifecycleEnd ? { phase: "finishing" } : {}
|
|
8936
8548
|
}
|
|
8937
8549
|
});
|
|
8938
8550
|
lifecycleTerminalEmitted = true;
|
|
@@ -9055,7 +8667,14 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
9055
8667
|
if (isTerminalTurnNotificationForTurn(notification, turnId)) terminalTurnNotificationQueued = true;
|
|
9056
8668
|
const isNativeResponseStreamDelta = isNativeResponseStreamDeltaNotification(notification);
|
|
9057
8669
|
const nativeResponseStreamDeltaMatchesActiveTurn = isNativeResponseStreamDelta && (correlation.matchesActiveTurn === true || isUnscopedCodexNotification(correlation) && canAttributeUnscopedNativeResponseDeltaToThisTurn(client));
|
|
9058
|
-
|
|
8670
|
+
const notificationMatchesActiveTurn = correlation.matchesActiveTurn === true || !isNativeResponseStreamDelta && correlation.matchesActiveTurn !== false || nativeResponseStreamDeltaMatchesActiveTurn;
|
|
8671
|
+
if (correlation.matchesActiveTurn === true) {
|
|
8672
|
+
const modelToolCallId = readRawResponseToolCallId(notification);
|
|
8673
|
+
if (modelToolCallId) allocateCodexToolOutcomeOrdinal?.(modelToolCallId);
|
|
8674
|
+
const nativeItem = readCodexNotificationItem(notification.params);
|
|
8675
|
+
if (nativeItem?.type === "webSearch") projector.recordNativeToolOutcome(nativeItem);
|
|
8676
|
+
}
|
|
8677
|
+
if (notificationMatchesActiveTurn) turnWatches.noteNotificationReceived(notification.method, isNativeResponseStreamDelta ? {
|
|
9059
8678
|
attemptProgress: true,
|
|
9060
8679
|
...turnCrossedToolHandoff ? { attemptTimeoutMs: postToolRawAssistantCompletionIdleTimeoutMs } : {},
|
|
9061
8680
|
details: { lastNotificationMethod: notification.method }
|
|
@@ -9063,13 +8682,14 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
9063
8682
|
notificationQueue = notificationQueue.then(() => handleNotification(notification), () => handleNotification(notification));
|
|
9064
8683
|
return notificationQueue;
|
|
9065
8684
|
};
|
|
8685
|
+
const nativeSubagentCodexHome = appServer.start.transport === "stdio" ? appServer.start.env?.CODEX_HOME ?? resolveCodexAppServerHomeDir(agentDir) : void 0;
|
|
9066
8686
|
registerCodexNativeSubagentMonitor({
|
|
9067
8687
|
client,
|
|
9068
8688
|
parentThreadId: thread.threadId,
|
|
9069
8689
|
requesterSessionKey: params.sessionKey,
|
|
9070
8690
|
taskRuntimeScope: params.agentHarnessTaskRuntimeScope,
|
|
9071
8691
|
agentId: params.agentId,
|
|
9072
|
-
codexHome:
|
|
8692
|
+
codexHome: nativeSubagentCodexHome
|
|
9073
8693
|
});
|
|
9074
8694
|
const notificationCleanup = client.addNotificationHandler(enqueueNotification);
|
|
9075
8695
|
const requestCleanup = client.addRequestHandler(async (request) => {
|
|
@@ -9141,6 +8761,7 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
9141
8761
|
}
|
|
9142
8762
|
const call = readDynamicToolCallParams(request.params);
|
|
9143
8763
|
if (!call || call.threadId !== thread.threadId || call.turnId !== turnId) return;
|
|
8764
|
+
const toolCallOrdinal = allocateCodexToolOutcomeOrdinal?.(call.callId);
|
|
9144
8765
|
armCompletionWatchOnResponse = true;
|
|
9145
8766
|
markCurrentTurnRequestProgress();
|
|
9146
8767
|
turnCrossedToolHandoff = true;
|
|
@@ -9204,7 +8825,11 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
9204
8825
|
toolBridge,
|
|
9205
8826
|
signal: runAbortController.signal,
|
|
9206
8827
|
timeoutMs: dynamicToolTimeoutMs,
|
|
8828
|
+
toolCallOrdinal,
|
|
9207
8829
|
onAgentToolResult: params.onAgentToolResult,
|
|
8830
|
+
onFallbackSelected: () => {
|
|
8831
|
+
if (toolCallOrdinal !== void 0) suppressedDynamicToolOutcomeOrdinals.add(toolCallOrdinal);
|
|
8832
|
+
},
|
|
9208
8833
|
onTimeout: () => {
|
|
9209
8834
|
trajectoryRecorder?.recordEvent("tool.timeout", {
|
|
9210
8835
|
threadId: call.threadId,
|
|
@@ -9216,6 +8841,17 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
9216
8841
|
}
|
|
9217
8842
|
});
|
|
9218
8843
|
const protocolResponse = toCodexDynamicToolProtocolResponse(response);
|
|
8844
|
+
if (!protocolResponse.success && toolCallOrdinal !== void 0) {
|
|
8845
|
+
suppressedDynamicToolOutcomeOrdinals.add(toolCallOrdinal);
|
|
8846
|
+
params.onToolOutcome?.({
|
|
8847
|
+
toolName: call.tool,
|
|
8848
|
+
argsHash: "",
|
|
8849
|
+
resultHash: "",
|
|
8850
|
+
toolCallOrdinal,
|
|
8851
|
+
terminalPresentation: void 0,
|
|
8852
|
+
presentationOnly: true
|
|
8853
|
+
});
|
|
8854
|
+
}
|
|
9219
8855
|
const toolDurationMs = Math.max(0, Date.now() - toolStartedAt);
|
|
9220
8856
|
trajectoryRecorder?.recordEvent("tool.result", {
|
|
9221
8857
|
threadId: call.threadId,
|
|
@@ -9289,6 +8925,7 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
9289
8925
|
});
|
|
9290
8926
|
throw error;
|
|
9291
8927
|
} finally {
|
|
8928
|
+
toolOutcomeOrdinals.delete(call.callId);
|
|
9292
8929
|
unsubscribeToolDiagnosticObserver();
|
|
9293
8930
|
}
|
|
9294
8931
|
} finally {
|
|
@@ -9564,7 +9201,7 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
9564
9201
|
}
|
|
9565
9202
|
});
|
|
9566
9203
|
params.abortSignal?.removeEventListener("abort", abortFromUpstream);
|
|
9567
|
-
|
|
9204
|
+
await releaseSharedClientLeaseAndRetireOneShotClient();
|
|
9568
9205
|
if (usageLimitError) {
|
|
9569
9206
|
await markCodexAuthProfileBlockedFromRateLimits({
|
|
9570
9207
|
params,
|
|
@@ -9582,7 +9219,7 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
9582
9219
|
}
|
|
9583
9220
|
}
|
|
9584
9221
|
if (!turn) {
|
|
9585
|
-
|
|
9222
|
+
await releaseSharedClientLeaseAndRetireOneShotClient();
|
|
9586
9223
|
throw new Error("codex app-server turn/start failed without an error");
|
|
9587
9224
|
}
|
|
9588
9225
|
turnIdRef.current = turn.turn.id;
|
|
@@ -9600,7 +9237,7 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
9600
9237
|
prompt: codexTurnPromptText,
|
|
9601
9238
|
imagesCount: params.images?.length ?? 0
|
|
9602
9239
|
});
|
|
9603
|
-
projectorRef.current = new CodexAppServerEventProjector(
|
|
9240
|
+
projectorRef.current = new CodexAppServerEventProjector(dynamicToolParams, thread.threadId, activeTurnId, {
|
|
9604
9241
|
nativePostToolUseRelayEnabled: nativeHookRelay?.allowedEvents.includes("post_tool_use") === true && nativeHookRelay.shouldRelayEvent("post_tool_use"),
|
|
9605
9242
|
trajectoryRecorder
|
|
9606
9243
|
});
|
|
@@ -9815,6 +9452,12 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
9815
9452
|
lastCallUsage: result.attemptUsage,
|
|
9816
9453
|
promptCache: result.promptCache
|
|
9817
9454
|
}),
|
|
9455
|
+
contextEngineHostSupport: CODEX_APP_SERVER_CONTEXT_ENGINE_HOST,
|
|
9456
|
+
providerId: params.provider,
|
|
9457
|
+
requestedModelId: params.requestedModelId,
|
|
9458
|
+
modelId: params.modelId,
|
|
9459
|
+
fallbackReason: params.fallbackReason,
|
|
9460
|
+
degradedReason: params.degradedReason,
|
|
9818
9461
|
runMaintenance: runHarnessContextEngineMaintenance,
|
|
9819
9462
|
config: params.config,
|
|
9820
9463
|
warn: (message) => embeddedAgentLog.warn(message),
|
|
@@ -9906,7 +9549,7 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
9906
9549
|
notificationCleanup();
|
|
9907
9550
|
requestCleanup();
|
|
9908
9551
|
closeCleanup?.();
|
|
9909
|
-
|
|
9552
|
+
await releaseSharedClientLeaseAndRetireOneShotClient();
|
|
9910
9553
|
if (nativeHookRelay) if (shouldDelayNativeHookRelayUnregister) scheduleCodexNativeHookRelayUnregister({
|
|
9911
9554
|
relay: nativeHookRelay,
|
|
9912
9555
|
hookTimeoutSec: options.nativeHookRelay?.hookTimeoutSec
|
|
@@ -10036,5 +9679,9 @@ function handleApprovalRequest(params) {
|
|
|
10036
9679
|
signal: params.signal
|
|
10037
9680
|
});
|
|
10038
9681
|
}
|
|
9682
|
+
function resolveCodexDynamicToolDirectNames(params) {
|
|
9683
|
+
if (params.sourceReplyDeliveryMode !== "message_tool_only") return [];
|
|
9684
|
+
return ["message"];
|
|
9685
|
+
}
|
|
10039
9686
|
//#endregion
|
|
10040
9687
|
export { runCodexAppServerAttempt };
|