@openclaw/codex 2026.5.3 → 2026.5.4-beta.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/{client-chGfNrq5.js → client-BGbqC7jk.js} +2 -2
- package/dist/{client-factory-MaOMEltT.js → client-factory--cll1Fba.js} +3 -2
- package/dist/command-formatters-PiJcdUbu.js +337 -0
- package/dist/{command-handlers-CeaXhO5y.js → command-handlers-Bbr7RAUs.js} +170 -177
- package/dist/{compact-C0_rGlHZ.js → compact-DcR5aTxd.js} +4 -4
- package/dist/{config-CkkoMeqF.js → config-ByrA30No.js} +0 -2
- package/dist/{conversation-binding-DjptpT9W.js → conversation-binding-IhbXJcXQ.js} +86 -48
- package/dist/doctor-contract-api.js +19 -0
- package/dist/harness.js +3 -3
- package/dist/index.js +8 -3
- package/dist/media-understanding-provider.js +4 -4
- package/dist/{models-Ds7g6191.js → models-CkowdYbm.js} +6 -4
- package/dist/{protocol-validators-Cpopom3_.js → protocol-validators-Dky2yV4W.js} +2354 -2258
- package/dist/provider.js +2 -2
- package/dist/{computer-use-amNk2zrB.js → rate-limit-cache-t6ebYmfS.js} +29 -5
- package/dist/{run-attempt-BNbVe-IG.js → run-attempt-CFL1BFBl.js} +360 -129
- package/dist/{shared-client-0El8eRIE.js → shared-client-Dfk3Enm-.js} +43 -23
- package/dist/test-api.js +2 -2
- package/dist/{thread-lifecycle-OAlp5Pku.js → thread-lifecycle-CzllX4PU.js} +61 -23
- package/package.json +6 -6
- package/dist/capabilities-BmhO5h8O.js +0 -22
|
@@ -1,155 +1,44 @@
|
|
|
1
|
-
import { i as resolveCodexAppServerRuntimeOptions } from "./config-
|
|
2
|
-
import { n as listCodexAppServerModels, t as listAllCodexAppServerModels } from "./models-
|
|
1
|
+
import { i as resolveCodexAppServerRuntimeOptions } from "./config-ByrA30No.js";
|
|
2
|
+
import { n as listCodexAppServerModels, t as listAllCodexAppServerModels } from "./models-CkowdYbm.js";
|
|
3
3
|
import { t as isJsonObject } from "./protocol-C9UWI98H.js";
|
|
4
|
-
import {
|
|
4
|
+
import { a as formatComputerUseStatus, c as formatThreads, d as CODEX_CONTROL_METHODS, f as describeControlFailure, i as formatCodexStatus, l as readString, n as formatAccount, o as formatList, r as formatCodexDisplayText, s as formatModels, t as buildHelp } from "./command-formatters-PiJcdUbu.js";
|
|
5
5
|
import { i as readCodexAppServerBinding, o as writeCodexAppServerBinding, t as clearCodexAppServerBinding } from "./session-binding-DuJYTJQy.js";
|
|
6
|
-
import { a as parseCodexFastModeArg, c as setCodexConversationFastMode, d as steerCodexConversationTurn, f as stopCodexConversationTurn, i as formatPermissionsMode, l as setCodexConversationModel, m as resolveCodexDefaultWorkspaceDir, o as parseCodexPermissionsModeArg, p as readCodexConversationBindingData, r as startCodexConversationThread, s as readCodexConversationActiveTurn, u as setCodexConversationPermissions } from "./conversation-binding-
|
|
7
|
-
import { i as
|
|
6
|
+
import { a as parseCodexFastModeArg, c as setCodexConversationFastMode, d as steerCodexConversationTurn, f as stopCodexConversationTurn, i as formatPermissionsMode, l as setCodexConversationModel, m as resolveCodexDefaultWorkspaceDir, o as parseCodexPermissionsModeArg, p as readCodexConversationBindingData, r as startCodexConversationThread, s as readCodexConversationActiveTurn, u as setCodexConversationPermissions } from "./conversation-binding-IhbXJcXQ.js";
|
|
7
|
+
import { a as readCodexComputerUseStatus, i as installCodexComputerUse, n as rememberCodexRateLimits, o as requestCodexAppServerJson } from "./rate-limit-cache-t6ebYmfS.js";
|
|
8
8
|
import crypto from "node:crypto";
|
|
9
|
-
//#region extensions/codex/src/command-formatters.ts
|
|
10
|
-
function formatCodexStatus(probes) {
|
|
11
|
-
const lines = [`Codex app-server: ${probes.models.ok || probes.account.ok || probes.limits.ok || probes.mcps.ok || probes.skills.ok ? "connected" : "unavailable"}`];
|
|
12
|
-
if (probes.models.ok) lines.push(`Models: ${probes.models.value.models.map((model) => model.id).slice(0, 8).join(", ") || "none"}`);
|
|
13
|
-
else lines.push(`Models: ${probes.models.error}`);
|
|
14
|
-
lines.push(`Account: ${probes.account.ok ? summarizeAccount(probes.account.value) : probes.account.error}`);
|
|
15
|
-
lines.push(`Rate limits: ${probes.limits.ok ? summarizeArrayLike(probes.limits.value) : probes.limits.error}`);
|
|
16
|
-
lines.push(`MCP servers: ${probes.mcps.ok ? summarizeArrayLike(probes.mcps.value) : probes.mcps.error}`);
|
|
17
|
-
lines.push(`Skills: ${probes.skills.ok ? summarizeArrayLike(probes.skills.value) : probes.skills.error}`);
|
|
18
|
-
return lines.join("\n");
|
|
19
|
-
}
|
|
20
|
-
function formatModels(result) {
|
|
21
|
-
if (result.models.length === 0) return "No Codex app-server models returned.";
|
|
22
|
-
const lines = ["Codex models:", ...result.models.map((model) => `- ${model.id}${model.isDefault ? " (default)" : ""}`)];
|
|
23
|
-
if (result.truncated) lines.push("- More models available; output truncated.");
|
|
24
|
-
return lines.join("\n");
|
|
25
|
-
}
|
|
26
|
-
function formatThreads(response) {
|
|
27
|
-
const threads = extractArray(response);
|
|
28
|
-
if (threads.length === 0) return "No Codex threads returned.";
|
|
29
|
-
return ["Codex threads:", ...threads.slice(0, 10).map((thread) => {
|
|
30
|
-
const record = isJsonObject(thread) ? thread : {};
|
|
31
|
-
const id = readString(record, "threadId") ?? readString(record, "id") ?? "<unknown>";
|
|
32
|
-
const title = readString(record, "title") ?? readString(record, "name") ?? readString(record, "summary");
|
|
33
|
-
const details = [
|
|
34
|
-
readString(record, "model"),
|
|
35
|
-
readString(record, "cwd"),
|
|
36
|
-
readString(record, "updatedAt") ?? readString(record, "lastUpdatedAt")
|
|
37
|
-
].filter(Boolean);
|
|
38
|
-
return `- ${id}${title ? ` - ${title}` : ""}${details.length > 0 ? ` (${details.join(", ")})` : ""}\n Resume: /codex resume ${id}`;
|
|
39
|
-
})].join("\n");
|
|
40
|
-
}
|
|
41
|
-
function formatAccount(account, limits) {
|
|
42
|
-
return [`Account: ${account.ok ? summarizeAccount(account.value) : account.error}`, `Rate limits: ${limits.ok ? summarizeArrayLike(limits.value) : limits.error}`].join("\n");
|
|
43
|
-
}
|
|
44
|
-
function formatComputerUseStatus(status) {
|
|
45
|
-
const lines = [`Computer Use: ${status.ready ? "ready" : status.enabled ? "not ready" : "disabled"}`];
|
|
46
|
-
lines.push(`Plugin: ${status.pluginName} (${computerUsePluginState(status)})`);
|
|
47
|
-
lines.push(`MCP server: ${status.mcpServerName}${status.mcpServerAvailable ? ` (${status.tools.length} tools)` : " (unavailable)"}`);
|
|
48
|
-
if (status.marketplaceName) lines.push(`Marketplace: ${status.marketplaceName}`);
|
|
49
|
-
if (status.tools.length > 0) lines.push(`Tools: ${status.tools.slice(0, 8).join(", ")}`);
|
|
50
|
-
lines.push(status.message);
|
|
51
|
-
return lines.join("\n");
|
|
52
|
-
}
|
|
53
|
-
function computerUsePluginState(status) {
|
|
54
|
-
if (!status.installed) return "not installed";
|
|
55
|
-
return status.pluginEnabled ? "installed" : "installed, disabled";
|
|
56
|
-
}
|
|
57
|
-
function formatList(response, label) {
|
|
58
|
-
const entries = extractArray(response);
|
|
59
|
-
if (entries.length === 0) return `${label}: none returned.`;
|
|
60
|
-
return [`${label}:`, ...entries.slice(0, 25).map((entry) => {
|
|
61
|
-
const record = isJsonObject(entry) ? entry : {};
|
|
62
|
-
return `- ${readString(record, "name") ?? readString(record, "id") ?? JSON.stringify(entry)}`;
|
|
63
|
-
})].join("\n");
|
|
64
|
-
}
|
|
65
|
-
function buildHelp() {
|
|
66
|
-
return [
|
|
67
|
-
"Codex commands:",
|
|
68
|
-
"- /codex status",
|
|
69
|
-
"- /codex models",
|
|
70
|
-
"- /codex threads [filter]",
|
|
71
|
-
"- /codex resume <thread-id>",
|
|
72
|
-
"- /codex bind [thread-id] [--cwd <path>] [--model <model>] [--provider <provider>]",
|
|
73
|
-
"- /codex binding",
|
|
74
|
-
"- /codex stop",
|
|
75
|
-
"- /codex steer <message>",
|
|
76
|
-
"- /codex model [model]",
|
|
77
|
-
"- /codex fast [on|off|status]",
|
|
78
|
-
"- /codex permissions [default|yolo|status]",
|
|
79
|
-
"- /codex detach",
|
|
80
|
-
"- /codex compact",
|
|
81
|
-
"- /codex review",
|
|
82
|
-
"- /codex diagnostics [note]",
|
|
83
|
-
"- /codex computer-use [status|install]",
|
|
84
|
-
"- /codex account",
|
|
85
|
-
"- /codex mcp",
|
|
86
|
-
"- /codex skills"
|
|
87
|
-
].join("\n");
|
|
88
|
-
}
|
|
89
|
-
function summarizeAccount(value) {
|
|
90
|
-
if (!isJsonObject(value)) return "unavailable";
|
|
91
|
-
const account = isJsonObject(value.account) ? value.account : value;
|
|
92
|
-
if (readString(account, "type") === "amazonBedrock") return "Amazon Bedrock";
|
|
93
|
-
return readString(account, "email") ?? readString(account, "accountEmail") ?? readString(account, "planType") ?? readString(account, "id") ?? "available";
|
|
94
|
-
}
|
|
95
|
-
function summarizeArrayLike(value) {
|
|
96
|
-
const entries = extractArray(value);
|
|
97
|
-
if (entries.length === 0) return "none returned";
|
|
98
|
-
return `${entries.length}`;
|
|
99
|
-
}
|
|
100
|
-
function extractArray(value) {
|
|
101
|
-
if (Array.isArray(value)) return value;
|
|
102
|
-
if (!isJsonObject(value)) return [];
|
|
103
|
-
for (const key of [
|
|
104
|
-
"data",
|
|
105
|
-
"items",
|
|
106
|
-
"threads",
|
|
107
|
-
"models",
|
|
108
|
-
"skills",
|
|
109
|
-
"servers",
|
|
110
|
-
"rateLimits"
|
|
111
|
-
]) {
|
|
112
|
-
const child = value[key];
|
|
113
|
-
if (Array.isArray(child)) return child;
|
|
114
|
-
}
|
|
115
|
-
return [];
|
|
116
|
-
}
|
|
117
|
-
function readString(record, key) {
|
|
118
|
-
const value = record[key];
|
|
119
|
-
return typeof value === "string" && value.trim() ? value.trim() : void 0;
|
|
120
|
-
}
|
|
121
|
-
//#endregion
|
|
122
9
|
//#region extensions/codex/src/command-rpc.ts
|
|
123
|
-
function requestOptions(pluginConfig, limit) {
|
|
10
|
+
function requestOptions(pluginConfig, limit, config) {
|
|
124
11
|
const runtime = resolveCodexAppServerRuntimeOptions({ pluginConfig });
|
|
125
12
|
return {
|
|
126
13
|
limit,
|
|
127
14
|
timeoutMs: runtime.requestTimeoutMs,
|
|
128
|
-
startOptions: runtime.start
|
|
15
|
+
startOptions: runtime.start,
|
|
16
|
+
config
|
|
129
17
|
};
|
|
130
18
|
}
|
|
131
|
-
async function codexControlRequest(pluginConfig, method, requestParams) {
|
|
19
|
+
async function codexControlRequest(pluginConfig, method, requestParams, options = {}) {
|
|
132
20
|
const runtime = resolveCodexAppServerRuntimeOptions({ pluginConfig });
|
|
133
21
|
return await requestCodexAppServerJson({
|
|
134
22
|
method,
|
|
135
23
|
requestParams,
|
|
136
24
|
timeoutMs: runtime.requestTimeoutMs,
|
|
137
|
-
startOptions: runtime.start
|
|
25
|
+
startOptions: runtime.start,
|
|
26
|
+
config: options.config
|
|
138
27
|
});
|
|
139
28
|
}
|
|
140
|
-
async function safeCodexControlRequest(pluginConfig, method, requestParams) {
|
|
141
|
-
return await safeValue(async () => await codexControlRequest(pluginConfig, method, requestParams));
|
|
29
|
+
async function safeCodexControlRequest(pluginConfig, method, requestParams, options = {}) {
|
|
30
|
+
return await safeValue(async () => await codexControlRequest(pluginConfig, method, requestParams, options));
|
|
142
31
|
}
|
|
143
|
-
async function safeCodexModelList(pluginConfig, limit) {
|
|
144
|
-
return await safeValue(async () => await listCodexAppServerModels(requestOptions(pluginConfig, limit)));
|
|
32
|
+
async function safeCodexModelList(pluginConfig, limit, config) {
|
|
33
|
+
return await safeValue(async () => await listCodexAppServerModels(requestOptions(pluginConfig, limit, config)));
|
|
145
34
|
}
|
|
146
|
-
async function readCodexStatusProbes(pluginConfig) {
|
|
35
|
+
async function readCodexStatusProbes(pluginConfig, config) {
|
|
147
36
|
const [models, account, limits, mcps, skills] = await Promise.all([
|
|
148
|
-
safeCodexModelList(pluginConfig, 20),
|
|
149
|
-
safeCodexControlRequest(pluginConfig, CODEX_CONTROL_METHODS.account, { refreshToken: false }),
|
|
150
|
-
safeCodexControlRequest(pluginConfig, CODEX_CONTROL_METHODS.rateLimits, void 0),
|
|
151
|
-
safeCodexControlRequest(pluginConfig, CODEX_CONTROL_METHODS.listMcpServers, { limit: 100 }),
|
|
152
|
-
safeCodexControlRequest(pluginConfig, CODEX_CONTROL_METHODS.listSkills, {})
|
|
37
|
+
safeCodexModelList(pluginConfig, 20, config),
|
|
38
|
+
safeCodexControlRequest(pluginConfig, CODEX_CONTROL_METHODS.account, { refreshToken: false }, { config }),
|
|
39
|
+
safeCodexControlRequest(pluginConfig, CODEX_CONTROL_METHODS.rateLimits, void 0, { config }),
|
|
40
|
+
safeCodexControlRequest(pluginConfig, CODEX_CONTROL_METHODS.listMcpServers, { limit: 100 }, { config }),
|
|
41
|
+
safeCodexControlRequest(pluginConfig, CODEX_CONTROL_METHODS.listSkills, {}, { config })
|
|
153
42
|
]);
|
|
154
43
|
return {
|
|
155
44
|
models,
|
|
@@ -217,29 +106,52 @@ async function handleCodexSubcommand(ctx, options) {
|
|
|
217
106
|
const [subcommand = "status", ...rest] = splitArgs(ctx.args);
|
|
218
107
|
const normalized = subcommand.toLowerCase();
|
|
219
108
|
if (normalized === "help") return { text: buildHelp() };
|
|
220
|
-
if (normalized === "status")
|
|
221
|
-
|
|
109
|
+
if (normalized === "status") {
|
|
110
|
+
if (rest.length > 0) return { text: "Usage: /codex status" };
|
|
111
|
+
return { text: formatCodexStatus(await deps.readCodexStatusProbes(options.pluginConfig, ctx.config)) };
|
|
112
|
+
}
|
|
113
|
+
if (normalized === "models") {
|
|
114
|
+
if (rest.length > 0) return { text: "Usage: /codex models" };
|
|
115
|
+
return { text: formatModels(await deps.listCodexAppServerModels(deps.requestOptions(options.pluginConfig, 100, ctx.config))) };
|
|
116
|
+
}
|
|
222
117
|
if (normalized === "threads") return { text: await buildThreads(deps, options.pluginConfig, rest.join(" ")) };
|
|
223
|
-
if (normalized === "resume") return { text: await resumeThread(deps, ctx, options.pluginConfig, rest
|
|
118
|
+
if (normalized === "resume") return { text: await resumeThread(deps, ctx, options.pluginConfig, rest) };
|
|
224
119
|
if (normalized === "bind") return await bindConversation(deps, ctx, options.pluginConfig, rest);
|
|
225
|
-
if (normalized === "detach" || normalized === "unbind")
|
|
226
|
-
|
|
227
|
-
|
|
120
|
+
if (normalized === "detach" || normalized === "unbind") {
|
|
121
|
+
if (rest.length > 0) return { text: "Usage: /codex detach" };
|
|
122
|
+
return { text: await detachConversation(deps, ctx) };
|
|
123
|
+
}
|
|
124
|
+
if (normalized === "binding") {
|
|
125
|
+
if (rest.length > 0) return { text: "Usage: /codex binding" };
|
|
126
|
+
return { text: await describeConversationBinding(deps, ctx) };
|
|
127
|
+
}
|
|
128
|
+
if (normalized === "stop") {
|
|
129
|
+
if (rest.length > 0) return { text: "Usage: /codex stop" };
|
|
130
|
+
return { text: await stopConversationTurn(deps, ctx, options.pluginConfig) };
|
|
131
|
+
}
|
|
228
132
|
if (normalized === "steer") return { text: await steerConversationTurn(deps, ctx, options.pluginConfig, rest.join(" ")) };
|
|
229
|
-
if (normalized === "model") return { text: await setConversationModel(deps, ctx, options.pluginConfig, rest
|
|
230
|
-
if (normalized === "fast") return { text: await setConversationFastMode(deps, ctx, options.pluginConfig, rest
|
|
231
|
-
if (normalized === "permissions") return { text: await setConversationPermissions(deps, ctx, options.pluginConfig, rest
|
|
232
|
-
if (normalized === "compact") return { text: await startThreadAction(deps, ctx, options.pluginConfig, CODEX_CONTROL_METHODS.compact, "compaction") };
|
|
233
|
-
if (normalized === "review") return { text: await startThreadAction(deps, ctx, options.pluginConfig, CODEX_CONTROL_METHODS.review, "review") };
|
|
133
|
+
if (normalized === "model") return { text: await setConversationModel(deps, ctx, options.pluginConfig, rest) };
|
|
134
|
+
if (normalized === "fast") return { text: await setConversationFastMode(deps, ctx, options.pluginConfig, rest) };
|
|
135
|
+
if (normalized === "permissions") return { text: await setConversationPermissions(deps, ctx, options.pluginConfig, rest) };
|
|
136
|
+
if (normalized === "compact") return { text: await startThreadAction(deps, ctx, options.pluginConfig, CODEX_CONTROL_METHODS.compact, "compaction", rest) };
|
|
137
|
+
if (normalized === "review") return { text: await startThreadAction(deps, ctx, options.pluginConfig, CODEX_CONTROL_METHODS.review, "review", rest) };
|
|
234
138
|
if (normalized === "diagnostics") return await handleCodexDiagnosticsFeedback(deps, ctx, options.pluginConfig, rest.join(" "), "/codex diagnostics");
|
|
235
139
|
if (normalized === "computer-use" || normalized === "computeruse") return { text: await handleComputerUseCommand(deps, options.pluginConfig, rest) };
|
|
236
|
-
if (normalized === "mcp")
|
|
237
|
-
|
|
140
|
+
if (normalized === "mcp") {
|
|
141
|
+
if (rest.length > 0) return { text: "Usage: /codex mcp" };
|
|
142
|
+
return { text: formatList(await deps.codexControlRequest(options.pluginConfig, CODEX_CONTROL_METHODS.listMcpServers, { limit: 100 }), "MCP servers") };
|
|
143
|
+
}
|
|
144
|
+
if (normalized === "skills") {
|
|
145
|
+
if (rest.length > 0) return { text: "Usage: /codex skills" };
|
|
146
|
+
return { text: formatList(await deps.codexControlRequest(options.pluginConfig, CODEX_CONTROL_METHODS.listSkills, {}), "Codex skills") };
|
|
147
|
+
}
|
|
238
148
|
if (normalized === "account") {
|
|
149
|
+
if (rest.length > 0) return { text: "Usage: /codex account" };
|
|
239
150
|
const [account, limits] = await Promise.all([deps.safeCodexControlRequest(options.pluginConfig, CODEX_CONTROL_METHODS.account, { refreshToken: false }), deps.safeCodexControlRequest(options.pluginConfig, CODEX_CONTROL_METHODS.rateLimits, void 0)]);
|
|
151
|
+
if (limits.ok) rememberCodexRateLimits(limits.value);
|
|
240
152
|
return { text: formatAccount(account, limits) };
|
|
241
153
|
}
|
|
242
|
-
return { text: `Unknown Codex command: ${subcommand}\n\n${buildHelp()}` };
|
|
154
|
+
return { text: `Unknown Codex command: ${formatCodexDisplayText(subcommand)}\n\n${buildHelp()}` };
|
|
243
155
|
}
|
|
244
156
|
async function handleComputerUseCommand(deps, pluginConfig, args) {
|
|
245
157
|
const parsed = parseComputerUseArgs(args);
|
|
@@ -253,9 +165,9 @@ async function handleComputerUseCommand(deps, pluginConfig, args) {
|
|
|
253
165
|
return formatComputerUseStatus(await deps.readCodexComputerUseStatus(params));
|
|
254
166
|
}
|
|
255
167
|
async function bindConversation(deps, ctx, pluginConfig, args) {
|
|
256
|
-
if (!ctx.sessionFile) return { text: "Cannot bind Codex because this command did not include an OpenClaw session file." };
|
|
257
168
|
const parsed = parseBindArgs(args);
|
|
258
169
|
if (parsed.help) return { text: "Usage: /codex bind [thread-id] [--cwd <path>] [--model <model>] [--provider <provider>]" };
|
|
170
|
+
if (!ctx.sessionFile) return { text: "Cannot bind Codex because this command did not include an OpenClaw session file." };
|
|
259
171
|
const workspaceDir = parsed.cwd ?? deps.resolveCodexDefaultWorkspaceDir(pluginConfig);
|
|
260
172
|
const authProfileId = (await deps.readCodexAppServerBinding(ctx.sessionFile))?.authProfileId;
|
|
261
173
|
const startParams = {
|
|
@@ -270,7 +182,7 @@ async function bindConversation(deps, ctx, pluginConfig, args) {
|
|
|
270
182
|
if (authProfileId) startParams.authProfileId = authProfileId;
|
|
271
183
|
const data = await deps.startCodexConversationThread(startParams);
|
|
272
184
|
const threadId = (await deps.readCodexAppServerBinding(ctx.sessionFile))?.threadId ?? parsed.threadId ?? "new thread";
|
|
273
|
-
const summary = `Codex app-server thread ${threadId} in ${workspaceDir}`;
|
|
185
|
+
const summary = `Codex app-server thread ${formatCodexDisplayText(threadId)} in ${formatCodexDisplayText(workspaceDir)}`;
|
|
274
186
|
let request;
|
|
275
187
|
try {
|
|
276
188
|
request = await ctx.requestConversationBinding({
|
|
@@ -282,10 +194,10 @@ async function bindConversation(deps, ctx, pluginConfig, args) {
|
|
|
282
194
|
await deps.clearCodexAppServerBinding(ctx.sessionFile);
|
|
283
195
|
throw error;
|
|
284
196
|
}
|
|
285
|
-
if (request.status === "bound") return { text: `Bound this conversation to Codex thread ${threadId} in ${workspaceDir}.` };
|
|
197
|
+
if (request.status === "bound") return { text: `Bound this conversation to Codex thread ${formatCodexDisplayText(threadId)} in ${formatCodexDisplayText(workspaceDir)}.` };
|
|
286
198
|
if (request.status === "pending") return request.reply;
|
|
287
199
|
await deps.clearCodexAppServerBinding(ctx.sessionFile);
|
|
288
|
-
return { text: request.message };
|
|
200
|
+
return { text: formatCodexDisplayText(request.message) };
|
|
289
201
|
}
|
|
290
202
|
async function detachConversation(deps, ctx) {
|
|
291
203
|
const data = readCodexConversationBindingData(await ctx.getCurrentConversationBinding());
|
|
@@ -302,13 +214,13 @@ async function describeConversationBinding(deps, ctx) {
|
|
|
302
214
|
const active = deps.readCodexConversationActiveTurn(data.sessionFile);
|
|
303
215
|
return [
|
|
304
216
|
"Codex conversation binding:",
|
|
305
|
-
`- Thread: ${threadBinding?.threadId ?? "unknown"}`,
|
|
306
|
-
`- Workspace: ${data.workspaceDir}`,
|
|
307
|
-
`- Model: ${threadBinding?.model ?? "default"}`,
|
|
217
|
+
`- Thread: ${formatCodexDisplayText(threadBinding?.threadId ?? "unknown")}`,
|
|
218
|
+
`- Workspace: ${formatCodexDisplayText(data.workspaceDir)}`,
|
|
219
|
+
`- Model: ${formatCodexDisplayText(threadBinding?.model ?? "default")}`,
|
|
308
220
|
`- Fast: ${threadBinding?.serviceTier === "fast" ? "on" : "off"}`,
|
|
309
221
|
`- Permissions: ${threadBinding ? formatPermissionsMode(threadBinding) : "default"}`,
|
|
310
|
-
`- Active run: ${active ? active.turnId : "none"}`,
|
|
311
|
-
`- Session: ${data.sessionFile}`
|
|
222
|
+
`- Active run: ${formatCodexDisplayText(active ? active.turnId : "none")}`,
|
|
223
|
+
`- Session: ${formatCodexDisplayText(data.sessionFile)}`
|
|
312
224
|
].join("\n");
|
|
313
225
|
}
|
|
314
226
|
async function buildThreads(deps, pluginConfig, filter) {
|
|
@@ -317,9 +229,10 @@ async function buildThreads(deps, pluginConfig, filter) {
|
|
|
317
229
|
...filter.trim() ? { searchTerm: filter.trim() } : {}
|
|
318
230
|
}));
|
|
319
231
|
}
|
|
320
|
-
async function resumeThread(deps, ctx, pluginConfig,
|
|
232
|
+
async function resumeThread(deps, ctx, pluginConfig, args) {
|
|
233
|
+
const [threadId] = args;
|
|
321
234
|
const normalizedThreadId = threadId?.trim();
|
|
322
|
-
if (!normalizedThreadId) return "Usage: /codex resume <thread-id>";
|
|
235
|
+
if (!normalizedThreadId || args.length !== 1) return "Usage: /codex resume <thread-id>";
|
|
323
236
|
if (!ctx.sessionFile) return "Cannot attach a Codex thread because this command did not include an OpenClaw session file.";
|
|
324
237
|
const response = await deps.codexControlRequest(pluginConfig, CODEX_CONTROL_METHODS.resumeThread, {
|
|
325
238
|
threadId: normalizedThreadId,
|
|
@@ -333,7 +246,7 @@ async function resumeThread(deps, ctx, pluginConfig, threadId) {
|
|
|
333
246
|
model: isJsonObject(response) ? readString(response, "model") : void 0,
|
|
334
247
|
modelProvider: isJsonObject(response) ? readString(response, "modelProvider") : void 0
|
|
335
248
|
});
|
|
336
|
-
return `Attached this OpenClaw session to Codex thread ${effectiveThreadId}.`;
|
|
249
|
+
return `Attached this OpenClaw session to Codex thread ${formatCodexDisplayText(effectiveThreadId)}.`;
|
|
337
250
|
}
|
|
338
251
|
async function stopConversationTurn(deps, ctx, pluginConfig) {
|
|
339
252
|
const sessionFile = await resolveControlSessionFile(ctx);
|
|
@@ -352,13 +265,15 @@ async function steerConversationTurn(deps, ctx, pluginConfig, message) {
|
|
|
352
265
|
message
|
|
353
266
|
})).message;
|
|
354
267
|
}
|
|
355
|
-
async function setConversationModel(deps, ctx, pluginConfig,
|
|
268
|
+
async function setConversationModel(deps, ctx, pluginConfig, args) {
|
|
269
|
+
if (args.length > 1) return "Usage: /codex model <model>";
|
|
356
270
|
const sessionFile = await resolveControlSessionFile(ctx);
|
|
357
271
|
if (!sessionFile) return "Cannot set Codex model because this command did not include an OpenClaw session file.";
|
|
272
|
+
const [model = ""] = args;
|
|
358
273
|
const normalized = model.trim();
|
|
359
274
|
if (!normalized) {
|
|
360
275
|
const binding = await deps.readCodexAppServerBinding(sessionFile);
|
|
361
|
-
return binding?.model ? `Codex model: ${binding.model}` : "Usage: /codex model <model>";
|
|
276
|
+
return binding?.model ? `Codex model: ${formatCodexDisplayText(binding.model)}` : "Usage: /codex model <model>";
|
|
362
277
|
}
|
|
363
278
|
return await deps.setCodexConversationModel({
|
|
364
279
|
sessionFile,
|
|
@@ -366,9 +281,11 @@ async function setConversationModel(deps, ctx, pluginConfig, model) {
|
|
|
366
281
|
model: normalized
|
|
367
282
|
});
|
|
368
283
|
}
|
|
369
|
-
async function setConversationFastMode(deps, ctx, pluginConfig,
|
|
284
|
+
async function setConversationFastMode(deps, ctx, pluginConfig, args) {
|
|
285
|
+
if (args.length > 1) return "Usage: /codex fast [on|off|status]";
|
|
370
286
|
const sessionFile = await resolveControlSessionFile(ctx);
|
|
371
287
|
if (!sessionFile) return "Cannot set Codex fast mode because this command did not include an OpenClaw session file.";
|
|
288
|
+
const value = args[0];
|
|
372
289
|
const parsed = parseCodexFastModeArg(value);
|
|
373
290
|
if (value && parsed == null && value.trim().toLowerCase() !== "status") return "Usage: /codex fast [on|off|status]";
|
|
374
291
|
return await deps.setCodexConversationFastMode({
|
|
@@ -377,9 +294,11 @@ async function setConversationFastMode(deps, ctx, pluginConfig, value) {
|
|
|
377
294
|
enabled: parsed
|
|
378
295
|
});
|
|
379
296
|
}
|
|
380
|
-
async function setConversationPermissions(deps, ctx, pluginConfig,
|
|
297
|
+
async function setConversationPermissions(deps, ctx, pluginConfig, args) {
|
|
298
|
+
if (args.length > 1) return "Usage: /codex permissions [default|yolo|status]";
|
|
381
299
|
const sessionFile = await resolveControlSessionFile(ctx);
|
|
382
300
|
if (!sessionFile) return "Cannot set Codex permissions because this command did not include an OpenClaw session file.";
|
|
301
|
+
const value = args[0];
|
|
383
302
|
const parsed = parseCodexPermissionsModeArg(value);
|
|
384
303
|
if (value && !parsed && value.trim().toLowerCase() !== "status") return "Usage: /codex permissions [default|yolo|status]";
|
|
385
304
|
return await deps.setCodexConversationPermissions({
|
|
@@ -394,6 +313,7 @@ async function resolveControlSessionFile(ctx) {
|
|
|
394
313
|
async function handleCodexDiagnosticsFeedback(deps, ctx, pluginConfig, args, commandPrefix) {
|
|
395
314
|
if (ctx.senderIsOwner !== true) return { text: "Only an owner can send Codex diagnostics." };
|
|
396
315
|
const parsed = parseDiagnosticsArgs(args);
|
|
316
|
+
if (parsed.action === "usage") return { text: formatDiagnosticsUsage(commandPrefix) };
|
|
397
317
|
if (parsed.action === "confirm") return { text: await confirmCodexDiagnosticsFeedback(deps, ctx, pluginConfig, parsed.token) };
|
|
398
318
|
if (parsed.action === "cancel") return { text: cancelCodexDiagnosticsFeedback(ctx, parsed.token) };
|
|
399
319
|
if (ctx.diagnosticsUploadApproved === true) return { text: await sendCodexDiagnosticsFeedbackForContext(deps, ctx, pluginConfig, parsed.note) };
|
|
@@ -640,21 +560,29 @@ function normalizeDiagnosticsReason(note) {
|
|
|
640
560
|
return normalized ? normalized.slice(0, CODEX_DIAGNOSTICS_REASON_MAX_CHARS) : void 0;
|
|
641
561
|
}
|
|
642
562
|
function parseDiagnosticsArgs(args) {
|
|
643
|
-
const [action, token] = splitArgs(args);
|
|
563
|
+
const [action, token, ...extra] = splitArgs(args);
|
|
644
564
|
const normalizedAction = action?.toLowerCase();
|
|
645
|
-
if ((normalizedAction === "confirm" || normalizedAction === "--confirm") && token) return {
|
|
565
|
+
if ((normalizedAction === "confirm" || normalizedAction === "--confirm") && token && extra.length === 0) return {
|
|
646
566
|
action: "confirm",
|
|
647
567
|
token
|
|
648
568
|
};
|
|
649
|
-
if ((normalizedAction === "cancel" || normalizedAction === "--cancel") && token) return {
|
|
569
|
+
if ((normalizedAction === "cancel" || normalizedAction === "--cancel") && token && extra.length === 0) return {
|
|
650
570
|
action: "cancel",
|
|
651
571
|
token
|
|
652
572
|
};
|
|
573
|
+
if (normalizedAction === "confirm" || normalizedAction === "--confirm" || normalizedAction === "cancel" || normalizedAction === "--cancel") return { action: "usage" };
|
|
653
574
|
return {
|
|
654
575
|
action: "request",
|
|
655
576
|
note: args
|
|
656
577
|
};
|
|
657
578
|
}
|
|
579
|
+
function formatDiagnosticsUsage(commandPrefix) {
|
|
580
|
+
return [
|
|
581
|
+
`Usage: ${commandPrefix} [note]`,
|
|
582
|
+
`Usage: ${commandPrefix} confirm <token>`,
|
|
583
|
+
`Usage: ${commandPrefix} cancel <token>`
|
|
584
|
+
].join("\n");
|
|
585
|
+
}
|
|
658
586
|
function createCodexDiagnosticsConfirmation(params) {
|
|
659
587
|
prunePendingCodexDiagnosticsConfirmations(params.now);
|
|
660
588
|
if (!pendingCodexDiagnosticsConfirmationTokensByScope.has(params.scopeKey) && pendingCodexDiagnosticsConfirmationTokensByScope.size >= CODEX_DIAGNOSTICS_CONFIRMATION_MAX_SCOPES) {
|
|
@@ -848,7 +776,8 @@ function normalizeCodexDiagnosticsScopeField(value) {
|
|
|
848
776
|
if (normalized.length <= CODEX_DIAGNOSTICS_SCOPE_FIELD_MAX_CHARS) return normalized;
|
|
849
777
|
return `sha256:${crypto.createHash("sha256").update(normalized).digest("hex")}`;
|
|
850
778
|
}
|
|
851
|
-
async function startThreadAction(deps, ctx, pluginConfig, method, label) {
|
|
779
|
+
async function startThreadAction(deps, ctx, pluginConfig, method, label, args) {
|
|
780
|
+
if (args.length > 0) return `Usage: /codex ${label === "compaction" ? "compact" : label}`;
|
|
852
781
|
const sessionFile = await resolveControlSessionFile(ctx);
|
|
853
782
|
if (!sessionFile) return `Cannot start Codex ${label} because this command did not include an OpenClaw session file.`;
|
|
854
783
|
const binding = await deps.readCodexAppServerBinding(sessionFile);
|
|
@@ -858,10 +787,52 @@ async function startThreadAction(deps, ctx, pluginConfig, method, label) {
|
|
|
858
787
|
target: { type: "uncommittedChanges" }
|
|
859
788
|
});
|
|
860
789
|
else await deps.codexControlRequest(pluginConfig, method, { threadId: binding.threadId });
|
|
861
|
-
return `Started Codex ${label} for thread ${binding.threadId}.`;
|
|
790
|
+
return `Started Codex ${label} for thread ${formatCodexDisplayText(binding.threadId)}.`;
|
|
862
791
|
}
|
|
863
792
|
function splitArgs(value) {
|
|
864
|
-
|
|
793
|
+
const input = value ?? "";
|
|
794
|
+
const args = [];
|
|
795
|
+
let current = "";
|
|
796
|
+
let quote;
|
|
797
|
+
let escaping = false;
|
|
798
|
+
let tokenStarted = false;
|
|
799
|
+
for (const char of input) {
|
|
800
|
+
if (escaping) {
|
|
801
|
+
current += char;
|
|
802
|
+
escaping = false;
|
|
803
|
+
tokenStarted = true;
|
|
804
|
+
continue;
|
|
805
|
+
}
|
|
806
|
+
if (char === "\\" && quote !== "'") {
|
|
807
|
+
escaping = true;
|
|
808
|
+
tokenStarted = true;
|
|
809
|
+
continue;
|
|
810
|
+
}
|
|
811
|
+
if (quote) {
|
|
812
|
+
if (char === quote) quote = void 0;
|
|
813
|
+
else current += char;
|
|
814
|
+
tokenStarted = true;
|
|
815
|
+
continue;
|
|
816
|
+
}
|
|
817
|
+
if (char === "\"" || char === "'") {
|
|
818
|
+
quote = char;
|
|
819
|
+
tokenStarted = true;
|
|
820
|
+
continue;
|
|
821
|
+
}
|
|
822
|
+
if (/\s/.test(char)) {
|
|
823
|
+
if (tokenStarted) {
|
|
824
|
+
args.push(current);
|
|
825
|
+
current = "";
|
|
826
|
+
tokenStarted = false;
|
|
827
|
+
}
|
|
828
|
+
continue;
|
|
829
|
+
}
|
|
830
|
+
current += char;
|
|
831
|
+
tokenStarted = true;
|
|
832
|
+
}
|
|
833
|
+
if (escaping) current += "\\";
|
|
834
|
+
if (tokenStarted) args.push(current);
|
|
835
|
+
return args;
|
|
865
836
|
}
|
|
866
837
|
function parseBindArgs(args) {
|
|
867
838
|
const parsed = {};
|
|
@@ -872,17 +843,32 @@ function parseBindArgs(args) {
|
|
|
872
843
|
continue;
|
|
873
844
|
}
|
|
874
845
|
if (arg === "--cwd") {
|
|
875
|
-
|
|
846
|
+
const value = readRequiredOptionValue(args, index);
|
|
847
|
+
if (!value || parsed.cwd !== void 0) {
|
|
848
|
+
parsed.help = true;
|
|
849
|
+
continue;
|
|
850
|
+
}
|
|
851
|
+
parsed.cwd = value;
|
|
876
852
|
index += 1;
|
|
877
853
|
continue;
|
|
878
854
|
}
|
|
879
855
|
if (arg === "--model") {
|
|
880
|
-
|
|
856
|
+
const value = readRequiredOptionValue(args, index);
|
|
857
|
+
if (!value || parsed.model !== void 0) {
|
|
858
|
+
parsed.help = true;
|
|
859
|
+
continue;
|
|
860
|
+
}
|
|
861
|
+
parsed.model = value;
|
|
881
862
|
index += 1;
|
|
882
863
|
continue;
|
|
883
864
|
}
|
|
884
865
|
if (arg === "--provider" || arg === "--model-provider") {
|
|
885
|
-
|
|
866
|
+
const value = readRequiredOptionValue(args, index);
|
|
867
|
+
if (!value || parsed.provider !== void 0) {
|
|
868
|
+
parsed.help = true;
|
|
869
|
+
continue;
|
|
870
|
+
}
|
|
871
|
+
parsed.provider = value;
|
|
886
872
|
index += 1;
|
|
887
873
|
continue;
|
|
888
874
|
}
|
|
@@ -904,6 +890,7 @@ function parseComputerUseArgs(args) {
|
|
|
904
890
|
overrides: {},
|
|
905
891
|
hasOverrides: false
|
|
906
892
|
};
|
|
893
|
+
let sawAction = false;
|
|
907
894
|
for (let index = 0; index < args.length; index += 1) {
|
|
908
895
|
const arg = args[index];
|
|
909
896
|
if (arg === "--help" || arg === "-h") {
|
|
@@ -911,12 +898,17 @@ function parseComputerUseArgs(args) {
|
|
|
911
898
|
continue;
|
|
912
899
|
}
|
|
913
900
|
if (arg === "status" || arg === "install") {
|
|
901
|
+
if (sawAction) {
|
|
902
|
+
parsed.help = true;
|
|
903
|
+
continue;
|
|
904
|
+
}
|
|
905
|
+
sawAction = true;
|
|
914
906
|
parsed.action = arg;
|
|
915
907
|
continue;
|
|
916
908
|
}
|
|
917
909
|
if (arg === "--source" || arg === "--marketplace-source") {
|
|
918
910
|
const value = readRequiredOptionValue(args, index);
|
|
919
|
-
if (!value) {
|
|
911
|
+
if (!value || parsed.overrides.marketplaceSource !== void 0) {
|
|
920
912
|
parsed.help = true;
|
|
921
913
|
continue;
|
|
922
914
|
}
|
|
@@ -926,7 +918,7 @@ function parseComputerUseArgs(args) {
|
|
|
926
918
|
}
|
|
927
919
|
if (arg === "--marketplace-path" || arg === "--path") {
|
|
928
920
|
const value = readRequiredOptionValue(args, index);
|
|
929
|
-
if (!value) {
|
|
921
|
+
if (!value || parsed.overrides.marketplacePath !== void 0) {
|
|
930
922
|
parsed.help = true;
|
|
931
923
|
continue;
|
|
932
924
|
}
|
|
@@ -936,7 +928,7 @@ function parseComputerUseArgs(args) {
|
|
|
936
928
|
}
|
|
937
929
|
if (arg === "--marketplace") {
|
|
938
930
|
const value = readRequiredOptionValue(args, index);
|
|
939
|
-
if (!value) {
|
|
931
|
+
if (!value || parsed.overrides.marketplaceName !== void 0) {
|
|
940
932
|
parsed.help = true;
|
|
941
933
|
continue;
|
|
942
934
|
}
|
|
@@ -946,7 +938,7 @@ function parseComputerUseArgs(args) {
|
|
|
946
938
|
}
|
|
947
939
|
if (arg === "--plugin") {
|
|
948
940
|
const value = readRequiredOptionValue(args, index);
|
|
949
|
-
if (!value) {
|
|
941
|
+
if (!value || parsed.overrides.pluginName !== void 0) {
|
|
950
942
|
parsed.help = true;
|
|
951
943
|
continue;
|
|
952
944
|
}
|
|
@@ -956,7 +948,7 @@ function parseComputerUseArgs(args) {
|
|
|
956
948
|
}
|
|
957
949
|
if (arg === "--server" || arg === "--mcp-server") {
|
|
958
950
|
const value = readRequiredOptionValue(args, index);
|
|
959
|
-
if (!value) {
|
|
951
|
+
if (!value || parsed.overrides.mcpServerName !== void 0) {
|
|
960
952
|
parsed.help = true;
|
|
961
953
|
continue;
|
|
962
954
|
}
|
|
@@ -972,7 +964,8 @@ function parseComputerUseArgs(args) {
|
|
|
972
964
|
}
|
|
973
965
|
function readRequiredOptionValue(args, index) {
|
|
974
966
|
const value = args[index + 1];
|
|
975
|
-
|
|
967
|
+
const normalized = value?.trim();
|
|
968
|
+
if (!normalized || normalized.startsWith("-")) return;
|
|
976
969
|
return value;
|
|
977
970
|
}
|
|
978
971
|
function normalizeComputerUseStringOverrides(overrides) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { i as resolveCodexAppServerRuntimeOptions } from "./config-
|
|
1
|
+
import { i as resolveCodexAppServerRuntimeOptions } from "./config-ByrA30No.js";
|
|
2
2
|
import { t as isJsonObject } from "./protocol-C9UWI98H.js";
|
|
3
3
|
import { i as readCodexAppServerBinding } from "./session-binding-DuJYTJQy.js";
|
|
4
|
-
import { n as defaultCodexAppServerClientFactory, t as createCodexAppServerClientFactoryTestHooks } from "./client-factory
|
|
4
|
+
import { n as defaultCodexAppServerClientFactory, t as createCodexAppServerClientFactoryTestHooks } from "./client-factory--cll1Fba.js";
|
|
5
5
|
import { embeddedAgentLog, formatErrorMessage, isActiveHarnessContextEngine, runHarnessContextEngineMaintenance } from "openclaw/plugin-sdk/agent-harness-runtime";
|
|
6
6
|
//#region extensions/codex/src/app-server/compact.ts
|
|
7
7
|
const DEFAULT_CODEX_COMPACTION_WAIT_TIMEOUT_MS = 300 * 1e3;
|
|
@@ -65,7 +65,7 @@ async function maybeCompactCodexAppServerSession(params, options = {}) {
|
|
|
65
65
|
}
|
|
66
66
|
async function compactCodexNativeThread(params, options = {}) {
|
|
67
67
|
const appServer = resolveCodexAppServerRuntimeOptions({ pluginConfig: options.pluginConfig });
|
|
68
|
-
const binding = await readCodexAppServerBinding(params.sessionFile);
|
|
68
|
+
const binding = await readCodexAppServerBinding(params.sessionFile, { config: params.config });
|
|
69
69
|
if (!binding?.threadId) return {
|
|
70
70
|
ok: false,
|
|
71
71
|
compacted: false,
|
|
@@ -77,7 +77,7 @@ async function compactCodexNativeThread(params, options = {}) {
|
|
|
77
77
|
compacted: false,
|
|
78
78
|
reason: "auth profile mismatch for session binding"
|
|
79
79
|
};
|
|
80
|
-
const client = await clientFactory(appServer.start, requestedAuthProfileId ?? binding.authProfileId, params.agentDir);
|
|
80
|
+
const client = await clientFactory(appServer.start, requestedAuthProfileId ?? binding.authProfileId, params.agentDir, params.config);
|
|
81
81
|
const waiter = createCodexNativeCompactionWaiter(client, binding.threadId);
|
|
82
82
|
let completion;
|
|
83
83
|
try {
|
|
@@ -139,13 +139,11 @@ function codexSandboxPolicyForTurn(mode, cwd) {
|
|
|
139
139
|
if (mode === "danger-full-access") return { type: "dangerFullAccess" };
|
|
140
140
|
if (mode === "read-only") return {
|
|
141
141
|
type: "readOnly",
|
|
142
|
-
access: { type: "fullAccess" },
|
|
143
142
|
networkAccess: false
|
|
144
143
|
};
|
|
145
144
|
return {
|
|
146
145
|
type: "workspaceWrite",
|
|
147
146
|
writableRoots: [cwd],
|
|
148
|
-
readOnlyAccess: { type: "fullAccess" },
|
|
149
147
|
networkAccess: false,
|
|
150
148
|
excludeTmpdirEnvVar: false,
|
|
151
149
|
excludeSlashTmp: false
|