@openclaw/codex 2026.8.2 → 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.
Files changed (61) hide show
  1. package/dist/api.js +3 -3
  2. package/dist/{attempt-client-cleanup-CpVfwctT.js → attempt-client-cleanup-DYHcRQAa.js} +6 -43
  3. package/dist/attempt-context-DmQUNWwT.js +634 -0
  4. package/dist/{binding-connection-CF7BmrDk.js → binding-connection-E6uDsPlx.js} +2 -2
  5. package/dist/{bounded-turn-DRC3hcjm.js → bounded-turn-wzJrwKKe.js} +8 -9
  6. package/dist/{capabilities-D6m_TdVy.js → capabilities-dIjNVCYH.js} +1 -1
  7. package/dist/cli-metadata.js +1 -1
  8. package/dist/{command-formatters--UToCokS.js → command-formatters-CLHhEB1Q.js} +3 -3
  9. package/dist/{command-handlers-CLFx2Ypa.js → command-handlers-CTGb2csu.js} +54 -55
  10. package/dist/{compact-5xqW1oCh.js → compact-_t0HQrUS.js} +33 -25
  11. package/dist/{config-CcYL77O6.js → config-BhmfC1s6.js} +12 -8
  12. package/dist/{context-compaction-activity-BOeJf7yo.js → context-compaction-activity-CMla5FPJ.js} +4 -1
  13. package/dist/doctor-contract-api.js +31 -4
  14. package/dist/{dynamic-tools-BmeXjwNZ.js → dynamic-tools-BU9tmlYm.js} +448 -457
  15. package/dist/{effective-mcp-catalog-XXQKgK1U.js → effective-mcp-catalog-DzYBW4h1.js} +2 -2
  16. package/dist/{event-projector-assistant-message-C5-Ds8mA.js → event-projector-assistant-message-DHRFXKbS.js} +4 -4
  17. package/dist/{event-projector-usage-B2r5vhWH.js → event-projector-usage-C5mcrGjp.js} +9 -137
  18. package/dist/{harness-BgeB7LnD.js → harness-DXVZ5II5.js} +13 -13
  19. package/dist/harness.js +1 -1
  20. package/dist/index.js +323 -313
  21. package/dist/{isolated-completion-CxTus3vZ.js → isolated-completion-kg9kv4iH.js} +4 -4
  22. package/dist/{launch-args-sXOAg0SX.js → launch-args-RXQwn8zV.js} +7 -1
  23. package/dist/{managed-binary-ZkGodW19.js → managed-binary-4-Vjz5GH.js} +14 -9
  24. package/dist/media-understanding-provider.js +1 -1
  25. package/dist/{model-catalog-DULBcniB.js → model-catalog-CUM68Hkl.js} +11 -11
  26. package/dist/{models-DaWfETQk.js → models-sYnEc0gd.js} +3 -3
  27. package/dist/{native-subagent-monitor-vXYUZH37.js → native-subagent-monitor-CnH147jH.js} +3 -3
  28. package/dist/{node-exec-server.runtime-DirKVZ5h.js → node-exec-server.runtime-CstNHCmC.js} +2 -2
  29. package/dist/{plugin-approval-roundtrip-CCWQGlAI.js → plugin-approval-roundtrip-CNe-Xrjx.js} +29 -3
  30. package/dist/{plugin-marketplace-discovery-BXjIFEiw.js → plugin-marketplace-discovery-CfFlKqDl.js} +6 -6
  31. package/dist/{plugin-metadata-cache-DQQm4gWT.js → plugin-metadata-cache-BFrPhb2c.js} +5 -5
  32. package/dist/provider-capabilities-DW5p4k9w.js +101 -0
  33. package/dist/{rate-limits-BqHEHXQJ.js → rate-limits-CawQJfUS.js} +1 -1
  34. package/dist/{request-BWxweEdK.js → request-DYAI5FQE.js} +18 -6
  35. package/dist/{run-attempt-BVLE4Gbi.js → run-attempt-D1hJO4fX.js} +483 -1865
  36. package/dist/{runtime-artifact-D9pYp4zL.js → runtime-artifact-C3jVimFn.js} +19 -12
  37. package/dist/{session-binding-D0zinCP1.js → session-binding-BHuTCRZQ.js} +8 -10
  38. package/dist/{session-catalog-eMhVm0Ql.js → session-catalog-yyvTWFOw.js} +138 -116
  39. package/dist/{session-cli-B2lyjJA0.js → session-cli-CmFEXMAM.js} +1 -1
  40. package/dist/session-initialization-BeWzjGiR.js +74 -0
  41. package/dist/{session-permission-policy-ScnAyG90.js → session-permission-policy-DeWVTCMj.js} +2 -2
  42. package/dist/{session-retirement-CtUtUTr9.js → session-retirement-BujDjXVF.js} +16 -9
  43. package/dist/{session-upstream-marker-gqrYIRHk.js → session-upstream-marker-C351-5Qw.js} +18 -2
  44. package/dist/{settled-turn-context-Bk3IUwod.js → settled-turn-context-D3SNWtUn.js} +6 -28
  45. package/dist/{settled-turn-finalizer-BXLN9PfJ.js → settled-turn-finalizer-BVJx4yoc.js} +5 -5
  46. package/dist/{shared-client-B1tT5U6r.js → shared-client-DxcfF9KX.js} +2748 -101
  47. package/dist/{side-question-CZ-mCw-t.js → side-question-BTZAII4l.js} +97 -63
  48. package/dist/{thread-lifecycle-CGGKP720.js → thread-lifecycle-DAcEJ_Om.js} +2039 -1487
  49. package/dist/{thread-ownership-RkaoZCmQ.js → thread-ownership-zGokd8i1.js} +10 -9
  50. package/dist/thread-policy-g4KbJPzp.js +54 -0
  51. package/dist/{thread-resume-BFt1-ZDa.js → thread-resume-C7pyVKeW.js} +15 -7
  52. package/dist/{transcript-mirror-1ep4XjzF.js → transcript-mirror-DTUxFWa_.js} +47 -10
  53. package/dist/{transport-stdio-NT_Dpd9V.js → transport-stdio-CyPldczm.js} +3 -1
  54. package/dist/upstream-session-fork-CYlBIGVt.js +966 -0
  55. package/dist/{usage-DUhd58gI.js → usage-Bj-rrzkR.js} +3 -3
  56. package/dist/{web-search-provider.runtime-BEmlE7ov.js → web-search-provider.runtime-D2FWSK4w.js} +3 -3
  57. package/openclaw.plugin.json +0 -30
  58. package/package.json +5 -5
  59. package/dist/protocol-validators-Bg5rpNxk.js +0 -2542
  60. package/dist/session-catalog-home-id-Dt2GiG5o.js +0 -112
  61. package/dist/upstream-session-fork-Dc8BFExw.js +0 -312
@@ -1,10 +1,11 @@
1
- import { Ct as retainCodexAppServerLiveThread, St as releaseCodexAppServerLiveThread, _ as retainSharedCodexAppServerClientByInstanceId, bt as isCodexAppServerLiveThreadClaimed } from "./shared-client-B1tT5U6r.js";
2
- import { a as closeCodexStartupClientBestEffort, f as unsubscribeCodexThreadBestEffort, r as CodexAppServerUnsafeSubscriptionError } from "./attempt-client-cleanup-CpVfwctT.js";
1
+ import { At as retainCodexAppServerLiveThread, Et as isCodexAppServerLiveThreadClaimed, _ as retainSharedCodexAppServerClientByInstanceId, kt as releaseCodexAppServerLiveThread } from "./shared-client-DxcfF9KX.js";
2
+ import { a as closeCodexStartupClientBestEffort, d as unsubscribeCodexThreadBestEffort, r as CodexAppServerUnsafeSubscriptionError } from "./attempt-client-cleanup-DYHcRQAa.js";
3
3
  import { isIncognitoSessionKey } from "openclaw/plugin-sdk/routing";
4
+ import { resolveGlobalSingleton } from "openclaw/plugin-sdk/global-singleton";
4
5
  import { KeyedAsyncQueue } from "openclaw/plugin-sdk/keyed-async-queue";
5
6
  //#region extensions/codex/src/app-server/thread-ownership.ts
6
- const nativeThreadOwners = new KeyedAsyncQueue();
7
- /** Serialize connection-scoped unsubscribe with attach/resume of the same native thread. */
7
+ const nativeThreadOwners = resolveGlobalSingleton(Symbol.for("openclaw.codexNativeThreadOwners"), () => new KeyedAsyncQueue());
8
+ /** Serialize OpenClaw-owned lifecycle changes, not native-internal thread controllers. */
8
9
  async function withCodexAppServerThreadMutation(threadId, run) {
9
10
  return await nativeThreadOwners.enqueue(`thread:${threadId}`, run);
10
11
  }
@@ -23,7 +24,7 @@ async function withExclusiveCodexAppServerThread(params) {
23
24
  async function withCodexConversationThreadActivity(bindingId, run) {
24
25
  return await nativeThreadOwners.enqueue(`conversation:${bindingId}`, run);
25
26
  }
26
- /** Publishes one owned persistent subscription into the shared bounded idle registry. */
27
+ /** Publishes one owned subscription with its persistent or ephemeral retention lifetime. */
27
28
  async function retainCodexAppServerBindingSubscription(client, threadId, ownership) {
28
29
  return await retainCodexAppServerLiveThread(client, threadId, ownership?.release ?? (async (releasedThreadId, assertCurrent) => {
29
30
  if (!await unsubscribeCodexThreadBestEffort(client, {
@@ -35,7 +36,7 @@ async function retainCodexAppServerBindingSubscription(client, threadId, ownersh
35
36
  await closeCodexStartupClientBestEffort(client);
36
37
  throw new CodexAppServerUnsafeSubscriptionError(`Codex thread subscription could not be released: ${releasedThreadId}`);
37
38
  }
38
- }), ownership?.configFingerprint, ownership?.serviceTier);
39
+ }), ownership?.configFingerprint, ownership?.serviceTier, ownership?.ephemeralPolicy);
39
40
  }
40
41
  /** Rolls back the exact subscription Codex created before its binding was committed. */
41
42
  async function rollbackCodexAppServerBindingSubscription(client, threadId, retained) {
@@ -72,9 +73,9 @@ async function releaseCodexAppServerBindingSubscription(binding, options = {}) {
72
73
  async function retireCodexConversationThreadBinding(params) {
73
74
  const expected = await params.bindingStore.read(params.identity);
74
75
  if (!expected || params.expectedThreadId && expected.threadId !== params.expectedThreadId) return false;
75
- return await params.bindingStore.withLease(params.identity, async () => {
76
+ return await withCodexAppServerThreadMutation(expected.threadId, () => params.bindingStore.withLease(params.identity, async () => {
76
77
  const current = await params.bindingStore.read(params.identity);
77
- if (current?.threadId !== expected.threadId || params.expectedStartId && current.conversationStartId !== params.expectedStartId) return false;
78
+ if (!current || !isSameCodexAppServerThreadOwner(current, expected) || params.expectedStartId && current?.conversationStartId !== params.expectedStartId) return false;
78
79
  await releaseCodexAppServerBindingSubscription(current, { allowUntracked: params.allowUntracked });
79
80
  const cleared = await params.bindingStore.mutate(params.identity, {
80
81
  kind: "clear",
@@ -96,7 +97,7 @@ async function retireCodexConversationThreadBinding(params) {
96
97
  }
97
98
  throw error;
98
99
  }
99
- });
100
+ }));
100
101
  }
101
102
  //#endregion
102
103
  export { rollbackCodexAppServerBindingSubscription as a, withExclusiveCodexAppServerThread as c, retireCodexConversationThreadBinding as i, isIncognitoSessionKey as l, releaseCodexAppServerBindingSubscription as n, withCodexAppServerThreadMutation as o, retainCodexAppServerBindingSubscription as r, withCodexConversationThreadActivity as s, isSameCodexAppServerThreadOwner as t };
@@ -0,0 +1,54 @@
1
+ import { H as isCodexAppServerOverloadError, U as isCodexAppServerPrewriteRequestCancellationError } from "./shared-client-DxcfF9KX.js";
2
+ import { r as requestCodexAppServerClientJson, t as CodexAppServerScopedRequestRejectedError } from "./request-DYAI5FQE.js";
3
+ import { AgentHarnessPreflightError } from "openclaw/plugin-sdk/agent-harness-runtime";
4
+ //#region extensions/codex/src/app-server/thread-policy.ts
5
+ /** A refusal, not a failed native write: the ephemeral conversation must stay alive. */
6
+ var CodexIncognitoPolicyChangeError = class extends AgentHarnessPreflightError {
7
+ constructor() {
8
+ super("Codex cannot change generic instructions in a live incognito conversation. No turn was sent and the conversation is preserved. Restore the previous instructions to continue it, or start a new incognito conversation for the changed policy.");
9
+ this.name = "CodexIncognitoPolicyChangeError";
10
+ }
11
+ };
12
+ /** Never replay a handoff: native persistence can precede an unsuccessful RPC response. */
13
+ var CodexThreadPolicyHandoffError = class extends AgentHarnessPreflightError {
14
+ constructor(outcome, cause) {
15
+ super(`Codex session policy handoff failed: ${cause instanceof Error ? cause.message : String(cause)}. The conversation is preserved; reconnect before retrying.`, { cause });
16
+ this.outcome = outcome;
17
+ this.name = "CodexThreadPolicyHandoffError";
18
+ }
19
+ };
20
+ /** The complete body remains generic configuration for compaction and native child inheritance. */
21
+ async function refreshCodexThreadPolicy(params) {
22
+ const text = "The following is the complete current OpenClaw-supplied generic instruction policy. It replaces earlier OpenClaw-supplied generic policy, including OpenClaw-carried workspace text and sections now absent. Independently supplied native managed, guardian, security, collaboration, and project instructions retain their authority. User requests retain their own authority.\n\n" + (params.developerInstructions === "" ? "The current OpenClaw generic policy is empty; earlier OpenClaw generic policy is withdrawn." : params.developerInstructions);
23
+ let outcome = "unknown";
24
+ try {
25
+ await requestCodexAppServerClientJson({
26
+ ...params,
27
+ method: "thread/inject_items",
28
+ requestParams: {
29
+ threadId: params.threadId,
30
+ items: [{
31
+ type: "message",
32
+ role: "developer",
33
+ content: [{
34
+ type: "input_text",
35
+ text
36
+ }]
37
+ }]
38
+ }
39
+ });
40
+ outcome = "acknowledged";
41
+ params.assertCurrent();
42
+ params.signal?.throwIfAborted();
43
+ } catch (cause) {
44
+ if (outcome !== "acknowledged" && (cause instanceof CodexAppServerScopedRequestRejectedError || isCodexAppServerPrewriteRequestCancellationError(cause) || isCodexAppServerOverloadError(cause))) outcome = "not-written";
45
+ throw new CodexThreadPolicyHandoffError(outcome, cause);
46
+ }
47
+ }
48
+ /** Native lineage classifies the exact bound thread; it never grants session authority. */
49
+ function assertCodexSupervisionThreadLineage(binding, thread) {
50
+ if (binding.connectionScope !== "supervision" || binding.pendingSupervisionBranch) return;
51
+ if (thread.id !== binding.threadId || !binding.supervisionSourceThreadId || thread.forkedFromId !== null && (typeof thread.forkedFromId !== "string" || !thread.forkedFromId.trim() || thread.forkedFromId === thread.id)) throw new Error("Codex supervision lineage could not be verified; reconnect before continuing.");
52
+ }
53
+ //#endregion
54
+ export { refreshCodexThreadPolicy as i, CodexThreadPolicyHandoffError as n, assertCodexSupervisionThreadLineage as r, CodexIncognitoPolicyChangeError as t };
@@ -1,8 +1,7 @@
1
- import { F as resolveCodexAppServerLocalHomeDir, I as resolveCodexAppServerUserHomeDir, P as resolveCodexAppServerHomeDir } from "./config-CcYL77O6.js";
2
- import { $ as CodexAppServerRpcError, J as isCodexAppServerOverloadError, P as isCodexAppServerStartupError, Y as isCodexAppServerPrewriteRequestCancellationError, u as isCodexAppServerStartSelectionChangedError } from "./shared-client-B1tT5U6r.js";
3
- import { o as assertCodexThreadResumeResponse } from "./protocol-validators-Bg5rpNxk.js";
4
- import { f as unsubscribeCodexThreadBestEffort, i as assertCodexThreadResumeSubscription, r as CodexAppServerUnsafeSubscriptionError } from "./attempt-client-cleanup-CpVfwctT.js";
5
- import { t as CodexAppServerScopedRequestRejectedError } from "./request-BWxweEdK.js";
1
+ import { $ as assertCodexThreadResumeResponse, H as isCodexAppServerOverloadError, M as isCodexAppServerStartupError, U as isCodexAppServerPrewriteRequestCancellationError, q as CodexAppServerRpcError, u as isCodexAppServerStartSelectionChangedError } from "./shared-client-DxcfF9KX.js";
2
+ import { F as resolveCodexAppServerHomeDir, I as resolveCodexAppServerLocalHomeDir, L as resolveCodexAppServerUserHomeDir } from "./config-BhmfC1s6.js";
3
+ import { d as unsubscribeCodexThreadBestEffort, i as assertCodexThreadResumeSubscription, r as CodexAppServerUnsafeSubscriptionError } from "./attempt-client-cleanup-DYHcRQAa.js";
4
+ import { t as CodexAppServerScopedRequestRejectedError } from "./request-DYAI5FQE.js";
6
5
  import { createRequire } from "node:module";
7
6
  import { isRecord } from "openclaw/plugin-sdk/string-coerce-runtime";
8
7
  import { readPluginPackageVersion } from "openclaw/plugin-sdk/extension-shared";
@@ -434,15 +433,24 @@ function fingerprintCodexPluginAppCacheCredentials(startOptions) {
434
433
  async function resumeCodexAppServerThread(params) {
435
434
  const threadId = params.request.threadId;
436
435
  let response;
436
+ let ownershipRejected = false;
437
+ const assertCurrent = params.assertCurrent && (() => {
438
+ try {
439
+ params.assertCurrent?.();
440
+ } catch (error) {
441
+ ownershipRejected = true;
442
+ throw error;
443
+ }
444
+ });
437
445
  try {
438
446
  response = assertCodexThreadResumeResponse(await (params.requestResume ? params.requestResume(params.request) : params.client.request("thread/resume", params.request, {
439
447
  ...params.timeoutMs !== void 0 ? { timeoutMs: params.timeoutMs } : {},
440
448
  ...params.signal ? { signal: params.signal } : {},
441
- assertCurrent: params.assertCurrent
449
+ assertCurrent
442
450
  })));
443
451
  assertCodexThreadResumeSubscription(threadId, response.thread.id);
444
452
  } catch (error) {
445
- if (params.isPrewriteOwnershipError?.(error) || isCodexAppServerStartSelectionChangedError(error) || isCodexAppServerStartupError(error) || error instanceof CodexAppServerScopedRequestRejectedError || isCodexAppServerPrewriteRequestCancellationError(error) || isCodexAppServerOverloadError(error)) throw error;
453
+ if (ownershipRejected || isCodexAppServerStartSelectionChangedError(error) || isCodexAppServerStartupError(error) || error instanceof CodexAppServerScopedRequestRejectedError || isCodexAppServerPrewriteRequestCancellationError(error) || isCodexAppServerOverloadError(error)) throw error;
446
454
  if (error instanceof CodexAppServerRpcError) {
447
455
  if (await unsubscribeCodexThreadBestEffort(params.client, {
448
456
  threadId,
@@ -1,11 +1,27 @@
1
1
  import { i as readUpstreamUserText, n as attachUpstreamUserText, r as readMirrorIdentity, t as attachCodexMirrorIdentity } from "./upstream-prompt-provenance-LphB8slG.js";
2
2
  import { asOptionalRecord, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
3
+ import path from "node:path";
3
4
  import { deliverAgentHarnessUserInputPrompt, embeddedAgentLog, formatErrorMessage, projectAgentHarnessTranscriptMessageForDisplay, runAgentHarnessBeforeMessageWriteHook } from "openclaw/plugin-sdk/agent-harness-runtime";
4
5
  import { createHash } from "node:crypto";
6
+ import fsSync from "node:fs";
5
7
  import { truncateUtf8Prefix } from "openclaw/plugin-sdk/text-utility-runtime";
6
8
  import { withCodexSessionTranscriptMirrorWriteLock } from "openclaw/plugin-sdk/codex-session-transcript-runtime";
7
9
  import { publishSessionTranscriptUpdateByIdentity } from "openclaw/plugin-sdk/session-transcript-runtime";
8
10
  import { Buffer } from "node:buffer";
11
+ //#region extensions/codex/src/session-catalog-home-id.ts
12
+ function canonicalCodexCatalogHome(value) {
13
+ const resolved = path.resolve(value);
14
+ try {
15
+ return fsSync.realpathSync.native(resolved);
16
+ } catch {
17
+ return resolved;
18
+ }
19
+ }
20
+ /** One canonical identity for catalog discovery and durable ownership rows. */
21
+ function codexCatalogHomeId(codexHome) {
22
+ return createHash("sha256").update("openclaw:codex-session-catalog-home:v1\0").update(canonicalCodexCatalogHome(codexHome)).digest("hex");
23
+ }
24
+ //#endregion
9
25
  //#region extensions/codex/src/app-server/transcript-history-projection.ts
10
26
  const CODEX_HISTORY_IMPORT_MAX_MESSAGES = 200;
11
27
  const CODEX_HISTORY_IMPORT_MAX_BYTES = 524288;
@@ -301,25 +317,26 @@ function readMirroredAssistantText(message) {
301
317
  }
302
318
  /** Imports a bounded, user-visible Codex history tail into a new OpenClaw transcript. */
303
319
  async function importCodexThreadHistoryToTranscript(params) {
304
- const projection = projectBoundedCodexThreadHistory({
320
+ const { transcriptMessages, importedMessages, omittedMessages } = projectBoundedCodexThreadHistory({
305
321
  thread: params.thread,
306
322
  throughTurnId: params.throughTurnId,
307
323
  importedAt: Date.now(),
308
324
  ...params.modelProvider ? { modelProvider: params.modelProvider } : {}
309
325
  });
310
- if (projection.transcriptMessages.length > 0) await mirror({
326
+ if (transcriptMessages.length > 0) await mirror({
327
+ assertCurrent: params.assertCurrent,
311
328
  storePath: params.storePath,
312
329
  sessionId: params.sessionId,
313
330
  sessionKey: params.sessionKey,
314
331
  ...params.agentId ? { agentId: params.agentId } : {},
315
332
  ...params.cwd ? { cwd: params.cwd } : {},
316
333
  ...params.config ? { config: params.config } : {},
317
- messages: projection.transcriptMessages,
334
+ messages: transcriptMessages,
318
335
  idempotencyScope: `codex-app-server:${params.thread.id}:history`
319
336
  });
320
337
  return {
321
- importedMessages: projection.importedMessages,
322
- omittedMessages: projection.omittedMessages
338
+ importedMessages,
339
+ omittedMessages
323
340
  };
324
341
  }
325
342
  async function mirrorBestEffort(params) {
@@ -422,7 +439,18 @@ async function mirrorPromptAtTurnStartBestEffort(params) {
422
439
  hidden: params.params.trigger === "memory",
423
440
  message: attachUpstreamUserText(attachCodexMirrorIdentity(await buildResolvedCodexUserPromptMessage(params.params), `${params.turnId}:prompt`), params.upstreamUserText)
424
441
  });
442
+ if (params.params.userTurnTranscriptRecorder?.getAdmissionReceipt()) {
443
+ const annotate = params.params.hostCapabilities.annotateCurrentUserTurn;
444
+ if (!annotate || userPromptMessage.role !== "user") throw new Error("current host admission is unavailable for native prompt annotation");
445
+ await annotate({
446
+ mirrorIdentity: `${params.turnId}:prompt`,
447
+ upstreamUserText: params.upstreamUserText,
448
+ mirrorOrigin: "codex-app-server",
449
+ mirrorSourceFingerprint: fingerprintCodexMirrorSourceMessage(userPromptMessage)
450
+ });
451
+ }
425
452
  const mirrorResult = await mirror({
453
+ assertCurrent: params.params.hostCapabilities.assertActive,
426
454
  agentId: params.agentId,
427
455
  sessionKey: params.sessionKey,
428
456
  sessionId: params.params.sessionId,
@@ -454,9 +482,7 @@ function fingerprintMirrorMessageContent(message) {
454
482
  return createHash("sha256").update(payload).digest("hex").slice(0, 16);
455
483
  }
456
484
  function buildMirrorDedupeIdentity(message) {
457
- const explicit = readMirrorIdentity(message);
458
- if (explicit) return explicit;
459
- return `${message.role}:${fingerprintMirrorMessageContent(message)}`;
485
+ return readMirrorIdentity(message) || `${message.role}:${fingerprintMirrorMessageContent(message)}`;
460
486
  }
461
487
  async function mirror(params) {
462
488
  const messages = params.messages.filter(isMirroredAgentMessage);
@@ -480,10 +506,12 @@ async function mirror(params) {
480
506
  });
481
507
  const candidateIdempotencyKeys = candidates.flatMap(({ idempotencyKey }) => idempotencyKey ? [idempotencyKey] : []);
482
508
  const transcriptTarget = resolveCodexMirrorTranscriptTarget(params);
483
- const { appendedUpdates, assistantMirrorIdentitiesAppended, assistantMirrorIdentitiesOwned, anchorsByMirrorIdentity, messagesPresent, userMessageReceipts, userMessagesPresent } = await withCodexSessionTranscriptMirrorWriteLock({
509
+ params.assertCurrent?.();
510
+ const mirrorBatch = await withCodexSessionTranscriptMirrorWriteLock({
484
511
  ...transcriptTarget,
485
512
  config: params.config
486
513
  }, async (transcript) => {
514
+ params.assertCurrent?.();
487
515
  const nextAppendedUpdates = [];
488
516
  const nextAssistantMirrorIdentitiesAppended = /* @__PURE__ */ new Set();
489
517
  const nextAssistantMirrorIdentitiesOwned = /* @__PURE__ */ new Set();
@@ -492,6 +520,7 @@ async function mirror(params) {
492
520
  const nextUserMessageReceipts = [];
493
521
  const nextUserMessagesPresent = [];
494
522
  const mirrorFacts = await transcript.readMessageFacts({ idempotencyKeys: candidateIdempotencyKeys });
523
+ params.assertCurrent?.();
495
524
  for (const { dedupeIdentity, idempotencyKey, message, sourceFingerprint } of candidates) {
496
525
  const mirrorIdentity = readMirrorIdentity(message);
497
526
  const ownsRun = Boolean(params.runId && (!params.runMirrorIdentityPrefix || mirrorIdentity?.startsWith(params.runMirrorIdentityPrefix)));
@@ -540,11 +569,17 @@ async function mirror(params) {
540
569
  hidden: message.display === false,
541
570
  message: messageToAppend
542
571
  });
572
+ params.assertCurrent?.();
543
573
  const { messageSeq, result: appended } = await transcript.appendMessageWithMessageSequence({
544
574
  message: messageToAppend,
575
+ ...params.assertCurrent ? { prepareMessageAfterIdempotencyCheck: (preparedMessage) => {
576
+ params.assertCurrent?.();
577
+ return preparedMessage;
578
+ } } : {},
545
579
  idempotencyLookup: "scan",
546
580
  cwd: params.cwd
547
581
  });
582
+ params.assertCurrent?.();
548
583
  if (!appended) continue;
549
584
  const { messageId, message: appendedMessage } = appended;
550
585
  if (isMirroredAgentMessage(appendedMessage)) {
@@ -583,6 +618,8 @@ async function mirror(params) {
583
618
  userMessagesPresent: nextUserMessagesPresent
584
619
  };
585
620
  });
621
+ params.assertCurrent?.();
622
+ const { appendedUpdates, assistantMirrorIdentitiesAppended, assistantMirrorIdentitiesOwned, anchorsByMirrorIdentity, messagesPresent, userMessageReceipts, userMessagesPresent } = mirrorBatch;
586
623
  for (const update of appendedUpdates) try {
587
624
  const terminalOwner = params.terminalAssistantOwner;
588
625
  const terminalRunId = update.message.role === "assistant" && terminalOwner && readMirrorIdentity(update.message) === terminalOwner.mirrorIdentity ? terminalOwner.runId : void 0;
@@ -691,4 +728,4 @@ function resolveCodexMirrorTranscriptTarget(params) {
691
728
  };
692
729
  }
693
730
  //#endregion
694
- export { buildCodexUserPromptMessage as a, fingerprintCodexMirrorSourceMessage as c, serializeCodexMirrorSourceEvidence as d, projectBoundedCodexThreadHistory as f, mirrorPromptAtTurnStartBestEffort as i, hasCodexMirrorOrigin as l, projectCodexUserItemText as m, createCodexAppServerUserMessagePersistenceNotifier as n, promptSnapshot as o, projectBoundedCodexVisibleSessionHistory as p, importCodexThreadHistoryToTranscript as r, applyCodexTranscriptTaint as s, codexTranscriptMirrorRuntime as t, readCodexMirrorSourceFingerprint as u };
731
+ export { buildCodexUserPromptMessage as a, fingerprintCodexMirrorSourceMessage as c, serializeCodexMirrorSourceEvidence as d, projectBoundedCodexThreadHistory as f, codexCatalogHomeId as g, canonicalCodexCatalogHome as h, mirrorPromptAtTurnStartBestEffort as i, hasCodexMirrorOrigin as l, projectCodexUserItemText as m, createCodexAppServerUserMessagePersistenceNotifier as n, promptSnapshot as o, projectBoundedCodexVisibleSessionHistory as p, importCodexThreadHistoryToTranscript as r, applyCodexTranscriptTaint as s, codexTranscriptMirrorRuntime as t, readCodexMirrorSourceFingerprint as u };
@@ -1,4 +1,4 @@
1
- import { t as normalizeCodexAppServerArgs } from "./launch-args-sXOAg0SX.js";
1
+ import { n as normalizeCodexAppServerArgs } from "./launch-args-RXQwn8zV.js";
2
2
  import { readFile, readdir } from "node:fs/promises";
3
3
  import { createHash, randomUUID } from "node:crypto";
4
4
  import { materializeWindowsSpawnProgram, resolveWindowsSpawnProgram } from "openclaw/plugin-sdk/windows-spawn";
@@ -115,6 +115,8 @@ async function readProcessOutput(args, deadline) {
115
115
  inspector.unref();
116
116
  }, Math.max(1, remainingMs));
117
117
  timer.unref?.();
118
+ }).catch((error) => {
119
+ throw inspectionFailure(error);
118
120
  });
119
121
  }
120
122
  function parseProcesses(output, selected) {