@openclaw/codex 2026.9.1 → 2026.9.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.
Files changed (67) hide show
  1. package/dist/api.js +6 -6
  2. package/dist/{attempt-client-cleanup-DYHcRQAa.js → attempt-client-cleanup-Bp1ZOnk2.js} +76 -32
  3. package/dist/{attempt-context-DmQUNWwT.js → attempt-context-CSazkWns.js} +6 -6
  4. package/dist/{bounded-turn-wzJrwKKe.js → bounded-turn-DxGJRYbY.js} +46 -45
  5. package/dist/{capabilities-dIjNVCYH.js → capabilities-B1mgvpP8.js} +2 -1
  6. package/dist/cli-metadata.js +1 -1
  7. package/dist/{command-formatters-CLHhEB1Q.js → command-formatters-DSbGMXA0.js} +2 -2
  8. package/dist/{command-handlers-CTGb2csu.js → command-handlers-DOJvGv6-.js} +146 -74
  9. package/dist/{compact-_t0HQrUS.js → compact-Y_xBqrHN.js} +83 -48
  10. package/dist/{config-BhmfC1s6.js → config-CyapYSji.js} +47 -105
  11. package/dist/config-utils-C57JiJrU.js +69 -0
  12. package/dist/doctor-contract-api.js +4 -5
  13. package/dist/{dynamic-tools-BU9tmlYm.js → dynamic-tools-BwpvTxaX.js} +678 -638
  14. package/dist/{effective-mcp-catalog-DzYBW4h1.js → effective-mcp-catalog-CY9Jn4bA.js} +4 -3
  15. package/dist/{event-projector-assistant-message-DHRFXKbS.js → event-projector-assistant-message-B9kp6iGC.js} +11 -2
  16. package/dist/{event-projector-usage-C5mcrGjp.js → event-projector-usage-ZqEVbAEY.js} +30 -13
  17. package/dist/{harness-DXVZ5II5.js → harness-Czh2Sdoc.js} +36 -13
  18. package/dist/harness.js +1 -1
  19. package/dist/{image-payload-sanitizer-CnfoUPCE.js → image-payload-sanitizer-tupAr-2o.js} +29 -15
  20. package/dist/index.js +68 -84
  21. package/dist/{isolated-completion-kg9kv4iH.js → isolated-completion-CRh-51AK.js} +9 -21
  22. package/dist/{managed-binary-4-Vjz5GH.js → managed-binary-DcpnJF9x.js} +105 -73
  23. package/dist/media-understanding-provider.js +1 -1
  24. package/dist/{model-catalog-CUM68Hkl.js → model-catalog-DT5vo6qo.js} +5 -5
  25. package/dist/{models-sYnEc0gd.js → models-CcrgSMQR.js} +4 -4
  26. package/dist/{native-subagent-monitor-CnH147jH.js → native-subagent-monitor-B3bvQGcg.js} +12 -11
  27. package/dist/{node-exec-server.runtime-CstNHCmC.js → node-exec-server.runtime-nfbUOtUB.js} +3 -3
  28. package/dist/{plugin-approval-roundtrip-CNe-Xrjx.js → plugin-approval-roundtrip-aQVdyL5g.js} +1 -1
  29. package/dist/{plugin-marketplace-discovery-CfFlKqDl.js → plugin-marketplace-discovery-B7gHXJ3d.js} +35 -22
  30. package/dist/{plugin-metadata-cache-BFrPhb2c.js → plugin-metadata-cache-BwCLTY_U.js} +5 -5
  31. package/dist/{provider-capabilities-DW5p4k9w.js → provider-capabilities-BpG9Ltc5.js} +2 -2
  32. package/dist/{rate-limits-CawQJfUS.js → rate-limits-Fx_l4eNa.js} +1 -1
  33. package/dist/{request-DYAI5FQE.js → request-C8H22rPi.js} +2 -2
  34. package/dist/{run-attempt-D1hJO4fX.js → run-attempt-BzthFQSM.js} +977 -723
  35. package/dist/{runtime-artifact-C3jVimFn.js → runtime-artifact-Bh_gf6-t.js} +3 -3
  36. package/dist/{session-binding-BHuTCRZQ.js → session-binding-4Ki04sW-.js} +94 -282
  37. package/dist/session-binding-record-CyaXZvTe.js +270 -0
  38. package/dist/{session-catalog-yyvTWFOw.js → session-catalog-B47uwekb.js} +266 -114
  39. package/dist/{session-cli-CmFEXMAM.js → session-cli-BjLhpmS1.js} +1 -1
  40. package/dist/session-history-DWmMqiqW.js +93 -0
  41. package/dist/session-history-read-LHldwvyh.js +36 -0
  42. package/dist/session-history-worker-runtime.js +48 -0
  43. package/dist/{settled-turn-context-D3SNWtUn.js → session-history.worker-zZVcx0ME.js} +30 -31
  44. package/dist/session-history.worker.js +2 -0
  45. package/dist/{session-initialization-BeWzjGiR.js → session-initialization-BCFVnLL4.js} +2 -1
  46. package/dist/{session-permission-policy-DeWVTCMj.js → session-permission-policy-BaueHmSj.js} +1 -1
  47. package/dist/{session-retirement-BujDjXVF.js → session-retirement-DNdmYdFc.js} +7 -7
  48. package/dist/{session-upstream-marker-C351-5Qw.js → session-upstream-marker-DReTpGz6.js} +4 -3
  49. package/dist/settled-turn-context-BOM3Y1pl.js +45 -0
  50. package/dist/{settled-turn-finalizer-BVJx4yoc.js → settled-turn-finalizer-BI-b1sry.js} +53 -42
  51. package/dist/{shared-client-DxcfF9KX.js → shared-client-CKhX2kFt.js} +279 -268
  52. package/dist/{side-question-BTZAII4l.js → side-question-B6DWAw1A.js} +85 -36
  53. package/dist/{thread-lifecycle-DAcEJ_Om.js → thread-lifecycle-DPK30jad.js} +382 -388
  54. package/dist/{thread-ownership-zGokd8i1.js → thread-ownership-CbucAmmp.js} +5 -5
  55. package/dist/thread-policy-CTalhWFy.js +105 -0
  56. package/dist/{thread-resume-C7pyVKeW.js → thread-resume-BLgqkUc1.js} +7 -7
  57. package/dist/{transcript-mirror-DTUxFWa_.js → transcript-mirror-_njEB84z.js} +67 -125
  58. package/dist/transcript-mirror-attestation-Byl34PC-.js +76 -0
  59. package/dist/{transport-stdio-CyPldczm.js → transport-stdio-CzTngV0j.js} +10 -8
  60. package/dist/{upstream-session-fork-CYlBIGVt.js → upstream-session-fork-1fwbNKzQ.js} +85 -165
  61. package/dist/{usage-Bj-rrzkR.js → usage-i9fv5-4m.js} +3 -3
  62. package/dist/{web-search-provider.runtime-D2FWSK4w.js → web-search-provider.runtime-DKQn67A7.js} +3 -3
  63. package/package.json +6 -6
  64. package/dist/binding-connection-E6uDsPlx.js +0 -45
  65. package/dist/launch-args-RXQwn8zV.js +0 -90
  66. package/dist/session-history-C5J1AKzG.js +0 -87
  67. package/dist/thread-policy-g4KbJPzp.js +0 -54
@@ -1,5 +1,6 @@
1
- import { _ as retainSharedCodexAppServerClientByInstanceId } from "./shared-client-DxcfF9KX.js";
2
- import { d as sessionBindingIdentity } from "./session-binding-BHuTCRZQ.js";
1
+ import { l as sessionBindingIdentity } from "./session-binding-record-CyaXZvTe.js";
2
+ import { _ as retainSharedCodexAppServerClientByInstanceId } from "./shared-client-CKhX2kFt.js";
3
+ import "./session-binding-4Ki04sW-.js";
3
4
  import { asOptionalRecord, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
4
5
  import { assignMcpCatalogSafeServerNames } from "openclaw/plugin-sdk/agent-harness-runtime";
5
6
  //#region extensions/codex/src/app-server/effective-mcp-catalog.ts
@@ -95,7 +96,7 @@ async function loadCodexEffectiveMcpCatalogFromThread(params) {
95
96
  }
96
97
  /** Loads MCP inventory from the bound Codex client while retaining its lease through all pages. */
97
98
  async function loadCodexEffectiveMcpCatalog(params, options) {
98
- const binding = await options.bindingStore.read(sessionBindingIdentity({
99
+ const binding = options.bindingStore.read(sessionBindingIdentity({
99
100
  agentId: params.agentId,
100
101
  sessionId: params.sessionId,
101
102
  sessionKey: params.sessionKey,
@@ -33,6 +33,7 @@ function createAttributedCodexAssistantMessage(attribution, text, options) {
33
33
  totalTokens: options.tokenUsage.total ?? (options.tokenUsage.input ?? 0) + (options.tokenUsage.output ?? 0) + (options.tokenUsage.cacheRead ?? 0) + (options.tokenUsage.cacheWrite ?? 0),
34
34
  cost: ZERO_USAGE.cost
35
35
  } : ZERO_USAGE;
36
+ const refusal = options.providerRefusal;
36
37
  return {
37
38
  role: "assistant",
38
39
  content: [{
@@ -43,8 +44,16 @@ function createAttributedCodexAssistantMessage(attribution, text, options) {
43
44
  provider: attribution.provider,
44
45
  model: attribution.modelId,
45
46
  usage,
46
- stopReason: options.aborted ? "aborted" : options.promptError ? "error" : "stop",
47
- errorMessage: options.promptError ? formatErrorMessage(options.promptError) : void 0,
47
+ stopReason: options.aborted ? "aborted" : options.promptError || refusal ? "error" : "stop",
48
+ errorMessage: refusal?.message ?? (options.promptError ? formatErrorMessage(options.promptError) : void 0),
49
+ ...refusal ? { diagnostics: [{
50
+ type: "provider_refusal",
51
+ timestamp: Date.now(),
52
+ details: {
53
+ provider: "openai",
54
+ category: refusal.category
55
+ }
56
+ }] } : {},
48
57
  timestamp: Date.now()
49
58
  };
50
59
  }
@@ -1,4 +1,4 @@
1
- import { $t as isJsonObject } from "./shared-client-DxcfF9KX.js";
1
+ import { B as isJsonObject } from "./config-CyapYSji.js";
2
2
  import { asSafeIntegerInRange, readStringField } from "openclaw/plugin-sdk/string-coerce-runtime";
3
3
  import { normalizeUsage } from "openclaw/plugin-sdk/agent-harness-runtime";
4
4
  //#region extensions/codex/src/app-server/attempt-notifications.ts
@@ -139,11 +139,6 @@ function readCodexThreadContextSnapshot(params) {
139
139
  ...reasoningOutputTokens !== void 0 ? { reasoningOutputTokens } : {}
140
140
  };
141
141
  }
142
- function projectCodexThreadUsageUpdate(params, currentUsage, applyUsage, emitContext) {
143
- applyUsage(readCodexThreadTokenUsage(params) ?? currentUsage);
144
- const context = readCodexThreadContextSnapshot(params);
145
- if (Object.keys(context).length > 0) emitContext(context);
146
- }
147
142
  function normalizeCodexResponseTokenUsage(record) {
148
143
  const totalTokens = readTokenCount(record, "totalTokens");
149
144
  const inputTokens = readTokenCount(record, "inputTokens");
@@ -171,25 +166,47 @@ function normalizeCodexResponseTokenUsage(record) {
171
166
  } : { state: "unavailable" }
172
167
  };
173
168
  }
174
- var CodexResponseCompletionProjection = class {
169
+ var CodexUsageProjection = class {
175
170
  constructor() {
176
171
  this.responseIds = /* @__PURE__ */ new Set();
177
172
  }
173
+ get usage() {
174
+ const usage = this.responseUsage ?? this.threadUsage;
175
+ return usage ? {
176
+ ...usage,
177
+ contextUsage: this.contextUsage
178
+ } : void 0;
179
+ }
178
180
  get modelIterations() {
179
181
  return this.responseIds.size;
180
182
  }
181
- clear() {
182
- this.usage = void 0;
183
+ invalidateContext() {
184
+ this.contextUsage = { state: "unavailable" };
185
+ }
186
+ recordThread(params) {
187
+ const usage = readCodexThreadTokenUsage(params);
188
+ this.threadUsage = usage ?? this.threadUsage;
189
+ if (!this.responseUsage && usage) this.contextUsage = usage.contextUsage;
190
+ return readCodexThreadContextSnapshot(params);
183
191
  }
184
192
  record(params, reportOutputTokens) {
185
193
  const responseId = readStringField(params, "responseId");
186
194
  if (!responseId || this.responseIds.has(responseId)) return;
187
195
  this.responseIds.add(responseId);
188
- const usage = isJsonObject(params.usage) ? params.usage : void 0;
189
- this.usage = usage ? normalizeCodexResponseTokenUsage(usage) : void 0;
190
- const outputTokens = this.usage?.output;
196
+ const usage = isJsonObject(params.usage) ? normalizeCodexResponseTokenUsage(params.usage) : void 0;
197
+ this.contextUsage = usage?.contextUsage ?? { state: "unavailable" };
198
+ this.responseUsage ??= {};
199
+ for (const field of [
200
+ "input",
201
+ "output",
202
+ "cacheRead",
203
+ "cacheWrite",
204
+ "reasoningTokens",
205
+ "total"
206
+ ]) if (usage?.[field] !== void 0) this.responseUsage[field] = (this.responseUsage[field] ?? 0) + usage[field];
207
+ const outputTokens = usage?.output;
191
208
  if (outputTokens !== void 0) reportOutputTokens?.(outputTokens);
192
209
  }
193
210
  };
194
211
  //#endregion
195
- export { codexExecutionToolName as a, isPendingOpenClawDynamicToolCompletionNotification as c, isTerminalTurnStatus as d, readCodexNotificationItem as f, updateActiveTurnItemIds as h, readCodexThreadContextSnapshot as i, isRawFunctionToolOutputCompletionNotification as l, readRawResponseToolCallId as m, normalizeCodexResponseTokenUsage as n, isAssistantCommentaryCompletionNotification as o, readNotificationItemId as p, projectCodexThreadUsageUpdate as r, isCodexTurnAbortMarkerNotification as s, CodexResponseCompletionProjection as t, isRetryableErrorNotification as u };
212
+ export { isCodexTurnAbortMarkerNotification as a, isRetryableErrorNotification as c, readNotificationItemId as d, readRawResponseToolCallId as f, isAssistantCommentaryCompletionNotification as i, isTerminalTurnStatus as l, readCodexThreadContextSnapshot as n, isPendingOpenClawDynamicToolCompletionNotification as o, updateActiveTurnItemIds as p, codexExecutionToolName as r, isRawFunctionToolOutputCompletionNotification as s, CodexUsageProjection as t, readCodexNotificationItem as u };
@@ -1,3 +1,4 @@
1
+ import { l as sessionBindingIdentity, o as readCodexSessionOwnershipBinding } from "./session-binding-record-CyaXZvTe.js";
1
2
  import { resolvePluginConfigObject } from "openclaw/plugin-sdk/plugin-config-runtime";
2
3
  import { runHostPreparedIsolatedCompletion } from "openclaw/plugin-sdk/simple-completion-runtime";
3
4
  import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
@@ -74,10 +75,32 @@ function createCodexAppServerAgentHarness(options) {
74
75
  conversationToolPolicySafeDenyTools: CODEX_TOOL_POLICY_SAFE_DENY_NAMES,
75
76
  deliveryDefaults: { visibleReplies: "message_tool" },
76
77
  authBootstrap: "harness",
78
+ resolveSessionRuntimeOwnership: (params) => {
79
+ const assertCurrent = () => {
80
+ params.assertCurrent();
81
+ if (disposed) throw new Error("Codex agent harness is disposed");
82
+ };
83
+ assertCurrent();
84
+ const binding = readCodexSessionOwnershipBinding({
85
+ bindingStore: options.bindingStore,
86
+ identity: sessionBindingIdentity(params),
87
+ config: params.config,
88
+ storePath: params.storePath
89
+ });
90
+ assertCurrent();
91
+ return binding?.preserveNativeModel === true ? {
92
+ model: "native",
93
+ auth: binding.connectionScope === "supervision" ? "native" : "host",
94
+ ...binding.model?.trim() && binding.modelProvider ? { modelRef: {
95
+ provider: binding.modelProvider,
96
+ model: binding.model
97
+ } } : {}
98
+ } : void 0;
99
+ },
77
100
  ...sessionCatalogControlFactory && sessionRuntime ? { sessionFork: {
78
101
  upstreamKinds: ["codex-app-server"],
79
102
  fork: async (params) => {
80
- const { forkCodexUpstreamSession } = await import("./upstream-session-fork-CYlBIGVt.js");
103
+ const { forkCodexUpstreamSession } = await import("./upstream-session-fork-1fwbNKzQ.js");
81
104
  return await forkCodexUpstreamSession(params, {
82
105
  bindingStore: options.bindingStore,
83
106
  controlFactory: sessionCatalogControlFactory,
@@ -92,22 +115,22 @@ function createCodexAppServerAgentHarness(options) {
92
115
  return fingerprintCodexAppServerAuthBinding(params);
93
116
  } },
94
117
  runtimeArtifact: { validate: async (binding) => {
95
- const { validateCodexAppServerRuntimeArtifact } = await import("./runtime-artifact-C3jVimFn.js");
118
+ const { validateCodexAppServerRuntimeArtifact } = await import("./runtime-artifact-Bh_gf6-t.js");
96
119
  return validateCodexAppServerRuntimeArtifact(binding);
97
120
  } },
98
121
  fetchUsageSnapshot: async (ctx) => {
99
- const { fetchCodexAppServerUsageSnapshot } = await import("./usage-Bj-rrzkR.js");
122
+ const { fetchCodexAppServerUsageSnapshot } = await import("./usage-i9fv5-4m.js");
100
123
  return await fetchCodexAppServerUsageSnapshot(ctx, { pluginConfig: options?.resolvePluginConfig?.() ?? options?.pluginConfig });
101
124
  },
102
125
  loadModelCatalog: async (params) => {
103
- const { createCodexAppServerModelCatalog } = await import("./model-catalog-CUM68Hkl.js");
126
+ const { createCodexAppServerModelCatalog } = await import("./model-catalog-DT5vo6qo.js");
104
127
  if (disposed) return [];
105
128
  modelCatalog ??= createCodexAppServerModelCatalog(harnessRuntimeId);
106
129
  return await modelCatalog.load(params, resolveAttemptPluginConfig(params.config));
107
130
  },
108
131
  readModelCatalogReadiness: (params) => modelCatalog?.read(params, resolveAttemptPluginConfig(params.config)),
109
132
  loadMcpToolCatalog: async (params) => {
110
- const { loadCodexEffectiveMcpCatalog } = await import("./effective-mcp-catalog-DzYBW4h1.js");
133
+ const { loadCodexEffectiveMcpCatalog } = await import("./effective-mcp-catalog-CY9Jn4bA.js");
111
134
  return await loadCodexEffectiveMcpCatalog(params, { bindingStore: options.bindingStore });
112
135
  },
113
136
  supports: (ctx) => {
@@ -150,7 +173,7 @@ function createCodexAppServerAgentHarness(options) {
150
173
  };
151
174
  },
152
175
  runAttempt: async (params) => {
153
- const { runCodexAppServerAttempt } = await import("./run-attempt-D1hJO4fX.js");
176
+ const { runCodexAppServerAttempt } = await import("./run-attempt-BzthFQSM.js");
154
177
  return runCodexAppServerAttempt(params, {
155
178
  bindingStore: options.bindingStore,
156
179
  pluginConfig: resolveAttemptPluginConfig(params.config),
@@ -161,7 +184,7 @@ function createCodexAppServerAgentHarness(options) {
161
184
  },
162
185
  runIsolatedCompletionV2: async (params) => {
163
186
  if (params.authorization.owner === "host") return runHostPreparedIsolatedCompletion(params);
164
- const { runCodexIsolatedCompletion } = await import("./isolated-completion-kg9kv4iH.js");
187
+ const { runCodexIsolatedCompletion } = await import("./isolated-completion-CRh-51AK.js");
165
188
  return runCodexIsolatedCompletion(params, { pluginConfig: options?.resolvePluginConfig?.() ?? options?.pluginConfig });
166
189
  },
167
190
  runIsolatedCompletion: async (params) => {
@@ -176,11 +199,11 @@ function createCodexAppServerAgentHarness(options) {
176
199
  });
177
200
  },
178
201
  finalizeSettledTurn: async (params) => {
179
- const { runCodexSettledTurnFinalization } = await import("./settled-turn-finalizer-BVJx4yoc.js");
202
+ const { runCodexSettledTurnFinalization } = await import("./settled-turn-finalizer-BI-b1sry.js");
180
203
  return runCodexSettledTurnFinalization(params, { pluginConfig: options?.resolvePluginConfig?.() ?? options?.pluginConfig });
181
204
  },
182
205
  runSideQuestion: async (params) => {
183
- const { runCodexAppServerSideQuestion } = await import("./side-question-BTZAII4l.js");
206
+ const { runCodexAppServerSideQuestion } = await import("./side-question-B6DWAw1A.js");
184
207
  return runCodexAppServerSideQuestion(params, {
185
208
  bindingStore: options.bindingStore,
186
209
  pluginConfig: options?.resolvePluginConfig?.() ?? options?.pluginConfig,
@@ -190,20 +213,20 @@ function createCodexAppServerAgentHarness(options) {
190
213
  });
191
214
  },
192
215
  compact: async (params) => {
193
- const { maybeCompactCodexAppServerSession } = await import("./compact-_t0HQrUS.js");
216
+ const { maybeCompactCodexAppServerSession } = await import("./compact-Y_xBqrHN.js");
194
217
  return maybeCompactCodexAppServerSession(params, {
195
218
  bindingStore: options.bindingStore,
196
219
  pluginConfig: options?.resolvePluginConfig?.() ?? options?.pluginConfig
197
220
  });
198
221
  },
199
222
  withSessionDeletion: async (params, run) => {
200
- const { withCodexAppServerSessionDeletion } = await import("./session-retirement-BujDjXVF.js");
223
+ const { withCodexAppServerSessionDeletion } = await import("./session-retirement-DNdmYdFc.js");
201
224
  params.assertCurrent();
202
225
  return withCodexAppServerSessionDeletion(options.bindingStore, params, run);
203
226
  },
204
227
  reset: async (params) => {
205
228
  if (params.sessionId && params.reason !== "deleted") {
206
- const [{ reclaimCurrentCodexSessionGeneration, sessionBindingIdentity }, { retireCodexAppServerSessionGeneration }] = await Promise.all([import("./session-binding-BHuTCRZQ.js").then((n) => n.f), import("./session-retirement-BujDjXVF.js")]);
229
+ const [{ reclaimCurrentCodexSessionGeneration }, { retireCodexAppServerSessionGeneration }] = await Promise.all([import("./session-binding-4Ki04sW-.js").then((n) => n.d), import("./session-retirement-DNdmYdFc.js")]);
207
230
  const identity = sessionBindingIdentity({
208
231
  agentId: params.agentId,
209
232
  sessionId: params.sessionId,
@@ -235,7 +258,7 @@ function createCodexAppServerAgentHarness(options) {
235
258
  /** Creates the private native-compaction bridge registered in host-owned capability state. */
236
259
  function createCodexAppServerNativeCompaction(options) {
237
260
  return async (params) => {
238
- const { maybeCompactCodexAppServerSession } = await import("./compact-_t0HQrUS.js");
261
+ const { maybeCompactCodexAppServerSession } = await import("./compact-Y_xBqrHN.js");
239
262
  return maybeCompactCodexAppServerSession(params, {
240
263
  bindingStore: options.bindingStore,
241
264
  pluginConfig: options.resolvePluginConfig?.() ?? options.pluginConfig,
package/dist/harness.js CHANGED
@@ -1,2 +1,2 @@
1
- import { n as createCodexAppServerNativeCompaction, t as createCodexAppServerAgentHarness } from "./harness-DXVZ5II5.js";
1
+ import { n as createCodexAppServerNativeCompaction, t as createCodexAppServerAgentHarness } from "./harness-Czh2Sdoc.js";
2
2
  export { createCodexAppServerAgentHarness, createCodexAppServerNativeCompaction };
@@ -24,42 +24,56 @@ function sanitizeImageContentRecord(record, label) {
24
24
  };
25
25
  const commaIndex = imageUrl.indexOf(",");
26
26
  const mime = imageUrl.slice(INLINE_IMAGE_DATA_URL_PREFIX.length, commaIndex).split(";")[0] ?? mimeType;
27
- return {
27
+ const data = imageUrl.slice(commaIndex + 1);
28
+ return mime === record.mimeType && data === record.data ? record : {
28
29
  ...record,
29
30
  mimeType: mime,
30
- data: imageUrl.slice(commaIndex + 1)
31
+ data
31
32
  };
32
33
  }
33
34
  if (record.type === "inputImage" && typeof record.imageUrl === "string") {
34
35
  const imageUrl = sanitizeInlineImageDataUrl$1(record.imageUrl);
35
- return imageUrl ? {
36
- ...record,
37
- imageUrl
38
- } : {
36
+ if (!imageUrl) return {
39
37
  type: "inputText",
40
38
  text: invalidInlineImageText(label)
41
39
  };
40
+ return imageUrl === record.imageUrl ? record : {
41
+ ...record,
42
+ imageUrl
43
+ };
42
44
  }
43
45
  if (record.type === "input_image" && typeof record.image_url === "string") {
44
46
  const imageUrl = sanitizeInlineImageDataUrl$1(record.image_url);
45
- return imageUrl ? {
46
- ...record,
47
- image_url: imageUrl
48
- } : {
47
+ if (!imageUrl) return {
49
48
  type: "input_text",
50
49
  text: invalidInlineImageText(label)
51
50
  };
51
+ return imageUrl === record.image_url ? record : {
52
+ ...record,
53
+ image_url: imageUrl
54
+ };
52
55
  }
53
56
  }
54
- /** Recursively sanitizes all Codex history image shapes while preserving unknown structure. */
57
+ /** Sanitizes images without copying unchanged history or mutating its owned snapshot. */
55
58
  function sanitizeCodexHistoryImagePayloads(value, label) {
56
- if (Array.isArray(value)) return value.map((entry) => sanitizeCodexHistoryImagePayloads(entry, label));
59
+ if (Array.isArray(value)) {
60
+ let next;
61
+ for (let index = 0; index < value.length; index++) {
62
+ const child = sanitizeCodexHistoryImagePayloads(value[index], label);
63
+ if (child !== value[index]) (next ??= value.slice())[index] = child;
64
+ }
65
+ return next ?? value;
66
+ }
57
67
  if (!isRecord(value)) return value;
58
68
  const imageRecord = sanitizeImageContentRecord(value, label);
59
69
  if (imageRecord) return imageRecord;
60
- const next = {};
61
- for (const [key, child] of Object.entries(value)) next[key] = sanitizeCodexHistoryImagePayloads(child, label);
62
- return next;
70
+ let next;
71
+ for (const key in value) {
72
+ if (!Object.hasOwn(value, key)) continue;
73
+ const child = sanitizeCodexHistoryImagePayloads(value[key], label);
74
+ if (child !== value[key]) (next ??= { ...value })[key] = child;
75
+ }
76
+ return next ?? value;
63
77
  }
64
78
  //#endregion
65
79
  export { sanitizeCodexHistoryImagePayloads as n, sanitizeInlineImageDataUrl$1 as r, invalidInlineImageText as t };