@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.
@@ -1,155 +1,44 @@
1
- import { i as resolveCodexAppServerRuntimeOptions } from "./config-CkkoMeqF.js";
2
- import { n as listCodexAppServerModels, t as listAllCodexAppServerModels } from "./models-Ds7g6191.js";
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 { n as describeControlFailure, t as CODEX_CONTROL_METHODS } from "./capabilities-BmhO5h8O.js";
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-DjptpT9W.js";
7
- import { i as requestCodexAppServerJson, n as installCodexComputerUse, r as readCodexComputerUseStatus } from "./computer-use-amNk2zrB.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-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") return { text: formatCodexStatus(await deps.readCodexStatusProbes(options.pluginConfig)) };
221
- if (normalized === "models") return { text: formatModels(await deps.listCodexAppServerModels(deps.requestOptions(options.pluginConfig, 100))) };
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[0]) };
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") return { text: await detachConversation(deps, ctx) };
226
- if (normalized === "binding") return { text: await describeConversationBinding(deps, ctx) };
227
- if (normalized === "stop") return { text: await stopConversationTurn(deps, ctx, options.pluginConfig) };
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.join(" ")) };
230
- if (normalized === "fast") return { text: await setConversationFastMode(deps, ctx, options.pluginConfig, rest[0]) };
231
- if (normalized === "permissions") return { text: await setConversationPermissions(deps, ctx, options.pluginConfig, rest[0]) };
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") return { text: formatList(await deps.codexControlRequest(options.pluginConfig, CODEX_CONTROL_METHODS.listMcpServers, { limit: 100 }), "MCP servers") };
237
- if (normalized === "skills") return { text: formatList(await deps.codexControlRequest(options.pluginConfig, CODEX_CONTROL_METHODS.listSkills, {}), "Codex skills") };
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, threadId) {
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, model) {
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, value) {
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, value) {
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
- return (value ?? "").trim().split(/\s+/).filter(Boolean);
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
- parsed.cwd = args[index + 1];
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
- parsed.model = args[index + 1];
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
- parsed.provider = args[index + 1];
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
- if (!value || value.startsWith("-")) return;
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-CkkoMeqF.js";
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-MaOMEltT.js";
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