@openclaw/codex 2026.5.7-beta.1 → 2026.5.9-beta.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.
- package/dist/{client-BGbqC7jk.js → client-DYkCXAze.js} +6 -6
- package/dist/{client-factory--cll1Fba.js → client-factory-D3-EhEwN.js} +1 -1
- package/dist/{command-handlers-DiH-D13x.js → command-handlers-De-V2-4K.js} +7 -7
- package/dist/{compact-DcR5aTxd.js → compact-BaeaEEoQ.js} +3 -3
- package/dist/config-BZiM7rhH.js +498 -0
- package/dist/{conversation-binding-CtHkMJfG.js → conversation-binding-BjanzgDh.js} +10 -8
- package/dist/harness.js +4 -4
- package/dist/index.js +406 -33
- package/dist/media-understanding-provider.js +4 -4
- package/dist/{models-CkowdYbm.js → models-nfvRggjT.js} +2 -2
- package/dist/plugin-activation-D0uXssSN.js +389 -0
- package/dist/{protocol-validators-Dky2yV4W.js → protocol-validators-CbqWfY5M.js} +147 -14
- package/dist/provider.js +2 -2
- package/dist/{rate-limit-cache-t6ebYmfS.js → rate-limit-cache-BZWGqXPP.js} +3 -17
- package/dist/{command-formatters-PiJcdUbu.js → request-CaW8DCAa.js} +16 -2
- package/dist/{run-attempt-BaT_FcTv.js → run-attempt-DCCThMaw.js} +388 -132
- package/dist/{session-binding-DuJYTJQy.js → session-binding-C_HDlZx8.js} +44 -5
- package/dist/{shared-client-Dfk3Enm-.js → shared-client-pLCOzMaZ.js} +77 -22
- package/dist/test-api.js +7 -4
- package/dist/{thread-lifecycle-CzllX4PU.js → thread-lifecycle-unEEsXe-.js} +326 -15
- package/openclaw.plugin.json +79 -3
- package/package.json +7 -8
- package/dist/config-ByrA30No.js +0 -242
package/dist/harness.js
CHANGED
|
@@ -18,21 +18,21 @@ function createCodexAppServerAgentHarness(options) {
|
|
|
18
18
|
};
|
|
19
19
|
},
|
|
20
20
|
runAttempt: async (params) => {
|
|
21
|
-
const { runCodexAppServerAttempt } = await import("./run-attempt-
|
|
21
|
+
const { runCodexAppServerAttempt } = await import("./run-attempt-DCCThMaw.js");
|
|
22
22
|
return runCodexAppServerAttempt(params, { pluginConfig: options?.pluginConfig });
|
|
23
23
|
},
|
|
24
24
|
compact: async (params) => {
|
|
25
|
-
const { maybeCompactCodexAppServerSession } = await import("./compact-
|
|
25
|
+
const { maybeCompactCodexAppServerSession } = await import("./compact-BaeaEEoQ.js");
|
|
26
26
|
return maybeCompactCodexAppServerSession(params, { pluginConfig: options?.pluginConfig });
|
|
27
27
|
},
|
|
28
28
|
reset: async (params) => {
|
|
29
29
|
if (params.sessionFile) {
|
|
30
|
-
const { clearCodexAppServerBinding } = await import("./session-binding-
|
|
30
|
+
const { clearCodexAppServerBinding } = await import("./session-binding-C_HDlZx8.js").then((n) => n.a);
|
|
31
31
|
await clearCodexAppServerBinding(params.sessionFile);
|
|
32
32
|
}
|
|
33
33
|
},
|
|
34
34
|
dispose: async () => {
|
|
35
|
-
const { clearSharedCodexAppServerClientAndWait } = await import("./shared-client-
|
|
35
|
+
const { clearSharedCodexAppServerClientAndWait } = await import("./shared-client-pLCOzMaZ.js").then((n) => n.r);
|
|
36
36
|
await clearSharedCodexAppServerClientAndWait();
|
|
37
37
|
}
|
|
38
38
|
};
|
package/dist/index.js
CHANGED
|
@@ -1,16 +1,20 @@
|
|
|
1
1
|
import { createCodexAppServerAgentHarness } from "./harness.js";
|
|
2
|
+
import { t as CODEX_PLUGINS_MARKETPLACE_NAME } from "./config-BZiM7rhH.js";
|
|
2
3
|
import { buildCodexMediaUnderstandingProvider } from "./media-understanding-provider.js";
|
|
3
4
|
import { buildCodexProvider } from "./provider.js";
|
|
4
|
-
import {
|
|
5
|
-
import { n as handleCodexConversationInboundClaim, t as handleCodexConversationBindingResolved } from "./conversation-binding-
|
|
5
|
+
import { i as formatCodexDisplayText, p as describeControlFailure, t as requestCodexAppServerJson } from "./request-CaW8DCAa.js";
|
|
6
|
+
import { n as handleCodexConversationInboundClaim, t as handleCodexConversationBindingResolved } from "./conversation-binding-BjanzgDh.js";
|
|
7
|
+
import { i as defaultCodexAppInventoryCache, t as ensureCodexPluginActivation } from "./plugin-activation-D0uXssSN.js";
|
|
6
8
|
import { resolveLivePluginConfigObject } from "openclaw/plugin-sdk/plugin-config-runtime";
|
|
7
9
|
import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";
|
|
10
|
+
import os from "node:os";
|
|
8
11
|
import fs from "node:fs/promises";
|
|
9
12
|
import path from "node:path";
|
|
10
13
|
import { resolveAgentConfig, resolveAgentWorkspaceDir, resolveDefaultAgentId } from "openclaw/plugin-sdk/agent-runtime";
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import
|
|
14
|
+
import { pathExists } from "openclaw/plugin-sdk/security-runtime";
|
|
15
|
+
import { MIGRATION_REASON_TARGET_EXISTS, applyMigrationManualItem, createMigrationItem, createMigrationManualItem, hasMigrationConfigPatchConflict, markMigrationItemConflict, markMigrationItemError, markMigrationItemSkipped, readMigrationConfigPath, summarizeMigrationItems, writeMigrationConfigPath } from "openclaw/plugin-sdk/migration";
|
|
16
|
+
import { archiveMigrationItem, copyMigrationFileItem, withCachedMigrationConfigRuntime, writeMigrationReport } from "openclaw/plugin-sdk/migration-runtime";
|
|
17
|
+
import { readJsonFileWithFallback } from "openclaw/plugin-sdk/json-store";
|
|
14
18
|
//#region extensions/codex/src/commands.ts
|
|
15
19
|
function createCodexCommand(options) {
|
|
16
20
|
return {
|
|
@@ -24,7 +28,7 @@ function createCodexCommand(options) {
|
|
|
24
28
|
};
|
|
25
29
|
}
|
|
26
30
|
async function handleCodexCommand(ctx, options = {}) {
|
|
27
|
-
const { handleCodexSubcommand } = await import("./command-handlers-
|
|
31
|
+
const { handleCodexSubcommand } = await import("./command-handlers-De-V2-4K.js");
|
|
28
32
|
try {
|
|
29
33
|
return await handleCodexSubcommand(ctx, options);
|
|
30
34
|
} catch (error) {
|
|
@@ -34,12 +38,7 @@ async function handleCodexCommand(ctx, options = {}) {
|
|
|
34
38
|
//#endregion
|
|
35
39
|
//#region extensions/codex/src/migration/helpers.ts
|
|
36
40
|
async function exists(filePath) {
|
|
37
|
-
|
|
38
|
-
await fs.access(filePath);
|
|
39
|
-
return true;
|
|
40
|
-
} catch {
|
|
41
|
-
return false;
|
|
42
|
-
}
|
|
41
|
+
return await pathExists(filePath);
|
|
43
42
|
}
|
|
44
43
|
async function isDirectory(filePath) {
|
|
45
44
|
if (!filePath) return false;
|
|
@@ -62,12 +61,8 @@ function sanitizeName(value) {
|
|
|
62
61
|
}
|
|
63
62
|
async function readJsonObject(filePath) {
|
|
64
63
|
if (!filePath) return {};
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
|
|
68
|
-
} catch {
|
|
69
|
-
return {};
|
|
70
|
-
}
|
|
64
|
+
const { value: parsed } = await readJsonFileWithFallback(filePath, {});
|
|
65
|
+
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
|
|
71
66
|
}
|
|
72
67
|
//#endregion
|
|
73
68
|
//#region extensions/codex/src/migration/source.ts
|
|
@@ -119,7 +114,10 @@ async function discoverPluginDirs(codexHome) {
|
|
|
119
114
|
discovered.set(dir, {
|
|
120
115
|
name,
|
|
121
116
|
source: dir,
|
|
122
|
-
manifestPath
|
|
117
|
+
manifestPath,
|
|
118
|
+
sourceKind: "cache",
|
|
119
|
+
migratable: false,
|
|
120
|
+
message: "Cached Codex plugin bundle found. Review manually unless the plugin is also installed in the source Codex app-server inventory."
|
|
123
121
|
});
|
|
124
122
|
return;
|
|
125
123
|
}
|
|
@@ -131,6 +129,62 @@ async function discoverPluginDirs(codexHome) {
|
|
|
131
129
|
await visit(root, 0);
|
|
132
130
|
return [...discovered.values()].toSorted((a, b) => a.source.localeCompare(b.source));
|
|
133
131
|
}
|
|
132
|
+
async function discoverInstalledCuratedPlugins(codexHome) {
|
|
133
|
+
try {
|
|
134
|
+
const marketplace = (await requestCodexAppServerJson({
|
|
135
|
+
method: "plugin/list",
|
|
136
|
+
requestParams: { cwds: [] },
|
|
137
|
+
timeoutMs: 6e4,
|
|
138
|
+
startOptions: {
|
|
139
|
+
transport: "stdio",
|
|
140
|
+
command: "codex",
|
|
141
|
+
commandSource: "config",
|
|
142
|
+
args: [
|
|
143
|
+
"app-server",
|
|
144
|
+
"--listen",
|
|
145
|
+
"stdio://"
|
|
146
|
+
],
|
|
147
|
+
headers: {},
|
|
148
|
+
env: {
|
|
149
|
+
CODEX_HOME: codexHome,
|
|
150
|
+
HOME: path.dirname(codexHome)
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
})).marketplaces.find((entry) => entry.name === CODEX_PLUGINS_MARKETPLACE_NAME);
|
|
154
|
+
if (!marketplace) return {
|
|
155
|
+
plugins: [],
|
|
156
|
+
error: `Codex marketplace ${CODEX_PLUGINS_MARKETPLACE_NAME} was not found in source plugin inventory.`
|
|
157
|
+
};
|
|
158
|
+
return { plugins: marketplace.plugins.filter((plugin) => plugin.installed).map((plugin) => {
|
|
159
|
+
const pluginName = pluginNameFromSummary(plugin);
|
|
160
|
+
if (!pluginName) return;
|
|
161
|
+
return {
|
|
162
|
+
name: plugin.name,
|
|
163
|
+
pluginName,
|
|
164
|
+
marketplaceName: CODEX_PLUGINS_MARKETPLACE_NAME,
|
|
165
|
+
source: `${CODEX_PLUGINS_MARKETPLACE_NAME}/${pluginName}`,
|
|
166
|
+
sourceKind: "app-server",
|
|
167
|
+
migratable: true,
|
|
168
|
+
installed: plugin.installed,
|
|
169
|
+
enabled: plugin.enabled
|
|
170
|
+
};
|
|
171
|
+
}).filter((plugin) => plugin !== void 0).toSorted((a, b) => (a.pluginName ?? a.name).localeCompare(b.pluginName ?? b.name)) };
|
|
172
|
+
} catch (error) {
|
|
173
|
+
return {
|
|
174
|
+
plugins: [],
|
|
175
|
+
error: error instanceof Error ? error.message : String(error)
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
function pluginNameFromSummary(summary) {
|
|
180
|
+
const candidates = [summary.id, summary.name];
|
|
181
|
+
for (const candidate of candidates) {
|
|
182
|
+
const trimmed = candidate.trim();
|
|
183
|
+
if (!trimmed) continue;
|
|
184
|
+
const normalized = ((trimmed.endsWith(`@openai-curated`) ? trimmed.slice(0, -`@${CODEX_PLUGINS_MARKETPLACE_NAME}`.length) : trimmed).split("/").at(-1)?.trim())?.toLowerCase().replaceAll(/\s+/gu, "-");
|
|
185
|
+
if (normalized) return normalized;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
134
188
|
async function discoverCodexSource(input) {
|
|
135
189
|
const codexHome = resolveHomePath(input?.trim() || defaultCodexHome());
|
|
136
190
|
const codexSkillsDir = path.join(codexHome, "skills");
|
|
@@ -146,7 +200,13 @@ async function discoverCodexSource(input) {
|
|
|
146
200
|
root: agentsSkillsDir,
|
|
147
201
|
sourceLabel: "personal AgentSkill"
|
|
148
202
|
});
|
|
149
|
-
const
|
|
203
|
+
const sourcePluginDiscovery = await discoverInstalledCuratedPlugins(codexHome);
|
|
204
|
+
const sourcePluginNames = new Set(sourcePluginDiscovery.plugins.flatMap((plugin) => plugin.pluginName ? [plugin.pluginName] : []));
|
|
205
|
+
const cachedPlugins = (await discoverPluginDirs(codexHome)).filter((plugin) => {
|
|
206
|
+
const normalizedName = sanitizePluginName(plugin.name);
|
|
207
|
+
return !sourcePluginNames.has(normalizedName);
|
|
208
|
+
});
|
|
209
|
+
const plugins = [...sourcePluginDiscovery.plugins, ...cachedPlugins].toSorted((a, b) => a.source.localeCompare(b.source));
|
|
150
210
|
const archivePaths = [];
|
|
151
211
|
if (await exists(configPath)) archivePaths.push({
|
|
152
212
|
id: "archive:config.toml",
|
|
@@ -173,12 +233,16 @@ async function discoverCodexSource(input) {
|
|
|
173
233
|
...await exists(hooksPath) ? { hooksPath } : {},
|
|
174
234
|
skills,
|
|
175
235
|
plugins,
|
|
236
|
+
...sourcePluginDiscovery.error ? { pluginDiscoveryError: sourcePluginDiscovery.error } : {},
|
|
176
237
|
archivePaths
|
|
177
238
|
};
|
|
178
239
|
}
|
|
179
240
|
function hasCodexSource(source) {
|
|
180
241
|
return source.confidence !== "low";
|
|
181
242
|
}
|
|
243
|
+
function sanitizePluginName(value) {
|
|
244
|
+
return value.trim().toLowerCase().replaceAll(/\s+/gu, "-");
|
|
245
|
+
}
|
|
182
246
|
//#endregion
|
|
183
247
|
//#region extensions/codex/src/migration/targets.ts
|
|
184
248
|
function resolveCodexMigrationTargets(ctx) {
|
|
@@ -193,6 +257,26 @@ function resolveCodexMigrationTargets(ctx) {
|
|
|
193
257
|
}
|
|
194
258
|
//#endregion
|
|
195
259
|
//#region extensions/codex/src/migration/plan.ts
|
|
260
|
+
const CODEX_PLUGIN_CONFIG_ITEM_ID = "config:codex-plugins";
|
|
261
|
+
const CODEX_PLUGIN_CONFIG_PATH = [
|
|
262
|
+
"plugins",
|
|
263
|
+
"entries",
|
|
264
|
+
"codex"
|
|
265
|
+
];
|
|
266
|
+
const CODEX_PLUGIN_ENABLED_PATH = [
|
|
267
|
+
"plugins",
|
|
268
|
+
"entries",
|
|
269
|
+
"codex",
|
|
270
|
+
"enabled"
|
|
271
|
+
];
|
|
272
|
+
const CODEX_PLUGIN_NATIVE_CONFIG_PATH = [
|
|
273
|
+
"plugins",
|
|
274
|
+
"entries",
|
|
275
|
+
"codex",
|
|
276
|
+
"config",
|
|
277
|
+
"codexPlugins"
|
|
278
|
+
];
|
|
279
|
+
const MIGRATION_REASON_PLUGIN_EXISTS = "plugin exists";
|
|
196
280
|
function uniqueSkillName(skill, counts) {
|
|
197
281
|
const base = sanitizeName(skill.name) || "codex-skill";
|
|
198
282
|
if ((counts.get(base) ?? 0) <= 1) return base;
|
|
@@ -239,6 +323,137 @@ async function buildSkillItems(params) {
|
|
|
239
323
|
}
|
|
240
324
|
return items;
|
|
241
325
|
}
|
|
326
|
+
function uniquePluginConfigKey(plugin, counts, usedCounts) {
|
|
327
|
+
const base = sanitizeName(plugin.pluginName ?? plugin.name) || "codex-plugin";
|
|
328
|
+
if ((counts.get(base) ?? 0) <= 1) return base;
|
|
329
|
+
const next = (usedCounts.get(base) ?? 0) + 1;
|
|
330
|
+
usedCounts.set(base, next);
|
|
331
|
+
return sanitizeName(`${base}-${next}`) || base;
|
|
332
|
+
}
|
|
333
|
+
function readExistingCodexPluginEntries(config) {
|
|
334
|
+
const entries = readMigrationConfigPath(config, [...CODEX_PLUGIN_NATIVE_CONFIG_PATH, "plugins"]);
|
|
335
|
+
return isRecord(entries) ? entries : {};
|
|
336
|
+
}
|
|
337
|
+
function hasExistingCodexPluginEntry(existingEntries, configKey, pluginName) {
|
|
338
|
+
if (existingEntries[configKey] !== void 0) return true;
|
|
339
|
+
return Object.values(existingEntries).some((entry) => {
|
|
340
|
+
if (!isRecord(entry)) return false;
|
|
341
|
+
return entry.pluginName === pluginName;
|
|
342
|
+
});
|
|
343
|
+
}
|
|
344
|
+
function buildPluginItems(ctx, plugins) {
|
|
345
|
+
const baseCounts = /* @__PURE__ */ new Map();
|
|
346
|
+
for (const plugin of plugins.filter((entry) => entry.migratable)) {
|
|
347
|
+
const base = sanitizeName(plugin.pluginName ?? plugin.name) || "codex-plugin";
|
|
348
|
+
baseCounts.set(base, (baseCounts.get(base) ?? 0) + 1);
|
|
349
|
+
}
|
|
350
|
+
const existingPluginEntries = readExistingCodexPluginEntries(ctx.config);
|
|
351
|
+
const usedCounts = /* @__PURE__ */ new Map();
|
|
352
|
+
let manualIndex = 0;
|
|
353
|
+
const items = [];
|
|
354
|
+
for (const plugin of plugins) {
|
|
355
|
+
if (plugin.migratable && plugin.marketplaceName === "openai-curated" && plugin.pluginName) {
|
|
356
|
+
const configKey = uniquePluginConfigKey(plugin, baseCounts, usedCounts);
|
|
357
|
+
const conflict = !ctx.overwrite && hasExistingCodexPluginEntry(existingPluginEntries, configKey, plugin.pluginName);
|
|
358
|
+
items.push(createMigrationItem({
|
|
359
|
+
id: `plugin:${configKey}`,
|
|
360
|
+
kind: "plugin",
|
|
361
|
+
action: "install",
|
|
362
|
+
status: conflict ? "conflict" : "planned",
|
|
363
|
+
reason: conflict ? MIGRATION_REASON_PLUGIN_EXISTS : void 0,
|
|
364
|
+
source: plugin.source,
|
|
365
|
+
target: `plugins.entries.codex.config.codexPlugins.plugins.${configKey}`,
|
|
366
|
+
message: `Install Codex plugin "${plugin.pluginName}" in the OpenClaw-managed Codex app-server runtime.`,
|
|
367
|
+
details: {
|
|
368
|
+
configKey,
|
|
369
|
+
marketplaceName: CODEX_PLUGINS_MARKETPLACE_NAME,
|
|
370
|
+
pluginName: plugin.pluginName,
|
|
371
|
+
sourceInstalled: plugin.installed === true,
|
|
372
|
+
sourceEnabled: plugin.enabled === true
|
|
373
|
+
}
|
|
374
|
+
}));
|
|
375
|
+
continue;
|
|
376
|
+
}
|
|
377
|
+
manualIndex += 1;
|
|
378
|
+
items.push(createMigrationManualItem({
|
|
379
|
+
id: `plugin:${sanitizeName(plugin.name) || sanitizeName(path.basename(plugin.source))}:${manualIndex}`,
|
|
380
|
+
source: plugin.source,
|
|
381
|
+
message: plugin.message ?? `Codex native plugin "${plugin.name}" was found but not activated automatically.`,
|
|
382
|
+
recommendation: "Review the plugin bundle first, then install trusted compatible plugins with openclaw plugins install <path>."
|
|
383
|
+
}));
|
|
384
|
+
}
|
|
385
|
+
return items;
|
|
386
|
+
}
|
|
387
|
+
function readCodexPluginMigrationConfigEntry(item, enabled) {
|
|
388
|
+
const configKey = item.details?.configKey;
|
|
389
|
+
const marketplaceName = item.details?.marketplaceName;
|
|
390
|
+
const pluginName = item.details?.pluginName;
|
|
391
|
+
if (item.kind !== "plugin" || item.action !== "install" || typeof configKey !== "string" || marketplaceName !== "openai-curated" || typeof pluginName !== "string") return;
|
|
392
|
+
return {
|
|
393
|
+
configKey,
|
|
394
|
+
pluginName,
|
|
395
|
+
enabled
|
|
396
|
+
};
|
|
397
|
+
}
|
|
398
|
+
function readExistingAllowDestructiveActions(config) {
|
|
399
|
+
const value = readMigrationConfigPath(config, [...CODEX_PLUGIN_NATIVE_CONFIG_PATH, "allow_destructive_actions"]);
|
|
400
|
+
return typeof value === "boolean" ? value : void 0;
|
|
401
|
+
}
|
|
402
|
+
function isRecord(value) {
|
|
403
|
+
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
404
|
+
}
|
|
405
|
+
function buildCodexPluginsConfigValue(entries, params = {}) {
|
|
406
|
+
const plugins = Object.fromEntries(entries.toSorted((a, b) => a.configKey.localeCompare(b.configKey)).map((entry) => [entry.configKey, {
|
|
407
|
+
enabled: entry.enabled,
|
|
408
|
+
marketplaceName: CODEX_PLUGINS_MARKETPLACE_NAME,
|
|
409
|
+
pluginName: entry.pluginName
|
|
410
|
+
}]));
|
|
411
|
+
return {
|
|
412
|
+
enabled: true,
|
|
413
|
+
config: { codexPlugins: {
|
|
414
|
+
enabled: true,
|
|
415
|
+
allow_destructive_actions: params.config === void 0 ? false : readExistingAllowDestructiveActions(params.config) ?? false,
|
|
416
|
+
plugins
|
|
417
|
+
} }
|
|
418
|
+
};
|
|
419
|
+
}
|
|
420
|
+
function hasCodexPluginConfigConflict(config, value) {
|
|
421
|
+
const enabled = readMigrationConfigPath(config, CODEX_PLUGIN_ENABLED_PATH);
|
|
422
|
+
if (enabled !== void 0 && enabled !== true) return true;
|
|
423
|
+
const nativeConfig = value.config?.codexPlugins;
|
|
424
|
+
if (!isRecord(nativeConfig)) return hasMigrationConfigPatchConflict(config, CODEX_PLUGIN_NATIVE_CONFIG_PATH, nativeConfig);
|
|
425
|
+
const existingNativeConfig = readMigrationConfigPath(config, CODEX_PLUGIN_NATIVE_CONFIG_PATH);
|
|
426
|
+
if (existingNativeConfig === void 0) return false;
|
|
427
|
+
if (!isRecord(existingNativeConfig)) return true;
|
|
428
|
+
if (existingNativeConfig.enabled !== void 0 && existingNativeConfig.enabled !== true) return true;
|
|
429
|
+
const allowDestructiveActions = nativeConfig.allow_destructive_actions;
|
|
430
|
+
if (existingNativeConfig.allow_destructive_actions !== void 0 && existingNativeConfig.allow_destructive_actions !== allowDestructiveActions) return true;
|
|
431
|
+
const plugins = nativeConfig.plugins;
|
|
432
|
+
if (!isRecord(plugins)) return false;
|
|
433
|
+
return Object.entries(plugins).some(([configKey, plugin]) => {
|
|
434
|
+
if (!isRecord(plugin)) return existingNativeConfig[configKey] !== void 0;
|
|
435
|
+
return hasExistingCodexPluginEntry(readExistingCodexPluginEntries(config), configKey, typeof plugin.pluginName === "string" ? plugin.pluginName : configKey);
|
|
436
|
+
});
|
|
437
|
+
}
|
|
438
|
+
function buildPluginConfigItem(ctx, pluginItems) {
|
|
439
|
+
const entries = pluginItems.filter((item) => item.status === "planned").map((item) => readCodexPluginMigrationConfigEntry(item, true)).filter((entry) => entry !== void 0);
|
|
440
|
+
if (entries.length === 0) return;
|
|
441
|
+
const value = buildCodexPluginsConfigValue(entries, { config: ctx.config });
|
|
442
|
+
const conflict = !ctx.overwrite && hasCodexPluginConfigConflict(ctx.config, value);
|
|
443
|
+
return createMigrationItem({
|
|
444
|
+
id: CODEX_PLUGIN_CONFIG_ITEM_ID,
|
|
445
|
+
kind: "config",
|
|
446
|
+
action: "merge",
|
|
447
|
+
target: "plugins.entries.codex.config.codexPlugins",
|
|
448
|
+
status: conflict ? "conflict" : "planned",
|
|
449
|
+
reason: conflict ? MIGRATION_REASON_TARGET_EXISTS : void 0,
|
|
450
|
+
message: "Enable OpenClaw's Codex plugin integration and record migrated source-installed curated plugins.",
|
|
451
|
+
details: {
|
|
452
|
+
path: [...CODEX_PLUGIN_CONFIG_PATH],
|
|
453
|
+
value
|
|
454
|
+
}
|
|
455
|
+
});
|
|
456
|
+
}
|
|
242
457
|
async function buildCodexMigrationPlan(ctx) {
|
|
243
458
|
const source = await discoverCodexSource(ctx.source);
|
|
244
459
|
if (!hasCodexSource(source)) throw new Error(`Codex state was not found at ${source.root}. Pass --from <path> if it lives elsewhere.`);
|
|
@@ -249,12 +464,10 @@ async function buildCodexMigrationPlan(ctx) {
|
|
|
249
464
|
workspaceDir: targets.workspaceDir,
|
|
250
465
|
overwrite: ctx.overwrite
|
|
251
466
|
}));
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
recommendation: "Review the plugin bundle first, then install trusted compatible plugins with openclaw plugins install <path>."
|
|
257
|
-
}));
|
|
467
|
+
const pluginItems = buildPluginItems(ctx, source.plugins);
|
|
468
|
+
items.push(...pluginItems);
|
|
469
|
+
const pluginConfigItem = buildPluginConfigItem(ctx, pluginItems);
|
|
470
|
+
if (pluginConfigItem) items.push(pluginConfigItem);
|
|
258
471
|
for (const archivePath of source.archivePaths) items.push(createMigrationItem({
|
|
259
472
|
id: archivePath.id,
|
|
260
473
|
kind: "archive",
|
|
@@ -264,8 +477,9 @@ async function buildCodexMigrationPlan(ctx) {
|
|
|
264
477
|
details: { archiveRelativePath: archivePath.relativePath }
|
|
265
478
|
}));
|
|
266
479
|
const warnings = [
|
|
267
|
-
...items.some((item) => item.status === "conflict") ? ["Conflicts were found. Re-run with --overwrite to replace conflicting
|
|
268
|
-
...source.plugins.length > 0 ? ["Codex
|
|
480
|
+
...items.some((item) => item.status === "conflict") ? ["Conflicts were found. Re-run with --overwrite to replace conflicting migration targets after item-level backups."] : [],
|
|
481
|
+
...source.plugins.length > 0 ? ["Codex source-installed openai-curated plugins are planned for native activation; cached plugin bundles remain manual-review only."] : [],
|
|
482
|
+
...source.pluginDiscoveryError ? [`Codex app-server plugin inventory discovery failed: ${source.pluginDiscoveryError}. Cached plugin bundles, if any, are advisory only.`] : [],
|
|
269
483
|
...source.archivePaths.length > 0 ? ["Codex config and hook files are archive-only. They are preserved in the migration report, not loaded into OpenClaw automatically."] : []
|
|
270
484
|
];
|
|
271
485
|
return {
|
|
@@ -275,7 +489,7 @@ async function buildCodexMigrationPlan(ctx) {
|
|
|
275
489
|
summary: summarizeMigrationItems(items),
|
|
276
490
|
items,
|
|
277
491
|
warnings,
|
|
278
|
-
nextSteps: ["Run openclaw doctor after applying the migration.", "Review skipped Codex plugin/config/hook items before
|
|
492
|
+
nextSteps: ["Run openclaw doctor after applying the migration.", "Review skipped or auth-required Codex plugin/config/hook items before exposing them in OpenClaw sessions."],
|
|
279
493
|
metadata: {
|
|
280
494
|
agentDir: targets.agentDir,
|
|
281
495
|
codexHome: source.codexHome,
|
|
@@ -286,16 +500,33 @@ async function buildCodexMigrationPlan(ctx) {
|
|
|
286
500
|
}
|
|
287
501
|
//#endregion
|
|
288
502
|
//#region extensions/codex/src/migration/apply.ts
|
|
503
|
+
const CODEX_PLUGIN_AUTH_REQUIRED_REASON = "auth_required";
|
|
504
|
+
const CODEX_PLUGIN_NOT_SELECTED_REASON = "not selected for migration";
|
|
505
|
+
var CodexPluginConfigConflictError = class extends Error {
|
|
506
|
+
constructor(reason) {
|
|
507
|
+
super(reason);
|
|
508
|
+
this.reason = reason;
|
|
509
|
+
this.name = "CodexPluginConfigConflictError";
|
|
510
|
+
}
|
|
511
|
+
};
|
|
289
512
|
async function applyCodexMigrationPlan(params) {
|
|
290
513
|
const plan = params.plan ?? await buildCodexMigrationPlan(params.ctx);
|
|
291
514
|
const reportDir = params.ctx.reportDir ?? path.join(params.ctx.stateDir, "migration", "codex");
|
|
292
515
|
const items = [];
|
|
516
|
+
const runtime = withCachedMigrationConfigRuntime(params.ctx.runtime ?? params.runtime, params.ctx.config);
|
|
517
|
+
const applyCtx = {
|
|
518
|
+
...params.ctx,
|
|
519
|
+
runtime
|
|
520
|
+
};
|
|
293
521
|
for (const item of plan.items) {
|
|
294
522
|
if (item.status !== "planned") {
|
|
295
523
|
items.push(item);
|
|
296
524
|
continue;
|
|
297
525
|
}
|
|
298
|
-
if (item.
|
|
526
|
+
if (item.id === "config:codex-plugins") items.push(await applyCodexPluginConfigItem(applyCtx, item, items));
|
|
527
|
+
else if (item.kind === "plugin" && item.action === "install") items.push(await applyCodexPluginInstallItem(applyCtx, item));
|
|
528
|
+
else if (item.kind === "manual") items.push(applyMigrationManualItem(item));
|
|
529
|
+
else if (item.action === "archive") items.push(await archiveMigrationItem(item, reportDir));
|
|
299
530
|
else items.push(await copyMigrationFileItem(item, reportDir, { overwrite: params.ctx.overwrite }));
|
|
300
531
|
}
|
|
301
532
|
const result = {
|
|
@@ -308,9 +539,150 @@ async function applyCodexMigrationPlan(params) {
|
|
|
308
539
|
await writeMigrationReport(result, { title: "Codex Migration Report" });
|
|
309
540
|
return result;
|
|
310
541
|
}
|
|
542
|
+
async function applyCodexPluginInstallItem(ctx, item) {
|
|
543
|
+
const policy = readCodexPluginPolicy(item);
|
|
544
|
+
if (!policy) return {
|
|
545
|
+
...markMigrationItemError(item, "invalid Codex plugin migration item"),
|
|
546
|
+
details: {
|
|
547
|
+
...item.details,
|
|
548
|
+
code: "invalid_plugin_item"
|
|
549
|
+
}
|
|
550
|
+
};
|
|
551
|
+
try {
|
|
552
|
+
const result = await ensureCodexPluginActivation({
|
|
553
|
+
identity: policy,
|
|
554
|
+
installEvenIfActive: true,
|
|
555
|
+
request: async (method, requestParams) => await requestCodexAppServerJson({
|
|
556
|
+
method,
|
|
557
|
+
requestParams,
|
|
558
|
+
timeoutMs: 6e4,
|
|
559
|
+
config: ctx.config
|
|
560
|
+
})
|
|
561
|
+
});
|
|
562
|
+
defaultCodexAppInventoryCache.clear();
|
|
563
|
+
const baseDetails = {
|
|
564
|
+
...item.details,
|
|
565
|
+
code: result.reason,
|
|
566
|
+
activationReason: result.reason,
|
|
567
|
+
...codexPluginActivationReportState(result),
|
|
568
|
+
installAttempted: result.installAttempted,
|
|
569
|
+
diagnostics: result.diagnostics.map((diagnostic) => diagnostic.message)
|
|
570
|
+
};
|
|
571
|
+
if (result.ok) return {
|
|
572
|
+
...item,
|
|
573
|
+
status: "migrated",
|
|
574
|
+
...result.reason === "already_active" ? { reason: "already active" } : {},
|
|
575
|
+
details: baseDetails
|
|
576
|
+
};
|
|
577
|
+
if (result.reason === CODEX_PLUGIN_AUTH_REQUIRED_REASON) return {
|
|
578
|
+
...item,
|
|
579
|
+
status: "skipped",
|
|
580
|
+
reason: CODEX_PLUGIN_AUTH_REQUIRED_REASON,
|
|
581
|
+
details: {
|
|
582
|
+
...baseDetails,
|
|
583
|
+
appsNeedingAuth: sanitizeAppsNeedingAuth(result.installResponse?.appsNeedingAuth ?? [])
|
|
584
|
+
}
|
|
585
|
+
};
|
|
586
|
+
return {
|
|
587
|
+
...item,
|
|
588
|
+
status: "error",
|
|
589
|
+
reason: result.reason,
|
|
590
|
+
details: baseDetails
|
|
591
|
+
};
|
|
592
|
+
} catch (error) {
|
|
593
|
+
return {
|
|
594
|
+
...item,
|
|
595
|
+
status: "error",
|
|
596
|
+
reason: error instanceof Error ? error.message : String(error),
|
|
597
|
+
details: {
|
|
598
|
+
...item.details,
|
|
599
|
+
code: "plugin_install_failed"
|
|
600
|
+
}
|
|
601
|
+
};
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
async function applyCodexPluginConfigItem(ctx, item, appliedItems) {
|
|
605
|
+
const entries = appliedItems.map(readAppliedPluginConfigEntry).filter((entry) => entry !== void 0);
|
|
606
|
+
if (entries.length === 0) return markMigrationItemSkipped(item, "no selected Codex plugins");
|
|
607
|
+
const configApi = ctx.runtime?.config;
|
|
608
|
+
if (!configApi?.current || !configApi.mutateConfigFile) return markMigrationItemError(item, "config runtime unavailable");
|
|
609
|
+
const currentConfig = configApi.current();
|
|
610
|
+
const value = buildCodexPluginsConfigValue(entries, { config: currentConfig });
|
|
611
|
+
if (!ctx.overwrite && hasCodexPluginConfigConflict(currentConfig, value)) return markMigrationItemConflict(item, MIGRATION_REASON_TARGET_EXISTS);
|
|
612
|
+
try {
|
|
613
|
+
await configApi.mutateConfigFile({
|
|
614
|
+
base: "runtime",
|
|
615
|
+
afterWrite: { mode: "auto" },
|
|
616
|
+
mutate(draft) {
|
|
617
|
+
if (!ctx.overwrite && hasCodexPluginConfigConflict(draft, value)) throw new CodexPluginConfigConflictError(MIGRATION_REASON_TARGET_EXISTS);
|
|
618
|
+
writeMigrationConfigPath(draft, CODEX_PLUGIN_CONFIG_PATH, value);
|
|
619
|
+
}
|
|
620
|
+
});
|
|
621
|
+
return {
|
|
622
|
+
...item,
|
|
623
|
+
status: "migrated",
|
|
624
|
+
details: {
|
|
625
|
+
...item.details,
|
|
626
|
+
path: [...CODEX_PLUGIN_CONFIG_PATH],
|
|
627
|
+
value
|
|
628
|
+
}
|
|
629
|
+
};
|
|
630
|
+
} catch (error) {
|
|
631
|
+
if (error instanceof CodexPluginConfigConflictError) return markMigrationItemConflict(item, error.reason);
|
|
632
|
+
return markMigrationItemError(item, error instanceof Error ? error.message : String(error));
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
function readAppliedPluginConfigEntry(item) {
|
|
636
|
+
if (item.status === "migrated") return readCodexPluginMigrationConfigEntry(item, true);
|
|
637
|
+
if (item.status === "skipped" && item.reason !== CODEX_PLUGIN_NOT_SELECTED_REASON && item.reason === CODEX_PLUGIN_AUTH_REQUIRED_REASON) return readCodexPluginMigrationConfigEntry(item, false);
|
|
638
|
+
}
|
|
639
|
+
function readCodexPluginPolicy(item) {
|
|
640
|
+
const configKey = item.details?.configKey;
|
|
641
|
+
const marketplaceName = item.details?.marketplaceName;
|
|
642
|
+
const pluginName = item.details?.pluginName;
|
|
643
|
+
if (typeof configKey !== "string" || marketplaceName !== "openai-curated" || typeof pluginName !== "string") return;
|
|
644
|
+
return {
|
|
645
|
+
configKey,
|
|
646
|
+
marketplaceName: CODEX_PLUGINS_MARKETPLACE_NAME,
|
|
647
|
+
pluginName,
|
|
648
|
+
enabled: true,
|
|
649
|
+
allowDestructiveActions: false
|
|
650
|
+
};
|
|
651
|
+
}
|
|
652
|
+
function codexPluginActivationReportState(result) {
|
|
653
|
+
switch (result.reason) {
|
|
654
|
+
case "already_active":
|
|
655
|
+
case "installed": return {
|
|
656
|
+
installed: true,
|
|
657
|
+
enabled: true
|
|
658
|
+
};
|
|
659
|
+
case "auth_required": return {
|
|
660
|
+
installed: true,
|
|
661
|
+
enabled: false
|
|
662
|
+
};
|
|
663
|
+
case "disabled":
|
|
664
|
+
case "marketplace_missing":
|
|
665
|
+
case "plugin_missing": return {
|
|
666
|
+
installed: false,
|
|
667
|
+
enabled: false
|
|
668
|
+
};
|
|
669
|
+
case "refresh_failed": return {
|
|
670
|
+
installed: true,
|
|
671
|
+
enabled: false
|
|
672
|
+
};
|
|
673
|
+
}
|
|
674
|
+
return result.reason;
|
|
675
|
+
}
|
|
676
|
+
function sanitizeAppsNeedingAuth(apps) {
|
|
677
|
+
return apps.map((app) => ({
|
|
678
|
+
id: app.id,
|
|
679
|
+
name: app.name,
|
|
680
|
+
needsAuth: app.needsAuth
|
|
681
|
+
}));
|
|
682
|
+
}
|
|
311
683
|
//#endregion
|
|
312
684
|
//#region extensions/codex/src/migration/provider.ts
|
|
313
|
-
function buildCodexMigrationProvider() {
|
|
685
|
+
function buildCodexMigrationProvider(params = {}) {
|
|
314
686
|
return {
|
|
315
687
|
id: "codex",
|
|
316
688
|
label: "Codex",
|
|
@@ -330,7 +702,8 @@ function buildCodexMigrationProvider() {
|
|
|
330
702
|
async apply(ctx, plan) {
|
|
331
703
|
return await applyCodexMigrationPlan({
|
|
332
704
|
ctx,
|
|
333
|
-
plan
|
|
705
|
+
plan,
|
|
706
|
+
runtime: params.runtime
|
|
334
707
|
});
|
|
335
708
|
}
|
|
336
709
|
};
|
|
@@ -346,7 +719,7 @@ var codex_default = definePluginEntry({
|
|
|
346
719
|
api.registerAgentHarness(createCodexAppServerAgentHarness({ pluginConfig: api.pluginConfig }));
|
|
347
720
|
api.registerProvider(buildCodexProvider({ pluginConfig: api.pluginConfig }));
|
|
348
721
|
api.registerMediaUnderstandingProvider(buildCodexMediaUnderstandingProvider({ pluginConfig: api.pluginConfig }));
|
|
349
|
-
api.registerMigrationProvider(buildCodexMigrationProvider());
|
|
722
|
+
api.registerMigrationProvider(buildCodexMigrationProvider({ runtime: api.runtime }));
|
|
350
723
|
api.registerCommand(createCodexCommand({ pluginConfig: api.pluginConfig }));
|
|
351
724
|
api.on("inbound_claim", (event, ctx) => handleCodexConversationInboundClaim(event, ctx, { pluginConfig: resolveCurrentPluginConfig() }));
|
|
352
725
|
api.onConversationBindingResolved?.(handleCodexConversationBindingResolved);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { CODEX_PROVIDER_ID, FALLBACK_CODEX_MODELS } from "./provider-catalog.js";
|
|
2
|
-
import {
|
|
3
|
-
import { a as readCodexErrorNotification, c as readCodexTurnCompletedNotification, n as assertCodexThreadStartResponse, r as assertCodexTurnStartResponse } from "./protocol-validators-
|
|
4
|
-
import { i as readModelListResult } from "./models-
|
|
2
|
+
import { s as resolveCodexAppServerRuntimeOptions } from "./config-BZiM7rhH.js";
|
|
3
|
+
import { a as readCodexErrorNotification, c as readCodexTurnCompletedNotification, n as assertCodexThreadStartResponse, r as assertCodexTurnStartResponse } from "./protocol-validators-CbqWfY5M.js";
|
|
4
|
+
import { i as readModelListResult } from "./models-nfvRggjT.js";
|
|
5
5
|
import { t as isJsonObject } from "./protocol-C9UWI98H.js";
|
|
6
6
|
//#region extensions/codex/media-understanding-provider.ts
|
|
7
7
|
const DEFAULT_CODEX_IMAGE_MODEL = FALLBACK_CODEX_MODELS.find((model) => model.inputModalities.includes("image"))?.id ?? FALLBACK_CODEX_MODELS[0]?.id;
|
|
@@ -37,7 +37,7 @@ async function describeCodexImages(req, options) {
|
|
|
37
37
|
const appServer = resolveCodexAppServerRuntimeOptions({ pluginConfig: options.pluginConfig });
|
|
38
38
|
const timeoutMs = Math.max(100, req.timeoutMs);
|
|
39
39
|
const ownsClient = !options.clientFactory;
|
|
40
|
-
const client = options.clientFactory ? await options.clientFactory(appServer.start, req.profile) : await import("./shared-client-
|
|
40
|
+
const client = options.clientFactory ? await options.clientFactory(appServer.start, req.profile) : await import("./shared-client-pLCOzMaZ.js").then((n) => n.r).then(({ createIsolatedCodexAppServerClient }) => createIsolatedCodexAppServerClient({
|
|
41
41
|
startOptions: appServer.start,
|
|
42
42
|
timeoutMs,
|
|
43
43
|
authProfileId: req.profile
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as __exportAll } from "./rolldown-runtime-DUslC3ob.js";
|
|
2
|
-
import { o as readCodexModelListResponse } from "./protocol-validators-
|
|
2
|
+
import { o as readCodexModelListResponse } from "./protocol-validators-CbqWfY5M.js";
|
|
3
3
|
//#region extensions/codex/src/app-server/models.ts
|
|
4
4
|
var models_exports = /* @__PURE__ */ __exportAll({
|
|
5
5
|
listAllCodexAppServerModels: () => listAllCodexAppServerModels,
|
|
@@ -39,7 +39,7 @@ async function listAllCodexAppServerModels(options = {}) {
|
|
|
39
39
|
async function withCodexAppServerModelClient(options, run) {
|
|
40
40
|
const timeoutMs = options.timeoutMs ?? 2500;
|
|
41
41
|
const useSharedClient = options.sharedClient !== false;
|
|
42
|
-
const { createIsolatedCodexAppServerClient, getSharedCodexAppServerClient } = await import("./shared-client-
|
|
42
|
+
const { createIsolatedCodexAppServerClient, getSharedCodexAppServerClient } = await import("./shared-client-pLCOzMaZ.js").then((n) => n.r);
|
|
43
43
|
const client = useSharedClient ? await getSharedCodexAppServerClient({
|
|
44
44
|
startOptions: options.startOptions,
|
|
45
45
|
timeoutMs,
|