@openclaw/codex 2026.7.2-beta.7 → 2026.8.1-beta.2
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/README.md +2 -0
- package/dist/{app-server-policy-BSaO2JIT.js → app-server-policy-zcBDc1JU.js} +1 -1
- package/dist/attempt-client-cleanup-DMLXUfa8.js +735 -0
- package/dist/{notification-correlation-CU6_AnOb.js → binding-connection-I5Bo-AsX.js} +3 -37
- package/dist/{bounded-turn-D2ZAgZVz.js → bounded-turn-qgZmzy_4.js} +50 -49
- package/dist/{capabilities-BFDTVYr4.js → capabilities-CybGI1oz.js} +8 -2
- package/dist/cli-metadata.js +1 -1
- package/dist/{command-formatters-C336eRVS.js → command-formatters-B1AEz8ZA.js} +18 -18
- package/dist/{command-handlers-DAHUSry9.js → command-handlers-Db8pu_ds.js} +484 -95
- package/dist/{compact-D_uvHurS.js → compact-LspQaGfl.js} +213 -199
- package/dist/{conversation-binding-data-BHRpYbX3.js → conversation-binding-data-CW2GuupV.js} +6 -10
- package/dist/doctor-contract-api.js +40 -43
- package/dist/{dynamic-tools-D2gYkSBO.js → dynamic-tools-BVdyWkUD.js} +2597 -1221
- package/dist/{effective-mcp-catalog-Bbd98Inw.js → effective-mcp-catalog-DIIhAtOZ.js} +20 -15
- package/dist/{event-projector-assistant-message-DTgnPPVF.js → event-projector-assistant-message-BwxV4d6N.js} +11 -23
- package/dist/{attempt-notifications-AP-a-Q5k.js → event-projector-usage-e5huIQWu.js} +113 -29
- package/dist/harness.js +80 -14
- package/dist/image-payload-sanitizer-CnfoUPCE.js +65 -0
- package/dist/index.js +591 -240
- package/dist/isolated-completion-C58NbL40.js +75 -0
- package/dist/local-runtime-attribution-B_2mnqhb.js +19 -0
- package/dist/media-understanding-provider.js +5 -5
- package/dist/{models-BBMKU4jA.js → models-BFlpn1Ex.js} +12 -17
- package/dist/native-subagent-monitor-DyTGmTUx.js +3111 -0
- package/dist/{plugin-app-cache-key-DztPafOA.js → plugin-app-cache-key-C3H2CVp6.js} +5 -5
- package/dist/plugin-marketplace-discovery-CzrGJdCR.js +385 -0
- package/dist/{computer-use-CYEc8U3w.js → plugin-metadata-cache-CNJPj4_b.js} +105 -5
- package/dist/protocol-validators-B4F7L8Rf.js +2346 -0
- package/dist/{rate-limits-CU-gVCCS.js → rate-limits-DZXmOL8-.js} +17 -35
- package/dist/{request-qKh331yu.js → request-BRl5_UfX.js} +3 -3
- package/dist/{run-attempt-CY9WlDLc.js → run-attempt-P8BdxC1I.js} +4837 -9047
- package/dist/{runtime-artifact-CmtG_t1L.js → runtime-artifact-BVSPdd6g.js} +8 -23
- package/dist/{sandbox-guard-NuhpXmPB.js → sandbox-guard-Cmwc9eIk.js} +6 -13
- package/dist/{session-binding-BXpo9ymA.js → session-binding-DPxIvMgE.js} +246 -265
- package/dist/{session-catalog-DyOgR4WH.js → session-catalog-xwNi_SDM.js} +159 -109
- package/dist/{session-cli-2PZaFLRh.js → session-cli-7hgXZDV7.js} +1 -1
- package/dist/session-retirement-DoMMJFKm.js +36 -0
- package/dist/{session-upstream-marker-B6U7tLw5.js → session-upstream-marker-CrIFX06J.js} +1 -1
- package/dist/{settled-turn-finalizer-CXY2Z9dT.js → settled-turn-finalizer-BRWBO4MO.js} +21 -13
- package/dist/{shared-client-DTbvH-XV.js → shared-client-kIBbGjk4.js} +587 -223
- package/dist/{side-question-_ulBk1AL.js → side-question-9HAL26l9.js} +101 -52
- package/dist/{thread-lifecycle-DF53ogiA.js → thread-lifecycle-Bu1BTDXr.js} +694 -753
- package/dist/thread-ownership-6kOQHlyC.js +92 -0
- package/dist/thread-resume-CPrJNQVM.js +30 -0
- package/dist/transcript-mirror-B9gGgnJS.js +570 -0
- package/dist/{transport-stdio-DXgGZ7Ib.js → transport-stdio-DIImwDVS.js} +11 -0
- package/dist/upstream-prompt-provenance-ClRBije0.js +41 -0
- package/dist/{upstream-session-fork-Dy4Xvuoj.js → upstream-session-fork-CE-_LdnP.js} +5 -5
- package/dist/{usage-CQ6GhD5-.js → usage-CHlV0e-o.js} +3 -3
- package/dist/{web-search-provider.runtime-CCFhg2z5.js → web-search-provider.runtime-DRw2Vl42.js} +8 -9
- package/openclaw.plugin.json +18 -3
- package/package.json +5 -5
- package/dist/conversation-control-xsIeXbo4.js +0 -287
- package/dist/event-projector-usage-Xp4AlR2k.js +0 -86
- package/dist/transcript-mirror-DzsdNCf5.js +0 -6924
|
@@ -1,21 +1,23 @@
|
|
|
1
1
|
import { t as __exportAll } from "./rolldown-runtime-8H4AJuhK.js";
|
|
2
|
-
import { _ as resolveCodexAppServerStartOptionsForAgent, g as resolveCodexAppServerRuntimeOptions, o as isCodexAppServerNativeAuthProfile, p as codexAppServerStartOptionsKey, v as resolveCodexComputerUseConfig
|
|
3
|
-
import { n as resolveCodexAppServerSpawnEnv, t as createStdioTransport } from "./transport-stdio-
|
|
2
|
+
import { A as resolveCodexAppServerUserHomeDir, _ as resolveCodexAppServerStartOptionsForAgent, g as resolveCodexAppServerRuntimeOptions, o as isCodexAppServerNativeAuthProfile, p as codexAppServerStartOptionsKey, v as resolveCodexComputerUseConfig } from "./session-binding-DPxIvMgE.js";
|
|
3
|
+
import { n as resolveCodexAppServerSpawnEnv, t as createStdioTransport } from "./transport-stdio-DIImwDVS.js";
|
|
4
4
|
import { createRequire } from "node:module";
|
|
5
|
+
import { isRecord, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
5
6
|
import fs, { access } from "node:fs/promises";
|
|
6
7
|
import path from "node:path";
|
|
8
|
+
import { createDeferred } from "openclaw/plugin-sdk/extension-shared";
|
|
7
9
|
import { addTimerTimeoutGraceMs, resolveTimerTimeoutMs } from "openclaw/plugin-sdk/number-runtime";
|
|
8
|
-
import { AgentHarnessPreflightError, OPENCLAW_VERSION, embeddedAgentLog } from "openclaw/plugin-sdk/agent-harness-runtime";
|
|
10
|
+
import { AgentHarnessPreflightError, OPENCLAW_VERSION, embeddedAgentLog, formatErrorMessage } from "openclaw/plugin-sdk/agent-harness-runtime";
|
|
9
11
|
import { createHash, randomUUID } from "node:crypto";
|
|
10
|
-
import { ensureAuthProfileStore, findPersistedAuthProfileCredential, loadAuthProfileStoreForSecretsRuntime, refreshOAuthCredentialForRuntime, resolveApiKeyForProfile, resolveAuthProfileOrder, resolveDefaultAgentDir, resolvePersistedAuthProfileOwnerAgentDir, resolveProviderIdForAuth } from "openclaw/plugin-sdk/agent-runtime";
|
|
11
|
-
import { createDeferred } from "openclaw/plugin-sdk/extension-shared";
|
|
12
12
|
import fsSync, { constants, existsSync, readFileSync, realpathSync } from "node:fs";
|
|
13
13
|
import os from "node:os";
|
|
14
14
|
import { isDeepStrictEqual } from "node:util";
|
|
15
|
+
import { ensureAuthProfileStore, findPersistedAuthProfileCredential, loadAuthProfileStoreForSecretsRuntime, refreshOAuthCredentialForRuntime, resolveApiKeyForProfile, resolveAuthProfileOrder, resolveDefaultAgentDir, resolvePersistedAuthProfileOwnerAgentDir, resolveProviderIdForAuth } from "openclaw/plugin-sdk/agent-runtime";
|
|
15
16
|
import { hasUsableOAuthCredential } from "openclaw/plugin-sdk/provider-auth";
|
|
16
17
|
import { readSecretFile } from "openclaw/plugin-sdk/secret-file";
|
|
17
18
|
import { runExec } from "openclaw/plugin-sdk/process-runtime";
|
|
18
19
|
import { createInterface } from "node:readline";
|
|
20
|
+
import { coerceErrorMessage, toStringifiedError } from "openclaw/plugin-sdk/error-runtime";
|
|
19
21
|
import { sliceUtf16Safe, truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
|
|
20
22
|
import { EventEmitter } from "node:events";
|
|
21
23
|
import net from "node:net";
|
|
@@ -25,109 +27,18 @@ import WebSocket from "ws";
|
|
|
25
27
|
import { fileURLToPath } from "node:url";
|
|
26
28
|
import { expectDefined } from "openclaw/plugin-sdk/expect-runtime";
|
|
27
29
|
import { withTimeout } from "openclaw/plugin-sdk/security-runtime";
|
|
28
|
-
//#region extensions/codex/src/app-server/attempt-timeouts.ts
|
|
29
|
-
/**
|
|
30
|
-
* Timeout defaults and normalizers for Codex app-server startup and turn
|
|
31
|
-
* liveness watches.
|
|
32
|
-
*/
|
|
33
|
-
/** Minimum startup timeout accepted by the Codex app-server harness. */
|
|
34
|
-
const CODEX_APP_SERVER_STARTUP_TIMEOUT_FLOOR_MS = 100;
|
|
35
|
-
/** Default idle timeout while waiting for app-server turn completion. */
|
|
36
|
-
const CODEX_TURN_COMPLETION_IDLE_TIMEOUT_MS = 6e4;
|
|
37
|
-
/** Short guard after apparent assistant completion. */
|
|
38
|
-
const CODEX_TURN_ASSISTANT_COMPLETION_IDLE_TIMEOUT_MS = 1e4;
|
|
39
|
-
const CODEX_POST_TOOL_RAW_ASSISTANT_COMPLETION_IDLE_TIMEOUT_MS = 5 * 6e4;
|
|
40
|
-
/** Guard after reasoning/commentary progress when no tool handoff occurred. */
|
|
41
|
-
const CODEX_POST_REASONING_REPLY_IDLE_TIMEOUT_MS = 5 * 6e4;
|
|
42
|
-
/** Long terminal idle watch for app-server turns that never send completion. */
|
|
43
|
-
const CODEX_TURN_TERMINAL_IDLE_TIMEOUT_MS = 30 * 6e4;
|
|
44
|
-
var CodexAppServerStartupError = class extends Error {
|
|
45
|
-
constructor(reason, message = reason === "timed_out" ? "codex app-server startup timed out" : "codex app-server startup aborted") {
|
|
46
|
-
super(message);
|
|
47
|
-
this.reason = reason;
|
|
48
|
-
this.code = "CODEX_APP_SERVER_STARTUP_CANCELLED";
|
|
49
|
-
this.name = "CodexAppServerStartupError";
|
|
50
|
-
}
|
|
51
|
-
};
|
|
52
|
-
function isCodexAppServerStartupError(error, reason) {
|
|
53
|
-
return error instanceof Error && "code" in error && error.code === "CODEX_APP_SERVER_STARTUP_CANCELLED" && "reason" in error && (error.reason === "aborted" || error.reason === "timed_out") && (reason === void 0 || error.reason === reason);
|
|
54
|
-
}
|
|
55
|
-
function resolvePositiveIntegerTimeoutMs(value, fallbackMs) {
|
|
56
|
-
return resolveTimerTimeoutMs(value, resolveTimerTimeoutMs(fallbackMs, 1));
|
|
57
|
-
}
|
|
58
|
-
/** Runs startup work with abort and timeout handling plus optional cleanup. */
|
|
59
|
-
async function withCodexStartupTimeout(params) {
|
|
60
|
-
if (params.signal.aborted) throw new CodexAppServerStartupError("aborted");
|
|
61
|
-
let timeout;
|
|
62
|
-
let abortCleanup;
|
|
63
|
-
let timeoutError;
|
|
64
|
-
let timeoutCleanup;
|
|
65
|
-
try {
|
|
66
|
-
return await Promise.race([params.operation(), new Promise((_, reject) => {
|
|
67
|
-
const rejectOnce = (error) => {
|
|
68
|
-
if (timeout) {
|
|
69
|
-
clearTimeout(timeout);
|
|
70
|
-
timeout = void 0;
|
|
71
|
-
}
|
|
72
|
-
reject(error);
|
|
73
|
-
};
|
|
74
|
-
timeout = setTimeout(() => {
|
|
75
|
-
timeoutError = new CodexAppServerStartupError("timed_out");
|
|
76
|
-
timeoutCleanup = Promise.resolve(params.onTimeout?.()).then(() => void 0, () => void 0);
|
|
77
|
-
timeoutCleanup.finally(() => {
|
|
78
|
-
rejectOnce(timeoutError);
|
|
79
|
-
});
|
|
80
|
-
}, params.timeoutMs);
|
|
81
|
-
const abortListener = () => rejectOnce(new CodexAppServerStartupError("aborted"));
|
|
82
|
-
params.signal.addEventListener("abort", abortListener, { once: true });
|
|
83
|
-
abortCleanup = () => params.signal.removeEventListener("abort", abortListener);
|
|
84
|
-
})]);
|
|
85
|
-
} catch (error) {
|
|
86
|
-
if (timeoutError) {
|
|
87
|
-
await timeoutCleanup;
|
|
88
|
-
throw timeoutError;
|
|
89
|
-
}
|
|
90
|
-
throw error;
|
|
91
|
-
} finally {
|
|
92
|
-
if (timeout) clearTimeout(timeout);
|
|
93
|
-
abortCleanup?.();
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
/** Resolves startup timeout while honoring the configured floor. */
|
|
97
|
-
function resolveCodexStartupTimeoutMs(params) {
|
|
98
|
-
const timeoutFloorMs = resolvePositiveIntegerTimeoutMs(params.timeoutFloorMs, CODEX_APP_SERVER_STARTUP_TIMEOUT_FLOOR_MS);
|
|
99
|
-
const timeoutMs = resolvePositiveIntegerTimeoutMs(params.timeoutMs, timeoutFloorMs);
|
|
100
|
-
return Math.max(timeoutFloorMs, timeoutMs);
|
|
101
|
-
}
|
|
102
|
-
/** Resolves the completion-idle timeout for an active turn. */
|
|
103
|
-
function resolveCodexTurnCompletionIdleTimeoutMs(value) {
|
|
104
|
-
return resolvePositiveIntegerTimeoutMs(value, CODEX_TURN_COMPLETION_IDLE_TIMEOUT_MS);
|
|
105
|
-
}
|
|
106
|
-
/** Resolves the short assistant-completion release timeout. */
|
|
107
|
-
function resolveCodexTurnAssistantCompletionIdleTimeoutMs(value) {
|
|
108
|
-
return resolvePositiveIntegerTimeoutMs(value, CODEX_TURN_ASSISTANT_COMPLETION_IDLE_TIMEOUT_MS);
|
|
109
|
-
}
|
|
110
|
-
/** Resolves the conservative post-tool raw assistant guard timeout. */
|
|
111
|
-
function resolveCodexPostToolRawAssistantCompletionIdleTimeoutMs(value, fallbackMs) {
|
|
112
|
-
return resolvePositiveIntegerTimeoutMs(value, Math.max(resolvePositiveIntegerTimeoutMs(void 0, fallbackMs), CODEX_POST_TOOL_RAW_ASSISTANT_COMPLETION_IDLE_TIMEOUT_MS));
|
|
113
|
-
}
|
|
114
|
-
/** Resolves the long terminal turn idle timeout. */
|
|
115
|
-
function resolveCodexTurnTerminalIdleTimeoutMs(value, runTimeoutOverrideMs) {
|
|
116
|
-
const explicitRunBudgetMs = resolvePositiveIntegerTimeoutMs(runTimeoutOverrideMs, CODEX_TURN_TERMINAL_IDLE_TIMEOUT_MS);
|
|
117
|
-
return resolvePositiveIntegerTimeoutMs(value, Math.max(CODEX_TURN_TERMINAL_IDLE_TIMEOUT_MS, explicitRunBudgetMs));
|
|
118
|
-
}
|
|
119
|
-
/** Adds gateway grace time to a caller timeout without overflowing invalid values. */
|
|
120
|
-
function resolveCodexGatewayTimeoutWithGraceMs(timeoutMs, graceMs = 1e4) {
|
|
121
|
-
const timeout = resolvePositiveIntegerTimeoutMs(timeoutMs, 1);
|
|
122
|
-
return addTimerTimeoutGraceMs(timeout, resolveTimerTimeoutMs(graceMs, 0, 0)) ?? timeout;
|
|
123
|
-
}
|
|
124
|
-
//#endregion
|
|
125
30
|
//#region extensions/codex/src/app-server/auth-start-options.ts
|
|
126
31
|
const CODEX_APP_SERVER_HOME_DIRNAME = "codex-home";
|
|
127
32
|
const CODEX_EPHEMERAL_AUTH_STORE_OVERRIDE = "cli_auth_credentials_store=\"ephemeral\"";
|
|
128
33
|
function resolveCodexAppServerHomeDir(agentDir) {
|
|
129
34
|
return path.join(path.resolve(agentDir), CODEX_APP_SERVER_HOME_DIRNAME);
|
|
130
35
|
}
|
|
36
|
+
/** Resolves the local CODEX_HOME used when starting one app-server connection. */
|
|
37
|
+
function resolveCodexAppServerLocalHomeDir(startOptions, agentDir, env = process.env) {
|
|
38
|
+
const configured = startOptions.env?.CODEX_HOME;
|
|
39
|
+
if (configured?.trim()) return configured;
|
|
40
|
+
return startOptions.homeScope === "user" ? resolveCodexAppServerUserHomeDir(env) : resolveCodexAppServerHomeDir(agentDir);
|
|
41
|
+
}
|
|
131
42
|
/** Forces OpenClaw-owned Codex auth to remain process-local. */
|
|
132
43
|
function withEphemeralCodexAuthStore(params) {
|
|
133
44
|
const { startOptions } = params;
|
|
@@ -408,8 +319,8 @@ function flattenCodexDynamicToolFunctions(tools) {
|
|
|
408
319
|
}
|
|
409
320
|
const CODEX_INTERACTIVE_THREAD_SOURCE_KINDS = ["cli", "vscode"];
|
|
410
321
|
const CODEX_INTERACTIVE_CUSTOM_THREAD_SOURCES = ["atlas", "chatgpt"];
|
|
411
|
-
function isJsonObject
|
|
412
|
-
return
|
|
322
|
+
function isJsonObject(value) {
|
|
323
|
+
return isRecord(value);
|
|
413
324
|
}
|
|
414
325
|
function isRpcResponse(message) {
|
|
415
326
|
return "id" in message && !("method" in message);
|
|
@@ -436,24 +347,41 @@ const CODEX_HOME_DIRNAME = ".codex";
|
|
|
436
347
|
const scopedOAuthRefreshQueues = /* @__PURE__ */ new WeakMap();
|
|
437
348
|
async function bridgeCodexAppServerStartOptions(params) {
|
|
438
349
|
if (params.startOptions.transport !== "stdio") return params.startOptions;
|
|
439
|
-
const
|
|
440
|
-
if (params.preparedAuth) return withClearedEnvironmentVariables(
|
|
441
|
-
if (params.authProfileId === null) return
|
|
350
|
+
const scopeStartOptions = () => withCodexHomeEnvironment(withEphemeralCodexAuthStore(params), params.agentDir, params.pluginConfig);
|
|
351
|
+
if (params.preparedAuth) return withClearedEnvironmentVariables(await scopeStartOptions(), CODEX_APP_SERVER_PREPARED_AUTH_ENV_VARS);
|
|
352
|
+
if (params.authProfileId === null) return scopeStartOptions();
|
|
442
353
|
const store = resolveCodexAppServerAuthProfileStore({
|
|
443
354
|
agentDir: params.agentDir,
|
|
444
355
|
authProfileId: params.authProfileId,
|
|
445
356
|
authProfileStore: params.authProfileStore,
|
|
446
357
|
config: params.config
|
|
447
358
|
});
|
|
359
|
+
const authProfileId = resolveCodexAppServerAuthProfileId({
|
|
360
|
+
authProfileId: params.authProfileId,
|
|
361
|
+
store,
|
|
362
|
+
config: params.config
|
|
363
|
+
});
|
|
364
|
+
if (!authProfileId) assertNoUnimportedAgentCodexAuthFile(params);
|
|
365
|
+
const scopedStartOptions = await scopeStartOptions();
|
|
448
366
|
return shouldClearOpenAiApiKeyForCodexAuthProfile({
|
|
449
367
|
store,
|
|
450
|
-
authProfileId
|
|
451
|
-
authProfileId: params.authProfileId,
|
|
452
|
-
store,
|
|
453
|
-
config: params.config
|
|
454
|
-
})
|
|
368
|
+
authProfileId
|
|
455
369
|
}) ? withClearedEnvironmentVariables(scopedStartOptions, CODEX_APP_SERVER_API_KEY_ENV_VARS) : scopedStartOptions;
|
|
456
370
|
}
|
|
371
|
+
function assertNoUnimportedAgentCodexAuthFile(params) {
|
|
372
|
+
if (params.authRequirement === "api-key" && resolveCodexAppServerFallbackApiKeyCacheKey({ startOptions: params.startOptions })) return;
|
|
373
|
+
const message = resolveUnimportedAgentCodexAuthMessage(params);
|
|
374
|
+
if (message) throw new AgentHarnessPreflightError(message);
|
|
375
|
+
}
|
|
376
|
+
function resolveUnimportedAgentCodexAuthMessage(params) {
|
|
377
|
+
const managedCodexCli = params.startOptions.commandSource === "managed" || params.startOptions.commandSource === "resolved-managed";
|
|
378
|
+
if (params.startOptions.transport !== "stdio" || !managedCodexCli || params.startOptions.homeScope === "user") return;
|
|
379
|
+
const codexHome = resolveCodexAppServerHomeDir(params.agentDir);
|
|
380
|
+
const authPath = path.join(codexHome, CODEX_AUTH_JSON_FILENAME);
|
|
381
|
+
if (!fsSync.existsSync(authPath)) return;
|
|
382
|
+
const targetAgentId = params.agentId?.trim() || "<agent-id>";
|
|
383
|
+
return `A Codex auth file exists at ${authPath}, but agent-scoped Codex runs use OpenClaw's auth store and do not read that file. Preview only that credential import with \`openclaw migrate plan codex --from <codex-home> --agent ${targetAgentId} --include-secrets --item auth:openai\`, then run \`openclaw migrate apply codex --from <codex-home> --agent ${targetAgentId} --include-secrets --item auth:openai --yes\`. If the plan finds no credentials, remove the stale auth file.`;
|
|
384
|
+
}
|
|
457
385
|
function resolveCodexAppServerAuthProfileId(params) {
|
|
458
386
|
const requested = params.authProfileId?.trim();
|
|
459
387
|
if (requested) return requested;
|
|
@@ -518,14 +446,18 @@ async function resolveCodexAppServerPreparedAuthProfileSnapshot(params) {
|
|
|
518
446
|
if (!loginParams) return;
|
|
519
447
|
const accountId = loginParams.type === "chatgptAuthTokens" ? loginParams.chatgptAccountId : resolveChatgptAccountId(profileId, credential);
|
|
520
448
|
const stableChatgptAccountId = resolveStableChatgptAccountId(credential);
|
|
449
|
+
const secretFreeCacheKey = credential.type === "api_key" && loginParams.type === "apiKey" ? `${accountId}:${fingerprintApiKeyAuthProfileCacheKey(loginParams.apiKey)}` : loginParams.type === "chatgptAuthTokens" && (credential.type === "token" || !stableChatgptAccountId) ? `${accountId}:${fingerprintTokenAuthProfileCacheKey(loginParams.accessToken)}` : accountId;
|
|
450
|
+
const chatgptAccountId = resolveExplicitChatgptAccountId(credential);
|
|
521
451
|
return {
|
|
522
452
|
loginParams,
|
|
523
|
-
secretFreeCacheKey
|
|
453
|
+
secretFreeCacheKey,
|
|
454
|
+
...chatgptAccountId ? { chatgptAccountId } : {}
|
|
524
455
|
};
|
|
525
456
|
}
|
|
526
457
|
/** Maps one prepared route to one mutually exclusive app-server auth handoff. */
|
|
527
458
|
async function resolveCodexAppServerPreparedAuthHandoff(params) {
|
|
528
459
|
const usesNativeHome = params.homeScope === "user";
|
|
460
|
+
if (params.requirePreparedAuth && usesNativeHome) throw createCodexAppServerAuthError("Codex remote-exec cloud placement requires prepared OpenAI auth. Configure an OpenAI API-key, OAuth, or token profile and use appServer.homeScope=\"agent\"; ambient credentials and native Codex auth are not allowed.");
|
|
529
461
|
if (params.authRequirement === "api-key" && !usesNativeHome) {
|
|
530
462
|
const apiKey = params.resolvedApiKey?.trim();
|
|
531
463
|
if (!apiKey) throw new Error("Prepared Codex API-key route is missing its resolved API key.");
|
|
@@ -544,18 +476,18 @@ async function resolveCodexAppServerPreparedAuthHandoff(params) {
|
|
|
544
476
|
agentDir: params.agentDir,
|
|
545
477
|
config: params.config
|
|
546
478
|
});
|
|
547
|
-
if (usesNativeHome || params.authRequirement !== "subscription") return {
|
|
479
|
+
if (usesNativeHome || params.authRequirement !== "subscription" && !params.requirePreparedAuth) return {
|
|
548
480
|
authProfileId,
|
|
549
481
|
nativeAuthProfile
|
|
550
482
|
};
|
|
551
|
-
if (!authProfileId || !nativeAuthProfile) throw createCodexAppServerAuthError(params.subscriptionProfileRequiredError);
|
|
483
|
+
if (!authProfileId || params.authRequirement === "subscription" && !nativeAuthProfile) throw createCodexAppServerAuthError(params.requirePreparedAuth ? "Codex remote-exec cloud placement requires prepared OpenAI auth. Configure an OpenAI API-key, OAuth, or token profile; ambient CODEX_API_KEY, OPENAI_API_KEY, and native Codex auth are not allowed." : params.subscriptionProfileRequiredError);
|
|
552
484
|
const snapshot = await resolveCodexAppServerPreparedAuthProfileSnapshot({
|
|
553
485
|
authProfileId,
|
|
554
486
|
authProfileStore: params.authProfileStore,
|
|
555
487
|
agentDir: params.agentDir,
|
|
556
488
|
config: params.config
|
|
557
489
|
});
|
|
558
|
-
if (!snapshot) throw createCodexAppServerAuthError(params.subscriptionProfileUnusableError);
|
|
490
|
+
if (!snapshot) throw createCodexAppServerAuthError(params.requirePreparedAuth ? "Codex remote-exec cloud placement could not prepare the selected OpenAI auth profile. Repair or replace the profile, then retry." : params.subscriptionProfileUnusableError);
|
|
559
491
|
return {
|
|
560
492
|
authProfileId,
|
|
561
493
|
nativeAuthProfile,
|
|
@@ -644,7 +576,7 @@ function fingerprintCodexCliAuthFileApiKeyCacheKey(apiKey) {
|
|
|
644
576
|
return `CODEX_AUTH_JSON:sha256:${hash.digest("hex")}`;
|
|
645
577
|
}
|
|
646
578
|
async function withCodexHomeEnvironment(startOptions, agentDir, pluginConfig) {
|
|
647
|
-
const codexHome =
|
|
579
|
+
const codexHome = resolveCodexAppServerLocalHomeDir(startOptions, agentDir);
|
|
648
580
|
const nativeHome = startOptions.env?.[HOME_ENV_VAR]?.trim() ? startOptions.env[HOME_ENV_VAR] : void 0;
|
|
649
581
|
await fs.mkdir(codexHome, { recursive: true });
|
|
650
582
|
const computerUseConfig = resolveCodexComputerUseConfig({ pluginConfig });
|
|
@@ -658,7 +590,10 @@ async function withCodexHomeEnvironment(startOptions, agentDir, pluginConfig) {
|
|
|
658
590
|
appServerCommand: startOptions.command
|
|
659
591
|
});
|
|
660
592
|
} catch (error) {
|
|
661
|
-
throw new AgentHarnessPreflightError("Codex Computer Use client provisioning failed.", {
|
|
593
|
+
throw new AgentHarnessPreflightError("Codex Computer Use client provisioning failed.", {
|
|
594
|
+
cause: error,
|
|
595
|
+
scope: "harness"
|
|
596
|
+
});
|
|
662
597
|
}
|
|
663
598
|
if (nativeHome) await fs.mkdir(nativeHome, { recursive: true });
|
|
664
599
|
const nextStartOptions = {
|
|
@@ -733,7 +668,7 @@ async function applyCodexAppServerAuthProfile(params) {
|
|
|
733
668
|
async function assertNativeCodexAccountMatchesRoute(client, authRequirement) {
|
|
734
669
|
if (!authRequirement) return;
|
|
735
670
|
const response = await client.request("account/read", { refreshToken: false });
|
|
736
|
-
const accountType = isJsonObject
|
|
671
|
+
const accountType = isJsonObject(response.account) ? response.account.type : void 0;
|
|
737
672
|
if (authRequirement === "subscription") {
|
|
738
673
|
if (accountType !== "chatgpt") throw createCodexAppServerAuthError("Codex subscription auth profile could not produce login credentials.");
|
|
739
674
|
return;
|
|
@@ -1019,11 +954,13 @@ function resolveChatgptAccountId(profileId, credential) {
|
|
|
1019
954
|
return resolveStableChatgptAccountId(credential) ?? profileId;
|
|
1020
955
|
}
|
|
1021
956
|
function resolveStableChatgptAccountId(credential) {
|
|
957
|
+
return resolveExplicitChatgptAccountId(credential) ?? (credential.email?.trim() || void 0);
|
|
958
|
+
}
|
|
959
|
+
function resolveExplicitChatgptAccountId(credential) {
|
|
1022
960
|
if ("accountId" in credential && typeof credential.accountId === "string") {
|
|
1023
961
|
const accountId = credential.accountId.trim();
|
|
1024
962
|
if (accountId) return accountId;
|
|
1025
963
|
}
|
|
1026
|
-
return credential.email?.trim() || void 0;
|
|
1027
964
|
}
|
|
1028
965
|
//#endregion
|
|
1029
966
|
//#region extensions/codex/src/app-server/rate-limit-cache.ts
|
|
@@ -1048,7 +985,7 @@ function rememberCodexRateLimitsRead(client, value, nowMs = Date.now()) {
|
|
|
1048
985
|
}
|
|
1049
986
|
/** Merges a sparse rolling notification into one physical client's latest read response. */
|
|
1050
987
|
function mergeCodexRateLimitsUpdate(client, value, nowMs = Date.now()) {
|
|
1051
|
-
const update = isJsonObject
|
|
988
|
+
const update = isJsonObject(value) && isJsonObject(value.rateLimits) ? value.rateLimits : void 0;
|
|
1052
989
|
if (!update) return;
|
|
1053
990
|
const currentState = rateLimitsByClient.get(client);
|
|
1054
991
|
const current = currentState?.value;
|
|
@@ -1075,13 +1012,13 @@ function readRecentCodexRateLimits(client, options) {
|
|
|
1075
1012
|
return maxAgeMs >= 0 && nowMs - state.updatedAtMs > maxAgeMs ? void 0 : state.value;
|
|
1076
1013
|
}
|
|
1077
1014
|
function mergeRateLimitUpdate(current, update) {
|
|
1078
|
-
const currentEnvelope = isJsonObject
|
|
1079
|
-
const currentPrimary = currentEnvelope && isJsonObject
|
|
1080
|
-
const currentByLimitId = currentEnvelope && isJsonObject
|
|
1015
|
+
const currentEnvelope = isJsonObject(current) ? current : void 0;
|
|
1016
|
+
const currentPrimary = currentEnvelope && isJsonObject(currentEnvelope.rateLimits) ? currentEnvelope.rateLimits : void 0;
|
|
1017
|
+
const currentByLimitId = currentEnvelope && isJsonObject(currentEnvelope.rateLimitsByLimitId) ? currentEnvelope.rateLimitsByLimitId : void 0;
|
|
1081
1018
|
const limitId = readLimitId(update);
|
|
1082
1019
|
const currentPrimaryLimitId = currentPrimary ? readLimitId(currentPrimary) : void 0;
|
|
1083
|
-
const currentForLimit = (currentByLimitId && isJsonObject
|
|
1084
|
-
const merged = mergeSparseSnapshot(isJsonObject
|
|
1020
|
+
const currentForLimit = (currentByLimitId && isJsonObject(currentByLimitId[limitId]) ? currentByLimitId[limitId] : void 0) ?? (currentPrimaryLimitId === limitId ? currentPrimary : void 0);
|
|
1021
|
+
const merged = mergeSparseSnapshot(isJsonObject(currentForLimit) ? currentForLimit : void 0, currentPrimary, update, limitId);
|
|
1085
1022
|
const nextPrimary = !currentPrimary || currentPrimaryLimitId === limitId ? merged : currentPrimary;
|
|
1086
1023
|
let nextByLimitId;
|
|
1087
1024
|
if (currentByLimitId) nextByLimitId = {
|
|
@@ -1099,11 +1036,11 @@ function mergeRateLimitUpdate(current, update) {
|
|
|
1099
1036
|
};
|
|
1100
1037
|
}
|
|
1101
1038
|
function readRateLimitIds(value) {
|
|
1102
|
-
if (!isJsonObject
|
|
1039
|
+
if (!isJsonObject(value)) return [];
|
|
1103
1040
|
const ids = /* @__PURE__ */ new Set();
|
|
1104
|
-
if (isJsonObject
|
|
1105
|
-
if (isJsonObject
|
|
1106
|
-
const snapshotLimitId = isJsonObject
|
|
1041
|
+
if (isJsonObject(value.rateLimits)) ids.add(readLimitId(value.rateLimits));
|
|
1042
|
+
if (isJsonObject(value.rateLimitsByLimitId)) for (const [key, snapshot] of Object.entries(value.rateLimitsByLimitId)) {
|
|
1043
|
+
const snapshotLimitId = isJsonObject(snapshot) && typeof snapshot.limitId === "string" ? snapshot.limitId.trim() : "";
|
|
1107
1044
|
ids.add(snapshotLimitId || key);
|
|
1108
1045
|
}
|
|
1109
1046
|
return [...ids];
|
|
@@ -1126,16 +1063,45 @@ function readLimitId(snapshot) {
|
|
|
1126
1063
|
//#endregion
|
|
1127
1064
|
//#region extensions/codex/src/app-server/client-runtime.ts
|
|
1128
1065
|
/** Client-scoped Codex auth and account observers. */
|
|
1066
|
+
/** Match Codex's native grace window without retaining inactive conversations indefinitely. */
|
|
1067
|
+
const CODEX_APP_SERVER_LIVE_THREAD_IDLE_TIMEOUT_MS = 30 * 6e4;
|
|
1068
|
+
/** Native-child parents are active ownership, so only otherwise-idle threads count against this cap. */
|
|
1069
|
+
const CODEX_APP_SERVER_LIVE_THREAD_MAX_IDLE = 64;
|
|
1129
1070
|
const configuredClients = /* @__PURE__ */ new WeakMap();
|
|
1071
|
+
const physicalThreadReleases = /* @__PURE__ */ new WeakMap();
|
|
1072
|
+
const claimedThreadReleaseTokens = /* @__PURE__ */ new WeakMap();
|
|
1073
|
+
/** Only an initialized, still-open physical client can own retained native subscriptions. */
|
|
1074
|
+
function isCodexAppServerClientRuntimeLive(client) {
|
|
1075
|
+
const runtime = configuredClients.get(client);
|
|
1076
|
+
return runtime !== void 0 && !runtime.closed;
|
|
1077
|
+
}
|
|
1130
1078
|
/** Installs one auth-refresh handler and one rate-limit observer per physical client. */
|
|
1131
1079
|
function ensureCodexAppServerClientRuntime(client, context) {
|
|
1132
1080
|
const existing = configuredClients.get(client);
|
|
1133
1081
|
if (existing) {
|
|
1082
|
+
if (existing.closed) return;
|
|
1134
1083
|
existing.context = context;
|
|
1135
1084
|
return;
|
|
1136
1085
|
}
|
|
1137
|
-
const runtime = {
|
|
1086
|
+
const runtime = {
|
|
1087
|
+
context,
|
|
1088
|
+
closed: false,
|
|
1089
|
+
retainedThreads: /* @__PURE__ */ new Map(),
|
|
1090
|
+
claimedThreads: /* @__PURE__ */ new Map(),
|
|
1091
|
+
releasingThreads: /* @__PURE__ */ new Map(),
|
|
1092
|
+
protectedThreads: /* @__PURE__ */ new Map()
|
|
1093
|
+
};
|
|
1138
1094
|
configuredClients.set(client, runtime);
|
|
1095
|
+
client.addCloseHandler(() => {
|
|
1096
|
+
runtime.closed = true;
|
|
1097
|
+
if (runtime.evictionTimer) {
|
|
1098
|
+
clearTimeout(runtime.evictionTimer);
|
|
1099
|
+
runtime.evictionTimer = void 0;
|
|
1100
|
+
}
|
|
1101
|
+
runtime.retainedThreads.clear();
|
|
1102
|
+
runtime.claimedThreads.clear();
|
|
1103
|
+
runtime.protectedThreads.clear();
|
|
1104
|
+
});
|
|
1139
1105
|
client.addRequestHandler(async (request) => {
|
|
1140
1106
|
if (request.method !== "account/chatgptAuthTokens/refresh") return;
|
|
1141
1107
|
if (runtime.context.authMode === "prepared-api-key") throw new Error("ChatGPT token refresh is unavailable for prepared Codex API-key auth.");
|
|
@@ -1147,41 +1113,278 @@ function ensureCodexAppServerClientRuntime(client, context) {
|
|
|
1147
1113
|
});
|
|
1148
1114
|
});
|
|
1149
1115
|
client.addNotificationHandler((notification) => {
|
|
1150
|
-
if (notification.method === "account/rateLimits/updated")
|
|
1116
|
+
if (notification.method === "account/rateLimits/updated") {
|
|
1117
|
+
mergeCodexRateLimitsUpdate(client, notification.params);
|
|
1118
|
+
return;
|
|
1119
|
+
}
|
|
1120
|
+
if (notification.method === "thread/archived" || notification.method === "thread/deleted" || notification.method === "thread/closed") {
|
|
1121
|
+
const threadId = notification.params?.threadId;
|
|
1122
|
+
if (typeof threadId === "string") {
|
|
1123
|
+
const releasing = runtime.releasingThreads.get(threadId);
|
|
1124
|
+
if (releasing) releasing.invalidated = true;
|
|
1125
|
+
runtime.retainedThreads.delete(threadId);
|
|
1126
|
+
runtime.claimedThreads.delete(threadId);
|
|
1127
|
+
scheduleRetainedThreadEviction(client, runtime);
|
|
1128
|
+
}
|
|
1129
|
+
}
|
|
1151
1130
|
});
|
|
1152
1131
|
}
|
|
1153
|
-
|
|
1154
|
-
|
|
1132
|
+
function scheduleRetainedThreadEviction(client, runtime) {
|
|
1133
|
+
if (runtime.evictionTimer) {
|
|
1134
|
+
clearTimeout(runtime.evictionTimer);
|
|
1135
|
+
runtime.evictionTimer = void 0;
|
|
1136
|
+
}
|
|
1137
|
+
if (runtime.closed) return;
|
|
1138
|
+
let expiresAt = Number.POSITIVE_INFINITY;
|
|
1139
|
+
for (const [threadId, thread] of runtime.retainedThreads) if (!runtime.protectedThreads.has(threadId)) expiresAt = Math.min(expiresAt, thread.expiresAt);
|
|
1140
|
+
if (!Number.isFinite(expiresAt)) return;
|
|
1141
|
+
runtime.evictionTimer = setTimeout(() => {
|
|
1142
|
+
runtime.evictionTimer = void 0;
|
|
1143
|
+
evictExpiredRetainedThreads(client, runtime).catch((error) => {
|
|
1144
|
+
embeddedAgentLog.warn("codex retained thread expiry failed", { reason: formatErrorMessage(error) });
|
|
1145
|
+
});
|
|
1146
|
+
}, Math.max(0, expiresAt - Date.now()));
|
|
1147
|
+
runtime.evictionTimer.unref?.();
|
|
1148
|
+
}
|
|
1149
|
+
async function releaseRetainedThread(client, runtime, threadId) {
|
|
1150
|
+
const pendingRelease = runtime.releasingThreads.get(threadId);
|
|
1151
|
+
if (pendingRelease) {
|
|
1152
|
+
await pendingRelease.completion;
|
|
1153
|
+
return false;
|
|
1154
|
+
}
|
|
1155
|
+
const retained = runtime.retainedThreads.get(threadId);
|
|
1156
|
+
if (!retained) return false;
|
|
1157
|
+
const olderThreadIds = /* @__PURE__ */ new Set();
|
|
1158
|
+
for (const candidateThreadId of runtime.retainedThreads.keys()) {
|
|
1159
|
+
if (candidateThreadId === threadId) break;
|
|
1160
|
+
olderThreadIds.add(candidateThreadId);
|
|
1161
|
+
}
|
|
1162
|
+
runtime.retainedThreads.delete(threadId);
|
|
1163
|
+
scheduleRetainedThreadEviction(client, runtime);
|
|
1164
|
+
const transition = { completion: Promise.resolve().then(() => retained.release(threadId)) };
|
|
1165
|
+
runtime.releasingThreads.set(threadId, transition);
|
|
1166
|
+
try {
|
|
1167
|
+
await transition.completion;
|
|
1168
|
+
return true;
|
|
1169
|
+
} catch (error) {
|
|
1170
|
+
if (!runtime.closed && !transition.invalidated && runtime.releasingThreads.get(threadId) === transition && !runtime.retainedThreads.has(threadId) && !runtime.claimedThreads.has(threadId)) {
|
|
1171
|
+
retained.expiresAt = Date.now() + CODEX_APP_SERVER_LIVE_THREAD_IDLE_TIMEOUT_MS;
|
|
1172
|
+
const newerThreads = [...runtime.retainedThreads.entries()].filter(([candidateThreadId]) => !olderThreadIds.has(candidateThreadId));
|
|
1173
|
+
for (const [candidateThreadId] of newerThreads) runtime.retainedThreads.delete(candidateThreadId);
|
|
1174
|
+
runtime.retainedThreads.set(threadId, retained);
|
|
1175
|
+
for (const [candidateThreadId, newerThread] of newerThreads) runtime.retainedThreads.set(candidateThreadId, newerThread);
|
|
1176
|
+
}
|
|
1177
|
+
throw error;
|
|
1178
|
+
} finally {
|
|
1179
|
+
if (runtime.releasingThreads.get(threadId) === transition) runtime.releasingThreads.delete(threadId);
|
|
1180
|
+
scheduleRetainedThreadEviction(client, runtime);
|
|
1181
|
+
}
|
|
1182
|
+
}
|
|
1183
|
+
async function evictExpiredRetainedThreads(client, runtime) {
|
|
1184
|
+
const now = Date.now();
|
|
1185
|
+
for (const [threadId, thread] of runtime.retainedThreads) if (thread.expiresAt <= now && !runtime.protectedThreads.has(threadId)) await releaseRetainedThread(client, runtime, threadId);
|
|
1186
|
+
scheduleRetainedThreadEviction(client, runtime);
|
|
1187
|
+
}
|
|
1188
|
+
async function evictExcessIdleThreads(client, runtime) {
|
|
1189
|
+
let idleThreadIds = [...runtime.retainedThreads.keys()].filter((threadId) => !runtime.protectedThreads.has(threadId));
|
|
1190
|
+
while (idleThreadIds.length > CODEX_APP_SERVER_LIVE_THREAD_MAX_IDLE) {
|
|
1191
|
+
await releaseRetainedThread(client, runtime, idleThreadIds[0]);
|
|
1192
|
+
idleThreadIds = [...runtime.retainedThreads.keys()].filter((threadId) => !runtime.protectedThreads.has(threadId));
|
|
1193
|
+
}
|
|
1194
|
+
}
|
|
1195
|
+
/** Retain separately owned Codex subscriptions; completing B must never cold-restart A. */
|
|
1196
|
+
async function retainCodexAppServerLiveThread(client, threadId, releaseThread, configFingerprint, serviceTier) {
|
|
1197
|
+
const runtime = configuredClients.get(client);
|
|
1198
|
+
if (!runtime || runtime.closed) return false;
|
|
1199
|
+
const claimed = runtime.claimedThreads.get(threadId);
|
|
1200
|
+
if (claimed !== void 0 && (releaseThread === void 0 || claimedThreadReleaseTokens.get(releaseThread) !== claimed)) return false;
|
|
1201
|
+
const pendingRelease = runtime.releasingThreads.get(threadId);
|
|
1202
|
+
if (pendingRelease) {
|
|
1203
|
+
await pendingRelease.completion;
|
|
1204
|
+
if (runtime.closed || claimed !== void 0 && runtime.claimedThreads.get(threadId) !== claimed) return false;
|
|
1205
|
+
}
|
|
1206
|
+
runtime.retainedThreads.delete(threadId);
|
|
1207
|
+
const retained = {
|
|
1208
|
+
configFingerprint,
|
|
1209
|
+
serviceTier,
|
|
1210
|
+
expiresAt: Date.now() + CODEX_APP_SERVER_LIVE_THREAD_IDLE_TIMEOUT_MS,
|
|
1211
|
+
release: (releaseThread ? physicalThreadReleases.get(releaseThread) ?? releaseThread : void 0) ?? (async (releasedThreadId) => {
|
|
1212
|
+
await unsubscribeCodexAppServerLiveThread(client, releasedThreadId, 5e3);
|
|
1213
|
+
})
|
|
1214
|
+
};
|
|
1215
|
+
runtime.retainedThreads.set(threadId, retained);
|
|
1216
|
+
try {
|
|
1217
|
+
await evictExcessIdleThreads(client, runtime);
|
|
1218
|
+
} catch (error) {
|
|
1219
|
+
if (runtime.retainedThreads.get(threadId) === retained) runtime.retainedThreads.delete(threadId);
|
|
1220
|
+
scheduleRetainedThreadEviction(client, runtime);
|
|
1221
|
+
embeddedAgentLog.warn("codex retained thread capacity eviction failed", {
|
|
1222
|
+
threadId,
|
|
1223
|
+
reason: formatErrorMessage(error)
|
|
1224
|
+
});
|
|
1225
|
+
return false;
|
|
1226
|
+
}
|
|
1227
|
+
if (runtime.closed) return false;
|
|
1228
|
+
if (claimed !== void 0 && runtime.claimedThreads.get(threadId) === claimed) runtime.claimedThreads.delete(threadId);
|
|
1229
|
+
scheduleRetainedThreadEviction(client, runtime);
|
|
1230
|
+
return true;
|
|
1231
|
+
}
|
|
1232
|
+
/** Transfer one idle subscription to its next turn or compaction without touching sibling threads. */
|
|
1233
|
+
async function consumeCodexAppServerLiveThread(client, threadId, configFingerprint) {
|
|
1155
1234
|
const runtime = configuredClients.get(client);
|
|
1156
|
-
if (!runtime) return;
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1235
|
+
if (!runtime || runtime.closed) return;
|
|
1236
|
+
const pendingRelease = runtime.releasingThreads.get(threadId);
|
|
1237
|
+
if (pendingRelease) {
|
|
1238
|
+
await pendingRelease.completion;
|
|
1239
|
+
return;
|
|
1240
|
+
}
|
|
1241
|
+
const retained = runtime.retainedThreads.get(threadId);
|
|
1242
|
+
if (!retained || configFingerprint !== void 0 && retained.configFingerprint !== configFingerprint) return;
|
|
1243
|
+
return claimCodexAppServerThreadOwnership(client, runtime, threadId, retained);
|
|
1244
|
+
}
|
|
1245
|
+
/** Claims an observed Codex auto-subscription without exposing a temporarily idle owner. */
|
|
1246
|
+
async function claimCodexAppServerLiveThread(client, threadId) {
|
|
1247
|
+
const runtime = configuredClients.get(client);
|
|
1248
|
+
if (!runtime || runtime.closed || runtime.claimedThreads.has(threadId)) return;
|
|
1249
|
+
const pendingRelease = runtime.releasingThreads.get(threadId);
|
|
1250
|
+
if (pendingRelease) {
|
|
1251
|
+
await pendingRelease.completion;
|
|
1252
|
+
return;
|
|
1253
|
+
}
|
|
1254
|
+
return claimCodexAppServerThreadOwnership(client, runtime, threadId, runtime.retainedThreads.get(threadId) ?? {
|
|
1255
|
+
expiresAt: Date.now() + CODEX_APP_SERVER_LIVE_THREAD_IDLE_TIMEOUT_MS,
|
|
1256
|
+
release: async (releasedThreadId) => {
|
|
1257
|
+
await unsubscribeCodexAppServerLiveThread(client, releasedThreadId, 5e3);
|
|
1258
|
+
}
|
|
1259
|
+
});
|
|
1260
|
+
}
|
|
1261
|
+
function claimCodexAppServerThreadOwnership(client, runtime, threadId, retained) {
|
|
1262
|
+
runtime.retainedThreads.delete(threadId);
|
|
1263
|
+
const claimed = Symbol(threadId);
|
|
1264
|
+
runtime.claimedThreads.set(threadId, claimed);
|
|
1265
|
+
scheduleRetainedThreadEviction(client, runtime);
|
|
1266
|
+
const release = async (releasedThreadId) => {
|
|
1267
|
+
if (releasedThreadId !== threadId || runtime.claimedThreads.get(threadId) !== claimed) return;
|
|
1268
|
+
const pendingRelease = runtime.releasingThreads.get(threadId);
|
|
1269
|
+
if (pendingRelease) {
|
|
1270
|
+
await pendingRelease.completion;
|
|
1271
|
+
return;
|
|
1272
|
+
}
|
|
1273
|
+
const transition = { completion: Promise.resolve().then(async () => {
|
|
1274
|
+
if (runtime.closed || runtime.claimedThreads.get(threadId) !== claimed) return;
|
|
1275
|
+
await retained.release(releasedThreadId);
|
|
1276
|
+
}) };
|
|
1277
|
+
runtime.releasingThreads.set(threadId, transition);
|
|
1162
1278
|
try {
|
|
1163
|
-
await
|
|
1164
|
-
|
|
1165
|
-
runtime.retainedThreadId = void 0;
|
|
1166
|
-
runtime.retainedThreadConfigFingerprint = void 0;
|
|
1167
|
-
throw error;
|
|
1279
|
+
await transition.completion;
|
|
1280
|
+
if (runtime.claimedThreads.get(threadId) === claimed) runtime.claimedThreads.delete(threadId);
|
|
1168
1281
|
} finally {
|
|
1169
|
-
if (runtime.
|
|
1282
|
+
if (runtime.releasingThreads.get(threadId) === transition) runtime.releasingThreads.delete(threadId);
|
|
1170
1283
|
}
|
|
1284
|
+
};
|
|
1285
|
+
physicalThreadReleases.set(release, retained.release);
|
|
1286
|
+
claimedThreadReleaseTokens.set(release, claimed);
|
|
1287
|
+
return {
|
|
1288
|
+
configFingerprint: retained.configFingerprint,
|
|
1289
|
+
serviceTier: retained.serviceTier,
|
|
1290
|
+
release
|
|
1291
|
+
};
|
|
1292
|
+
}
|
|
1293
|
+
/** Distinguish active claimed ownership from an already-evicted idle subscription. */
|
|
1294
|
+
function isCodexAppServerLiveThreadClaimed(client, threadId) {
|
|
1295
|
+
const runtime = configuredClients.get(client);
|
|
1296
|
+
return runtime !== void 0 && !runtime.closed && runtime.claimedThreads.has(threadId);
|
|
1297
|
+
}
|
|
1298
|
+
/** Release the exact physical subscription and finish only its observed claim generation. */
|
|
1299
|
+
async function unsubscribeCodexAppServerLiveThread(client, threadId, timeoutMs) {
|
|
1300
|
+
const runtime = configuredClients.get(client);
|
|
1301
|
+
const claimed = runtime?.claimedThreads.get(threadId);
|
|
1302
|
+
let transition = runtime?.releasingThreads.get(threadId);
|
|
1303
|
+
if (transition?.physicalRelease) {
|
|
1304
|
+
await transition.physicalRelease;
|
|
1305
|
+
return;
|
|
1306
|
+
}
|
|
1307
|
+
const physicalRelease = Promise.resolve().then(async () => {
|
|
1308
|
+
if (claimed !== void 0 && runtime?.claimedThreads.get(threadId) !== claimed) return;
|
|
1309
|
+
await client.request("thread/unsubscribe", { threadId }, { timeoutMs });
|
|
1310
|
+
});
|
|
1311
|
+
const ownsTransition = runtime !== void 0 && transition === void 0;
|
|
1312
|
+
if (transition) transition.physicalRelease = physicalRelease;
|
|
1313
|
+
else if (runtime) {
|
|
1314
|
+
transition = {
|
|
1315
|
+
completion: physicalRelease,
|
|
1316
|
+
physicalRelease
|
|
1317
|
+
};
|
|
1318
|
+
runtime.releasingThreads.set(threadId, transition);
|
|
1319
|
+
}
|
|
1320
|
+
try {
|
|
1321
|
+
await physicalRelease;
|
|
1322
|
+
if (claimed !== void 0 && runtime?.claimedThreads.get(threadId) === claimed) runtime.claimedThreads.delete(threadId);
|
|
1323
|
+
} finally {
|
|
1324
|
+
if (ownsTransition && runtime.releasingThreads.get(threadId) === transition) runtime.releasingThreads.delete(threadId);
|
|
1171
1325
|
}
|
|
1172
|
-
runtime.retainedThreadId = threadId;
|
|
1173
|
-
runtime.retainedThreadConfigFingerprint = configFingerprint;
|
|
1174
|
-
return previousThreadId ? { previousThreadId } : {};
|
|
1175
1326
|
}
|
|
1176
|
-
/**
|
|
1177
|
-
async function
|
|
1327
|
+
/** Reset/end owns the exact thread; failed generation retirement must never release its successor. */
|
|
1328
|
+
async function releaseCodexAppServerLiveThread(client, threadId) {
|
|
1178
1329
|
const runtime = configuredClients.get(client);
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
runtime
|
|
1184
|
-
return
|
|
1330
|
+
return runtime ? await releaseRetainedThread(client, runtime, threadId) : false;
|
|
1331
|
+
}
|
|
1332
|
+
/** Native child work pins its parent's subscription even after the foreground parent turn ends. */
|
|
1333
|
+
function protectCodexAppServerLiveThread(client, threadId) {
|
|
1334
|
+
const runtime = configuredClients.get(client);
|
|
1335
|
+
if (!runtime || runtime.closed) return () => void 0;
|
|
1336
|
+
runtime.protectedThreads.set(threadId, (runtime.protectedThreads.get(threadId) ?? 0) + 1);
|
|
1337
|
+
scheduleRetainedThreadEviction(client, runtime);
|
|
1338
|
+
let protectedThread = true;
|
|
1339
|
+
return () => {
|
|
1340
|
+
if (!protectedThread) return;
|
|
1341
|
+
protectedThread = false;
|
|
1342
|
+
if (runtime.closed) return;
|
|
1343
|
+
const count = runtime.protectedThreads.get(threadId) ?? 0;
|
|
1344
|
+
if (count <= 1) {
|
|
1345
|
+
runtime.protectedThreads.delete(threadId);
|
|
1346
|
+
const retained = runtime.retainedThreads.get(threadId);
|
|
1347
|
+
if (retained) {
|
|
1348
|
+
runtime.retainedThreads.delete(threadId);
|
|
1349
|
+
runtime.retainedThreads.set(threadId, {
|
|
1350
|
+
...retained,
|
|
1351
|
+
expiresAt: Date.now() + CODEX_APP_SERVER_LIVE_THREAD_IDLE_TIMEOUT_MS
|
|
1352
|
+
});
|
|
1353
|
+
}
|
|
1354
|
+
} else runtime.protectedThreads.set(threadId, count - 1);
|
|
1355
|
+
scheduleRetainedThreadEviction(client, runtime);
|
|
1356
|
+
evictExcessIdleThreads(client, runtime).catch((error) => {
|
|
1357
|
+
embeddedAgentLog.warn("codex retained thread unpin eviction failed", {
|
|
1358
|
+
threadId,
|
|
1359
|
+
reason: formatErrorMessage(error)
|
|
1360
|
+
});
|
|
1361
|
+
});
|
|
1362
|
+
};
|
|
1363
|
+
}
|
|
1364
|
+
//#endregion
|
|
1365
|
+
//#region extensions/codex/src/app-server/rpc-error.ts
|
|
1366
|
+
/** RPC error wrapper that preserves app-server error code and data. */
|
|
1367
|
+
var CodexAppServerRpcError = class extends Error {
|
|
1368
|
+
constructor(error, method) {
|
|
1369
|
+
super(formatCodexAppServerRpcErrorMessage(error, method));
|
|
1370
|
+
this.name = "CodexAppServerRpcError";
|
|
1371
|
+
this.code = error.code;
|
|
1372
|
+
this.data = error.data;
|
|
1373
|
+
this.method = method;
|
|
1374
|
+
}
|
|
1375
|
+
};
|
|
1376
|
+
function formatCodexAppServerRpcErrorMessage(error, method) {
|
|
1377
|
+
const message = error.message || `${method} failed`;
|
|
1378
|
+
const detail = readCodexAppServerRpcReloginDetail(error.data);
|
|
1379
|
+
return detail && !message.includes(detail) ? `${message}: ${detail}` : message;
|
|
1380
|
+
}
|
|
1381
|
+
function readCodexAppServerRpcReloginDetail(data) {
|
|
1382
|
+
const record = isJsonObject(data) ? data : void 0;
|
|
1383
|
+
const nested = isJsonObject(record?.error) ? record.error : record;
|
|
1384
|
+
if (!nested) return;
|
|
1385
|
+
const isRelogin = nested.action === "relogin" || nested.reason === "cloudRequirements" && nested.errorCode === "Auth";
|
|
1386
|
+
const detail = typeof nested.detail === "string" ? nested.detail.trim() : "";
|
|
1387
|
+
return isRelogin && detail ? detail : void 0;
|
|
1185
1388
|
}
|
|
1186
1389
|
//#endregion
|
|
1187
1390
|
//#region extensions/codex/src/app-server/transport-websocket.ts
|
|
@@ -1189,6 +1392,10 @@ async function consumeCodexAppServerLiveThread(client, threadId, configFingerpri
|
|
|
1189
1392
|
* Adapts a remote Codex app-server WebSocket endpoint to the shared stdio-like
|
|
1190
1393
|
* transport interface.
|
|
1191
1394
|
*/
|
|
1395
|
+
const WEBSOCKET_HANDSHAKE_TIMEOUT_MS = 1e4;
|
|
1396
|
+
const WEBSOCKET_PING_INTERVAL_MS = 2e4;
|
|
1397
|
+
const WEBSOCKET_PONG_TIMEOUT_MS = 2e4;
|
|
1398
|
+
const MAX_CONSECUTIVE_MISSED_WEBSOCKET_PONGS = 5;
|
|
1192
1399
|
/** Opens a WebSocket app-server transport and maps newline-delimited frames to stdout/stdin. */
|
|
1193
1400
|
function createWebSocketTransport(options) {
|
|
1194
1401
|
if (!options.url) throw new Error("codex app-server websocket transport requires plugins.entries.codex.config.appServer.url");
|
|
@@ -1200,7 +1407,8 @@ function createWebSocketTransport(options) {
|
|
|
1200
1407
|
...options.headers,
|
|
1201
1408
|
...options.authToken ? { Authorization: `Bearer ${options.authToken}` } : {}
|
|
1202
1409
|
},
|
|
1203
|
-
perMessageDeflate: false
|
|
1410
|
+
perMessageDeflate: false,
|
|
1411
|
+
...options.transport === "websocket" ? { handshakeTimeout: WEBSOCKET_HANDSHAKE_TIMEOUT_MS } : {}
|
|
1204
1412
|
};
|
|
1205
1413
|
const unixSocketPath = resolveCodexAppServerUnixSocketPath(options);
|
|
1206
1414
|
const socket = unixSocketPath ? new WebSocket("ws://localhost/", {
|
|
@@ -1211,6 +1419,58 @@ function createWebSocketTransport(options) {
|
|
|
1211
1419
|
const stdinDecoder = new StringDecoder("utf8");
|
|
1212
1420
|
let pendingLine = "";
|
|
1213
1421
|
let killed = false;
|
|
1422
|
+
let pingTimeout;
|
|
1423
|
+
let pongTimeout;
|
|
1424
|
+
let expectedPong;
|
|
1425
|
+
let consecutiveMissedPongs = 0;
|
|
1426
|
+
let heartbeatSequence = 0;
|
|
1427
|
+
const clearConnectionHealthTimers = () => {
|
|
1428
|
+
if (pingTimeout) {
|
|
1429
|
+
clearTimeout(pingTimeout);
|
|
1430
|
+
pingTimeout = void 0;
|
|
1431
|
+
}
|
|
1432
|
+
if (pongTimeout) {
|
|
1433
|
+
clearTimeout(pongTimeout);
|
|
1434
|
+
pongTimeout = void 0;
|
|
1435
|
+
}
|
|
1436
|
+
expectedPong = void 0;
|
|
1437
|
+
};
|
|
1438
|
+
const sendHeartbeatPing = () => {
|
|
1439
|
+
if (socket.readyState !== WebSocket.OPEN || pongTimeout) return;
|
|
1440
|
+
const payload = Buffer.from(`openclaw-codex-${++heartbeatSequence}`);
|
|
1441
|
+
expectedPong = payload;
|
|
1442
|
+
pongTimeout = setTimeout(() => {
|
|
1443
|
+
pongTimeout = void 0;
|
|
1444
|
+
expectedPong = void 0;
|
|
1445
|
+
consecutiveMissedPongs += 1;
|
|
1446
|
+
if (consecutiveMissedPongs >= MAX_CONSECUTIVE_MISSED_WEBSOCKET_PONGS) {
|
|
1447
|
+
socket.terminate();
|
|
1448
|
+
return;
|
|
1449
|
+
}
|
|
1450
|
+
sendHeartbeatPing();
|
|
1451
|
+
}, WEBSOCKET_PONG_TIMEOUT_MS);
|
|
1452
|
+
pongTimeout.unref();
|
|
1453
|
+
socket.ping(payload, void 0, (error) => {
|
|
1454
|
+
if (error) socket.terminate();
|
|
1455
|
+
});
|
|
1456
|
+
};
|
|
1457
|
+
const scheduleHeartbeatPing = () => {
|
|
1458
|
+
if (options.transport !== "websocket" || socket.readyState !== WebSocket.OPEN || pingTimeout || pongTimeout) return;
|
|
1459
|
+
pingTimeout = setTimeout(() => {
|
|
1460
|
+
pingTimeout = void 0;
|
|
1461
|
+
sendHeartbeatPing();
|
|
1462
|
+
}, WEBSOCKET_PING_INTERVAL_MS);
|
|
1463
|
+
pingTimeout.unref();
|
|
1464
|
+
};
|
|
1465
|
+
const recordConnectionActivity = () => {
|
|
1466
|
+
consecutiveMissedPongs = 0;
|
|
1467
|
+
if (pongTimeout) {
|
|
1468
|
+
clearTimeout(pongTimeout);
|
|
1469
|
+
pongTimeout = void 0;
|
|
1470
|
+
}
|
|
1471
|
+
expectedPong = void 0;
|
|
1472
|
+
scheduleHeartbeatPing();
|
|
1473
|
+
};
|
|
1214
1474
|
const sendFrame = (frame) => {
|
|
1215
1475
|
const trimmed = frame.trim();
|
|
1216
1476
|
if (!trimmed) return;
|
|
@@ -1222,13 +1482,22 @@ function createWebSocketTransport(options) {
|
|
|
1222
1482
|
};
|
|
1223
1483
|
socket.once("open", () => {
|
|
1224
1484
|
for (const frame of pendingFrames.splice(0)) socket.send(frame);
|
|
1485
|
+
scheduleHeartbeatPing();
|
|
1486
|
+
});
|
|
1487
|
+
socket.on("pong", (payload) => {
|
|
1488
|
+
if (expectedPong?.equals(payload)) recordConnectionActivity();
|
|
1489
|
+
});
|
|
1490
|
+
socket.once("error", (error) => {
|
|
1491
|
+
clearConnectionHealthTimers();
|
|
1492
|
+
events.emit("error", error);
|
|
1225
1493
|
});
|
|
1226
|
-
socket.once("error", (error) => events.emit("error", error));
|
|
1227
1494
|
socket.once("close", (code, reason) => {
|
|
1495
|
+
clearConnectionHealthTimers();
|
|
1228
1496
|
killed = true;
|
|
1229
1497
|
events.emit("exit", code, reason.toString("utf8"));
|
|
1230
1498
|
});
|
|
1231
1499
|
socket.on("message", (data) => {
|
|
1500
|
+
if (options.transport === "websocket") recordConnectionActivity();
|
|
1232
1501
|
const text = websocketFrameToText(data);
|
|
1233
1502
|
stdout.write(text.endsWith("\n") ? text : `${text}\n`);
|
|
1234
1503
|
});
|
|
@@ -1262,6 +1531,7 @@ function createWebSocketTransport(options) {
|
|
|
1262
1531
|
},
|
|
1263
1532
|
kill: () => {
|
|
1264
1533
|
killed = true;
|
|
1534
|
+
clearConnectionHealthTimers();
|
|
1265
1535
|
socket.close();
|
|
1266
1536
|
},
|
|
1267
1537
|
once: (event, listener) => events.once(event, listener)
|
|
@@ -1349,7 +1619,7 @@ function signalCodexAppServerTransport(child, signal) {
|
|
|
1349
1619
|
* Version and package pins for the managed Codex app-server runtime.
|
|
1350
1620
|
*/
|
|
1351
1621
|
/** Exact Codex app-server version shipped and supported by the OpenClaw Codex bridge. */
|
|
1352
|
-
const CODEX_APP_SERVER_VERSION = "0.
|
|
1622
|
+
const CODEX_APP_SERVER_VERSION = "0.147.0";
|
|
1353
1623
|
/** npm package name for the managed Codex app-server binary. */
|
|
1354
1624
|
const MANAGED_CODEX_APP_SERVER_PACKAGE = "@openai/codex";
|
|
1355
1625
|
//#endregion
|
|
@@ -1379,16 +1649,6 @@ function getCodexAppServerClientInstanceId(client) {
|
|
|
1379
1649
|
function resolveCodexAppServerClientInstanceId(client) {
|
|
1380
1650
|
return client.getInstanceId?.call(client) ?? getCodexAppServerClientInstanceId(client);
|
|
1381
1651
|
}
|
|
1382
|
-
/** RPC error wrapper that preserves app-server error code and data. */
|
|
1383
|
-
var CodexAppServerRpcError = class extends Error {
|
|
1384
|
-
constructor(error, method) {
|
|
1385
|
-
super(formatCodexAppServerRpcErrorMessage(error, method));
|
|
1386
|
-
this.name = "CodexAppServerRpcError";
|
|
1387
|
-
this.code = error.code;
|
|
1388
|
-
this.data = error.data;
|
|
1389
|
-
this.method = method;
|
|
1390
|
-
}
|
|
1391
|
-
};
|
|
1392
1652
|
var CodexAppServerLocalRequestCancellationError = class extends Error {
|
|
1393
1653
|
constructor(method, reason, mayHaveWritten) {
|
|
1394
1654
|
super(`${method} ${reason}`);
|
|
@@ -1431,22 +1691,6 @@ function isCodexAppServerPrewriteRequestCancellationError(error) {
|
|
|
1431
1691
|
function isCodexAppServerIndeterminateTransportError(error) {
|
|
1432
1692
|
return error instanceof Error && "code" in error && error.code === "CODEX_APP_SERVER_REQUEST_TRANSPORT_INDETERMINATE" && "mayHaveWritten" in error && error.mayHaveWritten === true;
|
|
1433
1693
|
}
|
|
1434
|
-
function formatCodexAppServerRpcErrorMessage(error, method) {
|
|
1435
|
-
const message = error.message || `${method} failed`;
|
|
1436
|
-
const detail = readCodexAppServerRpcReloginDetail(error.data);
|
|
1437
|
-
return detail && !message.includes(detail) ? `${message}: ${detail}` : message;
|
|
1438
|
-
}
|
|
1439
|
-
function readCodexAppServerRpcReloginDetail(data) {
|
|
1440
|
-
const record = isJsonObject(data) ? data : void 0;
|
|
1441
|
-
const nested = isJsonObject(record?.error) ? record.error : record;
|
|
1442
|
-
if (!nested) return;
|
|
1443
|
-
const isRelogin = nested.action === "relogin" || nested.reason === "cloudRequirements" && nested.errorCode === "Auth";
|
|
1444
|
-
const detail = typeof nested.detail === "string" ? nested.detail.trim() : "";
|
|
1445
|
-
return isRelogin && detail ? detail : void 0;
|
|
1446
|
-
}
|
|
1447
|
-
function isJsonObject(value) {
|
|
1448
|
-
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
1449
|
-
}
|
|
1450
1694
|
/** Returns true for errors that mean the app-server transport is closed. */
|
|
1451
1695
|
function isCodexAppServerConnectionClosedError(error) {
|
|
1452
1696
|
if (!(error instanceof Error)) return false;
|
|
@@ -1469,8 +1713,8 @@ var CodexAppServerClient = class CodexAppServerClient {
|
|
|
1469
1713
|
this.child = child;
|
|
1470
1714
|
this.lines = createInterface({ input: child.stdout });
|
|
1471
1715
|
this.lines.on("line", (line) => this.handleLine(line));
|
|
1472
|
-
this.lines.on("error", (error) => this.closeWithError(
|
|
1473
|
-
child.stdout.on("error", (error) => this.closeWithError(
|
|
1716
|
+
this.lines.on("error", (error) => this.closeWithError(toStringifiedError(error)));
|
|
1717
|
+
child.stdout.on("error", (error) => this.closeWithError(toStringifiedError(error)));
|
|
1474
1718
|
child.stderr.setEncoding("utf8");
|
|
1475
1719
|
child.stderr.on("data", (text) => {
|
|
1476
1720
|
this.stderrTail = appendBoundedTail(this.stderrTail, text, CODEX_APP_SERVER_STDERR_TAIL_MAX);
|
|
@@ -1480,12 +1724,12 @@ var CodexAppServerClient = class CodexAppServerClient {
|
|
|
1480
1724
|
child.stderr.on("error", (error) => {
|
|
1481
1725
|
embeddedAgentLog.warn("codex app-server stderr stream failed", { error });
|
|
1482
1726
|
});
|
|
1483
|
-
child.once("error", (error) => this.closeWithError(
|
|
1727
|
+
child.once("error", (error) => this.closeWithError(toStringifiedError(error)));
|
|
1484
1728
|
child.once("exit", (code, signal) => {
|
|
1485
1729
|
this.transportExited = true;
|
|
1486
1730
|
this.closeWithError(buildCodexAppServerExitError(code, signal, this.stderrTail));
|
|
1487
1731
|
});
|
|
1488
|
-
child.stdin.on?.("error", (error) => this.closeWithError(
|
|
1732
|
+
child.stdin.on?.("error", (error) => this.closeWithError(toStringifiedError(error)));
|
|
1489
1733
|
}
|
|
1490
1734
|
/** Starts a new app-server client using resolved runtime start options. */
|
|
1491
1735
|
static start(options) {
|
|
@@ -1531,6 +1775,10 @@ var CodexAppServerClient = class CodexAppServerClient {
|
|
|
1531
1775
|
getStderrDiagnostic() {
|
|
1532
1776
|
return redactCodexAppServerLinePreview(this.stderrTail) || void 0;
|
|
1533
1777
|
}
|
|
1778
|
+
/** Returns the terminal transport error that closed this physical client. */
|
|
1779
|
+
getCloseError() {
|
|
1780
|
+
return this.closeError;
|
|
1781
|
+
}
|
|
1534
1782
|
/** Stable generation id for this exact physical client instance. */
|
|
1535
1783
|
getInstanceId() {
|
|
1536
1784
|
return this.instanceId;
|
|
@@ -1700,7 +1948,7 @@ var CodexAppServerClient = class CodexAppServerClient {
|
|
|
1700
1948
|
onWriteAttempt?.();
|
|
1701
1949
|
this.writeMessage(message, (error) => rejectPending(error));
|
|
1702
1950
|
} catch (error) {
|
|
1703
|
-
rejectPending(
|
|
1951
|
+
rejectPending(toStringifiedError(error));
|
|
1704
1952
|
}
|
|
1705
1953
|
});
|
|
1706
1954
|
}
|
|
@@ -1871,7 +2119,7 @@ var CodexAppServerClient = class CodexAppServerClient {
|
|
|
1871
2119
|
result: defaultServerRequestResponse(request)
|
|
1872
2120
|
});
|
|
1873
2121
|
} catch (error) {
|
|
1874
|
-
const message =
|
|
2122
|
+
const message = coerceErrorMessage(error);
|
|
1875
2123
|
embeddedAgentLog.warn("codex app-server server request handler failed", {
|
|
1876
2124
|
id: request.id,
|
|
1877
2125
|
method: request.method,
|
|
@@ -1985,17 +2233,17 @@ var CodexAppServerVersionError = class extends Error {
|
|
|
1985
2233
|
};
|
|
1986
2234
|
function assertSupportedCodexAppServerVersion(response) {
|
|
1987
2235
|
const detectedVersion = readCodexVersionFromUserAgent(response.userAgent);
|
|
1988
|
-
if (detectedVersion !== "0.
|
|
2236
|
+
if (detectedVersion !== "0.147.0") throw new CodexAppServerVersionError(detectedVersion);
|
|
1989
2237
|
return detectedVersion;
|
|
1990
2238
|
}
|
|
1991
2239
|
function isUnsupportedCodexAppServerVersionError(error) {
|
|
1992
2240
|
return error instanceof CodexAppServerVersionError;
|
|
1993
2241
|
}
|
|
1994
2242
|
function buildCodexAppServerRuntimeIdentity(response, serverVersion) {
|
|
1995
|
-
const userAgent =
|
|
1996
|
-
const codexHome =
|
|
1997
|
-
const platformFamily =
|
|
1998
|
-
const platformOs =
|
|
2243
|
+
const userAgent = normalizeOptionalString(response.userAgent);
|
|
2244
|
+
const codexHome = normalizeOptionalString(response.codexHome);
|
|
2245
|
+
const platformFamily = normalizeOptionalString(response.platformFamily);
|
|
2246
|
+
const platformOs = normalizeOptionalString(response.platformOs);
|
|
1999
2247
|
return {
|
|
2000
2248
|
serverVersion,
|
|
2001
2249
|
...userAgent ? { userAgent } : {},
|
|
@@ -2004,10 +2252,6 @@ function buildCodexAppServerRuntimeIdentity(response, serverVersion) {
|
|
|
2004
2252
|
...platformOs ? { platformOs } : {}
|
|
2005
2253
|
};
|
|
2006
2254
|
}
|
|
2007
|
-
function readNonEmptyInitializeString(value) {
|
|
2008
|
-
const trimmed = value?.trim();
|
|
2009
|
-
return trimmed ? trimmed : void 0;
|
|
2010
|
-
}
|
|
2011
2255
|
/** Extracts the Codex version from the app-server initialize user-agent field. */
|
|
2012
2256
|
function readCodexVersionFromUserAgent(userAgent) {
|
|
2013
2257
|
return (userAgent?.match(/^[^/]+\/(\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?)(?:[\s(]|$)/))?.[1];
|
|
@@ -2027,7 +2271,7 @@ function buildCodexAppServerExitError(code, signal, stderrTail) {
|
|
|
2027
2271
|
}
|
|
2028
2272
|
function shouldBufferCodexAppServerParseFailure(value, error) {
|
|
2029
2273
|
if (!value.startsWith("{") && !value.startsWith("[")) return false;
|
|
2030
|
-
const message =
|
|
2274
|
+
const message = coerceErrorMessage(error);
|
|
2031
2275
|
return message.includes("Unterminated string") || message.includes("Unexpected end of JSON input");
|
|
2032
2276
|
}
|
|
2033
2277
|
function logCodexAppServerParseFailure(value, error, fragmentCount) {
|
|
@@ -2035,7 +2279,7 @@ function logCodexAppServerParseFailure(value, error, fragmentCount) {
|
|
|
2035
2279
|
const suffix = fragmentCount > 1 ? ` fragments=${fragmentCount}` : "";
|
|
2036
2280
|
embeddedAgentLog.warn("failed to parse codex app-server message", {
|
|
2037
2281
|
error,
|
|
2038
|
-
errorMessage:
|
|
2282
|
+
errorMessage: coerceErrorMessage(error),
|
|
2039
2283
|
fragmentCount,
|
|
2040
2284
|
linePreview,
|
|
2041
2285
|
consoleMessage: `failed to parse codex app-server message${suffix}: preview=${JSON.stringify(linePreview)}`
|
|
@@ -2056,6 +2300,103 @@ function formatExitValue(value) {
|
|
|
2056
2300
|
return "unknown";
|
|
2057
2301
|
}
|
|
2058
2302
|
//#endregion
|
|
2303
|
+
//#region extensions/codex/src/app-server/attempt-timeouts.ts
|
|
2304
|
+
/**
|
|
2305
|
+
* Timeout defaults and normalizers for Codex app-server startup and turn
|
|
2306
|
+
* liveness watches.
|
|
2307
|
+
*/
|
|
2308
|
+
/** Minimum startup timeout accepted by the Codex app-server harness. */
|
|
2309
|
+
const CODEX_APP_SERVER_STARTUP_TIMEOUT_FLOOR_MS = 100;
|
|
2310
|
+
/** Default idle timeout while waiting for app-server turn completion. */
|
|
2311
|
+
const CODEX_TURN_COMPLETION_IDLE_TIMEOUT_MS = 6e4;
|
|
2312
|
+
/** Short guard after apparent assistant completion. */
|
|
2313
|
+
const CODEX_TURN_ASSISTANT_COMPLETION_IDLE_TIMEOUT_MS = 1e4;
|
|
2314
|
+
const CODEX_POST_TOOL_RAW_ASSISTANT_COMPLETION_IDLE_TIMEOUT_MS = 5 * 6e4;
|
|
2315
|
+
/** Guard after reasoning/commentary progress when no tool handoff occurred. */
|
|
2316
|
+
const CODEX_POST_REASONING_REPLY_IDLE_TIMEOUT_MS = 5 * 6e4;
|
|
2317
|
+
/** Long terminal idle watch for app-server turns that never send completion. */
|
|
2318
|
+
const CODEX_TURN_TERMINAL_IDLE_TIMEOUT_MS = 30 * 6e4;
|
|
2319
|
+
var CodexAppServerStartupError = class extends Error {
|
|
2320
|
+
constructor(reason, message = reason === "timed_out" ? "codex app-server startup timed out" : "codex app-server startup aborted") {
|
|
2321
|
+
super(message);
|
|
2322
|
+
this.reason = reason;
|
|
2323
|
+
this.code = "CODEX_APP_SERVER_STARTUP_CANCELLED";
|
|
2324
|
+
this.name = "CodexAppServerStartupError";
|
|
2325
|
+
}
|
|
2326
|
+
};
|
|
2327
|
+
function isCodexAppServerStartupError(error, reason) {
|
|
2328
|
+
return error instanceof Error && "code" in error && error.code === "CODEX_APP_SERVER_STARTUP_CANCELLED" && "reason" in error && (error.reason === "aborted" || error.reason === "timed_out") && (reason === void 0 || error.reason === reason);
|
|
2329
|
+
}
|
|
2330
|
+
function resolvePositiveIntegerTimeoutMs(value, fallbackMs) {
|
|
2331
|
+
return resolveTimerTimeoutMs(value, resolveTimerTimeoutMs(fallbackMs, 1));
|
|
2332
|
+
}
|
|
2333
|
+
/** Runs startup work with abort and timeout handling plus optional cleanup. */
|
|
2334
|
+
async function withCodexStartupTimeout(params) {
|
|
2335
|
+
if (params.signal.aborted) throw new CodexAppServerStartupError("aborted");
|
|
2336
|
+
let timeout;
|
|
2337
|
+
let abortCleanup;
|
|
2338
|
+
let timeoutError;
|
|
2339
|
+
let timeoutCleanup;
|
|
2340
|
+
try {
|
|
2341
|
+
return await Promise.race([params.operation(), new Promise((_, reject) => {
|
|
2342
|
+
const rejectOnce = (error) => {
|
|
2343
|
+
if (timeout) {
|
|
2344
|
+
clearTimeout(timeout);
|
|
2345
|
+
timeout = void 0;
|
|
2346
|
+
}
|
|
2347
|
+
reject(error);
|
|
2348
|
+
};
|
|
2349
|
+
timeout = setTimeout(() => {
|
|
2350
|
+
timeoutError = new CodexAppServerStartupError("timed_out");
|
|
2351
|
+
timeoutCleanup = Promise.resolve(params.onTimeout?.()).then(() => void 0, () => void 0);
|
|
2352
|
+
timeoutCleanup.finally(() => {
|
|
2353
|
+
rejectOnce(timeoutError);
|
|
2354
|
+
});
|
|
2355
|
+
}, params.timeoutMs);
|
|
2356
|
+
const abortListener = () => rejectOnce(new CodexAppServerStartupError("aborted"));
|
|
2357
|
+
params.signal.addEventListener("abort", abortListener, { once: true });
|
|
2358
|
+
abortCleanup = () => params.signal.removeEventListener("abort", abortListener);
|
|
2359
|
+
})]);
|
|
2360
|
+
} catch (error) {
|
|
2361
|
+
if (timeoutError) {
|
|
2362
|
+
await timeoutCleanup;
|
|
2363
|
+
throw timeoutError;
|
|
2364
|
+
}
|
|
2365
|
+
throw error;
|
|
2366
|
+
} finally {
|
|
2367
|
+
if (timeout) clearTimeout(timeout);
|
|
2368
|
+
abortCleanup?.();
|
|
2369
|
+
}
|
|
2370
|
+
}
|
|
2371
|
+
/** Resolves startup timeout while honoring the configured floor. */
|
|
2372
|
+
function resolveCodexStartupTimeoutMs(params) {
|
|
2373
|
+
const timeoutFloorMs = resolvePositiveIntegerTimeoutMs(params.timeoutFloorMs, CODEX_APP_SERVER_STARTUP_TIMEOUT_FLOOR_MS);
|
|
2374
|
+
const timeoutMs = resolvePositiveIntegerTimeoutMs(params.timeoutMs, timeoutFloorMs);
|
|
2375
|
+
return Math.max(timeoutFloorMs, timeoutMs);
|
|
2376
|
+
}
|
|
2377
|
+
/** Resolves the completion-idle timeout for an active turn. */
|
|
2378
|
+
function resolveCodexTurnCompletionIdleTimeoutMs(value) {
|
|
2379
|
+
return resolvePositiveIntegerTimeoutMs(value, CODEX_TURN_COMPLETION_IDLE_TIMEOUT_MS);
|
|
2380
|
+
}
|
|
2381
|
+
/** Resolves the short assistant-completion release timeout. */
|
|
2382
|
+
function resolveCodexTurnAssistantCompletionIdleTimeoutMs(value) {
|
|
2383
|
+
return resolvePositiveIntegerTimeoutMs(value, CODEX_TURN_ASSISTANT_COMPLETION_IDLE_TIMEOUT_MS);
|
|
2384
|
+
}
|
|
2385
|
+
/** Resolves the conservative post-tool raw assistant guard timeout. */
|
|
2386
|
+
function resolveCodexPostToolRawAssistantCompletionIdleTimeoutMs(value, fallbackMs) {
|
|
2387
|
+
return resolvePositiveIntegerTimeoutMs(value, Math.max(resolvePositiveIntegerTimeoutMs(void 0, fallbackMs), CODEX_POST_TOOL_RAW_ASSISTANT_COMPLETION_IDLE_TIMEOUT_MS));
|
|
2388
|
+
}
|
|
2389
|
+
/** Resolves the long terminal turn idle timeout. */
|
|
2390
|
+
function resolveCodexTurnTerminalIdleTimeoutMs(value, runTimeoutOverrideMs) {
|
|
2391
|
+
const explicitRunBudgetMs = resolvePositiveIntegerTimeoutMs(runTimeoutOverrideMs, CODEX_TURN_TERMINAL_IDLE_TIMEOUT_MS);
|
|
2392
|
+
return resolvePositiveIntegerTimeoutMs(value, Math.max(CODEX_TURN_TERMINAL_IDLE_TIMEOUT_MS, explicitRunBudgetMs));
|
|
2393
|
+
}
|
|
2394
|
+
/** Adds gateway grace time to a caller timeout without overflowing invalid values. */
|
|
2395
|
+
function resolveCodexGatewayTimeoutWithGraceMs(timeoutMs, graceMs = 1e4) {
|
|
2396
|
+
const timeout = resolvePositiveIntegerTimeoutMs(timeoutMs, 1);
|
|
2397
|
+
return addTimerTimeoutGraceMs(timeout, resolveTimerTimeoutMs(graceMs, 0, 0)) ?? timeout;
|
|
2398
|
+
}
|
|
2399
|
+
//#endregion
|
|
2059
2400
|
//#region extensions/codex/src/app-server/managed-binary.ts
|
|
2060
2401
|
/**
|
|
2061
2402
|
* Resolves the managed Codex app-server binary shipped with or installed beside
|
|
@@ -2221,15 +2562,13 @@ function resolveManagedCodexPackageBinCandidate(root) {
|
|
|
2221
2562
|
const packageJsonPath = createRequire(path.join(root, "package.json")).resolve(`${MANAGED_CODEX_APP_SERVER_PACKAGE}/package.json`);
|
|
2222
2563
|
const packageRoot = path.dirname(packageJsonPath);
|
|
2223
2564
|
const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf8"));
|
|
2224
|
-
const
|
|
2565
|
+
const packageBin = packageJson.bin && typeof packageJson.bin === "object" ? packageJson.bin : void 0;
|
|
2566
|
+
const binPath = typeof packageJson.bin === "string" ? packageJson.bin : typeof packageBin?.codex === "string" ? packageBin.codex : null;
|
|
2225
2567
|
return binPath ? path.resolve(packageRoot, binPath) : null;
|
|
2226
2568
|
} catch {
|
|
2227
2569
|
return null;
|
|
2228
2570
|
}
|
|
2229
2571
|
}
|
|
2230
|
-
function isRecord(value) {
|
|
2231
|
-
return typeof value === "object" && value !== null;
|
|
2232
|
-
}
|
|
2233
2572
|
function isDistExtensionRoot(pluginRoot, platform) {
|
|
2234
2573
|
const pathApi = pathForPlatform(platform);
|
|
2235
2574
|
const extensionsDir = pathApi.dirname(pluginRoot);
|
|
@@ -2325,6 +2664,9 @@ async function waitForPreviousFence(previous, options) {
|
|
|
2325
2664
|
* Thin Codex app-server timeout adapter around OpenClaw's shared security
|
|
2326
2665
|
* runtime timeout helper.
|
|
2327
2666
|
*/
|
|
2667
|
+
function resolveAbortError(signal) {
|
|
2668
|
+
return signal.reason instanceof Error ? signal.reason : new Error("Codex app-server operation aborted", { cause: signal.reason });
|
|
2669
|
+
}
|
|
2328
2670
|
/** Awaits a promise with a Codex-specific timeout error message. */
|
|
2329
2671
|
async function withTimeout$1(promise, timeoutMs, timeoutMessage, createError) {
|
|
2330
2672
|
return await withTimeout(promise, timeoutMs, {
|
|
@@ -2332,6 +2674,22 @@ async function withTimeout$1(promise, timeoutMs, timeoutMessage, createError) {
|
|
|
2332
2674
|
...createError ? { createError } : {}
|
|
2333
2675
|
});
|
|
2334
2676
|
}
|
|
2677
|
+
/** Bounds an operation by both its owner lifecycle and one total wall-clock budget. */
|
|
2678
|
+
async function withAbortableTimeout(params) {
|
|
2679
|
+
const signal = params.signal;
|
|
2680
|
+
if (signal?.aborted) throw resolveAbortError(signal);
|
|
2681
|
+
let removeAbortListener;
|
|
2682
|
+
const operation = signal ? Promise.race([params.promise, new Promise((_, reject) => {
|
|
2683
|
+
const onAbort = () => reject(resolveAbortError(signal));
|
|
2684
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
2685
|
+
removeAbortListener = () => signal.removeEventListener("abort", onAbort);
|
|
2686
|
+
})]) : params.promise;
|
|
2687
|
+
try {
|
|
2688
|
+
return await withTimeout$1(operation, params.timeoutMs, params.timeoutMessage, params.createTimeoutError);
|
|
2689
|
+
} finally {
|
|
2690
|
+
removeAbortListener?.();
|
|
2691
|
+
}
|
|
2692
|
+
}
|
|
2335
2693
|
//#endregion
|
|
2336
2694
|
//#region extensions/codex/src/app-server/shared-client.ts
|
|
2337
2695
|
/**
|
|
@@ -2358,7 +2716,6 @@ var shared_client_exports = /* @__PURE__ */ __exportAll({
|
|
|
2358
2716
|
withLeasedCodexAppServerClientStartSelectionRetry: () => withLeasedCodexAppServerClientStartSelectionRetry
|
|
2359
2717
|
});
|
|
2360
2718
|
const CODEX_APP_SERVER_INITIALIZE_TIMEOUT_MESSAGE = "codex app-server initialize timed out";
|
|
2361
|
-
const suspectClosedClients = /* @__PURE__ */ new WeakSet();
|
|
2362
2719
|
const SHARED_CODEX_APP_SERVER_CLIENT_STATE = Symbol.for("openclaw.codexAppServerClientState");
|
|
2363
2720
|
const SHARED_CODEX_APP_SERVER_CLIENT_DISPOSER = Symbol.for("openclaw.codexAppServerClientDisposer");
|
|
2364
2721
|
const CODEX_APP_SERVER_CLIENT_START_METADATA = Symbol.for("openclaw.codexAppServerClientStartMetadata");
|
|
@@ -2366,6 +2723,8 @@ function getSharedCodexAppServerClientState() {
|
|
|
2366
2723
|
const globalState = globalThis;
|
|
2367
2724
|
globalState[SHARED_CODEX_APP_SERVER_CLIENT_STATE] ??= {
|
|
2368
2725
|
clients: /* @__PURE__ */ new Map(),
|
|
2726
|
+
liveClients: /* @__PURE__ */ new Set(),
|
|
2727
|
+
entriesByClient: /* @__PURE__ */ new WeakMap(),
|
|
2369
2728
|
leasedReleases: /* @__PURE__ */ new WeakMap()
|
|
2370
2729
|
};
|
|
2371
2730
|
return globalState[SHARED_CODEX_APP_SERVER_CLIENT_STATE];
|
|
@@ -2480,9 +2839,11 @@ async function resolveCodexAppServerClientStartContext(options) {
|
|
|
2480
2839
|
startOptions: requestedStartOptions,
|
|
2481
2840
|
agentDir
|
|
2482
2841
|
})),
|
|
2842
|
+
agentId: options?.agentId,
|
|
2483
2843
|
agentDir,
|
|
2484
2844
|
authProfileId: usesNativeAuth || preparedAuth?.kind === "api-key" ? null : authProfileId,
|
|
2485
2845
|
...resolvedPreparedAuth ? { preparedAuth: resolvedPreparedAuth } : {},
|
|
2846
|
+
authRequirement,
|
|
2486
2847
|
config: options?.config,
|
|
2487
2848
|
pluginConfig: options?.pluginConfig,
|
|
2488
2849
|
...authProfileStore ? { authProfileStore } : {}
|
|
@@ -2725,14 +3086,20 @@ function createSharedCodexAppServerClientStartup(params) {
|
|
|
2725
3086
|
runtimeArtifactSignal: params.runtimeArtifactSignal,
|
|
2726
3087
|
config: params.config,
|
|
2727
3088
|
onStartedClient: (startedClient) => {
|
|
3089
|
+
const state = getSharedCodexAppServerClientState();
|
|
2728
3090
|
params.entry.client = startedClient;
|
|
3091
|
+
state.entriesByClient.set(startedClient, params.entry);
|
|
3092
|
+
state.liveClients.add(startedClient);
|
|
3093
|
+
startedClient.addCloseHandler((closedClient) => {
|
|
3094
|
+
getSharedCodexAppServerClientState().liveClients.delete(closedClient);
|
|
3095
|
+
clearSharedClientEntryIfCurrent(params.key, closedClient);
|
|
3096
|
+
});
|
|
2729
3097
|
for (const callback of params.entry.onStartedClientCallbacks) callback(startedClient);
|
|
2730
3098
|
retirePendingSharedClientEntryIfUnclaimed(params.key, params.entry);
|
|
2731
3099
|
},
|
|
2732
3100
|
onInitializedClient: () => initialized.resolve()
|
|
2733
3101
|
}).then((client) => {
|
|
2734
3102
|
params.entry.client = client;
|
|
2735
|
-
client.addCloseHandler((closedClient) => clearSharedClientEntryIfCurrent(params.key, closedClient));
|
|
2736
3103
|
return client;
|
|
2737
3104
|
}, (error) => {
|
|
2738
3105
|
initialized.reject(error);
|
|
@@ -2772,7 +3139,7 @@ async function startInitializedCodexAppServerClient(params) {
|
|
|
2772
3139
|
const timeoutMs = params.timeoutMs ?? 0;
|
|
2773
3140
|
const startOptionsCandidates = resolveManagedFallbackStartOptions(params.startOptions);
|
|
2774
3141
|
for (const [index, startOptions] of startOptionsCandidates.entries()) {
|
|
2775
|
-
const runtimeArtifactModule = params.runtimeArtifactMode ? await import("./runtime-artifact-
|
|
3142
|
+
const runtimeArtifactModule = params.runtimeArtifactMode ? await import("./runtime-artifact-BVSPdd6g.js") : void 0;
|
|
2776
3143
|
const nativeCommandBeforeStart = startOptions.commandSource === "resolved-managed" ? resolveManagedCodexNativeCommand(startOptions.command) : void 0;
|
|
2777
3144
|
const runtimeArtifactBeforeStart = runtimeArtifactModule ? await runtimeArtifactModule.captureCodexAppServerRuntimeArtifactBeforeStart({
|
|
2778
3145
|
startOptions,
|
|
@@ -2922,11 +3289,9 @@ function retireSharedCodexAppServerClientIfCurrent(client, opts) {
|
|
|
2922
3289
|
entry.closeWhenIdle = true;
|
|
2923
3290
|
if (opts?.failActiveLeases) {
|
|
2924
3291
|
entry.closeError = /* @__PURE__ */ new Error("codex app-server client is closed");
|
|
2925
|
-
const closed = closeRetiredSharedClientEntry(entry);
|
|
2926
|
-
if (closed) suspectClosedClients.add(client);
|
|
2927
3292
|
return {
|
|
2928
3293
|
activeLeases: entry.activeLeases,
|
|
2929
|
-
closed
|
|
3294
|
+
closed: closeRetiredSharedClientEntry(entry)
|
|
2930
3295
|
};
|
|
2931
3296
|
}
|
|
2932
3297
|
const closed = closeRetiredSharedClientEntryIfIdle(entry);
|
|
@@ -2935,18 +3300,17 @@ function retireSharedCodexAppServerClientIfCurrent(client, opts) {
|
|
|
2935
3300
|
closed
|
|
2936
3301
|
};
|
|
2937
3302
|
}
|
|
2938
|
-
const
|
|
2939
|
-
if (
|
|
2940
|
-
if (opts?.failActiveLeases && !
|
|
2941
|
-
|
|
2942
|
-
client.close();
|
|
3303
|
+
const detachedEntry = state.entriesByClient.get(client);
|
|
3304
|
+
if (detachedEntry && (detachedEntry.client === client || detachedEntry.closeError)) {
|
|
3305
|
+
if (opts?.failActiveLeases && !detachedEntry.closeError) {
|
|
3306
|
+
detachedEntry.closeError = /* @__PURE__ */ new Error("codex app-server client is closed");
|
|
2943
3307
|
return {
|
|
2944
|
-
activeLeases,
|
|
2945
|
-
closed:
|
|
3308
|
+
activeLeases: detachedEntry.activeLeases,
|
|
3309
|
+
closed: closeRetiredSharedClientEntry(detachedEntry)
|
|
2946
3310
|
};
|
|
2947
3311
|
}
|
|
2948
3312
|
return {
|
|
2949
|
-
activeLeases,
|
|
3313
|
+
activeLeases: detachedEntry.activeLeases,
|
|
2950
3314
|
closed: false
|
|
2951
3315
|
};
|
|
2952
3316
|
}
|
|
@@ -3063,7 +3427,7 @@ function retirePendingSharedClientEntryIfUnclaimed(key, entry) {
|
|
|
3063
3427
|
closeRetiredSharedClientEntry(entry);
|
|
3064
3428
|
}
|
|
3065
3429
|
function collectSharedClients(state) {
|
|
3066
|
-
return [...
|
|
3430
|
+
return [...state.liveClients];
|
|
3067
3431
|
}
|
|
3068
3432
|
//#endregion
|
|
3069
|
-
export {
|
|
3433
|
+
export { resolveCodexAppServerAuthProfileId as $, isCodexAppServerApprovalRequest as A, claimCodexAppServerLiveThread as B, resolveCodexPostToolRawAssistantCompletionIdleTimeoutMs as C, resolveCodexTurnTerminalIdleTimeoutMs as D, resolveCodexTurnCompletionIdleTimeoutMs as E, isCodexAppServerPrewriteRequestCancellationError as F, protectCodexAppServerLiveThread as G, ensureCodexAppServerClientRuntime as H, isCodexAppServerRequestTimeoutError as I, unsubscribeCodexAppServerLiveThread as J, releaseCodexAppServerLiveThread as K, isUnsupportedCodexAppServerVersionError as L, isCodexAppServerConnectionClosedError as M, isCodexAppServerIndeterminateRequestCancellationError as N, withCodexStartupTimeout as O, isCodexAppServerIndeterminateTransportError as P, resolveCodexAppServerAuthAccountCacheKey as Q, resolveCodexAppServerClientInstanceId as R, resolveCodexGatewayTimeoutWithGraceMs as S, resolveCodexTurnAssistantCompletionIdleTimeoutMs as T, isCodexAppServerClientRuntimeLive as U, consumeCodexAppServerLiveThread as V, isCodexAppServerLiveThreadClaimed as W, readRecentCodexRateLimits as X, readCodexRateLimitsRevision as Y, rememberCodexRateLimitsRead as Z, withTimeout$1 as _, getLeasedSharedCodexAppServerClient as a, CODEX_INTERACTIVE_THREAD_SOURCE_KINDS as at, CodexAppServerStartupError as b, releaseCodexAppServerClientLease as c, isJsonObject as ct, retainSharedCodexAppServerClientByInstanceId as d, resolveCodexAppServerLocalHomeDir as dt, resolveCodexAppServerAuthProfileIdForAgent as et, retainSharedCodexAppServerClientIfCurrent as f, withAbortableTimeout as g, withLeasedCodexAppServerClientStartSelectionRetry as h, createIsolatedCodexAppServerClient as i, CODEX_INTERACTIVE_CUSTOM_THREAD_SOURCES as it, isCodexAppServerBrokenPipeError as j, getCodexAppServerClientInstanceId as k, releaseLeasedSharedCodexAppServerClient as l, resolveFirstExistingMacOSDesktopCodexBundledMarketplacePath as lt, shared_client_exports as m, clearSharedCodexAppServerClientIfCurrentAndUnclaimed as n, resolveCodexAppServerPreparedApiKeyCacheKey as nt, getSharedCodexAppServerClient as o, CODEX_OPENCLAW_DIRECT_DYNAMIC_TOOL_NAMESPACE as ot, retireSharedCodexAppServerClientIfCurrent as p, retainCodexAppServerLiveThread as q, clearSharedCodexAppServerClientIfCurrentAndWait as r, resolveCodexAppServerPreparedAuthHandoff as rt, isCodexAppServerStartSelectionChangedError as s, flattenCodexDynamicToolFunctions as st, clearSharedCodexAppServerClientIfCurrent as t, resolveCodexAppServerFallbackApiKeyCacheKey as tt, resolveCodexNativeConfigFenceKey as u, resolveCodexAppServerHomeDir as ut, acquireCodexNativeConfigFence as v, resolveCodexStartupTimeoutMs as w, isCodexAppServerStartupError as x, CODEX_POST_REASONING_REPLY_IDLE_TIMEOUT_MS as y, CodexAppServerRpcError as z };
|