@openclaw/codex 2026.5.10-beta.2 → 2026.5.10-beta.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (25) hide show
  1. package/dist/{client-CTzy3Y6M.js → client-CpksBQ9l.js} +1 -1
  2. package/dist/{client-factory-BJL_efz4.js → client-factory-D2P0KD6r.js} +1 -1
  3. package/dist/{request-DC1Dz3iZ.js → command-formatters-Ttwc_kgX.js} +192 -57
  4. package/dist/{command-handlers-BLZCm3fD.js → command-handlers-iLF1EI-b.js} +306 -15
  5. package/dist/{compact-4FVe6NwI.js → compact-BJ1UYEyA.js} +3 -3
  6. package/dist/{rate-limit-cache-DbZvmrAD.js → computer-use-CVLaKaW3.js} +3 -26
  7. package/dist/{config-CT01BBDc.js → config-C7xdbzrp.js} +1 -1
  8. package/dist/{conversation-binding-FqeYliIk.js → conversation-binding-D4XZ-tvV.js} +5 -4
  9. package/dist/harness.js +8 -4
  10. package/dist/index.js +11 -6
  11. package/dist/media-understanding-provider.js +142 -41
  12. package/dist/{models-H-PTi3W0.js → models-Bg-Qf5s-.js} +2 -2
  13. package/dist/{plugin-activation-CweAZa7r.js → plugin-activation-C0soz2YD.js} +1 -1
  14. package/dist/{protocol-validators-CeCyJaWj.js → protocol-validators-CSY0BFBo.js} +4 -1
  15. package/dist/provider.js +2 -2
  16. package/dist/rate-limit-cache-dvhq-4pi.js +24 -0
  17. package/dist/request-BCAfJvSg.js +41 -0
  18. package/dist/{run-attempt-CefRS5_d.js → run-attempt-DZvighJE.js} +548 -1053
  19. package/dist/{session-binding-B44KIZM2.js → session-binding-UFKjHkKJ.js} +13 -4
  20. package/dist/{shared-client-p-TvEiNL.js → shared-client-K13b0L1X.js} +78 -13
  21. package/dist/side-question-Dh_g53P9.js +548 -0
  22. package/dist/test-api.js +2 -2
  23. package/dist/{thread-lifecycle-CGc-O_5d.js → thread-lifecycle-i42nWiSS.js} +18 -11
  24. package/dist/vision-tools-Bo0P6gwM.js +1008 -0
  25. package/package.json +7 -6
@@ -1,4 +1,4 @@
1
- import { s as resolveCodexAppServerRuntimeOptions } from "./config-CT01BBDc.js";
1
+ import { s as resolveCodexAppServerRuntimeOptions } from "./config-C7xdbzrp.js";
2
2
  import { n as isRpcResponse } from "./protocol-C9UWI98H.js";
3
3
  import { createInterface } from "node:readline";
4
4
  import { OPENCLAW_VERSION, embeddedAgentLog } from "openclaw/plugin-sdk/agent-harness-runtime";
@@ -1,5 +1,5 @@
1
1
  //#region extensions/codex/src/app-server/client-factory.ts
2
- const defaultCodexAppServerClientFactory = (startOptions, authProfileId, agentDir, config) => import("./shared-client-p-TvEiNL.js").then((n) => n.r).then(({ getSharedCodexAppServerClient }) => getSharedCodexAppServerClient({
2
+ const defaultCodexAppServerClientFactory = (startOptions, authProfileId, agentDir, config) => import("./shared-client-K13b0L1X.js").then((n) => n.i).then(({ getSharedCodexAppServerClient }) => getSharedCodexAppServerClient({
3
3
  startOptions,
4
4
  authProfileId,
5
5
  agentDir,
@@ -1,26 +1,4 @@
1
1
  import { t as isJsonObject } from "./protocol-C9UWI98H.js";
2
- import { n as CodexAppServerRpcError } from "./client-CTzy3Y6M.js";
3
- import { i as withTimeout, n as getSharedCodexAppServerClient } from "./shared-client-p-TvEiNL.js";
4
- //#region extensions/codex/src/app-server/capabilities.ts
5
- const CODEX_CONTROL_METHODS = {
6
- account: "account/read",
7
- compact: "thread/compact/start",
8
- feedback: "feedback/upload",
9
- listMcpServers: "mcpServerStatus/list",
10
- listSkills: "skills/list",
11
- listThreads: "thread/list",
12
- rateLimits: "account/rateLimits/read",
13
- resumeThread: "thread/resume",
14
- review: "review/start"
15
- };
16
- function describeControlFailure(error) {
17
- if (isUnsupportedControlError(error)) return "unsupported by this Codex app-server";
18
- return error instanceof Error ? error.message : String(error);
19
- }
20
- function isUnsupportedControlError(error) {
21
- return error instanceof CodexAppServerRpcError && error.code === -32601;
22
- }
23
- //#endregion
24
2
  //#region extensions/codex/src/app-server/rate-limits.ts
25
3
  const CODEX_LIMIT_ID = "codex";
26
4
  const LIMIT_WINDOW_KEYS = ["primary", "secondary"];
@@ -34,15 +12,53 @@ function formatCodexUsageLimitErrorMessage(params) {
34
12
  const nextReset = selectNextRateLimitReset(params.rateLimits, nowMs);
35
13
  const parts = ["You've reached your Codex subscription usage limit."];
36
14
  if (nextReset) parts.push(`Next reset ${formatResetTime(nextReset.resetsAtMs, nowMs)}.`);
37
- else parts.push("Codex did not return a reset time for this limit.");
15
+ else {
16
+ const codexRetryHint = extractCodexRetryHint(message);
17
+ if (codexRetryHint) parts.push(`Codex says to try again ${codexRetryHint}.`);
18
+ else parts.push("Codex did not return a reset time for this limit.");
19
+ }
38
20
  parts.push("Run /codex account for current usage details.");
39
21
  return parts.join(" ");
40
22
  }
23
+ function shouldRefreshCodexRateLimitsForUsageLimitMessage(message) {
24
+ const text = normalizeText(message);
25
+ return Boolean(text?.includes("You've reached your Codex subscription usage limit.") && !text.includes("Next reset "));
26
+ }
41
27
  function summarizeCodexRateLimits(value, nowMs = Date.now()) {
42
28
  const snapshots = collectCodexRateLimitSnapshots(value);
43
29
  if (snapshots.length === 0) return;
44
30
  return snapshots.slice(0, 4).map((snapshot) => summarizeRateLimitSnapshot(snapshot, nowMs)).join("; ");
45
31
  }
32
+ function summarizeCodexAccountRateLimits(value, nowMs = Date.now()) {
33
+ const summary = summarizeCodexAccountUsage(value, nowMs);
34
+ if (!summary) return;
35
+ if (!summary.blocked) return ["Codex is available."];
36
+ return [summary.blockedUntilText ? `Codex is paused until ${summary.blockedUntilText}.` : "Codex is paused by a usage limit.", summary.blockingReason ? `Your ${summary.blockingReason}.` : "Your Codex usage limit is reached."];
37
+ }
38
+ function resolveCodexUsageLimitResetAtMs(value, nowMs = Date.now()) {
39
+ return selectBlockingRateLimitReset(value, nowMs)?.resetsAtMs;
40
+ }
41
+ function summarizeCodexAccountUsage(value, nowMs = Date.now()) {
42
+ const snapshots = collectCodexRateLimitSnapshots(value);
43
+ if (snapshots.length === 0) return;
44
+ const usageSnapshot = snapshots.find(isCodexLimitSnapshot) ?? snapshots[0];
45
+ const blockedSnapshots = snapshots.filter(snapshotHasLimitBlock);
46
+ const blockingSnapshot = blockedSnapshots.find(isCodexLimitSnapshot) ?? blockedSnapshots[0] ?? void 0;
47
+ const blockingReset = blockingSnapshot ? selectSnapshotBlockingReset(blockingSnapshot, nowMs) : void 0;
48
+ const blockingPeriod = formatBlockingLimitPeriod(blockingReset?.windowDurationMins);
49
+ const blockedUntilText = blockingReset ? formatAccountResetTime(blockingReset.resetsAtMs, nowMs) : void 0;
50
+ const blockedResetRelative = blockingReset ? `in ${formatRelativeDuration(blockingReset.resetsAtMs - nowMs)}` : void 0;
51
+ const blockingReason = blockingPeriod ? `${blockingPeriod} Codex usage limit is reached` : blockingSnapshot ? "Codex usage limit is reached" : void 0;
52
+ return {
53
+ usageLine: formatUsageLine(usageSnapshot),
54
+ blocked: Boolean(blockingSnapshot),
55
+ ...blockingReset ? { blockedUntilMs: blockingReset.resetsAtMs } : {},
56
+ ...blockedUntilText ? { blockedUntilText } : {},
57
+ ...blockedResetRelative ? { blockedResetRelative } : {},
58
+ ...blockingPeriod ? { blockingPeriod } : {},
59
+ ...blockingReason ? { blockingReason } : {}
60
+ };
61
+ }
46
62
  function isCodexUsageLimitError(codexErrorInfo, message) {
47
63
  if (codexErrorInfo === "usageLimitExceeded") return true;
48
64
  if (typeof codexErrorInfo === "string") {
@@ -54,9 +70,12 @@ function selectNextRateLimitReset(value, nowMs) {
54
70
  const futureWindows = collectCodexRateLimitSnapshots(value).flatMap((snapshot) => LIMIT_WINDOW_KEYS.flatMap((key) => readRateLimitWindow(snapshot, key) ?? [])).filter((window) => window.resetsAtMs > nowMs);
55
71
  if (futureWindows.length === 0) return;
56
72
  const exhaustedWindows = futureWindows.filter((window) => window.usedPercent !== void 0 && window.usedPercent >= 100);
57
- const candidates = exhaustedWindows.length > 0 ? exhaustedWindows : futureWindows;
58
- candidates.sort((left, right) => left.resetsAtMs - right.resetsAtMs);
59
- return candidates[0];
73
+ return (exhaustedWindows.length > 0 ? exhaustedWindows : futureWindows).toSorted((left, right) => left.resetsAtMs - right.resetsAtMs)[0];
74
+ }
75
+ function selectBlockingRateLimitReset(value, nowMs) {
76
+ const blockedSnapshots = collectCodexRateLimitSnapshots(value).filter(snapshotHasLimitBlock);
77
+ const blockingSnapshot = blockedSnapshots.find(isCodexLimitSnapshot) ?? blockedSnapshots[0] ?? void 0;
78
+ return blockingSnapshot ? selectSnapshotBlockingReset(blockingSnapshot, nowMs) : void 0;
60
79
  }
61
80
  function summarizeRateLimitSnapshot(snapshot, nowMs) {
62
81
  const label = formatLimitLabel(snapshot);
@@ -64,7 +83,7 @@ function summarizeRateLimitSnapshot(snapshot, nowMs) {
64
83
  const window = readRateLimitWindow(snapshot, key);
65
84
  return window ? [formatRateLimitWindow(key, window, nowMs)] : [];
66
85
  });
67
- const reachedType = readString$1(snapshot, "rateLimitReachedType");
86
+ const reachedType = readString$1(snapshot, "rateLimitReachedType") ?? readString$1(snapshot, "rate_limit_reached_type");
68
87
  const suffix = reachedType ? ` (${formatReachedType(reachedType)})` : "";
69
88
  return `${label}: ${windows.join(", ") || "available"}${suffix}`;
70
89
  }
@@ -85,7 +104,10 @@ function collectRateLimitSnapshots(value, snapshots, seen) {
85
104
  }
86
105
  const byLimitId = value.rateLimitsByLimitId;
87
106
  if (isJsonObject(byLimitId)) for (const key of sortedRateLimitKeys(Object.keys(byLimitId))) collectRateLimitSnapshots(byLimitId[key], snapshots, seen);
107
+ const snakeByLimitId = value.rate_limits_by_limit_id;
108
+ if (isJsonObject(snakeByLimitId)) for (const key of sortedRateLimitKeys(Object.keys(snakeByLimitId))) collectRateLimitSnapshots(snakeByLimitId[key], snapshots, seen);
88
109
  collectRateLimitSnapshots(value.rateLimits, snapshots, seen);
110
+ collectRateLimitSnapshots(value.rate_limits, snapshots, seen);
89
111
  collectRateLimitSnapshots(value.data, snapshots, seen);
90
112
  collectRateLimitSnapshots(value.items, snapshots, seen);
91
113
  }
@@ -98,8 +120,8 @@ function sortedRateLimitKeys(keys) {
98
120
  }
99
121
  function addRateLimitSnapshot(snapshot, snapshots, seen) {
100
122
  const signature = [
101
- readNullableString(snapshot, "limitId") ?? "",
102
- readNullableString(snapshot, "limitName") ?? "",
123
+ readNullableString(snapshot, "limitId") ?? readNullableString(snapshot, "limit_id") ?? "",
124
+ readNullableString(snapshot, "limitName") ?? readNullableString(snapshot, "limit_name") ?? "",
103
125
  formatWindowSignature(snapshot.primary),
104
126
  formatWindowSignature(snapshot.secondary)
105
127
  ].join("|");
@@ -108,26 +130,31 @@ function addRateLimitSnapshot(snapshot, snapshots, seen) {
108
130
  snapshots.push(snapshot);
109
131
  }
110
132
  function isRateLimitSnapshot(value) {
111
- return isJsonObject(value.primary) || isJsonObject(value.secondary) || value.rateLimitReachedType !== void 0 || value.limitId !== void 0 || value.limitName !== void 0;
133
+ return isJsonObject(value.primary) || isJsonObject(value.secondary) || value.rateLimitReachedType !== void 0 || value.rate_limit_reached_type !== void 0 || value.limitId !== void 0 || value.limit_id !== void 0 || value.limitName !== void 0 || value.limit_name !== void 0;
112
134
  }
113
135
  function readRateLimitWindow(snapshot, key) {
114
136
  const window = snapshot[key];
115
137
  if (!isJsonObject(window)) return;
116
- const resetsAt = readNumber(window, "resetsAt");
138
+ const resetsAt = readNumber(window, "resetsAt") ?? readNumber(window, "resets_at");
117
139
  return {
118
140
  ...typeof resetsAt === "number" && Number.isFinite(resetsAt) && resetsAt > 0 ? { resetsAtMs: resetsAt * 1e3 } : { resetsAtMs: 0 },
119
- ...readOptionalNumberField(window, "usedPercent")
141
+ ...readOptionalNumberField(window, "usedPercent", "used_percent"),
142
+ ...readOptionalNumberField(window, "windowDurationMins", "window_duration_mins", "windowMinutes", "window_minutes")
120
143
  };
121
144
  }
122
- function readOptionalNumberField(record, key) {
123
- const value = readNumber(record, key);
124
- return value === void 0 ? {} : { usedPercent: value };
145
+ function readOptionalNumberField(record, ...keys) {
146
+ const value = keys.map((key) => readNumber(record, key)).find((entry) => entry !== void 0);
147
+ if (value === void 0) return {};
148
+ return keys.some((key) => key.toLowerCase().includes("window")) ? { windowDurationMins: value } : { usedPercent: value };
125
149
  }
126
150
  function formatRateLimitWindow(key, window, nowMs) {
127
- return `${key} ${window.usedPercent === void 0 ? "usage unknown" : `${Math.round(window.usedPercent)}%`}${window.resetsAtMs > nowMs ? `, resets ${formatResetTime(window.resetsAtMs, nowMs)}` : ""}`;
151
+ return `${key} ${formatRateLimitWindowDetails(window, nowMs)}`;
152
+ }
153
+ function formatRateLimitWindowDetails(window, nowMs) {
154
+ return `${window.usedPercent === void 0 ? "usage unknown" : `${Math.round(window.usedPercent)}%`}${window.resetsAtMs > nowMs ? `, resets ${formatResetTime(window.resetsAtMs, nowMs)}` : ""}`;
128
155
  }
129
156
  function formatLimitLabel(snapshot) {
130
- const label = readNullableString(snapshot, "limitName") ?? readNullableString(snapshot, "limitId");
157
+ const label = readNullableString(snapshot, "limitName") ?? readNullableString(snapshot, "limit_name") ?? readNullableString(snapshot, "limitId") ?? readNullableString(snapshot, "limit_id");
131
158
  if (!label || label === CODEX_LIMIT_ID) return "Codex";
132
159
  return label.replace(/[_-]+/gu, " ").replace(/\s+/gu, " ").trim();
133
160
  }
@@ -135,7 +162,78 @@ function formatReachedType(value) {
135
162
  return value.replace(/[_-]+/gu, " ").replace(/\s+/gu, " ").trim();
136
163
  }
137
164
  function formatResetTime(resetsAtMs, nowMs) {
138
- return `in ${formatRelativeDuration(resetsAtMs - nowMs)} (${new Date(resetsAtMs).toISOString()})`;
165
+ return `in ${formatRelativeDuration(resetsAtMs - nowMs)}, ${formatCalendarResetTime(resetsAtMs, nowMs)}`;
166
+ }
167
+ function formatAccountResetTime(resetsAtMs, nowMs) {
168
+ return `${formatCalendarResetTime(resetsAtMs, nowMs)} (in ${formatRelativeDuration(resetsAtMs - nowMs)})`;
169
+ }
170
+ function snapshotHasLimitBlock(snapshot) {
171
+ return Boolean(readString$1(snapshot, "rateLimitReachedType") ?? readString$1(snapshot, "rate_limit_reached_type") ?? readWindowEntries(snapshot).some((entry) => entry.window.usedPercent !== void 0 && entry.window.usedPercent >= 100));
172
+ }
173
+ function isCodexLimitSnapshot(snapshot) {
174
+ const id = readNullableString(snapshot, "limitId") ?? readNullableString(snapshot, "limit_id");
175
+ return !id || id === CODEX_LIMIT_ID;
176
+ }
177
+ function selectSnapshotBlockingReset(snapshot, nowMs) {
178
+ const futureWindows = readWindowEntries(snapshot).map((entry) => entry.window).filter((window) => window.resetsAtMs > nowMs);
179
+ const exhaustedWindows = futureWindows.filter((window) => window.usedPercent !== void 0 && window.usedPercent >= 100);
180
+ const candidates = exhaustedWindows.length > 0 ? exhaustedWindows : futureWindows;
181
+ const resetSort = exhaustedWindows.length > 0 ? (left, right) => right.resetsAtMs - left.resetsAtMs : (left, right) => left.resetsAtMs - right.resetsAtMs;
182
+ return candidates.toSorted(resetSort)[0];
183
+ }
184
+ function readWindowEntries(snapshot) {
185
+ return LIMIT_WINDOW_KEYS.flatMap((key) => {
186
+ const window = readRateLimitWindow(snapshot, key);
187
+ return window ? [{
188
+ key,
189
+ window
190
+ }] : [];
191
+ });
192
+ }
193
+ function formatBlockingLimitPeriod(minutes) {
194
+ if (minutes === 10080) return "weekly";
195
+ if (minutes === 1440) return "daily";
196
+ if (minutes !== void 0 && minutes > 0 && minutes < 1440) return "short-term";
197
+ }
198
+ function formatUsageLine(snapshot) {
199
+ const windows = readWindowEntries(snapshot).filter((entry) => entry.window.usedPercent !== void 0).toSorted((left, right) => (right.window.windowDurationMins ?? 0) - (left.window.windowDurationMins ?? 0)).map((entry) => {
200
+ return `${formatUsageWindowLabel(entry.window.windowDurationMins)} ${Math.round(entry.window.usedPercent ?? 0)}%`;
201
+ });
202
+ return windows.length > 0 ? windows.join(" · ") : void 0;
203
+ }
204
+ function formatUsageWindowLabel(minutes) {
205
+ if (minutes === 10080) return "weekly";
206
+ if (minutes === 1440) return "daily";
207
+ if (minutes !== void 0 && minutes > 0 && minutes < 1440) return "short-term";
208
+ if (minutes !== void 0 && minutes > 0 && minutes % 1440 === 0) return `${minutes / 1440}-day`;
209
+ if (minutes !== void 0 && minutes > 0 && minutes % 60 === 0) return `${minutes / 60}-hour`;
210
+ return "usage";
211
+ }
212
+ function formatCalendarResetTime(resetsAtMs, nowMs) {
213
+ const resetDate = new Date(resetsAtMs);
214
+ const resetParts = new Intl.DateTimeFormat("en-US", {
215
+ month: "short",
216
+ day: "numeric",
217
+ ...resetDate.getFullYear() === new Date(nowMs).getFullYear() ? {} : { year: "numeric" },
218
+ hour: "numeric",
219
+ minute: "2-digit",
220
+ timeZoneName: "short"
221
+ }).formatToParts(resetDate);
222
+ const part = (type) => resetParts.find((entry) => entry.type === type)?.value;
223
+ const dateParts = [
224
+ part("month"),
225
+ part("day"),
226
+ part("year")
227
+ ].filter(Boolean);
228
+ return [
229
+ dateParts.length > 1 ? `${dateParts[0]} ${dateParts.slice(1).join(", ")}` : dateParts[0],
230
+ "at",
231
+ [
232
+ [part("hour"), part("minute")].filter(Boolean).join(":"),
233
+ part("dayPeriod"),
234
+ part("timeZoneName")
235
+ ].filter(Boolean).join(" ")
236
+ ].filter(Boolean).join(" ");
139
237
  }
140
238
  function formatRelativeDuration(durationMs) {
141
239
  const safeMs = Math.max(1e3, durationMs);
@@ -153,7 +251,13 @@ function formatRelativeDuration(durationMs) {
153
251
  }
154
252
  function formatWindowSignature(value) {
155
253
  if (!isJsonObject(value)) return "";
156
- return `${readNumber(value, "usedPercent") ?? ""}:${readNumber(value, "resetsAt") ?? ""}`;
254
+ return `${readNumber(value, "usedPercent") ?? readNumber(value, "used_percent") ?? ""}:${readNumber(value, "resetsAt") ?? readNumber(value, "resets_at") ?? ""}`;
255
+ }
256
+ function extractCodexRetryHint(message) {
257
+ if (!message) return;
258
+ const tryAgainAt = /\btry again\s+(at\s+[^.!?\n]+)(?:[.!?]|$)/iu.exec(message);
259
+ if (tryAgainAt?.[1]) return tryAgainAt[1].trim();
260
+ return /\btry again\s+((?:tomorrow|in\s+[^.!?\n]+)[^.!?\n]*)(?:[.!?]|$)/iu.exec(message)?.[1]?.trim();
157
261
  }
158
262
  function readString$1(record, key) {
159
263
  const value = record[key];
@@ -203,8 +307,29 @@ function formatThreads(response) {
203
307
  return `- ${formatCodexDisplayText(id)}${title ? ` - ${formatCodexDisplayText(title)}` : ""}${details.length > 0 ? ` (${details.map(formatCodexDisplayText).join(", ")})` : ""}\n Resume: ${formatCodexResumeHint(id)}`;
204
308
  })].join("\n");
205
309
  }
206
- function formatAccount(account, limits) {
207
- return [`Account: ${account.ok ? formatCodexAccountSummary(account.value) : formatCodexDisplayText(account.error)}`, `Rate limits: ${limits.ok ? formatCodexRateLimitSummary(limits.value) : formatCodexDisplayText(limits.error)}`].join("\n");
310
+ function formatAccount(account, limits, authOverview) {
311
+ if (authOverview) return formatAccountAuthOverview(authOverview);
312
+ const formattedLimits = limits.ok ? formatCodexRateLimitDetails(limits.value) : formatCodexDisplayText(limits.error);
313
+ const rateLimitBlock = formattedLimits.startsWith("Codex is ") ? formattedLimits : formattedLimits.includes("\n") ? `Rate limits:\n${formattedLimits}` : `Rate limits: ${formattedLimits}`;
314
+ return [`Account: ${account.ok ? formatCodexAccountSummary(account.value) : formatCodexDisplayText(account.error)}`, rateLimitBlock].join("\n\n");
315
+ }
316
+ function formatAccountAuthOverview(overview) {
317
+ const lines = [];
318
+ if (overview.currentLine) lines.push(overview.currentLine, "");
319
+ if (overview.subscriptionLabel) {
320
+ lines.push(`Subscription ${overview.subscriptionLabel}`);
321
+ if (overview.subscriptionUsage) lines.push(` ${overview.subscriptionUsage}`);
322
+ lines.push("");
323
+ }
324
+ if (overview.rows.length > 0) {
325
+ lines.push(overview.orderTitle);
326
+ for (const [index, row] of overview.rows.entries()) lines.push(` ${index + 1}. ${row.label} ${row.kind} — ${formatAuthRowStatus(row)}`);
327
+ }
328
+ while (lines.at(-1) === "") lines.pop();
329
+ return lines.map(formatCodexAccountLine).join("\n");
330
+ }
331
+ function formatAuthRowStatus(row) {
332
+ return row.billingNote ? `${row.status} · ${row.billingNote}` : row.status;
208
333
  }
209
334
  function formatComputerUseStatus(status) {
210
335
  const lines = [`Computer Use: ${status.ready ? "ready" : status.enabled ? "not ready" : "disabled"}`];
@@ -241,13 +366,15 @@ function formatCodexAccountSummary(value) {
241
366
  return isLikelyEmailAddress(safe) ? escapeCodexChatTextPreservingAt(safe) : escapeCodexChatText(safe);
242
367
  }
243
368
  function formatCodexTextForDisplay(value) {
369
+ return sanitizeCodexTextForDisplay(value).trim() || "<unknown>";
370
+ }
371
+ function sanitizeCodexTextForDisplay(value) {
244
372
  let safe = "";
245
373
  for (const character of value) {
246
374
  const codePoint = character.codePointAt(0);
247
375
  safe += codePoint != null && isUnsafeDisplayCodePoint(codePoint) ? "?" : character;
248
376
  }
249
- safe = safe.trim();
250
- return safe || "<unknown>";
377
+ return safe;
251
378
  }
252
379
  function escapeCodexChatText(value) {
253
380
  return value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll("@", "@").replaceAll("`", "`").replaceAll("[", "[").replaceAll("]", "]").replaceAll("(", "(").replaceAll(")", ")").replaceAll("*", "∗").replaceAll("_", "_").replaceAll("~", "~").replaceAll("|", "|");
@@ -255,6 +382,22 @@ function escapeCodexChatText(value) {
255
382
  function escapeCodexChatTextPreservingAt(value) {
256
383
  return escapeCodexChatText(value).replaceAll("@", "@");
257
384
  }
385
+ function formatCodexAccountLine(value) {
386
+ if (value === "") return "";
387
+ const safe = sanitizeCodexTextForDisplay(value).trimEnd();
388
+ if (!safe.trim()) return "";
389
+ const emailPattern = /[^\s@<>()[\]`]+@[^\s@<>()[\]`]+\.[^\s@<>()[\]`]+/gu;
390
+ let formatted = "";
391
+ let lastIndex = 0;
392
+ for (const match of safe.matchAll(emailPattern)) {
393
+ const index = match.index ?? 0;
394
+ formatted += escapeCodexChatText(safe.slice(lastIndex, index));
395
+ formatted += escapeCodexChatTextPreservingAt(match[0]);
396
+ lastIndex = index + match[0].length;
397
+ }
398
+ formatted += escapeCodexChatText(safe.slice(lastIndex));
399
+ return formatted;
400
+ }
258
401
  function isLikelyEmailAddress(value) {
259
402
  return /^[^\s@<>()[\]`]+@[^\s@<>()[\]`]+\.[^\s@<>()[\]`]+$/.test(value);
260
403
  }
@@ -299,6 +442,11 @@ function summarizeArrayLike(value) {
299
442
  function formatCodexRateLimitSummary(value) {
300
443
  return formatCodexDisplayText(summarizeCodexRateLimits(value) ?? summarizeRateLimits(value));
301
444
  }
445
+ function formatCodexRateLimitDetails(value) {
446
+ const lines = summarizeCodexAccountRateLimits(value);
447
+ if (!lines) return formatCodexDisplayText(summarizeRateLimits(value));
448
+ return lines.map(formatCodexDisplayText).join("\n");
449
+ }
302
450
  function summarizeRateLimits(value) {
303
451
  const entries = extractArray(value);
304
452
  if (entries.length > 0) return `${entries.length}`;
@@ -335,17 +483,4 @@ function readString(record, key) {
335
483
  return typeof value === "string" && value.trim() ? value.trim() : void 0;
336
484
  }
337
485
  //#endregion
338
- //#region extensions/codex/src/app-server/request.ts
339
- async function requestCodexAppServerJson(params) {
340
- const timeoutMs = params.timeoutMs ?? 6e4;
341
- return await withTimeout((async () => {
342
- return await (await getSharedCodexAppServerClient({
343
- startOptions: params.startOptions,
344
- timeoutMs,
345
- authProfileId: params.authProfileId,
346
- config: params.config
347
- })).request(params.method, params.requestParams, { timeoutMs });
348
- })(), timeoutMs, `codex app-server ${params.method} timed out`);
349
- }
350
- //#endregion
351
- export { formatCodexStatus as a, formatModels as c, formatCodexUsageLimitErrorMessage as d, CODEX_CONTROL_METHODS as f, formatCodexDisplayText as i, formatThreads as l, buildHelp as n, formatComputerUseStatus as o, describeControlFailure as p, formatAccount as r, formatList as s, requestCodexAppServerJson as t, readString as u };
486
+ export { formatComputerUseStatus as a, formatThreads as c, resolveCodexUsageLimitResetAtMs as d, shouldRefreshCodexRateLimitsForUsageLimitMessage as f, formatCodexStatus as i, readString as l, formatAccount as n, formatList as o, summarizeCodexAccountUsage as p, formatCodexDisplayText as r, formatModels as s, buildHelp as t, formatCodexUsageLimitErrorMessage as u };