@openclaw/codex 2026.5.10-beta.1 → 2026.5.10-beta.3

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,6 +1,6 @@
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";
2
+ import { n as CodexAppServerRpcError } from "./client-CpksBQ9l.js";
3
+ import { i as withTimeout, n as getSharedCodexAppServerClient } from "./shared-client-BRX9tReb.js";
4
4
  //#region extensions/codex/src/app-server/capabilities.ts
5
5
  const CODEX_CONTROL_METHODS = {
6
6
  account: "account/read",
@@ -34,15 +34,32 @@ function formatCodexUsageLimitErrorMessage(params) {
34
34
  const nextReset = selectNextRateLimitReset(params.rateLimits, nowMs);
35
35
  const parts = ["You've reached your Codex subscription usage limit."];
36
36
  if (nextReset) parts.push(`Next reset ${formatResetTime(nextReset.resetsAtMs, nowMs)}.`);
37
- else parts.push("Codex did not return a reset time for this limit.");
37
+ else {
38
+ const codexRetryHint = extractCodexRetryHint(message);
39
+ if (codexRetryHint) parts.push(`Codex says to try again ${codexRetryHint}.`);
40
+ else parts.push("Codex did not return a reset time for this limit.");
41
+ }
38
42
  parts.push("Run /codex account for current usage details.");
39
43
  return parts.join(" ");
40
44
  }
45
+ function shouldRefreshCodexRateLimitsForUsageLimitMessage(message) {
46
+ const text = normalizeText(message);
47
+ return Boolean(text?.includes("You've reached your Codex subscription usage limit.") && !text.includes("Next reset "));
48
+ }
41
49
  function summarizeCodexRateLimits(value, nowMs = Date.now()) {
42
50
  const snapshots = collectCodexRateLimitSnapshots(value);
43
51
  if (snapshots.length === 0) return;
44
52
  return snapshots.slice(0, 4).map((snapshot) => summarizeRateLimitSnapshot(snapshot, nowMs)).join("; ");
45
53
  }
54
+ function summarizeCodexAccountRateLimits(value, nowMs = Date.now()) {
55
+ const snapshots = collectCodexRateLimitSnapshots(value);
56
+ if (snapshots.length === 0) return;
57
+ const blockedSnapshots = snapshots.filter(snapshotHasLimitBlock);
58
+ const blockingSnapshot = blockedSnapshots.find(isCodexLimitSnapshot) ?? blockedSnapshots[0] ?? void 0;
59
+ if (!blockingSnapshot) return ["Codex is available."];
60
+ const blockingReset = selectSnapshotBlockingReset(blockingSnapshot, nowMs);
61
+ return [blockingReset ? `Codex is paused until ${formatAccountResetTime(blockingReset.resetsAtMs, nowMs)}.` : "Codex is paused by a usage limit.", formatBlockingLimitReason(blockingReset)];
62
+ }
46
63
  function isCodexUsageLimitError(codexErrorInfo, message) {
47
64
  if (codexErrorInfo === "usageLimitExceeded") return true;
48
65
  if (typeof codexErrorInfo === "string") {
@@ -64,7 +81,7 @@ function summarizeRateLimitSnapshot(snapshot, nowMs) {
64
81
  const window = readRateLimitWindow(snapshot, key);
65
82
  return window ? [formatRateLimitWindow(key, window, nowMs)] : [];
66
83
  });
67
- const reachedType = readString$1(snapshot, "rateLimitReachedType");
84
+ const reachedType = readString$1(snapshot, "rateLimitReachedType") ?? readString$1(snapshot, "rate_limit_reached_type");
68
85
  const suffix = reachedType ? ` (${formatReachedType(reachedType)})` : "";
69
86
  return `${label}: ${windows.join(", ") || "available"}${suffix}`;
70
87
  }
@@ -85,7 +102,10 @@ function collectRateLimitSnapshots(value, snapshots, seen) {
85
102
  }
86
103
  const byLimitId = value.rateLimitsByLimitId;
87
104
  if (isJsonObject(byLimitId)) for (const key of sortedRateLimitKeys(Object.keys(byLimitId))) collectRateLimitSnapshots(byLimitId[key], snapshots, seen);
105
+ const snakeByLimitId = value.rate_limits_by_limit_id;
106
+ if (isJsonObject(snakeByLimitId)) for (const key of sortedRateLimitKeys(Object.keys(snakeByLimitId))) collectRateLimitSnapshots(snakeByLimitId[key], snapshots, seen);
88
107
  collectRateLimitSnapshots(value.rateLimits, snapshots, seen);
108
+ collectRateLimitSnapshots(value.rate_limits, snapshots, seen);
89
109
  collectRateLimitSnapshots(value.data, snapshots, seen);
90
110
  collectRateLimitSnapshots(value.items, snapshots, seen);
91
111
  }
@@ -98,8 +118,8 @@ function sortedRateLimitKeys(keys) {
98
118
  }
99
119
  function addRateLimitSnapshot(snapshot, snapshots, seen) {
100
120
  const signature = [
101
- readNullableString(snapshot, "limitId") ?? "",
102
- readNullableString(snapshot, "limitName") ?? "",
121
+ readNullableString(snapshot, "limitId") ?? readNullableString(snapshot, "limit_id") ?? "",
122
+ readNullableString(snapshot, "limitName") ?? readNullableString(snapshot, "limit_name") ?? "",
103
123
  formatWindowSignature(snapshot.primary),
104
124
  formatWindowSignature(snapshot.secondary)
105
125
  ].join("|");
@@ -108,26 +128,31 @@ function addRateLimitSnapshot(snapshot, snapshots, seen) {
108
128
  snapshots.push(snapshot);
109
129
  }
110
130
  function isRateLimitSnapshot(value) {
111
- return isJsonObject(value.primary) || isJsonObject(value.secondary) || value.rateLimitReachedType !== void 0 || value.limitId !== void 0 || value.limitName !== void 0;
131
+ 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
132
  }
113
133
  function readRateLimitWindow(snapshot, key) {
114
134
  const window = snapshot[key];
115
135
  if (!isJsonObject(window)) return;
116
- const resetsAt = readNumber(window, "resetsAt");
136
+ const resetsAt = readNumber(window, "resetsAt") ?? readNumber(window, "resets_at");
117
137
  return {
118
138
  ...typeof resetsAt === "number" && Number.isFinite(resetsAt) && resetsAt > 0 ? { resetsAtMs: resetsAt * 1e3 } : { resetsAtMs: 0 },
119
- ...readOptionalNumberField(window, "usedPercent")
139
+ ...readOptionalNumberField(window, "usedPercent", "used_percent"),
140
+ ...readOptionalNumberField(window, "windowDurationMins", "window_duration_mins", "windowMinutes", "window_minutes")
120
141
  };
121
142
  }
122
- function readOptionalNumberField(record, key) {
123
- const value = readNumber(record, key);
124
- return value === void 0 ? {} : { usedPercent: value };
143
+ function readOptionalNumberField(record, ...keys) {
144
+ const value = keys.map((key) => readNumber(record, key)).find((entry) => entry !== void 0);
145
+ if (value === void 0) return {};
146
+ return keys.some((key) => key.toLowerCase().includes("window")) ? { windowDurationMins: value } : { usedPercent: value };
125
147
  }
126
148
  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)}` : ""}`;
149
+ return `${key} ${formatRateLimitWindowDetails(window, nowMs)}`;
150
+ }
151
+ function formatRateLimitWindowDetails(window, nowMs) {
152
+ return `${window.usedPercent === void 0 ? "usage unknown" : `${Math.round(window.usedPercent)}%`}${window.resetsAtMs > nowMs ? `, resets ${formatResetTime(window.resetsAtMs, nowMs)}` : ""}`;
128
153
  }
129
154
  function formatLimitLabel(snapshot) {
130
- const label = readNullableString(snapshot, "limitName") ?? readNullableString(snapshot, "limitId");
155
+ const label = readNullableString(snapshot, "limitName") ?? readNullableString(snapshot, "limit_name") ?? readNullableString(snapshot, "limitId") ?? readNullableString(snapshot, "limit_id");
131
156
  if (!label || label === CODEX_LIMIT_ID) return "Codex";
132
157
  return label.replace(/[_-]+/gu, " ").replace(/\s+/gu, " ").trim();
133
158
  }
@@ -135,7 +160,68 @@ function formatReachedType(value) {
135
160
  return value.replace(/[_-]+/gu, " ").replace(/\s+/gu, " ").trim();
136
161
  }
137
162
  function formatResetTime(resetsAtMs, nowMs) {
138
- return `in ${formatRelativeDuration(resetsAtMs - nowMs)} (${new Date(resetsAtMs).toISOString()})`;
163
+ return `in ${formatRelativeDuration(resetsAtMs - nowMs)}, ${formatCalendarResetTime(resetsAtMs, nowMs)}`;
164
+ }
165
+ function formatAccountResetTime(resetsAtMs, nowMs) {
166
+ return `${formatCalendarResetTime(resetsAtMs, nowMs)} (in ${formatRelativeDuration(resetsAtMs - nowMs)})`;
167
+ }
168
+ function snapshotHasLimitBlock(snapshot) {
169
+ 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));
170
+ }
171
+ function isCodexLimitSnapshot(snapshot) {
172
+ const id = readNullableString(snapshot, "limitId") ?? readNullableString(snapshot, "limit_id");
173
+ return !id || id === CODEX_LIMIT_ID;
174
+ }
175
+ function selectSnapshotBlockingReset(snapshot, nowMs) {
176
+ const futureWindows = readWindowEntries(snapshot).map((entry) => entry.window).filter((window) => window.resetsAtMs > nowMs);
177
+ const exhaustedWindows = futureWindows.filter((window) => window.usedPercent !== void 0 && window.usedPercent >= 100);
178
+ const candidates = exhaustedWindows.length > 0 ? exhaustedWindows : futureWindows;
179
+ candidates.sort((left, right) => left.resetsAtMs - right.resetsAtMs);
180
+ return candidates[0];
181
+ }
182
+ function readWindowEntries(snapshot) {
183
+ return LIMIT_WINDOW_KEYS.flatMap((key) => {
184
+ const window = readRateLimitWindow(snapshot, key);
185
+ return window ? [{
186
+ key,
187
+ window
188
+ }] : [];
189
+ });
190
+ }
191
+ function formatBlockingLimitReason(window) {
192
+ const period = formatBlockingLimitPeriod(window?.windowDurationMins);
193
+ return period ? `Your ${period} Codex usage limit is reached.` : "Your Codex usage limit is reached.";
194
+ }
195
+ function formatBlockingLimitPeriod(minutes) {
196
+ if (minutes === 10080) return "weekly";
197
+ if (minutes === 1440) return "daily";
198
+ if (minutes !== void 0 && minutes > 0 && minutes < 1440) return "short-term";
199
+ }
200
+ function formatCalendarResetTime(resetsAtMs, nowMs) {
201
+ const resetDate = new Date(resetsAtMs);
202
+ const resetParts = new Intl.DateTimeFormat("en-US", {
203
+ month: "short",
204
+ day: "numeric",
205
+ ...resetDate.getFullYear() === new Date(nowMs).getFullYear() ? {} : { year: "numeric" },
206
+ hour: "numeric",
207
+ minute: "2-digit",
208
+ timeZoneName: "short"
209
+ }).formatToParts(resetDate);
210
+ const part = (type) => resetParts.find((entry) => entry.type === type)?.value;
211
+ const dateParts = [
212
+ part("month"),
213
+ part("day"),
214
+ part("year")
215
+ ].filter(Boolean);
216
+ return [
217
+ dateParts.length > 1 ? `${dateParts[0]} ${dateParts.slice(1).join(", ")}` : dateParts[0],
218
+ "at",
219
+ [
220
+ [part("hour"), part("minute")].filter(Boolean).join(":"),
221
+ part("dayPeriod"),
222
+ part("timeZoneName")
223
+ ].filter(Boolean).join(" ")
224
+ ].filter(Boolean).join(" ");
139
225
  }
140
226
  function formatRelativeDuration(durationMs) {
141
227
  const safeMs = Math.max(1e3, durationMs);
@@ -153,7 +239,13 @@ function formatRelativeDuration(durationMs) {
153
239
  }
154
240
  function formatWindowSignature(value) {
155
241
  if (!isJsonObject(value)) return "";
156
- return `${readNumber(value, "usedPercent") ?? ""}:${readNumber(value, "resetsAt") ?? ""}`;
242
+ return `${readNumber(value, "usedPercent") ?? readNumber(value, "used_percent") ?? ""}:${readNumber(value, "resetsAt") ?? readNumber(value, "resets_at") ?? ""}`;
243
+ }
244
+ function extractCodexRetryHint(message) {
245
+ if (!message) return;
246
+ const tryAgainAt = /\btry again\s+(at\s+[^.!?\n]+)(?:[.!?]|$)/iu.exec(message);
247
+ if (tryAgainAt?.[1]) return tryAgainAt[1].trim();
248
+ return /\btry again\s+((?:tomorrow|in\s+[^.!?\n]+)[^.!?\n]*)(?:[.!?]|$)/iu.exec(message)?.[1]?.trim();
157
249
  }
158
250
  function readString$1(record, key) {
159
251
  const value = record[key];
@@ -204,7 +296,9 @@ function formatThreads(response) {
204
296
  })].join("\n");
205
297
  }
206
298
  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");
299
+ const formattedLimits = limits.ok ? formatCodexRateLimitDetails(limits.value) : formatCodexDisplayText(limits.error);
300
+ const rateLimitBlock = formattedLimits.startsWith("Codex is ") ? formattedLimits : formattedLimits.includes("\n") ? `Rate limits:\n${formattedLimits}` : `Rate limits: ${formattedLimits}`;
301
+ return [`Account: ${account.ok ? formatCodexAccountSummary(account.value) : formatCodexDisplayText(account.error)}`, rateLimitBlock].join("\n\n");
208
302
  }
209
303
  function formatComputerUseStatus(status) {
210
304
  const lines = [`Computer Use: ${status.ready ? "ready" : status.enabled ? "not ready" : "disabled"}`];
@@ -299,6 +393,11 @@ function summarizeArrayLike(value) {
299
393
  function formatCodexRateLimitSummary(value) {
300
394
  return formatCodexDisplayText(summarizeCodexRateLimits(value) ?? summarizeRateLimits(value));
301
395
  }
396
+ function formatCodexRateLimitDetails(value) {
397
+ const lines = summarizeCodexAccountRateLimits(value);
398
+ if (!lines) return formatCodexDisplayText(summarizeRateLimits(value));
399
+ return lines.map(formatCodexDisplayText).join("\n");
400
+ }
302
401
  function summarizeRateLimits(value) {
303
402
  const entries = extractArray(value);
304
403
  if (entries.length > 0) return `${entries.length}`;
@@ -348,4 +447,4 @@ async function requestCodexAppServerJson(params) {
348
447
  })(), timeoutMs, `codex app-server ${params.method} timed out`);
349
448
  }
350
449
  //#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 };
450
+ export { formatCodexStatus as a, formatModels as c, formatCodexUsageLimitErrorMessage as d, shouldRefreshCodexRateLimitsForUsageLimitMessage as f, formatCodexDisplayText as i, formatThreads as l, describeControlFailure as m, buildHelp as n, formatComputerUseStatus as o, CODEX_CONTROL_METHODS as p, formatAccount as r, formatList as s, requestCodexAppServerJson as t, readString as u };