@openclaw/codex 2026.9.1-beta.1 → 2026.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api.js +5 -6
- package/dist/{attempt-client-cleanup-bfsmcQ6m.js → attempt-client-cleanup-DYHcRQAa.js} +31 -45
- package/dist/attempt-context-DmQUNWwT.js +634 -0
- package/dist/{auth-binding-B4FfbcCg.js → auth-binding-Ds_QVm-X.js} +18 -3
- package/dist/{binding-connection-BMvPX73o.js → binding-connection-E6uDsPlx.js} +2 -2
- package/dist/{bounded-turn-B7iBUcuP.js → bounded-turn-wzJrwKKe.js} +15 -20
- package/dist/{capabilities-BRMh0aIq.js → capabilities-dIjNVCYH.js} +1 -1
- package/dist/cli-metadata.js +1 -1
- package/dist/{command-formatters-DEsIufkt.js → command-formatters-CLHhEB1Q.js} +5 -4
- package/dist/{command-handlers-D_-1_qRp.js → command-handlers-CTGb2csu.js} +124 -101
- package/dist/{compact-BglNFZrQ.js → compact-_t0HQrUS.js} +38 -29
- package/dist/{config-giW8X0QA.js → config-BhmfC1s6.js} +294 -282
- package/dist/{context-compaction-activity-BOeJf7yo.js → context-compaction-activity-CMla5FPJ.js} +4 -1
- package/dist/{conversation-binding-data-CW2GuupV.js → conversation-binding-data-BiodpIzq.js} +2 -1
- package/dist/doctor-contract-api.js +143 -12
- package/dist/{dynamic-tools-Dnlfa--w.js → dynamic-tools-BU9tmlYm.js} +599 -655
- package/dist/{effective-mcp-catalog-CTeGrnfO.js → effective-mcp-catalog-DzYBW4h1.js} +2 -2
- package/dist/{event-projector-assistant-message-C5-Ds8mA.js → event-projector-assistant-message-DHRFXKbS.js} +4 -4
- package/dist/{event-projector-usage-Bk1I90Bg.js → event-projector-usage-C5mcrGjp.js} +15 -148
- package/dist/{harness-Csz0F-DK.js → harness-DXVZ5II5.js} +42 -52
- package/dist/harness.js +1 -1
- package/dist/index.js +458 -404
- package/dist/{isolated-completion-Cv6FqygM.js → isolated-completion-kg9kv4iH.js} +4 -4
- package/dist/launch-args-RXQwn8zV.js +90 -0
- package/dist/{managed-binary-DFYK4DWq.js → managed-binary-4-Vjz5GH.js} +14 -9
- package/dist/media-understanding-provider.js +1 -1
- package/dist/model-catalog-CUM68Hkl.js +101 -0
- package/dist/{models-TS3HBU-q.js → models-sYnEc0gd.js} +25 -28
- package/dist/{native-subagent-monitor-4Mfq2HDs.js → native-subagent-monitor-CnH147jH.js} +55 -115
- package/dist/{node-exec-server.runtime-BpWqJO1V.js → node-exec-server.runtime-CstNHCmC.js} +9 -6
- package/dist/{plugin-approval-roundtrip-bUm777tR.js → plugin-approval-roundtrip-CNe-Xrjx.js} +30 -3
- package/dist/{plugin-marketplace-discovery-B9DvaAG-.js → plugin-marketplace-discovery-CfFlKqDl.js} +15 -14
- package/dist/{plugin-metadata-cache-CTCT3w5L.js → plugin-metadata-cache-BFrPhb2c.js} +6 -6
- package/dist/provider-capabilities-DW5p4k9w.js +101 -0
- package/dist/{rate-limits-C5_D8Gmb.js → rate-limits-CawQJfUS.js} +3 -2
- package/dist/{sandbox-guard-kuWTn9C5.js → request-DYAI5FQE.js} +195 -2
- package/dist/{run-attempt-DYc0QCBF.js → run-attempt-D1hJO4fX.js} +828 -2100
- package/dist/{runtime-artifact-BvyT1uyd.js → runtime-artifact-C3jVimFn.js} +21 -14
- package/dist/{session-binding-Bcynfd-_.js → session-binding-BHuTCRZQ.js} +198 -127
- package/dist/{session-catalog-DaLKVtpH.js → session-catalog-yyvTWFOw.js} +564 -408
- package/dist/{session-cli-DMc4oS2w.js → session-cli-CmFEXMAM.js} +1 -1
- package/dist/session-history-C5J1AKzG.js +87 -0
- package/dist/session-initialization-BeWzjGiR.js +74 -0
- package/dist/{session-permission-policy-BrNH1bjy.js → session-permission-policy-DeWVTCMj.js} +2 -2
- package/dist/session-retirement-BujDjXVF.js +97 -0
- package/dist/{session-upstream-marker-BIkusb95.js → session-upstream-marker-C351-5Qw.js} +19 -4
- package/dist/settled-turn-context-D3SNWtUn.js +268 -0
- package/dist/settled-turn-finalizer-BVJx4yoc.js +104 -0
- package/dist/{shared-client-DKz23hHY.js → shared-client-DxcfF9KX.js} +3480 -679
- package/dist/{side-question-DjA_jsNe.js → side-question-BTZAII4l.js} +108 -70
- package/dist/{thread-lifecycle-L7oEkTlq.js → thread-lifecycle-DAcEJ_Om.js} +2188 -1915
- package/dist/{thread-ownership-DZeuKH1j.js → thread-ownership-zGokd8i1.js} +25 -14
- package/dist/thread-policy-g4KbJPzp.js +54 -0
- package/dist/{plugin-app-cache-key-C1CAdfcP.js → thread-resume-C7pyVKeW.js} +59 -7
- package/dist/{transcript-mirror-DsCMWBca.js → transcript-mirror-DTUxFWa_.js} +79 -17
- package/dist/transport-stdio-CyPldczm.js +726 -0
- package/dist/{upstream-prompt-provenance-CFmsKwr9.js → upstream-prompt-provenance-LphB8slG.js} +8 -4
- package/dist/upstream-session-fork-CYlBIGVt.js +966 -0
- package/dist/{usage-ROIaW3wo.js → usage-Bj-rrzkR.js} +3 -3
- package/dist/{web-search-provider.runtime-ClaNPV7N.js → web-search-provider.runtime-D2FWSK4w.js} +3 -3
- package/openclaw.plugin.json +1 -30
- package/package.json +6 -6
- package/dist/command-rpc-CCeCkf_v.js +0 -90
- package/dist/incognito-session-ET_ufDH-.js +0 -2
- package/dist/model-catalog-i9rNBthX.js +0 -48
- package/dist/protocol-validators-VeJxxJ0U.js +0 -2421
- package/dist/request-DXXGHko0.js +0 -157
- package/dist/session-catalog-home-id-BNwAJ9D7.js +0 -18
- package/dist/session-retirement-CcNC3YSY.js +0 -36
- package/dist/settled-turn-finalizer-Dc3ApjU4.js +0 -328
- package/dist/thread-resume-BE9qNEW0.js +0 -30
- package/dist/transport-stdio-DhoGy33Z.js +0 -99
- package/dist/upstream-session-fork-DlaHxSLC.js +0 -326
|
@@ -1,58 +1,142 @@
|
|
|
1
1
|
import { t as __exportAll } from "./rolldown-runtime-8H4AJuhK.js";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { o as
|
|
5
|
-
import {
|
|
2
|
+
import { t as isCodexAppServerProxyLaunch } from "./launch-args-RXQwn8zV.js";
|
|
3
|
+
import { F as resolveCodexAppServerHomeDir, I as resolveCodexAppServerLocalHomeDir, L as resolveCodexAppServerUserHomeDir, R as withEphemeralCodexAuthStore, a as resolveCodexAppServerStartOptionsForAgent, i as resolveCodexAppServerRuntimeOptions, o as resolveCodexComputerUseConfig, t as codexAppServerStartOptionsKey } from "./config-BhmfC1s6.js";
|
|
4
|
+
import { c as resolveFirstExistingMacOSDesktopCodexBundledMarketplacePath, d as resolveMacOSDesktopCodexComputerUseServiceAppCandidates, l as resolveMacOSDesktopCodexAppPathCandidates, n as resolveManagedCodexAppServerStartOptions, o as CODEX_APP_SERVER_VERSION, r as resolveManagedCodexNativeCommand, s as MIN_SUPPORTED_CODEX_APP_SERVER_VERSION, t as isManagedCodexDesktopCommand, u as resolveMacOSDesktopCodexBundledMarketplaceCandidates } from "./managed-binary-4-Vjz5GH.js";
|
|
5
|
+
import { o as isCodexAppServerNativeAuthProfile } from "./session-binding-BHuTCRZQ.js";
|
|
6
|
+
import { a as hasCodexAppServerNaturalExit, i as closeCodexAppServerTransportAndWait, n as resolveCodexAppServerSpawnEnv, r as closeCodexAppServerTransport, t as createStdioTransport } from "./transport-stdio-CyPldczm.js";
|
|
6
7
|
import { isRecord, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
7
8
|
import fs from "node:fs/promises";
|
|
8
9
|
import path from "node:path";
|
|
9
10
|
import { createDeferred } from "openclaw/plugin-sdk/extension-shared";
|
|
10
|
-
import { addTimerTimeoutGraceMs, resolveTimerTimeoutMs } from "openclaw/plugin-sdk/number-runtime";
|
|
11
|
-
import { AgentHarnessPreflightError, OPENCLAW_VERSION, embeddedAgentLog, formatErrorMessage } from "openclaw/plugin-sdk/agent-harness-runtime";
|
|
11
|
+
import { addTimerTimeoutGraceMs, parseStrictNonNegativeInteger, resolveTimerTimeoutMs } from "openclaw/plugin-sdk/number-runtime";
|
|
12
|
+
import { AgentHarnessPreflightError, OPENCLAW_VERSION, embeddedAgentLog, formatErrorMessage, formatToolExecutionErrorMessage, normalizeQuestionTimeoutSeconds, resolveToolExecutionErrorKind } from "openclaw/plugin-sdk/agent-harness-runtime";
|
|
13
|
+
import { pruneMapToMaxSize } from "openclaw/plugin-sdk/collection-runtime";
|
|
14
|
+
import { createZstdDecompress } from "node:zlib";
|
|
15
|
+
import { root } from "openclaw/plugin-sdk/file-access-runtime";
|
|
12
16
|
import { createHash, randomUUID } from "node:crypto";
|
|
13
|
-
import fsSync, { constants, existsSync, watch } from "node:fs";
|
|
17
|
+
import fsSync, { constants as constants$1, existsSync, watch } from "node:fs";
|
|
14
18
|
import os from "node:os";
|
|
15
19
|
import { isDeepStrictEqual } from "node:util";
|
|
16
|
-
import { ensureAuthProfileStore, findPersistedAuthProfileCredential, loadAuthProfileStoreForSecretsRuntime, refreshOAuthCredentialForRuntime, resolveApiKeyForProfile,
|
|
17
|
-
import { hasUsableOAuthCredential, resolveOpenAICodexAuthIdentity } from "openclaw/plugin-sdk/provider-auth";
|
|
20
|
+
import { ensureAuthProfileStore, findPersistedAuthProfileCredential, loadAuthProfileStoreForSecretsRuntime, refreshOAuthCredentialForRuntime, resolveApiKeyForProfile, resolveDefaultAgentDir, resolvePersistedAuthProfileOwnerAgentDir, resolveProviderIdForAuth } from "openclaw/plugin-sdk/agent-runtime";
|
|
21
|
+
import { hasUsableOAuthCredential, resolveAuthProfileOrder, resolveOpenAICodexAuthIdentity } from "openclaw/plugin-sdk/provider-auth";
|
|
18
22
|
import { readSecretFile } from "openclaw/plugin-sdk/secret-file";
|
|
19
23
|
import { assertNoSymlinkParents, withTimeout } from "openclaw/plugin-sdk/security-runtime";
|
|
20
24
|
import { runExec } from "openclaw/plugin-sdk/process-runtime";
|
|
21
|
-
import {
|
|
25
|
+
import { EventEmitter } from "node:events";
|
|
22
26
|
import { createInterface } from "node:readline";
|
|
23
27
|
import { coerceErrorMessage, toStringifiedError } from "openclaw/plugin-sdk/error-runtime";
|
|
24
28
|
import { sliceUtf16Safe, truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
|
|
25
29
|
import { parse } from "semver";
|
|
26
|
-
import {
|
|
30
|
+
import { hasPendingInternalDiagnosticEvent } from "openclaw/plugin-sdk/diagnostic-runtime";
|
|
31
|
+
import { Compile } from "typebox/compile";
|
|
27
32
|
import net from "node:net";
|
|
28
33
|
import { PassThrough, Writable } from "node:stream";
|
|
29
34
|
import { StringDecoder } from "node:string_decoder";
|
|
30
35
|
import WebSocket from "ws";
|
|
31
|
-
//#region extensions/codex/src/app-server/
|
|
32
|
-
|
|
33
|
-
const
|
|
34
|
-
function
|
|
35
|
-
return
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
36
|
+
//#region extensions/codex/src/app-server/protocol.ts
|
|
37
|
+
/** Namespace Codex keeps directly model-visible without exposing it to Code Mode guests. */
|
|
38
|
+
const CODEX_OPENCLAW_DIRECT_DYNAMIC_TOOL_NAMESPACE = "openclaw_direct";
|
|
39
|
+
function flattenCodexDynamicToolFunctions(tools) {
|
|
40
|
+
return (tools ?? []).flatMap((tool) => tool.type === "namespace" ? tool.tools : [tool]);
|
|
41
|
+
}
|
|
42
|
+
const CODEX_INTERACTIVE_THREAD_SOURCE_KINDS = ["cli", "vscode"];
|
|
43
|
+
const CODEX_INTERACTIVE_CUSTOM_THREAD_SOURCES = ["atlas", "chatgpt"];
|
|
44
|
+
function isJsonObject(value) {
|
|
45
|
+
return isRecord(value);
|
|
46
|
+
}
|
|
47
|
+
function isRpcResponse(message) {
|
|
48
|
+
return "id" in message && !("method" in message);
|
|
49
|
+
}
|
|
50
|
+
//#endregion
|
|
51
|
+
//#region extensions/codex/src/session-catalog-provenance.ts
|
|
52
|
+
const MAX_SESSION_META_BYTES = 1048576;
|
|
53
|
+
const SESSION_META_READ_CHUNK_BYTES = 65536;
|
|
54
|
+
const MAX_PROVENANCE_CACHE_ENTRIES = 2e4;
|
|
55
|
+
const provenanceByPath = /* @__PURE__ */ new Map();
|
|
56
|
+
function cacheProvenance(key, value) {
|
|
57
|
+
provenanceByPath.delete(key);
|
|
58
|
+
provenanceByPath.set(key, value);
|
|
59
|
+
while (provenanceByPath.size > MAX_PROVENANCE_CACHE_ENTRIES) {
|
|
60
|
+
const oldest = provenanceByPath.keys().next().value;
|
|
61
|
+
if (oldest === void 0) break;
|
|
62
|
+
provenanceByPath.delete(oldest);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/** Undefined means the metadata line is not durable enough to cache yet. */
|
|
66
|
+
async function readCodexSessionMeta(sessionsRoot, rolloutPath, threadId) {
|
|
67
|
+
let safeRoot;
|
|
68
|
+
try {
|
|
69
|
+
safeRoot = await root(sessionsRoot, {
|
|
70
|
+
hardlinks: "reject",
|
|
71
|
+
maxBytes: Number.MAX_SAFE_INTEGER,
|
|
72
|
+
symlinks: "reject"
|
|
73
|
+
});
|
|
74
|
+
} catch {
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
const candidates = rolloutPath.endsWith(".zst") ? [rolloutPath, rolloutPath.slice(0, -4)] : [rolloutPath, `${rolloutPath}.zst`];
|
|
78
|
+
for (const candidate of candidates) {
|
|
79
|
+
let opened;
|
|
80
|
+
try {
|
|
81
|
+
opened = await safeRoot.open(path.relative(sessionsRoot, candidate));
|
|
82
|
+
} catch {
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
const input = opened.handle.createReadStream({
|
|
86
|
+
autoClose: false,
|
|
87
|
+
highWaterMark: SESSION_META_READ_CHUNK_BYTES
|
|
88
|
+
});
|
|
89
|
+
const reader = candidate.endsWith(".zst") ? input.pipe(createZstdDecompress()) : input;
|
|
90
|
+
try {
|
|
91
|
+
const chunks = [];
|
|
92
|
+
let bytesReadTotal = 0;
|
|
93
|
+
let line;
|
|
94
|
+
for await (const value of reader) {
|
|
95
|
+
const chunk = Buffer.isBuffer(value) ? value : Buffer.from(value);
|
|
96
|
+
const remaining = MAX_SESSION_META_BYTES - bytesReadTotal;
|
|
97
|
+
if (remaining <= 0) break;
|
|
98
|
+
const bounded = chunk.subarray(0, remaining);
|
|
99
|
+
bytesReadTotal += bounded.length;
|
|
100
|
+
const newline = bounded.indexOf(10);
|
|
101
|
+
chunks.push(newline >= 0 ? bounded.subarray(0, newline) : bounded);
|
|
102
|
+
if (newline >= 0) {
|
|
103
|
+
line = Buffer.concat(chunks).toString("utf8");
|
|
104
|
+
break;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
if (!line) continue;
|
|
108
|
+
let parsed;
|
|
109
|
+
try {
|
|
110
|
+
parsed = JSON.parse(line);
|
|
111
|
+
} catch {
|
|
112
|
+
continue;
|
|
113
|
+
}
|
|
114
|
+
if (!isJsonObject(parsed) || parsed.type !== "session_meta" || !isJsonObject(parsed.payload)) return null;
|
|
115
|
+
const payload = parsed.payload;
|
|
116
|
+
return payload.id === threadId ? payload : null;
|
|
117
|
+
} catch {
|
|
118
|
+
continue;
|
|
119
|
+
} finally {
|
|
120
|
+
reader.destroy();
|
|
121
|
+
input.destroy();
|
|
122
|
+
await opened.handle.close().catch(() => void 0);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Codex 0.147 reports OpenClaw app-server rollouts as `vscode`, so the rollout's
|
|
128
|
+
* immutable session metadata is the authoritative historical provenance.
|
|
129
|
+
*/
|
|
130
|
+
async function isOpenClawManagedCodexThread(thread, localSessionsRoot) {
|
|
131
|
+
const rolloutPath = typeof thread.path === "string" ? thread.path.trim() : "";
|
|
132
|
+
if (!localSessionsRoot || !rolloutPath) return false;
|
|
133
|
+
const cacheKey = `${localSessionsRoot}\0${rolloutPath}`;
|
|
134
|
+
const cached = provenanceByPath.get(cacheKey);
|
|
135
|
+
if (cached !== void 0) return cached;
|
|
136
|
+
const metadata = await readCodexSessionMeta(localSessionsRoot, rolloutPath, thread.id);
|
|
137
|
+
const managed = metadata === void 0 ? void 0 : metadata?.originator === "openclaw";
|
|
138
|
+
if (managed !== void 0) cacheProvenance(cacheKey, managed);
|
|
139
|
+
return managed ?? false;
|
|
56
140
|
}
|
|
57
141
|
//#endregion
|
|
58
142
|
//#region extensions/codex/src/app-server/computer-use-service-path.ts
|
|
@@ -713,7 +797,7 @@ function identitiesMatch(left, right) {
|
|
|
713
797
|
}
|
|
714
798
|
async function hasExecutableClient(appPath) {
|
|
715
799
|
try {
|
|
716
|
-
await fs.access(path.join(appPath, CLIENT_RELATIVE_PATH), constants.X_OK);
|
|
800
|
+
await fs.access(path.join(appPath, CLIENT_RELATIVE_PATH), constants$1.X_OK);
|
|
717
801
|
return true;
|
|
718
802
|
} catch {
|
|
719
803
|
return false;
|
|
@@ -814,21 +898,6 @@ async function copyServiceAppWithDitto(sourcePath, targetPath) {
|
|
|
814
898
|
});
|
|
815
899
|
}
|
|
816
900
|
//#endregion
|
|
817
|
-
//#region extensions/codex/src/app-server/protocol.ts
|
|
818
|
-
/** Namespace Codex keeps directly model-visible without exposing it to Code Mode guests. */
|
|
819
|
-
const CODEX_OPENCLAW_DIRECT_DYNAMIC_TOOL_NAMESPACE = "openclaw_direct";
|
|
820
|
-
function flattenCodexDynamicToolFunctions(tools) {
|
|
821
|
-
return (tools ?? []).flatMap((tool) => tool.type === "namespace" ? tool.tools : [tool]);
|
|
822
|
-
}
|
|
823
|
-
const CODEX_INTERACTIVE_THREAD_SOURCE_KINDS = ["cli", "vscode"];
|
|
824
|
-
const CODEX_INTERACTIVE_CUSTOM_THREAD_SOURCES = ["atlas", "chatgpt"];
|
|
825
|
-
function isJsonObject(value) {
|
|
826
|
-
return isRecord(value);
|
|
827
|
-
}
|
|
828
|
-
function isRpcResponse(message) {
|
|
829
|
-
return "id" in message && !("method" in message);
|
|
830
|
-
}
|
|
831
|
-
//#endregion
|
|
832
901
|
//#region extensions/codex/src/app-server/auth-bridge.ts
|
|
833
902
|
const CODEX_APP_SERVER_AUTH_PROVIDER = "openai";
|
|
834
903
|
const CODEX_APP_SERVER_EXTERNAL_CLI_PROVIDER_IDS = [CODEX_APP_SERVER_AUTH_PROVIDER];
|
|
@@ -879,8 +948,7 @@ function assertNoUnimportedAgentCodexAuthFile(params) {
|
|
|
879
948
|
if (message) throw new AgentHarnessPreflightError(message);
|
|
880
949
|
}
|
|
881
950
|
function resolveUnimportedAgentCodexAuthMessage(params) {
|
|
882
|
-
|
|
883
|
-
if (params.startOptions.transport !== "stdio" || !managedCodexCli || params.startOptions.homeScope === "user") return;
|
|
951
|
+
if (params.startOptions.transport !== "stdio" || params.startOptions.homeScope === "user") return;
|
|
884
952
|
const codexHome = resolveCodexAppServerHomeDir(params.agentDir);
|
|
885
953
|
const authPath = path.join(codexHome, CODEX_AUTH_JSON_FILENAME);
|
|
886
954
|
if (!fsSync.existsSync(authPath)) return;
|
|
@@ -1238,36 +1306,21 @@ function withoutClearedCodexHomeEnv(clearEnv) {
|
|
|
1238
1306
|
return filtered.length === clearEnv.length ? clearEnv : filtered;
|
|
1239
1307
|
}
|
|
1240
1308
|
async function applyCodexAppServerAuthProfile(params) {
|
|
1241
|
-
if (params.preparedAuth
|
|
1242
|
-
await params.client.request("account/login/start", params.preparedAuth.snapshot.loginParams);
|
|
1243
|
-
return;
|
|
1244
|
-
}
|
|
1245
|
-
if (params.preparedAuth?.kind === "api-key") {
|
|
1246
|
-
await params.client.request("account/login/start", {
|
|
1247
|
-
type: "apiKey",
|
|
1248
|
-
apiKey: params.preparedAuth.apiKey
|
|
1249
|
-
});
|
|
1250
|
-
return;
|
|
1251
|
-
}
|
|
1252
|
-
if (params.authProfileId === null) {
|
|
1309
|
+
if (!params.preparedAuth && params.authProfileId === null) {
|
|
1253
1310
|
await assertNativeCodexAccountMatchesRoute(params.client, params.authRequirement);
|
|
1254
1311
|
return;
|
|
1255
1312
|
}
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
}
|
|
1265
|
-
|
|
1266
|
-
throw error;
|
|
1267
|
-
}
|
|
1268
|
-
if (params.authRequirement === "subscription" && loginParams?.type !== "chatgptAuthTokens") throw createCodexAppServerAuthError("Codex subscription auth profile could not produce login credentials.");
|
|
1313
|
+
const loginParams = params.preparedAuth?.kind === "profile" ? params.preparedAuth.snapshot.loginParams : params.preparedAuth?.kind === "api-key" ? {
|
|
1314
|
+
type: "apiKey",
|
|
1315
|
+
apiKey: params.preparedAuth.apiKey
|
|
1316
|
+
} : await resolveCodexAppServerAuthProfileLoginParams({
|
|
1317
|
+
agentDir: params.agentDir,
|
|
1318
|
+
authProfileId: params.authProfileId ?? void 0,
|
|
1319
|
+
authProfileStore: params.authProfileStore,
|
|
1320
|
+
config: params.config
|
|
1321
|
+
});
|
|
1322
|
+
if (params.authRequirement === "subscription" && loginParams?.type !== "chatgptAuthTokens") throw createCodexAppServerAuthError("Codex subscription auth profile could not produce login credentials. Sign in with `openclaw models auth login --provider openai`, select that profile, then retry.");
|
|
1269
1323
|
if (!loginParams) {
|
|
1270
|
-
if (params.authRequirement === "subscription") throw createCodexAppServerAuthError("Codex subscription auth profile could not produce login credentials.");
|
|
1271
1324
|
if (params.authRequirement !== "api-key" || params.startOptions?.transport !== "stdio") return;
|
|
1272
1325
|
const env = resolveCodexAppServerSpawnEnv(params.startOptions, process.env);
|
|
1273
1326
|
const fallbackLoginParams = await resolveCodexAppServerFallbackApiKeyLoginParams({
|
|
@@ -1292,7 +1345,7 @@ async function assertNativeCodexAccountMatchesRoute(client, authRequirement) {
|
|
|
1292
1345
|
const response = await client.request("account/read", { refreshToken: false });
|
|
1293
1346
|
const accountType = isJsonObject(response.account) ? response.account.type : void 0;
|
|
1294
1347
|
if (authRequirement === "subscription") {
|
|
1295
|
-
if (accountType !== "chatgpt") throw createCodexAppServerAuthError("Codex subscription auth
|
|
1348
|
+
if (accountType !== "chatgpt") throw createCodexAppServerAuthError("Codex subscription route requires ChatGPT auth in the native Codex home. Run `codex login` for that home, or use appServer.homeScope=\"agent\" with an OpenClaw OAuth profile, then retry.");
|
|
1296
1349
|
return;
|
|
1297
1350
|
}
|
|
1298
1351
|
if (accountType === "chatgpt") throw createCodexAppServerAuthError("Codex Platform route requires an API-key account, but the native Codex home is signed in with a ChatGPT subscription. Sign that home in with `codex login --with-api-key`, or set appServer.homeScope=\"agent\" so OpenClaw can inject its own key.");
|
|
@@ -1301,7 +1354,13 @@ function createCodexAppServerAuthError(message, cause) {
|
|
|
1301
1354
|
const error = cause === void 0 ? new Error(message) : new Error(message, { cause });
|
|
1302
1355
|
return Object.assign(error, { status: 401 });
|
|
1303
1356
|
}
|
|
1304
|
-
var CodexAppServerAuthProfileUnavailableError = class extends Error {
|
|
1357
|
+
var CodexAppServerAuthProfileUnavailableError = class extends Error {
|
|
1358
|
+
constructor(..._args) {
|
|
1359
|
+
super(..._args);
|
|
1360
|
+
this.status = 401;
|
|
1361
|
+
this.code = "selected_auth_profile_unavailable";
|
|
1362
|
+
}
|
|
1363
|
+
};
|
|
1305
1364
|
async function resolveCodexAppServerAuthProfileLoginParams(params) {
|
|
1306
1365
|
const store = resolveCodexAppServerAuthProfileStore(params);
|
|
1307
1366
|
const profileId = resolveCodexAppServerAuthProfileId({
|
|
@@ -1310,7 +1369,7 @@ async function resolveCodexAppServerAuthProfileLoginParams(params) {
|
|
|
1310
1369
|
config: params.config
|
|
1311
1370
|
});
|
|
1312
1371
|
const profile = profileId ? store.profiles[profileId] : void 0;
|
|
1313
|
-
if (profileId && !profile) throw new CodexAppServerAuthProfileUnavailableError(`Codex app-server auth profile "${profileId}" was not found.`);
|
|
1372
|
+
if (profileId && !profile) throw new CodexAppServerAuthProfileUnavailableError(`Codex app-server auth profile "${profileId}" was not found. Select an existing OpenAI profile or sign in again with OpenClaw, then retry.`);
|
|
1314
1373
|
if (profileId && profile && !isCodexAppServerAuthProfileCredential(profile)) throw new CodexAppServerAuthProfileUnavailableError(`Codex app-server auth profile "${profileId}" must use the canonical OpenAI auth provider; run "openclaw doctor --fix" to migrate legacy provider IDs.`);
|
|
1315
1374
|
return await resolveCodexAppServerAuthProfileLoginParamsInternal({
|
|
1316
1375
|
...params,
|
|
@@ -1328,14 +1387,14 @@ async function refreshCodexAppServerAuthTokens(params) {
|
|
|
1328
1387
|
});
|
|
1329
1388
|
const credential = profileId ? store.profiles[profileId] : void 0;
|
|
1330
1389
|
const selectedAccountId = credential ? resolveExplicitChatgptAccountId(credential) ?? (credential.type === "oauth" ? resolveOpenAICodexAuthIdentity({ access: credential.access }).accountId : void 0) : void 0;
|
|
1331
|
-
if (selectedAccountId && selectedAccountId !== previousAccountId) throw new Error("ChatGPT workspace changed before Codex token refresh.");
|
|
1390
|
+
if (selectedAccountId && selectedAccountId !== previousAccountId) throw new Error("ChatGPT workspace changed before Codex token refresh. Retry to start a client for the selected workspace.");
|
|
1332
1391
|
}
|
|
1333
1392
|
const loginParams = await resolveCodexAppServerAuthProfileLoginParamsInternal({
|
|
1334
1393
|
...params,
|
|
1335
1394
|
forceOAuthRefresh: true
|
|
1336
1395
|
});
|
|
1337
|
-
if (!loginParams || loginParams.type !== "chatgptAuthTokens") throw new Error("Codex app-server ChatGPT token refresh requires an OAuth auth profile.");
|
|
1338
|
-
if (previousAccountId && loginParams.chatgptAccountId !== previousAccountId) throw new Error("ChatGPT workspace changed during Codex token refresh.");
|
|
1396
|
+
if (!loginParams || loginParams.type !== "chatgptAuthTokens") throw new Error("Codex app-server ChatGPT token refresh requires an OAuth auth profile. Sign in with `openclaw models auth login --provider openai`, select that profile, then retry.");
|
|
1397
|
+
if (previousAccountId && loginParams.chatgptAccountId !== previousAccountId) throw new Error("ChatGPT workspace changed during Codex token refresh. Retry to start a client for the selected workspace.");
|
|
1339
1398
|
return {
|
|
1340
1399
|
accessToken: loginParams.accessToken,
|
|
1341
1400
|
chatgptAccountId: loginParams.chatgptAccountId,
|
|
@@ -1356,8 +1415,8 @@ async function resolveCodexAppServerAuthProfileLoginParamsInternal(params) {
|
|
|
1356
1415
|
});
|
|
1357
1416
|
if (!profileId) return;
|
|
1358
1417
|
const credential = store.profiles[profileId];
|
|
1359
|
-
if (!credential) throw new
|
|
1360
|
-
if (!isCodexAppServerAuthProfileCredential(credential)) throw new
|
|
1418
|
+
if (!credential) throw new CodexAppServerAuthProfileUnavailableError(`Codex app-server auth profile "${profileId}" was not found. Select an existing OpenAI profile or sign in again with OpenClaw, then retry.`);
|
|
1419
|
+
if (!isCodexAppServerAuthProfileCredential(credential)) throw new CodexAppServerAuthProfileUnavailableError(`Codex app-server auth profile "${profileId}" must use the canonical OpenAI auth provider; run "openclaw doctor --fix" to migrate legacy provider IDs.`);
|
|
1361
1420
|
const loginParams = await resolveLoginParamsForCredential(profileId, credential, {
|
|
1362
1421
|
agentDir: params.agentDir,
|
|
1363
1422
|
store,
|
|
@@ -1365,7 +1424,7 @@ async function resolveCodexAppServerAuthProfileLoginParamsInternal(params) {
|
|
|
1365
1424
|
forceOAuthRefresh: params.forceOAuthRefresh === true,
|
|
1366
1425
|
config: params.config
|
|
1367
1426
|
});
|
|
1368
|
-
if (!loginParams) throw new CodexAppServerAuthProfileUnavailableError(`Codex app-server auth profile "${profileId}" does not contain usable credentials.`);
|
|
1427
|
+
if (!loginParams) throw new CodexAppServerAuthProfileUnavailableError(`Codex app-server auth profile "${profileId}" does not contain usable credentials. Repair or replace the selected OpenAI credential, then retry.`);
|
|
1369
1428
|
return loginParams;
|
|
1370
1429
|
}
|
|
1371
1430
|
async function resolveCodexAppServerFallbackApiKeyLoginParams(params) {
|
|
@@ -1479,7 +1538,7 @@ async function resolveOAuthCredentialForCodexAppServer(profileId, credential, pa
|
|
|
1479
1538
|
});
|
|
1480
1539
|
if (params.forceRefresh && !persistedOAuthCredential && overlaidOAuthCredential) {
|
|
1481
1540
|
const refreshedRuntimeCredential = await refreshOAuthCredentialForRuntime({ credential: overlaidOAuthCredential });
|
|
1482
|
-
if (!refreshedRuntimeCredential?.access?.trim()) throw new Error(`Codex app-server auth profile "${profileId}" could not refresh.`);
|
|
1541
|
+
if (!refreshedRuntimeCredential?.access?.trim()) throw new Error(`Codex app-server auth profile "${profileId}" could not refresh. Sign in again with OpenClaw, then retry.`);
|
|
1483
1542
|
store.profiles[profileId] = refreshedRuntimeCredential;
|
|
1484
1543
|
return refreshedRuntimeCredential;
|
|
1485
1544
|
}
|
|
@@ -1507,8 +1566,8 @@ function shouldUseScopedOAuthCredential(params) {
|
|
|
1507
1566
|
return !isDeepStrictEqual(persisted, params.suppliedCredential) && !hasMatchingOAuthIdentity(persisted, params.suppliedCredential);
|
|
1508
1567
|
}
|
|
1509
1568
|
function hasMatchingOAuthIdentity(persisted, supplied) {
|
|
1510
|
-
const persistedAccountId = persisted.accountId?.trim();
|
|
1511
|
-
const suppliedAccountId = supplied.accountId?.trim();
|
|
1569
|
+
const persistedAccountId = resolveOpenAICodexAuthIdentity(persisted).accountId?.trim();
|
|
1570
|
+
const suppliedAccountId = resolveOpenAICodexAuthIdentity(supplied).accountId?.trim();
|
|
1512
1571
|
if (persistedAccountId && suppliedAccountId) return persistedAccountId === suppliedAccountId;
|
|
1513
1572
|
const persistedEmail = persisted.email?.trim().toLowerCase();
|
|
1514
1573
|
const suppliedEmail = supplied.email?.trim().toLowerCase();
|
|
@@ -1525,8 +1584,8 @@ async function resolveScopedOAuthCredential(params) {
|
|
|
1525
1584
|
const credential = current?.type === "oauth" ? current : params.credential;
|
|
1526
1585
|
if (!params.forceRefresh && hasUsableOAuthCredential(credential)) return credential;
|
|
1527
1586
|
const refreshed = await refreshOAuthCredentialForRuntime({ credential });
|
|
1528
|
-
if (!refreshed?.access?.trim()) throw new Error(`Codex app-server auth profile "${params.profileId}" could not refresh.`);
|
|
1529
|
-
if (!isDeepStrictEqual(params.store.profiles[params.profileId], credential)) throw new Error(`Codex app-server auth profile "${params.profileId}" changed while refreshing.`);
|
|
1587
|
+
if (!refreshed?.access?.trim()) throw new Error(`Codex app-server auth profile "${params.profileId}" could not refresh. Sign in again with OpenClaw, then retry.`);
|
|
1588
|
+
if (!isDeepStrictEqual(params.store.profiles[params.profileId], credential)) throw new Error(`Codex app-server auth profile "${params.profileId}" changed while refreshing. Retry with the newly selected OpenAI profile.`);
|
|
1530
1589
|
params.store.profiles[params.profileId] = refreshed;
|
|
1531
1590
|
return refreshed;
|
|
1532
1591
|
})();
|
|
@@ -1604,7 +1663,7 @@ function resolveExplicitChatgptAccountId(credential) {
|
|
|
1604
1663
|
}
|
|
1605
1664
|
//#endregion
|
|
1606
1665
|
//#region extensions/codex/src/app-server/rate-limit-cache.ts
|
|
1607
|
-
const DEFAULT_CODEX_RATE_LIMIT_CACHE_MAX_AGE_MS =
|
|
1666
|
+
const DEFAULT_CODEX_RATE_LIMIT_CACHE_MAX_AGE_MS = 6e5;
|
|
1608
1667
|
const SPARSE_ACCOUNT_METADATA_KEYS = [
|
|
1609
1668
|
"credits",
|
|
1610
1669
|
"individualLimit",
|
|
@@ -1736,7 +1795,7 @@ async function withAbortableTimeout(params) {
|
|
|
1736
1795
|
//#region extensions/codex/src/app-server/client-runtime.ts
|
|
1737
1796
|
/** Client-scoped Codex auth and account observers. */
|
|
1738
1797
|
/** Match Codex's native grace window without retaining inactive conversations indefinitely. */
|
|
1739
|
-
const CODEX_APP_SERVER_LIVE_THREAD_IDLE_TIMEOUT_MS =
|
|
1798
|
+
const CODEX_APP_SERVER_LIVE_THREAD_IDLE_TIMEOUT_MS = 18e5;
|
|
1740
1799
|
/** Native-child parents are active ownership, so only otherwise-idle threads count against this cap. */
|
|
1741
1800
|
const CODEX_APP_SERVER_LIVE_THREAD_MAX_IDLE = 64;
|
|
1742
1801
|
/** Return a deterministic error before Codex cancels its ten-second external-auth request. */
|
|
@@ -1749,6 +1808,32 @@ function isCodexAppServerClientRuntimeLive(client) {
|
|
|
1749
1808
|
const runtime = configuredClients.get(client);
|
|
1750
1809
|
return runtime !== void 0 && !runtime.closed;
|
|
1751
1810
|
}
|
|
1811
|
+
/** Immutable declarations are data owned by this physical client, never retained executors. */
|
|
1812
|
+
async function readCodexClientSessionMeta(client, sessionsRoot, boundRolloutPath, threadId) {
|
|
1813
|
+
let rolloutPath = boundRolloutPath;
|
|
1814
|
+
const runtime = configuredClients.get(client);
|
|
1815
|
+
if (!runtime || runtime.closed) throw new Error("Codex native metadata requires a live selected client");
|
|
1816
|
+
const cached = runtime.sessionMetadata.get(threadId);
|
|
1817
|
+
if (cached && cached.sessionsRoot === sessionsRoot && (!rolloutPath || cached.rolloutPath === rolloutPath)) return structuredClone(cached.metadata);
|
|
1818
|
+
if (!rolloutPath) {
|
|
1819
|
+
const { thread } = await client.request("thread/read", {
|
|
1820
|
+
threadId,
|
|
1821
|
+
includeTurns: false
|
|
1822
|
+
});
|
|
1823
|
+
if (thread.id !== threadId || !thread.path) throw new Error("Codex native metadata has no verified thread path");
|
|
1824
|
+
rolloutPath = thread.path;
|
|
1825
|
+
}
|
|
1826
|
+
const metadata = await readCodexSessionMeta(sessionsRoot, rolloutPath, threadId);
|
|
1827
|
+
if (runtime.closed || !metadata) throw new Error("Codex native metadata is unavailable on the selected client");
|
|
1828
|
+
runtime.sessionMetadata.delete(threadId);
|
|
1829
|
+
runtime.sessionMetadata.set(threadId, {
|
|
1830
|
+
sessionsRoot,
|
|
1831
|
+
rolloutPath,
|
|
1832
|
+
metadata
|
|
1833
|
+
});
|
|
1834
|
+
pruneMapToMaxSize(runtime.sessionMetadata, CODEX_APP_SERVER_LIVE_THREAD_MAX_IDLE);
|
|
1835
|
+
return structuredClone(metadata);
|
|
1836
|
+
}
|
|
1752
1837
|
/** Installs one auth-refresh handler and one rate-limit observer per physical client. */
|
|
1753
1838
|
function ensureCodexAppServerClientRuntime(client, context) {
|
|
1754
1839
|
const existing = configuredClients.get(client);
|
|
@@ -1766,7 +1851,8 @@ function ensureCodexAppServerClientRuntime(client, context) {
|
|
|
1766
1851
|
retainedThreads: /* @__PURE__ */ new Map(),
|
|
1767
1852
|
claimedThreads: /* @__PURE__ */ new Map(),
|
|
1768
1853
|
releasingThreads: /* @__PURE__ */ new Map(),
|
|
1769
|
-
protectedThreads: /* @__PURE__ */ new Map()
|
|
1854
|
+
protectedThreads: /* @__PURE__ */ new Map(),
|
|
1855
|
+
sessionMetadata: /* @__PURE__ */ new Map()
|
|
1770
1856
|
};
|
|
1771
1857
|
configuredClients.set(client, runtime);
|
|
1772
1858
|
client.addCloseHandler(() => {
|
|
@@ -1778,20 +1864,26 @@ function ensureCodexAppServerClientRuntime(client, context) {
|
|
|
1778
1864
|
runtime.retainedThreads.clear();
|
|
1779
1865
|
runtime.claimedThreads.clear();
|
|
1780
1866
|
runtime.protectedThreads.clear();
|
|
1867
|
+
runtime.sessionMetadata.clear();
|
|
1781
1868
|
});
|
|
1782
1869
|
client.addRequestHandler(async (request) => {
|
|
1783
1870
|
if (request.method !== "account/chatgptAuthTokens/refresh") return;
|
|
1784
1871
|
if (runtime.context.authMode === "prepared-api-key") throw new Error("ChatGPT token refresh is unavailable for prepared Codex API-key auth.");
|
|
1785
1872
|
const previousAccountId = isJsonObject(request.params) && typeof request.params.previousAccountId === "string" ? request.params.previousAccountId.trim() || void 0 : void 0;
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1873
|
+
try {
|
|
1874
|
+
const tokens = await withTimeout$1(refreshCodexAppServerAuthTokens({
|
|
1875
|
+
agentDir: runtime.context.agentDir,
|
|
1876
|
+
authProfileId: runtime.context.authProfileId,
|
|
1877
|
+
...previousAccountId ? { previousAccountId } : {},
|
|
1878
|
+
...runtime.context.authProfileStore ? { authProfileStore: runtime.context.authProfileStore } : {},
|
|
1879
|
+
config: runtime.context.config
|
|
1880
|
+
}), CODEX_EXTERNAL_AUTH_REFRESH_TIMEOUT_MS, "Codex app-server ChatGPT token refresh timed out before its external-auth deadline. Retry the request; if it persists, sign in again with OpenClaw.");
|
|
1881
|
+
if (previousAccountId && tokens.chatgptAccountId !== previousAccountId) throw new Error("ChatGPT workspace changed during Codex token refresh. Retry to start a client for the selected workspace.");
|
|
1882
|
+
return { ...tokens };
|
|
1883
|
+
} catch (error) {
|
|
1884
|
+
runtime.context.onAuthRefreshFailure?.();
|
|
1885
|
+
throw error;
|
|
1886
|
+
}
|
|
1795
1887
|
});
|
|
1796
1888
|
client.addNotificationHandler((notification) => {
|
|
1797
1889
|
if (notification.method === "account/rateLimits/updated") {
|
|
@@ -1805,6 +1897,7 @@ function ensureCodexAppServerClientRuntime(client, context) {
|
|
|
1805
1897
|
if (releasing) releasing.invalidated = true;
|
|
1806
1898
|
runtime.retainedThreads.delete(threadId);
|
|
1807
1899
|
runtime.claimedThreads.delete(threadId);
|
|
1900
|
+
runtime.sessionMetadata.delete(threadId);
|
|
1808
1901
|
scheduleRetainedThreadEviction(client, runtime);
|
|
1809
1902
|
}
|
|
1810
1903
|
}
|
|
@@ -1827,10 +1920,11 @@ function scheduleRetainedThreadEviction(client, runtime) {
|
|
|
1827
1920
|
}, Math.max(0, expiresAt - Date.now()));
|
|
1828
1921
|
runtime.evictionTimer.unref?.();
|
|
1829
1922
|
}
|
|
1830
|
-
async function releaseRetainedThread(client, runtime, threadId) {
|
|
1923
|
+
async function releaseRetainedThread(client, runtime, threadId, assertCurrent) {
|
|
1831
1924
|
const pendingRelease = runtime.releasingThreads.get(threadId);
|
|
1832
1925
|
if (pendingRelease) {
|
|
1833
1926
|
await pendingRelease.completion;
|
|
1927
|
+
assertCurrent?.();
|
|
1834
1928
|
return false;
|
|
1835
1929
|
}
|
|
1836
1930
|
const retained = runtime.retainedThreads.get(threadId);
|
|
@@ -1842,14 +1936,17 @@ async function releaseRetainedThread(client, runtime, threadId) {
|
|
|
1842
1936
|
}
|
|
1843
1937
|
runtime.retainedThreads.delete(threadId);
|
|
1844
1938
|
scheduleRetainedThreadEviction(client, runtime);
|
|
1845
|
-
const transition = { completion: Promise.resolve().then(() =>
|
|
1939
|
+
const transition = { completion: Promise.resolve().then(() => {
|
|
1940
|
+
assertCurrent?.();
|
|
1941
|
+
return assertCurrent ? retained.release(threadId, assertCurrent) : retained.release(threadId);
|
|
1942
|
+
}) };
|
|
1846
1943
|
runtime.releasingThreads.set(threadId, transition);
|
|
1847
1944
|
try {
|
|
1848
1945
|
await transition.completion;
|
|
1849
1946
|
return true;
|
|
1850
1947
|
} catch (error) {
|
|
1851
1948
|
if (!runtime.closed && !transition.invalidated && runtime.releasingThreads.get(threadId) === transition && !runtime.retainedThreads.has(threadId) && !runtime.claimedThreads.has(threadId)) {
|
|
1852
|
-
retained.expiresAt = Date.now() + CODEX_APP_SERVER_LIVE_THREAD_IDLE_TIMEOUT_MS;
|
|
1949
|
+
if (retained.ephemeralPolicy === void 0) retained.expiresAt = Date.now() + CODEX_APP_SERVER_LIVE_THREAD_IDLE_TIMEOUT_MS;
|
|
1853
1950
|
const newerThreads = [...runtime.retainedThreads.entries()].filter(([candidateThreadId]) => !olderThreadIds.has(candidateThreadId));
|
|
1854
1951
|
for (const [candidateThreadId] of newerThreads) runtime.retainedThreads.delete(candidateThreadId);
|
|
1855
1952
|
runtime.retainedThreads.set(threadId, retained);
|
|
@@ -1867,14 +1964,15 @@ async function evictExpiredRetainedThreads(client, runtime) {
|
|
|
1867
1964
|
scheduleRetainedThreadEviction(client, runtime);
|
|
1868
1965
|
}
|
|
1869
1966
|
async function evictExcessIdleThreads(client, runtime) {
|
|
1870
|
-
|
|
1967
|
+
const idleThreads = () => [...runtime.retainedThreads].filter(([threadId, thread]) => thread.ephemeralPolicy === void 0 && !runtime.protectedThreads.has(threadId));
|
|
1968
|
+
let idleThreadIds = idleThreads();
|
|
1871
1969
|
while (idleThreadIds.length > CODEX_APP_SERVER_LIVE_THREAD_MAX_IDLE) {
|
|
1872
|
-
await releaseRetainedThread(client, runtime, idleThreadIds[0]);
|
|
1873
|
-
idleThreadIds =
|
|
1970
|
+
await releaseRetainedThread(client, runtime, idleThreadIds[0][0]);
|
|
1971
|
+
idleThreadIds = idleThreads();
|
|
1874
1972
|
}
|
|
1875
1973
|
}
|
|
1876
1974
|
/** Retain separately owned Codex subscriptions; completing B must never cold-restart A. */
|
|
1877
|
-
async function retainCodexAppServerLiveThread(client, threadId, releaseThread, configFingerprint, serviceTier) {
|
|
1975
|
+
async function retainCodexAppServerLiveThread(client, threadId, releaseThread, configFingerprint, serviceTier, ephemeralPolicy) {
|
|
1878
1976
|
const runtime = configuredClients.get(client);
|
|
1879
1977
|
if (!runtime || runtime.closed) return false;
|
|
1880
1978
|
const claimed = runtime.claimedThreads.get(threadId);
|
|
@@ -1882,15 +1980,16 @@ async function retainCodexAppServerLiveThread(client, threadId, releaseThread, c
|
|
|
1882
1980
|
const pendingRelease = runtime.releasingThreads.get(threadId);
|
|
1883
1981
|
if (pendingRelease) {
|
|
1884
1982
|
await pendingRelease.completion;
|
|
1885
|
-
|
|
1983
|
+
return false;
|
|
1886
1984
|
}
|
|
1887
1985
|
runtime.retainedThreads.delete(threadId);
|
|
1888
1986
|
const retained = {
|
|
1889
1987
|
configFingerprint,
|
|
1988
|
+
ephemeralPolicy,
|
|
1890
1989
|
serviceTier,
|
|
1891
|
-
expiresAt: Date.now() + CODEX_APP_SERVER_LIVE_THREAD_IDLE_TIMEOUT_MS,
|
|
1892
|
-
release: (releaseThread ? physicalThreadReleases.get(releaseThread) ?? releaseThread : void 0) ?? (async (releasedThreadId) => {
|
|
1893
|
-
await unsubscribeCodexAppServerLiveThread(client, releasedThreadId, 5e3);
|
|
1990
|
+
expiresAt: ephemeralPolicy === void 0 ? Date.now() + CODEX_APP_SERVER_LIVE_THREAD_IDLE_TIMEOUT_MS : Number.POSITIVE_INFINITY,
|
|
1991
|
+
release: (releaseThread ? physicalThreadReleases.get(releaseThread) ?? releaseThread : void 0) ?? (async (releasedThreadId, assertCurrent) => {
|
|
1992
|
+
await unsubscribeCodexAppServerLiveThread(client, releasedThreadId, 5e3, assertCurrent);
|
|
1894
1993
|
})
|
|
1895
1994
|
};
|
|
1896
1995
|
runtime.retainedThreads.set(threadId, retained);
|
|
@@ -1934,8 +2033,8 @@ async function claimCodexAppServerLiveThread(client, threadId) {
|
|
|
1934
2033
|
}
|
|
1935
2034
|
return claimCodexAppServerThreadOwnership(client, runtime, threadId, runtime.retainedThreads.get(threadId) ?? {
|
|
1936
2035
|
expiresAt: Date.now() + CODEX_APP_SERVER_LIVE_THREAD_IDLE_TIMEOUT_MS,
|
|
1937
|
-
release: async (releasedThreadId) => {
|
|
1938
|
-
await unsubscribeCodexAppServerLiveThread(client, releasedThreadId, 5e3);
|
|
2036
|
+
release: async (releasedThreadId, assertCurrent) => {
|
|
2037
|
+
await unsubscribeCodexAppServerLiveThread(client, releasedThreadId, 5e3, assertCurrent);
|
|
1939
2038
|
}
|
|
1940
2039
|
});
|
|
1941
2040
|
}
|
|
@@ -1944,16 +2043,26 @@ function claimCodexAppServerThreadOwnership(client, runtime, threadId, retained)
|
|
|
1944
2043
|
const claimed = Symbol(threadId);
|
|
1945
2044
|
runtime.claimedThreads.set(threadId, claimed);
|
|
1946
2045
|
scheduleRetainedThreadEviction(client, runtime);
|
|
1947
|
-
const
|
|
1948
|
-
if (
|
|
2046
|
+
const assertCurrent = () => {
|
|
2047
|
+
if (runtime.closed || runtime.claimedThreads.get(threadId) !== claimed) throw new Error(`Codex thread subscription ownership changed: ${threadId}`);
|
|
2048
|
+
};
|
|
2049
|
+
const release = async (releasedThreadId, assertReleaseCurrent) => {
|
|
2050
|
+
if (releasedThreadId !== threadId || runtime.claimedThreads.get(threadId) !== claimed) {
|
|
2051
|
+
assertReleaseCurrent?.();
|
|
2052
|
+
return;
|
|
2053
|
+
}
|
|
1949
2054
|
const pendingRelease = runtime.releasingThreads.get(threadId);
|
|
1950
2055
|
if (pendingRelease) {
|
|
1951
2056
|
await pendingRelease.completion;
|
|
1952
2057
|
return;
|
|
1953
2058
|
}
|
|
1954
2059
|
const transition = { completion: Promise.resolve().then(async () => {
|
|
1955
|
-
if (runtime.closed || runtime.claimedThreads.get(threadId) !== claimed)
|
|
1956
|
-
|
|
2060
|
+
if (runtime.closed || runtime.claimedThreads.get(threadId) !== claimed) {
|
|
2061
|
+
assertReleaseCurrent?.();
|
|
2062
|
+
return;
|
|
2063
|
+
}
|
|
2064
|
+
assertReleaseCurrent?.();
|
|
2065
|
+
await (assertReleaseCurrent ? retained.release(releasedThreadId, assertReleaseCurrent) : retained.release(releasedThreadId));
|
|
1957
2066
|
}) };
|
|
1958
2067
|
runtime.releasingThreads.set(threadId, transition);
|
|
1959
2068
|
try {
|
|
@@ -1962,95 +2071,3099 @@ function claimCodexAppServerThreadOwnership(client, runtime, threadId, retained)
|
|
|
1962
2071
|
} finally {
|
|
1963
2072
|
if (runtime.releasingThreads.get(threadId) === transition) runtime.releasingThreads.delete(threadId);
|
|
1964
2073
|
}
|
|
1965
|
-
};
|
|
1966
|
-
physicalThreadReleases.set(release, retained.release);
|
|
1967
|
-
claimedThreadReleaseTokens.set(release, claimed);
|
|
2074
|
+
};
|
|
2075
|
+
physicalThreadReleases.set(release, retained.release);
|
|
2076
|
+
claimedThreadReleaseTokens.set(release, claimed);
|
|
2077
|
+
return {
|
|
2078
|
+
assertCurrent,
|
|
2079
|
+
configFingerprint: retained.configFingerprint,
|
|
2080
|
+
ephemeralPolicy: retained.ephemeralPolicy,
|
|
2081
|
+
serviceTier: retained.serviceTier,
|
|
2082
|
+
release
|
|
2083
|
+
};
|
|
2084
|
+
}
|
|
2085
|
+
/** Distinguish active claimed ownership from an already-evicted idle subscription. */
|
|
2086
|
+
function hasCodexAppServerLiveThread(client, threadId) {
|
|
2087
|
+
const runtime = configuredClients.get(client);
|
|
2088
|
+
return runtime !== void 0 && !runtime.closed && (runtime.retainedThreads.has(threadId) || runtime.releasingThreads.has(threadId) || runtime.claimedThreads.has(threadId));
|
|
2089
|
+
}
|
|
2090
|
+
function isCodexAppServerLiveThreadClaimed(client, threadId) {
|
|
2091
|
+
const runtime = configuredClients.get(client);
|
|
2092
|
+
return runtime !== void 0 && !runtime.closed && runtime.claimedThreads.has(threadId);
|
|
2093
|
+
}
|
|
2094
|
+
/** Release the exact physical subscription and finish only its observed ownership generation. */
|
|
2095
|
+
async function unsubscribeCodexAppServerLiveThread(client, threadId, timeoutMs, assertCurrent) {
|
|
2096
|
+
const runtime = configuredClients.get(client);
|
|
2097
|
+
const claimed = runtime?.claimedThreads.get(threadId);
|
|
2098
|
+
const retained = runtime?.retainedThreads.get(threadId);
|
|
2099
|
+
let transition = runtime?.releasingThreads.get(threadId);
|
|
2100
|
+
if (transition?.physicalRelease) {
|
|
2101
|
+
await transition.physicalRelease;
|
|
2102
|
+
assertCurrent?.();
|
|
2103
|
+
return;
|
|
2104
|
+
}
|
|
2105
|
+
const physicalRelease = Promise.resolve().then(async () => {
|
|
2106
|
+
if (claimed !== void 0 && runtime?.claimedThreads.get(threadId) !== claimed || retained !== void 0 && runtime?.retainedThreads.get(threadId) !== retained) {
|
|
2107
|
+
assertCurrent?.();
|
|
2108
|
+
return;
|
|
2109
|
+
}
|
|
2110
|
+
assertCurrent?.();
|
|
2111
|
+
await client.request("thread/unsubscribe", { threadId }, {
|
|
2112
|
+
timeoutMs,
|
|
2113
|
+
assertCurrent
|
|
2114
|
+
});
|
|
2115
|
+
assertCurrent?.();
|
|
2116
|
+
});
|
|
2117
|
+
const ownsTransition = runtime !== void 0 && transition === void 0;
|
|
2118
|
+
if (transition) transition.physicalRelease = physicalRelease;
|
|
2119
|
+
else if (runtime) {
|
|
2120
|
+
transition = {
|
|
2121
|
+
completion: physicalRelease,
|
|
2122
|
+
physicalRelease
|
|
2123
|
+
};
|
|
2124
|
+
runtime.releasingThreads.set(threadId, transition);
|
|
2125
|
+
}
|
|
2126
|
+
try {
|
|
2127
|
+
await physicalRelease;
|
|
2128
|
+
if (retained !== void 0 && runtime?.retainedThreads.get(threadId) === retained) {
|
|
2129
|
+
runtime.retainedThreads.delete(threadId);
|
|
2130
|
+
scheduleRetainedThreadEviction(client, runtime);
|
|
2131
|
+
}
|
|
2132
|
+
if (claimed !== void 0 && runtime?.claimedThreads.get(threadId) === claimed) runtime.claimedThreads.delete(threadId);
|
|
2133
|
+
} finally {
|
|
2134
|
+
if (ownsTransition && runtime.releasingThreads.get(threadId) === transition) runtime.releasingThreads.delete(threadId);
|
|
2135
|
+
}
|
|
2136
|
+
}
|
|
2137
|
+
/** Reset/end owns the exact thread; failed generation retirement must never release its successor. */
|
|
2138
|
+
async function releaseCodexAppServerLiveThread(client, threadId, assertCurrent) {
|
|
2139
|
+
const runtime = configuredClients.get(client);
|
|
2140
|
+
return runtime ? await releaseRetainedThread(client, runtime, threadId, assertCurrent) : false;
|
|
2141
|
+
}
|
|
2142
|
+
/** Native child work pins its parent's subscription even after the foreground parent turn ends. */
|
|
2143
|
+
function protectCodexAppServerLiveThread(client, threadId) {
|
|
2144
|
+
const runtime = configuredClients.get(client);
|
|
2145
|
+
if (!runtime || runtime.closed) return () => void 0;
|
|
2146
|
+
runtime.protectedThreads.set(threadId, (runtime.protectedThreads.get(threadId) ?? 0) + 1);
|
|
2147
|
+
scheduleRetainedThreadEviction(client, runtime);
|
|
2148
|
+
let protectedThread = true;
|
|
2149
|
+
return () => {
|
|
2150
|
+
if (!protectedThread) return;
|
|
2151
|
+
protectedThread = false;
|
|
2152
|
+
if (runtime.closed) return;
|
|
2153
|
+
const count = runtime.protectedThreads.get(threadId) ?? 0;
|
|
2154
|
+
if (count <= 1) {
|
|
2155
|
+
runtime.protectedThreads.delete(threadId);
|
|
2156
|
+
const retained = runtime.retainedThreads.get(threadId);
|
|
2157
|
+
if (retained) {
|
|
2158
|
+
if (retained.ephemeralPolicy === void 0) retained.expiresAt = Date.now() + CODEX_APP_SERVER_LIVE_THREAD_IDLE_TIMEOUT_MS;
|
|
2159
|
+
runtime.retainedThreads.delete(threadId);
|
|
2160
|
+
runtime.retainedThreads.set(threadId, retained);
|
|
2161
|
+
}
|
|
2162
|
+
} else runtime.protectedThreads.set(threadId, count - 1);
|
|
2163
|
+
scheduleRetainedThreadEviction(client, runtime);
|
|
2164
|
+
evictExcessIdleThreads(client, runtime).catch((error) => {
|
|
2165
|
+
embeddedAgentLog.warn("codex retained thread unpin eviction failed", {
|
|
2166
|
+
threadId,
|
|
2167
|
+
reason: formatErrorMessage(error)
|
|
2168
|
+
});
|
|
2169
|
+
});
|
|
2170
|
+
};
|
|
2171
|
+
}
|
|
2172
|
+
//#endregion
|
|
2173
|
+
//#region extensions/codex/src/app-server/dynamic-tool-response-state.ts
|
|
2174
|
+
/** Retains the host-owned app preview without adding it to Codex's response payload. */
|
|
2175
|
+
function withDynamicToolTranscriptDetails(response, details) {
|
|
2176
|
+
if (details === void 0) return response;
|
|
2177
|
+
Object.defineProperty(response, "transcriptDetails", {
|
|
2178
|
+
configurable: true,
|
|
2179
|
+
enumerable: false,
|
|
2180
|
+
value: details
|
|
2181
|
+
});
|
|
2182
|
+
return response;
|
|
2183
|
+
}
|
|
2184
|
+
function withDynamicToolTerminalResolution(response, terminalResolution) {
|
|
2185
|
+
if (terminalResolution) {
|
|
2186
|
+
Object.defineProperties(response, {
|
|
2187
|
+
terminalResolution: {
|
|
2188
|
+
configurable: true,
|
|
2189
|
+
enumerable: false,
|
|
2190
|
+
value: terminalResolution
|
|
2191
|
+
},
|
|
2192
|
+
executionStarted: {
|
|
2193
|
+
configurable: true,
|
|
2194
|
+
enumerable: false,
|
|
2195
|
+
value: terminalResolution.executionStarted
|
|
2196
|
+
},
|
|
2197
|
+
...terminalResolution.executedArguments ? { executedArguments: {
|
|
2198
|
+
configurable: true,
|
|
2199
|
+
enumerable: false,
|
|
2200
|
+
value: terminalResolution.executedArguments
|
|
2201
|
+
} } : {}
|
|
2202
|
+
});
|
|
2203
|
+
withDynamicToolSideEffectEvidence(response, terminalResolution.sideEffectEvidence);
|
|
2204
|
+
}
|
|
2205
|
+
return response;
|
|
2206
|
+
}
|
|
2207
|
+
function withDynamicToolExecutionState(response, state) {
|
|
2208
|
+
Object.defineProperties(response, {
|
|
2209
|
+
executedArguments: {
|
|
2210
|
+
configurable: true,
|
|
2211
|
+
enumerable: false,
|
|
2212
|
+
value: state.executedArguments
|
|
2213
|
+
},
|
|
2214
|
+
executionStarted: {
|
|
2215
|
+
configurable: true,
|
|
2216
|
+
enumerable: false,
|
|
2217
|
+
value: state.executionStarted
|
|
2218
|
+
}
|
|
2219
|
+
});
|
|
2220
|
+
return withDynamicToolSideEffectEvidence(response, state.sideEffectEvidence === true);
|
|
2221
|
+
}
|
|
2222
|
+
function withDynamicToolSideEffectEvidence(response, sideEffectEvidence) {
|
|
2223
|
+
if (!sideEffectEvidence) {
|
|
2224
|
+
delete response.sideEffectEvidence;
|
|
2225
|
+
return response;
|
|
2226
|
+
}
|
|
2227
|
+
Object.defineProperty(response, "sideEffectEvidence", {
|
|
2228
|
+
configurable: true,
|
|
2229
|
+
enumerable: false,
|
|
2230
|
+
value: true
|
|
2231
|
+
});
|
|
2232
|
+
return response;
|
|
2233
|
+
}
|
|
2234
|
+
function createFailedDynamicToolResponse(message, options) {
|
|
2235
|
+
const response = {
|
|
2236
|
+
contentItems: [{
|
|
2237
|
+
type: "inputText",
|
|
2238
|
+
text: message
|
|
2239
|
+
}],
|
|
2240
|
+
success: false
|
|
2241
|
+
};
|
|
2242
|
+
Object.defineProperties(response, {
|
|
2243
|
+
diagnosticTerminalReason: {
|
|
2244
|
+
configurable: true,
|
|
2245
|
+
enumerable: false,
|
|
2246
|
+
value: options?.terminalReason ?? "failed"
|
|
2247
|
+
},
|
|
2248
|
+
diagnosticTerminalType: {
|
|
2249
|
+
configurable: true,
|
|
2250
|
+
enumerable: false,
|
|
2251
|
+
value: "error"
|
|
2252
|
+
}
|
|
2253
|
+
});
|
|
2254
|
+
if (options?.executionStarted !== void 0) Object.defineProperty(response, "executionStarted", {
|
|
2255
|
+
configurable: true,
|
|
2256
|
+
enumerable: false,
|
|
2257
|
+
value: options.executionStarted
|
|
2258
|
+
});
|
|
2259
|
+
if (options?.executedArguments !== void 0) Object.defineProperty(response, "executedArguments", {
|
|
2260
|
+
configurable: true,
|
|
2261
|
+
enumerable: false,
|
|
2262
|
+
value: options.executedArguments
|
|
2263
|
+
});
|
|
2264
|
+
return withDynamicToolSideEffectEvidence(response, options?.sideEffectEvidence === true);
|
|
2265
|
+
}
|
|
2266
|
+
//#endregion
|
|
2267
|
+
//#region extensions/codex/src/app-server/tool-abort-terminal-reason.ts
|
|
2268
|
+
/** Leaf helper shared by native and dynamic tool diagnostics. */
|
|
2269
|
+
const CODEX_TIMEOUT_ABORT_REASONS = /* @__PURE__ */ new Set([
|
|
2270
|
+
"codex_startup_timeout",
|
|
2271
|
+
"turn_completion_idle_timeout",
|
|
2272
|
+
"turn_progress_idle_timeout",
|
|
2273
|
+
"turn_terminal_idle_timeout"
|
|
2274
|
+
]);
|
|
2275
|
+
/** Preserves timeout provenance when an enclosing run aborts an active tool. */
|
|
2276
|
+
function resolveCodexToolAbortTerminalReason(signal) {
|
|
2277
|
+
try {
|
|
2278
|
+
const reason = signal.reason;
|
|
2279
|
+
if (typeof reason === "string") {
|
|
2280
|
+
if (CODEX_TIMEOUT_ABORT_REASONS.has(reason)) return "timed_out";
|
|
2281
|
+
return reason === "client_closed" ? "failed" : "cancelled";
|
|
2282
|
+
}
|
|
2283
|
+
if (reason && typeof reason === "object") {
|
|
2284
|
+
const record = reason;
|
|
2285
|
+
if (record.name === "TimeoutError" || record.reason === "timeout") return "timed_out";
|
|
2286
|
+
}
|
|
2287
|
+
} catch {
|
|
2288
|
+
return "cancelled";
|
|
2289
|
+
}
|
|
2290
|
+
return "cancelled";
|
|
2291
|
+
}
|
|
2292
|
+
//#endregion
|
|
2293
|
+
//#region extensions/codex/src/app-server/dynamic-tool-execution.ts
|
|
2294
|
+
/**
|
|
2295
|
+
* Timeout, terminal-release, and diagnostic helpers for Codex dynamic tool
|
|
2296
|
+
* calls.
|
|
2297
|
+
*/
|
|
2298
|
+
/** Default timeout for Codex dynamic tool calls. */
|
|
2299
|
+
const CODEX_DYNAMIC_TOOL_TIMEOUT_MS = 9e4;
|
|
2300
|
+
/** Hard cap for per-call Codex dynamic tool timeout overrides. */
|
|
2301
|
+
const CODEX_DYNAMIC_TOOL_MAX_TIMEOUT_MS = 6e5;
|
|
2302
|
+
const CODEX_DYNAMIC_TOOL_TIMEOUT_SECONDS_GRACE_MS = 3e4;
|
|
2303
|
+
const CODEX_DYNAMIC_IMAGE_GENERATION_TOOL_TIMEOUT_MS = 12e4;
|
|
2304
|
+
const CODEX_DYNAMIC_COMPUTER_GATEWAY_TIMEOUT_MS = 3e4;
|
|
2305
|
+
const CODEX_DYNAMIC_COMPUTER_COMPLETION_GRACE_MS = 3e4;
|
|
2306
|
+
/** Timeout for image-understanding style dynamic tool calls. */
|
|
2307
|
+
const CODEX_DYNAMIC_IMAGE_TOOL_TIMEOUT_MS = 6e4;
|
|
2308
|
+
/** Timeout for message-delivery dynamic tool calls. */
|
|
2309
|
+
const CODEX_DYNAMIC_MESSAGE_TOOL_TIMEOUT_MS = 6e5;
|
|
2310
|
+
/** Outer default for collector waits: full swarm budget plus completion grace. */
|
|
2311
|
+
const CODEX_DYNAMIC_AGENTS_WAIT_TOOL_TIMEOUT_MS = 63e4;
|
|
2312
|
+
const LOG_FIELD_MAX_LENGTH = 160;
|
|
2313
|
+
function normalizeLogField(value) {
|
|
2314
|
+
if (typeof value !== "string") return;
|
|
2315
|
+
const normalized = value.replaceAll(String.fromCharCode(27), " ").replaceAll("\r", " ").replaceAll("\n", " ").replaceAll(" ", " ").trim();
|
|
2316
|
+
if (!normalized) return;
|
|
2317
|
+
return normalized.length > LOG_FIELD_MAX_LENGTH ? `${truncateUtf16Safe(normalized, 157)}...` : normalized;
|
|
2318
|
+
}
|
|
2319
|
+
function readNumericTimeoutMs(value) {
|
|
2320
|
+
if (typeof value === "number" && Number.isFinite(value)) return Math.max(0, Math.floor(value));
|
|
2321
|
+
if (typeof value === "string") {
|
|
2322
|
+
const parsed = parseStrictNonNegativeInteger(value);
|
|
2323
|
+
if (parsed !== void 0) return Math.max(0, Math.floor(parsed));
|
|
2324
|
+
}
|
|
2325
|
+
}
|
|
2326
|
+
function formatDynamicToolTimeoutDetails(params) {
|
|
2327
|
+
const tool = normalizeLogField(params.call.tool) ?? "unknown";
|
|
2328
|
+
const baseMeta = {
|
|
2329
|
+
tool: params.call.tool,
|
|
2330
|
+
toolCallId: params.call.callId,
|
|
2331
|
+
threadId: params.call.threadId,
|
|
2332
|
+
turnId: params.call.turnId,
|
|
2333
|
+
timeoutMs: params.timeoutMs,
|
|
2334
|
+
timeoutKind: "codex_dynamic_tool_rpc"
|
|
2335
|
+
};
|
|
2336
|
+
if (tool !== "process" || !isJsonObject(params.call.arguments)) return {
|
|
2337
|
+
responseMessage: `OpenClaw dynamic tool call timed out after ${params.timeoutMs}ms while running tool ${tool}.`,
|
|
2338
|
+
consoleMessage: `codex dynamic tool timeout: tool=${tool} toolTimeoutMs=${params.timeoutMs}; per-tool-call watchdog, not session idle`,
|
|
2339
|
+
meta: baseMeta
|
|
2340
|
+
};
|
|
2341
|
+
const action = normalizeLogField(params.call.arguments.action);
|
|
2342
|
+
const sessionId = normalizeLogField(params.call.arguments.sessionId);
|
|
2343
|
+
const requestedTimeoutMs = readNumericTimeoutMs(params.call.arguments.timeout);
|
|
2344
|
+
const actionPart = action ? ` action=${action}` : "";
|
|
2345
|
+
const sessionPart = sessionId ? ` sessionId=${sessionId}` : "";
|
|
2346
|
+
const requestedPart = requestedTimeoutMs === void 0 ? "" : ` requestedWaitMs=${requestedTimeoutMs}`;
|
|
2347
|
+
const retryHint = action === "poll" ? "; repeated lines usually mean process-poll retry churn, not model progress" : "";
|
|
2348
|
+
const responseTarget = action || sessionId ? ` while waiting for process${actionPart}${sessionPart}` : " while waiting for the process tool";
|
|
2349
|
+
return {
|
|
2350
|
+
responseMessage: `OpenClaw dynamic tool call timed out after ${params.timeoutMs}ms${responseTarget}. This is a tool RPC timeout, not a session idle timeout.`,
|
|
2351
|
+
consoleMessage: `codex process tool timeout:${actionPart}${sessionPart} toolTimeoutMs=${params.timeoutMs}${requestedPart}; per-tool-call watchdog, not session idle${retryHint}`,
|
|
2352
|
+
meta: {
|
|
2353
|
+
...baseMeta,
|
|
2354
|
+
processAction: action,
|
|
2355
|
+
processSessionId: sessionId,
|
|
2356
|
+
processRequestedTimeoutMs: requestedTimeoutMs
|
|
2357
|
+
}
|
|
2358
|
+
};
|
|
2359
|
+
}
|
|
2360
|
+
/**
|
|
2361
|
+
* Runs a dynamic tool call with run-abort and the budget prepared by
|
|
2362
|
+
* resolveDynamicToolCallTimeoutMs, preserving tool-specific completion grace.
|
|
2363
|
+
*/
|
|
2364
|
+
async function handleDynamicToolCallWithTimeout(params) {
|
|
2365
|
+
let didNotifyAgentToolResult = false;
|
|
2366
|
+
const conservativeRaceResponses = /* @__PURE__ */ new WeakSet();
|
|
2367
|
+
const finalizeTerminal = (response) => {
|
|
2368
|
+
const executionSnapshot = params.toolBridge.consumeToolExecutionSnapshot?.(params.call.callId);
|
|
2369
|
+
const ownerKey = params.toolBridge.sideEffectOwnerKeyForTool?.(params.call.tool);
|
|
2370
|
+
const observedExecutionStarted = executionSnapshot?.executionStarted ?? (conservativeRaceResponses.has(response) ? void 0 : response.executionStarted);
|
|
2371
|
+
const terminalResolution = params.observeToolTerminal?.({
|
|
2372
|
+
toolCallId: params.call.callId,
|
|
2373
|
+
toolName: params.call.tool,
|
|
2374
|
+
arguments: response.executedArguments ?? executionSnapshot?.executedArguments ?? params.call.arguments,
|
|
2375
|
+
...params.toolMeta ? { meta: params.toolMeta } : {},
|
|
2376
|
+
...ownerKey ? { ownerMutation: { ownerKey } } : {},
|
|
2377
|
+
...observedExecutionStarted !== void 0 ? { executionStarted: observedExecutionStarted } : {},
|
|
2378
|
+
outcome: response.success ? "success" : "failure",
|
|
2379
|
+
...!response.success ? { failure: { error: readDynamicToolResponseText(response) } } : {}
|
|
2380
|
+
});
|
|
2381
|
+
return withDynamicToolTerminalResolution(response, terminalResolution);
|
|
2382
|
+
};
|
|
2383
|
+
const createFailedAfterPossibleDispatch = (message, terminalReason) => {
|
|
2384
|
+
const response = createFailedDynamicToolResponse(message, {
|
|
2385
|
+
executionStarted: true,
|
|
2386
|
+
sideEffectEvidence: true,
|
|
2387
|
+
terminalReason
|
|
2388
|
+
});
|
|
2389
|
+
conservativeRaceResponses.add(response);
|
|
2390
|
+
return response;
|
|
2391
|
+
};
|
|
2392
|
+
const notifyAgentToolResult = (event) => {
|
|
2393
|
+
if (didNotifyAgentToolResult) return;
|
|
2394
|
+
didNotifyAgentToolResult = true;
|
|
2395
|
+
try {
|
|
2396
|
+
params.onAgentToolResult?.(event);
|
|
2397
|
+
} catch (error) {
|
|
2398
|
+
embeddedAgentLog.warn(`onAgentToolResult handler failed: tool=${params.call.tool} error=${String(error)}`);
|
|
2399
|
+
}
|
|
2400
|
+
};
|
|
2401
|
+
const notifyFailedToolResult = (message, terminalReason = "failed") => {
|
|
2402
|
+
notifyAgentToolResult({
|
|
2403
|
+
toolName: params.call.tool,
|
|
2404
|
+
result: {
|
|
2405
|
+
content: [{
|
|
2406
|
+
type: "text",
|
|
2407
|
+
text: message
|
|
2408
|
+
}],
|
|
2409
|
+
details: {
|
|
2410
|
+
status: terminalReason,
|
|
2411
|
+
error: message
|
|
2412
|
+
}
|
|
2413
|
+
},
|
|
2414
|
+
isError: true
|
|
2415
|
+
});
|
|
2416
|
+
};
|
|
2417
|
+
if (params.signal.aborted) {
|
|
2418
|
+
const message = "OpenClaw dynamic tool call aborted before execution.";
|
|
2419
|
+
const terminalReason = resolveCodexToolAbortTerminalReason(params.signal);
|
|
2420
|
+
params.onFallbackSelected?.();
|
|
2421
|
+
notifyFailedToolResult(message, terminalReason);
|
|
2422
|
+
return finalizeTerminal(createFailedDynamicToolResponse(message, {
|
|
2423
|
+
executionStarted: false,
|
|
2424
|
+
terminalReason
|
|
2425
|
+
}));
|
|
2426
|
+
}
|
|
2427
|
+
const controller = new AbortController();
|
|
2428
|
+
let timeout;
|
|
2429
|
+
let timedOut = false;
|
|
2430
|
+
let resolveAbort;
|
|
2431
|
+
const abortFromRun = () => {
|
|
2432
|
+
const message = "OpenClaw dynamic tool call aborted.";
|
|
2433
|
+
const terminalReason = resolveCodexToolAbortTerminalReason(params.signal);
|
|
2434
|
+
params.onFallbackSelected?.();
|
|
2435
|
+
controller.abort(params.signal.reason ?? /* @__PURE__ */ new Error(message));
|
|
2436
|
+
notifyFailedToolResult(message, terminalReason);
|
|
2437
|
+
resolveAbort?.(createFailedAfterPossibleDispatch(message, terminalReason));
|
|
2438
|
+
};
|
|
2439
|
+
const abortPromise = new Promise((resolve) => {
|
|
2440
|
+
resolveAbort = resolve;
|
|
2441
|
+
});
|
|
2442
|
+
const timeoutPromise = new Promise((resolve) => {
|
|
2443
|
+
const { timeoutMs } = params;
|
|
2444
|
+
timeout = setTimeout(() => {
|
|
2445
|
+
timedOut = true;
|
|
2446
|
+
const timeoutDetails = formatDynamicToolTimeoutDetails({
|
|
2447
|
+
call: params.call,
|
|
2448
|
+
timeoutMs
|
|
2449
|
+
});
|
|
2450
|
+
params.onFallbackSelected?.();
|
|
2451
|
+
controller.abort(new Error(timeoutDetails.responseMessage));
|
|
2452
|
+
params.onTimeout?.();
|
|
2453
|
+
embeddedAgentLog.warn("codex dynamic tool call timed out", {
|
|
2454
|
+
...timeoutDetails.meta,
|
|
2455
|
+
consoleMessage: timeoutDetails.consoleMessage
|
|
2456
|
+
});
|
|
2457
|
+
notifyFailedToolResult(timeoutDetails.responseMessage, "timed_out");
|
|
2458
|
+
resolve(createFailedAfterPossibleDispatch(timeoutDetails.responseMessage, "timed_out"));
|
|
2459
|
+
}, timeoutMs);
|
|
2460
|
+
timeout.unref?.();
|
|
2461
|
+
});
|
|
2462
|
+
try {
|
|
2463
|
+
params.signal.addEventListener("abort", abortFromRun, { once: true });
|
|
2464
|
+
if (params.signal.aborted) abortFromRun();
|
|
2465
|
+
const response = await Promise.race([
|
|
2466
|
+
params.toolBridge.handleToolCall(params.call, {
|
|
2467
|
+
signal: controller.signal,
|
|
2468
|
+
onAgentToolResult: notifyAgentToolResult,
|
|
2469
|
+
toolCallOrdinal: params.toolCallOrdinal,
|
|
2470
|
+
retainExecutionSnapshot: true
|
|
2471
|
+
}),
|
|
2472
|
+
abortPromise,
|
|
2473
|
+
timeoutPromise
|
|
2474
|
+
]);
|
|
2475
|
+
if (!response.success && !didNotifyAgentToolResult) notifyFailedToolResult(readDynamicToolResponseText(response), response.diagnosticTerminalReason ?? "failed");
|
|
2476
|
+
return finalizeTerminal(response);
|
|
2477
|
+
} catch (error) {
|
|
2478
|
+
const terminalReason = params.signal.aborted ? resolveCodexToolAbortTerminalReason(params.signal) : resolveToolExecutionErrorKind(error);
|
|
2479
|
+
const message = formatToolExecutionErrorMessage(error, "OpenClaw dynamic tool call failed.");
|
|
2480
|
+
notifyFailedToolResult(message, terminalReason);
|
|
2481
|
+
return finalizeTerminal(createFailedAfterPossibleDispatch(message, terminalReason));
|
|
2482
|
+
} finally {
|
|
2483
|
+
if (timeout) clearTimeout(timeout);
|
|
2484
|
+
params.signal.removeEventListener("abort", abortFromRun);
|
|
2485
|
+
resolveAbort = void 0;
|
|
2486
|
+
if (!timedOut && !controller.signal.aborted) controller.abort(/* @__PURE__ */ new Error("OpenClaw dynamic tool call finished."));
|
|
2487
|
+
}
|
|
2488
|
+
}
|
|
2489
|
+
function readDynamicToolResponseText(response) {
|
|
2490
|
+
return response.contentItems.flatMap((item) => item.type === "inputText" && typeof item.text === "string" ? [item.text] : []).join("\n").trim() || "OpenClaw dynamic tool call failed.";
|
|
2491
|
+
}
|
|
2492
|
+
/** Strips OpenClaw-only metadata before sending a dynamic tool response to Codex. */
|
|
2493
|
+
function toCodexDynamicToolProtocolResponse(response) {
|
|
2494
|
+
return {
|
|
2495
|
+
contentItems: response.contentItems,
|
|
2496
|
+
success: response.success
|
|
2497
|
+
};
|
|
2498
|
+
}
|
|
2499
|
+
/** Adds async-started progress details when a tool result continues out of band. */
|
|
2500
|
+
function toCodexDynamicToolProgressResponse(response, protocolResponse) {
|
|
2501
|
+
const transcriptDetails = isJsonObject(response.transcriptDetails) ? response.transcriptDetails : void 0;
|
|
2502
|
+
const mcpAppPreview = isJsonObject(transcriptDetails?.mcpAppPreview) ? transcriptDetails.mcpAppPreview : void 0;
|
|
2503
|
+
const progressDetails = mcpAppPreview ? { mcpAppPreview } : void 0;
|
|
2504
|
+
if (response.asyncStarted !== true && progressDetails === void 0) return protocolResponse;
|
|
2505
|
+
return {
|
|
2506
|
+
...protocolResponse,
|
|
2507
|
+
...progressDetails ? { details: progressDetails } : {},
|
|
2508
|
+
...response.asyncStarted === true ? { details: {
|
|
2509
|
+
...progressDetails,
|
|
2510
|
+
async: true,
|
|
2511
|
+
status: "started"
|
|
2512
|
+
} } : {}
|
|
2513
|
+
};
|
|
2514
|
+
}
|
|
2515
|
+
/** Decides whether a terminal dynamic tool response can release the Codex turn. */
|
|
2516
|
+
function shouldReleaseTurnAfterTerminalDynamicTool(state) {
|
|
2517
|
+
return !state.completed && !state.aborted && state.responseSuccess && !state.currentTurnHadNonTerminalDynamicToolResult && state.activeAppServerTurnRequests === 0 && state.activeTurnItemIdsCount === 0 && state.pendingOpenClawDynamicToolCompletionIdsCount === 0;
|
|
2518
|
+
}
|
|
2519
|
+
/** Returns true when a non-async result should block terminal-release shortcuts. */
|
|
2520
|
+
function shouldBlockTerminalReleaseForNonTerminalDynamicToolResult(response) {
|
|
2521
|
+
return response.asyncStarted !== true;
|
|
2522
|
+
}
|
|
2523
|
+
/** Resolves whether terminal diagnostic state should release, wait, or stay idle. */
|
|
2524
|
+
function resolveTerminalDynamicToolBatchAction(state) {
|
|
2525
|
+
if (state.activeAppServerTurnRequests > 0 || state.activeTurnItemIdsCount > 0 || state.pendingOpenClawDynamicToolCompletionIdsCount > 0) return "wait";
|
|
2526
|
+
if (state.currentTurnHadNonTerminalDynamicToolResult) return "clear-nonterminal-batch";
|
|
2527
|
+
if (state.hasPendingTerminalDynamicToolRelease) return "release-pending-terminal";
|
|
2528
|
+
return "idle";
|
|
2529
|
+
}
|
|
2530
|
+
/** Returns true for diagnostic events that terminate a dynamic tool call. */
|
|
2531
|
+
function isDynamicToolTerminalDiagnosticEvent(event) {
|
|
2532
|
+
return event.type === "tool.execution.completed" || event.type === "tool.execution.error" || event.type === "tool.execution.blocked";
|
|
2533
|
+
}
|
|
2534
|
+
/** Matches terminal diagnostics to a specific dynamic tool call id/name. */
|
|
2535
|
+
function isMatchingDynamicToolTerminalDiagnostic(params) {
|
|
2536
|
+
if (params.event.toolCallId !== params.call.callId || params.event.toolName !== params.call.tool) return false;
|
|
2537
|
+
if (params.runId !== void 0) return params.event.runId === params.runId;
|
|
2538
|
+
if (params.sessionId !== void 0) return params.event.sessionId === params.sessionId;
|
|
2539
|
+
if (params.sessionKey !== void 0) return params.event.sessionKey === params.sessionKey;
|
|
2540
|
+
return params.event.runId === void 0 && params.event.sessionId === void 0 && params.event.sessionKey === void 0;
|
|
2541
|
+
}
|
|
2542
|
+
/** Checks pending diagnostics for a terminal event matching a tool call. */
|
|
2543
|
+
function hasPendingDynamicToolTerminalDiagnostic(params) {
|
|
2544
|
+
return hasPendingInternalDiagnosticEvent((event) => {
|
|
2545
|
+
if (!isDynamicToolTerminalDiagnosticEvent(event)) return false;
|
|
2546
|
+
return isMatchingDynamicToolTerminalDiagnostic({
|
|
2547
|
+
event,
|
|
2548
|
+
call: params.call,
|
|
2549
|
+
runId: params.runId,
|
|
2550
|
+
sessionId: params.sessionId,
|
|
2551
|
+
sessionKey: params.sessionKey
|
|
2552
|
+
});
|
|
2553
|
+
});
|
|
2554
|
+
}
|
|
2555
|
+
/** Resolves per-tool timeout, applying media/message defaults and hard caps. */
|
|
2556
|
+
function resolveDynamicToolCallTimeoutMs(params) {
|
|
2557
|
+
const args = isJsonObject(params.call.arguments) ? params.call.arguments : void 0;
|
|
2558
|
+
if (params.call.tool === "ask_user" || params.call.tool === "secrets" && args?.action === "request") try {
|
|
2559
|
+
return normalizeQuestionTimeoutSeconds(args?.timeoutSeconds) * 1e3 + CODEX_DYNAMIC_TOOL_TIMEOUT_SECONDS_GRACE_MS;
|
|
2560
|
+
} catch {
|
|
2561
|
+
return CODEX_DYNAMIC_TOOL_TIMEOUT_MS;
|
|
2562
|
+
}
|
|
2563
|
+
if (params.call.tool === "computer") return clampDynamicToolTimeoutMs(readComputerToolTimeoutMs(params.call.arguments));
|
|
2564
|
+
if (params.call.tool === "message") return CODEX_DYNAMIC_MESSAGE_TOOL_TIMEOUT_MS;
|
|
2565
|
+
if (params.call.tool === "agents_wait") {
|
|
2566
|
+
const requestedMs = readDynamicToolCallTimeoutMs(params.call.arguments) ?? readConfiguredDynamicToolTimeoutMs(params.call.tool, params.config) ?? CODEX_DYNAMIC_AGENTS_WAIT_TOOL_TIMEOUT_MS;
|
|
2567
|
+
return Math.max(1, Math.min(63e4, Math.floor(requestedMs)));
|
|
2568
|
+
}
|
|
2569
|
+
return clampDynamicToolTimeoutMs(readDynamicToolCallTimeoutMs(params.call.arguments) ?? readConfiguredDynamicToolTimeoutMs(params.call.tool, params.config) ?? CODEX_DYNAMIC_TOOL_TIMEOUT_MS);
|
|
2570
|
+
}
|
|
2571
|
+
/** Transport guard stays outside the handler's bounded tool wait and completion grace. */
|
|
2572
|
+
function resolveDynamicToolServerRequestTimeoutMs(call) {
|
|
2573
|
+
return Math.max(63e4, call ? resolveDynamicToolCallTimeoutMs({
|
|
2574
|
+
call,
|
|
2575
|
+
config: void 0
|
|
2576
|
+
}) : 0) + CODEX_DYNAMIC_TOOL_TIMEOUT_SECONDS_GRACE_MS;
|
|
2577
|
+
}
|
|
2578
|
+
function readComputerToolTimeoutMs(value) {
|
|
2579
|
+
const args = isJsonObject(value) ? value : void 0;
|
|
2580
|
+
const action = typeof args?.action === "string" ? args.action : void 0;
|
|
2581
|
+
const gatewayTimeoutMs = readPositiveFiniteTimeoutMs(args?.timeoutMs) ?? CODEX_DYNAMIC_COMPUTER_GATEWAY_TIMEOUT_MS;
|
|
2582
|
+
const gatewayCallCount = action === "screenshot" || action === "wait" ? 3 : 4;
|
|
2583
|
+
return (action === "wait" || action === "hold_key" ? Math.max(0, Number(args?.duration) || 0) * 1e3 : 0) + gatewayCallCount * gatewayTimeoutMs + CODEX_DYNAMIC_COMPUTER_COMPLETION_GRACE_MS;
|
|
2584
|
+
}
|
|
2585
|
+
function readDynamicToolCallTimeoutMs(value) {
|
|
2586
|
+
if (!isJsonObject(value)) return;
|
|
2587
|
+
const timeoutMs = readPositiveFiniteTimeoutMs(value.timeoutMs);
|
|
2588
|
+
if (timeoutMs !== void 0) return timeoutMs;
|
|
2589
|
+
const timeoutSecondsMs = readDynamicToolTimeoutSecondsAsMs(value.timeoutSeconds);
|
|
2590
|
+
return timeoutSecondsMs === void 0 ? void 0 : addTimerTimeoutGraceMs(timeoutSecondsMs, CODEX_DYNAMIC_TOOL_TIMEOUT_SECONDS_GRACE_MS);
|
|
2591
|
+
}
|
|
2592
|
+
function readConfiguredDynamicToolTimeoutMs(toolName, config) {
|
|
2593
|
+
if (toolName === "image_generate") {
|
|
2594
|
+
const imageModel = config?.agents?.defaults?.mediaModels?.image;
|
|
2595
|
+
if (!imageModel || typeof imageModel !== "object") return CODEX_DYNAMIC_IMAGE_GENERATION_TOOL_TIMEOUT_MS;
|
|
2596
|
+
return readPositiveFiniteTimeoutMs(imageModel.timeoutMs) ?? CODEX_DYNAMIC_IMAGE_GENERATION_TOOL_TIMEOUT_MS;
|
|
2597
|
+
}
|
|
2598
|
+
if (toolName === "view_image") {
|
|
2599
|
+
const candidates = (config?.tools?.media?.models ?? []).filter((entry) => !entry.capabilities || entry.capabilities.includes("image"));
|
|
2600
|
+
const capabilityTimeoutMs = readTimeoutSecondsAsMs(config?.tools?.media?.image?.timeoutSeconds);
|
|
2601
|
+
return Math.max(capabilityTimeoutMs ?? CODEX_DYNAMIC_IMAGE_TOOL_TIMEOUT_MS, ...candidates.map((entry) => readTimeoutSecondsAsMs(entry.timeoutSeconds) ?? capabilityTimeoutMs ?? CODEX_DYNAMIC_IMAGE_TOOL_TIMEOUT_MS));
|
|
2602
|
+
}
|
|
2603
|
+
if (toolName === "message") return CODEX_DYNAMIC_MESSAGE_TOOL_TIMEOUT_MS;
|
|
2604
|
+
}
|
|
2605
|
+
function readTimeoutSecondsAsMs(value) {
|
|
2606
|
+
const seconds = readPositiveFiniteTimeoutMs(value);
|
|
2607
|
+
return seconds === void 0 ? void 0 : seconds * 1e3;
|
|
2608
|
+
}
|
|
2609
|
+
function readDynamicToolTimeoutSecondsAsMs(value) {
|
|
2610
|
+
if (typeof value !== "number" || !Number.isFinite(value) || !Number.isInteger(value) || value <= 0) return;
|
|
2611
|
+
return value * 1e3;
|
|
2612
|
+
}
|
|
2613
|
+
function readPositiveFiniteTimeoutMs(value) {
|
|
2614
|
+
return typeof value === "number" && Number.isFinite(value) && value > 0 ? Math.floor(value) : void 0;
|
|
2615
|
+
}
|
|
2616
|
+
function clampDynamicToolTimeoutMs(timeoutMs) {
|
|
2617
|
+
return Math.max(1, Math.min(CODEX_DYNAMIC_TOOL_MAX_TIMEOUT_MS, Math.floor(timeoutMs)));
|
|
2618
|
+
}
|
|
2619
|
+
//#endregion
|
|
2620
|
+
//#region extensions/codex/src/app-server/elicitation-response.ts
|
|
2621
|
+
function createCodexElicitationResponse(action, content = null, meta = null) {
|
|
2622
|
+
return {
|
|
2623
|
+
action,
|
|
2624
|
+
content,
|
|
2625
|
+
_meta: meta
|
|
2626
|
+
};
|
|
2627
|
+
}
|
|
2628
|
+
//#endregion
|
|
2629
|
+
//#region extensions/codex/src/app-server/protocol-generated/json/DynamicToolCallParams.json
|
|
2630
|
+
var DynamicToolCallParams_default = {
|
|
2631
|
+
$schema: "http://json-schema.org/draft-07/schema#",
|
|
2632
|
+
properties: {
|
|
2633
|
+
"arguments": true,
|
|
2634
|
+
"callId": { "type": "string" },
|
|
2635
|
+
"namespace": { "type": ["string", "null"] },
|
|
2636
|
+
"threadId": { "type": "string" },
|
|
2637
|
+
"tool": { "type": "string" },
|
|
2638
|
+
"turnId": { "type": "string" }
|
|
2639
|
+
},
|
|
2640
|
+
required: [
|
|
2641
|
+
"arguments",
|
|
2642
|
+
"callId",
|
|
2643
|
+
"threadId",
|
|
2644
|
+
"tool",
|
|
2645
|
+
"turnId"
|
|
2646
|
+
],
|
|
2647
|
+
title: "DynamicToolCallParams",
|
|
2648
|
+
type: "object"
|
|
2649
|
+
};
|
|
2650
|
+
//#endregion
|
|
2651
|
+
//#region extensions/codex/src/app-server/protocol-generated/json/v2/CodexAppServerProtocolDefinitions.json
|
|
2652
|
+
var definitions = {
|
|
2653
|
+
"AbsolutePathBuf": {
|
|
2654
|
+
"description": "A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.",
|
|
2655
|
+
"type": "string"
|
|
2656
|
+
},
|
|
2657
|
+
"Account": { "oneOf": [
|
|
2658
|
+
{
|
|
2659
|
+
"properties": { "type": {
|
|
2660
|
+
"enum": ["apiKey"],
|
|
2661
|
+
"title": "ApiKeyAccountType",
|
|
2662
|
+
"type": "string"
|
|
2663
|
+
} },
|
|
2664
|
+
"required": ["type"],
|
|
2665
|
+
"title": "ApiKeyAccount",
|
|
2666
|
+
"type": "object"
|
|
2667
|
+
},
|
|
2668
|
+
{
|
|
2669
|
+
"properties": {
|
|
2670
|
+
"email": { "type": ["string", "null"] },
|
|
2671
|
+
"planType": { "$ref": "#/definitions/PlanType" },
|
|
2672
|
+
"type": {
|
|
2673
|
+
"enum": ["chatgpt"],
|
|
2674
|
+
"title": "ChatgptAccountType",
|
|
2675
|
+
"type": "string"
|
|
2676
|
+
}
|
|
2677
|
+
},
|
|
2678
|
+
"required": [
|
|
2679
|
+
"email",
|
|
2680
|
+
"planType",
|
|
2681
|
+
"type"
|
|
2682
|
+
],
|
|
2683
|
+
"title": "ChatgptAccount",
|
|
2684
|
+
"type": "object"
|
|
2685
|
+
},
|
|
2686
|
+
{
|
|
2687
|
+
"properties": {
|
|
2688
|
+
"type": {
|
|
2689
|
+
"enum": ["amazonBedrock"],
|
|
2690
|
+
"title": "AmazonBedrockAccountType",
|
|
2691
|
+
"type": "string"
|
|
2692
|
+
},
|
|
2693
|
+
"usesCodexManagedCredentials": {
|
|
2694
|
+
"default": false,
|
|
2695
|
+
"type": "boolean"
|
|
2696
|
+
}
|
|
2697
|
+
},
|
|
2698
|
+
"required": ["type"],
|
|
2699
|
+
"title": "AmazonBedrockAccount",
|
|
2700
|
+
"type": "object"
|
|
2701
|
+
}
|
|
2702
|
+
] },
|
|
2703
|
+
"ActivePermissionProfile": {
|
|
2704
|
+
"properties": {
|
|
2705
|
+
"extends": {
|
|
2706
|
+
"default": null,
|
|
2707
|
+
"description": "Parent profile identifier from the selected permissions profile's `extends` setting, when present.",
|
|
2708
|
+
"type": ["string", "null"]
|
|
2709
|
+
},
|
|
2710
|
+
"id": {
|
|
2711
|
+
"description": "Identifier from `default_permissions` or the implicit built-in default, such as `:workspace` or a user-defined `[permissions.<id>]` profile.",
|
|
2712
|
+
"type": "string"
|
|
2713
|
+
}
|
|
2714
|
+
},
|
|
2715
|
+
"required": ["id"],
|
|
2716
|
+
"type": "object"
|
|
2717
|
+
},
|
|
2718
|
+
"AgentMessageDelivery": {
|
|
2719
|
+
"enum": ["async"],
|
|
2720
|
+
"type": "string"
|
|
2721
|
+
},
|
|
2722
|
+
"AgentPath": { "type": "string" },
|
|
2723
|
+
"ApprovalsReviewer": {
|
|
2724
|
+
"description": "Configures who approval requests are routed to for review. Examples include sandbox escapes, blocked network access, MCP approval prompts, and ARC escalations. Defaults to `user`. `auto_review` uses a carefully prompted subagent to gather relevant context and apply a risk-based decision framework before approving or denying the request. The legacy value `guardian_subagent` is accepted for compatibility.",
|
|
2725
|
+
"enum": [
|
|
2726
|
+
"user",
|
|
2727
|
+
"auto_review",
|
|
2728
|
+
"guardian_subagent"
|
|
2729
|
+
],
|
|
2730
|
+
"type": "string"
|
|
2731
|
+
},
|
|
2732
|
+
"AskForApproval": { "oneOf": [{
|
|
2733
|
+
"additionalProperties": false,
|
|
2734
|
+
"properties": { "granular": {
|
|
2735
|
+
"properties": {
|
|
2736
|
+
"mcp_elicitations": { "type": "boolean" },
|
|
2737
|
+
"request_permissions": {
|
|
2738
|
+
"default": false,
|
|
2739
|
+
"type": "boolean"
|
|
2740
|
+
},
|
|
2741
|
+
"rules": { "type": "boolean" },
|
|
2742
|
+
"sandbox_approval": { "type": "boolean" },
|
|
2743
|
+
"skill_approval": {
|
|
2744
|
+
"default": false,
|
|
2745
|
+
"type": "boolean"
|
|
2746
|
+
}
|
|
2747
|
+
},
|
|
2748
|
+
"required": [
|
|
2749
|
+
"mcp_elicitations",
|
|
2750
|
+
"rules",
|
|
2751
|
+
"sandbox_approval"
|
|
2752
|
+
],
|
|
2753
|
+
"type": "object"
|
|
2754
|
+
} },
|
|
2755
|
+
"required": ["granular"],
|
|
2756
|
+
"title": "GranularAskForApproval",
|
|
2757
|
+
"type": "object"
|
|
2758
|
+
}, {
|
|
2759
|
+
"enum": [
|
|
2760
|
+
"untrusted",
|
|
2761
|
+
"on-request",
|
|
2762
|
+
"never"
|
|
2763
|
+
],
|
|
2764
|
+
"type": "string"
|
|
2765
|
+
}] },
|
|
2766
|
+
"ByteRange": {
|
|
2767
|
+
"properties": {
|
|
2768
|
+
"end": {
|
|
2769
|
+
"format": "uint",
|
|
2770
|
+
"minimum": 0,
|
|
2771
|
+
"type": "integer"
|
|
2772
|
+
},
|
|
2773
|
+
"start": {
|
|
2774
|
+
"format": "uint",
|
|
2775
|
+
"minimum": 0,
|
|
2776
|
+
"type": "integer"
|
|
2777
|
+
}
|
|
2778
|
+
},
|
|
2779
|
+
"required": ["end", "start"],
|
|
2780
|
+
"type": "object"
|
|
2781
|
+
},
|
|
2782
|
+
"CodexErrorInfo": {
|
|
2783
|
+
"description": "This translation layer make sure that we expose codex error code in camel case.\n\nWhen an upstream HTTP status is available (for example, from the Responses API or a provider), it is forwarded in `httpStatusCode` on the relevant `codexErrorInfo` variant.",
|
|
2784
|
+
"oneOf": [
|
|
2785
|
+
{
|
|
2786
|
+
"additionalProperties": false,
|
|
2787
|
+
"properties": { "httpConnectionFailed": {
|
|
2788
|
+
"properties": { "httpStatusCode": {
|
|
2789
|
+
"format": "uint16",
|
|
2790
|
+
"minimum": 0,
|
|
2791
|
+
"type": ["integer", "null"]
|
|
2792
|
+
} },
|
|
2793
|
+
"type": "object"
|
|
2794
|
+
} },
|
|
2795
|
+
"required": ["httpConnectionFailed"],
|
|
2796
|
+
"title": "HttpConnectionFailedCodexErrorInfo",
|
|
2797
|
+
"type": "object"
|
|
2798
|
+
},
|
|
2799
|
+
{
|
|
2800
|
+
"additionalProperties": false,
|
|
2801
|
+
"description": "Failed to connect to the response SSE stream.",
|
|
2802
|
+
"properties": { "responseStreamConnectionFailed": {
|
|
2803
|
+
"properties": { "httpStatusCode": {
|
|
2804
|
+
"format": "uint16",
|
|
2805
|
+
"minimum": 0,
|
|
2806
|
+
"type": ["integer", "null"]
|
|
2807
|
+
} },
|
|
2808
|
+
"type": "object"
|
|
2809
|
+
} },
|
|
2810
|
+
"required": ["responseStreamConnectionFailed"],
|
|
2811
|
+
"title": "ResponseStreamConnectionFailedCodexErrorInfo",
|
|
2812
|
+
"type": "object"
|
|
2813
|
+
},
|
|
2814
|
+
{
|
|
2815
|
+
"additionalProperties": false,
|
|
2816
|
+
"description": "The response SSE stream disconnected in the middle of a turn before completion.",
|
|
2817
|
+
"properties": { "responseStreamDisconnected": {
|
|
2818
|
+
"properties": { "httpStatusCode": {
|
|
2819
|
+
"format": "uint16",
|
|
2820
|
+
"minimum": 0,
|
|
2821
|
+
"type": ["integer", "null"]
|
|
2822
|
+
} },
|
|
2823
|
+
"type": "object"
|
|
2824
|
+
} },
|
|
2825
|
+
"required": ["responseStreamDisconnected"],
|
|
2826
|
+
"title": "ResponseStreamDisconnectedCodexErrorInfo",
|
|
2827
|
+
"type": "object"
|
|
2828
|
+
},
|
|
2829
|
+
{
|
|
2830
|
+
"additionalProperties": false,
|
|
2831
|
+
"description": "Reached the retry limit for responses.",
|
|
2832
|
+
"properties": { "responseTooManyFailedAttempts": {
|
|
2833
|
+
"properties": { "httpStatusCode": {
|
|
2834
|
+
"format": "uint16",
|
|
2835
|
+
"minimum": 0,
|
|
2836
|
+
"type": ["integer", "null"]
|
|
2837
|
+
} },
|
|
2838
|
+
"type": "object"
|
|
2839
|
+
} },
|
|
2840
|
+
"required": ["responseTooManyFailedAttempts"],
|
|
2841
|
+
"title": "ResponseTooManyFailedAttemptsCodexErrorInfo",
|
|
2842
|
+
"type": "object"
|
|
2843
|
+
},
|
|
2844
|
+
{
|
|
2845
|
+
"additionalProperties": false,
|
|
2846
|
+
"description": "Returned when `turn/start` or `turn/steer` is submitted while the current active turn cannot accept same-turn steering, for example `/review` or manual `/compact`.",
|
|
2847
|
+
"properties": { "activeTurnNotSteerable": {
|
|
2848
|
+
"properties": { "turnKind": { "$ref": "#/definitions/NonSteerableTurnKind" } },
|
|
2849
|
+
"required": ["turnKind"],
|
|
2850
|
+
"type": "object"
|
|
2851
|
+
} },
|
|
2852
|
+
"required": ["activeTurnNotSteerable"],
|
|
2853
|
+
"title": "ActiveTurnNotSteerableCodexErrorInfo",
|
|
2854
|
+
"type": "object"
|
|
2855
|
+
},
|
|
2856
|
+
{
|
|
2857
|
+
"enum": [
|
|
2858
|
+
"contextWindowExceeded",
|
|
2859
|
+
"sessionBudgetExceeded",
|
|
2860
|
+
"usageLimitExceeded",
|
|
2861
|
+
"rateLimitExceeded",
|
|
2862
|
+
"serverOverloaded",
|
|
2863
|
+
"cyberPolicy",
|
|
2864
|
+
"misalignmentPolicyViolation",
|
|
2865
|
+
"internalServerError",
|
|
2866
|
+
"unauthorized",
|
|
2867
|
+
"badRequest",
|
|
2868
|
+
"threadRollbackFailed",
|
|
2869
|
+
"sandboxError",
|
|
2870
|
+
"other"
|
|
2871
|
+
],
|
|
2872
|
+
"type": "string"
|
|
2873
|
+
}
|
|
2874
|
+
]
|
|
2875
|
+
},
|
|
2876
|
+
"CollabAgentState": {
|
|
2877
|
+
"properties": {
|
|
2878
|
+
"message": { "type": ["string", "null"] },
|
|
2879
|
+
"status": { "$ref": "#/definitions/CollabAgentStatus" }
|
|
2880
|
+
},
|
|
2881
|
+
"required": ["status"],
|
|
2882
|
+
"type": "object"
|
|
2883
|
+
},
|
|
2884
|
+
"CollabAgentStatus": {
|
|
2885
|
+
"enum": [
|
|
2886
|
+
"pendingInit",
|
|
2887
|
+
"running",
|
|
2888
|
+
"interrupted",
|
|
2889
|
+
"completed",
|
|
2890
|
+
"errored",
|
|
2891
|
+
"shutdown",
|
|
2892
|
+
"notFound"
|
|
2893
|
+
],
|
|
2894
|
+
"type": "string"
|
|
2895
|
+
},
|
|
2896
|
+
"CollabAgentTool": {
|
|
2897
|
+
"enum": [
|
|
2898
|
+
"spawnAgent",
|
|
2899
|
+
"sendInput",
|
|
2900
|
+
"resumeAgent",
|
|
2901
|
+
"wait",
|
|
2902
|
+
"closeAgent",
|
|
2903
|
+
"sendMessage",
|
|
2904
|
+
"followupTask",
|
|
2905
|
+
"interruptAgent",
|
|
2906
|
+
"listAgents"
|
|
2907
|
+
],
|
|
2908
|
+
"type": "string"
|
|
2909
|
+
},
|
|
2910
|
+
"CollabAgentToolCallStatus": {
|
|
2911
|
+
"enum": [
|
|
2912
|
+
"inProgress",
|
|
2913
|
+
"completed",
|
|
2914
|
+
"failed",
|
|
2915
|
+
"interrupted"
|
|
2916
|
+
],
|
|
2917
|
+
"type": "string"
|
|
2918
|
+
},
|
|
2919
|
+
"CommandAction": { "oneOf": [
|
|
2920
|
+
{
|
|
2921
|
+
"properties": {
|
|
2922
|
+
"command": { "type": "string" },
|
|
2923
|
+
"name": { "type": "string" },
|
|
2924
|
+
"path": { "$ref": "#/definitions/LegacyAppPathString" },
|
|
2925
|
+
"type": {
|
|
2926
|
+
"enum": ["read"],
|
|
2927
|
+
"title": "ReadCommandActionType",
|
|
2928
|
+
"type": "string"
|
|
2929
|
+
}
|
|
2930
|
+
},
|
|
2931
|
+
"required": [
|
|
2932
|
+
"command",
|
|
2933
|
+
"name",
|
|
2934
|
+
"path",
|
|
2935
|
+
"type"
|
|
2936
|
+
],
|
|
2937
|
+
"title": "ReadCommandAction",
|
|
2938
|
+
"type": "object"
|
|
2939
|
+
},
|
|
2940
|
+
{
|
|
2941
|
+
"properties": {
|
|
2942
|
+
"command": { "type": "string" },
|
|
2943
|
+
"path": { "type": ["string", "null"] },
|
|
2944
|
+
"type": {
|
|
2945
|
+
"enum": ["listFiles"],
|
|
2946
|
+
"title": "ListFilesCommandActionType",
|
|
2947
|
+
"type": "string"
|
|
2948
|
+
}
|
|
2949
|
+
},
|
|
2950
|
+
"required": ["command", "type"],
|
|
2951
|
+
"title": "ListFilesCommandAction",
|
|
2952
|
+
"type": "object"
|
|
2953
|
+
},
|
|
2954
|
+
{
|
|
2955
|
+
"properties": {
|
|
2956
|
+
"command": { "type": "string" },
|
|
2957
|
+
"path": { "type": ["string", "null"] },
|
|
2958
|
+
"query": { "type": ["string", "null"] },
|
|
2959
|
+
"type": {
|
|
2960
|
+
"enum": ["search"],
|
|
2961
|
+
"title": "SearchCommandActionType",
|
|
2962
|
+
"type": "string"
|
|
2963
|
+
}
|
|
2964
|
+
},
|
|
2965
|
+
"required": ["command", "type"],
|
|
2966
|
+
"title": "SearchCommandAction",
|
|
2967
|
+
"type": "object"
|
|
2968
|
+
},
|
|
2969
|
+
{
|
|
2970
|
+
"properties": {
|
|
2971
|
+
"command": { "type": "string" },
|
|
2972
|
+
"type": {
|
|
2973
|
+
"enum": ["unknown"],
|
|
2974
|
+
"title": "UnknownCommandActionType",
|
|
2975
|
+
"type": "string"
|
|
2976
|
+
}
|
|
2977
|
+
},
|
|
2978
|
+
"required": ["command", "type"],
|
|
2979
|
+
"title": "UnknownCommandAction",
|
|
2980
|
+
"type": "object"
|
|
2981
|
+
}
|
|
2982
|
+
] },
|
|
2983
|
+
"CommandExecutionSource": {
|
|
2984
|
+
"enum": [
|
|
2985
|
+
"agent",
|
|
2986
|
+
"userShell",
|
|
2987
|
+
"unifiedExecStartup",
|
|
2988
|
+
"unifiedExecInteraction"
|
|
2989
|
+
],
|
|
2990
|
+
"type": "string"
|
|
2991
|
+
},
|
|
2992
|
+
"CommandExecutionStatus": {
|
|
2993
|
+
"enum": [
|
|
2994
|
+
"inProgress",
|
|
2995
|
+
"completed",
|
|
2996
|
+
"failed",
|
|
2997
|
+
"declined"
|
|
2998
|
+
],
|
|
2999
|
+
"type": "string"
|
|
3000
|
+
},
|
|
3001
|
+
"DynamicToolCallOutputContentItem": { "oneOf": [
|
|
3002
|
+
{
|
|
3003
|
+
"properties": {
|
|
3004
|
+
"text": { "type": "string" },
|
|
3005
|
+
"type": {
|
|
3006
|
+
"enum": ["inputText"],
|
|
3007
|
+
"title": "InputTextDynamicToolCallOutputContentItemType",
|
|
3008
|
+
"type": "string"
|
|
3009
|
+
}
|
|
3010
|
+
},
|
|
3011
|
+
"required": ["text", "type"],
|
|
3012
|
+
"title": "InputTextDynamicToolCallOutputContentItem",
|
|
3013
|
+
"type": "object"
|
|
3014
|
+
},
|
|
3015
|
+
{
|
|
3016
|
+
"properties": {
|
|
3017
|
+
"imageUrl": { "type": "string" },
|
|
3018
|
+
"type": {
|
|
3019
|
+
"enum": ["inputImage"],
|
|
3020
|
+
"title": "InputImageDynamicToolCallOutputContentItemType",
|
|
3021
|
+
"type": "string"
|
|
3022
|
+
}
|
|
3023
|
+
},
|
|
3024
|
+
"required": ["imageUrl", "type"],
|
|
3025
|
+
"title": "InputImageDynamicToolCallOutputContentItem",
|
|
3026
|
+
"type": "object"
|
|
3027
|
+
},
|
|
3028
|
+
{
|
|
3029
|
+
"properties": {
|
|
3030
|
+
"audioUrl": { "type": "string" },
|
|
3031
|
+
"type": {
|
|
3032
|
+
"enum": ["inputAudio"],
|
|
3033
|
+
"title": "InputAudioDynamicToolCallOutputContentItemType",
|
|
3034
|
+
"type": "string"
|
|
3035
|
+
}
|
|
3036
|
+
},
|
|
3037
|
+
"required": ["audioUrl", "type"],
|
|
3038
|
+
"title": "InputAudioDynamicToolCallOutputContentItem",
|
|
3039
|
+
"type": "object"
|
|
3040
|
+
}
|
|
3041
|
+
] },
|
|
3042
|
+
"DynamicToolCallStatus": {
|
|
3043
|
+
"enum": [
|
|
3044
|
+
"inProgress",
|
|
3045
|
+
"completed",
|
|
3046
|
+
"failed"
|
|
3047
|
+
],
|
|
3048
|
+
"type": "string"
|
|
3049
|
+
},
|
|
3050
|
+
"FileUpdateChange": {
|
|
3051
|
+
"properties": {
|
|
3052
|
+
"diff": { "type": "string" },
|
|
3053
|
+
"kind": { "$ref": "#/definitions/PatchChangeKind" },
|
|
3054
|
+
"path": { "type": "string" }
|
|
3055
|
+
},
|
|
3056
|
+
"required": [
|
|
3057
|
+
"diff",
|
|
3058
|
+
"kind",
|
|
3059
|
+
"path"
|
|
3060
|
+
],
|
|
3061
|
+
"type": "object"
|
|
3062
|
+
},
|
|
3063
|
+
"FunctionCallOutputBody": { "anyOf": [{
|
|
3064
|
+
"items": { "$ref": "#/definitions/FunctionCallOutputContentItem" },
|
|
3065
|
+
"type": "array"
|
|
3066
|
+
}, { "type": "string" }] },
|
|
3067
|
+
"FunctionCallOutputContentItem": {
|
|
3068
|
+
"description": "Responses API compatible content items that can be returned by a tool call. This is a subset of ContentItem with the types we support as function call outputs.",
|
|
3069
|
+
"oneOf": [
|
|
3070
|
+
{
|
|
3071
|
+
"properties": {
|
|
3072
|
+
"text": { "type": "string" },
|
|
3073
|
+
"type": {
|
|
3074
|
+
"enum": ["input_text"],
|
|
3075
|
+
"title": "InputTextFunctionCallOutputContentItemType",
|
|
3076
|
+
"type": "string"
|
|
3077
|
+
}
|
|
3078
|
+
},
|
|
3079
|
+
"required": ["text", "type"],
|
|
3080
|
+
"title": "InputTextFunctionCallOutputContentItem",
|
|
3081
|
+
"type": "object"
|
|
3082
|
+
},
|
|
3083
|
+
{
|
|
3084
|
+
"properties": {
|
|
3085
|
+
"detail": { "anyOf": [{ "$ref": "#/definitions/ImageDetail" }, { "type": "null" }] },
|
|
3086
|
+
"image_url": { "type": "string" },
|
|
3087
|
+
"type": {
|
|
3088
|
+
"enum": ["input_image"],
|
|
3089
|
+
"title": "InputImageFunctionCallOutputContentItemType",
|
|
3090
|
+
"type": "string"
|
|
3091
|
+
}
|
|
3092
|
+
},
|
|
3093
|
+
"required": ["image_url", "type"],
|
|
3094
|
+
"title": "InputImageFunctionCallOutputContentItem",
|
|
3095
|
+
"type": "object"
|
|
3096
|
+
},
|
|
3097
|
+
{
|
|
3098
|
+
"properties": {
|
|
3099
|
+
"audio_url": { "type": "string" },
|
|
3100
|
+
"type": {
|
|
3101
|
+
"enum": ["input_audio"],
|
|
3102
|
+
"title": "InputAudioFunctionCallOutputContentItemType",
|
|
3103
|
+
"type": "string"
|
|
3104
|
+
}
|
|
3105
|
+
},
|
|
3106
|
+
"required": ["audio_url", "type"],
|
|
3107
|
+
"title": "InputAudioFunctionCallOutputContentItem",
|
|
3108
|
+
"type": "object"
|
|
3109
|
+
},
|
|
3110
|
+
{
|
|
3111
|
+
"properties": {
|
|
3112
|
+
"encrypted_content": { "type": "string" },
|
|
3113
|
+
"type": {
|
|
3114
|
+
"enum": ["encrypted_content"],
|
|
3115
|
+
"title": "EncryptedContentFunctionCallOutputContentItemType",
|
|
3116
|
+
"type": "string"
|
|
3117
|
+
}
|
|
3118
|
+
},
|
|
3119
|
+
"required": ["encrypted_content", "type"],
|
|
3120
|
+
"title": "EncryptedContentFunctionCallOutputContentItem",
|
|
3121
|
+
"type": "object"
|
|
3122
|
+
}
|
|
3123
|
+
]
|
|
3124
|
+
},
|
|
3125
|
+
"GitInfo": {
|
|
3126
|
+
"properties": {
|
|
3127
|
+
"branch": { "type": ["string", "null"] },
|
|
3128
|
+
"originUrl": { "type": ["string", "null"] },
|
|
3129
|
+
"sha": { "type": ["string", "null"] }
|
|
3130
|
+
},
|
|
3131
|
+
"type": "object"
|
|
3132
|
+
},
|
|
3133
|
+
"HookPromptFragment": {
|
|
3134
|
+
"properties": {
|
|
3135
|
+
"hookRunId": { "type": "string" },
|
|
3136
|
+
"text": { "type": "string" }
|
|
3137
|
+
},
|
|
3138
|
+
"required": ["hookRunId", "text"],
|
|
3139
|
+
"type": "object"
|
|
3140
|
+
},
|
|
3141
|
+
"ImageDetail": {
|
|
3142
|
+
"enum": [
|
|
3143
|
+
"auto",
|
|
3144
|
+
"low",
|
|
3145
|
+
"high",
|
|
3146
|
+
"original"
|
|
3147
|
+
],
|
|
3148
|
+
"type": "string"
|
|
3149
|
+
},
|
|
3150
|
+
"ImageGenerationFailure": { "oneOf": [{
|
|
3151
|
+
"properties": {
|
|
3152
|
+
"limitId": { "type": "string" },
|
|
3153
|
+
"resetsAt": {
|
|
3154
|
+
"format": "int64",
|
|
3155
|
+
"type": ["integer", "null"]
|
|
3156
|
+
},
|
|
3157
|
+
"type": {
|
|
3158
|
+
"enum": ["usageLimitExceeded"],
|
|
3159
|
+
"title": "UsageLimitExceededImageGenerationFailureType",
|
|
3160
|
+
"type": "string"
|
|
3161
|
+
}
|
|
3162
|
+
},
|
|
3163
|
+
"required": ["limitId", "type"],
|
|
3164
|
+
"title": "UsageLimitExceededImageGenerationFailure",
|
|
3165
|
+
"type": "object"
|
|
3166
|
+
}] },
|
|
3167
|
+
"InputModality": {
|
|
3168
|
+
"description": "Canonical user-input modality tags advertised by a model.",
|
|
3169
|
+
"oneOf": [
|
|
3170
|
+
{
|
|
3171
|
+
"description": "Plain text turns and tool payloads.",
|
|
3172
|
+
"enum": ["text"],
|
|
3173
|
+
"type": "string"
|
|
3174
|
+
},
|
|
3175
|
+
{
|
|
3176
|
+
"description": "Image attachments included in user turns.",
|
|
3177
|
+
"enum": ["image"],
|
|
3178
|
+
"type": "string"
|
|
3179
|
+
},
|
|
3180
|
+
{
|
|
3181
|
+
"description": "Audio attachments included in user turns.",
|
|
3182
|
+
"enum": ["audio"],
|
|
3183
|
+
"type": "string"
|
|
3184
|
+
}
|
|
3185
|
+
]
|
|
3186
|
+
},
|
|
3187
|
+
"LegacyAppPathString": { "type": "string" },
|
|
3188
|
+
"McpToolCallAppContext": {
|
|
3189
|
+
"properties": {
|
|
3190
|
+
"actionName": { "type": ["string", "null"] },
|
|
3191
|
+
"appName": { "type": ["string", "null"] },
|
|
3192
|
+
"connectorId": { "type": "string" },
|
|
3193
|
+
"linkId": { "type": ["string", "null"] },
|
|
3194
|
+
"resourceUri": { "type": ["string", "null"] }
|
|
3195
|
+
},
|
|
3196
|
+
"required": ["connectorId"],
|
|
3197
|
+
"type": "object"
|
|
3198
|
+
},
|
|
3199
|
+
"McpToolCallError": {
|
|
3200
|
+
"properties": { "message": { "type": "string" } },
|
|
3201
|
+
"required": ["message"],
|
|
3202
|
+
"type": "object"
|
|
3203
|
+
},
|
|
3204
|
+
"McpToolCallResult": {
|
|
3205
|
+
"properties": {
|
|
3206
|
+
"_meta": true,
|
|
3207
|
+
"content": {
|
|
3208
|
+
"items": true,
|
|
3209
|
+
"type": "array"
|
|
3210
|
+
},
|
|
3211
|
+
"structuredContent": true
|
|
3212
|
+
},
|
|
3213
|
+
"required": ["content"],
|
|
3214
|
+
"type": "object"
|
|
3215
|
+
},
|
|
3216
|
+
"McpToolCallStatus": {
|
|
3217
|
+
"enum": [
|
|
3218
|
+
"inProgress",
|
|
3219
|
+
"completed",
|
|
3220
|
+
"failed"
|
|
3221
|
+
],
|
|
3222
|
+
"type": "string"
|
|
3223
|
+
},
|
|
3224
|
+
"MemoryCitation": {
|
|
3225
|
+
"properties": {
|
|
3226
|
+
"entries": {
|
|
3227
|
+
"items": { "$ref": "#/definitions/MemoryCitationEntry" },
|
|
3228
|
+
"type": "array"
|
|
3229
|
+
},
|
|
3230
|
+
"threadIds": {
|
|
3231
|
+
"items": { "type": "string" },
|
|
3232
|
+
"type": "array"
|
|
3233
|
+
}
|
|
3234
|
+
},
|
|
3235
|
+
"required": ["entries", "threadIds"],
|
|
3236
|
+
"type": "object"
|
|
3237
|
+
},
|
|
3238
|
+
"MemoryCitationEntry": {
|
|
3239
|
+
"properties": {
|
|
3240
|
+
"lineEnd": {
|
|
3241
|
+
"format": "uint32",
|
|
3242
|
+
"minimum": 0,
|
|
3243
|
+
"type": "integer"
|
|
3244
|
+
},
|
|
3245
|
+
"lineStart": {
|
|
3246
|
+
"format": "uint32",
|
|
3247
|
+
"minimum": 0,
|
|
3248
|
+
"type": "integer"
|
|
3249
|
+
},
|
|
3250
|
+
"note": { "type": "string" },
|
|
3251
|
+
"path": { "type": "string" }
|
|
3252
|
+
},
|
|
3253
|
+
"required": [
|
|
3254
|
+
"lineEnd",
|
|
3255
|
+
"lineStart",
|
|
3256
|
+
"note",
|
|
3257
|
+
"path"
|
|
3258
|
+
],
|
|
3259
|
+
"type": "object"
|
|
3260
|
+
},
|
|
3261
|
+
"MessagePhase": {
|
|
3262
|
+
"description": "Classifies an assistant message as interim commentary or final answer text.\n\nProviders do not emit this consistently, so callers must treat `None` as \"phase unknown\" and keep compatibility behavior for legacy models.",
|
|
3263
|
+
"oneOf": [{
|
|
3264
|
+
"description": "Mid-turn assistant text (for example preamble/progress narration).\n\nAdditional tool calls or assistant output may follow before turn completion.",
|
|
3265
|
+
"enum": ["commentary"],
|
|
3266
|
+
"type": "string"
|
|
3267
|
+
}, {
|
|
3268
|
+
"description": "The assistant's terminal answer text for the current turn.",
|
|
3269
|
+
"enum": ["final_answer"],
|
|
3270
|
+
"type": "string"
|
|
3271
|
+
}]
|
|
3272
|
+
},
|
|
3273
|
+
"MisalignmentErrorDetails": {
|
|
3274
|
+
"properties": {
|
|
3275
|
+
"detailedExplanation": {
|
|
3276
|
+
"description": "A substantive localized explanation is required before offering continuation.",
|
|
3277
|
+
"type": ["string", "null"]
|
|
3278
|
+
},
|
|
3279
|
+
"errorType": {
|
|
3280
|
+
"description": "Open-ended classification; clients must accept categories added by Responses.",
|
|
3281
|
+
"type": ["string", "null"]
|
|
3282
|
+
},
|
|
3283
|
+
"steer": {
|
|
3284
|
+
"anyOf": [{ "$ref": "#/definitions/MisalignmentSteer" }, { "type": "null" }],
|
|
3285
|
+
"description": "Instruction to submit as the next turn's user input if continuation is confirmed."
|
|
3286
|
+
}
|
|
3287
|
+
},
|
|
3288
|
+
"type": "object"
|
|
3289
|
+
},
|
|
3290
|
+
"MisalignmentSteer": {
|
|
3291
|
+
"properties": { "message": { "type": "string" } },
|
|
3292
|
+
"required": ["message"],
|
|
3293
|
+
"type": "object"
|
|
3294
|
+
},
|
|
3295
|
+
"Model": {
|
|
3296
|
+
"properties": {
|
|
3297
|
+
"additionalSpeedTiers": {
|
|
3298
|
+
"default": [],
|
|
3299
|
+
"description": "Deprecated: use `serviceTiers` instead.",
|
|
3300
|
+
"items": { "type": "string" },
|
|
3301
|
+
"type": "array"
|
|
3302
|
+
},
|
|
3303
|
+
"availabilityNux": { "anyOf": [{ "$ref": "#/definitions/ModelAvailabilityNux" }, { "type": "null" }] },
|
|
3304
|
+
"defaultReasoningEffort": { "$ref": "#/definitions/ReasoningEffort" },
|
|
3305
|
+
"defaultServiceTier": {
|
|
3306
|
+
"default": null,
|
|
3307
|
+
"description": "Catalog default service tier id for this model, when one is configured.",
|
|
3308
|
+
"type": ["string", "null"]
|
|
3309
|
+
},
|
|
3310
|
+
"description": { "type": "string" },
|
|
3311
|
+
"displayName": { "type": "string" },
|
|
3312
|
+
"hidden": { "type": "boolean" },
|
|
3313
|
+
"id": { "type": "string" },
|
|
3314
|
+
"inputModalities": {
|
|
3315
|
+
"default": ["text", "image"],
|
|
3316
|
+
"items": { "$ref": "#/definitions/InputModality" },
|
|
3317
|
+
"type": "array"
|
|
3318
|
+
},
|
|
3319
|
+
"isDefault": { "type": "boolean" },
|
|
3320
|
+
"model": { "type": "string" },
|
|
3321
|
+
"modelSpecialty": {
|
|
3322
|
+
"default": null,
|
|
3323
|
+
"type": ["string", "null"]
|
|
3324
|
+
},
|
|
3325
|
+
"multiAgentVersion": {
|
|
3326
|
+
"anyOf": [{ "$ref": "#/definitions/MultiAgentVersion" }, { "type": "null" }],
|
|
3327
|
+
"description": "Multi-agent runtime declared by this model, when available."
|
|
3328
|
+
},
|
|
3329
|
+
"serviceTiers": {
|
|
3330
|
+
"default": [],
|
|
3331
|
+
"items": { "$ref": "#/definitions/ModelServiceTier" },
|
|
3332
|
+
"type": "array"
|
|
3333
|
+
},
|
|
3334
|
+
"supportedReasoningEfforts": {
|
|
3335
|
+
"items": { "$ref": "#/definitions/ReasoningEffortOption" },
|
|
3336
|
+
"type": "array"
|
|
3337
|
+
},
|
|
3338
|
+
"supportsPersonality": {
|
|
3339
|
+
"default": false,
|
|
3340
|
+
"type": "boolean"
|
|
3341
|
+
},
|
|
3342
|
+
"upgrade": { "type": ["string", "null"] },
|
|
3343
|
+
"upgradeInfo": { "anyOf": [{ "$ref": "#/definitions/ModelUpgradeInfo" }, { "type": "null" }] }
|
|
3344
|
+
},
|
|
3345
|
+
"required": [
|
|
3346
|
+
"defaultReasoningEffort",
|
|
3347
|
+
"description",
|
|
3348
|
+
"displayName",
|
|
3349
|
+
"hidden",
|
|
3350
|
+
"id",
|
|
3351
|
+
"isDefault",
|
|
3352
|
+
"model",
|
|
3353
|
+
"supportedReasoningEfforts"
|
|
3354
|
+
],
|
|
3355
|
+
"type": "object"
|
|
3356
|
+
},
|
|
3357
|
+
"ModelAvailabilityNux": {
|
|
3358
|
+
"properties": { "message": { "type": "string" } },
|
|
3359
|
+
"required": ["message"],
|
|
3360
|
+
"type": "object"
|
|
3361
|
+
},
|
|
3362
|
+
"ModelServiceTier": {
|
|
3363
|
+
"properties": {
|
|
3364
|
+
"description": { "type": "string" },
|
|
3365
|
+
"id": { "type": "string" },
|
|
3366
|
+
"name": { "type": "string" }
|
|
3367
|
+
},
|
|
3368
|
+
"required": [
|
|
3369
|
+
"description",
|
|
3370
|
+
"id",
|
|
3371
|
+
"name"
|
|
3372
|
+
],
|
|
3373
|
+
"type": "object"
|
|
3374
|
+
},
|
|
3375
|
+
"ModelUpgradeInfo": {
|
|
3376
|
+
"properties": {
|
|
3377
|
+
"migrationMarkdown": { "type": ["string", "null"] },
|
|
3378
|
+
"model": { "type": "string" },
|
|
3379
|
+
"modelLink": { "type": ["string", "null"] },
|
|
3380
|
+
"retirementAt": {
|
|
3381
|
+
"description": "Informational Unix timestamp for this upgrade's scheduled retirement, if known.",
|
|
3382
|
+
"format": "int64",
|
|
3383
|
+
"type": ["integer", "null"]
|
|
3384
|
+
},
|
|
3385
|
+
"upgradeCopy": { "type": ["string", "null"] }
|
|
3386
|
+
},
|
|
3387
|
+
"required": ["model"],
|
|
3388
|
+
"type": "object"
|
|
3389
|
+
},
|
|
3390
|
+
"MultiAgentMode": {
|
|
3391
|
+
"description": "Controls the effective multi-agent delegation instructions for a turn. `custom` means the configured mode hint defines the policy instead of a built-in policy.",
|
|
3392
|
+
"oneOf": [{
|
|
3393
|
+
"additionalProperties": false,
|
|
3394
|
+
"properties": { "custom": { "type": "string" } },
|
|
3395
|
+
"required": ["custom"],
|
|
3396
|
+
"title": "CustomMultiAgentMode",
|
|
3397
|
+
"type": "object"
|
|
3398
|
+
}, {
|
|
3399
|
+
"enum": ["explicitRequestOnly", "proactive"],
|
|
3400
|
+
"type": "string"
|
|
3401
|
+
}]
|
|
3402
|
+
},
|
|
3403
|
+
"MultiAgentVersion": {
|
|
3404
|
+
"description": "Multi-agent runtime supported by a model.",
|
|
3405
|
+
"enum": [
|
|
3406
|
+
"disabled",
|
|
3407
|
+
"v1",
|
|
3408
|
+
"v2"
|
|
3409
|
+
],
|
|
3410
|
+
"type": "string"
|
|
3411
|
+
},
|
|
3412
|
+
"NetworkAccess": {
|
|
3413
|
+
"enum": ["restricted", "enabled"],
|
|
3414
|
+
"type": "string"
|
|
3415
|
+
},
|
|
3416
|
+
"NonSteerableTurnKind": {
|
|
3417
|
+
"enum": ["review", "compact"],
|
|
3418
|
+
"type": "string"
|
|
3419
|
+
},
|
|
3420
|
+
"PatchApplyStatus": {
|
|
3421
|
+
"enum": [
|
|
3422
|
+
"inProgress",
|
|
3423
|
+
"completed",
|
|
3424
|
+
"failed",
|
|
3425
|
+
"declined"
|
|
3426
|
+
],
|
|
3427
|
+
"type": "string"
|
|
3428
|
+
},
|
|
3429
|
+
"PatchChangeKind": { "oneOf": [
|
|
3430
|
+
{
|
|
3431
|
+
"properties": { "type": {
|
|
3432
|
+
"enum": ["add"],
|
|
3433
|
+
"title": "AddPatchChangeKindType",
|
|
3434
|
+
"type": "string"
|
|
3435
|
+
} },
|
|
3436
|
+
"required": ["type"],
|
|
3437
|
+
"title": "AddPatchChangeKind",
|
|
3438
|
+
"type": "object"
|
|
3439
|
+
},
|
|
3440
|
+
{
|
|
3441
|
+
"properties": { "type": {
|
|
3442
|
+
"enum": ["delete"],
|
|
3443
|
+
"title": "DeletePatchChangeKindType",
|
|
3444
|
+
"type": "string"
|
|
3445
|
+
} },
|
|
3446
|
+
"required": ["type"],
|
|
3447
|
+
"title": "DeletePatchChangeKind",
|
|
3448
|
+
"type": "object"
|
|
3449
|
+
},
|
|
3450
|
+
{
|
|
3451
|
+
"properties": {
|
|
3452
|
+
"move_path": { "type": ["string", "null"] },
|
|
3453
|
+
"type": {
|
|
3454
|
+
"enum": ["update"],
|
|
3455
|
+
"title": "UpdatePatchChangeKindType",
|
|
3456
|
+
"type": "string"
|
|
3457
|
+
}
|
|
3458
|
+
},
|
|
3459
|
+
"required": ["type"],
|
|
3460
|
+
"title": "UpdatePatchChangeKind",
|
|
3461
|
+
"type": "object"
|
|
3462
|
+
}
|
|
3463
|
+
] },
|
|
3464
|
+
"PlanType": {
|
|
3465
|
+
"enum": [
|
|
3466
|
+
"free",
|
|
3467
|
+
"go",
|
|
3468
|
+
"plus",
|
|
3469
|
+
"pro",
|
|
3470
|
+
"prolite",
|
|
3471
|
+
"team",
|
|
3472
|
+
"self_serve_business_prolite",
|
|
3473
|
+
"self_serve_business_usage_based",
|
|
3474
|
+
"business",
|
|
3475
|
+
"ent26",
|
|
3476
|
+
"enterprise_cbp_automation",
|
|
3477
|
+
"enterprise_cbp_usage_based",
|
|
3478
|
+
"enterprise",
|
|
3479
|
+
"edu",
|
|
3480
|
+
"edu_plus",
|
|
3481
|
+
"edu_pro",
|
|
3482
|
+
"unknown"
|
|
3483
|
+
],
|
|
3484
|
+
"type": "string"
|
|
3485
|
+
},
|
|
3486
|
+
"ReasoningEffort": {
|
|
3487
|
+
"description": "A non-empty reasoning effort value advertised by the model.",
|
|
3488
|
+
"minLength": 1,
|
|
3489
|
+
"type": "string"
|
|
3490
|
+
},
|
|
3491
|
+
"ReasoningEffortOption": {
|
|
3492
|
+
"properties": {
|
|
3493
|
+
"description": { "type": "string" },
|
|
3494
|
+
"reasoningEffort": { "$ref": "#/definitions/ReasoningEffort" }
|
|
3495
|
+
},
|
|
3496
|
+
"required": ["description", "reasoningEffort"],
|
|
3497
|
+
"type": "object"
|
|
3498
|
+
},
|
|
3499
|
+
"SandboxPolicy": { "oneOf": [
|
|
3500
|
+
{
|
|
3501
|
+
"properties": { "type": {
|
|
3502
|
+
"enum": ["dangerFullAccess"],
|
|
3503
|
+
"title": "DangerFullAccessSandboxPolicyType",
|
|
3504
|
+
"type": "string"
|
|
3505
|
+
} },
|
|
3506
|
+
"required": ["type"],
|
|
3507
|
+
"title": "DangerFullAccessSandboxPolicy",
|
|
3508
|
+
"type": "object"
|
|
3509
|
+
},
|
|
3510
|
+
{
|
|
3511
|
+
"properties": {
|
|
3512
|
+
"networkAccess": {
|
|
3513
|
+
"default": false,
|
|
3514
|
+
"type": "boolean"
|
|
3515
|
+
},
|
|
3516
|
+
"type": {
|
|
3517
|
+
"enum": ["readOnly"],
|
|
3518
|
+
"title": "ReadOnlySandboxPolicyType",
|
|
3519
|
+
"type": "string"
|
|
3520
|
+
}
|
|
3521
|
+
},
|
|
3522
|
+
"required": ["type"],
|
|
3523
|
+
"title": "ReadOnlySandboxPolicy",
|
|
3524
|
+
"type": "object"
|
|
3525
|
+
},
|
|
3526
|
+
{
|
|
3527
|
+
"properties": {
|
|
3528
|
+
"networkAccess": {
|
|
3529
|
+
"allOf": [{ "$ref": "#/definitions/NetworkAccess" }],
|
|
3530
|
+
"default": "restricted"
|
|
3531
|
+
},
|
|
3532
|
+
"type": {
|
|
3533
|
+
"enum": ["externalSandbox"],
|
|
3534
|
+
"title": "ExternalSandboxSandboxPolicyType",
|
|
3535
|
+
"type": "string"
|
|
3536
|
+
}
|
|
3537
|
+
},
|
|
3538
|
+
"required": ["type"],
|
|
3539
|
+
"title": "ExternalSandboxSandboxPolicy",
|
|
3540
|
+
"type": "object"
|
|
3541
|
+
},
|
|
3542
|
+
{
|
|
3543
|
+
"properties": {
|
|
3544
|
+
"excludeSlashTmp": {
|
|
3545
|
+
"default": false,
|
|
3546
|
+
"type": "boolean"
|
|
3547
|
+
},
|
|
3548
|
+
"excludeTmpdirEnvVar": {
|
|
3549
|
+
"default": false,
|
|
3550
|
+
"type": "boolean"
|
|
3551
|
+
},
|
|
3552
|
+
"networkAccess": {
|
|
3553
|
+
"default": false,
|
|
3554
|
+
"type": "boolean"
|
|
3555
|
+
},
|
|
3556
|
+
"type": {
|
|
3557
|
+
"enum": ["workspaceWrite"],
|
|
3558
|
+
"title": "WorkspaceWriteSandboxPolicyType",
|
|
3559
|
+
"type": "string"
|
|
3560
|
+
},
|
|
3561
|
+
"writableRoots": {
|
|
3562
|
+
"default": [],
|
|
3563
|
+
"items": { "$ref": "#/definitions/AbsolutePathBuf" },
|
|
3564
|
+
"type": "array"
|
|
3565
|
+
}
|
|
3566
|
+
},
|
|
3567
|
+
"required": ["type"],
|
|
3568
|
+
"title": "WorkspaceWriteSandboxPolicy",
|
|
3569
|
+
"type": "object"
|
|
3570
|
+
}
|
|
3571
|
+
] },
|
|
3572
|
+
"SessionSource": { "oneOf": [
|
|
3573
|
+
{
|
|
3574
|
+
"additionalProperties": false,
|
|
3575
|
+
"properties": { "custom": { "type": "string" } },
|
|
3576
|
+
"required": ["custom"],
|
|
3577
|
+
"title": "CustomSessionSource",
|
|
3578
|
+
"type": "object"
|
|
3579
|
+
},
|
|
3580
|
+
{
|
|
3581
|
+
"additionalProperties": false,
|
|
3582
|
+
"properties": { "subAgent": { "$ref": "#/definitions/SubAgentSource" } },
|
|
3583
|
+
"required": ["subAgent"],
|
|
3584
|
+
"title": "SubAgentSessionSource",
|
|
3585
|
+
"type": "object"
|
|
3586
|
+
},
|
|
3587
|
+
{
|
|
3588
|
+
"enum": [
|
|
3589
|
+
"cli",
|
|
3590
|
+
"vscode",
|
|
3591
|
+
"exec",
|
|
3592
|
+
"appServer",
|
|
3593
|
+
"unknown"
|
|
3594
|
+
],
|
|
3595
|
+
"type": "string"
|
|
3596
|
+
}
|
|
3597
|
+
] },
|
|
3598
|
+
"SubAgentActivityKind": {
|
|
3599
|
+
"enum": [
|
|
3600
|
+
"started",
|
|
3601
|
+
"interacted",
|
|
3602
|
+
"interrupted",
|
|
3603
|
+
"completed"
|
|
3604
|
+
],
|
|
3605
|
+
"type": "string"
|
|
3606
|
+
},
|
|
3607
|
+
"SubAgentSource": { "oneOf": [
|
|
3608
|
+
{
|
|
3609
|
+
"additionalProperties": false,
|
|
3610
|
+
"properties": { "thread_spawn": {
|
|
3611
|
+
"properties": {
|
|
3612
|
+
"agent_nickname": {
|
|
3613
|
+
"default": null,
|
|
3614
|
+
"type": ["string", "null"]
|
|
3615
|
+
},
|
|
3616
|
+
"agent_path": {
|
|
3617
|
+
"anyOf": [{ "$ref": "#/definitions/AgentPath" }, { "type": "null" }],
|
|
3618
|
+
"default": null
|
|
3619
|
+
},
|
|
3620
|
+
"agent_role": {
|
|
3621
|
+
"default": null,
|
|
3622
|
+
"type": ["string", "null"]
|
|
3623
|
+
},
|
|
3624
|
+
"depth": {
|
|
3625
|
+
"format": "int32",
|
|
3626
|
+
"type": "integer"
|
|
3627
|
+
},
|
|
3628
|
+
"parent_thread_id": { "$ref": "#/definitions/ThreadId" }
|
|
3629
|
+
},
|
|
3630
|
+
"required": ["depth", "parent_thread_id"],
|
|
3631
|
+
"type": "object"
|
|
3632
|
+
} },
|
|
3633
|
+
"required": ["thread_spawn"],
|
|
3634
|
+
"title": "ThreadSpawnSubAgentSource",
|
|
3635
|
+
"type": "object"
|
|
3636
|
+
},
|
|
3637
|
+
{
|
|
3638
|
+
"additionalProperties": false,
|
|
3639
|
+
"properties": { "other": { "type": "string" } },
|
|
3640
|
+
"required": ["other"],
|
|
3641
|
+
"title": "OtherSubAgentSource",
|
|
3642
|
+
"type": "object"
|
|
3643
|
+
},
|
|
3644
|
+
{
|
|
3645
|
+
"enum": [
|
|
3646
|
+
"review",
|
|
3647
|
+
"compact",
|
|
3648
|
+
"memory_consolidation"
|
|
3649
|
+
],
|
|
3650
|
+
"type": "string"
|
|
3651
|
+
}
|
|
3652
|
+
] },
|
|
3653
|
+
"TextElement": {
|
|
3654
|
+
"properties": {
|
|
3655
|
+
"byteRange": {
|
|
3656
|
+
"allOf": [{ "$ref": "#/definitions/ByteRange" }],
|
|
3657
|
+
"description": "Byte range in the parent `text` buffer that this element occupies."
|
|
3658
|
+
},
|
|
3659
|
+
"placeholder": {
|
|
3660
|
+
"description": "Optional human-readable placeholder for the element, displayed in the UI.",
|
|
3661
|
+
"type": ["string", "null"]
|
|
3662
|
+
}
|
|
3663
|
+
},
|
|
3664
|
+
"required": ["byteRange"],
|
|
3665
|
+
"type": "object"
|
|
3666
|
+
},
|
|
3667
|
+
"Thread": {
|
|
3668
|
+
"properties": {
|
|
3669
|
+
"agentNickname": {
|
|
3670
|
+
"description": "Optional random unique nickname assigned to an AgentControl-spawned sub-agent.",
|
|
3671
|
+
"type": ["string", "null"]
|
|
3672
|
+
},
|
|
3673
|
+
"agentRole": {
|
|
3674
|
+
"description": "Optional role (agent_role) assigned to an AgentControl-spawned sub-agent.",
|
|
3675
|
+
"type": ["string", "null"]
|
|
3676
|
+
},
|
|
3677
|
+
"canAcceptDirectInput": {
|
|
3678
|
+
"description": "Whether the app server accepts direct turn input for this loaded thread. `None` means the capability is unavailable, such as for an unloaded stored thread.",
|
|
3679
|
+
"type": ["boolean", "null"]
|
|
3680
|
+
},
|
|
3681
|
+
"cliVersion": {
|
|
3682
|
+
"description": "Version of the CLI that created the thread.",
|
|
3683
|
+
"type": "string"
|
|
3684
|
+
},
|
|
3685
|
+
"createdAt": {
|
|
3686
|
+
"description": "Unix timestamp (in seconds) when the thread was created.",
|
|
3687
|
+
"format": "int64",
|
|
3688
|
+
"type": "integer"
|
|
3689
|
+
},
|
|
3690
|
+
"cwd": {
|
|
3691
|
+
"allOf": [{ "$ref": "#/definitions/AbsolutePathBuf" }],
|
|
3692
|
+
"description": "Working directory captured for the thread."
|
|
3693
|
+
},
|
|
3694
|
+
"ephemeral": {
|
|
3695
|
+
"description": "Whether the thread is ephemeral and should not be materialized on disk.",
|
|
3696
|
+
"type": "boolean"
|
|
3697
|
+
},
|
|
3698
|
+
"extra": {
|
|
3699
|
+
"anyOf": [{ "$ref": "#/definitions/ThreadExtra" }, { "type": "null" }],
|
|
3700
|
+
"description": "Optional implementation-specific thread data."
|
|
3701
|
+
},
|
|
3702
|
+
"forkedFromId": {
|
|
3703
|
+
"description": "Source thread id when this thread was created by forking another thread.",
|
|
3704
|
+
"type": ["string", "null"]
|
|
3705
|
+
},
|
|
3706
|
+
"gitInfo": {
|
|
3707
|
+
"anyOf": [{ "$ref": "#/definitions/GitInfo" }, { "type": "null" }],
|
|
3708
|
+
"description": "Optional Git metadata captured when the thread was created."
|
|
3709
|
+
},
|
|
3710
|
+
"historyMode": {
|
|
3711
|
+
"allOf": [{ "$ref": "#/definitions/ThreadHistoryMode" }],
|
|
3712
|
+
"default": "legacy",
|
|
3713
|
+
"description": "Persisted thread history contract selected when this thread was created."
|
|
3714
|
+
},
|
|
3715
|
+
"id": {
|
|
3716
|
+
"description": "Identifier for this thread. Codex-generated thread IDs are UUIDv7.",
|
|
3717
|
+
"type": "string"
|
|
3718
|
+
},
|
|
3719
|
+
"modelProvider": {
|
|
3720
|
+
"description": "Model provider used for this thread (for example, 'openai').",
|
|
3721
|
+
"type": "string"
|
|
3722
|
+
},
|
|
3723
|
+
"name": {
|
|
3724
|
+
"description": "Optional user-facing thread title.",
|
|
3725
|
+
"type": ["string", "null"]
|
|
3726
|
+
},
|
|
3727
|
+
"parentThreadId": {
|
|
3728
|
+
"description": "The ID of the parent thread. This will only be set if this thread is a subagent.",
|
|
3729
|
+
"type": ["string", "null"]
|
|
3730
|
+
},
|
|
3731
|
+
"path": {
|
|
3732
|
+
"description": "[UNSTABLE] Path to the thread on disk.",
|
|
3733
|
+
"type": ["string", "null"]
|
|
3734
|
+
},
|
|
3735
|
+
"preview": {
|
|
3736
|
+
"description": "Usually the first user message in the thread, if available.",
|
|
3737
|
+
"type": "string"
|
|
3738
|
+
},
|
|
3739
|
+
"projectId": {
|
|
3740
|
+
"description": "Canonical project assignment owned by app-server, if any.",
|
|
3741
|
+
"type": ["string", "null"]
|
|
3742
|
+
},
|
|
3743
|
+
"recencyAt": {
|
|
3744
|
+
"description": "Unix timestamp (in seconds) used for thread recency ordering.",
|
|
3745
|
+
"format": "int64",
|
|
3746
|
+
"type": ["integer", "null"]
|
|
3747
|
+
},
|
|
3748
|
+
"section": {
|
|
3749
|
+
"anyOf": [{ "$ref": "#/definitions/ThreadSection" }, { "type": "null" }],
|
|
3750
|
+
"default": null,
|
|
3751
|
+
"description": "The independently persisted section selected for this thread, if any."
|
|
3752
|
+
},
|
|
3753
|
+
"sectionEnteredAt": {
|
|
3754
|
+
"default": null,
|
|
3755
|
+
"description": "Unix timestamp in seconds when the thread entered its current section.",
|
|
3756
|
+
"format": "int64",
|
|
3757
|
+
"type": ["integer", "null"]
|
|
3758
|
+
},
|
|
3759
|
+
"sessionId": {
|
|
3760
|
+
"description": "Session id shared by threads that belong to the same session tree.",
|
|
3761
|
+
"type": "string"
|
|
3762
|
+
},
|
|
3763
|
+
"source": {
|
|
3764
|
+
"allOf": [{ "$ref": "#/definitions/SessionSource" }],
|
|
3765
|
+
"description": "Origin of the thread (CLI, VSCode, codex exec, codex app-server, etc.)."
|
|
3766
|
+
},
|
|
3767
|
+
"status": {
|
|
3768
|
+
"allOf": [{ "$ref": "#/definitions/ThreadStatus" }],
|
|
3769
|
+
"description": "Current runtime status for the thread."
|
|
3770
|
+
},
|
|
3771
|
+
"threadSource": {
|
|
3772
|
+
"anyOf": [{ "$ref": "#/definitions/ThreadSource" }, { "type": "null" }],
|
|
3773
|
+
"description": "Optional analytics source classification for this thread."
|
|
3774
|
+
},
|
|
3775
|
+
"turns": {
|
|
3776
|
+
"description": "Only populated on `thread/resume`, `thread/rollback`, `thread/fork`, and `thread/read` (when `includeTurns` is true) responses. For all other responses and notifications returning a Thread, the turns field will be an empty list.",
|
|
3777
|
+
"items": { "$ref": "#/definitions/Turn" },
|
|
3778
|
+
"type": "array"
|
|
3779
|
+
},
|
|
3780
|
+
"updatedAt": {
|
|
3781
|
+
"description": "Unix timestamp (in seconds) when the thread was last updated.",
|
|
3782
|
+
"format": "int64",
|
|
3783
|
+
"type": "integer"
|
|
3784
|
+
}
|
|
3785
|
+
},
|
|
3786
|
+
"required": [
|
|
3787
|
+
"cliVersion",
|
|
3788
|
+
"createdAt",
|
|
3789
|
+
"cwd",
|
|
3790
|
+
"ephemeral",
|
|
3791
|
+
"id",
|
|
3792
|
+
"modelProvider",
|
|
3793
|
+
"preview",
|
|
3794
|
+
"projectId",
|
|
3795
|
+
"sessionId",
|
|
3796
|
+
"source",
|
|
3797
|
+
"status",
|
|
3798
|
+
"turns",
|
|
3799
|
+
"updatedAt"
|
|
3800
|
+
],
|
|
3801
|
+
"type": "object"
|
|
3802
|
+
},
|
|
3803
|
+
"ThreadActiveFlag": {
|
|
3804
|
+
"enum": ["waitingOnApproval", "waitingOnUserInput"],
|
|
3805
|
+
"type": "string"
|
|
3806
|
+
},
|
|
3807
|
+
"ThreadExtra": {
|
|
3808
|
+
"description": "Extra app-server data for a thread.",
|
|
3809
|
+
"type": "object"
|
|
3810
|
+
},
|
|
3811
|
+
"ThreadHistoryMode": {
|
|
3812
|
+
"enum": ["legacy", "paginated"],
|
|
3813
|
+
"type": "string"
|
|
3814
|
+
},
|
|
3815
|
+
"ThreadId": { "type": "string" },
|
|
3816
|
+
"ThreadItem": { "oneOf": [
|
|
3817
|
+
{
|
|
3818
|
+
"properties": {
|
|
3819
|
+
"clientId": { "type": ["string", "null"] },
|
|
3820
|
+
"content": {
|
|
3821
|
+
"items": { "$ref": "#/definitions/UserInput" },
|
|
3822
|
+
"type": "array"
|
|
3823
|
+
},
|
|
3824
|
+
"id": { "type": "string" },
|
|
3825
|
+
"type": {
|
|
3826
|
+
"enum": ["userMessage"],
|
|
3827
|
+
"title": "UserMessageThreadItemType",
|
|
3828
|
+
"type": "string"
|
|
3829
|
+
}
|
|
3830
|
+
},
|
|
3831
|
+
"required": [
|
|
3832
|
+
"content",
|
|
3833
|
+
"id",
|
|
3834
|
+
"type"
|
|
3835
|
+
],
|
|
3836
|
+
"title": "UserMessageThreadItem",
|
|
3837
|
+
"type": "object"
|
|
3838
|
+
},
|
|
3839
|
+
{
|
|
3840
|
+
"properties": {
|
|
3841
|
+
"fragments": {
|
|
3842
|
+
"items": { "$ref": "#/definitions/HookPromptFragment" },
|
|
3843
|
+
"type": "array"
|
|
3844
|
+
},
|
|
3845
|
+
"id": { "type": "string" },
|
|
3846
|
+
"type": {
|
|
3847
|
+
"enum": ["hookPrompt"],
|
|
3848
|
+
"title": "HookPromptThreadItemType",
|
|
3849
|
+
"type": "string"
|
|
3850
|
+
}
|
|
3851
|
+
},
|
|
3852
|
+
"required": [
|
|
3853
|
+
"fragments",
|
|
3854
|
+
"id",
|
|
3855
|
+
"type"
|
|
3856
|
+
],
|
|
3857
|
+
"title": "HookPromptThreadItem",
|
|
3858
|
+
"type": "object"
|
|
3859
|
+
},
|
|
3860
|
+
{
|
|
3861
|
+
"properties": {
|
|
3862
|
+
"delivery": {
|
|
3863
|
+
"anyOf": [{ "$ref": "#/definitions/AgentMessageDelivery" }, { "type": "null" }],
|
|
3864
|
+
"default": null
|
|
3865
|
+
},
|
|
3866
|
+
"id": { "type": "string" },
|
|
3867
|
+
"memoryCitation": {
|
|
3868
|
+
"anyOf": [{ "$ref": "#/definitions/MemoryCitation" }, { "type": "null" }],
|
|
3869
|
+
"default": null
|
|
3870
|
+
},
|
|
3871
|
+
"phase": {
|
|
3872
|
+
"anyOf": [{ "$ref": "#/definitions/MessagePhase" }, { "type": "null" }],
|
|
3873
|
+
"default": null
|
|
3874
|
+
},
|
|
3875
|
+
"text": { "type": "string" },
|
|
3876
|
+
"type": {
|
|
3877
|
+
"enum": ["agentMessage"],
|
|
3878
|
+
"title": "AgentMessageThreadItemType",
|
|
3879
|
+
"type": "string"
|
|
3880
|
+
}
|
|
3881
|
+
},
|
|
3882
|
+
"required": [
|
|
3883
|
+
"id",
|
|
3884
|
+
"text",
|
|
3885
|
+
"type"
|
|
3886
|
+
],
|
|
3887
|
+
"title": "AgentMessageThreadItem",
|
|
3888
|
+
"type": "object"
|
|
3889
|
+
},
|
|
3890
|
+
{
|
|
3891
|
+
"properties": {
|
|
3892
|
+
"id": { "type": "string" },
|
|
3893
|
+
"name": { "type": "string" },
|
|
3894
|
+
"namespace": { "type": ["string", "null"] },
|
|
3895
|
+
"output": { "$ref": "#/definitions/FunctionCallOutputBody" },
|
|
3896
|
+
"type": {
|
|
3897
|
+
"enum": ["functionCallOutput"],
|
|
3898
|
+
"title": "FunctionCallOutputThreadItemType",
|
|
3899
|
+
"type": "string"
|
|
3900
|
+
}
|
|
3901
|
+
},
|
|
3902
|
+
"required": [
|
|
3903
|
+
"id",
|
|
3904
|
+
"name",
|
|
3905
|
+
"output",
|
|
3906
|
+
"type"
|
|
3907
|
+
],
|
|
3908
|
+
"title": "FunctionCallOutputThreadItem",
|
|
3909
|
+
"type": "object"
|
|
3910
|
+
},
|
|
3911
|
+
{
|
|
3912
|
+
"description": "EXPERIMENTAL - proposed plan item content. The completed plan item is authoritative and may not match the concatenation of `PlanDelta` text.",
|
|
3913
|
+
"properties": {
|
|
3914
|
+
"id": { "type": "string" },
|
|
3915
|
+
"text": { "type": "string" },
|
|
3916
|
+
"type": {
|
|
3917
|
+
"enum": ["plan"],
|
|
3918
|
+
"title": "PlanThreadItemType",
|
|
3919
|
+
"type": "string"
|
|
3920
|
+
}
|
|
3921
|
+
},
|
|
3922
|
+
"required": [
|
|
3923
|
+
"id",
|
|
3924
|
+
"text",
|
|
3925
|
+
"type"
|
|
3926
|
+
],
|
|
3927
|
+
"title": "PlanThreadItem",
|
|
3928
|
+
"type": "object"
|
|
3929
|
+
},
|
|
3930
|
+
{
|
|
3931
|
+
"properties": {
|
|
3932
|
+
"content": {
|
|
3933
|
+
"default": [],
|
|
3934
|
+
"items": { "type": "string" },
|
|
3935
|
+
"type": "array"
|
|
3936
|
+
},
|
|
3937
|
+
"id": { "type": "string" },
|
|
3938
|
+
"summary": {
|
|
3939
|
+
"default": [],
|
|
3940
|
+
"items": { "type": "string" },
|
|
3941
|
+
"type": "array"
|
|
3942
|
+
},
|
|
3943
|
+
"type": {
|
|
3944
|
+
"enum": ["reasoning"],
|
|
3945
|
+
"title": "ReasoningThreadItemType",
|
|
3946
|
+
"type": "string"
|
|
3947
|
+
}
|
|
3948
|
+
},
|
|
3949
|
+
"required": ["id", "type"],
|
|
3950
|
+
"title": "ReasoningThreadItem",
|
|
3951
|
+
"type": "object"
|
|
3952
|
+
},
|
|
3953
|
+
{
|
|
3954
|
+
"properties": {
|
|
3955
|
+
"aggregatedOutput": {
|
|
3956
|
+
"description": "The command's output, aggregated from stdout and stderr.",
|
|
3957
|
+
"type": ["string", "null"]
|
|
3958
|
+
},
|
|
3959
|
+
"command": {
|
|
3960
|
+
"description": "The command to be executed.",
|
|
3961
|
+
"type": "string"
|
|
3962
|
+
},
|
|
3963
|
+
"commandActions": {
|
|
3964
|
+
"description": "A best-effort parsing of the command to understand the action(s) it will perform. This returns a list of CommandAction objects because a single shell command may be composed of many commands piped together.",
|
|
3965
|
+
"items": { "$ref": "#/definitions/CommandAction" },
|
|
3966
|
+
"type": "array"
|
|
3967
|
+
},
|
|
3968
|
+
"cwd": {
|
|
3969
|
+
"allOf": [{ "$ref": "#/definitions/LegacyAppPathString" }],
|
|
3970
|
+
"description": "The command's working directory."
|
|
3971
|
+
},
|
|
3972
|
+
"durationMs": {
|
|
3973
|
+
"description": "The duration of the command execution in milliseconds.",
|
|
3974
|
+
"format": "int64",
|
|
3975
|
+
"type": ["integer", "null"]
|
|
3976
|
+
},
|
|
3977
|
+
"exitCode": {
|
|
3978
|
+
"description": "The command's exit code.",
|
|
3979
|
+
"format": "int32",
|
|
3980
|
+
"type": ["integer", "null"]
|
|
3981
|
+
},
|
|
3982
|
+
"id": { "type": "string" },
|
|
3983
|
+
"pluginId": {
|
|
3984
|
+
"default": null,
|
|
3985
|
+
"description": "Trusted first-party plugin id when this command resolves to one plugin script.",
|
|
3986
|
+
"type": ["string", "null"]
|
|
3987
|
+
},
|
|
3988
|
+
"processId": {
|
|
3989
|
+
"description": "Identifier for the underlying PTY process (when available).",
|
|
3990
|
+
"type": ["string", "null"]
|
|
3991
|
+
},
|
|
3992
|
+
"scriptPath": {
|
|
3993
|
+
"default": null,
|
|
3994
|
+
"description": "Safe plugin-relative path when this command resolves to one plugin script.",
|
|
3995
|
+
"type": ["string", "null"]
|
|
3996
|
+
},
|
|
3997
|
+
"source": {
|
|
3998
|
+
"allOf": [{ "$ref": "#/definitions/CommandExecutionSource" }],
|
|
3999
|
+
"default": "agent"
|
|
4000
|
+
},
|
|
4001
|
+
"status": { "$ref": "#/definitions/CommandExecutionStatus" },
|
|
4002
|
+
"type": {
|
|
4003
|
+
"enum": ["commandExecution"],
|
|
4004
|
+
"title": "CommandExecutionThreadItemType",
|
|
4005
|
+
"type": "string"
|
|
4006
|
+
}
|
|
4007
|
+
},
|
|
4008
|
+
"required": [
|
|
4009
|
+
"command",
|
|
4010
|
+
"commandActions",
|
|
4011
|
+
"cwd",
|
|
4012
|
+
"id",
|
|
4013
|
+
"status",
|
|
4014
|
+
"type"
|
|
4015
|
+
],
|
|
4016
|
+
"title": "CommandExecutionThreadItem",
|
|
4017
|
+
"type": "object"
|
|
4018
|
+
},
|
|
4019
|
+
{
|
|
4020
|
+
"properties": {
|
|
4021
|
+
"changes": {
|
|
4022
|
+
"items": { "$ref": "#/definitions/FileUpdateChange" },
|
|
4023
|
+
"type": "array"
|
|
4024
|
+
},
|
|
4025
|
+
"id": { "type": "string" },
|
|
4026
|
+
"status": { "$ref": "#/definitions/PatchApplyStatus" },
|
|
4027
|
+
"type": {
|
|
4028
|
+
"enum": ["fileChange"],
|
|
4029
|
+
"title": "FileChangeThreadItemType",
|
|
4030
|
+
"type": "string"
|
|
4031
|
+
}
|
|
4032
|
+
},
|
|
4033
|
+
"required": [
|
|
4034
|
+
"changes",
|
|
4035
|
+
"id",
|
|
4036
|
+
"status",
|
|
4037
|
+
"type"
|
|
4038
|
+
],
|
|
4039
|
+
"title": "FileChangeThreadItem",
|
|
4040
|
+
"type": "object"
|
|
4041
|
+
},
|
|
4042
|
+
{
|
|
4043
|
+
"properties": {
|
|
4044
|
+
"appContext": { "anyOf": [{ "$ref": "#/definitions/McpToolCallAppContext" }, { "type": "null" }] },
|
|
4045
|
+
"arguments": true,
|
|
4046
|
+
"durationMs": {
|
|
4047
|
+
"description": "The duration of the MCP tool call in milliseconds.",
|
|
4048
|
+
"format": "int64",
|
|
4049
|
+
"type": ["integer", "null"]
|
|
4050
|
+
},
|
|
4051
|
+
"error": { "anyOf": [{ "$ref": "#/definitions/McpToolCallError" }, { "type": "null" }] },
|
|
4052
|
+
"id": { "type": "string" },
|
|
4053
|
+
"mcpAppResourceUri": {
|
|
4054
|
+
"description": "Deprecated: use `appContext.resourceUri` instead.",
|
|
4055
|
+
"type": ["string", "null"]
|
|
4056
|
+
},
|
|
4057
|
+
"pluginId": { "type": ["string", "null"] },
|
|
4058
|
+
"readOnlyHint": { "type": ["boolean", "null"] },
|
|
4059
|
+
"result": { "anyOf": [{ "$ref": "#/definitions/McpToolCallResult" }, { "type": "null" }] },
|
|
4060
|
+
"server": { "type": "string" },
|
|
4061
|
+
"status": { "$ref": "#/definitions/McpToolCallStatus" },
|
|
4062
|
+
"tool": { "type": "string" },
|
|
4063
|
+
"type": {
|
|
4064
|
+
"enum": ["mcpToolCall"],
|
|
4065
|
+
"title": "McpToolCallThreadItemType",
|
|
4066
|
+
"type": "string"
|
|
4067
|
+
}
|
|
4068
|
+
},
|
|
4069
|
+
"required": [
|
|
4070
|
+
"arguments",
|
|
4071
|
+
"id",
|
|
4072
|
+
"server",
|
|
4073
|
+
"status",
|
|
4074
|
+
"tool",
|
|
4075
|
+
"type"
|
|
4076
|
+
],
|
|
4077
|
+
"title": "McpToolCallThreadItem",
|
|
4078
|
+
"type": "object"
|
|
4079
|
+
},
|
|
4080
|
+
{
|
|
4081
|
+
"properties": {
|
|
4082
|
+
"arguments": true,
|
|
4083
|
+
"contentItems": {
|
|
4084
|
+
"items": { "$ref": "#/definitions/DynamicToolCallOutputContentItem" },
|
|
4085
|
+
"type": ["array", "null"]
|
|
4086
|
+
},
|
|
4087
|
+
"durationMs": {
|
|
4088
|
+
"description": "The duration of the dynamic tool call in milliseconds.",
|
|
4089
|
+
"format": "int64",
|
|
4090
|
+
"type": ["integer", "null"]
|
|
4091
|
+
},
|
|
4092
|
+
"id": { "type": "string" },
|
|
4093
|
+
"namespace": { "type": ["string", "null"] },
|
|
4094
|
+
"status": { "$ref": "#/definitions/DynamicToolCallStatus" },
|
|
4095
|
+
"success": { "type": ["boolean", "null"] },
|
|
4096
|
+
"tool": { "type": "string" },
|
|
4097
|
+
"type": {
|
|
4098
|
+
"enum": ["dynamicToolCall"],
|
|
4099
|
+
"title": "DynamicToolCallThreadItemType",
|
|
4100
|
+
"type": "string"
|
|
4101
|
+
}
|
|
4102
|
+
},
|
|
4103
|
+
"required": [
|
|
4104
|
+
"arguments",
|
|
4105
|
+
"id",
|
|
4106
|
+
"status",
|
|
4107
|
+
"tool",
|
|
4108
|
+
"type"
|
|
4109
|
+
],
|
|
4110
|
+
"title": "DynamicToolCallThreadItem",
|
|
4111
|
+
"type": "object"
|
|
4112
|
+
},
|
|
4113
|
+
{
|
|
4114
|
+
"properties": {
|
|
4115
|
+
"agentsStates": {
|
|
4116
|
+
"additionalProperties": { "$ref": "#/definitions/CollabAgentState" },
|
|
4117
|
+
"description": "Last known status of the target agents, when available.",
|
|
4118
|
+
"type": "object"
|
|
4119
|
+
},
|
|
4120
|
+
"id": {
|
|
4121
|
+
"description": "Unique identifier for this collab tool call.",
|
|
4122
|
+
"type": "string"
|
|
4123
|
+
},
|
|
4124
|
+
"model": {
|
|
4125
|
+
"description": "Model requested for the spawned agent, when applicable.",
|
|
4126
|
+
"type": ["string", "null"]
|
|
4127
|
+
},
|
|
4128
|
+
"prompt": {
|
|
4129
|
+
"description": "Prompt text sent as part of the collab tool call, when available.",
|
|
4130
|
+
"type": ["string", "null"]
|
|
4131
|
+
},
|
|
4132
|
+
"reasoningEffort": {
|
|
4133
|
+
"anyOf": [{ "$ref": "#/definitions/ReasoningEffort" }, { "type": "null" }],
|
|
4134
|
+
"description": "Reasoning effort requested for the spawned agent, when applicable."
|
|
4135
|
+
},
|
|
4136
|
+
"receiverThreadIds": {
|
|
4137
|
+
"description": "Thread ID of the receiving agent, when applicable. In case of spawn operation, this corresponds to the newly spawned agent.",
|
|
4138
|
+
"items": { "type": "string" },
|
|
4139
|
+
"type": "array"
|
|
4140
|
+
},
|
|
4141
|
+
"senderThreadId": {
|
|
4142
|
+
"description": "Thread ID of the agent issuing the collab request.",
|
|
4143
|
+
"type": "string"
|
|
4144
|
+
},
|
|
4145
|
+
"status": {
|
|
4146
|
+
"allOf": [{ "$ref": "#/definitions/CollabAgentToolCallStatus" }],
|
|
4147
|
+
"description": "Current status of the collab tool call."
|
|
4148
|
+
},
|
|
4149
|
+
"tool": {
|
|
4150
|
+
"allOf": [{ "$ref": "#/definitions/CollabAgentTool" }],
|
|
4151
|
+
"description": "Name of the collab tool that was invoked."
|
|
4152
|
+
},
|
|
4153
|
+
"type": {
|
|
4154
|
+
"enum": ["collabAgentToolCall"],
|
|
4155
|
+
"title": "CollabAgentToolCallThreadItemType",
|
|
4156
|
+
"type": "string"
|
|
4157
|
+
}
|
|
4158
|
+
},
|
|
4159
|
+
"required": [
|
|
4160
|
+
"agentsStates",
|
|
4161
|
+
"id",
|
|
4162
|
+
"receiverThreadIds",
|
|
4163
|
+
"senderThreadId",
|
|
4164
|
+
"status",
|
|
4165
|
+
"tool",
|
|
4166
|
+
"type"
|
|
4167
|
+
],
|
|
4168
|
+
"title": "CollabAgentToolCallThreadItem",
|
|
4169
|
+
"type": "object"
|
|
4170
|
+
},
|
|
4171
|
+
{
|
|
4172
|
+
"properties": {
|
|
4173
|
+
"agentPath": { "type": "string" },
|
|
4174
|
+
"agentThreadId": { "type": "string" },
|
|
4175
|
+
"id": { "type": "string" },
|
|
4176
|
+
"kind": { "$ref": "#/definitions/SubAgentActivityKind" },
|
|
4177
|
+
"type": {
|
|
4178
|
+
"enum": ["subAgentActivity"],
|
|
4179
|
+
"title": "SubAgentActivityThreadItemType",
|
|
4180
|
+
"type": "string"
|
|
4181
|
+
}
|
|
4182
|
+
},
|
|
4183
|
+
"required": [
|
|
4184
|
+
"agentPath",
|
|
4185
|
+
"agentThreadId",
|
|
4186
|
+
"id",
|
|
4187
|
+
"kind",
|
|
4188
|
+
"type"
|
|
4189
|
+
],
|
|
4190
|
+
"title": "SubAgentActivityThreadItem",
|
|
4191
|
+
"type": "object"
|
|
4192
|
+
},
|
|
4193
|
+
{
|
|
4194
|
+
"properties": {
|
|
4195
|
+
"action": { "anyOf": [{ "$ref": "#/definitions/WebSearchAction" }, { "type": "null" }] },
|
|
4196
|
+
"id": { "type": "string" },
|
|
4197
|
+
"query": { "type": "string" },
|
|
4198
|
+
"results": {
|
|
4199
|
+
"default": null,
|
|
4200
|
+
"description": "Structured search results returned out-of-band by standalone web search.\n\nThese stay as opaque JSON at the extension/app-server boundary so new result fields and result types can pass through without a Codex release.",
|
|
4201
|
+
"items": true,
|
|
4202
|
+
"type": ["array", "null"]
|
|
4203
|
+
},
|
|
4204
|
+
"type": {
|
|
4205
|
+
"enum": ["webSearch"],
|
|
4206
|
+
"title": "WebSearchThreadItemType",
|
|
4207
|
+
"type": "string"
|
|
4208
|
+
}
|
|
4209
|
+
},
|
|
4210
|
+
"required": [
|
|
4211
|
+
"id",
|
|
4212
|
+
"query",
|
|
4213
|
+
"type"
|
|
4214
|
+
],
|
|
4215
|
+
"title": "WebSearchThreadItem",
|
|
4216
|
+
"type": "object"
|
|
4217
|
+
},
|
|
4218
|
+
{
|
|
4219
|
+
"properties": {
|
|
4220
|
+
"id": { "type": "string" },
|
|
4221
|
+
"path": { "$ref": "#/definitions/LegacyAppPathString" },
|
|
4222
|
+
"type": {
|
|
4223
|
+
"enum": ["imageView"],
|
|
4224
|
+
"title": "ImageViewThreadItemType",
|
|
4225
|
+
"type": "string"
|
|
4226
|
+
}
|
|
4227
|
+
},
|
|
4228
|
+
"required": [
|
|
4229
|
+
"id",
|
|
4230
|
+
"path",
|
|
4231
|
+
"type"
|
|
4232
|
+
],
|
|
4233
|
+
"title": "ImageViewThreadItem",
|
|
4234
|
+
"type": "object"
|
|
4235
|
+
},
|
|
4236
|
+
{
|
|
4237
|
+
"description": "Display item emitted by the interruptible `clock.sleep` tool.",
|
|
4238
|
+
"properties": {
|
|
4239
|
+
"durationMs": {
|
|
4240
|
+
"format": "uint64",
|
|
4241
|
+
"minimum": 0,
|
|
4242
|
+
"type": "integer"
|
|
4243
|
+
},
|
|
4244
|
+
"id": { "type": "string" },
|
|
4245
|
+
"type": {
|
|
4246
|
+
"enum": ["sleep"],
|
|
4247
|
+
"title": "SleepThreadItemType",
|
|
4248
|
+
"type": "string"
|
|
4249
|
+
}
|
|
4250
|
+
},
|
|
4251
|
+
"required": [
|
|
4252
|
+
"durationMs",
|
|
4253
|
+
"id",
|
|
4254
|
+
"type"
|
|
4255
|
+
],
|
|
4256
|
+
"title": "SleepThreadItem",
|
|
4257
|
+
"type": "object"
|
|
4258
|
+
},
|
|
4259
|
+
{
|
|
4260
|
+
"properties": {
|
|
4261
|
+
"failure": {
|
|
4262
|
+
"anyOf": [{ "$ref": "#/definitions/ImageGenerationFailure" }, { "type": "null" }],
|
|
4263
|
+
"default": null
|
|
4264
|
+
},
|
|
4265
|
+
"id": { "type": "string" },
|
|
4266
|
+
"result": { "type": "string" },
|
|
4267
|
+
"revisedPrompt": { "type": ["string", "null"] },
|
|
4268
|
+
"savedPath": { "anyOf": [{ "$ref": "#/definitions/AbsolutePathBuf" }, { "type": "null" }] },
|
|
4269
|
+
"status": { "type": "string" },
|
|
4270
|
+
"transparentBackground": {
|
|
4271
|
+
"default": null,
|
|
4272
|
+
"type": ["boolean", "null"]
|
|
4273
|
+
},
|
|
4274
|
+
"type": {
|
|
4275
|
+
"enum": ["imageGeneration"],
|
|
4276
|
+
"title": "ImageGenerationThreadItemType",
|
|
4277
|
+
"type": "string"
|
|
4278
|
+
}
|
|
4279
|
+
},
|
|
4280
|
+
"required": [
|
|
4281
|
+
"id",
|
|
4282
|
+
"result",
|
|
4283
|
+
"status",
|
|
4284
|
+
"type"
|
|
4285
|
+
],
|
|
4286
|
+
"title": "ImageGenerationThreadItem",
|
|
4287
|
+
"type": "object"
|
|
4288
|
+
},
|
|
4289
|
+
{
|
|
4290
|
+
"properties": {
|
|
4291
|
+
"id": { "type": "string" },
|
|
4292
|
+
"review": { "type": "string" },
|
|
4293
|
+
"type": {
|
|
4294
|
+
"enum": ["enteredReviewMode"],
|
|
4295
|
+
"title": "EnteredReviewModeThreadItemType",
|
|
4296
|
+
"type": "string"
|
|
4297
|
+
}
|
|
4298
|
+
},
|
|
4299
|
+
"required": [
|
|
4300
|
+
"id",
|
|
4301
|
+
"review",
|
|
4302
|
+
"type"
|
|
4303
|
+
],
|
|
4304
|
+
"title": "EnteredReviewModeThreadItem",
|
|
4305
|
+
"type": "object"
|
|
4306
|
+
},
|
|
4307
|
+
{
|
|
4308
|
+
"properties": {
|
|
4309
|
+
"id": { "type": "string" },
|
|
4310
|
+
"review": { "type": "string" },
|
|
4311
|
+
"type": {
|
|
4312
|
+
"enum": ["exitedReviewMode"],
|
|
4313
|
+
"title": "ExitedReviewModeThreadItemType",
|
|
4314
|
+
"type": "string"
|
|
4315
|
+
}
|
|
4316
|
+
},
|
|
4317
|
+
"required": [
|
|
4318
|
+
"id",
|
|
4319
|
+
"review",
|
|
4320
|
+
"type"
|
|
4321
|
+
],
|
|
4322
|
+
"title": "ExitedReviewModeThreadItem",
|
|
4323
|
+
"type": "object"
|
|
4324
|
+
},
|
|
4325
|
+
{
|
|
4326
|
+
"properties": {
|
|
4327
|
+
"id": { "type": "string" },
|
|
4328
|
+
"type": {
|
|
4329
|
+
"enum": ["contextCompaction"],
|
|
4330
|
+
"title": "ContextCompactionThreadItemType",
|
|
4331
|
+
"type": "string"
|
|
4332
|
+
}
|
|
4333
|
+
},
|
|
4334
|
+
"required": ["id", "type"],
|
|
4335
|
+
"title": "ContextCompactionThreadItem",
|
|
4336
|
+
"type": "object"
|
|
4337
|
+
}
|
|
4338
|
+
] },
|
|
4339
|
+
"ThreadSection": {
|
|
4340
|
+
"description": "An independently persisted, user-visible thread section.",
|
|
4341
|
+
"properties": {
|
|
4342
|
+
"appearance": {
|
|
4343
|
+
"anyOf": [{ "$ref": "#/definitions/ThreadSectionAppearance" }, { "type": "null" }],
|
|
4344
|
+
"default": null,
|
|
4345
|
+
"description": "Optional appearance synchronized across clients."
|
|
4346
|
+
},
|
|
4347
|
+
"id": {
|
|
4348
|
+
"description": "Opaque UUIDv7 identity that remains stable when the section is renamed.",
|
|
4349
|
+
"type": "string"
|
|
4350
|
+
},
|
|
4351
|
+
"name": {
|
|
4352
|
+
"description": "The current user-visible section name.",
|
|
4353
|
+
"type": "string"
|
|
4354
|
+
}
|
|
4355
|
+
},
|
|
4356
|
+
"required": ["id", "name"],
|
|
4357
|
+
"type": "object"
|
|
4358
|
+
},
|
|
4359
|
+
"ThreadSectionAppearance": {
|
|
4360
|
+
"description": "Extensible visual presentation for a custom thread section.",
|
|
4361
|
+
"properties": {
|
|
4362
|
+
"color": { "type": ["string", "null"] },
|
|
4363
|
+
"icon": { "type": ["string", "null"] }
|
|
4364
|
+
},
|
|
4365
|
+
"type": "object"
|
|
4366
|
+
},
|
|
4367
|
+
"ThreadSource": { "type": "string" },
|
|
4368
|
+
"ThreadStatus": { "oneOf": [
|
|
4369
|
+
{
|
|
4370
|
+
"properties": { "type": {
|
|
4371
|
+
"enum": ["notLoaded"],
|
|
4372
|
+
"title": "NotLoadedThreadStatusType",
|
|
4373
|
+
"type": "string"
|
|
4374
|
+
} },
|
|
4375
|
+
"required": ["type"],
|
|
4376
|
+
"title": "NotLoadedThreadStatus",
|
|
4377
|
+
"type": "object"
|
|
4378
|
+
},
|
|
4379
|
+
{
|
|
4380
|
+
"properties": { "type": {
|
|
4381
|
+
"enum": ["idle"],
|
|
4382
|
+
"title": "IdleThreadStatusType",
|
|
4383
|
+
"type": "string"
|
|
4384
|
+
} },
|
|
4385
|
+
"required": ["type"],
|
|
4386
|
+
"title": "IdleThreadStatus",
|
|
4387
|
+
"type": "object"
|
|
4388
|
+
},
|
|
4389
|
+
{
|
|
4390
|
+
"properties": { "type": {
|
|
4391
|
+
"enum": ["systemError"],
|
|
4392
|
+
"title": "SystemErrorThreadStatusType",
|
|
4393
|
+
"type": "string"
|
|
4394
|
+
} },
|
|
4395
|
+
"required": ["type"],
|
|
4396
|
+
"title": "SystemErrorThreadStatus",
|
|
4397
|
+
"type": "object"
|
|
4398
|
+
},
|
|
4399
|
+
{
|
|
4400
|
+
"properties": {
|
|
4401
|
+
"activeFlags": {
|
|
4402
|
+
"items": { "$ref": "#/definitions/ThreadActiveFlag" },
|
|
4403
|
+
"type": "array"
|
|
4404
|
+
},
|
|
4405
|
+
"type": {
|
|
4406
|
+
"enum": ["active"],
|
|
4407
|
+
"title": "ActiveThreadStatusType",
|
|
4408
|
+
"type": "string"
|
|
4409
|
+
}
|
|
4410
|
+
},
|
|
4411
|
+
"required": ["activeFlags", "type"],
|
|
4412
|
+
"title": "ActiveThreadStatus",
|
|
4413
|
+
"type": "object"
|
|
4414
|
+
}
|
|
4415
|
+
] },
|
|
4416
|
+
"Turn": {
|
|
4417
|
+
"properties": {
|
|
4418
|
+
"completedAt": {
|
|
4419
|
+
"description": "Unix timestamp (in seconds) when the turn completed.",
|
|
4420
|
+
"format": "int64",
|
|
4421
|
+
"type": ["integer", "null"]
|
|
4422
|
+
},
|
|
4423
|
+
"durationMs": {
|
|
4424
|
+
"description": "Duration between turn start and completion in milliseconds, if known.",
|
|
4425
|
+
"format": "int64",
|
|
4426
|
+
"type": ["integer", "null"]
|
|
4427
|
+
},
|
|
4428
|
+
"error": {
|
|
4429
|
+
"anyOf": [{ "$ref": "#/definitions/TurnError" }, { "type": "null" }],
|
|
4430
|
+
"description": "Only populated when the Turn's status is failed."
|
|
4431
|
+
},
|
|
4432
|
+
"id": {
|
|
4433
|
+
"description": "Identifier for this turn. Codex-generated turn IDs are UUIDv7.",
|
|
4434
|
+
"type": "string"
|
|
4435
|
+
},
|
|
4436
|
+
"items": {
|
|
4437
|
+
"description": "Thread items currently included in this turn payload.",
|
|
4438
|
+
"items": { "$ref": "#/definitions/ThreadItem" },
|
|
4439
|
+
"type": "array"
|
|
4440
|
+
},
|
|
4441
|
+
"itemsView": {
|
|
4442
|
+
"allOf": [{ "$ref": "#/definitions/TurnItemsView" }],
|
|
4443
|
+
"default": "full",
|
|
4444
|
+
"description": "Describes how much of `items` has been loaded for this turn."
|
|
4445
|
+
},
|
|
4446
|
+
"startedAt": {
|
|
4447
|
+
"description": "Unix timestamp (in seconds) when the turn started.",
|
|
4448
|
+
"format": "int64",
|
|
4449
|
+
"type": ["integer", "null"]
|
|
4450
|
+
},
|
|
4451
|
+
"status": { "$ref": "#/definitions/TurnStatus" }
|
|
4452
|
+
},
|
|
4453
|
+
"required": [
|
|
4454
|
+
"id",
|
|
4455
|
+
"items",
|
|
4456
|
+
"status"
|
|
4457
|
+
],
|
|
4458
|
+
"type": "object"
|
|
4459
|
+
},
|
|
4460
|
+
"TurnError": {
|
|
4461
|
+
"properties": {
|
|
4462
|
+
"additionalDetails": {
|
|
4463
|
+
"default": null,
|
|
4464
|
+
"type": ["string", "null"]
|
|
4465
|
+
},
|
|
4466
|
+
"codexErrorInfo": { "anyOf": [{ "$ref": "#/definitions/CodexErrorInfo" }, { "type": "null" }] },
|
|
4467
|
+
"message": { "type": "string" },
|
|
4468
|
+
"misalignment": {
|
|
4469
|
+
"anyOf": [{ "$ref": "#/definitions/MisalignmentErrorDetails" }, { "type": "null" }],
|
|
4470
|
+
"default": null,
|
|
4471
|
+
"description": "Optional public explanation and continuation instruction for a misalignment block."
|
|
4472
|
+
}
|
|
4473
|
+
},
|
|
4474
|
+
"required": ["message"],
|
|
4475
|
+
"type": "object"
|
|
4476
|
+
},
|
|
4477
|
+
"TurnItemsView": { "oneOf": [
|
|
4478
|
+
{
|
|
4479
|
+
"description": "`items` was not loaded for this turn. The field is intentionally empty.",
|
|
4480
|
+
"enum": ["notLoaded"],
|
|
4481
|
+
"type": "string"
|
|
4482
|
+
},
|
|
4483
|
+
{
|
|
4484
|
+
"description": "`items` contains only a display summary for this turn.",
|
|
4485
|
+
"enum": ["summary"],
|
|
4486
|
+
"type": "string"
|
|
4487
|
+
},
|
|
4488
|
+
{
|
|
4489
|
+
"description": "`items` contains every ThreadItem available from persisted app-server history for this turn.",
|
|
4490
|
+
"enum": ["full"],
|
|
4491
|
+
"type": "string"
|
|
4492
|
+
}
|
|
4493
|
+
] },
|
|
4494
|
+
"TurnStatus": {
|
|
4495
|
+
"enum": [
|
|
4496
|
+
"completed",
|
|
4497
|
+
"interrupted",
|
|
4498
|
+
"failed",
|
|
4499
|
+
"inProgress"
|
|
4500
|
+
],
|
|
4501
|
+
"type": "string"
|
|
4502
|
+
},
|
|
4503
|
+
"TurnsPage": {
|
|
4504
|
+
"properties": {
|
|
4505
|
+
"backwardsCursor": { "type": ["string", "null"] },
|
|
4506
|
+
"data": {
|
|
4507
|
+
"items": { "$ref": "#/definitions/Turn" },
|
|
4508
|
+
"type": "array"
|
|
4509
|
+
},
|
|
4510
|
+
"nextCursor": { "type": ["string", "null"] }
|
|
4511
|
+
},
|
|
4512
|
+
"required": ["data"],
|
|
4513
|
+
"type": "object"
|
|
4514
|
+
},
|
|
4515
|
+
"UserInput": { "oneOf": [
|
|
4516
|
+
{
|
|
4517
|
+
"properties": {
|
|
4518
|
+
"text": { "type": "string" },
|
|
4519
|
+
"text_elements": {
|
|
4520
|
+
"default": [],
|
|
4521
|
+
"description": "UI-defined spans within `text` used to render or persist special elements.",
|
|
4522
|
+
"items": { "$ref": "#/definitions/TextElement" },
|
|
4523
|
+
"type": "array"
|
|
4524
|
+
},
|
|
4525
|
+
"type": {
|
|
4526
|
+
"enum": ["text"],
|
|
4527
|
+
"title": "TextUserInputType",
|
|
4528
|
+
"type": "string"
|
|
4529
|
+
}
|
|
4530
|
+
},
|
|
4531
|
+
"required": ["text", "type"],
|
|
4532
|
+
"title": "TextUserInput",
|
|
4533
|
+
"type": "object"
|
|
4534
|
+
},
|
|
4535
|
+
{
|
|
4536
|
+
"properties": {
|
|
4537
|
+
"detail": {
|
|
4538
|
+
"anyOf": [{ "$ref": "#/definitions/ImageDetail" }, { "type": "null" }],
|
|
4539
|
+
"default": null
|
|
4540
|
+
},
|
|
4541
|
+
"type": {
|
|
4542
|
+
"enum": ["image"],
|
|
4543
|
+
"title": "ImageUserInputType",
|
|
4544
|
+
"type": "string"
|
|
4545
|
+
},
|
|
4546
|
+
"url": { "type": "string" }
|
|
4547
|
+
},
|
|
4548
|
+
"required": ["type", "url"],
|
|
4549
|
+
"title": "ImageUserInput",
|
|
4550
|
+
"type": "object"
|
|
4551
|
+
},
|
|
4552
|
+
{
|
|
4553
|
+
"properties": {
|
|
4554
|
+
"detail": {
|
|
4555
|
+
"anyOf": [{ "$ref": "#/definitions/ImageDetail" }, { "type": "null" }],
|
|
4556
|
+
"default": null
|
|
4557
|
+
},
|
|
4558
|
+
"path": { "type": "string" },
|
|
4559
|
+
"type": {
|
|
4560
|
+
"enum": ["localImage"],
|
|
4561
|
+
"title": "LocalImageUserInputType",
|
|
4562
|
+
"type": "string"
|
|
4563
|
+
}
|
|
4564
|
+
},
|
|
4565
|
+
"required": ["path", "type"],
|
|
4566
|
+
"title": "LocalImageUserInput",
|
|
4567
|
+
"type": "object"
|
|
4568
|
+
},
|
|
4569
|
+
{
|
|
4570
|
+
"properties": {
|
|
4571
|
+
"type": {
|
|
4572
|
+
"enum": ["audio"],
|
|
4573
|
+
"title": "AudioUserInputType",
|
|
4574
|
+
"type": "string"
|
|
4575
|
+
},
|
|
4576
|
+
"url": { "type": "string" }
|
|
4577
|
+
},
|
|
4578
|
+
"required": ["type", "url"],
|
|
4579
|
+
"title": "AudioUserInput",
|
|
4580
|
+
"type": "object"
|
|
4581
|
+
},
|
|
4582
|
+
{
|
|
4583
|
+
"properties": {
|
|
4584
|
+
"path": { "type": "string" },
|
|
4585
|
+
"type": {
|
|
4586
|
+
"enum": ["localAudio"],
|
|
4587
|
+
"title": "LocalAudioUserInputType",
|
|
4588
|
+
"type": "string"
|
|
4589
|
+
}
|
|
4590
|
+
},
|
|
4591
|
+
"required": ["path", "type"],
|
|
4592
|
+
"title": "LocalAudioUserInput",
|
|
4593
|
+
"type": "object"
|
|
4594
|
+
},
|
|
4595
|
+
{
|
|
4596
|
+
"properties": {
|
|
4597
|
+
"name": { "type": "string" },
|
|
4598
|
+
"path": { "type": "string" },
|
|
4599
|
+
"type": {
|
|
4600
|
+
"enum": ["skill"],
|
|
4601
|
+
"title": "SkillUserInputType",
|
|
4602
|
+
"type": "string"
|
|
4603
|
+
}
|
|
4604
|
+
},
|
|
4605
|
+
"required": [
|
|
4606
|
+
"name",
|
|
4607
|
+
"path",
|
|
4608
|
+
"type"
|
|
4609
|
+
],
|
|
4610
|
+
"title": "SkillUserInput",
|
|
4611
|
+
"type": "object"
|
|
4612
|
+
},
|
|
4613
|
+
{
|
|
4614
|
+
"properties": {
|
|
4615
|
+
"name": { "type": "string" },
|
|
4616
|
+
"path": { "type": "string" },
|
|
4617
|
+
"type": {
|
|
4618
|
+
"enum": ["mention"],
|
|
4619
|
+
"title": "MentionUserInputType",
|
|
4620
|
+
"type": "string"
|
|
4621
|
+
}
|
|
4622
|
+
},
|
|
4623
|
+
"required": [
|
|
4624
|
+
"name",
|
|
4625
|
+
"path",
|
|
4626
|
+
"type"
|
|
4627
|
+
],
|
|
4628
|
+
"title": "MentionUserInput",
|
|
4629
|
+
"type": "object"
|
|
4630
|
+
}
|
|
4631
|
+
] },
|
|
4632
|
+
"WebSearchAction": { "oneOf": [
|
|
4633
|
+
{
|
|
4634
|
+
"properties": {
|
|
4635
|
+
"queries": {
|
|
4636
|
+
"items": { "type": "string" },
|
|
4637
|
+
"type": ["array", "null"]
|
|
4638
|
+
},
|
|
4639
|
+
"query": { "type": ["string", "null"] },
|
|
4640
|
+
"type": {
|
|
4641
|
+
"enum": ["search"],
|
|
4642
|
+
"title": "SearchWebSearchActionType",
|
|
4643
|
+
"type": "string"
|
|
4644
|
+
}
|
|
4645
|
+
},
|
|
4646
|
+
"required": ["type"],
|
|
4647
|
+
"title": "SearchWebSearchAction",
|
|
4648
|
+
"type": "object"
|
|
4649
|
+
},
|
|
4650
|
+
{
|
|
4651
|
+
"properties": {
|
|
4652
|
+
"type": {
|
|
4653
|
+
"enum": ["openPage"],
|
|
4654
|
+
"title": "OpenPageWebSearchActionType",
|
|
4655
|
+
"type": "string"
|
|
4656
|
+
},
|
|
4657
|
+
"url": { "type": ["string", "null"] }
|
|
4658
|
+
},
|
|
4659
|
+
"required": ["type"],
|
|
4660
|
+
"title": "OpenPageWebSearchAction",
|
|
4661
|
+
"type": "object"
|
|
4662
|
+
},
|
|
4663
|
+
{
|
|
4664
|
+
"properties": {
|
|
4665
|
+
"pattern": { "type": ["string", "null"] },
|
|
4666
|
+
"type": {
|
|
4667
|
+
"enum": ["findInPage"],
|
|
4668
|
+
"title": "FindInPageWebSearchActionType",
|
|
4669
|
+
"type": "string"
|
|
4670
|
+
},
|
|
4671
|
+
"url": { "type": ["string", "null"] }
|
|
4672
|
+
},
|
|
4673
|
+
"required": ["type"],
|
|
4674
|
+
"title": "FindInPageWebSearchAction",
|
|
4675
|
+
"type": "object"
|
|
4676
|
+
},
|
|
4677
|
+
{
|
|
4678
|
+
"properties": { "type": {
|
|
4679
|
+
"enum": ["other"],
|
|
4680
|
+
"title": "OtherWebSearchActionType",
|
|
4681
|
+
"type": "string"
|
|
4682
|
+
} },
|
|
4683
|
+
"required": ["type"],
|
|
4684
|
+
"title": "OtherWebSearchAction",
|
|
4685
|
+
"type": "object"
|
|
4686
|
+
}
|
|
4687
|
+
] }
|
|
4688
|
+
};
|
|
4689
|
+
//#endregion
|
|
4690
|
+
//#region extensions/codex/src/app-server/protocol-generated/json/v2/ErrorNotification.json
|
|
4691
|
+
var ErrorNotification_default = {
|
|
4692
|
+
$schema: "http://json-schema.org/draft-07/schema#",
|
|
4693
|
+
properties: {
|
|
4694
|
+
"error": { "$ref": "./CodexAppServerProtocolDefinitions.json#/definitions/TurnError" },
|
|
4695
|
+
"threadId": { "type": "string" },
|
|
4696
|
+
"turnId": { "type": "string" },
|
|
4697
|
+
"willRetry": { "type": "boolean" }
|
|
4698
|
+
},
|
|
4699
|
+
required: [
|
|
4700
|
+
"error",
|
|
4701
|
+
"threadId",
|
|
4702
|
+
"turnId",
|
|
4703
|
+
"willRetry"
|
|
4704
|
+
],
|
|
4705
|
+
title: "ErrorNotification",
|
|
4706
|
+
type: "object"
|
|
4707
|
+
};
|
|
4708
|
+
//#endregion
|
|
4709
|
+
//#region extensions/codex/src/app-server/protocol-generated/json/v2/ModelListResponse.json
|
|
4710
|
+
var ModelListResponse_default = {
|
|
4711
|
+
$schema: "http://json-schema.org/draft-07/schema#",
|
|
4712
|
+
properties: {
|
|
4713
|
+
"data": {
|
|
4714
|
+
"items": { "$ref": "./CodexAppServerProtocolDefinitions.json#/definitions/Model" },
|
|
4715
|
+
"type": "array"
|
|
4716
|
+
},
|
|
4717
|
+
"nextCursor": {
|
|
4718
|
+
"description": "Opaque cursor to pass to the next call to continue after the last item. If None, there are no more items to return.",
|
|
4719
|
+
"type": ["string", "null"]
|
|
4720
|
+
}
|
|
4721
|
+
},
|
|
4722
|
+
required: ["data"],
|
|
4723
|
+
title: "ModelListResponse",
|
|
4724
|
+
type: "object"
|
|
4725
|
+
};
|
|
4726
|
+
//#endregion
|
|
4727
|
+
//#region extensions/codex/src/app-server/protocol-generated/json/v2/ThreadResumeResponse.json
|
|
4728
|
+
var ThreadResumeResponse_default = {
|
|
4729
|
+
$schema: "http://json-schema.org/draft-07/schema#",
|
|
4730
|
+
properties: {
|
|
4731
|
+
"activePermissionProfile": {
|
|
4732
|
+
"anyOf": [{ "$ref": "./CodexAppServerProtocolDefinitions.json#/definitions/ActivePermissionProfile" }, { "type": "null" }],
|
|
4733
|
+
"default": null,
|
|
4734
|
+
"description": "Named or implicit built-in profile that produced the active permissions, when known."
|
|
4735
|
+
},
|
|
4736
|
+
"approvalPolicy": { "$ref": "./CodexAppServerProtocolDefinitions.json#/definitions/AskForApproval" },
|
|
4737
|
+
"approvalsReviewer": {
|
|
4738
|
+
"allOf": [{ "$ref": "./CodexAppServerProtocolDefinitions.json#/definitions/ApprovalsReviewer" }],
|
|
4739
|
+
"description": "Reviewer currently used for approval requests on this thread."
|
|
4740
|
+
},
|
|
4741
|
+
"cwd": { "$ref": "./CodexAppServerProtocolDefinitions.json#/definitions/AbsolutePathBuf" },
|
|
4742
|
+
"initialTurnsPage": {
|
|
4743
|
+
"anyOf": [{ "$ref": "./CodexAppServerProtocolDefinitions.json#/definitions/TurnsPage" }, { "type": "null" }],
|
|
4744
|
+
"default": null,
|
|
4745
|
+
"description": "`thread/turns/list` page returned when requested by `initialTurnsPage`."
|
|
4746
|
+
},
|
|
4747
|
+
"instructionSources": {
|
|
4748
|
+
"default": [],
|
|
4749
|
+
"description": "Environment-native paths to instruction source files currently loaded for this thread.",
|
|
4750
|
+
"items": { "$ref": "./CodexAppServerProtocolDefinitions.json#/definitions/LegacyAppPathString" },
|
|
4751
|
+
"type": "array"
|
|
4752
|
+
},
|
|
4753
|
+
"itemsBackwardsCursor": {
|
|
4754
|
+
"default": null,
|
|
4755
|
+
"description": "Opaque cursor for hydrating paginated items backwards.\n\nPass this as `cursor` to `thread/items/list` with `sortDirection: \"desc\"`. The first page includes the item identified by the cursor.",
|
|
4756
|
+
"type": ["string", "null"]
|
|
4757
|
+
},
|
|
4758
|
+
"model": { "type": "string" },
|
|
4759
|
+
"modelProvider": { "type": "string" },
|
|
4760
|
+
"multiAgentMode": {
|
|
4761
|
+
"allOf": [{ "$ref": "./CodexAppServerProtocolDefinitions.json#/definitions/MultiAgentMode" }],
|
|
4762
|
+
"default": "explicitRequestOnly",
|
|
4763
|
+
"description": "@deprecated Always `explicitRequestOnly`. Use `reasoningEffort` for Ultra behavior."
|
|
4764
|
+
},
|
|
4765
|
+
"reasoningEffort": { "anyOf": [{ "$ref": "./CodexAppServerProtocolDefinitions.json#/definitions/ReasoningEffort" }, { "type": "null" }] },
|
|
4766
|
+
"runtimeWorkspaceRoots": {
|
|
4767
|
+
"default": [],
|
|
4768
|
+
"description": "Thread-scoped runtime workspace roots used to materialize `:workspace_roots`.",
|
|
4769
|
+
"items": { "$ref": "./CodexAppServerProtocolDefinitions.json#/definitions/AbsolutePathBuf" },
|
|
4770
|
+
"type": "array"
|
|
4771
|
+
},
|
|
4772
|
+
"sandbox": {
|
|
4773
|
+
"allOf": [{ "$ref": "./CodexAppServerProtocolDefinitions.json#/definitions/SandboxPolicy" }],
|
|
4774
|
+
"description": "Legacy sandbox policy retained for compatibility. Experimental clients should prefer `activePermissionProfile` for profile provenance."
|
|
4775
|
+
},
|
|
4776
|
+
"serviceTier": { "type": ["string", "null"] },
|
|
4777
|
+
"thread": { "$ref": "./CodexAppServerProtocolDefinitions.json#/definitions/Thread" },
|
|
4778
|
+
"turnsBackwardsCursor": {
|
|
4779
|
+
"default": null,
|
|
4780
|
+
"description": "Opaque cursor for hydrating paginated turns backwards.\n\nPass this as `cursor` to `thread/turns/list` with `sortDirection: \"desc\"`. The first page includes the turn identified by the cursor.",
|
|
4781
|
+
"type": ["string", "null"]
|
|
4782
|
+
}
|
|
4783
|
+
},
|
|
4784
|
+
required: [
|
|
4785
|
+
"approvalPolicy",
|
|
4786
|
+
"approvalsReviewer",
|
|
4787
|
+
"cwd",
|
|
4788
|
+
"model",
|
|
4789
|
+
"modelProvider",
|
|
4790
|
+
"sandbox",
|
|
4791
|
+
"thread"
|
|
4792
|
+
],
|
|
4793
|
+
title: "ThreadResumeResponse",
|
|
4794
|
+
type: "object"
|
|
4795
|
+
};
|
|
4796
|
+
//#endregion
|
|
4797
|
+
//#region extensions/codex/src/app-server/protocol-generated/json/v2/ThreadStartResponse.json
|
|
4798
|
+
var ThreadStartResponse_default = {
|
|
4799
|
+
$schema: "http://json-schema.org/draft-07/schema#",
|
|
4800
|
+
properties: {
|
|
4801
|
+
"activePermissionProfile": {
|
|
4802
|
+
"anyOf": [{ "$ref": "./CodexAppServerProtocolDefinitions.json#/definitions/ActivePermissionProfile" }, { "type": "null" }],
|
|
4803
|
+
"default": null,
|
|
4804
|
+
"description": "Named or implicit built-in profile that produced the active permissions, when known."
|
|
4805
|
+
},
|
|
4806
|
+
"approvalPolicy": { "$ref": "./CodexAppServerProtocolDefinitions.json#/definitions/AskForApproval" },
|
|
4807
|
+
"approvalsReviewer": {
|
|
4808
|
+
"allOf": [{ "$ref": "./CodexAppServerProtocolDefinitions.json#/definitions/ApprovalsReviewer" }],
|
|
4809
|
+
"description": "Reviewer currently used for approval requests on this thread."
|
|
4810
|
+
},
|
|
4811
|
+
"cwd": { "$ref": "./CodexAppServerProtocolDefinitions.json#/definitions/AbsolutePathBuf" },
|
|
4812
|
+
"instructionSources": {
|
|
4813
|
+
"default": [],
|
|
4814
|
+
"description": "Environment-native paths to instruction source files currently loaded for this thread.",
|
|
4815
|
+
"items": { "$ref": "./CodexAppServerProtocolDefinitions.json#/definitions/LegacyAppPathString" },
|
|
4816
|
+
"type": "array"
|
|
4817
|
+
},
|
|
4818
|
+
"model": { "type": "string" },
|
|
4819
|
+
"modelProvider": { "type": "string" },
|
|
4820
|
+
"multiAgentMode": {
|
|
4821
|
+
"allOf": [{ "$ref": "./CodexAppServerProtocolDefinitions.json#/definitions/MultiAgentMode" }],
|
|
4822
|
+
"default": "explicitRequestOnly",
|
|
4823
|
+
"description": "@deprecated Always `explicitRequestOnly`. Use `reasoningEffort` for Ultra behavior."
|
|
4824
|
+
},
|
|
4825
|
+
"reasoningEffort": { "anyOf": [{ "$ref": "./CodexAppServerProtocolDefinitions.json#/definitions/ReasoningEffort" }, { "type": "null" }] },
|
|
4826
|
+
"runtimeWorkspaceRoots": {
|
|
4827
|
+
"default": [],
|
|
4828
|
+
"description": "Thread-scoped runtime workspace roots used to materialize `:workspace_roots`.",
|
|
4829
|
+
"items": { "$ref": "./CodexAppServerProtocolDefinitions.json#/definitions/AbsolutePathBuf" },
|
|
4830
|
+
"type": "array"
|
|
4831
|
+
},
|
|
4832
|
+
"sandbox": {
|
|
4833
|
+
"allOf": [{ "$ref": "./CodexAppServerProtocolDefinitions.json#/definitions/SandboxPolicy" }],
|
|
4834
|
+
"description": "Legacy sandbox policy retained for compatibility. Experimental clients should prefer `activePermissionProfile` for profile provenance."
|
|
4835
|
+
},
|
|
4836
|
+
"serviceTier": { "type": ["string", "null"] },
|
|
4837
|
+
"thread": { "$ref": "./CodexAppServerProtocolDefinitions.json#/definitions/Thread" }
|
|
4838
|
+
},
|
|
4839
|
+
required: [
|
|
4840
|
+
"approvalPolicy",
|
|
4841
|
+
"approvalsReviewer",
|
|
4842
|
+
"cwd",
|
|
4843
|
+
"model",
|
|
4844
|
+
"modelProvider",
|
|
4845
|
+
"sandbox",
|
|
4846
|
+
"thread"
|
|
4847
|
+
],
|
|
4848
|
+
title: "ThreadStartResponse",
|
|
4849
|
+
type: "object"
|
|
4850
|
+
};
|
|
4851
|
+
//#endregion
|
|
4852
|
+
//#region extensions/codex/src/app-server/protocol-generated/json/v2/TurnCompletedNotification.json
|
|
4853
|
+
var TurnCompletedNotification_default = {
|
|
4854
|
+
$schema: "http://json-schema.org/draft-07/schema#",
|
|
4855
|
+
properties: {
|
|
4856
|
+
"threadId": { "type": "string" },
|
|
4857
|
+
"turn": { "$ref": "./CodexAppServerProtocolDefinitions.json#/definitions/Turn" }
|
|
4858
|
+
},
|
|
4859
|
+
required: ["threadId", "turn"],
|
|
4860
|
+
title: "TurnCompletedNotification",
|
|
4861
|
+
type: "object"
|
|
4862
|
+
};
|
|
4863
|
+
//#endregion
|
|
4864
|
+
//#region extensions/codex/src/app-server/protocol-generated/json/v2/TurnStartResponse.json
|
|
4865
|
+
var TurnStartResponse_default = {
|
|
4866
|
+
$schema: "http://json-schema.org/draft-07/schema#",
|
|
4867
|
+
properties: { "turn": { "$ref": "./CodexAppServerProtocolDefinitions.json#/definitions/Turn" } },
|
|
4868
|
+
required: ["turn"],
|
|
4869
|
+
title: "TurnStartResponse",
|
|
4870
|
+
type: "object"
|
|
4871
|
+
};
|
|
4872
|
+
//#endregion
|
|
4873
|
+
//#region extensions/codex/src/app-server/protocol-validators.ts
|
|
4874
|
+
/**
|
|
4875
|
+
* Runtime validators for Codex app-server protocol payloads, including schema
|
|
4876
|
+
* normalization for generated JSON Schema before TypeBox compilation.
|
|
4877
|
+
*/
|
|
4878
|
+
const externalDefinitionRefPrefix = "./CodexAppServerProtocolDefinitions.json#/definitions/";
|
|
4879
|
+
const rootExternalDefinitionRefPrefix = "./v2/CodexAppServerProtocolDefinitions.json#/definitions/";
|
|
4880
|
+
const localDefinitionRefPrefix = "#/definitions/";
|
|
4881
|
+
function materializeCodexSchema(schema, externalRefPrefix = externalDefinitionRefPrefix) {
|
|
4882
|
+
const sharedDefinitions = definitions;
|
|
4883
|
+
if (!isRecord(schema) || !isRecord(sharedDefinitions)) return schema;
|
|
4884
|
+
const reachable = collectDefinitionRefs(schema, externalRefPrefix);
|
|
4885
|
+
const pending = [...reachable];
|
|
4886
|
+
while (pending.length > 0) {
|
|
4887
|
+
const name = pending.pop();
|
|
4888
|
+
if (name === void 0) continue;
|
|
4889
|
+
const definition = sharedDefinitions[name];
|
|
4890
|
+
if (definition === void 0) throw new Error(`Missing generated Codex schema definition: ${name}`);
|
|
4891
|
+
for (const dependency of collectDefinitionRefs(definition, localDefinitionRefPrefix)) if (!reachable.has(dependency)) {
|
|
4892
|
+
reachable.add(dependency);
|
|
4893
|
+
pending.push(dependency);
|
|
4894
|
+
}
|
|
4895
|
+
}
|
|
4896
|
+
if (reachable.size === 0) return schema;
|
|
4897
|
+
const definitions$1 = Object.fromEntries(Object.entries(sharedDefinitions).filter(([name]) => reachable.has(name)));
|
|
4898
|
+
return rewriteDefinitionRefs({
|
|
4899
|
+
...schema,
|
|
4900
|
+
definitions: definitions$1
|
|
4901
|
+
}, externalRefPrefix);
|
|
4902
|
+
}
|
|
4903
|
+
function collectDefinitionRefs(value, prefix, names = /* @__PURE__ */ new Set()) {
|
|
4904
|
+
if (Array.isArray(value)) for (const entry of value) collectDefinitionRefs(entry, prefix, names);
|
|
4905
|
+
else if (isRecord(value)) {
|
|
4906
|
+
if (typeof value.$ref === "string" && value.$ref.startsWith(prefix)) {
|
|
4907
|
+
const name = value.$ref.slice(prefix.length).split("/", 1)[0];
|
|
4908
|
+
if (name) names.add(name.replaceAll("~1", "/").replaceAll("~0", "~"));
|
|
4909
|
+
}
|
|
4910
|
+
for (const entry of Object.values(value)) collectDefinitionRefs(entry, prefix, names);
|
|
4911
|
+
}
|
|
4912
|
+
return names;
|
|
4913
|
+
}
|
|
4914
|
+
function rewriteDefinitionRefs(value, externalRefPrefix) {
|
|
4915
|
+
if (Array.isArray(value)) return value.map((entry) => rewriteDefinitionRefs(entry, externalRefPrefix));
|
|
4916
|
+
if (!isRecord(value)) return value;
|
|
4917
|
+
return Object.fromEntries(Object.entries(value).map(([key, entry]) => [key, key === "$ref" && typeof entry === "string" && entry.startsWith(externalRefPrefix) ? `${localDefinitionRefPrefix}${entry.slice(externalRefPrefix.length)}` : rewriteDefinitionRefs(entry, externalRefPrefix)]));
|
|
4918
|
+
}
|
|
4919
|
+
const dynamicToolCallParamsSchema = materializeCodexSchema(DynamicToolCallParams_default, rootExternalDefinitionRefPrefix);
|
|
4920
|
+
const errorNotificationSchema = materializeCodexSchema(ErrorNotification_default);
|
|
4921
|
+
const modelListResponseSchema = materializeCodexSchema(ModelListResponse_default);
|
|
4922
|
+
const threadResumeResponseSchema = materializeCodexSchema(ThreadResumeResponse_default);
|
|
4923
|
+
const threadStartResponseSchema = materializeCodexSchema(ThreadStartResponse_default);
|
|
4924
|
+
const turnCompletedNotificationSchema = materializeCodexSchema(TurnCompletedNotification_default);
|
|
4925
|
+
const turnStartResponseSchema = materializeCodexSchema(TurnStartResponse_default);
|
|
4926
|
+
function compileCodexSchema(schema) {
|
|
4927
|
+
const validator = Compile(normalizeJsonSchemaNode(schema));
|
|
1968
4928
|
return {
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
release
|
|
4929
|
+
check: (value) => validator.Check(value),
|
|
4930
|
+
errors: (value) => [...validator.Errors(value)]
|
|
1972
4931
|
};
|
|
1973
4932
|
}
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
4933
|
+
const schemaMapKeywords = /* @__PURE__ */ new Set([
|
|
4934
|
+
"$defs",
|
|
4935
|
+
"definitions",
|
|
4936
|
+
"dependentSchemas",
|
|
4937
|
+
"patternProperties",
|
|
4938
|
+
"properties"
|
|
4939
|
+
]);
|
|
4940
|
+
const schemaValueKeywords = /* @__PURE__ */ new Set([
|
|
4941
|
+
"additionalItems",
|
|
4942
|
+
"additionalProperties",
|
|
4943
|
+
"contains",
|
|
4944
|
+
"else",
|
|
4945
|
+
"if",
|
|
4946
|
+
"items",
|
|
4947
|
+
"not",
|
|
4948
|
+
"propertyNames",
|
|
4949
|
+
"then",
|
|
4950
|
+
"unevaluatedItems",
|
|
4951
|
+
"unevaluatedProperties"
|
|
4952
|
+
]);
|
|
4953
|
+
const schemaArrayKeywords = /* @__PURE__ */ new Set([
|
|
4954
|
+
"allOf",
|
|
4955
|
+
"anyOf",
|
|
4956
|
+
"oneOf",
|
|
4957
|
+
"prefixItems"
|
|
4958
|
+
]);
|
|
4959
|
+
function schemaTypeIncludes(schema, type) {
|
|
4960
|
+
return schema.type === type || Array.isArray(schema.type) && schema.type.includes(type);
|
|
4961
|
+
}
|
|
4962
|
+
function normalizeSchemaMap(value) {
|
|
4963
|
+
if (!isRecord(value)) return value;
|
|
4964
|
+
return Object.fromEntries(Object.entries(value).map(([key, entry]) => [key, normalizeJsonSchemaNode(entry)]));
|
|
4965
|
+
}
|
|
4966
|
+
function expandJsonSchemaTypeArray(schema) {
|
|
4967
|
+
const { type, ...rest } = schema;
|
|
4968
|
+
if (!Array.isArray(type)) return schema;
|
|
4969
|
+
return { anyOf: type.map((entry) => Object.assign({}, rest, { type: entry })) };
|
|
4970
|
+
}
|
|
4971
|
+
function normalizeJsonSchemaNode(schema) {
|
|
4972
|
+
if (Array.isArray(schema)) return schema.map((entry) => normalizeJsonSchemaNode(entry));
|
|
4973
|
+
if (!isRecord(schema)) return schema;
|
|
4974
|
+
const normalizedSchema = expandJsonSchemaTypeArray(schema);
|
|
4975
|
+
return Object.fromEntries(Object.entries(normalizedSchema).map(([key, value]) => {
|
|
4976
|
+
if (schemaMapKeywords.has(key)) return [key, normalizeSchemaMap(value)];
|
|
4977
|
+
if (schemaValueKeywords.has(key) || schemaArrayKeywords.has(key)) return [key, normalizeJsonSchemaNode(value)];
|
|
4978
|
+
return [key, value];
|
|
4979
|
+
}));
|
|
1978
4980
|
}
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
4981
|
+
function readDefault(schema) {
|
|
4982
|
+
if (!isRecord(schema) || !Object.hasOwn(schema, "default")) return;
|
|
4983
|
+
return structuredClone(schema.default);
|
|
4984
|
+
}
|
|
4985
|
+
function decodePointerSegment(segment) {
|
|
4986
|
+
return segment.replace(/~1/g, "/").replace(/~0/g, "~");
|
|
4987
|
+
}
|
|
4988
|
+
function resolveLocalRef(root, ref) {
|
|
4989
|
+
if (ref === "#") return root;
|
|
4990
|
+
if (!ref.startsWith("#/")) return;
|
|
4991
|
+
let current = root;
|
|
4992
|
+
for (const segment of ref.slice(2).split("/").map(decodePointerSegment)) {
|
|
4993
|
+
if (!isRecord(current)) return;
|
|
4994
|
+
current = current[segment];
|
|
4995
|
+
}
|
|
4996
|
+
return current;
|
|
4997
|
+
}
|
|
4998
|
+
function applySchemaDefaults(schema, value, root = schema, resolvingRefs = /* @__PURE__ */ new Set()) {
|
|
4999
|
+
if (value === void 0) {
|
|
5000
|
+
const defaultValue = readDefault(schema);
|
|
5001
|
+
if (defaultValue !== void 0) return defaultValue;
|
|
5002
|
+
}
|
|
5003
|
+
if (!isRecord(schema)) return value;
|
|
5004
|
+
let nextValue = value;
|
|
5005
|
+
if (typeof schema.$ref === "string" && !resolvingRefs.has(schema.$ref)) {
|
|
5006
|
+
const target = resolveLocalRef(root, schema.$ref);
|
|
5007
|
+
if (target !== void 0) {
|
|
5008
|
+
resolvingRefs.add(schema.$ref);
|
|
5009
|
+
nextValue = applySchemaDefaults(target, nextValue, root, resolvingRefs);
|
|
5010
|
+
resolvingRefs.delete(schema.$ref);
|
|
5011
|
+
}
|
|
1987
5012
|
}
|
|
1988
|
-
const
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
});
|
|
1992
|
-
const ownsTransition = runtime !== void 0 && transition === void 0;
|
|
1993
|
-
if (transition) transition.physicalRelease = physicalRelease;
|
|
1994
|
-
else if (runtime) {
|
|
1995
|
-
transition = {
|
|
1996
|
-
completion: physicalRelease,
|
|
1997
|
-
physicalRelease
|
|
1998
|
-
};
|
|
1999
|
-
runtime.releasingThreads.set(threadId, transition);
|
|
5013
|
+
for (const key of ["allOf"]) {
|
|
5014
|
+
const branches = schema[key];
|
|
5015
|
+
if (Array.isArray(branches)) for (const branch of branches) nextValue = applySchemaDefaults(branch, nextValue, root, resolvingRefs);
|
|
2000
5016
|
}
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
5017
|
+
if (schemaTypeIncludes(schema, "object") && isRecord(nextValue) && isRecord(schema.properties)) {
|
|
5018
|
+
for (const [key, propertySchema] of Object.entries(schema.properties)) {
|
|
5019
|
+
const currentValue = nextValue[key];
|
|
5020
|
+
const defaultedValue = applySchemaDefaults(propertySchema, currentValue, root, resolvingRefs);
|
|
5021
|
+
if (defaultedValue !== void 0 && defaultedValue !== currentValue) nextValue[key] = defaultedValue;
|
|
5022
|
+
}
|
|
5023
|
+
if (isRecord(schema.additionalProperties)) for (const key of Object.keys(nextValue)) {
|
|
5024
|
+
if (Object.hasOwn(schema.properties, key)) continue;
|
|
5025
|
+
nextValue[key] = applySchemaDefaults(schema.additionalProperties, nextValue[key], root, resolvingRefs);
|
|
5026
|
+
}
|
|
2006
5027
|
}
|
|
5028
|
+
if (schemaTypeIncludes(schema, "array") && Array.isArray(nextValue) && isRecord(schema.items)) return nextValue.map((entry) => applySchemaDefaults(schema.items, entry, root, resolvingRefs));
|
|
5029
|
+
return nextValue;
|
|
5030
|
+
}
|
|
5031
|
+
function normalizeWithDefaults(schema, value) {
|
|
5032
|
+
if (value === void 0 || value === null) return value;
|
|
5033
|
+
return applySchemaDefaults(schema, structuredClone(value));
|
|
5034
|
+
}
|
|
5035
|
+
const validateDynamicToolCallParams = compileCodexSchema(dynamicToolCallParamsSchema);
|
|
5036
|
+
const validateErrorNotification = compileCodexSchema(errorNotificationSchema);
|
|
5037
|
+
const validateModelListResponse = compileCodexSchema(modelListResponseSchema);
|
|
5038
|
+
const validateThreadResumeResponse = compileCodexSchema(threadResumeResponseSchema);
|
|
5039
|
+
const validateThreadStartResponse = compileCodexSchema(threadStartResponseSchema);
|
|
5040
|
+
const validateTurnCompletedNotification = compileCodexSchema(turnCompletedNotificationSchema);
|
|
5041
|
+
const validateTurnStartResponse = compileCodexSchema(turnStartResponseSchema);
|
|
5042
|
+
/** Asserts and normalizes a Codex thread/start response. */
|
|
5043
|
+
function assertCodexThreadStartResponse(value) {
|
|
5044
|
+
const normalized = normalizeWithDefaults(threadStartResponseSchema, value);
|
|
5045
|
+
return assertCodexShape(validateThreadStartResponse, normalized, "thread/start response");
|
|
5046
|
+
}
|
|
5047
|
+
/** Asserts and normalizes a Codex thread/fork response. */
|
|
5048
|
+
function assertCodexThreadForkResponse(value) {
|
|
5049
|
+
const normalized = normalizeWithDefaults(threadStartResponseSchema, value);
|
|
5050
|
+
return assertCodexShape(validateThreadStartResponse, normalized, "thread/fork response");
|
|
5051
|
+
}
|
|
5052
|
+
/** Asserts the experimental beforeTurnId request field before it crosses the app-server boundary. */
|
|
5053
|
+
function assertCodexThreadForkParams(value) {
|
|
5054
|
+
if (!isRecord(value) || typeof value.threadId !== "string" || !value.threadId.trim() || value.beforeTurnId !== void 0 && value.beforeTurnId !== null && typeof value.beforeTurnId !== "string") throw new Error("Invalid Codex app-server thread/fork params");
|
|
5055
|
+
return value;
|
|
2007
5056
|
}
|
|
2008
|
-
/**
|
|
2009
|
-
|
|
2010
|
-
const
|
|
2011
|
-
return
|
|
5057
|
+
/** Asserts and normalizes a Codex thread/resume response. */
|
|
5058
|
+
function assertCodexThreadResumeResponse(value) {
|
|
5059
|
+
const normalized = normalizeWithDefaults(threadResumeResponseSchema, value);
|
|
5060
|
+
return assertCodexShape(validateThreadResumeResponse, normalized, "thread/resume response");
|
|
2012
5061
|
}
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
5062
|
+
var CodexThreadDirectInputError = class extends Error {
|
|
5063
|
+
constructor(threadId) {
|
|
5064
|
+
super(`Codex thread ${threadId} is controlled by its parent and cannot accept direct input. Continue its parent thread, or use /new for a separate OpenClaw session.`);
|
|
5065
|
+
this.name = "CodexThreadDirectInputError";
|
|
5066
|
+
}
|
|
5067
|
+
};
|
|
5068
|
+
/** Native V2 children allow observation, but only their parent may supply turn input. */
|
|
5069
|
+
function assertCodexThreadAcceptsDirectInput(thread) {
|
|
5070
|
+
if (thread.canAcceptDirectInput === false) throw new CodexThreadDirectInputError(thread.id);
|
|
5071
|
+
}
|
|
5072
|
+
/** Asserts and normalizes a Codex turn/start response. */
|
|
5073
|
+
function assertCodexTurnStartResponse(value) {
|
|
5074
|
+
const normalized = normalizeWithDefaults(turnStartResponseSchema, normalizeTurnStartResponse(value));
|
|
5075
|
+
return assertCodexShape(validateTurnStartResponse, normalized, "turn/start response");
|
|
5076
|
+
}
|
|
5077
|
+
/** Reads Codex dynamic-tool call params, returning undefined for invalid payloads. */
|
|
5078
|
+
function readCodexDynamicToolCallParams(value) {
|
|
5079
|
+
return readCodexShape(validateDynamicToolCallParams, normalizeWithDefaults(dynamicToolCallParamsSchema, value));
|
|
5080
|
+
}
|
|
5081
|
+
/** Reads a Codex error notification payload if it matches the protocol schema. */
|
|
5082
|
+
function readCodexErrorNotification(value) {
|
|
5083
|
+
return readCodexShape(validateErrorNotification, normalizeWithDefaults(errorNotificationSchema, value));
|
|
5084
|
+
}
|
|
5085
|
+
/** Asserts and normalizes a Codex model/list response. */
|
|
5086
|
+
function assertCodexModelListResponse(value) {
|
|
5087
|
+
return assertCodexShape(validateModelListResponse, normalizeWithDefaults(modelListResponseSchema, value), "model/list response");
|
|
5088
|
+
}
|
|
5089
|
+
/** Reads and normalizes a Codex turn object. */
|
|
5090
|
+
function readCodexTurn(value) {
|
|
5091
|
+
return readCodexShape(validateTurnStartResponse, normalizeWithDefaults(turnStartResponseSchema, { turn: normalizeTurn(value) }))?.turn;
|
|
5092
|
+
}
|
|
5093
|
+
/** Reads a Codex turn/completed notification payload if it matches the protocol schema. */
|
|
5094
|
+
function readCodexTurnCompletedNotification(value) {
|
|
5095
|
+
return readCodexShape(validateTurnCompletedNotification, normalizeWithDefaults(turnCompletedNotificationSchema, normalizeTurnCompletedNotification(value)));
|
|
5096
|
+
}
|
|
5097
|
+
function assertCodexShape(validate, value, label) {
|
|
5098
|
+
if (validate.check(value)) return value;
|
|
5099
|
+
throw new Error(`Invalid Codex app-server ${label}: ${formatValidationErrors(validate, value)}`);
|
|
5100
|
+
}
|
|
5101
|
+
function readCodexShape(validate, value) {
|
|
5102
|
+
return validate.check(value) ? value : void 0;
|
|
5103
|
+
}
|
|
5104
|
+
function normalizeTurn(value) {
|
|
5105
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return value;
|
|
5106
|
+
return {
|
|
5107
|
+
error: null,
|
|
5108
|
+
startedAt: null,
|
|
5109
|
+
completedAt: null,
|
|
5110
|
+
durationMs: null,
|
|
5111
|
+
...value,
|
|
5112
|
+
items: Array.isArray(value.items) ? value.items.map(normalizeThreadItem) : []
|
|
2043
5113
|
};
|
|
2044
5114
|
}
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
5115
|
+
function normalizeThreadItem(value) {
|
|
5116
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return value;
|
|
5117
|
+
switch (value.type) {
|
|
5118
|
+
case "agentMessage": return {
|
|
5119
|
+
phase: null,
|
|
5120
|
+
delivery: null,
|
|
5121
|
+
memoryCitation: null,
|
|
5122
|
+
...value
|
|
5123
|
+
};
|
|
5124
|
+
case "plan": return {
|
|
5125
|
+
text: "",
|
|
5126
|
+
...value
|
|
5127
|
+
};
|
|
5128
|
+
case "reasoning": return {
|
|
5129
|
+
summary: [],
|
|
5130
|
+
content: [],
|
|
5131
|
+
...value
|
|
5132
|
+
};
|
|
5133
|
+
case "dynamicToolCall": return {
|
|
5134
|
+
namespace: null,
|
|
5135
|
+
arguments: null,
|
|
5136
|
+
status: "completed",
|
|
5137
|
+
contentItems: null,
|
|
5138
|
+
success: null,
|
|
5139
|
+
durationMs: null,
|
|
5140
|
+
...value
|
|
5141
|
+
};
|
|
5142
|
+
default: return value;
|
|
5143
|
+
}
|
|
5144
|
+
}
|
|
5145
|
+
function normalizeTurnStartResponse(value) {
|
|
5146
|
+
if (!value || typeof value !== "object" || Array.isArray(value) || !("turn" in value)) return value;
|
|
2048
5147
|
return {
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
5148
|
+
...value,
|
|
5149
|
+
turn: normalizeTurn(value.turn)
|
|
5150
|
+
};
|
|
5151
|
+
}
|
|
5152
|
+
function normalizeTurnCompletedNotification(value) {
|
|
5153
|
+
if (!value || typeof value !== "object" || Array.isArray(value) || !("turn" in value)) return value;
|
|
5154
|
+
return {
|
|
5155
|
+
...value,
|
|
5156
|
+
turn: normalizeTurn(value.turn)
|
|
2052
5157
|
};
|
|
2053
5158
|
}
|
|
5159
|
+
function formatValidationErrors(validate, value) {
|
|
5160
|
+
const errors = validate.errors(value);
|
|
5161
|
+
if (!errors || errors.length === 0) return "schema validation failed";
|
|
5162
|
+
return errors.map((error) => {
|
|
5163
|
+
const message = error.message?.trim() || "schema validation failed";
|
|
5164
|
+
return error.instancePath ? `${error.instancePath} ${message}` : message;
|
|
5165
|
+
}).join("; ");
|
|
5166
|
+
}
|
|
2054
5167
|
//#endregion
|
|
2055
5168
|
//#region extensions/codex/src/app-server/rpc-error.ts
|
|
2056
5169
|
/** RPC error wrapper that preserves app-server error code and data. */
|
|
@@ -2248,339 +5361,14 @@ function websocketFrameToText(data) {
|
|
|
2248
5361
|
return Buffer.from(data).toString("utf8");
|
|
2249
5362
|
}
|
|
2250
5363
|
//#endregion
|
|
2251
|
-
//#region extensions/codex/src/app-server/transport-process-containment.ts
|
|
2252
|
-
const PROCESS_COLUMNS = "pid=,ppid=,pgid=,stat=,lstart=";
|
|
2253
|
-
const MAX_CONTAINED_PROCESSES = 512;
|
|
2254
|
-
const MAX_PROCESS_CONTAINMENT_MS = 2e3;
|
|
2255
|
-
const MAX_PROCESS_QUIESCE_PASSES = 16;
|
|
2256
|
-
const PROCESS_INSPECTION_MAX_BYTES = 8 * 1024 * 1024;
|
|
2257
|
-
async function terminateCodexAppServerDescendants(child) {
|
|
2258
|
-
const rootPid = child.pid;
|
|
2259
|
-
if (process.platform === "win32" || !rootPid || !child.kill || hasExited(child)) return;
|
|
2260
|
-
const deadline = Date.now() + MAX_PROCESS_CONTAINMENT_MS;
|
|
2261
|
-
const snapshot = await readProcessSnapshot(deadline);
|
|
2262
|
-
if (!snapshot || Date.now() >= deadline) return;
|
|
2263
|
-
const root = snapshot.find((row) => row.pid === rootPid);
|
|
2264
|
-
if (!root || !isSameLiveRoot(root, root)) return;
|
|
2265
|
-
const initialDescendants = collectDescendants(snapshot, [rootPid]);
|
|
2266
|
-
if (initialDescendants.length > MAX_CONTAINED_PROCESSES) return;
|
|
2267
|
-
const stoppedDescendants = /* @__PURE__ */ new Map();
|
|
2268
|
-
if (!await signalSameRoot(root, "SIGSTOP", deadline)) return;
|
|
2269
|
-
let resumeRootOnUnwind = true;
|
|
2270
|
-
try {
|
|
2271
|
-
const descendants = await quiesceDescendants(root, initialDescendants, stoppedDescendants, deadline);
|
|
2272
|
-
if (!descendants) return;
|
|
2273
|
-
for (const descendant of descendants.toReversed()) {
|
|
2274
|
-
if (Date.now() >= deadline) return;
|
|
2275
|
-
if (!descendant.state.startsWith("Z")) {
|
|
2276
|
-
if (!await signalSameProcess(descendant, "SIGKILL", deadline) || Date.now() >= deadline) return;
|
|
2277
|
-
}
|
|
2278
|
-
}
|
|
2279
|
-
resumeRootOnUnwind = false;
|
|
2280
|
-
let resumed = false;
|
|
2281
|
-
return () => {
|
|
2282
|
-
if (resumed) return;
|
|
2283
|
-
resumed = true;
|
|
2284
|
-
resumeTransportRoot(child, root, false);
|
|
2285
|
-
};
|
|
2286
|
-
} finally {
|
|
2287
|
-
if (resumeRootOnUnwind) {
|
|
2288
|
-
for (const descendant of stoppedDescendants.values()) signalProcess(descendant.pid, "SIGCONT");
|
|
2289
|
-
resumeTransportRoot(child, root, true);
|
|
2290
|
-
}
|
|
2291
|
-
}
|
|
2292
|
-
}
|
|
2293
|
-
async function quiesceDescendants(root, initialDescendants, stopped, deadline) {
|
|
2294
|
-
const provenByPid = new Map(initialDescendants.map((descendant) => [descendant.pid, descendant]));
|
|
2295
|
-
const stopFailures = /* @__PURE__ */ new Map();
|
|
2296
|
-
for (let pass = 0; pass < MAX_PROCESS_QUIESCE_PASSES; pass += 1) {
|
|
2297
|
-
if (Date.now() >= deadline) return;
|
|
2298
|
-
const snapshot = await readProcessSnapshot(deadline);
|
|
2299
|
-
if (!snapshot || Date.now() >= deadline) return;
|
|
2300
|
-
const currentRoot = snapshot.find((row) => row.pid === root.pid);
|
|
2301
|
-
if (!currentRoot || !isSameLiveRoot(currentRoot, root)) return;
|
|
2302
|
-
if (!isSameLiveRoot(currentRoot, root, true)) {
|
|
2303
|
-
if (!await signalSameRoot(root, "SIGSTOP", deadline) || Date.now() >= deadline) return;
|
|
2304
|
-
continue;
|
|
2305
|
-
}
|
|
2306
|
-
const snapshotByPid = new Map(snapshot.map((process) => [process.pid, process]));
|
|
2307
|
-
const liveProven = [];
|
|
2308
|
-
for (const proven of provenByPid.values()) {
|
|
2309
|
-
const current = snapshotByPid.get(proven.pid);
|
|
2310
|
-
if (!current) {
|
|
2311
|
-
provenByPid.delete(proven.pid);
|
|
2312
|
-
stopped.delete(identityKey(proven));
|
|
2313
|
-
continue;
|
|
2314
|
-
}
|
|
2315
|
-
if (!hasSameIdentity(proven, current)) return;
|
|
2316
|
-
provenByPid.set(current.pid, current);
|
|
2317
|
-
const key = identityKey(current);
|
|
2318
|
-
if (stopped.has(key)) stopped.set(key, current);
|
|
2319
|
-
liveProven.push(current);
|
|
2320
|
-
}
|
|
2321
|
-
const descendants = collectDescendants(snapshot, [root.pid, ...liveProven.map(({ pid }) => pid)]);
|
|
2322
|
-
for (const descendant of descendants) {
|
|
2323
|
-
const proven = provenByPid.get(descendant.pid);
|
|
2324
|
-
if (proven && !hasSameIdentity(proven, descendant)) return;
|
|
2325
|
-
provenByPid.set(descendant.pid, descendant);
|
|
2326
|
-
}
|
|
2327
|
-
if (provenByPid.size > MAX_CONTAINED_PROCESSES) return;
|
|
2328
|
-
const quiescenceTargets = new Map(liveProven.map((process) => [process.pid, process]));
|
|
2329
|
-
for (const descendant of descendants) quiescenceTargets.set(descendant.pid, descendant);
|
|
2330
|
-
let allStopped = true;
|
|
2331
|
-
for (const descendant of quiescenceTargets.values()) {
|
|
2332
|
-
if (Date.now() >= deadline) return;
|
|
2333
|
-
if (isStoppedState(descendant.state)) continue;
|
|
2334
|
-
const stopQueued = await signalSameProcess(descendant, "SIGSTOP", deadline);
|
|
2335
|
-
if (Date.now() >= deadline) return;
|
|
2336
|
-
if (stopQueued) {
|
|
2337
|
-
stopFailures.delete(identityKey(descendant));
|
|
2338
|
-
stopped.set(identityKey(descendant), descendant);
|
|
2339
|
-
} else {
|
|
2340
|
-
const key = identityKey(descendant);
|
|
2341
|
-
const failures = (stopFailures.get(key) ?? 0) + 1;
|
|
2342
|
-
if (failures >= 2) return;
|
|
2343
|
-
stopFailures.set(key, failures);
|
|
2344
|
-
}
|
|
2345
|
-
if (!isUninterruptibleState(descendant.state) || !stopQueued) allStopped = false;
|
|
2346
|
-
}
|
|
2347
|
-
if (allStopped) return [...provenByPid.values()];
|
|
2348
|
-
}
|
|
2349
|
-
}
|
|
2350
|
-
async function readProcessSnapshot(deadline) {
|
|
2351
|
-
return await readProcesses(["-axo", PROCESS_COLUMNS], deadline);
|
|
2352
|
-
}
|
|
2353
|
-
async function readProcess(pid, deadline) {
|
|
2354
|
-
return (await readProcesses([
|
|
2355
|
-
"-o",
|
|
2356
|
-
PROCESS_COLUMNS,
|
|
2357
|
-
"-p",
|
|
2358
|
-
String(pid)
|
|
2359
|
-
], deadline))?.find((row) => row.pid === pid);
|
|
2360
|
-
}
|
|
2361
|
-
async function readProcesses(args, deadline) {
|
|
2362
|
-
const remainingMs = deadline - Date.now();
|
|
2363
|
-
if (remainingMs <= 0) return;
|
|
2364
|
-
return await new Promise((resolve) => {
|
|
2365
|
-
let settled = false;
|
|
2366
|
-
const settle = (processes) => {
|
|
2367
|
-
if (settled) return;
|
|
2368
|
-
settled = true;
|
|
2369
|
-
clearTimeout(timer);
|
|
2370
|
-
resolve(processes);
|
|
2371
|
-
};
|
|
2372
|
-
const inspector = execFile("ps", args, {
|
|
2373
|
-
encoding: "utf8",
|
|
2374
|
-
maxBuffer: PROCESS_INSPECTION_MAX_BYTES
|
|
2375
|
-
}, (error, stdout) => {
|
|
2376
|
-
settle(error ? void 0 : parseProcesses(stdout));
|
|
2377
|
-
});
|
|
2378
|
-
const timer = setTimeout(() => {
|
|
2379
|
-
settle(void 0);
|
|
2380
|
-
inspector.stdout?.destroy();
|
|
2381
|
-
inspector.stderr?.destroy();
|
|
2382
|
-
inspector.kill("SIGKILL");
|
|
2383
|
-
inspector.unref();
|
|
2384
|
-
}, Math.max(1, remainingMs));
|
|
2385
|
-
timer.unref?.();
|
|
2386
|
-
});
|
|
2387
|
-
}
|
|
2388
|
-
function parseProcesses(output) {
|
|
2389
|
-
const rows = [];
|
|
2390
|
-
for (const line of output.split("\n")) {
|
|
2391
|
-
const match = /^\s*(\d+)\s+(\d+)\s+(\d+)\s+(\S+)\s+(.+?)\s*$/.exec(line);
|
|
2392
|
-
if (!match) continue;
|
|
2393
|
-
const pid = Number(match[1] ?? "");
|
|
2394
|
-
const ppid = Number(match[2] ?? "");
|
|
2395
|
-
const pgid = Number(match[3] ?? "");
|
|
2396
|
-
const startedAt = (match[5] ?? "").trim().replace(/\s+/g, " ");
|
|
2397
|
-
if (![
|
|
2398
|
-
pid,
|
|
2399
|
-
ppid,
|
|
2400
|
-
pgid
|
|
2401
|
-
].every(Number.isSafeInteger) || pid <= 0 || ppid < 0 || pgid <= 0 || !startedAt) continue;
|
|
2402
|
-
rows.push({
|
|
2403
|
-
pid,
|
|
2404
|
-
ppid,
|
|
2405
|
-
pgid,
|
|
2406
|
-
state: match[4] ?? "",
|
|
2407
|
-
startedAt
|
|
2408
|
-
});
|
|
2409
|
-
}
|
|
2410
|
-
return rows;
|
|
2411
|
-
}
|
|
2412
|
-
function collectDescendants(snapshot, rootPids) {
|
|
2413
|
-
const childrenByParent = /* @__PURE__ */ new Map();
|
|
2414
|
-
for (const row of snapshot) {
|
|
2415
|
-
const children = childrenByParent.get(row.ppid) ?? [];
|
|
2416
|
-
children.push(row);
|
|
2417
|
-
childrenByParent.set(row.ppid, children);
|
|
2418
|
-
}
|
|
2419
|
-
const descendants = [];
|
|
2420
|
-
const pending = [...new Set(rootPids)];
|
|
2421
|
-
const seen = new Set(pending);
|
|
2422
|
-
for (const parentPid of pending) for (const child of childrenByParent.get(parentPid) ?? []) {
|
|
2423
|
-
if (seen.has(child.pid)) continue;
|
|
2424
|
-
seen.add(child.pid);
|
|
2425
|
-
descendants.push(child);
|
|
2426
|
-
pending.push(child.pid);
|
|
2427
|
-
}
|
|
2428
|
-
return descendants;
|
|
2429
|
-
}
|
|
2430
|
-
function isStoppedState(state) {
|
|
2431
|
-
return state.startsWith("T") || state.startsWith("t") || state.startsWith("Z");
|
|
2432
|
-
}
|
|
2433
|
-
function isQuiescedState(state) {
|
|
2434
|
-
return isStoppedState(state) || isUninterruptibleState(state);
|
|
2435
|
-
}
|
|
2436
|
-
function isUninterruptibleState(state) {
|
|
2437
|
-
return state.startsWith("D") || state.startsWith("U");
|
|
2438
|
-
}
|
|
2439
|
-
function isSameLiveProcess(current, expected) {
|
|
2440
|
-
return current.pgid === expected.pgid && !current.state.startsWith("Z") && hasSameIdentity(current, expected);
|
|
2441
|
-
}
|
|
2442
|
-
function isSameLiveRoot(current, expected, requireStopped = false) {
|
|
2443
|
-
return current.ppid === process.pid && (!requireStopped || isQuiescedState(current.state)) && isSameLiveProcess(current, expected);
|
|
2444
|
-
}
|
|
2445
|
-
async function signalSameRoot(root, signal, deadline) {
|
|
2446
|
-
const current = await readProcess(root.pid, deadline);
|
|
2447
|
-
return Boolean(current && isSameLiveRoot(current, root) && signalProcess(current.pid, signal));
|
|
2448
|
-
}
|
|
2449
|
-
function resumeTransportRoot(child, root, allowSynchronousPidFallback) {
|
|
2450
|
-
try {
|
|
2451
|
-
if (child.kill) {
|
|
2452
|
-
child.kill("SIGCONT");
|
|
2453
|
-
return;
|
|
2454
|
-
}
|
|
2455
|
-
} catch {
|
|
2456
|
-
if (!allowSynchronousPidFallback) return;
|
|
2457
|
-
}
|
|
2458
|
-
if (allowSynchronousPidFallback) signalProcess(root.pid, "SIGCONT");
|
|
2459
|
-
}
|
|
2460
|
-
async function signalSameProcess(expected, signal, deadline) {
|
|
2461
|
-
const current = await readProcess(expected.pid, deadline);
|
|
2462
|
-
return Boolean(current && isSameLiveProcess(current, expected) && signalProcess(current.pid, signal));
|
|
2463
|
-
}
|
|
2464
|
-
function hasSameIdentity(left, right) {
|
|
2465
|
-
return identityKey(left) === identityKey(right);
|
|
2466
|
-
}
|
|
2467
|
-
function identityKey(row) {
|
|
2468
|
-
return `${row.pid}\0${row.startedAt}`;
|
|
2469
|
-
}
|
|
2470
|
-
function hasExited(child) {
|
|
2471
|
-
return child.exitCode != null || child.signalCode != null;
|
|
2472
|
-
}
|
|
2473
|
-
function signalProcess(pid, signal) {
|
|
2474
|
-
try {
|
|
2475
|
-
process.kill(pid, signal);
|
|
2476
|
-
return true;
|
|
2477
|
-
} catch {
|
|
2478
|
-
return false;
|
|
2479
|
-
}
|
|
2480
|
-
}
|
|
2481
|
-
//#endregion
|
|
2482
|
-
//#region extensions/codex/src/app-server/transport.ts
|
|
2483
|
-
/**
|
|
2484
|
-
* Shared transport lifecycle helpers for stdio and WebSocket Codex app-server
|
|
2485
|
-
* connections.
|
|
2486
|
-
*/
|
|
2487
|
-
const CODEX_APP_SERVER_TRANSPORT_CLOSES = /* @__PURE__ */ new WeakMap();
|
|
2488
|
-
/** Starts graceful transport shutdown and schedules a force kill fallback. */
|
|
2489
|
-
function closeCodexAppServerTransport(child, options = {}) {
|
|
2490
|
-
beginCodexAppServerTransportClose(child, options);
|
|
2491
|
-
}
|
|
2492
|
-
function beginCodexAppServerTransportClose(child, options) {
|
|
2493
|
-
const current = CODEX_APP_SERVER_TRANSPORT_CLOSES.get(child);
|
|
2494
|
-
if (current) return current;
|
|
2495
|
-
if (process.platform === "win32" || !child.pid || !child.kill || hasCodexAppServerTransportExited(child)) {
|
|
2496
|
-
finishCodexAppServerTransportClose(child, options);
|
|
2497
|
-
const completed = Promise.resolve();
|
|
2498
|
-
CODEX_APP_SERVER_TRANSPORT_CLOSES.set(child, completed);
|
|
2499
|
-
return completed;
|
|
2500
|
-
}
|
|
2501
|
-
const closing = (async () => {
|
|
2502
|
-
let resumeRoot;
|
|
2503
|
-
try {
|
|
2504
|
-
resumeRoot = await terminateCodexAppServerDescendants(child);
|
|
2505
|
-
} catch {
|
|
2506
|
-
resumeRoot = void 0;
|
|
2507
|
-
}
|
|
2508
|
-
try {
|
|
2509
|
-
finishCodexAppServerTransportClose(child, options, resumeRoot);
|
|
2510
|
-
} catch {
|
|
2511
|
-
signalCodexAppServerTransport(child, "SIGKILL");
|
|
2512
|
-
}
|
|
2513
|
-
})();
|
|
2514
|
-
CODEX_APP_SERVER_TRANSPORT_CLOSES.set(child, closing);
|
|
2515
|
-
return closing;
|
|
2516
|
-
}
|
|
2517
|
-
function finishCodexAppServerTransportClose(child, options, resumeRoot) {
|
|
2518
|
-
const forceKillDelayMs = options.forceKillDelayMs ?? 1e3;
|
|
2519
|
-
const forceKill = setTimeout(() => {
|
|
2520
|
-
if (hasCodexAppServerTransportExited(child)) return;
|
|
2521
|
-
signalCodexAppServerTransport(child, "SIGKILL");
|
|
2522
|
-
}, Math.max(1, forceKillDelayMs));
|
|
2523
|
-
forceKill.unref?.();
|
|
2524
|
-
child.once("exit", () => {
|
|
2525
|
-
clearTimeout(forceKill);
|
|
2526
|
-
child.stdout.destroy?.();
|
|
2527
|
-
child.stderr.destroy?.();
|
|
2528
|
-
});
|
|
2529
|
-
try {
|
|
2530
|
-
child.stdin.end?.();
|
|
2531
|
-
child.stdin.destroy?.();
|
|
2532
|
-
} finally {
|
|
2533
|
-
resumeRoot?.();
|
|
2534
|
-
}
|
|
2535
|
-
child.unref?.();
|
|
2536
|
-
child.stdout.unref?.();
|
|
2537
|
-
child.stderr.unref?.();
|
|
2538
|
-
child.stdin.unref?.();
|
|
2539
|
-
}
|
|
2540
|
-
/** Closes a transport and waits briefly for an exit event. */
|
|
2541
|
-
async function closeCodexAppServerTransportAndWait(child, options = {}) {
|
|
2542
|
-
if (!hasCodexAppServerTransportExited(child)) await beginCodexAppServerTransportClose(child, options);
|
|
2543
|
-
return await waitForCodexAppServerTransportExit(child, options.exitTimeoutMs ?? 2e3);
|
|
2544
|
-
}
|
|
2545
|
-
function hasCodexAppServerTransportExited(child) {
|
|
2546
|
-
return child.exitCode !== null && child.exitCode !== void 0 ? true : child.signalCode !== null && child.signalCode !== void 0;
|
|
2547
|
-
}
|
|
2548
|
-
async function waitForCodexAppServerTransportExit(child, timeoutMs) {
|
|
2549
|
-
if (hasCodexAppServerTransportExited(child)) return true;
|
|
2550
|
-
return await new Promise((resolve) => {
|
|
2551
|
-
let settled = false;
|
|
2552
|
-
const onExit = () => {
|
|
2553
|
-
if (settled) return;
|
|
2554
|
-
settled = true;
|
|
2555
|
-
clearTimeout(timeout);
|
|
2556
|
-
resolve(true);
|
|
2557
|
-
};
|
|
2558
|
-
const timeout = setTimeout(() => {
|
|
2559
|
-
if (settled) return;
|
|
2560
|
-
settled = true;
|
|
2561
|
-
child.off?.("exit", onExit);
|
|
2562
|
-
resolve(false);
|
|
2563
|
-
}, Math.max(1, timeoutMs));
|
|
2564
|
-
child.once("exit", onExit);
|
|
2565
|
-
});
|
|
2566
|
-
}
|
|
2567
|
-
function signalCodexAppServerTransport(child, signal) {
|
|
2568
|
-
if (child.pid && process.platform !== "win32") try {
|
|
2569
|
-
process.kill(-child.pid, signal);
|
|
2570
|
-
return;
|
|
2571
|
-
} catch {}
|
|
2572
|
-
child.kill?.(signal);
|
|
2573
|
-
}
|
|
2574
|
-
//#endregion
|
|
2575
5364
|
//#region extensions/codex/src/app-server/client.ts
|
|
2576
5365
|
/**
|
|
2577
5366
|
* JSON-RPC client for Codex app-server transports, including request/response
|
|
2578
5367
|
* routing, notification fanout, server request handlers, and version checks.
|
|
2579
5368
|
*/
|
|
2580
5369
|
const CODEX_APP_SERVER_PARSE_LOG_MAX = 500;
|
|
2581
|
-
const CODEX_APP_SERVER_PARSE_BUFFER_MAX =
|
|
5370
|
+
const CODEX_APP_SERVER_PARSE_BUFFER_MAX = 8388608;
|
|
2582
5371
|
const CODEX_APP_SERVER_PARSE_BUFFER_MAX_LINES = 1e3;
|
|
2583
|
-
const CODEX_DYNAMIC_TOOL_SERVER_REQUEST_TIMEOUT_MS = 66e4;
|
|
2584
5372
|
const CODEX_APP_SERVER_STDERR_TAIL_MAX = 2e3;
|
|
2585
5373
|
const CODEX_APP_SERVER_OVERLOADED_ERROR_CODE = -32001;
|
|
2586
5374
|
const CODEX_APP_SERVER_OVERLOAD_MAX_RETRIES = 3;
|
|
@@ -2599,6 +5387,10 @@ function getCodexAppServerClientInstanceId(client) {
|
|
|
2599
5387
|
function resolveCodexAppServerClientInstanceId(client) {
|
|
2600
5388
|
return client.getInstanceId?.call(client) ?? getCodexAppServerClientInstanceId(client);
|
|
2601
5389
|
}
|
|
5390
|
+
/** Codex rejects this exact code before enqueueing, including mutating requests. */
|
|
5391
|
+
function isCodexAppServerOverloadError(error) {
|
|
5392
|
+
return error instanceof CodexAppServerRpcError && error.code === CODEX_APP_SERVER_OVERLOADED_ERROR_CODE;
|
|
5393
|
+
}
|
|
2602
5394
|
var CodexAppServerLocalRequestCancellationError = class extends Error {
|
|
2603
5395
|
constructor(method, reason, mayHaveWritten) {
|
|
2604
5396
|
super(`${method} ${reason}`);
|
|
@@ -2658,6 +5450,7 @@ var CodexAppServerClient = class CodexAppServerClient {
|
|
|
2658
5450
|
this.closeHandlers = /* @__PURE__ */ new Set();
|
|
2659
5451
|
this.nextId = 1;
|
|
2660
5452
|
this.initialized = false;
|
|
5453
|
+
this.modelCatalogRevision = 0;
|
|
2661
5454
|
this.closed = false;
|
|
2662
5455
|
this.transportExited = false;
|
|
2663
5456
|
this.stderrTail = "";
|
|
@@ -2683,7 +5476,7 @@ var CodexAppServerClient = class CodexAppServerClient {
|
|
|
2683
5476
|
child.stdin.on?.("error", (error) => this.closeWithError(toStringifiedError(error)));
|
|
2684
5477
|
}
|
|
2685
5478
|
/** Starts a new app-server client using resolved runtime start options. */
|
|
2686
|
-
static start(options) {
|
|
5479
|
+
static async start(options, assertCurrent) {
|
|
2687
5480
|
const defaults = resolveCodexAppServerRuntimeOptions().start;
|
|
2688
5481
|
const startOptions = {
|
|
2689
5482
|
...defaults,
|
|
@@ -2692,7 +5485,18 @@ var CodexAppServerClient = class CodexAppServerClient {
|
|
|
2692
5485
|
};
|
|
2693
5486
|
if (startOptions.transport === "stdio" && startOptions.commandSource === "managed") throw new Error("Managed Codex app-server start options must be resolved before spawn.");
|
|
2694
5487
|
if (startOptions.transport === "websocket" || startOptions.transport === "unix") return new CodexAppServerClient(createWebSocketTransport(startOptions));
|
|
2695
|
-
|
|
5488
|
+
let client;
|
|
5489
|
+
try {
|
|
5490
|
+
await createStdioTransport(startOptions, process.env, assertCurrent, (child) => {
|
|
5491
|
+
client = new CodexAppServerClient(child);
|
|
5492
|
+
});
|
|
5493
|
+
return client;
|
|
5494
|
+
} catch (error) {
|
|
5495
|
+
assertCurrent?.();
|
|
5496
|
+
if (client?.transportExited && hasCodexAppServerNaturalExit(client.child)) throw buildCodexAppServerExitError(client.child.exitCode, client.child.signalCode, client.stderrTail);
|
|
5497
|
+
const stderr = client?.getStderrDiagnostic();
|
|
5498
|
+
throw stderr ? new Error(`${coerceErrorMessage(error)}; stderr=${JSON.stringify(stderr)}`, { cause: error }) : error;
|
|
5499
|
+
}
|
|
2696
5500
|
}
|
|
2697
5501
|
/** Builds a client around a fake transport for tests. */
|
|
2698
5502
|
static fromTransportForTests(child) {
|
|
@@ -2741,6 +5545,10 @@ var CodexAppServerClient = class CodexAppServerClient {
|
|
|
2741
5545
|
getInstanceId() {
|
|
2742
5546
|
return this.instanceId;
|
|
2743
5547
|
}
|
|
5548
|
+
/** Account/config observations become stale before a mutation can enter the wire. */
|
|
5549
|
+
getModelCatalogRevision() {
|
|
5550
|
+
return this.modelCatalogRevision;
|
|
5551
|
+
}
|
|
2744
5552
|
/** Installs the spawn-owner check run before config-loading thread requests. */
|
|
2745
5553
|
setThreadSessionRequestGuard(guard) {
|
|
2746
5554
|
this.threadSessionRequestGuard = guard;
|
|
@@ -2750,8 +5558,7 @@ var CodexAppServerClient = class CodexAppServerClient {
|
|
|
2750
5558
|
return this.child.pid;
|
|
2751
5559
|
}
|
|
2752
5560
|
request(method, params, optionsInput) {
|
|
2753
|
-
|
|
2754
|
-
options ??= {};
|
|
5561
|
+
const options = optionsInput ?? {};
|
|
2755
5562
|
if (this.closed) return Promise.reject(this.closeError ?? /* @__PURE__ */ new Error("codex app-server client is closed"));
|
|
2756
5563
|
if (options.signal?.aborted) return Promise.reject(new CodexAppServerLocalRequestCancellationError(method, "aborted", false));
|
|
2757
5564
|
const guard = method === "thread/start" || method === "thread/resume" || method === "thread/fork" ? this.threadSessionRequestGuard : void 0;
|
|
@@ -2786,11 +5593,11 @@ var CodexAppServerClient = class CodexAppServerClient {
|
|
|
2786
5593
|
const elapsedMs = Date.now() - guardStartedAt;
|
|
2787
5594
|
const remainingTimeoutMs = options.timeoutMs === void 0 ? void 0 : options.timeoutMs - elapsedMs;
|
|
2788
5595
|
if (remainingTimeoutMs !== void 0 && remainingTimeoutMs <= 0) throw new CodexAppServerLocalRequestCancellationError(method, "timed out", false);
|
|
2789
|
-
return await this.
|
|
5596
|
+
return await this.requestWithOverloadRetry(method, params, {
|
|
2790
5597
|
...options,
|
|
2791
5598
|
...remainingTimeoutMs !== void 0 ? { timeoutMs: remainingTimeoutMs } : {}
|
|
2792
|
-
}, () => {
|
|
2793
|
-
requestMayHaveWritten =
|
|
5599
|
+
}, (mayHaveWritten) => {
|
|
5600
|
+
requestMayHaveWritten = mayHaveWritten;
|
|
2794
5601
|
});
|
|
2795
5602
|
} catch (error) {
|
|
2796
5603
|
if (requestMayHaveWritten && !(error instanceof CodexAppServerRpcError)) {
|
|
@@ -2803,12 +5610,9 @@ var CodexAppServerClient = class CodexAppServerClient {
|
|
|
2803
5610
|
}
|
|
2804
5611
|
})();
|
|
2805
5612
|
}
|
|
2806
|
-
return this.
|
|
5613
|
+
return this.requestWithOverloadRetry(method, params, options);
|
|
2807
5614
|
}
|
|
2808
|
-
|
|
2809
|
-
return this.requestWithOverloadRetry(method, params, options, onWriteAttempt);
|
|
2810
|
-
}
|
|
2811
|
-
async requestWithOverloadRetry(method, params, options, onWriteAttempt) {
|
|
5615
|
+
async requestWithOverloadRetry(method, params, options, onWriteStateChange) {
|
|
2812
5616
|
const deadline = options.timeoutMs !== void 0 && Number.isFinite(options.timeoutMs) ? Date.now() + options.timeoutMs : void 0;
|
|
2813
5617
|
for (let retry = 0;; retry += 1) {
|
|
2814
5618
|
if (options.signal?.aborted) throw new CodexAppServerLocalRequestCancellationError(method, "aborted", false);
|
|
@@ -2818,9 +5622,10 @@ var CodexAppServerClient = class CodexAppServerClient {
|
|
|
2818
5622
|
return await this.requestOnce(method, params, {
|
|
2819
5623
|
...options,
|
|
2820
5624
|
...remainingTimeoutMs !== void 0 ? { timeoutMs: remainingTimeoutMs } : {}
|
|
2821
|
-
},
|
|
5625
|
+
}, onWriteStateChange);
|
|
2822
5626
|
} catch (error) {
|
|
2823
|
-
if (!(error
|
|
5627
|
+
if (!isCodexAppServerOverloadError(error) || retry >= CODEX_APP_SERVER_OVERLOAD_MAX_RETRIES) throw error;
|
|
5628
|
+
onWriteStateChange?.(false);
|
|
2824
5629
|
const backoffMs = Math.round(CODEX_APP_SERVER_OVERLOAD_RETRY_BASE_MS * 2 ** retry * (.75 + Math.random() * .5));
|
|
2825
5630
|
await this.waitForOverloadRetry(method, backoffMs, deadline, options.signal);
|
|
2826
5631
|
}
|
|
@@ -2849,10 +5654,11 @@ var CodexAppServerClient = class CodexAppServerClient {
|
|
|
2849
5654
|
if (signal?.aborted) abortListener();
|
|
2850
5655
|
});
|
|
2851
5656
|
}
|
|
2852
|
-
requestOnce(method, params, options,
|
|
5657
|
+
requestOnce(method, params, options, onWriteStateChange) {
|
|
2853
5658
|
if (this.closed) return Promise.reject(this.closeError ?? /* @__PURE__ */ new Error("codex app-server client is closed"));
|
|
2854
5659
|
if (options.signal?.aborted) return Promise.reject(new CodexAppServerLocalRequestCancellationError(method, "aborted", false));
|
|
2855
5660
|
const id = this.nextId++;
|
|
5661
|
+
if (method === "account/login/start" || method === "account/logout" || method === "config/value/write" || method === "config/batchWrite") this.modelCatalogRevision += 1;
|
|
2856
5662
|
const message = {
|
|
2857
5663
|
id,
|
|
2858
5664
|
method,
|
|
@@ -2902,8 +5708,9 @@ var CodexAppServerClient = class CodexAppServerClient {
|
|
|
2902
5708
|
return;
|
|
2903
5709
|
}
|
|
2904
5710
|
try {
|
|
5711
|
+
options.assertCurrent?.();
|
|
2905
5712
|
mayHaveWritten = true;
|
|
2906
|
-
|
|
5713
|
+
onWriteStateChange?.(true);
|
|
2907
5714
|
this.writeMessage(message, (error) => rejectPending(error));
|
|
2908
5715
|
} catch (error) {
|
|
2909
5716
|
rejectPending(toStringifiedError(error));
|
|
@@ -3105,8 +5912,9 @@ var CodexAppServerClient = class CodexAppServerClient {
|
|
|
3105
5912
|
}
|
|
3106
5913
|
async runServerRequestHandlers(request) {
|
|
3107
5914
|
const controller = new AbortController();
|
|
3108
|
-
|
|
3109
|
-
|
|
5915
|
+
if (request.method !== "item/tool/call") return await this.runServerRequestHandlersWithoutTimeout(request, controller.signal);
|
|
5916
|
+
const timeoutMs = resolveDynamicToolServerRequestTimeoutMs(readCodexDynamicToolCallParams(request.params));
|
|
5917
|
+
const timeoutResponse = timeoutServerRequestResponse(timeoutMs);
|
|
3110
5918
|
let timeout;
|
|
3111
5919
|
try {
|
|
3112
5920
|
return await Promise.race([this.runServerRequestHandlersWithoutTimeout(request, controller.signal), new Promise((resolve) => {
|
|
@@ -3114,11 +5922,11 @@ var CodexAppServerClient = class CodexAppServerClient {
|
|
|
3114
5922
|
embeddedAgentLog.warn("codex app-server server request timed out", {
|
|
3115
5923
|
id: request.id,
|
|
3116
5924
|
method: request.method,
|
|
3117
|
-
timeoutMs
|
|
5925
|
+
timeoutMs
|
|
3118
5926
|
});
|
|
3119
5927
|
controller.abort(/* @__PURE__ */ new Error("codex app-server server request timed out"));
|
|
3120
5928
|
resolve(timeoutResponse);
|
|
3121
|
-
},
|
|
5929
|
+
}, timeoutMs);
|
|
3122
5930
|
timeout.unref?.();
|
|
3123
5931
|
})]);
|
|
3124
5932
|
} finally {
|
|
@@ -3133,6 +5941,7 @@ var CodexAppServerClient = class CodexAppServerClient {
|
|
|
3133
5941
|
}
|
|
3134
5942
|
}
|
|
3135
5943
|
handleNotification(notification) {
|
|
5944
|
+
if (notification.method === "account/updated") this.modelCatalogRevision += 1;
|
|
3136
5945
|
if (this.notificationHandlers.size === 0 && notification.method === "configWarning") {
|
|
3137
5946
|
if (this.pendingStartupWarnings.length === CODEX_APP_SERVER_PENDING_STARTUP_WARNINGS_MAX) this.pendingStartupWarnings.shift();
|
|
3138
5947
|
this.pendingStartupWarnings.push(notification);
|
|
@@ -3186,12 +5995,11 @@ function defaultServerRequestResponse(request) {
|
|
|
3186
5995
|
function stringifyCodexAppServerMessage(message) {
|
|
3187
5996
|
return JSON.stringify(message, (_key, value) => typeof value === "string" ? value.replace(UNPAIRED_SURROGATE_RE, "") : value) ?? "null";
|
|
3188
5997
|
}
|
|
3189
|
-
function timeoutServerRequestResponse(
|
|
3190
|
-
if (request.method !== "item/tool/call") return;
|
|
5998
|
+
function timeoutServerRequestResponse(timeoutMs) {
|
|
3191
5999
|
return {
|
|
3192
6000
|
contentItems: [{
|
|
3193
6001
|
type: "inputText",
|
|
3194
|
-
text: `OpenClaw dynamic tool call timed out after ${
|
|
6002
|
+
text: `OpenClaw dynamic tool call timed out after ${timeoutMs}ms before sending a response to Codex.`
|
|
3195
6003
|
}],
|
|
3196
6004
|
success: false
|
|
3197
6005
|
};
|
|
@@ -3210,7 +6018,7 @@ function assertSupportedCodexAppServerVersion(response) {
|
|
|
3210
6018
|
if (!detectedVersion) throw new CodexAppServerVersionError(detectedVersion);
|
|
3211
6019
|
const detected = parse(detectedVersion);
|
|
3212
6020
|
if (!detected || detected.compare("0.149.0") < 0) throw new CodexAppServerVersionError(detectedVersion);
|
|
3213
|
-
if (detected.compare("0.
|
|
6021
|
+
if (detected.compare("0.152.1") > 0) embeddedAgentLog.warn("codex app-server is newer than OpenClaw's managed runtime; continuing with normal startup validation", {
|
|
3214
6022
|
detectedVersion,
|
|
3215
6023
|
validatedVersion: CODEX_APP_SERVER_VERSION
|
|
3216
6024
|
});
|
|
@@ -3287,15 +6095,8 @@ function formatExitValue(value) {
|
|
|
3287
6095
|
*/
|
|
3288
6096
|
/** Minimum startup timeout accepted by the Codex app-server harness. */
|
|
3289
6097
|
const CODEX_APP_SERVER_STARTUP_TIMEOUT_FLOOR_MS = 100;
|
|
3290
|
-
|
|
3291
|
-
const
|
|
3292
|
-
/** Short guard after apparent assistant completion. */
|
|
3293
|
-
const CODEX_TURN_ASSISTANT_COMPLETION_IDLE_TIMEOUT_MS = 1e4;
|
|
3294
|
-
const CODEX_POST_TOOL_RAW_ASSISTANT_COMPLETION_IDLE_TIMEOUT_MS = 5 * 6e4;
|
|
3295
|
-
/** Guard after reasoning/commentary progress when no tool handoff occurred. */
|
|
3296
|
-
const CODEX_POST_REASONING_REPLY_IDLE_TIMEOUT_MS = 5 * 6e4;
|
|
3297
|
-
/** Long terminal idle watch for app-server turns that never send completion. */
|
|
3298
|
-
const CODEX_TURN_TERMINAL_IDLE_TIMEOUT_MS = 30 * 6e4;
|
|
6098
|
+
const TURN_TERMINAL_SETTLEMENT_TIMEOUT_MS = 12e4;
|
|
6099
|
+
const TURN_FINALIZE_DRAIN_ABORT_GRACE_MS = 5e3;
|
|
3299
6100
|
var CodexAppServerStartupError = class extends Error {
|
|
3300
6101
|
constructor(reason, message = reason === "timed_out" ? "codex app-server startup timed out" : "codex app-server startup aborted") {
|
|
3301
6102
|
super(message);
|
|
@@ -3308,7 +6109,8 @@ function isCodexAppServerStartupError(error, reason) {
|
|
|
3308
6109
|
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);
|
|
3309
6110
|
}
|
|
3310
6111
|
function resolvePositiveIntegerTimeoutMs(value, fallbackMs) {
|
|
3311
|
-
|
|
6112
|
+
const fallback = resolveTimerTimeoutMs(fallbackMs, 1);
|
|
6113
|
+
return resolveTimerTimeoutMs(value, fallback);
|
|
3312
6114
|
}
|
|
3313
6115
|
/** Runs startup work with abort and timeout handling plus optional cleanup. */
|
|
3314
6116
|
async function withCodexStartupTimeout(params) {
|
|
@@ -3354,27 +6156,11 @@ function resolveCodexStartupTimeoutMs(params) {
|
|
|
3354
6156
|
const timeoutMs = resolvePositiveIntegerTimeoutMs(params.timeoutMs, timeoutFloorMs);
|
|
3355
6157
|
return Math.max(timeoutFloorMs, timeoutMs);
|
|
3356
6158
|
}
|
|
3357
|
-
/** Resolves the completion-idle timeout for an active turn. */
|
|
3358
|
-
function resolveCodexTurnCompletionIdleTimeoutMs(value) {
|
|
3359
|
-
return resolvePositiveIntegerTimeoutMs(value, CODEX_TURN_COMPLETION_IDLE_TIMEOUT_MS);
|
|
3360
|
-
}
|
|
3361
|
-
/** Resolves the short assistant-completion release timeout. */
|
|
3362
|
-
function resolveCodexTurnAssistantCompletionIdleTimeoutMs(value) {
|
|
3363
|
-
return resolvePositiveIntegerTimeoutMs(value, CODEX_TURN_ASSISTANT_COMPLETION_IDLE_TIMEOUT_MS);
|
|
3364
|
-
}
|
|
3365
|
-
/** Resolves the conservative post-tool raw assistant guard timeout. */
|
|
3366
|
-
function resolveCodexPostToolRawAssistantCompletionIdleTimeoutMs(value, fallbackMs) {
|
|
3367
|
-
return resolvePositiveIntegerTimeoutMs(value, Math.max(resolvePositiveIntegerTimeoutMs(void 0, fallbackMs), CODEX_POST_TOOL_RAW_ASSISTANT_COMPLETION_IDLE_TIMEOUT_MS));
|
|
3368
|
-
}
|
|
3369
|
-
/** Resolves the long terminal turn idle timeout. */
|
|
3370
|
-
function resolveCodexTurnTerminalIdleTimeoutMs(value, runTimeoutOverrideMs) {
|
|
3371
|
-
const explicitRunBudgetMs = resolvePositiveIntegerTimeoutMs(runTimeoutOverrideMs, CODEX_TURN_TERMINAL_IDLE_TIMEOUT_MS);
|
|
3372
|
-
return resolvePositiveIntegerTimeoutMs(value, Math.max(CODEX_TURN_TERMINAL_IDLE_TIMEOUT_MS, explicitRunBudgetMs));
|
|
3373
|
-
}
|
|
3374
6159
|
/** Adds gateway grace time to a caller timeout without overflowing invalid values. */
|
|
3375
6160
|
function resolveCodexGatewayTimeoutWithGraceMs(timeoutMs, graceMs = 1e4) {
|
|
3376
6161
|
const timeout = resolvePositiveIntegerTimeoutMs(timeoutMs, 1);
|
|
3377
|
-
|
|
6162
|
+
const grace = resolveTimerTimeoutMs(graceMs, 0, 0);
|
|
6163
|
+
return addTimerTimeoutGraceMs(timeout, grace) ?? timeout;
|
|
3378
6164
|
}
|
|
3379
6165
|
//#endregion
|
|
3380
6166
|
//#region extensions/codex/src/app-server/desktop-generation-fingerprint.ts
|
|
@@ -3459,8 +6245,8 @@ async function statFingerprint(filePath) {
|
|
|
3459
6245
|
}
|
|
3460
6246
|
}
|
|
3461
6247
|
async function readFileFingerprint(filePath, expected, followsSymlink) {
|
|
3462
|
-
const noFollow = followsSymlink ? 0 : constants.O_NOFOLLOW ?? 0;
|
|
3463
|
-
const handle = await fs.open(filePath, constants.O_RDONLY | noFollow);
|
|
6248
|
+
const noFollow = followsSymlink ? 0 : constants$1.O_NOFOLLOW ?? 0;
|
|
6249
|
+
const handle = await fs.open(filePath, constants$1.O_RDONLY | noFollow);
|
|
3464
6250
|
try {
|
|
3465
6251
|
const before = await handle.stat({ bigint: true });
|
|
3466
6252
|
if (!sameStat(before, expected)) throw new Error(`Codex desktop artifact changed while fingerprinting: ${filePath}`);
|
|
@@ -3757,6 +6543,26 @@ async function waitForPreviousFence(previous, options) {
|
|
|
3757
6543
|
});
|
|
3758
6544
|
}
|
|
3759
6545
|
//#endregion
|
|
6546
|
+
//#region extensions/codex/src/app-server/thread-lifecycle-errors.ts
|
|
6547
|
+
var CodexThreadStartRequestError = class extends Error {
|
|
6548
|
+
constructor(cause) {
|
|
6549
|
+
super(`thread/start: ${formatErrorMessage(cause)}`, { cause });
|
|
6550
|
+
this.name = "CodexThreadStartRequestError";
|
|
6551
|
+
}
|
|
6552
|
+
};
|
|
6553
|
+
var CodexThreadBindingConflictError = class extends Error {
|
|
6554
|
+
constructor(threadId, operation) {
|
|
6555
|
+
super(`Codex thread binding changed while ${operation}: ${threadId}`);
|
|
6556
|
+
this.name = "CodexThreadBindingConflictError";
|
|
6557
|
+
}
|
|
6558
|
+
};
|
|
6559
|
+
var CodexAdoptedThreadActiveError = class extends AgentHarnessPreflightError {
|
|
6560
|
+
constructor(message = "Codex session became active in another runner; wait for it to finish before continuing") {
|
|
6561
|
+
super(message);
|
|
6562
|
+
this.name = "CodexAdoptedThreadActiveError";
|
|
6563
|
+
}
|
|
6564
|
+
};
|
|
6565
|
+
//#endregion
|
|
3760
6566
|
//#region extensions/codex/src/app-server/shared-client.ts
|
|
3761
6567
|
/**
|
|
3762
6568
|
* Owns shared and isolated Codex app-server client startup, auth application,
|
|
@@ -3764,6 +6570,8 @@ async function waitForPreviousFence(previous, options) {
|
|
|
3764
6570
|
*/
|
|
3765
6571
|
var shared_client_exports = /* @__PURE__ */ __exportAll({
|
|
3766
6572
|
assertCodexAppServerClientStartSelectionCurrent: () => assertCodexAppServerClientStartSelectionCurrent,
|
|
6573
|
+
captureCodexAppServerClientLifetime: () => captureCodexAppServerClientLifetime,
|
|
6574
|
+
captureSharedCodexAppServerCatalogLifetime: () => captureSharedCodexAppServerCatalogLifetime,
|
|
3767
6575
|
clearSharedCodexAppServerClientAndWait: () => clearSharedCodexAppServerClientAndWait,
|
|
3768
6576
|
clearSharedCodexAppServerClientIfCurrent: () => clearSharedCodexAppServerClientIfCurrent,
|
|
3769
6577
|
clearSharedCodexAppServerClientIfCurrentAndUnclaimed: () => clearSharedCodexAppServerClientIfCurrentAndUnclaimed,
|
|
@@ -3902,7 +6710,7 @@ async function resolveCodexAppServerClientStartContext(options) {
|
|
|
3902
6710
|
const preparedAuth = options?.preparedAuth;
|
|
3903
6711
|
const preparedApiKey = preparedAuth?.kind === "api-key" ? preparedAuth.apiKey.trim() : void 0;
|
|
3904
6712
|
if (preparedAuth && options?.authProfileId !== void 0) throw new Error("Prepared Codex auth cannot also select a legacy auth profile.");
|
|
3905
|
-
if (preparedAuth?.kind === "profile" && !preparedAuth.store.profiles[preparedAuth.profileId]) throw new Error(`Prepared Codex auth profile "${preparedAuth.profileId}" was not found.`);
|
|
6713
|
+
if (preparedAuth?.kind === "profile" && !preparedAuth.store.profiles[preparedAuth.profileId]) throw new Error(`Prepared Codex auth profile "${preparedAuth.profileId}" was not found. Select an existing OpenAI profile or sign in again with OpenClaw, then retry.`);
|
|
3906
6714
|
if (preparedAuth?.kind === "api-key" && !preparedApiKey) throw new Error("Prepared Codex API-key auth is missing its resolved key.");
|
|
3907
6715
|
if (preparedAuth && requestedStartOptions.homeScope === "user") throw new Error("Prepared Codex auth requires an isolated app-server home.");
|
|
3908
6716
|
const preparedAuthRequirement = inferAuthRequirement(preparedAuth);
|
|
@@ -3910,11 +6718,11 @@ async function resolveCodexAppServerClientStartContext(options) {
|
|
|
3910
6718
|
const authRequirement = options?.authRequirement ?? preparedAuthRequirement;
|
|
3911
6719
|
const usesNativeAuth = !preparedAuth && (options?.authProfileId === null || requestedStartOptions.homeScope === "user");
|
|
3912
6720
|
const requestedAuthProfileId = preparedAuth?.kind === "profile" ? preparedAuth.profileId : options?.authProfileId ?? void 0;
|
|
3913
|
-
const authProfileStore = preparedAuth?.kind === "profile" ? preparedAuth.store : !usesNativeAuth &&
|
|
6721
|
+
const authProfileStore = preparedAuth?.kind === "profile" ? preparedAuth.store : !usesNativeAuth && preparedAuth?.kind !== "api-key" ? resolveCodexAppServerAuthProfileStore({
|
|
3914
6722
|
agentDir,
|
|
3915
6723
|
authProfileId: requestedAuthProfileId,
|
|
3916
|
-
authProfileStore: options
|
|
3917
|
-
config: options
|
|
6724
|
+
authProfileStore: options?.authProfileStore,
|
|
6725
|
+
config: options?.config
|
|
3918
6726
|
}) : options?.authProfileStore;
|
|
3919
6727
|
const authProfileId = preparedAuth?.kind === "profile" ? preparedAuth.profileId : usesNativeAuth || preparedAuth?.kind === "api-key" ? void 0 : resolveCodexAppServerAuthProfileIdForAgent({
|
|
3920
6728
|
authProfileId: requestedAuthProfileId,
|
|
@@ -3922,20 +6730,26 @@ async function resolveCodexAppServerClientStartContext(options) {
|
|
|
3922
6730
|
config: options?.config,
|
|
3923
6731
|
...authProfileStore ? { authProfileStore } : {}
|
|
3924
6732
|
});
|
|
3925
|
-
const preparedAuthProfileSnapshot = preparedAuth?.kind === "profile" ? preparedAuth.snapshot ?? await resolveCodexAppServerPreparedAuthProfileSnapshot({
|
|
6733
|
+
const preparedAuthProfileSnapshot = !usesNativeAuth && authProfileId ? (preparedAuth?.kind === "profile" ? preparedAuth.snapshot : void 0) ?? await resolveCodexAppServerPreparedAuthProfileSnapshot({
|
|
3926
6734
|
authProfileId,
|
|
3927
6735
|
authProfileStore,
|
|
3928
6736
|
agentDir,
|
|
3929
6737
|
config: options?.config
|
|
3930
6738
|
}) : void 0;
|
|
3931
|
-
if (preparedAuth?.kind === "profile" && !preparedAuthProfileSnapshot) throw new Error(`Prepared Codex auth profile "${preparedAuth.profileId}" is unusable.`);
|
|
6739
|
+
if (preparedAuth?.kind === "profile" && !preparedAuthProfileSnapshot) throw new Error(`Prepared Codex auth profile "${preparedAuth.profileId}" is unusable. Repair or replace the selected OpenAI profile, then retry.`);
|
|
3932
6740
|
const resolvedPreparedAuth = preparedAuth?.kind === "api-key" ? {
|
|
3933
6741
|
kind: "api-key",
|
|
3934
6742
|
apiKey: preparedApiKey
|
|
3935
|
-
} :
|
|
3936
|
-
|
|
6743
|
+
} : preparedAuthProfileSnapshot && authProfileId && authProfileStore ? {
|
|
6744
|
+
kind: "profile",
|
|
6745
|
+
profileId: authProfileId,
|
|
6746
|
+
store: authProfileStore,
|
|
3937
6747
|
snapshot: preparedAuthProfileSnapshot
|
|
3938
6748
|
} : void 0;
|
|
6749
|
+
const agentStartOptions = resolveCodexAppServerStartOptionsForAgent({
|
|
6750
|
+
startOptions: requestedStartOptions,
|
|
6751
|
+
agentDir
|
|
6752
|
+
});
|
|
3939
6753
|
return {
|
|
3940
6754
|
agentDir,
|
|
3941
6755
|
usesNativeAuth,
|
|
@@ -3945,14 +6759,11 @@ async function resolveCodexAppServerClientStartContext(options) {
|
|
|
3945
6759
|
preparedAuth: resolvedPreparedAuth,
|
|
3946
6760
|
authRequirement,
|
|
3947
6761
|
startOptions: await bridgeCodexAppServerStartOptions({
|
|
3948
|
-
startOptions: await resolveManagedCodexAppServerStartOptions(
|
|
3949
|
-
startOptions: requestedStartOptions,
|
|
3950
|
-
agentDir
|
|
3951
|
-
})),
|
|
6762
|
+
startOptions: await resolveManagedCodexAppServerStartOptions(agentStartOptions),
|
|
3952
6763
|
agentId: options?.agentId,
|
|
3953
6764
|
agentDir,
|
|
3954
6765
|
authProfileId: usesNativeAuth || preparedAuth?.kind === "api-key" ? null : authProfileId,
|
|
3955
|
-
...resolvedPreparedAuth ? { preparedAuth: resolvedPreparedAuth } : {},
|
|
6766
|
+
...preparedAuth && resolvedPreparedAuth ? { preparedAuth: resolvedPreparedAuth } : {},
|
|
3956
6767
|
authRequirement,
|
|
3957
6768
|
config: options?.config,
|
|
3958
6769
|
pluginConfig: options?.pluginConfig,
|
|
@@ -3967,44 +6778,6 @@ function shouldTrackDesktopGeneration(startOptions, pluginConfig) {
|
|
|
3967
6778
|
if (resolveCodexComputerUseConfig({ pluginConfig }).enabled && (startOptions.commandSource === "managed" || startOptions.commandSource === "resolved-managed")) return true;
|
|
3968
6779
|
return startOptions.commandSource === "managed" && (startOptions.managedCommandOrder ?? "package-first") === "desktop-first";
|
|
3969
6780
|
}
|
|
3970
|
-
function resolveWarmSharedCodexAppServerClientIdentity(options) {
|
|
3971
|
-
if (!options?.config || typeof options.config !== "object" || !options.startOptions || options.pluginConfig !== void 0 || options.authProfileStore !== void 0 || options.preparedAuth !== void 0 || options.runtimeArtifactMode !== void 0 || options.expectedRuntimeArtifact !== void 0) return;
|
|
3972
|
-
const authProfileSelector = options.authProfileId === null ? ["native"] : options.authProfileId === void 0 ? ["implicit"] : ["profile", options.authProfileId];
|
|
3973
|
-
return {
|
|
3974
|
-
config: options.config,
|
|
3975
|
-
startOptions: options.startOptions,
|
|
3976
|
-
selectorKey: JSON.stringify([
|
|
3977
|
-
options.agentDir ?? resolveDefaultAgentDir(options.config),
|
|
3978
|
-
authProfileSelector,
|
|
3979
|
-
options.authBindingFingerprint ?? null,
|
|
3980
|
-
options.authRequirement ?? null
|
|
3981
|
-
])
|
|
3982
|
-
};
|
|
3983
|
-
}
|
|
3984
|
-
function readWarmSharedCodexAppServerClient(state, identity) {
|
|
3985
|
-
const aliases = state.warmClientsByConfig?.get(identity.config)?.get(identity.startOptions);
|
|
3986
|
-
const warm = aliases?.get(identity.selectorKey);
|
|
3987
|
-
if (!warm) return;
|
|
3988
|
-
if (state.clients.get(warm.key) !== warm.entry || warm.entry.client !== warm.client || warm.entry.closeWhenIdle || warm.entry.closeError) {
|
|
3989
|
-
aliases?.delete(identity.selectorKey);
|
|
3990
|
-
return;
|
|
3991
|
-
}
|
|
3992
|
-
return warm;
|
|
3993
|
-
}
|
|
3994
|
-
function rememberWarmSharedCodexAppServerClient(state, identity, warm) {
|
|
3995
|
-
state.warmClientsByConfig ??= /* @__PURE__ */ new WeakMap();
|
|
3996
|
-
let byStartOptions = state.warmClientsByConfig.get(identity.config);
|
|
3997
|
-
if (!byStartOptions) {
|
|
3998
|
-
byStartOptions = /* @__PURE__ */ new WeakMap();
|
|
3999
|
-
state.warmClientsByConfig.set(identity.config, byStartOptions);
|
|
4000
|
-
}
|
|
4001
|
-
let aliases = byStartOptions.get(identity.startOptions);
|
|
4002
|
-
if (!aliases) {
|
|
4003
|
-
aliases = /* @__PURE__ */ new Map();
|
|
4004
|
-
byStartOptions.set(identity.startOptions, aliases);
|
|
4005
|
-
}
|
|
4006
|
-
aliases.set(identity.selectorKey, warm);
|
|
4007
|
-
}
|
|
4008
6781
|
/** Gets or starts a shared Codex app-server client without retaining a lease. */
|
|
4009
6782
|
async function getSharedCodexAppServerClient(options) {
|
|
4010
6783
|
return (await acquireSharedCodexAppServerClient(options)).client;
|
|
@@ -4035,7 +6808,7 @@ function releaseCodexAppServerClientLease(lease) {
|
|
|
4035
6808
|
lease.client = void 0;
|
|
4036
6809
|
return client ? releaseLeasedSharedCodexAppServerClient(client) : false;
|
|
4037
6810
|
}
|
|
4038
|
-
/** Retries one config-loading
|
|
6811
|
+
/** Retries one config-loading operation with a shared deadline and current client lease. */
|
|
4039
6812
|
async function withLeasedCodexAppServerClientStartSelectionRetry(params) {
|
|
4040
6813
|
let client = params.lease.client;
|
|
4041
6814
|
if (!client) throw new Error("Codex app-server selection retry requires an active client lease");
|
|
@@ -4051,24 +6824,40 @@ async function withLeasedCodexAppServerClientStartSelectionRetry(params) {
|
|
|
4051
6824
|
...signal ? { signal } : {}
|
|
4052
6825
|
};
|
|
4053
6826
|
};
|
|
4054
|
-
for (let attempt = 0; attempt < 2; attempt += 1)
|
|
4055
|
-
|
|
4056
|
-
|
|
4057
|
-
|
|
4058
|
-
|
|
4059
|
-
|
|
4060
|
-
|
|
4061
|
-
|
|
4062
|
-
|
|
6827
|
+
for (let attempt = 0; attempt < 2; attempt += 1) {
|
|
6828
|
+
const attemptClient = client;
|
|
6829
|
+
let scopeActive = true;
|
|
6830
|
+
const assertCurrent = () => {
|
|
6831
|
+
if (!scopeActive || params.lease.client !== attemptClient) throw new CodexAppServerStartupError("aborted", "Codex app-server request scope is closed");
|
|
6832
|
+
};
|
|
6833
|
+
try {
|
|
6834
|
+
requestOptions();
|
|
6835
|
+
return await params.run(client, () => {
|
|
6836
|
+
assertCurrent();
|
|
6837
|
+
return {
|
|
6838
|
+
...requestOptions(),
|
|
6839
|
+
assertCurrent
|
|
6840
|
+
};
|
|
6841
|
+
});
|
|
6842
|
+
} catch (error) {
|
|
6843
|
+
if (!isCodexAppServerStartSelectionChangedError(error) || attempt > 0) throw error;
|
|
6844
|
+
retireSharedCodexAppServerClientIfCurrent(client);
|
|
6845
|
+
params.lease.client = void 0;
|
|
6846
|
+
if (!releaseLeasedSharedCodexAppServerClient(client)) {
|
|
6847
|
+
client.close();
|
|
6848
|
+
throw new Error("Codex app-server selection retry requires a leased shared client", { cause: error });
|
|
6849
|
+
}
|
|
6850
|
+
const replacementOptions = requestOptions();
|
|
6851
|
+
client = await getLeasedSharedCodexAppServerClient({
|
|
6852
|
+
...params.options,
|
|
6853
|
+
timeoutMs: replacementOptions.timeoutMs,
|
|
6854
|
+
...signal ? { abandonSignal: signal } : {}
|
|
6855
|
+
});
|
|
6856
|
+
params.lease.client = client;
|
|
6857
|
+
params.onClientChange?.(client);
|
|
6858
|
+
} finally {
|
|
6859
|
+
scopeActive = false;
|
|
4063
6860
|
}
|
|
4064
|
-
const replacementOptions = requestOptions();
|
|
4065
|
-
client = await getLeasedSharedCodexAppServerClient({
|
|
4066
|
-
...params.options,
|
|
4067
|
-
timeoutMs: replacementOptions.timeoutMs,
|
|
4068
|
-
...signal ? { abandonSignal: signal } : {}
|
|
4069
|
-
});
|
|
4070
|
-
params.lease.client = client;
|
|
4071
|
-
params.onClientChange(client);
|
|
4072
6861
|
}
|
|
4073
6862
|
throw new Error("Codex app-server selection retry loop exited unexpectedly");
|
|
4074
6863
|
}
|
|
@@ -4077,24 +6866,6 @@ async function acquireSharedCodexAppServerClient(options, leaseOptions) {
|
|
|
4077
6866
|
const acquireStartedAt = Date.now();
|
|
4078
6867
|
const timeoutMs = options?.timeoutMs ?? 0;
|
|
4079
6868
|
const state = getSharedCodexAppServerClientState();
|
|
4080
|
-
const warmIdentity = resolveWarmSharedCodexAppServerClientIdentity(options);
|
|
4081
|
-
let warmClient = warmIdentity ? readWarmSharedCodexAppServerClient(state, warmIdentity) : void 0;
|
|
4082
|
-
const warmGeneration = warmClient ? getCodexAppServerClientStartMetadata().get(warmClient.client)?.desktopGeneration : void 0;
|
|
4083
|
-
if (warmClient && warmGeneration && !isCodexDesktopGenerationCurrent(warmGeneration)) {
|
|
4084
|
-
await withCodexAppServerAcquireDeadline(resolveRemainingAcquireTimeout(timeoutMs, acquireStartedAt), waitForCodexDesktopGeneration(), options?.abandonSignal);
|
|
4085
|
-
if (!isCodexDesktopGenerationCurrent(warmGeneration)) {
|
|
4086
|
-
retireSharedCodexAppServerClientIfCurrent(warmClient.client);
|
|
4087
|
-
warmClient = void 0;
|
|
4088
|
-
}
|
|
4089
|
-
}
|
|
4090
|
-
if (warmClient) {
|
|
4091
|
-
options?.onStartedClient?.(warmClient.client);
|
|
4092
|
-
const release = leaseOptions?.leased ? retainSharedClientEntry(warmClient.entry) : void 0;
|
|
4093
|
-
return release ? {
|
|
4094
|
-
client: warmClient.client,
|
|
4095
|
-
release
|
|
4096
|
-
} : { client: warmClient.client };
|
|
4097
|
-
}
|
|
4098
6869
|
const { agentDir, usesNativeAuth, authProfileId, authProfileStore, preparedAuth, authRequirement, requestedStartOptions, startOptions, desktopGeneration, pluginConfig } = await withCodexAppServerAcquireDeadline(timeoutMs, resolveCodexAppServerClientStartContext(options), options?.abandonSignal);
|
|
4099
6870
|
const remainingTimeoutMs = resolveRemainingAcquireTimeout(timeoutMs, acquireStartedAt);
|
|
4100
6871
|
const authIdentityCacheKey = preparedAuth?.kind === "api-key" ? resolveCodexAppServerPreparedApiKeyCacheKey(preparedAuth.apiKey) : preparedAuth?.snapshot.secretFreeCacheKey ?? (authRequirement === "api-key" && !authProfileId ? resolveCodexAppServerFallbackApiKeyCacheKey({ startOptions }) : void 0);
|
|
@@ -4166,11 +6937,6 @@ async function acquireSharedCodexAppServerClient(options, leaseOptions) {
|
|
|
4166
6937
|
config: options?.config
|
|
4167
6938
|
});
|
|
4168
6939
|
const release = leaseOptions?.leased ? retainSharedClientEntry(entry) : void 0;
|
|
4169
|
-
if (warmIdentity) rememberWarmSharedCodexAppServerClient(state, warmIdentity, {
|
|
4170
|
-
key,
|
|
4171
|
-
entry,
|
|
4172
|
-
client
|
|
4173
|
-
});
|
|
4174
6940
|
return release ? {
|
|
4175
6941
|
client,
|
|
4176
6942
|
release
|
|
@@ -4328,11 +7094,10 @@ async function startInitializedCodexAppServerClient(params) {
|
|
|
4328
7094
|
} finally {
|
|
4329
7095
|
artifactDrain?.cancel();
|
|
4330
7096
|
}
|
|
4331
|
-
const runtimeArtifactModule = params.runtimeArtifactMode ? await import("./runtime-artifact-
|
|
4332
|
-
const nativeCommandBeforeStart = startOptions.commandSource === "resolved-managed" ? resolveManagedCodexNativeCommand(startOptions.command) : void 0;
|
|
7097
|
+
const runtimeArtifactModule = params.runtimeArtifactMode ? await import("./runtime-artifact-C3jVimFn.js") : void 0;
|
|
4333
7098
|
const runtimeArtifactBeforeStart = runtimeArtifactModule ? await runtimeArtifactModule.captureCodexAppServerRuntimeArtifactBeforeStart({
|
|
4334
7099
|
startOptions,
|
|
4335
|
-
spawnIdentity: resolveCodexAppServerSpawnIdentity(startOptions
|
|
7100
|
+
spawnIdentity: resolveCodexAppServerSpawnIdentity(startOptions),
|
|
4336
7101
|
signal: params.runtimeArtifactSignal
|
|
4337
7102
|
}) : void 0;
|
|
4338
7103
|
if (runtimeArtifactModule && runtimeArtifactBeforeStart && params.expectedRuntimeArtifact && !runtimeArtifactModule.validateCodexAppServerRuntimeArtifactCapture(params.expectedRuntimeArtifact, runtimeArtifactBeforeStart)) {
|
|
@@ -4340,7 +7105,17 @@ async function startInitializedCodexAppServerClient(params) {
|
|
|
4340
7105
|
throw new Error("Codex app-server runtime artifact does not match verified inference");
|
|
4341
7106
|
}
|
|
4342
7107
|
assertDesktopGenerationCurrent();
|
|
4343
|
-
|
|
7108
|
+
let starting;
|
|
7109
|
+
let client;
|
|
7110
|
+
try {
|
|
7111
|
+
client = await withCodexAppServerAcquireDeadline(resolveRemainingAcquireTimeout(timeoutMs, acquireStartedAt), starting = CodexAppServerClient.start(startOptions, () => {
|
|
7112
|
+
assertDesktopGenerationCurrent();
|
|
7113
|
+
resolveRemainingAcquireTimeout(timeoutMs, acquireStartedAt);
|
|
7114
|
+
}), params.abandonSignal);
|
|
7115
|
+
} catch (error) {
|
|
7116
|
+
starting?.then((lateClient) => lateClient.close(), () => {});
|
|
7117
|
+
throw error;
|
|
7118
|
+
}
|
|
4344
7119
|
const nativeCommandAtStart = startOptions.commandSource === "resolved-managed" ? resolveManagedCodexNativeCommand(startOptions.command) : void 0;
|
|
4345
7120
|
getCodexAppServerClientStartMetadata().set(client, {
|
|
4346
7121
|
requestedStartOptions: params.requestedStartOptions,
|
|
@@ -4369,11 +7144,10 @@ async function startInitializedCodexAppServerClient(params) {
|
|
|
4369
7144
|
let runtimeArtifact;
|
|
4370
7145
|
try {
|
|
4371
7146
|
if (runtimeArtifactModule && runtimeArtifactBeforeStart) {
|
|
4372
|
-
const nativeCommand = startOptions.commandSource === "resolved-managed" ? resolveManagedCodexNativeCommand(startOptions.command) : void 0;
|
|
4373
7147
|
runtimeArtifact = await runtimeArtifactModule.finalizeCodexAppServerRuntimeArtifact({
|
|
4374
7148
|
before: runtimeArtifactBeforeStart,
|
|
4375
7149
|
startOptions,
|
|
4376
|
-
spawnIdentity: resolveCodexAppServerSpawnIdentity(startOptions
|
|
7150
|
+
spawnIdentity: resolveCodexAppServerSpawnIdentity(startOptions),
|
|
4377
7151
|
runtimeIdentity: client.getRuntimeIdentity(),
|
|
4378
7152
|
signal: params.runtimeArtifactSignal
|
|
4379
7153
|
});
|
|
@@ -4388,7 +7162,8 @@ async function startInitializedCodexAppServerClient(params) {
|
|
|
4388
7162
|
authProfileId: params.authProfileId ?? void 0,
|
|
4389
7163
|
authMode: params.preparedAuth?.kind === "api-key" ? "prepared-api-key" : "profile",
|
|
4390
7164
|
...params.authProfileStore ? { authProfileStore: params.authProfileStore } : {},
|
|
4391
|
-
config: params.config
|
|
7165
|
+
config: params.config,
|
|
7166
|
+
onAuthRefreshFailure: () => retireSharedCodexAppServerClientIfCurrent(client)
|
|
4392
7167
|
});
|
|
4393
7168
|
try {
|
|
4394
7169
|
assertDesktopGenerationCurrent();
|
|
@@ -4455,6 +7230,20 @@ function clearSharedCodexAppServerClientIfCurrent(client) {
|
|
|
4455
7230
|
}
|
|
4456
7231
|
return false;
|
|
4457
7232
|
}
|
|
7233
|
+
/** Captures a revocable observation of the exact shared client and native account/config. */
|
|
7234
|
+
function captureSharedCodexAppServerCatalogLifetime(client) {
|
|
7235
|
+
const isCurrent = captureSharedClientRegistration(client);
|
|
7236
|
+
const revision = client.getModelCatalogRevision();
|
|
7237
|
+
return () => isCurrent() && client.getModelCatalogRevision() === revision;
|
|
7238
|
+
}
|
|
7239
|
+
/** Registration ends on retirement even when sibling leases keep the process alive. */
|
|
7240
|
+
function captureSharedClientRegistration(client) {
|
|
7241
|
+
const state = getSharedCodexAppServerClientState();
|
|
7242
|
+
const entry = state.entriesByClient.get(client);
|
|
7243
|
+
const key = [...state.clients].find(([, candidate]) => candidate === entry)?.[0];
|
|
7244
|
+
const generation = readCodexAppServerClientDesktopGeneration(client);
|
|
7245
|
+
return () => key !== void 0 && state.clients.get(key) === entry && entry?.client === client && !entry.closeWhenIdle && !entry.closeError && !client.getCloseError() && (!generation || isCodexDesktopGenerationCurrent(generation));
|
|
7246
|
+
}
|
|
4458
7247
|
/** Retains the matching shared client and returns a release callback. */
|
|
4459
7248
|
function retainSharedCodexAppServerClientIfCurrent(client) {
|
|
4460
7249
|
if (!client) return;
|
|
@@ -4474,6 +7263,19 @@ function retainSharedCodexAppServerClientByInstanceId(clientId) {
|
|
|
4474
7263
|
};
|
|
4475
7264
|
}
|
|
4476
7265
|
}
|
|
7266
|
+
/** Captures physical ownership, independently of unrelated thread and reader leases. */
|
|
7267
|
+
function captureCodexAppServerClientLifetime(client, requiredOwnership) {
|
|
7268
|
+
const state = getSharedCodexAppServerClientState();
|
|
7269
|
+
const start = getCodexAppServerClientStartMetadata().get(client)?.startOptions;
|
|
7270
|
+
if (requiredOwnership === "native-process" && (start?.transport !== "stdio" || isCodexAppServerProxyLaunch(start.args))) throw new AgentHarnessPreflightError("Codex ordinary configuration refresh requires an OpenClaw-managed local stdio process, not an external socket or app-server proxy. No turn was sent; reconnect through managed local stdio before continuing.");
|
|
7271
|
+
const isCurrent = requiredOwnership === "native-process" && state.isolatedClients.has(client) ? () => state.isolatedClients.has(client) && !client.getCloseError() : captureSharedClientRegistration(client);
|
|
7272
|
+
const assertCurrent = () => {
|
|
7273
|
+
if (!isCurrent()) throw new CodexAdoptedThreadActiveError("Codex app-server connection changed during thread preparation; reconnect before continuing");
|
|
7274
|
+
assertCodexAppServerClientStartSelectionCurrent({ client });
|
|
7275
|
+
};
|
|
7276
|
+
assertCurrent();
|
|
7277
|
+
return assertCurrent;
|
|
7278
|
+
}
|
|
4477
7279
|
/**
|
|
4478
7280
|
* Retires a matching shared client. Default is graceful: detach from the map
|
|
4479
7281
|
* (future acquisitions get a fresh client) and close once leases drain.
|
|
@@ -4589,7 +7391,6 @@ async function clearSharedCodexAppServerClientAndWait(options) {
|
|
|
4589
7391
|
const state = getSharedCodexAppServerClientState();
|
|
4590
7392
|
const clients = collectSharedClients(state);
|
|
4591
7393
|
state.clients.clear();
|
|
4592
|
-
state.warmClientsByConfig = /* @__PURE__ */ new WeakMap();
|
|
4593
7394
|
await Promise.all(clients.map((client) => client.closeAndWait(options)));
|
|
4594
7395
|
}
|
|
4595
7396
|
globalThis[SHARED_CODEX_APP_SERVER_CLIENT_DISPOSER] = clearSharedCodexAppServerClientAndWait;
|
|
@@ -4690,4 +7491,4 @@ function collectSharedClients(state) {
|
|
|
4690
7491
|
return [...state.liveClients];
|
|
4691
7492
|
}
|
|
4692
7493
|
//#endregion
|
|
4693
|
-
export {
|
|
7494
|
+
export { assertCodexThreadResumeResponse as $, isJsonObject as $t, TURN_FINALIZE_DRAIN_ABORT_GRACE_MS as A, retainCodexAppServerLiveThread as At, isCodexAppServerIndeterminateRequestCancellationError as B, resolveCodexAppServerAuthProfileIdForAgent as Bt, withLeasedCodexAppServerClientStartSelectionRetry as C, ensureCodexAppServerClientRuntime as Ct, acquireCodexNativeConfigFence as D, protectCodexAppServerLiveThread as Dt, CodexThreadStartRequestError as E, isCodexAppServerLiveThreadClaimed as Et, withCodexStartupTimeout as F, readRecentCodexRateLimits as Ft, isUnsupportedCodexAppServerVersionError as G, resolveCodexManagedBundledMarketplacePath as Gt, isCodexAppServerOverloadError as H, resolveCodexAppServerFallbackApiKeyCacheKey as Ht, getCodexAppServerClientInstanceId as I, rememberCodexRateLimitsRead as It, CodexThreadDirectInputError as J, readCodexSessionMeta as Jt, resolveCodexAppServerClientInstanceId as K, assertNotSymlink as Kt, isCodexAppServerApprovalRequest as L, reconcileCodexComputerUseStartArtifacts as Lt, isCodexAppServerStartupError as M, withAbortableTimeout as Mt, resolveCodexGatewayTimeoutWithGraceMs as N, withTimeout$1 as Nt, createCodexDesktopGenerationService as O, readCodexClientSessionMeta as Ot, resolveCodexStartupTimeoutMs as P, readCodexRateLimitsRevision as Pt, assertCodexThreadForkResponse as Q, flattenCodexDynamicToolFunctions as Qt, isCodexAppServerBrokenPipeError as R, resolveCodexAppServerAuthAccountCacheKey as Rt, waitForCodexAppServerClientDesktopGenerationDrain as S, consumeCodexAppServerLiveThread as St, CodexThreadBindingConflictError as T, isCodexAppServerClientRuntimeLive as Tt, isCodexAppServerPrewriteRequestCancellationError as U, resolveCodexAppServerPreparedApiKeyCacheKey as Ut, isCodexAppServerIndeterminateTransportError as V, resolveCodexAppServerAuthProfileStore as Vt, isCodexAppServerRequestTimeoutError as W, resolveCodexAppServerPreparedAuthHandoff as Wt, assertCodexThreadAcceptsDirectInput as X, CODEX_INTERACTIVE_THREAD_SOURCE_KINDS as Xt, assertCodexModelListResponse as Y, CODEX_INTERACTIVE_CUSTOM_THREAD_SOURCES as Yt, assertCodexThreadForkParams as Z, CODEX_OPENCLAW_DIRECT_DYNAMIC_TOOL_NAMESPACE as Zt, retainSharedCodexAppServerClientByInstanceId as _, resolveCodexToolAbortTerminalReason as _t, clearSharedCodexAppServerClientIfCurrentAndUnclaimed as a, readCodexTurnCompletedNotification as at, retireSharedCodexAppServerClientsBeforeDesktopGeneration as b, withDynamicToolTranscriptDetails as bt, getLeasedSharedCodexAppServerClient as c, hasPendingDynamicToolTerminalDiagnostic as ct, readCodexAppServerClientDesktopGeneration as d, resolveDynamicToolCallTimeoutMs as dt, assertCodexThreadStartResponse as et, readCodexAppServerClientDesktopGenerationFingerprint as f, resolveTerminalDynamicToolBatchAction as ft, resolveCodexNativeConfigFenceKey as g, toCodexDynamicToolProtocolResponse as gt, releaseLeasedSharedCodexAppServerClient as h, toCodexDynamicToolProgressResponse as ht, clearSharedCodexAppServerClientIfCurrent as i, readCodexTurn as it, TURN_TERMINAL_SETTLEMENT_TIMEOUT_MS as j, unsubscribeCodexAppServerLiveThread as jt, CodexAppServerStartupError as k, releaseCodexAppServerLiveThread as kt, getSharedCodexAppServerClient as l, isDynamicToolTerminalDiagnosticEvent as lt, releaseCodexAppServerClientLease as m, shouldReleaseTurnAfterTerminalDynamicTool as mt, captureCodexAppServerClientLifetime as n, readCodexDynamicToolCallParams as nt, clearSharedCodexAppServerClientIfCurrentAndWait as o, createCodexElicitationResponse as ot, readCodexAppServerClientProcessIdentity as p, shouldBlockTerminalReleaseForNonTerminalDynamicToolResult as pt, CodexAppServerRpcError as q, isOpenClawManagedCodexThread as qt, captureSharedCodexAppServerCatalogLifetime as r, readCodexErrorNotification as rt, createIsolatedCodexAppServerClient as s, handleDynamicToolCallWithTimeout as st, assertCodexAppServerClientStartSelectionCurrent as t, assertCodexTurnStartResponse as tt, isCodexAppServerStartSelectionChangedError as u, isMatchingDynamicToolTerminalDiagnostic as ut, retainSharedCodexAppServerClientIfCurrent as v, createFailedDynamicToolResponse as vt, CodexAdoptedThreadActiveError as w, hasCodexAppServerLiveThread as wt, shared_client_exports as x, claimCodexAppServerLiveThread as xt, retireSharedCodexAppServerClientIfCurrent as y, withDynamicToolExecutionState as yt, isCodexAppServerConnectionClosedError as z, resolveCodexAppServerAuthProfileId as zt };
|