@openclaw/codex 2026.7.2-beta.7 → 2026.8.1-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/README.md +2 -0
  2. package/dist/{app-server-policy-BSaO2JIT.js → app-server-policy-zcBDc1JU.js} +1 -1
  3. package/dist/attempt-client-cleanup-DMLXUfa8.js +735 -0
  4. package/dist/{notification-correlation-CU6_AnOb.js → binding-connection-I5Bo-AsX.js} +3 -37
  5. package/dist/{bounded-turn-D2ZAgZVz.js → bounded-turn-qgZmzy_4.js} +50 -49
  6. package/dist/{capabilities-BFDTVYr4.js → capabilities-CybGI1oz.js} +8 -2
  7. package/dist/cli-metadata.js +1 -1
  8. package/dist/{command-formatters-C336eRVS.js → command-formatters-B1AEz8ZA.js} +18 -18
  9. package/dist/{command-handlers-DAHUSry9.js → command-handlers-Db8pu_ds.js} +484 -95
  10. package/dist/{compact-D_uvHurS.js → compact-LspQaGfl.js} +213 -199
  11. package/dist/{conversation-binding-data-BHRpYbX3.js → conversation-binding-data-CW2GuupV.js} +6 -10
  12. package/dist/doctor-contract-api.js +40 -43
  13. package/dist/{dynamic-tools-D2gYkSBO.js → dynamic-tools-BVdyWkUD.js} +2597 -1221
  14. package/dist/{effective-mcp-catalog-Bbd98Inw.js → effective-mcp-catalog-DIIhAtOZ.js} +20 -15
  15. package/dist/{event-projector-assistant-message-DTgnPPVF.js → event-projector-assistant-message-BwxV4d6N.js} +11 -23
  16. package/dist/{attempt-notifications-AP-a-Q5k.js → event-projector-usage-e5huIQWu.js} +113 -29
  17. package/dist/harness.js +80 -14
  18. package/dist/image-payload-sanitizer-CnfoUPCE.js +65 -0
  19. package/dist/index.js +591 -240
  20. package/dist/isolated-completion-C58NbL40.js +75 -0
  21. package/dist/local-runtime-attribution-B_2mnqhb.js +19 -0
  22. package/dist/media-understanding-provider.js +5 -5
  23. package/dist/{models-BBMKU4jA.js → models-BFlpn1Ex.js} +12 -17
  24. package/dist/native-subagent-monitor-DyTGmTUx.js +3111 -0
  25. package/dist/{plugin-app-cache-key-DztPafOA.js → plugin-app-cache-key-C3H2CVp6.js} +5 -5
  26. package/dist/plugin-marketplace-discovery-CzrGJdCR.js +385 -0
  27. package/dist/{computer-use-CYEc8U3w.js → plugin-metadata-cache-CNJPj4_b.js} +105 -5
  28. package/dist/protocol-validators-B4F7L8Rf.js +2346 -0
  29. package/dist/{rate-limits-CU-gVCCS.js → rate-limits-DZXmOL8-.js} +17 -35
  30. package/dist/{request-qKh331yu.js → request-BRl5_UfX.js} +3 -3
  31. package/dist/{run-attempt-CY9WlDLc.js → run-attempt-P8BdxC1I.js} +4837 -9047
  32. package/dist/{runtime-artifact-CmtG_t1L.js → runtime-artifact-BVSPdd6g.js} +8 -23
  33. package/dist/{sandbox-guard-NuhpXmPB.js → sandbox-guard-Cmwc9eIk.js} +6 -13
  34. package/dist/{session-binding-BXpo9ymA.js → session-binding-DPxIvMgE.js} +246 -265
  35. package/dist/{session-catalog-DyOgR4WH.js → session-catalog-xwNi_SDM.js} +159 -109
  36. package/dist/{session-cli-2PZaFLRh.js → session-cli-7hgXZDV7.js} +1 -1
  37. package/dist/session-retirement-DoMMJFKm.js +36 -0
  38. package/dist/{session-upstream-marker-B6U7tLw5.js → session-upstream-marker-CrIFX06J.js} +1 -1
  39. package/dist/{settled-turn-finalizer-CXY2Z9dT.js → settled-turn-finalizer-BRWBO4MO.js} +21 -13
  40. package/dist/{shared-client-DTbvH-XV.js → shared-client-kIBbGjk4.js} +587 -223
  41. package/dist/{side-question-_ulBk1AL.js → side-question-9HAL26l9.js} +101 -52
  42. package/dist/{thread-lifecycle-DF53ogiA.js → thread-lifecycle-Bu1BTDXr.js} +694 -753
  43. package/dist/thread-ownership-6kOQHlyC.js +92 -0
  44. package/dist/thread-resume-CPrJNQVM.js +30 -0
  45. package/dist/transcript-mirror-B9gGgnJS.js +570 -0
  46. package/dist/{transport-stdio-DXgGZ7Ib.js → transport-stdio-DIImwDVS.js} +11 -0
  47. package/dist/upstream-prompt-provenance-ClRBije0.js +41 -0
  48. package/dist/{upstream-session-fork-Dy4Xvuoj.js → upstream-session-fork-CE-_LdnP.js} +5 -5
  49. package/dist/{usage-CQ6GhD5-.js → usage-CHlV0e-o.js} +3 -3
  50. package/dist/{web-search-provider.runtime-CCFhg2z5.js → web-search-provider.runtime-DRw2Vl42.js} +8 -9
  51. package/openclaw.plugin.json +18 -3
  52. package/package.json +5 -5
  53. package/dist/conversation-control-xsIeXbo4.js +0 -287
  54. package/dist/event-projector-usage-Xp4AlR2k.js +0 -86
  55. package/dist/transcript-mirror-DzsdNCf5.js +0 -6924
@@ -0,0 +1,570 @@
1
+ import { i as readUpstreamUserText, n as attachUpstreamUserText, r as readMirrorIdentity, t as attachCodexMirrorIdentity } from "./upstream-prompt-provenance-ClRBije0.js";
2
+ import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
3
+ import { embeddedAgentLog, formatErrorMessage, projectAgentHarnessTranscriptMessageForDisplay, runAgentHarnessBeforeMessageWriteHook } from "openclaw/plugin-sdk/agent-harness-runtime";
4
+ import { createHash } from "node:crypto";
5
+ import { withCodexSessionTranscriptMirrorWriteLock } from "openclaw/plugin-sdk/codex-session-transcript-runtime";
6
+ import { publishSessionTranscriptUpdateByIdentity } from "openclaw/plugin-sdk/session-transcript-runtime";
7
+ import { Buffer } from "node:buffer";
8
+ //#region extensions/codex/src/app-server/transcript-history-projection.ts
9
+ const CODEX_HISTORY_IMPORT_MAX_MESSAGES = 200;
10
+ const CODEX_HISTORY_IMPORT_MAX_BYTES = 512 * 1024;
11
+ const CODEX_HISTORY_IMPORT_MAX_MESSAGE_BYTES = 64 * 1024;
12
+ const CODEX_HISTORY_TRUNCATION_SUFFIX = "\n\n[Message truncated during Codex history import.]";
13
+ const CODEX_HISTORY_ASSISTANT_API = "openai-chatgpt-responses";
14
+ const CODEX_HISTORY_ASSISTANT_PROVIDER = "openai";
15
+ const CODEX_HISTORY_ASSISTANT_MODEL = "native-history";
16
+ const CODEX_HISTORY_ZERO_USAGE = {
17
+ input: 0,
18
+ output: 0,
19
+ cacheRead: 0,
20
+ cacheWrite: 0,
21
+ totalTokens: 0,
22
+ cost: {
23
+ input: 0,
24
+ output: 0,
25
+ cacheRead: 0,
26
+ cacheWrite: 0,
27
+ total: 0
28
+ }
29
+ };
30
+ function isUtf8ContinuationByte(byte) {
31
+ return byte !== void 0 && (byte & 192) === 128;
32
+ }
33
+ function truncateUtf8Prefix(value, maxBytes) {
34
+ const bytes = Buffer.from(value);
35
+ if (bytes.byteLength <= maxBytes) return value;
36
+ let end = Math.max(0, maxBytes);
37
+ while (end > 0 && isUtf8ContinuationByte(bytes[end])) end -= 1;
38
+ return bytes.subarray(0, end).toString("utf8");
39
+ }
40
+ function normalizeImportedHistoryText(value) {
41
+ if (typeof value !== "string") return;
42
+ const text = value.trim();
43
+ if (!text) return;
44
+ if (Buffer.byteLength(text, "utf8") <= CODEX_HISTORY_IMPORT_MAX_MESSAGE_BYTES) return text;
45
+ const suffixBytes = Buffer.byteLength(CODEX_HISTORY_TRUNCATION_SUFFIX, "utf8");
46
+ return `${truncateUtf8Prefix(text, Math.max(0, CODEX_HISTORY_IMPORT_MAX_MESSAGE_BYTES - suffixBytes))}${CODEX_HISTORY_TRUNCATION_SUFFIX}`;
47
+ }
48
+ function projectCodexUserItemText(item) {
49
+ if (!Array.isArray(item.content)) return;
50
+ const parts = [];
51
+ for (const value of item.content) {
52
+ if (!value || typeof value !== "object" || Array.isArray(value)) continue;
53
+ const input = value;
54
+ if (input.type === "text") {
55
+ const text = normalizeImportedHistoryText(input.text);
56
+ if (text) parts.push(text);
57
+ continue;
58
+ }
59
+ if (input.type === "image" || input.type === "localImage") {
60
+ parts.push("[Image attachment]");
61
+ continue;
62
+ }
63
+ if (input.type === "audio" || input.type === "localAudio" || input.type === "local_audio") parts.push("[Audio attachment]");
64
+ if (input.type === "skill" || input.type === "mention") {
65
+ const name = normalizeOptionalString(input.name);
66
+ if (name) parts.push(`${input.type === "skill" ? "$" : "@"}${name}`);
67
+ }
68
+ }
69
+ return normalizeImportedHistoryText(parts.join("\n"));
70
+ }
71
+ function selectTurnsThroughBoundary(thread, throughTurnId) {
72
+ if (throughTurnId === null) return [];
73
+ const turns = thread.turns ?? [];
74
+ const boundaryIndex = turns.findIndex((turn) => turn.id === throughTurnId);
75
+ if (boundaryIndex < 0) throw new Error(`Codex history boundary turn not found: ${throughTurnId}`);
76
+ const boundary = turns[boundaryIndex];
77
+ if (boundary?.status !== "completed" && boundary?.status !== "interrupted" && boundary?.status !== "failed") throw new Error(`Codex history boundary turn is not terminal: ${throughTurnId}`);
78
+ return turns.slice(0, boundaryIndex + 1);
79
+ }
80
+ function projectCodexThreadHistory(params) {
81
+ const projected = [];
82
+ const threadTimestamp = typeof params.thread.createdAt === "number" && Number.isFinite(params.thread.createdAt) ? params.thread.createdAt * 1e3 : params.importedAt;
83
+ let itemOffset = 0;
84
+ for (const turn of selectTurnsThroughBoundary(params.thread, params.throughTurnId)) for (const value of turn.items) {
85
+ const item = value;
86
+ const itemId = normalizeOptionalString(item.id);
87
+ const identity = `${turn.id}:${itemId ?? itemOffset}`;
88
+ const timestampSeconds = item.type === "agentMessage" ? turn.completedAt ?? turn.startedAt : turn.startedAt ?? turn.completedAt;
89
+ const timestamp = typeof timestampSeconds === "number" && Number.isFinite(timestampSeconds) ? timestampSeconds * 1e3 + itemOffset : threadTimestamp + itemOffset;
90
+ const text = item.type === "userMessage" ? projectCodexUserItemText(item) : item.type === "agentMessage" ? normalizeImportedHistoryText(item.text) : void 0;
91
+ const role = item.type === "userMessage" ? "user" : item.type === "agentMessage" ? "assistant" : void 0;
92
+ itemOffset += 1;
93
+ if (!text || !role) continue;
94
+ const message = role === "assistant" ? attachCodexMirrorIdentity({
95
+ role,
96
+ content: [{
97
+ type: "text",
98
+ text
99
+ }],
100
+ api: CODEX_HISTORY_ASSISTANT_API,
101
+ provider: normalizeOptionalString(params.modelProvider) ?? normalizeOptionalString(params.thread.modelProvider) ?? CODEX_HISTORY_ASSISTANT_PROVIDER,
102
+ model: CODEX_HISTORY_ASSISTANT_MODEL,
103
+ usage: CODEX_HISTORY_ZERO_USAGE,
104
+ stopReason: turn.status === "interrupted" ? "aborted" : turn.status === "failed" ? "error" : "stop",
105
+ ...turn.status === "failed" && turn.error?.message ? { errorMessage: turn.error.message } : {},
106
+ timestamp
107
+ }, identity) : attachCodexMirrorIdentity({
108
+ role,
109
+ content: text,
110
+ timestamp
111
+ }, identity);
112
+ const phase = item.phase === "commentary" || item.phase === "final_answer" ? item.phase : void 0;
113
+ projected.push({
114
+ message,
115
+ responseItem: {
116
+ type: "message",
117
+ role,
118
+ content: [{
119
+ type: role === "assistant" ? "output_text" : "input_text",
120
+ text
121
+ }],
122
+ ...role === "assistant" && phase ? { phase } : {}
123
+ },
124
+ textBytes: Buffer.byteLength(text, "utf8")
125
+ });
126
+ }
127
+ return projected;
128
+ }
129
+ function selectBoundedCodexHistoryTail(projected) {
130
+ const selected = [];
131
+ let selectedBytes = 0;
132
+ for (let index = projected.length - 1; index >= 0; index -= 1) {
133
+ const candidate = projected[index];
134
+ if (!candidate) continue;
135
+ if (selected.length >= CODEX_HISTORY_IMPORT_MAX_MESSAGES || selectedBytes + candidate.textBytes > CODEX_HISTORY_IMPORT_MAX_BYTES) break;
136
+ selected.push(candidate);
137
+ selectedBytes += candidate.textBytes;
138
+ }
139
+ return selected.toReversed();
140
+ }
141
+ /** Projects one terminal Codex history prefix into transcript and Responses API items. */
142
+ function projectBoundedCodexThreadHistory(params) {
143
+ const projected = projectCodexThreadHistory({
144
+ thread: params.thread,
145
+ throughTurnId: params.throughTurnId,
146
+ importedAt: params.importedAt,
147
+ ...params.modelProvider ? { modelProvider: params.modelProvider } : {}
148
+ });
149
+ const selected = selectBoundedCodexHistoryTail(projected);
150
+ return {
151
+ importedMessages: selected.length,
152
+ omittedMessages: projected.length - selected.length,
153
+ responseItems: selected.filter(({ message }) => message.role !== "assistant" || message.stopReason !== "aborted" && message.stopReason !== "error").map(({ responseItem }) => responseItem),
154
+ transcriptMessages: selected.map(({ message }) => message)
155
+ };
156
+ }
157
+ /** Projects only visible local user/assistant messages through the same bounded history policy. */
158
+ function projectBoundedCodexVisibleSessionHistory(entries) {
159
+ const projected = [];
160
+ for (const entry of entries) {
161
+ if (entry.role !== "user" && entry.role !== "assistant" || !("content" in entry.message)) continue;
162
+ if (entry.role === "assistant" && "stopReason" in entry.message && (entry.message.stopReason === "aborted" || entry.message.stopReason === "error")) continue;
163
+ const content = entry.message.content;
164
+ const text = normalizeImportedHistoryText(typeof content === "string" ? content : Array.isArray(content) ? content.flatMap((part) => part && typeof part === "object" && "text" in part && typeof part.text === "string" ? [part.text] : []).join("\n") : void 0);
165
+ if (!text) continue;
166
+ projected.push({
167
+ message: entry.message,
168
+ responseItem: {
169
+ type: "message",
170
+ role: entry.role,
171
+ content: [{
172
+ type: entry.role === "assistant" ? "output_text" : "input_text",
173
+ text
174
+ }]
175
+ },
176
+ textBytes: Buffer.byteLength(text, "utf8")
177
+ });
178
+ }
179
+ return selectBoundedCodexHistoryTail(projected).map(({ responseItem }) => responseItem);
180
+ }
181
+ //#endregion
182
+ //#region extensions/codex/src/app-server/transcript-mirror-attestation.ts
183
+ const MIRROR_ORIGIN_META_KEY = "mirrorOrigin";
184
+ const MIRROR_SOURCE_FINGERPRINT_META_KEY = "mirrorSourceFingerprint";
185
+ const CODEX_APP_SERVER_MIRROR_ORIGIN = "codex-app-server";
186
+ function attachCodexMirrorAttestation(message, sourceFingerprint) {
187
+ const record = message;
188
+ const existing = record["__openclaw"];
189
+ const baseMeta = existing && typeof existing === "object" && !Array.isArray(existing) ? existing : {};
190
+ return {
191
+ ...record,
192
+ __openclaw: {
193
+ ...baseMeta,
194
+ [MIRROR_ORIGIN_META_KEY]: CODEX_APP_SERVER_MIRROR_ORIGIN,
195
+ ...sourceFingerprint ? { [MIRROR_SOURCE_FINGERPRINT_META_KEY]: sourceFingerprint } : {}
196
+ }
197
+ };
198
+ }
199
+ function readCodexMirrorSourceFingerprint(message) {
200
+ const meta = message["__openclaw"];
201
+ if (!meta || typeof meta !== "object" || Array.isArray(meta)) return;
202
+ const value = meta[MIRROR_SOURCE_FINGERPRINT_META_KEY];
203
+ return typeof value === "string" && value ? value : void 0;
204
+ }
205
+ function serializeCodexMirrorSourceEvidence(message) {
206
+ const record = message;
207
+ return JSON.stringify({
208
+ role: message.role,
209
+ content: record.content,
210
+ ...message.role === "user" ? { upstreamUserText: readUpstreamUserText(message) } : {},
211
+ ...message.role === "toolResult" ? {
212
+ toolCallId: record.toolCallId,
213
+ toolName: record.toolName,
214
+ isError: record.isError === true
215
+ } : {}
216
+ });
217
+ }
218
+ function fingerprintCodexMirrorSourceMessage(message) {
219
+ return createHash("sha256").update(serializeCodexMirrorSourceEvidence(message)).digest("hex").slice(0, 32);
220
+ }
221
+ //#endregion
222
+ //#region extensions/codex/src/app-server/user-prompt-message.ts
223
+ function buildSenderLabel(params) {
224
+ const label = params.senderName ?? params.senderUsername ?? params.senderE164 ?? params.senderId;
225
+ if (!label) return;
226
+ return !params.senderId || label.includes(params.senderId) ? label : `${label} (${params.senderId})`;
227
+ }
228
+ function buildFromPrepared(params, preparedUserMessage) {
229
+ const senderId = normalizeOptionalString(params.senderId);
230
+ const senderName = normalizeOptionalString(params.senderName);
231
+ const senderUsername = normalizeOptionalString(params.senderUsername);
232
+ const senderE164 = normalizeOptionalString(params.senderE164);
233
+ const senderLabel = buildSenderLabel({
234
+ senderId,
235
+ senderName,
236
+ senderUsername,
237
+ senderE164
238
+ });
239
+ const sourceChannel = normalizeOptionalString(params.inputProvenance?.sourceChannel ?? params.messageChannel ?? params.messageProvider);
240
+ return {
241
+ role: "user",
242
+ timestamp: Date.now(),
243
+ ...params.inputProvenance ? { provenance: params.inputProvenance } : {},
244
+ ...sourceChannel ? { sourceChannel } : {},
245
+ ...senderId ? { senderId } : {},
246
+ ...senderName ? { senderName } : {},
247
+ ...senderUsername ? { senderUsername } : {},
248
+ ...senderE164 ? { senderE164 } : {},
249
+ ...senderLabel ? { senderLabel } : {},
250
+ ...preparedUserMessage ? preparedUserMessage : { content: params.prompt }
251
+ };
252
+ }
253
+ function buildCodexUserPromptMessage(params) {
254
+ return buildFromPrepared(params, params.userTurnTranscriptRecorder?.message);
255
+ }
256
+ function buildCodexUpstreamPromptMessage(params, identity, upstreamUserText) {
257
+ const message = attachCodexMirrorIdentity(buildCodexUserPromptMessage(params), identity);
258
+ return upstreamUserText ? attachUpstreamUserText(message, upstreamUserText) : message;
259
+ }
260
+ function promptSnapshot(params, turnId, upstreamUserText) {
261
+ return params.suppressNextUserMessagePersistence ? [] : [buildCodexUpstreamPromptMessage(params, `${turnId}:prompt`, upstreamUserText)];
262
+ }
263
+ async function buildResolvedCodexUserPromptMessage(params) {
264
+ return buildFromPrepared(params, await params.userTurnTranscriptRecorder?.resolveMessage() ?? params.userTurnTranscriptRecorder?.message);
265
+ }
266
+ //#endregion
267
+ //#region extensions/codex/src/app-server/transcript-mirror.ts
268
+ function isMirroredAgentMessage(message) {
269
+ return message.role === "user" || message.role === "assistant" || message.role === "toolResult";
270
+ }
271
+ /** Imports a bounded, user-visible Codex history tail into a new OpenClaw transcript. */
272
+ async function importCodexThreadHistoryToTranscript(params) {
273
+ const projection = projectBoundedCodexThreadHistory({
274
+ thread: params.thread,
275
+ throughTurnId: params.throughTurnId,
276
+ importedAt: Date.now(),
277
+ ...params.modelProvider ? { modelProvider: params.modelProvider } : {}
278
+ });
279
+ if (projection.transcriptMessages.length > 0) await mirror({
280
+ storePath: params.storePath,
281
+ sessionId: params.sessionId,
282
+ sessionKey: params.sessionKey,
283
+ ...params.agentId ? { agentId: params.agentId } : {},
284
+ ...params.cwd ? { cwd: params.cwd } : {},
285
+ ...params.config ? { config: params.config } : {},
286
+ messages: projection.transcriptMessages,
287
+ idempotencyScope: `codex-app-server:${params.thread.id}:history`
288
+ });
289
+ return {
290
+ importedMessages: projection.importedMessages,
291
+ omittedMessages: projection.omittedMessages
292
+ };
293
+ }
294
+ async function mirrorBestEffort(params) {
295
+ if (!params.params.sessionTarget) return {
296
+ assistantTranscriptOwned: false,
297
+ mirroredMessages: []
298
+ };
299
+ try {
300
+ const messages = await resolveFinalCodexMirrorMessages({
301
+ params: params.params,
302
+ messagesSnapshot: params.result.messagesSnapshot,
303
+ turnId: params.turnId
304
+ });
305
+ const mirrorResult = await mirror({
306
+ agentId: params.agentId,
307
+ sessionKey: params.sessionKey,
308
+ sessionId: params.params.sessionId,
309
+ storePath: params.params.sessionTarget?.storePath,
310
+ cwd: params.cwd,
311
+ messages,
312
+ idempotencyScope: `codex-app-server:${params.threadId}`,
313
+ config: params.params.config
314
+ });
315
+ for (const receipt of mirrorResult.userMessageReceipts) try {
316
+ params.notifyUserMessagePersisted(receipt.message, receipt.anchor);
317
+ } catch (error) {
318
+ embeddedAgentLog.warn("failed to notify codex app-server user-message persistence", { error: formatErrorMessage(error) });
319
+ }
320
+ const expectedFingerprints = new Map(messages.flatMap((message) => {
321
+ if (!isMirroredAgentMessage(message)) return [];
322
+ const identity = readMirrorIdentity(message);
323
+ return identity ? [[identity, fingerprintCodexMirrorSourceMessage(message)]] : [];
324
+ }));
325
+ const mirroredMessages = mirrorResult.messagesPresent.filter((message) => {
326
+ const identity = readMirrorIdentity(message);
327
+ return identity !== void 0 && readCodexMirrorSourceFingerprint(message) === expectedFingerprints.get(identity);
328
+ });
329
+ const assistantMirrorIdentity = `${params.turnId}:assistant`;
330
+ const assistantTranscriptOwned = mirrorResult.assistantMirrorIdentitiesOwned.includes(assistantMirrorIdentity);
331
+ const assistantTranscriptIdempotencyKey = normalizeOptionalString((assistantTranscriptOwned ? mirroredMessages.find((message) => readMirrorIdentity(message) === assistantMirrorIdentity) : void 0)?.idempotencyKey);
332
+ const terminalMessage = mirroredMessages.at(-1);
333
+ const terminalMirrorIdentity = terminalMessage ? readMirrorIdentity(terminalMessage) : void 0;
334
+ const terminalAnchor = (terminalMirrorIdentity ? mirrorResult.anchorsByMirrorIdentity.get(terminalMirrorIdentity) : void 0) ?? params.params.userTurnTranscriptRecorder?.getAdmissionReceipt();
335
+ return {
336
+ assistantTranscriptOwned,
337
+ ...assistantTranscriptIdempotencyKey ? { assistantTranscriptIdempotencyKey } : {},
338
+ ...terminalAnchor ? { terminalAnchor } : {},
339
+ mirroredMessages
340
+ };
341
+ } catch (error) {
342
+ embeddedAgentLog.warn("failed to mirror codex app-server transcript", {
343
+ error: formatErrorMessage(error),
344
+ runId: params.params.runId,
345
+ sessionId: params.params.sessionId
346
+ });
347
+ return {
348
+ assistantTranscriptOwned: false,
349
+ mirroredMessages: []
350
+ };
351
+ }
352
+ }
353
+ async function resolveFinalCodexMirrorMessages(params) {
354
+ if (params.params.suppressNextUserMessagePersistence || !params.params.userTurnTranscriptRecorder) return params.messagesSnapshot;
355
+ const promptSnapshot = params.messagesSnapshot.find((message) => message.role === "user");
356
+ const resolvedBase = attachCodexMirrorIdentity(await buildResolvedCodexUserPromptMessage(params.params), `${params.turnId}:prompt`);
357
+ const upstreamUserText = readUpstreamUserText(promptSnapshot);
358
+ const resolvedPrompt = upstreamUserText ? attachUpstreamUserText(resolvedBase, upstreamUserText) : resolvedBase;
359
+ const firstUserIndex = params.messagesSnapshot.findIndex((message) => message.role === "user");
360
+ if (firstUserIndex === -1) return [resolvedPrompt, ...params.messagesSnapshot];
361
+ const messages = params.messagesSnapshot.slice();
362
+ messages[firstUserIndex] = resolvedPrompt;
363
+ return messages;
364
+ }
365
+ function createCodexAppServerUserMessagePersistenceNotifier(runParams) {
366
+ let notified = false;
367
+ return (message, anchor) => {
368
+ if (notified) return;
369
+ notified = true;
370
+ runParams.userTurnTranscriptRecorder?.markRuntimePersisted(message, anchor);
371
+ try {
372
+ runParams.onUserMessagePersisted?.(message);
373
+ } catch (error) {
374
+ embeddedAgentLog.warn("codex app-server user persistence notification failed", { error: formatErrorMessage(error) });
375
+ }
376
+ };
377
+ }
378
+ async function mirrorPromptAtTurnStartBestEffort(params) {
379
+ if (params.params.suppressNextUserMessagePersistence || !params.params.sessionTarget) return;
380
+ try {
381
+ const mirrorPromise = (async () => {
382
+ const userPromptMessage = projectAgentHarnessTranscriptMessageForDisplay({
383
+ hidden: params.params.trigger === "memory",
384
+ message: attachUpstreamUserText(attachCodexMirrorIdentity(await buildResolvedCodexUserPromptMessage(params.params), `${params.turnId}:prompt`), params.upstreamUserText)
385
+ });
386
+ const mirrorResult = await mirror({
387
+ agentId: params.agentId,
388
+ sessionKey: params.sessionKey,
389
+ sessionId: params.params.sessionId,
390
+ storePath: params.params.sessionTarget?.storePath,
391
+ cwd: params.cwd,
392
+ messages: [userPromptMessage],
393
+ idempotencyScope: `codex-app-server:${params.threadId}`,
394
+ config: params.params.config
395
+ });
396
+ for (const receipt of mirrorResult.userMessageReceipts) params.notifyUserMessagePersisted(receipt.message, receipt.anchor);
397
+ })();
398
+ params.params.userTurnTranscriptRecorder?.markRuntimePersistencePending(mirrorPromise);
399
+ await mirrorPromise;
400
+ } catch (error) {
401
+ embeddedAgentLog.warn("failed to mirror codex app-server prompt at turn start", {
402
+ error: formatErrorMessage(error),
403
+ runId: params.params.runId,
404
+ sessionId: params.params.sessionId
405
+ });
406
+ }
407
+ }
408
+ function fingerprintMirrorMessageContent(message) {
409
+ const payload = JSON.stringify({
410
+ role: message.role,
411
+ content: message.content
412
+ });
413
+ return createHash("sha256").update(payload).digest("hex").slice(0, 16);
414
+ }
415
+ function buildMirrorDedupeIdentity(message) {
416
+ const explicit = readMirrorIdentity(message);
417
+ if (explicit) return explicit;
418
+ return `${message.role}:${fingerprintMirrorMessageContent(message)}`;
419
+ }
420
+ async function mirror(params) {
421
+ const messages = params.messages.filter(isMirroredAgentMessage);
422
+ if (messages.length === 0) return {
423
+ assistantMirrorIdentitiesOwned: [],
424
+ anchorsByMirrorIdentity: /* @__PURE__ */ new Map(),
425
+ messagesPresent: [],
426
+ userMessageReceipts: [],
427
+ userMessagesPresent: []
428
+ };
429
+ const candidates = messages.map((message) => {
430
+ const dedupeIdentity = buildMirrorDedupeIdentity(message);
431
+ const sourceFingerprint = fingerprintCodexMirrorSourceMessage(message);
432
+ return {
433
+ dedupeIdentity,
434
+ idempotencyKey: (message.role === "user" ? normalizeOptionalString(message.idempotencyKey) : void 0) ?? (params.idempotencyScope ? `${params.idempotencyScope}:${dedupeIdentity}` : void 0),
435
+ message,
436
+ sourceFingerprint
437
+ };
438
+ });
439
+ const candidateIdempotencyKeys = candidates.flatMap(({ idempotencyKey }) => idempotencyKey ? [idempotencyKey] : []);
440
+ const transcriptTarget = resolveCodexMirrorTranscriptTarget(params);
441
+ const { appendedUpdates, assistantMirrorIdentitiesOwned, anchorsByMirrorIdentity, messagesPresent, userMessageReceipts, userMessagesPresent } = await withCodexSessionTranscriptMirrorWriteLock({
442
+ ...transcriptTarget,
443
+ config: params.config
444
+ }, async (transcript) => {
445
+ const nextAppendedUpdates = [];
446
+ const nextAssistantMirrorIdentitiesOwned = /* @__PURE__ */ new Set();
447
+ const nextAnchorsByMirrorIdentity = /* @__PURE__ */ new Map();
448
+ const nextMessagesPresent = [];
449
+ const nextUserMessageReceipts = [];
450
+ const nextUserMessagesPresent = [];
451
+ const mirrorFacts = await transcript.readMessageFacts({ idempotencyKeys: candidateIdempotencyKeys });
452
+ for (const { dedupeIdentity, idempotencyKey, message, sourceFingerprint } of candidates) {
453
+ const transcriptMessage = {
454
+ ...attachCodexMirrorAttestation(message, sourceFingerprint),
455
+ ...idempotencyKey ? { idempotencyKey } : {}
456
+ };
457
+ if (idempotencyKey && mirrorFacts.existingIdempotencyKeys.has(idempotencyKey)) {
458
+ const persistedMessage = mirrorFacts.messagesByIdempotencyKey.get(idempotencyKey);
459
+ const persistedAnchor = mirrorFacts.anchorsByIdempotencyKey.get(idempotencyKey);
460
+ if (persistedMessage && isMirroredAgentMessage(persistedMessage)) {
461
+ nextMessagesPresent.push(persistedMessage);
462
+ if (persistedMessage.role === "user") {
463
+ nextUserMessagesPresent.push(persistedMessage);
464
+ if (persistedAnchor) nextUserMessageReceipts.push({
465
+ anchor: persistedAnchor,
466
+ message: persistedMessage
467
+ });
468
+ }
469
+ }
470
+ if (persistedAnchor) nextAnchorsByMirrorIdentity.set(dedupeIdentity, persistedAnchor);
471
+ if (message.role === "assistant") nextAssistantMirrorIdentitiesOwned.add(dedupeIdentity);
472
+ continue;
473
+ }
474
+ const nextMessage = params.skipBeforeMessageWriteHooks ? transcriptMessage : runAgentHarnessBeforeMessageWriteHook({
475
+ message: transcriptMessage,
476
+ agentId: params.agentId,
477
+ sessionKey: params.sessionKey
478
+ });
479
+ if (!nextMessage) {
480
+ if (message.role === "assistant") nextAssistantMirrorIdentitiesOwned.add(dedupeIdentity);
481
+ continue;
482
+ }
483
+ let messageToAppend = idempotencyKey ? {
484
+ ...attachCodexMirrorAttestation(nextMessage, sourceFingerprint),
485
+ idempotencyKey
486
+ } : attachCodexMirrorAttestation(nextMessage, sourceFingerprint);
487
+ const mirrorIdentity = readMirrorIdentity(message);
488
+ if (mirrorIdentity) messageToAppend = attachCodexMirrorIdentity(messageToAppend, mirrorIdentity);
489
+ messageToAppend = projectAgentHarnessTranscriptMessageForDisplay({
490
+ hidden: message.display === false,
491
+ message: messageToAppend
492
+ });
493
+ const { messageSeq, result: appended } = await transcript.appendMessageWithMessageSequence({
494
+ message: messageToAppend,
495
+ idempotencyLookup: "scan",
496
+ cwd: params.cwd
497
+ });
498
+ if (!appended) continue;
499
+ const { messageId, message: appendedMessage } = appended;
500
+ if (isMirroredAgentMessage(appendedMessage)) {
501
+ nextMessagesPresent.push(appendedMessage);
502
+ if (idempotencyKey) mirrorFacts.messagesByIdempotencyKey.set(idempotencyKey, appendedMessage);
503
+ }
504
+ if (message.role === "assistant") nextAssistantMirrorIdentitiesOwned.add(dedupeIdentity);
505
+ if (appended.anchor) nextAnchorsByMirrorIdentity.set(dedupeIdentity, appended.anchor);
506
+ if (appendedMessage.role === "user" && appended.anchor) {
507
+ nextUserMessagesPresent.push(appendedMessage);
508
+ nextUserMessageReceipts.push({
509
+ anchor: appended.anchor,
510
+ message: appendedMessage
511
+ });
512
+ }
513
+ if (appended.appended) nextAppendedUpdates.push({
514
+ messageId,
515
+ message: appendedMessage,
516
+ ...messageSeq !== void 0 ? { messageSeq } : {}
517
+ });
518
+ if (idempotencyKey) {
519
+ mirrorFacts.existingIdempotencyKeys.add(idempotencyKey);
520
+ if (appended.anchor) mirrorFacts.anchorsByIdempotencyKey.set(idempotencyKey, appended.anchor);
521
+ }
522
+ }
523
+ return {
524
+ appendedUpdates: nextAppendedUpdates,
525
+ assistantMirrorIdentitiesOwned: [...nextAssistantMirrorIdentitiesOwned],
526
+ anchorsByMirrorIdentity: nextAnchorsByMirrorIdentity,
527
+ messagesPresent: nextMessagesPresent,
528
+ userMessageReceipts: nextUserMessageReceipts,
529
+ userMessagesPresent: nextUserMessagesPresent
530
+ };
531
+ });
532
+ for (const update of appendedUpdates) try {
533
+ await publishSessionTranscriptUpdateByIdentity({
534
+ ...transcriptTarget,
535
+ update: {
536
+ ...params.agentId ? { agentId: params.agentId } : {},
537
+ message: update.message,
538
+ messageId: update.messageId,
539
+ ...update.messageSeq !== void 0 ? { messageSeq: update.messageSeq } : {},
540
+ sessionKey: transcriptTarget.sessionKey
541
+ }
542
+ });
543
+ } catch (error) {
544
+ embeddedAgentLog.warn("failed to publish codex app-server transcript update", { error: formatErrorMessage(error) });
545
+ }
546
+ return {
547
+ assistantMirrorIdentitiesOwned,
548
+ anchorsByMirrorIdentity,
549
+ messagesPresent,
550
+ userMessageReceipts,
551
+ userMessagesPresent
552
+ };
553
+ }
554
+ const codexTranscriptMirrorRuntime = {
555
+ mirror,
556
+ mirrorBestEffort
557
+ };
558
+ function resolveCodexMirrorTranscriptTarget(params) {
559
+ const sessionKey = params.sessionKey?.trim();
560
+ const storePath = params.storePath?.trim();
561
+ if (!sessionKey || !storePath) throw new Error("Codex transcript mirror requires a runtime session identity");
562
+ return {
563
+ ...params.agentId ? { agentId: params.agentId } : {},
564
+ sessionId: params.sessionId,
565
+ sessionKey,
566
+ storePath
567
+ };
568
+ }
569
+ //#endregion
570
+ export { buildCodexUserPromptMessage as a, readCodexMirrorSourceFingerprint as c, projectBoundedCodexVisibleSessionHistory as d, mirrorPromptAtTurnStartBestEffort as i, serializeCodexMirrorSourceEvidence as l, createCodexAppServerUserMessagePersistenceNotifier as n, promptSnapshot as o, importCodexThreadHistoryToTranscript as r, fingerprintCodexMirrorSourceMessage as s, codexTranscriptMirrorRuntime as t, projectBoundedCodexThreadHistory as u };
@@ -10,6 +10,12 @@ const UNSAFE_ENVIRONMENT_KEYS = /* @__PURE__ */ new Set([
10
10
  "constructor",
11
11
  "prototype"
12
12
  ]);
13
+ const RUNTIME_INJECTION_ENVIRONMENT_KEYS = /* @__PURE__ */ new Set([
14
+ "NODE_PATH",
15
+ "LD_AUDIT",
16
+ "LD_LIBRARY_PATH",
17
+ "LD_PRELOAD"
18
+ ]);
13
19
  const QA_PARENT_PID_ENV = "OPENCLAW_QA_PARENT_PID";
14
20
  const DEFAULT_SPAWN_RUNTIME = {
15
21
  platform: process.platform,
@@ -43,8 +49,13 @@ function resolveCodexAppServerSpawnEnv(options, baseEnv = process.env, platform
43
49
  const lowerCaseKeysToClear = new Set(keysToClear.map((key) => key.toLowerCase()));
44
50
  for (const candidate of Object.keys(env)) if (lowerCaseKeysToClear.has(candidate.toLowerCase())) delete env[candidate];
45
51
  } else for (const key of keysToClear) delete env[key];
52
+ for (const key of Object.keys(env)) if (isCodexRuntimeInjectionEnvironmentKey(key)) delete env[key];
46
53
  return env;
47
54
  }
55
+ function isCodexRuntimeInjectionEnvironmentKey(rawKey) {
56
+ const key = rawKey.toUpperCase();
57
+ return RUNTIME_INJECTION_ENVIRONMENT_KEYS.has(key) || key.startsWith("DYLD_");
58
+ }
48
59
  /** Keeps QA-owned app-server processes inside the gateway process-group cleanup boundary. */
49
60
  function resolveCodexAppServerDetachedMode(env, platform = process.platform) {
50
61
  return platform !== "win32" && !env[QA_PARENT_PID_ENV]?.trim();
@@ -0,0 +1,41 @@
1
+ //#region extensions/codex/src/app-server/upstream-prompt-provenance.ts
2
+ const UPSTREAM_USER_TEXT_META_KEY = "upstreamUserText";
3
+ const MIRROR_IDENTITY_META_KEY = "mirrorIdentity";
4
+ function attachCodexMirrorIdentity(message, identity) {
5
+ const record = message;
6
+ const existing = record["__openclaw"];
7
+ const baseMeta = existing && typeof existing === "object" && !Array.isArray(existing) ? existing : {};
8
+ return {
9
+ ...record,
10
+ __openclaw: {
11
+ ...baseMeta,
12
+ [MIRROR_IDENTITY_META_KEY]: identity
13
+ }
14
+ };
15
+ }
16
+ function readMirrorIdentity(message) {
17
+ const meta = message["__openclaw"];
18
+ if (!meta || typeof meta !== "object" || Array.isArray(meta)) return;
19
+ const id = meta[MIRROR_IDENTITY_META_KEY];
20
+ return typeof id === "string" && id ? id : void 0;
21
+ }
22
+ function attachUpstreamUserText(message, text) {
23
+ const record = message;
24
+ const existing = record["__openclaw"];
25
+ const baseMeta = existing && typeof existing === "object" && !Array.isArray(existing) ? existing : {};
26
+ return {
27
+ ...record,
28
+ __openclaw: {
29
+ ...baseMeta,
30
+ [UPSTREAM_USER_TEXT_META_KEY]: text
31
+ }
32
+ };
33
+ }
34
+ function readUpstreamUserText(message) {
35
+ const meta = message?.["__openclaw"];
36
+ if (!meta || typeof meta !== "object" || Array.isArray(meta)) return;
37
+ const text = meta[UPSTREAM_USER_TEXT_META_KEY];
38
+ return typeof text === "string" && text ? text : void 0;
39
+ }
40
+ //#endregion
41
+ export { readUpstreamUserText as i, attachUpstreamUserText as n, readMirrorIdentity as r, attachCodexMirrorIdentity as t };
@@ -1,8 +1,8 @@
1
- import { d as sessionBindingIdentity } from "./session-binding-BXpo9ymA.js";
2
- import { h as assertCodexThreadForkResponse } from "./transcript-mirror-DzsdNCf5.js";
1
+ import { d as sessionBindingIdentity } from "./session-binding-DPxIvMgE.js";
2
+ import { r as assertCodexThreadForkResponse } from "./protocol-validators-B4F7L8Rf.js";
3
3
  import { t as isIncognitoSessionKey } from "./incognito-session-ET_ufDH-.js";
4
- import { i as createImportedCodexSession, n as codexUpstreamBaseline, t as codexLastTerminalTurnId } from "./session-upstream-marker-B6U7tLw5.js";
5
- import { isRecord } from "openclaw/plugin-sdk/string-coerce-runtime";
4
+ import { i as createImportedCodexSession, n as codexUpstreamBaseline, t as codexLastTerminalTurnId } from "./session-upstream-marker-CrIFX06J.js";
5
+ import { isRecord, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
6
6
  import { readVisibleSessionTranscriptMessageEntries } from "openclaw/plugin-sdk/session-transcript-runtime";
7
7
  import { deleteSessionUpstreamLink, upsertSessionUpstreamLink } from "openclaw/plugin-sdk/session-catalog";
8
8
  //#region extensions/codex/src/app-server/upstream-fork-boundary.ts
@@ -167,7 +167,7 @@ function readConnectionFingerprint(ref) {
167
167
  return typeof ref.connectionFingerprint === "string" && ref.connectionFingerprint.trim() ? ref.connectionFingerprint : void 0;
168
168
  }
169
169
  function normalizeTurnId(value) {
170
- return typeof value === "string" && value.trim() ? value.trim() : void 0;
170
+ return normalizeOptionalString(value);
171
171
  }
172
172
  async function forkCodexUpstreamSession(params, options) {
173
173
  try {
@@ -1,6 +1,6 @@
1
- import { g as resolveCodexAppServerRuntimeOptions } from "./session-binding-BXpo9ymA.js";
2
- import { t as buildCodexAppServerUsageSnapshot } from "./rate-limits-CU-gVCCS.js";
3
- import { t as readCodexAppServerUsage } from "./request-qKh331yu.js";
1
+ import { g as resolveCodexAppServerRuntimeOptions } from "./session-binding-DPxIvMgE.js";
2
+ import { t as buildCodexAppServerUsageSnapshot } from "./rate-limits-DZXmOL8-.js";
3
+ import { t as readCodexAppServerUsage } from "./request-BRl5_UfX.js";
4
4
  import { CODEX_APP_SERVER_AUTH_MARKER } from "openclaw/plugin-sdk/agent-runtime";
5
5
  //#region extensions/codex/src/app-server/usage.ts
6
6
  /** Handles the synthetic usage credential for a Codex-backed OpenAI route. */