@openclaw/codex 2026.8.1-beta.2 → 2026.8.1

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 (64) hide show
  1. package/dist/api.js +146 -0
  2. package/dist/{attempt-client-cleanup-DMLXUfa8.js → attempt-client-cleanup-CVPvp9dL.js} +47 -5
  3. package/dist/{auth-binding-B4FfbcCg.js → auth-binding-Ds_QVm-X.js} +18 -3
  4. package/dist/{binding-connection-I5Bo-AsX.js → binding-connection-CCQFs8lf.js} +15 -3
  5. package/dist/{bounded-turn-qgZmzy_4.js → bounded-turn-rq5tiSXk.js} +27 -26
  6. package/dist/{capabilities-CybGI1oz.js → capabilities-CGm_94eL.js} +1 -1
  7. package/dist/cli-metadata.js +1 -1
  8. package/dist/{command-formatters-B1AEz8ZA.js → command-formatters-C54Yg3eA.js} +2 -2
  9. package/dist/{command-handlers-Db8pu_ds.js → command-handlers-BvOAHTrA.js} +111 -67
  10. package/dist/{compact-LspQaGfl.js → compact-Hd7SAc0N.js} +35 -30
  11. package/dist/{session-binding-DPxIvMgE.js → config-Cxw3Cl3k.js} +361 -1161
  12. package/dist/context-compaction-activity-BOeJf7yo.js +58 -0
  13. package/dist/doctor-contract-api.js +128 -26
  14. package/dist/{dynamic-tools-BVdyWkUD.js → dynamic-tools-BFoUcRdx.js} +1341 -1464
  15. package/dist/{effective-mcp-catalog-DIIhAtOZ.js → effective-mcp-catalog-BTJHnDSx.js} +2 -2
  16. package/dist/elicitation-input-DMkeki8d.js +71 -0
  17. package/dist/{event-projector-assistant-message-BwxV4d6N.js → event-projector-assistant-message-C5-Ds8mA.js} +18 -1
  18. package/dist/{event-projector-usage-e5huIQWu.js → event-projector-usage-D3PHFFXh.js} +18 -18
  19. package/dist/harness-DVfUQBlQ.js +248 -0
  20. package/dist/harness.js +2 -226
  21. package/dist/index.js +405 -299
  22. package/dist/{isolated-completion-C58NbL40.js → isolated-completion-Cbbx_5Ed.js} +4 -4
  23. package/dist/launch-args-sXOAg0SX.js +84 -0
  24. package/dist/managed-binary-ZkGodW19.js +248 -0
  25. package/dist/media-understanding-provider.js +2 -2
  26. package/dist/model-catalog-o6Cgjoss.js +101 -0
  27. package/dist/{models-BFlpn1Ex.js → models-DgFWSuxA.js} +25 -28
  28. package/dist/{native-subagent-monitor-DyTGmTUx.js → native-subagent-monitor-CwFyoylz.js} +385 -94
  29. package/dist/node-exec-server.runtime-DXrqpw1c.js +195 -0
  30. package/dist/plugin-approval-roundtrip-D80UZiJ_.js +95 -0
  31. package/dist/{plugin-marketplace-discovery-CzrGJdCR.js → plugin-marketplace-discovery-mdmScYOj.js} +60 -55
  32. package/dist/{plugin-metadata-cache-CNJPj4_b.js → plugin-metadata-cache-CulOABwu.js} +164 -134
  33. package/dist/{protocol-validators-B4F7L8Rf.js → protocol-validators-Bg5rpNxk.js} +203 -7
  34. package/dist/{rate-limits-DZXmOL8-.js → rate-limits-hFtzt2Up.js} +1 -1
  35. package/dist/{sandbox-guard-Cmwc9eIk.js → request-CCm4LaED.js} +207 -20
  36. package/dist/{run-attempt-P8BdxC1I.js → run-attempt-BwNQDH2u.js} +1506 -836
  37. package/dist/{runtime-artifact-BVSPdd6g.js → runtime-artifact-DeBvleJw.js} +4 -7
  38. package/dist/session-binding-q2WSTVmC.js +947 -0
  39. package/dist/{session-catalog-xwNi_SDM.js → session-catalog-C2Tae4rI.js} +1698 -1346
  40. package/dist/session-catalog-home-id-DAKUrm3C.js +112 -0
  41. package/dist/{session-cli-7hgXZDV7.js → session-cli-BuDjm5Ou.js} +20 -7
  42. package/dist/session-permission-policy-gLm40Vtq.js +160 -0
  43. package/dist/session-retirement-CdkI0bvb.js +90 -0
  44. package/dist/{session-upstream-marker-CrIFX06J.js → session-upstream-marker-Bcy33kam.js} +2 -3
  45. package/dist/{settled-turn-finalizer-BRWBO4MO.js → settled-turn-finalizer-B8JJcxCi.js} +27 -22
  46. package/dist/{shared-client-kIBbGjk4.js → shared-client-kNkljY-R.js} +2023 -607
  47. package/dist/{side-question-9HAL26l9.js → side-question-GwD73tX6.js} +109 -57
  48. package/dist/{thread-lifecycle-Bu1BTDXr.js → thread-lifecycle-Ss-uwnC4.js} +1208 -497
  49. package/dist/{thread-ownership-6kOQHlyC.js → thread-ownership-CeYBqg_4.js} +18 -8
  50. package/dist/{plugin-app-cache-key-C3H2CVp6.js → thread-resume-DF54hagX.js} +64 -6
  51. package/dist/{transcript-mirror-B9gGgnJS.js → transcript-mirror-CkEQIna-.js} +158 -41
  52. package/dist/transport-stdio-C7-s9TLG.js +708 -0
  53. package/dist/{upstream-prompt-provenance-ClRBije0.js → upstream-prompt-provenance-CFmsKwr9.js} +12 -14
  54. package/dist/{upstream-session-fork-CE-_LdnP.js → upstream-session-fork-BACGlOFa.js} +86 -88
  55. package/dist/{usage-CHlV0e-o.js → usage-C2l8Mils.js} +3 -3
  56. package/dist/{web-search-provider.runtime-DRw2Vl42.js → web-search-provider.runtime-B2XgRdFv.js} +3 -3
  57. package/openclaw.plugin.json +50 -2
  58. package/package.json +9 -8
  59. package/dist/app-server-policy-zcBDc1JU.js +0 -49
  60. package/dist/incognito-session-ET_ufDH-.js +0 -2
  61. package/dist/request-BRl5_UfX.js +0 -157
  62. package/dist/session-retirement-DoMMJFKm.js +0 -36
  63. package/dist/thread-resume-CPrJNQVM.js +0 -30
  64. package/dist/transport-stdio-DIImwDVS.js +0 -99
@@ -1,12 +1,12 @@
1
+ import { asOptionalRecord } from "openclaw/plugin-sdk/string-coerce-runtime";
1
2
  //#region extensions/codex/src/app-server/upstream-prompt-provenance.ts
2
3
  const UPSTREAM_USER_TEXT_META_KEY = "upstreamUserText";
3
4
  const MIRROR_IDENTITY_META_KEY = "mirrorIdentity";
5
+ const CODEX_META_KEY = "__openclaw";
4
6
  function attachCodexMirrorIdentity(message, identity) {
5
- const record = message;
6
- const existing = record["__openclaw"];
7
- const baseMeta = existing && typeof existing === "object" && !Array.isArray(existing) ? existing : {};
7
+ const baseMeta = asOptionalRecord(CODEX_META_KEY in message ? message[CODEX_META_KEY] : void 0) ?? {};
8
8
  return {
9
- ...record,
9
+ ...message,
10
10
  __openclaw: {
11
11
  ...baseMeta,
12
12
  [MIRROR_IDENTITY_META_KEY]: identity
@@ -14,17 +14,15 @@ function attachCodexMirrorIdentity(message, identity) {
14
14
  };
15
15
  }
16
16
  function readMirrorIdentity(message) {
17
- const meta = message["__openclaw"];
18
- if (!meta || typeof meta !== "object" || Array.isArray(meta)) return;
19
- const id = meta[MIRROR_IDENTITY_META_KEY];
17
+ const record = asOptionalRecord(CODEX_META_KEY in message ? message[CODEX_META_KEY] : void 0);
18
+ if (!record) return;
19
+ const id = record[MIRROR_IDENTITY_META_KEY];
20
20
  return typeof id === "string" && id ? id : void 0;
21
21
  }
22
22
  function attachUpstreamUserText(message, text) {
23
- const record = message;
24
- const existing = record["__openclaw"];
25
- const baseMeta = existing && typeof existing === "object" && !Array.isArray(existing) ? existing : {};
23
+ const baseMeta = asOptionalRecord(CODEX_META_KEY in message ? message[CODEX_META_KEY] : void 0) ?? {};
26
24
  return {
27
- ...record,
25
+ ...message,
28
26
  __openclaw: {
29
27
  ...baseMeta,
30
28
  [UPSTREAM_USER_TEXT_META_KEY]: text
@@ -32,9 +30,9 @@ function attachUpstreamUserText(message, text) {
32
30
  };
33
31
  }
34
32
  function readUpstreamUserText(message) {
35
- const meta = message?.["__openclaw"];
36
- if (!meta || typeof meta !== "object" || Array.isArray(meta)) return;
37
- const text = meta[UPSTREAM_USER_TEXT_META_KEY];
33
+ const record = asOptionalRecord(message && CODEX_META_KEY in message ? message[CODEX_META_KEY] : void 0);
34
+ if (!record) return;
35
+ const text = record[UPSTREAM_USER_TEXT_META_KEY];
38
36
  return typeof text === "string" && text ? text : void 0;
39
37
  }
40
38
  //#endregion
@@ -1,7 +1,8 @@
1
- import { d as sessionBindingIdentity } from "./session-binding-DPxIvMgE.js";
2
- import { r as assertCodexThreadForkResponse } from "./protocol-validators-B4F7L8Rf.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-CrIFX06J.js";
1
+ import { d as sessionBindingIdentity } from "./session-binding-q2WSTVmC.js";
2
+ import { a as assertCodexThreadForkResponse } from "./protocol-validators-Bg5rpNxk.js";
3
+ import { i as readUpstreamUserText, r as readMirrorIdentity } from "./upstream-prompt-provenance-CFmsKwr9.js";
4
+ import { c as fingerprintCodexMirrorSourceMessage, l as readCodexMirrorSourceFingerprint, p as projectCodexUserItemText } from "./transcript-mirror-CkEQIna-.js";
5
+ import { i as createImportedCodexSession, n as codexUpstreamBaseline, t as codexLastTerminalTurnId } from "./session-upstream-marker-Bcy33kam.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";
@@ -17,31 +18,6 @@ function failure(code, message) {
17
18
  function asInputs(item) {
18
19
  return Array.isArray(item.content) ? item.content : [];
19
20
  }
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
21
  function localMessageText(content) {
46
22
  if (typeof content === "string") return content;
47
23
  if (!Array.isArray(content)) return;
@@ -52,37 +28,35 @@ function localMessageText(content) {
52
28
  if (typed.type !== "text" || typeof typed.text !== "string") return;
53
29
  texts.push(typed.text);
54
30
  }
55
- return texts.join("");
31
+ return texts.join("\n");
56
32
  }
57
33
  function resolveCodexUpstreamForkBoundaryFromTurns(params) {
58
- let visibleUserMessagesSeen = 0;
59
- let reviewMode = false;
34
+ let localIndex = 0;
35
+ let matchedPrefix = false;
60
36
  for (const [turnIndex, turn] of params.turns.entries()) {
61
- const hiddenNestedReviewTurn = isHiddenNestedReviewTurn(params.turns[turnIndex - 1], turn);
62
37
  let userMessagesInTurn = 0;
63
38
  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
39
  if (item.type !== "userMessage") continue;
73
40
  const isSteer = userMessagesInTurn > 0;
74
41
  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;
42
+ if (asInputs(item).some((input) => input.type !== "text")) 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.");
43
+ const text = projectCodexUserItemText(item);
44
+ if (!text) continue;
45
+ const local = params.localPrefix[localIndex];
46
+ const identity = local && readMirrorIdentity(local.message);
47
+ const matchesIdentity = identity === `${turn.id}:${item.id}` || !isSteer && identity === `${turn.id}:prompt`;
48
+ if (!matchedPrefix && !matchesIdentity) continue;
49
+ matchedPrefix = true;
50
+ const localText = localMessageText(local && "content" in local.message ? local.message.content : void 0);
51
+ const upstreamText = local && readUpstreamUserText(local.message);
52
+ const upstreamPromptVerified = !upstreamText || local?.message.role === "user" && readCodexMirrorSourceFingerprint(local.message) === fingerprintCodexMirrorSourceMessage(local.message);
53
+ const expectedText = upstreamText ? projectCodexUserItemText({ content: [{
54
+ type: "text",
55
+ text: upstreamText
56
+ }] }) : localText;
57
+ if (!matchesIdentity || !upstreamPromptVerified || localText === void 0 || text !== expectedText) return failure("drift-mismatch", "The local conversation no longer matches the Codex thread. Refresh the session and try again.");
58
+ if (localIndex < params.localPrefix.length - 1) {
59
+ localIndex += 1;
86
60
  continue;
87
61
  }
88
62
  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 +78,7 @@ function resolveCodexUpstreamForkBoundaryFromTurns(params) {
104
78
  };
105
79
  }
106
80
  }
107
- return failure("drift-mismatch", "The message could not be matched to the Codex thread. Refresh the session and try again.");
81
+ return failure("drift-mismatch", "The local history has no verified boundary in this Codex thread. Use native Codex to fork this conversation.");
108
82
  }
109
83
  async function listCodexUpstreamTurns(control, threadId) {
110
84
  const turns = [];
@@ -128,24 +102,23 @@ async function listCodexUpstreamTurns(control, threadId) {
128
102
  }
129
103
  async function resolveCodexUpstreamForkBoundary(params) {
130
104
  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
105
  const visibleUserEntries = (await readVisibleSessionTranscriptMessageEntries({
133
106
  agentId: params.agentId,
134
107
  sessionId: params.sessionId,
135
108
  sessionKey: params.sessionKey,
136
109
  storePath: params.storePath
137
110
  })).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));
111
+ const targetIndex = visibleUserEntries.findIndex((entry) => entry.entryId === params.entryId);
112
+ if (targetIndex < 0) return failure("drift-mismatch", "The local message could not be mapped to the Codex thread. Refresh the session and try again.");
113
+ const localPrefix = visibleUserEntries.slice(0, targetIndex + 1);
141
114
  const resolved = resolveCodexUpstreamForkBoundaryFromTurns({
142
115
  turns: await listCodexUpstreamTurns(params.control, params.threadId),
143
- userMessageOrdinal,
144
- localPrefixTexts
116
+ localPrefix
145
117
  });
118
+ const target = localPrefix.at(-1)?.message;
146
119
  return resolved.ok ? {
147
120
  ...resolved,
148
- editorText: localPrefixTexts[userMessageOrdinal]
121
+ editorText: localMessageText(target && "content" in target ? target.content : void 0)
149
122
  } : resolved;
150
123
  } catch {
151
124
  return failure("upstream-unavailable", "The Codex thread could not be read. Check that Codex is available, then try again.");
@@ -166,34 +139,43 @@ function readConnectionFingerprint(ref) {
166
139
  if (!isRecord(ref)) return;
167
140
  return typeof ref.connectionFingerprint === "string" && ref.connectionFingerprint.trim() ? ref.connectionFingerprint : void 0;
168
141
  }
169
- function normalizeTurnId(value) {
170
- return normalizeOptionalString(value);
171
- }
172
142
  async function forkCodexUpstreamSession(params, options) {
173
143
  try {
174
- return await options.control.withPinnedConnection(async (control) => {
175
- const incognito = isIncognitoSessionKey(params.targetKey);
176
- const clientId = control.clientId?.trim();
177
- if (incognito && !clientId) throw new Error("Incognito Codex forks require the live pinned app-server client");
144
+ const sourceFingerprint = params.upstream.kind === "codex-app-server" ? readConnectionFingerprint(params.upstream.ref) : void 0;
145
+ const requestControl = sourceFingerprint ? options.controlFactory.forUpstream(params.source.agentId, sourceFingerprint) : void 0;
146
+ if (!sourceFingerprint || !requestControl) return {
147
+ status: "failed",
148
+ code: "upstream-unavailable",
149
+ message: "This Codex thread is not available on the current connection. Reconnect to its host and try again."
150
+ };
151
+ return await requestControl.withPinnedConnection(async (control) => {
152
+ const sourceBinding = await options.bindingStore.read(sessionBindingIdentity({
153
+ ...params.source,
154
+ config: options.resolveConfig?.()
155
+ }));
156
+ const supervised = sourceBinding?.connectionScope === "supervision";
157
+ const sourceThreadId = params.upstream.threadId;
178
158
  let linked = false;
179
- let bindingIdentity;
159
+ let createdBinding;
180
160
  const compensateFork = async (forkedThreadId) => {
181
- if (bindingIdentity) await options.bindingStore.mutate(bindingIdentity, {
182
- kind: "clear",
183
- threadId: forkedThreadId
184
- }).catch(() => void 0);
161
+ if (createdBinding) {
162
+ if (!await options.bindingStore.mutate(createdBinding.identity, {
163
+ kind: "clear",
164
+ threadId: forkedThreadId,
165
+ expectedPendingSupervisionBranch: createdBinding.pending
166
+ }).catch(() => false)) return;
167
+ }
185
168
  if (linked) deleteSessionUpstreamLink(params.targetKey, params.source.agentId);
186
169
  await control.archiveThread(forkedThreadId).catch(() => void 0);
187
170
  };
188
- const sourceFingerprint = readConnectionFingerprint(params.upstream.ref);
189
- if (params.upstream.kind !== "codex-app-server" || !sourceFingerprint || sourceFingerprint !== control.connectionFingerprint) return {
171
+ if (sourceFingerprint !== control.connectionFingerprint || supervised && (sourceBinding.supervisionSourceThreadId !== params.upstream.threadId || (sourceBinding.pendingSupervisionBranch?.connectionFingerprint ?? sourceBinding.appServerRuntimeFingerprint) !== sourceFingerprint)) return {
190
172
  status: "failed",
191
173
  code: "upstream-unavailable",
192
174
  message: "This Codex thread is not available on the current connection. Reconnect to its host and try again."
193
175
  };
194
176
  const resolved = await resolveCodexUpstreamForkBoundary({
195
177
  ...params.source,
196
- threadId: params.upstream.threadId,
178
+ threadId: sourceThreadId,
197
179
  control
198
180
  });
199
181
  if (!resolved.ok) return {
@@ -201,7 +183,7 @@ async function forkCodexUpstreamSession(params, options) {
201
183
  code: resolved.code,
202
184
  message: resolved.message
203
185
  };
204
- const liveTurns = await listCodexUpstreamTurns(control, params.upstream.threadId);
186
+ const liveTurns = await listCodexUpstreamTurns(control, sourceThreadId);
205
187
  const precheck = precheckCodexUpstreamForkBoundary({
206
188
  boundary: resolved.boundary,
207
189
  turns: liveTurns
@@ -212,27 +194,27 @@ async function forkCodexUpstreamSession(params, options) {
212
194
  message: precheck.message
213
195
  };
214
196
  const rawResponse = await control.forkThread({
215
- threadId: params.upstream.threadId,
197
+ threadId: sourceThreadId,
216
198
  beforeTurnId: resolved.boundary.beforeTurnId,
217
- ...incognito ? { ephemeral: true } : {},
218
- excludeTurns: !incognito
199
+ ...params.sandbox === "required" ? { sandbox: "workspace-write" } : {},
200
+ excludeTurns: true
219
201
  });
220
202
  let response;
221
203
  try {
222
204
  response = assertCodexThreadForkResponse(rawResponse);
223
205
  } catch (error) {
224
206
  const orphanThreadId = isRecord(rawResponse.thread) && typeof rawResponse.thread.id === "string" ? rawResponse.thread.id.trim() : "";
225
- if (orphanThreadId && orphanThreadId !== params.upstream.threadId) await control.archiveThread(orphanThreadId).catch(() => void 0);
207
+ if (orphanThreadId && orphanThreadId !== sourceThreadId && orphanThreadId !== sourceBinding?.threadId) await control.archiveThread(orphanThreadId).catch(() => void 0);
226
208
  throw error;
227
209
  }
228
210
  const threadId = response.thread.id.trim();
229
211
  if (!threadId) throw new Error("Codex thread/fork response did not include a thread id");
230
- if (threadId === params.upstream.threadId) throw new Error("Codex thread/fork response reused the source thread id");
212
+ if (threadId === sourceThreadId || threadId === sourceBinding?.threadId) throw new Error("Codex thread/fork response reused the source thread id");
231
213
  const forkedThreadId = threadId;
232
214
  try {
233
- const connectionFingerprint = control.connectionFingerprint;
215
+ const connectionFingerprint = normalizeOptionalString(control.connectionFingerprint);
234
216
  if (!connectionFingerprint) throw new Error("Codex fork connection did not include a fingerprint");
235
- const forkedTurns = incognito ? response.thread.turns ?? [] : await listCodexUpstreamTurns(control, threadId);
217
+ const forkedTurns = await listCodexUpstreamTurns(control, threadId);
236
218
  const expectedLastTurnId = resolved.boundary.retainedMarker.turnId;
237
219
  if ((forkedTurns.at(-1)?.id ?? null) !== expectedLastTurnId) {
238
220
  await compensateFork(forkedThreadId);
@@ -246,8 +228,8 @@ async function forkCodexUpstreamSession(params, options) {
246
228
  ...response.thread,
247
229
  turns: forkedTurns
248
230
  };
249
- const throughTurnId = codexLastTerminalTurnId(forkedThread, normalizeTurnId) ?? null;
250
- const marker = codexUpstreamBaseline(forkedThread, normalizeTurnId);
231
+ const throughTurnId = codexLastTerminalTurnId(forkedThread, normalizeOptionalString) ?? null;
232
+ const marker = codexUpstreamBaseline(forkedThread, normalizeOptionalString);
251
233
  const config = options.resolveConfig?.() ?? {};
252
234
  return {
253
235
  status: "created",
@@ -263,7 +245,7 @@ async function forkCodexUpstreamSession(params, options) {
263
245
  modelSelectionLocked: true
264
246
  },
265
247
  afterImport: async (entry) => {
266
- bindingIdentity = sessionBindingIdentity({
248
+ const bindingIdentity = sessionBindingIdentity({
267
249
  agentId: entry.agentId,
268
250
  sessionId: entry.sessionId,
269
251
  sessionKey: entry.key,
@@ -283,17 +265,33 @@ async function forkCodexUpstreamSession(params, options) {
283
265
  marker
284
266
  });
285
267
  if (!linked) throw new Error("Codex fork link could not be persisted");
268
+ createdBinding = {
269
+ identity: bindingIdentity,
270
+ pending: {
271
+ sourceThreadId: threadId,
272
+ connectionFingerprint,
273
+ ...throughTurnId ? { lastTurnId: throughTurnId } : {}
274
+ }
275
+ };
286
276
  if (!await options.bindingStore.mutate(bindingIdentity, {
287
277
  kind: "set",
278
+ if: { kind: "absent" },
288
279
  binding: {
289
280
  threadId,
290
- ...incognito && clientId ? { clientId } : {},
281
+ connectionScope: "supervision",
282
+ supervisionSourceThreadId: threadId,
283
+ preserveNativeModel: true,
284
+ conversationSourceTransferComplete: true,
285
+ pendingSupervisionBranch: createdBinding.pending,
291
286
  cwd: forkedThread.cwd ?? "",
292
287
  model: response.model,
293
288
  modelProvider: response.modelProvider ?? void 0,
294
289
  historyCoveredThrough: (/* @__PURE__ */ new Date()).toISOString()
295
290
  }
296
- })) throw new Error("Codex session binding changed before the fork could be attached");
291
+ })) {
292
+ createdBinding = void 0;
293
+ throw new Error("Codex session binding changed before the fork could be attached");
294
+ }
297
295
  return { pluginExtensions: entry.entry.pluginExtensions };
298
296
  }
299
297
  })).key,
@@ -1,6 +1,6 @@
1
- import { g as resolveCodexAppServerRuntimeOptions } from "./session-binding-DPxIvMgE.js";
2
- import { t as buildCodexAppServerUsageSnapshot } from "./rate-limits-DZXmOL8-.js";
3
- import { t as readCodexAppServerUsage } from "./request-BRl5_UfX.js";
1
+ import { i as resolveCodexAppServerRuntimeOptions } from "./config-Cxw3Cl3k.js";
2
+ import { n as readCodexAppServerUsage } from "./request-CCm4LaED.js";
3
+ import { t as buildCodexAppServerUsageSnapshot } from "./rate-limits-hFtzt2Up.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 { ct as isJsonObject } from "./shared-client-kIBbGjk4.js";
2
- import { d as buildCodexNativeWebSearchThreadConfig } from "./thread-lifecycle-Bu1BTDXr.js";
3
- import { t as runBoundedCodexAppServerTurn } from "./bounded-turn-qgZmzy_4.js";
1
+ import { Ht as isJsonObject } from "./shared-client-kNkljY-R.js";
2
+ import { b as buildCodexNativeWebSearchThreadConfig } from "./thread-lifecycle-Ss-uwnC4.js";
3
+ import { t as runBoundedCodexAppServerTurn } from "./bounded-turn-rq5tiSXk.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",
@@ -16,6 +34,13 @@
16
34
  ],
17
35
  "name": "Codex",
18
36
  "description": "Codex app-server harness and native session catalog.",
37
+ "cliCommands": [
38
+ {
39
+ "name": "codex",
40
+ "description": "Inspect and branch from Codex sessions through the Gateway",
41
+ "hasSubcommands": true
42
+ }
43
+ ],
19
44
  "contracts": {
20
45
  "mediaUnderstandingProviders": ["codex"],
21
46
  "migrationProviders": ["codex"],
@@ -45,6 +70,7 @@
45
70
  "onConfigPaths": [
46
71
  "plugins.entries.codex.config.appServer.transport",
47
72
  "plugins.entries.codex.config.sessionCatalog.enabled",
73
+ "plugins.entries.codex.config.sessionCatalog.homes",
48
74
  "plugins.entries.codex.config.supervision.enabled"
49
75
  ]
50
76
  },
@@ -73,7 +99,24 @@
73
99
  "type": "object",
74
100
  "additionalProperties": false,
75
101
  "properties": {
76
- "enabled": { "type": "boolean", "default": true }
102
+ "enabled": { "type": "boolean", "default": true },
103
+ "homes": {
104
+ "type": "array",
105
+ "items": {
106
+ "anyOf": [
107
+ { "type": "string", "minLength": 1, "pattern": "\\S" },
108
+ {
109
+ "type": "object",
110
+ "additionalProperties": false,
111
+ "required": ["path"],
112
+ "properties": {
113
+ "path": { "type": "string", "minLength": 1, "pattern": "\\S" },
114
+ "label": { "type": "string", "minLength": 1, "pattern": "\\S" }
115
+ }
116
+ }
117
+ ]
118
+ }
119
+ }
77
120
  }
78
121
  },
79
122
  "discovery": {
@@ -392,6 +435,11 @@
392
435
  "label": "Discover Codex Sessions",
393
436
  "help": "List native Codex sessions in the sidebar from this Gateway and eligible paired nodes."
394
437
  },
438
+ "sessionCatalog.homes": {
439
+ "label": "Additional Codex Homes",
440
+ "help": "Existing local Codex home directories to include in native session discovery. String paths use the canonical directory basename as their label; object entries can override it with label. Paths are canonicalized and deduplicated. Requires appServer.transport=stdio and a Gateway restart.",
441
+ "advanced": true
442
+ },
395
443
  "codexDynamicToolsLoading": {
396
444
  "label": "Dynamic Tools Loading",
397
445
  "help": "Use searchable to defer OpenClaw dynamic tools behind Codex tool search, or direct to expose them in the initial context.",
@@ -467,7 +515,7 @@
467
515
  },
468
516
  "computerUse.autoRepair": {
469
517
  "label": "Auto Repair",
470
- "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.",
471
519
  "advanced": true
472
520
  },
473
521
  "computerUse.marketplaceSource": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openclaw/codex",
3
- "version": "2026.8.1-beta.2",
3
+ "version": "2026.8.1",
4
4
  "description": "OpenClaw Codex app-server harness and native session supervision plugin.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -8,10 +8,11 @@
8
8
  },
9
9
  "type": "module",
10
10
  "dependencies": {
11
- "@openai/codex": "0.147.0",
12
- "smol-toml": "1.7.1",
13
- "typebox": "1.3.6",
14
- "ws": "8.21.1",
11
+ "@openai/codex": "0.151.0",
12
+ "semver": "7.8.5",
13
+ "smol-toml": "1.8.0",
14
+ "typebox": "1.3.16",
15
+ "ws": "8.21.3",
15
16
  "zod": "4.4.3"
16
17
  },
17
18
  "devDependencies": {
@@ -35,10 +36,10 @@
35
36
  ]
36
37
  },
37
38
  "compat": {
38
- "pluginApi": ">=2026.8.1-beta.2"
39
+ "pluginApi": ">=2026.8.1"
39
40
  },
40
41
  "build": {
41
- "openclawVersion": "2026.8.1-beta.2"
42
+ "openclawVersion": "2026.8.1"
42
43
  },
43
44
  "release": {
44
45
  "publishToClawHub": true,
@@ -58,7 +59,7 @@
58
59
  "README.md"
59
60
  ],
60
61
  "peerDependencies": {
61
- "openclaw": ">=2026.8.1-beta.2"
62
+ "openclaw": ">=2026.8.1"
62
63
  },
63
64
  "peerDependenciesMeta": {
64
65
  "openclaw": {
@@ -1,49 +0,0 @@
1
- import { k as canUseCodexModelBackedApprovalsReviewerForModel } from "./session-binding-DPxIvMgE.js";
2
- //#region extensions/codex/src/app-server/app-server-policy.ts
3
- /**
4
- * Policy promotion for Codex app-server runs that can safely use OpenClaw tool
5
- * approvals.
6
- */
7
- /**
8
- * Promotes implicit `never` approval policy to `untrusted` only when runtime
9
- * requirements allow OpenClaw to handle tool approvals.
10
- */
11
- function resolveCodexAppServerForOpenClawToolPolicy(params) {
12
- if (!params.shouldPromote || !params.canUseUntrustedApprovalPolicy || params.appServer.approvalPolicy !== "never") return params.appServer;
13
- const explicitMode = params.execPolicy?.mode === "full" || params.pluginConfig.appServer?.mode !== void 0 || isCodexAppServerPolicyMode(params.env.OPENCLAW_CODEX_APP_SERVER_MODE);
14
- const explicitApprovalPolicy = params.pluginConfig.appServer?.approvalPolicy !== void 0 || isConfiguredCodexAppServerApprovalPolicy(params.env.OPENCLAW_CODEX_APP_SERVER_APPROVAL_POLICY) || params.appServer.approvalPolicySource === "requirements";
15
- if (explicitMode || explicitApprovalPolicy) return params.appServer;
16
- return {
17
- ...params.appServer,
18
- approvalPolicy: "untrusted"
19
- };
20
- }
21
- function resolveCodexAppServerForModelProvider(params) {
22
- const explicitProvider = normalizeModelBackedReviewerProvider(params.provider);
23
- if (!isCodexModelBackedApprovalsReviewer(params.appServer.approvalsReviewer) || canUseCodexModelBackedApprovalsReviewerForModel({
24
- modelProvider: explicitProvider,
25
- model: params.model,
26
- config: params.config,
27
- env: params.env,
28
- agentDir: params.agentDir,
29
- codexConfigToml: params.codexConfigToml
30
- })) return params.appServer;
31
- return {
32
- ...params.appServer,
33
- approvalsReviewer: "user"
34
- };
35
- }
36
- function isCodexAppServerPolicyMode(value) {
37
- return value === "guardian" || value === "yolo";
38
- }
39
- function isConfiguredCodexAppServerApprovalPolicy(value) {
40
- return value === "never" || value === "on-request" || value === "on-failure" || value === "untrusted";
41
- }
42
- function isCodexModelBackedApprovalsReviewer(value) {
43
- return value === "auto_review" || value === "guardian_subagent";
44
- }
45
- function normalizeModelBackedReviewerProvider(provider) {
46
- return provider?.trim().toLowerCase() || void 0;
47
- }
48
- //#endregion
49
- export { resolveCodexAppServerForOpenClawToolPolicy as n, resolveCodexAppServerForModelProvider as t };
@@ -1,2 +0,0 @@
1
- import { isIncognitoSessionKey } from "openclaw/plugin-sdk/routing";
2
- export { isIncognitoSessionKey as t };