@openclaw/codex 2026.8.1-beta.2 → 2026.8.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 (64) hide show
  1. package/dist/api.js +146 -0
  2. package/dist/{attempt-client-cleanup-DMLXUfa8.js → attempt-client-cleanup-CVPvp9dL.js} +47 -5
  3. package/dist/{auth-binding-B4FfbcCg.js → auth-binding-Ds_QVm-X.js} +18 -3
  4. package/dist/{binding-connection-I5Bo-AsX.js → binding-connection-CCQFs8lf.js} +15 -3
  5. package/dist/{bounded-turn-qgZmzy_4.js → bounded-turn-rq5tiSXk.js} +27 -26
  6. package/dist/{capabilities-CybGI1oz.js → capabilities-CGm_94eL.js} +1 -1
  7. package/dist/cli-metadata.js +1 -1
  8. package/dist/{command-formatters-B1AEz8ZA.js → command-formatters-C54Yg3eA.js} +2 -2
  9. package/dist/{command-handlers-Db8pu_ds.js → command-handlers-BvOAHTrA.js} +111 -67
  10. package/dist/{compact-LspQaGfl.js → compact-Hd7SAc0N.js} +35 -30
  11. package/dist/{session-binding-DPxIvMgE.js → config-Cxw3Cl3k.js} +361 -1161
  12. package/dist/context-compaction-activity-BOeJf7yo.js +58 -0
  13. package/dist/doctor-contract-api.js +128 -26
  14. package/dist/{dynamic-tools-BVdyWkUD.js → dynamic-tools-BFoUcRdx.js} +1341 -1464
  15. package/dist/{effective-mcp-catalog-DIIhAtOZ.js → effective-mcp-catalog-BTJHnDSx.js} +2 -2
  16. package/dist/elicitation-input-DMkeki8d.js +71 -0
  17. package/dist/{event-projector-assistant-message-BwxV4d6N.js → event-projector-assistant-message-C5-Ds8mA.js} +18 -1
  18. package/dist/{event-projector-usage-e5huIQWu.js → event-projector-usage-D3PHFFXh.js} +18 -18
  19. package/dist/harness-DVfUQBlQ.js +248 -0
  20. package/dist/harness.js +2 -226
  21. package/dist/index.js +405 -299
  22. package/dist/{isolated-completion-C58NbL40.js → isolated-completion-Cbbx_5Ed.js} +4 -4
  23. package/dist/launch-args-sXOAg0SX.js +84 -0
  24. package/dist/managed-binary-ZkGodW19.js +248 -0
  25. package/dist/media-understanding-provider.js +2 -2
  26. package/dist/model-catalog-o6Cgjoss.js +101 -0
  27. package/dist/{models-BFlpn1Ex.js → models-DgFWSuxA.js} +25 -28
  28. package/dist/{native-subagent-monitor-DyTGmTUx.js → native-subagent-monitor-CwFyoylz.js} +385 -94
  29. package/dist/node-exec-server.runtime-DXrqpw1c.js +195 -0
  30. package/dist/plugin-approval-roundtrip-D80UZiJ_.js +95 -0
  31. package/dist/{plugin-marketplace-discovery-CzrGJdCR.js → plugin-marketplace-discovery-mdmScYOj.js} +60 -55
  32. package/dist/{plugin-metadata-cache-CNJPj4_b.js → plugin-metadata-cache-CulOABwu.js} +164 -134
  33. package/dist/{protocol-validators-B4F7L8Rf.js → protocol-validators-Bg5rpNxk.js} +203 -7
  34. package/dist/{rate-limits-DZXmOL8-.js → rate-limits-hFtzt2Up.js} +1 -1
  35. package/dist/{sandbox-guard-Cmwc9eIk.js → request-CCm4LaED.js} +207 -20
  36. package/dist/{run-attempt-P8BdxC1I.js → run-attempt-BwNQDH2u.js} +1506 -836
  37. package/dist/{runtime-artifact-BVSPdd6g.js → runtime-artifact-DeBvleJw.js} +4 -7
  38. package/dist/session-binding-q2WSTVmC.js +947 -0
  39. package/dist/{session-catalog-xwNi_SDM.js → session-catalog-C2Tae4rI.js} +1698 -1346
  40. package/dist/session-catalog-home-id-DAKUrm3C.js +112 -0
  41. package/dist/{session-cli-7hgXZDV7.js → session-cli-BuDjm5Ou.js} +20 -7
  42. package/dist/session-permission-policy-gLm40Vtq.js +160 -0
  43. package/dist/session-retirement-CdkI0bvb.js +90 -0
  44. package/dist/{session-upstream-marker-CrIFX06J.js → session-upstream-marker-Bcy33kam.js} +2 -3
  45. package/dist/{settled-turn-finalizer-BRWBO4MO.js → settled-turn-finalizer-B8JJcxCi.js} +27 -22
  46. package/dist/{shared-client-kIBbGjk4.js → shared-client-kNkljY-R.js} +2023 -607
  47. package/dist/{side-question-9HAL26l9.js → side-question-GwD73tX6.js} +109 -57
  48. package/dist/{thread-lifecycle-Bu1BTDXr.js → thread-lifecycle-Ss-uwnC4.js} +1208 -497
  49. package/dist/{thread-ownership-6kOQHlyC.js → thread-ownership-CeYBqg_4.js} +18 -8
  50. package/dist/{plugin-app-cache-key-C3H2CVp6.js → thread-resume-DF54hagX.js} +64 -6
  51. package/dist/{transcript-mirror-B9gGgnJS.js → transcript-mirror-CkEQIna-.js} +158 -41
  52. package/dist/transport-stdio-C7-s9TLG.js +708 -0
  53. package/dist/{upstream-prompt-provenance-ClRBije0.js → upstream-prompt-provenance-CFmsKwr9.js} +12 -14
  54. package/dist/{upstream-session-fork-CE-_LdnP.js → upstream-session-fork-BACGlOFa.js} +86 -88
  55. package/dist/{usage-CHlV0e-o.js → usage-C2l8Mils.js} +3 -3
  56. package/dist/{web-search-provider.runtime-DRw2Vl42.js → web-search-provider.runtime-B2XgRdFv.js} +3 -3
  57. package/openclaw.plugin.json +50 -2
  58. package/package.json +9 -8
  59. package/dist/app-server-policy-zcBDc1JU.js +0 -49
  60. package/dist/incognito-session-ET_ufDH-.js +0 -2
  61. package/dist/request-BRl5_UfX.js +0 -157
  62. package/dist/session-retirement-DoMMJFKm.js +0 -36
  63. package/dist/thread-resume-CPrJNQVM.js +0 -30
  64. package/dist/transport-stdio-DIImwDVS.js +0 -99
@@ -1,8 +1,9 @@
1
- import { B as claimCodexAppServerLiveThread, K as releaseCodexAppServerLiveThread, ct as isJsonObject, q as retainCodexAppServerLiveThread } from "./shared-client-kIBbGjk4.js";
2
- import { A as shouldSynthesizeToolProgressForItem, B as readNullableString$1, C as isSideEffectingNativeToolItem, D as itemTitle, E as itemStatus, F as readItem, L as readNonEmptyString, M as normalizeOptionalString$1, P as readHookOutputEntries, R as readNonEmptyStringArray, S as isNonSuccessItemStatus, T as itemName, k as shouldRecordNativeToolTranscript, w as itemKind, x as isMutatingNativeToolItem, y as auditNativeToolTerminalStatus } from "./attempt-client-cleanup-DMLXUfa8.js";
3
- import { t as attachCodexMirrorIdentity } from "./upstream-prompt-provenance-ClRBije0.js";
1
+ import { Ct as retainCodexAppServerLiveThread, Ht as isJsonObject, St as releaseCodexAppServerLiveThread, ht as claimCodexAppServerLiveThread } from "./shared-client-kNkljY-R.js";
2
+ import { A as shouldRecordNativeToolTranscript, C as isNonSuccessItemStatus, D as itemStatus, E as itemName, F as readHookOutputEntries, I as readItem, N as normalizeOptionalString$1, O as itemTitle, R as readNonEmptyString, S as isMutatingNativeToolItem, T as itemKind, V as readNullableString$1, b as auditNativeToolTerminalStatus, j as shouldSynthesizeToolProgressForItem, w as isSideEffectingNativeToolItem, z as readNonEmptyStringArray } from "./attempt-client-cleanup-CVPvp9dL.js";
3
+ import { t as attachCodexMirrorIdentity } from "./upstream-prompt-provenance-CFmsKwr9.js";
4
4
  import { n as sanitizeCodexHistoryImagePayloads } from "./image-payload-sanitizer-CnfoUPCE.js";
5
5
  import { t as resolveCodexLocalRuntimeAttribution } from "./local-runtime-attribution-B_2mnqhb.js";
6
+ import { n as codexApprovalTimeoutText } from "./plugin-approval-roundtrip-D80UZiJ_.js";
6
7
  import { asFiniteNumber, asNonArrayRecord, normalizeOptionalString, readStringField } from "openclaw/plugin-sdk/string-coerce-runtime";
7
8
  import fs from "node:fs/promises";
8
9
  import path from "node:path";
@@ -11,9 +12,9 @@ import { TOOL_PROGRESS_OUTPUT_MAX_CHARS, embeddedAgentLog, emitAgentEvent, forma
11
12
  import { getSessionEntry, parseSqliteSessionFileMarker, resolveTranscriptSessionKeyBySessionId } from "openclaw/plugin-sdk/session-store-runtime";
12
13
  import { truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
13
14
  import { redactSensitiveFieldValue, redactToolPayloadText } from "openclaw/plugin-sdk/logging-core";
15
+ import { KeyedAsyncQueue } from "openclaw/plugin-sdk/keyed-async-queue";
14
16
  import { readCodexSessionTranscriptEventsBeforeAdmission } from "openclaw/plugin-sdk/codex-session-transcript-runtime";
15
17
  import { readSessionTranscriptEvents } from "openclaw/plugin-sdk/session-transcript-runtime";
16
- import { KeyedAsyncQueue } from "openclaw/plugin-sdk/keyed-async-queue";
17
18
  import { buildSessionContext, migrateSessionEntries, parseSessionEntries } from "openclaw/plugin-sdk/agent-sessions";
18
19
  import { createAgentHarnessTaskRuntime, deliverAgentHarnessTaskCompletion, isDurableAgentHarnessCompletionDelivery } from "openclaw/plugin-sdk/agent-harness-task-runtime";
19
20
  //#region extensions/codex/src/app-server/event-projector-tool-output.ts
@@ -196,7 +197,7 @@ function sanitizeCodexToolArguments(value) {
196
197
  }
197
198
  /** Sanitizes a Codex dynamic-tool response before diagnostic/event emission. */
198
199
  function sanitizeCodexToolResponse(response) {
199
- return sanitizeCodexAgentEventRecord(response);
200
+ return sanitizeCodexAgentEventRecord({ ...response });
200
201
  }
201
202
  /** Infers compact human-readable tool metadata from Codex dynamic-tool arguments. */
202
203
  function inferCodexDynamicToolMeta(call, detailMode) {
@@ -204,17 +205,6 @@ function inferCodexDynamicToolMeta(call, detailMode) {
204
205
  }
205
206
  //#endregion
206
207
  //#region extensions/codex/src/app-server/event-projector-tool-items.ts
207
- function nativeToolActionFingerprint(item) {
208
- if (item.type === "commandExecution" && typeof item.command === "string") return JSON.stringify({
209
- type: item.type,
210
- command: item.command,
211
- cwd: typeof item.cwd === "string" ? item.cwd : ""
212
- });
213
- if (item.type === "fileChange") return JSON.stringify({
214
- type: item.type,
215
- changes: itemFileChanges(item)
216
- });
217
- }
218
208
  function isNativePostToolUseRelayItem(item) {
219
209
  switch (item.type) {
220
210
  case "commandExecution":
@@ -434,6 +424,7 @@ var CodexToolProgressProjection = class {
434
424
  this.sideEffectingNativeIds = /* @__PURE__ */ new Set();
435
425
  this.sideEffectingDynamicIds = /* @__PURE__ */ new Set();
436
426
  this.transcriptProgressCallIds = /* @__PURE__ */ new Set();
427
+ this.approvalTimeoutKinds = /* @__PURE__ */ new Map();
437
428
  }
438
429
  get outputTextByItem() {
439
430
  return this.output.textByItem;
@@ -450,6 +441,10 @@ var CodexToolProgressProjection = class {
450
441
  get hasPotentialSideEffects() {
451
442
  return this.sideEffectingNativeIds.size > 0 || this.sideEffectingDynamicIds.size > 0;
452
443
  }
444
+ approvalTimeoutExplanation(itemId, status) {
445
+ const kind = isNonSuccessItemStatus(status) && this.approvalTimeoutKinds.get(itemId);
446
+ return kind ? codexApprovalTimeoutText(kind) : void 0;
447
+ }
453
448
  setLastToolError(error) {
454
449
  if (!error) {
455
450
  this.lastNativeToolError = void 0;
@@ -468,9 +463,7 @@ var CodexToolProgressProjection = class {
468
463
  },
469
464
  nativeMutation: {
470
465
  mutatingAction: error.mutatingAction === true,
471
- replaySafe: error.mutatingAction !== true,
472
- ...error.actionFingerprint ? { actionFingerprint: error.actionFingerprint } : {},
473
- ...error.fileTarget ? { fileTarget: error.fileTarget } : {}
466
+ replaySafe: error.mutatingAction !== true
474
467
  }
475
468
  });
476
469
  this.lastNativeToolError = terminalResolution?.lastToolError ?? (this.lastNativeToolError?.mutatingAction && error.mutatingAction !== true ? this.lastNativeToolError : error);
@@ -537,9 +530,14 @@ var CodexToolProgressProjection = class {
537
530
  recordNativeToolError(params) {
538
531
  const executionStarted = params.status !== "blocked";
539
532
  const mutatingAction = executionStarted && isMutatingNativeToolItem(params.item);
540
- const actionFingerprint = mutatingAction ? nativeToolActionFingerprint(params.item) : void 0;
541
533
  const isFailure = isNonSuccessItemStatus(params.status);
542
- const error = isFailure ? itemToolError(params.item, params.status, this.output.textByItem) : void 0;
534
+ const approvalTimeoutExplanation = this.approvalTimeoutExplanation(params.item.id, params.status);
535
+ const error = isFailure ? approvalTimeoutExplanation ?? itemToolError(params.item, params.status, this.output.textByItem) : void 0;
536
+ const failure = error ? {
537
+ ...approvalTimeoutExplanation ? { errorCode: "approval_timeout" } : {},
538
+ error,
539
+ ...approvalTimeoutExplanation ? { timedOut: true } : {}
540
+ } : {};
543
541
  const terminalResolution = this.params.observeToolTerminal?.({
544
542
  toolCallId: params.item.id,
545
543
  toolName: params.name,
@@ -547,11 +545,10 @@ var CodexToolProgressProjection = class {
547
545
  ...params.meta ? { meta: params.meta } : {},
548
546
  executionStarted,
549
547
  outcome: isFailure ? "failure" : "success",
550
- ...isFailure ? { failure: error ? { error } : {} } : {},
548
+ ...isFailure ? { failure } : {},
551
549
  nativeMutation: {
552
550
  mutatingAction,
553
- replaySafe: !mutatingAction,
554
- ...actionFingerprint ? { actionFingerprint } : {}
551
+ replaySafe: !mutatingAction
555
552
  }
556
553
  });
557
554
  if (terminalResolution) {
@@ -561,9 +558,8 @@ var CodexToolProgressProjection = class {
561
558
  if (isFailure) this.lastNativeToolError = {
562
559
  toolName: params.name,
563
560
  ...params.meta ? { meta: params.meta } : {},
564
- ...error ? { error } : {},
565
- ...mutatingAction ? { mutatingAction: true } : {},
566
- ...actionFingerprint ? { actionFingerprint } : {}
561
+ ...failure,
562
+ ...mutatingAction ? { mutatingAction: true } : {}
567
563
  };
568
564
  else if (this.lastNativeToolError?.mutatingAction !== true) this.lastNativeToolError = void 0;
569
565
  }
@@ -574,7 +570,7 @@ var CodexToolProgressProjection = class {
574
570
  const args = itemToolArgs(item);
575
571
  if (!toolName || !shouldEmitTranscriptToolProgress(toolName, args)) return;
576
572
  this.resultSummaryItemIds.add(item.id);
577
- const meta = this.shouldEmitToolOutput() || !isCommandBearingToolItem(item, args) ? itemMeta(item, this.toolProgressDetailMode()) : void 0;
573
+ const meta = this.shouldIncludeFormattedMeta(isCommandBearingToolItem(item, args)) ? itemMeta(item, this.toolProgressDetailMode()) : void 0;
578
574
  this.emitToolResultMessage({
579
575
  itemId: item.id,
580
576
  text: formatToolSummary(toolName, meta)
@@ -586,9 +582,10 @@ var CodexToolProgressProjection = class {
586
582
  const toolName = itemName(item);
587
583
  const output = itemOutputText(item, this.output.textByItem);
588
584
  if (!toolName || !output || !shouldEmitTranscriptToolProgress(toolName, itemToolArgs(item))) return;
585
+ const meta = this.shouldIncludeFormattedMeta(isCommandBearingToolItem(item, itemToolArgs(item))) ? itemMeta(item, this.toolProgressDetailMode()) : void 0;
589
586
  this.emitToolResultMessage({
590
587
  itemId: item.id,
591
- text: formatToolOutput(toolName, itemMeta(item, this.toolProgressDetailMode()), output),
588
+ text: formatToolOutput(toolName, meta, output),
592
589
  finalOutput: true,
593
590
  isError: isNonSuccessItemStatus(itemStatus(item))
594
591
  });
@@ -647,6 +644,7 @@ var CodexToolProgressProjection = class {
647
644
  try {
648
645
  Promise.resolve(this.params.onToolResult?.({
649
646
  text,
647
+ ...(this.params.messageChannel || this.params.messageProvider) && { channelData: { openclawToolProgressId: params.itemId } },
650
648
  ...params.isError === true ? { isError: true } : {}
651
649
  })).catch(() => {});
652
650
  } catch {}
@@ -657,11 +655,15 @@ var CodexToolProgressProjection = class {
657
655
  shouldEmitToolOutput() {
658
656
  return typeof this.params.shouldEmitToolOutput === "function" ? this.params.shouldEmitToolOutput() : this.params.verboseLevel === "full";
659
657
  }
658
+ shouldIncludeFormattedMeta(commandBearing) {
659
+ const channel = this.params.messageChannel ?? this.params.messageProvider;
660
+ return !commandBearing || !channel && this.shouldEmitToolOutput();
661
+ }
660
662
  emitTranscriptToolCallProgress(params) {
661
663
  if (!shouldEmitTranscriptToolProgress(params.name, params.arguments)) return;
662
664
  this.transcriptProgressCallIds.add(params.id);
663
665
  const args = normalizeToolTranscriptArguments(params.arguments);
664
- const meta = this.shouldEmitToolOutput() || !isCodexCommandBearingToolCall(params.name, args) ? inferToolMetaFromArgs(params.name, args, { detailMode: this.toolProgressDetailMode() }) : void 0;
666
+ const meta = this.shouldIncludeFormattedMeta(isCodexCommandBearingToolCall(params.name, args)) ? inferToolMetaFromArgs(params.name, args, { detailMode: this.toolProgressDetailMode() }) : void 0;
665
667
  if (!this.params.onToolResult || !this.shouldEmitToolResult() || this.resultSummaryItemIds.has(params.id) || this.resultOutputStreamedItemIds.has(params.id)) return;
666
668
  this.resultSummaryItemIds.add(params.id);
667
669
  this.emitToolResultMessage({
@@ -819,6 +821,10 @@ const MISSING_TOOL_RESULT_ERROR = "OpenClaw recorded a native Codex tool.call wi
819
821
  const NATIVE_PATCH_REJECTION_RE = /^\s*patch rejected:\s*writing outside of the project;\s*rejected by user approval settings\s*$/iu;
820
822
  const CODE_MODE_NATIVE_PATCH_SOURCE_RE = /^\s*(?:\/\/[^\r\n]*\r?\n\s*)?(?:const|let)\s+([A-Za-z_$][\w$]*)\s*=\s*await\s+tools\.apply_patch\(\s*("(?:\\[\s\S]|[^"\\])*")\s*\)\s*;?\s*text\(\s*\1\s*\)\s*;?\s*$/u;
821
823
  const CODE_MODE_NATIVE_PATCH_RESULT_RE = /^\s*Script (completed|failed)\s*\r?\nWall time\s+\d+(?:\.\d+)?\s+seconds\s*\r?\nOutput:\s*([\s\S]*?)\s*$/iu;
824
+ const MAX_TOOL_APPROVAL_REVIEWS = 16;
825
+ function toolApprovalReviewOutcome(state) {
826
+ return state.denied ? "denied" : state.unresolvedReviewIds === null || state.unresolvedReviewIds.size > 0 ? "reviewing" : "approved";
827
+ }
822
828
  function readCodeModeNativePatchInput(source) {
823
829
  if (typeof source !== "string") return;
824
830
  const match = CODE_MODE_NATIVE_PATCH_SOURCE_RE.exec(source);
@@ -864,12 +870,38 @@ var CodexToolTranscriptProjection = class {
864
870
  this.afterToolCallObservedItemIds = /* @__PURE__ */ new Set();
865
871
  this.nativeMcpAppResultDetails = /* @__PURE__ */ new Map();
866
872
  this.nativeMcpAppResultDetailsAttempted = /* @__PURE__ */ new Set();
873
+ this.approvalReviewsByCallId = /* @__PURE__ */ new Map();
867
874
  this.rawNativeToolOutputByCallId = /* @__PURE__ */ new Map();
875
+ this.pendingRawPatchOutputIds = /* @__PURE__ */ new Set();
868
876
  this.codeModeNativePatchInputsByCallId = /* @__PURE__ */ new Map();
869
877
  }
870
878
  get transcriptMessages() {
871
879
  return this.messages;
872
880
  }
881
+ recordToolApprovalReview(toolCallId, reviewId, status, review) {
882
+ const state = this.approvalReviewsByCallId.get(toolCallId) ?? {
883
+ reviews: [],
884
+ denied: false,
885
+ unresolvedReviewIds: /* @__PURE__ */ new Set()
886
+ };
887
+ state.reviews = [...state.reviews.filter((candidate) => candidate.id !== reviewId), review].slice(-16);
888
+ state.denied ||= [
889
+ "denied",
890
+ "timed_out",
891
+ "aborted"
892
+ ].includes(status);
893
+ const unresolved = state.unresolvedReviewIds;
894
+ if (status === "in_progress") state.unresolvedReviewIds = unresolved && (unresolved.size < MAX_TOOL_APPROVAL_REVIEWS || unresolved.has(reviewId)) ? unresolved.add(reviewId) : null;
895
+ else unresolved?.delete(reviewId);
896
+ this.approvalReviewsByCallId.set(toolCallId, state);
897
+ return toolApprovalReviewOutcome(state);
898
+ }
899
+ finalizeToolApprovalReviews(toolCallId) {
900
+ const state = this.approvalReviewsByCallId.get(toolCallId);
901
+ if (!state) return;
902
+ state.unresolvedReviewIds = /* @__PURE__ */ new Set();
903
+ return toolApprovalReviewOutcome(state);
904
+ }
873
905
  recordDynamicToolCall(params) {
874
906
  this.recordToolCall({
875
907
  id: params.callId,
@@ -897,16 +929,21 @@ var CodexToolTranscriptProjection = class {
897
929
  });
898
930
  }
899
931
  recordNativeToolResult(item, details) {
900
- if (!item || !shouldRecordNativeToolTranscript(item)) return;
932
+ if (!item || !shouldRecordNativeToolTranscript(item) || this.resultIds.has(item.id)) return;
901
933
  const name = itemName(item);
902
- if (name) this.recordToolResult({
903
- id: item.id,
904
- name,
905
- text: this.rawNativeToolOutputByCallId.get(item.id) ?? itemTranscriptResultText(item, this.progress.outputTextByItem),
906
- isError: isNonSuccessItemStatus(itemStatus(item)),
907
- details,
908
- ...item.type === "webSearch" ? { resultContentSource: "network" } : {}
909
- });
934
+ if (name) {
935
+ const status = itemStatus(item);
936
+ const approvalTimeoutExplanation = this.progress.approvalTimeoutExplanation(item.id, status);
937
+ this.recordToolResult({
938
+ id: item.id,
939
+ name,
940
+ text: approvalTimeoutExplanation ?? this.rawNativeToolOutputByCallId.get(item.id) ?? itemTranscriptResultText(item, this.progress.outputTextByItem),
941
+ isError: isNonSuccessItemStatus(status),
942
+ details,
943
+ ...item.type === "webSearch" ? { resultContentSource: "network" } : {}
944
+ });
945
+ this.progress.approvalTimeoutKinds.delete(item.id);
946
+ }
910
947
  }
911
948
  recordRawNativeToolItem(item) {
912
949
  const type = typeof item.type === "string" ? item.type : void 0;
@@ -939,14 +976,18 @@ var CodexToolTranscriptProjection = class {
939
976
  } catch {
940
977
  return;
941
978
  }
942
- if (args) this.recordToolCall({
943
- id: callId,
944
- name: "apply_patch",
945
- arguments: args
946
- });
979
+ if (args) {
980
+ this.pendingRawPatchOutputIds.add(callId);
981
+ this.recordToolCall({
982
+ id: callId,
983
+ name: "apply_patch",
984
+ arguments: args
985
+ });
986
+ }
947
987
  return;
948
988
  }
949
989
  if (type !== "custom_tool_call_output" && type !== "function_call_output" || this.namesById.get(callId) !== "apply_patch" && !this.codeModeNativePatchInputsByCallId.has(callId)) return;
990
+ this.pendingRawPatchOutputIds.delete(callId);
950
991
  const text = typeof item.output === "string" ? item.output : Array.isArray(item.output) ? collectDynamicToolContentText(item.output) : "";
951
992
  if (!text.trim()) return;
952
993
  const codeModePatchInput = this.codeModeNativePatchInputsByCallId.get(callId);
@@ -985,11 +1026,24 @@ var CodexToolTranscriptProjection = class {
985
1026
  id: callId,
986
1027
  name: "apply_patch",
987
1028
  text,
988
- isError: result.isError === true
1029
+ isError: result.isError
989
1030
  }).content;
990
1031
  }
991
1032
  async recordNativeToolResultWithDetails(item) {
992
- this.recordNativeToolResult(item, await this.prepareNativeMcpAppResultDetails(item));
1033
+ const preparedDetails = await this.prepareNativeMcpAppResultDetails(item);
1034
+ const approvalReviewState = item ? this.approvalReviewsByCallId.get(item.id) : void 0;
1035
+ const reviewDetails = approvalReviewState ? {
1036
+ approvalReviews: approvalReviewState.reviews,
1037
+ approvalReviewOutcome: toolApprovalReviewOutcome(approvalReviewState)
1038
+ } : void 0;
1039
+ const details = reviewDetails ? isJsonObject(preparedDetails) ? {
1040
+ ...preparedDetails,
1041
+ ...reviewDetails
1042
+ } : {
1043
+ ...preparedDetails !== void 0 ? { toolDetails: preparedDetails } : {},
1044
+ ...reviewDetails
1045
+ } : preparedDetails;
1046
+ this.recordNativeToolResult(item, details);
993
1047
  }
994
1048
  async prepareNativeMcpAppResultDetails(item) {
995
1049
  if (!item || item.type !== "mcpToolCall" || itemStatus(item) === "running") return;
@@ -1025,7 +1079,7 @@ var CodexToolTranscriptProjection = class {
1025
1079
  }
1026
1080
  this.trajectoryResultIds.add(params.item.id);
1027
1081
  const toolResult = itemToolResult(params.item).result;
1028
- const output = itemOutputText(params.item, this.progress.outputTextByItem);
1082
+ const output = this.progress.approvalTimeoutExplanation(params.item.id, params.status) ?? itemOutputText(params.item, this.progress.outputTextByItem);
1029
1083
  this.options.trajectoryRecorder?.recordEvent("tool.result", {
1030
1084
  threadId: this.threadId,
1031
1085
  turnId: this.turnId,
@@ -1045,7 +1099,7 @@ var CodexToolTranscriptProjection = class {
1045
1099
  if (!name || status === "running") return;
1046
1100
  this.afterToolCallObservedItemIds.add(item.id);
1047
1101
  const result = itemToolResult(item).result;
1048
- const error = itemToolError(item, status, this.progress.outputTextByItem);
1102
+ const error = this.progress.approvalTimeoutExplanation(item.id, status) ?? itemToolError(item, status, this.progress.outputTextByItem);
1049
1103
  const startedAt = resolveStartedAtFromDurationMs(item.durationMs);
1050
1104
  const hookParams = {
1051
1105
  toolName: name,
@@ -1077,7 +1131,8 @@ var CodexToolTranscriptProjection = class {
1077
1131
  id,
1078
1132
  name
1079
1133
  }),
1080
- isError: true
1134
+ isError: true,
1135
+ details: { reason: "missing_tool_result" }
1081
1136
  });
1082
1137
  }
1083
1138
  for (const id of missingTrajectoryIds) {
@@ -1124,13 +1179,20 @@ var CodexToolTranscriptProjection = class {
1124
1179
  this.callIds.add(params.id);
1125
1180
  this.namesById.set(params.id, params.name);
1126
1181
  this.progress.recordTranscriptCall(params);
1127
- this.messages.push(attachCodexMirrorIdentity(this.createToolCallMessage(params), `${this.turnId}:tool:${params.id}:call`));
1182
+ const message = attachCodexMirrorIdentity(this.createToolCallMessage(params), `${this.turnId}:tool:${params.id}:call`);
1183
+ this.messages.push(message);
1184
+ this.options.checkpointMessage?.({ read: () => message });
1128
1185
  }
1129
1186
  recordToolResult(params) {
1130
1187
  if (!params.id || !params.name || this.resultIds.has(params.id)) return;
1131
1188
  this.resultIds.add(params.id);
1132
1189
  this.progress.recordTranscriptResult(params);
1133
- this.messages.push(attachCodexMirrorIdentity(this.createToolResultMessage(params), `${this.turnId}:tool:${params.id}:result`));
1190
+ const message = attachCodexMirrorIdentity(this.createToolResultMessage(params), `${this.turnId}:tool:${params.id}:result`);
1191
+ this.messages.push(message);
1192
+ this.options.checkpointMessage?.({
1193
+ read: () => message,
1194
+ ready: () => !this.pendingRawPatchOutputIds.has(params.id)
1195
+ });
1134
1196
  }
1135
1197
  recordMissingToolError(missingTranscriptIds, missingTrajectoryIds) {
1136
1198
  const firstMissingId = missingTranscriptIds.find((id) => Boolean(this.namesById.get(id))) ?? missingTrajectoryIds.find((id) => Boolean(this.trajectoryNamesById.get(id) ?? this.namesById.get(id)));
@@ -1139,7 +1201,6 @@ var CodexToolTranscriptProjection = class {
1139
1201
  if (!name) return;
1140
1202
  const item = this.trajectoryItemsById.get(firstMissingId);
1141
1203
  const meta = item ? itemMeta(item, this.progress.toolProgressDetailMode()) : this.progress.getToolMeta(firstMissingId)?.meta;
1142
- const actionFingerprint = item ? nativeToolActionFingerprint(item) : void 0;
1143
1204
  this.progress.setLastToolError({
1144
1205
  toolName: name,
1145
1206
  ...meta ? { meta } : {},
@@ -1147,8 +1208,7 @@ var CodexToolTranscriptProjection = class {
1147
1208
  id: firstMissingId,
1148
1209
  name
1149
1210
  }),
1150
- ...item && isMutatingNativeToolItem(item) ? { mutatingAction: true } : {},
1151
- ...actionFingerprint ? { actionFingerprint } : {}
1211
+ ...item && isMutatingNativeToolItem(item) ? { mutatingAction: true } : {}
1152
1212
  });
1153
1213
  }
1154
1214
  shouldEmitAfterToolCallObservation(item) {
@@ -1211,6 +1271,42 @@ function resolveStartedAtFromDurationMs(durationMs) {
1211
1271
  }
1212
1272
  //#endregion
1213
1273
  //#region extensions/codex/src/app-server/event-projector-events.ts
1274
+ /** Downstream event consumers must never corrupt the canonical Codex turn projection. */
1275
+ function emitCodexAgentEvent(params, event) {
1276
+ try {
1277
+ emitAgentEvent({
1278
+ runId: params.runId,
1279
+ stream: event.stream,
1280
+ data: event.data,
1281
+ ...params.sessionKey ? { sessionKey: params.sessionKey } : {}
1282
+ });
1283
+ } catch (error) {
1284
+ embeddedAgentLog.debug("codex app-server global agent event emit failed", { error });
1285
+ }
1286
+ try {
1287
+ const maybePromise = params.onAgentEvent?.(event);
1288
+ Promise.resolve(maybePromise).catch((error) => {
1289
+ embeddedAgentLog.debug("codex app-server agent event handler rejected", { error });
1290
+ });
1291
+ } catch (error) {
1292
+ embeddedAgentLog.debug("codex app-server agent event handler threw", { error });
1293
+ }
1294
+ }
1295
+ function guardianActionCommand(action) {
1296
+ if (!action) return;
1297
+ const directLabel = readStringField(action, "command") ?? readStringField(action, "target") ?? readStringField(action, "toolTitle") ?? readStringField(action, "reason");
1298
+ if (directLabel) return directLabel;
1299
+ const server = readStringField(action, "connectorName") ?? readStringField(action, "server");
1300
+ const tool = readStringField(action, "toolName");
1301
+ if (server && tool) return `${server}/${tool}`;
1302
+ const argv = Array.isArray(action.argv) ? action.argv.filter((value) => typeof value === "string") : [];
1303
+ return argv.length > 0 ? argv.join(" ") : readStringField(action, "program");
1304
+ }
1305
+ function normalizeApprovalReviewStatus(status) {
1306
+ return status === "inProgress" ? "in_progress" : status === "timedOut" ? "timed_out" : status;
1307
+ }
1308
+ const GUARDIAN_TIMEOUT_WARNING = "Automatic approval review timed out while evaluating the requested approval.";
1309
+ const LOG_ONLY_CODEX_WARNING_PATTERNS = [/^Configured service tier `[^`\r\n]+` is not advertised as supported for model `[^`\r\n]+` and will be omitted from requests\.$/, /^Code Mode is enabled in configuration, but model `[^`\r\n]+` does not advertise Code Mode support\. This may degrade model performance\. Disable `features\.code_mode` and `features\.code_mode_only`, or select a model whose metadata enables Code Mode\.$/];
1214
1310
  function projectNormalizedToolItem(params) {
1215
1311
  const { item } = params;
1216
1312
  if (!item || !shouldSynthesizeToolProgressForItem(item)) return;
@@ -1257,32 +1353,147 @@ var CodexEventProjection = class {
1257
1353
  get guardianReviewCount() {
1258
1354
  return this.reviewCount;
1259
1355
  }
1356
+ emitCompactionEnd(itemId, completed) {
1357
+ this.emitAgentEvent({
1358
+ stream: "compaction",
1359
+ data: {
1360
+ phase: "end",
1361
+ backend: "codex-app-server",
1362
+ completed,
1363
+ threadId: this.threadId,
1364
+ turnId: this.turnId,
1365
+ itemId
1366
+ }
1367
+ });
1368
+ }
1260
1369
  handleGuardianReview(method, params) {
1261
1370
  this.reviewCount += 1;
1262
1371
  const review = isJsonObject(params.review) ? params.review : void 0;
1263
1372
  const action = isJsonObject(params.action) ? params.action : void 0;
1373
+ const reviewId = readStringField(params, "reviewId");
1374
+ const targetItemId = readNullableString$1(params, "targetItemId");
1375
+ const command = guardianActionCommand(action);
1376
+ const reviewStatus = review ? readStringField(review, "status") : void 0;
1377
+ const status = normalizeApprovalReviewStatus(reviewStatus);
1378
+ const riskLevel = review ? readStringField(review, "riskLevel") : void 0;
1379
+ const userAuthorization = review ? readStringField(review, "userAuthorization") : void 0;
1380
+ const rationale = review ? readNullableString$1(review, "rationale") : void 0;
1381
+ const expectedWarning = status === "timed_out" ? GUARDIAN_TIMEOUT_WARNING : rationale && riskLevel && userAuthorization && (status === "approved" || status === "denied") ? `Automatic approval review ${status} (risk: ${riskLevel}, authorization: ${userAuthorization}): ${rationale}` : void 0;
1382
+ if (Boolean(targetItemId) && Boolean(reviewId) && this.pendingGuardianWarning === expectedWarning) this.pendingGuardianWarning = void 0;
1383
+ else this.flushPendingGuardianWarning();
1384
+ const threadId = readStringField(params, "threadId") ?? this.threadId;
1385
+ const turnId = readStringField(params, "turnId") ?? this.turnId;
1386
+ if (method.endsWith("/started")) this.activeGuardianReview = {
1387
+ reviewId,
1388
+ targetItemId,
1389
+ command,
1390
+ threadId,
1391
+ turnId
1392
+ };
1264
1393
  this.emitAgentEvent({
1265
1394
  stream: "codex_app_server.guardian",
1266
1395
  data: {
1267
1396
  method,
1268
1397
  phase: method.endsWith("/started") ? "started" : "completed",
1269
- reviewId: readStringField(params, "reviewId"),
1270
- targetItemId: readNullableString$1(params, "targetItemId"),
1398
+ threadId,
1399
+ turnId,
1400
+ reviewId,
1401
+ targetItemId,
1271
1402
  decisionSource: readStringField(params, "decisionSource"),
1272
- status: review ? readStringField(review, "status") : void 0,
1273
- riskLevel: review ? readStringField(review, "riskLevel") : void 0,
1274
- userAuthorization: review ? readStringField(review, "userAuthorization") : void 0,
1275
- rationale: review ? readNullableString$1(review, "rationale") : void 0,
1276
- actionType: action ? readStringField(action, "type") : void 0
1403
+ status: reviewStatus,
1404
+ riskLevel,
1405
+ userAuthorization,
1406
+ rationale,
1407
+ actionType: action ? readStringField(action, "type") : void 0,
1408
+ command
1277
1409
  }
1278
1410
  });
1411
+ if (reviewId && targetItemId && status) {
1412
+ const approvalReview = {
1413
+ id: reviewId,
1414
+ label: "Guardian",
1415
+ status,
1416
+ ...riskLevel ? { riskLevel } : {},
1417
+ ...userAuthorization ? { userAuthorization } : {},
1418
+ ...rationale ? { rationale } : {}
1419
+ };
1420
+ const approvalReviewOutcome = this.toolTranscript.recordToolApprovalReview(targetItemId, reviewId, status, approvalReview);
1421
+ this.emitAgentEvent({
1422
+ stream: "tool",
1423
+ data: {
1424
+ phase: "review",
1425
+ toolCallId: targetItemId,
1426
+ hideFromChannelProgress: true,
1427
+ approvalReviewOutcome,
1428
+ review: approvalReview
1429
+ }
1430
+ });
1431
+ }
1432
+ if (method.endsWith("/completed") && this.activeGuardianReview?.reviewId === reviewId) this.activeGuardianReview = void 0;
1279
1433
  }
1280
1434
  handleGuardianWarning(params) {
1435
+ this.flushPendingGuardianWarning();
1436
+ const message = readStringField(params, "message");
1437
+ if (message) {
1438
+ this.pendingGuardianWarning = message;
1439
+ return;
1440
+ }
1281
1441
  this.emitAgentEvent({
1282
1442
  stream: "codex_app_server.guardian",
1283
1443
  data: {
1284
1444
  phase: "warning",
1285
- message: readStringField(params, "message")
1445
+ message
1446
+ }
1447
+ });
1448
+ }
1449
+ handleWarning(params) {
1450
+ const message = [readStringField(params, "summary") ?? readStringField(params, "message"), readStringField(params, "details")].filter(Boolean).join("\n");
1451
+ if (LOG_ONLY_CODEX_WARNING_PATTERNS.some((pattern) => pattern.test(message))) embeddedAgentLog.warn(message);
1452
+ else if (message) this.emitAgentEvent({
1453
+ stream: "notice",
1454
+ data: {
1455
+ phase: "warning",
1456
+ message
1457
+ }
1458
+ });
1459
+ }
1460
+ handleModelRerouted(params) {
1461
+ const fromModel = readStringField(params, "fromModel");
1462
+ const toModel = readStringField(params, "toModel");
1463
+ const reason = readStringField(params, "reason");
1464
+ if (fromModel && toModel && fromModel !== toModel) this.emitAgentEvent({
1465
+ stream: "fallback",
1466
+ data: {
1467
+ fromModel,
1468
+ toModel,
1469
+ ...reason ? { reason } : {}
1470
+ }
1471
+ });
1472
+ }
1473
+ flushPendingGuardianWarning() {
1474
+ const pending = this.pendingGuardianWarning;
1475
+ if (!pending) return;
1476
+ this.pendingGuardianWarning = void 0;
1477
+ this.emitAgentEvent({
1478
+ stream: "codex_app_server.guardian",
1479
+ data: {
1480
+ phase: "warning",
1481
+ message: pending
1482
+ }
1483
+ });
1484
+ }
1485
+ handleStrictReviewRequired(params) {
1486
+ this.emitAgentEvent({
1487
+ stream: "codex_app_server.guardian",
1488
+ data: {
1489
+ method: "autoApprovalReview/strictReviewRequired",
1490
+ phase: "strict_review_required",
1491
+ threadId: readStringField(params, "threadId") ?? this.activeGuardianReview?.threadId ?? this.threadId,
1492
+ turnId: readStringField(params, "turnId") ?? this.activeGuardianReview?.turnId ?? this.turnId,
1493
+ reviewId: this.activeGuardianReview?.reviewId,
1494
+ targetItemId: this.activeGuardianReview?.targetItemId,
1495
+ command: this.activeGuardianReview?.command,
1496
+ startedAtMs: asFiniteNumber(params.startedAtMs)
1286
1497
  }
1287
1498
  });
1288
1499
  }
@@ -1344,6 +1555,8 @@ var CodexEventProjection = class {
1344
1555
  if (!projection || !params.item) return;
1345
1556
  const { item } = params;
1346
1557
  const { name, status, args, meta, event } = projection;
1558
+ const approvalReviewOutcome = params.phase === "result" ? this.toolTranscript.finalizeToolApprovalReviews(item.id) : void 0;
1559
+ if (event && approvalReviewOutcome) event.data.approvalReviewOutcome = approvalReviewOutcome;
1347
1560
  this.toolTranscript.recordTrajectoryEvent({
1348
1561
  phase: params.phase,
1349
1562
  item,
@@ -1408,8 +1621,23 @@ function extractCodexNativeSubagentCompletionsFromText(text) {
1408
1621
  }
1409
1622
  const codexNativeSubagentNotifications = {
1410
1623
  fromNotification: extractCodexNativeSubagentCompletions,
1411
- fromText: extractCodexNativeSubagentCompletionsFromText
1624
+ fromText: extractCodexNativeSubagentCompletionsFromText,
1625
+ deliveredAgentPaths: readDeliveredNativeCompletionPaths
1412
1626
  };
1627
+ /** Reads native delivery receipts, leaving status and result ownership with the child lifecycle. */
1628
+ function readDeliveredNativeCompletionPaths(notification) {
1629
+ if (notification.method !== "rawResponseItem/completed") return [];
1630
+ const params = isJsonObject(notification.params) ? notification.params : void 0;
1631
+ const item = isJsonObject(params?.item) ? params.item : void 0;
1632
+ if (!item || readStringField(item, "type") !== "agent_message") return extractCodexNativeSubagentCompletions(notification).map((completion) => completion.agentPath);
1633
+ const author = readStringField(item, "author");
1634
+ const recipient = readStringField(item, "recipient");
1635
+ const content = item.content;
1636
+ if (!author || !recipient || !Array.isArray(content) || content.length !== 1) return [];
1637
+ const part = content[0];
1638
+ if (!isJsonObject(part) || readStringField(part, "type") !== "input_text") return [];
1639
+ return readStringField(part, "text")?.startsWith(`Message Type: FINAL_ANSWER\nTask name: ${recipient}\nSender: ${author}\nPayload:\n`) ? [author] : [];
1640
+ }
1413
1641
  function parseCodexNativeSubagentNotificationBody(body) {
1414
1642
  let payload;
1415
1643
  try {
@@ -1957,7 +2185,8 @@ function registerMonitor(params) {
1957
2185
  taskRuntimeScope: params.taskRuntimeScope,
1958
2186
  agentId: params.agentId,
1959
2187
  claimDirectChild: params.claimDirectChild,
1960
- rejectPendingDirectChild: params.rejectPendingDirectChild
2188
+ rejectPendingDirectChild: params.rejectPendingDirectChild,
2189
+ onDirectChildAccepted: params.onDirectChildAccepted
1961
2190
  });
1962
2191
  }
1963
2192
  var Monitor = class {
@@ -2007,7 +2236,11 @@ var Monitor = class {
2007
2236
  this.releaseRetainedClient();
2008
2237
  for (const release of this.parentThreadRetentions.values()) release();
2009
2238
  this.parentThreadRetentions.clear();
2010
- for (const state of this.parentStates.values()) state.owners.clear();
2239
+ for (const state of this.parentStates.values()) {
2240
+ state.owners.clear();
2241
+ state.turnIds.clear();
2242
+ this.deliverDetachedCompletions(state);
2243
+ }
2011
2244
  this.pendingDirectSpawnEvidence.clear();
2012
2245
  for (const [parentThreadId] of this.parentStates) if (![...this.childStates.values()].some((childState) => childState.parentThreadId === parentThreadId)) this.parentStates.delete(parentThreadId);
2013
2246
  }
@@ -2020,7 +2253,9 @@ var Monitor = class {
2020
2253
  if (!state) {
2021
2254
  state = {
2022
2255
  parentThreadId,
2023
- owners: /* @__PURE__ */ new Map()
2256
+ owners: /* @__PURE__ */ new Map(),
2257
+ turnIds: /* @__PURE__ */ new Set(),
2258
+ nativeCompletionReceipts: /* @__PURE__ */ new Set()
2024
2259
  };
2025
2260
  this.parentStates.set(parentThreadId, state);
2026
2261
  }
@@ -2030,7 +2265,8 @@ var Monitor = class {
2030
2265
  const owner = Symbol("codex-native-subagent-owner");
2031
2266
  state.owners.set(owner, {
2032
2267
  claimDirectChild: params.claimDirectChild,
2033
- rejectPendingDirectChild: params.rejectPendingDirectChild
2268
+ rejectPendingDirectChild: params.rejectPendingDirectChild,
2269
+ onDirectChildAccepted: params.onDirectChildAccepted
2034
2270
  });
2035
2271
  this.prepareParentTaskRuntime(state);
2036
2272
  for (const childState of this.childStates.values()) if (childState.parentThreadId === parentThreadId && childState.pendingCompletion) this.deliverPendingCompletion(state, childState);
@@ -2049,6 +2285,7 @@ var Monitor = class {
2049
2285
  const current = registeredState.owners.get(owner);
2050
2286
  if (!current || [...registeredState.owners.values()].some((other) => other !== current && other.turnId === turnId)) return;
2051
2287
  current.turnId = turnId;
2288
+ registeredState.turnIds.add(turnId);
2052
2289
  this.drainPendingDirectSpawnEvidence(registeredState, current, turnId);
2053
2290
  this.clearUnconsumablePendingDirectSpawnEvidence();
2054
2291
  },
@@ -2057,8 +2294,15 @@ var Monitor = class {
2057
2294
  registered = false;
2058
2295
  const current = this.parentStates.get(parentThreadId);
2059
2296
  if (current === registeredState) {
2297
+ const turnId = current.owners.get(owner)?.turnId;
2060
2298
  current.owners.delete(owner);
2299
+ if (turnId) current.turnIds.delete(turnId);
2300
+ if (current.owners.size === 0) {
2301
+ current.turnIds.clear();
2302
+ current.nativeCompletionReceipts = /* @__PURE__ */ new Set();
2303
+ }
2061
2304
  this.clearUnconsumablePendingDirectSpawnEvidence();
2305
+ this.deliverDetachedCompletions(current);
2062
2306
  this.pruneParentIfUnused(current);
2063
2307
  }
2064
2308
  }
@@ -2096,6 +2340,11 @@ var Monitor = class {
2096
2340
  const startedThread = isJsonObject(params?.thread) ? params.thread : void 0;
2097
2341
  const threadId = readStringField(params, "threadId")?.trim() ?? readStringField(startedThread, "id")?.trim();
2098
2342
  const threadStatus = isJsonObject(params?.status) ? normalizeIdentifier(readStringField(params.status, "type")) : void 0;
2343
+ const parent = threadId ? this.parentStates.get(threadId) : void 0;
2344
+ if (parent && parent.owners.size > 0 && notification.method === "turn/started") {
2345
+ const turnId = isJsonObject(params?.turn) ? readStringField(params.turn, "id") : void 0;
2346
+ if (turnId) parent.turnIds.add(turnId);
2347
+ }
2099
2348
  const tracksRecoveryRevision = Boolean(threadId && this.threadStatusRevisions.has(threadId));
2100
2349
  if (RECOVERY_REVISION_NOTIFICATION_METHODS.has(notification.method) && threadId && tracksRecoveryRevision) this.threadStatusRevisions.get(threadId).value += 1;
2101
2350
  if (!state && (!threadId || !this.parentStates.has(threadId) && !this.childStates.has(threadId) && !tracksRecoveryRevision)) return;
@@ -2109,8 +2358,13 @@ var Monitor = class {
2109
2358
  }
2110
2359
  if (state) this.handleClosedChild(notification, state);
2111
2360
  const childState = threadId ? this.childStates.get(threadId) : void 0;
2112
- if (notification.method === "turn/started" && childState) this.resumeChild(childState);
2113
- if (childState && !childState.terminal) this.emitChildTaskActivity(notification, childState.childThreadId);
2361
+ if (notification.method === "turn/started" && childState) {
2362
+ childState.nativeCompletionDelivered = false;
2363
+ for (const key of childState.agentPathKeys) state?.nativeCompletionReceipts.delete(key);
2364
+ this.resumeChild(childState);
2365
+ }
2366
+ if (parent && parent.turnIds.has(readStringField(params, "turnId") ?? "")) this.recordNativeCompletionDelivery(parent, notification);
2367
+ if (childState && !childState.terminal) this.emitChildTaskActivity(notification, childState);
2114
2368
  this.captureChildAssistantMessage(notification);
2115
2369
  await this.handleChildTurnCompletion(notification);
2116
2370
  if (notification.method === "thread/status/changed" && threadId && threadStatus) if (threadStatus !== "systemerror") {
@@ -2129,14 +2383,17 @@ var Monitor = class {
2129
2383
  }
2130
2384
  await this.handleCompletionNotification(notification);
2131
2385
  }
2132
- emitChildTaskActivity(notification, childThreadId) {
2386
+ emitChildTaskActivity(notification, childState) {
2133
2387
  const params = isJsonObject(notification.params) ? notification.params : void 0;
2134
2388
  if (!params) return;
2135
- const runId = codexNativeSubagentRunId(childThreadId);
2389
+ const owner = {
2390
+ runId: codexNativeSubagentRunId(childState.childThreadId),
2391
+ ...childState.agentId ? { agentId: childState.agentId } : {}
2392
+ };
2136
2393
  if (notification.method === "item/agentMessage/delta") {
2137
2394
  const delta = readStringField(params, "delta");
2138
2395
  if (delta) emitAgentEvent({
2139
- runId,
2396
+ ...owner,
2140
2397
  stream: "assistant",
2141
2398
  data: { delta }
2142
2399
  });
@@ -2145,7 +2402,7 @@ var Monitor = class {
2145
2402
  if (notification.method === "item/reasoning/summaryTextDelta") {
2146
2403
  const delta = readStringField(params, "delta");
2147
2404
  if (delta) emitAgentEvent({
2148
- runId,
2405
+ ...owner,
2149
2406
  stream: "thinking",
2150
2407
  data: { delta }
2151
2408
  });
@@ -2154,7 +2411,7 @@ var Monitor = class {
2154
2411
  if (notification.method !== "item/started" && notification.method !== "item/completed") return;
2155
2412
  const item = readItem(params.item);
2156
2413
  if (item?.type === "agentMessage" && notification.method === "item/completed" && item.text) emitAgentEvent({
2157
- runId,
2414
+ ...owner,
2158
2415
  stream: "assistant",
2159
2416
  data: { text: item.text }
2160
2417
  });
@@ -2163,7 +2420,7 @@ var Monitor = class {
2163
2420
  item
2164
2421
  });
2165
2422
  if (projection?.event) emitAgentEvent({
2166
- runId,
2423
+ ...owner,
2167
2424
  ...projection.event
2168
2425
  });
2169
2426
  }
@@ -2287,7 +2544,7 @@ var Monitor = class {
2287
2544
  const childThreadId = thread ? readStringField(thread, "id")?.trim() : void 0;
2288
2545
  const agentPath = readStringField(readThreadSpawnSource(thread), "agent_path")?.trim();
2289
2546
  const state = parentThreadId ? this.parentStates.get(parentThreadId) : void 0;
2290
- if (state && childThreadId && parentThreadId) return this.registerChildThread(parentThreadId, childThreadId, agentPath === void 0 ? {} : { agentPath }) ? state : void 0;
2547
+ if (state && childThreadId && parentThreadId) return this.registerChildThread(state, childThreadId, agentPath === void 0 ? {} : { agentPath }) ? state : void 0;
2291
2548
  return state;
2292
2549
  }
2293
2550
  if (notification.method === "thread/status/changed" || notification.method === "turn/started" || notification.method === "turn/completed" || notification.method === "item/agentMessage/delta") {
@@ -2319,7 +2576,7 @@ var Monitor = class {
2319
2576
  for (const childThreadId of childThreadIds) accepted = Boolean(isCompletedSpawnAgentTool ? this.registerDirectSpawnChild(state, turnId, {
2320
2577
  parentThreadId,
2321
2578
  childThreadId
2322
- }, owner) : this.registerChildThread(parentThreadId, childThreadId)) && accepted;
2579
+ }, owner) : this.registerChildThread(state, childThreadId)) && accepted;
2323
2580
  if (!accepted) return;
2324
2581
  }
2325
2582
  return state;
@@ -2418,6 +2675,7 @@ var Monitor = class {
2418
2675
  this.unregisterChild(childState);
2419
2676
  return false;
2420
2677
  }
2678
+ if (recovery.agentPath) this.registerAgentPath(childState, recovery.agentPath);
2421
2679
  if (recovery.threadState === "active") {
2422
2680
  this.observeActiveChild(childState);
2423
2681
  return false;
@@ -2483,6 +2741,7 @@ var Monitor = class {
2483
2741
  }
2484
2742
  return {
2485
2743
  parentThreadId: readThreadParentThreadId(thread),
2744
+ agentPath: normalizeOptionalString(readStringField(readThreadSpawnSource(thread), "agent_path")),
2486
2745
  completion,
2487
2746
  fallbackCompletion,
2488
2747
  resumable,
@@ -2514,6 +2773,10 @@ var Monitor = class {
2514
2773
  this.unregisterChild(childState);
2515
2774
  return;
2516
2775
  }
2776
+ if (childState.nativeCompletionDelivered) {
2777
+ this.finishCompletionDelivery(state, childState);
2778
+ return;
2779
+ }
2517
2780
  childState.pendingCompletion = completion;
2518
2781
  state.taskRuntime?.setDetachedTaskDeliveryStatusByRunId({
2519
2782
  runId: codexNativeSubagentRunId(completion.childThreadId),
@@ -2525,6 +2788,7 @@ var Monitor = class {
2525
2788
  async deliverPendingCompletion(state, childState) {
2526
2789
  const completion = childState.pendingCompletion;
2527
2790
  if (!completion || !state.requesterSessionKey || !state.taskRuntimeScope) return;
2791
+ if (state.owners.size > 0) return;
2528
2792
  if (childState.deliveringCompletion || childState.completionDeliveryTimer) return;
2529
2793
  childState.deliveringCompletion = true;
2530
2794
  try {
@@ -2542,13 +2806,7 @@ var Monitor = class {
2542
2806
  });
2543
2807
  if (this.childStates.get(childState.childThreadId) !== childState || this.parentStates.get(state.parentThreadId) !== state) return;
2544
2808
  if (isDurableAgentHarnessCompletionDelivery(delivery)) {
2545
- childState.pendingCompletion = void 0;
2546
- childState.completionDeliveryAttempt = 0;
2547
- state.taskRuntime?.setDetachedTaskDeliveryStatusByRunId({
2548
- runId: codexNativeSubagentRunId(completion.childThreadId),
2549
- deliveryStatus: "delivered"
2550
- });
2551
- this.unregisterChild(childState);
2809
+ this.finishCompletionDelivery(state, childState);
2552
2810
  return;
2553
2811
  }
2554
2812
  const error = delivery.error ?? "completion delivery did not produce a parent response";
@@ -2576,6 +2834,29 @@ var Monitor = class {
2576
2834
  childState.deliveringCompletion = false;
2577
2835
  }
2578
2836
  }
2837
+ recordNativeCompletionDelivery(state, notification) {
2838
+ for (const agentPath of codexNativeSubagentNotifications.deliveredAgentPaths(notification)) {
2839
+ const key = buildParentAgentPathKey(state.parentThreadId, agentPath);
2840
+ state.nativeCompletionReceipts.add(key);
2841
+ const childThreadId = this.childThreadIdsByAgentPath.get(key);
2842
+ const child = childThreadId ? this.childStates.get(childThreadId) : void 0;
2843
+ if (!child || child.parentThreadId !== state.parentThreadId) continue;
2844
+ child.nativeCompletionDelivered = true;
2845
+ if (child.pendingCompletion && !child.deliveringCompletion) this.finishCompletionDelivery(state, child);
2846
+ }
2847
+ }
2848
+ finishCompletionDelivery(state, child) {
2849
+ child.pendingCompletion = void 0;
2850
+ child.completionDeliveryAttempt = 0;
2851
+ state.taskRuntime?.setDetachedTaskDeliveryStatusByRunId({
2852
+ runId: codexNativeSubagentRunId(child.childThreadId),
2853
+ deliveryStatus: "delivered"
2854
+ });
2855
+ this.unregisterChild(child);
2856
+ }
2857
+ deliverDetachedCompletions(state) {
2858
+ for (const child of this.childStates.values()) if (child.parentThreadId === state.parentThreadId && child.pendingCompletion) this.deliverPendingCompletion(state, child);
2859
+ }
2579
2860
  scheduleCompletionDeliveryRetry(childState, error) {
2580
2861
  if (!childState.pendingCompletion || childState.completionDeliveryTimer || this.childStates.get(childState.childThreadId) !== childState) return;
2581
2862
  if (childState.completionDeliveryAttempt >= this.completionDeliveryMaxRetries) {
@@ -2596,8 +2877,8 @@ var Monitor = class {
2596
2877
  }, delayMs);
2597
2878
  unrefTimer(childState.completionDeliveryTimer);
2598
2879
  }
2599
- registerChildThread(parentThreadIdInput, childThreadIdInput, options = {}) {
2600
- const parentThreadId = parentThreadIdInput.trim();
2880
+ registerChildThread(state, childThreadIdInput, options = {}) {
2881
+ const parentThreadId = state.parentThreadId;
2601
2882
  const childThreadId = childThreadIdInput.trim();
2602
2883
  if (!parentThreadId || !childThreadId || this.disposed) return;
2603
2884
  if (options.claimDirectChild && this.threadStatusRevisions.get(childThreadId)?.terminal) return;
@@ -2620,10 +2901,12 @@ var Monitor = class {
2620
2901
  childState = {
2621
2902
  childThreadId,
2622
2903
  parentThreadId,
2904
+ agentId: state.agentId,
2623
2905
  agentPathKeys: /* @__PURE__ */ new Set(),
2624
2906
  assistantMessagesByTurn: /* @__PURE__ */ new Map(),
2625
2907
  recoveryAttempt: 0,
2626
2908
  terminal: false,
2909
+ nativeCompletionDelivered: false,
2627
2910
  settledWithoutCompletion: false,
2628
2911
  completionDeliveryAttempt: 0,
2629
2912
  deliveringCompletion: false
@@ -2637,7 +2920,7 @@ var Monitor = class {
2637
2920
  }
2638
2921
  if (options.claimDirectChild && !childState.terminal && !childState.settledWithoutCompletion && !childState.releaseDirectChild) childState.releaseDirectChild = options.claimDirectChild(childThreadId);
2639
2922
  this.registerAgentPath(childState, childThreadId);
2640
- this.parentStates.get(parentThreadId)?.mirror?.markAuthoritativeCompletionExpected(childThreadId);
2923
+ state.mirror?.markAuthoritativeCompletionExpected(childThreadId);
2641
2924
  const agentPath = normalizeOptionalString(options.agentPath);
2642
2925
  if (agentPath) this.registerAgentPath(childState, agentPath);
2643
2926
  this.scheduleRecoveryPoll(childState);
@@ -2650,11 +2933,12 @@ var Monitor = class {
2650
2933
  return owners.length === 1 ? owners[0] : void 0;
2651
2934
  }
2652
2935
  registerDirectSpawnChild(state, turnIdInput, evidence, owner) {
2653
- const childState = this.registerChildThread(state.parentThreadId, evidence.childThreadId, {
2936
+ const childState = this.registerChildThread(state, evidence.childThreadId, {
2654
2937
  ...evidence.agentPath === void 0 ? {} : { agentPath: evidence.agentPath },
2655
2938
  ...owner?.claimDirectChild ? { claimDirectChild: owner.claimDirectChild } : {}
2656
2939
  });
2657
2940
  if (!owner) this.bufferPendingDirectSpawnEvidence(turnIdInput, evidence);
2941
+ else if (childState) owner.onDirectChildAccepted?.();
2658
2942
  return childState;
2659
2943
  }
2660
2944
  bufferPendingDirectSpawnEvidence(turnIdInput, evidence) {
@@ -2669,10 +2953,12 @@ var Monitor = class {
2669
2953
  const pending = this.pendingDirectSpawnEvidence.get(turnId);
2670
2954
  this.pendingDirectSpawnEvidence.delete(turnId);
2671
2955
  if (!pending || !owner.claimDirectChild) return;
2672
- for (const evidence of pending) if (evidence.parentThreadId === state.parentThreadId) this.registerChildThread(state.parentThreadId, evidence.childThreadId, {
2673
- ...evidence.agentPath === void 0 ? {} : { agentPath: evidence.agentPath },
2674
- claimDirectChild: owner.claimDirectChild
2675
- });
2956
+ for (const evidence of pending) if (evidence.parentThreadId === state.parentThreadId) {
2957
+ if (this.registerChildThread(state, evidence.childThreadId, {
2958
+ ...evidence.agentPath === void 0 ? {} : { agentPath: evidence.agentPath },
2959
+ claimDirectChild: owner.claimDirectChild
2960
+ })) owner.onDirectChildAccepted?.();
2961
+ }
2676
2962
  }
2677
2963
  hasUnboundParentOwner(parentThreadId) {
2678
2964
  return [...parentThreadId ? [this.parentStates.get(parentThreadId)].filter((state) => Boolean(state)) : this.parentStates.values()].some((state) => [...state.owners.values()].some((owner) => owner.turnId === void 0));
@@ -2707,6 +2993,7 @@ var Monitor = class {
2707
2993
  }
2708
2994
  this.childThreadIdsByAgentPath.set(key, childState.childThreadId);
2709
2995
  childState.agentPathKeys.add(key);
2996
+ if (this.parentStates.get(childState.parentThreadId)?.nativeCompletionReceipts.has(key)) childState.nativeCompletionDelivered = true;
2710
2997
  }
2711
2998
  unregisterChild(childState, options = {}) {
2712
2999
  this.releaseDirectChild(childState);
@@ -2856,6 +3143,7 @@ var Monitor = class {
2856
3143
  const childThreadId = task.runId.slice(13).trim();
2857
3144
  candidates.set(childThreadId, {
2858
3145
  parentState: state,
3146
+ nativeCompletionReceipts: state.nativeCompletionReceipts,
2859
3147
  requesterSessionKey: state.requesterSessionKey,
2860
3148
  childThreadId,
2861
3149
  recoveryAttempt: 0,
@@ -2932,6 +3220,8 @@ var Monitor = class {
2932
3220
  state = {
2933
3221
  parentThreadId,
2934
3222
  owners: /* @__PURE__ */ new Map(),
3223
+ turnIds: /* @__PURE__ */ new Set(),
3224
+ nativeCompletionReceipts: /* @__PURE__ */ new Set(),
2935
3225
  requesterSessionKey: candidate.requesterSessionKey,
2936
3226
  taskRuntimeScope: candidate.taskRuntimeScope,
2937
3227
  agentId: candidate.agentId,
@@ -2940,11 +3230,12 @@ var Monitor = class {
2940
3230
  this.prepareParentTaskRuntime(state);
2941
3231
  this.parentStates.set(parentThreadId, state);
2942
3232
  }
2943
- const childState = this.registerChildThread(parentThreadId, candidate.childThreadId);
3233
+ const childState = this.registerChildThread(state, candidate.childThreadId, recovery.agentPath ? { agentPath: recovery.agentPath } : {});
2944
3234
  if (!childState) {
2945
3235
  this.pruneParentIfUnused(state);
2946
3236
  return;
2947
3237
  }
3238
+ if ([...childState.agentPathKeys].some((key) => candidate.nativeCompletionReceipts.has(key))) childState.nativeCompletionDelivered = true;
2948
3239
  if (recovery.threadState === "active") this.observeActiveChild(childState);
2949
3240
  if (recovery.threadState === "other") this.clearSystemErrorFallback(childState);
2950
3241
  if (recovery.resumable) {
@@ -3108,4 +3399,4 @@ function unrefTimer(timer) {
3108
3399
  if (typeof timer === "object" && timer && "unref" in timer) timer.unref();
3109
3400
  }
3110
3401
  //#endregion
3111
- export { CodexToolProgressProjection as a, isCodexCommandBearingToolCall as c, sanitizeCodexToolResponse as d, readCodexMirroredSessionHistoryMessages as i, resolveCodexToolProgressDetailMode as l, CodexEventProjection as n, shouldEmitTranscriptToolProgress as o, CodexToolTranscriptProjection as r, inferCodexDynamicToolMeta as s, codexNativeSubagentMonitorRuntime as t, sanitizeCodexToolArguments as u };
3402
+ export { readCodexMirroredSessionHistoryMessages as a, inferCodexDynamicToolMeta as c, sanitizeCodexToolArguments as d, sanitizeCodexToolResponse as f, CodexToolTranscriptProjection as i, isCodexCommandBearingToolCall as l, CodexEventProjection as n, CodexToolProgressProjection as o, emitCodexAgentEvent as r, shouldEmitTranscriptToolProgress as s, codexNativeSubagentMonitorRuntime as t, resolveCodexToolProgressDetailMode as u };