@openclaw/codex 2026.8.1-beta.2 → 2026.8.1-beta.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/dist/api.js +147 -0
  2. package/dist/app-server-policy-bg5QPSVP.js +25 -0
  3. package/dist/{attempt-client-cleanup-DMLXUfa8.js → attempt-client-cleanup-URjUlCHg.js} +1 -1
  4. package/dist/{binding-connection-I5Bo-AsX.js → binding-connection-DAvZwp96.js} +15 -3
  5. package/dist/{bounded-turn-qgZmzy_4.js → bounded-turn-4BjrZEwW.js} +22 -16
  6. package/dist/{capabilities-CybGI1oz.js → capabilities-CH3K57v4.js} +1 -1
  7. package/dist/cli-metadata.js +1 -1
  8. package/dist/{command-formatters-B1AEz8ZA.js → command-formatters-D0nZ3qtd.js} +2 -2
  9. package/dist/{command-handlers-Db8pu_ds.js → command-handlers-DC86lgT4.js} +39 -22
  10. package/dist/command-rpc-xUIIonsO.js +90 -0
  11. package/dist/{compact-LspQaGfl.js → compact-COqgBRny.js} +35 -29
  12. package/dist/{session-binding-DPxIvMgE.js → config-CpNeo5AE.js} +28 -888
  13. package/dist/context-compaction-activity-BOeJf7yo.js +58 -0
  14. package/dist/doctor-contract-api.js +15 -14
  15. package/dist/{dynamic-tools-BVdyWkUD.js → dynamic-tools-fJZhl4CE.js} +1284 -651
  16. package/dist/{effective-mcp-catalog-DIIhAtOZ.js → effective-mcp-catalog-4YKn51aG.js} +2 -2
  17. package/dist/elicitation-input-DMkeki8d.js +71 -0
  18. package/dist/{event-projector-usage-e5huIQWu.js → event-projector-usage-CLwNEJqW.js} +16 -16
  19. package/dist/harness-DoKQcF8n.js +258 -0
  20. package/dist/harness.js +2 -226
  21. package/dist/index.js +171 -48
  22. package/dist/{isolated-completion-C58NbL40.js → isolated-completion-DPMtlH9r.js} +3 -3
  23. package/dist/managed-binary-By4FZC6i.js +212 -0
  24. package/dist/media-understanding-provider.js +2 -2
  25. package/dist/model-catalog-CmGoqVKB.js +48 -0
  26. package/dist/{models-BFlpn1Ex.js → models-CZw1wClT.js} +2 -2
  27. package/dist/{native-subagent-monitor-DyTGmTUx.js → native-subagent-monitor-GGq3RnOo.js} +185 -71
  28. package/dist/node-exec-server.runtime-Bsu1LdFZ.js +192 -0
  29. package/dist/{plugin-app-cache-key-C3H2CVp6.js → plugin-app-cache-key-DMNQ8Zi8.js} +15 -3
  30. package/dist/plugin-approval-roundtrip-C75Yiiwc.js +95 -0
  31. package/dist/{plugin-marketplace-discovery-CzrGJdCR.js → plugin-marketplace-discovery-CSWDkMrP.js} +40 -26
  32. package/dist/{plugin-metadata-cache-CNJPj4_b.js → plugin-metadata-cache-BXH5NF-4.js} +8 -5
  33. package/dist/{protocol-validators-B4F7L8Rf.js → protocol-validators-VAVyEnDp.js} +55 -2
  34. package/dist/{rate-limits-DZXmOL8-.js → rate-limits-BI1dMHDG.js} +1 -1
  35. package/dist/{request-BRl5_UfX.js → request-DSK0W6YI.js} +2 -2
  36. package/dist/{run-attempt-P8BdxC1I.js → run-attempt-BV3HzuCf.js} +1098 -666
  37. package/dist/{runtime-artifact-BVSPdd6g.js → runtime-artifact-BvyT1uyd.js} +4 -7
  38. package/dist/{sandbox-guard-Cmwc9eIk.js → sandbox-guard-C1qEeZ5C.js} +25 -19
  39. package/dist/session-binding-BTrLf9Qm.js +874 -0
  40. package/dist/{session-catalog-xwNi_SDM.js → session-catalog-ezP_UcRM.js} +1541 -1296
  41. package/dist/session-catalog-home-id-BNwAJ9D7.js +18 -0
  42. package/dist/{session-cli-7hgXZDV7.js → session-cli-B1hKvfkI.js} +20 -7
  43. package/dist/{session-retirement-DoMMJFKm.js → session-retirement-CE4iMiLh.js} +3 -3
  44. package/dist/{session-upstream-marker-CrIFX06J.js → session-upstream-marker-D_2npHlA.js} +1 -1
  45. package/dist/{settled-turn-finalizer-BRWBO4MO.js → settled-turn-finalizer-Dx1onIqg.js} +23 -19
  46. package/dist/{shared-client-kIBbGjk4.js → shared-client-Dw-rzii0.js} +755 -273
  47. package/dist/{side-question-9HAL26l9.js → side-question-DbXkJZzg.js} +52 -30
  48. package/dist/{thread-lifecycle-Bu1BTDXr.js → thread-lifecycle-DKdrnTMX.js} +310 -92
  49. package/dist/{thread-ownership-6kOQHlyC.js → thread-ownership-i2NBwDUL.js} +2 -2
  50. package/dist/{thread-resume-CPrJNQVM.js → thread-resume-CdJk2Ehf.js} +3 -3
  51. package/dist/{transcript-mirror-B9gGgnJS.js → transcript-mirror-BU0_LKAL.js} +46 -28
  52. package/dist/{transport-stdio-DIImwDVS.js → transport-stdio-DhoGy33Z.js} +2 -2
  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-BDVJCLAD.js} +12 -6
  55. package/dist/{usage-CHlV0e-o.js → usage-9dKJCgcy.js} +3 -3
  56. package/dist/{web-search-provider.runtime-DRw2Vl42.js → web-search-provider.runtime-DCdx4DGu.js} +3 -3
  57. package/openclaw.plugin.json +31 -1
  58. package/package.json +6 -5
  59. package/dist/app-server-policy-zcBDc1JU.js +0 -49
@@ -0,0 +1,48 @@
1
+ import { r as buildCodexRuntimeModelParams } from "./harness-DoKQcF8n.js";
2
+ import { h as readCodexPluginConfig } from "./config-CpNeo5AE.js";
3
+ import { t as listAllCodexAppServerModels } from "./models-CZw1wClT.js";
4
+ import { r as requestOptions } from "./command-rpc-xUIIonsO.js";
5
+ //#region extensions/codex/src/app-server/model-catalog.ts
6
+ const OPENAI_CODEX_BASE_URL = "https://chatgpt.com/backend-api/codex";
7
+ const DEFAULT_MODEL_DISCOVERY_TIMEOUT_MS = 2500;
8
+ const INPUT_TYPES = /* @__PURE__ */ new Set([
9
+ "text",
10
+ "image",
11
+ "audio",
12
+ "video",
13
+ "document"
14
+ ]);
15
+ function isModelInputType(value) {
16
+ return INPUT_TYPES.has(value);
17
+ }
18
+ function codexAppServerModelsToCatalogEntries(models) {
19
+ return models.map((model, providerOrder) => {
20
+ const input = model.inputModalities.filter(isModelInputType);
21
+ const runtimeParams = buildCodexRuntimeModelParams(model.id, model.model);
22
+ return {
23
+ provider: "openai",
24
+ id: model.id,
25
+ name: model.displayName ?? model.id,
26
+ providerOrder,
27
+ api: "openai-chatgpt-responses",
28
+ baseUrl: OPENAI_CODEX_BASE_URL,
29
+ reasoning: model.supportedReasoningEfforts.length > 0,
30
+ ...input.length > 0 ? { input } : {},
31
+ ...runtimeParams ? { params: runtimeParams } : {},
32
+ compat: {
33
+ supportsReasoningEffort: model.supportedReasoningEfforts.length > 0,
34
+ supportedReasoningEfforts: model.supportedReasoningEfforts
35
+ }
36
+ };
37
+ });
38
+ }
39
+ async function loadCodexAppServerModelCatalog(params, pluginConfig) {
40
+ const discovery = readCodexPluginConfig(pluginConfig).discovery;
41
+ if (discovery?.enabled === false) return [];
42
+ return codexAppServerModelsToCatalogEntries((await listAllCodexAppServerModels({
43
+ ...requestOptions(pluginConfig, 100, params.config, params.agentDir),
44
+ timeoutMs: discovery?.timeoutMs ?? DEFAULT_MODEL_DISCOVERY_TIMEOUT_MS
45
+ })).models);
46
+ }
47
+ //#endregion
48
+ export { loadCodexAppServerModelCatalog };
@@ -1,4 +1,4 @@
1
- import { t as assertCodexModelListResponse } from "./protocol-validators-B4F7L8Rf.js";
1
+ import { t as assertCodexModelListResponse } from "./protocol-validators-VAVyEnDp.js";
2
2
  import { normalizeOptionalString, uniqueStrings } from "openclaw/plugin-sdk/string-coerce-runtime";
3
3
  //#region extensions/codex/src/app-server/models.ts
4
4
  /**
@@ -40,7 +40,7 @@ async function listAllCodexAppServerModels(options = {}) {
40
40
  async function withCodexAppServerModelClient(options, run) {
41
41
  const timeoutMs = options.timeoutMs ?? 2500;
42
42
  const useSharedClient = options.sharedClient !== false;
43
- const { createIsolatedCodexAppServerClient, getLeasedSharedCodexAppServerClient, releaseLeasedSharedCodexAppServerClient } = await import("./shared-client-kIBbGjk4.js").then((n) => n.m);
43
+ const { createIsolatedCodexAppServerClient, getLeasedSharedCodexAppServerClient, releaseLeasedSharedCodexAppServerClient } = await import("./shared-client-Dw-rzii0.js").then((n) => n.m);
44
44
  const client = useSharedClient ? await getLeasedSharedCodexAppServerClient({
45
45
  startOptions: options.startOptions,
46
46
  timeoutMs,
@@ -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 { H as claimCodexAppServerLiveThread, J as releaseCodexAppServerLiveThread, Y as retainCodexAppServerLiveThread, ut as isJsonObject } from "./shared-client-Dw-rzii0.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-URjUlCHg.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-C75Yiiwc.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";
@@ -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
  }
@@ -819,6 +815,10 @@ const MISSING_TOOL_RESULT_ERROR = "OpenClaw recorded a native Codex tool.call wi
819
815
  const NATIVE_PATCH_REJECTION_RE = /^\s*patch rejected:\s*writing outside of the project;\s*rejected by user approval settings\s*$/iu;
820
816
  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
817
  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;
818
+ const MAX_TOOL_APPROVAL_REVIEWS = 16;
819
+ function toolApprovalReviewOutcome(state) {
820
+ return state.denied ? "denied" : state.unresolvedReviewIds === null || state.unresolvedReviewIds.size > 0 ? "reviewing" : "approved";
821
+ }
822
822
  function readCodeModeNativePatchInput(source) {
823
823
  if (typeof source !== "string") return;
824
824
  const match = CODE_MODE_NATIVE_PATCH_SOURCE_RE.exec(source);
@@ -864,12 +864,37 @@ var CodexToolTranscriptProjection = class {
864
864
  this.afterToolCallObservedItemIds = /* @__PURE__ */ new Set();
865
865
  this.nativeMcpAppResultDetails = /* @__PURE__ */ new Map();
866
866
  this.nativeMcpAppResultDetailsAttempted = /* @__PURE__ */ new Set();
867
+ this.approvalReviewsByCallId = /* @__PURE__ */ new Map();
867
868
  this.rawNativeToolOutputByCallId = /* @__PURE__ */ new Map();
868
869
  this.codeModeNativePatchInputsByCallId = /* @__PURE__ */ new Map();
869
870
  }
870
871
  get transcriptMessages() {
871
872
  return this.messages;
872
873
  }
874
+ recordToolApprovalReview(toolCallId, reviewId, status, review) {
875
+ const state = this.approvalReviewsByCallId.get(toolCallId) ?? {
876
+ reviews: [],
877
+ denied: false,
878
+ unresolvedReviewIds: /* @__PURE__ */ new Set()
879
+ };
880
+ state.reviews = [...state.reviews.filter((candidate) => candidate.id !== reviewId), review].slice(-16);
881
+ state.denied ||= [
882
+ "denied",
883
+ "timed_out",
884
+ "aborted"
885
+ ].includes(status);
886
+ const unresolved = state.unresolvedReviewIds;
887
+ if (status === "in_progress") state.unresolvedReviewIds = unresolved && (unresolved.size < MAX_TOOL_APPROVAL_REVIEWS || unresolved.has(reviewId)) ? unresolved.add(reviewId) : null;
888
+ else unresolved?.delete(reviewId);
889
+ this.approvalReviewsByCallId.set(toolCallId, state);
890
+ return toolApprovalReviewOutcome(state);
891
+ }
892
+ finalizeToolApprovalReviews(toolCallId) {
893
+ const state = this.approvalReviewsByCallId.get(toolCallId);
894
+ if (!state) return;
895
+ state.unresolvedReviewIds = /* @__PURE__ */ new Set();
896
+ return toolApprovalReviewOutcome(state);
897
+ }
873
898
  recordDynamicToolCall(params) {
874
899
  this.recordToolCall({
875
900
  id: params.callId,
@@ -897,16 +922,21 @@ var CodexToolTranscriptProjection = class {
897
922
  });
898
923
  }
899
924
  recordNativeToolResult(item, details) {
900
- if (!item || !shouldRecordNativeToolTranscript(item)) return;
925
+ if (!item || !shouldRecordNativeToolTranscript(item) || this.resultIds.has(item.id)) return;
901
926
  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
- });
927
+ if (name) {
928
+ const status = itemStatus(item);
929
+ const approvalTimeoutExplanation = this.progress.approvalTimeoutExplanation(item.id, status);
930
+ this.recordToolResult({
931
+ id: item.id,
932
+ name,
933
+ text: approvalTimeoutExplanation ?? this.rawNativeToolOutputByCallId.get(item.id) ?? itemTranscriptResultText(item, this.progress.outputTextByItem),
934
+ isError: isNonSuccessItemStatus(status),
935
+ details,
936
+ ...item.type === "webSearch" ? { resultContentSource: "network" } : {}
937
+ });
938
+ this.progress.approvalTimeoutKinds.delete(item.id);
939
+ }
910
940
  }
911
941
  recordRawNativeToolItem(item) {
912
942
  const type = typeof item.type === "string" ? item.type : void 0;
@@ -985,11 +1015,24 @@ var CodexToolTranscriptProjection = class {
985
1015
  id: callId,
986
1016
  name: "apply_patch",
987
1017
  text,
988
- isError: result.isError === true
1018
+ isError: result.isError
989
1019
  }).content;
990
1020
  }
991
1021
  async recordNativeToolResultWithDetails(item) {
992
- this.recordNativeToolResult(item, await this.prepareNativeMcpAppResultDetails(item));
1022
+ const preparedDetails = await this.prepareNativeMcpAppResultDetails(item);
1023
+ const approvalReviewState = item ? this.approvalReviewsByCallId.get(item.id) : void 0;
1024
+ const reviewDetails = approvalReviewState ? {
1025
+ approvalReviews: approvalReviewState.reviews,
1026
+ approvalReviewOutcome: toolApprovalReviewOutcome(approvalReviewState)
1027
+ } : void 0;
1028
+ const details = reviewDetails ? isJsonObject(preparedDetails) ? {
1029
+ ...preparedDetails,
1030
+ ...reviewDetails
1031
+ } : {
1032
+ ...preparedDetails !== void 0 ? { toolDetails: preparedDetails } : {},
1033
+ ...reviewDetails
1034
+ } : preparedDetails;
1035
+ this.recordNativeToolResult(item, details);
993
1036
  }
994
1037
  async prepareNativeMcpAppResultDetails(item) {
995
1038
  if (!item || item.type !== "mcpToolCall" || itemStatus(item) === "running") return;
@@ -1025,7 +1068,7 @@ var CodexToolTranscriptProjection = class {
1025
1068
  }
1026
1069
  this.trajectoryResultIds.add(params.item.id);
1027
1070
  const toolResult = itemToolResult(params.item).result;
1028
- const output = itemOutputText(params.item, this.progress.outputTextByItem);
1071
+ const output = this.progress.approvalTimeoutExplanation(params.item.id, params.status) ?? itemOutputText(params.item, this.progress.outputTextByItem);
1029
1072
  this.options.trajectoryRecorder?.recordEvent("tool.result", {
1030
1073
  threadId: this.threadId,
1031
1074
  turnId: this.turnId,
@@ -1045,7 +1088,7 @@ var CodexToolTranscriptProjection = class {
1045
1088
  if (!name || status === "running") return;
1046
1089
  this.afterToolCallObservedItemIds.add(item.id);
1047
1090
  const result = itemToolResult(item).result;
1048
- const error = itemToolError(item, status, this.progress.outputTextByItem);
1091
+ const error = this.progress.approvalTimeoutExplanation(item.id, status) ?? itemToolError(item, status, this.progress.outputTextByItem);
1049
1092
  const startedAt = resolveStartedAtFromDurationMs(item.durationMs);
1050
1093
  const hookParams = {
1051
1094
  toolName: name,
@@ -1077,7 +1120,8 @@ var CodexToolTranscriptProjection = class {
1077
1120
  id,
1078
1121
  name
1079
1122
  }),
1080
- isError: true
1123
+ isError: true,
1124
+ details: { reason: "missing_tool_result" }
1081
1125
  });
1082
1126
  }
1083
1127
  for (const id of missingTrajectoryIds) {
@@ -1139,7 +1183,6 @@ var CodexToolTranscriptProjection = class {
1139
1183
  if (!name) return;
1140
1184
  const item = this.trajectoryItemsById.get(firstMissingId);
1141
1185
  const meta = item ? itemMeta(item, this.progress.toolProgressDetailMode()) : this.progress.getToolMeta(firstMissingId)?.meta;
1142
- const actionFingerprint = item ? nativeToolActionFingerprint(item) : void 0;
1143
1186
  this.progress.setLastToolError({
1144
1187
  toolName: name,
1145
1188
  ...meta ? { meta } : {},
@@ -1147,8 +1190,7 @@ var CodexToolTranscriptProjection = class {
1147
1190
  id: firstMissingId,
1148
1191
  name
1149
1192
  }),
1150
- ...item && isMutatingNativeToolItem(item) ? { mutatingAction: true } : {},
1151
- ...actionFingerprint ? { actionFingerprint } : {}
1193
+ ...item && isMutatingNativeToolItem(item) ? { mutatingAction: true } : {}
1152
1194
  });
1153
1195
  }
1154
1196
  shouldEmitAfterToolCallObservation(item) {
@@ -1211,6 +1253,17 @@ function resolveStartedAtFromDurationMs(durationMs) {
1211
1253
  }
1212
1254
  //#endregion
1213
1255
  //#region extensions/codex/src/app-server/event-projector-events.ts
1256
+ function guardianActionCommand(action) {
1257
+ if (!action) return;
1258
+ const command = readStringField(action, "command");
1259
+ if (command) return command;
1260
+ const argv = Array.isArray(action.argv) ? action.argv.filter((value) => typeof value === "string") : [];
1261
+ return argv.length > 0 ? argv.join(" ") : readStringField(action, "program");
1262
+ }
1263
+ function normalizeApprovalReviewStatus(status) {
1264
+ return status === "inProgress" ? "in_progress" : status === "timedOut" ? "timed_out" : status;
1265
+ }
1266
+ const GUARDIAN_TIMEOUT_WARNING = "Automatic approval review timed out while evaluating the requested approval.";
1214
1267
  function projectNormalizedToolItem(params) {
1215
1268
  const { item } = params;
1216
1269
  if (!item || !shouldSynthesizeToolProgressForItem(item)) return;
@@ -1261,28 +1314,78 @@ var CodexEventProjection = class {
1261
1314
  this.reviewCount += 1;
1262
1315
  const review = isJsonObject(params.review) ? params.review : void 0;
1263
1316
  const action = isJsonObject(params.action) ? params.action : void 0;
1317
+ const reviewId = readStringField(params, "reviewId");
1318
+ const targetItemId = readNullableString$1(params, "targetItemId");
1319
+ const reviewStatus = review ? readStringField(review, "status") : void 0;
1320
+ const status = normalizeApprovalReviewStatus(reviewStatus);
1321
+ const riskLevel = review ? readStringField(review, "riskLevel") : void 0;
1322
+ const userAuthorization = review ? readStringField(review, "userAuthorization") : void 0;
1323
+ const rationale = review ? readNullableString$1(review, "rationale") : void 0;
1324
+ 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;
1325
+ if (Boolean(targetItemId) && Boolean(reviewId) && this.pendingGuardianWarning === expectedWarning) this.pendingGuardianWarning = void 0;
1326
+ else this.flushPendingGuardianWarning();
1264
1327
  this.emitAgentEvent({
1265
1328
  stream: "codex_app_server.guardian",
1266
1329
  data: {
1267
1330
  method,
1268
1331
  phase: method.endsWith("/started") ? "started" : "completed",
1269
- reviewId: readStringField(params, "reviewId"),
1270
- targetItemId: readNullableString$1(params, "targetItemId"),
1332
+ reviewId,
1333
+ targetItemId,
1271
1334
  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
1335
+ status: reviewStatus,
1336
+ riskLevel,
1337
+ userAuthorization,
1338
+ rationale,
1339
+ actionType: action ? readStringField(action, "type") : void 0,
1340
+ command: guardianActionCommand(action)
1277
1341
  }
1278
1342
  });
1343
+ if (reviewId && targetItemId && status) {
1344
+ const approvalReview = {
1345
+ id: reviewId,
1346
+ label: "Guardian",
1347
+ status,
1348
+ ...riskLevel ? { riskLevel } : {},
1349
+ ...userAuthorization ? { userAuthorization } : {},
1350
+ ...rationale ? { rationale } : {}
1351
+ };
1352
+ const approvalReviewOutcome = this.toolTranscript.recordToolApprovalReview(targetItemId, reviewId, status, approvalReview);
1353
+ this.emitAgentEvent({
1354
+ stream: "tool",
1355
+ data: {
1356
+ phase: "review",
1357
+ toolCallId: targetItemId,
1358
+ hideFromChannelProgress: true,
1359
+ approvalReviewOutcome,
1360
+ review: approvalReview
1361
+ }
1362
+ });
1363
+ }
1279
1364
  }
1280
1365
  handleGuardianWarning(params) {
1366
+ this.flushPendingGuardianWarning();
1367
+ const message = readStringField(params, "message");
1368
+ if (message) {
1369
+ this.pendingGuardianWarning = message;
1370
+ return;
1371
+ }
1372
+ this.emitAgentEvent({
1373
+ stream: "codex_app_server.guardian",
1374
+ data: {
1375
+ phase: "warning",
1376
+ message
1377
+ }
1378
+ });
1379
+ }
1380
+ flushPendingGuardianWarning() {
1381
+ const pending = this.pendingGuardianWarning;
1382
+ if (!pending) return;
1383
+ this.pendingGuardianWarning = void 0;
1281
1384
  this.emitAgentEvent({
1282
1385
  stream: "codex_app_server.guardian",
1283
1386
  data: {
1284
1387
  phase: "warning",
1285
- message: readStringField(params, "message")
1388
+ message: pending
1286
1389
  }
1287
1390
  });
1288
1391
  }
@@ -1344,6 +1447,8 @@ var CodexEventProjection = class {
1344
1447
  if (!projection || !params.item) return;
1345
1448
  const { item } = params;
1346
1449
  const { name, status, args, meta, event } = projection;
1450
+ const approvalReviewOutcome = params.phase === "result" ? this.toolTranscript.finalizeToolApprovalReviews(item.id) : void 0;
1451
+ if (event && approvalReviewOutcome) event.data.approvalReviewOutcome = approvalReviewOutcome;
1347
1452
  this.toolTranscript.recordTrajectoryEvent({
1348
1453
  phase: params.phase,
1349
1454
  item,
@@ -1957,7 +2062,8 @@ function registerMonitor(params) {
1957
2062
  taskRuntimeScope: params.taskRuntimeScope,
1958
2063
  agentId: params.agentId,
1959
2064
  claimDirectChild: params.claimDirectChild,
1960
- rejectPendingDirectChild: params.rejectPendingDirectChild
2065
+ rejectPendingDirectChild: params.rejectPendingDirectChild,
2066
+ onDirectChildAccepted: params.onDirectChildAccepted
1961
2067
  });
1962
2068
  }
1963
2069
  var Monitor = class {
@@ -2030,7 +2136,8 @@ var Monitor = class {
2030
2136
  const owner = Symbol("codex-native-subagent-owner");
2031
2137
  state.owners.set(owner, {
2032
2138
  claimDirectChild: params.claimDirectChild,
2033
- rejectPendingDirectChild: params.rejectPendingDirectChild
2139
+ rejectPendingDirectChild: params.rejectPendingDirectChild,
2140
+ onDirectChildAccepted: params.onDirectChildAccepted
2034
2141
  });
2035
2142
  this.prepareParentTaskRuntime(state);
2036
2143
  for (const childState of this.childStates.values()) if (childState.parentThreadId === parentThreadId && childState.pendingCompletion) this.deliverPendingCompletion(state, childState);
@@ -2110,7 +2217,7 @@ var Monitor = class {
2110
2217
  if (state) this.handleClosedChild(notification, state);
2111
2218
  const childState = threadId ? this.childStates.get(threadId) : void 0;
2112
2219
  if (notification.method === "turn/started" && childState) this.resumeChild(childState);
2113
- if (childState && !childState.terminal) this.emitChildTaskActivity(notification, childState.childThreadId);
2220
+ if (childState && !childState.terminal) this.emitChildTaskActivity(notification, childState);
2114
2221
  this.captureChildAssistantMessage(notification);
2115
2222
  await this.handleChildTurnCompletion(notification);
2116
2223
  if (notification.method === "thread/status/changed" && threadId && threadStatus) if (threadStatus !== "systemerror") {
@@ -2129,14 +2236,17 @@ var Monitor = class {
2129
2236
  }
2130
2237
  await this.handleCompletionNotification(notification);
2131
2238
  }
2132
- emitChildTaskActivity(notification, childThreadId) {
2239
+ emitChildTaskActivity(notification, childState) {
2133
2240
  const params = isJsonObject(notification.params) ? notification.params : void 0;
2134
2241
  if (!params) return;
2135
- const runId = codexNativeSubagentRunId(childThreadId);
2242
+ const owner = {
2243
+ runId: codexNativeSubagentRunId(childState.childThreadId),
2244
+ ...childState.agentId ? { agentId: childState.agentId } : {}
2245
+ };
2136
2246
  if (notification.method === "item/agentMessage/delta") {
2137
2247
  const delta = readStringField(params, "delta");
2138
2248
  if (delta) emitAgentEvent({
2139
- runId,
2249
+ ...owner,
2140
2250
  stream: "assistant",
2141
2251
  data: { delta }
2142
2252
  });
@@ -2145,7 +2255,7 @@ var Monitor = class {
2145
2255
  if (notification.method === "item/reasoning/summaryTextDelta") {
2146
2256
  const delta = readStringField(params, "delta");
2147
2257
  if (delta) emitAgentEvent({
2148
- runId,
2258
+ ...owner,
2149
2259
  stream: "thinking",
2150
2260
  data: { delta }
2151
2261
  });
@@ -2154,7 +2264,7 @@ var Monitor = class {
2154
2264
  if (notification.method !== "item/started" && notification.method !== "item/completed") return;
2155
2265
  const item = readItem(params.item);
2156
2266
  if (item?.type === "agentMessage" && notification.method === "item/completed" && item.text) emitAgentEvent({
2157
- runId,
2267
+ ...owner,
2158
2268
  stream: "assistant",
2159
2269
  data: { text: item.text }
2160
2270
  });
@@ -2163,7 +2273,7 @@ var Monitor = class {
2163
2273
  item
2164
2274
  });
2165
2275
  if (projection?.event) emitAgentEvent({
2166
- runId,
2276
+ ...owner,
2167
2277
  ...projection.event
2168
2278
  });
2169
2279
  }
@@ -2287,7 +2397,7 @@ var Monitor = class {
2287
2397
  const childThreadId = thread ? readStringField(thread, "id")?.trim() : void 0;
2288
2398
  const agentPath = readStringField(readThreadSpawnSource(thread), "agent_path")?.trim();
2289
2399
  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;
2400
+ if (state && childThreadId && parentThreadId) return this.registerChildThread(state, childThreadId, agentPath === void 0 ? {} : { agentPath }) ? state : void 0;
2291
2401
  return state;
2292
2402
  }
2293
2403
  if (notification.method === "thread/status/changed" || notification.method === "turn/started" || notification.method === "turn/completed" || notification.method === "item/agentMessage/delta") {
@@ -2319,7 +2429,7 @@ var Monitor = class {
2319
2429
  for (const childThreadId of childThreadIds) accepted = Boolean(isCompletedSpawnAgentTool ? this.registerDirectSpawnChild(state, turnId, {
2320
2430
  parentThreadId,
2321
2431
  childThreadId
2322
- }, owner) : this.registerChildThread(parentThreadId, childThreadId)) && accepted;
2432
+ }, owner) : this.registerChildThread(state, childThreadId)) && accepted;
2323
2433
  if (!accepted) return;
2324
2434
  }
2325
2435
  return state;
@@ -2596,8 +2706,8 @@ var Monitor = class {
2596
2706
  }, delayMs);
2597
2707
  unrefTimer(childState.completionDeliveryTimer);
2598
2708
  }
2599
- registerChildThread(parentThreadIdInput, childThreadIdInput, options = {}) {
2600
- const parentThreadId = parentThreadIdInput.trim();
2709
+ registerChildThread(state, childThreadIdInput, options = {}) {
2710
+ const parentThreadId = state.parentThreadId;
2601
2711
  const childThreadId = childThreadIdInput.trim();
2602
2712
  if (!parentThreadId || !childThreadId || this.disposed) return;
2603
2713
  if (options.claimDirectChild && this.threadStatusRevisions.get(childThreadId)?.terminal) return;
@@ -2620,6 +2730,7 @@ var Monitor = class {
2620
2730
  childState = {
2621
2731
  childThreadId,
2622
2732
  parentThreadId,
2733
+ agentId: state.agentId,
2623
2734
  agentPathKeys: /* @__PURE__ */ new Set(),
2624
2735
  assistantMessagesByTurn: /* @__PURE__ */ new Map(),
2625
2736
  recoveryAttempt: 0,
@@ -2637,7 +2748,7 @@ var Monitor = class {
2637
2748
  }
2638
2749
  if (options.claimDirectChild && !childState.terminal && !childState.settledWithoutCompletion && !childState.releaseDirectChild) childState.releaseDirectChild = options.claimDirectChild(childThreadId);
2639
2750
  this.registerAgentPath(childState, childThreadId);
2640
- this.parentStates.get(parentThreadId)?.mirror?.markAuthoritativeCompletionExpected(childThreadId);
2751
+ state.mirror?.markAuthoritativeCompletionExpected(childThreadId);
2641
2752
  const agentPath = normalizeOptionalString(options.agentPath);
2642
2753
  if (agentPath) this.registerAgentPath(childState, agentPath);
2643
2754
  this.scheduleRecoveryPoll(childState);
@@ -2650,11 +2761,12 @@ var Monitor = class {
2650
2761
  return owners.length === 1 ? owners[0] : void 0;
2651
2762
  }
2652
2763
  registerDirectSpawnChild(state, turnIdInput, evidence, owner) {
2653
- const childState = this.registerChildThread(state.parentThreadId, evidence.childThreadId, {
2764
+ const childState = this.registerChildThread(state, evidence.childThreadId, {
2654
2765
  ...evidence.agentPath === void 0 ? {} : { agentPath: evidence.agentPath },
2655
2766
  ...owner?.claimDirectChild ? { claimDirectChild: owner.claimDirectChild } : {}
2656
2767
  });
2657
2768
  if (!owner) this.bufferPendingDirectSpawnEvidence(turnIdInput, evidence);
2769
+ else if (childState) owner.onDirectChildAccepted?.();
2658
2770
  return childState;
2659
2771
  }
2660
2772
  bufferPendingDirectSpawnEvidence(turnIdInput, evidence) {
@@ -2669,10 +2781,12 @@ var Monitor = class {
2669
2781
  const pending = this.pendingDirectSpawnEvidence.get(turnId);
2670
2782
  this.pendingDirectSpawnEvidence.delete(turnId);
2671
2783
  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
- });
2784
+ for (const evidence of pending) if (evidence.parentThreadId === state.parentThreadId) {
2785
+ if (this.registerChildThread(state, evidence.childThreadId, {
2786
+ ...evidence.agentPath === void 0 ? {} : { agentPath: evidence.agentPath },
2787
+ claimDirectChild: owner.claimDirectChild
2788
+ })) owner.onDirectChildAccepted?.();
2789
+ }
2676
2790
  }
2677
2791
  hasUnboundParentOwner(parentThreadId) {
2678
2792
  return [...parentThreadId ? [this.parentStates.get(parentThreadId)].filter((state) => Boolean(state)) : this.parentStates.values()].some((state) => [...state.owners.values()].some((owner) => owner.turnId === void 0));
@@ -2940,7 +3054,7 @@ var Monitor = class {
2940
3054
  this.prepareParentTaskRuntime(state);
2941
3055
  this.parentStates.set(parentThreadId, state);
2942
3056
  }
2943
- const childState = this.registerChildThread(parentThreadId, candidate.childThreadId);
3057
+ const childState = this.registerChildThread(state, candidate.childThreadId);
2944
3058
  if (!childState) {
2945
3059
  this.pruneParentIfUnused(state);
2946
3060
  return;