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