@songsid/agend 2.1.4-beta.6 → 2.1.4-beta.61

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 (185) hide show
  1. package/README.md +1 -1
  2. package/README.zh-TW.md +1 -1
  3. package/dist/agent-cli-instructions.md +2 -2
  4. package/dist/agent-endpoint.js +1 -1
  5. package/dist/agent-endpoint.js.map +1 -1
  6. package/dist/backend/antigravity.d.ts +12 -8
  7. package/dist/backend/antigravity.js +189 -42
  8. package/dist/backend/antigravity.js.map +1 -1
  9. package/dist/backend/claude-code.d.ts +87 -23
  10. package/dist/backend/claude-code.js +361 -46
  11. package/dist/backend/claude-code.js.map +1 -1
  12. package/dist/backend/codex.d.ts +18 -0
  13. package/dist/backend/codex.js +143 -7
  14. package/dist/backend/codex.js.map +1 -1
  15. package/dist/backend/gemini-cli.js +2 -2
  16. package/dist/backend/gemini-cli.js.map +1 -1
  17. package/dist/backend/grok.js +2 -2
  18. package/dist/backend/grok.js.map +1 -1
  19. package/dist/backend/kiro.d.ts +52 -2
  20. package/dist/backend/kiro.js +267 -12
  21. package/dist/backend/kiro.js.map +1 -1
  22. package/dist/backend/opencode.js +17 -4
  23. package/dist/backend/opencode.js.map +1 -1
  24. package/dist/backend/types.d.ts +122 -3
  25. package/dist/backend/types.js +5 -1
  26. package/dist/backend/types.js.map +1 -1
  27. package/dist/backend-outage.d.ts +61 -0
  28. package/dist/backend-outage.js +71 -0
  29. package/dist/backend-outage.js.map +1 -0
  30. package/dist/channel/adapters/discord.d.ts +44 -2
  31. package/dist/channel/adapters/discord.js +529 -89
  32. package/dist/channel/adapters/discord.js.map +1 -1
  33. package/dist/channel/adapters/telegram.d.ts +30 -0
  34. package/dist/channel/adapters/telegram.js +221 -19
  35. package/dist/channel/adapters/telegram.js.map +1 -1
  36. package/dist/channel/agy-mcp-launcher.d.ts +2 -0
  37. package/dist/channel/agy-mcp-launcher.js +28 -0
  38. package/dist/channel/agy-mcp-launcher.js.map +1 -0
  39. package/dist/channel/ipc-bridge.d.ts +2 -1
  40. package/dist/channel/ipc-bridge.js +33 -4
  41. package/dist/channel/ipc-bridge.js.map +1 -1
  42. package/dist/channel/markdown-chunk.d.ts +42 -0
  43. package/dist/channel/markdown-chunk.js +205 -0
  44. package/dist/channel/markdown-chunk.js.map +1 -0
  45. package/dist/channel/mcp-server.js +28 -25
  46. package/dist/channel/mcp-server.js.map +1 -1
  47. package/dist/channel/mcp-tools.js +6 -4
  48. package/dist/channel/mcp-tools.js.map +1 -1
  49. package/dist/channel/message-queue.js +64 -8
  50. package/dist/channel/message-queue.js.map +1 -1
  51. package/dist/channel/types.d.ts +31 -1
  52. package/dist/classic-channel-manager.d.ts +65 -0
  53. package/dist/classic-channel-manager.js +172 -3
  54. package/dist/classic-channel-manager.js.map +1 -1
  55. package/dist/cli.js +124 -83
  56. package/dist/cli.js.map +1 -1
  57. package/dist/config-validator.js +16 -0
  58. package/dist/config-validator.js.map +1 -1
  59. package/dist/config.d.ts +4 -0
  60. package/dist/config.js +12 -1
  61. package/dist/config.js.map +1 -1
  62. package/dist/cross-instance-envelope.d.ts +6 -0
  63. package/dist/cross-instance-envelope.js +30 -0
  64. package/dist/cross-instance-envelope.js.map +1 -0
  65. package/dist/daemon.d.ts +506 -11
  66. package/dist/daemon.js +2162 -313
  67. package/dist/daemon.js.map +1 -1
  68. package/dist/doctor.d.ts +41 -0
  69. package/dist/doctor.js +267 -0
  70. package/dist/doctor.js.map +1 -0
  71. package/dist/fleet-context.d.ts +63 -0
  72. package/dist/fleet-context.js.map +1 -1
  73. package/dist/fleet-manager.d.ts +462 -12
  74. package/dist/fleet-manager.js +3027 -634
  75. package/dist/fleet-manager.js.map +1 -1
  76. package/dist/fleet-yaml-slim.d.ts +10 -0
  77. package/dist/fleet-yaml-slim.js +59 -0
  78. package/dist/fleet-yaml-slim.js.map +1 -0
  79. package/dist/general-knowledge/skills/backend-providers/SKILL.md +114 -0
  80. package/dist/general-knowledge/skills/cross-instance-messaging/SKILL.md +4 -1
  81. package/dist/general-knowledge/skills/delegation-playbook/SKILL.md +52 -0
  82. package/dist/general-knowledge/skills/development-workflow/SKILL.md +28 -0
  83. package/dist/general-knowledge/skills/fleet-config/SKILL.md +1 -0
  84. package/dist/general-knowledge/skills/fleet-health/SKILL.md +1 -0
  85. package/dist/general-knowledge/skills/fleet-restart/SKILL.md +1 -0
  86. package/dist/general-knowledge/skills/instance-lifecycle/SKILL.md +1 -0
  87. package/dist/general-knowledge/skills/model-discovery/SKILL.md +64 -16
  88. package/dist/general-knowledge/skills/multi-channel/SKILL.md +1 -0
  89. package/dist/general-knowledge/skills/scheduling/SKILL.md +1 -0
  90. package/dist/general-knowledge/skills/session-management/SKILL.md +172 -8
  91. package/dist/general-knowledge/skills/tui-effort/SKILL.md +1 -0
  92. package/dist/general-knowledge/skills/worker-collaboration/SKILL.md +30 -0
  93. package/dist/instance-lifecycle.d.ts +99 -0
  94. package/dist/instance-lifecycle.js +357 -11
  95. package/dist/instance-lifecycle.js.map +1 -1
  96. package/dist/instructions.d.ts +12 -0
  97. package/dist/instructions.js +74 -3
  98. package/dist/instructions.js.map +1 -1
  99. package/dist/locale.js +1022 -310
  100. package/dist/locale.js.map +1 -1
  101. package/dist/login-flows.d.ts +91 -0
  102. package/dist/login-flows.js +170 -0
  103. package/dist/login-flows.js.map +1 -0
  104. package/dist/login-manager.d.ts +63 -0
  105. package/dist/login-manager.js +134 -0
  106. package/dist/login-manager.js.map +1 -0
  107. package/dist/network-family.d.ts +18 -0
  108. package/dist/network-family.js +20 -0
  109. package/dist/network-family.js.map +1 -0
  110. package/dist/outbound-handlers.d.ts +16 -1
  111. package/dist/outbound-handlers.js +174 -40
  112. package/dist/outbound-handlers.js.map +1 -1
  113. package/dist/outbound-schemas.d.ts +11 -3
  114. package/dist/outbound-schemas.js +11 -0
  115. package/dist/outbound-schemas.js.map +1 -1
  116. package/dist/pane-input-residue.d.ts +52 -0
  117. package/dist/pane-input-residue.js +107 -0
  118. package/dist/pane-input-residue.js.map +1 -0
  119. package/dist/process-memory.d.ts +6 -0
  120. package/dist/process-memory.js +45 -0
  121. package/dist/process-memory.js.map +1 -1
  122. package/dist/reply-dedup.d.ts +7 -8
  123. package/dist/reply-dedup.js +0 -0
  124. package/dist/reply-dedup.js.map +1 -1
  125. package/dist/restart-progress.d.ts +2 -0
  126. package/dist/restart-progress.js +3 -0
  127. package/dist/restart-progress.js.map +1 -1
  128. package/dist/scheduler/db.d.ts +12 -0
  129. package/dist/scheduler/db.js +59 -0
  130. package/dist/scheduler/db.js.map +1 -1
  131. package/dist/service-installer.d.ts +11 -0
  132. package/dist/service-installer.js +84 -18
  133. package/dist/service-installer.js.map +1 -1
  134. package/dist/settings-api.js +1 -1
  135. package/dist/settings-api.js.map +1 -1
  136. package/dist/setup-wizard.js +2 -2
  137. package/dist/setup-wizard.js.map +1 -1
  138. package/dist/spawn-gate.d.ts +30 -0
  139. package/dist/spawn-gate.js +79 -0
  140. package/dist/spawn-gate.js.map +1 -0
  141. package/dist/steer-capability.d.ts +1 -0
  142. package/dist/steer-capability.js +6 -0
  143. package/dist/steer-capability.js.map +1 -0
  144. package/dist/storm-window.d.ts +83 -0
  145. package/dist/storm-window.js +251 -0
  146. package/dist/storm-window.js.map +1 -0
  147. package/dist/tips.d.ts +44 -0
  148. package/dist/tips.js +355 -0
  149. package/dist/tips.js.map +1 -0
  150. package/dist/tmux-manager.d.ts +16 -0
  151. package/dist/tmux-manager.js +110 -25
  152. package/dist/tmux-manager.js.map +1 -1
  153. package/dist/tool-progress.d.ts +40 -0
  154. package/dist/tool-progress.js +289 -0
  155. package/dist/tool-progress.js.map +1 -0
  156. package/dist/topic-commands.d.ts +45 -6
  157. package/dist/topic-commands.js +394 -66
  158. package/dist/topic-commands.js.map +1 -1
  159. package/dist/transcript-monitor.d.ts +15 -2
  160. package/dist/transcript-monitor.js +63 -17
  161. package/dist/transcript-monitor.js.map +1 -1
  162. package/dist/transcript-sources.d.ts +131 -0
  163. package/dist/transcript-sources.js +580 -0
  164. package/dist/transcript-sources.js.map +1 -0
  165. package/dist/types.d.ts +11 -0
  166. package/dist/ui/dashboard.html +55 -32
  167. package/dist/ui/settings.html +200 -60
  168. package/dist/ui/view.html +147 -30
  169. package/dist/usage/format-rich.d.ts +1 -1
  170. package/dist/usage/format-rich.js +28 -24
  171. package/dist/usage/format-rich.js.map +1 -1
  172. package/dist/usage/i18n-keys.d.ts +7 -0
  173. package/dist/usage/i18n-keys.js +34 -0
  174. package/dist/usage/i18n-keys.js.map +1 -0
  175. package/dist/usage/i18n.d.ts +5 -0
  176. package/dist/usage/i18n.js +27 -0
  177. package/dist/usage/i18n.js.map +1 -0
  178. package/dist/usage/providers.d.ts +21 -0
  179. package/dist/usage/providers.js +153 -75
  180. package/dist/usage/providers.js.map +1 -1
  181. package/dist/usage/usage-api.d.ts +11 -3
  182. package/dist/usage/usage-api.js +61 -24
  183. package/dist/usage/usage-api.js.map +1 -1
  184. package/dist/workflow-templates/default.md +2 -1
  185. package/package.json +2 -2
package/dist/ui/view.html CHANGED
@@ -129,17 +129,17 @@
129
129
  </style>
130
130
  </head>
131
131
  <body>
132
- <button class="help-btn" id="usageBtn" title="AI usage" style="right:140px; display:none">📊</button>
133
- <button class="help-btn" id="densityBtn" title="Font density" style="right:98px">⤢</button>
134
- <button class="help-btn" id="langBtn" title="Language" style="right:56px">🌐</button>
135
- <button class="help-btn" id="helpBtn" title="Help">ℹ️</button>
132
+ <button class="help-btn" id="usageBtn" data-i18n-title="usageButton" title="AI usage" style="right:140px; display:none">📊</button>
133
+ <button class="help-btn" id="densityBtn" data-i18n-title="densityLabel" title="Font density" style="right:98px">⤢</button>
134
+ <button class="help-btn" id="langBtn" data-i18n-title="languageButton" title="Language" style="right:56px">🌐</button>
135
+ <button class="help-btn" id="helpBtn" data-i18n-title="helpButton" title="Help">ℹ️</button>
136
136
  <div class="help-backdrop" id="helpBackdrop"></div>
137
137
  <aside class="help-panel" id="helpPanel">
138
- <button class="close" id="helpClose" title="Close">×</button>
138
+ <button class="close" id="helpClose" data-i18n-title="close" title="Close">×</button>
139
139
  <div id="helpContent"></div>
140
140
  </aside>
141
141
  <aside class="help-panel" id="usagePanel">
142
- <button class="close" id="usageClose" title="Close">×</button>
142
+ <button class="close" id="usageClose" data-i18n-title="close" title="Close">×</button>
143
143
  <div id="usageContent"></div>
144
144
  </aside>
145
145
  <div id="sidebar"><h1 data-i18n="viewTitle">AgEnD · View</h1><div id="list"></div></div>
@@ -152,7 +152,7 @@
152
152
  <div class="meta" id="meta"></div>
153
153
  <div class="desc" id="desc"></div>
154
154
  </div>
155
- <button id="cardToggle" title="Expand profile" aria-expanded="false">▲</button>
155
+ <button id="cardToggle" data-i18n-title="expandProfile" title="Expand profile" aria-expanded="false">▲</button>
156
156
  <button id="editBtn" data-i18n="editProfile">✏️ Edit</button>
157
157
  <div id="edit">
158
158
  <input id="fDisplay" data-i18n-ph="displayName" placeholder="Display name">
@@ -193,7 +193,54 @@
193
193
  tooltipBackend: "Backend: {value}", tooltipStatus: "Status: {value}", tooltipContext: "Context: {value}",
194
194
  tooltipUnavailable: "Unavailable", statusRunning: "Running", statusPaused: "Paused",
195
195
  statusStopped: "Stopped", statusCrashed: "Crashed", statusUnknown: "Unknown",
196
- usageResets: "resets in {t}", usageSoon: "resets soon", usageFail: "Could not load usage data." },
196
+ usageResets: "resets in {t}", usageSoon: "resets soon", usageFail: "Could not load usage data.",
197
+ "usage.title": "AI Subscription Usage", "usage.title_plain": "AI subscription usage", "usage.empty_active": "No active backends with usage tracking",
198
+ "usage.not_logged_in": "not logged in", "usage.error_fallback": "error", "usage.no_data": "no data",
199
+ "usage.reset.in": "resets in {0}", "usage.reset.soon": "resets soon",
200
+ "usage.duration.days_hours": "{0}d {1}h", "usage.duration.hours_minutes": "{0}h {1}m", "usage.duration.minutes": "{0}m",
201
+ "usage.metric.session": "Session", "usage.metric.weekly": "Weekly", "usage.metric.monthly": "Monthly",
202
+ "usage.metric.days_window": "{0}-day window", "usage.metric.named": "{0}",
203
+ "usage.metric.named_session": "{0} (session)", "usage.metric.named_weekly": "{0} (weekly)",
204
+ "usage.metric.named_monthly": "{0} (monthly)", "usage.metric.named_days": "{0} ({1}d)",
205
+ "usage.metric.extra_usage": "Extra usage", "usage.metric.rate_limit_resets": "Rate limit resets",
206
+ "usage.metric.credits": "Credits", "usage.metric.weekly_limit": "Weekly limit",
207
+ "usage.metric.pay_as_you_go": "Pay as you go", "usage.metric.bonus_credits": "Bonus credits",
208
+ "usage.metric.overage_charges": "Overage charges", "usage.metric.pay_per_use": "Pay-per-use",
209
+ "usage.metric.usage_monthly": "Usage (monthly)",
210
+ "usage.unit.available": "available", "usage.unit.credits": "credits",
211
+ "usage.value.disabled": "Disabled", "usage.value.cap": "{0} cap",
212
+ "usage.note.binding": "binding", "usage.note.binding_severity": "binding · {0}",
213
+ "usage.note.busiest_model": "busiest of {0} model", "usage.note.busiest_models": "busiest of {0} models",
214
+ "usage.note.used_limit_unit": "{0} / {1} {2}", "usage.note.bonus_codes": "{0} / {1} {2} · {3} codes",
215
+ "usage.metric.agy_claude_others": "Claude & others", "usage.metric.agy_claude_others_session": "Claude & others (session)",
216
+ "usage.metric.agy_claude_others_weekly": "Claude & others (weekly)",
217
+ "usage.hint.statusline_now": "from {0}'s statusline, just now — no API call; plan and per-model limits need a CLI login",
218
+ "usage.hint.statusline_minutes": "from {0}'s statusline, {1}m ago — no API call; plan and per-model limits need a CLI login",
219
+ "usage.hint.claude_api_key": "API-key login has no subscription usage. Use `claude /login` or set CLAUDE_CODE_OAUTH_TOKEN (from `claude setup-token`).",
220
+ "usage.hint.login_claude": "Log in with the Claude Code CLI (`claude`).",
221
+ "usage.hint.login_agy": "Log in with the Antigravity CLI (`agy`).", "usage.hint.no_quota": "No quota information reported for this account.",
222
+ "usage.hint.login_codex": "Log in with the Codex CLI (`codex`).", "usage.hint.codex_no_oauth": "auth.json has no OAuth login (API-key-only auth cannot read usage).",
223
+ "usage.hint.login_grok": "Log in with the Grok CLI (`grok login`).", "usage.hint.grok_no_login": "auth.json has no usable login. Run `grok login`.",
224
+ "usage.hint.login_kiro": "Log in with the Kiro CLI (`kiro-cli`).", "usage.hint.kiro_signed_out": "Signed out — run `kiro-cli` to log in.",
225
+ "usage.hint.token_refreshing": "Token refreshing — try again in a moment.", "usage.hint.subscription_no_credit": "Subscription — no credit usage to report.",
226
+ "usage.hint.no_quota_account": "No quota information available for this account type.",
227
+ "usage.error.unreachable": "Could not reach {0}.", "usage.error.token_rejected": "Token rejected. Run `{0}` once to refresh the login.",
228
+ "usage.error.rate_limited": "Rate limited by {0} — try again later.", "usage.error.http": "Usage request failed (HTTP {0}).",
229
+ "usage.error.billing_http": "Billing request failed (HTTP {0}).", "usage.error.invalid_response": "Invalid response from usage endpoint.",
230
+ "usage.error.invalid_billing_response": "Invalid response from billing endpoint.", "usage.error.invalid_kiro_response": "Invalid response from GetUsageLimits.",
231
+ "usage.error.claude_token_expired": "Access token expired — it refreshes the next time any Claude instance runs.",
232
+ "usage.error.codex_token_expired": "Access token expired. Run `codex` once to refresh it.",
233
+ "usage.error.grok_expired": "Grok session expired. Run `grok login` again.", "usage.error.grok_response_changed": "Grok billing response changed.",
234
+ "usage.error.agy_cap": "Individual cap reached — CLI is rate limited (resets in ~{0}). The per-model pool quotas are separate and may still read 0% used.",
235
+ "usage.error.agy_no_refresh": "Access token expired and no refresh token is stored. Run `agy` once.",
236
+ "usage.error.agy_token_expired": "Access token expired. Run `agy` once to refresh it (or set AGY_OAUTH_CLIENT_ID/SECRET to refresh automatically).",
237
+ "usage.error.agy_login_expired": "Google sign-in expired. Run `agy` once to log in again.", "usage.error.agy_refresh_empty": "Google token refresh returned no token.",
238
+ "usage.error.grok_auth_readonly": "Token expired and auth.json is read-only. Run `grok` once to refresh it.", "usage.error.grok_no_refresh": "Token expired and no refresh token was found. Run `grok login`.",
239
+ "usage.error.grok_refresh_unreachable": "Could not reach auth.x.ai to refresh the token.", "usage.error.grok_invalid_refresh": "Invalid refresh response from auth.x.ai.",
240
+ "usage.error.grok_persist": "Refreshed but could not write auth.json. Run `grok` once instead.",
241
+ usageButton: "AI usage", languageButton: "Language", helpButton: "Help", close: "Close", expandProfile: "Expand profile",
242
+ rosterFailed: "Failed to load roster: {error}\n(Is the fleet running?)", paneFailed: "⚠ Could not load pane for {name} (HTTP {status}).",
243
+ tokenRequired: "web.token required", avatarFailed: "Avatar upload failed: {error}", saved: "Saved", saveFailed: "Save failed: {error}" },
197
244
  "zh-TW": { viewTitle: "AgEnD · 檢視", editProfile: "✏️ 編輯", save: "儲存", cancel: "取消",
198
245
  displayName: "顯示名稱", role: "角色", description: "描述", tokenPh: "web.token(儲存時需要)",
199
246
  saveHint: "檢視為公開(唯讀)。儲存需要 web.token(~/.agend/web.token)。", helpTitle: "📖 使用說明",
@@ -208,14 +255,63 @@
208
255
  tooltipBackend: "後端:{value}", tooltipStatus: "狀態:{value}", tooltipContext: "上下文:{value}",
209
256
  tooltipUnavailable: "無資料", statusRunning: "運行中", statusPaused: "已暫停",
210
257
  statusStopped: "已停止", statusCrashed: "已崩潰", statusUnknown: "未知",
211
- usageResets: "{t} 後重置", usageSoon: "即將重置", usageFail: "無法載入用量資料。" },
258
+ usageResets: "{t}後重置", usageSoon: "即將重置", usageFail: "無法載入用量資料。",
259
+ "usage.title": "AI 訂閱用量", "usage.title_plain": "AI 訂閱用量", "usage.empty_active": "沒有使用中且支援用量追蹤的 Backend",
260
+ "usage.not_logged_in": "未登入", "usage.error_fallback": "錯誤", "usage.no_data": "無資料",
261
+ "usage.reset.in": "{0} 後重置", "usage.reset.soon": "即將重置",
262
+ "usage.duration.days_hours": "{0}d{1}h", "usage.duration.hours_minutes": "{0}h{1}m", "usage.duration.minutes": "{0}m",
263
+ "usage.metric.session": "Session", "usage.metric.weekly": "每週", "usage.metric.monthly": "每月",
264
+ "usage.metric.days_window": "{0} 天視窗", "usage.metric.named": "{0}",
265
+ "usage.metric.named_session": "{0}(Session)", "usage.metric.named_weekly": "{0}(週)",
266
+ "usage.metric.named_monthly": "{0}(每月)", "usage.metric.named_days": "{0}({1} 天)",
267
+ "usage.metric.extra_usage": "額外用量", "usage.metric.rate_limit_resets": "額度重置券",
268
+ "usage.metric.credits": "額度", "usage.metric.weekly_limit": "每週上限",
269
+ "usage.metric.pay_as_you_go": "隨用隨付", "usage.metric.bonus_credits": "贈送額度",
270
+ "usage.metric.overage_charges": "超額費用", "usage.metric.pay_per_use": "隨用隨付",
271
+ "usage.metric.usage_monthly": "用量(每月)",
272
+ "usage.unit.available": "可用", "usage.unit.credits": "額度",
273
+ "usage.value.disabled": "已停用", "usage.value.cap": "上限 {0}",
274
+ "usage.note.binding": "生效", "usage.note.binding_severity": "生效 · {0}",
275
+ "usage.note.busiest_model": "{0} 個模型中用量最高者", "usage.note.busiest_models": "{0} 個模型中用量最高者",
276
+ "usage.note.used_limit_unit": "{0} / {1} {2}", "usage.note.bonus_codes": "{0} / {1} {2} · {3} 組代碼",
277
+ "usage.metric.agy_claude_others": "Claude 與其他模型", "usage.metric.agy_claude_others_session": "Claude 與其他模型(Session)",
278
+ "usage.metric.agy_claude_others_weekly": "Claude 與其他模型(每週)",
279
+ "usage.hint.statusline_now": "來自 {0} 的 statusline(剛剛);未呼叫 API,方案與各模型上限需要 CLI 登入資料",
280
+ "usage.hint.statusline_minutes": "來自 {0} 的 statusline({1} 分鐘前);未呼叫 API,方案與各模型上限需要 CLI 登入資料",
281
+ "usage.hint.claude_api_key": "API key 登入沒有訂閱用量資料。請使用 `claude /login`,或設定 CLAUDE_CODE_OAUTH_TOKEN(由 `claude setup-token` 取得)。",
282
+ "usage.hint.login_claude": "請使用 Claude Code CLI(`claude`)登入。",
283
+ "usage.hint.login_agy": "請使用 Antigravity CLI(`agy`)登入。", "usage.hint.no_quota": "此帳號未回報額度資訊。",
284
+ "usage.hint.login_codex": "請使用 Codex CLI(`codex`)登入。", "usage.hint.codex_no_oauth": "auth.json 沒有 OAuth 登入資料;只有 API key 時無法讀取用量。",
285
+ "usage.hint.login_grok": "請使用 Grok CLI(`grok login`)登入。", "usage.hint.grok_no_login": "auth.json 沒有可用的登入資料。請執行 `grok login`。",
286
+ "usage.hint.login_kiro": "請使用 Kiro CLI(`kiro-cli`)登入。", "usage.hint.kiro_signed_out": "目前已登出;請執行 `kiro-cli` 登入。",
287
+ "usage.hint.token_refreshing": "Token 更新中 — 請稍候再試。", "usage.hint.subscription_no_credit": "訂閱方案沒有可回報的額度用量。",
288
+ "usage.hint.no_quota_account": "此帳號類型沒有可用的額度資訊。",
289
+ "usage.error.unreachable": "無法連線至 {0}。", "usage.error.token_rejected": "Token 已被拒絕。請執行一次 `{0}` 以更新登入。",
290
+ "usage.error.rate_limited": "{0} 暫時限制請求速率,請稍後再試。", "usage.error.http": "用量請求失敗(HTTP {0})。",
291
+ "usage.error.billing_http": "計費請求失敗(HTTP {0})。", "usage.error.invalid_response": "用量端點回傳了無效資料。",
292
+ "usage.error.invalid_billing_response": "計費端點回傳了無效資料。", "usage.error.invalid_kiro_response": "GetUsageLimits 回傳了無效資料。",
293
+ "usage.error.claude_token_expired": "Access token 已過期;下次啟動任一 Claude instance 時會重新整理。",
294
+ "usage.error.codex_token_expired": "Access token 已過期。請執行一次 `codex` 以重新整理。",
295
+ "usage.error.grok_expired": "Grok session 已過期。請再次執行 `grok login`。", "usage.error.grok_response_changed": "Grok 計費回應格式已變更。",
296
+ "usage.error.agy_cap": "個人上限已用完,CLI 正受到速率限制(約 {0} 後重置)。各模型的額度池是另一組計數,因此仍可能顯示 0% 已使用。",
297
+ "usage.error.agy_no_refresh": "Access token 已過期,且未儲存 refresh token。請執行一次 `agy`。",
298
+ "usage.error.agy_token_expired": "Access token 已過期。請執行一次 `agy` 重新整理,或設定 AGY_OAUTH_CLIENT_ID/SECRET 以自動更新。",
299
+ "usage.error.agy_login_expired": "Google 登入已過期。請執行一次 `agy` 重新登入。", "usage.error.agy_refresh_empty": "Google token 更新回應沒有 access token。",
300
+ "usage.error.grok_auth_readonly": "Token 已過期且 auth.json 為唯讀。請執行一次 `grok` 重新整理。", "usage.error.grok_no_refresh": "Token 已過期且找不到 refresh token。請執行 `grok login`。",
301
+ "usage.error.grok_refresh_unreachable": "無法連線至 auth.x.ai 以更新 token。", "usage.error.grok_invalid_refresh": "auth.x.ai 回傳了無效的 token 更新資料。",
302
+ "usage.error.grok_persist": "Token 已更新但無法寫入 auth.json。請改為執行一次 `grok`。",
303
+ usageButton: "AI 訂閱用量", languageButton: "語言", helpButton: "使用說明", close: "關閉", expandProfile: "展開個人資料",
304
+ rosterFailed: "載入 instance 清單失敗:{error}\n(Fleet 是否正在執行?)", paneFailed: "⚠ 無法載入 {name} 的 pane(HTTP {status})。",
305
+ tokenRequired: "需要 web.token", avatarFailed: "上傳頭像失敗:{error}", saved: "已儲存", saveFailed: "儲存失敗:{error}" },
212
306
  };
213
307
  let lang = localStorage.getItem("agend_lang") || (navigator.language && navigator.language.toLowerCase().startsWith("zh") ? "zh-TW" : "en");
214
308
  if (!I18N[lang]) lang = "en";
215
309
  const T = (k) => (I18N[lang] && I18N[lang][k]) || I18N.en[k] || k;
310
+ const TF = (k, values = {}) => Object.entries(values).reduce((s, [name, value]) => s.replaceAll(`{${name}}`, String(value)), T(k));
216
311
  function applyI18n() {
217
312
  document.querySelectorAll("[data-i18n]").forEach(e => { e.textContent = T(e.getAttribute("data-i18n")); });
218
313
  document.querySelectorAll("[data-i18n-ph]").forEach(e => { e.setAttribute("placeholder", T(e.getAttribute("data-i18n-ph"))); });
314
+ document.querySelectorAll("[data-i18n-title]").forEach(e => { e.setAttribute("title", T(e.getAttribute("data-i18n-title"))); });
219
315
  const hc = q("helpContent");
220
316
  if (hc) { hc.innerHTML = ""; const h3 = document.createElement("h3"); h3.textContent = T("helpTitle"); hc.append(h3);
221
317
  const ul = document.createElement("ul"); for (const k of ["help1","help2","help3","help4","help5"]) { const li = document.createElement("li"); li.textContent = T(k); ul.append(li); } hc.append(ul); }
@@ -557,7 +653,7 @@
557
653
  if (!current && roster.length) current = roster[0].instance_name;
558
654
  computeOrder();
559
655
  renderList(); renderCard();
560
- } catch (e) { q("pre").textContent = "Failed to load roster: " + e.message + "\n(Is the fleet running?)"; }
656
+ } catch (e) { q("pre").textContent = TF("rosterFailed", { error: e.message }); }
561
657
  }
562
658
 
563
659
  // ── Terminal ──────────────────────────────────────────
@@ -575,7 +671,7 @@
575
671
  if (!r.ok) {
576
672
  // Surface the failure instead of leaving the previous instance's output
577
673
  // on screen (which reads as "switching did nothing").
578
- q("pre").textContent = `⚠ Could not load pane for ${target} (HTTP ${r.status}).`;
674
+ q("pre").textContent = TF("paneFailed", { name: target, status: r.status });
579
675
  return;
580
676
  }
581
677
  const text = await r.text();
@@ -714,7 +810,7 @@
714
810
  const it = roster.find(r => r.instance_name === current);
715
811
  if (!it) return;
716
812
  const wt = q("fToken").value.trim();
717
- if (!wt) { q("msg").className = "err"; q("msg").textContent = "web.token required"; return; }
813
+ if (!wt) { q("msg").className = "err"; q("msg").textContent = T("tokenRequired"); return; }
718
814
  localStorage.setItem("agend_web_token", wt);
719
815
  const name = encodeURIComponent(current);
720
816
  try {
@@ -727,12 +823,12 @@
727
823
  const file = q("fAvatar").files[0];
728
824
  if (file) {
729
825
  const ar = await fetch(`/api/avatar/${name}`, { method: "POST", headers: { "Content-Type": file.type, "X-Agend-Token": wt }, body: file });
730
- if (!ar.ok) { const e = await ar.json().catch(() => ({})); throw new Error("avatar: " + (e.error || ar.status)); }
826
+ if (!ar.ok) { const e = await ar.json().catch(() => ({})); throw new Error(TF("avatarFailed", { error: e.error || ar.status })); }
731
827
  }
732
- q("msg").className = "ok"; q("msg").textContent = "Saved";
828
+ q("msg").className = "ok"; q("msg").textContent = T("saved");
733
829
  await loadRoster();
734
830
  setTimeout(exitEdit, 500);
735
- } catch (e) { q("msg").className = "err"; q("msg").textContent = e.message; }
831
+ } catch (e) { q("msg").className = "err"; q("msg").textContent = e.message.startsWith(T("avatarFailed").split("{")[0]) ? e.message : TF("saveFailed", { error: e.message }); }
736
832
  }
737
833
 
738
834
  q("editBtn").onclick = enterEdit;
@@ -783,19 +879,32 @@
783
879
  if (!iso) return "";
784
880
  const ms = new Date(iso).getTime() - Date.now();
785
881
  if (isNaN(ms)) return "";
786
- if (ms <= 0) return T("usageSoon");
787
- const h = Math.floor(ms / 3600000), m = Math.floor((ms % 3600000) / 60000);
788
- const t = h >= 48 ? `${Math.floor(h / 24)}d ${h % 24}h` : h > 0 ? `${h}h ${m}m` : `${m}m`;
789
- return T("usageResets").replace("{t}", t);
882
+ if (ms <= 0) return T("usage.reset.soon");
883
+ const totalMinutes = Math.max(1, Math.ceil(ms / 60000));
884
+ const d = Math.floor(totalMinutes / 1440), h = Math.floor((totalMinutes % 1440) / 60), m = totalMinutes % 60;
885
+ const duration = totalMinutes >= 2880
886
+ ? usageLocalized("", { key: "usage.duration.days_hours", args: [d, h] })
887
+ : totalMinutes >= 60
888
+ ? usageLocalized("", { key: "usage.duration.hours_minutes", args: [Math.floor(totalMinutes / 60), m] })
889
+ : usageLocalized("", { key: "usage.duration.minutes", args: [totalMinutes] });
890
+ return usageLocalized("", { key: "usage.reset.in", args: [duration] });
891
+ }
892
+
893
+ function usageLocalized(fallback, ref) {
894
+ if (!ref || typeof ref.key !== "string") return fallback == null ? "" : String(fallback);
895
+ const args = Array.isArray(ref.args) ? ref.args : [];
896
+ return args.reduce((text, value, index) => text.replaceAll(`{${index}}`, String(value)), T(ref.key));
790
897
  }
791
898
 
792
899
  function usageMetricHtml(m) {
900
+ const label = usageLocalized(m.label, m.labelI18n);
901
+ const note = m.note ? usageLocalized(m.note, m.noteI18n) : "";
793
902
  if (m.type === "percent") {
794
903
  const pct = Math.min(100, Math.max(0, m.used ?? 0));
795
904
  const cls = pct >= 90 ? "crit" : pct >= 70 ? "warn" : "";
796
905
  const word = pct >= 90 ? T("usageNear") : pct >= 70 ? T("usageHigh") : "";
797
- const sub = [m.note, usageResetText(m.resetsAt)].filter(Boolean).join(" · ");
798
- return `<div class="u-metric"><div class="u-row"><span class="u-label">${esc(m.label)}</span>` +
906
+ const sub = [note, usageResetText(m.resetsAt)].filter(Boolean).join(" · ");
907
+ return `<div class="u-metric"><div class="u-row"><span class="u-label">${esc(label)}</span>` +
799
908
  (word ? `<span class="u-status ${cls}">${esc(word)}</span>` : "") +
800
909
  `<span class="u-val">${pct.toFixed(0)}%</span></div>` +
801
910
  `<div class="u-meter"><div class="u-fill ${cls}" style="width:${pct}%"></div></div>` +
@@ -803,19 +912,22 @@
803
912
  }
804
913
  if (m.type === "dollars") {
805
914
  const val = m.limit ? `$${(m.used ?? 0).toFixed(2)} / $${m.limit.toFixed(2)}` : `$${(m.used ?? 0).toFixed(2)}`;
806
- return `<div class="u-metric"><div class="u-row"><span class="u-label">${esc(m.label)}</span><span class="u-val">${esc(val)}</span></div></div>`;
915
+ return `<div class="u-metric"><div class="u-row"><span class="u-label">${esc(label)}</span><span class="u-val">${esc(val)}</span></div>` +
916
+ (note ? `<div class="u-sub">${esc(note)}</div>` : "") + `</div>`;
807
917
  }
808
- const val = `${m.value ?? ""} ${m.unit ?? ""}`.trim();
809
- return `<div class="u-metric"><div class="u-row"><span class="u-label">${esc(m.label)}</span><span class="u-val">${esc(val)}</span></div>` +
810
- (m.note ? `<div class="u-sub">${esc(m.note)}</div>` : "") + `</div>`;
918
+ const value = usageLocalized(m.value ?? "", m.valueI18n);
919
+ const unit = usageLocalized(m.unit ?? "", m.unitI18n);
920
+ const val = `${value} ${unit}`.trim();
921
+ return `<div class="u-metric"><div class="u-row"><span class="u-label">${esc(label)}</span><span class="u-val">${esc(val)}</span></div>` +
922
+ (note ? `<div class="u-sub">${esc(note)}</div>` : "") + `</div>`;
811
923
  }
812
924
 
813
925
  function renderUsage() {
814
926
  const box = q("usageContent");
815
- if (!usageData || !Array.isArray(usageData.providers)) { box.innerHTML = `<h3>${T("usageTitle")}</h3><div class="u-err">${T("usageFail")}</div>`; return; }
816
- let html = `<h3>${T("usageTitle")}</h3>`;
927
+ if (!usageData || !Array.isArray(usageData.providers)) { box.innerHTML = `<h3>📊 ${T("usage.title")}</h3><div class="u-err">${T("usageFail")}</div>`; return; }
928
+ let html = `<h3>📊 ${T("usage.title")}</h3>`;
817
929
  const providers = orderedUsageProviders(usageData.providers);
818
- if (!providers.length) html += `<div class="u-err">${T("usageEmpty")}</div>`;
930
+ if (!providers.length) html += `<div class="u-err">${T("usage.empty_active")}</div>`;
819
931
  for (let index = 0; index < providers.length; index++) {
820
932
  const p = providers[index];
821
933
  const key = providerKey(p);
@@ -823,13 +935,18 @@
823
935
  (p.plan ? `<span class="u-plan">${esc(p.plan)}</span>` : "") +
824
936
  `<span class="u-order"><button class="u-move" data-provider="${esc(key)}" data-delta="-1" title="${T("usageMoveUp")}" aria-label="${T("usageMoveUp")}"${index === 0 ? " disabled" : ""}>↑</button>` +
825
937
  `<button class="u-move" data-provider="${esc(key)}" data-delta="1" title="${T("usageMoveDown")}" aria-label="${T("usageMoveDown")}"${index === providers.length - 1 ? " disabled" : ""}>↓</button></span></div>`;
826
- if (p.status === "error") html += `<div class="u-err">${esc(p.error || "error")}</div>`;
938
+ if (p.status === "error") html += `<div class="u-err">${esc(usageLocalized(p.error || T("usage.error_fallback"), p.errorI18n))}</div>`;
939
+ else if (p.status === "no-credentials") {
940
+ html += `<div class="u-note">${esc(T("usage.not_logged_in"))}</div>`;
941
+ if (p.hint) html += `<div class="u-note">${esc(usageLocalized(p.hint, p.hintI18n))}</div>`;
942
+ }
827
943
  else {
828
944
  html += (p.metrics || []).map(usageMetricHtml).join("");
829
945
  // A provider with nothing to meter (subscription plan) or one awaiting
830
946
  // sign-in carries a hint instead of metrics. Without this the panel
831
947
  // rendered an empty box, so those states looked broken.
832
- if (p.hint) html += `<div class="u-note">${esc(p.hint)}</div>`;
948
+ if (p.hint) html += `<div class="u-note">${esc(usageLocalized(p.hint, p.hintI18n))}</div>`;
949
+ else if (!(p.metrics || []).length) html += `<div class="u-note">${esc(T("usage.no_data"))}</div>`;
833
950
  }
834
951
  html += `</div>`;
835
952
  }
@@ -1,4 +1,4 @@
1
- import type { UsagePayload } from "./usage-api.js";
1
+ import { type UsagePayload } from "./usage-api.js";
2
2
  /** `████░░░░░░` for 40%. Clamped — a vendor "105% used" must not overflow. */
3
3
  export declare function usageBar(percent: number): string;
4
4
  /** Discord: native Markdown in plain message content. */
@@ -1,3 +1,6 @@
1
+ import { isVisibleUsageMetric } from "./usage-api.js";
2
+ import { t } from "../locale.js";
3
+ import { usageResetText, usageText } from "./i18n.js";
1
4
  const BAR_WIDTH = 10;
2
5
  /** `████░░░░░░` for 40%. Clamped — a vendor "105% used" must not overflow. */
3
6
  export function usageBar(percent) {
@@ -22,36 +25,35 @@ function metricPercent(m) {
22
25
  return null;
23
26
  }
24
27
  function resetSuffix(resetsAt) {
25
- if (!resetsAt)
26
- return "";
27
- const at = new Date(resetsAt);
28
- if (Number.isNaN(at.getTime()))
29
- return "";
30
- const hours = Math.round((at.getTime() - Date.now()) / 3_600_000);
31
- if (hours <= 0)
32
- return "";
33
- return hours >= 48 ? ` · resets in ${Math.round(hours / 24)}d` : ` · resets in ${hours}h`;
28
+ const text = usageResetText(resetsAt);
29
+ return text ? ` · ${text}` : "";
34
30
  }
35
31
  function metricLine(m) {
36
32
  const pct = metricPercent(m);
33
+ const label = usageText(m.label, m.labelI18n);
34
+ const note = m.note ? usageText(m.note, m.noteI18n) : "";
37
35
  switch (m.type) {
38
36
  case "percent":
39
37
  return {
40
38
  bar: usageBar(pct ?? 0),
41
39
  // note explains WHICH number this is (e.g. "busiest of 8 models"); it is
42
40
  // what stops a legitimate 0% from reading as a broken meter.
43
- text: `${Math.round(m.used ?? 0)}% ${m.label}${m.note ? ` (${m.note})` : ""}${resetSuffix(m.resetsAt)}`,
41
+ text: `${Math.round(m.used ?? 0)}% ${label}${note ? ` (${note})` : ""}${resetSuffix(m.resetsAt)}`,
44
42
  };
45
43
  case "dollars": {
46
44
  const used = `$${(m.used ?? 0).toFixed(2)}`;
47
45
  return m.limit
48
- ? { bar: usageBar(pct ?? 0), text: `${used}/$${m.limit.toFixed(2)} ${m.label}` }
49
- : { bar: null, text: `${used} ${m.label}` };
46
+ ? { bar: usageBar(pct ?? 0), text: `${used}/$${m.limit.toFixed(2)} ${label}` }
47
+ : { bar: null, text: `${used} ${label}` };
48
+ }
49
+ case "count": {
50
+ const unit = m.unit ? usageText(m.unit, m.unitI18n) : "";
51
+ return { bar: null, text: `${label}: ${m.value ?? "?"}${unit ? ` ${unit}` : ""}${note ? ` (${note})` : ""}` };
52
+ }
53
+ case "text": {
54
+ const value = m.value != null ? usageText(String(m.value), m.valueI18n) : null;
55
+ return value != null ? { bar: null, text: `${label}: ${value}${note ? ` (${note})` : ""}` } : null;
50
56
  }
51
- case "count":
52
- return { bar: null, text: `${m.label}: ${m.value ?? "?"}${m.unit ? ` ${m.unit}` : ""}` };
53
- case "text":
54
- return m.value != null ? { bar: null, text: `${m.label}: ${m.value}` } : null;
55
57
  }
56
58
  }
57
59
  function toBlocks(payload) {
@@ -62,16 +64,18 @@ function toBlocks(payload) {
62
64
  // An ok row can carry a hint too — e.g. "cached 3m ago — live query is rate
63
65
  // limited" from the stale fallback. Shown under the metrics, not instead of
64
66
  // them, so old numbers still read as numbers.
65
- note: p.status === "no-credentials" ? "not logged in"
66
- : p.status === "error" ? `⚠️ ${p.error ?? "error"}`
67
+ note: p.status === "no-credentials" ? t("usage.not_logged_in")
68
+ : p.status === "error" ? `⚠️ ${usageText(p.error ?? t("usage.error_fallback"), p.errorI18n)}`
67
69
  : null,
68
- okHint: p.status === "ok" && p.hint ? p.hint : null,
69
- lines: p.status === "ok" ? p.metrics.map(metricLine).filter((l) => l !== null) : [],
70
+ okHint: p.status === "ok" && p.hint ? usageText(p.hint, p.hintI18n) : null,
71
+ lines: p.status === "ok"
72
+ ? p.metrics.filter(isVisibleUsageMetric).map(metricLine).filter((l) => l !== null)
73
+ : [],
70
74
  }));
71
75
  }
72
76
  /** Discord: native Markdown in plain message content. */
73
77
  export function renderUsageMarkdown(payload) {
74
- const out = ["📊 **AI Subscription Usage**"];
78
+ const out = [`📊 **${t("usage.title")}**`];
75
79
  for (const b of toBlocks(payload)) {
76
80
  out.push("", `${b.dot} **${b.name}**${b.plan ? ` (${b.plan})` : ""}`);
77
81
  if (b.note) {
@@ -79,7 +83,7 @@ export function renderUsageMarkdown(payload) {
79
83
  continue;
80
84
  }
81
85
  if (b.lines.length === 0) {
82
- out.push(b.okHint ? `> ${b.okHint}` : "> no data");
86
+ out.push(b.okHint ? `> ${b.okHint}` : `> ${t("usage.no_data")}`);
83
87
  continue;
84
88
  }
85
89
  for (const l of b.lines) {
@@ -99,7 +103,7 @@ function escapeHtml(s) {
99
103
  * `<` would make Telegram reject the whole message.
100
104
  */
101
105
  export function renderUsageHtml(payload) {
102
- const out = ["📊 <b>AI Subscription Usage</b>"];
106
+ const out = [`📊 <b>${escapeHtml(t("usage.title"))}</b>`];
103
107
  for (const b of toBlocks(payload)) {
104
108
  out.push("", `${b.dot} <b>${escapeHtml(b.name)}</b>${b.plan ? ` (${escapeHtml(b.plan)})` : ""}`);
105
109
  if (b.note) {
@@ -107,7 +111,7 @@ export function renderUsageHtml(payload) {
107
111
  continue;
108
112
  }
109
113
  if (b.lines.length === 0) {
110
- out.push(b.okHint ? escapeHtml(b.okHint) : "no data");
114
+ out.push(b.okHint ? escapeHtml(b.okHint) : escapeHtml(t("usage.no_data")));
111
115
  continue;
112
116
  }
113
117
  for (const l of b.lines) {
@@ -1 +1 @@
1
- {"version":3,"file":"format-rich.js","sourceRoot":"","sources":["../../src/usage/format-rich.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"format-rich.js","sourceRoot":"","sources":["../../src/usage/format-rich.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Usage copy shared by the server renderers and the browser-only View renderer.
3
+ * Keep this list explicit: the parity test rejects a key missing from either
4
+ * locale surface before a mixed-language release can ship.
5
+ */
6
+ export declare const USAGE_I18N_KEYS: readonly ["usage.title", "usage.title_plain", "usage.empty_active", "usage.not_logged_in", "usage.error_fallback", "usage.no_data", "usage.reset.in", "usage.reset.soon", "usage.duration.days_hours", "usage.duration.hours_minutes", "usage.duration.minutes", "usage.metric.session", "usage.metric.weekly", "usage.metric.monthly", "usage.metric.days_window", "usage.metric.named", "usage.metric.named_session", "usage.metric.named_weekly", "usage.metric.named_monthly", "usage.metric.named_days", "usage.metric.extra_usage", "usage.metric.rate_limit_resets", "usage.metric.credits", "usage.metric.weekly_limit", "usage.metric.pay_as_you_go", "usage.metric.bonus_credits", "usage.metric.overage_charges", "usage.metric.pay_per_use", "usage.unit.available", "usage.unit.credits", "usage.metric.usage_monthly", "usage.note.used_limit_unit", "usage.note.bonus_codes", "usage.value.disabled", "usage.value.cap", "usage.note.binding", "usage.note.binding_severity", "usage.note.busiest_model", "usage.note.busiest_models", "usage.metric.agy_claude_others", "usage.metric.agy_claude_others_session", "usage.metric.agy_claude_others_weekly", "usage.hint.statusline_now", "usage.hint.statusline_minutes", "usage.hint.claude_api_key", "usage.hint.login_claude", "usage.hint.login_agy", "usage.hint.no_quota", "usage.hint.login_codex", "usage.hint.codex_no_oauth", "usage.hint.login_grok", "usage.hint.grok_no_login", "usage.hint.login_kiro", "usage.hint.kiro_signed_out", "usage.hint.token_refreshing", "usage.hint.subscription_no_credit", "usage.hint.no_quota_account", "usage.error.unreachable", "usage.error.token_rejected", "usage.error.rate_limited", "usage.error.http", "usage.error.billing_http", "usage.error.invalid_response", "usage.error.invalid_billing_response", "usage.error.invalid_kiro_response", "usage.error.claude_token_expired", "usage.error.codex_token_expired", "usage.error.grok_expired", "usage.error.grok_response_changed", "usage.error.agy_cap", "usage.error.agy_no_refresh", "usage.error.agy_token_expired", "usage.error.agy_login_expired", "usage.error.agy_refresh_empty", "usage.error.grok_auth_readonly", "usage.error.grok_no_refresh", "usage.error.grok_refresh_unreachable", "usage.error.grok_invalid_refresh", "usage.error.grok_persist"];
7
+ export type UsageI18nKey = typeof USAGE_I18N_KEYS[number];
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Usage copy shared by the server renderers and the browser-only View renderer.
3
+ * Keep this list explicit: the parity test rejects a key missing from either
4
+ * locale surface before a mixed-language release can ship.
5
+ */
6
+ export const USAGE_I18N_KEYS = [
7
+ "usage.title", "usage.title_plain", "usage.empty_active", "usage.not_logged_in",
8
+ "usage.error_fallback", "usage.no_data", "usage.reset.in", "usage.reset.soon",
9
+ "usage.duration.days_hours", "usage.duration.hours_minutes", "usage.duration.minutes",
10
+ "usage.metric.session", "usage.metric.weekly", "usage.metric.monthly", "usage.metric.days_window",
11
+ "usage.metric.named", "usage.metric.named_session", "usage.metric.named_weekly",
12
+ "usage.metric.named_monthly", "usage.metric.named_days", "usage.metric.extra_usage",
13
+ "usage.metric.rate_limit_resets", "usage.metric.credits", "usage.metric.weekly_limit",
14
+ "usage.metric.pay_as_you_go", "usage.metric.bonus_credits", "usage.metric.overage_charges",
15
+ "usage.metric.pay_per_use", "usage.unit.available", "usage.unit.credits",
16
+ "usage.metric.usage_monthly", "usage.note.used_limit_unit", "usage.note.bonus_codes",
17
+ "usage.value.disabled", "usage.value.cap", "usage.note.binding",
18
+ "usage.note.binding_severity", "usage.note.busiest_model", "usage.note.busiest_models",
19
+ "usage.metric.agy_claude_others", "usage.metric.agy_claude_others_session", "usage.metric.agy_claude_others_weekly",
20
+ "usage.hint.statusline_now", "usage.hint.statusline_minutes", "usage.hint.claude_api_key",
21
+ "usage.hint.login_claude", "usage.hint.login_agy", "usage.hint.no_quota",
22
+ "usage.hint.login_codex", "usage.hint.codex_no_oauth", "usage.hint.login_grok",
23
+ "usage.hint.grok_no_login", "usage.hint.login_kiro", "usage.hint.kiro_signed_out",
24
+ "usage.hint.token_refreshing", "usage.hint.subscription_no_credit", "usage.hint.no_quota_account",
25
+ "usage.error.unreachable", "usage.error.token_rejected", "usage.error.rate_limited",
26
+ "usage.error.http", "usage.error.billing_http", "usage.error.invalid_response",
27
+ "usage.error.invalid_billing_response", "usage.error.invalid_kiro_response",
28
+ "usage.error.claude_token_expired", "usage.error.codex_token_expired",
29
+ "usage.error.grok_expired", "usage.error.grok_response_changed", "usage.error.agy_cap",
30
+ "usage.error.agy_no_refresh", "usage.error.agy_token_expired", "usage.error.agy_login_expired",
31
+ "usage.error.agy_refresh_empty", "usage.error.grok_auth_readonly", "usage.error.grok_no_refresh",
32
+ "usage.error.grok_refresh_unreachable", "usage.error.grok_invalid_refresh", "usage.error.grok_persist",
33
+ ];
34
+ //# sourceMappingURL=i18n-keys.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"i18n-keys.js","sourceRoot":"","sources":["../../src/usage/i18n-keys.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,aAAa,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,qBAAqB;IAC/E,sBAAsB,EAAE,eAAe,EAAE,gBAAgB,EAAE,kBAAkB;IAC7E,2BAA2B,EAAE,8BAA8B,EAAE,wBAAwB;IACrF,sBAAsB,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,0BAA0B;IACjG,oBAAoB,EAAE,4BAA4B,EAAE,2BAA2B;IAC/E,4BAA4B,EAAE,yBAAyB,EAAE,0BAA0B;IACnF,gCAAgC,EAAE,sBAAsB,EAAE,2BAA2B;IACrF,4BAA4B,EAAE,4BAA4B,EAAE,8BAA8B;IAC1F,0BAA0B,EAAE,sBAAsB,EAAE,oBAAoB;IACxE,4BAA4B,EAAE,4BAA4B,EAAE,wBAAwB;IACpF,sBAAsB,EAAE,iBAAiB,EAAE,oBAAoB;IAC/D,6BAA6B,EAAE,0BAA0B,EAAE,2BAA2B;IACtF,gCAAgC,EAAE,wCAAwC,EAAE,uCAAuC;IACnH,2BAA2B,EAAE,+BAA+B,EAAE,2BAA2B;IACzF,yBAAyB,EAAE,sBAAsB,EAAE,qBAAqB;IACxE,wBAAwB,EAAE,2BAA2B,EAAE,uBAAuB;IAC9E,0BAA0B,EAAE,uBAAuB,EAAE,4BAA4B;IACjF,6BAA6B,EAAE,mCAAmC,EAAE,6BAA6B;IACjG,yBAAyB,EAAE,4BAA4B,EAAE,0BAA0B;IACnF,kBAAkB,EAAE,0BAA0B,EAAE,8BAA8B;IAC9E,sCAAsC,EAAE,mCAAmC;IAC3E,kCAAkC,EAAE,iCAAiC;IACrE,0BAA0B,EAAE,mCAAmC,EAAE,qBAAqB;IACtF,4BAA4B,EAAE,+BAA+B,EAAE,+BAA+B;IAC9F,+BAA+B,EAAE,gCAAgC,EAAE,6BAA6B;IAChG,sCAAsC,EAAE,kCAAkC,EAAE,0BAA0B;CAC9F,CAAC"}
@@ -0,0 +1,5 @@
1
+ import type { UsageI18nRef } from "./providers.js";
2
+ /** Resolve AgEnD-owned usage copy while preserving raw vendor text as fallback. */
3
+ export declare function usageText(fallback: string, ref?: UsageI18nRef): string;
4
+ /** Minute-precision duration shared by the chat and MCP usage renderers. */
5
+ export declare function usageResetText(resetsAt?: string | null): string;
@@ -0,0 +1,27 @@
1
+ import { t } from "../locale.js";
2
+ /** Resolve AgEnD-owned usage copy while preserving raw vendor text as fallback. */
3
+ export function usageText(fallback, ref) {
4
+ return ref ? t(ref.key, ...(ref.args ?? [])) : fallback;
5
+ }
6
+ /** Minute-precision duration shared by the chat and MCP usage renderers. */
7
+ export function usageResetText(resetsAt) {
8
+ if (!resetsAt)
9
+ return "";
10
+ const at = new Date(resetsAt);
11
+ if (Number.isNaN(at.getTime()))
12
+ return "";
13
+ const remainingMs = at.getTime() - Date.now();
14
+ if (remainingMs <= 0)
15
+ return t("usage.reset.soon");
16
+ const totalMinutes = Math.max(1, Math.ceil(remainingMs / 60_000));
17
+ const days = Math.floor(totalMinutes / 1_440);
18
+ const hours = Math.floor((totalMinutes % 1_440) / 60);
19
+ const minutes = totalMinutes % 60;
20
+ const duration = totalMinutes >= 2_880
21
+ ? t("usage.duration.days_hours", days, hours)
22
+ : totalMinutes >= 60
23
+ ? t("usage.duration.hours_minutes", Math.floor(totalMinutes / 60), minutes)
24
+ : t("usage.duration.minutes", totalMinutes);
25
+ return t("usage.reset.in", duration);
26
+ }
27
+ //# sourceMappingURL=i18n.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"i18n.js","sourceRoot":"","sources":["../../src/usage/i18n.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,cAAc,CAAC;AAGjC,mFAAmF;AACnF,MAAM,UAAU,SAAS,CAAC,QAAgB,EAAE,GAAkB;IAC5D,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;AAC1D,CAAC;AAED,4EAA4E;AAC5E,MAAM,UAAU,cAAc,CAAC,QAAwB;IACrD,IAAI,CAAC,QAAQ;QAAE,OAAO,EAAE,CAAC;IACzB,MAAM,EAAE,GAAG,IAAI,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC9B,IAAI,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC;QAAE,OAAO,EAAE,CAAC;IAC1C,MAAM,WAAW,GAAG,EAAE,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAC9C,IAAI,WAAW,IAAI,CAAC;QAAE,OAAO,CAAC,CAAC,kBAAkB,CAAC,CAAC;IAEnD,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,WAAW,GAAG,MAAM,CAAC,CAAC,CAAC;IAClE,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,GAAG,KAAK,CAAC,CAAC;IAC9C,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,YAAY,GAAG,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC;IACtD,MAAM,OAAO,GAAG,YAAY,GAAG,EAAE,CAAC;IAClC,MAAM,QAAQ,GAAG,YAAY,IAAI,KAAK;QACpC,CAAC,CAAC,CAAC,CAAC,2BAA2B,EAAE,IAAI,EAAE,KAAK,CAAC;QAC7C,CAAC,CAAC,YAAY,IAAI,EAAE;YAClB,CAAC,CAAC,CAAC,CAAC,8BAA8B,EAAE,IAAI,CAAC,KAAK,CAAC,YAAY,GAAG,EAAE,CAAC,EAAE,OAAO,CAAC;YAC3E,CAAC,CAAC,CAAC,CAAC,wBAAwB,EAAE,YAAY,CAAC,CAAC;IAChD,OAAO,CAAC,CAAC,gBAAgB,EAAE,QAAQ,CAAC,CAAC;AACvC,CAAC"}
@@ -1,12 +1,20 @@
1
1
  import { type StatuslineRateLimits } from "./statusline-usage.js";
2
+ import type { UsageI18nKey } from "./i18n-keys.js";
2
3
  export interface UsageMetric {
3
4
  label: string;
5
+ /** Locale-neutral semantic text. Renderers translate this and keep `label` as a fallback. */
6
+ labelI18n?: UsageI18nRef;
7
+ /** Vendor-reported per-model quota, rather than an account's primary window. */
8
+ scope?: "model";
4
9
  type: "percent" | "dollars" | "count" | "text";
5
10
  used?: number;
6
11
  limit?: number;
7
12
  value?: number | string;
13
+ valueI18n?: UsageI18nRef;
8
14
  unit?: string;
15
+ unitI18n?: UsageI18nRef;
9
16
  note?: string;
17
+ noteI18n?: UsageI18nRef;
10
18
  resetsAt?: string | null;
11
19
  windowMs?: number | null;
12
20
  }
@@ -16,9 +24,15 @@ export interface ProviderUsage {
16
24
  status: "ok" | "error" | "no-credentials";
17
25
  plan?: string | null;
18
26
  error?: string;
27
+ errorI18n?: UsageI18nRef;
19
28
  hint?: string;
29
+ hintI18n?: UsageI18nRef;
20
30
  metrics: UsageMetric[];
21
31
  }
32
+ export interface UsageI18nRef {
33
+ key: UsageI18nKey;
34
+ args?: Array<string | number>;
35
+ }
22
36
  /** `CLAUDE_CODE_OAUTH_TOKEN` as exported in a shell rc file, or null. */
23
37
  export declare function tokenFromShellRc(read: (path: string) => string, home?: string, files?: readonly string[]): string | null;
24
38
  /**
@@ -62,6 +76,12 @@ export declare function resolveClaudeAuth(file: {
62
76
  * even live?".
63
77
  */
64
78
  export declare function statuslineUsage(reading: StatuslineRateLimits, plan: string | null, now?: number): Omit<ProviderUsage, "id" | "name">;
79
+ /**
80
+ * Best-effort OAuth access token for direct Anthropic API calls (the /model
81
+ * catalog probe). Same resolution order as the usage panel: credentials file →
82
+ * CLAUDE_CODE_OAUTH_TOKEN → shell rc. Null when nothing usable exists.
83
+ */
84
+ export declare function getClaudeOAuthToken(): Promise<string | null>;
65
85
  /** Exported for tests — the statusline/API preference order is the subject. */
66
86
  export declare function fetchClaudeUsage(): Promise<Omit<ProviderUsage, "id" | "name">>;
67
87
  interface AgyBucket {
@@ -98,6 +118,7 @@ interface AgyStoredToken {
98
118
  * uses) is read alongside `expiry` (RFC3339) for the same reason.
99
119
  */
100
120
  export declare function readAgyToken(file: unknown): AgyStoredToken;
121
+ export declare function fetchCodexUsage(): Promise<Omit<ProviderUsage, "id" | "name">>;
101
122
  interface KiroToken {
102
123
  access_token?: string;
103
124
  expires_at?: string;