@openclaw/codex 2026.7.2-beta.3 → 2026.7.2-beta.5

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 (43) hide show
  1. package/dist/{app-server-policy-DUMF2Xyr.js → app-server-policy-BmDgseo_.js} +1 -1
  2. package/dist/attempt-client-cleanup-Ia52yRWc.js +127 -0
  3. package/dist/{attempt-notifications-Ecjyzufe.js → attempt-notifications-CMR2_fmR.js} +1 -1
  4. package/dist/{media-understanding-provider-IPNNQre6.js → bounded-turn-FEbUXoYT.js} +71 -188
  5. package/dist/capabilities-BHRSI6Cn.js +36 -0
  6. package/dist/cli-metadata.js +1 -1
  7. package/dist/{command-formatters-NCTL7A2q.js → command-formatters-ico4ZFnk.js} +3 -37
  8. package/dist/{command-handlers-DtFbZiba.js → command-handlers-CRmnwI2N.js} +1233 -1221
  9. package/dist/{compact-Kgy26gIM.js → compact-dEN49UH6.js} +8 -7
  10. package/dist/{computer-use-C7x4ZaqR.js → computer-use-BjGylO-E.js} +16 -6
  11. package/dist/{conversation-control-B0s3aIjT.js → conversation-control-DE7d9DOj.js} +6 -5
  12. package/dist/doctor-contract-api.js +24 -86
  13. package/dist/{dynamic-tools-D_vSVmv9.js → dynamic-tools-LIt9ojep.js} +135 -2696
  14. package/dist/event-projector-assistant-message-DTgnPPVF.js +101 -0
  15. package/dist/event-projector-usage-tvgb1NCX.js +69 -0
  16. package/dist/harness.js +31 -11
  17. package/dist/incognito-session-ET_ufDH-.js +2 -0
  18. package/dist/index.js +250 -275
  19. package/dist/media-understanding-provider.js +173 -1
  20. package/dist/{models-DD5zBdX5.js → models-BA01NEez.js} +2 -2
  21. package/dist/{notification-correlation-C8DVQ_Bq.js → notification-correlation-Bj_Ak_jI.js} +3 -3
  22. package/dist/{plugin-app-cache-key-DJbhLYSK.js → plugin-app-cache-key-DSXX-rXO.js} +5 -5
  23. package/dist/{transcript-mirror-D9rTxx2P.js → protocol-validators-Dm4eXZmt.js} +335 -595
  24. package/dist/{rate-limits-CqhWQ2R9.js → rate-limits-S_PXs0ul.js} +1 -1
  25. package/dist/realtime-voice-api-BPcA1uN9.js +494 -0
  26. package/dist/realtime-voice-api.js +2 -0
  27. package/dist/{request-9yf9pZjf.js → request-CXpPennK.js} +1 -1
  28. package/dist/{run-attempt-BIoO8ISr.js → run-attempt-C5GTPJOE.js} +3111 -387
  29. package/dist/{session-binding-Bmt20HfB.js → session-binding-DlVQ-Pxs.js} +957 -890
  30. package/dist/{session-catalog-CA7R-hX2.js → session-catalog-CP2oCcEb.js} +98 -87
  31. package/dist/{session-cli-Bxk3-Wqz.js → session-cli-CqZ0Fp2a.js} +2 -2
  32. package/dist/session-upstream-marker-QE-m5QFG.js +82 -0
  33. package/dist/settled-turn-finalizer-CA_2QXIE.js +303 -0
  34. package/dist/{shared-client-CSXLtCLE.js → shared-client-BVKE40c-.js} +1870 -1694
  35. package/dist/{side-question-DtzquMOb.js → side-question-CO12sHxo.js} +24 -16
  36. package/dist/{thread-lifecycle-CQ_9mAa1.js → thread-lifecycle-DRg_FdzC.js} +127 -153
  37. package/dist/transcript-mirror-uKA-A4tB.js +550 -0
  38. package/dist/upstream-session-fork-_Vrz4WJr.js +320 -0
  39. package/dist/{usage-CuPpFgTc.js → usage-UpVbdX5G.js} +3 -3
  40. package/dist/{web-search-provider.runtime-_x5XTeqh.js → web-search-provider.runtime-CaQMYDbp.js} +3 -3
  41. package/package.json +7 -8
  42. package/npm-shrinkwrap.json +0 -202
  43. package/dist/{auth-binding-C1czuHPA.js → auth-binding-B4FfbcCg.js} +1 -1
@@ -1,184 +1,21 @@
1
- import { Y as CODEX_OPENCLAW_DIRECT_DYNAMIC_TOOL_NAMESPACE, Z as isJsonObject, _ as readCodexRateLimitsRevision, c as releaseLeasedSharedCodexAppServerClient, j as resolveCodexGatewayTimeoutWithGraceMs, v as readRecentCodexRateLimits, y as rememberCodexRateLimitsRead } from "./shared-client-CSXLtCLE.js";
2
- import { y as readCodexPluginConfig } from "./session-binding-Bmt20HfB.js";
3
- import { c as attachCodexMirrorIdentity, g as readCodexTurn, s as promptSnapshot } from "./transcript-mirror-D9rTxx2P.js";
4
- import { C as isForcedPrivateQaCodexRuntime, S as filterCodexDynamicToolsWithOpenClawShell, T as normalizeCodexDynamicToolName, a as sanitizeCodexHistoryImagePayloads, d as resolveCodexWebSearchPlan, i as invalidInlineImageText, o as sanitizeInlineImageDataUrl, w as isSystemAgentOnlyCodexDynamicToolAllowlist, x as filterCodexDynamicTools } from "./thread-lifecycle-CQ_9mAa1.js";
5
- import { d as CODEX_CONTROL_METHODS, r as formatCodexDisplayText } from "./command-formatters-NCTL7A2q.js";
6
- import { a as shouldRefreshCodexRateLimitsForUsageLimitMessage, i as resolveCodexUsageLimitResetAtMs, n as formatCodexUsageLimitErrorMessage } from "./rate-limits-CqhWQ2R9.js";
1
+ import { V as isJsonObject, l as releaseLeasedSharedCodexAppServerClient, q as resolveCodexGatewayTimeoutWithGraceMs, z as CODEX_OPENCLAW_DIRECT_DYNAMIC_TOOL_NAMESPACE } from "./shared-client-BVKE40c-.js";
2
+ import { T as readCodexPluginConfig } from "./session-binding-DlVQ-Pxs.js";
3
+ import { D as isForcedPrivateQaCodexRuntime, E as filterCodexDynamicToolsWithOpenClawShell, O as isSystemAgentOnlyCodexDynamicToolAllowlist, T as filterCodexDynamicTools, et as readItem, h as resolveCodexWebSearchPlan, i as invalidInlineImageText, k as normalizeCodexDynamicToolName, o as sanitizeInlineImageDataUrl, st as readString$2, tt as readItemString } from "./thread-lifecycle-DRg_FdzC.js";
4
+ import { l as readCodexTurn } from "./protocol-validators-Dm4eXZmt.js";
5
+ import { r as formatCodexDisplayText } from "./command-formatters-ico4ZFnk.js";
7
6
  import { a as resolveCodexNodeExecToolOverrides, i as resolveCodexNativeExecutionPolicy } from "./sandbox-guard-D1Wky__S.js";
8
- import { n as readCodexNotificationThreadId, r as readCodexNotificationTurnId } from "./notification-correlation-C8DVQ_Bq.js";
9
- import fs from "node:fs/promises";
7
+ import { n as readCodexNotificationThreadId, r as readCodexNotificationTurnId } from "./notification-correlation-Bj_Ak_jI.js";
10
8
  import { addTimerTimeoutGraceMs, asDateTimestampMs, finiteSecondsToTimerSafeMilliseconds, parseStrictNonNegativeInteger } from "openclaw/plugin-sdk/number-runtime";
11
- import { sliceUtf16Safe, truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
9
+ import { HEARTBEAT_RESPONSE_TOOL_NAME, buildAgentHookContextChannelFields, buildEmbeddedAttemptToolRunContext, callGatewayTool, consumeAdjustedParamsForToolCall, consumePreExecutionBlockedToolCall, createAgentToolResultMiddlewareRunner, createCodexAppServerToolResultExtensionRunner, embeddedAgentLog, extractMessagingToolSend, extractMessagingToolSendResult, extractToolResultMediaArtifact, filterProviderNormalizableTools, filterToolResultMediaUrls, finalizeToolTerminalPresentation, formatApprovalDisplayPath, formatToolExecutionErrorMessage, getBeforeToolCallFailureDisposition, getChannelAgentToolMeta, getPluginToolMeta, hasNativeHookRelayInvocation, invokeNativeHookRelay, isDeliveredMessageToolOnlySourceReplyResult, isDeliveredMessagingToolResult, isHostScopedAgentToolActive, isMessagingTool, isMessagingToolSendAction, isReplaySafeToolCall, isSubagentSessionKey, isToolResultError, isToolWrappedWithBeforeToolCallHook, normalizeAgentRuntimeTools, normalizeHeartbeatToolResponse, projectRuntimeToolInputSchema, registerNativeHookRelay, resolveAttemptSpawnWorkspaceDir, resolveModelAuthMode, resolveNativeHookRelayDeferredToolApproval, resolveToolExecutionErrorKind, resolveToolResultFailureKind, runAgentHarnessAfterToolCallHook, runBeforeToolCallHook, sanitizeToolResult, setBeforeToolCallDiagnosticsEnabled, supportsModelTools, wrapToolWithBeforeToolCallHook } from "openclaw/plugin-sdk/agent-harness-runtime";
12
10
  import { createHash } from "node:crypto";
13
- import { markAuthProfileBlockedUntil, resolveAgentDir } from "openclaw/plugin-sdk/agent-runtime";
14
- import { normalizeAgentId } from "openclaw/plugin-sdk/routing";
15
- import { asOptionalRecord, isRecord, normalizeTrimmedStringList } from "openclaw/plugin-sdk/string-coerce-runtime";
16
- import { HEARTBEAT_RESPONSE_TOOL_NAME, TOOL_PROGRESS_OUTPUT_MAX_CHARS, buildAgentHookContextChannelFields, buildEmbeddedAttemptToolRunContext, callGatewayTool, classifyAgentHarnessTerminalOutcome, consumeAdjustedParamsForToolCall, consumePreExecutionBlockedToolCall, createAgentToolResultMiddlewareRunner, createCodexAppServerToolResultExtensionRunner, embeddedAgentLog, emitAgentEvent, extractMessagingToolSend, extractMessagingToolSendResult, extractToolResultMediaArtifact, filterProviderNormalizableTools, filterToolResultMediaUrls, finalizeToolTerminalPresentation, formatApprovalDisplayPath, formatErrorMessage, formatToolAggregate, formatToolExecutionErrorMessage, formatToolProgressOutput, getBeforeToolCallFailureDisposition, getChannelAgentToolMeta, getPluginToolMeta, hasNativeHookRelayInvocation, inferToolMetaFromArgs, invokeNativeHookRelay, isDeliveredMessageToolOnlySourceReplyResult, isDeliveredMessagingToolResult, isHostScopedAgentToolActive, isMessagingTool, isMessagingToolSendAction, isReplaySafeToolCall, isSubagentSessionKey, isToolResultError, isToolWrappedWithBeforeToolCallHook, normalizeAgentRuntimeTools, normalizeHeartbeatToolResponse, normalizeUsage, projectRuntimeToolInputSchema, registerNativeHookRelay, resolveAttemptSpawnWorkspaceDir, resolveModelAuthMode, resolveNativeHookRelayDeferredToolApproval, resolveToolExecutionErrorKind, resolveToolResultFailureKind, runAgentHarnessAfterCompactionHook, runAgentHarnessAfterToolCallHook, runAgentHarnessBeforeCompactionHook, runBeforeToolCallHook, sanitizeToolResult, setBeforeToolCallDiagnosticsEnabled, supportsModelTools, wrapToolWithBeforeToolCallHook } from "openclaw/plugin-sdk/agent-harness-runtime";
17
- import { listSessionEntries, parseSqliteSessionFileMarker } from "openclaw/plugin-sdk/session-store-runtime";
11
+ import { resolveAgentDir as resolveAgentDir$1 } from "openclaw/plugin-sdk/agent-runtime";
12
+ import { isRecord, normalizeTrimmedStringList } from "openclaw/plugin-sdk/string-coerce-runtime";
13
+ import { sliceUtf16Safe, truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
18
14
  import { expectDefined } from "openclaw/plugin-sdk/expect-runtime";
19
- import { redactSensitiveFieldValue, redactSensitiveText, redactToolPayloadText } from "openclaw/plugin-sdk/logging-core";
20
15
  import { emitTrustedDiagnosticEvent, hasPendingInternalDiagnosticEvent } from "openclaw/plugin-sdk/diagnostic-runtime";
21
- import { readSessionTranscriptEvents } from "openclaw/plugin-sdk/session-transcript-runtime";
22
16
  import { isToolAllowed } from "openclaw/plugin-sdk/sandbox";
23
- import { sanitizeTerminalText } from "openclaw/plugin-sdk/text-chunking";
24
- import { buildSessionContext, migrateSessionEntries, parseSessionEntries } from "openclaw/plugin-sdk/agent-sessions";
25
- import { generatedImageAssetFromBase64 } from "openclaw/plugin-sdk/image-generation";
26
- import { saveMediaBuffer } from "openclaw/plugin-sdk/media-store";
17
+ import { isApprovalNotFoundError } from "openclaw/plugin-sdk/error-runtime";
27
18
  import { normalizeOpenAIToolSchemas } from "openclaw/plugin-sdk/provider-tools";
28
- //#region extensions/codex/src/app-server/local-runtime-attribution.ts
29
- const OPENAI_PROVIDER_ID = "openai";
30
- const OPENAI_RESPONSES_API = "openai-responses";
31
- const OPENAI_CODEX_RESPONSES_API = "openai-chatgpt-responses";
32
- function normalizeRuntimeId(value) {
33
- return value?.trim().toLowerCase() ?? "";
34
- }
35
- /** Maps local Codex runtime plans onto the provider/api pair exposed to event projection. */
36
- function resolveCodexLocalRuntimeAttribution(params) {
37
- const authProfileProvider = normalizeRuntimeId(params.runtimePlan?.auth?.authProfileProviderForAuth);
38
- if (normalizeRuntimeId(params.runtimePlan?.observability.harnessId) === "codex" && authProfileProvider !== OPENAI_PROVIDER_ID && normalizeRuntimeId(params.model.provider) === OPENAI_PROVIDER_ID && normalizeRuntimeId(params.model.api) === OPENAI_RESPONSES_API) return {
39
- provider: OPENAI_PROVIDER_ID,
40
- api: OPENAI_CODEX_RESPONSES_API
41
- };
42
- return {
43
- provider: params.provider,
44
- api: params.model.api
45
- };
46
- }
47
- //#endregion
48
- //#region extensions/codex/src/app-server/event-projector-assistant-message.ts
49
- const ZERO_USAGE$1 = {
50
- input: 0,
51
- output: 0,
52
- cacheRead: 0,
53
- cacheWrite: 0,
54
- totalTokens: 0,
55
- cost: {
56
- input: 0,
57
- output: 0,
58
- cacheRead: 0,
59
- cacheWrite: 0,
60
- total: 0
61
- }
62
- };
63
- function createAssistantMessage(params, text, options) {
64
- const attribution = resolveCodexLocalRuntimeAttribution(params);
65
- const usage = options.tokenUsage ? {
66
- input: options.tokenUsage.input ?? 0,
67
- output: options.tokenUsage.output ?? 0,
68
- cacheRead: options.tokenUsage.cacheRead ?? 0,
69
- cacheWrite: options.tokenUsage.cacheWrite ?? 0,
70
- ...options.tokenUsage.contextUsage ? { contextUsage: options.tokenUsage.contextUsage } : {},
71
- totalTokens: options.tokenUsage.total ?? (options.tokenUsage.input ?? 0) + (options.tokenUsage.output ?? 0) + (options.tokenUsage.cacheRead ?? 0) + (options.tokenUsage.cacheWrite ?? 0),
72
- cost: ZERO_USAGE$1.cost
73
- } : ZERO_USAGE$1;
74
- return {
75
- role: "assistant",
76
- content: [{
77
- type: "text",
78
- text
79
- }],
80
- api: attribution.api ?? "openai-chatgpt-responses",
81
- provider: attribution.provider,
82
- model: params.modelId,
83
- usage,
84
- stopReason: options.aborted ? "aborted" : options.promptError ? "error" : "stop",
85
- errorMessage: options.promptError ? formatErrorMessage(options.promptError) : void 0,
86
- timestamp: Date.now()
87
- };
88
- }
89
- function createAssistantMirrorMessage(params, title, text) {
90
- const attribution = resolveCodexLocalRuntimeAttribution(params);
91
- return {
92
- role: "assistant",
93
- content: [{
94
- type: "text",
95
- text: `${title}:\n${text}`
96
- }],
97
- api: attribution.api ?? "openai-chatgpt-responses",
98
- provider: attribution.provider,
99
- model: params.modelId,
100
- usage: ZERO_USAGE$1,
101
- stopReason: "stop",
102
- timestamp: Date.now()
103
- };
104
- }
105
- //#endregion
106
- //#region extensions/codex/src/app-server/event-projector-values.ts
107
- function readString$3(record, key) {
108
- const value = record[key];
109
- return typeof value === "string" ? value : void 0;
110
- }
111
- function normalizeNonEmptyString(value) {
112
- if (typeof value !== "string") return;
113
- return value.trim() || void 0;
114
- }
115
- function readNonEmptyString(record, key) {
116
- return normalizeNonEmptyString(record[key]);
117
- }
118
- function readNonEmptyStringArray(record, key) {
119
- const value = record[key];
120
- if (!Array.isArray(value)) return [];
121
- const entries = [];
122
- for (const entry of value) {
123
- const normalized = normalizeNonEmptyString(entry);
124
- if (normalized) entries.push(normalized);
125
- }
126
- return entries;
127
- }
128
- function readNullableString(record, key) {
129
- const value = record[key];
130
- if (value === null) return null;
131
- return typeof value === "string" ? value : void 0;
132
- }
133
- function readNumber(record, key) {
134
- const value = record[key];
135
- return typeof value === "number" && Number.isFinite(value) ? value : void 0;
136
- }
137
- function readNonNegativeInteger(record, key) {
138
- const value = readNumber(record, key);
139
- return value !== void 0 && Number.isInteger(value) && value >= 0 ? value : void 0;
140
- }
141
- function readCodexErrorNotificationMessage(record) {
142
- const error = record.error;
143
- return isJsonObject(error) ? readString$3(error, "message") : void 0;
144
- }
145
- function readHookOutputEntries(value) {
146
- if (!Array.isArray(value)) return [];
147
- return value.flatMap((entry) => {
148
- if (!isJsonObject(entry)) return [];
149
- const text = readString$3(entry, "text");
150
- if (!text) return [];
151
- const kind = readString$3(entry, "kind");
152
- return [{
153
- ...kind ? { kind } : {},
154
- text
155
- }];
156
- });
157
- }
158
- function splitPlanText(text) {
159
- return text.split(/\r?\n/).map((line) => line.trim().replace(/^[-*]\s+/, "")).filter((line) => line.length > 0);
160
- }
161
- function extractRawAssistantText(item) {
162
- return (Array.isArray(item.content) ? item.content : []).flatMap((entry) => {
163
- if (!isJsonObject(entry)) return [];
164
- const type = readString$3(entry, "type");
165
- if (type !== "output_text" && type !== "text") return [];
166
- const value = readString$3(entry, "text");
167
- return value ? [value] : [];
168
- }).join("").trim() || void 0;
169
- }
170
- function readItemString(item, key) {
171
- const value = item[key];
172
- return typeof value === "string" ? value : void 0;
173
- }
174
- function readItem(value) {
175
- if (!isJsonObject(value)) return;
176
- const type = typeof value.type === "string" ? value.type : void 0;
177
- const id = typeof value.id === "string" ? value.id : void 0;
178
- if (!type || !id) return;
179
- return value;
180
- }
181
- //#endregion
182
19
  //#region extensions/codex/src/app-server/event-projector-items.ts
183
20
  function itemKind(item) {
184
21
  switch (item.type) {
@@ -230,1680 +67,79 @@ function auditNativeToolTerminalStatus(item) {
230
67
  const status = readItemString(item, "status");
231
68
  if (status === "completed") return "completed";
232
69
  if (status === "failed" || status === "error") return "failed";
233
- if (status === "declined") return "blocked";
234
- return "unknown";
235
- }
236
- function auditNativeToolUnfinishedStatus(item) {
237
- return item.type === "webSearch" || item.type === "imageGeneration" ? "unknown" : "failed";
238
- }
239
- function isNonSuccessItemStatus(status) {
240
- return status === "failed" || status === "blocked";
241
- }
242
- function itemName(item) {
243
- if (item.type === "dynamicToolCall" && typeof item.tool === "string") return item.tool;
244
- if (item.type === "mcpToolCall" && typeof item.tool === "string") {
245
- const server = typeof item.server === "string" ? item.server : void 0;
246
- return server ? `${server}.${item.tool}` : item.tool;
247
- }
248
- if (item.type === "commandExecution") return "bash";
249
- if (item.type === "fileChange") return "apply_patch";
250
- if (item.type === "webSearch") return "web_search";
251
- }
252
- function auditNativeToolName(item) {
253
- if (item.type === "dynamicToolCall") return;
254
- const progressName = itemName(item);
255
- if (progressName) return progressName;
256
- if (item.type === "collabAgentToolCall") return typeof item.tool === "string" && item.tool.trim() ? `collab.${item.tool.trim()}` : "collab_agent";
257
- if (item.type === "imageGeneration") return "image_generation";
258
- if (item.type === "imageView") return "image_view";
259
- if (item.type === "sleep") return "sleep";
260
- }
261
- function isSideEffectingNativeToolItem(item) {
262
- return itemStatus(item) !== "blocked" && (isMutatingNativeToolItem(item) || item.type === "mcpToolCall");
263
- }
264
- function shouldSynthesizeToolProgressForItem(item) {
265
- switch (item.type) {
266
- case "commandExecution":
267
- case "fileChange":
268
- case "webSearch":
269
- case "mcpToolCall": return true;
270
- default: return false;
271
- }
272
- }
273
- function shouldRecordNativeToolTranscript(item) {
274
- return shouldSynthesizeToolProgressForItem(item) && item.type !== "webSearch";
275
- }
276
- function isMutatingNativeToolItem(item) {
277
- if (item.type === "commandExecution") return true;
278
- return item.type === "fileChange" || item.type === "collabAgentToolCall" || item.type === "imageGeneration";
279
- }
280
- function shouldClearTerminalPresentationForNativeItem(item) {
281
- switch (item.type) {
282
- case "collabAgentToolCall":
283
- case "commandExecution":
284
- case "fileChange":
285
- case "imageGeneration":
286
- case "imageView":
287
- case "mcpToolCall":
288
- case "webSearch": return true;
289
- default: return false;
290
- }
291
- }
292
- //#endregion
293
- //#region extensions/codex/src/app-server/event-projector-assistant.ts
294
- var CodexAssistantProjection = class {
295
- constructor(params, emitAgentEvent, matchesToolProgressEcho) {
296
- this.params = params;
297
- this.emitAgentEvent = emitAgentEvent;
298
- this.matchesToolProgressEcho = matchesToolProgressEcho;
299
- this.assistantTextByItem = /* @__PURE__ */ new Map();
300
- this.assistantItemOrder = [];
301
- this.assistantPhaseByItem = /* @__PURE__ */ new Map();
302
- this.latestTerminalAssistantCandidateSuperseded = false;
303
- this.latestTerminalAssistantCandidateCanReleaseAfterToolHandoff = false;
304
- this.terminalAssistantCandidateEarlierActiveItemIds = /* @__PURE__ */ new Set();
305
- this.lastCommentaryProgressTextByItem = /* @__PURE__ */ new Map();
306
- this.lastAnswerCandidateEventByItem = /* @__PURE__ */ new Map();
307
- this.pendingRawCommentaryEchoes = 0;
308
- this.rawPromotedAssistantItemIds = /* @__PURE__ */ new Set();
309
- this.assistantStarted = false;
310
- this.streamedPartialAssistantItemReplaceable = false;
311
- }
312
- hasCompletedTerminalAssistantText(completedItemIds) {
313
- const latestCompletedItemId = this.latestCompletedTerminalAssistantItemId;
314
- if (!latestCompletedItemId) return false;
315
- const finalItem = this.resolveFinalAssistantTextItem();
316
- return this.latestCompletedItemId === latestCompletedItemId && finalItem?.itemId === latestCompletedItemId && completedItemIds.has(latestCompletedItemId);
317
- }
318
- getLatestTerminalAssistantCandidate() {
319
- const itemId = this.latestTerminalAssistantCandidateItemId;
320
- if (!itemId) return;
321
- const text = this.assistantTextByItem.get(itemId)?.trim();
322
- return {
323
- itemId,
324
- hasText: Boolean(text && !this.isToolProgressEchoText(itemId, text))
325
- };
326
- }
327
- hasLatestTerminalAssistantCandidateText() {
328
- return !this.latestTerminalAssistantCandidateSuperseded && this.getLatestTerminalAssistantCandidate()?.hasText === true;
329
- }
330
- canReleaseLatestTerminalAssistantAfterToolHandoff() {
331
- return this.latestTerminalAssistantCandidateCanReleaseAfterToolHandoff && this.hasLatestTerminalAssistantCandidateText();
332
- }
333
- async handleAssistantDelta(params) {
334
- const itemId = readString$3(params, "itemId") ?? "assistant";
335
- const delta = readString$3(params, "delta") ?? "";
336
- if (!delta) return;
337
- if (itemId !== this.pendingRawTerminalAssistantEchoItemId) this.pendingRawTerminalAssistantEchoItemId = void 0;
338
- const isCommentary = this.isCommentaryAssistantItem(itemId);
339
- if (!isCommentary && itemId !== this.latestTerminalAssistantCandidateItemId) this.markTerminalAssistantCandidateSupersededBy();
340
- if (!this.assistantStarted) {
341
- this.assistantStarted = true;
342
- await this.params.onAssistantMessageStart?.();
343
- }
344
- this.rememberAssistantItem(itemId);
345
- const text = `${this.assistantTextByItem.get(itemId) ?? ""}${delta}`;
346
- this.assistantTextByItem.set(itemId, text);
347
- if (isCommentary) {
348
- this.emitCommentaryProgress({
349
- itemId,
350
- text
351
- });
352
- return;
353
- }
354
- if (this.isFinalAnswerAssistantItem(itemId)) this.emitAnswerCandidate(itemId, "candidate");
355
- const knownFinalAnswer = this.shouldStreamAssistantPartial(itemId);
356
- const replace = this.streamedPartialAssistantItemId !== void 0 && this.streamedPartialAssistantItemId !== itemId;
357
- if (replace && (!knownFinalAnswer || this.streamedPartialAssistantItemReplaceable)) this.streamedPartialAssistantItemReplaceable = true;
358
- else if (this.streamedPartialAssistantItemId === void 0) this.streamedPartialAssistantItemReplaceable = !knownFinalAnswer;
359
- this.streamedPartialAssistantItemId = itemId;
360
- const replaceable = this.streamedPartialAssistantItemReplaceable;
361
- const replacement = replace && replaceable;
362
- const streamPayload = {
363
- text,
364
- delta: replacement ? "" : delta,
365
- ...replacement ? { replace: true } : {}
366
- };
367
- this.emitAgentEvent({
368
- stream: "assistant",
369
- data: {
370
- ...streamPayload,
371
- ...replaceable ? { replaceable: true } : {}
372
- }
373
- });
374
- if (knownFinalAnswer && !replaceable) await this.params.onPartialReply?.(streamPayload);
375
- }
376
- recordItemStarted(item, itemId) {
377
- if (item?.type === "agentMessage" && itemId && itemId !== this.pendingRawTerminalAssistantEchoItemId) this.pendingRawTerminalAssistantEchoItemId = void 0;
378
- this.rememberAssistantPhase(item);
379
- if (itemId && itemId !== this.latestTerminalAssistantCandidateItemId) {
380
- this.markTerminalAssistantCandidateSupersededBy(itemId, { preserveEarlierActiveItem: true });
381
- if (this.latestTerminalAssistantCandidateSuperseded) this.pendingRawTerminalAssistantEchoItemId = void 0;
382
- }
383
- }
384
- recordItemCompleted(item, itemId, activeItemIds) {
385
- if (item?.type === "agentMessage" && itemId && itemId !== this.pendingRawTerminalAssistantEchoItemId) this.pendingRawTerminalAssistantEchoItemId = void 0;
386
- if (itemId) this.latestCompletedItemId = itemId;
387
- this.rememberAssistantPhase(item);
388
- if (item?.type === "agentMessage" && !this.isCommentaryAssistantItem(item.id)) {
389
- this.latestCompletedTerminalAssistantItemId = item.id;
390
- this.markLatestTerminalAssistantCandidate(item.id, activeItemIds);
391
- this.pendingRawTerminalAssistantEchoItemId = item.id;
392
- } else if (itemId) {
393
- this.markTerminalAssistantCandidateSupersededBy(itemId, { preserveEarlierActiveItem: true });
394
- if (this.latestTerminalAssistantCandidateSuperseded) this.pendingRawTerminalAssistantEchoItemId = void 0;
395
- }
396
- if (item?.type === "agentMessage" && typeof item.text === "string") {
397
- this.rememberAssistantItem(item.id);
398
- this.assistantTextByItem.set(item.id, item.text);
399
- if (item.text && this.isCommentaryAssistantItem(item.id)) {
400
- this.emitCommentaryProgress({
401
- itemId: item.id,
402
- text: item.text
403
- });
404
- this.pendingRawCommentaryEchoes += 1;
405
- } else if (item.text && this.isFinalAnswerAssistantItem(item.id)) this.emitAnswerCandidate(item.id, "candidate");
406
- }
407
- }
408
- recordSnapshotItem(item) {
409
- this.rememberAssistantPhase(item);
410
- if (item.type === "agentMessage" && typeof item.text === "string") {
411
- this.rememberAssistantItem(item.id);
412
- this.assistantTextByItem.set(item.id, item.text);
413
- }
414
- }
415
- handleRawResponseItemCompleted(item, activeItemIds) {
416
- const role = readString$3(item, "role");
417
- const phase = readString$3(item, "phase");
418
- const rawItemId = readString$3(item, "id");
419
- const candidateWasSupersededBeforeRaw = this.latestTerminalAssistantCandidateSuperseded;
420
- const pendingTerminalAssistantEchoItemId = this.pendingRawTerminalAssistantEchoItemId;
421
- const isPendingTerminalAssistantEcho = role === "assistant" && phase !== "commentary" && pendingTerminalAssistantEchoItemId !== void 0 && (rawItemId === void 0 || rawItemId === pendingTerminalAssistantEchoItemId);
422
- if (pendingTerminalAssistantEchoItemId !== void 0 && !isPendingTerminalAssistantEcho) this.pendingRawTerminalAssistantEchoItemId = void 0;
423
- if (!isPendingTerminalAssistantEcho) {
424
- this.latestCompletedItemId = void 0;
425
- this.markTerminalAssistantCandidateSupersededBy(rawItemId);
426
- }
427
- if (role !== "assistant") return;
428
- if (phase === "commentary" && this.pendingRawCommentaryEchoes > 0) {
429
- this.pendingRawCommentaryEchoes -= 1;
430
- return;
431
- }
432
- const text = extractRawAssistantText(item);
433
- if (isPendingTerminalAssistantEcho) {
434
- const typedItemId = pendingTerminalAssistantEchoItemId;
435
- this.pendingRawTerminalAssistantEchoItemId = void 0;
436
- if (this.assistantTextByItem.get(typedItemId)?.trim() || !text) return;
437
- this.rememberAssistantItem(typedItemId);
438
- this.assistantTextByItem.set(typedItemId, text);
439
- return;
440
- }
441
- if (!text) return;
442
- const itemId = rawItemId ?? `raw-assistant-${this.assistantItemOrder.length + 1}`;
443
- const isIdlessTerminalAssistantAfterCompletedWork = candidateWasSupersededBeforeRaw && rawItemId === void 0 && pendingTerminalAssistantEchoItemId === void 0 && activeItemIds.size === 0;
444
- if (phase !== "commentary" && candidateWasSupersededBeforeRaw && itemId !== this.streamedPartialAssistantItemId && !isIdlessTerminalAssistantAfterCompletedWork) return;
445
- if (phase) this.assistantPhaseByItem.set(itemId, phase);
446
- this.rememberAssistantItem(itemId);
447
- this.assistantTextByItem.set(itemId, text);
448
- this.rawPromotedAssistantItemIds.add(itemId);
449
- if (phase === "commentary") this.emitCommentaryProgress({
450
- itemId,
451
- text
452
- });
453
- else this.markLatestTerminalAssistantCandidate(itemId, activeItemIds, { canReleaseAfterToolHandoff: isIdlessTerminalAssistantAfterCompletedWork });
454
- }
455
- collectAssistantTexts() {
456
- const finalText = this.resolveFinalAssistantTextItem()?.text;
457
- return finalText ? [finalText] : [];
458
- }
459
- finalizeAnswerCandidate(turn) {
460
- if (turn.status !== "completed") {
461
- this.supersedeVisibleAnswerCandidate();
462
- return;
463
- }
464
- const turnItems = turn.items ?? [];
465
- const authoritativeIndex = turnItems.findLastIndex((item) => item.type === "agentMessage" && readItemString(item, "phase") === "final_answer" && typeof item.text === "string" && item.text.trim().length > 0);
466
- const authoritative = authoritativeIndex >= 0 ? turnItems[authoritativeIndex] : void 0;
467
- if (turnItems.slice(authoritativeIndex + 1).some(shouldClearTerminalPresentationForNativeItem) || authoritative?.id === this.latestTerminalAssistantCandidateItemId && this.latestTerminalAssistantCandidateSuperseded) {
468
- this.supersedeVisibleAnswerCandidate();
469
- return;
470
- }
471
- const itemId = authoritative?.id ?? this.visibleAnswerCandidateItemId;
472
- if (!itemId) return;
473
- if (itemId !== this.visibleAnswerCandidateItemId) {
474
- this.supersedeVisibleAnswerCandidate();
475
- this.visibleAnswerCandidateItemId = itemId;
476
- }
477
- this.emitAnswerCandidate(itemId, "selected");
478
- }
479
- hasAssistantItemTextForSynthesis() {
480
- for (let i = this.assistantItemOrder.length - 1; i >= 0; i -= 1) {
481
- const itemId = this.assistantItemOrder[i];
482
- if (!itemId || this.assistantPhaseByItem.get(itemId) === "commentary") continue;
483
- const text = this.assistantTextByItem.get(itemId);
484
- if (text && text.length > 0) return true;
485
- }
486
- return false;
487
- }
488
- createCurrentAttemptAssistantMessage(options) {
489
- for (let i = this.assistantItemOrder.length - 1; i >= 0; i -= 1) {
490
- const itemId = this.assistantItemOrder[i];
491
- if (!itemId || this.isCommentaryAssistantItem(itemId) || !this.assistantTextByItem.has(itemId)) continue;
492
- const text = this.assistantTextByItem.get(itemId) ?? "";
493
- const normalizedText = text.trim();
494
- if (normalizedText && this.isToolProgressEchoText(itemId, normalizedText)) continue;
495
- return this.createAssistantMessage(text, options);
496
- }
497
- }
498
- createAssistantMessage(text, options) {
499
- return createAssistantMessage(this.params, text, options);
500
- }
501
- createAssistantMirrorMessage(title, text) {
502
- return createAssistantMirrorMessage(this.params, title, text);
503
- }
504
- rememberAssistantPhase(item) {
505
- if (item?.type !== "agentMessage") return;
506
- const phase = readItemString(item, "phase");
507
- if (phase) this.assistantPhaseByItem.set(item.id, phase);
508
- }
509
- isCommentaryAssistantItem(itemId) {
510
- return this.assistantPhaseByItem.get(itemId) === "commentary";
511
- }
512
- isFinalAnswerAssistantItem(itemId) {
513
- return this.assistantPhaseByItem.get(itemId) === "final_answer";
514
- }
515
- shouldStreamAssistantPartial(itemId) {
516
- return this.assistantPhaseByItem.get(itemId) === "final_answer";
517
- }
518
- emitCommentaryProgress(params) {
519
- const progressText = params.text.replace(/\s+/g, " ").trim();
520
- if (!progressText || this.lastCommentaryProgressTextByItem.get(params.itemId) === progressText) return;
521
- this.lastCommentaryProgressTextByItem.set(params.itemId, progressText);
522
- this.emitAgentEvent({
523
- stream: "item",
524
- data: {
525
- itemId: params.itemId,
526
- kind: "preamble",
527
- title: "Preamble",
528
- phase: "update",
529
- progressText,
530
- source: "codex-app-server"
531
- }
532
- });
533
- }
534
- emitAnswerCandidate(itemId, status) {
535
- const text = this.assistantTextByItem.get(itemId)?.trim();
536
- if (!text) return;
537
- if (status === "candidate" && this.visibleAnswerCandidateItemId !== itemId) {
538
- this.supersedeVisibleAnswerCandidate();
539
- this.visibleAnswerCandidateItemId = itemId;
540
- }
541
- const signature = `${status}\0${text}`;
542
- if (this.lastAnswerCandidateEventByItem.get(itemId) === signature) return;
543
- this.lastAnswerCandidateEventByItem.set(itemId, signature);
544
- this.emitAgentEvent({
545
- stream: "item",
546
- data: {
547
- itemId,
548
- kind: "answer_candidate",
549
- title: "Answer candidate",
550
- phase: "update",
551
- status,
552
- progressText: text,
553
- source: "codex-app-server",
554
- hideFromChannelProgress: true
555
- }
556
- });
557
- }
558
- supersedeVisibleAnswerCandidate() {
559
- const itemId = this.visibleAnswerCandidateItemId;
560
- if (!itemId) return;
561
- this.emitAnswerCandidate(itemId, "superseded");
562
- this.visibleAnswerCandidateItemId = void 0;
563
- }
564
- markLatestTerminalAssistantCandidate(itemId, activeItemIds, options) {
565
- this.latestTerminalAssistantCandidateItemId = itemId;
566
- this.latestTerminalAssistantCandidateSuperseded = false;
567
- this.latestTerminalAssistantCandidateCanReleaseAfterToolHandoff = options?.canReleaseAfterToolHandoff === true;
568
- this.terminalAssistantCandidateEarlierActiveItemIds = new Set(activeItemIds);
569
- }
570
- markTerminalAssistantCandidateSupersededBy(itemId, options) {
571
- if (!this.latestTerminalAssistantCandidateItemId) return;
572
- if (itemId && this.terminalAssistantCandidateEarlierActiveItemIds.has(itemId)) {
573
- if (!options?.preserveEarlierActiveItem) this.terminalAssistantCandidateEarlierActiveItemIds.delete(itemId);
574
- return;
575
- }
576
- this.latestTerminalAssistantCandidateSuperseded = true;
577
- this.latestTerminalAssistantCandidateCanReleaseAfterToolHandoff = false;
578
- this.terminalAssistantCandidateEarlierActiveItemIds.clear();
579
- this.supersedeVisibleAnswerCandidate();
580
- }
581
- resolveFinalAssistantTextItem() {
582
- for (let i = this.assistantItemOrder.length - 1; i >= 0; i -= 1) {
583
- const itemId = this.assistantItemOrder[i];
584
- if (!itemId) continue;
585
- const text = this.assistantTextByItem.get(itemId)?.trim();
586
- if (this.assistantPhaseByItem.get(itemId) === "commentary") continue;
587
- if (text && !this.isToolProgressEchoText(itemId, text)) return {
588
- itemId,
589
- text
590
- };
591
- }
592
- }
593
- rememberAssistantItem(itemId) {
594
- if (!itemId || this.assistantItemOrder.includes(itemId)) return;
595
- this.assistantItemOrder.push(itemId);
596
- }
597
- isToolProgressEchoText(itemId, text) {
598
- return this.rawPromotedAssistantItemIds.has(itemId) && this.matchesToolProgressEcho(text);
599
- }
600
- };
601
- //#endregion
602
- //#region extensions/codex/src/app-server/event-projector-diagnostics.ts
603
- function redactCodexEventKind(method) {
604
- return redactSensitiveText(sanitizeTerminalText(method));
605
- }
606
- var CodexProjectionDiagnostics = class {
607
- constructor(threadId, turnId) {
608
- this.threadId = threadId;
609
- this.turnId = turnId;
610
- this.warningKeys = /* @__PURE__ */ new Set();
611
- }
612
- warnUnknownItemStatus(item) {
613
- if (!item) return;
614
- const status = unknownItemStatus(item);
615
- if (!status) return;
616
- const safeStatus = redactCodexEventKind(status);
617
- const safeItemType = redactCodexEventKind(item.type);
618
- this.warnOnce(JSON.stringify([
619
- "status",
620
- item.type,
621
- status
622
- ]), "codex app-server item reported unknown status; continuing projection", {
623
- itemId: item.id,
624
- itemType: safeItemType,
625
- status: safeStatus
626
- });
627
- }
628
- warnUnknownEvent(notification, params) {
629
- const notificationThreadId = readCodexNotificationThreadId(params);
630
- const notificationTurnId = readCodexNotificationTurnId(params);
631
- const eventKind = redactCodexEventKind(notification.method);
632
- this.warnOnce(JSON.stringify(["method", notification.method]), `codex app-server projector received unknown event kind; continuing: ${eventKind}`, {
633
- eventKind,
634
- activeThreadId: this.threadId,
635
- activeTurnId: this.turnId,
636
- threadId: notificationThreadId,
637
- turnId: notificationTurnId,
638
- matchesActiveThread: notificationThreadId === this.threadId,
639
- matchesActiveTurn: notificationTurnId === this.turnId
640
- });
641
- }
642
- warnOnce(key, message, context) {
643
- if (this.warningKeys.has(key)) return;
644
- this.warningKeys.add(key);
645
- embeddedAgentLog.warn(message, context);
646
- }
647
- };
648
- //#endregion
649
- //#region extensions/codex/src/app-server/event-projector-tool-output.ts
650
- const TOOL_TRANSCRIPT_OUTPUT_MAX_CHARS = 1e4;
651
- const TOOL_OUTPUT_TRUNCATION_NOTICE_PREFIX = "...(OpenClaw truncated Codex native tool output";
652
- var ToolOutputAccumulator = class {
653
- constructor() {
654
- this.prefixByItem = /* @__PURE__ */ new Map();
655
- this.originalLengthByItem = /* @__PURE__ */ new Map();
656
- this.normalizedLengthByItem = /* @__PURE__ */ new Map();
657
- this.trimStateByItem = /* @__PURE__ */ new Map();
658
- this.truncatedItemIds = /* @__PURE__ */ new Set();
659
- this.textByItem = /* @__PURE__ */ new Map();
660
- }
661
- append(itemId, delta) {
662
- const originalLength = (this.originalLengthByItem.get(itemId) ?? this.textByItem.get(itemId)?.length ?? 0) + delta.length;
663
- this.originalLengthByItem.set(itemId, originalLength);
664
- const normalizedLength = updateToolOutputTrimState(this.trimStateByItem, itemId, delta);
665
- this.normalizedLengthByItem.set(itemId, normalizedLength);
666
- if (this.truncatedItemIds.has(itemId)) {
667
- const next = appendBoundedToolTranscriptText(this.prefixByItem.get(itemId) ?? this.textByItem.get(itemId) ?? "", "", originalLength);
668
- this.prefixByItem.set(itemId, next.rawPrefix);
669
- this.textByItem.set(itemId, next.text);
670
- return {
671
- text: next.text,
672
- originalLength,
673
- normalizedLength,
674
- rawPrefix: next.rawPrefix
675
- };
676
- }
677
- const next = appendBoundedToolTranscriptText(this.prefixByItem.get(itemId) ?? this.textByItem.get(itemId) ?? "", delta, originalLength);
678
- this.prefixByItem.set(itemId, next.rawPrefix);
679
- this.textByItem.set(itemId, next.text);
680
- if (originalLength > 1e4) this.truncatedItemIds.add(itemId);
681
- return {
682
- text: next.text,
683
- originalLength,
684
- normalizedLength,
685
- rawPrefix: next.rawPrefix
686
- };
687
- }
688
- };
689
- function updateToolOutputTrimState(trimStateByItem, itemId, delta) {
690
- const state = trimStateByItem.get(itemId) ?? {
691
- totalLength: 0,
692
- leadingWhitespaceLength: 0,
693
- trailingWhitespaceLength: 0,
694
- sawNonWhitespace: false
695
- };
696
- state.totalLength += delta.length;
697
- const firstNonWhitespace = delta.search(/\S/u);
698
- if (firstNonWhitespace === -1) {
699
- if (!state.sawNonWhitespace) state.leadingWhitespaceLength += delta.length;
700
- state.trailingWhitespaceLength += delta.length;
701
- trimStateByItem.set(itemId, state);
702
- return state.sawNonWhitespace ? state.totalLength - state.leadingWhitespaceLength - state.trailingWhitespaceLength : 0;
703
- }
704
- if (!state.sawNonWhitespace) {
705
- state.leadingWhitespaceLength += firstNonWhitespace;
706
- state.sawNonWhitespace = true;
707
- }
708
- state.trailingWhitespaceLength = delta.match(/\s*$/u)?.[0].length ?? 0;
709
- trimStateByItem.set(itemId, state);
710
- return state.totalLength - state.leadingWhitespaceLength - state.trailingWhitespaceLength;
711
- }
712
- function toolOutputRawEchoSignature(text) {
713
- const trimmed = text.trim();
714
- if (!trimmed) return;
715
- return {
716
- rawLength: trimmed.length,
717
- rawPrefix: trimmed.slice(0, TOOL_TRANSCRIPT_OUTPUT_MAX_CHARS)
718
- };
719
- }
720
- function normalizeToolTranscriptArguments(value) {
721
- if (!value || typeof value !== "object" || Array.isArray(value)) return {};
722
- return value;
723
- }
724
- function collectDynamicToolContentText(contentItems) {
725
- if (!Array.isArray(contentItems)) return "";
726
- return contentItems.flatMap((entry) => {
727
- if (!isJsonObject(entry)) return [];
728
- const text = readString$3(entry, "text");
729
- return text ? [text] : [];
730
- }).join("\n");
731
- }
732
- function appendBoundedToolTranscriptText(currentPrefix, delta, originalLength) {
733
- if (originalLength <= 1e4) {
734
- const rawPrefix = currentPrefix + delta;
735
- return {
736
- text: rawPrefix,
737
- rawPrefix
738
- };
739
- }
740
- const notice = toolTranscriptTruncationNotice(originalLength);
741
- if (notice.length >= 1e4) return {
742
- text: notice.slice(0, TOOL_TRANSCRIPT_OUTPUT_MAX_CHARS),
743
- rawPrefix: ""
744
- };
745
- const textBudget = TOOL_TRANSCRIPT_OUTPUT_MAX_CHARS - notice.length;
746
- const remaining = Math.max(0, textBudget - currentPrefix.length);
747
- const rawPrefix = truncateUtf16Safe(remaining > 0 ? `${currentPrefix}${truncateUtf16Safe(delta, remaining)}` : currentPrefix, textBudget);
748
- return {
749
- text: `${rawPrefix}${notice}`,
750
- rawPrefix
751
- };
752
- }
753
- function toolTranscriptTruncationNotice(originalLength) {
754
- return `\n${`${TOOL_OUTPUT_TRUNCATION_NOTICE_PREFIX}: original ${originalLength} chars, showing ${TOOL_TRANSCRIPT_OUTPUT_MAX_CHARS}; rerun with narrower args.)`}`;
755
- }
756
- function truncateToolTranscriptText(text, originalLength = text.length) {
757
- if (originalLength <= 1e4 && text.length <= 1e4) return text;
758
- const notice = toolTranscriptTruncationNotice(originalLength);
759
- if (notice.length >= 1e4) return notice.slice(1, 10001);
760
- return `${truncateUtf16Safe(text, TOOL_TRANSCRIPT_OUTPUT_MAX_CHARS - notice.length)}${notice}`;
761
- }
762
- function formatToolSummary(toolName, meta) {
763
- const trimmedMeta = meta?.trim();
764
- return formatToolAggregate(toolName, trimmedMeta ? [trimmedMeta] : void 0, { markdown: true });
765
- }
766
- function formatToolOutput(toolName, meta, output) {
767
- const formattedOutput = formatToolProgressOutput(output);
768
- if (!formattedOutput) return formatToolSummary(toolName, meta);
769
- const fence = markdownFenceForText(formattedOutput);
770
- return `${formatToolSummary(toolName, meta)}\n${fence}txt\n${formattedOutput}\n${fence}`;
771
- }
772
- function markdownFenceForText(text) {
773
- return "`".repeat(Math.max(3, longestBacktickRun(text) + 1));
774
- }
775
- function longestBacktickRun(value) {
776
- let longest = 0;
777
- let current = 0;
778
- for (const char of value) {
779
- if (char === "`") {
780
- current += 1;
781
- longest = Math.max(longest, current);
782
- continue;
783
- }
784
- current = 0;
785
- }
786
- return longest;
787
- }
788
- //#endregion
789
- //#region extensions/codex/src/app-server/tool-progress-normalization.ts
790
- /**
791
- * Normalizes and sanitizes Codex dynamic-tool progress payloads before they are
792
- * emitted into OpenClaw events or logs.
793
- */
794
- /** Maps OpenClaw tool-progress config to the mode used by Codex progress metadata. */
795
- function resolveCodexToolProgressDetailMode(value) {
796
- return value === "raw" ? "raw" : "explain";
797
- }
798
- /** Recursively redacts sensitive strings and handles circular values in event payloads. */
799
- function sanitizeCodexAgentEventValue(value, seen = /* @__PURE__ */ new WeakSet()) {
800
- if (typeof value === "string") return redactToolPayloadText(value);
801
- if (Array.isArray(value)) {
802
- if (seen.has(value)) return "[Circular]";
803
- seen.add(value);
804
- return value.map((entry) => sanitizeCodexAgentEventValue(entry, seen));
805
- }
806
- if (value && typeof value === "object") {
807
- if (seen.has(value)) return "[Circular]";
808
- seen.add(value);
809
- const out = {};
810
- for (const [key, child] of Object.entries(value)) out[key] = typeof child === "string" ? redactSensitiveFieldValue(key, child) : sanitizeCodexAgentEventValue(child, seen);
811
- return out;
812
- }
813
- return value;
814
- }
815
- /** Sanitizes a record-shaped Codex agent event payload. */
816
- function sanitizeCodexAgentEventRecord(value) {
817
- return sanitizeCodexAgentEventValue(value);
818
- }
819
- /** Sanitizes dynamic-tool arguments before diagnostic/event emission. */
820
- function sanitizeCodexToolArguments(value) {
821
- if (!isJsonObject(value)) return;
822
- return sanitizeCodexAgentEventRecord(value);
823
- }
824
- /** Sanitizes a Codex dynamic-tool response before diagnostic/event emission. */
825
- function sanitizeCodexToolResponse(response) {
826
- return sanitizeCodexAgentEventRecord(response);
827
- }
828
- /** Infers compact human-readable tool metadata from Codex dynamic-tool arguments. */
829
- function inferCodexDynamicToolMeta(call, detailMode) {
830
- return inferToolMetaFromArgs(call.tool, call.arguments, { detailMode });
831
- }
832
- //#endregion
833
- //#region extensions/codex/src/app-server/event-projector-tool-items.ts
834
- function nativeToolActionFingerprint(item) {
835
- if (item.type === "commandExecution" && typeof item.command === "string") return JSON.stringify({
836
- type: item.type,
837
- command: item.command,
838
- cwd: typeof item.cwd === "string" ? item.cwd : ""
839
- });
840
- if (item.type === "fileChange") return JSON.stringify({
841
- type: item.type,
842
- changes: itemFileChanges(item)
843
- });
844
- }
845
- function isNativePostToolUseRelayItem(item) {
846
- switch (item.type) {
847
- case "commandExecution":
848
- case "fileChange":
849
- case "mcpToolCall": return true;
850
- default: return false;
851
- }
852
- }
853
- function shouldSuppressChannelProgressForItem(item) {
854
- if (shouldSynthesizeToolProgressForItem(item)) return true;
855
- return item.type === "dynamicToolCall";
856
- }
857
- function itemToolArgs(item) {
858
- if (item.type === "commandExecution") return sanitizeCodexAgentEventRecord({
859
- command: item.command,
860
- ...typeof item.cwd === "string" ? { cwd: item.cwd } : {}
861
- });
862
- if (item.type === "fileChange") return sanitizeCodexAgentEventRecord({ changes: itemFileChangesForTranscript(item) });
863
- if (item.type === "webSearch") return webSearchToolArgs(item);
864
- if (item.type === "dynamicToolCall" || item.type === "mcpToolCall") return sanitizeCodexToolArguments(item.arguments);
865
- }
866
- function webSearchToolArgs(item) {
867
- const action = isJsonObject(item.action) ? item.action : void 0;
868
- const actionType = action ? readNonEmptyString(action, "type") : void 0;
869
- const queries = action && actionType === "search" ? readNonEmptyStringArray(action, "queries") : [];
870
- const query = normalizeNonEmptyString(item.query) ?? (action && actionType === "search" ? readNonEmptyString(action, "query") : void 0) ?? queries[0];
871
- const url = action ? readNonEmptyString(action, "url") : void 0;
872
- const pattern = action ? readNonEmptyString(action, "pattern") : void 0;
873
- const args = {};
874
- if (query) args.query = query;
875
- if (queries.length > 0) args.queries = queries;
876
- if (actionType && actionType !== "search") args.action = actionType;
877
- if (url) args.url = url;
878
- if (pattern) args.pattern = pattern;
879
- if (!query && !url && !pattern) args.queryUnavailable = true;
880
- return sanitizeCodexAgentEventRecord(args);
881
- }
882
- function itemToolResult(item) {
883
- if (item.type === "commandExecution") return { result: sanitizeCodexAgentEventRecord({
884
- status: item.status,
885
- exitCode: item.exitCode,
886
- durationMs: item.durationMs
887
- }) };
888
- if (item.type === "fileChange") return { result: sanitizeCodexAgentEventRecord({
889
- status: item.status,
890
- changes: itemFileChanges(item)
891
- }) };
892
- if (item.type === "mcpToolCall") return { result: sanitizeCodexAgentEventRecord({
893
- status: item.status,
894
- durationMs: item.durationMs,
895
- ...item.error ? { error: item.error } : {},
896
- ...item.result ? { result: item.result } : {}
897
- }) };
898
- if (item.type === "webSearch") return { result: webSearchToolResult(item) };
899
- return {};
900
- }
901
- function webSearchToolResult(item) {
902
- return sanitizeCodexAgentEventRecord({
903
- status: itemStatus(item),
904
- ...typeof item.durationMs === "number" ? { durationMs: item.durationMs } : {},
905
- ...webSearchToolArgs(item)
906
- });
907
- }
908
- function itemFileChangeRecords(item) {
909
- const changes = item.changes;
910
- return Array.isArray(changes) ? changes.filter(isJsonObject) : [];
911
- }
912
- function itemFileChanges(item) {
913
- return itemFileChangeRecords(item).flatMap((change) => {
914
- const path = normalizeNonEmptyString(change.path);
915
- if (!path || change.kind === void 0) return [];
916
- return [{
917
- path,
918
- kind: change.kind
919
- }];
920
- });
921
- }
922
- function fileChangeKindType(kind) {
923
- if (typeof kind === "string") return kind;
924
- return isJsonObject(kind) ? normalizeNonEmptyString(kind.type) : void 0;
925
- }
926
- function countFileContentLines(content) {
927
- if (!content) return 0;
928
- const lines = content.replace(/\r\n/g, "\n").replace(/\r/g, "\n").split("\n");
929
- if (lines.length > 1 && lines.at(-1) === "") lines.pop();
930
- return lines.length;
931
- }
932
- function fileChangeDiffStat(diff, kind) {
933
- const kindType = fileChangeKindType(kind);
934
- if (kindType === "add") return {
935
- added: countFileContentLines(diff),
936
- removed: 0
937
- };
938
- if (kindType === "delete") return {
939
- added: 0,
940
- removed: countFileContentLines(diff)
941
- };
942
- let added = 0;
943
- let removed = 0;
944
- let inHunk = false;
945
- for (const line of diff.replace(/\r\n/g, "\n").replace(/\r/g, "\n").split("\n")) {
946
- if (line.startsWith("@@")) {
947
- inHunk = true;
948
- continue;
949
- }
950
- if (!inHunk) continue;
951
- if (line.startsWith("+")) added += 1;
952
- else if (line.startsWith("-")) removed += 1;
953
- }
954
- return {
955
- added,
956
- removed
957
- };
958
- }
959
- function truncateFileChangeDiffAtLineBoundary(diff, maxChars) {
960
- if (diff.length <= maxChars) return { diff };
961
- if (maxChars <= 0) return { diffTruncated: true };
962
- const boundary = diff.lastIndexOf("\n", maxChars - 1);
963
- return boundary >= 0 ? {
964
- diff: diff.slice(0, boundary + 1),
965
- diffTruncated: true
966
- } : { diffTruncated: true };
967
- }
968
- function itemFileChangesForTranscript(item) {
969
- let remainingDiffChars = 1e4;
970
- return itemFileChangeRecords(item).flatMap((change) => {
971
- const path = normalizeNonEmptyString(change.path);
972
- if (!path || change.kind === void 0) return [];
973
- const result = {
974
- path,
975
- kind: change.kind
976
- };
977
- if (typeof change.diff !== "string") return [result];
978
- result.stat = fileChangeDiffStat(change.diff, change.kind);
979
- const bounded = truncateFileChangeDiffAtLineBoundary(change.diff, remainingDiffChars);
980
- if (bounded.diff !== void 0) {
981
- result.diff = bounded.diff;
982
- remainingDiffChars -= bounded.diff.length;
983
- }
984
- if (bounded.diffTruncated) result.diffTruncated = true;
985
- return [result];
986
- });
987
- }
988
- function itemToolError(item, status, outputTextByItem) {
989
- if (status === "blocked") return "codex native tool blocked";
990
- if (status !== "failed") return;
991
- return itemOutputText(item, outputTextByItem) ?? "codex native tool failed";
992
- }
993
- function itemMeta(item, detailMode = "explain") {
994
- if (item.type === "commandExecution" && typeof item.command === "string") return inferToolMetaFromArgs("exec", {
995
- command: item.command,
996
- cwd: typeof item.cwd === "string" ? item.cwd : void 0
997
- }, { detailMode });
998
- if (item.type === "webSearch") return inferToolMetaFromArgs("web_search", webSearchToolArgs(item), { detailMode });
999
- const toolName = itemName(item);
1000
- if ((item.type === "dynamicToolCall" || item.type === "mcpToolCall") && toolName) return inferToolMetaFromArgs(toolName, item.arguments, { detailMode });
1001
- }
1002
- function itemOutputText(item, outputTextByItem) {
1003
- if (item.type === "commandExecution") {
1004
- const output = item.aggregatedOutput?.trim() || outputTextByItem?.get(item.id)?.trim();
1005
- return output ? truncateToolTranscriptText(output) : void 0;
1006
- }
1007
- if (item.type === "dynamicToolCall") {
1008
- const output = collectDynamicToolContentText(item.contentItems).trim();
1009
- return output ? truncateToolTranscriptText(output) : void 0;
1010
- }
1011
- if (item.type === "mcpToolCall") {
1012
- const output = item.error ? stringifyJsonValue(item.error) : item.result ? stringifyJsonValue(item.result) : void 0;
1013
- return output ? truncateToolTranscriptText(output) : void 0;
1014
- }
1015
- }
1016
- function itemTranscriptResultText(item, outputTextByItem) {
1017
- const output = itemOutputText(item, outputTextByItem);
1018
- if (output) return output;
1019
- const result = itemToolResult(item).result;
1020
- const resultText = result ? stringifyJsonValue(result) : void 0;
1021
- return resultText ? truncateToolTranscriptText(resultText) : itemStatus(item);
1022
- }
1023
- function stringifyJsonValue(value) {
1024
- try {
1025
- return JSON.stringify(value, null, 2);
1026
- } catch {
1027
- return;
1028
- }
1029
- }
1030
- //#endregion
1031
- //#region extensions/codex/src/app-server/event-projector-tool-progress.ts
1032
- const TRANSCRIPT_PROGRESS_SUPPRESSED_TOOL_NAMES = /* @__PURE__ */ new Set([
1033
- "message",
1034
- "messages",
1035
- "reply",
1036
- "send",
1037
- "reaction",
1038
- "react",
1039
- "typing"
1040
- ]);
1041
- function shouldEmitTranscriptToolProgress(toolName, _args) {
1042
- const normalized = typeof toolName === "string" ? toolName.trim().toLowerCase() : "";
1043
- return Boolean(normalized && !TRANSCRIPT_PROGRESS_SUPPRESSED_TOOL_NAMES.has(normalized));
1044
- }
1045
- var CodexToolProgressProjection = class {
1046
- constructor(params) {
1047
- this.params = params;
1048
- this.echoesByItem = /* @__PURE__ */ new Map();
1049
- this.resultSummaryItemIds = /* @__PURE__ */ new Set();
1050
- this.resultOutputItemIds = /* @__PURE__ */ new Set();
1051
- this.resultOutputStreamedItemIds = /* @__PURE__ */ new Set();
1052
- this.transcriptProgressSuppressedIds = /* @__PURE__ */ new Set();
1053
- this.transcriptArgumentsById = /* @__PURE__ */ new Map();
1054
- this.resultOutputDeltaState = /* @__PURE__ */ new Map();
1055
- this.output = new ToolOutputAccumulator();
1056
- this.metas = /* @__PURE__ */ new Map();
1057
- this.sideEffectingNativeIds = /* @__PURE__ */ new Set();
1058
- this.sideEffectingDynamicIds = /* @__PURE__ */ new Set();
1059
- this.transcriptProgressCallIds = /* @__PURE__ */ new Set();
1060
- }
1061
- get outputTextByItem() {
1062
- return this.output.textByItem;
1063
- }
1064
- get toolMetas() {
1065
- return [...this.metas.values()];
1066
- }
1067
- getToolMeta(itemId) {
1068
- return this.metas.get(itemId);
1069
- }
1070
- get lastToolError() {
1071
- return this.lastNativeToolError;
1072
- }
1073
- get hasPotentialSideEffects() {
1074
- return this.sideEffectingNativeIds.size > 0 || this.sideEffectingDynamicIds.size > 0;
1075
- }
1076
- setLastToolError(error) {
1077
- if (!error) {
1078
- this.lastNativeToolError = void 0;
1079
- return;
1080
- }
1081
- const terminalResolution = this.params.observeToolTerminal?.({
1082
- toolName: error.toolName,
1083
- ...error.meta ? { meta: error.meta } : {},
1084
- outcome: "failure",
1085
- failure: {
1086
- ...error.errorCode ? { errorCode: error.errorCode } : {},
1087
- ...error.error ? { error: error.error } : {},
1088
- ...error.validationErrorSummary ? { validationErrorSummary: error.validationErrorSummary } : {},
1089
- ...error.timedOut ? { timedOut: true } : {},
1090
- ...error.middlewareError ? { middlewareError: true } : {}
1091
- },
1092
- nativeMutation: {
1093
- mutatingAction: error.mutatingAction === true,
1094
- replaySafe: error.mutatingAction !== true,
1095
- ...error.actionFingerprint ? { actionFingerprint: error.actionFingerprint } : {},
1096
- ...error.fileTarget ? { fileTarget: error.fileTarget } : {}
1097
- }
1098
- });
1099
- this.lastNativeToolError = terminalResolution?.lastToolError ?? (this.lastNativeToolError?.mutatingAction && error.mutatingAction !== true ? this.lastNativeToolError : error);
1100
- }
1101
- recordDynamicToolResult(params) {
1102
- const resultText = collectDynamicToolContentText(params.contentItems);
1103
- const existing = this.metas.get(params.callId);
1104
- this.metas.set(params.callId, {
1105
- toolName: existing?.toolName ?? params.tool,
1106
- ...existing?.meta ? { meta: existing.meta } : {},
1107
- ...params.asyncStarted === true ? { asyncStarted: true } : {},
1108
- ...!params.success ? { isError: true } : {}
1109
- });
1110
- if (params.terminalResolution) this.lastNativeToolError = params.terminalResolution.lastToolError;
1111
- else if (!params.success) this.lastNativeToolError = {
1112
- toolName: params.tool,
1113
- error: resultText || (params.terminalType === "blocked" ? "codex dynamic tool blocked" : "codex dynamic tool failed")
1114
- };
1115
- else if (this.lastNativeToolError?.mutatingAction !== true) this.lastNativeToolError = void 0;
1116
- if (params.sideEffectEvidence === true) this.sideEffectingDynamicIds.add(params.callId);
1117
- }
1118
- handleOutputDelta(params, toolName) {
1119
- const itemId = readString$3(params, "itemId");
1120
- const delta = readString$3(params, "delta");
1121
- if (!itemId || !delta) return;
1122
- const storedOutput = this.output.append(itemId, delta);
1123
- this.rememberEcho(itemId, {
1124
- displayText: storedOutput.text,
1125
- rawLength: storedOutput.normalizedLength,
1126
- rawPrefix: storedOutput.rawPrefix,
1127
- streamedDisplay: true
1128
- });
1129
- if (!this.shouldEmitToolOutput()) return;
1130
- if (this.transcriptProgressSuppressedIds.has(itemId) || !shouldEmitTranscriptToolProgress(toolName, this.transcriptArgumentsById.get(itemId))) return;
1131
- const state = this.resultOutputDeltaState.get(itemId) ?? {
1132
- chars: 0,
1133
- messages: 0,
1134
- truncated: false
1135
- };
1136
- if (state.truncated) return;
1137
- const remainingChars = Math.max(0, TOOL_PROGRESS_OUTPUT_MAX_CHARS - state.chars);
1138
- const remainingMessages = Math.max(0, 20 - state.messages);
1139
- if (remainingChars === 0 || remainingMessages === 0) {
1140
- state.truncated = true;
1141
- this.resultOutputDeltaState.set(itemId, state);
1142
- this.emitToolResultMessage({
1143
- itemId,
1144
- text: formatToolOutput(toolName, void 0, "(output truncated)")
1145
- });
1146
- return;
1147
- }
1148
- const chunk = delta.length > remainingChars ? truncateUtf16Safe(delta, remainingChars) : delta;
1149
- state.chars += chunk.length;
1150
- state.messages += 1;
1151
- const reachedLimit = delta.length > remainingChars || state.chars >= TOOL_PROGRESS_OUTPUT_MAX_CHARS || state.messages >= 20;
1152
- if (reachedLimit) state.truncated = true;
1153
- this.resultOutputDeltaState.set(itemId, state);
1154
- this.resultOutputStreamedItemIds.add(itemId);
1155
- this.emitToolResultMessage({
1156
- itemId,
1157
- text: formatToolOutput(toolName, void 0, reachedLimit ? `${chunk}\n...(truncated)...` : chunk)
1158
- });
1159
- }
1160
- recordNativeToolError(params) {
1161
- const executionStarted = params.status !== "blocked";
1162
- const mutatingAction = executionStarted && isMutatingNativeToolItem(params.item);
1163
- const actionFingerprint = mutatingAction ? nativeToolActionFingerprint(params.item) : void 0;
1164
- const isFailure = isNonSuccessItemStatus(params.status);
1165
- const error = isFailure ? itemToolError(params.item, params.status, this.output.textByItem) : void 0;
1166
- const terminalResolution = this.params.observeToolTerminal?.({
1167
- toolCallId: params.item.id,
1168
- toolName: params.name,
1169
- arguments: itemToolArgs(params.item),
1170
- ...params.meta ? { meta: params.meta } : {},
1171
- executionStarted,
1172
- outcome: isFailure ? "failure" : "success",
1173
- ...isFailure ? { failure: error ? { error } : {} } : {},
1174
- nativeMutation: {
1175
- mutatingAction,
1176
- replaySafe: !mutatingAction,
1177
- ...actionFingerprint ? { actionFingerprint } : {}
1178
- }
1179
- });
1180
- if (terminalResolution) {
1181
- this.lastNativeToolError = terminalResolution.lastToolError;
1182
- return;
1183
- }
1184
- if (isFailure) this.lastNativeToolError = {
1185
- toolName: params.name,
1186
- ...params.meta ? { meta: params.meta } : {},
1187
- ...error ? { error } : {},
1188
- ...mutatingAction ? { mutatingAction: true } : {},
1189
- ...actionFingerprint ? { actionFingerprint } : {}
1190
- };
1191
- else if (this.lastNativeToolError?.mutatingAction !== true) this.lastNativeToolError = void 0;
1192
- }
1193
- emitToolResultSummary(item) {
1194
- if (!item || !this.params.onToolResult || !this.shouldEmitToolResult()) return;
1195
- if (this.resultSummaryItemIds.has(item.id)) return;
1196
- const toolName = itemName(item);
1197
- if (!toolName || !shouldEmitTranscriptToolProgress(toolName, itemToolArgs(item))) return;
1198
- this.resultSummaryItemIds.add(item.id);
1199
- this.emitToolResultMessage({
1200
- itemId: item.id,
1201
- text: formatToolSummary(toolName, itemMeta(item, this.toolProgressDetailMode()))
1202
- });
1203
- }
1204
- emitToolResultOutput(item) {
1205
- if (!item || !this.params.onToolResult || !this.shouldEmitToolOutput()) return;
1206
- if (this.resultOutputItemIds.has(item.id) || this.resultOutputStreamedItemIds.has(item.id)) return;
1207
- const toolName = itemName(item);
1208
- const output = itemOutputText(item, this.output.textByItem);
1209
- if (!toolName || !output || !shouldEmitTranscriptToolProgress(toolName, itemToolArgs(item))) return;
1210
- this.emitToolResultMessage({
1211
- itemId: item.id,
1212
- text: formatToolOutput(toolName, itemMeta(item, this.toolProgressDetailMode()), output),
1213
- finalOutput: true,
1214
- isError: isNonSuccessItemStatus(itemStatus(item))
1215
- });
1216
- }
1217
- recordToolMeta(item) {
1218
- if (!item) return;
1219
- if (isSideEffectingNativeToolItem(item)) this.sideEffectingNativeIds.add(item.id);
1220
- else this.sideEffectingNativeIds.delete(item.id);
1221
- const toolName = itemName(item);
1222
- if (!toolName) return;
1223
- const meta = itemMeta(item, this.toolProgressDetailMode());
1224
- const status = itemStatus(item);
1225
- const existing = this.metas.get(item.id);
1226
- this.metas.set(item.id, {
1227
- toolName,
1228
- ...meta ? { meta } : {},
1229
- ...existing?.asyncStarted ? { asyncStarted: true } : {},
1230
- ...status !== "running" && isNonSuccessItemStatus(status) ? { isError: true } : {}
1231
- });
1232
- }
1233
- recordTranscriptCall(params) {
1234
- this.transcriptArgumentsById.set(params.id, params.arguments);
1235
- if (!shouldEmitTranscriptToolProgress(params.name, params.arguments)) this.transcriptProgressSuppressedIds.add(params.id);
1236
- else this.transcriptProgressSuppressedIds.delete(params.id);
1237
- this.emitTranscriptToolCallProgress(params);
1238
- }
1239
- recordTranscriptResult(params) {
1240
- this.emitTranscriptToolResultProgress(params);
1241
- }
1242
- matchesEcho(text) {
1243
- for (const state of this.echoesByItem.values()) {
1244
- if (state.streamedDisplayText === text || state.displayTexts.includes(text)) return true;
1245
- if (state.streamedRawSignature && text.length === state.streamedRawSignature.length && text.startsWith(state.streamedRawSignature.prefix)) return true;
1246
- for (const signature of state.rawSignatures) if (text.length === signature.length && text.startsWith(signature.prefix)) return true;
1247
- }
1248
- return false;
1249
- }
1250
- rememberCommandAggregateOutputEcho(item) {
1251
- if (item?.type !== "commandExecution" || typeof item.aggregatedOutput !== "string") return;
1252
- const signature = toolOutputRawEchoSignature(item.aggregatedOutput);
1253
- if (signature) this.rememberEcho(item.id, signature);
1254
- }
1255
- toolProgressDetailMode() {
1256
- return resolveCodexToolProgressDetailMode(this.params.toolProgressDetail);
1257
- }
1258
- emitToolResultMessage(params) {
1259
- const rawText = params.text.trim();
1260
- const text = truncateToolTranscriptText(rawText);
1261
- if (!text) return;
1262
- this.rememberEcho(params.itemId, {
1263
- displayText: text,
1264
- rawText
1265
- });
1266
- if (params.finalOutput) this.resultOutputItemIds.add(params.itemId);
1267
- try {
1268
- Promise.resolve(this.params.onToolResult?.({
1269
- text,
1270
- ...params.isError === true ? { isError: true } : {}
1271
- })).catch(() => {});
1272
- } catch {}
1273
- }
1274
- shouldEmitToolResult() {
1275
- return typeof this.params.shouldEmitToolResult === "function" ? this.params.shouldEmitToolResult() : this.params.verboseLevel === "on" || this.params.verboseLevel === "full";
1276
- }
1277
- shouldEmitToolOutput() {
1278
- return typeof this.params.shouldEmitToolOutput === "function" ? this.params.shouldEmitToolOutput() : this.params.verboseLevel === "full";
1279
- }
1280
- emitTranscriptToolCallProgress(params) {
1281
- if (!shouldEmitTranscriptToolProgress(params.name, params.arguments)) return;
1282
- this.transcriptProgressCallIds.add(params.id);
1283
- const args = normalizeToolTranscriptArguments(params.arguments);
1284
- const meta = inferToolMetaFromArgs(params.name, args, { detailMode: this.toolProgressDetailMode() });
1285
- if (!this.params.onToolResult || !this.shouldEmitToolResult() || this.resultSummaryItemIds.has(params.id) || this.resultOutputStreamedItemIds.has(params.id)) return;
1286
- this.resultSummaryItemIds.add(params.id);
1287
- this.emitToolResultMessage({
1288
- itemId: params.id,
1289
- text: formatToolSummary(params.name, meta)
1290
- });
1291
- }
1292
- emitTranscriptToolResultProgress(params) {
1293
- if (this.transcriptProgressSuppressedIds.has(params.id) || !shouldEmitTranscriptToolProgress(params.name, this.transcriptArgumentsById.get(params.id))) return;
1294
- if (!this.transcriptProgressCallIds.has(params.id)) this.emitTranscriptToolCallProgress({
1295
- id: params.id,
1296
- name: params.name,
1297
- arguments: {}
1298
- });
1299
- if (!this.params.onToolResult || !this.shouldEmitToolOutput() || this.resultOutputItemIds.has(params.id) || this.resultOutputStreamedItemIds.has(params.id)) return;
1300
- const text = params.text?.trim();
1301
- if (text) this.emitToolResultMessage({
1302
- itemId: params.id,
1303
- text: formatToolOutput(params.name, void 0, text),
1304
- finalOutput: true,
1305
- isError: params.isError
1306
- });
1307
- }
1308
- rememberEcho(itemId, signature) {
1309
- if (!itemId) return;
1310
- const existing = this.echoesByItem.get(itemId) ?? {
1311
- displayTexts: [],
1312
- rawSignatures: []
1313
- };
1314
- const displayText = signature.displayText?.trim();
1315
- if (displayText) {
1316
- if (signature.streamedDisplay) existing.streamedDisplayText = displayText;
1317
- else if (!existing.displayTexts.includes(displayText)) {
1318
- if (existing.displayTexts.length >= 24) existing.displayTexts.shift();
1319
- existing.displayTexts.push(displayText);
1320
- }
1321
- }
1322
- const rawText = signature.rawText?.trim();
1323
- const rawLength = signature.rawLength ?? rawText?.length;
1324
- const rawPrefix = signature.rawPrefix?.trim() ?? rawText;
1325
- if (rawLength !== void 0 && rawPrefix && rawPrefix.length >= 1024) {
1326
- const next = {
1327
- length: rawLength,
1328
- prefix: rawPrefix.slice(0, TOOL_TRANSCRIPT_OUTPUT_MAX_CHARS)
1329
- };
1330
- if (signature.streamedDisplay) existing.streamedRawSignature = next;
1331
- else {
1332
- const matchIndex = existing.rawSignatures.findIndex((entry) => entry.prefix === next.prefix);
1333
- if (matchIndex >= 0) existing.rawSignatures[matchIndex] = next;
1334
- else {
1335
- if (existing.rawSignatures.length >= 24) existing.rawSignatures.shift();
1336
- existing.rawSignatures.push(next);
1337
- }
1338
- }
1339
- }
1340
- this.echoesByItem.set(itemId, existing);
1341
- }
1342
- };
1343
- //#endregion
1344
- //#region extensions/codex/src/app-server/session-history.ts
1345
- /**
1346
- * Reads OpenClaw session history for Codex transcript mirroring and sanitizes
1347
- * image payloads before replaying messages into the app-server projector.
1348
- */
1349
- function isMissingFileError(error) {
1350
- return Boolean(error && typeof error === "object" && "code" in error && error.code === "ENOENT");
1351
- }
1352
- /** Returns sanitized session-context messages for a Codex mirrored session file. */
1353
- async function readCodexMirroredSessionHistoryMessages(target) {
1354
- try {
1355
- const entries = await readCodexMirroredSessionEntries(target);
1356
- if (entries.length === 0) return [];
1357
- const firstEntry = entries[0];
1358
- if (firstEntry?.type !== "session") return [];
1359
- if (typeof firstEntry.id !== "string") return;
1360
- migrateSessionEntries(entries);
1361
- return sanitizeCodexHistoryImagePayloads(buildSessionContext(entries.filter((entry) => {
1362
- return entry !== null && typeof entry === "object" && !Array.isArray(entry) && entry.type !== "session";
1363
- })).messages, "codex mirrored history");
1364
- } catch (error) {
1365
- if (isMissingFileError(error)) return [];
1366
- return;
1367
- }
1368
- }
1369
- async function readCodexMirroredSessionEntries(target) {
1370
- const sqliteMarker = parseSqliteSessionFileMarker(target.sessionFile);
1371
- if (sqliteMarker) {
1372
- if (sqliteMarker.sessionId !== target.sessionId || target.agentId !== void 0 && sqliteMarker.agentId !== target.agentId) return [];
1373
- const sessionKey = resolveSqliteMarkerSessionKey(target, sqliteMarker);
1374
- if (!sessionKey) return [];
1375
- return await readSessionTranscriptEvents({
1376
- agentId: sqliteMarker.agentId,
1377
- sessionId: sqliteMarker.sessionId,
1378
- sessionKey,
1379
- storePath: sqliteMarker.storePath
1380
- });
1381
- }
1382
- return parseSessionEntries(await fs.readFile(target.sessionFile, "utf-8"));
1383
- }
1384
- function resolveSqliteMarkerSessionKey(target, marker) {
1385
- const explicitSessionKey = target.sessionKey?.trim();
1386
- if (explicitSessionKey) return explicitSessionKey;
1387
- const entries = listSessionEntries({
1388
- agentId: marker.agentId,
1389
- storePath: marker.storePath
1390
- });
1391
- return (entries.find(({ entry }) => {
1392
- return entry.sessionId === marker.sessionId && entry.sessionFile === target.sessionFile;
1393
- }) ?? entries.find(({ entry }) => {
1394
- return entry.sessionId === marker.sessionId;
1395
- }))?.sessionKey;
1396
- }
1397
- //#endregion
1398
- //#region extensions/codex/src/app-server/event-projector-tool-transcript.ts
1399
- const ZERO_USAGE = {
1400
- input: 0,
1401
- output: 0,
1402
- cacheRead: 0,
1403
- cacheWrite: 0,
1404
- totalTokens: 0,
1405
- cost: {
1406
- input: 0,
1407
- output: 0,
1408
- cacheRead: 0,
1409
- cacheWrite: 0,
1410
- total: 0
1411
- }
1412
- };
1413
- const MISSING_TOOL_RESULT_ERROR = "OpenClaw recorded a native Codex tool.call without a matching tool.result before the turn completed.";
1414
- var CodexToolTranscriptProjection = class {
1415
- constructor(params, threadId, turnId, progress, options = {}) {
1416
- this.params = params;
1417
- this.threadId = threadId;
1418
- this.turnId = turnId;
1419
- this.progress = progress;
1420
- this.options = options;
1421
- this.messages = [];
1422
- this.callIds = /* @__PURE__ */ new Set();
1423
- this.resultIds = /* @__PURE__ */ new Set();
1424
- this.namesById = /* @__PURE__ */ new Map();
1425
- this.trajectoryCallIds = /* @__PURE__ */ new Set();
1426
- this.trajectoryResultIds = /* @__PURE__ */ new Set();
1427
- this.trajectoryNamesById = /* @__PURE__ */ new Map();
1428
- this.trajectoryItemsById = /* @__PURE__ */ new Map();
1429
- this.afterToolCallObservedItemIds = /* @__PURE__ */ new Set();
1430
- }
1431
- get transcriptMessages() {
1432
- return this.messages;
1433
- }
1434
- recordDynamicToolCall(params) {
1435
- this.recordToolCall({
1436
- id: params.callId,
1437
- name: params.tool,
1438
- arguments: sanitizeCodexToolArguments(params.arguments)
1439
- });
1440
- }
1441
- recordDynamicToolResult(params) {
1442
- this.recordToolResult({
1443
- id: params.callId,
1444
- name: params.tool,
1445
- text: collectDynamicToolContentText(params.contentItems),
1446
- isError: !params.success
1447
- });
1448
- }
1449
- recordNativeToolCall(item) {
1450
- if (!item || !shouldRecordNativeToolTranscript(item)) return;
1451
- const name = itemName(item);
1452
- if (name) this.recordToolCall({
1453
- id: item.id,
1454
- name,
1455
- arguments: itemToolArgs(item)
1456
- });
1457
- }
1458
- recordNativeToolResult(item) {
1459
- if (!item || !shouldRecordNativeToolTranscript(item)) return;
1460
- const name = itemName(item);
1461
- if (name) this.recordToolResult({
1462
- id: item.id,
1463
- name,
1464
- text: itemTranscriptResultText(item, this.progress.outputTextByItem),
1465
- isError: isNonSuccessItemStatus(itemStatus(item))
1466
- });
1467
- }
1468
- recordTrajectoryEvent(params) {
1469
- if (params.phase === "start") {
1470
- this.trajectoryCallIds.add(params.item.id);
1471
- this.trajectoryNamesById.set(params.item.id, params.name);
1472
- this.trajectoryItemsById.set(params.item.id, params.item);
1473
- this.options.trajectoryRecorder?.recordEvent("tool.call", {
1474
- threadId: this.threadId,
1475
- turnId: this.turnId,
1476
- itemId: params.item.id,
1477
- toolCallId: params.item.id,
1478
- name: params.name,
1479
- arguments: params.args
1480
- });
1481
- return;
1482
- }
1483
- this.trajectoryResultIds.add(params.item.id);
1484
- const toolResult = itemToolResult(params.item).result;
1485
- const output = itemOutputText(params.item, this.progress.outputTextByItem);
1486
- this.options.trajectoryRecorder?.recordEvent("tool.result", {
1487
- threadId: this.threadId,
1488
- turnId: this.turnId,
1489
- itemId: params.item.id,
1490
- toolCallId: params.item.id,
1491
- name: params.name,
1492
- status: params.status,
1493
- isError: isNonSuccessItemStatus(params.status),
1494
- ...toolResult ? { result: toolResult } : {},
1495
- ...output ? { output } : {}
1496
- });
1497
- }
1498
- emitAfterToolCallObservation(item) {
1499
- if (!this.shouldEmitAfterToolCallObservation(item)) return;
1500
- const name = itemName(item);
1501
- const status = itemStatus(item);
1502
- if (!name || status === "running") return;
1503
- this.afterToolCallObservedItemIds.add(item.id);
1504
- const result = itemToolResult(item).result;
1505
- const error = itemToolError(item, status, this.progress.outputTextByItem);
1506
- const startedAt = resolveStartedAtFromDurationMs(item.durationMs);
1507
- const hookParams = {
1508
- toolName: name,
1509
- toolCallId: item.id,
1510
- runId: this.params.runId,
1511
- agentId: this.params.agentId,
1512
- sessionId: this.params.sessionId,
1513
- sessionKey: this.params.sessionKey,
1514
- startArgs: itemToolArgs(item) ?? {},
1515
- ...result !== void 0 ? { result } : {},
1516
- ...error ? { error } : {},
1517
- ...startedAt !== void 0 ? { startedAt } : {}
1518
- };
1519
- setImmediate(() => {
1520
- runAgentHarnessAfterToolCallHook(hookParams);
1521
- });
1522
- }
1523
- synthesizeMissingToolResults(params) {
1524
- if (!params.synthesize) return;
1525
- const missingTranscriptIds = [...this.callIds].filter((id) => !this.resultIds.has(id));
1526
- const missingTrajectoryIds = [...this.trajectoryCallIds].filter((id) => !this.trajectoryResultIds.has(id));
1527
- if (missingTranscriptIds.length === 0 && missingTrajectoryIds.length === 0) return;
1528
- for (const id of missingTranscriptIds) {
1529
- const name = this.namesById.get(id) ?? this.trajectoryNamesById.get(id);
1530
- if (name) this.recordToolResult({
1531
- id,
1532
- name,
1533
- text: formatMissingToolResultError({
1534
- id,
1535
- name
1536
- }),
1537
- isError: true
1538
- });
1539
- }
1540
- for (const id of missingTrajectoryIds) {
1541
- const name = this.trajectoryNamesById.get(id) ?? this.namesById.get(id);
1542
- if (!name) continue;
1543
- this.trajectoryResultIds.add(id);
1544
- const text = formatMissingToolResultError({
1545
- id,
1546
- name
1547
- });
1548
- this.options.trajectoryRecorder?.recordEvent("tool.result", {
1549
- threadId: this.threadId,
1550
- turnId: this.turnId,
1551
- itemId: id,
1552
- toolCallId: id,
1553
- name,
1554
- status: "failed",
1555
- isError: true,
1556
- result: {
1557
- status: "failed",
1558
- reason: "missing_tool_result"
1559
- },
1560
- output: text
1561
- });
1562
- }
1563
- if (!params.recordPromptError) {
1564
- this.recordMissingToolError(missingTranscriptIds, missingTrajectoryIds);
1565
- return;
1566
- }
1567
- const missingCount = (/* @__PURE__ */ new Set([...missingTranscriptIds, ...missingTrajectoryIds])).size;
1568
- return missingCount === 1 ? MISSING_TOOL_RESULT_ERROR : `${MISSING_TOOL_RESULT_ERROR} missingToolResultCount=${missingCount}`;
1569
- }
1570
- async readMirroredSessionMessages() {
1571
- return await readCodexMirroredSessionHistoryMessages({
1572
- agentId: this.params.agentId,
1573
- sessionFile: this.params.sessionFile,
1574
- sessionId: this.params.sessionId,
1575
- sessionKey: this.params.sessionKey
1576
- }) ?? [];
1577
- }
1578
- recordToolCall(params) {
1579
- if (!params.id || !params.name || this.callIds.has(params.id)) return;
1580
- this.callIds.add(params.id);
1581
- this.namesById.set(params.id, params.name);
1582
- this.progress.recordTranscriptCall(params);
1583
- this.messages.push(attachCodexMirrorIdentity(this.createToolCallMessage(params), `${this.turnId}:tool:${params.id}:call`));
1584
- }
1585
- recordToolResult(params) {
1586
- if (!params.id || !params.name || this.resultIds.has(params.id)) return;
1587
- this.resultIds.add(params.id);
1588
- this.progress.recordTranscriptResult(params);
1589
- this.messages.push(attachCodexMirrorIdentity(this.createToolResultMessage(params), `${this.turnId}:tool:${params.id}:result`));
1590
- }
1591
- recordMissingToolError(missingTranscriptIds, missingTrajectoryIds) {
1592
- const firstMissingId = missingTranscriptIds.find((id) => Boolean(this.namesById.get(id))) ?? missingTrajectoryIds.find((id) => Boolean(this.trajectoryNamesById.get(id) ?? this.namesById.get(id)));
1593
- if (!firstMissingId) return;
1594
- const name = this.namesById.get(firstMissingId) ?? this.trajectoryNamesById.get(firstMissingId);
1595
- if (!name) return;
1596
- const item = this.trajectoryItemsById.get(firstMissingId);
1597
- const meta = item ? itemMeta(item, this.progress.toolProgressDetailMode()) : this.progress.getToolMeta(firstMissingId)?.meta;
1598
- const actionFingerprint = item ? nativeToolActionFingerprint(item) : void 0;
1599
- this.progress.setLastToolError({
1600
- toolName: name,
1601
- ...meta ? { meta } : {},
1602
- error: formatMissingToolResultError({
1603
- id: firstMissingId,
1604
- name
1605
- }),
1606
- ...item && isMutatingNativeToolItem(item) ? { mutatingAction: true } : {},
1607
- ...actionFingerprint ? { actionFingerprint } : {}
1608
- });
1609
- }
1610
- shouldEmitAfterToolCallObservation(item) {
1611
- if (!shouldSynthesizeToolProgressForItem(item) || this.afterToolCallObservedItemIds.has(item.id)) return false;
1612
- return !(this.options.nativePostToolUseRelayEnabled && isNativePostToolUseRelayItem(item));
1613
- }
1614
- createToolCallMessage(params) {
1615
- const args = normalizeToolTranscriptArguments(params.arguments);
1616
- const attribution = resolveCodexLocalRuntimeAttribution(this.params);
1617
- return {
1618
- role: "assistant",
1619
- content: [{
1620
- type: "toolCall",
1621
- id: params.id,
1622
- name: params.name,
1623
- arguments: args,
1624
- input: args
1625
- }],
1626
- api: attribution.api ?? "openai-chatgpt-responses",
1627
- provider: attribution.provider,
1628
- model: this.params.modelId,
1629
- usage: ZERO_USAGE,
1630
- stopReason: "toolUse",
1631
- timestamp: Date.now()
1632
- };
1633
- }
1634
- createToolResultMessage(params) {
1635
- const text = truncateToolTranscriptText(params.text?.trim() || toolResultStatusText(params));
1636
- return {
1637
- role: "toolResult",
1638
- toolCallId: params.id,
1639
- toolName: params.name,
1640
- isError: params.isError,
1641
- content: [{
1642
- type: "toolResult",
1643
- id: params.id,
1644
- name: params.name,
1645
- toolName: params.name,
1646
- toolCallId: params.id,
1647
- toolUseId: params.id,
1648
- tool_use_id: params.id,
1649
- content: text,
1650
- text
1651
- }],
1652
- timestamp: Date.now()
1653
- };
1654
- }
1655
- };
1656
- function formatMissingToolResultError(params) {
1657
- return `${MISSING_TOOL_RESULT_ERROR} toolCallId=${params.id}; toolName=${params.name}`;
1658
- }
1659
- function toolResultStatusText(params) {
1660
- return params.isError ? `${params.name} failed` : `${params.name} completed`;
1661
- }
1662
- function resolveStartedAtFromDurationMs(durationMs) {
1663
- if (typeof durationMs !== "number" || !Number.isFinite(durationMs)) return;
1664
- return asDateTimestampMs(Date.now() - Math.max(0, durationMs));
1665
- }
1666
- //#endregion
1667
- //#region extensions/codex/src/app-server/event-projector-events.ts
1668
- var CodexEventProjection = class {
1669
- constructor(threadId, turnId, emitAgentEvent, toolProgress, toolTranscript, onNativeToolResultRecorded) {
1670
- this.threadId = threadId;
1671
- this.turnId = turnId;
1672
- this.emitAgentEvent = emitAgentEvent;
1673
- this.toolProgress = toolProgress;
1674
- this.toolTranscript = toolTranscript;
1675
- this.onNativeToolResultRecorded = onNativeToolResultRecorded;
1676
- this.reviewCount = 0;
1677
- }
1678
- get guardianReviewCount() {
1679
- return this.reviewCount;
1680
- }
1681
- handleGuardianReview(method, params) {
1682
- this.reviewCount += 1;
1683
- const review = isJsonObject(params.review) ? params.review : void 0;
1684
- const action = isJsonObject(params.action) ? params.action : void 0;
1685
- this.emitAgentEvent({
1686
- stream: "codex_app_server.guardian",
1687
- data: {
1688
- method,
1689
- phase: method.endsWith("/started") ? "started" : "completed",
1690
- reviewId: readString$3(params, "reviewId"),
1691
- targetItemId: readNullableString(params, "targetItemId"),
1692
- decisionSource: readString$3(params, "decisionSource"),
1693
- status: review ? readString$3(review, "status") : void 0,
1694
- riskLevel: review ? readString$3(review, "riskLevel") : void 0,
1695
- userAuthorization: review ? readString$3(review, "userAuthorization") : void 0,
1696
- rationale: review ? readNullableString(review, "rationale") : void 0,
1697
- actionType: action ? readString$3(action, "type") : void 0
1698
- }
1699
- });
1700
- }
1701
- handleGuardianWarning(params) {
1702
- this.emitAgentEvent({
1703
- stream: "codex_app_server.guardian",
1704
- data: {
1705
- phase: "warning",
1706
- message: readString$3(params, "message")
1707
- }
1708
- });
1709
- }
1710
- handleHook(method, params) {
1711
- const run = isJsonObject(params.run) ? params.run : void 0;
1712
- if (!run) return;
1713
- const durationMs = readNumber(run, "durationMs");
1714
- const entries = readHookOutputEntries(run.entries);
1715
- const hookTurnId = readNullableString(params, "turnId");
1716
- this.emitAgentEvent({
1717
- stream: "codex_app_server.hook",
1718
- data: {
1719
- phase: method === "hook/started" ? "started" : "completed",
1720
- threadId: this.threadId,
1721
- turnId: hookTurnId === void 0 ? this.turnId : hookTurnId,
1722
- hookRunId: readString$3(run, "id"),
1723
- eventName: readString$3(run, "eventName"),
1724
- handlerType: readString$3(run, "handlerType"),
1725
- executionMode: readString$3(run, "executionMode"),
1726
- scope: readString$3(run, "scope"),
1727
- source: readString$3(run, "source"),
1728
- sourcePath: readString$3(run, "sourcePath"),
1729
- status: readString$3(run, "status"),
1730
- statusMessage: readNullableString(run, "statusMessage"),
1731
- ...durationMs !== void 0 ? { durationMs } : {},
1732
- ...entries.length > 0 ? { entries } : {}
1733
- }
1734
- });
1735
- }
1736
- emitStandardItemEvent(params) {
1737
- const { item } = params;
1738
- if (!item) return;
1739
- const kind = itemKind(item);
1740
- if (!kind) return;
1741
- const meta = itemMeta(item, this.toolProgress.toolProgressDetailMode());
1742
- const suppressChannelProgress = shouldSuppressChannelProgressForItem(item);
1743
- this.emitAgentEvent({
1744
- stream: "item",
1745
- data: {
1746
- itemId: item.id,
1747
- phase: params.phase,
1748
- kind,
1749
- title: itemTitle(item),
1750
- status: params.phase === "start" ? "running" : itemStatus(item),
1751
- ...itemName(item) ? { name: itemName(item) } : {},
1752
- ...meta ? { meta } : {},
1753
- ...suppressChannelProgress ? { suppressChannelProgress: true } : {}
1754
- }
1755
- });
1756
- }
1757
- async emitNormalizedToolItemEvent(params) {
1758
- const { item } = params;
1759
- if (!item || !shouldSynthesizeToolProgressForItem(item)) return;
1760
- const name = itemName(item);
1761
- if (!name) return;
1762
- const status = params.phase === "result" ? itemStatus(item) : "running";
1763
- const args = itemToolArgs(item);
1764
- const meta = itemMeta(item, this.toolProgress.toolProgressDetailMode());
1765
- this.toolTranscript.recordTrajectoryEvent({
1766
- phase: params.phase,
1767
- item,
1768
- name,
1769
- args,
1770
- status
1771
- });
1772
- if (params.phase === "result") this.toolProgress.recordNativeToolError({
1773
- item,
1774
- name,
1775
- meta,
1776
- status
1777
- });
1778
- if (!shouldEmitTranscriptToolProgress(name, args)) {
1779
- if (params.phase === "result") {
1780
- this.toolTranscript.emitAfterToolCallObservation(item);
1781
- await this.onNativeToolResultRecorded?.();
1782
- }
1783
- return;
1784
- }
1785
- this.emitAgentEvent({
1786
- stream: "tool",
1787
- data: {
1788
- phase: params.phase,
1789
- name,
1790
- itemId: item.id,
1791
- toolCallId: item.id,
1792
- ...meta ? { meta } : {},
1793
- ...params.phase === "start" && args ? { args } : {},
1794
- ...params.phase === "result" ? {
1795
- status,
1796
- isError: isNonSuccessItemStatus(status),
1797
- ...itemToolResult(item)
1798
- } : {}
1799
- }
1800
- });
1801
- if (params.phase === "result") {
1802
- this.toolTranscript.emitAfterToolCallObservation(item);
1803
- await this.onNativeToolResultRecorded?.();
1804
- }
1805
- }
1806
- };
1807
- //#endregion
1808
- //#region extensions/codex/src/app-server/event-projector-media.ts
1809
- const GENERATED_IMAGE_MEDIA_SUBDIR = "tool-image-generation";
1810
- const BYTES_PER_MB = 1024 * 1024;
1811
- const DEFAULT_GENERATED_IMAGE_MAX_BYTES = 6 * BYTES_PER_MB;
1812
- var CodexGeneratedMediaProjection = class {
1813
- constructor(config) {
1814
- this.config = config;
1815
- this.itemIds = /* @__PURE__ */ new Set();
1816
- this.urlsByItemId = /* @__PURE__ */ new Map();
1817
- }
1818
- hasGeneratedMedia() {
1819
- return this.itemIds.size > 0;
1820
- }
1821
- recordNative(item) {
1822
- if (item?.type !== "imageGeneration") return;
1823
- const savedPath = readItemString(item, "savedPath")?.trim();
1824
- if (savedPath) this.recordUrl({
1825
- itemId: item.id,
1826
- mediaUrl: savedPath
1827
- });
1828
- }
1829
- async recordRaw(item) {
1830
- if (readString$3(item, "type") !== "image_generation_call") return;
1831
- const result = readString$3(item, "result");
1832
- if (!result) return;
1833
- const itemId = readString$3(item, "id") ?? `raw-image-${this.itemIds.size}`;
1834
- this.itemIds.add(itemId);
1835
- const maxBytes = resolveGeneratedImageMaxBytes(this.config);
1836
- const estimatedDecodedBytes = estimateBase64DecodedBytes(result);
1837
- if (estimatedDecodedBytes !== void 0 && estimatedDecodedBytes > maxBytes) {
1838
- embeddedAgentLog.warn("codex app-server raw image generation result exceeds media limit", {
1839
- itemId,
1840
- estimatedDecodedBytes,
1841
- maxBytes
1842
- });
1843
- return;
1844
- }
1845
- const asset = generatedImageAssetFromBase64({
1846
- base64: result,
1847
- index: this.itemIds.size,
1848
- revisedPrompt: readString$3(item, "revised_prompt") ?? readString$3(item, "revisedPrompt"),
1849
- fileNamePrefix: "codex-image-generation",
1850
- sniffMimeType: true
1851
- });
1852
- if (!asset) return;
1853
- try {
1854
- const saved = await saveMediaBuffer(asset.buffer, asset.mimeType, GENERATED_IMAGE_MEDIA_SUBDIR, maxBytes, asset.fileName);
1855
- this.recordUrl({
1856
- itemId,
1857
- mediaUrl: saved.path,
1858
- replaceExisting: true
1859
- });
1860
- } catch (error) {
1861
- embeddedAgentLog.warn("codex app-server raw image generation result save failed", {
1862
- itemId,
1863
- error
1864
- });
1865
- }
1866
- }
1867
- buildToolMediaUrls(params) {
1868
- const mediaUrls = new Set(params.toolMediaUrls?.map((url) => url.trim()).filter(Boolean) ?? []);
1869
- if ((params.messagingToolSentMediaUrls?.length ?? 0) === 0) for (const mediaUrl of this.urlsByItemId.values()) mediaUrls.add(mediaUrl);
1870
- return mediaUrls.size > 0 ? [...mediaUrls] : params.toolMediaUrls;
1871
- }
1872
- recordUrl(params) {
1873
- if (this.urlsByItemId.has(params.itemId) && params.replaceExisting !== true) {
1874
- this.itemIds.add(params.itemId);
1875
- return;
1876
- }
1877
- this.urlsByItemId.set(params.itemId, params.mediaUrl);
1878
- this.itemIds.add(params.itemId);
70
+ if (status === "declined") return "blocked";
71
+ return "unknown";
72
+ }
73
+ function auditNativeToolUnfinishedStatus(item) {
74
+ return item.type === "webSearch" || item.type === "imageGeneration" ? "unknown" : "failed";
75
+ }
76
+ function isNonSuccessItemStatus(status) {
77
+ return status === "failed" || status === "blocked";
78
+ }
79
+ function itemName(item) {
80
+ if (item.type === "dynamicToolCall" && typeof item.tool === "string") return item.tool;
81
+ if (item.type === "mcpToolCall" && typeof item.tool === "string") {
82
+ const server = typeof item.server === "string" ? item.server : void 0;
83
+ return server ? `${server}.${item.tool}` : item.tool;
1879
84
  }
1880
- };
1881
- function estimateBase64DecodedBytes(base64) {
1882
- let nonWhitespaceLength = 0;
1883
- let previousCode = -1;
1884
- let lastCode = -1;
1885
- for (let i = 0; i < base64.length; i += 1) {
1886
- const code = base64.charCodeAt(i);
1887
- if (isBase64WhitespaceCode(code)) continue;
1888
- nonWhitespaceLength += 1;
1889
- previousCode = lastCode;
1890
- lastCode = code;
85
+ if (item.type === "commandExecution") return "bash";
86
+ if (item.type === "fileChange") return "apply_patch";
87
+ if (item.type === "webSearch") return "web_search";
88
+ }
89
+ function auditNativeToolName(item) {
90
+ if (item.type === "dynamicToolCall") return;
91
+ const progressName = itemName(item);
92
+ if (progressName) return progressName;
93
+ if (item.type === "collabAgentToolCall") return typeof item.tool === "string" && item.tool.trim() ? `collab.${item.tool.trim()}` : "collab_agent";
94
+ if (item.type === "imageGeneration") return "image_generation";
95
+ if (item.type === "imageView") return "image_view";
96
+ if (item.type === "sleep") return "sleep";
97
+ }
98
+ function isSideEffectingNativeToolItem(item) {
99
+ return itemStatus(item) !== "blocked" && (isMutatingNativeToolItem(item) || item.type === "mcpToolCall");
100
+ }
101
+ function shouldSynthesizeToolProgressForItem(item) {
102
+ switch (item.type) {
103
+ case "commandExecution":
104
+ case "fileChange":
105
+ case "webSearch":
106
+ case "mcpToolCall": return true;
107
+ default: return false;
1891
108
  }
1892
- if (nonWhitespaceLength === 0) return;
1893
- const equalsCode = "=".charCodeAt(0);
1894
- const padding = lastCode === equalsCode ? previousCode === equalsCode ? 2 : 1 : 0;
1895
- return Math.max(0, Math.floor(nonWhitespaceLength * 3 / 4) - padding);
1896
109
  }
1897
- function isBase64WhitespaceCode(code) {
1898
- return code === 32 || code === 9 || code === 10 || code === 13;
110
+ function shouldRecordNativeToolTranscript(item) {
111
+ return shouldSynthesizeToolProgressForItem(item) && item.type !== "webSearch";
112
+ }
113
+ function isMutatingNativeToolItem(item) {
114
+ if (item.type === "commandExecution") return true;
115
+ return item.type === "fileChange" || item.type === "collabAgentToolCall" || item.type === "imageGeneration";
1899
116
  }
1900
- function resolveGeneratedImageMaxBytes(config) {
1901
- const configured = config?.agents?.defaults?.mediaMaxMb;
1902
- if (typeof configured === "number" && Number.isFinite(configured) && configured > 0) return Math.floor(configured * BYTES_PER_MB);
1903
- return DEFAULT_GENERATED_IMAGE_MAX_BYTES;
117
+ function shouldClearTerminalPresentationForNativeItem(item) {
118
+ switch (item.type) {
119
+ case "collabAgentToolCall":
120
+ case "commandExecution":
121
+ case "fileChange":
122
+ case "imageGeneration":
123
+ case "imageView":
124
+ case "mcpToolCall":
125
+ case "webSearch": return true;
126
+ default: return false;
127
+ }
1904
128
  }
1905
129
  //#endregion
1906
130
  //#region extensions/codex/src/app-server/dynamic-tool-response-state.ts
131
+ /** Retains the host-owned app preview without adding it to Codex's response payload. */
132
+ function withDynamicToolTranscriptDetails(response, details) {
133
+ if (!details || typeof details !== "object" || Array.isArray(details)) return response;
134
+ const mcpAppPreview = details.mcpAppPreview;
135
+ if (!mcpAppPreview || typeof mcpAppPreview !== "object" || Array.isArray(mcpAppPreview)) return response;
136
+ Object.defineProperty(response, "transcriptDetails", {
137
+ configurable: true,
138
+ enumerable: false,
139
+ value: { mcpAppPreview }
140
+ });
141
+ return response;
142
+ }
1907
143
  function withDynamicToolTerminalResolution(response, terminalResolution) {
1908
144
  if (terminalResolution) {
1909
145
  Object.defineProperties(response, {
@@ -2029,7 +265,9 @@ const CODEX_DYNAMIC_COMPUTER_COMPLETION_GRACE_MS = 3e4;
2029
265
  /** Timeout for image-understanding style dynamic tool calls. */
2030
266
  const CODEX_DYNAMIC_IMAGE_TOOL_TIMEOUT_MS = 6e4;
2031
267
  /** Timeout for message-delivery dynamic tool calls. */
2032
- const CODEX_DYNAMIC_MESSAGE_TOOL_TIMEOUT_MS = CODEX_DYNAMIC_TOOL_MAX_TIMEOUT_MS;
268
+ const CODEX_DYNAMIC_MESSAGE_TOOL_TIMEOUT_MS = 6e5;
269
+ /** Outer default for collector waits: full swarm budget plus completion grace. */
270
+ const CODEX_DYNAMIC_AGENTS_WAIT_TOOL_TIMEOUT_MS = 63e4;
2033
271
  const LOG_FIELD_MAX_LENGTH = 160;
2034
272
  function normalizeLogField(value) {
2035
273
  if (typeof value !== "string") return;
@@ -2217,13 +455,16 @@ function toCodexDynamicToolProtocolResponse(response) {
2217
455
  }
2218
456
  /** Adds async-started progress details when a tool result continues out of band. */
2219
457
  function toCodexDynamicToolProgressResponse(response, protocolResponse) {
2220
- if (response.asyncStarted !== true) return protocolResponse;
458
+ const transcriptDetails = response.transcriptDetails;
459
+ if (response.asyncStarted !== true && transcriptDetails === void 0) return protocolResponse;
2221
460
  return {
2222
461
  ...protocolResponse,
2223
- details: {
462
+ ...transcriptDetails ? { details: transcriptDetails } : {},
463
+ ...response.asyncStarted === true ? { details: {
464
+ ...transcriptDetails,
2224
465
  async: true,
2225
466
  status: "started"
2226
- }
467
+ } } : {}
2227
468
  };
2228
469
  }
2229
470
  /** Decides whether a terminal dynamic tool response can release the Codex turn. */
@@ -2270,6 +511,10 @@ function hasPendingDynamicToolTerminalDiagnostic(params) {
2270
511
  function resolveDynamicToolCallTimeoutMs(params) {
2271
512
  if (params.call.tool === "computer") return clampDynamicToolTimeoutMs(readComputerToolTimeoutMs(params.call.arguments));
2272
513
  if (params.call.tool === "message") return CODEX_DYNAMIC_MESSAGE_TOOL_TIMEOUT_MS;
514
+ if (params.call.tool === "agents_wait") {
515
+ const requestedMs = readDynamicToolCallTimeoutMs(params.call.arguments) ?? readConfiguredDynamicToolTimeoutMs(params.call.tool, params.config) ?? CODEX_DYNAMIC_AGENTS_WAIT_TOOL_TIMEOUT_MS;
516
+ return Math.max(1, Math.min(63e4, Math.floor(requestedMs)));
517
+ }
2273
518
  return clampDynamicToolTimeoutMs(readDynamicToolCallTimeoutMs(params.call.arguments) ?? readConfiguredDynamicToolTimeoutMs(params.call.tool, params.config) ?? CODEX_DYNAMIC_TOOL_TIMEOUT_MS);
2274
519
  }
2275
520
  function readComputerToolTimeoutMs(value) {
@@ -2288,11 +533,15 @@ function readDynamicToolCallTimeoutMs(value) {
2288
533
  }
2289
534
  function readConfiguredDynamicToolTimeoutMs(toolName, config) {
2290
535
  if (toolName === "image_generate") {
2291
- const imageGenerationModel = config?.agents?.defaults?.imageGenerationModel;
2292
- if (!imageGenerationModel || typeof imageGenerationModel !== "object") return CODEX_DYNAMIC_IMAGE_GENERATION_TOOL_TIMEOUT_MS;
2293
- return readPositiveFiniteTimeoutMs(imageGenerationModel.timeoutMs) ?? CODEX_DYNAMIC_IMAGE_GENERATION_TOOL_TIMEOUT_MS;
536
+ const imageModel = config?.agents?.defaults?.mediaModels?.image;
537
+ if (!imageModel || typeof imageModel !== "object") return CODEX_DYNAMIC_IMAGE_GENERATION_TOOL_TIMEOUT_MS;
538
+ return readPositiveFiniteTimeoutMs(imageModel.timeoutMs) ?? CODEX_DYNAMIC_IMAGE_GENERATION_TOOL_TIMEOUT_MS;
539
+ }
540
+ if (toolName === "image") {
541
+ const candidates = (config?.tools?.media?.models ?? []).filter((entry) => !entry.capabilities || entry.capabilities.includes("image"));
542
+ const capabilityTimeoutMs = readTimeoutSecondsAsMs(config?.tools?.media?.image?.timeoutSeconds);
543
+ return Math.max(capabilityTimeoutMs ?? CODEX_DYNAMIC_IMAGE_TOOL_TIMEOUT_MS, ...candidates.map((entry) => readTimeoutSecondsAsMs(entry.timeoutSeconds) ?? capabilityTimeoutMs ?? CODEX_DYNAMIC_IMAGE_TOOL_TIMEOUT_MS));
2294
544
  }
2295
- if (toolName === "image") return readTimeoutSecondsAsMs(config?.tools?.media?.image?.timeoutSeconds) ?? CODEX_DYNAMIC_IMAGE_TOOL_TIMEOUT_MS;
2296
545
  if (toolName === "message") return CODEX_DYNAMIC_MESSAGE_TOOL_TIMEOUT_MS;
2297
546
  }
2298
547
  function readTimeoutSecondsAsMs(value) {
@@ -2412,6 +661,7 @@ function createCodexNativeHookRelay(params) {
2412
661
  ...params.config ? { config: params.config } : {},
2413
662
  runId: params.runId,
2414
663
  ...params.channelId ? { channelId: params.channelId } : {},
664
+ ...params.requester ? { requester: params.requester } : {},
2415
665
  allowedEvents: params.events,
2416
666
  preToolUseLoopDetection: params.loopDetectionPreToolUseRelay,
2417
667
  ttlMs: resolveCodexNativeHookRelayTtlMs({
@@ -2616,12 +866,12 @@ var CodexNativeToolLifecycleProjector = class {
2616
866
  this.preToolUseFailureByItem.set(failure.toolCallId, record);
2617
867
  }
2618
868
  recordRawWebSearchResult(item) {
2619
- if (readString$3(item, "type") !== "web_search_call") return;
2620
- const toolCallId = readString$3(item, "id");
869
+ if (readString$2(item, "type") !== "web_search_call") return;
870
+ const toolCallId = readString$2(item, "id");
2621
871
  if (!toolCallId || this.completedItemIds.has(toolCallId)) return;
2622
872
  const toolName = "web_search";
2623
873
  this.recordStarted(toolCallId, toolName, "unknown");
2624
- const rawStatus = readString$3(item, "status");
874
+ const rawStatus = readString$2(item, "status");
2625
875
  if (rawStatus === "in_progress" || rawStatus === "running") return;
2626
876
  const status = rawStatus === "completed" ? "completed" : rawStatus === "cancelled" ? "cancelled" : rawStatus === "failed" || rawStatus === "error" || rawStatus === "incomplete" ? "failed" : "unknown";
2627
877
  this.recordTerminal(toolCallId, toolName, status, { sourceTimestampMs: this.webSearchCompletionByItem.get(toolCallId)?.sourceTimestampMs });
@@ -2734,815 +984,6 @@ var CodexNativeToolLifecycleProjector = class {
2734
984
  }
2735
985
  };
2736
986
  //#endregion
2737
- //#region extensions/codex/src/app-server/event-projector-reasoning.ts
2738
- var CodexReasoningProjection = class {
2739
- constructor(params, emitAgentEvent) {
2740
- this.params = params;
2741
- this.emitAgentEvent = emitAgentEvent;
2742
- this.reasoningTextByGroup = /* @__PURE__ */ new Map();
2743
- this.reasoningItemOrder = /* @__PURE__ */ new Map();
2744
- this.planTextByItem = /* @__PURE__ */ new Map();
2745
- this.reasoningStarted = false;
2746
- this.reasoningEnded = false;
2747
- }
2748
- async handleReasoningDelta(method, params) {
2749
- const itemId = readString$3(params, "itemId") ?? "reasoning";
2750
- const delta = readString$3(params, "delta") ?? "";
2751
- if (!delta) return;
2752
- this.reasoningStarted = true;
2753
- if (!this.reasoningItemOrder.has(itemId)) this.reasoningItemOrder.set(itemId, this.reasoningItemOrder.size);
2754
- const groupIndex = method === "item/reasoning/textDelta" ? readNonNegativeInteger(params, "contentIndex") ?? 0 : readNonNegativeInteger(params, "summaryIndex") ?? 0;
2755
- const groupKey = `${method}\0${itemId}\0${groupIndex}`;
2756
- const current = this.reasoningTextByGroup.get(groupKey);
2757
- this.reasoningTextByGroup.set(groupKey, {
2758
- itemId,
2759
- method,
2760
- index: groupIndex,
2761
- text: `${current?.text ?? ""}${delta}`
2762
- });
2763
- await this.params.onReasoningStream?.({
2764
- text: this.reasoningText(),
2765
- isReasoningSnapshot: true
2766
- });
2767
- }
2768
- handlePlanDelta(params) {
2769
- const itemId = readString$3(params, "itemId") ?? "plan";
2770
- const delta = readString$3(params, "delta") ?? "";
2771
- if (!delta) return;
2772
- const text = `${this.planTextByItem.get(itemId) ?? ""}${delta}`;
2773
- this.planTextByItem.set(itemId, text);
2774
- this.emitPlanUpdate({
2775
- explanation: void 0,
2776
- steps: splitPlanText(text).map((step) => ({
2777
- step,
2778
- status: "pending"
2779
- }))
2780
- });
2781
- }
2782
- handleTurnPlanUpdated(params) {
2783
- const explanation = readNullableString(params, "explanation");
2784
- const plan = Array.isArray(params.plan) ? params.plan.flatMap((entry) => {
2785
- if (!entry || typeof entry !== "object" || Array.isArray(entry)) return [];
2786
- const record = entry;
2787
- const step = readString$3(record, "step");
2788
- if (!step) return [];
2789
- return [{
2790
- step,
2791
- status: normalizePlanStepStatus(readString$3(record, "status"))
2792
- }];
2793
- }) : void 0;
2794
- const planText = [explanation, ...(plan ?? []).map(({ step, status }) => `- [${status}] ${step}`)].filter((part) => Boolean(part)).join("\n");
2795
- if (planText) this.turnPlanText = planText;
2796
- this.emitPlanUpdate({
2797
- explanation,
2798
- steps: plan
2799
- });
2800
- }
2801
- recordItem(item) {
2802
- if (item?.type === "plan" && typeof item.text === "string" && item.text) {
2803
- this.planTextByItem.set(item.id, item.text);
2804
- this.emitPlanUpdate({
2805
- explanation: void 0,
2806
- steps: splitPlanText(item.text).map((step) => ({
2807
- step,
2808
- status: "pending"
2809
- }))
2810
- });
2811
- }
2812
- }
2813
- async maybeEndReasoning() {
2814
- if (!this.reasoningStarted || this.reasoningEnded) return;
2815
- this.reasoningEnded = true;
2816
- await this.params.onReasoningEnd?.();
2817
- }
2818
- reasoningText() {
2819
- return collectReasoningTextValues(this.reasoningTextByGroup, this.reasoningItemOrder).join("\n\n");
2820
- }
2821
- planText() {
2822
- return this.turnPlanText ?? [...this.planTextByItem.values()].filter((text) => text.trim().length > 0).join("\n\n");
2823
- }
2824
- emitPlanUpdate(params) {
2825
- if (!params.explanation && (!params.steps || params.steps.length === 0)) return;
2826
- this.emitAgentEvent({
2827
- stream: "plan",
2828
- data: {
2829
- phase: "update",
2830
- title: "Plan updated",
2831
- source: "codex-app-server",
2832
- ...params.explanation ? { explanation: params.explanation } : {},
2833
- ...params.steps && params.steps.length > 0 ? { steps: params.steps } : {}
2834
- }
2835
- });
2836
- }
2837
- };
2838
- function normalizePlanStepStatus(status) {
2839
- if (status === "inProgress" || status === "in_progress") return "in_progress";
2840
- return status === "completed" ? "completed" : "pending";
2841
- }
2842
- function collectReasoningTextValues(groups, itemOrder) {
2843
- return [...groups.values()].toSorted((left, right) => {
2844
- const itemDelta = (itemOrder.get(left.itemId) ?? Number.MAX_SAFE_INTEGER) - (itemOrder.get(right.itemId) ?? Number.MAX_SAFE_INTEGER);
2845
- if (itemDelta !== 0) return itemDelta;
2846
- const methodDelta = reasoningMethodOrder(left.method) - reasoningMethodOrder(right.method);
2847
- return methodDelta !== 0 ? methodDelta : left.index - right.index;
2848
- }).map((group) => group.text).filter((text) => text.trim().length > 0);
2849
- }
2850
- function reasoningMethodOrder(method) {
2851
- return method === "item/reasoning/summaryTextDelta" ? 0 : 1;
2852
- }
2853
- //#endregion
2854
- //#region extensions/codex/src/app-server/event-projector-usage.ts
2855
- function readTokenCount(record, key) {
2856
- const value = readNonNegativeInteger(record, key);
2857
- return value !== void 0 && Number.isSafeInteger(value) ? value : void 0;
2858
- }
2859
- function readCodexThreadTokenUsage(params) {
2860
- const tokenUsage = isJsonObject(params.tokenUsage) ? params.tokenUsage : void 0;
2861
- const last = tokenUsage && isJsonObject(tokenUsage.last) ? tokenUsage.last : void 0;
2862
- return last ? normalizeCodexThreadTokenUsage(last) : void 0;
2863
- }
2864
- function normalizeCodexThreadTokenUsage(record) {
2865
- const inputTokens = readNumber(record, "inputTokens");
2866
- const cacheRead = readNumber(record, "cachedInputTokens");
2867
- const usage = normalizeUsage({
2868
- input: inputTokens !== void 0 && cacheRead !== void 0 ? Math.max(0, inputTokens - cacheRead) : inputTokens,
2869
- output: readNumber(record, "outputTokens"),
2870
- cacheRead,
2871
- total: readNumber(record, "totalTokens")
2872
- });
2873
- return usage ? {
2874
- ...usage,
2875
- contextUsage: { state: "unavailable" }
2876
- } : void 0;
2877
- }
2878
- function normalizeCodexResponseTokenUsage(record) {
2879
- const totalTokens = readTokenCount(record, "totalTokens");
2880
- const inputTokens = readTokenCount(record, "inputTokens");
2881
- const cacheRead = readTokenCount(record, "cachedInputTokens");
2882
- const output = readTokenCount(record, "outputTokens");
2883
- const reasoningOutput = readTokenCount(record, "reasoningOutputTokens");
2884
- const cacheWrite = record.cacheWriteInputTokens === void 0 ? 0 : readTokenCount(record, "cacheWriteInputTokens");
2885
- if (totalTokens === void 0 || inputTokens === void 0 || cacheRead === void 0 || cacheWrite === void 0 || output === void 0 || reasoningOutput === void 0 || cacheRead + cacheWrite > inputTokens || totalTokens !== inputTokens + output) return;
2886
- const usage = normalizeUsage({
2887
- input: inputTokens - cacheRead - cacheWrite,
2888
- output,
2889
- cacheRead,
2890
- cacheWrite,
2891
- total: totalTokens
2892
- });
2893
- if (!usage) return;
2894
- return {
2895
- ...usage,
2896
- contextUsage: {
2897
- state: "available",
2898
- promptTokens: inputTokens,
2899
- totalTokens
2900
- }
2901
- };
2902
- }
2903
- //#endregion
2904
- //#region extensions/codex/src/app-server/usage-limit-error.ts
2905
- /**
2906
- * Enriches Codex usage-limit failures with current rate-limit information and
2907
- * marks blocked auth profiles when Codex exposes a reset time.
2908
- */
2909
- const CODEX_USAGE_LIMIT_RATE_LIMIT_REFRESH_TIMEOUT_MS = 5e3;
2910
- function createCodexUsageLimitPromptError(message) {
2911
- return Object.assign(new Error(message), { status: 429 });
2912
- }
2913
- function isCodexUsageLimitPromptError(error) {
2914
- return error instanceof Error && "status" in error && error.status === 429;
2915
- }
2916
- /** Marks a Codex auth profile blocked until the reset time advertised by rate limits. */
2917
- async function markCodexAuthProfileBlockedFromRateLimits(params) {
2918
- const authProfileId = params.authProfileId?.trim();
2919
- if (!authProfileId || !params.params.authProfileStore) return;
2920
- const blockedUntil = resolveCodexUsageLimitResetAtMs(params.rateLimits);
2921
- if (!blockedUntil) return;
2922
- try {
2923
- await markAuthProfileBlockedUntil({
2924
- store: params.params.authProfileStore,
2925
- profileId: authProfileId,
2926
- blockedUntil,
2927
- source: "codex_rate_limits",
2928
- agentDir: params.params.agentDir,
2929
- runId: params.params.runId,
2930
- modelId: params.params.modelId
2931
- });
2932
- } catch (error) {
2933
- embeddedAgentLog.debug("failed to mark Codex auth profile blocked from app-server limits", {
2934
- authProfileId,
2935
- error: formatErrorMessage(error)
2936
- });
2937
- }
2938
- }
2939
- /** Formats a turn-start usage-limit error, refreshing rate limits when needed. */
2940
- async function formatCodexTurnStartUsageLimitError(params) {
2941
- return refreshCodexUsageLimitError({
2942
- client: params.client,
2943
- source: readCodexTurnStartUsageLimitErrorSource(params.client, params.error, params.errorNotification, params.rateLimitsRevisionBeforeTurnStart),
2944
- timeoutMs: params.timeoutMs,
2945
- signal: params.signal
2946
- });
2947
- }
2948
- /** Refreshes a generic prompt usage-limit message into a reset-aware message. */
2949
- async function refreshCodexUsageLimitPromptError(params) {
2950
- if (!shouldRefreshCodexRateLimitsForUsageLimitMessage(params.message)) return;
2951
- return refreshCodexUsageLimitError({
2952
- client: params.client,
2953
- source: {
2954
- message: params.message,
2955
- codexErrorInfo: "usageLimitExceeded",
2956
- rateLimits: readRecentCodexRateLimits(params.client)
2957
- },
2958
- timeoutMs: params.timeoutMs,
2959
- signal: params.signal
2960
- });
2961
- }
2962
- async function refreshCodexUsageLimitError(params) {
2963
- const initialMessage = formatCodexUsageLimitErrorMessage(params.source);
2964
- if (!shouldRefreshCodexRateLimitsForUsageLimitMessage(initialMessage)) return initialMessage ? {
2965
- message: initialMessage,
2966
- ...params.source.rateLimitsTrustedForProfile ? { rateLimitsForProfile: params.source.rateLimits } : {}
2967
- } : void 0;
2968
- const rateLimits = await readCodexRateLimitsFromAppServerForUsageLimitError({
2969
- client: params.client,
2970
- timeoutMs: params.timeoutMs,
2971
- signal: params.signal
2972
- });
2973
- if (!rateLimits) return initialMessage ? {
2974
- message: initialMessage,
2975
- ...params.source.rateLimitsTrustedForProfile ? { rateLimitsForProfile: params.source.rateLimits } : {}
2976
- } : void 0;
2977
- const message = formatCodexUsageLimitErrorMessage({
2978
- message: params.source.message,
2979
- codexErrorInfo: params.source.codexErrorInfo,
2980
- rateLimits,
2981
- rateLimitsAuthoritative: true
2982
- }) ?? initialMessage;
2983
- return message ? {
2984
- message,
2985
- rateLimitsForProfile: rateLimits
2986
- } : void 0;
2987
- }
2988
- async function readCodexRateLimitsFromAppServerForUsageLimitError(params) {
2989
- if (params.signal?.aborted) return;
2990
- try {
2991
- const rateLimits = await params.client.request(CODEX_CONTROL_METHODS.rateLimits, void 0, {
2992
- timeoutMs: resolveCodexUsageLimitRateLimitRefreshTimeoutMs(params.timeoutMs),
2993
- signal: params.signal
2994
- });
2995
- rememberCodexRateLimitsRead(params.client, rateLimits);
2996
- return rateLimits;
2997
- } catch (error) {
2998
- embeddedAgentLog.debug("codex app-server rate-limit refresh failed after usage-limit error", { error: formatErrorMessage(error) });
2999
- return;
3000
- }
3001
- }
3002
- function resolveCodexUsageLimitRateLimitRefreshTimeoutMs(timeoutMs) {
3003
- if (timeoutMs === void 0 || !Number.isFinite(timeoutMs) || timeoutMs <= 0) return CODEX_USAGE_LIMIT_RATE_LIMIT_REFRESH_TIMEOUT_MS;
3004
- return Math.max(100, Math.min(timeoutMs, CODEX_USAGE_LIMIT_RATE_LIMIT_REFRESH_TIMEOUT_MS));
3005
- }
3006
- function readCodexTurnStartUsageLimitErrorSource(client, error, errorNotification, rateLimitsRevisionBeforeTurnStart) {
3007
- const notificationError = readCodexErrorNotification(errorNotification);
3008
- const errorPayload = readCodexErrorPayload(error);
3009
- const rateLimits = errorPayload.rateLimits ?? readRecentCodexRateLimits(client);
3010
- const cacheUpdatedDuringTurnStart = rateLimitsRevisionBeforeTurnStart !== void 0 && readCodexRateLimitsRevision(client) > rateLimitsRevisionBeforeTurnStart;
3011
- return {
3012
- message: notificationError?.message ?? errorPayload.message ?? formatErrorMessage(error),
3013
- codexErrorInfo: notificationError?.codexErrorInfo ?? errorPayload.codexErrorInfo,
3014
- rateLimits,
3015
- rateLimitsTrustedForProfile: errorPayload.rateLimits !== void 0 || cacheUpdatedDuringTurnStart
3016
- };
3017
- }
3018
- function readCodexErrorNotification(notification) {
3019
- if (notification?.method !== "error" || !isJsonObject(notification.params)) return;
3020
- const error = notification.params.error;
3021
- return isJsonObject(error) ? {
3022
- message: readString$2(error, "message"),
3023
- codexErrorInfo: error.codexErrorInfo
3024
- } : void 0;
3025
- }
3026
- function readCodexErrorPayload(error) {
3027
- const message = error instanceof Error ? error.message : void 0;
3028
- if (!error || typeof error !== "object" || !("data" in error)) return { message };
3029
- const data = error.data;
3030
- if (!isJsonObject(data)) return { message };
3031
- const nestedError = isJsonObject(data.error) ? data.error : data;
3032
- const rateLimits = nestedError.rateLimits ?? data.rateLimits;
3033
- return {
3034
- message: readString$2(nestedError, "message") ?? message,
3035
- codexErrorInfo: nestedError.codexErrorInfo,
3036
- rateLimits
3037
- };
3038
- }
3039
- function readString$2(record, key) {
3040
- const value = record[key];
3041
- return typeof value === "string" ? value : void 0;
3042
- }
3043
- //#endregion
3044
- //#region extensions/codex/src/app-server/event-projector.ts
3045
- var CodexAppServerEventProjector = class {
3046
- constructor(params, threadId, turnId, options = {}) {
3047
- this.params = params;
3048
- this.threadId = threadId;
3049
- this.turnId = turnId;
3050
- this.options = options;
3051
- this.activeItemIds = /* @__PURE__ */ new Set();
3052
- this.completedItemIds = /* @__PURE__ */ new Set();
3053
- this.activeCompactionItemIds = /* @__PURE__ */ new Set();
3054
- this.terminalPresentationClearedItemIds = /* @__PURE__ */ new Set();
3055
- this.nativeToolOutcomeOrdinals = /* @__PURE__ */ new Map();
3056
- this.promptErrorSource = null;
3057
- this.synthesizedMissingToolResultError = null;
3058
- this.aborted = false;
3059
- this.completedCompactionCount = 0;
3060
- this.diagnostics = new CodexProjectionDiagnostics(threadId, turnId);
3061
- this.nativeToolLifecycleProjector = new CodexNativeToolLifecycleProjector(params, threadId, turnId, { runAbortSignal: options.runAbortSignal });
3062
- this.generatedMediaProjection = new CodexGeneratedMediaProjection(params.config);
3063
- this.toolProgressProjection = new CodexToolProgressProjection(params);
3064
- this.toolTranscriptProjection = new CodexToolTranscriptProjection(params, threadId, turnId, this.toolProgressProjection, {
3065
- nativePostToolUseRelayEnabled: options.nativePostToolUseRelayEnabled,
3066
- trajectoryRecorder: options.trajectoryRecorder
3067
- });
3068
- this.eventProjection = new CodexEventProjection(threadId, turnId, (event) => this.emitAgentEvent(event), this.toolProgressProjection, this.toolTranscriptProjection, options.onNativeToolResultRecorded);
3069
- this.assistantProjection = new CodexAssistantProjection(params, (event) => this.emitAgentEvent(event), (text) => this.toolProgressProjection.matchesEcho(text));
3070
- this.reasoningProjection = new CodexReasoningProjection(params, (event) => this.emitAgentEvent(event));
3071
- }
3072
- getCompletedTurnStatus() {
3073
- return this.completedTurn?.status;
3074
- }
3075
- hasCompletedTerminalAssistantText() {
3076
- return this.assistantProjection.hasCompletedTerminalAssistantText(this.completedItemIds);
3077
- }
3078
- getLatestTerminalAssistantCandidate() {
3079
- return this.assistantProjection.getLatestTerminalAssistantCandidate();
3080
- }
3081
- hasLatestTerminalAssistantCandidateText() {
3082
- return this.assistantProjection.hasLatestTerminalAssistantCandidateText();
3083
- }
3084
- canReleaseLatestTerminalAssistantAfterToolHandoff() {
3085
- return this.assistantProjection.canReleaseLatestTerminalAssistantAfterToolHandoff();
3086
- }
3087
- /** Restores a completed final item after only the enclosing turn timeout fired. */
3088
- recoverCompletedTerminalAssistantAfterTurnWatchTimeout() {
3089
- if (!this.aborted || this.promptError !== "codex app-server attempt timed out" || !this.hasCompletedTerminalAssistantText()) return false;
3090
- this.aborted = false;
3091
- this.promptError = void 0;
3092
- this.promptErrorSource = null;
3093
- return true;
3094
- }
3095
- /** Resolves the shared model-order position for a native tool item. */
3096
- recordNativeToolOutcome(item) {
3097
- if (!item || this.nativeToolOutcomeOrdinals.has(item.id) || !shouldClearTerminalPresentationForNativeItem(item)) return;
3098
- const ordinal = this.params.allocateToolOutcomeOrdinal?.(item.id);
3099
- if (ordinal !== void 0) this.nativeToolOutcomeOrdinals.set(item.id, ordinal);
3100
- }
3101
- recordNativeToolApprovalFailure(toolCallId, disposition) {
3102
- this.nativeToolLifecycleProjector.recordApprovalFailureDisposition(toolCallId, disposition);
3103
- }
3104
- recordNativeToolPreToolUseFailure(failure) {
3105
- this.nativeToolLifecycleProjector.recordPreToolUseFailure(failure);
3106
- }
3107
- async handleNotification(notification) {
3108
- const params = isJsonObject(notification.params) ? notification.params : void 0;
3109
- if (!params) return;
3110
- if (isHookNotificationMethod(notification.method)) {
3111
- if (!this.isHookNotificationForCurrentThread(params)) return;
3112
- } else if (notification.method === "guardianWarning") {
3113
- if (readCodexNotificationThreadId(params) !== this.threadId) return;
3114
- } else if (!this.isNotificationForTurn(params)) return;
3115
- this.nativeToolLifecycleProjector.handleNotification(notification);
3116
- switch (notification.method) {
3117
- case "item/agentMessage/delta":
3118
- await this.assistantProjection.handleAssistantDelta(params);
3119
- break;
3120
- case "item/reasoning/summaryTextDelta":
3121
- case "item/reasoning/textDelta":
3122
- await this.reasoningProjection.handleReasoningDelta(notification.method, params);
3123
- break;
3124
- case "item/plan/delta":
3125
- this.reasoningProjection.handlePlanDelta(params);
3126
- break;
3127
- case "turn/plan/updated":
3128
- this.reasoningProjection.handleTurnPlanUpdated(params);
3129
- break;
3130
- case "item/started":
3131
- await this.handleItemStarted(params);
3132
- break;
3133
- case "item/completed":
3134
- await this.handleItemCompleted(params);
3135
- break;
3136
- case "item/commandExecution/outputDelta":
3137
- this.toolProgressProjection.handleOutputDelta(params, "bash");
3138
- break;
3139
- case "item/autoApprovalReview/started":
3140
- case "item/autoApprovalReview/completed":
3141
- this.eventProjection.handleGuardianReview(notification.method, params);
3142
- break;
3143
- case "guardianWarning":
3144
- this.eventProjection.handleGuardianWarning(params);
3145
- break;
3146
- case "hook/started":
3147
- case "hook/completed":
3148
- this.eventProjection.handleHook(notification.method, params);
3149
- break;
3150
- case "thread/tokenUsage/updated":
3151
- this.tokenUsage = readCodexThreadTokenUsage(params) ?? this.tokenUsage;
3152
- break;
3153
- case "turn/completed":
3154
- await this.handleTurnCompleted(params);
3155
- break;
3156
- case "rawResponse/completed":
3157
- this.handleRawResponseCompleted(params);
3158
- break;
3159
- case "rawResponseItem/completed":
3160
- await this.handleRawResponseItemCompleted(params);
3161
- break;
3162
- case "error":
3163
- this.responseUsage = void 0;
3164
- if (params.willRetry === true) break;
3165
- this.promptError = this.formatCodexErrorMessage(params) ?? "codex app-server error";
3166
- this.promptErrorSource = "prompt";
3167
- break;
3168
- case "thread/compacted":
3169
- case "turn/started":
3170
- case "turn/diff/updated":
3171
- case "item/reasoning/summaryPartAdded":
3172
- case "item/commandExecution/terminalInteraction":
3173
- case "item/fileChange/outputDelta":
3174
- case "item/fileChange/patchUpdated":
3175
- case "item/mcpToolCall/progress":
3176
- case "model/rerouted":
3177
- case "model/verification":
3178
- case "turn/moderationMetadata":
3179
- case "model/safetyBuffering/updated": break;
3180
- default:
3181
- this.diagnostics.warnUnknownEvent(notification, params);
3182
- break;
3183
- }
3184
- }
3185
- buildResult(toolTelemetry, options) {
3186
- this.nativeToolLifecycleProjector.finalizeActive();
3187
- const assistantTexts = this.assistantProjection.collectAssistantTexts();
3188
- const reasoningText = this.reasoningProjection.reasoningText();
3189
- const planText = this.reasoningProjection.planText();
3190
- const projectedUsage = this.aborted ? this.tokenUsage : this.responseUsage ?? this.tokenUsage;
3191
- const hasAssistantItemText = this.assistantProjection.hasAssistantItemTextForSynthesis();
3192
- const legacyFailClosed = !this.completedTurn || this.completedTurn.status !== "completed" || hasAssistantItemText;
3193
- const hasDeliverableAssistantOnCompletedTurn = this.completedTurn?.status === "completed" && assistantTexts.some((text) => text.trim().length > 0);
3194
- const synthesizedMissingToolResultError = this.toolTranscriptProjection.synthesizeMissingToolResults({
3195
- synthesize: legacyFailClosed,
3196
- recordPromptError: legacyFailClosed && !hasDeliverableAssistantOnCompletedTurn && !this.aborted
3197
- });
3198
- if (synthesizedMissingToolResultError) {
3199
- this.synthesizedMissingToolResultError = synthesizedMissingToolResultError;
3200
- this.promptErrorSource = this.promptErrorSource ?? "prompt";
3201
- }
3202
- const assistantMessageOptions = {
3203
- tokenUsage: projectedUsage,
3204
- aborted: this.aborted,
3205
- promptError: this.promptError
3206
- };
3207
- const lastAssistant = assistantTexts.length ? this.assistantProjection.createAssistantMessage(assistantTexts.join("\n\n"), assistantMessageOptions) : void 0;
3208
- const currentAttemptAssistant = this.assistantProjection.createCurrentAttemptAssistantMessage(assistantMessageOptions);
3209
- const turnId = this.turnId;
3210
- const messagesSnapshot = promptSnapshot(this.params, turnId, this.options.upstreamUserText);
3211
- if (reasoningText) messagesSnapshot.push(attachCodexMirrorIdentity(this.assistantProjection.createAssistantMirrorMessage("Codex reasoning", reasoningText), `${turnId}:reasoning`));
3212
- if (planText) messagesSnapshot.push(attachCodexMirrorIdentity(this.assistantProjection.createAssistantMirrorMessage("Codex plan", planText), `${turnId}:plan`));
3213
- messagesSnapshot.push(...this.toolTranscriptProjection.transcriptMessages);
3214
- if (lastAssistant) messagesSnapshot.push(attachCodexMirrorIdentity(lastAssistant, `${turnId}:assistant`));
3215
- const turnFailed = this.completedTurn?.status === "failed";
3216
- const promptError = this.promptError ?? this.synthesizedMissingToolResultError ?? (turnFailed ? this.completedTurn?.error?.message ?? "codex app-server turn failed" : null);
3217
- const agentHarnessResultClassification = classifyAgentHarnessTerminalOutcome({
3218
- assistantTexts,
3219
- reasoningText,
3220
- planText,
3221
- promptError,
3222
- turnCompleted: Boolean(this.completedTurn)
3223
- });
3224
- const toolMetas = this.toolProgressProjection.toolMetas;
3225
- const hadPotentialSideEffects = toolTelemetry.didSendViaMessagingTool || (toolTelemetry.successfulCronAdds ?? 0) > 0 || this.generatedMediaProjection.hasGeneratedMedia() || this.toolProgressProjection.hasPotentialSideEffects;
3226
- return {
3227
- aborted: this.aborted,
3228
- externalAbort: false,
3229
- timedOut: false,
3230
- idleTimedOut: false,
3231
- timedOutDuringCompaction: false,
3232
- timedOutDuringToolExecution: false,
3233
- promptError,
3234
- promptErrorSource: promptError ? this.promptErrorSource || "prompt" : null,
3235
- sessionIdUsed: this.params.sessionId,
3236
- ...agentHarnessResultClassification ? { agentHarnessResultClassification } : {},
3237
- bootstrapPromptWarningSignaturesSeen: this.params.bootstrapPromptWarningSignaturesSeen,
3238
- bootstrapPromptWarningSignature: this.params.bootstrapPromptWarningSignature,
3239
- messagesSnapshot,
3240
- assistantTexts,
3241
- toolMetas,
3242
- lastAssistant,
3243
- currentAttemptAssistant,
3244
- ...this.toolProgressProjection.lastToolError ? { lastToolError: this.toolProgressProjection.lastToolError } : {},
3245
- didSendViaMessagingTool: toolTelemetry.didSendViaMessagingTool,
3246
- didDeliverSourceReplyViaMessageTool: toolTelemetry.didDeliverSourceReplyViaMessageTool === true,
3247
- messagingToolSentTexts: toolTelemetry.messagingToolSentTexts,
3248
- messagingToolSentMediaUrls: toolTelemetry.messagingToolSentMediaUrls,
3249
- messagingToolSentTargets: toolTelemetry.messagingToolSentTargets,
3250
- messagingToolSourceReplyPayloads: toolTelemetry.messagingToolSourceReplyPayloads ?? [],
3251
- heartbeatToolResponse: toolTelemetry.heartbeatToolResponse,
3252
- toolMediaUrls: this.generatedMediaProjection.buildToolMediaUrls(toolTelemetry),
3253
- toolAudioAsVoice: toolTelemetry.toolAudioAsVoice,
3254
- successfulCronAdds: toolTelemetry.successfulCronAdds,
3255
- cloudCodeAssistFormatError: false,
3256
- attemptUsage: projectedUsage,
3257
- ...this.completedCompactionCount > 0 ? { compactionCount: this.completedCompactionCount } : {},
3258
- replayMetadata: {
3259
- hadPotentialSideEffects,
3260
- replaySafe: !hadPotentialSideEffects
3261
- },
3262
- itemLifecycle: {
3263
- startedCount: this.activeItemIds.size + this.completedItemIds.size,
3264
- completedCount: this.completedItemIds.size,
3265
- activeCount: this.activeItemIds.size
3266
- },
3267
- yieldDetected: options?.yieldDetected || false,
3268
- didSendDeterministicApprovalPrompt: this.eventProjection.guardianReviewCount > 0 ? false : void 0
3269
- };
3270
- }
3271
- recordDynamicToolCall(params) {
3272
- this.toolTranscriptProjection.recordDynamicToolCall(params);
3273
- }
3274
- recordDynamicToolResult(params) {
3275
- this.toolProgressProjection.recordDynamicToolResult(params);
3276
- this.toolTranscriptProjection.recordDynamicToolResult(params);
3277
- }
3278
- markTimedOut() {
3279
- this.aborted = true;
3280
- this.promptError = "codex app-server attempt timed out";
3281
- this.promptErrorSource = "prompt";
3282
- }
3283
- markAborted() {
3284
- this.aborted = true;
3285
- this.responseUsage = void 0;
3286
- }
3287
- isCompacting() {
3288
- return this.activeCompactionItemIds.size > 0;
3289
- }
3290
- async handleItemStarted(params) {
3291
- const item = readItem(params.item);
3292
- const itemId = item?.id ?? readString$3(params, "itemId");
3293
- this.assistantProjection.recordItemStarted(item, itemId);
3294
- if (itemId) this.activeItemIds.add(itemId);
3295
- this.recordNativeToolOutcome(item);
3296
- if (item?.type === "contextCompaction" && itemId) {
3297
- this.activeCompactionItemIds.add(itemId);
3298
- await runAgentHarnessBeforeCompactionHook({
3299
- sessionFile: this.params.sessionFile,
3300
- messages: await this.toolTranscriptProjection.readMirroredSessionMessages(),
3301
- ctx: {
3302
- runId: this.params.runId,
3303
- agentId: this.params.agentId,
3304
- sessionKey: this.params.sessionKey,
3305
- sessionId: this.params.sessionId,
3306
- workspaceDir: this.params.workspaceDir,
3307
- messageProvider: this.params.messageProvider ?? void 0,
3308
- trigger: this.params.trigger,
3309
- channelId: this.params.messageChannel ?? this.params.messageProvider ?? void 0
3310
- }
3311
- });
3312
- this.emitAgentEvent({
3313
- stream: "compaction",
3314
- data: {
3315
- phase: "start",
3316
- backend: "codex-app-server",
3317
- threadId: this.threadId,
3318
- turnId: this.turnId,
3319
- itemId
3320
- }
3321
- });
3322
- }
3323
- this.toolProgressProjection.recordToolMeta(item);
3324
- this.eventProjection.emitStandardItemEvent({
3325
- phase: "start",
3326
- item
3327
- });
3328
- await this.eventProjection.emitNormalizedToolItemEvent({
3329
- phase: "start",
3330
- item
3331
- });
3332
- this.toolTranscriptProjection.recordNativeToolCall(item);
3333
- this.toolProgressProjection.emitToolResultSummary(item);
3334
- this.emitAgentEvent({
3335
- stream: "codex_app_server.item",
3336
- data: {
3337
- phase: "started",
3338
- itemId,
3339
- type: item?.type
3340
- }
3341
- });
3342
- }
3343
- async handleItemCompleted(params) {
3344
- const item = readItem(params.item);
3345
- this.diagnostics.warnUnknownItemStatus(item);
3346
- this.recordNativeToolOutcome(item);
3347
- this.clearTerminalPresentationForNativeItem(item);
3348
- const itemId = item?.id ?? readString$3(params, "itemId");
3349
- if (itemId) {
3350
- this.activeItemIds.delete(itemId);
3351
- this.completedItemIds.add(itemId);
3352
- }
3353
- this.assistantProjection.recordItemCompleted(item, itemId, this.activeItemIds);
3354
- this.reasoningProjection.recordItem(item);
3355
- this.generatedMediaProjection.recordNative(item);
3356
- if (item?.type === "contextCompaction" && itemId) {
3357
- this.activeCompactionItemIds.delete(itemId);
3358
- this.completedCompactionCount += 1;
3359
- this.options.onContextCompacted?.();
3360
- await runAgentHarnessAfterCompactionHook({
3361
- sessionFile: this.params.sessionFile,
3362
- messages: await this.toolTranscriptProjection.readMirroredSessionMessages(),
3363
- compactedCount: -1,
3364
- ctx: {
3365
- runId: this.params.runId,
3366
- agentId: this.params.agentId,
3367
- sessionKey: this.params.sessionKey,
3368
- sessionId: this.params.sessionId,
3369
- workspaceDir: this.params.workspaceDir,
3370
- messageProvider: this.params.messageProvider ?? void 0,
3371
- trigger: this.params.trigger,
3372
- channelId: this.params.messageChannel ?? this.params.messageProvider ?? void 0
3373
- }
3374
- });
3375
- this.emitAgentEvent({
3376
- stream: "compaction",
3377
- data: {
3378
- phase: "end",
3379
- backend: "codex-app-server",
3380
- completed: true,
3381
- threadId: this.threadId,
3382
- turnId: this.turnId,
3383
- itemId
3384
- }
3385
- });
3386
- }
3387
- this.toolProgressProjection.recordToolMeta(item);
3388
- this.toolProgressProjection.rememberCommandAggregateOutputEcho(item);
3389
- this.eventProjection.emitStandardItemEvent({
3390
- phase: "end",
3391
- item
3392
- });
3393
- await this.eventProjection.emitNormalizedToolItemEvent({
3394
- phase: "result",
3395
- item
3396
- });
3397
- this.toolTranscriptProjection.recordNativeToolCall(item);
3398
- this.toolTranscriptProjection.recordNativeToolResult(item);
3399
- this.toolProgressProjection.emitToolResultSummary(item);
3400
- this.toolProgressProjection.emitToolResultOutput(item);
3401
- this.emitAgentEvent({
3402
- stream: "codex_app_server.item",
3403
- data: {
3404
- phase: "completed",
3405
- itemId,
3406
- type: item?.type
3407
- }
3408
- });
3409
- }
3410
- handleRawResponseCompleted(params) {
3411
- const usage = isJsonObject(params.usage) ? params.usage : void 0;
3412
- this.responseUsage = usage ? normalizeCodexResponseTokenUsage(usage) : void 0;
3413
- }
3414
- async handleTurnCompleted(params) {
3415
- const turn = readCodexTurn(params.turn);
3416
- if (!turn || turn.id !== this.turnId) return;
3417
- this.completedTurn = turn;
3418
- if (turn.status !== "completed") this.responseUsage = void 0;
3419
- if (turn.status === "failed") {
3420
- const usageLimitMessage = formatCodexUsageLimitErrorMessage({
3421
- message: turn.error?.message,
3422
- codexErrorInfo: turn.error?.codexErrorInfo,
3423
- rateLimits: this.options.readRecentRateLimits?.()
3424
- });
3425
- this.promptError = usageLimitMessage ? createCodexUsageLimitPromptError(usageLimitMessage) : turn.error?.message ?? "codex app-server turn failed";
3426
- this.promptErrorSource = "prompt";
3427
- }
3428
- const turnItems = turn.items ?? [];
3429
- for (let index = turnItems.length - 1; index >= 0; index -= 1) {
3430
- const item = turnItems[index];
3431
- if (!item || !this.isCurrentTurnSnapshotItem(item)) continue;
3432
- if (item?.type === "dynamicToolCall") break;
3433
- if (shouldClearTerminalPresentationForNativeItem(item)) {
3434
- this.clearTerminalPresentationForNativeItem(item);
3435
- break;
3436
- }
3437
- }
3438
- for (const item of turnItems) {
3439
- this.diagnostics.warnUnknownItemStatus(item);
3440
- this.assistantProjection.recordSnapshotItem(item);
3441
- this.reasoningProjection.recordItem(item);
3442
- this.generatedMediaProjection.recordNative(item);
3443
- this.toolProgressProjection.recordToolMeta(item);
3444
- this.toolProgressProjection.rememberCommandAggregateOutputEcho(item);
3445
- await this.emitSnapshotOnlyNativeToolProgress(item);
3446
- this.toolTranscriptProjection.recordNativeToolCall(item);
3447
- this.toolTranscriptProjection.recordNativeToolResult(item);
3448
- this.toolTranscriptProjection.emitAfterToolCallObservation(item);
3449
- this.toolProgressProjection.emitToolResultSummary(item);
3450
- this.toolProgressProjection.emitToolResultOutput(item);
3451
- }
3452
- this.assistantProjection.finalizeAnswerCandidate(turn);
3453
- this.activeCompactionItemIds.clear();
3454
- await this.reasoningProjection.maybeEndReasoning();
3455
- }
3456
- async emitSnapshotOnlyNativeToolProgress(item) {
3457
- if (!shouldSynthesizeToolProgressForItem(item) || !this.isCurrentTurnSnapshotItem(item) || this.completedItemIds.has(item.id) || itemStatus(item) === "running") return;
3458
- if (!this.activeItemIds.has(item.id)) {
3459
- this.eventProjection.emitStandardItemEvent({
3460
- phase: "start",
3461
- item
3462
- });
3463
- await this.eventProjection.emitNormalizedToolItemEvent({
3464
- phase: "start",
3465
- item
3466
- });
3467
- }
3468
- this.activeItemIds.delete(item.id);
3469
- this.eventProjection.emitStandardItemEvent({
3470
- phase: "end",
3471
- item
3472
- });
3473
- await this.eventProjection.emitNormalizedToolItemEvent({
3474
- phase: "result",
3475
- item
3476
- });
3477
- this.completedItemIds.add(item.id);
3478
- }
3479
- isCurrentTurnSnapshotItem(item) {
3480
- const itemTurnId = readItemString(item, "turnId");
3481
- return itemTurnId === void 0 || itemTurnId === this.turnId;
3482
- }
3483
- async handleRawResponseItemCompleted(params) {
3484
- const item = isJsonObject(params.item) ? params.item : void 0;
3485
- if (!item) return;
3486
- this.assistantProjection.handleRawResponseItemCompleted(item, this.activeItemIds);
3487
- await this.generatedMediaProjection.recordRaw(item);
3488
- }
3489
- clearTerminalPresentationForNativeItem(item) {
3490
- if (!item || this.terminalPresentationClearedItemIds.has(item.id) || !shouldClearTerminalPresentationForNativeItem(item)) return;
3491
- const toolCallOrdinal = this.nativeToolOutcomeOrdinals.get(item.id);
3492
- this.terminalPresentationClearedItemIds.add(item.id);
3493
- this.params.onToolOutcome?.({
3494
- toolName: itemName(item) ?? item.type,
3495
- argsHash: "",
3496
- resultHash: "",
3497
- ...toolCallOrdinal !== void 0 ? { toolCallOrdinal } : {},
3498
- terminalPresentation: void 0,
3499
- presentationOnly: true
3500
- });
3501
- }
3502
- formatCodexErrorMessage(params) {
3503
- const error = isJsonObject(params.error) ? params.error : void 0;
3504
- const usageLimitMessage = formatCodexUsageLimitErrorMessage({
3505
- message: error ? readString$3(error, "message") : void 0,
3506
- codexErrorInfo: error?.codexErrorInfo,
3507
- rateLimits: this.options.readRecentRateLimits?.()
3508
- });
3509
- return usageLimitMessage ? createCodexUsageLimitPromptError(usageLimitMessage) : readCodexErrorNotificationMessage(params);
3510
- }
3511
- emitAgentEvent(event) {
3512
- try {
3513
- emitAgentEvent({
3514
- runId: this.params.runId,
3515
- stream: event.stream,
3516
- data: event.data,
3517
- ...this.params.sessionKey ? { sessionKey: this.params.sessionKey } : {}
3518
- });
3519
- } catch (error) {
3520
- embeddedAgentLog.debug("codex app-server global agent event emit failed", { error });
3521
- }
3522
- try {
3523
- const maybePromise = this.params.onAgentEvent?.(event);
3524
- Promise.resolve(maybePromise).catch((error) => {
3525
- embeddedAgentLog.debug("codex app-server agent event handler rejected", { error });
3526
- });
3527
- } catch (error) {
3528
- embeddedAgentLog.debug("codex app-server agent event handler threw", { error });
3529
- }
3530
- }
3531
- isNotificationForTurn(params) {
3532
- const threadId = readCodexNotificationThreadId(params);
3533
- const turnId = readCodexNotificationTurnId(params);
3534
- return threadId === this.threadId && turnId === this.turnId;
3535
- }
3536
- isHookNotificationForCurrentThread(params) {
3537
- const threadId = readString$3(params, "threadId");
3538
- const turnId = params.turnId;
3539
- return threadId === this.threadId && (turnId === this.turnId || turnId === null);
3540
- }
3541
- };
3542
- function isHookNotificationMethod(method) {
3543
- return method === "hook/started" || method === "hook/completed";
3544
- }
3545
- //#endregion
3546
987
  //#region extensions/codex/src/app-server/dynamic-tool-build-state.ts
3547
988
  /** Mutable dependency seam shared by dynamic-tool construction and its behavioral tests. */
3548
989
  const dynamicToolBuildState = {};
@@ -3751,7 +1192,7 @@ async function buildDynamicTools(input) {
3751
1192
  }
3752
1193
  const toolBuildStages = createCodexDynamicToolBuildStageTracker({ enabled: input.profilerEnabled });
3753
1194
  const modelHasVision = params.model.input?.includes("image") ?? false;
3754
- const agentDir = params.agentDir ?? resolveAgentDir(params.config ?? {}, input.sessionAgentId);
1195
+ const agentDir = params.agentDir ?? resolveAgentDir$1(params.config ?? {}, input.sessionAgentId);
3755
1196
  const { createOpenClawCodingTools: defaultCreateOpenClawCodingTools, resolveWebSearchToolPolicy } = await import("openclaw/plugin-sdk/agent-harness");
3756
1197
  const createOpenClawCodingTools = dynamicToolBuildState.openClawCodingToolsFactory ?? defaultCreateOpenClawCodingTools;
3757
1198
  toolBuildStages.mark("load-agent-harness-tools");
@@ -3785,6 +1226,9 @@ async function buildDynamicTools(input) {
3785
1226
  senderUsername: params.senderUsername,
3786
1227
  senderE164: params.senderE164,
3787
1228
  senderIsOwner: params.senderIsOwner,
1229
+ inputProvenance: params.inputProvenance,
1230
+ trustedInternalHandoff: params.trustedInternalHandoff,
1231
+ scheduledToolPolicy: params.scheduledToolPolicy,
3788
1232
  allowGatewaySubagentBinding: params.allowGatewaySubagentBinding || isForcedPrivateQaCodexRuntime(),
3789
1233
  ...sessionKeys,
3790
1234
  sessionId: params.sessionId,
@@ -3877,7 +1321,10 @@ async function buildDynamicTools(input) {
3877
1321
  senderId: params.senderId,
3878
1322
  senderName: params.senderName,
3879
1323
  senderUsername: params.senderUsername,
3880
- senderE164: params.senderE164
1324
+ senderE164: params.senderE164,
1325
+ inputProvenance: params.inputProvenance,
1326
+ trustedInternalHandoff: params.trustedInternalHandoff,
1327
+ scheduledToolPolicy: params.scheduledToolPolicy
3881
1328
  });
3882
1329
  const transientWebSearchRestriction = !webSearchPolicy.allowed && webSearchPolicy.persistentAllowed || isCodexMemoryFlushRun(params);
3883
1330
  const persistentCodexWebSearchSurface = params.config?.tools?.web?.search?.enabled !== false && !(input.pluginConfig.codexDynamicToolsExclude ?? []).some((name) => normalizeCodexDynamicToolName(name) === "web_search");
@@ -3943,6 +1390,7 @@ function includeForcedCodexDynamicToolAllow(toolsAllow, params) {
3943
1390
  /** Decides whether Codex native code mode can own shell/file tools for this turn. */
3944
1391
  function shouldEnableCodexAppServerNativeToolSurface(params, sandbox, options = {}) {
3945
1392
  if (isCodexMemoryFlushRun(params)) return false;
1393
+ if (params.disableTools) return false;
3946
1394
  const toolsAllow = includeForcedCodexDynamicToolAllow(params.toolsAllow, params);
3947
1395
  if (toolsAllow === void 0) return canCodexAppServerNativeToolSurfaceHonorSandbox(sandbox, options);
3948
1396
  return hasWildcardCodexToolsAllow(toolsAllow) && canCodexAppServerNativeToolSurfaceHonorSandbox(sandbox, options);
@@ -4155,6 +1603,11 @@ function settleCodexSourceReplyFinality(owner, turnSucceeded) {
4155
1603
  }
4156
1604
  //#endregion
4157
1605
  //#region extensions/codex/src/app-server/provider-capabilities.ts
1606
+ function resolveOverriddenProviderWebSearchSupport(modelProviderOverride) {
1607
+ const provider = modelProviderOverride?.trim().toLowerCase();
1608
+ if (!provider) return;
1609
+ return provider === "openai" ? "supported" : "unsupported";
1610
+ }
4158
1611
  async function readConfiguredProviderWebSearchSupport(params) {
4159
1612
  return (await params.client.request("modelProvider/capabilities/read", {}, {
4160
1613
  timeoutMs: params.timeoutMs,
@@ -4162,9 +1615,8 @@ async function readConfiguredProviderWebSearchSupport(params) {
4162
1615
  })).webSearch ? "supported" : "unsupported";
4163
1616
  }
4164
1617
  async function resolveCodexProviderWebSearchSupportForClient(params) {
4165
- const modelProviderOverride = params.modelProviderOverride?.trim().toLowerCase();
4166
- if (modelProviderOverride === "openai") return "supported";
4167
- if (modelProviderOverride) return "unsupported";
1618
+ const overrideSupport = resolveOverriddenProviderWebSearchSupport(params.modelProviderOverride);
1619
+ if (overrideSupport) return overrideSupport;
4168
1620
  try {
4169
1621
  return await readConfiguredProviderWebSearchSupport(params);
4170
1622
  } catch {
@@ -4172,6 +1624,8 @@ async function resolveCodexProviderWebSearchSupportForClient(params) {
4172
1624
  }
4173
1625
  }
4174
1626
  async function resolveCodexProviderWebSearchSupport(params) {
1627
+ const overrideSupport = resolveOverriddenProviderWebSearchSupport(params.modelProviderOverride);
1628
+ if (overrideSupport) return overrideSupport;
4175
1629
  let client;
4176
1630
  try {
4177
1631
  client = await params.clientFactory({
@@ -4303,8 +1757,11 @@ function approvalRequestExplicitlyUnavailable(result) {
4303
1757
  }
4304
1758
  /** Waits for the gateway's final approval decision, respecting turn aborts. */
4305
1759
  async function waitForPluginApprovalDecision(params) {
4306
- const waitPromise = callGatewayTool("plugin.approval.waitDecision", { timeoutMs: resolveCodexGatewayTimeoutWithGraceMs(DEFAULT_CODEX_APPROVAL_TIMEOUT_MS) }, { id: params.approvalId });
4307
- const bindDecision = (result) => result?.id === params.approvalId ? result.decision : void 0;
1760
+ const waitPromise = callGatewayTool("plugin.approval.waitDecision", { timeoutMs: resolveCodexGatewayTimeoutWithGraceMs(DEFAULT_CODEX_APPROVAL_TIMEOUT_MS) }, { id: params.approvalId }).catch((error) => {
1761
+ if (isApprovalNotFoundError(error)) return null;
1762
+ throw error;
1763
+ });
1764
+ const bindDecision = (result) => result === null ? null : result?.id === params.approvalId ? result.decision : void 0;
4308
1765
  if (!params.signal) return bindDecision(await waitPromise);
4309
1766
  let onAbort;
4310
1767
  const abortPromise = new Promise((_, reject) => {
@@ -5717,25 +3174,6 @@ function formatErrorMessage$1(error) {
5717
3174
  return error instanceof Error ? error.message : String(error);
5718
3175
  }
5719
3176
  //#endregion
5720
- //#region extensions/codex/src/app-server/agent-context-limits.ts
5721
- /** Resolves an agent override before falling back to the configured default. */
5722
- function resolveAgentContextLimitValue(params) {
5723
- const agents = asOptionalRecord(params.config?.agents);
5724
- const defaultValue = readPositiveInteger(asOptionalRecord(asOptionalRecord(agents?.defaults)?.contextLimits)?.[params.key]);
5725
- if (!params.agentId) return defaultValue;
5726
- const list = agents?.list;
5727
- if (!Array.isArray(list)) return defaultValue;
5728
- const normalizedAgentId = normalizeAgentId(params.agentId);
5729
- return readPositiveInteger(asOptionalRecord(asOptionalRecord(list.find((entry) => {
5730
- const entryId = asOptionalRecord(entry)?.id;
5731
- return typeof entryId === "string" && normalizeAgentId(entryId) === normalizedAgentId;
5732
- }))?.contextLimits)?.[params.key]) ?? defaultValue;
5733
- }
5734
- function readPositiveInteger(value) {
5735
- if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) return;
5736
- return Math.floor(value);
5737
- }
5738
- //#endregion
5739
3177
  //#region extensions/codex/src/app-server/dynamic-tools.ts
5740
3178
  /**
5741
3179
  * Bridges OpenClaw runtime tools into Codex app-server dynamic tool specs and
@@ -5884,6 +3322,13 @@ const EXPLICIT_MESSAGE_REPLY_KEYS = [
5884
3322
  "replyToIdFull"
5885
3323
  ];
5886
3324
  const DEFAULT_CODEX_DYNAMIC_TOOL_RESULT_MAX_CHARS = 16e3;
3325
+ const LARGE_CONTEXT_CODEX_DYNAMIC_TOOL_RESULT_MAX_CHARS = 32e3;
3326
+ const XL_CONTEXT_CODEX_DYNAMIC_TOOL_RESULT_MAX_CHARS = 64e3;
3327
+ function resolveCodexDynamicToolResultMaxChars(contextWindowTokens) {
3328
+ if (typeof contextWindowTokens !== "number" || !Number.isFinite(contextWindowTokens) || contextWindowTokens <= 0) return DEFAULT_CODEX_DYNAMIC_TOOL_RESULT_MAX_CHARS;
3329
+ const tokens = Math.floor(contextWindowTokens);
3330
+ return Math.min(tokens >= 2e5 ? XL_CONTEXT_CODEX_DYNAMIC_TOOL_RESULT_MAX_CHARS : tokens >= 1e5 ? LARGE_CONTEXT_CODEX_DYNAMIC_TOOL_RESULT_MAX_CHARS : DEFAULT_CODEX_DYNAMIC_TOOL_RESULT_MAX_CHARS, Math.max(1, Math.floor(tokens * .3) * 4));
3331
+ }
5887
3332
  function computerFrameImageIdentity(content) {
5888
3333
  if (!Array.isArray(content)) return;
5889
3334
  const images = content.filter((block) => block.type === "image");
@@ -5902,7 +3347,7 @@ function invalidateComputerFrame(contextEpoch) {
5902
3347
  */
5903
3348
  function createCodexDynamicToolBridge(params) {
5904
3349
  const toolResultHookContext = toToolResultHookContext(params.hookContext);
5905
- const toolResultMaxChars = resolveCodexDynamicToolResultMaxChars(params.hookContext);
3350
+ const toolResultMaxChars = resolveCodexDynamicToolResultMaxChars(params.hookContext?.contextWindowTokens);
5906
3351
  const availableProjection = projectCodexDynamicTools(params.tools);
5907
3352
  const registeredProjection = params.registeredTools ? projectCodexDynamicTools(params.registeredTools) : availableProjection;
5908
3353
  const wrappedAvailableProjection = wrapProjectedCodexDynamicTools(availableProjection.tools, params.hookContext);
@@ -6081,6 +3526,7 @@ function createCodexDynamicToolBridge(params) {
6081
3526
  contentItems,
6082
3527
  success: !resultIsError
6083
3528
  }, terminalType);
3529
+ withDynamicToolTranscriptDetails(response, result.details);
6084
3530
  withDiagnosticFailureDisposition(response, resultFailureKind);
6085
3531
  const blocksSourceReplyTermination = hasExplicitNonSourceMessageRoute(executedArgs, params.hookContext, confirmedMessagingTarget);
6086
3532
  const deliveredSourceReply = isDeliveredMessageToolOnlySourceReplyResult({
@@ -6421,13 +3867,6 @@ function toToolResultHookContext(ctx) {
6421
3867
  ...channelId && { channelId }
6422
3868
  };
6423
3869
  }
6424
- function resolveCodexDynamicToolResultMaxChars(ctx) {
6425
- return resolveAgentContextLimitValue({
6426
- config: ctx?.config,
6427
- agentId: ctx?.agentId,
6428
- key: "toolResultMaxChars"
6429
- }) ?? DEFAULT_CODEX_DYNAMIC_TOOL_RESULT_MAX_CHARS;
6430
- }
6431
3870
  function composeAbortSignals(...signals) {
6432
3871
  const activeSignals = signals.filter((signal) => Boolean(signal));
6433
3872
  if (activeSignals.length === 0) return new AbortController().signal;
@@ -6691,4 +4130,4 @@ function isCronAddAction(args) {
6691
4130
  return typeof action === "string" && action.trim().toLowerCase() === "add";
6692
4131
  }
6693
4132
  //#endregion
6694
- export { resolveCodexToolProgressDetailMode as $, CODEX_NATIVE_HOOK_RELAY_EVENTS as A, hasPendingDynamicToolTerminalDiagnostic as B, CodexAppServerEventProjector as C, markCodexAuthProfileBlockedFromRateLimits as D, isCodexUsageLimitPromptError as E, emitCodexNativePreToolUseFailureDiagnostic as F, shouldBlockTerminalReleaseForNonTerminalDynamicToolResult as G, isMatchingDynamicToolTerminalDiagnostic as H, resolveCodexNativeHookRelayEvents as I, toCodexDynamicToolProtocolResponse as J, shouldReleaseTurnAfterTerminalDynamicTool as K, resolveCodexNativeHookRelayTtlMs as L, buildCodexNativeHookRelayConfig as M, buildCodexNativeHookRelayDisabledConfig as N, refreshCodexUsageLimitPromptError as O, createCodexNativeHookRelay as P, inferCodexDynamicToolMeta as Q, scheduleCodexNativeHookRelayUnregister as R, filterToolsForVisionInputs as S, formatCodexTurnStartUsageLimitError as T, resolveDynamicToolCallTimeoutMs as U, isDynamicToolTerminalDiagnosticEvent as V, resolveTerminalDynamicToolBatchAction as W, readCodexMirroredSessionHistoryMessages as X, resolveCodexToolAbortTerminalReason as Y, shouldEmitTranscriptToolProgress as Z, resolveCodexMessageToolProvider as _, emitDynamicToolStartedDiagnostic as a, shouldRequireCodexSandboxExecServerEnvironment as b, resolveCodexProviderWebSearchSupportForClient as c, createCodexDynamicToolBuildStageTracker as d, sanitizeCodexToolArguments as et, disableCodexPluginThreadConfig as f, resolveCodexExternalSandboxPolicyForOpenClawSandbox as g, resolveCodexAppServerHookChannelId as h, emitDynamicToolErrorDiagnostic as i, CODEX_NATIVE_HOOK_RELAY_TTL_GRACE_MS as j, CodexNativeToolLifecycleProjector as k, settleCodexSourceReplyFinality as l, resolveCodexAppServerExecutionCwd as m, handleCodexAppServerApprovalRequest as n, redactCodexEventKind as nt, emitDynamicToolTerminalDiagnostic as o, formatCodexDynamicToolBuildStageSummary as p, toCodexDynamicToolProgressResponse as q, handleCodexAppServerElicitationRequest as r, resolveCodexLocalRuntimeAttribution as rt, resolveCodexProviderWebSearchSupport as s, createCodexDynamicToolBridge as t, sanitizeCodexToolResponse as tt, buildDynamicTools as u, resolveCodexSandboxEnvironmentSelection as v, createCodexUsageLimitPromptError as w, shouldWarnCodexDynamicToolBuildStageSummary as x, shouldEnableCodexAppServerNativeToolSurface as y, handleDynamicToolCallWithTimeout as z };
4133
+ export { shouldSynthesizeToolProgressForItem as $, resolveCodexNativeHookRelayEvents as A, shouldReleaseTurnAfterTerminalDynamicTool as B, CodexNativeToolLifecycleProjector as C, buildCodexNativeHookRelayDisabledConfig as D, buildCodexNativeHookRelayConfig as E, isDynamicToolTerminalDiagnosticEvent as F, isNonSuccessItemStatus as G, toCodexDynamicToolProtocolResponse as H, isMatchingDynamicToolTerminalDiagnostic as I, itemName as J, isSideEffectingNativeToolItem as K, resolveDynamicToolCallTimeoutMs as L, scheduleCodexNativeHookRelayUnregister as M, handleDynamicToolCallWithTimeout as N, createCodexNativeHookRelay as O, hasPendingDynamicToolTerminalDiagnostic as P, shouldRecordNativeToolTranscript as Q, resolveTerminalDynamicToolBatchAction as R, filterToolsForVisionInputs as S, CODEX_NATIVE_HOOK_RELAY_TTL_GRACE_MS as T, resolveCodexToolAbortTerminalReason as U, toCodexDynamicToolProgressResponse as V, isMutatingNativeToolItem as W, itemTitle as X, itemStatus as Y, shouldClearTerminalPresentationForNativeItem as Z, resolveCodexMessageToolProvider as _, emitDynamicToolStartedDiagnostic as a, shouldRequireCodexSandboxExecServerEnvironment as b, resolveCodexProviderWebSearchSupportForClient as c, createCodexDynamicToolBuildStageTracker as d, unknownItemStatus as et, disableCodexPluginThreadConfig as f, resolveCodexExternalSandboxPolicyForOpenClawSandbox as g, resolveCodexAppServerHookChannelId as h, emitDynamicToolErrorDiagnostic as i, resolveCodexNativeHookRelayTtlMs as j, emitCodexNativePreToolUseFailureDiagnostic as k, settleCodexSourceReplyFinality as l, resolveCodexAppServerExecutionCwd as m, handleCodexAppServerApprovalRequest as n, emitDynamicToolTerminalDiagnostic as o, formatCodexDynamicToolBuildStageSummary as p, itemKind as q, handleCodexAppServerElicitationRequest as r, resolveCodexProviderWebSearchSupport as s, createCodexDynamicToolBridge as t, buildDynamicTools as u, resolveCodexSandboxEnvironmentSelection as v, CODEX_NATIVE_HOOK_RELAY_EVENTS as w, shouldWarnCodexDynamicToolBuildStageSummary as x, shouldEnableCodexAppServerNativeToolSurface as y, shouldBlockTerminalReleaseForNonTerminalDynamicToolResult as z };