@openclaw/codex 2026.8.1-beta.3 → 2026.8.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api.js +5 -6
- package/dist/{attempt-client-cleanup-URjUlCHg.js → attempt-client-cleanup-CpVfwctT.js} +47 -5
- package/dist/{auth-binding-B4FfbcCg.js → auth-binding-Ds_QVm-X.js} +18 -3
- package/dist/{binding-connection-DAvZwp96.js → binding-connection-CF7BmrDk.js} +2 -2
- package/dist/{bounded-turn-4BjrZEwW.js → bounded-turn-DRC3hcjm.js} +16 -20
- package/dist/{capabilities-CH3K57v4.js → capabilities-D6m_TdVy.js} +1 -1
- package/dist/cli-metadata.js +1 -1
- package/dist/{command-formatters-D0nZ3qtd.js → command-formatters--UToCokS.js} +4 -3
- package/dist/{command-handlers-DC86lgT4.js → command-handlers-CLFx2Ypa.js} +114 -79
- package/dist/{compact-COqgBRny.js → compact-5xqW1oCh.js} +13 -12
- package/dist/{config-CpNeo5AE.js → config-CcYL77O6.js} +350 -288
- package/dist/{conversation-binding-data-CW2GuupV.js → conversation-binding-data-BiodpIzq.js} +2 -1
- package/dist/doctor-contract-api.js +121 -16
- package/dist/{dynamic-tools-fJZhl4CE.js → dynamic-tools-BmeXjwNZ.js} +243 -1002
- package/dist/{effective-mcp-catalog-4YKn51aG.js → effective-mcp-catalog-XXQKgK1U.js} +2 -2
- package/dist/{event-projector-assistant-message-BwxV4d6N.js → event-projector-assistant-message-C5-Ds8mA.js} +18 -1
- package/dist/{event-projector-usage-CLwNEJqW.js → event-projector-usage-B2r5vhWH.js} +9 -14
- package/dist/{harness-DoKQcF8n.js → harness-BgeB7LnD.js} +42 -52
- package/dist/harness.js +1 -1
- package/dist/index.js +308 -306
- package/dist/{isolated-completion-DPMtlH9r.js → isolated-completion-CxTus3vZ.js} +4 -4
- package/dist/launch-args-sXOAg0SX.js +84 -0
- package/dist/{managed-binary-By4FZC6i.js → managed-binary-ZkGodW19.js} +43 -7
- package/dist/media-understanding-provider.js +1 -1
- package/dist/model-catalog-DULBcniB.js +101 -0
- package/dist/{models-CZw1wClT.js → models-DaWfETQk.js} +27 -29
- package/dist/{native-subagent-monitor-GGq3RnOo.js → native-subagent-monitor-vXYUZH37.js} +226 -129
- package/dist/{node-exec-server.runtime-Bsu1LdFZ.js → node-exec-server.runtime-DirKVZ5h.js} +9 -6
- package/dist/{plugin-approval-roundtrip-C75Yiiwc.js → plugin-approval-roundtrip-CCWQGlAI.js} +2 -1
- package/dist/{plugin-marketplace-discovery-CSWDkMrP.js → plugin-marketplace-discovery-BXjIFEiw.js} +38 -46
- package/dist/{plugin-metadata-cache-BXH5NF-4.js → plugin-metadata-cache-DQQm4gWT.js} +163 -136
- package/dist/{protocol-validators-VAVyEnDp.js → protocol-validators-Bg5rpNxk.js} +148 -5
- package/dist/{rate-limits-BI1dMHDG.js → rate-limits-BqHEHXQJ.js} +3 -2
- package/dist/{sandbox-guard-C1qEeZ5C.js → request-BWxweEdK.js} +183 -2
- package/dist/{run-attempt-BV3HzuCf.js → run-attempt-BVLE4Gbi.js} +706 -517
- package/dist/{runtime-artifact-BvyT1uyd.js → runtime-artifact-D9pYp4zL.js} +3 -3
- package/dist/{session-binding-BTrLf9Qm.js → session-binding-D0zinCP1.js} +195 -122
- package/dist/{session-catalog-ezP_UcRM.js → session-catalog-eMhVm0Ql.js} +448 -313
- package/dist/session-catalog-home-id-Dt2GiG5o.js +112 -0
- package/dist/{session-cli-B1hKvfkI.js → session-cli-B2lyjJA0.js} +1 -1
- package/dist/session-history-C5J1AKzG.js +87 -0
- package/dist/session-permission-policy-ScnAyG90.js +160 -0
- package/dist/session-retirement-CtUtUTr9.js +90 -0
- package/dist/{session-upstream-marker-D_2npHlA.js → session-upstream-marker-gqrYIRHk.js} +2 -3
- package/dist/settled-turn-context-Bk3IUwod.js +290 -0
- package/dist/settled-turn-finalizer-BXLN9PfJ.js +104 -0
- package/dist/{shared-client-Dw-rzii0.js → shared-client-B1tT5U6r.js} +1738 -806
- package/dist/{side-question-DbXkJZzg.js → side-question-CZ-mCw-t.js} +76 -43
- package/dist/{thread-lifecycle-DKdrnTMX.js → thread-lifecycle-CGGKP720.js} +991 -455
- package/dist/{thread-ownership-i2NBwDUL.js → thread-ownership-RkaoZCmQ.js} +18 -8
- package/dist/{plugin-app-cache-key-DMNQ8Zi8.js → thread-resume-BFt1-ZDa.js} +55 -8
- package/dist/{transcript-mirror-BU0_LKAL.js → transcript-mirror-1ep4XjzF.js} +124 -18
- package/dist/transport-stdio-NT_Dpd9V.js +724 -0
- package/dist/{upstream-prompt-provenance-CFmsKwr9.js → upstream-prompt-provenance-LphB8slG.js} +8 -4
- package/dist/{upstream-session-fork-BDVJCLAD.js → upstream-session-fork-Dc8BFExw.js} +76 -90
- package/dist/{usage-9dKJCgcy.js → usage-DUhd58gI.js} +3 -3
- package/dist/{web-search-provider.runtime-DCdx4DGu.js → web-search-provider.runtime-BEmlE7ov.js} +3 -3
- package/openclaw.plugin.json +19 -1
- package/package.json +8 -8
- package/dist/app-server-policy-bg5QPSVP.js +0 -25
- package/dist/command-rpc-xUIIonsO.js +0 -90
- package/dist/incognito-session-ET_ufDH-.js +0 -2
- package/dist/model-catalog-CmGoqVKB.js +0 -48
- package/dist/request-DSK0W6YI.js +0 -157
- package/dist/session-catalog-home-id-BNwAJ9D7.js +0 -18
- package/dist/session-retirement-CE4iMiLh.js +0 -36
- package/dist/settled-turn-finalizer-Dx1onIqg.js +0 -328
- package/dist/thread-resume-CdJk2Ehf.js +0 -30
- package/dist/transport-stdio-DhoGy33Z.js +0 -99
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { t as createStdioTransport } from "./transport-stdio-
|
|
3
|
-
import { n as resolveManagedCodexAppServerStartOptions, r as resolveManagedCodexNativeCommand, t as isManagedCodexDesktopCommand } from "./managed-binary-By4FZC6i.js";
|
|
1
|
+
import { n as resolveManagedCodexAppServerStartOptions, r as resolveManagedCodexNativeCommand, t as isManagedCodexDesktopCommand } from "./managed-binary-ZkGodW19.js";
|
|
2
|
+
import { i as closeCodexAppServerTransportAndWait, t as createStdioTransport } from "./transport-stdio-NT_Dpd9V.js";
|
|
4
3
|
import { isRecord } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
5
4
|
import { mkdir } from "node:fs/promises";
|
|
6
5
|
import path from "node:path";
|
|
@@ -9,7 +8,7 @@ import { killProcessTree } from "openclaw/plugin-sdk/process-runtime";
|
|
|
9
8
|
import { once } from "node:events";
|
|
10
9
|
import { sanitizeEnvVars } from "openclaw/plugin-sdk/sandbox";
|
|
11
10
|
//#region extensions/codex/src/node-exec-server.runtime.ts
|
|
12
|
-
const MAX_CODEX_EXEC_SERVER_MESSAGE_BYTES =
|
|
11
|
+
const MAX_CODEX_EXEC_SERVER_MESSAGE_BYTES = 67108864;
|
|
13
12
|
const CODEX_EXEC_SERVER_TERMINATION_GRACE_MS = 1e3;
|
|
14
13
|
const CODEX_EXEC_SERVER_REAP_TIMEOUT_MS = 5e3;
|
|
15
14
|
const NODE_EXEC_SERVER_PLATFORM_ENVIRONMENT = /^(?:SYSTEMROOT|WINDIR|COMSPEC|PATHEXT|TEMP|TMP|TMPDIR)$/iu;
|
|
@@ -125,7 +124,8 @@ async function runCodexNodeExecServer(params) {
|
|
|
125
124
|
customAllowedPatterns: [NODE_EXEC_SERVER_PLATFORM_ENVIRONMENT]
|
|
126
125
|
}).allowed;
|
|
127
126
|
if (io.signal.aborted) throw nodeExecServerAbortError(io.signal);
|
|
128
|
-
|
|
127
|
+
params.assertExecAuthorized();
|
|
128
|
+
const child = await createStdioTransport({
|
|
129
129
|
transport: "stdio",
|
|
130
130
|
command: native,
|
|
131
131
|
commandSource: "resolved-managed",
|
|
@@ -138,7 +138,10 @@ async function runCodexNodeExecServer(params) {
|
|
|
138
138
|
...process.platform === "win32" ? { USERPROFILE: dir } : {}
|
|
139
139
|
},
|
|
140
140
|
clearEnv: ["NODE_OPTIONS"]
|
|
141
|
-
}, baseEnv)
|
|
141
|
+
}, baseEnv, () => {
|
|
142
|
+
if (io.signal.aborted) throw nodeExecServerAbortError(io.signal);
|
|
143
|
+
params.assertExecAuthorized();
|
|
144
|
+
});
|
|
142
145
|
child.stdin.on("error", (error) => {
|
|
143
146
|
rejectDisconnected(error);
|
|
144
147
|
});
|
package/dist/{plugin-approval-roundtrip-C75Yiiwc.js → plugin-approval-roundtrip-CCWQGlAI.js}
RENAMED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { F as resolveCodexGatewayTimeoutWithGraceMs } from "./shared-client-B1tT5U6r.js";
|
|
2
2
|
import { isApprovalNotFoundError, toErrorObject } from "openclaw/plugin-sdk/error-runtime";
|
|
3
3
|
import { truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
|
|
4
4
|
//#region extensions/codex/src/app-server/plugin-approval-roundtrip.ts
|
|
@@ -23,6 +23,7 @@ function codexApprovalTimeoutText(kind) {
|
|
|
23
23
|
async function requestPluginApproval(params) {
|
|
24
24
|
const timeoutMs = DEFAULT_CODEX_APPROVAL_TIMEOUT_MS;
|
|
25
25
|
return params.hostCapabilities.requestApproval({
|
|
26
|
+
signal: params.signal,
|
|
26
27
|
title: truncateCodexApprovalDisplayText(params.title, MAX_PLUGIN_APPROVAL_TITLE_LENGTH),
|
|
27
28
|
description: truncateCodexApprovalDisplayText(params.description, MAX_PLUGIN_APPROVAL_DESCRIPTION_LENGTH),
|
|
28
29
|
severity: params.severity,
|
package/dist/{plugin-marketplace-discovery-CSWDkMrP.js → plugin-marketplace-discovery-BXjIFEiw.js}
RENAMED
|
@@ -1,15 +1,16 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { o as isCodexAppServerNativeAuthProfile, r as bindingStoreKey, s as normalizeCodexAppServerBindingModelProvider } from "./session-binding-
|
|
4
|
-
import {
|
|
5
|
-
import { r as formatCodexDisplayText } from "./command-formatters
|
|
6
|
-
import { n as resolveCodexBindingAppServerConnection } from "./binding-connection-
|
|
1
|
+
import { k as isCodexFastServiceTier } from "./config-CcYL77O6.js";
|
|
2
|
+
import { c as getLeasedSharedCodexAppServerClient, h as releaseLeasedSharedCodexAppServerClient } from "./shared-client-B1tT5U6r.js";
|
|
3
|
+
import { o as isCodexAppServerNativeAuthProfile, r as bindingStoreKey, s as normalizeCodexAppServerBindingModelProvider } from "./session-binding-D0zinCP1.js";
|
|
4
|
+
import { E as resolveCodexAppServerRequestModelSelection, O as resolveCodexBindingModelProviderFallback } from "./thread-lifecycle-CGGKP720.js";
|
|
5
|
+
import { r as formatCodexDisplayText } from "./command-formatters--UToCokS.js";
|
|
6
|
+
import { n as resolveCodexBindingAppServerConnection } from "./binding-connection-CF7BmrDk.js";
|
|
7
7
|
import { asOptionalRecord } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
8
8
|
import { resolveAgentDir } from "openclaw/plugin-sdk/agent-runtime";
|
|
9
9
|
import { getSessionEntry, patchSessionEntry, resolveStorePath } from "openclaw/plugin-sdk/session-store-runtime";
|
|
10
10
|
import { ModelSelectionLockedError, applyModelOverrideWithAuthProfileCompatibility } from "openclaw/plugin-sdk/model-session-runtime";
|
|
11
11
|
//#region extensions/codex/src/command-authorization.ts
|
|
12
12
|
const CODEX_NATIVE_EXECUTION_AUTH_ERROR = "Only an owner or operator.admin can control Codex native execution.";
|
|
13
|
+
const CODEX_HOST_INSPECTION_AUTH_ERROR = "Only an owner or operator.admin can inspect Codex host state.";
|
|
13
14
|
const CODEX_FULL_PERMISSIONS_AUTH_ERROR = "Full Codex permissions require operator.admin. Choose Admin in the Control UI permission picker, or use an admin-authenticated CLI.";
|
|
14
15
|
function hasCodexAdminScope(ctx) {
|
|
15
16
|
return ctx.gatewayClientScopes?.includes("operator.admin") === true;
|
|
@@ -126,15 +127,16 @@ async function setCodexConversationModel(params) {
|
|
|
126
127
|
const lookup = buildBindingLookup(params);
|
|
127
128
|
const binding = await requireThreadBinding(params.bindingStore, params.identity);
|
|
128
129
|
if (binding.connectionScope === "supervision") throw new ModelSelectionLockedError();
|
|
130
|
+
const modelProvider = resolveConversationControlModelProvider({
|
|
131
|
+
authProfileId: binding.authProfileId,
|
|
132
|
+
bindingModel: binding.model,
|
|
133
|
+
bindingModelProvider: binding.modelProvider,
|
|
134
|
+
currentModel: model,
|
|
135
|
+
...lookup
|
|
136
|
+
});
|
|
129
137
|
const modelSelection = resolveCodexAppServerRequestModelSelection({
|
|
130
138
|
model,
|
|
131
|
-
modelProvider
|
|
132
|
-
authProfileId: binding.authProfileId,
|
|
133
|
-
bindingModel: binding.model,
|
|
134
|
-
bindingModelProvider: binding.modelProvider,
|
|
135
|
-
currentModel: model,
|
|
136
|
-
...lookup
|
|
137
|
-
}),
|
|
139
|
+
modelProvider,
|
|
138
140
|
authProfileId: binding.authProfileId,
|
|
139
141
|
...lookup
|
|
140
142
|
});
|
|
@@ -145,23 +147,23 @@ async function setCodexConversationModel(params) {
|
|
|
145
147
|
});
|
|
146
148
|
const nextModel = modelSelection.model;
|
|
147
149
|
const modelChanged = nextModel !== binding.model || nextModelProvider !== binding.modelProvider;
|
|
148
|
-
const
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
if (session) {
|
|
150
|
+
const projectionPatch = modelChanged && binding.contextEngine?.projection ? { contextEngine: {
|
|
151
|
+
...binding.contextEngine,
|
|
152
|
+
projection: void 0
|
|
153
|
+
} } : {};
|
|
154
|
+
const identity = params.identity;
|
|
155
|
+
if (identity.kind === "session" && identity.sessionKey) {
|
|
154
156
|
if (!await patchSessionEntry({
|
|
155
|
-
agentId:
|
|
156
|
-
storePath: resolveStorePath(params.config?.session?.store, { agentId:
|
|
157
|
-
sessionKey:
|
|
157
|
+
agentId: identity.agentId,
|
|
158
|
+
storePath: resolveStorePath(params.config?.session?.store, { agentId: identity.agentId }),
|
|
159
|
+
sessionKey: identity.sessionKey,
|
|
158
160
|
requireWriteSuccess: true,
|
|
159
161
|
replaceEntry: true,
|
|
160
162
|
update: (entry) => {
|
|
161
|
-
if (entry.sessionId !==
|
|
163
|
+
if (entry.sessionId !== identity.sessionId) throw new Error("Codex session changed while applying the model selection.");
|
|
162
164
|
applyModelOverrideWithAuthProfileCompatibility({
|
|
163
165
|
cfg: params.config ?? {},
|
|
164
|
-
agentDir: params.agentDir ?? resolveAgentDir(params.config ?? {},
|
|
166
|
+
agentDir: params.agentDir ?? resolveAgentDir(params.config ?? {}, identity.agentId),
|
|
165
167
|
entry,
|
|
166
168
|
currentProvider: binding.modelProvider ?? "openai",
|
|
167
169
|
selection: {
|
|
@@ -173,25 +175,11 @@ async function setCodexConversationModel(params) {
|
|
|
173
175
|
return entry;
|
|
174
176
|
}
|
|
175
177
|
})) throw new Error("Codex session changed while applying the model selection.");
|
|
176
|
-
if (
|
|
177
|
-
model: nextModel,
|
|
178
|
-
modelProvider: nextModelProvider,
|
|
179
|
-
...modelChanged && binding.contextEngine?.projection ? { contextEngine: {
|
|
180
|
-
...binding.contextEngine,
|
|
181
|
-
projection: void 0
|
|
182
|
-
} } : {}
|
|
183
|
-
});
|
|
184
|
-
else if (modelChanged && binding.contextEngine?.projection) await patchThreadBinding(params.bindingStore, params.identity, binding.threadId, { contextEngine: {
|
|
185
|
-
...binding.contextEngine,
|
|
186
|
-
projection: void 0
|
|
187
|
-
} });
|
|
178
|
+
if (modelChanged && binding.contextEngine?.projection) await patchThreadBinding(params.bindingStore, identity, binding.threadId, projectionPatch);
|
|
188
179
|
} else await patchThreadBinding(params.bindingStore, params.identity, binding.threadId, {
|
|
189
180
|
model: nextModel,
|
|
190
181
|
modelProvider: nextModelProvider,
|
|
191
|
-
...
|
|
192
|
-
...binding.contextEngine,
|
|
193
|
-
projection: void 0
|
|
194
|
-
} } : {}
|
|
182
|
+
...projectionPatch
|
|
195
183
|
});
|
|
196
184
|
return `Codex model set to ${formatCodexDisplayText(nextModel)}.`;
|
|
197
185
|
}
|
|
@@ -223,12 +211,11 @@ async function setCodexConversationPermissions(params) {
|
|
|
223
211
|
replaceEntry: true,
|
|
224
212
|
update: (entry) => {
|
|
225
213
|
if (entry.sessionId !== params.session.sessionId) throw new Error("Codex session changed while applying the permission mode.");
|
|
226
|
-
|
|
227
|
-
else delete entry.permissionMode;
|
|
214
|
+
entry.permissionMode = params.mode === "yolo" ? "full" : "guarded";
|
|
228
215
|
return entry;
|
|
229
216
|
}
|
|
230
217
|
})) throw new Error("Codex session changed while applying the permission mode.");
|
|
231
|
-
return `Codex permissions set to ${params.mode === "yolo" ? "full access" : "
|
|
218
|
+
return `Codex permissions set to ${params.mode === "yolo" ? "full access" : "guarded"}.`;
|
|
232
219
|
}
|
|
233
220
|
function parseCodexFastModeArg(arg) {
|
|
234
221
|
const normalized = arg?.trim().toLowerCase();
|
|
@@ -240,10 +227,15 @@ function parseCodexPermissionsModeArg(arg) {
|
|
|
240
227
|
const normalized = arg?.trim().toLowerCase();
|
|
241
228
|
if (!normalized || normalized === "status") return;
|
|
242
229
|
if (normalized === "yolo" || normalized === "full" || normalized === "full-access") return "yolo";
|
|
243
|
-
if (
|
|
230
|
+
if ([
|
|
231
|
+
"default",
|
|
232
|
+
"guardian",
|
|
233
|
+
"guarded",
|
|
234
|
+
"approve"
|
|
235
|
+
].includes(normalized)) return "default";
|
|
244
236
|
}
|
|
245
237
|
function formatPermissionsMode(mode) {
|
|
246
|
-
return mode === "full" ? "full access" : "default";
|
|
238
|
+
return mode === "full" ? "full access" : mode ?? "default";
|
|
247
239
|
}
|
|
248
240
|
async function requireThreadBinding(bindingStore, identity) {
|
|
249
241
|
const binding = await bindingStore.read(identity);
|
|
@@ -396,4 +388,4 @@ function boundedCatalogText(value) {
|
|
|
396
388
|
return sanitized.replace(/\s+/g, " ").trim().slice(0, MAX_PLUGIN_DESCRIPTION_LENGTH);
|
|
397
389
|
}
|
|
398
390
|
//#endregion
|
|
399
|
-
export { parseCodexPermissionsModeArg as a, setCodexConversationModel as c, stopCodexConversationTurn as d, trackCodexConversationActiveTurn as f,
|
|
391
|
+
export { hasCodexAdminScope as _, parseCodexPermissionsModeArg as a, setCodexConversationModel as c, stopCodexConversationTurn as d, trackCodexConversationActiveTurn as f, canMutateCodexHost as g, CODEX_NATIVE_EXECUTION_AUTH_ERROR as h, parseCodexFastModeArg as i, setCodexConversationPermissions as l, CODEX_HOST_INSPECTION_AUTH_ERROR as m, parseCodexPluginMarketplaceId as n, readCodexConversationActiveTurn as o, CODEX_FULL_PERMISSIONS_AUTH_ERROR as p, formatPermissionsMode as r, setCodexConversationFastMode as s, discoverCodexMarketplacePlugins as t, steerCodexConversationTurn as u };
|
|
@@ -1,91 +1,11 @@
|
|
|
1
|
-
import { i as resolveCodexAppServerRuntimeOptions, o as resolveCodexComputerUseConfig } from "./config-
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
1
|
+
import { P as resolveCodexAppServerHomeDir, i as resolveCodexAppServerRuntimeOptions, o as resolveCodexComputerUseConfig } from "./config-CcYL77O6.js";
|
|
2
|
+
import { At as reconcileCodexComputerUseStartArtifacts, G as isCodexAppServerConnectionClosedError, K as isCodexAppServerIndeterminateRequestCancellationError, O as acquireCodexNativeConfigFence, S as waitForCodexAppServerClientDesktopGenerationDrain, Ut as resolveCodexManagedBundledMarketplacePath, Wt as assertNotSymlink, c as getLeasedSharedCodexAppServerClient, d as readCodexAppServerClientDesktopGeneration, g as resolveCodexNativeConfigFenceKey, h as releaseLeasedSharedCodexAppServerClient, p as readCodexAppServerClientProcessIdentity, q as isCodexAppServerIndeterminateTransportError, t as assertCodexAppServerClientStartSelectionCurrent, u as isCodexAppServerStartSelectionChangedError } from "./shared-client-B1tT5U6r.js";
|
|
3
|
+
import { l as resolveMacOSDesktopCodexBundledMarketplaceCandidates, s as resolveFirstExistingMacOSDesktopCodexBundledMarketplacePath, t as isManagedCodexDesktopCommand } from "./managed-binary-ZkGodW19.js";
|
|
4
|
+
import { i as requestCodexAppServerJson } from "./request-BWxweEdK.js";
|
|
5
|
+
import { n as describeControlFailure } from "./capabilities-D6m_TdVy.js";
|
|
6
|
+
import fs from "node:fs/promises";
|
|
7
|
+
import path from "node:path";
|
|
5
8
|
import { existsSync } from "node:fs";
|
|
6
|
-
import { runExec } from "openclaw/plugin-sdk/process-runtime";
|
|
7
|
-
//#region extensions/codex/src/app-server/computer-use-process-repair.ts
|
|
8
|
-
const COMPUTER_USE_PROCESS_LIST_TIMEOUT_MS = 2e3;
|
|
9
|
-
const COMPUTER_USE_PROCESS_LIST_MAX_BUFFER_BYTES = 5 * 1024 * 1024;
|
|
10
|
-
function scopedRepairUnavailableStatus() {
|
|
11
|
-
return {
|
|
12
|
-
attempted: false,
|
|
13
|
-
killedPids: [],
|
|
14
|
-
warnings: ["Computer Use auto-repair skipped because no scoped Codex app-server process was available."],
|
|
15
|
-
message: "Computer Use stale child repair requires a scoped local app-server PID."
|
|
16
|
-
};
|
|
17
|
-
}
|
|
18
|
-
async function killStaleComputerUseMcpChildren(options = {}) {
|
|
19
|
-
if (process.platform !== "darwin") return {
|
|
20
|
-
attempted: true,
|
|
21
|
-
killedPids: [],
|
|
22
|
-
warnings: [`Computer Use stale child repair is currently macOS-only, not ${process.platform}.`],
|
|
23
|
-
message: "Computer Use stale child repair skipped on this platform."
|
|
24
|
-
};
|
|
25
|
-
if (!options.ancestorPid || !Number.isSafeInteger(options.ancestorPid) || options.ancestorPid <= 0) return scopedRepairUnavailableStatus();
|
|
26
|
-
let stdout;
|
|
27
|
-
try {
|
|
28
|
-
stdout = (await runExec("/bin/ps", ["-axo", "pid=,ppid=,command="], {
|
|
29
|
-
logOutput: false,
|
|
30
|
-
maxBuffer: COMPUTER_USE_PROCESS_LIST_MAX_BUFFER_BYTES,
|
|
31
|
-
timeoutMs: COMPUTER_USE_PROCESS_LIST_TIMEOUT_MS
|
|
32
|
-
})).stdout;
|
|
33
|
-
} catch (error) {
|
|
34
|
-
return {
|
|
35
|
-
attempted: true,
|
|
36
|
-
killedPids: [],
|
|
37
|
-
warnings: [`Could not list processes for Computer Use repair: ${describeControlFailure(error)}`],
|
|
38
|
-
message: "Computer Use stale child repair could not inspect running processes."
|
|
39
|
-
};
|
|
40
|
-
}
|
|
41
|
-
const killedPids = [];
|
|
42
|
-
const warnings = [];
|
|
43
|
-
const processInfos = parsePsOutput(stdout);
|
|
44
|
-
for (const processInfo of processInfos) {
|
|
45
|
-
if (!isStaleComputerUseMcpChild(processInfo.command)) continue;
|
|
46
|
-
if (!isDescendantOfPid(processInfo.pid, options.ancestorPid, processInfos)) continue;
|
|
47
|
-
try {
|
|
48
|
-
process.kill(processInfo.pid, "SIGTERM");
|
|
49
|
-
killedPids.push(processInfo.pid);
|
|
50
|
-
} catch (error) {
|
|
51
|
-
warnings.push(`Could not terminate stale Computer Use MCP child pid ${processInfo.pid}: ${describeControlFailure(error)}`);
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
return {
|
|
55
|
-
attempted: true,
|
|
56
|
-
killedPids,
|
|
57
|
-
warnings,
|
|
58
|
-
message: killedPids.length === 0 ? "No stale Computer Use MCP children were found under the scoped Codex app-server process." : `Terminated ${killedPids.length} stale Computer Use MCP child process${killedPids.length === 1 ? "" : "es"} under the scoped Codex app-server process.`
|
|
59
|
-
};
|
|
60
|
-
}
|
|
61
|
-
function parsePsOutput(stdout) {
|
|
62
|
-
return stdout.split(/\r?\n/u).flatMap((line) => {
|
|
63
|
-
const match = /^\s*(\d+)\s+(\d+)\s+(.+)$/u.exec(line);
|
|
64
|
-
if (!match) return [];
|
|
65
|
-
return [{
|
|
66
|
-
pid: Number(match[1]),
|
|
67
|
-
ppid: Number(match[2]),
|
|
68
|
-
command: match[3] ?? ""
|
|
69
|
-
}];
|
|
70
|
-
}).filter((processInfo) => Number.isSafeInteger(processInfo.pid) && processInfo.pid > 0 && Number.isSafeInteger(processInfo.ppid) && processInfo.ppid >= 0);
|
|
71
|
-
}
|
|
72
|
-
function isStaleComputerUseMcpChild(command) {
|
|
73
|
-
return command.includes("SkyComputerUseClient") && /(?:^|\s)mcp(?:\s|$)/u.test(command);
|
|
74
|
-
}
|
|
75
|
-
function isDescendantOfPid(pid, ancestorPid, processInfos) {
|
|
76
|
-
const parents = new Map(processInfos.map((processInfo) => [processInfo.pid, processInfo.ppid]));
|
|
77
|
-
const seen = /* @__PURE__ */ new Set();
|
|
78
|
-
let current = pid;
|
|
79
|
-
while (!seen.has(current)) {
|
|
80
|
-
seen.add(current);
|
|
81
|
-
const parent = parents.get(current);
|
|
82
|
-
if (!parent || parent <= 0) return false;
|
|
83
|
-
if (parent === ancestorPid) return true;
|
|
84
|
-
current = parent;
|
|
85
|
-
}
|
|
86
|
-
return false;
|
|
87
|
-
}
|
|
88
|
-
//#endregion
|
|
89
9
|
//#region extensions/codex/src/app-server/computer-use.ts
|
|
90
10
|
/**
|
|
91
11
|
* Computer Use plugin/MCP readiness checks and optional install flow for Codex
|
|
@@ -99,8 +19,9 @@ var CodexComputerUseSetupError = class extends Error {
|
|
|
99
19
|
}
|
|
100
20
|
};
|
|
101
21
|
const CURATED_MARKETPLACE_POLL_INTERVAL_MS = 2e3;
|
|
22
|
+
const BUNDLED_MARKETPLACE_NAME = "openai-bundled";
|
|
102
23
|
const COMPUTER_USE_MARKETPLACE_NAME_PRIORITY = [
|
|
103
|
-
|
|
24
|
+
BUNDLED_MARKETPLACE_NAME,
|
|
104
25
|
"openai-curated",
|
|
105
26
|
"openai-api-curated",
|
|
106
27
|
"openai-curated-remote",
|
|
@@ -172,72 +93,96 @@ async function installCodexComputerUse(params = {}) {
|
|
|
172
93
|
}
|
|
173
94
|
async function inspectCodexComputerUse(params) {
|
|
174
95
|
if (!params.installPlugin) return await inspectCodexComputerUseWithoutFence(params);
|
|
175
|
-
const
|
|
96
|
+
const resolvedRuntime = resolveCodexAppServerRuntimeOptions({
|
|
176
97
|
pluginConfig: params.pluginConfig,
|
|
177
98
|
managedCommandOrder: "desktop-first"
|
|
178
99
|
});
|
|
179
|
-
const
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
agentDir: params.agentDir,
|
|
183
|
-
config: params.config
|
|
184
|
-
});
|
|
185
|
-
if (!fenceKey) return await inspectCodexComputerUseWithoutFence(params);
|
|
186
|
-
const release = await acquireCodexNativeConfigFence(fenceKey, {
|
|
187
|
-
signal: params.signal,
|
|
188
|
-
timeoutMs: params.timeoutMs ?? runtime?.requestTimeoutMs,
|
|
189
|
-
timeoutMessage: "Codex Computer Use install timed out waiting for native config",
|
|
190
|
-
abortMessage: "Codex Computer Use install aborted waiting for native config"
|
|
191
|
-
});
|
|
192
|
-
let releaseFenceOnReturn = true;
|
|
100
|
+
const operationTimeoutMs = params.timeoutMs ?? resolvedRuntime.requestTimeoutMs;
|
|
101
|
+
const deadline = operationTimeoutMs > 0 ? Date.now() + operationTimeoutMs : void 0;
|
|
102
|
+
const remainingTimeoutMs = () => deadline === void 0 ? operationTimeoutMs : Math.max(1, deadline - Date.now());
|
|
193
103
|
let leasedClient;
|
|
194
104
|
try {
|
|
195
105
|
let client = params.client;
|
|
196
106
|
if (!client && !params.request) {
|
|
197
|
-
if (!runtime) throw new Error("Computer Use install could not resolve its app-server runtime");
|
|
198
107
|
client = await getLeasedSharedCodexAppServerClient({
|
|
199
|
-
startOptions:
|
|
108
|
+
startOptions: resolvedRuntime.start,
|
|
200
109
|
pluginConfig: params.pluginConfig,
|
|
201
|
-
timeoutMs:
|
|
110
|
+
timeoutMs: remainingTimeoutMs(),
|
|
202
111
|
config: params.config,
|
|
203
112
|
agentDir: params.agentDir,
|
|
204
113
|
abandonSignal: params.signal
|
|
205
114
|
});
|
|
206
115
|
leasedClient = client;
|
|
207
116
|
}
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
117
|
+
const explicitManagedInstall = client && !resolveCodexComputerUseConfig({ pluginConfig: params.pluginConfig }).autoInstall ? await resolveExplicitManagedComputerUseInstallContext({
|
|
118
|
+
...params,
|
|
119
|
+
client
|
|
120
|
+
}) : void 0;
|
|
121
|
+
if (explicitManagedInstall) {
|
|
122
|
+
await waitForCodexAppServerClientDesktopGenerationDrain({
|
|
123
|
+
client: explicitManagedInstall.client,
|
|
124
|
+
timeoutMs: remainingTimeoutMs(),
|
|
125
|
+
...params.signal ? { signal: params.signal } : {}
|
|
216
126
|
});
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
127
|
+
assertCodexAppServerClientStartSelectionCurrent({ client: explicitManagedInstall.client });
|
|
128
|
+
}
|
|
129
|
+
const inspectionParams = {
|
|
130
|
+
...params,
|
|
131
|
+
...client ? { client } : {},
|
|
132
|
+
timeoutMs: remainingTimeoutMs(),
|
|
133
|
+
...explicitManagedInstall ? { explicitManagedInstall } : {}
|
|
134
|
+
};
|
|
135
|
+
const fenceKey = resolveCodexNativeConfigFenceKey({
|
|
136
|
+
client,
|
|
137
|
+
startOptions: resolvedRuntime.start,
|
|
138
|
+
agentDir: params.agentDir,
|
|
139
|
+
config: params.config
|
|
140
|
+
});
|
|
141
|
+
if (!fenceKey) return await inspectCodexComputerUseWithoutFence(inspectionParams);
|
|
142
|
+
const release = await acquireCodexNativeConfigFence(fenceKey, {
|
|
143
|
+
signal: params.signal,
|
|
144
|
+
timeoutMs: remainingTimeoutMs(),
|
|
145
|
+
timeoutMessage: "Codex Computer Use install timed out waiting for native config",
|
|
146
|
+
abortMessage: "Codex Computer Use install aborted waiting for native config"
|
|
147
|
+
});
|
|
148
|
+
let releaseFenceOnReturn = true;
|
|
149
|
+
try {
|
|
150
|
+
try {
|
|
151
|
+
return await inspectCodexComputerUseWithoutFence({
|
|
152
|
+
...inspectionParams,
|
|
153
|
+
releaseNativeConfigFence: release
|
|
154
|
+
});
|
|
155
|
+
} catch (error) {
|
|
156
|
+
if (client && (isCodexAppServerIndeterminateRequestCancellationError(error) || isCodexAppServerIndeterminateTransportError(error) || isCodexAppServerConnectionClosedError(error))) {
|
|
157
|
+
releaseFenceOnReturn = false;
|
|
158
|
+
await client.closeAndRunAfterExit(release, "Computer Use config mutation");
|
|
159
|
+
}
|
|
160
|
+
throw error;
|
|
221
161
|
}
|
|
222
|
-
throw error;
|
|
223
162
|
} finally {
|
|
224
|
-
if (
|
|
163
|
+
if (releaseFenceOnReturn) release();
|
|
225
164
|
}
|
|
226
165
|
} finally {
|
|
227
|
-
if (
|
|
166
|
+
if (leasedClient) releaseLeasedSharedCodexAppServerClient(leasedClient);
|
|
228
167
|
}
|
|
229
168
|
}
|
|
230
169
|
async function inspectCodexComputerUseWithoutFence(params) {
|
|
231
170
|
const request = createComputerUseRequest(params);
|
|
232
|
-
|
|
233
|
-
|
|
171
|
+
if (params.installPlugin) {
|
|
172
|
+
if (!resolveCodexComputerUseConfig({ pluginConfig: params.pluginConfig }).autoInstall) await prepareExplicitManagedComputerUseInstall(params);
|
|
173
|
+
await request("experimentalFeature/enablement/set", { enablement: { plugins: true } });
|
|
174
|
+
}
|
|
175
|
+
const managedMarketplacePath = await resolveClientManagedBundledMarketplacePath(params.client, params.agentDir);
|
|
176
|
+
const managedCodexHome = managedMarketplacePath ? params.client?.getRuntimeIdentity()?.codexHome : void 0;
|
|
177
|
+
if (params.installPlugin && managedCodexHome) await assertNotSymlink(path.join(managedCodexHome, "config.toml"), "Codex config");
|
|
234
178
|
const marketplace = await resolveMarketplaceRef({
|
|
235
179
|
request,
|
|
236
180
|
config: params.computerUseConfig,
|
|
237
181
|
allowAdd: params.installPlugin,
|
|
238
182
|
signal: params.signal,
|
|
239
|
-
defaultBundledMarketplacePath: params.defaultBundledMarketplacePath,
|
|
240
|
-
defaultBundledMarketplacePathCandidates: params.defaultBundledMarketplacePathCandidates
|
|
183
|
+
defaultBundledMarketplacePath: params.defaultBundledMarketplacePath ?? managedMarketplacePath,
|
|
184
|
+
defaultBundledMarketplacePathCandidates: params.defaultBundledMarketplacePathCandidates,
|
|
185
|
+
managedCodexHome
|
|
241
186
|
});
|
|
242
187
|
if (!marketplace.marketplace) return unavailableStatus(params.computerUseConfig, "marketplace_missing", marketplace.message ?? `No Codex marketplace containing ${params.computerUseConfig.pluginName} is registered. Configure computerUse.marketplaceSource or computerUse.marketplacePath, then run /codex computer-use install.`);
|
|
243
188
|
const pluginInspection = await ensureComputerUsePlugin({
|
|
@@ -252,10 +197,59 @@ async function inspectCodexComputerUseWithoutFence(params) {
|
|
|
252
197
|
config: params.computerUseConfig,
|
|
253
198
|
plugin: pluginInspection.plugin,
|
|
254
199
|
installPlugin: params.installPlugin,
|
|
255
|
-
repairComputerUseMcpChildren,
|
|
256
200
|
releaseNativeConfigFence: params.releaseNativeConfigFence
|
|
257
201
|
});
|
|
258
202
|
}
|
|
203
|
+
async function prepareExplicitManagedComputerUseInstall(params) {
|
|
204
|
+
const context = params.explicitManagedInstall;
|
|
205
|
+
if (!context) return;
|
|
206
|
+
await reconcileCodexComputerUseStartArtifacts({
|
|
207
|
+
startOptions: {
|
|
208
|
+
transport: "stdio",
|
|
209
|
+
command: context.command,
|
|
210
|
+
commandSource: "resolved-managed",
|
|
211
|
+
args: ["app-server"],
|
|
212
|
+
headers: {},
|
|
213
|
+
env: { CODEX_HOME: context.codexHome }
|
|
214
|
+
},
|
|
215
|
+
agentDir: context.agentDir,
|
|
216
|
+
pluginConfig: { computerUse: {
|
|
217
|
+
...params.computerUseConfig,
|
|
218
|
+
autoInstall: true
|
|
219
|
+
} },
|
|
220
|
+
ownsIsolatedCodexHome: true,
|
|
221
|
+
desktopGeneration: context.desktopGeneration,
|
|
222
|
+
forceCacheRefresh: true,
|
|
223
|
+
assertCurrent: () => assertCodexAppServerClientStartSelectionCurrent({ client: context.client })
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
async function resolveExplicitManagedComputerUseInstallContext(params) {
|
|
227
|
+
if (!params.agentDir) return;
|
|
228
|
+
const codexHome = params.client.getRuntimeIdentity()?.codexHome;
|
|
229
|
+
const processIdentity = readCodexAppServerClientProcessIdentity(params.client);
|
|
230
|
+
const command = processIdentity?.nativeCommand ?? (processIdentity && isManagedCodexDesktopCommand(processIdentity.command, "darwin") ? processIdentity.command : void 0);
|
|
231
|
+
if (!codexHome || !command) return;
|
|
232
|
+
const desktopGeneration = readCodexAppServerClientDesktopGeneration(params.client);
|
|
233
|
+
if (!desktopGeneration) throw new Error("Codex Computer Use install requires a desktop-generation-bound client; reconnect and retry.");
|
|
234
|
+
const expectedHome = resolveCodexAppServerHomeDir(params.agentDir);
|
|
235
|
+
const [actualRealHome, expectedRealHome] = await Promise.all([fs.realpath(codexHome).catch(() => void 0), fs.realpath(expectedHome).catch(() => void 0)]);
|
|
236
|
+
if (!actualRealHome || actualRealHome !== expectedRealHome) return;
|
|
237
|
+
return {
|
|
238
|
+
client: params.client,
|
|
239
|
+
agentDir: params.agentDir,
|
|
240
|
+
codexHome,
|
|
241
|
+
command,
|
|
242
|
+
desktopGeneration
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
async function resolveClientManagedBundledMarketplacePath(client, agentDir) {
|
|
246
|
+
const codexHome = client?.getRuntimeIdentity()?.codexHome;
|
|
247
|
+
if (!codexHome || !agentDir) return;
|
|
248
|
+
const [actualRealHome, expectedRealHome] = await Promise.all([fs.realpath(codexHome).catch(() => void 0), fs.realpath(resolveCodexAppServerHomeDir(agentDir)).catch(() => void 0)]);
|
|
249
|
+
if (!actualRealHome || actualRealHome !== expectedRealHome) return;
|
|
250
|
+
const managedPath = resolveCodexManagedBundledMarketplacePath(codexHome);
|
|
251
|
+
return existsSync(managedPath) ? managedPath : void 0;
|
|
252
|
+
}
|
|
259
253
|
async function ensureComputerUsePlugin(params) {
|
|
260
254
|
let plugin = await readComputerUsePlugin(params.request, params.marketplace, params.config.pluginName);
|
|
261
255
|
if (!plugin.summary.installed || !plugin.summary.enabled) {
|
|
@@ -320,8 +314,7 @@ async function readComputerUseTools(params) {
|
|
|
320
314
|
params.releaseNativeConfigFence?.();
|
|
321
315
|
const { liveTest, repair } = await runCodexComputerUseLiveTest({
|
|
322
316
|
request: params.request,
|
|
323
|
-
config: params.config
|
|
324
|
-
repairComputerUseMcpChildren: params.repairComputerUseMcpChildren
|
|
317
|
+
config: params.config
|
|
325
318
|
});
|
|
326
319
|
const compatibilityStartupAllowed = !liveTest.ok && !params.config.strictReadiness;
|
|
327
320
|
return {
|
|
@@ -351,8 +344,6 @@ async function runCodexComputerUseLiveTest(params) {
|
|
|
351
344
|
threadId = (await params.request("thread/start", {
|
|
352
345
|
input: [],
|
|
353
346
|
developerInstructions: COMPUTER_USE_LIVE_TEST_THREAD_NAME,
|
|
354
|
-
sandbox: "danger-full-access",
|
|
355
|
-
approvalPolicy: "never",
|
|
356
347
|
ephemeral: true
|
|
357
348
|
}, { timeoutMs: params.config.liveTestTimeoutMs })).thread.id;
|
|
358
349
|
await params.request("mcpServer/tool/call", {
|
|
@@ -369,19 +360,19 @@ async function runCodexComputerUseLiveTest(params) {
|
|
|
369
360
|
attempts: attempt + 1,
|
|
370
361
|
timeoutMs: params.config.liveTestTimeoutMs,
|
|
371
362
|
retried: attempt > 0,
|
|
372
|
-
repaired: Boolean(repair?.attempted),
|
|
363
|
+
repaired: Boolean(repair?.attempted && repair.warnings.length === 0),
|
|
373
364
|
durationMs: Math.max(0, Date.now() - startedAt),
|
|
374
365
|
message: "Computer Use live test passed."
|
|
375
366
|
},
|
|
376
367
|
...repair ? { repair } : {}
|
|
377
368
|
};
|
|
378
369
|
} catch (error) {
|
|
370
|
+
if (isCodexAppServerStartSelectionChangedError(error)) throw error;
|
|
379
371
|
lastError = error;
|
|
380
|
-
if (attempt >= COMPUTER_USE_LIVE_TEST_RETRY_COUNT) break;
|
|
381
|
-
if (params.config.autoRepair) repair = params.repairComputerUseMcpChildren ? await params.repairComputerUseMcpChildren() : scopedRepairUnavailableStatus();
|
|
382
372
|
} finally {
|
|
383
373
|
if (threadId) await cleanupComputerUseProbeThread(params.request, threadId, params.config);
|
|
384
374
|
}
|
|
375
|
+
if (attempt < COMPUTER_USE_LIVE_TEST_RETRY_COUNT && params.config.autoRepair) repair = await repairComputerUseMcpRuntime(params.request, params.config);
|
|
385
376
|
}
|
|
386
377
|
const errorMessage = describeControlFailure(lastError);
|
|
387
378
|
return {
|
|
@@ -392,7 +383,7 @@ async function runCodexComputerUseLiveTest(params) {
|
|
|
392
383
|
attempts: 2,
|
|
393
384
|
timeoutMs: params.config.liveTestTimeoutMs,
|
|
394
385
|
retried: true,
|
|
395
|
-
repaired: Boolean(repair?.attempted),
|
|
386
|
+
repaired: Boolean(repair?.attempted && repair.warnings.length === 0),
|
|
396
387
|
durationMs: Math.max(0, Date.now() - startedAt),
|
|
397
388
|
message: `Computer Use live test failed after 2 attempts: ${errorMessage}`,
|
|
398
389
|
error: errorMessage
|
|
@@ -400,6 +391,25 @@ async function runCodexComputerUseLiveTest(params) {
|
|
|
400
391
|
...repair ? { repair } : {}
|
|
401
392
|
};
|
|
402
393
|
}
|
|
394
|
+
async function repairComputerUseMcpRuntime(request, config) {
|
|
395
|
+
try {
|
|
396
|
+
await request("config/mcpServer/reload", void 0, { timeoutMs: config.liveTestTimeoutMs });
|
|
397
|
+
return {
|
|
398
|
+
attempted: true,
|
|
399
|
+
killedPids: [],
|
|
400
|
+
warnings: [],
|
|
401
|
+
message: "Reloaded Computer Use MCP servers through Codex app-server."
|
|
402
|
+
};
|
|
403
|
+
} catch (error) {
|
|
404
|
+
const message = `Could not reload Computer Use MCP servers: ${describeControlFailure(error)}`;
|
|
405
|
+
return {
|
|
406
|
+
attempted: true,
|
|
407
|
+
killedPids: [],
|
|
408
|
+
warnings: [message],
|
|
409
|
+
message
|
|
410
|
+
};
|
|
411
|
+
}
|
|
412
|
+
}
|
|
403
413
|
async function cleanupComputerUseProbeThread(request, threadId, config) {
|
|
404
414
|
await Promise.allSettled([request("thread/unsubscribe", { threadId }, { timeoutMs: config.liveTestTimeoutMs }), request("thread/archive", { threadId }, { timeoutMs: config.liveTestTimeoutMs })]);
|
|
405
415
|
}
|
|
@@ -420,6 +430,12 @@ async function resolveMarketplaceRef(params) {
|
|
|
420
430
|
let candidates = await listComputerUseMarketplaceCandidates(params.request, params.config);
|
|
421
431
|
const bundledMarketplacePath = resolveBundledComputerUseMarketplacePath(params);
|
|
422
432
|
if (candidates.length === 0 && bundledMarketplacePath && shouldAddBundledComputerUseMarketplace(params)) {
|
|
433
|
+
if (params.managedCodexHome) await migrateLegacyBundledMarketplaceSource({
|
|
434
|
+
request: params.request,
|
|
435
|
+
bundledMarketplacePath,
|
|
436
|
+
legacySources: params.defaultBundledMarketplacePathCandidates,
|
|
437
|
+
userConfigPath: path.join(params.managedCodexHome, "config.toml")
|
|
438
|
+
});
|
|
423
439
|
const added = await params.request("marketplace/add", { source: bundledMarketplacePath });
|
|
424
440
|
preferredMarketplaceName ??= added.marketplaceName;
|
|
425
441
|
candidates = await listComputerUseMarketplaceCandidates(params.request, params.config);
|
|
@@ -444,6 +460,16 @@ async function resolveMarketplaceRef(params) {
|
|
|
444
460
|
const marketplace = candidates[0];
|
|
445
461
|
return marketplace ? { marketplace } : {};
|
|
446
462
|
}
|
|
463
|
+
async function migrateLegacyBundledMarketplaceSource(params) {
|
|
464
|
+
const response = await params.request("config/read", { includeLayers: false });
|
|
465
|
+
const bundled = response.config.marketplaces?.[BUNDLED_MARKETPLACE_NAME];
|
|
466
|
+
const sourceOrigin = response.origins[`marketplaces.${BUNDLED_MARKETPLACE_NAME}.source`];
|
|
467
|
+
if (bundled?.source_type !== "local" || !bundled.source || sourceOrigin?.name.type !== "user" || sourceOrigin.name.profile !== null || path.resolve(sourceOrigin.name.file) !== path.resolve(params.userConfigPath)) return;
|
|
468
|
+
const configuredSource = path.resolve(bundled.source);
|
|
469
|
+
if (configuredSource === path.resolve(params.bundledMarketplacePath)) return;
|
|
470
|
+
if (!(params.legacySources ?? resolveMacOSDesktopCodexBundledMarketplaceCandidates()).some((source) => path.resolve(source) === configuredSource)) return;
|
|
471
|
+
await params.request("marketplace/remove", { marketplaceName: BUNDLED_MARKETPLACE_NAME });
|
|
472
|
+
}
|
|
447
473
|
async function listComputerUseMarketplaceCandidates(request, config) {
|
|
448
474
|
return findComputerUseMarketplaces(await request("plugin/list", { cwds: [] }), config.pluginName);
|
|
449
475
|
}
|
|
@@ -456,6 +482,7 @@ function shouldAddBundledComputerUseMarketplace(params) {
|
|
|
456
482
|
}
|
|
457
483
|
function resolveBundledComputerUseMarketplacePath(params) {
|
|
458
484
|
if (params.defaultBundledMarketplacePath) return existsSync(params.defaultBundledMarketplacePath) ? params.defaultBundledMarketplacePath : void 0;
|
|
485
|
+
if (!params.defaultBundledMarketplacePathCandidates) return;
|
|
459
486
|
return resolveFirstExistingMacOSDesktopCodexBundledMarketplacePath({ candidates: params.defaultBundledMarketplacePathCandidates });
|
|
460
487
|
}
|
|
461
488
|
function findComputerUseMarketplaces(listed, pluginName) {
|
|
@@ -694,7 +721,7 @@ function resolveComputerUseConfig(params) {
|
|
|
694
721
|
}
|
|
695
722
|
//#endregion
|
|
696
723
|
//#region extensions/codex/src/app-server/plugin-metadata-cache.ts
|
|
697
|
-
const CODEX_PLUGIN_METADATA_CACHE_TTL_MS =
|
|
724
|
+
const CODEX_PLUGIN_METADATA_CACHE_TTL_MS = 36e5;
|
|
698
725
|
/** Process-local plugin metadata cache with coalesced loads per query. */
|
|
699
726
|
var CodexPluginMetadataCache = class {
|
|
700
727
|
constructor(nowMs = Date.now) {
|
|
@@ -793,4 +820,4 @@ function buildMetadataCacheEntryKey(appCacheKey, queryKind, requestParams, catal
|
|
|
793
820
|
]);
|
|
794
821
|
}
|
|
795
822
|
//#endregion
|
|
796
|
-
export { runCodexComputerUseLiveTest as a, readCodexComputerUseStatus as i, ensureCodexComputerUse as n,
|
|
823
|
+
export { runCodexComputerUseLiveTest as a, readCodexComputerUseStatus as i, ensureCodexComputerUse as n, installCodexComputerUse as r, defaultCodexPluginMetadataCache as t };
|