@openclaw/codex 2026.7.2-beta.2 → 2026.7.2-beta.4

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 (39) hide show
  1. package/dist/{app-server-policy-Scc-Wevo.js → app-server-policy-BO3jYBkv.js} +1 -1
  2. package/dist/{attempt-notifications-BFmNhqFl.js → attempt-notifications-DdmnBMUp.js} +1 -1
  3. package/dist/{media-understanding-provider-D31dOJwb.js → bounded-turn-CaQL96kg.js} +43 -183
  4. package/dist/capabilities-CLICvTxf.js +36 -0
  5. package/dist/cli-metadata.js +1 -1
  6. package/dist/{command-formatters-Dq9InZUK.js → command-formatters-DgADqnHa.js} +4 -34
  7. package/dist/{command-handlers-IgqmL_kv.js → command-handlers-l_lVPNlB.js} +72 -13
  8. package/dist/{compact-DCTmg3id.js → compact-CC5KhBzX.js} +5 -4
  9. package/dist/{computer-use-CPcU8TjG.js → computer-use-Ip1-QGa-.js} +4 -4
  10. package/dist/{conversation-control-CGkBlfc5.js → conversation-control-sNPsbTCP.js} +6 -5
  11. package/dist/doctor-contract-api.js +1 -1
  12. package/dist/{dynamic-tools-C_1tEs34.js → dynamic-tools-CQI3UwqY.js} +117 -2543
  13. package/dist/event-projector-assistant-message-DTgnPPVF.js +101 -0
  14. package/dist/event-projector-usage-D6tE7_qD.js +69 -0
  15. package/dist/harness.js +27 -7
  16. package/dist/incognito-session-ET_ufDH-.js +2 -0
  17. package/dist/index.js +60 -26
  18. package/dist/media-understanding-provider.js +168 -1
  19. package/dist/{models-uh26C8QU.js → models-BNeMlHgg.js} +2 -2
  20. package/dist/{notification-correlation-KmfV4EkP.js → notification-correlation-BGLixv5_.js} +3 -3
  21. package/dist/{plugin-app-cache-key-Ceb-lm2c.js → plugin-app-cache-key-CvzvmBRz.js} +2 -2
  22. package/dist/{rate-limits-DyXaYAxU.js → rate-limits-D0IJT-a6.js} +3 -1
  23. package/dist/{request-B_oQsCXy.js → request-BTccUTD3.js} +1 -1
  24. package/dist/{run-attempt-MLzoMe_m.js → run-attempt--858NXDl.js} +2798 -172
  25. package/dist/{session-binding-h1mmCGnl.js → session-binding-ZSMX1omP.js} +9 -2
  26. package/dist/{session-catalog-CEvoXWHA.js → session-catalog-DsKaezgR.js} +119 -96
  27. package/dist/{session-cli-XsEuWb_C.js → session-cli-CYJTfRLG.js} +2 -2
  28. package/dist/session-upstream-marker-D7XlI9us.js +82 -0
  29. package/dist/settled-turn-finalizer-DHltNgtF.js +303 -0
  30. package/dist/{shared-client-JiAnW6pc.js → shared-client-wmgNFNYp.js} +82 -13
  31. package/dist/{side-question-DqDvIwSU.js → side-question-BfFZCsJ-.js} +21 -15
  32. package/dist/{thread-lifecycle-CN_pPtPh.js → thread-lifecycle-cqrOlJkq.js} +157 -32
  33. package/dist/{transcript-mirror-D9rTxx2P.js → transcript-mirror-2p7kl6e4.js} +433 -145
  34. package/dist/upstream-session-fork-vPjwkT1i.js +320 -0
  35. package/dist/{usage-D5Rohxoc.js → usage-DM_I3mPT.js} +3 -3
  36. package/dist/{web-search-provider.runtime-CKVBn3fP.js → web-search-provider.runtime-Bx6HAc_k.js} +3 -3
  37. package/npm-shrinkwrap.json +38 -38
  38. package/openclaw.plugin.json +11 -1
  39. package/package.json +7 -7
@@ -1,436 +1,22 @@
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-JiAnW6pc.js";
2
- import { y as readCodexPluginConfig } from "./session-binding-h1mmCGnl.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-CN_pPtPh.js";
5
- import { d as CODEX_CONTROL_METHODS, r as formatCodexDisplayText } from "./command-formatters-Dq9InZUK.js";
6
- import { a as shouldRefreshCodexRateLimitsForUsageLimitMessage, i as resolveCodexUsageLimitResetAtMs, n as formatCodexUsageLimitErrorMessage } from "./rate-limits-DyXaYAxU.js";
1
+ import { Q as isJsonObject, X as CODEX_OPENCLAW_DIRECT_DYNAMIC_TOOL_NAMESPACE, c as releaseLeasedSharedCodexAppServerClient, j as resolveCodexGatewayTimeoutWithGraceMs } from "./shared-client-wmgNFNYp.js";
2
+ import { b as readCodexPluginConfig } from "./session-binding-ZSMX1omP.js";
3
+ import { D as isForcedPrivateQaCodexRuntime, E as filterCodexDynamicToolsWithOpenClawShell, O as isSystemAgentOnlyCodexDynamicToolAllowlist, T as filterCodexDynamicTools, ct as readItemString, h as resolveCodexWebSearchPlan, i as invalidInlineImageText, k as normalizeCodexDynamicToolName, mt as readString$2, o as sanitizeInlineImageDataUrl, st as readItem } from "./thread-lifecycle-cqrOlJkq.js";
4
+ import { S as readCodexTurn } from "./transcript-mirror-2p7kl6e4.js";
5
+ import { r as formatCodexDisplayText } from "./command-formatters-DgADqnHa.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-KmfV4EkP.js";
9
- import fs from "node:fs/promises";
7
+ import { n as readCodexNotificationThreadId, r as readCodexNotificationTurnId } from "./notification-correlation-BGLixv5_.js";
10
8
  import { addTimerTimeoutGraceMs, asDateTimestampMs, finiteSecondsToTimerSafeMilliseconds, parseStrictNonNegativeInteger } from "openclaw/plugin-sdk/number-runtime";
11
9
  import { sliceUtf16Safe, truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
12
10
  import { createHash } from "node:crypto";
13
- import { markAuthProfileBlockedUntil, resolveAgentDir } from "openclaw/plugin-sdk/agent-runtime";
11
+ import { resolveAgentDir } from "openclaw/plugin-sdk/agent-runtime";
14
12
  import { normalizeAgentId } from "openclaw/plugin-sdk/routing";
15
13
  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";
14
+ 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";
18
15
  import { expectDefined } from "openclaw/plugin-sdk/expect-runtime";
19
- import { redactSensitiveFieldValue, redactToolPayloadText } from "openclaw/plugin-sdk/logging-core";
20
16
  import { emitTrustedDiagnosticEvent, hasPendingInternalDiagnosticEvent } from "openclaw/plugin-sdk/diagnostic-runtime";
21
- import { readSessionTranscriptEvents } from "openclaw/plugin-sdk/session-transcript-runtime";
22
17
  import { isToolAllowed } from "openclaw/plugin-sdk/sandbox";
23
- import { buildSessionContext, migrateSessionEntries, parseSessionEntries } from "openclaw/plugin-sdk/agent-sessions";
24
- import { generatedImageAssetFromBase64 } from "openclaw/plugin-sdk/image-generation";
25
- import { saveMediaBuffer } from "openclaw/plugin-sdk/media-store";
18
+ import { isApprovalNotFoundError } from "openclaw/plugin-sdk/error-runtime";
26
19
  import { normalizeOpenAIToolSchemas } from "openclaw/plugin-sdk/provider-tools";
27
- //#region extensions/codex/src/app-server/local-runtime-attribution.ts
28
- const OPENAI_PROVIDER_ID = "openai";
29
- const OPENAI_RESPONSES_API = "openai-responses";
30
- const OPENAI_CODEX_RESPONSES_API = "openai-chatgpt-responses";
31
- function normalizeRuntimeId(value) {
32
- return value?.trim().toLowerCase() ?? "";
33
- }
34
- /** Maps local Codex runtime plans onto the provider/api pair exposed to event projection. */
35
- function resolveCodexLocalRuntimeAttribution(params) {
36
- const authProfileProvider = normalizeRuntimeId(params.runtimePlan?.auth?.authProfileProviderForAuth);
37
- 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 {
38
- provider: OPENAI_PROVIDER_ID,
39
- api: OPENAI_CODEX_RESPONSES_API
40
- };
41
- return {
42
- provider: params.provider,
43
- api: params.model.api
44
- };
45
- }
46
- //#endregion
47
- //#region extensions/codex/src/app-server/event-projector-assistant-message.ts
48
- const ZERO_USAGE$1 = {
49
- input: 0,
50
- output: 0,
51
- cacheRead: 0,
52
- cacheWrite: 0,
53
- totalTokens: 0,
54
- cost: {
55
- input: 0,
56
- output: 0,
57
- cacheRead: 0,
58
- cacheWrite: 0,
59
- total: 0
60
- }
61
- };
62
- function createAssistantMessage(params, text, options) {
63
- const attribution = resolveCodexLocalRuntimeAttribution(params);
64
- const usage = options.tokenUsage ? {
65
- input: options.tokenUsage.input ?? 0,
66
- output: options.tokenUsage.output ?? 0,
67
- cacheRead: options.tokenUsage.cacheRead ?? 0,
68
- cacheWrite: options.tokenUsage.cacheWrite ?? 0,
69
- ...options.tokenUsage.contextUsage ? { contextUsage: options.tokenUsage.contextUsage } : {},
70
- totalTokens: options.tokenUsage.total ?? (options.tokenUsage.input ?? 0) + (options.tokenUsage.output ?? 0) + (options.tokenUsage.cacheRead ?? 0) + (options.tokenUsage.cacheWrite ?? 0),
71
- cost: ZERO_USAGE$1.cost
72
- } : ZERO_USAGE$1;
73
- return {
74
- role: "assistant",
75
- content: [{
76
- type: "text",
77
- text
78
- }],
79
- api: attribution.api ?? "openai-chatgpt-responses",
80
- provider: attribution.provider,
81
- model: params.modelId,
82
- usage,
83
- stopReason: options.aborted ? "aborted" : options.promptError ? "error" : "stop",
84
- errorMessage: options.promptError ? formatErrorMessage(options.promptError) : void 0,
85
- timestamp: Date.now()
86
- };
87
- }
88
- function createAssistantMirrorMessage(params, title, text) {
89
- const attribution = resolveCodexLocalRuntimeAttribution(params);
90
- return {
91
- role: "assistant",
92
- content: [{
93
- type: "text",
94
- text: `${title}:\n${text}`
95
- }],
96
- api: attribution.api ?? "openai-chatgpt-responses",
97
- provider: attribution.provider,
98
- model: params.modelId,
99
- usage: ZERO_USAGE$1,
100
- stopReason: "stop",
101
- timestamp: Date.now()
102
- };
103
- }
104
- //#endregion
105
- //#region extensions/codex/src/app-server/event-projector-values.ts
106
- function readString$3(record, key) {
107
- const value = record[key];
108
- return typeof value === "string" ? value : void 0;
109
- }
110
- function normalizeNonEmptyString(value) {
111
- if (typeof value !== "string") return;
112
- return value.trim() || void 0;
113
- }
114
- function readNonEmptyString(record, key) {
115
- return normalizeNonEmptyString(record[key]);
116
- }
117
- function readNonEmptyStringArray(record, key) {
118
- const value = record[key];
119
- if (!Array.isArray(value)) return [];
120
- const entries = [];
121
- for (const entry of value) {
122
- const normalized = normalizeNonEmptyString(entry);
123
- if (normalized) entries.push(normalized);
124
- }
125
- return entries;
126
- }
127
- function readNullableString(record, key) {
128
- const value = record[key];
129
- if (value === null) return null;
130
- return typeof value === "string" ? value : void 0;
131
- }
132
- function readNumber(record, key) {
133
- const value = record[key];
134
- return typeof value === "number" && Number.isFinite(value) ? value : void 0;
135
- }
136
- function readNonNegativeInteger(record, key) {
137
- const value = readNumber(record, key);
138
- return value !== void 0 && Number.isInteger(value) && value >= 0 ? value : void 0;
139
- }
140
- function readCodexErrorNotificationMessage(record) {
141
- const error = record.error;
142
- return isJsonObject(error) ? readString$3(error, "message") : void 0;
143
- }
144
- function readHookOutputEntries(value) {
145
- if (!Array.isArray(value)) return [];
146
- return value.flatMap((entry) => {
147
- if (!isJsonObject(entry)) return [];
148
- const text = readString$3(entry, "text");
149
- if (!text) return [];
150
- const kind = readString$3(entry, "kind");
151
- return [{
152
- ...kind ? { kind } : {},
153
- text
154
- }];
155
- });
156
- }
157
- function splitPlanText(text) {
158
- return text.split(/\r?\n/).map((line) => line.trim().replace(/^[-*]\s+/, "")).filter((line) => line.length > 0);
159
- }
160
- function extractRawAssistantText(item) {
161
- return (Array.isArray(item.content) ? item.content : []).flatMap((entry) => {
162
- if (!isJsonObject(entry)) return [];
163
- const type = readString$3(entry, "type");
164
- if (type !== "output_text" && type !== "text") return [];
165
- const value = readString$3(entry, "text");
166
- return value ? [value] : [];
167
- }).join("").trim() || void 0;
168
- }
169
- function readItemString(item, key) {
170
- const value = item[key];
171
- return typeof value === "string" ? value : void 0;
172
- }
173
- function readItem(value) {
174
- if (!isJsonObject(value)) return;
175
- const type = typeof value.type === "string" ? value.type : void 0;
176
- const id = typeof value.id === "string" ? value.id : void 0;
177
- if (!type || !id) return;
178
- return value;
179
- }
180
- //#endregion
181
- //#region extensions/codex/src/app-server/event-projector-assistant.ts
182
- var CodexAssistantProjection = class {
183
- constructor(params, emitAgentEvent, matchesToolProgressEcho) {
184
- this.params = params;
185
- this.emitAgentEvent = emitAgentEvent;
186
- this.matchesToolProgressEcho = matchesToolProgressEcho;
187
- this.assistantTextByItem = /* @__PURE__ */ new Map();
188
- this.assistantItemOrder = [];
189
- this.assistantPhaseByItem = /* @__PURE__ */ new Map();
190
- this.latestTerminalAssistantCandidateSuperseded = false;
191
- this.latestTerminalAssistantCandidateCanReleaseAfterToolHandoff = false;
192
- this.terminalAssistantCandidateEarlierActiveItemIds = /* @__PURE__ */ new Set();
193
- this.lastCommentaryProgressTextByItem = /* @__PURE__ */ new Map();
194
- this.pendingRawCommentaryEchoes = 0;
195
- this.rawPromotedAssistantItemIds = /* @__PURE__ */ new Set();
196
- this.assistantStarted = false;
197
- this.streamedPartialAssistantItemReplaceable = false;
198
- }
199
- hasCompletedTerminalAssistantText(completedItemIds) {
200
- const latestCompletedItemId = this.latestCompletedTerminalAssistantItemId;
201
- if (!latestCompletedItemId) return false;
202
- const finalItem = this.resolveFinalAssistantTextItem();
203
- return this.latestCompletedItemId === latestCompletedItemId && finalItem?.itemId === latestCompletedItemId && completedItemIds.has(latestCompletedItemId);
204
- }
205
- getLatestTerminalAssistantCandidate() {
206
- const itemId = this.latestTerminalAssistantCandidateItemId;
207
- if (!itemId) return;
208
- const text = this.assistantTextByItem.get(itemId)?.trim();
209
- return {
210
- itemId,
211
- hasText: Boolean(text && !this.isToolProgressEchoText(itemId, text))
212
- };
213
- }
214
- hasLatestTerminalAssistantCandidateText() {
215
- return !this.latestTerminalAssistantCandidateSuperseded && this.getLatestTerminalAssistantCandidate()?.hasText === true;
216
- }
217
- canReleaseLatestTerminalAssistantAfterToolHandoff() {
218
- return this.latestTerminalAssistantCandidateCanReleaseAfterToolHandoff && this.hasLatestTerminalAssistantCandidateText();
219
- }
220
- async handleAssistantDelta(params) {
221
- const itemId = readString$3(params, "itemId") ?? "assistant";
222
- const delta = readString$3(params, "delta") ?? "";
223
- if (!delta) return;
224
- if (itemId !== this.pendingRawTerminalAssistantEchoItemId) this.pendingRawTerminalAssistantEchoItemId = void 0;
225
- const isCommentary = this.isCommentaryAssistantItem(itemId);
226
- if (!isCommentary && itemId !== this.latestTerminalAssistantCandidateItemId) this.markTerminalAssistantCandidateSupersededBy();
227
- if (!this.assistantStarted) {
228
- this.assistantStarted = true;
229
- await this.params.onAssistantMessageStart?.();
230
- }
231
- this.rememberAssistantItem(itemId);
232
- const text = `${this.assistantTextByItem.get(itemId) ?? ""}${delta}`;
233
- this.assistantTextByItem.set(itemId, text);
234
- if (isCommentary) {
235
- this.emitCommentaryProgress({
236
- itemId,
237
- text
238
- });
239
- return;
240
- }
241
- const knownFinalAnswer = this.shouldStreamAssistantPartial(itemId);
242
- const replace = this.streamedPartialAssistantItemId !== void 0 && this.streamedPartialAssistantItemId !== itemId;
243
- if (replace && (!knownFinalAnswer || this.streamedPartialAssistantItemReplaceable)) this.streamedPartialAssistantItemReplaceable = true;
244
- else if (this.streamedPartialAssistantItemId === void 0) this.streamedPartialAssistantItemReplaceable = !knownFinalAnswer;
245
- this.streamedPartialAssistantItemId = itemId;
246
- const replaceable = this.streamedPartialAssistantItemReplaceable;
247
- const replacement = replace && replaceable;
248
- const streamPayload = {
249
- text,
250
- delta: replacement ? "" : delta,
251
- ...replacement ? { replace: true } : {}
252
- };
253
- this.emitAgentEvent({
254
- stream: "assistant",
255
- data: {
256
- ...streamPayload,
257
- ...replaceable ? { replaceable: true } : {}
258
- }
259
- });
260
- if (knownFinalAnswer && !replaceable) await this.params.onPartialReply?.(streamPayload);
261
- }
262
- recordItemStarted(item, itemId) {
263
- if (item?.type === "agentMessage" && itemId && itemId !== this.pendingRawTerminalAssistantEchoItemId) this.pendingRawTerminalAssistantEchoItemId = void 0;
264
- this.rememberAssistantPhase(item);
265
- if (itemId && itemId !== this.latestTerminalAssistantCandidateItemId) {
266
- this.markTerminalAssistantCandidateSupersededBy(itemId, { preserveEarlierActiveItem: true });
267
- if (this.latestTerminalAssistantCandidateSuperseded) this.pendingRawTerminalAssistantEchoItemId = void 0;
268
- }
269
- }
270
- recordItemCompleted(item, itemId, activeItemIds) {
271
- if (item?.type === "agentMessage" && itemId && itemId !== this.pendingRawTerminalAssistantEchoItemId) this.pendingRawTerminalAssistantEchoItemId = void 0;
272
- if (itemId) this.latestCompletedItemId = itemId;
273
- this.rememberAssistantPhase(item);
274
- if (item?.type === "agentMessage" && !this.isCommentaryAssistantItem(item.id)) {
275
- this.latestCompletedTerminalAssistantItemId = item.id;
276
- this.markLatestTerminalAssistantCandidate(item.id, activeItemIds);
277
- this.pendingRawTerminalAssistantEchoItemId = item.id;
278
- } else if (itemId) {
279
- this.markTerminalAssistantCandidateSupersededBy(itemId, { preserveEarlierActiveItem: true });
280
- if (this.latestTerminalAssistantCandidateSuperseded) this.pendingRawTerminalAssistantEchoItemId = void 0;
281
- }
282
- if (item?.type === "agentMessage" && typeof item.text === "string") {
283
- this.rememberAssistantItem(item.id);
284
- this.assistantTextByItem.set(item.id, item.text);
285
- if (item.text && this.isCommentaryAssistantItem(item.id)) {
286
- this.emitCommentaryProgress({
287
- itemId: item.id,
288
- text: item.text
289
- });
290
- this.pendingRawCommentaryEchoes += 1;
291
- }
292
- }
293
- }
294
- recordSnapshotItem(item) {
295
- this.rememberAssistantPhase(item);
296
- if (item.type === "agentMessage" && typeof item.text === "string") {
297
- this.rememberAssistantItem(item.id);
298
- this.assistantTextByItem.set(item.id, item.text);
299
- }
300
- }
301
- handleRawResponseItemCompleted(item, activeItemIds) {
302
- const role = readString$3(item, "role");
303
- const phase = readString$3(item, "phase");
304
- const rawItemId = readString$3(item, "id");
305
- const candidateWasSupersededBeforeRaw = this.latestTerminalAssistantCandidateSuperseded;
306
- const pendingTerminalAssistantEchoItemId = this.pendingRawTerminalAssistantEchoItemId;
307
- const isPendingTerminalAssistantEcho = role === "assistant" && phase !== "commentary" && pendingTerminalAssistantEchoItemId !== void 0 && (rawItemId === void 0 || rawItemId === pendingTerminalAssistantEchoItemId);
308
- if (pendingTerminalAssistantEchoItemId !== void 0 && !isPendingTerminalAssistantEcho) this.pendingRawTerminalAssistantEchoItemId = void 0;
309
- if (!isPendingTerminalAssistantEcho) {
310
- this.latestCompletedItemId = void 0;
311
- this.markTerminalAssistantCandidateSupersededBy(rawItemId);
312
- }
313
- if (role !== "assistant") return;
314
- if (phase === "commentary" && this.pendingRawCommentaryEchoes > 0) {
315
- this.pendingRawCommentaryEchoes -= 1;
316
- return;
317
- }
318
- const text = extractRawAssistantText(item);
319
- if (isPendingTerminalAssistantEcho) {
320
- const typedItemId = pendingTerminalAssistantEchoItemId;
321
- this.pendingRawTerminalAssistantEchoItemId = void 0;
322
- if (this.assistantTextByItem.get(typedItemId)?.trim() || !text) return;
323
- this.rememberAssistantItem(typedItemId);
324
- this.assistantTextByItem.set(typedItemId, text);
325
- return;
326
- }
327
- if (!text) return;
328
- const itemId = rawItemId ?? `raw-assistant-${this.assistantItemOrder.length + 1}`;
329
- const isIdlessTerminalAssistantAfterCompletedWork = candidateWasSupersededBeforeRaw && rawItemId === void 0 && pendingTerminalAssistantEchoItemId === void 0 && activeItemIds.size === 0;
330
- if (phase !== "commentary" && candidateWasSupersededBeforeRaw && itemId !== this.streamedPartialAssistantItemId && !isIdlessTerminalAssistantAfterCompletedWork) return;
331
- if (phase) this.assistantPhaseByItem.set(itemId, phase);
332
- this.rememberAssistantItem(itemId);
333
- this.assistantTextByItem.set(itemId, text);
334
- this.rawPromotedAssistantItemIds.add(itemId);
335
- if (phase === "commentary") this.emitCommentaryProgress({
336
- itemId,
337
- text
338
- });
339
- else this.markLatestTerminalAssistantCandidate(itemId, activeItemIds, { canReleaseAfterToolHandoff: isIdlessTerminalAssistantAfterCompletedWork });
340
- }
341
- collectAssistantTexts() {
342
- const finalText = this.resolveFinalAssistantTextItem()?.text;
343
- return finalText ? [finalText] : [];
344
- }
345
- hasAssistantItemTextForSynthesis() {
346
- for (let i = this.assistantItemOrder.length - 1; i >= 0; i -= 1) {
347
- const itemId = this.assistantItemOrder[i];
348
- if (!itemId || this.assistantPhaseByItem.get(itemId) === "commentary") continue;
349
- const text = this.assistantTextByItem.get(itemId);
350
- if (text && text.length > 0) return true;
351
- }
352
- return false;
353
- }
354
- createCurrentAttemptAssistantMessage(options) {
355
- for (let i = this.assistantItemOrder.length - 1; i >= 0; i -= 1) {
356
- const itemId = this.assistantItemOrder[i];
357
- if (!itemId || this.isCommentaryAssistantItem(itemId) || !this.assistantTextByItem.has(itemId)) continue;
358
- const text = this.assistantTextByItem.get(itemId) ?? "";
359
- const normalizedText = text.trim();
360
- if (normalizedText && this.isToolProgressEchoText(itemId, normalizedText)) continue;
361
- return this.createAssistantMessage(text, options);
362
- }
363
- }
364
- createAssistantMessage(text, options) {
365
- return createAssistantMessage(this.params, text, options);
366
- }
367
- createAssistantMirrorMessage(title, text) {
368
- return createAssistantMirrorMessage(this.params, title, text);
369
- }
370
- rememberAssistantPhase(item) {
371
- if (item?.type !== "agentMessage") return;
372
- const phase = readItemString(item, "phase");
373
- if (phase) this.assistantPhaseByItem.set(item.id, phase);
374
- }
375
- isCommentaryAssistantItem(itemId) {
376
- return this.assistantPhaseByItem.get(itemId) === "commentary";
377
- }
378
- shouldStreamAssistantPartial(itemId) {
379
- return this.assistantPhaseByItem.get(itemId) === "final_answer";
380
- }
381
- emitCommentaryProgress(params) {
382
- const progressText = params.text.replace(/\s+/g, " ").trim();
383
- if (!progressText || this.lastCommentaryProgressTextByItem.get(params.itemId) === progressText) return;
384
- this.lastCommentaryProgressTextByItem.set(params.itemId, progressText);
385
- this.emitAgentEvent({
386
- stream: "item",
387
- data: {
388
- itemId: params.itemId,
389
- kind: "preamble",
390
- title: "Preamble",
391
- phase: "update",
392
- progressText,
393
- source: "codex-app-server"
394
- }
395
- });
396
- }
397
- markLatestTerminalAssistantCandidate(itemId, activeItemIds, options) {
398
- this.latestTerminalAssistantCandidateItemId = itemId;
399
- this.latestTerminalAssistantCandidateSuperseded = false;
400
- this.latestTerminalAssistantCandidateCanReleaseAfterToolHandoff = options?.canReleaseAfterToolHandoff === true;
401
- this.terminalAssistantCandidateEarlierActiveItemIds = new Set(activeItemIds);
402
- }
403
- markTerminalAssistantCandidateSupersededBy(itemId, options) {
404
- if (!this.latestTerminalAssistantCandidateItemId) return;
405
- if (itemId && this.terminalAssistantCandidateEarlierActiveItemIds.has(itemId)) {
406
- if (!options?.preserveEarlierActiveItem) this.terminalAssistantCandidateEarlierActiveItemIds.delete(itemId);
407
- return;
408
- }
409
- this.latestTerminalAssistantCandidateSuperseded = true;
410
- this.latestTerminalAssistantCandidateCanReleaseAfterToolHandoff = false;
411
- this.terminalAssistantCandidateEarlierActiveItemIds.clear();
412
- }
413
- resolveFinalAssistantTextItem() {
414
- for (let i = this.assistantItemOrder.length - 1; i >= 0; i -= 1) {
415
- const itemId = this.assistantItemOrder[i];
416
- if (!itemId) continue;
417
- const text = this.assistantTextByItem.get(itemId)?.trim();
418
- if (this.assistantPhaseByItem.get(itemId) === "commentary") continue;
419
- if (text && !this.isToolProgressEchoText(itemId, text)) return {
420
- itemId,
421
- text
422
- };
423
- }
424
- }
425
- rememberAssistantItem(itemId) {
426
- if (!itemId || this.assistantItemOrder.includes(itemId)) return;
427
- this.assistantItemOrder.push(itemId);
428
- }
429
- isToolProgressEchoText(itemId, text) {
430
- return this.rawPromotedAssistantItemIds.has(itemId) && this.matchesToolProgressEcho(text);
431
- }
432
- };
433
- //#endregion
434
20
  //#region extensions/codex/src/app-server/event-projector-items.ts
435
21
  function itemKind(item) {
436
22
  switch (item.type) {
@@ -459,1330 +45,87 @@ function itemTitle(item) {
459
45
  function itemStatus(item) {
460
46
  const status = readItemString(item, "status");
461
47
  if (status === "failed" || status === "error") return "failed";
462
- if (status === "declined") return "blocked";
463
- if (status === "inProgress" || status === "in_progress" || status === "running") return "running";
464
- return "completed";
465
- }
466
- function auditNativeToolTerminalStatus(item) {
467
- if (item.type === "imageView" || item.type === "sleep") return "completed";
468
- const status = readItemString(item, "status");
469
- if (status === "completed") return "completed";
470
- if (status === "failed" || status === "error") return "failed";
471
- if (status === "declined") return "blocked";
472
- return "unknown";
473
- }
474
- function auditNativeToolUnfinishedStatus(item) {
475
- return item.type === "webSearch" || item.type === "imageGeneration" ? "unknown" : "failed";
476
- }
477
- function isNonSuccessItemStatus(status) {
478
- return status === "failed" || status === "blocked";
479
- }
480
- function itemName(item) {
481
- if (item.type === "dynamicToolCall" && typeof item.tool === "string") return item.tool;
482
- if (item.type === "mcpToolCall" && typeof item.tool === "string") {
483
- const server = typeof item.server === "string" ? item.server : void 0;
484
- return server ? `${server}.${item.tool}` : item.tool;
485
- }
486
- if (item.type === "commandExecution") return "bash";
487
- if (item.type === "fileChange") return "apply_patch";
488
- if (item.type === "webSearch") return "web_search";
489
- }
490
- function auditNativeToolName(item) {
491
- if (item.type === "dynamicToolCall") return;
492
- const progressName = itemName(item);
493
- if (progressName) return progressName;
494
- if (item.type === "collabAgentToolCall") return typeof item.tool === "string" && item.tool.trim() ? `collab.${item.tool.trim()}` : "collab_agent";
495
- if (item.type === "imageGeneration") return "image_generation";
496
- if (item.type === "imageView") return "image_view";
497
- if (item.type === "sleep") return "sleep";
498
- }
499
- function isSideEffectingNativeToolItem(item) {
500
- return itemStatus(item) !== "blocked" && (isMutatingNativeToolItem(item) || item.type === "mcpToolCall");
501
- }
502
- function shouldSynthesizeToolProgressForItem(item) {
503
- switch (item.type) {
504
- case "commandExecution":
505
- case "fileChange":
506
- case "webSearch":
507
- case "mcpToolCall": return true;
508
- default: return false;
509
- }
510
- }
511
- function shouldRecordNativeToolTranscript(item) {
512
- return shouldSynthesizeToolProgressForItem(item) && item.type !== "webSearch";
513
- }
514
- function isMutatingNativeToolItem(item) {
515
- if (item.type === "commandExecution") return true;
516
- return item.type === "fileChange" || item.type === "collabAgentToolCall" || item.type === "imageGeneration";
517
- }
518
- function shouldClearTerminalPresentationForNativeItem(item) {
519
- switch (item.type) {
520
- case "collabAgentToolCall":
521
- case "commandExecution":
522
- case "fileChange":
523
- case "imageGeneration":
524
- case "imageView":
525
- case "mcpToolCall":
526
- case "webSearch": return true;
527
- default: return false;
528
- }
529
- }
530
- //#endregion
531
- //#region extensions/codex/src/app-server/event-projector-tool-output.ts
532
- const TOOL_TRANSCRIPT_OUTPUT_MAX_CHARS = 1e4;
533
- const TOOL_OUTPUT_TRUNCATION_NOTICE_PREFIX = "...(OpenClaw truncated Codex native tool output";
534
- var ToolOutputAccumulator = class {
535
- constructor() {
536
- this.prefixByItem = /* @__PURE__ */ new Map();
537
- this.originalLengthByItem = /* @__PURE__ */ new Map();
538
- this.normalizedLengthByItem = /* @__PURE__ */ new Map();
539
- this.trimStateByItem = /* @__PURE__ */ new Map();
540
- this.truncatedItemIds = /* @__PURE__ */ new Set();
541
- this.textByItem = /* @__PURE__ */ new Map();
542
- }
543
- append(itemId, delta) {
544
- const originalLength = (this.originalLengthByItem.get(itemId) ?? this.textByItem.get(itemId)?.length ?? 0) + delta.length;
545
- this.originalLengthByItem.set(itemId, originalLength);
546
- const normalizedLength = updateToolOutputTrimState(this.trimStateByItem, itemId, delta);
547
- this.normalizedLengthByItem.set(itemId, normalizedLength);
548
- if (this.truncatedItemIds.has(itemId)) {
549
- const next = appendBoundedToolTranscriptText(this.prefixByItem.get(itemId) ?? this.textByItem.get(itemId) ?? "", "", originalLength);
550
- this.prefixByItem.set(itemId, next.rawPrefix);
551
- this.textByItem.set(itemId, next.text);
552
- return {
553
- text: next.text,
554
- originalLength,
555
- normalizedLength,
556
- rawPrefix: next.rawPrefix
557
- };
558
- }
559
- const next = appendBoundedToolTranscriptText(this.prefixByItem.get(itemId) ?? this.textByItem.get(itemId) ?? "", delta, originalLength);
560
- this.prefixByItem.set(itemId, next.rawPrefix);
561
- this.textByItem.set(itemId, next.text);
562
- if (originalLength > 1e4) this.truncatedItemIds.add(itemId);
563
- return {
564
- text: next.text,
565
- originalLength,
566
- normalizedLength,
567
- rawPrefix: next.rawPrefix
568
- };
569
- }
570
- };
571
- function updateToolOutputTrimState(trimStateByItem, itemId, delta) {
572
- const state = trimStateByItem.get(itemId) ?? {
573
- totalLength: 0,
574
- leadingWhitespaceLength: 0,
575
- trailingWhitespaceLength: 0,
576
- sawNonWhitespace: false
577
- };
578
- state.totalLength += delta.length;
579
- const firstNonWhitespace = delta.search(/\S/u);
580
- if (firstNonWhitespace === -1) {
581
- if (!state.sawNonWhitespace) state.leadingWhitespaceLength += delta.length;
582
- state.trailingWhitespaceLength += delta.length;
583
- trimStateByItem.set(itemId, state);
584
- return state.sawNonWhitespace ? state.totalLength - state.leadingWhitespaceLength - state.trailingWhitespaceLength : 0;
585
- }
586
- if (!state.sawNonWhitespace) {
587
- state.leadingWhitespaceLength += firstNonWhitespace;
588
- state.sawNonWhitespace = true;
589
- }
590
- state.trailingWhitespaceLength = delta.match(/\s*$/u)?.[0].length ?? 0;
591
- trimStateByItem.set(itemId, state);
592
- return state.totalLength - state.leadingWhitespaceLength - state.trailingWhitespaceLength;
593
- }
594
- function toolOutputRawEchoSignature(text) {
595
- const trimmed = text.trim();
596
- if (!trimmed) return;
597
- return {
598
- rawLength: trimmed.length,
599
- rawPrefix: trimmed.slice(0, TOOL_TRANSCRIPT_OUTPUT_MAX_CHARS)
600
- };
601
- }
602
- function normalizeToolTranscriptArguments(value) {
603
- if (!value || typeof value !== "object" || Array.isArray(value)) return {};
604
- return value;
605
- }
606
- function collectDynamicToolContentText(contentItems) {
607
- if (!Array.isArray(contentItems)) return "";
608
- return contentItems.flatMap((entry) => {
609
- if (!isJsonObject(entry)) return [];
610
- const text = readString$3(entry, "text");
611
- return text ? [text] : [];
612
- }).join("\n");
613
- }
614
- function appendBoundedToolTranscriptText(currentPrefix, delta, originalLength) {
615
- if (originalLength <= 1e4) {
616
- const rawPrefix = currentPrefix + delta;
617
- return {
618
- text: rawPrefix,
619
- rawPrefix
620
- };
621
- }
622
- const notice = toolTranscriptTruncationNotice(originalLength);
623
- if (notice.length >= 1e4) return {
624
- text: notice.slice(0, TOOL_TRANSCRIPT_OUTPUT_MAX_CHARS),
625
- rawPrefix: ""
626
- };
627
- const textBudget = TOOL_TRANSCRIPT_OUTPUT_MAX_CHARS - notice.length;
628
- const remaining = Math.max(0, textBudget - currentPrefix.length);
629
- const rawPrefix = truncateUtf16Safe(remaining > 0 ? `${currentPrefix}${truncateUtf16Safe(delta, remaining)}` : currentPrefix, textBudget);
630
- return {
631
- text: `${rawPrefix}${notice}`,
632
- rawPrefix
633
- };
634
- }
635
- function toolTranscriptTruncationNotice(originalLength) {
636
- return `\n${`${TOOL_OUTPUT_TRUNCATION_NOTICE_PREFIX}: original ${originalLength} chars, showing ${TOOL_TRANSCRIPT_OUTPUT_MAX_CHARS}; rerun with narrower args.)`}`;
637
- }
638
- function truncateToolTranscriptText(text, originalLength = text.length) {
639
- if (originalLength <= 1e4 && text.length <= 1e4) return text;
640
- const notice = toolTranscriptTruncationNotice(originalLength);
641
- if (notice.length >= 1e4) return notice.slice(1, 10001);
642
- return `${truncateUtf16Safe(text, TOOL_TRANSCRIPT_OUTPUT_MAX_CHARS - notice.length)}${notice}`;
643
- }
644
- function formatToolSummary(toolName, meta) {
645
- const trimmedMeta = meta?.trim();
646
- return formatToolAggregate(toolName, trimmedMeta ? [trimmedMeta] : void 0, { markdown: true });
647
- }
648
- function formatToolOutput(toolName, meta, output) {
649
- const formattedOutput = formatToolProgressOutput(output);
650
- if (!formattedOutput) return formatToolSummary(toolName, meta);
651
- const fence = markdownFenceForText(formattedOutput);
652
- return `${formatToolSummary(toolName, meta)}\n${fence}txt\n${formattedOutput}\n${fence}`;
653
- }
654
- function markdownFenceForText(text) {
655
- return "`".repeat(Math.max(3, longestBacktickRun(text) + 1));
656
- }
657
- function longestBacktickRun(value) {
658
- let longest = 0;
659
- let current = 0;
660
- for (const char of value) {
661
- if (char === "`") {
662
- current += 1;
663
- longest = Math.max(longest, current);
664
- continue;
665
- }
666
- current = 0;
667
- }
668
- return longest;
669
- }
670
- //#endregion
671
- //#region extensions/codex/src/app-server/tool-progress-normalization.ts
672
- /**
673
- * Normalizes and sanitizes Codex dynamic-tool progress payloads before they are
674
- * emitted into OpenClaw events or logs.
675
- */
676
- /** Maps OpenClaw tool-progress config to the mode used by Codex progress metadata. */
677
- function resolveCodexToolProgressDetailMode(value) {
678
- return value === "raw" ? "raw" : "explain";
679
- }
680
- /** Recursively redacts sensitive strings and handles circular values in event payloads. */
681
- function sanitizeCodexAgentEventValue(value, seen = /* @__PURE__ */ new WeakSet()) {
682
- if (typeof value === "string") return redactToolPayloadText(value);
683
- if (Array.isArray(value)) {
684
- if (seen.has(value)) return "[Circular]";
685
- seen.add(value);
686
- return value.map((entry) => sanitizeCodexAgentEventValue(entry, seen));
687
- }
688
- if (value && typeof value === "object") {
689
- if (seen.has(value)) return "[Circular]";
690
- seen.add(value);
691
- const out = {};
692
- for (const [key, child] of Object.entries(value)) out[key] = typeof child === "string" ? redactSensitiveFieldValue(key, child) : sanitizeCodexAgentEventValue(child, seen);
693
- return out;
694
- }
695
- return value;
696
- }
697
- /** Sanitizes a record-shaped Codex agent event payload. */
698
- function sanitizeCodexAgentEventRecord(value) {
699
- return sanitizeCodexAgentEventValue(value);
700
- }
701
- /** Sanitizes dynamic-tool arguments before diagnostic/event emission. */
702
- function sanitizeCodexToolArguments(value) {
703
- if (!isJsonObject(value)) return;
704
- return sanitizeCodexAgentEventRecord(value);
705
- }
706
- /** Sanitizes a Codex dynamic-tool response before diagnostic/event emission. */
707
- function sanitizeCodexToolResponse(response) {
708
- return sanitizeCodexAgentEventRecord(response);
709
- }
710
- /** Infers compact human-readable tool metadata from Codex dynamic-tool arguments. */
711
- function inferCodexDynamicToolMeta(call, detailMode) {
712
- return inferToolMetaFromArgs(call.tool, call.arguments, { detailMode });
713
- }
714
- //#endregion
715
- //#region extensions/codex/src/app-server/event-projector-tool-items.ts
716
- function nativeToolActionFingerprint(item) {
717
- if (item.type === "commandExecution" && typeof item.command === "string") return JSON.stringify({
718
- type: item.type,
719
- command: item.command,
720
- cwd: typeof item.cwd === "string" ? item.cwd : ""
721
- });
722
- if (item.type === "fileChange") return JSON.stringify({
723
- type: item.type,
724
- changes: itemFileChanges(item)
725
- });
726
- }
727
- function isNativePostToolUseRelayItem(item) {
728
- switch (item.type) {
729
- case "commandExecution":
730
- case "fileChange":
731
- case "mcpToolCall": return true;
732
- default: return false;
733
- }
734
- }
735
- function shouldSuppressChannelProgressForItem(item) {
736
- if (shouldSynthesizeToolProgressForItem(item)) return true;
737
- return item.type === "dynamicToolCall";
738
- }
739
- function itemToolArgs(item) {
740
- if (item.type === "commandExecution") return sanitizeCodexAgentEventRecord({
741
- command: item.command,
742
- ...typeof item.cwd === "string" ? { cwd: item.cwd } : {}
743
- });
744
- if (item.type === "fileChange") return sanitizeCodexAgentEventRecord({ changes: itemFileChangesForTranscript(item) });
745
- if (item.type === "webSearch") return webSearchToolArgs(item);
746
- if (item.type === "dynamicToolCall" || item.type === "mcpToolCall") return sanitizeCodexToolArguments(item.arguments);
747
- }
748
- function webSearchToolArgs(item) {
749
- const action = isJsonObject(item.action) ? item.action : void 0;
750
- const actionType = action ? readNonEmptyString(action, "type") : void 0;
751
- const queries = action && actionType === "search" ? readNonEmptyStringArray(action, "queries") : [];
752
- const query = normalizeNonEmptyString(item.query) ?? (action && actionType === "search" ? readNonEmptyString(action, "query") : void 0) ?? queries[0];
753
- const url = action ? readNonEmptyString(action, "url") : void 0;
754
- const pattern = action ? readNonEmptyString(action, "pattern") : void 0;
755
- const args = {};
756
- if (query) args.query = query;
757
- if (queries.length > 0) args.queries = queries;
758
- if (actionType && actionType !== "search") args.action = actionType;
759
- if (url) args.url = url;
760
- if (pattern) args.pattern = pattern;
761
- if (!query && !url && !pattern) args.queryUnavailable = true;
762
- return sanitizeCodexAgentEventRecord(args);
763
- }
764
- function itemToolResult(item) {
765
- if (item.type === "commandExecution") return { result: sanitizeCodexAgentEventRecord({
766
- status: item.status,
767
- exitCode: item.exitCode,
768
- durationMs: item.durationMs
769
- }) };
770
- if (item.type === "fileChange") return { result: sanitizeCodexAgentEventRecord({
771
- status: item.status,
772
- changes: itemFileChanges(item)
773
- }) };
774
- if (item.type === "mcpToolCall") return { result: sanitizeCodexAgentEventRecord({
775
- status: item.status,
776
- durationMs: item.durationMs,
777
- ...item.error ? { error: item.error } : {},
778
- ...item.result ? { result: item.result } : {}
779
- }) };
780
- if (item.type === "webSearch") return { result: webSearchToolResult(item) };
781
- return {};
782
- }
783
- function webSearchToolResult(item) {
784
- return sanitizeCodexAgentEventRecord({
785
- status: itemStatus(item),
786
- ...typeof item.durationMs === "number" ? { durationMs: item.durationMs } : {},
787
- ...webSearchToolArgs(item)
788
- });
789
- }
790
- function itemFileChangeRecords(item) {
791
- const changes = item.changes;
792
- return Array.isArray(changes) ? changes.filter(isJsonObject) : [];
793
- }
794
- function itemFileChanges(item) {
795
- return itemFileChangeRecords(item).flatMap((change) => {
796
- const path = normalizeNonEmptyString(change.path);
797
- if (!path || change.kind === void 0) return [];
798
- return [{
799
- path,
800
- kind: change.kind
801
- }];
802
- });
803
- }
804
- function fileChangeKindType(kind) {
805
- if (typeof kind === "string") return kind;
806
- return isJsonObject(kind) ? normalizeNonEmptyString(kind.type) : void 0;
807
- }
808
- function countFileContentLines(content) {
809
- if (!content) return 0;
810
- const lines = content.replace(/\r\n/g, "\n").replace(/\r/g, "\n").split("\n");
811
- if (lines.length > 1 && lines.at(-1) === "") lines.pop();
812
- return lines.length;
813
- }
814
- function fileChangeDiffStat(diff, kind) {
815
- const kindType = fileChangeKindType(kind);
816
- if (kindType === "add") return {
817
- added: countFileContentLines(diff),
818
- removed: 0
819
- };
820
- if (kindType === "delete") return {
821
- added: 0,
822
- removed: countFileContentLines(diff)
823
- };
824
- let added = 0;
825
- let removed = 0;
826
- let inHunk = false;
827
- for (const line of diff.replace(/\r\n/g, "\n").replace(/\r/g, "\n").split("\n")) {
828
- if (line.startsWith("@@")) {
829
- inHunk = true;
830
- continue;
831
- }
832
- if (!inHunk) continue;
833
- if (line.startsWith("+")) added += 1;
834
- else if (line.startsWith("-")) removed += 1;
835
- }
836
- return {
837
- added,
838
- removed
839
- };
840
- }
841
- function truncateFileChangeDiffAtLineBoundary(diff, maxChars) {
842
- if (diff.length <= maxChars) return { diff };
843
- if (maxChars <= 0) return { diffTruncated: true };
844
- const boundary = diff.lastIndexOf("\n", maxChars - 1);
845
- return boundary >= 0 ? {
846
- diff: diff.slice(0, boundary + 1),
847
- diffTruncated: true
848
- } : { diffTruncated: true };
849
- }
850
- function itemFileChangesForTranscript(item) {
851
- let remainingDiffChars = 1e4;
852
- return itemFileChangeRecords(item).flatMap((change) => {
853
- const path = normalizeNonEmptyString(change.path);
854
- if (!path || change.kind === void 0) return [];
855
- const result = {
856
- path,
857
- kind: change.kind
858
- };
859
- if (typeof change.diff !== "string") return [result];
860
- result.stat = fileChangeDiffStat(change.diff, change.kind);
861
- const bounded = truncateFileChangeDiffAtLineBoundary(change.diff, remainingDiffChars);
862
- if (bounded.diff !== void 0) {
863
- result.diff = bounded.diff;
864
- remainingDiffChars -= bounded.diff.length;
865
- }
866
- if (bounded.diffTruncated) result.diffTruncated = true;
867
- return [result];
868
- });
869
- }
870
- function itemToolError(item, status, outputTextByItem) {
871
- if (status === "blocked") return "codex native tool blocked";
872
- if (status !== "failed") return;
873
- return itemOutputText(item, outputTextByItem) ?? "codex native tool failed";
874
- }
875
- function itemMeta(item, detailMode = "explain") {
876
- if (item.type === "commandExecution" && typeof item.command === "string") return inferToolMetaFromArgs("exec", {
877
- command: item.command,
878
- cwd: typeof item.cwd === "string" ? item.cwd : void 0
879
- }, { detailMode });
880
- if (item.type === "webSearch") return inferToolMetaFromArgs("web_search", webSearchToolArgs(item), { detailMode });
881
- const toolName = itemName(item);
882
- if ((item.type === "dynamicToolCall" || item.type === "mcpToolCall") && toolName) return inferToolMetaFromArgs(toolName, item.arguments, { detailMode });
883
- }
884
- function itemOutputText(item, outputTextByItem) {
885
- if (item.type === "commandExecution") {
886
- const output = item.aggregatedOutput?.trim() || outputTextByItem?.get(item.id)?.trim();
887
- return output ? truncateToolTranscriptText(output) : void 0;
888
- }
889
- if (item.type === "dynamicToolCall") {
890
- const output = collectDynamicToolContentText(item.contentItems).trim();
891
- return output ? truncateToolTranscriptText(output) : void 0;
892
- }
893
- if (item.type === "mcpToolCall") {
894
- const output = item.error ? stringifyJsonValue(item.error) : item.result ? stringifyJsonValue(item.result) : void 0;
895
- return output ? truncateToolTranscriptText(output) : void 0;
896
- }
897
- }
898
- function itemTranscriptResultText(item, outputTextByItem) {
899
- const output = itemOutputText(item, outputTextByItem);
900
- if (output) return output;
901
- const result = itemToolResult(item).result;
902
- const resultText = result ? stringifyJsonValue(result) : void 0;
903
- return resultText ? truncateToolTranscriptText(resultText) : itemStatus(item);
904
- }
905
- function stringifyJsonValue(value) {
906
- try {
907
- return JSON.stringify(value, null, 2);
908
- } catch {
909
- return;
910
- }
911
- }
912
- //#endregion
913
- //#region extensions/codex/src/app-server/event-projector-tool-progress.ts
914
- const TRANSCRIPT_PROGRESS_SUPPRESSED_TOOL_NAMES = /* @__PURE__ */ new Set([
915
- "message",
916
- "messages",
917
- "reply",
918
- "send",
919
- "reaction",
920
- "react",
921
- "typing"
922
- ]);
923
- function shouldEmitTranscriptToolProgress(toolName, _args) {
924
- const normalized = typeof toolName === "string" ? toolName.trim().toLowerCase() : "";
925
- return Boolean(normalized && !TRANSCRIPT_PROGRESS_SUPPRESSED_TOOL_NAMES.has(normalized));
926
- }
927
- var CodexToolProgressProjection = class {
928
- constructor(params) {
929
- this.params = params;
930
- this.echoesByItem = /* @__PURE__ */ new Map();
931
- this.resultSummaryItemIds = /* @__PURE__ */ new Set();
932
- this.resultOutputItemIds = /* @__PURE__ */ new Set();
933
- this.resultOutputStreamedItemIds = /* @__PURE__ */ new Set();
934
- this.transcriptProgressSuppressedIds = /* @__PURE__ */ new Set();
935
- this.transcriptArgumentsById = /* @__PURE__ */ new Map();
936
- this.resultOutputDeltaState = /* @__PURE__ */ new Map();
937
- this.output = new ToolOutputAccumulator();
938
- this.metas = /* @__PURE__ */ new Map();
939
- this.sideEffectingNativeIds = /* @__PURE__ */ new Set();
940
- this.sideEffectingDynamicIds = /* @__PURE__ */ new Set();
941
- this.transcriptProgressCallIds = /* @__PURE__ */ new Set();
942
- }
943
- get outputTextByItem() {
944
- return this.output.textByItem;
945
- }
946
- get toolMetas() {
947
- return [...this.metas.values()];
948
- }
949
- getToolMeta(itemId) {
950
- return this.metas.get(itemId);
951
- }
952
- get lastToolError() {
953
- return this.lastNativeToolError;
954
- }
955
- get hasPotentialSideEffects() {
956
- return this.sideEffectingNativeIds.size > 0 || this.sideEffectingDynamicIds.size > 0;
957
- }
958
- setLastToolError(error) {
959
- if (!error) {
960
- this.lastNativeToolError = void 0;
961
- return;
962
- }
963
- const terminalResolution = this.params.observeToolTerminal?.({
964
- toolName: error.toolName,
965
- ...error.meta ? { meta: error.meta } : {},
966
- outcome: "failure",
967
- failure: {
968
- ...error.errorCode ? { errorCode: error.errorCode } : {},
969
- ...error.error ? { error: error.error } : {},
970
- ...error.validationErrorSummary ? { validationErrorSummary: error.validationErrorSummary } : {},
971
- ...error.timedOut ? { timedOut: true } : {},
972
- ...error.middlewareError ? { middlewareError: true } : {}
973
- },
974
- nativeMutation: {
975
- mutatingAction: error.mutatingAction === true,
976
- replaySafe: error.mutatingAction !== true,
977
- ...error.actionFingerprint ? { actionFingerprint: error.actionFingerprint } : {},
978
- ...error.fileTarget ? { fileTarget: error.fileTarget } : {}
979
- }
980
- });
981
- this.lastNativeToolError = terminalResolution?.lastToolError ?? (this.lastNativeToolError?.mutatingAction && error.mutatingAction !== true ? this.lastNativeToolError : error);
982
- }
983
- recordDynamicToolResult(params) {
984
- const resultText = collectDynamicToolContentText(params.contentItems);
985
- const existing = this.metas.get(params.callId);
986
- this.metas.set(params.callId, {
987
- toolName: existing?.toolName ?? params.tool,
988
- ...existing?.meta ? { meta: existing.meta } : {},
989
- ...params.asyncStarted === true ? { asyncStarted: true } : {},
990
- ...!params.success ? { isError: true } : {}
991
- });
992
- if (params.terminalResolution) this.lastNativeToolError = params.terminalResolution.lastToolError;
993
- else if (!params.success) this.lastNativeToolError = {
994
- toolName: params.tool,
995
- error: resultText || (params.terminalType === "blocked" ? "codex dynamic tool blocked" : "codex dynamic tool failed")
996
- };
997
- else if (this.lastNativeToolError?.mutatingAction !== true) this.lastNativeToolError = void 0;
998
- if (params.sideEffectEvidence === true) this.sideEffectingDynamicIds.add(params.callId);
999
- }
1000
- handleOutputDelta(params, toolName) {
1001
- const itemId = readString$3(params, "itemId");
1002
- const delta = readString$3(params, "delta");
1003
- if (!itemId || !delta) return;
1004
- const storedOutput = this.output.append(itemId, delta);
1005
- this.rememberEcho(itemId, {
1006
- displayText: storedOutput.text,
1007
- rawLength: storedOutput.normalizedLength,
1008
- rawPrefix: storedOutput.rawPrefix,
1009
- streamedDisplay: true
1010
- });
1011
- if (!this.shouldEmitToolOutput()) return;
1012
- if (this.transcriptProgressSuppressedIds.has(itemId) || !shouldEmitTranscriptToolProgress(toolName, this.transcriptArgumentsById.get(itemId))) return;
1013
- const state = this.resultOutputDeltaState.get(itemId) ?? {
1014
- chars: 0,
1015
- messages: 0,
1016
- truncated: false
1017
- };
1018
- if (state.truncated) return;
1019
- const remainingChars = Math.max(0, TOOL_PROGRESS_OUTPUT_MAX_CHARS - state.chars);
1020
- const remainingMessages = Math.max(0, 20 - state.messages);
1021
- if (remainingChars === 0 || remainingMessages === 0) {
1022
- state.truncated = true;
1023
- this.resultOutputDeltaState.set(itemId, state);
1024
- this.emitToolResultMessage({
1025
- itemId,
1026
- text: formatToolOutput(toolName, void 0, "(output truncated)")
1027
- });
1028
- return;
1029
- }
1030
- const chunk = delta.length > remainingChars ? truncateUtf16Safe(delta, remainingChars) : delta;
1031
- state.chars += chunk.length;
1032
- state.messages += 1;
1033
- const reachedLimit = delta.length > remainingChars || state.chars >= TOOL_PROGRESS_OUTPUT_MAX_CHARS || state.messages >= 20;
1034
- if (reachedLimit) state.truncated = true;
1035
- this.resultOutputDeltaState.set(itemId, state);
1036
- this.resultOutputStreamedItemIds.add(itemId);
1037
- this.emitToolResultMessage({
1038
- itemId,
1039
- text: formatToolOutput(toolName, void 0, reachedLimit ? `${chunk}\n...(truncated)...` : chunk)
1040
- });
1041
- }
1042
- recordNativeToolError(params) {
1043
- const executionStarted = params.status !== "blocked";
1044
- const mutatingAction = executionStarted && isMutatingNativeToolItem(params.item);
1045
- const actionFingerprint = mutatingAction ? nativeToolActionFingerprint(params.item) : void 0;
1046
- const isFailure = isNonSuccessItemStatus(params.status);
1047
- const error = isFailure ? itemToolError(params.item, params.status, this.output.textByItem) : void 0;
1048
- const terminalResolution = this.params.observeToolTerminal?.({
1049
- toolCallId: params.item.id,
1050
- toolName: params.name,
1051
- arguments: itemToolArgs(params.item),
1052
- ...params.meta ? { meta: params.meta } : {},
1053
- executionStarted,
1054
- outcome: isFailure ? "failure" : "success",
1055
- ...isFailure ? { failure: error ? { error } : {} } : {},
1056
- nativeMutation: {
1057
- mutatingAction,
1058
- replaySafe: !mutatingAction,
1059
- ...actionFingerprint ? { actionFingerprint } : {}
1060
- }
1061
- });
1062
- if (terminalResolution) {
1063
- this.lastNativeToolError = terminalResolution.lastToolError;
1064
- return;
1065
- }
1066
- if (isFailure) this.lastNativeToolError = {
1067
- toolName: params.name,
1068
- ...params.meta ? { meta: params.meta } : {},
1069
- ...error ? { error } : {},
1070
- ...mutatingAction ? { mutatingAction: true } : {},
1071
- ...actionFingerprint ? { actionFingerprint } : {}
1072
- };
1073
- else if (this.lastNativeToolError?.mutatingAction !== true) this.lastNativeToolError = void 0;
1074
- }
1075
- emitToolResultSummary(item) {
1076
- if (!item || !this.params.onToolResult || !this.shouldEmitToolResult()) return;
1077
- if (this.resultSummaryItemIds.has(item.id)) return;
1078
- const toolName = itemName(item);
1079
- if (!toolName || !shouldEmitTranscriptToolProgress(toolName, itemToolArgs(item))) return;
1080
- this.resultSummaryItemIds.add(item.id);
1081
- this.emitToolResultMessage({
1082
- itemId: item.id,
1083
- text: formatToolSummary(toolName, itemMeta(item, this.toolProgressDetailMode()))
1084
- });
1085
- }
1086
- emitToolResultOutput(item) {
1087
- if (!item || !this.params.onToolResult || !this.shouldEmitToolOutput()) return;
1088
- if (this.resultOutputItemIds.has(item.id) || this.resultOutputStreamedItemIds.has(item.id)) return;
1089
- const toolName = itemName(item);
1090
- const output = itemOutputText(item, this.output.textByItem);
1091
- if (!toolName || !output || !shouldEmitTranscriptToolProgress(toolName, itemToolArgs(item))) return;
1092
- this.emitToolResultMessage({
1093
- itemId: item.id,
1094
- text: formatToolOutput(toolName, itemMeta(item, this.toolProgressDetailMode()), output),
1095
- finalOutput: true,
1096
- isError: isNonSuccessItemStatus(itemStatus(item))
1097
- });
1098
- }
1099
- recordToolMeta(item) {
1100
- if (!item) return;
1101
- if (isSideEffectingNativeToolItem(item)) this.sideEffectingNativeIds.add(item.id);
1102
- else this.sideEffectingNativeIds.delete(item.id);
1103
- const toolName = itemName(item);
1104
- if (!toolName) return;
1105
- const meta = itemMeta(item, this.toolProgressDetailMode());
1106
- const status = itemStatus(item);
1107
- const existing = this.metas.get(item.id);
1108
- this.metas.set(item.id, {
1109
- toolName,
1110
- ...meta ? { meta } : {},
1111
- ...existing?.asyncStarted ? { asyncStarted: true } : {},
1112
- ...status !== "running" && isNonSuccessItemStatus(status) ? { isError: true } : {}
1113
- });
1114
- }
1115
- recordTranscriptCall(params) {
1116
- this.transcriptArgumentsById.set(params.id, params.arguments);
1117
- if (!shouldEmitTranscriptToolProgress(params.name, params.arguments)) this.transcriptProgressSuppressedIds.add(params.id);
1118
- else this.transcriptProgressSuppressedIds.delete(params.id);
1119
- this.emitTranscriptToolCallProgress(params);
1120
- }
1121
- recordTranscriptResult(params) {
1122
- this.emitTranscriptToolResultProgress(params);
1123
- }
1124
- matchesEcho(text) {
1125
- for (const state of this.echoesByItem.values()) {
1126
- if (state.streamedDisplayText === text || state.displayTexts.includes(text)) return true;
1127
- if (state.streamedRawSignature && text.length === state.streamedRawSignature.length && text.startsWith(state.streamedRawSignature.prefix)) return true;
1128
- for (const signature of state.rawSignatures) if (text.length === signature.length && text.startsWith(signature.prefix)) return true;
1129
- }
1130
- return false;
1131
- }
1132
- rememberCommandAggregateOutputEcho(item) {
1133
- if (item?.type !== "commandExecution" || typeof item.aggregatedOutput !== "string") return;
1134
- const signature = toolOutputRawEchoSignature(item.aggregatedOutput);
1135
- if (signature) this.rememberEcho(item.id, signature);
1136
- }
1137
- toolProgressDetailMode() {
1138
- return resolveCodexToolProgressDetailMode(this.params.toolProgressDetail);
1139
- }
1140
- emitToolResultMessage(params) {
1141
- const rawText = params.text.trim();
1142
- const text = truncateToolTranscriptText(rawText);
1143
- if (!text) return;
1144
- this.rememberEcho(params.itemId, {
1145
- displayText: text,
1146
- rawText
1147
- });
1148
- if (params.finalOutput) this.resultOutputItemIds.add(params.itemId);
1149
- try {
1150
- Promise.resolve(this.params.onToolResult?.({
1151
- text,
1152
- ...params.isError === true ? { isError: true } : {}
1153
- })).catch(() => {});
1154
- } catch {}
1155
- }
1156
- shouldEmitToolResult() {
1157
- return typeof this.params.shouldEmitToolResult === "function" ? this.params.shouldEmitToolResult() : this.params.verboseLevel === "on" || this.params.verboseLevel === "full";
1158
- }
1159
- shouldEmitToolOutput() {
1160
- return typeof this.params.shouldEmitToolOutput === "function" ? this.params.shouldEmitToolOutput() : this.params.verboseLevel === "full";
1161
- }
1162
- emitTranscriptToolCallProgress(params) {
1163
- if (!shouldEmitTranscriptToolProgress(params.name, params.arguments)) return;
1164
- this.transcriptProgressCallIds.add(params.id);
1165
- const args = normalizeToolTranscriptArguments(params.arguments);
1166
- const meta = inferToolMetaFromArgs(params.name, args, { detailMode: this.toolProgressDetailMode() });
1167
- if (!this.params.onToolResult || !this.shouldEmitToolResult() || this.resultSummaryItemIds.has(params.id) || this.resultOutputStreamedItemIds.has(params.id)) return;
1168
- this.resultSummaryItemIds.add(params.id);
1169
- this.emitToolResultMessage({
1170
- itemId: params.id,
1171
- text: formatToolSummary(params.name, meta)
1172
- });
1173
- }
1174
- emitTranscriptToolResultProgress(params) {
1175
- if (this.transcriptProgressSuppressedIds.has(params.id) || !shouldEmitTranscriptToolProgress(params.name, this.transcriptArgumentsById.get(params.id))) return;
1176
- if (!this.transcriptProgressCallIds.has(params.id)) this.emitTranscriptToolCallProgress({
1177
- id: params.id,
1178
- name: params.name,
1179
- arguments: {}
1180
- });
1181
- if (!this.params.onToolResult || !this.shouldEmitToolOutput() || this.resultOutputItemIds.has(params.id) || this.resultOutputStreamedItemIds.has(params.id)) return;
1182
- const text = params.text?.trim();
1183
- if (text) this.emitToolResultMessage({
1184
- itemId: params.id,
1185
- text: formatToolOutput(params.name, void 0, text),
1186
- finalOutput: true,
1187
- isError: params.isError
1188
- });
1189
- }
1190
- rememberEcho(itemId, signature) {
1191
- if (!itemId) return;
1192
- const existing = this.echoesByItem.get(itemId) ?? {
1193
- displayTexts: [],
1194
- rawSignatures: []
1195
- };
1196
- const displayText = signature.displayText?.trim();
1197
- if (displayText) {
1198
- if (signature.streamedDisplay) existing.streamedDisplayText = displayText;
1199
- else if (!existing.displayTexts.includes(displayText)) {
1200
- if (existing.displayTexts.length >= 24) existing.displayTexts.shift();
1201
- existing.displayTexts.push(displayText);
1202
- }
1203
- }
1204
- const rawText = signature.rawText?.trim();
1205
- const rawLength = signature.rawLength ?? rawText?.length;
1206
- const rawPrefix = signature.rawPrefix?.trim() ?? rawText;
1207
- if (rawLength !== void 0 && rawPrefix && rawPrefix.length >= 1024) {
1208
- const next = {
1209
- length: rawLength,
1210
- prefix: rawPrefix.slice(0, TOOL_TRANSCRIPT_OUTPUT_MAX_CHARS)
1211
- };
1212
- if (signature.streamedDisplay) existing.streamedRawSignature = next;
1213
- else {
1214
- const matchIndex = existing.rawSignatures.findIndex((entry) => entry.prefix === next.prefix);
1215
- if (matchIndex >= 0) existing.rawSignatures[matchIndex] = next;
1216
- else {
1217
- if (existing.rawSignatures.length >= 24) existing.rawSignatures.shift();
1218
- existing.rawSignatures.push(next);
1219
- }
1220
- }
1221
- }
1222
- this.echoesByItem.set(itemId, existing);
1223
- }
1224
- };
1225
- //#endregion
1226
- //#region extensions/codex/src/app-server/session-history.ts
1227
- /**
1228
- * Reads OpenClaw session history for Codex transcript mirroring and sanitizes
1229
- * image payloads before replaying messages into the app-server projector.
1230
- */
1231
- function isMissingFileError(error) {
1232
- return Boolean(error && typeof error === "object" && "code" in error && error.code === "ENOENT");
1233
- }
1234
- /** Returns sanitized session-context messages for a Codex mirrored session file. */
1235
- async function readCodexMirroredSessionHistoryMessages(target) {
1236
- try {
1237
- const entries = await readCodexMirroredSessionEntries(target);
1238
- if (entries.length === 0) return [];
1239
- const firstEntry = entries[0];
1240
- if (firstEntry?.type !== "session") return [];
1241
- if (typeof firstEntry.id !== "string") return;
1242
- migrateSessionEntries(entries);
1243
- return sanitizeCodexHistoryImagePayloads(buildSessionContext(entries.filter((entry) => {
1244
- return entry !== null && typeof entry === "object" && !Array.isArray(entry) && entry.type !== "session";
1245
- })).messages, "codex mirrored history");
1246
- } catch (error) {
1247
- if (isMissingFileError(error)) return [];
1248
- return;
1249
- }
1250
- }
1251
- async function readCodexMirroredSessionEntries(target) {
1252
- const sqliteMarker = parseSqliteSessionFileMarker(target.sessionFile);
1253
- if (sqliteMarker) {
1254
- if (sqliteMarker.sessionId !== target.sessionId || target.agentId !== void 0 && sqliteMarker.agentId !== target.agentId) return [];
1255
- const sessionKey = resolveSqliteMarkerSessionKey(target, sqliteMarker);
1256
- if (!sessionKey) return [];
1257
- return await readSessionTranscriptEvents({
1258
- agentId: sqliteMarker.agentId,
1259
- sessionId: sqliteMarker.sessionId,
1260
- sessionKey,
1261
- storePath: sqliteMarker.storePath
1262
- });
1263
- }
1264
- return parseSessionEntries(await fs.readFile(target.sessionFile, "utf-8"));
1265
- }
1266
- function resolveSqliteMarkerSessionKey(target, marker) {
1267
- const explicitSessionKey = target.sessionKey?.trim();
1268
- if (explicitSessionKey) return explicitSessionKey;
1269
- const entries = listSessionEntries({
1270
- agentId: marker.agentId,
1271
- storePath: marker.storePath
1272
- });
1273
- return (entries.find(({ entry }) => {
1274
- return entry.sessionId === marker.sessionId && entry.sessionFile === target.sessionFile;
1275
- }) ?? entries.find(({ entry }) => {
1276
- return entry.sessionId === marker.sessionId;
1277
- }))?.sessionKey;
1278
- }
1279
- //#endregion
1280
- //#region extensions/codex/src/app-server/event-projector-tool-transcript.ts
1281
- const ZERO_USAGE = {
1282
- input: 0,
1283
- output: 0,
1284
- cacheRead: 0,
1285
- cacheWrite: 0,
1286
- totalTokens: 0,
1287
- cost: {
1288
- input: 0,
1289
- output: 0,
1290
- cacheRead: 0,
1291
- cacheWrite: 0,
1292
- total: 0
1293
- }
1294
- };
1295
- const MISSING_TOOL_RESULT_ERROR = "OpenClaw recorded a native Codex tool.call without a matching tool.result before the turn completed.";
1296
- var CodexToolTranscriptProjection = class {
1297
- constructor(params, threadId, turnId, progress, options = {}) {
1298
- this.params = params;
1299
- this.threadId = threadId;
1300
- this.turnId = turnId;
1301
- this.progress = progress;
1302
- this.options = options;
1303
- this.messages = [];
1304
- this.callIds = /* @__PURE__ */ new Set();
1305
- this.resultIds = /* @__PURE__ */ new Set();
1306
- this.namesById = /* @__PURE__ */ new Map();
1307
- this.trajectoryCallIds = /* @__PURE__ */ new Set();
1308
- this.trajectoryResultIds = /* @__PURE__ */ new Set();
1309
- this.trajectoryNamesById = /* @__PURE__ */ new Map();
1310
- this.trajectoryItemsById = /* @__PURE__ */ new Map();
1311
- this.afterToolCallObservedItemIds = /* @__PURE__ */ new Set();
1312
- }
1313
- get transcriptMessages() {
1314
- return this.messages;
1315
- }
1316
- recordDynamicToolCall(params) {
1317
- this.recordToolCall({
1318
- id: params.callId,
1319
- name: params.tool,
1320
- arguments: sanitizeCodexToolArguments(params.arguments)
1321
- });
1322
- }
1323
- recordDynamicToolResult(params) {
1324
- this.recordToolResult({
1325
- id: params.callId,
1326
- name: params.tool,
1327
- text: collectDynamicToolContentText(params.contentItems),
1328
- isError: !params.success
1329
- });
1330
- }
1331
- recordNativeToolCall(item) {
1332
- if (!item || !shouldRecordNativeToolTranscript(item)) return;
1333
- const name = itemName(item);
1334
- if (name) this.recordToolCall({
1335
- id: item.id,
1336
- name,
1337
- arguments: itemToolArgs(item)
1338
- });
1339
- }
1340
- recordNativeToolResult(item) {
1341
- if (!item || !shouldRecordNativeToolTranscript(item)) return;
1342
- const name = itemName(item);
1343
- if (name) this.recordToolResult({
1344
- id: item.id,
1345
- name,
1346
- text: itemTranscriptResultText(item, this.progress.outputTextByItem),
1347
- isError: isNonSuccessItemStatus(itemStatus(item))
1348
- });
1349
- }
1350
- recordTrajectoryEvent(params) {
1351
- if (params.phase === "start") {
1352
- this.trajectoryCallIds.add(params.item.id);
1353
- this.trajectoryNamesById.set(params.item.id, params.name);
1354
- this.trajectoryItemsById.set(params.item.id, params.item);
1355
- this.options.trajectoryRecorder?.recordEvent("tool.call", {
1356
- threadId: this.threadId,
1357
- turnId: this.turnId,
1358
- itemId: params.item.id,
1359
- toolCallId: params.item.id,
1360
- name: params.name,
1361
- arguments: params.args
1362
- });
1363
- return;
1364
- }
1365
- this.trajectoryResultIds.add(params.item.id);
1366
- const toolResult = itemToolResult(params.item).result;
1367
- const output = itemOutputText(params.item, this.progress.outputTextByItem);
1368
- this.options.trajectoryRecorder?.recordEvent("tool.result", {
1369
- threadId: this.threadId,
1370
- turnId: this.turnId,
1371
- itemId: params.item.id,
1372
- toolCallId: params.item.id,
1373
- name: params.name,
1374
- status: params.status,
1375
- isError: isNonSuccessItemStatus(params.status),
1376
- ...toolResult ? { result: toolResult } : {},
1377
- ...output ? { output } : {}
1378
- });
1379
- }
1380
- emitAfterToolCallObservation(item) {
1381
- if (!this.shouldEmitAfterToolCallObservation(item)) return;
1382
- const name = itemName(item);
1383
- const status = itemStatus(item);
1384
- if (!name || status === "running") return;
1385
- this.afterToolCallObservedItemIds.add(item.id);
1386
- const result = itemToolResult(item).result;
1387
- const error = itemToolError(item, status, this.progress.outputTextByItem);
1388
- const startedAt = resolveStartedAtFromDurationMs(item.durationMs);
1389
- const hookParams = {
1390
- toolName: name,
1391
- toolCallId: item.id,
1392
- runId: this.params.runId,
1393
- agentId: this.params.agentId,
1394
- sessionId: this.params.sessionId,
1395
- sessionKey: this.params.sessionKey,
1396
- startArgs: itemToolArgs(item) ?? {},
1397
- ...result !== void 0 ? { result } : {},
1398
- ...error ? { error } : {},
1399
- ...startedAt !== void 0 ? { startedAt } : {}
1400
- };
1401
- setImmediate(() => {
1402
- runAgentHarnessAfterToolCallHook(hookParams);
1403
- });
1404
- }
1405
- synthesizeMissingToolResults(params) {
1406
- if (!params.synthesize) return;
1407
- const missingTranscriptIds = [...this.callIds].filter((id) => !this.resultIds.has(id));
1408
- const missingTrajectoryIds = [...this.trajectoryCallIds].filter((id) => !this.trajectoryResultIds.has(id));
1409
- if (missingTranscriptIds.length === 0 && missingTrajectoryIds.length === 0) return;
1410
- for (const id of missingTranscriptIds) {
1411
- const name = this.namesById.get(id) ?? this.trajectoryNamesById.get(id);
1412
- if (name) this.recordToolResult({
1413
- id,
1414
- name,
1415
- text: formatMissingToolResultError({
1416
- id,
1417
- name
1418
- }),
1419
- isError: true
1420
- });
1421
- }
1422
- for (const id of missingTrajectoryIds) {
1423
- const name = this.trajectoryNamesById.get(id) ?? this.namesById.get(id);
1424
- if (!name) continue;
1425
- this.trajectoryResultIds.add(id);
1426
- const text = formatMissingToolResultError({
1427
- id,
1428
- name
1429
- });
1430
- this.options.trajectoryRecorder?.recordEvent("tool.result", {
1431
- threadId: this.threadId,
1432
- turnId: this.turnId,
1433
- itemId: id,
1434
- toolCallId: id,
1435
- name,
1436
- status: "failed",
1437
- isError: true,
1438
- result: {
1439
- status: "failed",
1440
- reason: "missing_tool_result"
1441
- },
1442
- output: text
1443
- });
1444
- }
1445
- if (!params.recordPromptError) {
1446
- this.recordMissingToolError(missingTranscriptIds, missingTrajectoryIds);
1447
- return;
1448
- }
1449
- const missingCount = (/* @__PURE__ */ new Set([...missingTranscriptIds, ...missingTrajectoryIds])).size;
1450
- return missingCount === 1 ? MISSING_TOOL_RESULT_ERROR : `${MISSING_TOOL_RESULT_ERROR} missingToolResultCount=${missingCount}`;
1451
- }
1452
- async readMirroredSessionMessages() {
1453
- return await readCodexMirroredSessionHistoryMessages({
1454
- agentId: this.params.agentId,
1455
- sessionFile: this.params.sessionFile,
1456
- sessionId: this.params.sessionId,
1457
- sessionKey: this.params.sessionKey
1458
- }) ?? [];
1459
- }
1460
- recordToolCall(params) {
1461
- if (!params.id || !params.name || this.callIds.has(params.id)) return;
1462
- this.callIds.add(params.id);
1463
- this.namesById.set(params.id, params.name);
1464
- this.progress.recordTranscriptCall(params);
1465
- this.messages.push(attachCodexMirrorIdentity(this.createToolCallMessage(params), `${this.turnId}:tool:${params.id}:call`));
1466
- }
1467
- recordToolResult(params) {
1468
- if (!params.id || !params.name || this.resultIds.has(params.id)) return;
1469
- this.resultIds.add(params.id);
1470
- this.progress.recordTranscriptResult(params);
1471
- this.messages.push(attachCodexMirrorIdentity(this.createToolResultMessage(params), `${this.turnId}:tool:${params.id}:result`));
1472
- }
1473
- recordMissingToolError(missingTranscriptIds, missingTrajectoryIds) {
1474
- const firstMissingId = missingTranscriptIds.find((id) => Boolean(this.namesById.get(id))) ?? missingTrajectoryIds.find((id) => Boolean(this.trajectoryNamesById.get(id) ?? this.namesById.get(id)));
1475
- if (!firstMissingId) return;
1476
- const name = this.namesById.get(firstMissingId) ?? this.trajectoryNamesById.get(firstMissingId);
1477
- if (!name) return;
1478
- const item = this.trajectoryItemsById.get(firstMissingId);
1479
- const meta = item ? itemMeta(item, this.progress.toolProgressDetailMode()) : this.progress.getToolMeta(firstMissingId)?.meta;
1480
- const actionFingerprint = item ? nativeToolActionFingerprint(item) : void 0;
1481
- this.progress.setLastToolError({
1482
- toolName: name,
1483
- ...meta ? { meta } : {},
1484
- error: formatMissingToolResultError({
1485
- id: firstMissingId,
1486
- name
1487
- }),
1488
- ...item && isMutatingNativeToolItem(item) ? { mutatingAction: true } : {},
1489
- ...actionFingerprint ? { actionFingerprint } : {}
1490
- });
1491
- }
1492
- shouldEmitAfterToolCallObservation(item) {
1493
- if (!shouldSynthesizeToolProgressForItem(item) || this.afterToolCallObservedItemIds.has(item.id)) return false;
1494
- return !(this.options.nativePostToolUseRelayEnabled && isNativePostToolUseRelayItem(item));
1495
- }
1496
- createToolCallMessage(params) {
1497
- const args = normalizeToolTranscriptArguments(params.arguments);
1498
- const attribution = resolveCodexLocalRuntimeAttribution(this.params);
1499
- return {
1500
- role: "assistant",
1501
- content: [{
1502
- type: "toolCall",
1503
- id: params.id,
1504
- name: params.name,
1505
- arguments: args,
1506
- input: args
1507
- }],
1508
- api: attribution.api ?? "openai-chatgpt-responses",
1509
- provider: attribution.provider,
1510
- model: this.params.modelId,
1511
- usage: ZERO_USAGE,
1512
- stopReason: "toolUse",
1513
- timestamp: Date.now()
1514
- };
1515
- }
1516
- createToolResultMessage(params) {
1517
- const text = truncateToolTranscriptText(params.text?.trim() || toolResultStatusText(params));
1518
- return {
1519
- role: "toolResult",
1520
- toolCallId: params.id,
1521
- toolName: params.name,
1522
- isError: params.isError,
1523
- content: [{
1524
- type: "toolResult",
1525
- id: params.id,
1526
- name: params.name,
1527
- toolName: params.name,
1528
- toolCallId: params.id,
1529
- toolUseId: params.id,
1530
- tool_use_id: params.id,
1531
- content: text,
1532
- text
1533
- }],
1534
- timestamp: Date.now()
1535
- };
1536
- }
1537
- };
1538
- function formatMissingToolResultError(params) {
1539
- return `${MISSING_TOOL_RESULT_ERROR} toolCallId=${params.id}; toolName=${params.name}`;
1540
- }
1541
- function toolResultStatusText(params) {
1542
- return params.isError ? `${params.name} failed` : `${params.name} completed`;
1543
- }
1544
- function resolveStartedAtFromDurationMs(durationMs) {
1545
- if (typeof durationMs !== "number" || !Number.isFinite(durationMs)) return;
1546
- return asDateTimestampMs(Date.now() - Math.max(0, durationMs));
1547
- }
1548
- //#endregion
1549
- //#region extensions/codex/src/app-server/event-projector-events.ts
1550
- var CodexEventProjection = class {
1551
- constructor(threadId, turnId, emitAgentEvent, toolProgress, toolTranscript, onNativeToolResultRecorded) {
1552
- this.threadId = threadId;
1553
- this.turnId = turnId;
1554
- this.emitAgentEvent = emitAgentEvent;
1555
- this.toolProgress = toolProgress;
1556
- this.toolTranscript = toolTranscript;
1557
- this.onNativeToolResultRecorded = onNativeToolResultRecorded;
1558
- this.reviewCount = 0;
1559
- }
1560
- get guardianReviewCount() {
1561
- return this.reviewCount;
1562
- }
1563
- handleGuardianReview(method, params) {
1564
- this.reviewCount += 1;
1565
- const review = isJsonObject(params.review) ? params.review : void 0;
1566
- const action = isJsonObject(params.action) ? params.action : void 0;
1567
- this.emitAgentEvent({
1568
- stream: "codex_app_server.guardian",
1569
- data: {
1570
- method,
1571
- phase: method.endsWith("/started") ? "started" : "completed",
1572
- reviewId: readString$3(params, "reviewId"),
1573
- targetItemId: readNullableString(params, "targetItemId"),
1574
- decisionSource: readString$3(params, "decisionSource"),
1575
- status: review ? readString$3(review, "status") : void 0,
1576
- riskLevel: review ? readString$3(review, "riskLevel") : void 0,
1577
- userAuthorization: review ? readString$3(review, "userAuthorization") : void 0,
1578
- rationale: review ? readNullableString(review, "rationale") : void 0,
1579
- actionType: action ? readString$3(action, "type") : void 0
1580
- }
1581
- });
1582
- }
1583
- handleGuardianWarning(params) {
1584
- this.emitAgentEvent({
1585
- stream: "codex_app_server.guardian",
1586
- data: {
1587
- phase: "warning",
1588
- message: readString$3(params, "message")
1589
- }
1590
- });
1591
- }
1592
- handleHook(method, params) {
1593
- const run = isJsonObject(params.run) ? params.run : void 0;
1594
- if (!run) return;
1595
- const durationMs = readNumber(run, "durationMs");
1596
- const entries = readHookOutputEntries(run.entries);
1597
- const hookTurnId = readNullableString(params, "turnId");
1598
- this.emitAgentEvent({
1599
- stream: "codex_app_server.hook",
1600
- data: {
1601
- phase: method === "hook/started" ? "started" : "completed",
1602
- threadId: this.threadId,
1603
- turnId: hookTurnId === void 0 ? this.turnId : hookTurnId,
1604
- hookRunId: readString$3(run, "id"),
1605
- eventName: readString$3(run, "eventName"),
1606
- handlerType: readString$3(run, "handlerType"),
1607
- executionMode: readString$3(run, "executionMode"),
1608
- scope: readString$3(run, "scope"),
1609
- source: readString$3(run, "source"),
1610
- sourcePath: readString$3(run, "sourcePath"),
1611
- status: readString$3(run, "status"),
1612
- statusMessage: readNullableString(run, "statusMessage"),
1613
- ...durationMs !== void 0 ? { durationMs } : {},
1614
- ...entries.length > 0 ? { entries } : {}
1615
- }
1616
- });
1617
- }
1618
- emitStandardItemEvent(params) {
1619
- const { item } = params;
1620
- if (!item) return;
1621
- const kind = itemKind(item);
1622
- if (!kind) return;
1623
- const meta = itemMeta(item, this.toolProgress.toolProgressDetailMode());
1624
- const suppressChannelProgress = shouldSuppressChannelProgressForItem(item);
1625
- this.emitAgentEvent({
1626
- stream: "item",
1627
- data: {
1628
- itemId: item.id,
1629
- phase: params.phase,
1630
- kind,
1631
- title: itemTitle(item),
1632
- status: params.phase === "start" ? "running" : itemStatus(item),
1633
- ...itemName(item) ? { name: itemName(item) } : {},
1634
- ...meta ? { meta } : {},
1635
- ...suppressChannelProgress ? { suppressChannelProgress: true } : {}
1636
- }
1637
- });
1638
- }
1639
- async emitNormalizedToolItemEvent(params) {
1640
- const { item } = params;
1641
- if (!item || !shouldSynthesizeToolProgressForItem(item)) return;
1642
- const name = itemName(item);
1643
- if (!name) return;
1644
- const status = params.phase === "result" ? itemStatus(item) : "running";
1645
- const args = itemToolArgs(item);
1646
- const meta = itemMeta(item, this.toolProgress.toolProgressDetailMode());
1647
- this.toolTranscript.recordTrajectoryEvent({
1648
- phase: params.phase,
1649
- item,
1650
- name,
1651
- args,
1652
- status
1653
- });
1654
- if (params.phase === "result") this.toolProgress.recordNativeToolError({
1655
- item,
1656
- name,
1657
- meta,
1658
- status
1659
- });
1660
- if (!shouldEmitTranscriptToolProgress(name, args)) {
1661
- if (params.phase === "result") {
1662
- this.toolTranscript.emitAfterToolCallObservation(item);
1663
- await this.onNativeToolResultRecorded?.();
1664
- }
1665
- return;
1666
- }
1667
- this.emitAgentEvent({
1668
- stream: "tool",
1669
- data: {
1670
- phase: params.phase,
1671
- name,
1672
- itemId: item.id,
1673
- toolCallId: item.id,
1674
- ...meta ? { meta } : {},
1675
- ...params.phase === "start" && args ? { args } : {},
1676
- ...params.phase === "result" ? {
1677
- status,
1678
- isError: isNonSuccessItemStatus(status),
1679
- ...itemToolResult(item)
1680
- } : {}
1681
- }
1682
- });
1683
- if (params.phase === "result") {
1684
- this.toolTranscript.emitAfterToolCallObservation(item);
1685
- await this.onNativeToolResultRecorded?.();
1686
- }
1687
- }
1688
- };
1689
- //#endregion
1690
- //#region extensions/codex/src/app-server/event-projector-media.ts
1691
- const GENERATED_IMAGE_MEDIA_SUBDIR = "tool-image-generation";
1692
- const BYTES_PER_MB = 1024 * 1024;
1693
- const DEFAULT_GENERATED_IMAGE_MAX_BYTES = 6 * BYTES_PER_MB;
1694
- var CodexGeneratedMediaProjection = class {
1695
- constructor(config) {
1696
- this.config = config;
1697
- this.itemIds = /* @__PURE__ */ new Set();
1698
- this.urlsByItemId = /* @__PURE__ */ new Map();
1699
- }
1700
- hasGeneratedMedia() {
1701
- return this.itemIds.size > 0;
1702
- }
1703
- recordNative(item) {
1704
- if (item?.type !== "imageGeneration") return;
1705
- const savedPath = readItemString(item, "savedPath")?.trim();
1706
- if (savedPath) this.recordUrl({
1707
- itemId: item.id,
1708
- mediaUrl: savedPath
1709
- });
1710
- }
1711
- async recordRaw(item) {
1712
- if (readString$3(item, "type") !== "image_generation_call") return;
1713
- const result = readString$3(item, "result");
1714
- if (!result) return;
1715
- const itemId = readString$3(item, "id") ?? `raw-image-${this.itemIds.size}`;
1716
- this.itemIds.add(itemId);
1717
- const maxBytes = resolveGeneratedImageMaxBytes(this.config);
1718
- const estimatedDecodedBytes = estimateBase64DecodedBytes(result);
1719
- if (estimatedDecodedBytes !== void 0 && estimatedDecodedBytes > maxBytes) {
1720
- embeddedAgentLog.warn("codex app-server raw image generation result exceeds media limit", {
1721
- itemId,
1722
- estimatedDecodedBytes,
1723
- maxBytes
1724
- });
1725
- return;
1726
- }
1727
- const asset = generatedImageAssetFromBase64({
1728
- base64: result,
1729
- index: this.itemIds.size,
1730
- revisedPrompt: readString$3(item, "revised_prompt") ?? readString$3(item, "revisedPrompt"),
1731
- fileNamePrefix: "codex-image-generation",
1732
- sniffMimeType: true
1733
- });
1734
- if (!asset) return;
1735
- try {
1736
- const saved = await saveMediaBuffer(asset.buffer, asset.mimeType, GENERATED_IMAGE_MEDIA_SUBDIR, maxBytes, asset.fileName);
1737
- this.recordUrl({
1738
- itemId,
1739
- mediaUrl: saved.path,
1740
- replaceExisting: true
1741
- });
1742
- } catch (error) {
1743
- embeddedAgentLog.warn("codex app-server raw image generation result save failed", {
1744
- itemId,
1745
- error
1746
- });
1747
- }
1748
- }
1749
- buildToolMediaUrls(params) {
1750
- const mediaUrls = new Set(params.toolMediaUrls?.map((url) => url.trim()).filter(Boolean) ?? []);
1751
- if ((params.messagingToolSentMediaUrls?.length ?? 0) === 0) for (const mediaUrl of this.urlsByItemId.values()) mediaUrls.add(mediaUrl);
1752
- return mediaUrls.size > 0 ? [...mediaUrls] : params.toolMediaUrls;
48
+ if (status === "declined") return "blocked";
49
+ if (status === "inProgress" || status === "in_progress" || status === "running") return "running";
50
+ return "completed";
51
+ }
52
+ function unknownItemStatus(item) {
53
+ const status = readItemString(item, "status");
54
+ switch (status) {
55
+ case void 0:
56
+ case "completed":
57
+ case "failed":
58
+ case "error":
59
+ case "declined":
60
+ case "inProgress":
61
+ case "in_progress":
62
+ case "running": return;
63
+ default: return status;
1753
64
  }
1754
- recordUrl(params) {
1755
- if (this.urlsByItemId.has(params.itemId) && params.replaceExisting !== true) {
1756
- this.itemIds.add(params.itemId);
1757
- return;
1758
- }
1759
- this.urlsByItemId.set(params.itemId, params.mediaUrl);
1760
- this.itemIds.add(params.itemId);
65
+ }
66
+ function auditNativeToolTerminalStatus(item) {
67
+ if (item.type === "imageView" || item.type === "sleep") return "completed";
68
+ const status = readItemString(item, "status");
69
+ if (status === "completed") return "completed";
70
+ if (status === "failed" || status === "error") return "failed";
71
+ if (status === "declined") return "blocked";
72
+ return "unknown";
73
+ }
74
+ function auditNativeToolUnfinishedStatus(item) {
75
+ return item.type === "webSearch" || item.type === "imageGeneration" ? "unknown" : "failed";
76
+ }
77
+ function isNonSuccessItemStatus(status) {
78
+ return status === "failed" || status === "blocked";
79
+ }
80
+ function itemName(item) {
81
+ if (item.type === "dynamicToolCall" && typeof item.tool === "string") return item.tool;
82
+ if (item.type === "mcpToolCall" && typeof item.tool === "string") {
83
+ const server = typeof item.server === "string" ? item.server : void 0;
84
+ return server ? `${server}.${item.tool}` : item.tool;
1761
85
  }
1762
- };
1763
- function estimateBase64DecodedBytes(base64) {
1764
- let nonWhitespaceLength = 0;
1765
- let previousCode = -1;
1766
- let lastCode = -1;
1767
- for (let i = 0; i < base64.length; i += 1) {
1768
- const code = base64.charCodeAt(i);
1769
- if (isBase64WhitespaceCode(code)) continue;
1770
- nonWhitespaceLength += 1;
1771
- previousCode = lastCode;
1772
- lastCode = code;
86
+ if (item.type === "commandExecution") return "bash";
87
+ if (item.type === "fileChange") return "apply_patch";
88
+ if (item.type === "webSearch") return "web_search";
89
+ }
90
+ function auditNativeToolName(item) {
91
+ if (item.type === "dynamicToolCall") return;
92
+ const progressName = itemName(item);
93
+ if (progressName) return progressName;
94
+ if (item.type === "collabAgentToolCall") return typeof item.tool === "string" && item.tool.trim() ? `collab.${item.tool.trim()}` : "collab_agent";
95
+ if (item.type === "imageGeneration") return "image_generation";
96
+ if (item.type === "imageView") return "image_view";
97
+ if (item.type === "sleep") return "sleep";
98
+ }
99
+ function isSideEffectingNativeToolItem(item) {
100
+ return itemStatus(item) !== "blocked" && (isMutatingNativeToolItem(item) || item.type === "mcpToolCall");
101
+ }
102
+ function shouldSynthesizeToolProgressForItem(item) {
103
+ switch (item.type) {
104
+ case "commandExecution":
105
+ case "fileChange":
106
+ case "webSearch":
107
+ case "mcpToolCall": return true;
108
+ default: return false;
1773
109
  }
1774
- if (nonWhitespaceLength === 0) return;
1775
- const equalsCode = "=".charCodeAt(0);
1776
- const padding = lastCode === equalsCode ? previousCode === equalsCode ? 2 : 1 : 0;
1777
- return Math.max(0, Math.floor(nonWhitespaceLength * 3 / 4) - padding);
1778
110
  }
1779
- function isBase64WhitespaceCode(code) {
1780
- return code === 32 || code === 9 || code === 10 || code === 13;
111
+ function shouldRecordNativeToolTranscript(item) {
112
+ return shouldSynthesizeToolProgressForItem(item) && item.type !== "webSearch";
113
+ }
114
+ function isMutatingNativeToolItem(item) {
115
+ if (item.type === "commandExecution") return true;
116
+ return item.type === "fileChange" || item.type === "collabAgentToolCall" || item.type === "imageGeneration";
1781
117
  }
1782
- function resolveGeneratedImageMaxBytes(config) {
1783
- const configured = config?.agents?.defaults?.mediaMaxMb;
1784
- if (typeof configured === "number" && Number.isFinite(configured) && configured > 0) return Math.floor(configured * BYTES_PER_MB);
1785
- return DEFAULT_GENERATED_IMAGE_MAX_BYTES;
118
+ function shouldClearTerminalPresentationForNativeItem(item) {
119
+ switch (item.type) {
120
+ case "collabAgentToolCall":
121
+ case "commandExecution":
122
+ case "fileChange":
123
+ case "imageGeneration":
124
+ case "imageView":
125
+ case "mcpToolCall":
126
+ case "webSearch": return true;
127
+ default: return false;
128
+ }
1786
129
  }
1787
130
  //#endregion
1788
131
  //#region extensions/codex/src/app-server/dynamic-tool-response-state.ts
@@ -1911,7 +254,9 @@ const CODEX_DYNAMIC_COMPUTER_COMPLETION_GRACE_MS = 3e4;
1911
254
  /** Timeout for image-understanding style dynamic tool calls. */
1912
255
  const CODEX_DYNAMIC_IMAGE_TOOL_TIMEOUT_MS = 6e4;
1913
256
  /** Timeout for message-delivery dynamic tool calls. */
1914
- const CODEX_DYNAMIC_MESSAGE_TOOL_TIMEOUT_MS = CODEX_DYNAMIC_TOOL_MAX_TIMEOUT_MS;
257
+ const CODEX_DYNAMIC_MESSAGE_TOOL_TIMEOUT_MS = 6e5;
258
+ /** Outer default for collector waits: full swarm budget plus completion grace. */
259
+ const CODEX_DYNAMIC_AGENTS_WAIT_TOOL_TIMEOUT_MS = 63e4;
1915
260
  const LOG_FIELD_MAX_LENGTH = 160;
1916
261
  function normalizeLogField(value) {
1917
262
  if (typeof value !== "string") return;
@@ -2152,6 +497,10 @@ function hasPendingDynamicToolTerminalDiagnostic(params) {
2152
497
  function resolveDynamicToolCallTimeoutMs(params) {
2153
498
  if (params.call.tool === "computer") return clampDynamicToolTimeoutMs(readComputerToolTimeoutMs(params.call.arguments));
2154
499
  if (params.call.tool === "message") return CODEX_DYNAMIC_MESSAGE_TOOL_TIMEOUT_MS;
500
+ if (params.call.tool === "agents_wait") {
501
+ const requestedMs = readDynamicToolCallTimeoutMs(params.call.arguments) ?? readConfiguredDynamicToolTimeoutMs(params.call.tool, params.config) ?? CODEX_DYNAMIC_AGENTS_WAIT_TOOL_TIMEOUT_MS;
502
+ return Math.max(1, Math.min(63e4, Math.floor(requestedMs)));
503
+ }
2155
504
  return clampDynamicToolTimeoutMs(readDynamicToolCallTimeoutMs(params.call.arguments) ?? readConfiguredDynamicToolTimeoutMs(params.call.tool, params.config) ?? CODEX_DYNAMIC_TOOL_TIMEOUT_MS);
2156
505
  }
2157
506
  function readComputerToolTimeoutMs(value) {
@@ -2170,11 +519,15 @@ function readDynamicToolCallTimeoutMs(value) {
2170
519
  }
2171
520
  function readConfiguredDynamicToolTimeoutMs(toolName, config) {
2172
521
  if (toolName === "image_generate") {
2173
- const imageGenerationModel = config?.agents?.defaults?.imageGenerationModel;
2174
- if (!imageGenerationModel || typeof imageGenerationModel !== "object") return CODEX_DYNAMIC_IMAGE_GENERATION_TOOL_TIMEOUT_MS;
2175
- return readPositiveFiniteTimeoutMs(imageGenerationModel.timeoutMs) ?? CODEX_DYNAMIC_IMAGE_GENERATION_TOOL_TIMEOUT_MS;
522
+ const imageModel = config?.agents?.defaults?.mediaModels?.image;
523
+ if (!imageModel || typeof imageModel !== "object") return CODEX_DYNAMIC_IMAGE_GENERATION_TOOL_TIMEOUT_MS;
524
+ return readPositiveFiniteTimeoutMs(imageModel.timeoutMs) ?? CODEX_DYNAMIC_IMAGE_GENERATION_TOOL_TIMEOUT_MS;
525
+ }
526
+ if (toolName === "image") {
527
+ const candidates = (config?.tools?.media?.models ?? []).filter((entry) => !entry.capabilities || entry.capabilities.includes("image"));
528
+ const capabilityTimeoutMs = readTimeoutSecondsAsMs(config?.tools?.media?.image?.timeoutSeconds);
529
+ return Math.max(capabilityTimeoutMs ?? CODEX_DYNAMIC_IMAGE_TOOL_TIMEOUT_MS, ...candidates.map((entry) => readTimeoutSecondsAsMs(entry.timeoutSeconds) ?? capabilityTimeoutMs ?? CODEX_DYNAMIC_IMAGE_TOOL_TIMEOUT_MS));
2176
530
  }
2177
- if (toolName === "image") return readTimeoutSecondsAsMs(config?.tools?.media?.image?.timeoutSeconds) ?? CODEX_DYNAMIC_IMAGE_TOOL_TIMEOUT_MS;
2178
531
  if (toolName === "message") return CODEX_DYNAMIC_MESSAGE_TOOL_TIMEOUT_MS;
2179
532
  }
2180
533
  function readTimeoutSecondsAsMs(value) {
@@ -2294,6 +647,7 @@ function createCodexNativeHookRelay(params) {
2294
647
  ...params.config ? { config: params.config } : {},
2295
648
  runId: params.runId,
2296
649
  ...params.channelId ? { channelId: params.channelId } : {},
650
+ ...params.requester ? { requester: params.requester } : {},
2297
651
  allowedEvents: params.events,
2298
652
  preToolUseLoopDetection: params.loopDetectionPreToolUseRelay,
2299
653
  ttlMs: resolveCodexNativeHookRelayTtlMs({
@@ -2498,12 +852,12 @@ var CodexNativeToolLifecycleProjector = class {
2498
852
  this.preToolUseFailureByItem.set(failure.toolCallId, record);
2499
853
  }
2500
854
  recordRawWebSearchResult(item) {
2501
- if (readString$3(item, "type") !== "web_search_call") return;
2502
- const toolCallId = readString$3(item, "id");
855
+ if (readString$2(item, "type") !== "web_search_call") return;
856
+ const toolCallId = readString$2(item, "id");
2503
857
  if (!toolCallId || this.completedItemIds.has(toolCallId)) return;
2504
858
  const toolName = "web_search";
2505
859
  this.recordStarted(toolCallId, toolName, "unknown");
2506
- const rawStatus = readString$3(item, "status");
860
+ const rawStatus = readString$2(item, "status");
2507
861
  if (rawStatus === "in_progress" || rawStatus === "running") return;
2508
862
  const status = rawStatus === "completed" ? "completed" : rawStatus === "cancelled" ? "cancelled" : rawStatus === "failed" || rawStatus === "error" || rawStatus === "incomplete" ? "failed" : "unknown";
2509
863
  this.recordTerminal(toolCallId, toolName, status, { sourceTimestampMs: this.webSearchCompletionByItem.get(toolCallId)?.sourceTimestampMs });
@@ -2616,795 +970,6 @@ var CodexNativeToolLifecycleProjector = class {
2616
970
  }
2617
971
  };
2618
972
  //#endregion
2619
- //#region extensions/codex/src/app-server/event-projector-reasoning.ts
2620
- var CodexReasoningProjection = class {
2621
- constructor(params, emitAgentEvent) {
2622
- this.params = params;
2623
- this.emitAgentEvent = emitAgentEvent;
2624
- this.reasoningTextByGroup = /* @__PURE__ */ new Map();
2625
- this.reasoningItemOrder = /* @__PURE__ */ new Map();
2626
- this.planTextByItem = /* @__PURE__ */ new Map();
2627
- this.reasoningStarted = false;
2628
- this.reasoningEnded = false;
2629
- }
2630
- async handleReasoningDelta(method, params) {
2631
- const itemId = readString$3(params, "itemId") ?? "reasoning";
2632
- const delta = readString$3(params, "delta") ?? "";
2633
- if (!delta) return;
2634
- this.reasoningStarted = true;
2635
- if (!this.reasoningItemOrder.has(itemId)) this.reasoningItemOrder.set(itemId, this.reasoningItemOrder.size);
2636
- const groupIndex = method === "item/reasoning/textDelta" ? readNonNegativeInteger(params, "contentIndex") ?? 0 : readNonNegativeInteger(params, "summaryIndex") ?? 0;
2637
- const groupKey = `${method}\0${itemId}\0${groupIndex}`;
2638
- const current = this.reasoningTextByGroup.get(groupKey);
2639
- this.reasoningTextByGroup.set(groupKey, {
2640
- itemId,
2641
- method,
2642
- index: groupIndex,
2643
- text: `${current?.text ?? ""}${delta}`
2644
- });
2645
- await this.params.onReasoningStream?.({
2646
- text: this.reasoningText(),
2647
- isReasoningSnapshot: true
2648
- });
2649
- }
2650
- handlePlanDelta(params) {
2651
- const itemId = readString$3(params, "itemId") ?? "plan";
2652
- const delta = readString$3(params, "delta") ?? "";
2653
- if (!delta) return;
2654
- const text = `${this.planTextByItem.get(itemId) ?? ""}${delta}`;
2655
- this.planTextByItem.set(itemId, text);
2656
- this.emitPlanUpdate({
2657
- explanation: void 0,
2658
- steps: splitPlanText(text).map((step) => ({
2659
- step,
2660
- status: "pending"
2661
- }))
2662
- });
2663
- }
2664
- handleTurnPlanUpdated(params) {
2665
- const plan = Array.isArray(params.plan) ? params.plan.flatMap((entry) => {
2666
- if (!entry || typeof entry !== "object" || Array.isArray(entry)) return [];
2667
- const record = entry;
2668
- const step = readString$3(record, "step");
2669
- if (!step) return [];
2670
- return [{
2671
- step,
2672
- status: normalizePlanStepStatus(readString$3(record, "status"))
2673
- }];
2674
- }) : void 0;
2675
- this.emitPlanUpdate({
2676
- explanation: readNullableString(params, "explanation"),
2677
- steps: plan
2678
- });
2679
- }
2680
- recordItem(item) {
2681
- if (item?.type === "plan" && typeof item.text === "string" && item.text) {
2682
- this.planTextByItem.set(item.id, item.text);
2683
- this.emitPlanUpdate({
2684
- explanation: void 0,
2685
- steps: splitPlanText(item.text).map((step) => ({
2686
- step,
2687
- status: "pending"
2688
- }))
2689
- });
2690
- }
2691
- }
2692
- async maybeEndReasoning() {
2693
- if (!this.reasoningStarted || this.reasoningEnded) return;
2694
- this.reasoningEnded = true;
2695
- await this.params.onReasoningEnd?.();
2696
- }
2697
- reasoningText() {
2698
- return collectReasoningTextValues(this.reasoningTextByGroup, this.reasoningItemOrder).join("\n\n");
2699
- }
2700
- planText() {
2701
- return [...this.planTextByItem.values()].filter((text) => text.trim().length > 0).join("\n\n");
2702
- }
2703
- emitPlanUpdate(params) {
2704
- if (!params.explanation && (!params.steps || params.steps.length === 0)) return;
2705
- this.emitAgentEvent({
2706
- stream: "plan",
2707
- data: {
2708
- phase: "update",
2709
- title: "Plan updated",
2710
- source: "codex-app-server",
2711
- ...params.explanation ? { explanation: params.explanation } : {},
2712
- ...params.steps && params.steps.length > 0 ? { steps: params.steps } : {}
2713
- }
2714
- });
2715
- }
2716
- };
2717
- function normalizePlanStepStatus(status) {
2718
- if (status === "inProgress" || status === "in_progress") return "in_progress";
2719
- return status === "completed" ? "completed" : "pending";
2720
- }
2721
- function collectReasoningTextValues(groups, itemOrder) {
2722
- return [...groups.values()].toSorted((left, right) => {
2723
- const itemDelta = (itemOrder.get(left.itemId) ?? Number.MAX_SAFE_INTEGER) - (itemOrder.get(right.itemId) ?? Number.MAX_SAFE_INTEGER);
2724
- if (itemDelta !== 0) return itemDelta;
2725
- const methodDelta = reasoningMethodOrder(left.method) - reasoningMethodOrder(right.method);
2726
- return methodDelta !== 0 ? methodDelta : left.index - right.index;
2727
- }).map((group) => group.text).filter((text) => text.trim().length > 0);
2728
- }
2729
- function reasoningMethodOrder(method) {
2730
- return method === "item/reasoning/summaryTextDelta" ? 0 : 1;
2731
- }
2732
- //#endregion
2733
- //#region extensions/codex/src/app-server/event-projector-usage.ts
2734
- function readTokenCount(record, key) {
2735
- const value = readNonNegativeInteger(record, key);
2736
- return value !== void 0 && Number.isSafeInteger(value) ? value : void 0;
2737
- }
2738
- function normalizeCodexThreadTokenUsage(record) {
2739
- const inputTokens = readNumber(record, "inputTokens");
2740
- const cacheRead = readNumber(record, "cachedInputTokens");
2741
- const usage = normalizeUsage({
2742
- input: inputTokens !== void 0 && cacheRead !== void 0 ? Math.max(0, inputTokens - cacheRead) : inputTokens,
2743
- output: readNumber(record, "outputTokens"),
2744
- cacheRead,
2745
- total: readNumber(record, "totalTokens")
2746
- });
2747
- return usage ? {
2748
- ...usage,
2749
- contextUsage: { state: "unavailable" }
2750
- } : void 0;
2751
- }
2752
- function normalizeCodexResponseTokenUsage(record) {
2753
- const totalTokens = readTokenCount(record, "totalTokens");
2754
- const inputTokens = readTokenCount(record, "inputTokens");
2755
- const cacheRead = readTokenCount(record, "cachedInputTokens");
2756
- const output = readTokenCount(record, "outputTokens");
2757
- const reasoningOutput = readTokenCount(record, "reasoningOutputTokens");
2758
- const cacheWrite = record.cacheWriteInputTokens === void 0 ? 0 : readTokenCount(record, "cacheWriteInputTokens");
2759
- 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;
2760
- const usage = normalizeUsage({
2761
- input: inputTokens - cacheRead - cacheWrite,
2762
- output,
2763
- cacheRead,
2764
- cacheWrite,
2765
- total: totalTokens
2766
- });
2767
- if (!usage) return;
2768
- return {
2769
- ...usage,
2770
- contextUsage: {
2771
- state: "available",
2772
- promptTokens: inputTokens,
2773
- totalTokens
2774
- }
2775
- };
2776
- }
2777
- //#endregion
2778
- //#region extensions/codex/src/app-server/usage-limit-error.ts
2779
- /**
2780
- * Enriches Codex usage-limit failures with current rate-limit information and
2781
- * marks blocked auth profiles when Codex exposes a reset time.
2782
- */
2783
- const CODEX_USAGE_LIMIT_RATE_LIMIT_REFRESH_TIMEOUT_MS = 5e3;
2784
- function createCodexUsageLimitPromptError(message) {
2785
- return Object.assign(new Error(message), { status: 429 });
2786
- }
2787
- function isCodexUsageLimitPromptError(error) {
2788
- return error instanceof Error && "status" in error && error.status === 429;
2789
- }
2790
- /** Marks a Codex auth profile blocked until the reset time advertised by rate limits. */
2791
- async function markCodexAuthProfileBlockedFromRateLimits(params) {
2792
- const authProfileId = params.authProfileId?.trim();
2793
- if (!authProfileId || !params.params.authProfileStore) return;
2794
- const blockedUntil = resolveCodexUsageLimitResetAtMs(params.rateLimits);
2795
- if (!blockedUntil) return;
2796
- try {
2797
- await markAuthProfileBlockedUntil({
2798
- store: params.params.authProfileStore,
2799
- profileId: authProfileId,
2800
- blockedUntil,
2801
- source: "codex_rate_limits",
2802
- agentDir: params.params.agentDir,
2803
- runId: params.params.runId,
2804
- modelId: params.params.modelId
2805
- });
2806
- } catch (error) {
2807
- embeddedAgentLog.debug("failed to mark Codex auth profile blocked from app-server limits", {
2808
- authProfileId,
2809
- error: formatErrorMessage(error)
2810
- });
2811
- }
2812
- }
2813
- /** Formats a turn-start usage-limit error, refreshing rate limits when needed. */
2814
- async function formatCodexTurnStartUsageLimitError(params) {
2815
- return refreshCodexUsageLimitError({
2816
- client: params.client,
2817
- source: readCodexTurnStartUsageLimitErrorSource(params.client, params.error, params.errorNotification, params.rateLimitsRevisionBeforeTurnStart),
2818
- timeoutMs: params.timeoutMs,
2819
- signal: params.signal
2820
- });
2821
- }
2822
- /** Refreshes a generic prompt usage-limit message into a reset-aware message. */
2823
- async function refreshCodexUsageLimitPromptError(params) {
2824
- if (!shouldRefreshCodexRateLimitsForUsageLimitMessage(params.message)) return;
2825
- return refreshCodexUsageLimitError({
2826
- client: params.client,
2827
- source: {
2828
- message: params.message,
2829
- codexErrorInfo: "usageLimitExceeded",
2830
- rateLimits: readRecentCodexRateLimits(params.client)
2831
- },
2832
- timeoutMs: params.timeoutMs,
2833
- signal: params.signal
2834
- });
2835
- }
2836
- async function refreshCodexUsageLimitError(params) {
2837
- const initialMessage = formatCodexUsageLimitErrorMessage(params.source);
2838
- if (!shouldRefreshCodexRateLimitsForUsageLimitMessage(initialMessage)) return initialMessage ? {
2839
- message: initialMessage,
2840
- ...params.source.rateLimitsTrustedForProfile ? { rateLimitsForProfile: params.source.rateLimits } : {}
2841
- } : void 0;
2842
- const rateLimits = await readCodexRateLimitsFromAppServerForUsageLimitError({
2843
- client: params.client,
2844
- timeoutMs: params.timeoutMs,
2845
- signal: params.signal
2846
- });
2847
- if (!rateLimits) return initialMessage ? {
2848
- message: initialMessage,
2849
- ...params.source.rateLimitsTrustedForProfile ? { rateLimitsForProfile: params.source.rateLimits } : {}
2850
- } : void 0;
2851
- const message = formatCodexUsageLimitErrorMessage({
2852
- message: params.source.message,
2853
- codexErrorInfo: params.source.codexErrorInfo,
2854
- rateLimits
2855
- }) ?? initialMessage;
2856
- return message ? {
2857
- message,
2858
- rateLimitsForProfile: rateLimits
2859
- } : void 0;
2860
- }
2861
- async function readCodexRateLimitsFromAppServerForUsageLimitError(params) {
2862
- if (params.signal?.aborted) return;
2863
- try {
2864
- const rateLimits = await params.client.request(CODEX_CONTROL_METHODS.rateLimits, void 0, {
2865
- timeoutMs: resolveCodexUsageLimitRateLimitRefreshTimeoutMs(params.timeoutMs),
2866
- signal: params.signal
2867
- });
2868
- rememberCodexRateLimitsRead(params.client, rateLimits);
2869
- return rateLimits;
2870
- } catch (error) {
2871
- embeddedAgentLog.debug("codex app-server rate-limit refresh failed after usage-limit error", { error: formatErrorMessage(error) });
2872
- return;
2873
- }
2874
- }
2875
- function resolveCodexUsageLimitRateLimitRefreshTimeoutMs(timeoutMs) {
2876
- if (timeoutMs === void 0 || !Number.isFinite(timeoutMs) || timeoutMs <= 0) return CODEX_USAGE_LIMIT_RATE_LIMIT_REFRESH_TIMEOUT_MS;
2877
- return Math.max(100, Math.min(timeoutMs, CODEX_USAGE_LIMIT_RATE_LIMIT_REFRESH_TIMEOUT_MS));
2878
- }
2879
- function readCodexTurnStartUsageLimitErrorSource(client, error, errorNotification, rateLimitsRevisionBeforeTurnStart) {
2880
- const notificationError = readCodexErrorNotification(errorNotification);
2881
- const errorPayload = readCodexErrorPayload(error);
2882
- const rateLimits = errorPayload.rateLimits ?? readRecentCodexRateLimits(client);
2883
- const cacheUpdatedDuringTurnStart = rateLimitsRevisionBeforeTurnStart !== void 0 && readCodexRateLimitsRevision(client) > rateLimitsRevisionBeforeTurnStart;
2884
- return {
2885
- message: notificationError?.message ?? errorPayload.message ?? formatErrorMessage(error),
2886
- codexErrorInfo: notificationError?.codexErrorInfo ?? errorPayload.codexErrorInfo,
2887
- rateLimits,
2888
- rateLimitsTrustedForProfile: errorPayload.rateLimits !== void 0 || cacheUpdatedDuringTurnStart
2889
- };
2890
- }
2891
- function readCodexErrorNotification(notification) {
2892
- if (notification?.method !== "error" || !isJsonObject(notification.params)) return;
2893
- const error = notification.params.error;
2894
- return isJsonObject(error) ? {
2895
- message: readString$2(error, "message"),
2896
- codexErrorInfo: error.codexErrorInfo
2897
- } : void 0;
2898
- }
2899
- function readCodexErrorPayload(error) {
2900
- const message = error instanceof Error ? error.message : void 0;
2901
- if (!error || typeof error !== "object" || !("data" in error)) return { message };
2902
- const data = error.data;
2903
- if (!isJsonObject(data)) return { message };
2904
- const nestedError = isJsonObject(data.error) ? data.error : data;
2905
- const rateLimits = nestedError.rateLimits ?? data.rateLimits;
2906
- return {
2907
- message: readString$2(nestedError, "message") ?? message,
2908
- codexErrorInfo: nestedError.codexErrorInfo,
2909
- rateLimits
2910
- };
2911
- }
2912
- function readString$2(record, key) {
2913
- const value = record[key];
2914
- return typeof value === "string" ? value : void 0;
2915
- }
2916
- //#endregion
2917
- //#region extensions/codex/src/app-server/event-projector.ts
2918
- var CodexAppServerEventProjector = class {
2919
- constructor(params, threadId, turnId, options = {}) {
2920
- this.params = params;
2921
- this.threadId = threadId;
2922
- this.turnId = turnId;
2923
- this.options = options;
2924
- this.activeItemIds = /* @__PURE__ */ new Set();
2925
- this.completedItemIds = /* @__PURE__ */ new Set();
2926
- this.activeCompactionItemIds = /* @__PURE__ */ new Set();
2927
- this.terminalPresentationClearedItemIds = /* @__PURE__ */ new Set();
2928
- this.nativeToolOutcomeOrdinals = /* @__PURE__ */ new Map();
2929
- this.promptErrorSource = null;
2930
- this.synthesizedMissingToolResultError = null;
2931
- this.aborted = false;
2932
- this.completedCompactionCount = 0;
2933
- this.nativeToolLifecycleProjector = new CodexNativeToolLifecycleProjector(params, threadId, turnId, { runAbortSignal: options.runAbortSignal });
2934
- this.generatedMediaProjection = new CodexGeneratedMediaProjection(params.config);
2935
- this.toolProgressProjection = new CodexToolProgressProjection(params);
2936
- this.toolTranscriptProjection = new CodexToolTranscriptProjection(params, threadId, turnId, this.toolProgressProjection, {
2937
- nativePostToolUseRelayEnabled: options.nativePostToolUseRelayEnabled,
2938
- trajectoryRecorder: options.trajectoryRecorder
2939
- });
2940
- this.eventProjection = new CodexEventProjection(threadId, turnId, (event) => this.emitAgentEvent(event), this.toolProgressProjection, this.toolTranscriptProjection, options.onNativeToolResultRecorded);
2941
- this.assistantProjection = new CodexAssistantProjection(params, (event) => this.emitAgentEvent(event), (text) => this.toolProgressProjection.matchesEcho(text));
2942
- this.reasoningProjection = new CodexReasoningProjection(params, (event) => this.emitAgentEvent(event));
2943
- }
2944
- getCompletedTurnStatus() {
2945
- return this.completedTurn?.status;
2946
- }
2947
- hasCompletedTerminalAssistantText() {
2948
- return this.assistantProjection.hasCompletedTerminalAssistantText(this.completedItemIds);
2949
- }
2950
- getLatestTerminalAssistantCandidate() {
2951
- return this.assistantProjection.getLatestTerminalAssistantCandidate();
2952
- }
2953
- hasLatestTerminalAssistantCandidateText() {
2954
- return this.assistantProjection.hasLatestTerminalAssistantCandidateText();
2955
- }
2956
- canReleaseLatestTerminalAssistantAfterToolHandoff() {
2957
- return this.assistantProjection.canReleaseLatestTerminalAssistantAfterToolHandoff();
2958
- }
2959
- /** Restores a completed final item after only the enclosing turn timeout fired. */
2960
- recoverCompletedTerminalAssistantAfterTurnWatchTimeout() {
2961
- if (!this.aborted || this.promptError !== "codex app-server attempt timed out" || !this.hasCompletedTerminalAssistantText()) return false;
2962
- this.aborted = false;
2963
- this.promptError = void 0;
2964
- this.promptErrorSource = null;
2965
- return true;
2966
- }
2967
- /** Resolves the shared model-order position for a native tool item. */
2968
- recordNativeToolOutcome(item) {
2969
- if (!item || this.nativeToolOutcomeOrdinals.has(item.id) || !shouldClearTerminalPresentationForNativeItem(item)) return;
2970
- const ordinal = this.params.allocateToolOutcomeOrdinal?.(item.id);
2971
- if (ordinal !== void 0) this.nativeToolOutcomeOrdinals.set(item.id, ordinal);
2972
- }
2973
- recordNativeToolApprovalFailure(toolCallId, disposition) {
2974
- this.nativeToolLifecycleProjector.recordApprovalFailureDisposition(toolCallId, disposition);
2975
- }
2976
- recordNativeToolPreToolUseFailure(failure) {
2977
- this.nativeToolLifecycleProjector.recordPreToolUseFailure(failure);
2978
- }
2979
- async handleNotification(notification) {
2980
- const params = isJsonObject(notification.params) ? notification.params : void 0;
2981
- if (!params) return;
2982
- if (isHookNotificationMethod(notification.method)) {
2983
- if (!this.isHookNotificationForCurrentThread(params)) return;
2984
- } else if (notification.method === "guardianWarning") {
2985
- if (readCodexNotificationThreadId(params) !== this.threadId) return;
2986
- } else if (!this.isNotificationForTurn(params)) return;
2987
- this.nativeToolLifecycleProjector.handleNotification(notification);
2988
- switch (notification.method) {
2989
- case "item/agentMessage/delta":
2990
- await this.assistantProjection.handleAssistantDelta(params);
2991
- break;
2992
- case "item/reasoning/summaryTextDelta":
2993
- case "item/reasoning/textDelta":
2994
- await this.reasoningProjection.handleReasoningDelta(notification.method, params);
2995
- break;
2996
- case "item/plan/delta":
2997
- this.reasoningProjection.handlePlanDelta(params);
2998
- break;
2999
- case "turn/plan/updated":
3000
- this.reasoningProjection.handleTurnPlanUpdated(params);
3001
- break;
3002
- case "item/started":
3003
- await this.handleItemStarted(params);
3004
- break;
3005
- case "item/completed":
3006
- await this.handleItemCompleted(params);
3007
- break;
3008
- case "item/commandExecution/outputDelta":
3009
- this.toolProgressProjection.handleOutputDelta(params, "bash");
3010
- break;
3011
- case "item/autoApprovalReview/started":
3012
- case "item/autoApprovalReview/completed":
3013
- this.eventProjection.handleGuardianReview(notification.method, params);
3014
- break;
3015
- case "guardianWarning":
3016
- this.eventProjection.handleGuardianWarning(params);
3017
- break;
3018
- case "hook/started":
3019
- case "hook/completed":
3020
- this.eventProjection.handleHook(notification.method, params);
3021
- break;
3022
- case "thread/tokenUsage/updated":
3023
- this.handleTokenUsage(params);
3024
- break;
3025
- case "turn/completed":
3026
- await this.handleTurnCompleted(params);
3027
- break;
3028
- case "rawResponse/completed":
3029
- this.handleRawResponseCompleted(params);
3030
- break;
3031
- case "rawResponseItem/completed":
3032
- await this.handleRawResponseItemCompleted(params);
3033
- break;
3034
- case "error":
3035
- this.responseUsage = void 0;
3036
- if (params.willRetry === true) break;
3037
- this.promptError = this.formatCodexErrorMessage(params) ?? "codex app-server error";
3038
- this.promptErrorSource = "prompt";
3039
- break;
3040
- default: break;
3041
- }
3042
- }
3043
- buildResult(toolTelemetry, options) {
3044
- this.nativeToolLifecycleProjector.finalizeActive();
3045
- const assistantTexts = this.assistantProjection.collectAssistantTexts();
3046
- const reasoningText = this.reasoningProjection.reasoningText();
3047
- const planText = this.reasoningProjection.planText();
3048
- const projectedUsage = this.aborted ? this.tokenUsage : this.responseUsage ?? this.tokenUsage;
3049
- const hasAssistantItemText = this.assistantProjection.hasAssistantItemTextForSynthesis();
3050
- const legacyFailClosed = !this.completedTurn || this.completedTurn.status !== "completed" || hasAssistantItemText;
3051
- const hasDeliverableAssistantOnCompletedTurn = this.completedTurn?.status === "completed" && assistantTexts.some((text) => text.trim().length > 0);
3052
- const synthesizedMissingToolResultError = this.toolTranscriptProjection.synthesizeMissingToolResults({
3053
- synthesize: legacyFailClosed,
3054
- recordPromptError: legacyFailClosed && !hasDeliverableAssistantOnCompletedTurn && !this.aborted
3055
- });
3056
- if (synthesizedMissingToolResultError) {
3057
- this.synthesizedMissingToolResultError = synthesizedMissingToolResultError;
3058
- this.promptErrorSource = this.promptErrorSource ?? "prompt";
3059
- }
3060
- const assistantMessageOptions = {
3061
- tokenUsage: projectedUsage,
3062
- aborted: this.aborted,
3063
- promptError: this.promptError
3064
- };
3065
- const lastAssistant = assistantTexts.length ? this.assistantProjection.createAssistantMessage(assistantTexts.join("\n\n"), assistantMessageOptions) : void 0;
3066
- const currentAttemptAssistant = this.assistantProjection.createCurrentAttemptAssistantMessage(assistantMessageOptions);
3067
- const turnId = this.turnId;
3068
- const messagesSnapshot = promptSnapshot(this.params, turnId, this.options.upstreamUserText);
3069
- if (reasoningText) messagesSnapshot.push(attachCodexMirrorIdentity(this.assistantProjection.createAssistantMirrorMessage("Codex reasoning", reasoningText), `${turnId}:reasoning`));
3070
- if (planText) messagesSnapshot.push(attachCodexMirrorIdentity(this.assistantProjection.createAssistantMirrorMessage("Codex plan", planText), `${turnId}:plan`));
3071
- messagesSnapshot.push(...this.toolTranscriptProjection.transcriptMessages);
3072
- if (lastAssistant) messagesSnapshot.push(attachCodexMirrorIdentity(lastAssistant, `${turnId}:assistant`));
3073
- const turnFailed = this.completedTurn?.status === "failed";
3074
- const promptError = this.promptError ?? this.synthesizedMissingToolResultError ?? (turnFailed ? this.completedTurn?.error?.message ?? "codex app-server turn failed" : null);
3075
- const agentHarnessResultClassification = classifyAgentHarnessTerminalOutcome({
3076
- assistantTexts,
3077
- reasoningText,
3078
- planText,
3079
- promptError,
3080
- turnCompleted: Boolean(this.completedTurn)
3081
- });
3082
- const toolMetas = this.toolProgressProjection.toolMetas;
3083
- const hadPotentialSideEffects = toolTelemetry.didSendViaMessagingTool || (toolTelemetry.successfulCronAdds ?? 0) > 0 || this.generatedMediaProjection.hasGeneratedMedia() || this.toolProgressProjection.hasPotentialSideEffects;
3084
- return {
3085
- aborted: this.aborted,
3086
- externalAbort: false,
3087
- timedOut: false,
3088
- idleTimedOut: false,
3089
- timedOutDuringCompaction: false,
3090
- timedOutDuringToolExecution: false,
3091
- promptError,
3092
- promptErrorSource: promptError ? this.promptErrorSource || "prompt" : null,
3093
- sessionIdUsed: this.params.sessionId,
3094
- ...agentHarnessResultClassification ? { agentHarnessResultClassification } : {},
3095
- bootstrapPromptWarningSignaturesSeen: this.params.bootstrapPromptWarningSignaturesSeen,
3096
- bootstrapPromptWarningSignature: this.params.bootstrapPromptWarningSignature,
3097
- messagesSnapshot,
3098
- assistantTexts,
3099
- toolMetas,
3100
- lastAssistant,
3101
- currentAttemptAssistant,
3102
- ...this.toolProgressProjection.lastToolError ? { lastToolError: this.toolProgressProjection.lastToolError } : {},
3103
- didSendViaMessagingTool: toolTelemetry.didSendViaMessagingTool,
3104
- didDeliverSourceReplyViaMessageTool: toolTelemetry.didDeliverSourceReplyViaMessageTool === true,
3105
- messagingToolSentTexts: toolTelemetry.messagingToolSentTexts,
3106
- messagingToolSentMediaUrls: toolTelemetry.messagingToolSentMediaUrls,
3107
- messagingToolSentTargets: toolTelemetry.messagingToolSentTargets,
3108
- messagingToolSourceReplyPayloads: toolTelemetry.messagingToolSourceReplyPayloads ?? [],
3109
- heartbeatToolResponse: toolTelemetry.heartbeatToolResponse,
3110
- toolMediaUrls: this.generatedMediaProjection.buildToolMediaUrls(toolTelemetry),
3111
- toolAudioAsVoice: toolTelemetry.toolAudioAsVoice,
3112
- successfulCronAdds: toolTelemetry.successfulCronAdds,
3113
- cloudCodeAssistFormatError: false,
3114
- attemptUsage: projectedUsage,
3115
- replayMetadata: {
3116
- hadPotentialSideEffects,
3117
- replaySafe: !hadPotentialSideEffects
3118
- },
3119
- itemLifecycle: {
3120
- startedCount: this.activeItemIds.size + this.completedItemIds.size,
3121
- completedCount: this.completedItemIds.size,
3122
- activeCount: this.activeItemIds.size,
3123
- ...this.completedCompactionCount > 0 ? { compactionCount: this.completedCompactionCount } : {}
3124
- },
3125
- yieldDetected: options?.yieldDetected || false,
3126
- didSendDeterministicApprovalPrompt: this.eventProjection.guardianReviewCount > 0 ? false : void 0
3127
- };
3128
- }
3129
- recordDynamicToolCall(params) {
3130
- this.toolTranscriptProjection.recordDynamicToolCall(params);
3131
- }
3132
- recordDynamicToolResult(params) {
3133
- this.toolProgressProjection.recordDynamicToolResult(params);
3134
- this.toolTranscriptProjection.recordDynamicToolResult(params);
3135
- }
3136
- markTimedOut() {
3137
- this.aborted = true;
3138
- this.promptError = "codex app-server attempt timed out";
3139
- this.promptErrorSource = "prompt";
3140
- }
3141
- markAborted() {
3142
- this.aborted = true;
3143
- this.responseUsage = void 0;
3144
- }
3145
- isCompacting() {
3146
- return this.activeCompactionItemIds.size > 0;
3147
- }
3148
- async handleItemStarted(params) {
3149
- const item = readItem(params.item);
3150
- const itemId = item?.id ?? readString$3(params, "itemId");
3151
- this.assistantProjection.recordItemStarted(item, itemId);
3152
- if (itemId) this.activeItemIds.add(itemId);
3153
- this.recordNativeToolOutcome(item);
3154
- if (item?.type === "contextCompaction" && itemId) {
3155
- this.activeCompactionItemIds.add(itemId);
3156
- await runAgentHarnessBeforeCompactionHook({
3157
- sessionFile: this.params.sessionFile,
3158
- messages: await this.toolTranscriptProjection.readMirroredSessionMessages(),
3159
- ctx: {
3160
- runId: this.params.runId,
3161
- agentId: this.params.agentId,
3162
- sessionKey: this.params.sessionKey,
3163
- sessionId: this.params.sessionId,
3164
- workspaceDir: this.params.workspaceDir,
3165
- messageProvider: this.params.messageProvider ?? void 0,
3166
- trigger: this.params.trigger,
3167
- channelId: this.params.messageChannel ?? this.params.messageProvider ?? void 0
3168
- }
3169
- });
3170
- this.emitAgentEvent({
3171
- stream: "compaction",
3172
- data: {
3173
- phase: "start",
3174
- backend: "codex-app-server",
3175
- threadId: this.threadId,
3176
- turnId: this.turnId,
3177
- itemId
3178
- }
3179
- });
3180
- }
3181
- this.toolProgressProjection.recordToolMeta(item);
3182
- this.eventProjection.emitStandardItemEvent({
3183
- phase: "start",
3184
- item
3185
- });
3186
- await this.eventProjection.emitNormalizedToolItemEvent({
3187
- phase: "start",
3188
- item
3189
- });
3190
- this.toolTranscriptProjection.recordNativeToolCall(item);
3191
- this.toolProgressProjection.emitToolResultSummary(item);
3192
- this.emitAgentEvent({
3193
- stream: "codex_app_server.item",
3194
- data: {
3195
- phase: "started",
3196
- itemId,
3197
- type: item?.type
3198
- }
3199
- });
3200
- }
3201
- async handleItemCompleted(params) {
3202
- const item = readItem(params.item);
3203
- this.recordNativeToolOutcome(item);
3204
- this.clearTerminalPresentationForNativeItem(item);
3205
- const itemId = item?.id ?? readString$3(params, "itemId");
3206
- if (itemId) {
3207
- this.activeItemIds.delete(itemId);
3208
- this.completedItemIds.add(itemId);
3209
- }
3210
- this.assistantProjection.recordItemCompleted(item, itemId, this.activeItemIds);
3211
- this.reasoningProjection.recordItem(item);
3212
- this.generatedMediaProjection.recordNative(item);
3213
- if (item?.type === "contextCompaction" && itemId) {
3214
- this.activeCompactionItemIds.delete(itemId);
3215
- this.completedCompactionCount += 1;
3216
- this.options.onContextCompacted?.();
3217
- await runAgentHarnessAfterCompactionHook({
3218
- sessionFile: this.params.sessionFile,
3219
- messages: await this.toolTranscriptProjection.readMirroredSessionMessages(),
3220
- compactedCount: -1,
3221
- ctx: {
3222
- runId: this.params.runId,
3223
- agentId: this.params.agentId,
3224
- sessionKey: this.params.sessionKey,
3225
- sessionId: this.params.sessionId,
3226
- workspaceDir: this.params.workspaceDir,
3227
- messageProvider: this.params.messageProvider ?? void 0,
3228
- trigger: this.params.trigger,
3229
- channelId: this.params.messageChannel ?? this.params.messageProvider ?? void 0
3230
- }
3231
- });
3232
- this.emitAgentEvent({
3233
- stream: "compaction",
3234
- data: {
3235
- phase: "end",
3236
- backend: "codex-app-server",
3237
- completed: true,
3238
- threadId: this.threadId,
3239
- turnId: this.turnId,
3240
- itemId
3241
- }
3242
- });
3243
- }
3244
- this.toolProgressProjection.recordToolMeta(item);
3245
- this.toolProgressProjection.rememberCommandAggregateOutputEcho(item);
3246
- this.eventProjection.emitStandardItemEvent({
3247
- phase: "end",
3248
- item
3249
- });
3250
- await this.eventProjection.emitNormalizedToolItemEvent({
3251
- phase: "result",
3252
- item
3253
- });
3254
- this.toolTranscriptProjection.recordNativeToolCall(item);
3255
- this.toolTranscriptProjection.recordNativeToolResult(item);
3256
- this.toolProgressProjection.emitToolResultSummary(item);
3257
- this.toolProgressProjection.emitToolResultOutput(item);
3258
- this.emitAgentEvent({
3259
- stream: "codex_app_server.item",
3260
- data: {
3261
- phase: "completed",
3262
- itemId,
3263
- type: item?.type
3264
- }
3265
- });
3266
- }
3267
- handleTokenUsage(params) {
3268
- const tokenUsage = isJsonObject(params.tokenUsage) ? params.tokenUsage : void 0;
3269
- const last = tokenUsage && isJsonObject(tokenUsage.last) ? tokenUsage.last : void 0;
3270
- if (!last) return;
3271
- const usage = normalizeCodexThreadTokenUsage(last);
3272
- if (usage) this.tokenUsage = usage;
3273
- }
3274
- handleRawResponseCompleted(params) {
3275
- const usage = isJsonObject(params.usage) ? params.usage : void 0;
3276
- this.responseUsage = usage ? normalizeCodexResponseTokenUsage(usage) : void 0;
3277
- }
3278
- async handleTurnCompleted(params) {
3279
- const turn = readCodexTurn(params.turn);
3280
- if (!turn || turn.id !== this.turnId) return;
3281
- this.completedTurn = turn;
3282
- if (turn.status !== "completed") this.responseUsage = void 0;
3283
- if (turn.status === "failed") {
3284
- const usageLimitMessage = formatCodexUsageLimitErrorMessage({
3285
- message: turn.error?.message,
3286
- codexErrorInfo: turn.error?.codexErrorInfo,
3287
- rateLimits: this.options.readRecentRateLimits?.()
3288
- });
3289
- this.promptError = usageLimitMessage ? createCodexUsageLimitPromptError(usageLimitMessage) : turn.error?.message ?? "codex app-server turn failed";
3290
- this.promptErrorSource = "prompt";
3291
- }
3292
- const turnItems = turn.items ?? [];
3293
- for (let index = turnItems.length - 1; index >= 0; index -= 1) {
3294
- const item = turnItems[index];
3295
- if (!item || !this.isCurrentTurnSnapshotItem(item)) continue;
3296
- if (item?.type === "dynamicToolCall") break;
3297
- if (shouldClearTerminalPresentationForNativeItem(item)) {
3298
- this.clearTerminalPresentationForNativeItem(item);
3299
- break;
3300
- }
3301
- }
3302
- for (const item of turnItems) {
3303
- this.assistantProjection.recordSnapshotItem(item);
3304
- this.reasoningProjection.recordItem(item);
3305
- this.generatedMediaProjection.recordNative(item);
3306
- this.toolProgressProjection.recordToolMeta(item);
3307
- this.toolProgressProjection.rememberCommandAggregateOutputEcho(item);
3308
- await this.emitSnapshotOnlyNativeToolProgress(item);
3309
- this.toolTranscriptProjection.recordNativeToolCall(item);
3310
- this.toolTranscriptProjection.recordNativeToolResult(item);
3311
- this.toolTranscriptProjection.emitAfterToolCallObservation(item);
3312
- this.toolProgressProjection.emitToolResultSummary(item);
3313
- this.toolProgressProjection.emitToolResultOutput(item);
3314
- }
3315
- this.activeCompactionItemIds.clear();
3316
- await this.reasoningProjection.maybeEndReasoning();
3317
- }
3318
- async emitSnapshotOnlyNativeToolProgress(item) {
3319
- if (!shouldSynthesizeToolProgressForItem(item) || !this.isCurrentTurnSnapshotItem(item) || this.completedItemIds.has(item.id) || itemStatus(item) === "running") return;
3320
- if (!this.activeItemIds.has(item.id)) {
3321
- this.eventProjection.emitStandardItemEvent({
3322
- phase: "start",
3323
- item
3324
- });
3325
- await this.eventProjection.emitNormalizedToolItemEvent({
3326
- phase: "start",
3327
- item
3328
- });
3329
- }
3330
- this.activeItemIds.delete(item.id);
3331
- this.eventProjection.emitStandardItemEvent({
3332
- phase: "end",
3333
- item
3334
- });
3335
- await this.eventProjection.emitNormalizedToolItemEvent({
3336
- phase: "result",
3337
- item
3338
- });
3339
- this.completedItemIds.add(item.id);
3340
- }
3341
- isCurrentTurnSnapshotItem(item) {
3342
- const itemTurnId = readItemString(item, "turnId");
3343
- return itemTurnId === void 0 || itemTurnId === this.turnId;
3344
- }
3345
- async handleRawResponseItemCompleted(params) {
3346
- const item = isJsonObject(params.item) ? params.item : void 0;
3347
- if (!item) return;
3348
- this.assistantProjection.handleRawResponseItemCompleted(item, this.activeItemIds);
3349
- await this.generatedMediaProjection.recordRaw(item);
3350
- }
3351
- clearTerminalPresentationForNativeItem(item) {
3352
- if (!item || this.terminalPresentationClearedItemIds.has(item.id) || !shouldClearTerminalPresentationForNativeItem(item)) return;
3353
- const toolCallOrdinal = this.nativeToolOutcomeOrdinals.get(item.id);
3354
- this.terminalPresentationClearedItemIds.add(item.id);
3355
- this.params.onToolOutcome?.({
3356
- toolName: itemName(item) ?? item.type,
3357
- argsHash: "",
3358
- resultHash: "",
3359
- ...toolCallOrdinal !== void 0 ? { toolCallOrdinal } : {},
3360
- terminalPresentation: void 0,
3361
- presentationOnly: true
3362
- });
3363
- }
3364
- formatCodexErrorMessage(params) {
3365
- const error = isJsonObject(params.error) ? params.error : void 0;
3366
- const usageLimitMessage = formatCodexUsageLimitErrorMessage({
3367
- message: error ? readString$3(error, "message") : void 0,
3368
- codexErrorInfo: error?.codexErrorInfo,
3369
- rateLimits: this.options.readRecentRateLimits?.()
3370
- });
3371
- return usageLimitMessage ? createCodexUsageLimitPromptError(usageLimitMessage) : readCodexErrorNotificationMessage(params);
3372
- }
3373
- emitAgentEvent(event) {
3374
- try {
3375
- emitAgentEvent({
3376
- runId: this.params.runId,
3377
- stream: event.stream,
3378
- data: event.data,
3379
- ...this.params.sessionKey ? { sessionKey: this.params.sessionKey } : {}
3380
- });
3381
- } catch (error) {
3382
- embeddedAgentLog.debug("codex app-server global agent event emit failed", { error });
3383
- }
3384
- try {
3385
- const maybePromise = this.params.onAgentEvent?.(event);
3386
- Promise.resolve(maybePromise).catch((error) => {
3387
- embeddedAgentLog.debug("codex app-server agent event handler rejected", { error });
3388
- });
3389
- } catch (error) {
3390
- embeddedAgentLog.debug("codex app-server agent event handler threw", { error });
3391
- }
3392
- }
3393
- isNotificationForTurn(params) {
3394
- const threadId = readCodexNotificationThreadId(params);
3395
- const turnId = readCodexNotificationTurnId(params);
3396
- return threadId === this.threadId && turnId === this.turnId;
3397
- }
3398
- isHookNotificationForCurrentThread(params) {
3399
- const threadId = readString$3(params, "threadId");
3400
- const turnId = params.turnId;
3401
- return threadId === this.threadId && (turnId === this.turnId || turnId === null);
3402
- }
3403
- };
3404
- function isHookNotificationMethod(method) {
3405
- return method === "hook/started" || method === "hook/completed";
3406
- }
3407
- //#endregion
3408
973
  //#region extensions/codex/src/app-server/dynamic-tool-build-state.ts
3409
974
  /** Mutable dependency seam shared by dynamic-tool construction and its behavioral tests. */
3410
975
  const dynamicToolBuildState = {};
@@ -3647,6 +1212,8 @@ async function buildDynamicTools(input) {
3647
1212
  senderUsername: params.senderUsername,
3648
1213
  senderE164: params.senderE164,
3649
1214
  senderIsOwner: params.senderIsOwner,
1215
+ inputProvenance: params.inputProvenance,
1216
+ trustedInternalHandoff: params.trustedInternalHandoff,
3650
1217
  allowGatewaySubagentBinding: params.allowGatewaySubagentBinding || isForcedPrivateQaCodexRuntime(),
3651
1218
  ...sessionKeys,
3652
1219
  sessionId: params.sessionId,
@@ -3668,6 +1235,7 @@ async function buildDynamicTools(input) {
3668
1235
  modelCompat: params.model.compat && typeof params.model.compat === "object" ? params.model.compat : void 0,
3669
1236
  modelApi: params.model.api,
3670
1237
  modelContextWindowTokens: params.model.contextWindow,
1238
+ delegationCapability: params.delegationCapability,
3671
1239
  modelAuthMode: resolveModelAuthMode(params.model.provider, params.config, params.toolAuthProfileStore ?? params.authProfileStore, { workspaceDir: input.effectiveWorkspace }),
3672
1240
  suppressManagedWebSearch: false,
3673
1241
  currentChannelId: params.currentChannelId,
@@ -3738,7 +1306,9 @@ async function buildDynamicTools(input) {
3738
1306
  senderId: params.senderId,
3739
1307
  senderName: params.senderName,
3740
1308
  senderUsername: params.senderUsername,
3741
- senderE164: params.senderE164
1309
+ senderE164: params.senderE164,
1310
+ inputProvenance: params.inputProvenance,
1311
+ trustedInternalHandoff: params.trustedInternalHandoff
3742
1312
  });
3743
1313
  const transientWebSearchRestriction = !webSearchPolicy.allowed && webSearchPolicy.persistentAllowed || isCodexMemoryFlushRun(params);
3744
1314
  const persistentCodexWebSearchSurface = params.config?.tools?.web?.search?.enabled !== false && !(input.pluginConfig.codexDynamicToolsExclude ?? []).some((name) => normalizeCodexDynamicToolName(name) === "web_search");
@@ -3804,6 +1374,7 @@ function includeForcedCodexDynamicToolAllow(toolsAllow, params) {
3804
1374
  /** Decides whether Codex native code mode can own shell/file tools for this turn. */
3805
1375
  function shouldEnableCodexAppServerNativeToolSurface(params, sandbox, options = {}) {
3806
1376
  if (isCodexMemoryFlushRun(params)) return false;
1377
+ if (params.disableTools) return false;
3807
1378
  const toolsAllow = includeForcedCodexDynamicToolAllow(params.toolsAllow, params);
3808
1379
  if (toolsAllow === void 0) return canCodexAppServerNativeToolSurfaceHonorSandbox(sandbox, options);
3809
1380
  return hasWildcardCodexToolsAllow(toolsAllow) && canCodexAppServerNativeToolSurfaceHonorSandbox(sandbox, options);
@@ -4164,8 +1735,11 @@ function approvalRequestExplicitlyUnavailable(result) {
4164
1735
  }
4165
1736
  /** Waits for the gateway's final approval decision, respecting turn aborts. */
4166
1737
  async function waitForPluginApprovalDecision(params) {
4167
- const waitPromise = callGatewayTool("plugin.approval.waitDecision", { timeoutMs: resolveCodexGatewayTimeoutWithGraceMs(DEFAULT_CODEX_APPROVAL_TIMEOUT_MS) }, { id: params.approvalId });
4168
- const bindDecision = (result) => result?.id === params.approvalId ? result.decision : void 0;
1738
+ const waitPromise = callGatewayTool("plugin.approval.waitDecision", { timeoutMs: resolveCodexGatewayTimeoutWithGraceMs(DEFAULT_CODEX_APPROVAL_TIMEOUT_MS) }, { id: params.approvalId }).catch((error) => {
1739
+ if (isApprovalNotFoundError(error)) return null;
1740
+ throw error;
1741
+ });
1742
+ const bindDecision = (result) => result === null ? null : result?.id === params.approvalId ? result.decision : void 0;
4169
1743
  if (!params.signal) return bindDecision(await waitPromise);
4170
1744
  let onAbort;
4171
1745
  const abortPromise = new Promise((_, reject) => {
@@ -6552,4 +4126,4 @@ function isCronAddAction(args) {
6552
4126
  return typeof action === "string" && action.trim().toLowerCase() === "add";
6553
4127
  }
6554
4128
  //#endregion
6555
- 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, resolveCodexLocalRuntimeAttribution as nt, emitDynamicToolTerminalDiagnostic as o, formatCodexDynamicToolBuildStageSummary as p, toCodexDynamicToolProgressResponse as q, handleCodexAppServerElicitationRequest as r, 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 };
4129
+ 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 };