@openclaw/codex 2026.9.1-beta.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 (81) hide show
  1. package/dist/api.js +8 -9
  2. package/dist/{attempt-client-cleanup-bfsmcQ6m.js → attempt-client-cleanup-Bp1ZOnk2.js} +105 -75
  3. package/dist/attempt-context-CSazkWns.js +634 -0
  4. package/dist/{auth-binding-B4FfbcCg.js → auth-binding-Ds_QVm-X.js} +18 -3
  5. package/dist/{bounded-turn-B7iBUcuP.js → bounded-turn-DxGJRYbY.js} +53 -57
  6. package/dist/{capabilities-BRMh0aIq.js → capabilities-B1mgvpP8.js} +2 -1
  7. package/dist/cli-metadata.js +1 -1
  8. package/dist/{command-formatters-DEsIufkt.js → command-formatters-DSbGMXA0.js} +5 -4
  9. package/dist/{command-handlers-D_-1_qRp.js → command-handlers-DOJvGv6-.js} +243 -148
  10. package/dist/{compact-BglNFZrQ.js → compact-Y_xBqrHN.js} +109 -65
  11. package/dist/{config-giW8X0QA.js → config-CyapYSji.js} +328 -374
  12. package/dist/config-utils-C57JiJrU.js +69 -0
  13. package/dist/{context-compaction-activity-BOeJf7yo.js → context-compaction-activity-CMla5FPJ.js} +4 -1
  14. package/dist/{conversation-binding-data-CW2GuupV.js → conversation-binding-data-BiodpIzq.js} +2 -1
  15. package/dist/doctor-contract-api.js +144 -14
  16. package/dist/{dynamic-tools-Dnlfa--w.js → dynamic-tools-BwpvTxaX.js} +1119 -1135
  17. package/dist/{effective-mcp-catalog-CTeGrnfO.js → effective-mcp-catalog-CY9Jn4bA.js} +4 -3
  18. package/dist/{event-projector-assistant-message-C5-Ds8mA.js → event-projector-assistant-message-B9kp6iGC.js} +15 -6
  19. package/dist/event-projector-usage-ZqEVbAEY.js +212 -0
  20. package/dist/{harness-Csz0F-DK.js → harness-Czh2Sdoc.js} +65 -52
  21. package/dist/harness.js +1 -1
  22. package/dist/{image-payload-sanitizer-CnfoUPCE.js → image-payload-sanitizer-tupAr-2o.js} +29 -15
  23. package/dist/index.js +495 -457
  24. package/dist/{isolated-completion-Cv6FqygM.js → isolated-completion-CRh-51AK.js} +9 -21
  25. package/dist/{managed-binary-DFYK4DWq.js → managed-binary-DcpnJF9x.js} +117 -80
  26. package/dist/media-understanding-provider.js +1 -1
  27. package/dist/model-catalog-DT5vo6qo.js +101 -0
  28. package/dist/{models-TS3HBU-q.js → models-CcrgSMQR.js} +26 -29
  29. package/dist/{native-subagent-monitor-4Mfq2HDs.js → native-subagent-monitor-B3bvQGcg.js} +63 -122
  30. package/dist/{node-exec-server.runtime-BpWqJO1V.js → node-exec-server.runtime-nfbUOtUB.js} +10 -7
  31. package/dist/{plugin-approval-roundtrip-bUm777tR.js → plugin-approval-roundtrip-aQVdyL5g.js} +30 -3
  32. package/dist/{plugin-marketplace-discovery-B9DvaAG-.js → plugin-marketplace-discovery-B7gHXJ3d.js} +44 -30
  33. package/dist/{plugin-metadata-cache-CTCT3w5L.js → plugin-metadata-cache-BwCLTY_U.js} +6 -6
  34. package/dist/provider-capabilities-BpG9Ltc5.js +101 -0
  35. package/dist/{rate-limits-C5_D8Gmb.js → rate-limits-Fx_l4eNa.js} +3 -2
  36. package/dist/{sandbox-guard-kuWTn9C5.js → request-C8H22rPi.js} +195 -2
  37. package/dist/{run-attempt-DYc0QCBF.js → run-attempt-BzthFQSM.js} +1616 -2634
  38. package/dist/{runtime-artifact-BvyT1uyd.js → runtime-artifact-Bh_gf6-t.js} +22 -15
  39. package/dist/{session-binding-Bcynfd-_.js → session-binding-4Ki04sW-.js} +282 -399
  40. package/dist/session-binding-record-CyaXZvTe.js +270 -0
  41. package/dist/{session-catalog-DaLKVtpH.js → session-catalog-B47uwekb.js} +812 -504
  42. package/dist/{session-cli-DMc4oS2w.js → session-cli-BjLhpmS1.js} +1 -1
  43. package/dist/session-history-DWmMqiqW.js +93 -0
  44. package/dist/session-history-read-LHldwvyh.js +36 -0
  45. package/dist/session-history-worker-runtime.js +48 -0
  46. package/dist/session-history.worker-zZVcx0ME.js +267 -0
  47. package/dist/session-history.worker.js +2 -0
  48. package/dist/session-initialization-BCFVnLL4.js +75 -0
  49. package/dist/{session-permission-policy-BrNH1bjy.js → session-permission-policy-BaueHmSj.js} +2 -2
  50. package/dist/session-retirement-DNdmYdFc.js +97 -0
  51. package/dist/{session-upstream-marker-BIkusb95.js → session-upstream-marker-DReTpGz6.js} +20 -4
  52. package/dist/settled-turn-context-BOM3Y1pl.js +45 -0
  53. package/dist/settled-turn-finalizer-BI-b1sry.js +115 -0
  54. package/dist/{shared-client-DKz23hHY.js → shared-client-CKhX2kFt.js} +3659 -847
  55. package/dist/{side-question-DjA_jsNe.js → side-question-B6DWAw1A.js} +168 -81
  56. package/dist/{thread-lifecycle-L7oEkTlq.js → thread-lifecycle-DPK30jad.js} +2412 -2145
  57. package/dist/{thread-ownership-DZeuKH1j.js → thread-ownership-CbucAmmp.js} +27 -16
  58. package/dist/thread-policy-CTalhWFy.js +105 -0
  59. package/dist/{plugin-app-cache-key-C1CAdfcP.js → thread-resume-BLgqkUc1.js} +61 -9
  60. package/dist/{transcript-mirror-DsCMWBca.js → transcript-mirror-_njEB84z.js} +114 -110
  61. package/dist/transcript-mirror-attestation-Byl34PC-.js +76 -0
  62. package/dist/transport-stdio-CzTngV0j.js +728 -0
  63. package/dist/{upstream-prompt-provenance-CFmsKwr9.js → upstream-prompt-provenance-LphB8slG.js} +8 -4
  64. package/dist/upstream-session-fork-1fwbNKzQ.js +886 -0
  65. package/dist/{usage-ROIaW3wo.js → usage-i9fv5-4m.js} +3 -3
  66. package/dist/{web-search-provider.runtime-ClaNPV7N.js → web-search-provider.runtime-DKQn67A7.js} +3 -3
  67. package/openclaw.plugin.json +1 -30
  68. package/package.json +6 -6
  69. package/dist/binding-connection-BMvPX73o.js +0 -45
  70. package/dist/command-rpc-CCeCkf_v.js +0 -90
  71. package/dist/event-projector-usage-Bk1I90Bg.js +0 -328
  72. package/dist/incognito-session-ET_ufDH-.js +0 -2
  73. package/dist/model-catalog-i9rNBthX.js +0 -48
  74. package/dist/protocol-validators-VeJxxJ0U.js +0 -2421
  75. package/dist/request-DXXGHko0.js +0 -157
  76. package/dist/session-catalog-home-id-BNwAJ9D7.js +0 -18
  77. package/dist/session-retirement-CcNC3YSY.js +0 -36
  78. package/dist/settled-turn-finalizer-Dc3ApjU4.js +0 -328
  79. package/dist/thread-resume-BE9qNEW0.js +0 -30
  80. package/dist/transport-stdio-DhoGy33Z.js +0 -99
  81. package/dist/upstream-session-fork-DlaHxSLC.js +0 -326
@@ -1,5 +1,6 @@
1
- import { h as retainSharedCodexAppServerClientByInstanceId } from "./shared-client-DKz23hHY.js";
2
- import { d as sessionBindingIdentity } from "./session-binding-Bcynfd-_.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
  }
@@ -86,13 +95,13 @@ function createAssistantAsyncMessage(params, text, itemId, timestamp) {
86
95
  openclawAsyncDelivery: { itemId }
87
96
  };
88
97
  }
89
- function createAssistantMirrorMessage(params, title, text) {
98
+ function createAssistantReasoningMessage(params, text) {
90
99
  const attribution = resolveCodexLocalRuntimeAttribution(params);
91
100
  return {
92
101
  role: "assistant",
93
102
  content: [{
94
- type: "text",
95
- text: `${title}:\n${text}`
103
+ type: "thinking",
104
+ thinking: text
96
105
  }],
97
106
  api: attribution.api ?? "openai-chatgpt-responses",
98
107
  provider: attribution.provider,
@@ -103,4 +112,4 @@ function createAssistantMirrorMessage(params, title, text) {
103
112
  };
104
113
  }
105
114
  //#endregion
106
- export { createAttributedCodexAssistantMessage as a, createAssistantMirrorMessage as i, createAssistantCommentaryMessage as n, createAssistantMessage as r, createAssistantAsyncMessage as t };
115
+ export { createAttributedCodexAssistantMessage as a, createAssistantReasoningMessage as i, createAssistantCommentaryMessage as n, createAssistantMessage as r, createAssistantAsyncMessage as t };
@@ -0,0 +1,212 @@
1
+ import { B as isJsonObject } from "./config-CyapYSji.js";
2
+ import { asSafeIntegerInRange, readStringField } from "openclaw/plugin-sdk/string-coerce-runtime";
3
+ import { normalizeUsage } from "openclaw/plugin-sdk/agent-harness-runtime";
4
+ //#region extensions/codex/src/app-server/attempt-notifications.ts
5
+ const CODEX_TURN_ABORT_MARKER_START = "<turn_aborted>";
6
+ const CODEX_TURN_ABORT_MARKER_END = "</turn_aborted>";
7
+ /** Tracks actual native items for explicit terminal-tool batching. */
8
+ function updateActiveTurnItemIds(notification, activeItemIds) {
9
+ if (notification.method !== "item/started" && notification.method !== "item/completed") return;
10
+ const itemId = readNotificationItemId(notification);
11
+ if (!itemId) return;
12
+ if (notification.method === "item/started") {
13
+ activeItemIds.add(itemId);
14
+ return;
15
+ }
16
+ activeItemIds.delete(itemId);
17
+ }
18
+ /** Reads an item id from supported notification envelope shapes. */
19
+ function readNotificationItemId(notification) {
20
+ if (!isJsonObject(notification.params)) return;
21
+ const item = isJsonObject(notification.params.item) ? notification.params.item : void 0;
22
+ return (item ? readStringField(item, "id") : void 0) ?? readStringField(notification.params, "itemId") ?? readStringField(notification.params, "id");
23
+ }
24
+ /** Detects completion for an OpenClaw dynamic tool result still awaited by Codex. */
25
+ function isPendingOpenClawDynamicToolCompletionNotification(notification, pendingOpenClawDynamicToolCompletionIds) {
26
+ if (notification.method !== "item/completed" || !isJsonObject(notification.params)) return false;
27
+ const itemId = readNotificationItemId(notification);
28
+ if (!itemId || !pendingOpenClawDynamicToolCompletionIds.has(itemId)) return false;
29
+ const item = isJsonObject(notification.params.item) ? notification.params.item : void 0;
30
+ const itemType = item ? readStringField(item, "type") : void 0;
31
+ return itemType === void 0 || itemType === "dynamicToolCall";
32
+ }
33
+ function isRawFunctionToolOutputCompletionNotification(notification) {
34
+ if (notification.method !== "rawResponseItem/completed" || !isJsonObject(notification.params)) return false;
35
+ const item = isJsonObject(notification.params.item) ? notification.params.item : void 0;
36
+ return item ? readStringField(item, "type") === "function_call_output" : false;
37
+ }
38
+ /** Distinguishes progress-only assistant items from conversation answers. */
39
+ function isAssistantCommentaryCompletionNotification(notification) {
40
+ if (!isJsonObject(notification.params) || notification.method !== "item/completed") return false;
41
+ const item = isJsonObject(notification.params.item) ? notification.params.item : void 0;
42
+ return Boolean(item && readStringField(item, "type") === "agentMessage" && (readStringField(item, "phase") === "commentary" || readStringField(item, "delivery") === "async"));
43
+ }
44
+ /** A retryable native error is not a terminal outcome for bounded operations. */
45
+ function isRetryableErrorNotification(value) {
46
+ return isJsonObject(value) && value.willRetry === true;
47
+ }
48
+ /** Returns true for terminal app-server thread status strings. */
49
+ function isTerminalTurnStatus(status) {
50
+ return status === "completed" || status === "interrupted" || status === "failed";
51
+ }
52
+ /** Detects Codex's interrupted-turn marker, not user-authored copies of it. */
53
+ function isCodexTurnAbortMarkerNotification(notification, options = {}) {
54
+ if (notification.method !== "rawResponseItem/completed" || !isJsonObject(notification.params)) return false;
55
+ const item = notification.params.item;
56
+ const role = isJsonObject(item) ? readStringField(item, "role") : void 0;
57
+ if (!isJsonObject(item) || readStringField(item, "type") !== "message" || role !== "user" && role !== "developer") return false;
58
+ const text = extractRawResponseItemText(item).trim();
59
+ const currentPromptTexts = [options.currentPromptText, ...options.currentPromptTexts ?? []].filter(isNonEmptyString).map((prompt) => prompt.trim());
60
+ if (role === "user" && currentPromptTexts.includes(text)) return false;
61
+ return readCodexTurnAbortMarkerBody(text) !== void 0;
62
+ }
63
+ function readCodexTurnAbortMarkerBody(text) {
64
+ if (!text.startsWith(CODEX_TURN_ABORT_MARKER_START) || !text.endsWith(CODEX_TURN_ABORT_MARKER_END)) return;
65
+ return text.slice(14, -15).trim();
66
+ }
67
+ function extractRawResponseItemText(item) {
68
+ const content = item.content;
69
+ if (!Array.isArray(content)) return "";
70
+ return content.flatMap((entry) => {
71
+ if (!isJsonObject(entry)) return [];
72
+ const type = readStringField(entry, "type");
73
+ if (type !== "input_text" && type !== "text") return [];
74
+ const text = readStringField(entry, "text");
75
+ return text ? [text] : [];
76
+ }).join("");
77
+ }
78
+ /** Reads a typed Codex item from notification params when id/type are present. */
79
+ function readCodexNotificationItem(params) {
80
+ if (!isJsonObject(params) || !isJsonObject(params.item)) return;
81
+ const item = params.item;
82
+ return typeof item.id === "string" && typeof item.type === "string" ? item : void 0;
83
+ }
84
+ /** Reads the stable call id from a model-emitted raw tool item. */
85
+ function readRawResponseToolCallId(notification) {
86
+ if (notification.method !== "rawResponseItem/completed" || !isJsonObject(notification.params)) return;
87
+ const item = isJsonObject(notification.params.item) ? notification.params.item : void 0;
88
+ if (!item) return;
89
+ switch (readStringField(item, "type")) {
90
+ case "custom_tool_call":
91
+ case "function_call":
92
+ case "local_shell_call":
93
+ case "tool_search_call": return readStringField(item, "call_id");
94
+ case "image_generation_call":
95
+ case "web_search_call": return readStringField(item, "id");
96
+ default: return;
97
+ }
98
+ }
99
+ /** Maps Codex item types to the tool name shown in execution progress. */
100
+ function codexExecutionToolName(item) {
101
+ if (item.type === "dynamicToolCall" && typeof item.tool === "string") return item.tool;
102
+ if (item.type === "mcpToolCall" && typeof item.tool === "string") {
103
+ const server = typeof item.server === "string" && item.server ? item.server : void 0;
104
+ return server ? `${server}.${item.tool}` : item.tool;
105
+ }
106
+ if (item.type === "commandExecution") return "bash";
107
+ if (item.type === "fileChange") return "apply_patch";
108
+ if (item.type === "webSearch") return "web_search";
109
+ }
110
+ function isNonEmptyString(value) {
111
+ return typeof value === "string" && value.length > 0;
112
+ }
113
+ //#endregion
114
+ //#region extensions/codex/src/app-server/event-projector-usage.ts
115
+ function readTokenCount(record, key) {
116
+ return asSafeIntegerInRange(record[key], { min: 0 });
117
+ }
118
+ function readCodexThreadTokenUsage(params) {
119
+ const tokenUsage = isJsonObject(params.tokenUsage) ? params.tokenUsage : void 0;
120
+ const last = tokenUsage && isJsonObject(tokenUsage.last) ? tokenUsage.last : void 0;
121
+ return last ? normalizeCodexResponseTokenUsage(last) : void 0;
122
+ }
123
+ function readCodexThreadContextSnapshot(params) {
124
+ const tokenUsage = isJsonObject(params.tokenUsage) ? params.tokenUsage : void 0;
125
+ const last = tokenUsage && isJsonObject(tokenUsage.last) ? tokenUsage.last : void 0;
126
+ const modelContextWindow = tokenUsage ? readTokenCount(tokenUsage, "modelContextWindow") : void 0;
127
+ const activeContextTokens = last ? readTokenCount(last, "totalTokens") : void 0;
128
+ const inputTokens = last ? readTokenCount(last, "inputTokens") : void 0;
129
+ const cachedInputTokens = last ? readTokenCount(last, "cachedInputTokens") : void 0;
130
+ const cacheWriteInputTokens = last ? readTokenCount(last, "cacheWriteInputTokens") : void 0;
131
+ const reasoningOutputTokens = last ? readTokenCount(last, "reasoningOutputTokens") : void 0;
132
+ return {
133
+ ...activeContextTokens !== void 0 ? { activeContextTokens } : {},
134
+ ...cachedInputTokens !== void 0 ? { cachedInputTokens } : {},
135
+ ...cacheWriteInputTokens !== void 0 ? { cacheWriteInputTokens } : {},
136
+ ...inputTokens !== void 0 ? { inputTokens } : {},
137
+ ...modelContextWindow && modelContextWindow > 0 ? { modelContextWindow } : {},
138
+ ...inputTokens !== void 0 ? { promptTokens: inputTokens } : {},
139
+ ...reasoningOutputTokens !== void 0 ? { reasoningOutputTokens } : {}
140
+ };
141
+ }
142
+ function normalizeCodexResponseTokenUsage(record) {
143
+ const totalTokens = readTokenCount(record, "totalTokens");
144
+ const inputTokens = readTokenCount(record, "inputTokens");
145
+ const cacheRead = readTokenCount(record, "cachedInputTokens");
146
+ const output = readTokenCount(record, "outputTokens");
147
+ const reasoningTokens = readTokenCount(record, "reasoningOutputTokens");
148
+ const cacheWrite = record.cacheWriteInputTokens === void 0 ? 0 : readTokenCount(record, "cacheWriteInputTokens");
149
+ const hasCoherentInput = inputTokens !== void 0 && cacheRead !== void 0 && cacheWrite !== void 0 && cacheRead + cacheWrite <= inputTokens;
150
+ const hasCoherentContext = hasCoherentInput && totalTokens !== void 0 && output !== void 0 && totalTokens === inputTokens + output;
151
+ const usage = normalizeUsage({
152
+ input: hasCoherentInput ? inputTokens - cacheRead - cacheWrite : void 0,
153
+ output,
154
+ cacheRead,
155
+ cacheWrite,
156
+ reasoningTokens,
157
+ total: totalTokens
158
+ });
159
+ if (!usage) return;
160
+ return {
161
+ ...usage,
162
+ contextUsage: hasCoherentContext ? {
163
+ state: "available",
164
+ promptTokens: inputTokens,
165
+ totalTokens
166
+ } : { state: "unavailable" }
167
+ };
168
+ }
169
+ var CodexUsageProjection = class {
170
+ constructor() {
171
+ this.responseIds = /* @__PURE__ */ new Set();
172
+ }
173
+ get usage() {
174
+ const usage = this.responseUsage ?? this.threadUsage;
175
+ return usage ? {
176
+ ...usage,
177
+ contextUsage: this.contextUsage
178
+ } : void 0;
179
+ }
180
+ get modelIterations() {
181
+ return this.responseIds.size;
182
+ }
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);
191
+ }
192
+ record(params, reportOutputTokens) {
193
+ const responseId = readStringField(params, "responseId");
194
+ if (!responseId || this.responseIds.has(responseId)) return;
195
+ this.responseIds.add(responseId);
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;
208
+ if (outputTokens !== void 0) reportOutputTokens?.(outputTokens);
209
+ }
210
+ };
211
+ //#endregion
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,5 +1,6 @@
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
- import { completeWithPreparedSimpleCompletionModel } from "openclaw/plugin-sdk/simple-completion-runtime";
3
+ import { runHostPreparedIsolatedCompletion } from "openclaw/plugin-sdk/simple-completion-runtime";
3
4
  import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
4
5
  //#region extensions/codex/src/app-server/model-runtime.ts
5
6
  const CODEX_APP_SERVER_RUNTIME_MODEL_PARAM = "codexAppServerRuntimeModel";
@@ -40,30 +41,6 @@ const CODEX_APP_SERVER_CONTEXT_ENGINE_HOST_CAPABILITIES = [
40
41
  "runtime-llm-complete",
41
42
  "thread-bootstrap-projection"
42
43
  ];
43
- async function runCodexHostPreparedIsolatedCompletion(params) {
44
- const timeoutSignal = AbortSignal.timeout(params.timeoutMs);
45
- const signal = params.abortSignal ? AbortSignal.any([params.abortSignal, timeoutSignal]) : timeoutSignal;
46
- return { assistant: await completeWithPreparedSimpleCompletionModel({
47
- model: params.model,
48
- auth: params.auth,
49
- cfg: params.config,
50
- context: {
51
- systemPrompt: params.systemPrompt,
52
- messages: [{
53
- role: "user",
54
- content: params.prompt,
55
- timestamp: Date.now()
56
- }],
57
- tools: []
58
- },
59
- options: {
60
- maxTokens: params.streamParams?.maxTokens,
61
- temperature: params.streamParams?.temperature,
62
- reasoning: params.thinkLevel,
63
- signal
64
- }
65
- }) };
66
- }
67
44
  async function disposeSharedCodexAppServerClients() {
68
45
  const dispose = globalThis[SHARED_CODEX_APP_SERVER_CLIENT_DISPOSER];
69
46
  await dispose?.();
@@ -78,6 +55,8 @@ function createCodexAppServerAgentHarness(options) {
78
55
  const providerIds = new Set([...options?.providerIds ?? DEFAULT_CODEX_HARNESS_PROVIDER_IDS].map((id) => id.trim().toLowerCase()));
79
56
  const sessionCatalogControlFactory = options.sessionCatalogControlFactory;
80
57
  const sessionRuntime = options.runtime;
58
+ let modelCatalog;
59
+ let disposed = false;
81
60
  const resolveAttemptPluginConfig = (config) => resolvePluginConfigObject(config, "codex") ?? options.resolvePluginConfig?.() ?? options.pluginConfig;
82
61
  return {
83
62
  id: harnessRuntimeId,
@@ -96,10 +75,32 @@ function createCodexAppServerAgentHarness(options) {
96
75
  conversationToolPolicySafeDenyTools: CODEX_TOOL_POLICY_SAFE_DENY_NAMES,
97
76
  deliveryDefaults: { visibleReplies: "message_tool" },
98
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
+ },
99
100
  ...sessionCatalogControlFactory && sessionRuntime ? { sessionFork: {
100
101
  upstreamKinds: ["codex-app-server"],
101
102
  fork: async (params) => {
102
- const { forkCodexUpstreamSession } = await import("./upstream-session-fork-DlaHxSLC.js");
103
+ const { forkCodexUpstreamSession } = await import("./upstream-session-fork-1fwbNKzQ.js");
103
104
  return await forkCodexUpstreamSession(params, {
104
105
  bindingStore: options.bindingStore,
105
106
  controlFactory: sessionCatalogControlFactory,
@@ -110,23 +111,26 @@ function createCodexAppServerAgentHarness(options) {
110
111
  }
111
112
  } } : {},
112
113
  authBinding: { fingerprint: async (params) => {
113
- const { fingerprintCodexAppServerAuthBinding } = await import("./auth-binding-B4FfbcCg.js").then((n) => n.t);
114
+ const { fingerprintCodexAppServerAuthBinding } = await import("./auth-binding-Ds_QVm-X.js").then((n) => n.t);
114
115
  return fingerprintCodexAppServerAuthBinding(params);
115
116
  } },
116
117
  runtimeArtifact: { validate: async (binding) => {
117
- const { validateCodexAppServerRuntimeArtifact } = await import("./runtime-artifact-BvyT1uyd.js");
118
+ const { validateCodexAppServerRuntimeArtifact } = await import("./runtime-artifact-Bh_gf6-t.js");
118
119
  return validateCodexAppServerRuntimeArtifact(binding);
119
120
  } },
120
121
  fetchUsageSnapshot: async (ctx) => {
121
- const { fetchCodexAppServerUsageSnapshot } = await import("./usage-ROIaW3wo.js");
122
+ const { fetchCodexAppServerUsageSnapshot } = await import("./usage-i9fv5-4m.js");
122
123
  return await fetchCodexAppServerUsageSnapshot(ctx, { pluginConfig: options?.resolvePluginConfig?.() ?? options?.pluginConfig });
123
124
  },
124
125
  loadModelCatalog: async (params) => {
125
- const { loadCodexAppServerModelCatalog } = await import("./model-catalog-i9rNBthX.js");
126
- return await loadCodexAppServerModelCatalog(params, resolveAttemptPluginConfig(params.config));
126
+ const { createCodexAppServerModelCatalog } = await import("./model-catalog-DT5vo6qo.js");
127
+ if (disposed) return [];
128
+ modelCatalog ??= createCodexAppServerModelCatalog(harnessRuntimeId);
129
+ return await modelCatalog.load(params, resolveAttemptPluginConfig(params.config));
127
130
  },
131
+ readModelCatalogReadiness: (params) => modelCatalog?.read(params, resolveAttemptPluginConfig(params.config)),
128
132
  loadMcpToolCatalog: async (params) => {
129
- const { loadCodexEffectiveMcpCatalog } = await import("./effective-mcp-catalog-CTeGrnfO.js");
133
+ const { loadCodexEffectiveMcpCatalog } = await import("./effective-mcp-catalog-CY9Jn4bA.js");
130
134
  return await loadCodexEffectiveMcpCatalog(params, { bindingStore: options.bindingStore });
131
135
  },
132
136
  supports: (ctx) => {
@@ -169,7 +173,7 @@ function createCodexAppServerAgentHarness(options) {
169
173
  };
170
174
  },
171
175
  runAttempt: async (params) => {
172
- const { runCodexAppServerAttempt } = await import("./run-attempt-DYc0QCBF.js");
176
+ const { runCodexAppServerAttempt } = await import("./run-attempt-BzthFQSM.js");
173
177
  return runCodexAppServerAttempt(params, {
174
178
  bindingStore: options.bindingStore,
175
179
  pluginConfig: resolveAttemptPluginConfig(params.config),
@@ -179,27 +183,27 @@ function createCodexAppServerAgentHarness(options) {
179
183
  });
180
184
  },
181
185
  runIsolatedCompletionV2: async (params) => {
182
- if (params.authorization.owner === "host") {
183
- const { authorization, ...commonParams } = params;
184
- return runCodexHostPreparedIsolatedCompletion({
185
- ...commonParams,
186
- model: authorization.model,
187
- auth: authorization.auth,
188
- ...authorization.sourceAuthFingerprint ? { sourceAuthFingerprint: authorization.sourceAuthFingerprint } : {}
189
- });
190
- }
191
- const { runCodexIsolatedCompletion } = await import("./isolated-completion-Cv6FqygM.js");
186
+ if (params.authorization.owner === "host") return runHostPreparedIsolatedCompletion(params);
187
+ const { runCodexIsolatedCompletion } = await import("./isolated-completion-CRh-51AK.js");
192
188
  return runCodexIsolatedCompletion(params, { pluginConfig: options?.resolvePluginConfig?.() ?? options?.pluginConfig });
193
189
  },
194
190
  runIsolatedCompletion: async (params) => {
195
- return runCodexHostPreparedIsolatedCompletion(params);
191
+ return runHostPreparedIsolatedCompletion({
192
+ ...params,
193
+ authorization: {
194
+ owner: "host",
195
+ model: params.model,
196
+ auth: params.auth,
197
+ sourceAuthFingerprint: params.sourceAuthFingerprint
198
+ }
199
+ });
196
200
  },
197
201
  finalizeSettledTurn: async (params) => {
198
- const { runCodexSettledTurnFinalization } = await import("./settled-turn-finalizer-Dc3ApjU4.js");
202
+ const { runCodexSettledTurnFinalization } = await import("./settled-turn-finalizer-BI-b1sry.js");
199
203
  return runCodexSettledTurnFinalization(params, { pluginConfig: options?.resolvePluginConfig?.() ?? options?.pluginConfig });
200
204
  },
201
205
  runSideQuestion: async (params) => {
202
- const { runCodexAppServerSideQuestion } = await import("./side-question-DjA_jsNe.js");
206
+ const { runCodexAppServerSideQuestion } = await import("./side-question-B6DWAw1A.js");
203
207
  return runCodexAppServerSideQuestion(params, {
204
208
  bindingStore: options.bindingStore,
205
209
  pluginConfig: options?.resolvePluginConfig?.() ?? options?.pluginConfig,
@@ -209,15 +213,20 @@ function createCodexAppServerAgentHarness(options) {
209
213
  });
210
214
  },
211
215
  compact: async (params) => {
212
- const { maybeCompactCodexAppServerSession } = await import("./compact-BglNFZrQ.js");
216
+ const { maybeCompactCodexAppServerSession } = await import("./compact-Y_xBqrHN.js");
213
217
  return maybeCompactCodexAppServerSession(params, {
214
218
  bindingStore: options.bindingStore,
215
219
  pluginConfig: options?.resolvePluginConfig?.() ?? options?.pluginConfig
216
220
  });
217
221
  },
222
+ withSessionDeletion: async (params, run) => {
223
+ const { withCodexAppServerSessionDeletion } = await import("./session-retirement-DNdmYdFc.js");
224
+ params.assertCurrent();
225
+ return withCodexAppServerSessionDeletion(options.bindingStore, params, run);
226
+ },
218
227
  reset: async (params) => {
219
- if (params.sessionId) {
220
- const [{ reclaimCurrentCodexSessionGeneration, sessionBindingIdentity }, { retireCodexAppServerSessionGeneration }] = await Promise.all([import("./session-binding-Bcynfd-_.js").then((n) => n.f), import("./session-retirement-CcNC3YSY.js")]);
228
+ if (params.sessionId && params.reason !== "deleted") {
229
+ const [{ reclaimCurrentCodexSessionGeneration }, { retireCodexAppServerSessionGeneration }] = await Promise.all([import("./session-binding-4Ki04sW-.js").then((n) => n.d), import("./session-retirement-DNdmYdFc.js")]);
221
230
  const identity = sessionBindingIdentity({
222
231
  agentId: params.agentId,
223
232
  sessionId: params.sessionId,
@@ -226,7 +235,7 @@ function createCodexAppServerAgentHarness(options) {
226
235
  const resetGeneration = () => retireCodexAppServerSessionGeneration({
227
236
  bindingStore: options.bindingStore,
228
237
  identity,
229
- mode: params.reason === "deleted" ? "retire" : "reset"
238
+ mode: "reset"
230
239
  });
231
240
  let reset = await resetGeneration();
232
241
  if (reset === "conflict") {
@@ -239,13 +248,17 @@ function createCodexAppServerAgentHarness(options) {
239
248
  if (reset === "conflict") throw new Error(`Codex binding generation changed before session ${params.sessionId} could reset`);
240
249
  }
241
250
  },
242
- dispose: disposeSharedCodexAppServerClients
251
+ dispose: async () => {
252
+ disposed = true;
253
+ modelCatalog?.dispose();
254
+ await disposeSharedCodexAppServerClients();
255
+ }
243
256
  };
244
257
  }
245
258
  /** Creates the private native-compaction bridge registered in host-owned capability state. */
246
259
  function createCodexAppServerNativeCompaction(options) {
247
260
  return async (params) => {
248
- const { maybeCompactCodexAppServerSession } = await import("./compact-BglNFZrQ.js");
261
+ const { maybeCompactCodexAppServerSession } = await import("./compact-Y_xBqrHN.js");
249
262
  return maybeCompactCodexAppServerSession(params, {
250
263
  bindingStore: options.bindingStore,
251
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-Csz0F-DK.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 };