@openclaw/codex 2026.8.1-beta.3 → 2026.8.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 (69) hide show
  1. package/dist/api.js +5 -6
  2. package/dist/{attempt-client-cleanup-URjUlCHg.js → attempt-client-cleanup-CpVfwctT.js} +47 -5
  3. package/dist/{auth-binding-B4FfbcCg.js → auth-binding-Ds_QVm-X.js} +18 -3
  4. package/dist/{binding-connection-DAvZwp96.js → binding-connection-CF7BmrDk.js} +2 -2
  5. package/dist/{bounded-turn-4BjrZEwW.js → bounded-turn-DRC3hcjm.js} +16 -20
  6. package/dist/{capabilities-CH3K57v4.js → capabilities-D6m_TdVy.js} +1 -1
  7. package/dist/cli-metadata.js +1 -1
  8. package/dist/{command-formatters-D0nZ3qtd.js → command-formatters--UToCokS.js} +4 -3
  9. package/dist/{command-handlers-DC86lgT4.js → command-handlers-CLFx2Ypa.js} +114 -79
  10. package/dist/{compact-COqgBRny.js → compact-5xqW1oCh.js} +13 -12
  11. package/dist/{config-CpNeo5AE.js → config-CcYL77O6.js} +350 -288
  12. package/dist/{conversation-binding-data-CW2GuupV.js → conversation-binding-data-BiodpIzq.js} +2 -1
  13. package/dist/doctor-contract-api.js +121 -16
  14. package/dist/{dynamic-tools-fJZhl4CE.js → dynamic-tools-BmeXjwNZ.js} +243 -1002
  15. package/dist/{effective-mcp-catalog-4YKn51aG.js → effective-mcp-catalog-XXQKgK1U.js} +2 -2
  16. package/dist/{event-projector-assistant-message-BwxV4d6N.js → event-projector-assistant-message-C5-Ds8mA.js} +18 -1
  17. package/dist/{event-projector-usage-CLwNEJqW.js → event-projector-usage-B2r5vhWH.js} +9 -14
  18. package/dist/{harness-DoKQcF8n.js → harness-BgeB7LnD.js} +42 -52
  19. package/dist/harness.js +1 -1
  20. package/dist/index.js +308 -306
  21. package/dist/{isolated-completion-DPMtlH9r.js → isolated-completion-CxTus3vZ.js} +4 -4
  22. package/dist/launch-args-sXOAg0SX.js +84 -0
  23. package/dist/{managed-binary-By4FZC6i.js → managed-binary-ZkGodW19.js} +43 -7
  24. package/dist/media-understanding-provider.js +1 -1
  25. package/dist/model-catalog-DULBcniB.js +101 -0
  26. package/dist/{models-CZw1wClT.js → models-DaWfETQk.js} +27 -29
  27. package/dist/{native-subagent-monitor-GGq3RnOo.js → native-subagent-monitor-vXYUZH37.js} +226 -129
  28. package/dist/{node-exec-server.runtime-Bsu1LdFZ.js → node-exec-server.runtime-DirKVZ5h.js} +9 -6
  29. package/dist/{plugin-approval-roundtrip-C75Yiiwc.js → plugin-approval-roundtrip-CCWQGlAI.js} +2 -1
  30. package/dist/{plugin-marketplace-discovery-CSWDkMrP.js → plugin-marketplace-discovery-BXjIFEiw.js} +38 -46
  31. package/dist/{plugin-metadata-cache-BXH5NF-4.js → plugin-metadata-cache-DQQm4gWT.js} +163 -136
  32. package/dist/{protocol-validators-VAVyEnDp.js → protocol-validators-Bg5rpNxk.js} +148 -5
  33. package/dist/{rate-limits-BI1dMHDG.js → rate-limits-BqHEHXQJ.js} +3 -2
  34. package/dist/{sandbox-guard-C1qEeZ5C.js → request-BWxweEdK.js} +183 -2
  35. package/dist/{run-attempt-BV3HzuCf.js → run-attempt-BVLE4Gbi.js} +706 -517
  36. package/dist/{runtime-artifact-BvyT1uyd.js → runtime-artifact-D9pYp4zL.js} +3 -3
  37. package/dist/{session-binding-BTrLf9Qm.js → session-binding-D0zinCP1.js} +195 -122
  38. package/dist/{session-catalog-ezP_UcRM.js → session-catalog-eMhVm0Ql.js} +448 -313
  39. package/dist/session-catalog-home-id-Dt2GiG5o.js +112 -0
  40. package/dist/{session-cli-B1hKvfkI.js → session-cli-B2lyjJA0.js} +1 -1
  41. package/dist/session-history-C5J1AKzG.js +87 -0
  42. package/dist/session-permission-policy-ScnAyG90.js +160 -0
  43. package/dist/session-retirement-CtUtUTr9.js +90 -0
  44. package/dist/{session-upstream-marker-D_2npHlA.js → session-upstream-marker-gqrYIRHk.js} +2 -3
  45. package/dist/settled-turn-context-Bk3IUwod.js +290 -0
  46. package/dist/settled-turn-finalizer-BXLN9PfJ.js +104 -0
  47. package/dist/{shared-client-Dw-rzii0.js → shared-client-B1tT5U6r.js} +1738 -806
  48. package/dist/{side-question-DbXkJZzg.js → side-question-CZ-mCw-t.js} +76 -43
  49. package/dist/{thread-lifecycle-DKdrnTMX.js → thread-lifecycle-CGGKP720.js} +991 -455
  50. package/dist/{thread-ownership-i2NBwDUL.js → thread-ownership-RkaoZCmQ.js} +18 -8
  51. package/dist/{plugin-app-cache-key-DMNQ8Zi8.js → thread-resume-BFt1-ZDa.js} +55 -8
  52. package/dist/{transcript-mirror-BU0_LKAL.js → transcript-mirror-1ep4XjzF.js} +124 -18
  53. package/dist/transport-stdio-NT_Dpd9V.js +724 -0
  54. package/dist/{upstream-prompt-provenance-CFmsKwr9.js → upstream-prompt-provenance-LphB8slG.js} +8 -4
  55. package/dist/{upstream-session-fork-BDVJCLAD.js → upstream-session-fork-Dc8BFExw.js} +76 -90
  56. package/dist/{usage-9dKJCgcy.js → usage-DUhd58gI.js} +3 -3
  57. package/dist/{web-search-provider.runtime-DCdx4DGu.js → web-search-provider.runtime-BEmlE7ov.js} +3 -3
  58. package/openclaw.plugin.json +19 -1
  59. package/package.json +8 -8
  60. package/dist/app-server-policy-bg5QPSVP.js +0 -25
  61. package/dist/command-rpc-xUIIonsO.js +0 -90
  62. package/dist/incognito-session-ET_ufDH-.js +0 -2
  63. package/dist/model-catalog-CmGoqVKB.js +0 -48
  64. package/dist/request-DSK0W6YI.js +0 -157
  65. package/dist/session-catalog-home-id-BNwAJ9D7.js +0 -18
  66. package/dist/session-retirement-CE4iMiLh.js +0 -36
  67. package/dist/settled-turn-finalizer-Dx1onIqg.js +0 -328
  68. package/dist/thread-resume-CdJk2Ehf.js +0 -30
  69. package/dist/transport-stdio-DhoGy33Z.js +0 -99
@@ -4,7 +4,8 @@ const UPSTREAM_USER_TEXT_META_KEY = "upstreamUserText";
4
4
  const MIRROR_IDENTITY_META_KEY = "mirrorIdentity";
5
5
  const CODEX_META_KEY = "__openclaw";
6
6
  function attachCodexMirrorIdentity(message, identity) {
7
- const baseMeta = asOptionalRecord(CODEX_META_KEY in message ? message[CODEX_META_KEY] : void 0) ?? {};
7
+ const existing = CODEX_META_KEY in message ? message[CODEX_META_KEY] : void 0;
8
+ const baseMeta = asOptionalRecord(existing) ?? {};
8
9
  return {
9
10
  ...message,
10
11
  __openclaw: {
@@ -14,13 +15,15 @@ function attachCodexMirrorIdentity(message, identity) {
14
15
  };
15
16
  }
16
17
  function readMirrorIdentity(message) {
17
- const record = asOptionalRecord(CODEX_META_KEY in message ? message[CODEX_META_KEY] : void 0);
18
+ const meta = CODEX_META_KEY in message ? message[CODEX_META_KEY] : void 0;
19
+ const record = asOptionalRecord(meta);
18
20
  if (!record) return;
19
21
  const id = record[MIRROR_IDENTITY_META_KEY];
20
22
  return typeof id === "string" && id ? id : void 0;
21
23
  }
22
24
  function attachUpstreamUserText(message, text) {
23
- const baseMeta = asOptionalRecord(CODEX_META_KEY in message ? message[CODEX_META_KEY] : void 0) ?? {};
25
+ const existing = CODEX_META_KEY in message ? message[CODEX_META_KEY] : void 0;
26
+ const baseMeta = asOptionalRecord(existing) ?? {};
24
27
  return {
25
28
  ...message,
26
29
  __openclaw: {
@@ -30,7 +33,8 @@ function attachUpstreamUserText(message, text) {
30
33
  };
31
34
  }
32
35
  function readUpstreamUserText(message) {
33
- const record = asOptionalRecord(message && CODEX_META_KEY in message ? message[CODEX_META_KEY] : void 0);
36
+ const meta = message && CODEX_META_KEY in message ? message[CODEX_META_KEY] : void 0;
37
+ const record = asOptionalRecord(meta);
34
38
  if (!record) return;
35
39
  const text = record[UPSTREAM_USER_TEXT_META_KEY];
36
40
  return typeof text === "string" && text ? text : void 0;
@@ -1,7 +1,8 @@
1
- import { d as sessionBindingIdentity } from "./session-binding-BTrLf9Qm.js";
2
- import { r as assertCodexThreadForkResponse } from "./protocol-validators-VAVyEnDp.js";
3
- import { t as isIncognitoSessionKey } from "./incognito-session-ET_ufDH-.js";
4
- import { i as createImportedCodexSession, n as codexUpstreamBaseline, t as codexLastTerminalTurnId } from "./session-upstream-marker-D_2npHlA.js";
1
+ import { d as sessionBindingIdentity } from "./session-binding-D0zinCP1.js";
2
+ import { a as assertCodexThreadForkResponse } from "./protocol-validators-Bg5rpNxk.js";
3
+ import { i as readUpstreamUserText, r as readMirrorIdentity } from "./upstream-prompt-provenance-LphB8slG.js";
4
+ import { c as fingerprintCodexMirrorSourceMessage, m as projectCodexUserItemText, u as readCodexMirrorSourceFingerprint } from "./transcript-mirror-1ep4XjzF.js";
5
+ import { i as createImportedCodexSession, n as codexUpstreamBaseline, t as codexLastTerminalTurnId } from "./session-upstream-marker-gqrYIRHk.js";
5
6
  import { isRecord, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
6
7
  import { readVisibleSessionTranscriptMessageEntries } from "openclaw/plugin-sdk/session-transcript-runtime";
7
8
  import { deleteSessionUpstreamLink, upsertSessionUpstreamLink } from "openclaw/plugin-sdk/session-catalog";
@@ -14,35 +15,7 @@ function failure(code, message) {
14
15
  message
15
16
  };
16
17
  }
17
- function asInputs(item) {
18
- return Array.isArray(item.content) ? item.content : [];
19
- }
20
- function userMessageDisplay(item) {
21
- let text = "";
22
- let hasTextElement = false;
23
- let hasImage = false;
24
- let hasUnverifiableInput = false;
25
- for (const input of asInputs(item)) if (input.type === "text") {
26
- if (typeof input.text === "string") text += input.text;
27
- hasTextElement ||= Array.isArray(input.textElements) && input.textElements.length > 0;
28
- } else {
29
- hasUnverifiableInput = true;
30
- hasImage ||= input.type === "image" || input.type === "localImage";
31
- }
32
- return {
33
- text,
34
- visible: Boolean(text.trim()) || hasTextElement || hasImage,
35
- hasUnverifiableInput
36
- };
37
- }
38
- function isHiddenNestedReviewTurn(previous, turn) {
39
- if (previous?.status !== "completed" || turn.status !== "interrupted" || turn.completedAt != null || !previous.items.some((item) => item.type === "enteredReviewMode") || !previous.items.some((item) => item.type === "exitedReviewMode")) return false;
40
- const userMessages = turn.items.filter((item) => item.type === "userMessage");
41
- const [firstUserMessage, secondUserMessage] = userMessages;
42
- if (!firstUserMessage || !secondUserMessage || userMessages.length !== 2) return false;
43
- return JSON.stringify(asInputs(firstUserMessage)) === JSON.stringify(asInputs(secondUserMessage));
44
- }
45
- function localMessageText(content) {
18
+ function textOnlyMessage(content) {
46
19
  if (typeof content === "string") return content;
47
20
  if (!Array.isArray(content)) return;
48
21
  const texts = [];
@@ -52,37 +25,32 @@ function localMessageText(content) {
52
25
  if (typed.type !== "text" || typeof typed.text !== "string") return;
53
26
  texts.push(typed.text);
54
27
  }
55
- return texts.join("");
28
+ return texts.join("\n");
56
29
  }
57
30
  function resolveCodexUpstreamForkBoundaryFromTurns(params) {
58
- let visibleUserMessagesSeen = 0;
59
- let reviewMode = false;
31
+ let localIndex = 0;
32
+ let matchedPrefix = false;
60
33
  for (const [turnIndex, turn] of params.turns.entries()) {
61
- const hiddenNestedReviewTurn = isHiddenNestedReviewTurn(params.turns[turnIndex - 1], turn);
62
34
  let userMessagesInTurn = 0;
63
35
  for (const item of turn.items) {
64
- if (item.type === "enteredReviewMode") {
65
- reviewMode = true;
66
- continue;
67
- }
68
- if (item.type === "exitedReviewMode") {
69
- reviewMode = false;
70
- continue;
71
- }
72
36
  if (item.type !== "userMessage") continue;
73
37
  const isSteer = userMessagesInTurn > 0;
74
38
  userMessagesInTurn += 1;
75
- if (reviewMode || hiddenNestedReviewTurn) continue;
76
- const display = userMessageDisplay(item);
77
- if (display.hasUnverifiableInput) return failure("drift-mismatch", "A message before the fork point contains images or attachments that cannot be verified across OpenClaw and Codex. Fork from a text-only span instead.");
78
- if (!display.visible) continue;
79
- const ordinal = visibleUserMessagesSeen;
80
- if (ordinal > params.userMessageOrdinal) break;
81
- const localText = params.localPrefixTexts[ordinal];
82
- if (localText === void 0) return failure("drift-mismatch", "A message before the fork point contains images or attachments that cannot be verified across OpenClaw and Codex. Fork from a text-only span instead.");
83
- if (display.text !== localText) return failure("drift-mismatch", "The local conversation no longer matches the Codex thread. Refresh the session and try again.");
84
- if (ordinal !== params.userMessageOrdinal) {
85
- visibleUserMessagesSeen += 1;
39
+ const nativeText = textOnlyMessage(item.content);
40
+ if (nativeText === void 0) return failure("drift-mismatch", "A message before the fork point contains images or attachments that cannot be verified across OpenClaw and Codex. Fork from a text-only span instead.");
41
+ const local = params.localPrefix[localIndex];
42
+ const upstreamText = local && readUpstreamUserText(local.message);
43
+ const text = upstreamText ? nativeText : projectCodexUserItemText(item);
44
+ if (!text) continue;
45
+ const identity = local && readMirrorIdentity(local.message);
46
+ const matchesIdentity = identity === `${turn.id}:${item.id}` || !isSteer && identity === `${turn.id}:prompt`;
47
+ if (!matchedPrefix && !matchesIdentity) continue;
48
+ matchedPrefix = true;
49
+ const localText = textOnlyMessage(local && "content" in local.message ? local.message.content : void 0);
50
+ const upstreamPromptVerified = !upstreamText || local?.message.role === "user" && readCodexMirrorSourceFingerprint(local.message) === fingerprintCodexMirrorSourceMessage(local.message);
51
+ if (!matchesIdentity || !upstreamPromptVerified || localText === void 0 || text !== (upstreamText ?? localText)) return failure("drift-mismatch", "The local conversation no longer matches the Codex thread. Refresh the session and try again.");
52
+ if (localIndex < params.localPrefix.length - 1) {
53
+ localIndex += 1;
86
54
  continue;
87
55
  }
88
56
  if (isSteer) return failure("steer-message", "This message steered an existing Codex turn and cannot be forked independently. Fork from the turn's first message instead.");
@@ -104,7 +72,7 @@ function resolveCodexUpstreamForkBoundaryFromTurns(params) {
104
72
  };
105
73
  }
106
74
  }
107
- return failure("drift-mismatch", "The message could not be matched to the Codex thread. Refresh the session and try again.");
75
+ return failure("drift-mismatch", "The local history has no verified boundary in this Codex thread. Use native Codex to fork this conversation.");
108
76
  }
109
77
  async function listCodexUpstreamTurns(control, threadId) {
110
78
  const turns = [];
@@ -128,24 +96,23 @@ async function listCodexUpstreamTurns(control, threadId) {
128
96
  }
129
97
  async function resolveCodexUpstreamForkBoundary(params) {
130
98
  try {
131
- if ((await params.control.readThread(params.threadId, false)).historyMode === "paginated") return failure("upstream-unavailable", "This Codex thread uses paginated history, which cannot be forked from OpenClaw yet.");
132
99
  const visibleUserEntries = (await readVisibleSessionTranscriptMessageEntries({
133
100
  agentId: params.agentId,
134
101
  sessionId: params.sessionId,
135
102
  sessionKey: params.sessionKey,
136
103
  storePath: params.storePath
137
104
  })).filter((entry) => entry.role === "user");
138
- const userMessageOrdinal = visibleUserEntries.findIndex((entry) => entry.entryId === params.entryId);
139
- if (userMessageOrdinal < 0) return failure("drift-mismatch", "The local message could not be mapped to the Codex thread. Refresh the session and try again.");
140
- const localPrefixTexts = visibleUserEntries.slice(0, userMessageOrdinal + 1).map((entry) => localMessageText("content" in entry.message ? entry.message.content : void 0));
105
+ const targetIndex = visibleUserEntries.findIndex((entry) => entry.entryId === params.entryId);
106
+ if (targetIndex < 0) return failure("drift-mismatch", "The local message could not be mapped to the Codex thread. Refresh the session and try again.");
107
+ const localPrefix = visibleUserEntries.slice(0, targetIndex + 1);
141
108
  const resolved = resolveCodexUpstreamForkBoundaryFromTurns({
142
109
  turns: await listCodexUpstreamTurns(params.control, params.threadId),
143
- userMessageOrdinal,
144
- localPrefixTexts
110
+ localPrefix
145
111
  });
112
+ const target = localPrefix.at(-1)?.message;
146
113
  return resolved.ok ? {
147
114
  ...resolved,
148
- editorText: localPrefixTexts[userMessageOrdinal]
115
+ editorText: textOnlyMessage(target && "content" in target ? target.content : void 0)
149
116
  } : resolved;
150
117
  } catch {
151
118
  return failure("upstream-unavailable", "The Codex thread could not be read. Check that Codex is available, then try again.");
@@ -166,9 +133,6 @@ function readConnectionFingerprint(ref) {
166
133
  if (!isRecord(ref)) return;
167
134
  return typeof ref.connectionFingerprint === "string" && ref.connectionFingerprint.trim() ? ref.connectionFingerprint : void 0;
168
135
  }
169
- function normalizeTurnId(value) {
170
- return normalizeOptionalString(value);
171
- }
172
136
  async function forkCodexUpstreamSession(params, options) {
173
137
  try {
174
138
  const sourceFingerprint = params.upstream.kind === "codex-app-server" ? readConnectionFingerprint(params.upstream.ref) : void 0;
@@ -179,27 +143,33 @@ async function forkCodexUpstreamSession(params, options) {
179
143
  message: "This Codex thread is not available on the current connection. Reconnect to its host and try again."
180
144
  };
181
145
  return await requestControl.withPinnedConnection(async (control) => {
182
- const incognito = isIncognitoSessionKey(params.targetKey);
183
- const clientId = control.clientId?.trim();
184
- if (incognito && !clientId) throw new Error("Incognito Codex forks require the live pinned app-server client");
146
+ const sourceBinding = await options.bindingStore.read(sessionBindingIdentity({
147
+ ...params.source,
148
+ config: options.resolveConfig?.()
149
+ }));
150
+ const supervised = sourceBinding?.connectionScope === "supervision";
151
+ const sourceThreadId = params.upstream.threadId;
185
152
  let linked = false;
186
- let bindingIdentity;
153
+ let createdBinding;
187
154
  const compensateFork = async (forkedThreadId) => {
188
- if (bindingIdentity) await options.bindingStore.mutate(bindingIdentity, {
189
- kind: "clear",
190
- threadId: forkedThreadId
191
- }).catch(() => void 0);
155
+ if (createdBinding) {
156
+ if (!await options.bindingStore.mutate(createdBinding.identity, {
157
+ kind: "clear",
158
+ threadId: forkedThreadId,
159
+ expectedPendingSupervisionBranch: createdBinding.pending
160
+ }).catch(() => false)) return;
161
+ }
192
162
  if (linked) deleteSessionUpstreamLink(params.targetKey, params.source.agentId);
193
163
  await control.archiveThread(forkedThreadId).catch(() => void 0);
194
164
  };
195
- if (sourceFingerprint !== control.connectionFingerprint) return {
165
+ if (sourceFingerprint !== control.connectionFingerprint || supervised && (sourceBinding.supervisionSourceThreadId !== params.upstream.threadId || (sourceBinding.pendingSupervisionBranch?.connectionFingerprint ?? sourceBinding.appServerRuntimeFingerprint) !== sourceFingerprint)) return {
196
166
  status: "failed",
197
167
  code: "upstream-unavailable",
198
168
  message: "This Codex thread is not available on the current connection. Reconnect to its host and try again."
199
169
  };
200
170
  const resolved = await resolveCodexUpstreamForkBoundary({
201
171
  ...params.source,
202
- threadId: params.upstream.threadId,
172
+ threadId: sourceThreadId,
203
173
  control
204
174
  });
205
175
  if (!resolved.ok) return {
@@ -207,7 +177,7 @@ async function forkCodexUpstreamSession(params, options) {
207
177
  code: resolved.code,
208
178
  message: resolved.message
209
179
  };
210
- const liveTurns = await listCodexUpstreamTurns(control, params.upstream.threadId);
180
+ const liveTurns = await listCodexUpstreamTurns(control, sourceThreadId);
211
181
  const precheck = precheckCodexUpstreamForkBoundary({
212
182
  boundary: resolved.boundary,
213
183
  turns: liveTurns
@@ -218,27 +188,27 @@ async function forkCodexUpstreamSession(params, options) {
218
188
  message: precheck.message
219
189
  };
220
190
  const rawResponse = await control.forkThread({
221
- threadId: params.upstream.threadId,
191
+ threadId: sourceThreadId,
222
192
  beforeTurnId: resolved.boundary.beforeTurnId,
223
- ...incognito ? { ephemeral: true } : {},
224
- excludeTurns: !incognito
193
+ ...params.sandbox === "required" ? { sandbox: "workspace-write" } : {},
194
+ excludeTurns: true
225
195
  });
226
196
  let response;
227
197
  try {
228
198
  response = assertCodexThreadForkResponse(rawResponse);
229
199
  } catch (error) {
230
200
  const orphanThreadId = isRecord(rawResponse.thread) && typeof rawResponse.thread.id === "string" ? rawResponse.thread.id.trim() : "";
231
- if (orphanThreadId && orphanThreadId !== params.upstream.threadId) await control.archiveThread(orphanThreadId).catch(() => void 0);
201
+ if (orphanThreadId && orphanThreadId !== sourceThreadId && orphanThreadId !== sourceBinding?.threadId) await control.archiveThread(orphanThreadId).catch(() => void 0);
232
202
  throw error;
233
203
  }
234
204
  const threadId = response.thread.id.trim();
235
205
  if (!threadId) throw new Error("Codex thread/fork response did not include a thread id");
236
- if (threadId === params.upstream.threadId) throw new Error("Codex thread/fork response reused the source thread id");
206
+ if (threadId === sourceThreadId || threadId === sourceBinding?.threadId) throw new Error("Codex thread/fork response reused the source thread id");
237
207
  const forkedThreadId = threadId;
238
208
  try {
239
- const connectionFingerprint = control.connectionFingerprint;
209
+ const connectionFingerprint = normalizeOptionalString(control.connectionFingerprint);
240
210
  if (!connectionFingerprint) throw new Error("Codex fork connection did not include a fingerprint");
241
- const forkedTurns = incognito ? response.thread.turns ?? [] : await listCodexUpstreamTurns(control, threadId);
211
+ const forkedTurns = await listCodexUpstreamTurns(control, threadId);
242
212
  const expectedLastTurnId = resolved.boundary.retainedMarker.turnId;
243
213
  if ((forkedTurns.at(-1)?.id ?? null) !== expectedLastTurnId) {
244
214
  await compensateFork(forkedThreadId);
@@ -252,8 +222,8 @@ async function forkCodexUpstreamSession(params, options) {
252
222
  ...response.thread,
253
223
  turns: forkedTurns
254
224
  };
255
- const throughTurnId = codexLastTerminalTurnId(forkedThread, normalizeTurnId) ?? null;
256
- const marker = codexUpstreamBaseline(forkedThread, normalizeTurnId);
225
+ const throughTurnId = codexLastTerminalTurnId(forkedThread, normalizeOptionalString) ?? null;
226
+ const marker = codexUpstreamBaseline(forkedThread, normalizeOptionalString);
257
227
  const config = options.resolveConfig?.() ?? {};
258
228
  return {
259
229
  status: "created",
@@ -269,7 +239,7 @@ async function forkCodexUpstreamSession(params, options) {
269
239
  modelSelectionLocked: true
270
240
  },
271
241
  afterImport: async (entry) => {
272
- bindingIdentity = sessionBindingIdentity({
242
+ const bindingIdentity = sessionBindingIdentity({
273
243
  agentId: entry.agentId,
274
244
  sessionId: entry.sessionId,
275
245
  sessionKey: entry.key,
@@ -289,17 +259,33 @@ async function forkCodexUpstreamSession(params, options) {
289
259
  marker
290
260
  });
291
261
  if (!linked) throw new Error("Codex fork link could not be persisted");
262
+ createdBinding = {
263
+ identity: bindingIdentity,
264
+ pending: {
265
+ sourceThreadId: threadId,
266
+ connectionFingerprint,
267
+ ...throughTurnId ? { lastTurnId: throughTurnId } : {}
268
+ }
269
+ };
292
270
  if (!await options.bindingStore.mutate(bindingIdentity, {
293
271
  kind: "set",
272
+ if: { kind: "absent" },
294
273
  binding: {
295
274
  threadId,
296
- ...incognito && clientId ? { clientId } : {},
275
+ connectionScope: "supervision",
276
+ supervisionSourceThreadId: threadId,
277
+ preserveNativeModel: true,
278
+ conversationSourceTransferComplete: true,
279
+ pendingSupervisionBranch: createdBinding.pending,
297
280
  cwd: forkedThread.cwd ?? "",
298
281
  model: response.model,
299
282
  modelProvider: response.modelProvider ?? void 0,
300
283
  historyCoveredThrough: (/* @__PURE__ */ new Date()).toISOString()
301
284
  }
302
- })) throw new Error("Codex session binding changed before the fork could be attached");
285
+ })) {
286
+ createdBinding = void 0;
287
+ throw new Error("Codex session binding changed before the fork could be attached");
288
+ }
303
289
  return { pluginExtensions: entry.entry.pluginExtensions };
304
290
  }
305
291
  })).key,
@@ -1,6 +1,6 @@
1
- import { i as resolveCodexAppServerRuntimeOptions } from "./config-CpNeo5AE.js";
2
- import { t as buildCodexAppServerUsageSnapshot } from "./rate-limits-BI1dMHDG.js";
3
- import { t as readCodexAppServerUsage } from "./request-DSK0W6YI.js";
1
+ import { i as resolveCodexAppServerRuntimeOptions } from "./config-CcYL77O6.js";
2
+ import { n as readCodexAppServerUsage } from "./request-BWxweEdK.js";
3
+ import { t as buildCodexAppServerUsageSnapshot } from "./rate-limits-BqHEHXQJ.js";
4
4
  import { CODEX_APP_SERVER_AUTH_MARKER } from "openclaw/plugin-sdk/agent-runtime";
5
5
  //#region extensions/codex/src/app-server/usage.ts
6
6
  /** Handles the synthetic usage credential for a Codex-backed OpenAI route. */
@@ -1,6 +1,6 @@
1
- import { ut as isJsonObject } from "./shared-client-Dw-rzii0.js";
2
- import { d as buildCodexNativeWebSearchThreadConfig } from "./thread-lifecycle-DKdrnTMX.js";
3
- import { t as runBoundedCodexAppServerTurn } from "./bounded-turn-4BjrZEwW.js";
1
+ import { Ht as isJsonObject } from "./shared-client-B1tT5U6r.js";
2
+ import { b as buildCodexNativeWebSearchThreadConfig } from "./thread-lifecycle-CGGKP720.js";
3
+ import { t as runBoundedCodexAppServerTurn } from "./bounded-turn-DRC3hcjm.js";
4
4
  import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
5
5
  import { readStringParam, resolveSearchTimeoutSeconds, wrapWebContent } from "openclaw/plugin-sdk/provider-web-search";
6
6
  //#region extensions/codex/src/web-search-provider.runtime.ts
@@ -1,9 +1,27 @@
1
1
  {
2
2
  "id": "codex",
3
+ "backupResources": [
4
+ {
5
+ "disposition": "regenerable",
6
+ "scope": "agent",
7
+ "relativePath": "codex-home/tmp/arg0"
8
+ },
9
+ {
10
+ "disposition": "regenerable",
11
+ "scope": "agent",
12
+ "relativePath": "codex-home/.tmp/plugins"
13
+ },
14
+ {
15
+ "disposition": "regenerable",
16
+ "scope": "agent",
17
+ "relativePath": "codex-home/.tmp/bundled-marketplaces"
18
+ }
19
+ ],
3
20
  "doctorContract": {
4
21
  "configRepair": true,
5
22
  "stateMigrations": true
6
23
  },
24
+ "doctorHealthChecks": true,
7
25
  "sessionRouteStateOwners": [
8
26
  {
9
27
  "id": "codex",
@@ -497,7 +515,7 @@
497
515
  },
498
516
  "computerUse.autoRepair": {
499
517
  "label": "Auto Repair",
500
- "help": "When true, failed Computer Use live tests repair stale scoped Computer Use MCP children before retrying once.",
518
+ "help": "When true, failed Computer Use live tests reload the Codex-owned MCP runtime before retrying once.",
501
519
  "advanced": true
502
520
  },
503
521
  "computerUse.marketplaceSource": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openclaw/codex",
3
- "version": "2026.8.1-beta.3",
3
+ "version": "2026.8.2",
4
4
  "description": "OpenClaw Codex app-server harness and native session supervision plugin.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -8,11 +8,11 @@
8
8
  },
9
9
  "type": "module",
10
10
  "dependencies": {
11
- "@openai/codex": "0.149.1",
11
+ "@openai/codex": "0.151.0",
12
12
  "semver": "7.8.5",
13
- "smol-toml": "1.7.1",
14
- "typebox": "1.3.6",
15
- "ws": "8.21.1",
13
+ "smol-toml": "1.8.0",
14
+ "typebox": "1.3.17",
15
+ "ws": "8.21.3",
16
16
  "zod": "4.4.3"
17
17
  },
18
18
  "devDependencies": {
@@ -36,10 +36,10 @@
36
36
  ]
37
37
  },
38
38
  "compat": {
39
- "pluginApi": ">=2026.8.1-beta.3"
39
+ "pluginApi": ">=2026.8.2"
40
40
  },
41
41
  "build": {
42
- "openclawVersion": "2026.8.1-beta.3"
42
+ "openclawVersion": "2026.8.2"
43
43
  },
44
44
  "release": {
45
45
  "publishToClawHub": true,
@@ -59,7 +59,7 @@
59
59
  "README.md"
60
60
  ],
61
61
  "peerDependencies": {
62
- "openclaw": ">=2026.8.1-beta.3"
62
+ "openclaw": ">=2026.8.2"
63
63
  },
64
64
  "peerDependenciesMeta": {
65
65
  "openclaw": {
@@ -1,25 +0,0 @@
1
- import { b as canUseCodexModelBackedApprovalsReviewerForModel } from "./config-CpNeo5AE.js";
2
- //#region extensions/codex/src/app-server/app-server-policy.ts
3
- function resolveCodexAppServerForModelProvider(params) {
4
- const explicitProvider = normalizeModelBackedReviewerProvider(params.provider);
5
- if (!isCodexModelBackedApprovalsReviewer(params.appServer.approvalsReviewer) || canUseCodexModelBackedApprovalsReviewerForModel({
6
- modelProvider: explicitProvider,
7
- model: params.model,
8
- config: params.config,
9
- env: params.env,
10
- agentDir: params.agentDir,
11
- codexConfigToml: params.codexConfigToml
12
- })) return params.appServer;
13
- return {
14
- ...params.appServer,
15
- approvalsReviewer: "user"
16
- };
17
- }
18
- function isCodexModelBackedApprovalsReviewer(value) {
19
- return value === "auto_review" || value === "guardian_subagent";
20
- }
21
- function normalizeModelBackedReviewerProvider(provider) {
22
- return provider?.trim().toLowerCase() || void 0;
23
- }
24
- //#endregion
25
- export { resolveCodexAppServerForModelProvider as t };
@@ -1,90 +0,0 @@
1
- import { i as resolveCodexAppServerRuntimeOptions, s as resolveCodexSupervisionAppServerRuntimeOptions } from "./config-CpNeo5AE.js";
2
- import { n as listCodexAppServerModels } from "./models-CZw1wClT.js";
3
- import { n as describeControlFailure, t as CODEX_CONTROL_METHODS } from "./capabilities-CH3K57v4.js";
4
- import { i as withCodexAppServerJsonClient, r as requestCodexAppServerJson } from "./request-DSK0W6YI.js";
5
- //#region extensions/codex/src/command-rpc.ts
6
- function requestOptions(pluginConfig, limit, config, agentDir) {
7
- const runtime = resolveCodexAppServerRuntimeOptions({ pluginConfig });
8
- return {
9
- limit,
10
- timeoutMs: runtime.requestTimeoutMs,
11
- startOptions: runtime.start,
12
- config,
13
- agentDir
14
- };
15
- }
16
- async function codexControlRequest(pluginConfig, method, requestParams, options = {}) {
17
- const runtime = options.startOptions ? resolveCodexSupervisionAppServerRuntimeOptions({ pluginConfig }) : resolveCodexAppServerRuntimeOptions({ pluginConfig });
18
- const controlRequestOptions = {
19
- timeoutMs: options.timeoutMs ?? runtime.requestTimeoutMs,
20
- startOptions: options.startOptions ?? runtime.start,
21
- config: options.config,
22
- sessionKey: options.sessionKey,
23
- sessionId: options.sessionId,
24
- authProfileId: options.authProfileId,
25
- agentDir: options.agentDir,
26
- isolated: options.isolated
27
- };
28
- if (options.onResponse) return await withCodexAppServerJsonClient(controlRequestOptions, async (request, client) => {
29
- const response = await request({
30
- method,
31
- requestParams
32
- });
33
- await options.onResponse(response, client);
34
- return response;
35
- });
36
- return await requestCodexAppServerJson({
37
- method,
38
- requestParams,
39
- ...controlRequestOptions
40
- });
41
- }
42
- async function safeCodexControlRequest(pluginConfig, method, requestParams, options = {}) {
43
- return await safeValue(async () => await codexControlRequest(pluginConfig, method, requestParams, options));
44
- }
45
- async function safeCodexModelList(pluginConfig, limit, config, agentDir) {
46
- return await safeValue(async () => await listCodexAppServerModels(requestOptions(pluginConfig, limit, config, agentDir)));
47
- }
48
- async function readCodexStatusProbes(pluginConfig, config, agentDir) {
49
- const [models, account, limits, mcps, skills] = await Promise.all([
50
- safeCodexModelList(pluginConfig, 20, config, agentDir),
51
- safeCodexControlRequest(pluginConfig, CODEX_CONTROL_METHODS.account, { refreshToken: false }, {
52
- config,
53
- agentDir
54
- }),
55
- safeCodexControlRequest(pluginConfig, CODEX_CONTROL_METHODS.rateLimits, void 0, {
56
- config,
57
- agentDir
58
- }),
59
- safeCodexControlRequest(pluginConfig, CODEX_CONTROL_METHODS.listMcpServers, { limit: 100 }, {
60
- config,
61
- agentDir
62
- }),
63
- safeCodexControlRequest(pluginConfig, CODEX_CONTROL_METHODS.listSkills, {}, {
64
- config,
65
- agentDir
66
- })
67
- ]);
68
- return {
69
- models,
70
- account,
71
- limits,
72
- mcps,
73
- skills
74
- };
75
- }
76
- async function safeValue(read) {
77
- try {
78
- return {
79
- ok: true,
80
- value: await read()
81
- };
82
- } catch (error) {
83
- return {
84
- ok: false,
85
- error: describeControlFailure(error)
86
- };
87
- }
88
- }
89
- //#endregion
90
- export { safeCodexControlRequest as i, readCodexStatusProbes as n, requestOptions as r, codexControlRequest as t };
@@ -1,2 +0,0 @@
1
- import { isIncognitoSessionKey } from "openclaw/plugin-sdk/routing";
2
- export { isIncognitoSessionKey as t };
@@ -1,48 +0,0 @@
1
- import { r as buildCodexRuntimeModelParams } from "./harness-DoKQcF8n.js";
2
- import { h as readCodexPluginConfig } from "./config-CpNeo5AE.js";
3
- import { t as listAllCodexAppServerModels } from "./models-CZw1wClT.js";
4
- import { r as requestOptions } from "./command-rpc-xUIIonsO.js";
5
- //#region extensions/codex/src/app-server/model-catalog.ts
6
- const OPENAI_CODEX_BASE_URL = "https://chatgpt.com/backend-api/codex";
7
- const DEFAULT_MODEL_DISCOVERY_TIMEOUT_MS = 2500;
8
- const INPUT_TYPES = /* @__PURE__ */ new Set([
9
- "text",
10
- "image",
11
- "audio",
12
- "video",
13
- "document"
14
- ]);
15
- function isModelInputType(value) {
16
- return INPUT_TYPES.has(value);
17
- }
18
- function codexAppServerModelsToCatalogEntries(models) {
19
- return models.map((model, providerOrder) => {
20
- const input = model.inputModalities.filter(isModelInputType);
21
- const runtimeParams = buildCodexRuntimeModelParams(model.id, model.model);
22
- return {
23
- provider: "openai",
24
- id: model.id,
25
- name: model.displayName ?? model.id,
26
- providerOrder,
27
- api: "openai-chatgpt-responses",
28
- baseUrl: OPENAI_CODEX_BASE_URL,
29
- reasoning: model.supportedReasoningEfforts.length > 0,
30
- ...input.length > 0 ? { input } : {},
31
- ...runtimeParams ? { params: runtimeParams } : {},
32
- compat: {
33
- supportsReasoningEffort: model.supportedReasoningEfforts.length > 0,
34
- supportedReasoningEfforts: model.supportedReasoningEfforts
35
- }
36
- };
37
- });
38
- }
39
- async function loadCodexAppServerModelCatalog(params, pluginConfig) {
40
- const discovery = readCodexPluginConfig(pluginConfig).discovery;
41
- if (discovery?.enabled === false) return [];
42
- return codexAppServerModelsToCatalogEntries((await listAllCodexAppServerModels({
43
- ...requestOptions(pluginConfig, 100, params.config, params.agentDir),
44
- timeoutMs: discovery?.timeoutMs ?? DEFAULT_MODEL_DISCOVERY_TIMEOUT_MS
45
- })).models);
46
- }
47
- //#endregion
48
- export { loadCodexAppServerModelCatalog };