@openclaw/codex 2026.5.16-beta.2 → 2026.5.16-beta.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{client-CA7amCZ8.js → client-6FkrXfaz.js} +1 -1
- package/dist/{client-factory-DwzPofwS.js → client-factory-9L6Ie1dC.js} +1 -1
- package/dist/{command-handlers-D6UDzndR.js → command-handlers-jZV_1Ks9.js} +6 -6
- package/dist/{compact-96QPqIAu.js → compact-UKyG6Pw2.js} +3 -3
- package/dist/{computer-use-BX02ojP4.js → computer-use-UJ3dxrXF.js} +2 -2
- package/dist/{config-3ATInASk.js → config-B5pq6hEz.js} +7 -1
- package/dist/harness.js +5 -5
- package/dist/index.js +11 -8
- package/dist/media-understanding-provider.js +4 -4
- package/dist/{models-BHS-8DS_.js → models-C1zn2RN0.js} +2 -2
- package/dist/{node-cli-sessions-BLDFnUEF.js → node-cli-sessions-BKhlcAB9.js} +4 -4
- package/dist/{plugin-activation-BDU4e-NA.js → plugin-activation-B49xb7pI.js} +1 -1
- package/dist/{protocol-validators-CSY0BFBo.js → protocol-validators-BGBspNmF.js} +12 -40
- package/dist/provider.js +2 -2
- package/dist/{request-Czoa60Nt.js → request-XPjLayGw.js} +3 -3
- package/dist/{run-attempt-B6gN6CrO.js → run-attempt-DMKAwtUV.js} +264 -53
- package/dist/{session-binding-DbdVqMzW.js → session-binding-DqApZIgD.js} +1 -1
- package/dist/{shared-client-CnbrvEfV.js → shared-client-DlvmoLBJ.js} +70 -36
- package/dist/{side-question-CFcVH8fj.js → side-question-BYYJZq23.js} +6 -6
- package/dist/test-api.js +2 -2
- package/dist/{thread-lifecycle-BMK4m_PL.js → thread-lifecycle-wcyYqwrl.js} +10 -10
- package/package.json +4 -4
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import { c as resolveCodexAppServerRuntimeOptions, d as withMcpElicitationsApprovalPolicy, i as isCodexAppServerApprovalPolicyAllowedByRequirements, s as readCodexPluginConfig, u as resolveCodexPluginsPolicy } from "./config-
|
|
2
|
-
import { a as readCodexDynamicToolCallParams, c as readCodexTurn, i as assertCodexTurnStartResponse } from "./protocol-validators-
|
|
1
|
+
import { c as resolveCodexAppServerRuntimeOptions, d as withMcpElicitationsApprovalPolicy, i as isCodexAppServerApprovalPolicyAllowedByRequirements, s as readCodexPluginConfig, u as resolveCodexPluginsPolicy } from "./config-B5pq6hEz.js";
|
|
2
|
+
import { a as readCodexDynamicToolCallParams, c as readCodexTurn, i as assertCodexTurnStartResponse } from "./protocol-validators-BGBspNmF.js";
|
|
3
3
|
import { t as isJsonObject } from "./protocol-C9UWI98H.js";
|
|
4
|
-
import { i as isCodexAppServerConnectionClosedError, r as isCodexAppServerApprovalRequest } from "./client-
|
|
5
|
-
import { n as buildCodexPluginAppCacheKey, r as CODEX_CONTROL_METHODS } from "./request-
|
|
4
|
+
import { i as isCodexAppServerConnectionClosedError, r as isCodexAppServerApprovalRequest } from "./client-6FkrXfaz.js";
|
|
5
|
+
import { n as buildCodexPluginAppCacheKey, r as CODEX_CONTROL_METHODS } from "./request-XPjLayGw.js";
|
|
6
6
|
import { d as resolveCodexUsageLimitResetAtMs, f as shouldRefreshCodexRateLimitsForUsageLimitMessage, r as formatCodexDisplayText, u as formatCodexUsageLimitErrorMessage } from "./command-formatters-BRW7_Nu7.js";
|
|
7
|
-
import { c as resolveCodexAppServerAuthAccountCacheKey, d as resolveCodexAppServerEnvApiKeyCacheKey, l as resolveCodexAppServerAuthProfileId,
|
|
8
|
-
import { i as readCodexAppServerBinding, t as clearCodexAppServerBinding } from "./session-binding-
|
|
9
|
-
import { a as defaultCodexAppInventoryCache } from "./plugin-activation-
|
|
10
|
-
import { S as normalizeCodexDynamicToolName, _ as projectContextEngineAssemblyForCodex, b as createCodexDynamicToolBridge, c as codexDynamicToolsFingerprint, f as startOrResumeThread, g as shouldBuildCodexPluginThreadConfig, h as mergeCodexThreadConfigs, i as buildDeveloperInstructions, l as isContextEngineBindingCompatible, m as buildCodexPluginThreadConfigInputFingerprint, p as buildCodexPluginThreadConfig, r as buildContextEngineBinding, s as buildTurnStartParams, t as areCodexDynamicToolFingerprintsCompatible, v as resolveCodexContextEngineProjectionMaxChars, x as filterCodexDynamicTools, y as resolveCodexContextEngineProjectionReserveTokens } from "./thread-lifecycle-
|
|
11
|
-
import { t as defaultCodexAppServerClientFactory } from "./client-factory-
|
|
7
|
+
import { c as resolveCodexAppServerAuthAccountCacheKey, d as resolveCodexAppServerEnvApiKeyCacheKey, l as resolveCodexAppServerAuthProfileId, s as refreshCodexAppServerAuthTokens, t as clearSharedCodexAppServerClientIfCurrent, u as resolveCodexAppServerAuthProfileIdForAgent } from "./shared-client-DlvmoLBJ.js";
|
|
8
|
+
import { i as readCodexAppServerBinding, t as clearCodexAppServerBinding } from "./session-binding-DqApZIgD.js";
|
|
9
|
+
import { a as defaultCodexAppInventoryCache } from "./plugin-activation-B49xb7pI.js";
|
|
10
|
+
import { S as normalizeCodexDynamicToolName, _ as projectContextEngineAssemblyForCodex, b as createCodexDynamicToolBridge, c as codexDynamicToolsFingerprint, f as startOrResumeThread, g as shouldBuildCodexPluginThreadConfig, h as mergeCodexThreadConfigs, i as buildDeveloperInstructions, l as isContextEngineBindingCompatible, m as buildCodexPluginThreadConfigInputFingerprint, p as buildCodexPluginThreadConfig, r as buildContextEngineBinding, s as buildTurnStartParams, t as areCodexDynamicToolFingerprintsCompatible, v as resolveCodexContextEngineProjectionMaxChars, x as filterCodexDynamicTools, y as resolveCodexContextEngineProjectionReserveTokens } from "./thread-lifecycle-wcyYqwrl.js";
|
|
11
|
+
import { t as defaultCodexAppServerClientFactory } from "./client-factory-9L6Ie1dC.js";
|
|
12
12
|
import { n as handleCodexAppServerElicitationRequest, r as handleCodexAppServerApprovalRequest, t as filterToolsForVisionInputs } from "./vision-tools-Cm_YicZb.js";
|
|
13
|
-
import { t as ensureCodexComputerUse } from "./computer-use-
|
|
13
|
+
import { t as ensureCodexComputerUse } from "./computer-use-UJ3dxrXF.js";
|
|
14
14
|
import { n as rememberCodexRateLimits, t as readRecentCodexRateLimits } from "./rate-limit-cache-dvhq-4pi.js";
|
|
15
15
|
import { createHash } from "node:crypto";
|
|
16
16
|
import nodeFs from "node:fs";
|
|
@@ -23,6 +23,26 @@ import { redactSensitiveFieldValue, redactToolPayloadText } from "openclaw/plugi
|
|
|
23
23
|
import { emitTrustedDiagnosticEvent } from "openclaw/plugin-sdk/diagnostic-runtime";
|
|
24
24
|
import { createRunningTaskRun, finalizeTaskRunByRunId, recordTaskRunProgressByRunId } from "openclaw/plugin-sdk/codex-native-task-runtime";
|
|
25
25
|
import { buildSessionContext, migrateSessionEntries, parseSessionEntries } from "@earendil-works/pi-coding-agent";
|
|
26
|
+
//#region extensions/codex/src/app-server/local-runtime-attribution.ts
|
|
27
|
+
const OPENAI_PROVIDER_ID = "openai";
|
|
28
|
+
const OPENAI_RESPONSES_API = "openai-responses";
|
|
29
|
+
const OPENAI_CODEX_PROVIDER_ID = "openai-codex";
|
|
30
|
+
const OPENAI_CODEX_RESPONSES_API = "openai-codex-responses";
|
|
31
|
+
function normalizeRuntimeId(value) {
|
|
32
|
+
return value?.trim().toLowerCase() ?? "";
|
|
33
|
+
}
|
|
34
|
+
function resolveCodexLocalRuntimeAttribution(params) {
|
|
35
|
+
const authProfileProvider = normalizeRuntimeId(params.runtimePlan?.auth?.authProfileProviderForAuth);
|
|
36
|
+
if (normalizeRuntimeId(params.runtimePlan?.observability.harnessId) === "codex" && authProfileProvider !== OPENAI_PROVIDER_ID && normalizeRuntimeId(params.model.provider) === OPENAI_PROVIDER_ID && normalizeRuntimeId(params.model.api) === OPENAI_RESPONSES_API) return {
|
|
37
|
+
provider: OPENAI_CODEX_PROVIDER_ID,
|
|
38
|
+
api: OPENAI_CODEX_RESPONSES_API
|
|
39
|
+
};
|
|
40
|
+
return {
|
|
41
|
+
provider: params.provider,
|
|
42
|
+
api: params.model.api
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
//#endregion
|
|
26
46
|
//#region extensions/codex/src/app-server/native-subagent-task-mirror.ts
|
|
27
47
|
const CODEX_NATIVE_SUBAGENT_RUNTIME = "subagent";
|
|
28
48
|
const CODEX_NATIVE_SUBAGENT_TASK_KIND = "codex-native";
|
|
@@ -860,6 +880,7 @@ var CodexAppServerEventProjector = class {
|
|
|
860
880
|
data: {
|
|
861
881
|
phase: "end",
|
|
862
882
|
backend: "codex-app-server",
|
|
883
|
+
completed: true,
|
|
863
884
|
threadId: this.threadId,
|
|
864
885
|
turnId: this.turnId,
|
|
865
886
|
itemId
|
|
@@ -1017,8 +1038,14 @@ var CodexAppServerEventProjector = class {
|
|
|
1017
1038
|
const text = extractRawAssistantText(item);
|
|
1018
1039
|
if (!text) return;
|
|
1019
1040
|
const itemId = readString$2(item, "id") ?? `raw-assistant-${this.assistantItemOrder.length + 1}`;
|
|
1041
|
+
const phase = readString$2(item, "phase");
|
|
1042
|
+
if (phase) this.assistantPhaseByItem.set(itemId, phase);
|
|
1020
1043
|
this.rememberAssistantItem(itemId);
|
|
1021
1044
|
this.assistantTextByItem.set(itemId, text);
|
|
1045
|
+
if (phase === "commentary") this.emitCommentaryProgress({
|
|
1046
|
+
itemId,
|
|
1047
|
+
text
|
|
1048
|
+
});
|
|
1022
1049
|
}
|
|
1023
1050
|
recordNativeGeneratedMedia(item) {
|
|
1024
1051
|
if (item?.type !== "imageGeneration") return;
|
|
@@ -1327,6 +1354,7 @@ var CodexAppServerEventProjector = class {
|
|
|
1327
1354
|
return await readCodexMirroredSessionHistoryMessages(this.params.sessionFile) ?? [];
|
|
1328
1355
|
}
|
|
1329
1356
|
createAssistantMessage(text) {
|
|
1357
|
+
const attribution = resolveCodexLocalRuntimeAttribution(this.params);
|
|
1330
1358
|
const usage = this.tokenUsage ? {
|
|
1331
1359
|
input: this.tokenUsage.input ?? 0,
|
|
1332
1360
|
output: this.tokenUsage.output ?? 0,
|
|
@@ -1341,8 +1369,8 @@ var CodexAppServerEventProjector = class {
|
|
|
1341
1369
|
type: "text",
|
|
1342
1370
|
text
|
|
1343
1371
|
}],
|
|
1344
|
-
api:
|
|
1345
|
-
provider:
|
|
1372
|
+
api: attribution.api ?? "openai-codex-responses",
|
|
1373
|
+
provider: attribution.provider,
|
|
1346
1374
|
model: this.params.modelId,
|
|
1347
1375
|
usage,
|
|
1348
1376
|
stopReason: this.aborted ? "aborted" : this.promptError ? "error" : "stop",
|
|
@@ -1351,14 +1379,15 @@ var CodexAppServerEventProjector = class {
|
|
|
1351
1379
|
};
|
|
1352
1380
|
}
|
|
1353
1381
|
createAssistantMirrorMessage(title, text) {
|
|
1382
|
+
const attribution = resolveCodexLocalRuntimeAttribution(this.params);
|
|
1354
1383
|
return {
|
|
1355
1384
|
role: "assistant",
|
|
1356
1385
|
content: [{
|
|
1357
1386
|
type: "text",
|
|
1358
1387
|
text: `${title}:\n${text}`
|
|
1359
1388
|
}],
|
|
1360
|
-
api:
|
|
1361
|
-
provider:
|
|
1389
|
+
api: attribution.api ?? "openai-codex-responses",
|
|
1390
|
+
provider: attribution.provider,
|
|
1362
1391
|
model: this.params.modelId,
|
|
1363
1392
|
usage: ZERO_USAGE,
|
|
1364
1393
|
stopReason: "stop",
|
|
@@ -1367,6 +1396,7 @@ var CodexAppServerEventProjector = class {
|
|
|
1367
1396
|
}
|
|
1368
1397
|
createToolCallMessage(params) {
|
|
1369
1398
|
const args = normalizeToolTranscriptArguments(params.arguments);
|
|
1399
|
+
const attribution = resolveCodexLocalRuntimeAttribution(this.params);
|
|
1370
1400
|
return {
|
|
1371
1401
|
role: "assistant",
|
|
1372
1402
|
content: [{
|
|
@@ -1376,8 +1406,8 @@ var CodexAppServerEventProjector = class {
|
|
|
1376
1406
|
arguments: args,
|
|
1377
1407
|
input: args
|
|
1378
1408
|
}],
|
|
1379
|
-
api:
|
|
1380
|
-
provider:
|
|
1409
|
+
api: attribution.api ?? "openai-codex-responses",
|
|
1410
|
+
provider: attribution.provider,
|
|
1381
1411
|
model: this.params.modelId,
|
|
1382
1412
|
usage: ZERO_USAGE,
|
|
1383
1413
|
stopReason: "toolUse",
|
|
@@ -1882,6 +1912,7 @@ function createCodexTrajectoryRecorder(params) {
|
|
|
1882
1912
|
});
|
|
1883
1913
|
let queue = Promise.resolve();
|
|
1884
1914
|
let seq = 0;
|
|
1915
|
+
const attribution = resolveCodexLocalRuntimeAttribution(params.attempt);
|
|
1885
1916
|
return {
|
|
1886
1917
|
filePath,
|
|
1887
1918
|
recordEvent: (type, data) => {
|
|
@@ -1898,9 +1929,9 @@ function createCodexTrajectoryRecorder(params) {
|
|
|
1898
1929
|
sessionKey: params.attempt.sessionKey,
|
|
1899
1930
|
runId: params.attempt.runId,
|
|
1900
1931
|
workspaceDir: params.cwd,
|
|
1901
|
-
provider:
|
|
1932
|
+
provider: attribution.provider,
|
|
1902
1933
|
modelId: params.attempt.modelId,
|
|
1903
|
-
modelApi:
|
|
1934
|
+
modelApi: attribution.api,
|
|
1904
1935
|
data: data ? sanitizeValue(data) : void 0
|
|
1905
1936
|
});
|
|
1906
1937
|
if (!line) return;
|
|
@@ -2186,6 +2217,7 @@ const CODEX_TURN_ASSISTANT_COMPLETION_IDLE_TIMEOUT_MS = 1e4;
|
|
|
2186
2217
|
const CODEX_TURN_TERMINAL_IDLE_TIMEOUT_MS = 30 * 6e4;
|
|
2187
2218
|
const CODEX_NATIVE_HOOK_RELAY_MIN_TTL_MS = 30 * 6e4;
|
|
2188
2219
|
const CODEX_NATIVE_HOOK_RELAY_TTL_GRACE_MS = 5 * 6e4;
|
|
2220
|
+
const CODEX_NATIVE_HOOK_RELAY_RENEW_INTERVAL_MS = 6e4;
|
|
2189
2221
|
const CODEX_STEER_ALL_DEBOUNCE_MS = 500;
|
|
2190
2222
|
const LOG_FIELD_MAX_LENGTH = 160;
|
|
2191
2223
|
const CODEX_NATIVE_PROJECT_DOC_BASENAMES = new Set(["agents.md"]);
|
|
@@ -2612,7 +2644,7 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
2612
2644
|
prePromptMessageCount = projection.prePromptMessageCount;
|
|
2613
2645
|
}
|
|
2614
2646
|
const buildPromptFromCurrentInputs = () => resolveAgentHarnessBeforePromptBuildResult({
|
|
2615
|
-
prompt:
|
|
2647
|
+
prompt: prependCurrentInboundContext(promptText, params.currentInboundContext),
|
|
2616
2648
|
developerInstructions,
|
|
2617
2649
|
messages: historyMessages,
|
|
2618
2650
|
ctx: hookContext
|
|
@@ -2661,11 +2693,12 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
2661
2693
|
turnStartTimeoutMs: params.timeoutMs,
|
|
2662
2694
|
signal: runAbortController.signal
|
|
2663
2695
|
});
|
|
2664
|
-
const
|
|
2696
|
+
const nativeHookRelayConfig = nativeHookRelay ? buildCodexNativeHookRelayConfig({
|
|
2665
2697
|
relay: nativeHookRelay,
|
|
2666
2698
|
events: nativeHookRelayEvents,
|
|
2667
2699
|
hookTimeoutSec: options.nativeHookRelay?.hookTimeoutSec
|
|
2668
|
-
}) : options.nativeHookRelay?.enabled === false ? buildCodexNativeHookRelayDisabledConfig() : void 0
|
|
2700
|
+
}) : options.nativeHookRelay?.enabled === false ? buildCodexNativeHookRelayDisabledConfig() : void 0;
|
|
2701
|
+
const threadConfig = mergeCodexThreadConfigs(bundleMcpThreadConfig?.configPatch);
|
|
2669
2702
|
const pluginThreadConfigEnabled = shouldBuildCodexPluginThreadConfig(pluginConfig);
|
|
2670
2703
|
const pluginAppCacheKey = buildCodexPluginAppCacheKey({
|
|
2671
2704
|
appServer,
|
|
@@ -2708,6 +2741,7 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
2708
2741
|
appServer: pluginAppServer,
|
|
2709
2742
|
developerInstructions: promptBuild.developerInstructions,
|
|
2710
2743
|
config: threadConfig,
|
|
2744
|
+
finalConfigPatch: nativeHookRelayConfig,
|
|
2711
2745
|
mcpServersFingerprint: bundleMcpThreadConfig.fingerprint,
|
|
2712
2746
|
mcpServersFingerprintEvaluated: bundleMcpThreadConfig.evaluated,
|
|
2713
2747
|
contextEngineProjection,
|
|
@@ -2794,9 +2828,12 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
2794
2828
|
let userInputBridge;
|
|
2795
2829
|
let steeringQueue;
|
|
2796
2830
|
let completed = false;
|
|
2831
|
+
let terminalTurnNotificationQueued = false;
|
|
2797
2832
|
let timedOut = false;
|
|
2798
2833
|
let turnCompletionIdleTimedOut = false;
|
|
2799
2834
|
let turnCompletionIdleTimeoutMessage;
|
|
2835
|
+
let clientClosedPromptError;
|
|
2836
|
+
let clientClosedAbort = false;
|
|
2800
2837
|
let lifecycleStarted = false;
|
|
2801
2838
|
let lifecycleTerminalEmitted = false;
|
|
2802
2839
|
let resolveCompletion;
|
|
@@ -2810,18 +2847,27 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
2810
2847
|
let turnCompletionIdleTimer;
|
|
2811
2848
|
let turnCompletionIdleWatchArmed = false;
|
|
2812
2849
|
let turnCompletionIdleWatchPinnedByTerminalError = false;
|
|
2850
|
+
let turnCompletionIdleTimeoutOverrideMs;
|
|
2813
2851
|
let turnAssistantCompletionIdleTimer;
|
|
2814
2852
|
let turnAssistantCompletionIdleWatchArmed = false;
|
|
2815
2853
|
let turnAssistantCompletionLastActivityAt = Date.now();
|
|
2816
2854
|
let turnAssistantCompletionLastActivityDetails;
|
|
2855
|
+
const turnAttemptIdleTimeoutMs = Math.max(100, Math.floor(params.timeoutMs));
|
|
2856
|
+
let turnAttemptIdleTimer;
|
|
2857
|
+
let turnAttemptIdleWatchArmed = false;
|
|
2817
2858
|
let turnTerminalIdleTimer;
|
|
2818
2859
|
let turnTerminalIdleWatchArmed = false;
|
|
2819
2860
|
let turnCompletionLastActivityAt = Date.now();
|
|
2820
2861
|
let turnCompletionLastActivityReason = "startup";
|
|
2821
2862
|
let turnCompletionLastActivityDetails;
|
|
2863
|
+
let turnAttemptLastProgressAt = Date.now();
|
|
2864
|
+
let turnAttemptLastProgressReason = "startup";
|
|
2865
|
+
let turnAttemptLastProgressDetails;
|
|
2866
|
+
let nativeHookRelayLastRenewedAt = 0;
|
|
2822
2867
|
let activeAppServerTurnRequests = 0;
|
|
2823
2868
|
const activeOpenClawDynamicToolCallIds = /* @__PURE__ */ new Set();
|
|
2824
2869
|
const activeTurnItemIds = /* @__PURE__ */ new Set();
|
|
2870
|
+
let turnCrossedToolHandoff = false;
|
|
2825
2871
|
const clearTurnCompletionIdleTimer = () => {
|
|
2826
2872
|
if (turnCompletionIdleTimer) {
|
|
2827
2873
|
clearTimeout(turnCompletionIdleTimer);
|
|
@@ -2840,6 +2886,12 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
2840
2886
|
turnAssistantCompletionIdleTimer = void 0;
|
|
2841
2887
|
}
|
|
2842
2888
|
};
|
|
2889
|
+
const clearTurnAttemptIdleTimer = () => {
|
|
2890
|
+
if (turnAttemptIdleTimer) {
|
|
2891
|
+
clearTimeout(turnAttemptIdleTimer);
|
|
2892
|
+
turnAttemptIdleTimer = void 0;
|
|
2893
|
+
}
|
|
2894
|
+
};
|
|
2843
2895
|
const fireTurnAssistantCompletionIdleRelease = () => {
|
|
2844
2896
|
if (completed || runAbortController.signal.aborted || !turnAssistantCompletionIdleWatchArmed) return;
|
|
2845
2897
|
if (activeAppServerTurnRequests > 0 || activeTurnItemIds.size > 0) {
|
|
@@ -2876,10 +2928,40 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
2876
2928
|
completed = true;
|
|
2877
2929
|
resolveCompletion?.();
|
|
2878
2930
|
};
|
|
2931
|
+
const fireTurnAttemptIdleTimeout = () => {
|
|
2932
|
+
if (completed || runAbortController.signal.aborted || !turnAttemptIdleWatchArmed) return;
|
|
2933
|
+
const idleMs = Math.max(0, Date.now() - turnAttemptLastProgressAt);
|
|
2934
|
+
if (idleMs < turnAttemptIdleTimeoutMs) {
|
|
2935
|
+
scheduleTurnAttemptIdleWatch();
|
|
2936
|
+
return;
|
|
2937
|
+
}
|
|
2938
|
+
timedOut = true;
|
|
2939
|
+
turnCompletionIdleTimedOut = true;
|
|
2940
|
+
turnCompletionIdleTimeoutMessage = "codex app-server turn idle timed out waiting for turn/completed";
|
|
2941
|
+
projector?.markTimedOut();
|
|
2942
|
+
trajectoryRecorder?.recordEvent("turn.progress_idle_timeout", {
|
|
2943
|
+
threadId: thread.threadId,
|
|
2944
|
+
turnId,
|
|
2945
|
+
idleMs,
|
|
2946
|
+
timeoutMs: turnAttemptIdleTimeoutMs,
|
|
2947
|
+
lastActivityReason: turnAttemptLastProgressReason,
|
|
2948
|
+
...turnAttemptLastProgressDetails
|
|
2949
|
+
});
|
|
2950
|
+
embeddedAgentLog.warn("codex app-server turn idle timed out waiting for progress", {
|
|
2951
|
+
threadId: thread.threadId,
|
|
2952
|
+
turnId,
|
|
2953
|
+
idleMs,
|
|
2954
|
+
timeoutMs: turnAttemptIdleTimeoutMs,
|
|
2955
|
+
lastActivityReason: turnAttemptLastProgressReason,
|
|
2956
|
+
...turnAttemptLastProgressDetails
|
|
2957
|
+
});
|
|
2958
|
+
runAbortController.abort("turn_progress_idle_timeout");
|
|
2959
|
+
};
|
|
2879
2960
|
const fireTurnCompletionIdleTimeout = () => {
|
|
2880
2961
|
if (completed || runAbortController.signal.aborted || !turnCompletionIdleWatchArmed || activeAppServerTurnRequests > 0) return;
|
|
2962
|
+
const timeoutMs = turnCompletionIdleTimeoutOverrideMs ?? turnCompletionIdleTimeoutMs;
|
|
2881
2963
|
const idleMs = Math.max(0, Date.now() - turnCompletionLastActivityAt);
|
|
2882
|
-
if (idleMs <
|
|
2964
|
+
if (idleMs < timeoutMs) {
|
|
2883
2965
|
scheduleTurnCompletionIdleWatch();
|
|
2884
2966
|
return;
|
|
2885
2967
|
}
|
|
@@ -2891,7 +2973,7 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
2891
2973
|
threadId: thread.threadId,
|
|
2892
2974
|
turnId,
|
|
2893
2975
|
idleMs,
|
|
2894
|
-
timeoutMs
|
|
2976
|
+
timeoutMs,
|
|
2895
2977
|
lastActivityReason: turnCompletionLastActivityReason,
|
|
2896
2978
|
...turnCompletionLastActivityDetails
|
|
2897
2979
|
});
|
|
@@ -2899,7 +2981,7 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
2899
2981
|
threadId: thread.threadId,
|
|
2900
2982
|
turnId,
|
|
2901
2983
|
idleMs,
|
|
2902
|
-
timeoutMs
|
|
2984
|
+
timeoutMs,
|
|
2903
2985
|
lastActivityReason: turnCompletionLastActivityReason,
|
|
2904
2986
|
...turnCompletionLastActivityDetails
|
|
2905
2987
|
});
|
|
@@ -2938,7 +3020,7 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
2938
3020
|
clearTurnCompletionIdleTimer();
|
|
2939
3021
|
if (completed || runAbortController.signal.aborted || !turnCompletionIdleWatchArmed || activeAppServerTurnRequests > 0) return;
|
|
2940
3022
|
const elapsedMs = Math.max(0, Date.now() - turnCompletionLastActivityAt);
|
|
2941
|
-
const delayMs = Math.max(1, turnCompletionIdleTimeoutMs - elapsedMs);
|
|
3023
|
+
const delayMs = Math.max(1, (turnCompletionIdleTimeoutOverrideMs ?? turnCompletionIdleTimeoutMs) - elapsedMs);
|
|
2942
3024
|
turnCompletionIdleTimer = setTimeout(fireTurnCompletionIdleTimeout, delayMs);
|
|
2943
3025
|
turnCompletionIdleTimer.unref?.();
|
|
2944
3026
|
}
|
|
@@ -2950,6 +3032,14 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
2950
3032
|
turnAssistantCompletionIdleTimer = setTimeout(fireTurnAssistantCompletionIdleRelease, delayMs);
|
|
2951
3033
|
turnAssistantCompletionIdleTimer.unref?.();
|
|
2952
3034
|
}
|
|
3035
|
+
function scheduleTurnAttemptIdleWatch() {
|
|
3036
|
+
clearTurnAttemptIdleTimer();
|
|
3037
|
+
if (completed || runAbortController.signal.aborted || !turnAttemptIdleWatchArmed) return;
|
|
3038
|
+
const elapsedMs = Math.max(0, Date.now() - turnAttemptLastProgressAt);
|
|
3039
|
+
const delayMs = Math.max(1, turnAttemptIdleTimeoutMs - elapsedMs);
|
|
3040
|
+
turnAttemptIdleTimer = setTimeout(fireTurnAttemptIdleTimeout, delayMs);
|
|
3041
|
+
turnAttemptIdleTimer.unref?.();
|
|
3042
|
+
}
|
|
2953
3043
|
function scheduleTurnTerminalIdleWatch() {
|
|
2954
3044
|
clearTurnTerminalIdleTimer();
|
|
2955
3045
|
if (completed || runAbortController.signal.aborted || !turnTerminalIdleWatchArmed || activeAppServerTurnRequests > 0) return;
|
|
@@ -2958,10 +3048,42 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
2958
3048
|
turnTerminalIdleTimer = setTimeout(fireTurnTerminalIdleTimeout, delayMs);
|
|
2959
3049
|
turnTerminalIdleTimer.unref?.();
|
|
2960
3050
|
}
|
|
3051
|
+
function scheduleTurnProgressWatches() {
|
|
3052
|
+
scheduleTurnAttemptIdleWatch();
|
|
3053
|
+
scheduleTurnCompletionIdleWatch();
|
|
3054
|
+
scheduleTurnTerminalIdleWatch();
|
|
3055
|
+
}
|
|
3056
|
+
const renewNativeHookRelayForTurnProgress = () => {
|
|
3057
|
+
if (!nativeHookRelay || options.nativeHookRelay?.ttlMs !== void 0) return;
|
|
3058
|
+
const now = Date.now();
|
|
3059
|
+
const renewsRecently = now - nativeHookRelayLastRenewedAt < CODEX_NATIVE_HOOK_RELAY_RENEW_INTERVAL_MS;
|
|
3060
|
+
const expiresSoon = now >= nativeHookRelay.expiresAtMs - CODEX_NATIVE_HOOK_RELAY_TTL_GRACE_MS;
|
|
3061
|
+
if (renewsRecently && !expiresSoon) return;
|
|
3062
|
+
nativeHookRelayLastRenewedAt = now;
|
|
3063
|
+
nativeHookRelay.renew(resolveCodexNativeHookRelayTtlMs({
|
|
3064
|
+
explicitTtlMs: void 0,
|
|
3065
|
+
attemptTimeoutMs: turnAttemptIdleTimeoutMs,
|
|
3066
|
+
startupTimeoutMs,
|
|
3067
|
+
turnStartTimeoutMs: params.timeoutMs
|
|
3068
|
+
}));
|
|
3069
|
+
};
|
|
2961
3070
|
const touchTurnCompletionActivity = (reason, options) => {
|
|
2962
3071
|
turnCompletionLastActivityAt = Date.now();
|
|
2963
3072
|
turnCompletionLastActivityReason = reason;
|
|
2964
3073
|
turnCompletionLastActivityDetails = options?.details;
|
|
3074
|
+
turnCompletionIdleTimeoutOverrideMs = void 0;
|
|
3075
|
+
if (options?.attemptProgress) {
|
|
3076
|
+
turnAttemptLastProgressAt = turnCompletionLastActivityAt;
|
|
3077
|
+
turnAttemptLastProgressReason = reason;
|
|
3078
|
+
turnAttemptLastProgressDetails = options.details;
|
|
3079
|
+
renewNativeHookRelayForTurnProgress();
|
|
3080
|
+
params.onRunProgress?.({
|
|
3081
|
+
reason,
|
|
3082
|
+
provider: params.provider,
|
|
3083
|
+
model: params.modelId,
|
|
3084
|
+
backend: "codex-app-server"
|
|
3085
|
+
});
|
|
3086
|
+
}
|
|
2965
3087
|
emitTrustedDiagnosticEvent({
|
|
2966
3088
|
type: "run.progress",
|
|
2967
3089
|
runId: params.runId,
|
|
@@ -2973,12 +3095,12 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
2973
3095
|
turnCompletionIdleWatchArmed = true;
|
|
2974
3096
|
turnCompletionIdleWatchPinnedByTerminalError = false;
|
|
2975
3097
|
}
|
|
2976
|
-
|
|
2977
|
-
scheduleTurnTerminalIdleWatch();
|
|
3098
|
+
scheduleTurnProgressWatches();
|
|
2978
3099
|
};
|
|
2979
3100
|
const disarmTurnCompletionIdleWatch = () => {
|
|
2980
3101
|
turnCompletionIdleWatchArmed = false;
|
|
2981
3102
|
turnCompletionIdleWatchPinnedByTerminalError = false;
|
|
3103
|
+
turnCompletionIdleTimeoutOverrideMs = void 0;
|
|
2982
3104
|
clearTurnCompletionIdleTimer();
|
|
2983
3105
|
};
|
|
2984
3106
|
const disarmTurnAssistantCompletionIdleWatch = () => {
|
|
@@ -2995,6 +3117,7 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
2995
3117
|
const armTurnCompletionIdleWatch = (options) => {
|
|
2996
3118
|
turnCompletionIdleWatchArmed = true;
|
|
2997
3119
|
turnCompletionIdleWatchPinnedByTerminalError = options?.pinnedByTerminalError === true;
|
|
3120
|
+
turnCompletionIdleTimeoutOverrideMs = options?.timeoutMs !== void 0 ? Math.max(1, Math.floor(options.timeoutMs)) : void 0;
|
|
2998
3121
|
scheduleTurnCompletionIdleWatch();
|
|
2999
3122
|
};
|
|
3000
3123
|
const emitLifecycleStart = () => {
|
|
@@ -3049,6 +3172,10 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
3049
3172
|
itemId: item.id
|
|
3050
3173
|
});
|
|
3051
3174
|
};
|
|
3175
|
+
const isTerminalTurnNotificationForTurn = (notification, notificationTurnId) => {
|
|
3176
|
+
if (!isTurnNotification(notification.params, thread.threadId, notificationTurnId)) return false;
|
|
3177
|
+
return notification.method === "turn/completed" || isCodexTurnAbortMarkerNotification(notification, { currentPromptText: promptBuild.prompt });
|
|
3178
|
+
};
|
|
3052
3179
|
const handleNotification = async (notification) => {
|
|
3053
3180
|
userInputBridge?.handleNotification(notification);
|
|
3054
3181
|
if (!projector || !turnId) {
|
|
@@ -3058,27 +3185,35 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
3058
3185
|
const isCurrentTurnNotification = isTurnNotification(notification.params, thread.threadId, turnId);
|
|
3059
3186
|
const isTurnCompletion = notification.method === "turn/completed" && isCurrentTurnNotification;
|
|
3060
3187
|
if (isCurrentTurnNotification) {
|
|
3061
|
-
touchTurnCompletionActivity(`notification:${notification.method}`, {
|
|
3188
|
+
touchTurnCompletionActivity(`notification:${notification.method}`, {
|
|
3189
|
+
details: describeNotificationActivity(notification),
|
|
3190
|
+
attemptProgress: true
|
|
3191
|
+
});
|
|
3062
3192
|
reportCodexExecutionNotification(notification);
|
|
3063
3193
|
}
|
|
3064
3194
|
if (isCurrentTurnNotification) updateActiveTurnItemIds(notification, activeTurnItemIds);
|
|
3065
3195
|
const unblockedAssistantCompletionRelease = isCurrentTurnNotification && turnAssistantCompletionIdleWatchArmed && notification.method === "item/completed" && activeTurnItemIds.size === 0;
|
|
3066
3196
|
const trackedDynamicToolCompletion = isTrackedOpenClawDynamicToolCompletionNotification(notification, activeOpenClawDynamicToolCallIds);
|
|
3067
3197
|
const rawToolOutputCompletion = isRawToolOutputCompletionNotification(notification);
|
|
3068
|
-
|
|
3198
|
+
if (isCurrentTurnNotification && (rawToolOutputCompletion || isNativeToolProgressNotification(notification))) turnCrossedToolHandoff = true;
|
|
3199
|
+
const assistantCompletionCanRelease = isAssistantCompletionReleaseNotification(notification, turnCrossedToolHandoff);
|
|
3200
|
+
const postToolRawAssistantCompletionNeedsTerminalGuard = isCurrentTurnNotification && turnCrossedToolHandoff && isRawAssistantCompletionNotification(notification) && activeTurnItemIds.size === 0;
|
|
3201
|
+
const shouldRearmCompletionIdleWatchAfterLastCurrentTurnItem = isCurrentTurnNotification && notification.method === "item/completed" && activeTurnItemIds.size === 0 && !trackedDynamicToolCompletion && !assistantCompletionCanRelease;
|
|
3069
3202
|
if (isCurrentTurnNotification && notification.method === "error") {
|
|
3070
3203
|
if (isRetryableErrorNotification(notification.params)) disarmTurnCompletionIdleWatch();
|
|
3071
3204
|
else armTurnCompletionIdleWatch({ pinnedByTerminalError: true });
|
|
3072
3205
|
disarmTurnAssistantCompletionIdleWatch();
|
|
3073
3206
|
} else if (isTurnCompletion) disarmTurnAssistantCompletionIdleWatch();
|
|
3074
|
-
else if (isCurrentTurnNotification &&
|
|
3207
|
+
else if (isCurrentTurnNotification && assistantCompletionCanRelease) armTurnAssistantCompletionIdleWatch(describeNotificationActivity(notification));
|
|
3208
|
+
else if (postToolRawAssistantCompletionNeedsTerminalGuard) armTurnCompletionIdleWatch({ timeoutMs: turnAssistantCompletionIdleTimeoutMs });
|
|
3075
3209
|
else if (unblockedAssistantCompletionRelease) armTurnAssistantCompletionIdleWatch(describeNotificationActivity(notification));
|
|
3076
3210
|
else if (shouldRearmCompletionIdleWatchAfterLastCurrentTurnItem) armTurnCompletionIdleWatch();
|
|
3077
3211
|
else if (isCurrentTurnNotification && rawToolOutputCompletion) armTurnCompletionIdleWatch();
|
|
3078
3212
|
else if (isCurrentTurnNotification && shouldDisarmAssistantCompletionIdleWatch(notification)) disarmTurnAssistantCompletionIdleWatch();
|
|
3079
|
-
if (turnCompletionIdleWatchArmed && !turnCompletionIdleWatchPinnedByTerminalError && notification.method !== "turn/completed" && isCurrentTurnNotification && !trackedDynamicToolCompletion && !rawToolOutputCompletion && !shouldRearmCompletionIdleWatchAfterLastCurrentTurnItem) disarmTurnCompletionIdleWatch();
|
|
3213
|
+
if (turnCompletionIdleWatchArmed && !turnCompletionIdleWatchPinnedByTerminalError && notification.method !== "turn/completed" && isCurrentTurnNotification && !trackedDynamicToolCompletion && !rawToolOutputCompletion && !postToolRawAssistantCompletionNeedsTerminalGuard && !shouldRearmCompletionIdleWatchAfterLastCurrentTurnItem) disarmTurnCompletionIdleWatch();
|
|
3080
3214
|
const isTurnAbortMarker = isCurrentTurnNotification && isCodexTurnAbortMarkerNotification(notification, { currentPromptText: promptBuild.prompt });
|
|
3081
|
-
const isTurnTerminal =
|
|
3215
|
+
const isTurnTerminal = isTerminalTurnNotificationForTurn(notification, turnId);
|
|
3216
|
+
if (isTurnTerminal) terminalTurnNotificationQueued = true;
|
|
3082
3217
|
try {
|
|
3083
3218
|
await waitForCodexNotificationDispatchTurn();
|
|
3084
3219
|
await projector.handleNotification(notification);
|
|
@@ -3105,16 +3240,21 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
3105
3240
|
pendingNotifications.push(notification);
|
|
3106
3241
|
return Promise.resolve();
|
|
3107
3242
|
}
|
|
3243
|
+
if (isTerminalTurnNotificationForTurn(notification, turnId)) terminalTurnNotificationQueued = true;
|
|
3108
3244
|
notificationQueue = notificationQueue.then(() => handleNotification(notification), () => handleNotification(notification));
|
|
3109
3245
|
return notificationQueue;
|
|
3110
3246
|
};
|
|
3111
3247
|
const notificationCleanup = client.addNotificationHandler(enqueueNotification);
|
|
3112
3248
|
const requestCleanup = client.addRequestHandler(async (request) => {
|
|
3113
|
-
activeAppServerTurnRequests += 1;
|
|
3114
|
-
clearTurnCompletionIdleTimer();
|
|
3115
|
-
disarmTurnAssistantCompletionIdleWatch();
|
|
3116
|
-
touchTurnCompletionActivity(`request:${request.method}`);
|
|
3117
3249
|
let armCompletionWatchOnResponse = false;
|
|
3250
|
+
let requestCountsAsTurnActivity = false;
|
|
3251
|
+
const markCurrentTurnRequestProgress = () => {
|
|
3252
|
+
activeAppServerTurnRequests += 1;
|
|
3253
|
+
clearTurnCompletionIdleTimer();
|
|
3254
|
+
disarmTurnAssistantCompletionIdleWatch();
|
|
3255
|
+
requestCountsAsTurnActivity = true;
|
|
3256
|
+
touchTurnCompletionActivity(`request:${request.method}:start`, { attemptProgress: true });
|
|
3257
|
+
};
|
|
3118
3258
|
try {
|
|
3119
3259
|
if (request.method === "account/chatgptAuthTokens/refresh") return refreshCodexAppServerAuthTokens({
|
|
3120
3260
|
agentDir,
|
|
@@ -3123,7 +3263,10 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
3123
3263
|
});
|
|
3124
3264
|
if (!turnId) return;
|
|
3125
3265
|
if (request.method === "mcpServer/elicitation/request") {
|
|
3126
|
-
|
|
3266
|
+
if (isCurrentThreadOptionalTurnRequestParams(request.params, thread.threadId, turnId)) {
|
|
3267
|
+
armCompletionWatchOnResponse = true;
|
|
3268
|
+
markCurrentTurnRequestProgress();
|
|
3269
|
+
}
|
|
3127
3270
|
return handleCodexAppServerElicitationRequest({
|
|
3128
3271
|
requestParams: request.params,
|
|
3129
3272
|
paramsForRun: params,
|
|
@@ -3134,7 +3277,10 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
3134
3277
|
});
|
|
3135
3278
|
}
|
|
3136
3279
|
if (request.method === "item/tool/requestUserInput") {
|
|
3137
|
-
|
|
3280
|
+
if (isCurrentThreadTurnRequestParams(request.params, thread.threadId, turnId)) {
|
|
3281
|
+
armCompletionWatchOnResponse = true;
|
|
3282
|
+
markCurrentTurnRequestProgress();
|
|
3283
|
+
}
|
|
3138
3284
|
return userInputBridge?.handleRequest({
|
|
3139
3285
|
id: request.id,
|
|
3140
3286
|
params: request.params
|
|
@@ -3142,7 +3288,10 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
3142
3288
|
}
|
|
3143
3289
|
if (request.method !== "item/tool/call") {
|
|
3144
3290
|
if (isCodexAppServerApprovalRequest(request.method)) {
|
|
3145
|
-
|
|
3291
|
+
if (isCurrentApprovalTurnRequestParams(request.params, thread.threadId, turnId)) {
|
|
3292
|
+
armCompletionWatchOnResponse = true;
|
|
3293
|
+
markCurrentTurnRequestProgress();
|
|
3294
|
+
}
|
|
3146
3295
|
return handleApprovalRequest({
|
|
3147
3296
|
method: request.method,
|
|
3148
3297
|
params: request.params,
|
|
@@ -3157,6 +3306,8 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
3157
3306
|
const call = readDynamicToolCallParams(request.params);
|
|
3158
3307
|
if (!call || call.threadId !== thread.threadId || call.turnId !== turnId) return;
|
|
3159
3308
|
armCompletionWatchOnResponse = true;
|
|
3309
|
+
markCurrentTurnRequestProgress();
|
|
3310
|
+
turnCrossedToolHandoff = true;
|
|
3160
3311
|
activeOpenClawDynamicToolCallIds.add(call.callId);
|
|
3161
3312
|
trajectoryRecorder?.recordEvent("tool.call", {
|
|
3162
3313
|
threadId: call.threadId,
|
|
@@ -3233,10 +3384,16 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
3233
3384
|
});
|
|
3234
3385
|
return response;
|
|
3235
3386
|
} finally {
|
|
3236
|
-
|
|
3237
|
-
|
|
3387
|
+
if (requestCountsAsTurnActivity) {
|
|
3388
|
+
activeAppServerTurnRequests = Math.max(0, activeAppServerTurnRequests - 1);
|
|
3389
|
+
touchTurnCompletionActivity(`request:${request.method}:response`, {
|
|
3390
|
+
arm: armCompletionWatchOnResponse,
|
|
3391
|
+
attemptProgress: true
|
|
3392
|
+
});
|
|
3393
|
+
} else scheduleTurnProgressWatches();
|
|
3238
3394
|
}
|
|
3239
3395
|
});
|
|
3396
|
+
let closeCleanup;
|
|
3240
3397
|
const forceContextEngineCompactionForCodexOverflow = async (error) => {
|
|
3241
3398
|
if (!activeContextEngine?.info.ownsCompaction) return false;
|
|
3242
3399
|
embeddedAgentLog.warn("codex app-server context-engine turn overflowed; forcing context-engine compaction", {
|
|
@@ -3465,6 +3622,27 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
3465
3622
|
imagesCount: params.images?.length ?? 0
|
|
3466
3623
|
});
|
|
3467
3624
|
projector = new CodexAppServerEventProjector(params, thread.threadId, activeTurnId, { nativePostToolUseRelayEnabled: nativeHookRelay?.allowedEvents.includes("post_tool_use") === true });
|
|
3625
|
+
if (isTerminalTurnStatus(turn.turn.status) || pendingNotifications.some((notification) => isTerminalTurnNotificationForTurn(notification, activeTurnId))) terminalTurnNotificationQueued = true;
|
|
3626
|
+
closeCleanup = client.addCloseHandler?.(() => {
|
|
3627
|
+
if (completed || terminalTurnNotificationQueued || runAbortController.signal.aborted) return;
|
|
3628
|
+
clientClosedPromptError = "codex app-server client closed before turn completed";
|
|
3629
|
+
trajectoryRecorder?.recordEvent("turn.client_closed", {
|
|
3630
|
+
threadId: thread.threadId,
|
|
3631
|
+
turnId: activeTurnId
|
|
3632
|
+
});
|
|
3633
|
+
embeddedAgentLog.warn("codex app-server client closed before turn completed", {
|
|
3634
|
+
threadId: thread.threadId,
|
|
3635
|
+
turnId: activeTurnId
|
|
3636
|
+
});
|
|
3637
|
+
clientClosedAbort = true;
|
|
3638
|
+
runAbortController.abort("client_closed");
|
|
3639
|
+
completed = true;
|
|
3640
|
+
clearTurnAttemptIdleTimer();
|
|
3641
|
+
clearTurnCompletionIdleTimer();
|
|
3642
|
+
clearTurnAssistantCompletionIdleTimer();
|
|
3643
|
+
clearTurnTerminalIdleTimer();
|
|
3644
|
+
resolveCompletion?.();
|
|
3645
|
+
});
|
|
3468
3646
|
emitLifecycleStart();
|
|
3469
3647
|
const activeProjector = projector;
|
|
3470
3648
|
turnTerminalIdleWatchArmed = true;
|
|
@@ -3495,11 +3673,9 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
3495
3673
|
abort: () => runAbortController.abort("aborted")
|
|
3496
3674
|
};
|
|
3497
3675
|
setActiveEmbeddedRun(params.sessionId, handle, params.sessionKey);
|
|
3498
|
-
|
|
3499
|
-
|
|
3500
|
-
|
|
3501
|
-
runAbortController.abort("timeout");
|
|
3502
|
-
}, Math.max(100, params.timeoutMs));
|
|
3676
|
+
turnAttemptIdleWatchArmed = true;
|
|
3677
|
+
turnTerminalIdleWatchArmed = true;
|
|
3678
|
+
touchTurnCompletionActivity("turn:start", { attemptProgress: true });
|
|
3503
3679
|
const abortListener = () => {
|
|
3504
3680
|
const shouldRetireClient = timedOut;
|
|
3505
3681
|
interruptCodexTurnBestEffort(client, {
|
|
@@ -3519,8 +3695,8 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
3519
3695
|
try {
|
|
3520
3696
|
await completion;
|
|
3521
3697
|
const result = activeProjector.buildResult(toolBridge.telemetry, { yieldDetected });
|
|
3522
|
-
const finalAborted = result.aborted || runAbortController.signal.aborted;
|
|
3523
|
-
let finalPromptError = turnCompletionIdleTimedOut ? turnCompletionIdleTimeoutMessage : timedOut ? "codex app-server attempt timed out" : result.promptError;
|
|
3698
|
+
const finalAborted = result.aborted || runAbortController.signal.aborted && !clientClosedAbort;
|
|
3699
|
+
let finalPromptError = clientClosedPromptError ?? (turnCompletionIdleTimedOut ? turnCompletionIdleTimeoutMessage : timedOut ? "codex app-server attempt timed out" : result.promptError);
|
|
3524
3700
|
const finalPromptErrorMessage = typeof finalPromptError === "string" ? finalPromptError : finalPromptError ? formatErrorMessage(finalPromptError) : void 0;
|
|
3525
3701
|
if (shouldRefreshCodexRateLimitsForUsageLimitMessage(finalPromptErrorMessage)) finalPromptError = await refreshCodexUsageLimitErrorMessage({
|
|
3526
3702
|
client,
|
|
@@ -3532,7 +3708,7 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
3532
3708
|
timeoutMs: appServer.requestTimeoutMs,
|
|
3533
3709
|
signal: runAbortController.signal
|
|
3534
3710
|
});
|
|
3535
|
-
const finalPromptErrorSource = timedOut ? "prompt" : result.promptErrorSource;
|
|
3711
|
+
const finalPromptErrorSource = timedOut || clientClosedPromptError ? "prompt" : result.promptErrorSource;
|
|
3536
3712
|
recordCodexTrajectoryCompletion(trajectoryRecorder, {
|
|
3537
3713
|
attempt: params,
|
|
3538
3714
|
result,
|
|
@@ -3638,11 +3814,11 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
3638
3814
|
error: "codex app-server run completed without lifecycle terminal event"
|
|
3639
3815
|
});
|
|
3640
3816
|
if (trajectoryRecorder && !trajectoryEndRecorded) trajectoryRecorder.recordEvent("session.ended", {
|
|
3641
|
-
status: timedOut || runAbortController.signal.aborted ? "interrupted" : "cleanup",
|
|
3817
|
+
status: timedOut || runAbortController.signal.aborted && !clientClosedAbort ? "interrupted" : "cleanup",
|
|
3642
3818
|
threadId: thread.threadId,
|
|
3643
3819
|
turnId: activeTurnId,
|
|
3644
3820
|
timedOut,
|
|
3645
|
-
aborted: runAbortController.signal.aborted
|
|
3821
|
+
aborted: runAbortController.signal.aborted && !clientClosedAbort
|
|
3646
3822
|
});
|
|
3647
3823
|
await runAgentCleanupStep({
|
|
3648
3824
|
runId: params.runId,
|
|
@@ -3655,12 +3831,13 @@ async function runCodexAppServerAttempt(params, options = {}) {
|
|
|
3655
3831
|
});
|
|
3656
3832
|
if (!timedOut && !runAbortController.signal.aborted) await steeringQueue?.flushPending();
|
|
3657
3833
|
userInputBridge?.cancelPending();
|
|
3658
|
-
|
|
3834
|
+
clearTurnAttemptIdleTimer();
|
|
3659
3835
|
clearTurnCompletionIdleTimer();
|
|
3660
3836
|
clearTurnAssistantCompletionIdleTimer();
|
|
3661
3837
|
clearTurnTerminalIdleTimer();
|
|
3662
3838
|
notificationCleanup();
|
|
3663
3839
|
requestCleanup();
|
|
3840
|
+
closeCleanup?.();
|
|
3664
3841
|
nativeHookRelay?.unregister();
|
|
3665
3842
|
runAbortController.signal.removeEventListener("abort", abortListener);
|
|
3666
3843
|
params.abortSignal?.removeEventListener("abort", abortFromUpstream);
|
|
@@ -4217,6 +4394,10 @@ function isCompletedAssistantNotification(notification) {
|
|
|
4217
4394
|
const item = isJsonObject(notification.params.item) ? notification.params.item : void 0;
|
|
4218
4395
|
return Boolean(item && readString(item, "type") === "agentMessage" && readString(item, "phase") !== "commentary");
|
|
4219
4396
|
}
|
|
4397
|
+
function isAssistantCompletionReleaseNotification(notification, turnCrossedToolHandoff) {
|
|
4398
|
+
if (isCompletedAssistantNotification(notification)) return true;
|
|
4399
|
+
return !turnCrossedToolHandoff && isRawAssistantCompletionNotification(notification);
|
|
4400
|
+
}
|
|
4220
4401
|
function shouldDisarmAssistantCompletionIdleWatch(notification) {
|
|
4221
4402
|
if (!isJsonObject(notification.params)) return false;
|
|
4222
4403
|
if (notification.method === "item/started") return true;
|
|
@@ -4241,6 +4422,23 @@ function isRawToolOutputCompletionNotification(notification) {
|
|
|
4241
4422
|
const item = isJsonObject(notification.params.item) ? notification.params.item : void 0;
|
|
4242
4423
|
return item ? readString(item, "type") === "custom_tool_call_output" : false;
|
|
4243
4424
|
}
|
|
4425
|
+
function isNativeToolProgressNotification(notification) {
|
|
4426
|
+
if (notification.method !== "item/started" && notification.method !== "item/completed" && notification.method !== "item/updated") return false;
|
|
4427
|
+
if (!isJsonObject(notification.params)) return false;
|
|
4428
|
+
const item = isJsonObject(notification.params.item) ? notification.params.item : void 0;
|
|
4429
|
+
switch (item ? readString(item, "type") : void 0) {
|
|
4430
|
+
case "commandExecution":
|
|
4431
|
+
case "fileChange":
|
|
4432
|
+
case "mcpToolCall":
|
|
4433
|
+
case "webSearch": return true;
|
|
4434
|
+
default: return false;
|
|
4435
|
+
}
|
|
4436
|
+
}
|
|
4437
|
+
function isRawAssistantCompletionNotification(notification) {
|
|
4438
|
+
if (notification.method !== "rawResponseItem/completed" || !isJsonObject(notification.params)) return false;
|
|
4439
|
+
const item = isJsonObject(notification.params.item) ? notification.params.item : void 0;
|
|
4440
|
+
return Boolean(item && readString(item, "type") === "message" && readString(item, "role") === "assistant" && readString(item, "phase") !== "commentary" && readRawAssistantTextPreview(item));
|
|
4441
|
+
}
|
|
4244
4442
|
function readRawAssistantTextPreview(item) {
|
|
4245
4443
|
if (readString(item, "role") !== "assistant" || !Array.isArray(item.content)) return;
|
|
4246
4444
|
const text = item.content.flatMap((content) => {
|
|
@@ -4255,6 +4453,19 @@ function isTurnNotification(value, threadId, turnId) {
|
|
|
4255
4453
|
if (!isJsonObject(value)) return false;
|
|
4256
4454
|
return readString(value, "threadId") === threadId && readNotificationTurnId(value) === turnId;
|
|
4257
4455
|
}
|
|
4456
|
+
function isCurrentThreadTurnRequestParams(value, threadId, turnId) {
|
|
4457
|
+
if (!isJsonObject(value)) return false;
|
|
4458
|
+
return readString(value, "threadId") === threadId && readString(value, "turnId") === turnId;
|
|
4459
|
+
}
|
|
4460
|
+
function isCurrentApprovalTurnRequestParams(value, threadId, turnId) {
|
|
4461
|
+
if (!isJsonObject(value)) return false;
|
|
4462
|
+
return (readString(value, "threadId") ?? readString(value, "conversationId")) === threadId && readString(value, "turnId") === turnId;
|
|
4463
|
+
}
|
|
4464
|
+
function isCurrentThreadOptionalTurnRequestParams(value, threadId, turnId) {
|
|
4465
|
+
if (!isJsonObject(value) || readString(value, "threadId") !== threadId) return false;
|
|
4466
|
+
const requestTurnId = value.turnId;
|
|
4467
|
+
return requestTurnId === null || requestTurnId === void 0 || requestTurnId === turnId;
|
|
4468
|
+
}
|
|
4258
4469
|
function isRetryableErrorNotification(value) {
|
|
4259
4470
|
if (!isJsonObject(value)) return false;
|
|
4260
4471
|
return readBoolean(value, "willRetry") === true || readBoolean(value, "will_retry") === true;
|
|
@@ -4522,7 +4733,7 @@ function codexExecutionToolName(item) {
|
|
|
4522
4733
|
function joinPresentSections(...sections) {
|
|
4523
4734
|
return sections.filter((section) => Boolean(section?.trim())).join("\n\n");
|
|
4524
4735
|
}
|
|
4525
|
-
function
|
|
4736
|
+
function prependCurrentInboundContext(prompt, context) {
|
|
4526
4737
|
const text = context?.text.trim();
|
|
4527
4738
|
return text ? [text, prompt].filter(Boolean).join("\n\n") : prompt;
|
|
4528
4739
|
}
|