@gakr-gakr/codex 0.1.0 → 0.1.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 (115) hide show
  1. package/dist/client-DNN2uyJW.js +642 -0
  2. package/dist/client-factory-Bu9OClHJ.js +9 -0
  3. package/dist/command-formatters-BpPOTePl.js +520 -0
  4. package/dist/command-handlers-BBs7Vws9.js +1533 -0
  5. package/dist/compact-CDboBy7o.js +329 -0
  6. package/dist/computer-use-DCZB46Sw.js +367 -0
  7. package/dist/config-CLMSw0p2.js +510 -0
  8. package/dist/doctor-contract-api.js +53 -0
  9. package/dist/harness.js +51 -0
  10. package/dist/index.js +1171 -0
  11. package/dist/media-understanding-provider.js +335 -0
  12. package/dist/models-jLA2SIvd.js +110 -0
  13. package/dist/node-cli-sessions-BLRDs_US.js +1216 -0
  14. package/dist/plugin-activation-CEy_oYpx.js +452 -0
  15. package/dist/prompt-overlay.js +12 -0
  16. package/dist/protocol-C9UWI98H.js +9 -0
  17. package/dist/protocol-validators-BGBspNmF.js +5988 -0
  18. package/dist/provider-catalog.js +84 -0
  19. package/dist/provider-discovery.js +33 -0
  20. package/dist/provider.js +150 -0
  21. package/dist/rate-limit-cache-9LxQdE0K.js +24 -0
  22. package/dist/request-DbSPeTcV.js +89 -0
  23. package/dist/rolldown-runtime-DUslC3ob.js +14 -0
  24. package/dist/run-attempt-BoEwzQCv.js +5463 -0
  25. package/dist/session-binding-e2GFp9VH.js +222 -0
  26. package/dist/shared-client-D7Vy0glq.js +631 -0
  27. package/dist/side-question-BDLuEzFP.js +668 -0
  28. package/dist/test-api.js +49 -0
  29. package/dist/thread-lifecycle-Clo0EHMk.js +1565 -0
  30. package/dist/vision-tools-Cofrv35p.js +1379 -0
  31. package/package.json +16 -1
  32. package/doctor-contract-api.ts +0 -68
  33. package/harness.ts +0 -72
  34. package/index.ts +0 -124
  35. package/media-understanding-provider.ts +0 -521
  36. package/prompt-overlay.ts +0 -21
  37. package/provider-catalog.ts +0 -83
  38. package/provider-discovery.ts +0 -45
  39. package/provider.ts +0 -243
  40. package/src/app-server/app-inventory-cache.ts +0 -324
  41. package/src/app-server/approval-bridge.ts +0 -1211
  42. package/src/app-server/auth-bridge.ts +0 -614
  43. package/src/app-server/capabilities.ts +0 -27
  44. package/src/app-server/client-factory.ts +0 -24
  45. package/src/app-server/client.ts +0 -715
  46. package/src/app-server/compact.ts +0 -512
  47. package/src/app-server/computer-use.ts +0 -683
  48. package/src/app-server/config.ts +0 -1038
  49. package/src/app-server/context-engine-projection.ts +0 -403
  50. package/src/app-server/dynamic-tool-diagnostics.ts +0 -73
  51. package/src/app-server/dynamic-tool-profile.ts +0 -70
  52. package/src/app-server/dynamic-tools.ts +0 -623
  53. package/src/app-server/elicitation-bridge.ts +0 -783
  54. package/src/app-server/event-projector.ts +0 -2065
  55. package/src/app-server/image-payload-sanitizer.ts +0 -167
  56. package/src/app-server/local-runtime-attribution.ts +0 -39
  57. package/src/app-server/managed-binary.ts +0 -193
  58. package/src/app-server/models.ts +0 -172
  59. package/src/app-server/native-hook-relay.ts +0 -150
  60. package/src/app-server/native-subagent-task-mirror.ts +0 -497
  61. package/src/app-server/plugin-activation.ts +0 -283
  62. package/src/app-server/plugin-app-cache-key.ts +0 -74
  63. package/src/app-server/plugin-approval-roundtrip.ts +0 -122
  64. package/src/app-server/plugin-inventory.ts +0 -357
  65. package/src/app-server/plugin-thread-config.ts +0 -455
  66. package/src/app-server/protocol-generated/json/DynamicToolCallParams.json +0 -33
  67. package/src/app-server/protocol-generated/json/v2/ErrorNotification.json +0 -199
  68. package/src/app-server/protocol-generated/json/v2/GetAccountResponse.json +0 -102
  69. package/src/app-server/protocol-generated/json/v2/ModelListResponse.json +0 -227
  70. package/src/app-server/protocol-generated/json/v2/ThreadResumeResponse.json +0 -2630
  71. package/src/app-server/protocol-generated/json/v2/ThreadStartResponse.json +0 -2630
  72. package/src/app-server/protocol-generated/json/v2/TurnCompletedNotification.json +0 -1659
  73. package/src/app-server/protocol-generated/json/v2/TurnStartResponse.json +0 -1655
  74. package/src/app-server/protocol-validators.ts +0 -203
  75. package/src/app-server/protocol.ts +0 -520
  76. package/src/app-server/rate-limit-cache.ts +0 -48
  77. package/src/app-server/rate-limits.ts +0 -583
  78. package/src/app-server/request.ts +0 -73
  79. package/src/app-server/run-attempt.ts +0 -4862
  80. package/src/app-server/session-binding.ts +0 -398
  81. package/src/app-server/session-history.ts +0 -44
  82. package/src/app-server/shared-client.ts +0 -289
  83. package/src/app-server/side-question.ts +0 -1009
  84. package/src/app-server/test-support.ts +0 -48
  85. package/src/app-server/thread-lifecycle.ts +0 -959
  86. package/src/app-server/timeout.ts +0 -9
  87. package/src/app-server/tool-progress-normalization.ts +0 -77
  88. package/src/app-server/trajectory.ts +0 -368
  89. package/src/app-server/transcript-mirror.ts +0 -208
  90. package/src/app-server/transport-stdio.ts +0 -107
  91. package/src/app-server/transport-websocket.ts +0 -90
  92. package/src/app-server/transport.ts +0 -117
  93. package/src/app-server/user-input-bridge.ts +0 -316
  94. package/src/app-server/version.ts +0 -4
  95. package/src/app-server/vision-tools.ts +0 -12
  96. package/src/command-account.ts +0 -544
  97. package/src/command-formatters.ts +0 -426
  98. package/src/command-handlers.ts +0 -2021
  99. package/src/command-plugins-management.ts +0 -137
  100. package/src/command-rpc.ts +0 -142
  101. package/src/commands.ts +0 -65
  102. package/src/conversation-binding-data.ts +0 -124
  103. package/src/conversation-binding.ts +0 -561
  104. package/src/conversation-control.ts +0 -303
  105. package/src/conversation-turn-collector.ts +0 -186
  106. package/src/conversation-turn-input.ts +0 -106
  107. package/src/migration/apply.ts +0 -501
  108. package/src/migration/helpers.ts +0 -55
  109. package/src/migration/plan.ts +0 -461
  110. package/src/migration/provider.ts +0 -41
  111. package/src/migration/source.ts +0 -643
  112. package/src/migration/targets.ts +0 -25
  113. package/src/node-cli-sessions.ts +0 -711
  114. package/test-api.ts +0 -95
  115. package/tsconfig.json +0 -16
package/dist/index.js ADDED
@@ -0,0 +1,1171 @@
1
+ import { createCodexAppServerAgentHarness } from "./harness.js";
2
+ import { c as resolveCodexAppServerRuntimeOptions, s as readCodexPluginConfig, t as CODEX_PLUGINS_MARKETPLACE_NAME } from "./config-CLMSw0p2.js";
3
+ import { buildCodexMediaUnderstandingProvider } from "./media-understanding-provider.js";
4
+ import { buildCodexProvider } from "./provider.js";
5
+ import { i as describeControlFailure, n as buildCodexPluginAppCacheKey, t as requestCodexAppServerJson } from "./request-DbSPeTcV.js";
6
+ import { r as formatCodexDisplayText } from "./command-formatters-BpPOTePl.js";
7
+ import { c as resolveCodexAppServerAuthAccountCacheKey, d as resolveCodexAppServerEnvApiKeyCacheKey, i as getSharedCodexAppServerClient, n as clearSharedCodexAppServerClientIfCurrentAndWait, u as resolveCodexAppServerAuthProfileIdForAgent } from "./shared-client-D7Vy0glq.js";
8
+ import { a as resolveCodexCliSessionForBindingOnNode, c as handleCodexConversationInboundClaim, i as listCodexCliSessionsOnNode, n as createCodexCliSessionNodeInvokePolicies, o as resumeCodexCliSessionOnNode, s as handleCodexConversationBindingResolved, t as createCodexCliSessionNodeHostCommands } from "./node-cli-sessions-BLRDs_US.js";
9
+ import { a as defaultCodexAppInventoryCache, n as pluginReadParams, t as ensureCodexPluginActivation } from "./plugin-activation-CEy_oYpx.js";
10
+ import { mutateConfigFile } from "autobot/plugin-sdk/config-mutation";
11
+ import { resolveLivePluginConfigObject } from "autobot/plugin-sdk/plugin-config-runtime";
12
+ import { definePluginEntry } from "autobot/plugin-sdk/plugin-entry";
13
+ import os from "node:os";
14
+ import fs from "node:fs/promises";
15
+ import path from "node:path";
16
+ import { resolveAgentConfig, resolveAgentWorkspaceDir, resolveDefaultAgentId } from "autobot/plugin-sdk/agent-runtime";
17
+ import { pathExists } from "autobot/plugin-sdk/security-runtime";
18
+ import { MIGRATION_REASON_TARGET_EXISTS, applyMigrationManualItem, createMigrationItem, createMigrationManualItem, hasMigrationConfigPatchConflict, markMigrationItemConflict, markMigrationItemError, markMigrationItemSkipped, readMigrationConfigPath, summarizeMigrationItems, writeMigrationConfigPath } from "autobot/plugin-sdk/migration";
19
+ import { archiveMigrationItem, copyMigrationFileItem, withCachedMigrationConfigRuntime, writeMigrationReport } from "autobot/plugin-sdk/migration-runtime";
20
+ import { readJsonFileWithFallback } from "autobot/plugin-sdk/json-store";
21
+ //#region extensions/codex/src/commands.ts
22
+ function createCodexCommand(options) {
23
+ return {
24
+ name: "codex",
25
+ description: "Inspect and control the Codex app-server harness",
26
+ ownership: "reserved",
27
+ agentPromptGuidance: [{
28
+ text: "Native Codex app-server plugin is available (`/codex ...`). For Codex bind/control/thread/resume/steer/stop requests, prefer `/codex bind`, `/codex threads`, `/codex resume`, `/codex steer`, and `/codex stop` over ACP.",
29
+ surfaces: ["pi_main"]
30
+ }, {
31
+ text: "Use ACP for Codex only when the user explicitly asks for ACP/acpx or wants to test the ACP path.",
32
+ surfaces: ["pi_main"]
33
+ }],
34
+ acceptsArgs: true,
35
+ requireAuth: true,
36
+ handler: (ctx) => handleCodexCommand(ctx, options)
37
+ };
38
+ }
39
+ async function handleCodexCommand(ctx, options = {}) {
40
+ const { loadSubcommandHandler, ...subcommandOptions } = options;
41
+ try {
42
+ return await (loadSubcommandHandler ? await loadSubcommandHandler() : await loadDefaultCodexSubcommandHandler())(ctx, subcommandOptions);
43
+ } catch (error) {
44
+ return { text: `Codex command failed: ${formatCodexDisplayText(describeControlFailure(error))}` };
45
+ }
46
+ }
47
+ async function loadDefaultCodexSubcommandHandler() {
48
+ const { handleCodexSubcommand } = await import("./command-handlers-BBs7Vws9.js");
49
+ return handleCodexSubcommand;
50
+ }
51
+ //#endregion
52
+ //#region extensions/codex/src/migration/helpers.ts
53
+ async function exists(filePath) {
54
+ return await pathExists(filePath);
55
+ }
56
+ async function isDirectory(filePath) {
57
+ if (!filePath) return false;
58
+ try {
59
+ return (await fs.stat(filePath)).isDirectory();
60
+ } catch {
61
+ return false;
62
+ }
63
+ }
64
+ function resolveUserHomeDir() {
65
+ return process.env.HOME?.trim() || os.homedir();
66
+ }
67
+ function resolveHomePath(value) {
68
+ if (value === "~") return resolveUserHomeDir();
69
+ if (value.startsWith("~/")) return path.join(resolveUserHomeDir(), value.slice(2));
70
+ return path.resolve(value);
71
+ }
72
+ function sanitizeName(value) {
73
+ return value.trim().toLowerCase().replaceAll(/[^a-z0-9._-]+/gu, "-").replaceAll(/^-+|-+$/gu, "").slice(0, 64);
74
+ }
75
+ async function readJsonObject(filePath) {
76
+ if (!filePath) return {};
77
+ const { value: parsed } = await readJsonFileWithFallback(filePath, {});
78
+ return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
79
+ }
80
+ //#endregion
81
+ //#region extensions/codex/src/migration/source.ts
82
+ const SKILL_FILENAME = "SKILL.md";
83
+ const MAX_SCAN_DEPTH = 6;
84
+ const MAX_DISCOVERED_DIRS = 2e3;
85
+ function defaultCodexHome() {
86
+ return resolveHomePath(process.env.CODEX_HOME?.trim() || "~/.codex");
87
+ }
88
+ function personalAgentsSkillsDir() {
89
+ return path.join(resolveUserHomeDir(), ".agents", "skills");
90
+ }
91
+ async function safeReadDir(dir) {
92
+ return await fs.readdir(dir, { withFileTypes: true }).catch(() => []);
93
+ }
94
+ async function discoverSkillDirs(params) {
95
+ if (!params.root || !await isDirectory(params.root)) return [];
96
+ const discovered = [];
97
+ async function visit(dir, depth) {
98
+ if (discovered.length >= MAX_DISCOVERED_DIRS || depth > MAX_SCAN_DEPTH) return;
99
+ const name = path.basename(dir);
100
+ if (params.excludeSystem && depth === 1 && name === ".system") return;
101
+ if (await exists(path.join(dir, SKILL_FILENAME))) {
102
+ discovered.push({
103
+ name,
104
+ source: dir,
105
+ sourceLabel: params.sourceLabel
106
+ });
107
+ return;
108
+ }
109
+ for (const entry of await safeReadDir(dir)) {
110
+ if (!entry.isDirectory()) continue;
111
+ await visit(path.join(dir, entry.name), depth + 1);
112
+ }
113
+ }
114
+ await visit(params.root, 0);
115
+ return discovered;
116
+ }
117
+ async function discoverPluginDirs(codexHome) {
118
+ const root = path.join(codexHome, "plugins", "cache");
119
+ if (!await isDirectory(root)) return [];
120
+ const discovered = /* @__PURE__ */ new Map();
121
+ async function visit(dir, depth) {
122
+ if (discovered.size >= MAX_DISCOVERED_DIRS || depth > MAX_SCAN_DEPTH) return;
123
+ const manifestPath = path.join(dir, ".codex-plugin", "plugin.json");
124
+ if (await exists(manifestPath)) {
125
+ const manifest = await readJsonObject(manifestPath);
126
+ const name = (typeof manifest.name === "string" ? manifest.name.trim() : "") || path.basename(dir);
127
+ discovered.set(dir, {
128
+ name,
129
+ source: dir,
130
+ manifestPath,
131
+ sourceKind: "cache",
132
+ migratable: false,
133
+ message: "Cached Codex plugin bundle found. Review manually unless the plugin is also installed in the source Codex app-server inventory"
134
+ });
135
+ return;
136
+ }
137
+ for (const entry of await safeReadDir(dir)) {
138
+ if (!entry.isDirectory()) continue;
139
+ await visit(path.join(dir, entry.name), depth + 1);
140
+ }
141
+ }
142
+ await visit(root, 0);
143
+ return [...discovered.values()].toSorted((a, b) => a.source.localeCompare(b.source));
144
+ }
145
+ async function discoverInstalledCuratedPlugins(codexHome, options = {}) {
146
+ const requestOptions = { startOptions: sourceCodexAppServerStartOptions(codexHome) };
147
+ try {
148
+ const marketplace = (await requestSourceCodexAppServerJson(requestOptions, {
149
+ method: "plugin/list",
150
+ requestParams: { cwds: [] }
151
+ })).marketplaces.find((entry) => entry.name === CODEX_PLUGINS_MARKETPLACE_NAME);
152
+ if (!marketplace) return {
153
+ plugins: [],
154
+ error: `Codex marketplace ${CODEX_PLUGINS_MARKETPLACE_NAME} was not found in source plugin inventory.`
155
+ };
156
+ const plugins = marketplace.plugins.filter((plugin) => plugin.installed).map((plugin) => buildInstalledPluginSource(plugin)).filter((plugin) => plugin !== void 0);
157
+ return { plugins: (options.evaluatePluginMigrationEligibility === true ? await withPluginMigrationEligibility({
158
+ plugins,
159
+ marketplace: marketplaceRef(marketplace),
160
+ requestOptions,
161
+ verifyPluginApps: options.verifyPluginApps === true
162
+ }) : plugins).toSorted((a, b) => (a.pluginName ?? a.name).localeCompare(b.pluginName ?? b.name)) };
163
+ } catch (error) {
164
+ return {
165
+ plugins: [],
166
+ error: error instanceof Error ? error.message : String(error)
167
+ };
168
+ }
169
+ }
170
+ function sourceCodexAppServerStartOptions(codexHome) {
171
+ return {
172
+ transport: "stdio",
173
+ command: "codex",
174
+ commandSource: "managed",
175
+ args: [
176
+ "app-server",
177
+ "--listen",
178
+ "stdio://"
179
+ ],
180
+ headers: {},
181
+ env: {
182
+ CODEX_HOME: codexHome,
183
+ HOME: path.dirname(codexHome)
184
+ }
185
+ };
186
+ }
187
+ async function requestSourceCodexAppServerJson(options, params) {
188
+ return await requestCodexAppServerJson({
189
+ method: params.method,
190
+ requestParams: params.requestParams,
191
+ timeoutMs: 6e4,
192
+ startOptions: options.startOptions,
193
+ authProfileId: null,
194
+ isolated: true
195
+ });
196
+ }
197
+ function buildInstalledPluginSource(plugin) {
198
+ const pluginName = pluginNameFromSummary(plugin);
199
+ if (!pluginName) return;
200
+ return {
201
+ name: plugin.name,
202
+ pluginName,
203
+ marketplaceName: CODEX_PLUGINS_MARKETPLACE_NAME,
204
+ source: `${CODEX_PLUGINS_MARKETPLACE_NAME}/${pluginName}`,
205
+ sourceKind: "app-server",
206
+ migratable: true,
207
+ installed: plugin.installed,
208
+ enabled: plugin.enabled
209
+ };
210
+ }
211
+ function marketplaceRef(marketplace) {
212
+ return {
213
+ name: CODEX_PLUGINS_MARKETPLACE_NAME,
214
+ ...marketplace.path ? { path: marketplace.path } : {},
215
+ ...!marketplace.path ? { remoteMarketplaceName: marketplace.name } : {}
216
+ };
217
+ }
218
+ async function withPluginMigrationEligibility(params) {
219
+ const pending = [];
220
+ const evaluated = [];
221
+ for (const plugin of params.plugins) {
222
+ if (plugin.enabled !== true) {
223
+ evaluated.push({
224
+ ...plugin,
225
+ migratable: false,
226
+ migrationBlock: { code: "plugin_disabled" },
227
+ message: `Codex plugin "${plugin.pluginName ?? plugin.name}" is installed in Codex but disabled; enable it in Codex before migrating it to AutoBot.`
228
+ });
229
+ continue;
230
+ }
231
+ const detail = await readPluginDetail(params.requestOptions, params.marketplace, plugin);
232
+ if (!detail.ok) {
233
+ evaluated.push({
234
+ ...plugin,
235
+ migratable: false,
236
+ migrationBlock: {
237
+ code: "plugin_read_unavailable",
238
+ error: detail.error
239
+ },
240
+ message: `Codex plugin "${plugin.pluginName ?? plugin.name}" detail could not be read: ${detail.error}`
241
+ });
242
+ continue;
243
+ }
244
+ if (detail.detail.apps.length === 0) {
245
+ evaluated.push({
246
+ ...plugin,
247
+ migratable: true
248
+ });
249
+ continue;
250
+ }
251
+ const apps = detail.detail.apps.map(sourcePluginAppFact).toSorted((left, right) => left.id.localeCompare(right.id));
252
+ pending.push({
253
+ plugin,
254
+ apps
255
+ });
256
+ }
257
+ if (pending.length === 0) return evaluated;
258
+ let sourceAccount;
259
+ try {
260
+ sourceAccount = await readSourceCodexAccount(params.requestOptions);
261
+ } catch (error) {
262
+ if (!params.verifyPluginApps) {
263
+ const message = error instanceof Error ? error.message : String(error);
264
+ for (const { plugin, apps } of pending) evaluated.push({
265
+ ...plugin,
266
+ migratable: false,
267
+ migrationBlock: {
268
+ code: "codex_account_unavailable",
269
+ apps,
270
+ error: message
271
+ },
272
+ message: `Codex plugin "${plugin.pluginName ?? plugin.name}" owns apps, but the source Codex app-server account could not be read: ${message}`
273
+ });
274
+ return evaluated;
275
+ }
276
+ }
277
+ if (sourceAccount && sourceAccount !== "chatgpt") {
278
+ for (const { plugin, apps } of pending) evaluated.push({
279
+ ...plugin,
280
+ migratable: false,
281
+ migrationBlock: {
282
+ code: "codex_subscription_required",
283
+ apps
284
+ },
285
+ message: codexSubscriptionRequiredMessage(plugin)
286
+ });
287
+ return evaluated;
288
+ }
289
+ if (!params.verifyPluginApps) {
290
+ for (const { plugin, apps } of pending) evaluated.push({
291
+ ...plugin,
292
+ apps,
293
+ migratable: true
294
+ });
295
+ return evaluated;
296
+ }
297
+ const snapshot = await refreshSourceAppInventory(params.requestOptions).catch((error) => {
298
+ const message = error instanceof Error ? error.message : String(error);
299
+ for (const { plugin, apps } of pending) evaluated.push({
300
+ ...plugin,
301
+ migratable: false,
302
+ migrationBlock: {
303
+ code: "app_inventory_unavailable",
304
+ apps,
305
+ error: message
306
+ },
307
+ message: `Codex plugin "${plugin.pluginName ?? plugin.name}" owns apps, but source app inventory could not be read: ${message}`
308
+ });
309
+ });
310
+ if (!snapshot) return evaluated;
311
+ const appInfoById = new Map(snapshot.apps.map((app) => [app.id, app]));
312
+ for (const { plugin, apps: declaredApps } of pending) {
313
+ const apps = declaredApps.map((app) => sourcePluginAppFactWithInventory(app, appInfoById.get(app.id))).toSorted((left, right) => left.id.localeCompare(right.id));
314
+ const blockCode = migrationBlockCodeForApps(apps);
315
+ if (!blockCode) {
316
+ evaluated.push({
317
+ ...plugin,
318
+ apps,
319
+ migratable: true
320
+ });
321
+ continue;
322
+ }
323
+ evaluated.push({
324
+ ...plugin,
325
+ migratable: false,
326
+ migrationBlock: {
327
+ code: blockCode,
328
+ apps
329
+ },
330
+ message: appInventoryBlockMessage(plugin, apps, blockCode)
331
+ });
332
+ }
333
+ return evaluated;
334
+ }
335
+ async function readSourceCodexAccount(options) {
336
+ const response = await requestSourceCodexAppServerJson(options, {
337
+ method: "account/read",
338
+ requestParams: { refreshToken: false }
339
+ });
340
+ if (!response.account || typeof response.account !== "object" || Array.isArray(response.account)) return "missing";
341
+ return response.account.type === "chatgpt" ? "chatgpt" : "non_chatgpt";
342
+ }
343
+ async function readPluginDetail(options, marketplace, plugin) {
344
+ try {
345
+ return {
346
+ ok: true,
347
+ detail: (await requestSourceCodexAppServerJson(options, {
348
+ method: "plugin/read",
349
+ requestParams: pluginReadParams(marketplace, plugin.pluginName ?? plugin.name)
350
+ })).plugin
351
+ };
352
+ } catch (error) {
353
+ return {
354
+ ok: false,
355
+ error: error instanceof Error ? error.message : String(error)
356
+ };
357
+ }
358
+ }
359
+ async function refreshSourceAppInventory(options) {
360
+ const key = buildCodexPluginAppCacheKey({ appServer: { start: options.startOptions } });
361
+ const request = async (method, requestParams) => await requestSourceCodexAppServerJson(options, {
362
+ method,
363
+ requestParams
364
+ });
365
+ return await defaultCodexAppInventoryCache.refreshNow({
366
+ key,
367
+ request,
368
+ forceRefetch: true
369
+ });
370
+ }
371
+ function sourcePluginAppFact(app) {
372
+ return {
373
+ id: app.id,
374
+ name: app.name,
375
+ needsAuth: app.needsAuth
376
+ };
377
+ }
378
+ function sourcePluginAppFactWithInventory(app, info) {
379
+ if (!info) return app;
380
+ return {
381
+ ...app,
382
+ isAccessible: info.isAccessible,
383
+ isEnabled: info.isEnabled
384
+ };
385
+ }
386
+ function migrationBlockCodeForApps(apps) {
387
+ if (apps.some((app) => app.isAccessible === false)) return "app_inaccessible";
388
+ if (apps.some((app) => app.isEnabled === false)) return "app_disabled";
389
+ if (apps.some((app) => app.isAccessible === void 0 || app.isEnabled === void 0)) return "app_missing";
390
+ }
391
+ function appInventoryBlockMessage(plugin, apps, code) {
392
+ const status = code === "app_inaccessible" ? "inaccessible" : code === "app_disabled" ? "disabled" : "missing";
393
+ const blocking = apps.find((app) => code === "app_inaccessible" ? app.isAccessible === false : code === "app_disabled" ? app.isEnabled === false : app.isAccessible === void 0 || app.isEnabled === void 0) ?? apps[0];
394
+ const appLabel = blocking ? ` app "${blocking.name}"` : " an owned app";
395
+ return `Codex plugin "${plugin.pluginName ?? plugin.name}" owns${appLabel} but the source app inventory reports it is ${status}; authenticate or enable the app in Codex before migrating it to AutoBot.`;
396
+ }
397
+ function codexPluginMigrationSubscriptionWarning() {
398
+ return "Codex app-backed plugin migration requires the Codex app-server source account to be logged in with a ChatGPT subscription account. Log in to the Codex app with subscription auth; AutoBot auth or API-key auth does not satisfy Codex app connector access.";
399
+ }
400
+ function codexSubscriptionRequiredMessage(plugin) {
401
+ return `Codex plugin "${plugin.pluginName ?? plugin.name}" owns apps, but ${codexPluginMigrationSubscriptionWarning()}`;
402
+ }
403
+ function pluginNameFromSummary(summary) {
404
+ const candidates = [summary.id, summary.name];
405
+ for (const candidate of candidates) {
406
+ const trimmed = candidate.trim();
407
+ if (!trimmed) continue;
408
+ const normalized = ((trimmed.endsWith(`@openai-curated`) ? trimmed.slice(0, -`@${CODEX_PLUGINS_MARKETPLACE_NAME}`.length) : trimmed).split("/").at(-1)?.trim())?.toLowerCase().replaceAll(/\s+/gu, "-");
409
+ if (normalized) return normalized;
410
+ }
411
+ }
412
+ async function discoverCodexSource(inputOrOptions) {
413
+ const options = typeof inputOrOptions === "string" || inputOrOptions === void 0 ? { input: inputOrOptions } : inputOrOptions;
414
+ const codexHome = resolveHomePath(options.input?.trim() || defaultCodexHome());
415
+ const codexSkillsDir = path.join(codexHome, "skills");
416
+ const agentsSkillsDir = personalAgentsSkillsDir();
417
+ const configPath = path.join(codexHome, "config.toml");
418
+ const hooksPath = path.join(codexHome, "hooks", "hooks.json");
419
+ const codexSkills = await discoverSkillDirs({
420
+ root: codexSkillsDir,
421
+ sourceLabel: "Codex skill",
422
+ excludeSystem: true
423
+ });
424
+ const personalAgentSkills = await discoverSkillDirs({
425
+ root: agentsSkillsDir,
426
+ sourceLabel: "personal AgentSkill"
427
+ });
428
+ const sourcePluginDiscovery = await discoverInstalledCuratedPlugins(codexHome, options);
429
+ const sourcePluginNames = new Set(sourcePluginDiscovery.plugins.flatMap((plugin) => plugin.pluginName ? [plugin.pluginName] : []));
430
+ const cachedPlugins = (await discoverPluginDirs(codexHome)).filter((plugin) => {
431
+ const normalizedName = sanitizePluginName(plugin.name);
432
+ return !sourcePluginNames.has(normalizedName);
433
+ });
434
+ const plugins = [...sourcePluginDiscovery.plugins, ...cachedPlugins].toSorted((a, b) => a.source.localeCompare(b.source));
435
+ const archivePaths = [];
436
+ if (await exists(configPath)) archivePaths.push({
437
+ id: "archive:config.toml",
438
+ path: configPath,
439
+ relativePath: "config.toml",
440
+ message: "Codex config is archived for manual review; it is not activated automatically"
441
+ });
442
+ if (await exists(hooksPath)) archivePaths.push({
443
+ id: "archive:hooks/hooks.json",
444
+ path: hooksPath,
445
+ relativePath: "hooks/hooks.json",
446
+ message: "Codex native hooks are archived for manual review because they can execute commands"
447
+ });
448
+ const skills = [...codexSkills, ...personalAgentSkills].toSorted((a, b) => a.source.localeCompare(b.source));
449
+ const high = Boolean(codexSkills.length || plugins.length || archivePaths.length);
450
+ const medium = personalAgentSkills.length > 0;
451
+ return {
452
+ root: codexHome,
453
+ confidence: high ? "high" : medium ? "medium" : "low",
454
+ codexHome,
455
+ ...await isDirectory(codexSkillsDir) ? { codexSkillsDir } : {},
456
+ ...await isDirectory(agentsSkillsDir) ? { personalAgentsSkillsDir: agentsSkillsDir } : {},
457
+ ...await exists(configPath) ? { configPath } : {},
458
+ ...await exists(hooksPath) ? { hooksPath } : {},
459
+ skills,
460
+ plugins,
461
+ ...sourcePluginDiscovery.error ? { pluginDiscoveryError: sourcePluginDiscovery.error } : {},
462
+ archivePaths
463
+ };
464
+ }
465
+ function hasCodexSource(source) {
466
+ return source.confidence !== "low";
467
+ }
468
+ function sanitizePluginName(value) {
469
+ return value.trim().toLowerCase().replaceAll(/\s+/gu, "-");
470
+ }
471
+ //#endregion
472
+ //#region extensions/codex/src/migration/targets.ts
473
+ function resolveCodexMigrationTargets(ctx) {
474
+ const cfg = ctx.config;
475
+ const agentId = resolveDefaultAgentId(cfg);
476
+ const workspaceDir = resolveAgentWorkspaceDir(cfg, agentId);
477
+ const configuredAgentDir = resolveAgentConfig(cfg, agentId)?.agentDir?.trim();
478
+ return {
479
+ workspaceDir,
480
+ agentDir: ctx.runtime?.agent?.resolveAgentDir(cfg, agentId) ?? (configuredAgentDir ? resolveHomePath(configuredAgentDir) : void 0) ?? path.join(ctx.stateDir, "agents", agentId, "agent")
481
+ };
482
+ }
483
+ //#endregion
484
+ //#region extensions/codex/src/migration/plan.ts
485
+ const CODEX_PLUGIN_CONFIG_ITEM_ID = "config:codex-plugins";
486
+ const CODEX_PLUGIN_CONFIG_PATH = [
487
+ "plugins",
488
+ "entries",
489
+ "codex"
490
+ ];
491
+ const CODEX_PLUGIN_ENABLED_PATH = [
492
+ "plugins",
493
+ "entries",
494
+ "codex",
495
+ "enabled"
496
+ ];
497
+ const CODEX_PLUGIN_NATIVE_CONFIG_PATH = [
498
+ "plugins",
499
+ "entries",
500
+ "codex",
501
+ "config",
502
+ "codexPlugins"
503
+ ];
504
+ const MIGRATION_REASON_PLUGIN_EXISTS = "plugin exists";
505
+ const CODEX_PLUGIN_SOURCE_APP_VERIFICATION_UNVERIFIED = "not_run";
506
+ function uniqueSkillName(skill, counts) {
507
+ const base = sanitizeName(skill.name) || "codex-skill";
508
+ if ((counts.get(base) ?? 0) <= 1) return base;
509
+ return sanitizeName([
510
+ "codex",
511
+ sanitizeName(path.basename(path.dirname(skill.source))),
512
+ base
513
+ ].filter(Boolean).join("-")) || base;
514
+ }
515
+ async function buildSkillItems(params) {
516
+ const baseCounts = /* @__PURE__ */ new Map();
517
+ for (const skill of params.skills) {
518
+ const base = sanitizeName(skill.name) || "codex-skill";
519
+ baseCounts.set(base, (baseCounts.get(base) ?? 0) + 1);
520
+ }
521
+ const resolvedCounts = /* @__PURE__ */ new Map();
522
+ const planned = params.skills.map((skill) => {
523
+ const name = uniqueSkillName(skill, baseCounts);
524
+ resolvedCounts.set(name, (resolvedCounts.get(name) ?? 0) + 1);
525
+ return {
526
+ skill,
527
+ name,
528
+ target: path.join(params.workspaceDir, "skills", name)
529
+ };
530
+ });
531
+ const items = [];
532
+ for (const item of planned) {
533
+ const collides = (resolvedCounts.get(item.name) ?? 0) > 1;
534
+ const targetExists = await exists(item.target);
535
+ items.push(createMigrationItem({
536
+ id: `skill:${item.name}`,
537
+ kind: "skill",
538
+ action: "copy",
539
+ source: item.skill.source,
540
+ target: item.target,
541
+ status: collides ? "conflict" : targetExists && !params.overwrite ? "conflict" : "planned",
542
+ reason: collides ? `multiple Codex skills normalize to "${item.name}"` : targetExists && !params.overwrite ? MIGRATION_REASON_TARGET_EXISTS : void 0,
543
+ message: `Copy ${item.skill.sourceLabel} into this AutoBot agent workspace.`,
544
+ details: {
545
+ skillName: item.name,
546
+ sourceLabel: item.skill.sourceLabel
547
+ }
548
+ }));
549
+ }
550
+ return items;
551
+ }
552
+ function uniquePluginConfigKey(plugin, counts, usedCounts) {
553
+ const base = sanitizeName(plugin.pluginName ?? plugin.name) || "codex-plugin";
554
+ if ((counts.get(base) ?? 0) <= 1) return base;
555
+ const next = (usedCounts.get(base) ?? 0) + 1;
556
+ usedCounts.set(base, next);
557
+ return sanitizeName(`${base}-${next}`) || base;
558
+ }
559
+ function readExistingCodexPluginEntries(config) {
560
+ const entries = readMigrationConfigPath(config, [...CODEX_PLUGIN_NATIVE_CONFIG_PATH, "plugins"]);
561
+ return isRecord(entries) ? entries : {};
562
+ }
563
+ function hasExistingCodexPluginEntry(existingEntries, configKey, pluginName) {
564
+ if (existingEntries[configKey] !== void 0) return true;
565
+ return Object.values(existingEntries).some((entry) => {
566
+ if (!isRecord(entry)) return false;
567
+ return entry.pluginName === pluginName;
568
+ });
569
+ }
570
+ function buildPluginItems(ctx, plugins) {
571
+ const baseCounts = /* @__PURE__ */ new Map();
572
+ for (const plugin of plugins.filter((entry) => entry.migratable)) {
573
+ const base = sanitizeName(plugin.pluginName ?? plugin.name) || "codex-plugin";
574
+ baseCounts.set(base, (baseCounts.get(base) ?? 0) + 1);
575
+ }
576
+ const existingPluginEntries = readExistingCodexPluginEntries(ctx.config);
577
+ const usedCounts = /* @__PURE__ */ new Map();
578
+ let manualIndex = 0;
579
+ const items = [];
580
+ for (const plugin of plugins) {
581
+ if (plugin.migratable && plugin.marketplaceName === "openai-curated" && plugin.pluginName) {
582
+ const configKey = uniquePluginConfigKey(plugin, baseCounts, usedCounts);
583
+ const conflict = !ctx.overwrite && hasExistingCodexPluginEntry(existingPluginEntries, configKey, plugin.pluginName);
584
+ items.push(createMigrationItem({
585
+ id: `plugin:${configKey}`,
586
+ kind: "plugin",
587
+ action: "install",
588
+ status: conflict ? "conflict" : "planned",
589
+ reason: conflict ? MIGRATION_REASON_PLUGIN_EXISTS : void 0,
590
+ source: plugin.source,
591
+ target: `plugins.entries.codex.config.codexPlugins.plugins.${configKey}`,
592
+ message: `Install Codex plugin "${plugin.pluginName}" in the AutoBot-managed Codex app-server runtime.`,
593
+ details: {
594
+ configKey,
595
+ marketplaceName: CODEX_PLUGINS_MARKETPLACE_NAME,
596
+ pluginName: plugin.pluginName,
597
+ sourceInstalled: plugin.installed === true,
598
+ sourceEnabled: plugin.enabled === true,
599
+ ...plugin.apps && plugin.apps.length > 0 && !shouldVerifyPluginApps(ctx) ? { sourceAppVerification: CODEX_PLUGIN_SOURCE_APP_VERIFICATION_UNVERIFIED } : {}
600
+ }
601
+ }));
602
+ continue;
603
+ }
604
+ manualIndex += 1;
605
+ if (plugin.migrationBlock && plugin.pluginName) {
606
+ const details = {
607
+ pluginName: plugin.pluginName,
608
+ marketplaceName: CODEX_PLUGINS_MARKETPLACE_NAME,
609
+ ...plugin.migrationBlock.apps ? { apps: plugin.migrationBlock.apps } : {},
610
+ ...plugin.migrationBlock.error ? { error: plugin.migrationBlock.error } : {}
611
+ };
612
+ items.push(createMigrationItem({
613
+ id: `plugin:${sanitizeName(plugin.name) || sanitizeName(path.basename(plugin.source))}:${manualIndex}`,
614
+ kind: "manual",
615
+ action: "manual",
616
+ source: plugin.source,
617
+ status: "skipped",
618
+ reason: plugin.migrationBlock.code,
619
+ message: plugin.message ?? `Codex native plugin "${plugin.name}" was found but not activated automatically.`,
620
+ details: { ...details }
621
+ }));
622
+ continue;
623
+ }
624
+ items.push(createMigrationManualItem({
625
+ id: `plugin:${sanitizeName(plugin.name) || sanitizeName(path.basename(plugin.source))}:${manualIndex}`,
626
+ source: plugin.source,
627
+ message: plugin.message ?? `Codex native plugin "${plugin.name}" was found but not activated automatically.`,
628
+ recommendation: "Review the plugin bundle first, then install trusted compatible plugins with autobot plugins install <path>."
629
+ }));
630
+ }
631
+ return items;
632
+ }
633
+ function shouldVerifyPluginApps(ctx) {
634
+ return ctx.providerOptions?.verifyPluginApps === true;
635
+ }
636
+ function readCodexPluginMigrationConfigEntry(item, enabled) {
637
+ const configKey = item.details?.configKey;
638
+ const marketplaceName = item.details?.marketplaceName;
639
+ const pluginName = item.details?.pluginName;
640
+ if (item.kind !== "plugin" || item.action !== "install" || typeof configKey !== "string" || marketplaceName !== "openai-curated" || typeof pluginName !== "string") return;
641
+ return {
642
+ configKey,
643
+ pluginName,
644
+ enabled
645
+ };
646
+ }
647
+ function readExistingAllowDestructiveActions(config) {
648
+ const value = readMigrationConfigPath(config, [...CODEX_PLUGIN_NATIVE_CONFIG_PATH, "allow_destructive_actions"]);
649
+ return typeof value === "boolean" ? value : void 0;
650
+ }
651
+ function isRecord(value) {
652
+ return Boolean(value && typeof value === "object" && !Array.isArray(value));
653
+ }
654
+ function buildCodexPluginsConfigValue(entries, params = {}) {
655
+ const plugins = Object.fromEntries(entries.toSorted((a, b) => a.configKey.localeCompare(b.configKey)).map((entry) => [entry.configKey, {
656
+ enabled: entry.enabled,
657
+ marketplaceName: CODEX_PLUGINS_MARKETPLACE_NAME,
658
+ pluginName: entry.pluginName
659
+ }]));
660
+ return {
661
+ enabled: true,
662
+ config: { codexPlugins: {
663
+ enabled: true,
664
+ allow_destructive_actions: params.config === void 0 ? true : readExistingAllowDestructiveActions(params.config) ?? true,
665
+ plugins
666
+ } }
667
+ };
668
+ }
669
+ function hasCodexPluginConfigConflict(config, value) {
670
+ const enabled = readMigrationConfigPath(config, CODEX_PLUGIN_ENABLED_PATH);
671
+ if (enabled !== void 0 && enabled !== true) return true;
672
+ const nativeConfig = value.config?.codexPlugins;
673
+ if (!isRecord(nativeConfig)) return hasMigrationConfigPatchConflict(config, CODEX_PLUGIN_NATIVE_CONFIG_PATH, nativeConfig);
674
+ const existingNativeConfig = readMigrationConfigPath(config, CODEX_PLUGIN_NATIVE_CONFIG_PATH);
675
+ if (existingNativeConfig === void 0) return false;
676
+ if (!isRecord(existingNativeConfig)) return true;
677
+ if (existingNativeConfig.enabled !== void 0 && existingNativeConfig.enabled !== true) return true;
678
+ const allowDestructiveActions = nativeConfig.allow_destructive_actions;
679
+ if (existingNativeConfig.allow_destructive_actions !== void 0 && existingNativeConfig.allow_destructive_actions !== allowDestructiveActions) return true;
680
+ const plugins = nativeConfig.plugins;
681
+ if (!isRecord(plugins)) return false;
682
+ return Object.entries(plugins).some(([configKey, plugin]) => {
683
+ if (!isRecord(plugin)) return existingNativeConfig[configKey] !== void 0;
684
+ return hasExistingCodexPluginEntry(readExistingCodexPluginEntries(config), configKey, typeof plugin.pluginName === "string" ? plugin.pluginName : configKey);
685
+ });
686
+ }
687
+ function buildPluginConfigItem(ctx, pluginItems) {
688
+ const entries = pluginItems.filter((item) => item.status === "planned").map((item) => readCodexPluginMigrationConfigEntry(item, true)).filter((entry) => entry !== void 0);
689
+ if (entries.length === 0) return;
690
+ const value = buildCodexPluginsConfigValue(entries, { config: ctx.config });
691
+ const conflict = !ctx.overwrite && hasCodexPluginConfigConflict(ctx.config, value);
692
+ return createMigrationItem({
693
+ id: CODEX_PLUGIN_CONFIG_ITEM_ID,
694
+ kind: "config",
695
+ action: "merge",
696
+ target: "plugins.entries.codex.config.codexPlugins",
697
+ status: conflict ? "conflict" : "planned",
698
+ reason: conflict ? MIGRATION_REASON_TARGET_EXISTS : void 0,
699
+ message: "Enable AutoBot's Codex plugin integration and record migrated source-installed curated plugins.",
700
+ details: {
701
+ path: [...CODEX_PLUGIN_CONFIG_PATH],
702
+ value
703
+ }
704
+ });
705
+ }
706
+ async function buildCodexMigrationPlan(ctx) {
707
+ const targets = resolveCodexMigrationTargets(ctx);
708
+ const source = await discoverCodexSource({
709
+ input: ctx.source,
710
+ evaluatePluginMigrationEligibility: true,
711
+ verifyPluginApps: shouldVerifyPluginApps(ctx)
712
+ });
713
+ if (!hasCodexSource(source)) throw new Error(`Codex state was not found at ${source.root}. Pass --from <path> if it lives elsewhere.`);
714
+ const items = [];
715
+ items.push(...await buildSkillItems({
716
+ skills: source.skills,
717
+ workspaceDir: targets.workspaceDir,
718
+ overwrite: ctx.overwrite
719
+ }));
720
+ const pluginItems = buildPluginItems(ctx, source.plugins);
721
+ items.push(...pluginItems);
722
+ const pluginConfigItem = buildPluginConfigItem(ctx, pluginItems);
723
+ if (pluginConfigItem) items.push(pluginConfigItem);
724
+ for (const archivePath of source.archivePaths) items.push(createMigrationItem({
725
+ id: archivePath.id,
726
+ kind: "archive",
727
+ action: "archive",
728
+ source: archivePath.path,
729
+ message: archivePath.message ?? "Archived in the migration report for manual review; not imported into live config.",
730
+ details: { archiveRelativePath: archivePath.relativePath }
731
+ }));
732
+ const warnings = [
733
+ ...items.some((item) => item.status === "conflict") ? ["Conflicts were found. Re-run with --overwrite to replace conflicting migration targets after item-level backups."] : [],
734
+ ...source.pluginDiscoveryError ? [`Codex app-server plugin inventory discovery failed: ${source.pluginDiscoveryError}. Cached plugin bundles, if any, are advisory only.`] : [],
735
+ ...source.plugins.some((plugin) => plugin.migrationBlock?.code === "codex_subscription_required") ? [codexPluginMigrationSubscriptionWarning()] : []
736
+ ];
737
+ return {
738
+ providerId: "codex",
739
+ source: source.root,
740
+ target: targets.workspaceDir,
741
+ summary: summarizeMigrationItems(items),
742
+ items,
743
+ warnings,
744
+ nextSteps: ["Run autobot doctor after applying the migration.", "Review skipped or auth-required Codex plugin/config/hook items before exposing them in AutoBot sessions."],
745
+ metadata: {
746
+ agentDir: targets.agentDir,
747
+ codexHome: source.codexHome,
748
+ codexSkillsDir: source.codexSkillsDir,
749
+ personalAgentsSkillsDir: source.personalAgentsSkillsDir
750
+ }
751
+ };
752
+ }
753
+ //#endregion
754
+ //#region extensions/codex/src/migration/apply.ts
755
+ const CODEX_PLUGIN_AUTH_REQUIRED_REASON = "auth_required";
756
+ const CODEX_PLUGIN_NOT_SELECTED_REASON = "not selected for migration";
757
+ const CODEX_CONFIG_PATCH_MODE_RETURN = "return";
758
+ const CODEX_PLUGIN_LOAD_WARNING = "Some Codex plugins could not be migrated. Run `autobot migrate codex` after onboarding.";
759
+ const TARGET_CODEX_MARKETPLACE_DISCOVERY_POLL_MS = 250;
760
+ const TARGET_CODEX_MARKETPLACE_DISCOVERY_TIMEOUT_MS = 3e4;
761
+ const TARGET_CODEX_MARKETPLACE_DISCOVERY_TIMEOUT_ENV = "AUTOBOT_CODEX_MIGRATION_PLUGIN_LIST_TIMEOUT_MS";
762
+ var CodexPluginConfigConflictError = class extends Error {
763
+ constructor(reason) {
764
+ super(reason);
765
+ this.reason = reason;
766
+ this.name = "CodexPluginConfigConflictError";
767
+ }
768
+ };
769
+ function shouldReturnCodexPluginConfigPatch(ctx) {
770
+ return ctx.providerOptions?.configPatchMode === CODEX_CONFIG_PATCH_MODE_RETURN;
771
+ }
772
+ function prepareTargetCodexAppServer(ctx) {
773
+ const appServer = resolveTargetCodexAppServer(ctx);
774
+ const targets = resolveCodexMigrationTargets(ctx);
775
+ let warmedClient;
776
+ const ready = getSharedCodexAppServerClient({
777
+ startOptions: appServer.start,
778
+ timeoutMs: 6e4,
779
+ agentDir: targets.agentDir,
780
+ config: ctx.config
781
+ }).then((client) => {
782
+ warmedClient = client;
783
+ }, () => void 0);
784
+ return { async dispose() {
785
+ await ready;
786
+ await clearSharedCodexAppServerClientIfCurrentAndWait(warmedClient, {
787
+ exitTimeoutMs: 2e3,
788
+ forceKillDelayMs: 250
789
+ });
790
+ } };
791
+ }
792
+ async function applyCodexMigrationPlan(params) {
793
+ const plan = params.plan ?? await buildCodexMigrationPlan(params.ctx);
794
+ const reportDir = params.ctx.reportDir ?? path.join(params.ctx.stateDir, "migration", "codex");
795
+ const items = [];
796
+ const runtime = withCachedMigrationConfigRuntime(params.ctx.runtime ?? params.runtime, params.ctx.config);
797
+ const applyCtx = {
798
+ ...params.ctx,
799
+ runtime
800
+ };
801
+ for (const item of plan.items) {
802
+ if (item.status !== "planned") {
803
+ items.push(item);
804
+ continue;
805
+ }
806
+ if (item.id === "config:codex-plugins") items.push(await applyCodexPluginConfigItem(applyCtx, item, items));
807
+ else if (item.kind === "plugin" && item.action === "install") items.push(await applyCodexPluginInstallItem(applyCtx, item));
808
+ else if (item.kind === "manual") items.push(applyMigrationManualItem(item));
809
+ else if (item.action === "archive") items.push(await archiveMigrationItem(item, reportDir));
810
+ else items.push(await copyMigrationFileItem(item, reportDir, { overwrite: params.ctx.overwrite }));
811
+ }
812
+ const result = {
813
+ ...plan,
814
+ items,
815
+ summary: summarizeMigrationItems(items),
816
+ backupPath: params.ctx.backupPath,
817
+ reportDir
818
+ };
819
+ if (items.some(isCodexPluginLoadWarningItem)) {
820
+ result.warnings = [...new Set([...result.warnings ?? [], CODEX_PLUGIN_LOAD_WARNING])];
821
+ result.nextSteps = [...new Set([CODEX_PLUGIN_LOAD_WARNING, ...result.nextSteps ?? []])];
822
+ }
823
+ await writeMigrationReport(result, { title: "Codex Migration Report" });
824
+ return result;
825
+ }
826
+ async function applyCodexPluginInstallItem(ctx, item) {
827
+ const policy = readCodexPluginPolicy(item);
828
+ if (!policy) return {
829
+ ...markMigrationItemError(item, "invalid Codex plugin migration item"),
830
+ details: {
831
+ ...item.details,
832
+ code: "invalid_plugin_item"
833
+ }
834
+ };
835
+ try {
836
+ const appCacheKey = await buildTargetCodexPluginAppCacheKey(ctx);
837
+ const appServer = resolveTargetCodexAppServer(ctx);
838
+ const result = await ensureCodexPluginActivation({
839
+ identity: policy,
840
+ installEvenIfActive: true,
841
+ request: async (method, requestParams) => await requestTargetCodexAppServerJson({
842
+ method,
843
+ requestParams,
844
+ timeoutMs: 6e4,
845
+ startOptions: appServer.start,
846
+ agentDir: resolveCodexMigrationTargets(ctx).agentDir,
847
+ config: ctx.config,
848
+ isolated: false
849
+ }),
850
+ appCache: defaultCodexAppInventoryCache,
851
+ appCacheKey
852
+ });
853
+ const baseDetails = {
854
+ ...item.details,
855
+ code: result.reason,
856
+ activationReason: result.reason,
857
+ ...codexPluginActivationReportState(result),
858
+ installAttempted: result.installAttempted,
859
+ diagnostics: result.diagnostics.map((diagnostic) => diagnostic.message)
860
+ };
861
+ if (result.ok) return {
862
+ ...item,
863
+ status: "migrated",
864
+ ...result.reason === "already_active" ? { reason: "already active" } : {},
865
+ details: baseDetails
866
+ };
867
+ if (result.reason === CODEX_PLUGIN_AUTH_REQUIRED_REASON) return {
868
+ ...item,
869
+ status: "skipped",
870
+ reason: CODEX_PLUGIN_AUTH_REQUIRED_REASON,
871
+ details: {
872
+ ...baseDetails,
873
+ appsNeedingAuth: sanitizeAppsNeedingAuth(result.installResponse?.appsNeedingAuth ?? [])
874
+ }
875
+ };
876
+ if (result.reason === "plugin_missing" || result.reason === "marketplace_missing") return {
877
+ ...item,
878
+ status: "warning",
879
+ reason: result.reason,
880
+ message: `Codex plugin "${policy.pluginName}" could not be migrated automatically`,
881
+ details: {
882
+ ...baseDetails,
883
+ warningReason: CODEX_PLUGIN_LOAD_WARNING
884
+ }
885
+ };
886
+ return {
887
+ ...item,
888
+ status: "error",
889
+ reason: result.reason,
890
+ details: baseDetails
891
+ };
892
+ } catch (error) {
893
+ if (isCodexPluginInventoryLoadError(error)) return {
894
+ ...item,
895
+ status: "warning",
896
+ reason: "plugin_inventory_unavailable",
897
+ message: `Codex plugin "${policy.pluginName}" could not be migrated automatically`,
898
+ details: {
899
+ ...item.details,
900
+ code: "plugin_inventory_unavailable",
901
+ warningReason: CODEX_PLUGIN_LOAD_WARNING,
902
+ diagnostic: formatCodexMigrationError(error)
903
+ }
904
+ };
905
+ return {
906
+ ...item,
907
+ status: "error",
908
+ reason: formatCodexMigrationError(error),
909
+ details: {
910
+ ...item.details,
911
+ code: "plugin_install_failed"
912
+ }
913
+ };
914
+ }
915
+ }
916
+ function isCodexPluginInventoryLoadError(error) {
917
+ return formatCodexMigrationError(error).includes("codex app-server plugin/list timed out");
918
+ }
919
+ function formatCodexMigrationError(error) {
920
+ return error instanceof Error ? error.message : String(error);
921
+ }
922
+ function resolveTargetCodexAppServer(ctx) {
923
+ return resolveCodexAppServerRuntimeOptions({ pluginConfig: readCodexPluginConfig(ctx.config) });
924
+ }
925
+ async function requestTargetCodexAppServerJson(params) {
926
+ if (params.method !== "plugin/list") return await requestCodexAppServerJson(params);
927
+ const deadline = Date.now() + params.timeoutMs;
928
+ const discoveryTimeoutMs = targetCodexMarketplaceDiscoveryTimeoutMs();
929
+ const discoveryDeadline = Math.min(deadline, Date.now() + discoveryTimeoutMs);
930
+ let lastResponse;
931
+ let attempt = 0;
932
+ do {
933
+ attempt += 1;
934
+ const remainingMs = Math.max(1, discoveryDeadline - Date.now());
935
+ lastResponse = await requestCodexAppServerJson({
936
+ ...params,
937
+ timeoutMs: remainingMs
938
+ });
939
+ if (hasOpenAiCuratedMarketplace(lastResponse)) return lastResponse;
940
+ if (Date.now() >= discoveryDeadline) return lastResponse;
941
+ await sleep(Math.min(TARGET_CODEX_MARKETPLACE_DISCOVERY_POLL_MS, discoveryDeadline - Date.now()));
942
+ } while (Date.now() < discoveryDeadline);
943
+ return lastResponse;
944
+ }
945
+ function hasOpenAiCuratedMarketplace(response) {
946
+ if (!response || typeof response !== "object" || !("marketplaces" in response)) return false;
947
+ const marketplaces = response.marketplaces;
948
+ return Array.isArray(marketplaces) && marketplaces.some((marketplace) => marketplace && typeof marketplace === "object" && marketplace.name === "openai-curated");
949
+ }
950
+ function targetCodexMarketplaceDiscoveryTimeoutMs() {
951
+ const configured = Number(process.env[TARGET_CODEX_MARKETPLACE_DISCOVERY_TIMEOUT_ENV]);
952
+ if (Number.isFinite(configured) && configured >= 0) return configured;
953
+ return TARGET_CODEX_MARKETPLACE_DISCOVERY_TIMEOUT_MS;
954
+ }
955
+ function isCodexPluginLoadWarningItem(item) {
956
+ return item.kind === "plugin" && item.action === "install" && item.status === "warning" && item.details?.warningReason === CODEX_PLUGIN_LOAD_WARNING;
957
+ }
958
+ async function sleep(ms) {
959
+ await new Promise((resolve) => setTimeout(resolve, ms));
960
+ }
961
+ async function buildTargetCodexPluginAppCacheKey(ctx) {
962
+ const targets = resolveCodexMigrationTargets(ctx);
963
+ const appServer = resolveTargetCodexAppServer(ctx);
964
+ const authProfileId = resolveCodexAppServerAuthProfileIdForAgent({
965
+ agentDir: targets.agentDir,
966
+ config: ctx.config
967
+ });
968
+ const accountId = await resolveCodexAppServerAuthAccountCacheKey({
969
+ authProfileId,
970
+ agentDir: targets.agentDir,
971
+ config: ctx.config
972
+ });
973
+ const envApiKeyFingerprint = authProfileId ? void 0 : resolveCodexAppServerEnvApiKeyCacheKey({ startOptions: appServer.start });
974
+ return buildCodexPluginAppCacheKey({
975
+ appServer,
976
+ agentDir: targets.agentDir,
977
+ authProfileId,
978
+ accountId,
979
+ envApiKeyFingerprint
980
+ });
981
+ }
982
+ async function applyCodexPluginConfigItem(ctx, item, appliedItems) {
983
+ const entries = appliedItems.map(readAppliedPluginConfigEntry).filter((entry) => entry !== void 0);
984
+ if (entries.length === 0) return markMigrationItemSkipped(item, "no selected Codex plugins");
985
+ const returnPatch = shouldReturnCodexPluginConfigPatch(ctx);
986
+ const configApi = ctx.runtime?.config;
987
+ const currentConfig = returnPatch ? ctx.config : configApi?.current?.();
988
+ if (!currentConfig) return markMigrationItemError(item, "config runtime unavailable");
989
+ const value = buildCodexPluginsConfigValue(entries, { config: currentConfig });
990
+ if (!ctx.overwrite && hasCodexPluginConfigConflict(currentConfig, value)) return markMigrationItemConflict(item, MIGRATION_REASON_TARGET_EXISTS);
991
+ const migratedItem = {
992
+ ...item,
993
+ status: "migrated",
994
+ details: {
995
+ ...item.details,
996
+ path: [...CODEX_PLUGIN_CONFIG_PATH],
997
+ value
998
+ }
999
+ };
1000
+ if (returnPatch) return migratedItem;
1001
+ if (!configApi?.mutateConfigFile) return markMigrationItemError(item, "config runtime unavailable");
1002
+ try {
1003
+ await configApi.mutateConfigFile({
1004
+ base: "runtime",
1005
+ afterWrite: { mode: "auto" },
1006
+ mutate(draft) {
1007
+ if (!ctx.overwrite && hasCodexPluginConfigConflict(draft, value)) throw new CodexPluginConfigConflictError(MIGRATION_REASON_TARGET_EXISTS);
1008
+ writeMigrationConfigPath(draft, CODEX_PLUGIN_CONFIG_PATH, value);
1009
+ }
1010
+ });
1011
+ return migratedItem;
1012
+ } catch (error) {
1013
+ if (error instanceof CodexPluginConfigConflictError) return markMigrationItemConflict(item, error.reason);
1014
+ return markMigrationItemError(item, error instanceof Error ? error.message : String(error));
1015
+ }
1016
+ }
1017
+ function readAppliedPluginConfigEntry(item) {
1018
+ if (item.status === "migrated") return readCodexPluginMigrationConfigEntry(item, true);
1019
+ if (item.status === "skipped" && item.reason !== CODEX_PLUGIN_NOT_SELECTED_REASON && item.reason === CODEX_PLUGIN_AUTH_REQUIRED_REASON) return readCodexPluginMigrationConfigEntry(item, false);
1020
+ }
1021
+ function readCodexPluginPolicy(item) {
1022
+ const configKey = item.details?.configKey;
1023
+ const marketplaceName = item.details?.marketplaceName;
1024
+ const pluginName = item.details?.pluginName;
1025
+ if (typeof configKey !== "string" || marketplaceName !== "openai-curated" || typeof pluginName !== "string") return;
1026
+ return {
1027
+ configKey,
1028
+ marketplaceName: CODEX_PLUGINS_MARKETPLACE_NAME,
1029
+ pluginName,
1030
+ enabled: true,
1031
+ allowDestructiveActions: true
1032
+ };
1033
+ }
1034
+ function codexPluginActivationReportState(result) {
1035
+ switch (result.reason) {
1036
+ case "already_active":
1037
+ case "installed": return {
1038
+ installed: true,
1039
+ enabled: true
1040
+ };
1041
+ case "auth_required": return {
1042
+ installed: true,
1043
+ enabled: false
1044
+ };
1045
+ case "disabled":
1046
+ case "marketplace_missing":
1047
+ case "plugin_missing": return {
1048
+ installed: false,
1049
+ enabled: false
1050
+ };
1051
+ case "refresh_failed": return {
1052
+ installed: true,
1053
+ enabled: false
1054
+ };
1055
+ }
1056
+ return result.reason;
1057
+ }
1058
+ function sanitizeAppsNeedingAuth(apps) {
1059
+ return apps.map((app) => ({
1060
+ id: app.id,
1061
+ name: app.name,
1062
+ needsAuth: app.needsAuth
1063
+ }));
1064
+ }
1065
+ //#endregion
1066
+ //#region extensions/codex/src/migration/provider.ts
1067
+ function buildCodexMigrationProvider(params = {}) {
1068
+ return {
1069
+ id: "codex",
1070
+ label: "Codex",
1071
+ description: "Inventory and promote Codex CLI skills while keeping Codex native plugins and hooks explicit.",
1072
+ async detect(ctx) {
1073
+ const source = await discoverCodexSource({ input: ctx.source });
1074
+ const found = hasCodexSource(source);
1075
+ return {
1076
+ found,
1077
+ source: source.root,
1078
+ label: "Codex",
1079
+ confidence: found ? source.confidence : "low",
1080
+ message: found ? "Codex state found." : "Codex state not found."
1081
+ };
1082
+ },
1083
+ plan: buildCodexMigrationPlan,
1084
+ prepareApply(ctx) {
1085
+ return prepareTargetCodexAppServer(ctx);
1086
+ },
1087
+ async apply(ctx, plan) {
1088
+ return await applyCodexMigrationPlan({
1089
+ ctx,
1090
+ plan,
1091
+ runtime: params.runtime
1092
+ });
1093
+ }
1094
+ };
1095
+ }
1096
+ //#endregion
1097
+ //#region extensions/codex/index.ts
1098
+ var codex_default = definePluginEntry({
1099
+ id: "codex",
1100
+ name: "Codex",
1101
+ description: "Codex app-server harness and Codex-managed GPT model catalog.",
1102
+ register(api) {
1103
+ const resolveCurrentPluginConfig = () => resolveLivePluginConfigObject(api.runtime.config?.current ? () => api.runtime.config.current() : void 0, "codex", api.pluginConfig) ?? api.pluginConfig;
1104
+ api.registerAgentHarness(createCodexAppServerAgentHarness({ resolvePluginConfig: resolveCurrentPluginConfig }));
1105
+ api.registerProvider(buildCodexProvider({ pluginConfig: api.pluginConfig }));
1106
+ api.registerMediaUnderstandingProvider(buildCodexMediaUnderstandingProvider({ pluginConfig: api.pluginConfig }));
1107
+ api.registerMigrationProvider(buildCodexMigrationProvider({ runtime: api.runtime }));
1108
+ for (const command of createCodexCliSessionNodeHostCommands()) api.registerNodeHostCommand(command);
1109
+ for (const policy of createCodexCliSessionNodeInvokePolicies()) api.registerNodeInvokePolicy(policy);
1110
+ api.registerCommand(createCodexCommand({
1111
+ pluginConfig: api.pluginConfig,
1112
+ deps: {
1113
+ listCodexCliSessionsOnNode: (params) => listCodexCliSessionsOnNode({
1114
+ runtime: api.runtime,
1115
+ ...params
1116
+ }),
1117
+ resolveCodexCliSessionForBindingOnNode: (params) => resolveCodexCliSessionForBindingOnNode({
1118
+ runtime: api.runtime,
1119
+ ...params
1120
+ }),
1121
+ codexPluginsManagementIo: {
1122
+ readConfig: () => {
1123
+ const plugins = (api.runtime.config?.current?.() ?? {}).plugins;
1124
+ if (!plugins || typeof plugins !== "object") return Promise.resolve({});
1125
+ const entries = plugins.entries;
1126
+ if (!entries || typeof entries !== "object") return Promise.resolve({});
1127
+ const codexEntry = entries.codex;
1128
+ if (!codexEntry || typeof codexEntry !== "object") return Promise.resolve({});
1129
+ const config = codexEntry.config;
1130
+ if (!config || typeof config !== "object") return Promise.resolve({});
1131
+ const codexPlugins = config.codexPlugins;
1132
+ if (!codexPlugins || typeof codexPlugins !== "object") return Promise.resolve({});
1133
+ const declared = codexPlugins.plugins;
1134
+ if (!declared || typeof declared !== "object") return Promise.resolve({ enabled: codexPlugins.enabled === true });
1135
+ return Promise.resolve({
1136
+ enabled: codexPlugins.enabled === true,
1137
+ plugins: declared
1138
+ });
1139
+ },
1140
+ mutate: async (update) => {
1141
+ await mutateConfigFile({ mutate: (draft) => {
1142
+ const root = draft;
1143
+ root.plugins = root.plugins ?? {};
1144
+ const pluginsBlock = root.plugins;
1145
+ pluginsBlock.entries = pluginsBlock.entries ?? {};
1146
+ const entries = pluginsBlock.entries;
1147
+ entries.codex = entries.codex ?? {};
1148
+ const codexEntry = entries.codex;
1149
+ codexEntry.config = codexEntry.config ?? {};
1150
+ const config = codexEntry.config;
1151
+ config.codexPlugins = config.codexPlugins ?? {};
1152
+ const codexPlugins = config.codexPlugins;
1153
+ codexPlugins.plugins = codexPlugins.plugins ?? {};
1154
+ update(codexPlugins);
1155
+ } });
1156
+ }
1157
+ }
1158
+ }
1159
+ }));
1160
+ api.on("inbound_claim", (event, ctx) => handleCodexConversationInboundClaim(event, ctx, {
1161
+ pluginConfig: resolveCurrentPluginConfig(),
1162
+ resumeCodexCliSessionOnNode: (params) => resumeCodexCliSessionOnNode({
1163
+ runtime: api.runtime,
1164
+ ...params
1165
+ })
1166
+ }));
1167
+ api.onConversationBindingResolved?.(handleCodexConversationBindingResolved);
1168
+ }
1169
+ });
1170
+ //#endregion
1171
+ export { codex_default as default };