@openclaw/codex 2026.7.2-beta.7 → 2026.7.34
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -27
- package/dist/{command-formatters-C336eRVS.js → .setup/app-server-policy-C_qTMEMy.mjs} +51 -9
- package/dist/{attempt-notifications-AP-a-Q5k.js → .setup/attempt-notifications-F8krwWL4.mjs} +6 -3
- package/dist/{command-handlers-DAHUSry9.js → .setup/command-handlers-DSRFfor4.mjs} +1156 -1319
- package/dist/.setup/command-rpc-BvYsfQ7G.mjs +786 -0
- package/dist/{compact-D_uvHurS.js → .setup/compact-BNgh7I4t.mjs} +10 -40
- package/dist/.setup/computer-use-C3QkmSO3.mjs +377 -0
- package/dist/.setup/config-CYEDnLJ2.mjs +1138 -0
- package/dist/{conversation-binding-data-BHRpYbX3.js → .setup/conversation-binding-data-CrRxtDBu.mjs} +1 -1
- package/dist/{bounded-turn-D2ZAgZVz.js → .setup/media-understanding-provider-EbJCyDqe.mjs} +203 -109
- package/dist/{models-BBMKU4jA.js → .setup/models-C_aZk03A.mjs} +11 -6
- package/dist/.setup/notification-correlation-iYs4WieS.mjs +35 -0
- package/dist/.setup/plugin-app-cache-key-DR8jV9oS.mjs +99 -0
- package/dist/.setup/protocol-2POPqAY4.mjs +13 -0
- package/dist/{transcript-mirror-DzsdNCf5.js → .setup/protocol-validators-dZQ-UTOa.mjs} +112 -922
- package/dist/{rate-limits-CU-gVCCS.js → .setup/provider-DGxDs6g8.mjs} +269 -13
- package/dist/{dynamic-tools-D2gYkSBO.js → .setup/provider-capabilities-DS2N_zc1.mjs} +5632 -3953
- package/dist/.setup/request-DFR0JyoV.mjs +36 -0
- package/dist/.setup/run-attempt-C7xEKFVB.mjs +8180 -0
- package/dist/{sandbox-guard-NuhpXmPB.js → .setup/sandbox-guard-DA2TQfZW.mjs} +1 -14
- package/dist/.setup/session-binding-DuihlMJc.mjs +628 -0
- package/dist/.setup/shared-client-B2KmLPRw.mjs +1854 -0
- package/dist/{side-question-_ulBk1AL.js → .setup/side-question-Cv6JXWCS.mjs} +84 -159
- package/dist/.setup/thread-lifecycle-u6CZdOOH.mjs +2593 -0
- package/dist/{web-search-provider.runtime-CCFhg2z5.js → .setup/web-search-provider.runtime-Ce2zOHxW.mjs} +3 -3
- package/dist/doctor-contract-api.js +122 -88
- package/dist/harness.js +20 -89
- package/dist/index.js +436 -1615
- package/dist/media-understanding-provider.js +1 -173
- package/dist/prompt-overlay.js +15 -0
- package/dist/provider-catalog.js +79 -0
- package/dist/provider-discovery.js +34 -0
- package/dist/provider.js +2 -0
- package/dist/web-search-contract-api.js +1 -1
- package/openclaw.plugin.json +178 -221
- package/package.json +8 -9
- package/dist/app-server-policy-BSaO2JIT.js +0 -49
- package/dist/auth-binding-B4FfbcCg.js +0 -62
- package/dist/capabilities-BFDTVYr4.js +0 -36
- package/dist/cli-metadata.js +0 -20
- package/dist/computer-use-CYEc8U3w.js +0 -693
- package/dist/conversation-control-xsIeXbo4.js +0 -287
- package/dist/effective-mcp-catalog-Bbd98Inw.js +0 -114
- package/dist/event-projector-assistant-message-DTgnPPVF.js +0 -101
- package/dist/event-projector-usage-Xp4AlR2k.js +0 -86
- package/dist/incognito-session-ET_ufDH-.js +0 -2
- package/dist/notification-correlation-CU6_AnOb.js +0 -67
- package/dist/plugin-app-cache-key-DztPafOA.js +0 -408
- package/dist/request-qKh331yu.js +0 -157
- package/dist/run-attempt-CY9WlDLc.js +0 -12413
- package/dist/runtime-artifact-CmtG_t1L.js +0 -554
- package/dist/session-binding-BXpo9ymA.js +0 -2214
- package/dist/session-catalog-DyOgR4WH.js +0 -2668
- package/dist/session-cli-2PZaFLRh.js +0 -175
- package/dist/session-upstream-marker-B6U7tLw5.js +0 -82
- package/dist/settled-turn-finalizer-CXY2Z9dT.js +0 -316
- package/dist/shared-client-DTbvH-XV.js +0 -3069
- package/dist/thread-lifecycle-DF53ogiA.js +0 -3987
- package/dist/transport-stdio-DXgGZ7Ib.js +0 -88
- package/dist/upstream-session-fork-Dy4Xvuoj.js +0 -320
- package/dist/usage-CQ6GhD5-.js +0 -25
- /package/dist/{rolldown-runtime-8H4AJuhK.js → .setup/rolldown-runtime-8H4AJuhK.mjs} +0 -0
- /package/dist/{session-binding-meta-B7aEMU7g.js → .setup/session-binding-meta-B7aEMU7g.mjs} +0 -0
- /package/dist/{web-search-provider.shared-BrZmlqyR.js → .setup/web-search-provider.shared-BrZmlqyR.mjs} +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { r as isJsonObject } from "./protocol-2POPqAY4.mjs";
|
|
2
|
+
import { _ as buildCodexNativeWebSearchThreadConfig } from "./thread-lifecycle-u6CZdOOH.mjs";
|
|
3
|
+
import { n as runBoundedCodexAppServerTurn } from "./media-understanding-provider-EbJCyDqe.mjs";
|
|
4
4
|
import { readStringParam, resolveSearchTimeoutSeconds, wrapWebContent } from "openclaw/plugin-sdk/provider-web-search";
|
|
5
5
|
//#region extensions/codex/src/web-search-provider.runtime.ts
|
|
6
6
|
async function executeCodexWebSearchProviderTool(ctx, args, executionContext, options) {
|
|
@@ -1,13 +1,10 @@
|
|
|
1
|
-
import { n as CODEX_APP_SERVER_BINDING_NAMESPACE, t as CODEX_APP_SERVER_BINDING_MAX_ENTRIES } from "
|
|
1
|
+
import { n as CODEX_APP_SERVER_BINDING_NAMESPACE, t as CODEX_APP_SERVER_BINDING_MAX_ENTRIES } from "./.setup/session-binding-meta-B7aEMU7g.mjs";
|
|
2
2
|
import fs from "node:fs/promises";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { listAgentIds, resolveAgentDir, resolveSessionAgentIds } from "openclaw/plugin-sdk/agent-runtime";
|
|
5
5
|
import { isDeepStrictEqual } from "node:util";
|
|
6
|
-
import {
|
|
7
|
-
import { patchSessionEntry, resolveStorePath } from "openclaw/plugin-sdk/session-store-runtime";
|
|
8
|
-
import { canonicalPathFromExistingAncestor, isPathInside, pathExists } from "openclaw/plugin-sdk/security-runtime";
|
|
6
|
+
import { listSessionEntries, resolveSessionFilePath, resolveStorePath, updateSessionStoreEntry } from "openclaw/plugin-sdk/session-store-runtime";
|
|
9
7
|
import { withFileLock } from "openclaw/plugin-sdk/file-lock";
|
|
10
|
-
import { archiveLegacyStateSource, legacyStateFileExists } from "openclaw/plugin-sdk/runtime-doctor";
|
|
11
8
|
//#region extensions/codex/src/migration/session-binding-sidecars.ts
|
|
12
9
|
const LEGACY_BINDING_SUFFIX = ".codex-app-server.json";
|
|
13
10
|
const CODEX_AGENT_HARNESS_ID = "codex";
|
|
@@ -23,9 +20,9 @@ const LEGACY_BINDING_LOCK_OPTIONS = {
|
|
|
23
20
|
};
|
|
24
21
|
async function collectSessionSurfaces(params) {
|
|
25
22
|
const surfaces = /* @__PURE__ */ new Map();
|
|
26
|
-
const stateRoot = await
|
|
23
|
+
const stateRoot = await canonicalizePath(params.stateDir);
|
|
27
24
|
const add = async (root, storePath, agentId, scan) => {
|
|
28
|
-
const canonicalRoot = await
|
|
25
|
+
const canonicalRoot = await canonicalizePath(root);
|
|
29
26
|
const surface = surfaces.get(canonicalRoot) ?? {
|
|
30
27
|
root: canonicalRoot,
|
|
31
28
|
scan: false,
|
|
@@ -55,7 +52,7 @@ async function collectSessionSurfaces(params) {
|
|
|
55
52
|
env: params.env
|
|
56
53
|
});
|
|
57
54
|
const root = path.dirname(storePath);
|
|
58
|
-
await add(root, storePath, agentId,
|
|
55
|
+
await add(root, storePath, agentId, isPathWithin(stateRoot, await canonicalizePath(root)));
|
|
59
56
|
}
|
|
60
57
|
const legacyRoot = path.join(params.stateDir, "sessions");
|
|
61
58
|
const defaultAgentId = resolveSessionAgentIds({ config: params.config }).defaultAgentId;
|
|
@@ -66,7 +63,7 @@ async function collectLegacyBindingSources(params, options = {}) {
|
|
|
66
63
|
const surfaces = await collectSessionSurfaces(params);
|
|
67
64
|
const sources = /* @__PURE__ */ new Map();
|
|
68
65
|
const addSource = async (sidecarPath, surface) => {
|
|
69
|
-
const canonicalSidecar = await
|
|
66
|
+
const canonicalSidecar = await canonicalizePath(sidecarPath);
|
|
70
67
|
const source = sources.get(canonicalSidecar) ?? {
|
|
71
68
|
sidecarPath: canonicalSidecar,
|
|
72
69
|
transcriptPath: sidecarPath.slice(0, -22),
|
|
@@ -77,7 +74,7 @@ async function collectLegacyBindingSources(params, options = {}) {
|
|
|
77
74
|
return source;
|
|
78
75
|
};
|
|
79
76
|
for (const surface of surfaces) {
|
|
80
|
-
const sidecars = surface.scan ? walkSidecars(surface.root) : iterateIndexedSidecars(surface);
|
|
77
|
+
const sidecars = surface.scan ? walkSidecars(surface.root) : iterateIndexedSidecars(surface, params);
|
|
81
78
|
for await (const sidecarPath of sidecars) {
|
|
82
79
|
const source = await addSource(sidecarPath, surface);
|
|
83
80
|
if (options.firstOnly) return {
|
|
@@ -106,42 +103,59 @@ async function readLegacySessionIndex(storePath) {
|
|
|
106
103
|
return { failure: `session index ${storePath} could not be read (invalid JSON)` };
|
|
107
104
|
}
|
|
108
105
|
if (!isRecord(raw)) return { failure: `session index ${storePath} has invalid entries` };
|
|
106
|
+
let normalizedEntries;
|
|
107
|
+
try {
|
|
108
|
+
normalizedEntries = listSessionEntries({
|
|
109
|
+
storePath,
|
|
110
|
+
hydrateSkillPromptRefs: false
|
|
111
|
+
});
|
|
112
|
+
} catch {
|
|
113
|
+
return { failure: `session index ${storePath} could not be normalized` };
|
|
114
|
+
}
|
|
115
|
+
const normalizedByKey = new Map(normalizedEntries.map(({ sessionKey, entry }) => [sessionKey, entry]));
|
|
109
116
|
const entries = [];
|
|
110
117
|
for (const [sessionKey, value] of Object.entries(raw)) {
|
|
111
118
|
if (!isRecord(value)) return { failure: `session index ${storePath} has invalid entries` };
|
|
112
119
|
if (value.sessionId === void 0) continue;
|
|
113
|
-
const
|
|
120
|
+
const rawSessionId = typeof value.sessionId === "string" ? value.sessionId.trim() : "";
|
|
121
|
+
const sessionId = normalizedByKey.get(sessionKey)?.sessionId?.trim() ?? "";
|
|
114
122
|
const sessionFile = value.sessionFile;
|
|
115
123
|
const lifecycleRevision = value.lifecycleRevision;
|
|
116
124
|
const agentHarnessId = value.agentHarnessId;
|
|
117
|
-
if (!
|
|
125
|
+
if (!sessionId || sessionId !== rawSessionId || sessionFile !== void 0 && typeof sessionFile !== "string" || lifecycleRevision !== void 0 && typeof lifecycleRevision !== "string" || agentHarnessId !== void 0 && typeof agentHarnessId !== "string") return { failure: `session index ${storePath} has invalid entries` };
|
|
118
126
|
entries.push({
|
|
119
127
|
sessionKey,
|
|
120
128
|
entry: {
|
|
121
129
|
sessionId,
|
|
122
130
|
...typeof sessionFile === "string" ? { sessionFile } : {},
|
|
123
131
|
...typeof lifecycleRevision === "string" ? { lifecycleRevision } : {},
|
|
124
|
-
...typeof agentHarnessId === "string" ? { agentHarnessId } : {}
|
|
125
|
-
...typeof value.updatedAt === "number" && Number.isFinite(value.updatedAt) && value.updatedAt >= 0 ? { updatedAt: value.updatedAt } : {}
|
|
132
|
+
...typeof agentHarnessId === "string" ? { agentHarnessId } : {}
|
|
126
133
|
}
|
|
127
134
|
});
|
|
128
135
|
}
|
|
129
136
|
return { entries };
|
|
130
137
|
}
|
|
131
|
-
async function* iterateIndexedSidecars(surface) {
|
|
138
|
+
async function* iterateIndexedSidecars(surface, params) {
|
|
132
139
|
for (const storePath of surface.storePaths) {
|
|
133
140
|
const index = await readLegacySessionIndex(storePath);
|
|
134
141
|
if ("failure" in index) continue;
|
|
135
|
-
for (const { entry } of index.entries) {
|
|
136
|
-
|
|
142
|
+
for (const { sessionKey, entry } of index.entries) {
|
|
143
|
+
const agentId = resolveLegacyBindingOwnerAgentId({
|
|
144
|
+
sessionKey,
|
|
145
|
+
config: params.config,
|
|
146
|
+
storeAgentIds: surface.agentIds
|
|
147
|
+
});
|
|
137
148
|
let transcriptPath;
|
|
138
149
|
try {
|
|
139
|
-
transcriptPath =
|
|
150
|
+
transcriptPath = resolveSessionFilePath(entry.sessionId, entry, {
|
|
151
|
+
sessionsDir: path.dirname(storePath),
|
|
152
|
+
agentId
|
|
153
|
+
});
|
|
140
154
|
} catch {
|
|
141
155
|
continue;
|
|
142
156
|
}
|
|
143
157
|
const sidecarPath = `${transcriptPath}${LEGACY_BINDING_SUFFIX}`;
|
|
144
|
-
if (await
|
|
158
|
+
if (await isRegularFile(sidecarPath)) yield sidecarPath;
|
|
145
159
|
}
|
|
146
160
|
}
|
|
147
161
|
}
|
|
@@ -164,7 +178,7 @@ async function* walkSidecars(root) {
|
|
|
164
178
|
}
|
|
165
179
|
}
|
|
166
180
|
async function collectBindingOwners(sources, surfaces, params) {
|
|
167
|
-
const sourcePaths = new Set(await Promise.all(sources.map((source) =>
|
|
181
|
+
const sourcePaths = new Set(await Promise.all(sources.map((source) => canonicalizePath(source.transcriptPath))));
|
|
168
182
|
const owners = /* @__PURE__ */ new Map();
|
|
169
183
|
const storePaths = new Set(surfaces.flatMap((surface) => [...surface.storePaths]));
|
|
170
184
|
const storeAgentIds = /* @__PURE__ */ new Map();
|
|
@@ -175,7 +189,7 @@ async function collectBindingOwners(sources, surfaces, params) {
|
|
|
175
189
|
}
|
|
176
190
|
const failures = [];
|
|
177
191
|
for (const storePath of storePaths) {
|
|
178
|
-
const canonicalStorePath = await
|
|
192
|
+
const canonicalStorePath = await canonicalizePath(storePath);
|
|
179
193
|
const index = await readLegacySessionIndex(storePath);
|
|
180
194
|
if ("failure" in index) {
|
|
181
195
|
failures.push(index.failure);
|
|
@@ -189,34 +203,35 @@ async function collectBindingOwners(sources, surfaces, params) {
|
|
|
189
203
|
config: params.config,
|
|
190
204
|
storeAgentIds: storeAgentIds.get(storePath)
|
|
191
205
|
});
|
|
192
|
-
let
|
|
193
|
-
let canonicalLegacyTranscriptPath;
|
|
206
|
+
let effectiveTranscriptPath;
|
|
194
207
|
try {
|
|
195
|
-
|
|
196
|
-
|
|
208
|
+
effectiveTranscriptPath = resolveSessionFilePath(sessionId, entry, {
|
|
209
|
+
sessionsDir,
|
|
210
|
+
agentId
|
|
211
|
+
});
|
|
197
212
|
} catch {
|
|
198
213
|
failures.push(`session index ${storePath} has an invalid locator for ${sessionKey}`);
|
|
199
214
|
continue;
|
|
200
215
|
}
|
|
201
|
-
|
|
216
|
+
const transcriptPath = await canonicalizePath(effectiveTranscriptPath);
|
|
217
|
+
if (!sourcePaths.has(transcriptPath)) continue;
|
|
202
218
|
const owner = {
|
|
203
219
|
agentId,
|
|
204
220
|
sessionId,
|
|
205
221
|
sessionKey,
|
|
206
222
|
storePath,
|
|
207
|
-
transcriptPath:
|
|
223
|
+
transcriptPath: effectiveTranscriptPath,
|
|
208
224
|
...entry.lifecycleRevision ? { lifecycleRevision: entry.lifecycleRevision } : {},
|
|
209
|
-
...entry.agentHarnessId?.trim() ? { agentHarnessId: entry.agentHarnessId.trim() } : {}
|
|
210
|
-
...entry.updatedAt !== void 0 ? { updatedAt: entry.updatedAt } : {}
|
|
225
|
+
...entry.agentHarnessId?.trim() ? { agentHarnessId: entry.agentHarnessId.trim() } : {}
|
|
211
226
|
};
|
|
212
|
-
const candidates = owners.get(
|
|
227
|
+
const candidates = owners.get(transcriptPath) ?? /* @__PURE__ */ new Map();
|
|
213
228
|
const ownerKey = `${agentId}\0${sessionId}\0${sessionKey}\0${canonicalStorePath}`;
|
|
214
229
|
const configuredStorePath = resolveStorePath(params.config.session?.store, {
|
|
215
230
|
agentId,
|
|
216
231
|
env: params.env
|
|
217
232
|
});
|
|
218
233
|
if (!candidates.has(ownerKey) || storePath === configuredStorePath) candidates.set(ownerKey, owner);
|
|
219
|
-
owners.set(
|
|
234
|
+
owners.set(transcriptPath, candidates);
|
|
220
235
|
}
|
|
221
236
|
}
|
|
222
237
|
return {
|
|
@@ -224,16 +239,6 @@ async function collectBindingOwners(sources, surfaces, params) {
|
|
|
224
239
|
failures
|
|
225
240
|
};
|
|
226
241
|
}
|
|
227
|
-
async function resolveLegacySessionFileLocator(sessionsDir, entry, sessionId) {
|
|
228
|
-
const base = path.resolve(sessionsDir);
|
|
229
|
-
const fallback = path.join(base, `${sessionId}.jsonl`);
|
|
230
|
-
const sessionFile = entry.sessionFile?.trim();
|
|
231
|
-
if (!sessionFile) return fallback;
|
|
232
|
-
const candidate = path.resolve(base, sessionFile);
|
|
233
|
-
const [canonicalBase, canonicalCandidate] = await Promise.all([canonicalPathFromExistingAncestor(base), canonicalPathFromExistingAncestor(candidate)]);
|
|
234
|
-
if (!isPathInside(canonicalBase, canonicalCandidate)) throw new Error("legacy session file locator escapes its session directory");
|
|
235
|
-
return candidate;
|
|
236
|
-
}
|
|
237
242
|
function resolveLegacyBindingOwnerAgentId(params) {
|
|
238
243
|
if (params.sessionKey.trim().toLowerCase().startsWith("agent:")) return resolveSessionAgentIds({
|
|
239
244
|
sessionKey: params.sessionKey,
|
|
@@ -276,7 +281,7 @@ async function migrateSource(source, candidates, params, store) {
|
|
|
276
281
|
return await withFileLock(source.sidecarPath, LEGACY_BINDING_LOCK_OPTIONS, async () => {
|
|
277
282
|
const [contents, stat] = await Promise.all([fs.readFile(source.sidecarPath, "utf8"), fs.stat(source.sidecarPath)]);
|
|
278
283
|
const raw = JSON.parse(contents);
|
|
279
|
-
const [{ bindingStoreKey, createStoredCodexAppServerBinding, normalizeStoredCodexAppServerBindingFingerprints, readStoredCodexAppServerBinding }, { legacyCodexConversationBindingId }] = await Promise.all([import("
|
|
284
|
+
const [{ bindingStoreKey, createStoredCodexAppServerBinding, normalizeStoredCodexAppServerBindingFingerprints, readStoredCodexAppServerBinding }, { legacyCodexConversationBindingId }] = await Promise.all([import("./.setup/session-binding-DuihlMJc.mjs").then((n) => n.c), import("./.setup/conversation-binding-data-CrRxtDBu.mjs").then((n) => n.t)]);
|
|
280
285
|
const agentId = owner?.agentId ?? (source.agentIds.size === 1 ? [...source.agentIds][0] : void 0);
|
|
281
286
|
const baseStored = createStoredCodexAppServerBinding(raw, {
|
|
282
287
|
now: stat.mtime.toISOString(),
|
|
@@ -354,7 +359,7 @@ async function migrateSource(source, candidates, params, store) {
|
|
|
354
359
|
if (!hasExpected(await store.lookup(entry.key), entry.value)) return retain(`canonical plugin state changed at ${entry.key}`);
|
|
355
360
|
}
|
|
356
361
|
if (owner) {
|
|
357
|
-
const ownershipWarning = await recordSessionOwner(owner
|
|
362
|
+
const ownershipWarning = await recordSessionOwner(owner);
|
|
358
363
|
if (ownershipWarning) {
|
|
359
364
|
if (sessionEntry?.value.state === "active") {
|
|
360
365
|
const update = store.update;
|
|
@@ -372,18 +377,11 @@ async function migrateSource(source, candidates, params, store) {
|
|
|
372
377
|
});
|
|
373
378
|
if (hasExpected(await store.lookup(sessionEntry.key), sessionEntry.value)) return retain(`${ownershipWarning}; its stale session binding could not be retired`);
|
|
374
379
|
}
|
|
375
|
-
return
|
|
380
|
+
return retain(ownershipWarning);
|
|
376
381
|
}
|
|
377
382
|
for (const entry of entries) if (!hasExpected(await store.lookup(entry.key), entry.value)) return retain(`canonical plugin state changed at ${entry.key}`);
|
|
378
383
|
}
|
|
379
|
-
|
|
380
|
-
await archiveLegacyStateSource({
|
|
381
|
-
filePath: source.sidecarPath,
|
|
382
|
-
label: "Codex app-server binding",
|
|
383
|
-
changes: [],
|
|
384
|
-
warnings: archiveWarnings
|
|
385
|
-
});
|
|
386
|
-
if (archiveWarnings.length > 0 && await pathExists(source.sidecarPath)) return retain(archiveWarnings.join("; "));
|
|
384
|
+
await archiveBindingSidecar(source.sidecarPath);
|
|
387
385
|
return {
|
|
388
386
|
archived: true,
|
|
389
387
|
importedKeys
|
|
@@ -397,39 +395,18 @@ async function migrateSource(source, candidates, params, store) {
|
|
|
397
395
|
return retain(`migration or archiving failed: ${String(error)}`);
|
|
398
396
|
}
|
|
399
397
|
}
|
|
400
|
-
async function recordSessionOwner(owner
|
|
401
|
-
const currentIndex = await readLegacySessionIndex(owner.storePath);
|
|
402
|
-
if ("failure" in currentIndex) return "its legacy session owner could not be revalidated";
|
|
403
|
-
const currentOwner = currentIndex.entries.find(({ sessionKey }) => sessionKey === owner.sessionKey);
|
|
404
|
-
if (!currentOwner || currentOwner.entry.sessionId !== owner.sessionId) return "its session owner changed before Codex ownership could be recorded";
|
|
405
|
-
let currentTranscriptPath;
|
|
406
|
-
try {
|
|
407
|
-
currentTranscriptPath = await resolveLegacySessionFileLocator(path.dirname(owner.storePath), currentOwner.entry, currentOwner.entry.sessionId);
|
|
408
|
-
} catch {
|
|
409
|
-
return "its session owner changed before Codex ownership could be recorded";
|
|
410
|
-
}
|
|
411
|
-
if (await canonicalPathFromExistingAncestor(currentTranscriptPath) !== await canonicalPathFromExistingAncestor(owner.transcriptPath) || currentOwner.entry.lifecycleRevision !== owner.lifecycleRevision) return "its session owner changed before Codex ownership could be recorded";
|
|
412
|
-
const legacyHarnessId = currentOwner.entry.agentHarnessId?.trim();
|
|
413
|
-
if (currentOwner.entry.agentHarnessId !== void 0 && !legacyHarnessId) return "its session owner changed before Codex ownership could be recorded";
|
|
414
|
-
if (legacyHarnessId && legacyHarnessId !== CODEX_AGENT_HARNESS_ID) return `its session is owned by agent harness ${legacyHarnessId}`;
|
|
398
|
+
async function recordSessionOwner(owner) {
|
|
415
399
|
let observedForeignHarness;
|
|
416
|
-
const updated = await
|
|
417
|
-
agentId: owner.agentId,
|
|
418
|
-
env,
|
|
419
|
-
fallbackEntry: {
|
|
420
|
-
sessionId: owner.sessionId,
|
|
421
|
-
updatedAt: currentOwner.entry.updatedAt ?? owner.updatedAt ?? 0,
|
|
422
|
-
...owner.lifecycleRevision ? { lifecycleRevision: owner.lifecycleRevision } : {}
|
|
423
|
-
},
|
|
424
|
-
preserveActivity: true,
|
|
425
|
-
requireWriteSuccess: true,
|
|
426
|
-
skipMaintenance: true,
|
|
400
|
+
const updated = await updateSessionStoreEntry({
|
|
427
401
|
storePath: owner.storePath,
|
|
428
402
|
sessionKey: owner.sessionKey,
|
|
403
|
+
skipMaintenance: true,
|
|
404
|
+
requireWriteSuccess: true,
|
|
429
405
|
update: (entry) => {
|
|
430
|
-
|
|
406
|
+
const transcriptPath = resolveOwnerTranscriptPath(owner, entry);
|
|
407
|
+
if (entry.sessionId.trim() !== owner.sessionId || transcriptPath !== owner.transcriptPath || entry.lifecycleRevision !== owner.lifecycleRevision) return null;
|
|
431
408
|
const harnessId = typeof entry.agentHarnessId === "string" ? entry.agentHarnessId.trim() : void 0;
|
|
432
|
-
if (entry.agentHarnessId !== void 0 &&
|
|
409
|
+
if (entry.agentHarnessId !== void 0 && harnessId === void 0) return null;
|
|
433
410
|
if (harnessId && harnessId !== CODEX_AGENT_HARNESS_ID) {
|
|
434
411
|
observedForeignHarness = harnessId;
|
|
435
412
|
return null;
|
|
@@ -438,10 +415,21 @@ async function recordSessionOwner(owner, env) {
|
|
|
438
415
|
}
|
|
439
416
|
});
|
|
440
417
|
if (!updated) return observedForeignHarness ? `its session is owned by agent harness ${observedForeignHarness}` : "its session owner changed before Codex ownership could be recorded";
|
|
441
|
-
|
|
418
|
+
const transcriptPath = resolveOwnerTranscriptPath(owner, updated);
|
|
419
|
+
if (updated.sessionId.trim() !== owner.sessionId || transcriptPath !== owner.transcriptPath || updated.lifecycleRevision !== owner.lifecycleRevision) return "its session owner changed before Codex ownership could be recorded";
|
|
442
420
|
const harnessId = updated.agentHarnessId?.trim();
|
|
443
421
|
return harnessId === CODEX_AGENT_HARNESS_ID ? void 0 : harnessId ? `its session is owned by agent harness ${harnessId}` : "Codex harness ownership could not be recorded on its session";
|
|
444
422
|
}
|
|
423
|
+
function resolveOwnerTranscriptPath(owner, entry) {
|
|
424
|
+
try {
|
|
425
|
+
return resolveSessionFilePath(entry.sessionId, entry, {
|
|
426
|
+
sessionsDir: path.dirname(owner.storePath),
|
|
427
|
+
agentId: owner.agentId
|
|
428
|
+
});
|
|
429
|
+
} catch {
|
|
430
|
+
return;
|
|
431
|
+
}
|
|
432
|
+
}
|
|
445
433
|
async function readDirectoryEntries(directory) {
|
|
446
434
|
try {
|
|
447
435
|
return await fs.readdir(directory, { withFileTypes: true });
|
|
@@ -455,10 +443,53 @@ async function readDirectoryEntries(directory) {
|
|
|
455
443
|
throw error;
|
|
456
444
|
}
|
|
457
445
|
}
|
|
458
|
-
function
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
446
|
+
async function isRegularFile(filePath) {
|
|
447
|
+
try {
|
|
448
|
+
return (await fs.stat(filePath)).isFile();
|
|
449
|
+
} catch {
|
|
450
|
+
return false;
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
function isRecord(value) {
|
|
454
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
455
|
+
}
|
|
456
|
+
function isPathWithin(root, candidate) {
|
|
457
|
+
const relative = path.relative(root, candidate);
|
|
458
|
+
return relative === "" || relative !== ".." && !relative.startsWith(`..${path.sep}`) && !path.isAbsolute(relative);
|
|
459
|
+
}
|
|
460
|
+
async function canonicalizePath(filePath) {
|
|
461
|
+
try {
|
|
462
|
+
return await fs.realpath(filePath);
|
|
463
|
+
} catch {
|
|
464
|
+
return path.resolve(filePath);
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
async function pathExists(filePath) {
|
|
468
|
+
try {
|
|
469
|
+
await fs.access(filePath);
|
|
470
|
+
return true;
|
|
471
|
+
} catch {
|
|
472
|
+
return false;
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
async function firstFreeArchivePath(sourcePath) {
|
|
476
|
+
for (let index = 2;; index++) {
|
|
477
|
+
const candidate = `${sourcePath}.migrated.${index}`;
|
|
478
|
+
if (!await pathExists(candidate)) return candidate;
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
async function archiveBindingSidecar(sourcePath) {
|
|
482
|
+
const archivePath = `${sourcePath}.migrated`;
|
|
483
|
+
if (await pathExists(archivePath)) {
|
|
484
|
+
const [sourceBytes, archiveBytes] = await Promise.all([fs.readFile(sourcePath), fs.readFile(archivePath)]);
|
|
485
|
+
if (sourceBytes.equals(archiveBytes)) {
|
|
486
|
+
await fs.rm(sourcePath, { force: true });
|
|
487
|
+
return;
|
|
488
|
+
}
|
|
489
|
+
await fs.rename(sourcePath, await firstFreeArchivePath(sourcePath));
|
|
490
|
+
return;
|
|
491
|
+
}
|
|
492
|
+
await fs.rename(sourcePath, archivePath);
|
|
462
493
|
}
|
|
463
494
|
const stateMigrations = [{
|
|
464
495
|
id: "codex-app-server-sidecars-to-plugin-state",
|
|
@@ -492,7 +523,7 @@ const stateMigrations = [{
|
|
|
492
523
|
let migrated = 0;
|
|
493
524
|
let partialImports = 0;
|
|
494
525
|
for (const source of sources) {
|
|
495
|
-
const result = await migrateSource(source, ownerCollection.owners.get(await
|
|
526
|
+
const result = await migrateSource(source, ownerCollection.owners.get(await canonicalizePath(source.transcriptPath)) ?? [], params, store);
|
|
496
527
|
if (result.warning) warnings.push(result.warning);
|
|
497
528
|
if (result.notice) notices.push(result.notice);
|
|
498
529
|
if (result.archived) migrated++;
|
|
@@ -500,10 +531,13 @@ const stateMigrations = [{
|
|
|
500
531
|
}
|
|
501
532
|
if (migrated > 0) changes.push(`Migrated ${migrated} Codex app-server binding sidecar(s) to plugin state and archived the legacy sources`);
|
|
502
533
|
if (partialImports > 0) changes.push(`Migrated ${partialImports} safe Codex app-server binding row(s) to plugin state; retained legacy sidecars needing review`);
|
|
503
|
-
return {
|
|
534
|
+
return notices.length > 0 ? {
|
|
504
535
|
changes,
|
|
505
536
|
warnings,
|
|
506
|
-
|
|
537
|
+
notices
|
|
538
|
+
} : {
|
|
539
|
+
changes,
|
|
540
|
+
warnings
|
|
507
541
|
};
|
|
508
542
|
}
|
|
509
543
|
}];
|
package/dist/harness.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
//#region extensions/codex/harness.ts
|
|
2
2
|
const DEFAULT_CODEX_HARNESS_PROVIDER_IDS = /* @__PURE__ */ new Set(["codex", "openai"]);
|
|
3
|
-
const SHARED_CODEX_APP_SERVER_CLIENT_DISPOSER = Symbol.for("openclaw.codexAppServerClientDisposer");
|
|
4
3
|
const CODEX_APP_SERVER_CONTEXT_ENGINE_HOST_CAPABILITIES = [
|
|
5
4
|
"bootstrap",
|
|
6
5
|
"assemble-before-prompt",
|
|
@@ -10,108 +9,38 @@ const CODEX_APP_SERVER_CONTEXT_ENGINE_HOST_CAPABILITIES = [
|
|
|
10
9
|
"runtime-llm-complete",
|
|
11
10
|
"thread-bootstrap-projection"
|
|
12
11
|
];
|
|
13
|
-
async function disposeSharedCodexAppServerClients() {
|
|
14
|
-
const dispose = globalThis[SHARED_CODEX_APP_SERVER_CLIENT_DISPOSER];
|
|
15
|
-
await dispose?.();
|
|
16
|
-
}
|
|
17
12
|
/**
|
|
18
13
|
* Creates the Codex app-server harness used for attempts, side questions,
|
|
19
14
|
* compaction, reset, and disposal.
|
|
20
15
|
*/
|
|
21
16
|
function createCodexAppServerAgentHarness(options) {
|
|
22
|
-
const harnessRuntimeId = options?.id ?? "codex";
|
|
23
|
-
const normalizedHarnessRuntimeId = harnessRuntimeId.trim().toLowerCase();
|
|
24
17
|
const providerIds = new Set([...options?.providerIds ?? DEFAULT_CODEX_HARNESS_PROVIDER_IDS].map((id) => id.trim().toLowerCase()));
|
|
25
|
-
const sessionCatalogControl = options.sessionCatalogControl;
|
|
26
|
-
const sessionRuntime = options.runtime;
|
|
27
18
|
return {
|
|
28
|
-
id:
|
|
19
|
+
id: options?.id ?? "codex",
|
|
29
20
|
label: options?.label ?? "Codex agent harness",
|
|
30
|
-
autoSelection: { providerIds: [...providerIds] },
|
|
31
|
-
delegatedExecutionPluginIds: ["voice-call"],
|
|
32
21
|
contextEngineHostCapabilities: CODEX_APP_SERVER_CONTEXT_ENGINE_HOST_CAPABILITIES,
|
|
33
|
-
deliveryDefaults: {
|
|
34
|
-
authBootstrap: "harness",
|
|
35
|
-
...sessionCatalogControl && sessionRuntime ? { sessionFork: {
|
|
36
|
-
upstreamKinds: ["codex-app-server"],
|
|
37
|
-
fork: async (params) => {
|
|
38
|
-
const { forkCodexUpstreamSession } = await import("./upstream-session-fork-Dy4Xvuoj.js");
|
|
39
|
-
return await forkCodexUpstreamSession(params, {
|
|
40
|
-
bindingStore: options.bindingStore,
|
|
41
|
-
control: sessionCatalogControl,
|
|
42
|
-
harnessRuntimeId,
|
|
43
|
-
resolveConfig: options.resolveConfig,
|
|
44
|
-
runtime: sessionRuntime
|
|
45
|
-
});
|
|
46
|
-
}
|
|
47
|
-
} } : {},
|
|
48
|
-
authBinding: { fingerprint: async (params) => {
|
|
49
|
-
const { fingerprintCodexAppServerAuthBinding } = await import("./auth-binding-B4FfbcCg.js").then((n) => n.t);
|
|
50
|
-
return fingerprintCodexAppServerAuthBinding(params);
|
|
51
|
-
} },
|
|
52
|
-
runtimeArtifact: { validate: async (binding) => {
|
|
53
|
-
const { validateCodexAppServerRuntimeArtifact } = await import("./runtime-artifact-CmtG_t1L.js");
|
|
54
|
-
return validateCodexAppServerRuntimeArtifact(binding);
|
|
55
|
-
} },
|
|
56
|
-
fetchUsageSnapshot: async (ctx) => {
|
|
57
|
-
const { fetchCodexAppServerUsageSnapshot } = await import("./usage-CQ6GhD5-.js");
|
|
58
|
-
return await fetchCodexAppServerUsageSnapshot(ctx, { pluginConfig: options?.resolvePluginConfig?.() ?? options?.pluginConfig });
|
|
59
|
-
},
|
|
60
|
-
loadMcpToolCatalog: async (params) => {
|
|
61
|
-
const { loadCodexEffectiveMcpCatalog } = await import("./effective-mcp-catalog-Bbd98Inw.js");
|
|
62
|
-
return await loadCodexEffectiveMcpCatalog(params, { bindingStore: options.bindingStore });
|
|
63
|
-
},
|
|
22
|
+
deliveryDefaults: { sourceVisibleReplies: "message_tool" },
|
|
64
23
|
supports: (ctx) => {
|
|
65
24
|
const provider = ctx.provider.trim().toLowerCase();
|
|
66
|
-
if (
|
|
67
|
-
supported: false,
|
|
68
|
-
reason: `provider is not one of: ${[...providerIds].toSorted().join(", ")}`
|
|
69
|
-
};
|
|
70
|
-
if (ctx.modelProvider?.requestTransportOverrides === "present") return {
|
|
71
|
-
supported: false,
|
|
72
|
-
reason: "Codex cannot reproduce authored request transport overrides"
|
|
73
|
-
};
|
|
74
|
-
const preparedAuth = ctx.modelProvider?.preparedAuth;
|
|
75
|
-
const runtimePolicy = ctx.modelProvider?.runtimePolicy;
|
|
76
|
-
if (runtimePolicy) {
|
|
77
|
-
if (!runtimePolicy.compatibleIds.some((id) => id.trim().toLowerCase() === normalizedHarnessRuntimeId)) return {
|
|
78
|
-
supported: false,
|
|
79
|
-
reason: "Codex cannot reproduce the prepared provider route"
|
|
80
|
-
};
|
|
81
|
-
} else if (ctx.modelProvider && provider !== "codex") return {
|
|
82
|
-
supported: false,
|
|
83
|
-
reason: "provider route compatibility with Codex is not declared"
|
|
84
|
-
};
|
|
85
|
-
if (preparedAuth?.requirement === "subscription") {
|
|
86
|
-
if (!(preparedAuth.source === "profile" && (preparedAuth.mode === "oauth" || preparedAuth.mode === "token"))) return {
|
|
87
|
-
supported: false,
|
|
88
|
-
reason: "Codex subscription auth requires a prepared OAuth or token profile"
|
|
89
|
-
};
|
|
90
|
-
} else if (preparedAuth?.requirement === "api-key") {
|
|
91
|
-
if (!(preparedAuth.source !== "none" && preparedAuth.source !== "harness" && (preparedAuth.mode === "api-key" || preparedAuth.mode === "api_key"))) return {
|
|
92
|
-
supported: false,
|
|
93
|
-
reason: "Codex Platform auth requires a prepared API key"
|
|
94
|
-
};
|
|
95
|
-
}
|
|
96
|
-
return {
|
|
25
|
+
if (providerIds.has(provider)) return {
|
|
97
26
|
supported: true,
|
|
98
27
|
priority: 100
|
|
99
28
|
};
|
|
29
|
+
return {
|
|
30
|
+
supported: false,
|
|
31
|
+
reason: `provider is not one of: ${[...providerIds].toSorted().join(", ")}`
|
|
32
|
+
};
|
|
100
33
|
},
|
|
101
34
|
runAttempt: async (params) => {
|
|
102
|
-
const { runCodexAppServerAttempt } = await import("
|
|
35
|
+
const { runCodexAppServerAttempt } = await import("./.setup/run-attempt-C7xEKFVB.mjs");
|
|
103
36
|
return runCodexAppServerAttempt(params, {
|
|
104
37
|
bindingStore: options.bindingStore,
|
|
105
38
|
pluginConfig: options?.resolvePluginConfig?.() ?? options?.pluginConfig,
|
|
106
39
|
nativeHookRelay: { enabled: true }
|
|
107
40
|
});
|
|
108
41
|
},
|
|
109
|
-
finalizeSettledTurn: async (params) => {
|
|
110
|
-
const { runCodexSettledTurnFinalization } = await import("./settled-turn-finalizer-CXY2Z9dT.js");
|
|
111
|
-
return runCodexSettledTurnFinalization(params, { pluginConfig: options?.resolvePluginConfig?.() ?? options?.pluginConfig });
|
|
112
|
-
},
|
|
113
42
|
runSideQuestion: async (params) => {
|
|
114
|
-
const { runCodexAppServerSideQuestion } = await import("
|
|
43
|
+
const { runCodexAppServerSideQuestion } = await import("./.setup/side-question-Cv6JXWCS.mjs");
|
|
115
44
|
return runCodexAppServerSideQuestion(params, {
|
|
116
45
|
bindingStore: options.bindingStore,
|
|
117
46
|
pluginConfig: options?.resolvePluginConfig?.() ?? options?.pluginConfig,
|
|
@@ -119,14 +48,14 @@ function createCodexAppServerAgentHarness(options) {
|
|
|
119
48
|
});
|
|
120
49
|
},
|
|
121
50
|
compact: async (params) => {
|
|
122
|
-
const { maybeCompactCodexAppServerSession } = await import("
|
|
51
|
+
const { maybeCompactCodexAppServerSession } = await import("./.setup/compact-BNgh7I4t.mjs");
|
|
123
52
|
return maybeCompactCodexAppServerSession(params, {
|
|
124
53
|
bindingStore: options.bindingStore,
|
|
125
54
|
pluginConfig: options?.resolvePluginConfig?.() ?? options?.pluginConfig
|
|
126
55
|
});
|
|
127
56
|
},
|
|
128
57
|
compactAfterContextEngine: async (params) => {
|
|
129
|
-
const { maybeCompactCodexAppServerSession } = await import("
|
|
58
|
+
const { maybeCompactCodexAppServerSession } = await import("./.setup/compact-BNgh7I4t.mjs");
|
|
130
59
|
return maybeCompactCodexAppServerSession(params, {
|
|
131
60
|
bindingStore: options.bindingStore,
|
|
132
61
|
pluginConfig: options?.resolvePluginConfig?.() ?? options?.pluginConfig,
|
|
@@ -135,25 +64,27 @@ function createCodexAppServerAgentHarness(options) {
|
|
|
135
64
|
},
|
|
136
65
|
reset: async (params) => {
|
|
137
66
|
if (params.sessionId) {
|
|
138
|
-
const { reclaimCurrentCodexSessionGeneration, sessionBindingIdentity } = await import("
|
|
67
|
+
const { reclaimCurrentCodexSessionGeneration, sessionBindingIdentity } = await import("./.setup/session-binding-DuihlMJc.mjs").then((n) => n.c);
|
|
139
68
|
const identity = sessionBindingIdentity({
|
|
140
69
|
agentId: params.agentId,
|
|
141
70
|
sessionId: params.sessionId,
|
|
142
71
|
sessionKey: params.sessionKey
|
|
143
72
|
});
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
if (reset === "conflict") {
|
|
73
|
+
let retired = await options.bindingStore.retireSessionGeneration(identity);
|
|
74
|
+
if (retired === "conflict") {
|
|
147
75
|
if (await reclaimCurrentCodexSessionGeneration({
|
|
148
76
|
bindingStore: options.bindingStore,
|
|
149
77
|
identity,
|
|
150
78
|
config: options.resolveConfig?.()
|
|
151
|
-
}))
|
|
79
|
+
})) retired = await options.bindingStore.retireSessionGeneration(identity);
|
|
152
80
|
}
|
|
153
|
-
if (
|
|
81
|
+
if (retired === "conflict") throw new Error(`Codex binding generation changed before session ${params.sessionId} could reset`);
|
|
154
82
|
}
|
|
155
83
|
},
|
|
156
|
-
dispose:
|
|
84
|
+
dispose: async () => {
|
|
85
|
+
const { clearSharedCodexAppServerClientAndWait } = await import("./.setup/shared-client-B2KmLPRw.mjs").then((n) => n.c);
|
|
86
|
+
await clearSharedCodexAppServerClientAndWait();
|
|
87
|
+
}
|
|
157
88
|
};
|
|
158
89
|
}
|
|
159
90
|
//#endregion
|