@openclaw/codex 2026.7.2-beta.7 → 2026.8.1-beta.2
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/README.md +2 -0
- package/dist/{app-server-policy-BSaO2JIT.js → app-server-policy-zcBDc1JU.js} +1 -1
- package/dist/attempt-client-cleanup-DMLXUfa8.js +735 -0
- package/dist/{notification-correlation-CU6_AnOb.js → binding-connection-I5Bo-AsX.js} +3 -37
- package/dist/{bounded-turn-D2ZAgZVz.js → bounded-turn-qgZmzy_4.js} +50 -49
- package/dist/{capabilities-BFDTVYr4.js → capabilities-CybGI1oz.js} +8 -2
- package/dist/cli-metadata.js +1 -1
- package/dist/{command-formatters-C336eRVS.js → command-formatters-B1AEz8ZA.js} +18 -18
- package/dist/{command-handlers-DAHUSry9.js → command-handlers-Db8pu_ds.js} +484 -95
- package/dist/{compact-D_uvHurS.js → compact-LspQaGfl.js} +213 -199
- package/dist/{conversation-binding-data-BHRpYbX3.js → conversation-binding-data-CW2GuupV.js} +6 -10
- package/dist/doctor-contract-api.js +40 -43
- package/dist/{dynamic-tools-D2gYkSBO.js → dynamic-tools-BVdyWkUD.js} +2597 -1221
- package/dist/{effective-mcp-catalog-Bbd98Inw.js → effective-mcp-catalog-DIIhAtOZ.js} +20 -15
- package/dist/{event-projector-assistant-message-DTgnPPVF.js → event-projector-assistant-message-BwxV4d6N.js} +11 -23
- package/dist/{attempt-notifications-AP-a-Q5k.js → event-projector-usage-e5huIQWu.js} +113 -29
- package/dist/harness.js +80 -14
- package/dist/image-payload-sanitizer-CnfoUPCE.js +65 -0
- package/dist/index.js +591 -240
- package/dist/isolated-completion-C58NbL40.js +75 -0
- package/dist/local-runtime-attribution-B_2mnqhb.js +19 -0
- package/dist/media-understanding-provider.js +5 -5
- package/dist/{models-BBMKU4jA.js → models-BFlpn1Ex.js} +12 -17
- package/dist/native-subagent-monitor-DyTGmTUx.js +3111 -0
- package/dist/{plugin-app-cache-key-DztPafOA.js → plugin-app-cache-key-C3H2CVp6.js} +5 -5
- package/dist/plugin-marketplace-discovery-CzrGJdCR.js +385 -0
- package/dist/{computer-use-CYEc8U3w.js → plugin-metadata-cache-CNJPj4_b.js} +105 -5
- package/dist/protocol-validators-B4F7L8Rf.js +2346 -0
- package/dist/{rate-limits-CU-gVCCS.js → rate-limits-DZXmOL8-.js} +17 -35
- package/dist/{request-qKh331yu.js → request-BRl5_UfX.js} +3 -3
- package/dist/{run-attempt-CY9WlDLc.js → run-attempt-P8BdxC1I.js} +4837 -9047
- package/dist/{runtime-artifact-CmtG_t1L.js → runtime-artifact-BVSPdd6g.js} +8 -23
- package/dist/{sandbox-guard-NuhpXmPB.js → sandbox-guard-Cmwc9eIk.js} +6 -13
- package/dist/{session-binding-BXpo9ymA.js → session-binding-DPxIvMgE.js} +246 -265
- package/dist/{session-catalog-DyOgR4WH.js → session-catalog-xwNi_SDM.js} +159 -109
- package/dist/{session-cli-2PZaFLRh.js → session-cli-7hgXZDV7.js} +1 -1
- package/dist/session-retirement-DoMMJFKm.js +36 -0
- package/dist/{session-upstream-marker-B6U7tLw5.js → session-upstream-marker-CrIFX06J.js} +1 -1
- package/dist/{settled-turn-finalizer-CXY2Z9dT.js → settled-turn-finalizer-BRWBO4MO.js} +21 -13
- package/dist/{shared-client-DTbvH-XV.js → shared-client-kIBbGjk4.js} +587 -223
- package/dist/{side-question-_ulBk1AL.js → side-question-9HAL26l9.js} +101 -52
- package/dist/{thread-lifecycle-DF53ogiA.js → thread-lifecycle-Bu1BTDXr.js} +694 -753
- package/dist/thread-ownership-6kOQHlyC.js +92 -0
- package/dist/thread-resume-CPrJNQVM.js +30 -0
- package/dist/transcript-mirror-B9gGgnJS.js +570 -0
- package/dist/{transport-stdio-DXgGZ7Ib.js → transport-stdio-DIImwDVS.js} +11 -0
- package/dist/upstream-prompt-provenance-ClRBije0.js +41 -0
- package/dist/{upstream-session-fork-Dy4Xvuoj.js → upstream-session-fork-CE-_LdnP.js} +5 -5
- package/dist/{usage-CQ6GhD5-.js → usage-CHlV0e-o.js} +3 -3
- package/dist/{web-search-provider.runtime-CCFhg2z5.js → web-search-provider.runtime-DRw2Vl42.js} +8 -9
- package/openclaw.plugin.json +18 -3
- package/package.json +5 -5
- package/dist/conversation-control-xsIeXbo4.js +0 -287
- package/dist/event-projector-usage-Xp4AlR2k.js +0 -86
- package/dist/transcript-mirror-DzsdNCf5.js +0 -6924
|
@@ -1,25 +1,21 @@
|
|
|
1
|
-
import { d as
|
|
2
|
-
import { d as
|
|
1
|
+
import { d as sessionBindingIdentity } from "./session-binding-DPxIvMgE.js";
|
|
2
|
+
import { d as retainSharedCodexAppServerClientByInstanceId } from "./shared-client-kIBbGjk4.js";
|
|
3
|
+
import { asOptionalRecord, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
3
4
|
import { assignMcpCatalogSafeServerNames } from "openclaw/plugin-sdk/agent-harness-runtime";
|
|
4
5
|
//#region extensions/codex/src/app-server/effective-mcp-catalog.ts
|
|
5
6
|
const MCP_STATUS_PAGE_SIZE = 100;
|
|
6
7
|
const MCP_STATUS_MAX_PAGES = 100;
|
|
7
|
-
function asRecord(value) {
|
|
8
|
-
return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
9
|
-
}
|
|
10
|
-
function readString(value) {
|
|
11
|
-
return typeof value === "string" && value.trim() ? value.trim() : void 0;
|
|
12
|
-
}
|
|
13
8
|
function catalogTool(params) {
|
|
14
|
-
const raw =
|
|
15
|
-
const description =
|
|
9
|
+
const raw = asOptionalRecord(params.raw);
|
|
10
|
+
const description = normalizeOptionalString(raw?.description);
|
|
11
|
+
const title = normalizeOptionalString(raw?.title);
|
|
16
12
|
return {
|
|
17
13
|
serverName: params.serverName,
|
|
18
14
|
safeServerName: params.safeServerName,
|
|
19
15
|
toolName: params.toolName,
|
|
20
|
-
...
|
|
16
|
+
...title ? { title } : {},
|
|
21
17
|
...description ? { description } : {},
|
|
22
|
-
inputSchema:
|
|
18
|
+
inputSchema: asOptionalRecord(raw?.inputSchema) ?? { type: "object" },
|
|
23
19
|
fallbackDescription: description ?? params.toolName,
|
|
24
20
|
...params.deniedBySession ? { deniedBySession: true } : {}
|
|
25
21
|
};
|
|
@@ -92,7 +88,12 @@ async function listCodexMcpServerStatuses(client, threadId) {
|
|
|
92
88
|
}
|
|
93
89
|
throw new Error("Codex mcpServerStatus/list exceeded the bounded page limit");
|
|
94
90
|
}
|
|
95
|
-
/** Loads MCP inventory
|
|
91
|
+
/** Loads the requested MCP inventory from the exact client/thread already selected for a run. */
|
|
92
|
+
async function loadCodexEffectiveMcpCatalogFromThread(params) {
|
|
93
|
+
const allowedServerNames = new Set(params.mcpServerNames);
|
|
94
|
+
return buildCodexEffectiveMcpCatalog((await listCodexMcpServerStatuses(params.client, params.threadId)).filter((status) => allowedServerNames.has(status.name)), params.toolOverrides);
|
|
95
|
+
}
|
|
96
|
+
/** Loads MCP inventory from the bound Codex client while retaining its lease through all pages. */
|
|
96
97
|
async function loadCodexEffectiveMcpCatalog(params, options) {
|
|
97
98
|
const binding = await options.bindingStore.read(sessionBindingIdentity({
|
|
98
99
|
agentId: params.agentId,
|
|
@@ -104,8 +105,12 @@ async function loadCodexEffectiveMcpCatalog(params, options) {
|
|
|
104
105
|
const retained = retainSharedCodexAppServerClientByInstanceId(binding.clientId);
|
|
105
106
|
if (!retained) return;
|
|
106
107
|
try {
|
|
107
|
-
|
|
108
|
-
|
|
108
|
+
return await loadCodexEffectiveMcpCatalogFromThread({
|
|
109
|
+
client: retained.client,
|
|
110
|
+
threadId: binding.threadId,
|
|
111
|
+
mcpServerNames: params.mcpServerNames,
|
|
112
|
+
toolOverrides: params.toolOverrides
|
|
113
|
+
});
|
|
109
114
|
} finally {
|
|
110
115
|
retained.release();
|
|
111
116
|
}
|
|
@@ -1,24 +1,5 @@
|
|
|
1
|
+
import { t as resolveCodexLocalRuntimeAttribution } from "./local-runtime-attribution-B_2mnqhb.js";
|
|
1
2
|
import { formatErrorMessage } from "openclaw/plugin-sdk/agent-harness-runtime";
|
|
2
|
-
//#region extensions/codex/src/app-server/local-runtime-attribution.ts
|
|
3
|
-
const OPENAI_PROVIDER_ID = "openai";
|
|
4
|
-
const OPENAI_RESPONSES_API = "openai-responses";
|
|
5
|
-
const OPENAI_CODEX_RESPONSES_API = "openai-chatgpt-responses";
|
|
6
|
-
function normalizeRuntimeId(value) {
|
|
7
|
-
return value?.trim().toLowerCase() ?? "";
|
|
8
|
-
}
|
|
9
|
-
/** Maps local Codex runtime plans onto the provider/api pair exposed to event projection. */
|
|
10
|
-
function resolveCodexLocalRuntimeAttribution(params) {
|
|
11
|
-
const authProfileProvider = normalizeRuntimeId(params.runtimePlan?.auth?.authProfileProviderForAuth);
|
|
12
|
-
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 {
|
|
13
|
-
provider: OPENAI_PROVIDER_ID,
|
|
14
|
-
api: OPENAI_CODEX_RESPONSES_API
|
|
15
|
-
};
|
|
16
|
-
return {
|
|
17
|
-
provider: params.provider,
|
|
18
|
-
api: params.model.api
|
|
19
|
-
};
|
|
20
|
-
}
|
|
21
|
-
//#endregion
|
|
22
3
|
//#region extensions/codex/src/app-server/event-projector-assistant-message.ts
|
|
23
4
|
const ZERO_USAGE = {
|
|
24
5
|
input: 0,
|
|
@@ -35,12 +16,19 @@ const ZERO_USAGE = {
|
|
|
35
16
|
}
|
|
36
17
|
};
|
|
37
18
|
function createAssistantMessage(params, text, options) {
|
|
38
|
-
|
|
19
|
+
return createAttributedCodexAssistantMessage({
|
|
20
|
+
...resolveCodexLocalRuntimeAttribution(params),
|
|
21
|
+
modelId: params.modelId
|
|
22
|
+
}, text, options);
|
|
23
|
+
}
|
|
24
|
+
/** Creates a Codex assistant row when a bounded call already owns attribution. */
|
|
25
|
+
function createAttributedCodexAssistantMessage(attribution, text, options) {
|
|
39
26
|
const usage = options.tokenUsage ? {
|
|
40
27
|
input: options.tokenUsage.input ?? 0,
|
|
41
28
|
output: options.tokenUsage.output ?? 0,
|
|
42
29
|
cacheRead: options.tokenUsage.cacheRead ?? 0,
|
|
43
30
|
cacheWrite: options.tokenUsage.cacheWrite ?? 0,
|
|
31
|
+
...options.tokenUsage.reasoningTokens !== void 0 ? { reasoningTokens: options.tokenUsage.reasoningTokens } : {},
|
|
44
32
|
...options.tokenUsage.contextUsage ? { contextUsage: options.tokenUsage.contextUsage } : {},
|
|
45
33
|
totalTokens: options.tokenUsage.total ?? (options.tokenUsage.input ?? 0) + (options.tokenUsage.output ?? 0) + (options.tokenUsage.cacheRead ?? 0) + (options.tokenUsage.cacheWrite ?? 0),
|
|
46
34
|
cost: ZERO_USAGE.cost
|
|
@@ -53,7 +41,7 @@ function createAssistantMessage(params, text, options) {
|
|
|
53
41
|
}],
|
|
54
42
|
api: attribution.api ?? "openai-chatgpt-responses",
|
|
55
43
|
provider: attribution.provider,
|
|
56
|
-
model:
|
|
44
|
+
model: attribution.modelId,
|
|
57
45
|
usage,
|
|
58
46
|
stopReason: options.aborted ? "aborted" : options.promptError ? "error" : "stop",
|
|
59
47
|
errorMessage: options.promptError ? formatErrorMessage(options.promptError) : void 0,
|
|
@@ -98,4 +86,4 @@ function createAssistantMirrorMessage(params, title, text) {
|
|
|
98
86
|
};
|
|
99
87
|
}
|
|
100
88
|
//#endregion
|
|
101
|
-
export {
|
|
89
|
+
export { createAttributedCodexAssistantMessage as i, createAssistantMessage as n, createAssistantMirrorMessage as r, createAssistantCommentaryMessage as t };
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ct as isJsonObject } from "./shared-client-kIBbGjk4.js";
|
|
2
|
+
import { asFiniteNumber, asSafeIntegerInRange, readStringField } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
3
|
+
import { normalizeUsage } from "openclaw/plugin-sdk/agent-harness-runtime";
|
|
2
4
|
import { truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
|
|
3
5
|
//#region extensions/codex/src/app-server/attempt-notifications.ts
|
|
4
6
|
/**
|
|
@@ -14,9 +16,9 @@ function describeNotificationActivity(notification) {
|
|
|
14
16
|
if (!item) return { lastNotificationMethod: notification.method };
|
|
15
17
|
return {
|
|
16
18
|
lastNotificationMethod: notification.method,
|
|
17
|
-
lastNotificationItemId:
|
|
18
|
-
lastNotificationItemType:
|
|
19
|
-
lastNotificationItemRole:
|
|
19
|
+
lastNotificationItemId: readStringField(item, "id"),
|
|
20
|
+
lastNotificationItemType: readStringField(item, "type"),
|
|
21
|
+
lastNotificationItemRole: readStringField(item, "role"),
|
|
20
22
|
lastAssistantTextPreview: readRawAssistantTextPreview(item)
|
|
21
23
|
};
|
|
22
24
|
}
|
|
@@ -59,25 +61,25 @@ function isCompletedAssistantNotification(notification) {
|
|
|
59
61
|
if (!isJsonObject(notification.params)) return false;
|
|
60
62
|
if (notification.method !== "item/completed") return false;
|
|
61
63
|
const item = isJsonObject(notification.params.item) ? notification.params.item : void 0;
|
|
62
|
-
return Boolean(item &&
|
|
64
|
+
return Boolean(item && readStringField(item, "type") === "agentMessage" && readStringField(item, "phase") !== "commentary");
|
|
63
65
|
}
|
|
64
66
|
/** Returns true for completed app-server reasoning items. */
|
|
65
67
|
function isReasoningItemCompletionNotification(notification) {
|
|
66
68
|
if (!isJsonObject(notification.params) || notification.method !== "item/completed") return false;
|
|
67
69
|
const item = isJsonObject(notification.params.item) ? notification.params.item : void 0;
|
|
68
|
-
return item ?
|
|
70
|
+
return item ? readStringField(item, "type") === "reasoning" : false;
|
|
69
71
|
}
|
|
70
72
|
/** Returns true for completed assistant commentary items. */
|
|
71
73
|
function isAssistantCommentaryCompletionNotification(notification) {
|
|
72
74
|
if (!isJsonObject(notification.params) || notification.method !== "item/completed") return false;
|
|
73
75
|
const item = isJsonObject(notification.params.item) ? notification.params.item : void 0;
|
|
74
|
-
return Boolean(item &&
|
|
76
|
+
return Boolean(item && readStringField(item, "type") === "agentMessage" && readStringField(item, "phase") === "commentary");
|
|
75
77
|
}
|
|
76
78
|
/** Returns true for completed raw response reasoning items. */
|
|
77
79
|
function isRawReasoningCompletionNotification(notification) {
|
|
78
80
|
if (!isJsonObject(notification.params) || notification.method !== "rawResponseItem/completed") return false;
|
|
79
81
|
const item = isJsonObject(notification.params.item) ? notification.params.item : void 0;
|
|
80
|
-
return item ?
|
|
82
|
+
return item ? readStringField(item, "type") === "reasoning" : false;
|
|
81
83
|
}
|
|
82
84
|
/** Returns true for streamed app-server reasoning progress. */
|
|
83
85
|
function isReasoningProgressNotification(notification) {
|
|
@@ -99,7 +101,7 @@ function shouldDisarmAssistantCompletionIdleWatch(notification) {
|
|
|
99
101
|
function readNotificationItemId(notification) {
|
|
100
102
|
if (!isJsonObject(notification.params)) return;
|
|
101
103
|
const item = isJsonObject(notification.params.item) ? notification.params.item : void 0;
|
|
102
|
-
return (item ?
|
|
104
|
+
return (item ? readStringField(item, "id") : void 0) ?? readStringField(notification.params, "itemId") ?? readStringField(notification.params, "id");
|
|
103
105
|
}
|
|
104
106
|
/** Detects completion for an OpenClaw dynamic tool result still awaited by Codex. */
|
|
105
107
|
function isPendingOpenClawDynamicToolCompletionNotification(notification, pendingOpenClawDynamicToolCompletionIds) {
|
|
@@ -107,14 +109,14 @@ function isPendingOpenClawDynamicToolCompletionNotification(notification, pendin
|
|
|
107
109
|
const itemId = readNotificationItemId(notification);
|
|
108
110
|
if (!itemId || !pendingOpenClawDynamicToolCompletionIds.has(itemId)) return false;
|
|
109
111
|
const item = isJsonObject(notification.params.item) ? notification.params.item : void 0;
|
|
110
|
-
const itemType = item ?
|
|
112
|
+
const itemType = item ? readStringField(item, "type") : void 0;
|
|
111
113
|
return itemType === void 0 || itemType === "dynamicToolCall";
|
|
112
114
|
}
|
|
113
115
|
/** Returns true for raw response tool-output completion notifications. */
|
|
114
116
|
function isRawToolOutputCompletionNotification(notification) {
|
|
115
117
|
if (notification.method !== "rawResponseItem/completed" || !isJsonObject(notification.params)) return false;
|
|
116
118
|
const item = isJsonObject(notification.params.item) ? notification.params.item : void 0;
|
|
117
|
-
switch (item ?
|
|
119
|
+
switch (item ? readStringField(item, "type") : void 0) {
|
|
118
120
|
case "custom_tool_call_output":
|
|
119
121
|
case "function_call_output": return true;
|
|
120
122
|
default: return false;
|
|
@@ -123,14 +125,14 @@ function isRawToolOutputCompletionNotification(notification) {
|
|
|
123
125
|
function isRawFunctionToolOutputCompletionNotification(notification) {
|
|
124
126
|
if (notification.method !== "rawResponseItem/completed" || !isJsonObject(notification.params)) return false;
|
|
125
127
|
const item = isJsonObject(notification.params.item) ? notification.params.item : void 0;
|
|
126
|
-
return item ?
|
|
128
|
+
return item ? readStringField(item, "type") === "function_call_output" : false;
|
|
127
129
|
}
|
|
128
130
|
/** Returns true for progress on Codex-native tool item types. */
|
|
129
131
|
function isNativeToolProgressNotification(notification) {
|
|
130
132
|
if (notification.method !== "item/started" && notification.method !== "item/completed" && notification.method !== "item/updated") return false;
|
|
131
133
|
if (!isJsonObject(notification.params)) return false;
|
|
132
134
|
const item = isJsonObject(notification.params.item) ? notification.params.item : void 0;
|
|
133
|
-
switch (item ?
|
|
135
|
+
switch (item ? readStringField(item, "type") : void 0) {
|
|
134
136
|
case "commandExecution":
|
|
135
137
|
case "fileChange":
|
|
136
138
|
case "mcpToolCall":
|
|
@@ -146,19 +148,19 @@ function isFileChangePatchUpdatedNotification(notification) {
|
|
|
146
148
|
function isRawAssistantProgressNotification(notification) {
|
|
147
149
|
if (notification.method !== "rawResponseItem/completed" || !isJsonObject(notification.params)) return false;
|
|
148
150
|
const item = isJsonObject(notification.params.item) ? notification.params.item : void 0;
|
|
149
|
-
return Boolean(item &&
|
|
151
|
+
return Boolean(item && readStringField(item, "type") === "message" && readStringField(item, "role") === "assistant" && readRawAssistantTextPreview(item));
|
|
150
152
|
}
|
|
151
153
|
/** Returns true for raw assistant completion outside commentary phase. */
|
|
152
154
|
function isRawAssistantCompletionNotification(notification) {
|
|
153
155
|
if (!isRawAssistantProgressNotification(notification) || !isJsonObject(notification.params)) return false;
|
|
154
156
|
const item = isJsonObject(notification.params.item) ? notification.params.item : void 0;
|
|
155
|
-
return Boolean(item &&
|
|
157
|
+
return Boolean(item && readStringField(item, "phase") !== "commentary");
|
|
156
158
|
}
|
|
157
159
|
function readRawAssistantTextPreview(item) {
|
|
158
|
-
if (
|
|
160
|
+
if (readStringField(item, "role") !== "assistant" || !Array.isArray(item.content)) return;
|
|
159
161
|
const text = item.content.flatMap((content) => {
|
|
160
162
|
if (!isJsonObject(content)) return [];
|
|
161
|
-
const contentText =
|
|
163
|
+
const contentText = readStringField(content, "text");
|
|
162
164
|
return contentText ? [contentText] : [];
|
|
163
165
|
}).join("\n").trim();
|
|
164
166
|
if (!text) return;
|
|
@@ -179,8 +181,8 @@ function isTerminalTurnStatus(status) {
|
|
|
179
181
|
function isCodexTurnAbortMarkerNotification(notification, options = {}) {
|
|
180
182
|
if (notification.method !== "rawResponseItem/completed" || !isJsonObject(notification.params)) return false;
|
|
181
183
|
const item = notification.params.item;
|
|
182
|
-
const role = isJsonObject(item) ?
|
|
183
|
-
if (!isJsonObject(item) ||
|
|
184
|
+
const role = isJsonObject(item) ? readStringField(item, "role") : void 0;
|
|
185
|
+
if (!isJsonObject(item) || readStringField(item, "type") !== "message" || role !== "user" && role !== "developer") return false;
|
|
184
186
|
const text = extractRawResponseItemText(item).trim();
|
|
185
187
|
const currentPromptTexts = [options.currentPromptText, ...options.currentPromptTexts ?? []].filter(isNonEmptyString).map((prompt) => prompt.trim());
|
|
186
188
|
if (role === "user" && currentPromptTexts.includes(text)) return false;
|
|
@@ -195,16 +197,12 @@ function extractRawResponseItemText(item) {
|
|
|
195
197
|
if (!Array.isArray(content)) return "";
|
|
196
198
|
return content.flatMap((entry) => {
|
|
197
199
|
if (!isJsonObject(entry)) return [];
|
|
198
|
-
const type =
|
|
200
|
+
const type = readStringField(entry, "type");
|
|
199
201
|
if (type !== "input_text" && type !== "text") return [];
|
|
200
|
-
const text =
|
|
202
|
+
const text = readStringField(entry, "text");
|
|
201
203
|
return text ? [text] : [];
|
|
202
204
|
}).join("");
|
|
203
205
|
}
|
|
204
|
-
function readString(record, key) {
|
|
205
|
-
const value = record[key];
|
|
206
|
-
return typeof value === "string" ? value : void 0;
|
|
207
|
-
}
|
|
208
206
|
/** Reads a typed Codex item from notification params when id/type are present. */
|
|
209
207
|
function readCodexNotificationItem(params) {
|
|
210
208
|
if (!isJsonObject(params) || !isJsonObject(params.item)) return;
|
|
@@ -216,13 +214,13 @@ function readRawResponseToolCallId(notification) {
|
|
|
216
214
|
if (notification.method !== "rawResponseItem/completed" || !isJsonObject(notification.params)) return;
|
|
217
215
|
const item = isJsonObject(notification.params.item) ? notification.params.item : void 0;
|
|
218
216
|
if (!item) return;
|
|
219
|
-
switch (
|
|
217
|
+
switch (readStringField(item, "type")) {
|
|
220
218
|
case "custom_tool_call":
|
|
221
219
|
case "function_call":
|
|
222
220
|
case "local_shell_call":
|
|
223
|
-
case "tool_search_call": return
|
|
221
|
+
case "tool_search_call": return readStringField(item, "call_id");
|
|
224
222
|
case "image_generation_call":
|
|
225
|
-
case "web_search_call": return
|
|
223
|
+
case "web_search_call": return readStringField(item, "id");
|
|
226
224
|
default: return;
|
|
227
225
|
}
|
|
228
226
|
}
|
|
@@ -241,4 +239,90 @@ function isNonEmptyString(value) {
|
|
|
241
239
|
return typeof value === "string" && value.length > 0;
|
|
242
240
|
}
|
|
243
241
|
//#endregion
|
|
244
|
-
|
|
242
|
+
//#region extensions/codex/src/app-server/event-projector-usage.ts
|
|
243
|
+
function readTokenCount(record, key) {
|
|
244
|
+
return asSafeIntegerInRange(record[key], { min: 0 });
|
|
245
|
+
}
|
|
246
|
+
function readCodexThreadTokenUsage(params) {
|
|
247
|
+
const tokenUsage = isJsonObject(params.tokenUsage) ? params.tokenUsage : void 0;
|
|
248
|
+
const last = tokenUsage && isJsonObject(tokenUsage.last) ? tokenUsage.last : void 0;
|
|
249
|
+
return last ? normalizeCodexThreadTokenUsage(last) : void 0;
|
|
250
|
+
}
|
|
251
|
+
function readCodexThreadContextSnapshot(params) {
|
|
252
|
+
const tokenUsage = isJsonObject(params.tokenUsage) ? params.tokenUsage : void 0;
|
|
253
|
+
const last = tokenUsage && isJsonObject(tokenUsage.last) ? tokenUsage.last : void 0;
|
|
254
|
+
const modelContextWindow = tokenUsage ? readTokenCount(tokenUsage, "modelContextWindow") : void 0;
|
|
255
|
+
const activeContextTokens = last ? readTokenCount(last, "totalTokens") : void 0;
|
|
256
|
+
const inputTokens = last ? readTokenCount(last, "inputTokens") : void 0;
|
|
257
|
+
const cachedInputTokens = last ? readTokenCount(last, "cachedInputTokens") : void 0;
|
|
258
|
+
const cacheWriteInputTokens = last ? readTokenCount(last, "cacheWriteInputTokens") : void 0;
|
|
259
|
+
const outputTokens = last ? readTokenCount(last, "outputTokens") : void 0;
|
|
260
|
+
const reasoningOutputTokens = last ? readTokenCount(last, "reasoningOutputTokens") : void 0;
|
|
261
|
+
return {
|
|
262
|
+
...activeContextTokens !== void 0 ? { activeContextTokens } : {},
|
|
263
|
+
...cachedInputTokens !== void 0 ? { cachedInputTokens } : {},
|
|
264
|
+
...cacheWriteInputTokens !== void 0 ? { cacheWriteInputTokens } : {},
|
|
265
|
+
...inputTokens !== void 0 ? { inputTokens } : {},
|
|
266
|
+
...modelContextWindow && modelContextWindow > 0 ? { modelContextWindow } : {},
|
|
267
|
+
...outputTokens !== void 0 ? { outputTokens } : {},
|
|
268
|
+
...inputTokens !== void 0 ? { promptTokens: inputTokens } : {},
|
|
269
|
+
...reasoningOutputTokens !== void 0 ? { reasoningOutputTokens } : {}
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
function projectCodexThreadUsageUpdate(params, currentUsage, applyUsage, emitContext) {
|
|
273
|
+
applyUsage(readCodexThreadTokenUsage(params) ?? currentUsage);
|
|
274
|
+
const context = readCodexThreadContextSnapshot(params);
|
|
275
|
+
if (Object.keys(context).length > 0) emitContext(context);
|
|
276
|
+
}
|
|
277
|
+
function normalizeCodexThreadTokenUsage(record) {
|
|
278
|
+
return normalizeCodexTokenUsageBreakdown(record, "thread");
|
|
279
|
+
}
|
|
280
|
+
function normalizeCodexResponseTokenUsage(record) {
|
|
281
|
+
return normalizeCodexTokenUsageBreakdown(record, "response");
|
|
282
|
+
}
|
|
283
|
+
function normalizeCodexTokenUsageBreakdown(record, source) {
|
|
284
|
+
const readCount = source === "response" ? readTokenCount : (value, key) => asFiniteNumber(value[key]);
|
|
285
|
+
const totalTokens = readCount(record, "totalTokens");
|
|
286
|
+
const inputTokens = readCount(record, "inputTokens");
|
|
287
|
+
const cacheRead = readCount(record, "cachedInputTokens");
|
|
288
|
+
const output = readCount(record, "outputTokens");
|
|
289
|
+
const reasoningTokens = readCount(record, "reasoningOutputTokens");
|
|
290
|
+
const cacheWrite = record.cacheWriteInputTokens === void 0 && source === "response" ? 0 : readCount(record, "cacheWriteInputTokens");
|
|
291
|
+
if (source === "response" && (totalTokens === void 0 || inputTokens === void 0 || cacheRead === void 0 || cacheWrite === void 0 || output === void 0 || reasoningTokens === void 0 || cacheRead + cacheWrite > inputTokens || totalTokens !== inputTokens + output)) return;
|
|
292
|
+
const usage = normalizeUsage({
|
|
293
|
+
input: inputTokens === void 0 ? void 0 : Math.max(0, inputTokens - (cacheRead ?? 0) - (cacheWrite ?? 0)),
|
|
294
|
+
output,
|
|
295
|
+
cacheRead,
|
|
296
|
+
cacheWrite,
|
|
297
|
+
reasoningTokens,
|
|
298
|
+
total: totalTokens
|
|
299
|
+
});
|
|
300
|
+
if (!usage) return;
|
|
301
|
+
return {
|
|
302
|
+
...usage,
|
|
303
|
+
contextUsage: source === "response" && inputTokens !== void 0 && totalTokens !== void 0 ? {
|
|
304
|
+
state: "available",
|
|
305
|
+
promptTokens: inputTokens,
|
|
306
|
+
totalTokens
|
|
307
|
+
} : { state: "unavailable" }
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
var CodexResponseCompletionProjection = class {
|
|
311
|
+
constructor() {
|
|
312
|
+
this.responseIds = /* @__PURE__ */ new Set();
|
|
313
|
+
}
|
|
314
|
+
get modelIterations() {
|
|
315
|
+
return this.responseIds.size;
|
|
316
|
+
}
|
|
317
|
+
clear() {
|
|
318
|
+
this.usage = void 0;
|
|
319
|
+
}
|
|
320
|
+
record(params) {
|
|
321
|
+
const responseId = readStringField(params, "responseId");
|
|
322
|
+
if (responseId) this.responseIds.add(responseId);
|
|
323
|
+
const usage = isJsonObject(params.usage) ? params.usage : void 0;
|
|
324
|
+
this.usage = usage ? normalizeCodexResponseTokenUsage(usage) : void 0;
|
|
325
|
+
}
|
|
326
|
+
};
|
|
327
|
+
//#endregion
|
|
328
|
+
export { readRawResponseToolCallId as C, updateActiveTurnItemIds as E, readNotificationItemId as S, updateActiveCompletionBlockerItemIds as T, isReasoningItemCompletionNotification as _, codexExecutionToolName as a, isTerminalTurnStatus as b, isAssistantCompletionReleaseNotification as c, isNativeToolProgressNotification as d, isPendingOpenClawDynamicToolCompletionNotification as f, isRawToolOutputCompletionNotification as g, isRawReasoningCompletionNotification as h, readCodexThreadContextSnapshot as i, isCodexTurnAbortMarkerNotification as l, isRawFunctionToolOutputCompletionNotification as m, normalizeCodexResponseTokenUsage as n, describeNotificationActivity as o, isRawAssistantProgressNotification as p, projectCodexThreadUsageUpdate as r, isAssistantCommentaryCompletionNotification as s, CodexResponseCompletionProjection as t, isFileChangePatchUpdatedNotification as u, isReasoningProgressNotification as v, shouldDisarmAssistantCompletionIdleWatch as w, readCodexNotificationItem as x, isRetryableErrorNotification as y };
|
package/dist/harness.js
CHANGED
|
@@ -1,6 +1,24 @@
|
|
|
1
|
+
import { completeWithPreparedSimpleCompletionModel } from "openclaw/plugin-sdk/simple-completion-runtime";
|
|
1
2
|
//#region extensions/codex/harness.ts
|
|
2
3
|
const DEFAULT_CODEX_HARNESS_PROVIDER_IDS = /* @__PURE__ */ new Set(["codex", "openai"]);
|
|
3
4
|
const SHARED_CODEX_APP_SERVER_CLIENT_DISPOSER = Symbol.for("openclaw.codexAppServerClientDisposer");
|
|
5
|
+
const CODEX_TOOL_POLICY_SAFE_DENY_NAMES = [
|
|
6
|
+
"web_fetch",
|
|
7
|
+
"x_search",
|
|
8
|
+
"memory_search",
|
|
9
|
+
"memory_get",
|
|
10
|
+
"dashboard",
|
|
11
|
+
"canvas",
|
|
12
|
+
"show_widget",
|
|
13
|
+
"message",
|
|
14
|
+
"heartbeat_respond",
|
|
15
|
+
"automations",
|
|
16
|
+
"gateway",
|
|
17
|
+
"skill_workshop",
|
|
18
|
+
"music_generate",
|
|
19
|
+
"video_generate",
|
|
20
|
+
"tts"
|
|
21
|
+
];
|
|
4
22
|
const CODEX_APP_SERVER_CONTEXT_ENGINE_HOST_CAPABILITIES = [
|
|
5
23
|
"bootstrap",
|
|
6
24
|
"assemble-before-prompt",
|
|
@@ -10,6 +28,30 @@ const CODEX_APP_SERVER_CONTEXT_ENGINE_HOST_CAPABILITIES = [
|
|
|
10
28
|
"runtime-llm-complete",
|
|
11
29
|
"thread-bootstrap-projection"
|
|
12
30
|
];
|
|
31
|
+
async function runCodexHostPreparedIsolatedCompletion(params) {
|
|
32
|
+
const timeoutSignal = AbortSignal.timeout(params.timeoutMs);
|
|
33
|
+
const signal = params.abortSignal ? AbortSignal.any([params.abortSignal, timeoutSignal]) : timeoutSignal;
|
|
34
|
+
return { assistant: await completeWithPreparedSimpleCompletionModel({
|
|
35
|
+
model: params.model,
|
|
36
|
+
auth: params.auth,
|
|
37
|
+
cfg: params.config,
|
|
38
|
+
context: {
|
|
39
|
+
systemPrompt: params.systemPrompt,
|
|
40
|
+
messages: [{
|
|
41
|
+
role: "user",
|
|
42
|
+
content: params.prompt,
|
|
43
|
+
timestamp: Date.now()
|
|
44
|
+
}],
|
|
45
|
+
tools: []
|
|
46
|
+
},
|
|
47
|
+
options: {
|
|
48
|
+
maxTokens: params.streamParams?.maxTokens,
|
|
49
|
+
temperature: params.streamParams?.temperature,
|
|
50
|
+
reasoning: params.thinkLevel,
|
|
51
|
+
signal
|
|
52
|
+
}
|
|
53
|
+
}) };
|
|
54
|
+
}
|
|
13
55
|
async function disposeSharedCodexAppServerClients() {
|
|
14
56
|
const dispose = globalThis[SHARED_CODEX_APP_SERVER_CLIENT_DISPOSER];
|
|
15
57
|
await dispose?.();
|
|
@@ -28,14 +70,17 @@ function createCodexAppServerAgentHarness(options) {
|
|
|
28
70
|
id: harnessRuntimeId,
|
|
29
71
|
label: options?.label ?? "Codex agent harness",
|
|
30
72
|
autoSelection: { providerIds: [...providerIds] },
|
|
73
|
+
cloudPlacement: { mode: "remote-exec" },
|
|
31
74
|
delegatedExecutionPluginIds: ["voice-call"],
|
|
32
75
|
contextEngineHostCapabilities: CODEX_APP_SERVER_CONTEXT_ENGINE_HOST_CAPABILITIES,
|
|
76
|
+
conversationToolPolicySupport: "exact",
|
|
77
|
+
conversationToolPolicySafeDenyTools: CODEX_TOOL_POLICY_SAFE_DENY_NAMES,
|
|
33
78
|
deliveryDefaults: { visibleReplies: "message_tool" },
|
|
34
79
|
authBootstrap: "harness",
|
|
35
80
|
...sessionCatalogControl && sessionRuntime ? { sessionFork: {
|
|
36
81
|
upstreamKinds: ["codex-app-server"],
|
|
37
82
|
fork: async (params) => {
|
|
38
|
-
const { forkCodexUpstreamSession } = await import("./upstream-session-fork-
|
|
83
|
+
const { forkCodexUpstreamSession } = await import("./upstream-session-fork-CE-_LdnP.js");
|
|
39
84
|
return await forkCodexUpstreamSession(params, {
|
|
40
85
|
bindingStore: options.bindingStore,
|
|
41
86
|
control: sessionCatalogControl,
|
|
@@ -50,15 +95,15 @@ function createCodexAppServerAgentHarness(options) {
|
|
|
50
95
|
return fingerprintCodexAppServerAuthBinding(params);
|
|
51
96
|
} },
|
|
52
97
|
runtimeArtifact: { validate: async (binding) => {
|
|
53
|
-
const { validateCodexAppServerRuntimeArtifact } = await import("./runtime-artifact-
|
|
98
|
+
const { validateCodexAppServerRuntimeArtifact } = await import("./runtime-artifact-BVSPdd6g.js");
|
|
54
99
|
return validateCodexAppServerRuntimeArtifact(binding);
|
|
55
100
|
} },
|
|
56
101
|
fetchUsageSnapshot: async (ctx) => {
|
|
57
|
-
const { fetchCodexAppServerUsageSnapshot } = await import("./usage-
|
|
102
|
+
const { fetchCodexAppServerUsageSnapshot } = await import("./usage-CHlV0e-o.js");
|
|
58
103
|
return await fetchCodexAppServerUsageSnapshot(ctx, { pluginConfig: options?.resolvePluginConfig?.() ?? options?.pluginConfig });
|
|
59
104
|
},
|
|
60
105
|
loadMcpToolCatalog: async (params) => {
|
|
61
|
-
const { loadCodexEffectiveMcpCatalog } = await import("./effective-mcp-catalog-
|
|
106
|
+
const { loadCodexEffectiveMcpCatalog } = await import("./effective-mcp-catalog-DIIhAtOZ.js");
|
|
62
107
|
return await loadCodexEffectiveMcpCatalog(params, { bindingStore: options.bindingStore });
|
|
63
108
|
},
|
|
64
109
|
supports: (ctx) => {
|
|
@@ -69,7 +114,8 @@ function createCodexAppServerAgentHarness(options) {
|
|
|
69
114
|
};
|
|
70
115
|
if (ctx.modelProvider?.requestTransportOverrides === "present") return {
|
|
71
116
|
supported: false,
|
|
72
|
-
reason: "Codex cannot reproduce authored request transport overrides"
|
|
117
|
+
reason: "Codex cannot reproduce authored request transport overrides",
|
|
118
|
+
fallbackRuntime: "openclaw"
|
|
73
119
|
};
|
|
74
120
|
const preparedAuth = ctx.modelProvider?.preparedAuth;
|
|
75
121
|
const runtimePolicy = ctx.modelProvider?.runtimePolicy;
|
|
@@ -99,19 +145,35 @@ function createCodexAppServerAgentHarness(options) {
|
|
|
99
145
|
};
|
|
100
146
|
},
|
|
101
147
|
runAttempt: async (params) => {
|
|
102
|
-
const { runCodexAppServerAttempt } = await import("./run-attempt-
|
|
148
|
+
const { runCodexAppServerAttempt } = await import("./run-attempt-P8BdxC1I.js");
|
|
103
149
|
return runCodexAppServerAttempt(params, {
|
|
104
150
|
bindingStore: options.bindingStore,
|
|
105
151
|
pluginConfig: options?.resolvePluginConfig?.() ?? options?.pluginConfig,
|
|
106
152
|
nativeHookRelay: { enabled: true }
|
|
107
153
|
});
|
|
108
154
|
},
|
|
155
|
+
runIsolatedCompletionV2: async (params) => {
|
|
156
|
+
if (params.authorization.owner === "host") {
|
|
157
|
+
const { authorization, ...commonParams } = params;
|
|
158
|
+
return runCodexHostPreparedIsolatedCompletion({
|
|
159
|
+
...commonParams,
|
|
160
|
+
model: authorization.model,
|
|
161
|
+
auth: authorization.auth,
|
|
162
|
+
...authorization.sourceAuthFingerprint ? { sourceAuthFingerprint: authorization.sourceAuthFingerprint } : {}
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
const { runCodexIsolatedCompletion } = await import("./isolated-completion-C58NbL40.js");
|
|
166
|
+
return runCodexIsolatedCompletion(params, { pluginConfig: options?.resolvePluginConfig?.() ?? options?.pluginConfig });
|
|
167
|
+
},
|
|
168
|
+
runIsolatedCompletion: async (params) => {
|
|
169
|
+
return runCodexHostPreparedIsolatedCompletion(params);
|
|
170
|
+
},
|
|
109
171
|
finalizeSettledTurn: async (params) => {
|
|
110
|
-
const { runCodexSettledTurnFinalization } = await import("./settled-turn-finalizer-
|
|
172
|
+
const { runCodexSettledTurnFinalization } = await import("./settled-turn-finalizer-BRWBO4MO.js");
|
|
111
173
|
return runCodexSettledTurnFinalization(params, { pluginConfig: options?.resolvePluginConfig?.() ?? options?.pluginConfig });
|
|
112
174
|
},
|
|
113
175
|
runSideQuestion: async (params) => {
|
|
114
|
-
const { runCodexAppServerSideQuestion } = await import("./side-question-
|
|
176
|
+
const { runCodexAppServerSideQuestion } = await import("./side-question-9HAL26l9.js");
|
|
115
177
|
return runCodexAppServerSideQuestion(params, {
|
|
116
178
|
bindingStore: options.bindingStore,
|
|
117
179
|
pluginConfig: options?.resolvePluginConfig?.() ?? options?.pluginConfig,
|
|
@@ -119,14 +181,14 @@ function createCodexAppServerAgentHarness(options) {
|
|
|
119
181
|
});
|
|
120
182
|
},
|
|
121
183
|
compact: async (params) => {
|
|
122
|
-
const { maybeCompactCodexAppServerSession } = await import("./compact-
|
|
184
|
+
const { maybeCompactCodexAppServerSession } = await import("./compact-LspQaGfl.js");
|
|
123
185
|
return maybeCompactCodexAppServerSession(params, {
|
|
124
186
|
bindingStore: options.bindingStore,
|
|
125
187
|
pluginConfig: options?.resolvePluginConfig?.() ?? options?.pluginConfig
|
|
126
188
|
});
|
|
127
189
|
},
|
|
128
190
|
compactAfterContextEngine: async (params) => {
|
|
129
|
-
const { maybeCompactCodexAppServerSession } = await import("./compact-
|
|
191
|
+
const { maybeCompactCodexAppServerSession } = await import("./compact-LspQaGfl.js");
|
|
130
192
|
return maybeCompactCodexAppServerSession(params, {
|
|
131
193
|
bindingStore: options.bindingStore,
|
|
132
194
|
pluginConfig: options?.resolvePluginConfig?.() ?? options?.pluginConfig,
|
|
@@ -135,20 +197,24 @@ function createCodexAppServerAgentHarness(options) {
|
|
|
135
197
|
},
|
|
136
198
|
reset: async (params) => {
|
|
137
199
|
if (params.sessionId) {
|
|
138
|
-
const { reclaimCurrentCodexSessionGeneration, sessionBindingIdentity } = await import("./session-binding-
|
|
200
|
+
const [{ reclaimCurrentCodexSessionGeneration, sessionBindingIdentity }, { retireCodexAppServerSessionGeneration }] = await Promise.all([import("./session-binding-DPxIvMgE.js").then((n) => n.f), import("./session-retirement-DoMMJFKm.js")]);
|
|
139
201
|
const identity = sessionBindingIdentity({
|
|
140
202
|
agentId: params.agentId,
|
|
141
203
|
sessionId: params.sessionId,
|
|
142
204
|
sessionKey: params.sessionKey
|
|
143
205
|
});
|
|
144
|
-
const resetGeneration =
|
|
145
|
-
|
|
206
|
+
const resetGeneration = () => retireCodexAppServerSessionGeneration({
|
|
207
|
+
bindingStore: options.bindingStore,
|
|
208
|
+
identity,
|
|
209
|
+
mode: params.reason === "deleted" ? "retire" : "reset"
|
|
210
|
+
});
|
|
211
|
+
let reset = await resetGeneration();
|
|
146
212
|
if (reset === "conflict") {
|
|
147
213
|
if (await reclaimCurrentCodexSessionGeneration({
|
|
148
214
|
bindingStore: options.bindingStore,
|
|
149
215
|
identity,
|
|
150
216
|
config: options.resolveConfig?.()
|
|
151
|
-
})) reset = await resetGeneration(
|
|
217
|
+
})) reset = await resetGeneration();
|
|
152
218
|
}
|
|
153
219
|
if (reset === "conflict") throw new Error(`Codex binding generation changed before session ${params.sessionId} could reset`);
|
|
154
220
|
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { isRecord } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
2
|
+
import { INLINE_IMAGE_DATA_URL_PREFIX, sanitizeInlineImageDataUrl } from "openclaw/plugin-sdk/inline-image-data-url-runtime";
|
|
3
|
+
//#region extensions/codex/src/app-server/image-payload-sanitizer.ts
|
|
4
|
+
/**
|
|
5
|
+
* Sanitizes inline image payloads mirrored through Codex history so invalid
|
|
6
|
+
* base64 data becomes readable text instead of poisoning replayed transcripts.
|
|
7
|
+
*/
|
|
8
|
+
const IMAGE_OMITTED_TEXT = "omitted image payload: invalid inline image data";
|
|
9
|
+
/** Validates and normalizes an inline image data URL for Codex history payloads. */
|
|
10
|
+
function sanitizeInlineImageDataUrl$1(imageUrl) {
|
|
11
|
+
return sanitizeInlineImageDataUrl(imageUrl);
|
|
12
|
+
}
|
|
13
|
+
/** Builds the replacement text inserted when an inline image payload is invalid. */
|
|
14
|
+
function invalidInlineImageText(label) {
|
|
15
|
+
return `[${label}] ${IMAGE_OMITTED_TEXT}`;
|
|
16
|
+
}
|
|
17
|
+
function sanitizeImageContentRecord(record, label) {
|
|
18
|
+
if (record.type === "image" && typeof record.data === "string") {
|
|
19
|
+
const mimeType = typeof record.mimeType === "string" ? record.mimeType : "image/png";
|
|
20
|
+
const imageUrl = sanitizeInlineImageDataUrl$1(`data:${mimeType};base64,${record.data}`);
|
|
21
|
+
if (!imageUrl) return {
|
|
22
|
+
type: "text",
|
|
23
|
+
text: invalidInlineImageText(label)
|
|
24
|
+
};
|
|
25
|
+
const commaIndex = imageUrl.indexOf(",");
|
|
26
|
+
const mime = imageUrl.slice(INLINE_IMAGE_DATA_URL_PREFIX.length, commaIndex).split(";")[0] ?? mimeType;
|
|
27
|
+
return {
|
|
28
|
+
...record,
|
|
29
|
+
mimeType: mime,
|
|
30
|
+
data: imageUrl.slice(commaIndex + 1)
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
if (record.type === "inputImage" && typeof record.imageUrl === "string") {
|
|
34
|
+
const imageUrl = sanitizeInlineImageDataUrl$1(record.imageUrl);
|
|
35
|
+
return imageUrl ? {
|
|
36
|
+
...record,
|
|
37
|
+
imageUrl
|
|
38
|
+
} : {
|
|
39
|
+
type: "inputText",
|
|
40
|
+
text: invalidInlineImageText(label)
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
if (record.type === "input_image" && typeof record.image_url === "string") {
|
|
44
|
+
const imageUrl = sanitizeInlineImageDataUrl$1(record.image_url);
|
|
45
|
+
return imageUrl ? {
|
|
46
|
+
...record,
|
|
47
|
+
image_url: imageUrl
|
|
48
|
+
} : {
|
|
49
|
+
type: "input_text",
|
|
50
|
+
text: invalidInlineImageText(label)
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
/** Recursively sanitizes all Codex history image shapes while preserving unknown structure. */
|
|
55
|
+
function sanitizeCodexHistoryImagePayloads(value, label) {
|
|
56
|
+
if (Array.isArray(value)) return value.map((entry) => sanitizeCodexHistoryImagePayloads(entry, label));
|
|
57
|
+
if (!isRecord(value)) return value;
|
|
58
|
+
const imageRecord = sanitizeImageContentRecord(value, label);
|
|
59
|
+
if (imageRecord) return imageRecord;
|
|
60
|
+
const next = {};
|
|
61
|
+
for (const [key, child] of Object.entries(value)) next[key] = sanitizeCodexHistoryImagePayloads(child, label);
|
|
62
|
+
return next;
|
|
63
|
+
}
|
|
64
|
+
//#endregion
|
|
65
|
+
export { sanitizeCodexHistoryImagePayloads as n, sanitizeInlineImageDataUrl$1 as r, invalidInlineImageText as t };
|