@openclaw/codex 2026.7.2-beta.7 → 2026.8.1-beta.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/dist/api.js +147 -0
- package/dist/app-server-policy-bg5QPSVP.js +25 -0
- package/dist/attempt-client-cleanup-URjUlCHg.js +735 -0
- package/dist/binding-connection-DAvZwp96.js +45 -0
- package/dist/{bounded-turn-D2ZAgZVz.js → bounded-turn-4BjrZEwW.js} +63 -56
- package/dist/{capabilities-BFDTVYr4.js → capabilities-CH3K57v4.js} +8 -2
- package/dist/cli-metadata.js +1 -1
- package/dist/{command-formatters-C336eRVS.js → command-formatters-D0nZ3qtd.js} +18 -18
- package/dist/{command-handlers-DAHUSry9.js → command-handlers-DC86lgT4.js} +507 -101
- package/dist/command-rpc-xUIIonsO.js +90 -0
- package/dist/{compact-D_uvHurS.js → compact-COqgBRny.js} +234 -214
- package/dist/{session-binding-BXpo9ymA.js → config-CpNeo5AE.js} +284 -1163
- package/dist/context-compaction-activity-BOeJf7yo.js +58 -0
- package/dist/{conversation-binding-data-BHRpYbX3.js → conversation-binding-data-CW2GuupV.js} +6 -10
- package/dist/doctor-contract-api.js +48 -50
- package/dist/{dynamic-tools-D2gYkSBO.js → dynamic-tools-fJZhl4CE.js} +3442 -1433
- package/dist/{effective-mcp-catalog-Bbd98Inw.js → effective-mcp-catalog-4YKn51aG.js} +20 -15
- package/dist/elicitation-input-DMkeki8d.js +71 -0
- package/dist/{event-projector-assistant-message-DTgnPPVF.js → event-projector-assistant-message-BwxV4d6N.js} +11 -23
- package/dist/{attempt-notifications-AP-a-Q5k.js → event-projector-usage-CLwNEJqW.js} +113 -29
- package/dist/harness-DoKQcF8n.js +258 -0
- package/dist/harness.js +2 -160
- package/dist/image-payload-sanitizer-CnfoUPCE.js +65 -0
- package/dist/index.js +730 -256
- package/dist/isolated-completion-DPMtlH9r.js +75 -0
- package/dist/local-runtime-attribution-B_2mnqhb.js +19 -0
- package/dist/managed-binary-By4FZC6i.js +212 -0
- package/dist/media-understanding-provider.js +5 -5
- package/dist/model-catalog-CmGoqVKB.js +48 -0
- package/dist/{models-BBMKU4jA.js → models-CZw1wClT.js} +12 -17
- package/dist/native-subagent-monitor-GGq3RnOo.js +3225 -0
- package/dist/node-exec-server.runtime-Bsu1LdFZ.js +192 -0
- package/dist/{plugin-app-cache-key-DztPafOA.js → plugin-app-cache-key-DMNQ8Zi8.js} +18 -6
- package/dist/plugin-approval-roundtrip-C75Yiiwc.js +95 -0
- package/dist/plugin-marketplace-discovery-CSWDkMrP.js +399 -0
- package/dist/{computer-use-CYEc8U3w.js → plugin-metadata-cache-BXH5NF-4.js} +109 -6
- package/dist/protocol-validators-VAVyEnDp.js +2399 -0
- package/dist/{rate-limits-CU-gVCCS.js → rate-limits-BI1dMHDG.js} +17 -35
- package/dist/{request-qKh331yu.js → request-DSK0W6YI.js} +3 -3
- package/dist/{run-attempt-CY9WlDLc.js → run-attempt-BV3HzuCf.js} +3416 -7194
- package/dist/{runtime-artifact-CmtG_t1L.js → runtime-artifact-BvyT1uyd.js} +11 -29
- package/dist/{sandbox-guard-NuhpXmPB.js → sandbox-guard-C1qEeZ5C.js} +29 -30
- package/dist/session-binding-BTrLf9Qm.js +874 -0
- package/dist/{session-catalog-DyOgR4WH.js → session-catalog-ezP_UcRM.js} +1584 -1289
- package/dist/session-catalog-home-id-BNwAJ9D7.js +18 -0
- package/dist/{session-cli-2PZaFLRh.js → session-cli-B1hKvfkI.js} +20 -7
- package/dist/session-retirement-CE4iMiLh.js +36 -0
- package/dist/{session-upstream-marker-B6U7tLw5.js → session-upstream-marker-D_2npHlA.js} +1 -1
- package/dist/{settled-turn-finalizer-CXY2Z9dT.js → settled-turn-finalizer-Dx1onIqg.js} +40 -28
- package/dist/{shared-client-DTbvH-XV.js → shared-client-Dw-rzii0.js} +1315 -469
- package/dist/{side-question-_ulBk1AL.js → side-question-DbXkJZzg.js} +140 -69
- package/dist/{thread-lifecycle-DF53ogiA.js → thread-lifecycle-DKdrnTMX.js} +927 -768
- package/dist/thread-ownership-i2NBwDUL.js +92 -0
- package/dist/thread-resume-CdJk2Ehf.js +30 -0
- package/dist/transcript-mirror-BU0_LKAL.js +588 -0
- package/dist/{transport-stdio-DXgGZ7Ib.js → transport-stdio-DhoGy33Z.js} +13 -2
- package/dist/upstream-prompt-provenance-CFmsKwr9.js +39 -0
- package/dist/{upstream-session-fork-Dy4Xvuoj.js → upstream-session-fork-BDVJCLAD.js} +14 -8
- package/dist/{usage-CQ6GhD5-.js → usage-9dKJCgcy.js} +3 -3
- package/dist/{web-search-provider.runtime-CCFhg2z5.js → web-search-provider.runtime-DCdx4DGu.js} +8 -9
- package/openclaw.plugin.json +49 -4
- package/package.json +6 -5
- package/dist/app-server-policy-BSaO2JIT.js +0 -49
- package/dist/conversation-control-xsIeXbo4.js +0 -287
- package/dist/event-projector-usage-Xp4AlR2k.js +0 -86
- package/dist/notification-correlation-CU6_AnOb.js +0 -67
- package/dist/transcript-mirror-DzsdNCf5.js +0 -6924
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { createHash } from "node:crypto";
|
|
3
|
+
import fsSync from "node:fs";
|
|
4
|
+
//#region extensions/codex/src/session-catalog-home-id.ts
|
|
5
|
+
function canonicalCodexCatalogHome(value) {
|
|
6
|
+
const resolved = path.resolve(value);
|
|
7
|
+
try {
|
|
8
|
+
return fsSync.realpathSync.native(resolved);
|
|
9
|
+
} catch {
|
|
10
|
+
return resolved;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
/** One canonical identity for catalog discovery and durable ownership rows. */
|
|
14
|
+
function codexCatalogHomeId(codexHome) {
|
|
15
|
+
return createHash("sha256").update("openclaw:codex-session-catalog-home:v1\0").update(canonicalCodexCatalogHome(codexHome)).digest("hex");
|
|
16
|
+
}
|
|
17
|
+
//#endregion
|
|
18
|
+
export { codexCatalogHomeId as n, canonicalCodexCatalogHome as t };
|
|
@@ -1,10 +1,15 @@
|
|
|
1
|
-
import
|
|
1
|
+
import "./session-catalog-ezP_UcRM.js";
|
|
2
2
|
import { isRecord } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
3
3
|
import { truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
|
|
4
4
|
import { sanitizeTerminalText } from "openclaw/plugin-sdk/text-chunking";
|
|
5
|
+
import { normalizeAgentId } from "openclaw/plugin-sdk/routing";
|
|
5
6
|
import { addGatewayClientOptions, callGatewayFromCli } from "openclaw/plugin-sdk/gateway-runtime";
|
|
6
7
|
//#region extensions/codex/src/session-cli.ts
|
|
7
8
|
const CODEX_SESSION_CATALOG_CLI_TIMEOUT_MS = 75e3;
|
|
9
|
+
function requestedAgentId(options) {
|
|
10
|
+
const agentId = options.agent?.trim();
|
|
11
|
+
return agentId ? normalizeAgentId(agentId) : void 0;
|
|
12
|
+
}
|
|
8
13
|
function writeLine(value = "") {
|
|
9
14
|
process.stdout.write(`${value}\n`);
|
|
10
15
|
}
|
|
@@ -80,12 +85,14 @@ function filterHosts(result, selector) {
|
|
|
80
85
|
} : result;
|
|
81
86
|
}
|
|
82
87
|
async function listCodexSessions(options) {
|
|
88
|
+
const agentId = requestedAgentId(options);
|
|
83
89
|
const host = options.host?.trim() || void 0;
|
|
84
90
|
const cursor = options.cursor?.trim() || void 0;
|
|
85
91
|
if (cursor && !host) throw new Error("--cursor requires --host so the cursor is routed to one Codex host");
|
|
86
92
|
const search = options.search?.trim() || void 0;
|
|
87
93
|
const limitPerHost = parsePageLimit(options.limit);
|
|
88
94
|
const params = {
|
|
95
|
+
...agentId ? { agentId } : {},
|
|
89
96
|
...search ? { search } : {},
|
|
90
97
|
...limitPerHost !== void 0 ? { limitPerHost } : {},
|
|
91
98
|
...host ? { hostIds: [host] } : {},
|
|
@@ -122,10 +129,13 @@ function readThreadId(value) {
|
|
|
122
129
|
}
|
|
123
130
|
async function continueCodexSession(threadIdValue, options) {
|
|
124
131
|
const threadId = readThreadId(threadIdValue);
|
|
132
|
+
const agentId = requestedAgentId(options);
|
|
133
|
+
const hostId = options.host?.trim() || "gateway:local";
|
|
125
134
|
const raw = await callGatewayFromCli("sessions.catalog.continue", gatewayOptions(options), {
|
|
126
135
|
catalogId: "codex",
|
|
127
|
-
hostId
|
|
128
|
-
threadId
|
|
136
|
+
hostId,
|
|
137
|
+
threadId,
|
|
138
|
+
...agentId ? { agentId } : {}
|
|
129
139
|
}, {
|
|
130
140
|
mode: "cli",
|
|
131
141
|
scopes: ["operator.write"]
|
|
@@ -140,11 +150,14 @@ async function continueCodexSession(threadIdValue, options) {
|
|
|
140
150
|
}
|
|
141
151
|
async function archiveCodexSession(threadIdValue, options) {
|
|
142
152
|
const threadId = readThreadId(threadIdValue);
|
|
153
|
+
const agentId = requestedAgentId(options);
|
|
154
|
+
const hostId = options.host?.trim() || "gateway:local";
|
|
143
155
|
if (options.confirmNoOtherRunner !== true) throw new Error("--confirm-no-other-runner is required because Codex client and runner activity is process-local");
|
|
144
156
|
const raw = await callGatewayFromCli("sessions.catalog.archive", gatewayOptions(options), {
|
|
145
157
|
catalogId: "codex",
|
|
146
|
-
hostId
|
|
158
|
+
hostId,
|
|
147
159
|
threadId,
|
|
160
|
+
...agentId ? { agentId } : {},
|
|
148
161
|
confirmNoOtherRunner: true
|
|
149
162
|
}, {
|
|
150
163
|
mode: "cli",
|
|
@@ -161,13 +174,13 @@ async function archiveCodexSession(threadIdValue, options) {
|
|
|
161
174
|
/** Registers the plugin-owned Codex session supervision CLI. */
|
|
162
175
|
function registerCodexSessionCli(program) {
|
|
163
176
|
const codex = program.command("codex").description("Inspect and branch from Codex sessions through the Gateway");
|
|
164
|
-
addGatewayClientOptions(codex.command("sessions").description("List non-archived Codex app-server sessions across connected hosts").option("--search <text>", "Search session titles (case-insensitive)").option("--host <id>", "Filter by stable host id").option("--limit <count>", "Maximum sessions returned per host").option("--cursor <cursor>", "Continue one host page (requires --host)").option("--json", "Print the structured catalog response", false), { timeoutMs: CODEX_SESSION_CATALOG_CLI_TIMEOUT_MS }).action(async (options) => {
|
|
177
|
+
addGatewayClientOptions(codex.command("sessions").description("List non-archived Codex app-server sessions across connected hosts").option("--agent <id>", "Agent id that owns the Codex sessions").option("--search <text>", "Search session titles (case-insensitive)").option("--host <id>", "Filter by stable host id").option("--limit <count>", "Maximum sessions returned per host").option("--cursor <cursor>", "Continue one host page (requires --host)").option("--json", "Print the structured catalog response", false), { timeoutMs: CODEX_SESSION_CATALOG_CLI_TIMEOUT_MS }).action(async (options) => {
|
|
165
178
|
await listCodexSessions(options);
|
|
166
179
|
});
|
|
167
|
-
addGatewayClientOptions(codex.command("continue <thread-id>").description("Continue a Gateway-local Codex thread as an OpenClaw branch").option("--json", "Print the structured response", false)).action(async (threadId, options) => {
|
|
180
|
+
addGatewayClientOptions(codex.command("continue <thread-id>").description("Continue a Gateway-local Codex thread as an OpenClaw branch").option("--agent <id>", "Agent id that owns the Codex session").option("--host <id>", "Stable local host id from codex sessions").option("--json", "Print the structured response", false)).action(async (threadId, options) => {
|
|
168
181
|
await continueCodexSession(threadId, options);
|
|
169
182
|
});
|
|
170
|
-
addGatewayClientOptions(codex.command("archive <thread-id>").description("Archive a stored or idle Gateway-local Codex thread").option("--confirm-no-other-runner", "Confirm no other Codex client or OpenClaw runner is using this thread", false).option("--json", "Print the structured response", false)).action(async (threadId, options) => {
|
|
183
|
+
addGatewayClientOptions(codex.command("archive <thread-id>").description("Archive a stored or idle Gateway-local Codex thread").option("--agent <id>", "Agent id that owns the Codex session").option("--host <id>", "Stable local host id from codex sessions").option("--confirm-no-other-runner", "Confirm no other Codex client or OpenClaw runner is using this thread", false).option("--json", "Print the structured response", false)).action(async (threadId, options) => {
|
|
171
184
|
await archiveCodexSession(threadId, options);
|
|
172
185
|
});
|
|
173
186
|
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { J as releaseCodexAppServerLiveThread, d as retainSharedCodexAppServerClientByInstanceId } from "./shared-client-Dw-rzii0.js";
|
|
2
|
+
import { a as closeCodexStartupClientBestEffort, d as unsubscribeCodexThreadBestEffort, r as CodexAppServerUnsafeSubscriptionError } from "./attempt-client-cleanup-URjUlCHg.js";
|
|
3
|
+
import { t as isIncognitoSessionKey } from "./incognito-session-ET_ufDH-.js";
|
|
4
|
+
import { t as codexNativeSubagentMonitorRuntime } from "./native-subagent-monitor-GGq3RnOo.js";
|
|
5
|
+
//#region extensions/codex/src/app-server/session-retirement.ts
|
|
6
|
+
/** Retire binding and native subscription under the same generation/physical-client ownership fence. */
|
|
7
|
+
async function retireCodexAppServerSessionGeneration(params) {
|
|
8
|
+
const retireGeneration = () => params.mode === "reset" ? params.bindingStore.resetSessionGeneration(params.identity) : params.bindingStore.retireSessionGeneration(params.identity);
|
|
9
|
+
const expectedBinding = await params.bindingStore.read(params.identity);
|
|
10
|
+
if (!expectedBinding) return await retireGeneration();
|
|
11
|
+
return await params.bindingStore.withLease(params.identity, async () => {
|
|
12
|
+
const binding = await params.bindingStore.read(params.identity);
|
|
13
|
+
if (binding?.threadId !== expectedBinding.threadId) return "conflict";
|
|
14
|
+
const result = await retireGeneration();
|
|
15
|
+
if (result !== "applied" || !binding?.clientId) return result;
|
|
16
|
+
const clientLease = retainSharedCodexAppServerClientByInstanceId(binding.clientId);
|
|
17
|
+
if (!clientLease) return result;
|
|
18
|
+
try {
|
|
19
|
+
codexNativeSubagentMonitorRuntime.retireParent(clientLease.client, binding.threadId);
|
|
20
|
+
if (!await releaseCodexAppServerLiveThread(clientLease.client, binding.threadId) && isIncognitoSessionKey(params.identity.sessionKey)) {
|
|
21
|
+
if (!await unsubscribeCodexThreadBestEffort(clientLease.client, {
|
|
22
|
+
threadId: binding.threadId,
|
|
23
|
+
timeoutMs: 5e3
|
|
24
|
+
})) {
|
|
25
|
+
await closeCodexStartupClientBestEffort(clientLease.client);
|
|
26
|
+
throw new CodexAppServerUnsafeSubscriptionError(`Codex retired session subscription could not be released: ${binding.threadId}`);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
} finally {
|
|
30
|
+
clientLease.release();
|
|
31
|
+
}
|
|
32
|
+
return result;
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
//#endregion
|
|
36
|
+
export { retireCodexAppServerSessionGeneration };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { r as importCodexThreadHistoryToTranscript } from "./transcript-mirror-
|
|
1
|
+
import { r as importCodexThreadHistoryToTranscript } from "./transcript-mirror-BU0_LKAL.js";
|
|
2
2
|
import { resolveStorePath } from "openclaw/plugin-sdk/session-store-runtime";
|
|
3
3
|
//#region extensions/codex/src/app-server/session-history-import.ts
|
|
4
4
|
/** Creates a session whose transcript is derived from one verified Codex thread snapshot. */
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { t as
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
1
|
+
import { ut as isJsonObject } from "./shared-client-Dw-rzii0.js";
|
|
2
|
+
import { i as readUpstreamUserText, r as readMirrorIdentity, t as attachCodexMirrorIdentity } from "./upstream-prompt-provenance-CFmsKwr9.js";
|
|
3
|
+
import { c as readCodexMirrorSourceFingerprint, s as fingerprintCodexMirrorSourceMessage, t as codexTranscriptMirrorRuntime } from "./transcript-mirror-BU0_LKAL.js";
|
|
4
|
+
import { t as runBoundedCodexAppServerTurn } from "./bounded-turn-4BjrZEwW.js";
|
|
5
|
+
import { n as createAssistantMessage } from "./event-projector-assistant-message-BwxV4d6N.js";
|
|
6
|
+
import { isRecord, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
6
7
|
import { Buffer } from "node:buffer";
|
|
7
8
|
import { isSilentReplyText } from "openclaw/plugin-sdk/reply-runtime";
|
|
8
9
|
//#region extensions/codex/src/app-server/settled-turn-projection.ts
|
|
@@ -11,9 +12,6 @@ const MAX_PROJECTION_BYTES = 512 * 1024;
|
|
|
11
12
|
const MAX_TEXT_BYTES = 64 * 1024;
|
|
12
13
|
const TOOL_NAME_PATTERN = /^[a-zA-Z0-9_-]{1,128}$/u;
|
|
13
14
|
const TOOL_ERROR_STATUS_PREFIX = "[Tool result status: error]\n";
|
|
14
|
-
function readNonEmptyString(value) {
|
|
15
|
-
return typeof value === "string" ? value.trim() || void 0 : void 0;
|
|
16
|
-
}
|
|
17
15
|
function readBoundedText(value, label, maxBytes = MAX_TEXT_BYTES) {
|
|
18
16
|
if (typeof value !== "string" || !value.trim()) return;
|
|
19
17
|
if (Buffer.byteLength(value, "utf8") > maxBytes) throw new Error(`Codex settled-turn projection found oversized ${label}`);
|
|
@@ -28,12 +26,12 @@ function responseItemBytes(item) {
|
|
|
28
26
|
return Buffer.byteLength(JSON.stringify(item), "utf8");
|
|
29
27
|
}
|
|
30
28
|
function requireCallId(value) {
|
|
31
|
-
const callId =
|
|
29
|
+
const callId = normalizeOptionalString(value);
|
|
32
30
|
if (!callId || callId.length > 256) throw new Error("Codex settled-turn projection found an invalid tool call id");
|
|
33
31
|
return callId;
|
|
34
32
|
}
|
|
35
33
|
function requireToolName(value) {
|
|
36
|
-
const name =
|
|
34
|
+
const name = normalizeOptionalString(value);
|
|
37
35
|
if (!name || !TOOL_NAME_PATTERN.test(name)) throw new Error("Codex settled-turn projection found an invalid tool name");
|
|
38
36
|
return name;
|
|
39
37
|
}
|
|
@@ -58,27 +56,26 @@ function serializeToolArguments(value) {
|
|
|
58
56
|
return requireBoundedText(serialized, "tool arguments");
|
|
59
57
|
}
|
|
60
58
|
function projectUserMessage(message) {
|
|
61
|
-
const record = message;
|
|
62
59
|
const upstreamUserText = readUpstreamUserText(message);
|
|
63
|
-
if (upstreamUserText && typeof
|
|
60
|
+
if (upstreamUserText && typeof message.content === "string") return [{
|
|
64
61
|
type: "message",
|
|
65
62
|
role: "user",
|
|
66
63
|
content: [{
|
|
67
64
|
type: "input_text",
|
|
68
|
-
text: requireBoundedText(upstreamUserText, "upstream user text")
|
|
65
|
+
text: requireBoundedText(upstreamUserText, "upstream user text", MAX_PROJECTION_BYTES)
|
|
69
66
|
}]
|
|
70
67
|
}];
|
|
71
|
-
if (typeof
|
|
68
|
+
if (typeof message.content === "string") return [{
|
|
72
69
|
type: "message",
|
|
73
70
|
role: "user",
|
|
74
71
|
content: [{
|
|
75
72
|
type: "input_text",
|
|
76
|
-
text: requireBoundedText(
|
|
73
|
+
text: requireBoundedText(message.content, "user message")
|
|
77
74
|
}]
|
|
78
75
|
}];
|
|
79
|
-
if (!Array.isArray(
|
|
76
|
+
if (!Array.isArray(message.content)) throw new Error("Codex settled-turn projection found unsupported user content");
|
|
80
77
|
const content = [];
|
|
81
|
-
for (const value of
|
|
78
|
+
for (const value of message.content) {
|
|
82
79
|
if (!isRecord(value)) throw new Error("Codex settled-turn projection found malformed user content");
|
|
83
80
|
if (value.type === "text") {
|
|
84
81
|
const text = readBoundedText(value.text, "user text");
|
|
@@ -88,7 +85,7 @@ function projectUserMessage(message) {
|
|
|
88
85
|
});
|
|
89
86
|
continue;
|
|
90
87
|
}
|
|
91
|
-
throw new Error(`Codex settled-turn projection does not support user content ${
|
|
88
|
+
throw new Error(`Codex settled-turn projection does not support user content ${value.type}`);
|
|
92
89
|
}
|
|
93
90
|
if (content.length === 0) throw new Error("Codex settled-turn projection found an empty user message");
|
|
94
91
|
return [{
|
|
@@ -146,13 +143,14 @@ function projectToolResult(message) {
|
|
|
146
143
|
const id = requireCallId(message.toolCallId);
|
|
147
144
|
const name = requireToolName(message.toolName);
|
|
148
145
|
if (!Array.isArray(message.content)) throw new Error("Codex settled-turn projection found unsupported tool result content");
|
|
149
|
-
|
|
150
|
-
|
|
146
|
+
const isErrorValue = message.isError;
|
|
147
|
+
if (isErrorValue !== void 0 && typeof isErrorValue !== "boolean") throw new Error("Codex settled-turn projection found invalid tool result status");
|
|
148
|
+
const isError = isErrorValue === true;
|
|
151
149
|
const parts = [];
|
|
152
150
|
for (const value of message.content) {
|
|
153
151
|
if (!isRecord(value)) throw new Error("Codex settled-turn projection found malformed tool result content");
|
|
154
152
|
if (value.type === "image") {
|
|
155
|
-
const mimeType =
|
|
153
|
+
const mimeType = normalizeOptionalString(value.mimeType) ?? "unknown type";
|
|
156
154
|
parts.push(`[Image tool result: ${mimeType}]`);
|
|
157
155
|
continue;
|
|
158
156
|
}
|
|
@@ -175,17 +173,16 @@ function projectToolResult(message) {
|
|
|
175
173
|
};
|
|
176
174
|
}
|
|
177
175
|
function projectMessage(message) {
|
|
178
|
-
const record = message;
|
|
179
176
|
let items;
|
|
180
177
|
let calls = [];
|
|
181
178
|
let results = [];
|
|
182
179
|
if (message.role === "user") items = projectUserMessage(message);
|
|
183
180
|
else if (message.role === "assistant") {
|
|
184
|
-
const projected = projectAssistantMessage(
|
|
181
|
+
const projected = projectAssistantMessage(message);
|
|
185
182
|
items = projected.items;
|
|
186
183
|
calls = projected.calls;
|
|
187
184
|
} else if (message.role === "toolResult") {
|
|
188
|
-
const projected = projectToolResult(
|
|
185
|
+
const projected = projectToolResult(message);
|
|
189
186
|
items = [projected.item];
|
|
190
187
|
results = [projected.result];
|
|
191
188
|
} else throw new Error(`Codex settled-turn projection does not support role ${message.role}`);
|
|
@@ -246,6 +243,7 @@ async function runCodexSettledTurnFinalization(operation, options) {
|
|
|
246
243
|
mode: "required",
|
|
247
244
|
id: attempt.modelId
|
|
248
245
|
},
|
|
246
|
+
modelProvider: "openai",
|
|
249
247
|
profile: attempt.authProfileId,
|
|
250
248
|
timeoutMs: attempt.runTimeoutOverrideMs ?? attempt.timeoutMs,
|
|
251
249
|
signal: attempt.abortSignal,
|
|
@@ -262,7 +260,8 @@ async function runCodexSettledTurnFinalization(operation, options) {
|
|
|
262
260
|
requiredModalities: ["text"],
|
|
263
261
|
isolation: "private-stdio",
|
|
264
262
|
historyItems,
|
|
265
|
-
requireNoExternalCapabilities: true
|
|
263
|
+
requireNoExternalCapabilities: true,
|
|
264
|
+
allowEmptyText: true
|
|
266
265
|
});
|
|
267
266
|
let promptEchoSeen = false;
|
|
268
267
|
let unexpectedItem;
|
|
@@ -281,7 +280,15 @@ async function runCodexSettledTurnFinalization(operation, options) {
|
|
|
281
280
|
}
|
|
282
281
|
if (unexpectedItem) throw new Error(`Codex settled-turn finalization returned unexpected native item: ${unexpectedItem.type}`);
|
|
283
282
|
const text = bounded.text.trim();
|
|
284
|
-
if (!text
|
|
283
|
+
if (!text) return {
|
|
284
|
+
assistant: createAssistantMessage(attempt, "", {
|
|
285
|
+
tokenUsage: bounded.usage,
|
|
286
|
+
aborted: false,
|
|
287
|
+
promptError: null
|
|
288
|
+
}),
|
|
289
|
+
...bounded.usage ? { usage: bounded.usage } : {}
|
|
290
|
+
};
|
|
291
|
+
if (isSilentReplyText(text)) throw new Error("Codex settled-turn finalization completed without a visible answer");
|
|
285
292
|
const mirrorIdentity = `settled-finalizer:${attempt.runId}`;
|
|
286
293
|
const assistant = attachCodexMirrorIdentity(createAssistantMessage(attempt, text, {
|
|
287
294
|
tokenUsage: bounded.usage,
|
|
@@ -296,6 +303,11 @@ async function runCodexSettledTurnFinalization(operation, options) {
|
|
|
296
303
|
cwd: attempt.workspaceDir,
|
|
297
304
|
messages: [assistant],
|
|
298
305
|
idempotencyScope: `codex-settled-finalizer:${attempt.runId}`,
|
|
306
|
+
runId: attempt.runId,
|
|
307
|
+
terminalAssistantOwner: {
|
|
308
|
+
mirrorIdentity,
|
|
309
|
+
runId: attempt.runId
|
|
310
|
+
},
|
|
299
311
|
config: attempt.config,
|
|
300
312
|
skipBeforeMessageWriteHooks: true
|
|
301
313
|
});
|
|
@@ -303,8 +315,8 @@ async function runCodexSettledTurnFinalization(operation, options) {
|
|
|
303
315
|
const expectedFingerprint = fingerprintCodexMirrorSourceMessage(assistant);
|
|
304
316
|
if (!mirrorResult.assistantMirrorIdentitiesOwned.includes(mirrorIdentity) || !persistedMessage || persistedMessage.role !== "assistant" || readCodexMirrorSourceFingerprint(persistedMessage) !== expectedFingerprint) throw new Error("Codex settled-turn final answer transcript attestation mismatch");
|
|
305
317
|
const persistedAssistant = persistedMessage;
|
|
306
|
-
const
|
|
307
|
-
const assistantTranscriptIdempotencyKey = typeof
|
|
318
|
+
const persistedIdempotencyKey = "idempotencyKey" in persistedAssistant ? persistedAssistant.idempotencyKey : void 0;
|
|
319
|
+
const assistantTranscriptIdempotencyKey = typeof persistedIdempotencyKey === "string" ? persistedIdempotencyKey.trim() : "";
|
|
308
320
|
return {
|
|
309
321
|
assistant: persistedAssistant,
|
|
310
322
|
assistantTranscriptOwned: true,
|