@songsid/agend 2.1.12-beta.2 → 2.1.12-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 (133) hide show
  1. package/README.md +54 -8
  2. package/README.zh-TW.md +104 -11
  3. package/dist/agent-endpoint.d.ts +2 -0
  4. package/dist/agent-endpoint.js +38 -29
  5. package/dist/agent-endpoint.js.map +1 -1
  6. package/dist/backend/claude-code.d.ts +20 -0
  7. package/dist/backend/claude-code.js +84 -25
  8. package/dist/backend/claude-code.js.map +1 -1
  9. package/dist/backend/codex.d.ts +20 -0
  10. package/dist/backend/codex.js +55 -5
  11. package/dist/backend/codex.js.map +1 -1
  12. package/dist/backend/factory.js +5 -5
  13. package/dist/backend/factory.js.map +1 -1
  14. package/dist/backend/index.d.ts +0 -1
  15. package/dist/backend/index.js +0 -1
  16. package/dist/backend/index.js.map +1 -1
  17. package/dist/backend/kiro.d.ts +10 -1
  18. package/dist/backend/kiro.js +13 -0
  19. package/dist/backend/kiro.js.map +1 -1
  20. package/dist/backend/mock.d.ts +1 -1
  21. package/dist/backend/mock.js +1 -1
  22. package/dist/backend/muse.d.ts +20 -0
  23. package/dist/backend/muse.js +68 -11
  24. package/dist/backend/muse.js.map +1 -1
  25. package/dist/backend/removed.d.ts +12 -0
  26. package/dist/backend/removed.js +18 -0
  27. package/dist/backend/removed.js.map +1 -0
  28. package/dist/backend/session-signals.js +5 -10
  29. package/dist/backend/session-signals.js.map +1 -1
  30. package/dist/backend/types.d.ts +15 -1
  31. package/dist/backend/types.js +0 -1
  32. package/dist/backend/types.js.map +1 -1
  33. package/dist/channel/adapters/discord.js +9 -0
  34. package/dist/channel/adapters/discord.js.map +1 -1
  35. package/dist/channel/adapters/telegram.d.ts +14 -8
  36. package/dist/channel/adapters/telegram.js +80 -26
  37. package/dist/channel/adapters/telegram.js.map +1 -1
  38. package/dist/channel/mcp-tools.js +2 -2
  39. package/dist/channel/mcp-tools.js.map +1 -1
  40. package/dist/classic-channel-manager.js +2 -2
  41. package/dist/classic-channel-manager.js.map +1 -1
  42. package/dist/cli.js +27 -53
  43. package/dist/cli.js.map +1 -1
  44. package/dist/command-table.d.ts +1 -1
  45. package/dist/command-table.js +4 -2
  46. package/dist/command-table.js.map +1 -1
  47. package/dist/config-validator.js +48 -10
  48. package/dist/config-validator.js.map +1 -1
  49. package/dist/config.js +7 -5
  50. package/dist/config.js.map +1 -1
  51. package/dist/context-guardian.d.ts +1 -1
  52. package/dist/context-guardian.js +1 -1
  53. package/dist/cross-instance-notice.d.ts +39 -0
  54. package/dist/cross-instance-notice.js +84 -0
  55. package/dist/cross-instance-notice.js.map +1 -0
  56. package/dist/daemon.d.ts +73 -2
  57. package/dist/daemon.js +333 -31
  58. package/dist/daemon.js.map +1 -1
  59. package/dist/daily-summary.js +0 -3
  60. package/dist/daily-summary.js.map +1 -1
  61. package/dist/fleet-manager.d.ts +16 -3
  62. package/dist/fleet-manager.js +110 -53
  63. package/dist/fleet-manager.js.map +1 -1
  64. package/dist/general-knowledge/skills/fleet-config/SKILL.md +1 -1
  65. package/dist/instance-config-impact.js +3 -0
  66. package/dist/instance-config-impact.js.map +1 -1
  67. package/dist/instance-lifecycle.d.ts +9 -1
  68. package/dist/instance-lifecycle.js +62 -7
  69. package/dist/instance-lifecycle.js.map +1 -1
  70. package/dist/locale.js +30 -6
  71. package/dist/locale.js.map +1 -1
  72. package/dist/memory-pressure.d.ts +8 -2
  73. package/dist/memory-pressure.js +10 -4
  74. package/dist/memory-pressure.js.map +1 -1
  75. package/dist/outbound-handlers.js +47 -25
  76. package/dist/outbound-handlers.js.map +1 -1
  77. package/dist/outbound-schemas.d.ts +0 -1
  78. package/dist/outbound-schemas.js +3 -3
  79. package/dist/outbound-schemas.js.map +1 -1
  80. package/dist/reply-dedup.d.ts +5 -0
  81. package/dist/reply-dedup.js +9 -0
  82. package/dist/reply-dedup.js.map +1 -1
  83. package/dist/settings-api.js +5 -1
  84. package/dist/settings-api.js.map +1 -1
  85. package/dist/setup-wizard.js +0 -4
  86. package/dist/setup-wizard.js.map +1 -1
  87. package/dist/spawn-gate.js +4 -3
  88. package/dist/spawn-gate.js.map +1 -1
  89. package/dist/target-queue-worker.d.ts +1 -1
  90. package/dist/topic-commands.d.ts +64 -5
  91. package/dist/topic-commands.js +172 -14
  92. package/dist/topic-commands.js.map +1 -1
  93. package/dist/transcript-jsonl.d.ts +20 -0
  94. package/dist/transcript-jsonl.js +64 -0
  95. package/dist/transcript-jsonl.js.map +1 -0
  96. package/dist/transcript-monitor.js +21 -29
  97. package/dist/transcript-monitor.js.map +1 -1
  98. package/dist/transcript-sources.d.ts +1 -1
  99. package/dist/transcript-sources.js +29 -26
  100. package/dist/transcript-sources.js.map +1 -1
  101. package/dist/turn-reply-guard.d.ts +25 -1
  102. package/dist/turn-reply-guard.js +36 -1
  103. package/dist/turn-reply-guard.js.map +1 -1
  104. package/dist/types.d.ts +13 -4
  105. package/dist/ui/dashboard.html +3 -3
  106. package/dist/ui/settings.html +58 -16
  107. package/dist/ui/view.html +17 -10
  108. package/dist/ui/web-terminal/terminal.css +1 -1
  109. package/dist/ui/web-terminal/terminal.js +5 -1
  110. package/dist/update-check.d.ts +15 -6
  111. package/dist/update-check.js +20 -7
  112. package/dist/update-check.js.map +1 -1
  113. package/dist/usage/format-rich.js +3 -7
  114. package/dist/usage/format-rich.js.map +1 -1
  115. package/dist/usage/i18n-keys.d.ts +1 -1
  116. package/dist/usage/i18n-keys.js +1 -1
  117. package/dist/usage/i18n-keys.js.map +1 -1
  118. package/dist/usage/i18n.d.ts +5 -2
  119. package/dist/usage/i18n.js +9 -5
  120. package/dist/usage/i18n.js.map +1 -1
  121. package/dist/usage/providers.d.ts +11 -5
  122. package/dist/usage/providers.js +55 -1
  123. package/dist/usage/providers.js.map +1 -1
  124. package/dist/usage/usage-api.d.ts +0 -9
  125. package/dist/usage/usage-api.js +7 -32
  126. package/dist/usage/usage-api.js.map +1 -1
  127. package/dist/wake-coordinator.js +1 -1
  128. package/dist/web-api.js +1 -2
  129. package/dist/web-api.js.map +1 -1
  130. package/package.json +1 -1
  131. package/dist/backend/gemini-cli.d.ts +0 -20
  132. package/dist/backend/gemini-cli.js +0 -169
  133. package/dist/backend/gemini-cli.js.map +0 -1
@@ -250,7 +250,7 @@
250
250
  const $ = (id) => document.getElementById(id);
251
251
  const el = (tag, attrs = {}, ...kids) => { const e = document.createElement(tag); for (const k in attrs) { if (k === "class") e.className = attrs[k]; else if (k === "html") e.innerHTML = attrs[k]; else if (k.startsWith("on")) e.addEventListener(k.slice(2), attrs[k]); else e.setAttribute(k, attrs[k]); } for (const c of kids) if (c != null) e.append(c); return e; };
252
252
  const esc = (s) => String(s).replace(/[&<>]/g, c => ({ "&":"&amp;","<":"&lt;",">":"&gt;" }[c]));
253
- const BACKENDS = ["claude-code", "kiro-cli", "codex", "opencode", "gemini-cli", "antigravity", "grok"];
253
+ const BACKENDS = ["claude-code", "kiro-cli", "codex", "opencode", "antigravity", "grok", "muse"];
254
254
 
255
255
  // ── i18n ──
256
256
  const I18N = {
@@ -267,8 +267,8 @@
267
267
  se_src_instance: "agent", se_src_platform: "connection", se_src_builtin: "default", se_pick: "Pick…", se_useDefault: "Use the default", se_fallback: "the default is used instead",
268
268
  se_unicode: "Emoji", se_telegramOnly: "Telegram allows only these reactions", se_serverEmojis: "Server emojis", se_noServerEmojis: "No custom emojis on this server.", se_primaryServer: "primary", se_externalEmojiHint: "Another server's emoji needs the bot's Use External Emojis permission in the channel it reacts in.", se_unavailable: "unavailable",
269
269
  se_hint: "Empty keeps the default. The preview is resolved by AgEnD exactly as the bot will react.",
270
- detection: "Detection", startup: "Startup", backendSection: "Backend", advancedSection: "Advanced & Access", hangEnabled: "Hang detector enabled", hangTimeout: "Stuck timeout", agentMode: "Agent mode", toolSet: "Tool set", toolProgress: "Tool progress", replyCompletionGuard: "Require a delivered reply", replyGuardSupported: "Available for Claude Code and Kiro legacy/TUI in MCP mode.", replyGuardUnsupported: "Stored but inactive: {0} in {1} mode does not support reply-drop recovery.", logLevel: "Log level", concurrency: "Startup concurrency", staggerDelay: "Stagger delay", lightweight: "Lightweight mode", modelFailover: "Fallback model", displayName: "Display name", pause: "Pause", wake: "Wake", accessMode: "Access mode", affected: "Affected instances",
271
- language: "Language (bot replies)", defaultBackend: "Default backend", defaultModel: "Default model", allowedUsers: "Allowed users (primary bot)",
270
+ detection: "Detection", startup: "Startup", backendSection: "Backend", advancedSection: "Advanced & Access", hangEnabled: "Hang detector enabled", hangTimeout: "Stuck timeout", agentMode: "Agent mode", toolSet: "Tool set", toolProgress: "Tool progress", crossInstanceVisibility: "Bot-to-bot messages in topics", crossInstanceVisibilityHint: "full: the whole message · summary: one line · hidden: nothing. Messages are always delivered; the Mirror Topic still shows them.", replyCompletionGuard: "Require a delivered reply", replyGuardSupported: "Available for Claude Code and Kiro legacy/TUI in MCP mode.", replyGuardUnsupported: "Stored but inactive: {0} in {1} mode does not support reply-drop recovery.", logLevel: "Log level", concurrency: "Startup concurrency", staggerDelay: "Stagger delay", lightweight: "Lightweight mode", modelFailover: "Fallback model", displayName: "Display name", pause: "Pause", wake: "Wake", accessMode: "Access mode", affected: "Affected instances",
271
+ language: "Language (bot replies)", defaultBackend: "Default backend", defaultModel: "Default model", allowedUsers: "Allowed users (primary bot)", localeAuto: "Auto (follow system)",
272
272
  classicAdmins: "ClassicBot admins", allowedGuilds: "Allowed guilds", type: "Type", adapterId: "Adapter id",
273
273
  tokenEnv: "Bot token env var", groupId: "Group / guild id", nameField: "Name",
274
274
  envHint: "Put the actual token in ~/.agend/.env under this env var, then Reload Fleet.",
@@ -309,7 +309,7 @@
309
309
  signatureMismatch: "fleet.yaml and the running configuration disagree on: {0}. Restarting will not clear this — check daemon.log first.",
310
310
  applyStillWorking: "Still restarting ({0}s) — AgEnD is still working; this page keeps checking.",
311
311
  applyLostJob: "Lost track of this apply (the fleet may have restarted). Reload the page to see the current state.",
312
- changesPending: "{0} change(s) not applied", impactNow: "⚡ Immediately", impactAgent: "🔄 Restart this Agent", impactFleet: "🔄🔄 Restart AgEnD", queued: "Queued: {0}", applyFailed: "Apply failed", changesApplied: "✓ Changes applied. AgEnD is reconciling affected Agents.", reviewChanges: "Review changes", readyApply: "Ready to apply", copied: "Copied", expectedMapping: "expected a mapping", configLoadFailed: "Failed to load config — open the Settings link again.",
312
+ changesPending: "{0} change(s) not applied", impactNow: "⚡ Immediately", impactAgent: "🔄 Restart this Agent", impactFleet: "🔄🔄 Restart AgEnD", queued: "Queued: {0}", applyFailed: "Apply failed", changesApplied: "✓ Changes applied. AgEnD is reconciling affected Agents.", reviewChanges: "Review changes", backendUnavailable: "{0} (removed — choose another backend)", readyApply: "Ready to apply", copied: "Copied", expectedMapping: "expected a mapping", configLoadFailed: "Failed to load config — open the Settings link again.",
313
313
  confirmOpenAccess: "Open access allows anyone in this channel to operate the bot. Continue?", confirmLockedEmpty: "Locked access has no allowed users. This may leave nobody able to administer the bot. Continue?", accessLockedEmpty: "Locked mode has no allowed users; add at least one administrator to avoid lockout.", accessChangeCancelled: "Access mode change cancelled",
314
314
  mustNonNegative: "Must be 0 or greater", mustPositive: "Must be greater than 0", nonnegativeInteger: "Must be a non-negative integer", failoverEmpty: "Empty list disables failover", concurrencyRange: "Must be an integer from 1 to 20", concurrencyWarning: "May exceed CPU capacity on smaller hosts", staggerRange: "Must be between 0 and 30000", staggerWarning: "Very low values can cause startup spikes",
315
315
  },
@@ -326,8 +326,8 @@
326
326
  backend: "後端", model: "模型", workingDir: "工作目錄", channelBinding: "頻道綁定",
327
327
  description: "描述", systemPrompt: "System prompt", tags: "標籤", generalTopicField: "General topic(fleet 分派器)",
328
328
  runtimeResources: "執行環境與資源", autoPause: "閒置後自動暫停", minutes: "分鐘", inheritDefault: "沿用全域預設值",
329
- detection: "偵測", startup: "啟動", backendSection: "後端", advancedSection: "進階與存取", hangEnabled: "啟用卡住偵測", hangTimeout: "卡住逾時", agentMode: "Agent 模式", toolSet: "工具集", toolProgress: "工具進度", replyCompletionGuard: "要求送出回覆", replyGuardSupported: "Claude Code 與 Kiro legacy/TUI 的 MCP 模式可用。", replyGuardUnsupported: "設定會保留,但不會生效:{0} 的 {1} 模式不支援回覆遺失補救。", logLevel: "Log 等級", concurrency: "啟動併發數", staggerDelay: "錯開延遲", lightweight: "輕量模式", modelFailover: "備援模型", displayName: "顯示名稱", pause: "暫停", wake: "喚醒", accessMode: "存取模式", affected: "受影響 instances",
330
- language: "語言(bot 回覆)", defaultBackend: "預設後端", defaultModel: "預設模型", allowedUsers: "允許使用者(主 bot)",
329
+ detection: "偵測", startup: "啟動", backendSection: "後端", advancedSection: "進階與存取", hangEnabled: "啟用卡住偵測", hangTimeout: "卡住逾時", agentMode: "Agent 模式", toolSet: "工具集", toolProgress: "工具進度", crossInstanceVisibility: "Agent 之間的訊息在主題中", crossInstanceVisibilityHint: "full:完整訊息 · summary:一行摘要 · hidden:不顯示。訊息一律照常送達,Mirror Topic 也照常顯示。", replyCompletionGuard: "要求送出回覆", replyGuardSupported: "Claude Code 與 Kiro legacy/TUI 的 MCP 模式可用。", replyGuardUnsupported: "設定會保留,但不會生效:{0} 的 {1} 模式不支援回覆遺失補救。", logLevel: "Log 等級", concurrency: "啟動併發數", staggerDelay: "錯開延遲", lightweight: "輕量模式", modelFailover: "備援模型", displayName: "顯示名稱", pause: "暫停", wake: "喚醒", accessMode: "存取模式", affected: "受影響 instances",
330
+ language: "語言(bot 回覆)", defaultBackend: "預設後端", defaultModel: "預設模型", allowedUsers: "允許使用者(主 bot)", localeAuto: "自動(跟隨系統)",
331
331
  classicAdmins: "ClassicBot 管理員", allowedGuilds: "允許的伺服器", type: "類型", adapterId: "Adapter id",
332
332
  tokenEnv: "Bot token 環境變數", groupId: "群組 / guild id", nameField: "名稱",
333
333
  envHint: "把實際 token 放到 ~/.agend/.env 的這個環境變數下,然後點重新載入。",
@@ -368,7 +368,7 @@
368
368
  signatureMismatch: "fleet.yaml 與執行中的設定在這些項目上不一致:{0}。重新啟動無法解決,請先查看 daemon.log。",
369
369
  applyStillWorking: "仍在重啟中({0} 秒)—— AgEnD 還在處理,此頁面會持續確認。",
370
370
  applyLostJob: "已追蹤不到這次套用(AgEnD 可能重啟過)。請重新整理頁面查看目前狀態。",
371
- changesPending: "有 {0} 項變更尚未套用", impactNow: "⚡ 立即生效", impactAgent: "🔄 重新啟動此 Agent", impactFleet: "🔄🔄 重新啟動 AgEnD", queued: "已加入待套用:{0}", applyFailed: "套用失敗", changesApplied: "✓ 變更已套用,AgEnD 正在協調受影響的 Agent。", reviewChanges: "檢查變更", readyApply: "可套用變更", copied: "已複製", expectedMapping: "預期為 mapping", configLoadFailed: "載入設定失敗 — 請重新開啟 Settings 連結。",
371
+ changesPending: "有 {0} 項變更尚未套用", impactNow: "⚡ 立即生效", impactAgent: "🔄 重新啟動此 Agent", impactFleet: "🔄🔄 重新啟動 AgEnD", queued: "已加入待套用:{0}", applyFailed: "套用失敗", changesApplied: "✓ 變更已套用,AgEnD 正在協調受影響的 Agent。", reviewChanges: "檢查變更", backendUnavailable: "{0}(已移除,請選擇其他 backend)", readyApply: "可套用變更", copied: "已複製", expectedMapping: "預期為 mapping", configLoadFailed: "載入設定失敗 — 請重新開啟 Settings 連結。",
372
372
  confirmOpenAccess: "Open 模式會允許此頻道中的所有人操作 bot,確定要繼續嗎?", confirmLockedEmpty: "Locked 模式目前沒有允許的使用者,可能導致沒有人能管理 bot,確定要繼續嗎?", accessLockedEmpty: "Locked 模式沒有允許的使用者;建議至少加入一位管理員,避免無法操作。", accessChangeCancelled: "已取消 Access Mode 變更",
373
373
  mustNonNegative: "必須為 0 或更大的數值", mustPositive: "必須大於 0", nonnegativeInteger: "必須是非負整數", failoverEmpty: "空白清單會停用模型備援", concurrencyRange: "必須是 1 到 20 的整數", concurrencyWarning: "在較小的主機上可能超出 CPU 負荷", staggerRange: "必須介於 0 到 30000", staggerWarning: "數值太低可能造成啟動尖峰",
374
374
  },
@@ -473,6 +473,35 @@
473
473
  box.append(chips, el("div", { class: "chip-add" }, inp, el("button", { class: "sm", onclick: add }, "+ Add")));
474
474
  redraw(); return box;
475
475
  }
476
+ /**
477
+ * The backend picker keeps a current value it does not offer, such as the removed gemini-cli (#1280 review):
478
+ * otherwise the select falls to its first option and an unrelated edit would switch the instance's CLI and
479
+ * account to claude-code without anyone choosing it. The value stays until the user picks another.
480
+ */
481
+ function backendSelect(value) {
482
+ return select(value, BACKENDS.includes(value) ? BACKENDS : [{ value, label: tf("backendUnavailable", value) }, ...BACKENDS]);
483
+ }
484
+ const LOCALES = [["en", "English"], ["zh-TW", "繁體中文 (zh-TW)"]];
485
+ /**
486
+ * The locale picker adds an explicit "Auto (follow system)" option for unset (#1310):
487
+ * without it the select falls to its first option (en) and any unrelated defaults
488
+ * save writes locale: en, pinning the language and disabling timezone auto-detect.
489
+ * Like backendSelect, it also keeps a value it does not offer until the user picks another.
490
+ */
491
+ function localeSelect(value) {
492
+ const s = el("select");
493
+ const auto = el("option", {}, t("localeAuto")); auto.value = "";
494
+ if (!value) auto.selected = true;
495
+ s.append(auto);
496
+ if (value && !LOCALES.some(([v]) => v === value)) {
497
+ const unknown = el("option", {}, value); unknown.value = value; unknown.selected = true;
498
+ s.append(unknown);
499
+ }
500
+ for (const [v, lbl] of LOCALES) {
501
+ const o = el("option", {}, lbl); o.value = v; if (v === value) o.selected = true; s.append(o);
502
+ }
503
+ return s;
504
+ }
476
505
  function select(value, options) { const s = el("select"); for (const o of options) { const val = typeof o === "string" ? o : o.value; const label = typeof o === "string" ? o : o.label; const opt = el("option", {}, label); opt.value = val; if (val === value) opt.selected = true; s.append(opt); } return s; }
477
506
  const impactText = (kind) => t(kind === "now" ? "impactNow" : kind === "fleet" ? "impactFleet" : "impactAgent");
478
507
  // The server derives every field's impact from HOT_INSTANCE_CONFIG_KEYS and
@@ -1035,6 +1064,9 @@
1035
1064
  function changedFields(next, baseline) {
1036
1065
  return Object.fromEntries(Object.entries(next).filter(([key, value]) => !sameValue(value, baseline[key])));
1037
1066
  }
1067
+ // #1302: cross-instance (bot-to-bot) notices. Unset, or a value the fleet does not know, means full.
1068
+ const VISIBILITY_MODES = ["full", "summary", "hidden"];
1069
+ const visibilityDefault = (defaults) => VISIBILITY_MODES.includes(defaults?.cross_instance_visibility) ? defaults.cross_instance_visibility : "full";
1038
1070
  function overrideControl(inst, key, input, inheritedValue, impactField = `instance.${key}`) {
1039
1071
  const inherited = !hasOwn(inst, key);
1040
1072
  const toggle = el("input", { type: "checkbox" }); toggle.checked = inherited;
@@ -1151,7 +1183,7 @@
1151
1183
  function agentEditForm(name, inst) {
1152
1184
  const box = el("div", { class: "edit" });
1153
1185
  const defaults = state.fleet.defaults || {};
1154
- const fBackend = select(inst.backend || state.fleet.defaults?.backend || "claude-code", BACKENDS);
1186
+ const fBackend = backendSelect(inst.backend || state.fleet.defaults?.backend || "claude-code");
1155
1187
  const fModel = el("input", { type: "text", value: inst.model || "", placeholder: "(inherit default)" });
1156
1188
  const fWd = el("input", { type: "text", value: inst.working_directory || "" });
1157
1189
  const fChan = select(inst.channel_id || "", ["", ...channelIds()]);
@@ -1166,6 +1198,10 @@
1166
1198
  const agentMode = overrideControl(inst, "agent_mode", select(inst.agent_mode || defaults.agent_mode || "mcp", ["mcp", "cli"]), defaults.agent_mode || "mcp");
1167
1199
  const toolSet = overrideControl(inst, "tool_set", select(inst.tool_set || defaults.tool_set || "full", ["full", "standard", "minimal"]), defaults.tool_set || "full");
1168
1200
  const toolProgress = overrideControl(inst, "tool_progress", select(inst.tool_progress ?? defaults.tool_progress ?? "off", ["off", "standard", "verbose"]), defaults.tool_progress ?? "off");
1201
+ // #1302. The baseline is what the picker shows before anyone touches it, so a value it cannot show (a typo in
1202
+ // fleet.yaml, which the fleet reads as unset) is never rewritten by an unrelated edit.
1203
+ const visibility = overrideControl(inst, "cross_instance_visibility", select(inst.cross_instance_visibility ?? visibilityDefault(defaults), VISIBILITY_MODES), visibilityDefault(defaults));
1204
+ const visibilityBaseline = hasOwn(inst, "cross_instance_visibility") ? visibility.input.value : null;
1169
1205
  const fReplyGuard = el("input", { type: "checkbox" });
1170
1206
  fReplyGuard.checked = inst.reply_completion_guard ?? defaults.reply_completion_guard ?? true;
1171
1207
  const replyGuard = overrideControl(inst, "reply_completion_guard", fReplyGuard, defaults.reply_completion_guard ?? true);
@@ -1223,6 +1259,7 @@
1223
1259
  agent_mode: agentMode.toggle.checked ? null : agentMode.input.value,
1224
1260
  tool_set: toolSet.toggle.checked ? null : toolSet.input.value,
1225
1261
  tool_progress: toolProgress.toggle.checked ? null : toolProgress.input.value,
1262
+ cross_instance_visibility: visibility.toggle.checked ? null : visibility.input.value,
1226
1263
  reply_completion_guard: replyGuard.toggle.checked ? null : replyGuard.input.checked,
1227
1264
  log_level: logLevel.toggle.checked ? null : logLevel.input.value,
1228
1265
  lightweight: lightweight.toggle.checked ? null : lightweight.input.checked,
@@ -1244,6 +1281,7 @@
1244
1281
  agent_mode: hasOwn(inst, "agent_mode") ? inst.agent_mode : null,
1245
1282
  tool_set: hasOwn(inst, "tool_set") ? inst.tool_set : null,
1246
1283
  tool_progress: hasOwn(inst, "tool_progress") ? inst.tool_progress : null,
1284
+ cross_instance_visibility: visibilityBaseline,
1247
1285
  reply_completion_guard: hasOwn(inst, "reply_completion_guard") ? inst.reply_completion_guard : null,
1248
1286
  log_level: hasOwn(inst, "log_level") ? inst.log_level : null,
1249
1287
  lightweight: hasOwn(inst, "lightweight") ? inst.lightweight : null,
@@ -1281,6 +1319,7 @@
1281
1319
  el("div", {}, el("label", {}, t("agentMode"), impact("instance.agent_mode")), agentMode.row),
1282
1320
  el("div", {}, el("label", {}, t("toolSet"), impact("instance.tool_set")), toolSet.row),
1283
1321
  el("div", {}, el("label", {}, t("toolProgress"), impact("instance.tool_progress")), toolProgress.row),
1322
+ el("div", {}, el("label", {}, t("crossInstanceVisibility"), impact("instance.cross_instance_visibility")), visibility.row, el("div", { class: "hint" }, t("crossInstanceVisibilityHint"))),
1284
1323
  el("div", {}, el("label", {}, t("replyCompletionGuard"), impact("instance.reply_completion_guard")), replyGuard.row, replyHint),
1285
1324
  el("div", {}, el("label", {}, t("logLevel"), impact("instance.log_level")), logLevel.row),
1286
1325
  el("div", {}, el("label", {}, t("lightweight"), impact("instance.lightweight")), lightweight.row),
@@ -1306,7 +1345,7 @@
1306
1345
  "instance.display_name", "instance.description", "instance.backend",
1307
1346
  "instance.model", "instance.working_directory", "instance.auto_pause_after",
1308
1347
  "instance.topic_id", "instance.hang_detector", "instance.agent_mode",
1309
- "instance.tool_set", "instance.tool_progress",
1348
+ "instance.tool_set", "instance.tool_progress", "instance.cross_instance_visibility",
1310
1349
  "instance.reply_completion_guard", "instance.log_level",
1311
1350
  "instance.lightweight", "instance.model_failover", "instance.systemPrompt",
1312
1351
  "instance.tags", "instance.general_topic", "instance.status_emojis",
@@ -1650,7 +1689,7 @@
1650
1689
  const inheritedToolProgress = classicDefaults.tool_progress ?? fleetDefaults.tool_progress ?? "off";
1651
1690
  const inheritedReplyGuard = classicDefaults.reply_completion_guard ?? fleetDefaults.reply_completion_guard ?? true;
1652
1691
  const runtime = classicRuntime(c.instanceName);
1653
- const fBackend = select(c.backend || inheritedBackend, BACKENDS.filter(value => value !== "gemini-cli"));
1692
+ const fBackend = backendSelect(c.backend || inheritedBackend);
1654
1693
  const fModel = el("input", { type: "text", value: c.model || "", placeholder: inheritedModel || "(inherit default)" });
1655
1694
  const auto = overrideControl(c, "auto_pause_after", el("input", { type: "number", min: "0", step: "1", value: c.auto_pause_after ?? inheritedAutoPause, placeholder: "0 = disabled" }), inheritedAutoPause, "classic.auto_pause_after");
1656
1695
  const toolProgress = overrideControl(c, "tool_progress", select(c.tool_progress ?? inheritedToolProgress, ["off", "standard", "verbose"]), inheritedToolProgress, "classic.tool_progress");
@@ -1836,25 +1875,25 @@
1836
1875
  const allowedUsers = [...(originalPrimaryAccess.allowed_users || [])];
1837
1876
  c.admin_users = c.admin_users || []; c.allowed_guilds = c.allowed_guilds || [];
1838
1877
 
1839
- const fBackend = select(d.backend || "claude-code", BACKENDS);
1840
- const fClassicBackend = select(c.backend || d.backend || "claude-code", BACKENDS.filter(value => value !== "gemini-cli"));
1878
+ const fBackend = backendSelect(d.backend || "claude-code");
1879
+ const fClassicBackend = backendSelect(c.backend || d.backend || "claude-code");
1841
1880
  const fModel = el("input", { type: "text", value: d.model || "", placeholder: "e.g. claude-opus-4-8" });
1842
1881
  const fAgentMode = select(d.agent_mode || "mcp", ["mcp", "cli"]);
1843
1882
  const fToolSet = select(d.tool_set || "full", ["full", "standard", "minimal"]);
1844
1883
  const fToolProgress = select(d.tool_progress ?? "off", ["off", "standard", "verbose"]);
1884
+ const fVisibility = select(visibilityDefault(d), VISIBILITY_MODES);
1845
1885
  const fReplyGuard = el("input", { type: "checkbox" }); fReplyGuard.checked = d.reply_completion_guard ?? true;
1846
1886
  const fClassicToolProgress = overrideControl(c, "tool_progress", select(c.tool_progress ?? d.tool_progress ?? "off", ["off", "standard", "verbose"]), d.tool_progress ?? "off", "classic_defaults.tool_progress");
1847
1887
  const fClassicReplyInput = el("input", { type: "checkbox" }); fClassicReplyInput.checked = c.reply_completion_guard ?? d.reply_completion_guard ?? true;
1848
1888
  const fClassicReplyGuard = overrideControl(c, "reply_completion_guard", fClassicReplyInput, d.reply_completion_guard ?? true, "classic_defaults.reply_completion_guard");
1849
1889
  const fAccessMode = select(originalPrimaryAccess.mode || "locked", ["locked", "open", "pairing"]);
1850
1890
  const fLogLevel = select(d.log_level || "info", ["trace", "debug", "info", "warn", "error"]);
1851
- const fLocale = el("select");
1891
+ const fLocale = localeSelect(d.locale || "");
1852
1892
  const fAutoPause = el("input", { type: "number", min: "0", step: "1", value: d.auto_pause_after ?? 0, placeholder: "0 = disabled" });
1853
1893
  const fHangEnabled = el("input", { type: "checkbox" }); fHangEnabled.checked = hang.enabled !== false;
1854
1894
  const fHangTimeout = el("input", { type: "number", min: "0.1", step: "0.5", value: hang.timeout_minutes ?? 15 });
1855
1895
  const fConcurrency = el("input", { type: "number", min: "1", max: "20", step: "1", value: startup.concurrency ?? 10 });
1856
1896
  const fStagger = el("input", { type: "number", min: "0", max: "30000", step: "100", value: startup.stagger_delay_ms ?? 500 });
1857
- [["en", "English"], ["zh-TW", "繁體中文 (zh-TW)"]].forEach(([v, lbl]) => { const o = el("option", {}, lbl); o.value = v; if ((d.locale || "") === v) o.selected = true; fLocale.append(o); });
1858
1897
  const msg = el("span", { class: "msg" });
1859
1898
  const autoFeedback = el("div", { class: "feedback" });
1860
1899
  const hangFeedback = el("div", { class: "feedback" });
@@ -1894,11 +1933,12 @@
1894
1933
  const nextDefaults = {
1895
1934
  backend: fBackend.value,
1896
1935
  model: fModel.value || undefined,
1897
- locale: fLocale.value,
1936
+ locale: fLocale.value || null,
1898
1937
  auto_pause_after: Number(fAutoPause.value),
1899
1938
  agent_mode: fAgentMode.value,
1900
1939
  tool_set: fToolSet.value,
1901
1940
  tool_progress: fToolProgress.value,
1941
+ cross_instance_visibility: fVisibility.value,
1902
1942
  reply_completion_guard: fReplyGuard.checked,
1903
1943
  log_level: fLogLevel.value,
1904
1944
  hang_detector: { enabled: fHangEnabled.checked, timeout_minutes: Number(fHangTimeout.value) },
@@ -1907,11 +1947,12 @@
1907
1947
  const defaultsPatch = changedFields(nextDefaults, {
1908
1948
  backend: d.backend || "claude-code",
1909
1949
  model: d.model || undefined,
1910
- locale: d.locale || "",
1950
+ locale: d.locale || null,
1911
1951
  auto_pause_after: d.auto_pause_after ?? 0,
1912
1952
  agent_mode: d.agent_mode || "mcp",
1913
1953
  tool_set: d.tool_set || "full",
1914
1954
  tool_progress: d.tool_progress ?? "off",
1955
+ cross_instance_visibility: visibilityDefault(d),
1915
1956
  reply_completion_guard: d.reply_completion_guard ?? true,
1916
1957
  log_level: d.log_level || "info",
1917
1958
  hang_detector: { enabled: hang.enabled !== false, timeout_minutes: hang.timeout_minutes ?? 15 },
@@ -1959,6 +2000,7 @@
1959
2000
  el("div", { class: "field" }, el("label", {}, t("defaultModel"), impact("defaults.model")), fModel),
1960
2001
  el("div", { class: "field" }, el("label", {}, `${t("autoPause")} (${t("minutes")})`, impact("defaults.auto_pause_after")), fAutoPause, autoFeedback),
1961
2002
  el("div", { class: "field" }, el("label", {}, t("toolProgress"), impact("defaults.tool_progress")), fToolProgress),
2003
+ el("div", { class: "field" }, el("label", {}, t("crossInstanceVisibility"), impact("defaults.cross_instance_visibility")), fVisibility, el("div", { class: "hint" }, t("crossInstanceVisibilityHint"))),
1962
2004
  el("div", { class: "field" }, el("label", { style: "display:flex;align-items:center;gap:8px" }, fReplyGuard, el("span", {}, t("replyCompletionGuard")), impact("defaults.reply_completion_guard")), defaultReplyHint))),
1963
2005
  section("ClassicBot", true,
1964
2006
  el("div", { class: "grid2" },
package/dist/ui/view.html CHANGED
@@ -159,7 +159,6 @@
159
159
  /* Neutral note (subscription plan, or "sign-in needed") — deliberately not the
160
160
  amber error colour, since neither state is a failure. */
161
161
  .u-note { color: var(--dim); font-size: 13px; margin: 8px 0; }
162
- .u-next { font-size: 13px; font-weight: 600; margin: 4px 0 10px; line-height: 1.5; }
163
162
  .u-foot { color: var(--dim); font-size: 11px; margin-top: 14px; display: flex; gap: 8px; align-items: baseline; }
164
163
  .u-foot button { background: none; border: 1px solid var(--border); border-radius: 5px; color: var(--dim); cursor: pointer; font-size: 11px; padding: 2px 8px; }
165
164
  .u-foot button:hover { color: var(--fg); border-color: var(--accent); }
@@ -252,7 +251,7 @@
252
251
  usageResets: "resets in {t}", usageSoon: "resets soon", usageFail: "Could not load usage data.",
253
252
  "usage.title": "AI Subscription Usage", "usage.title_plain": "AI subscription usage", "usage.empty_active": "No active backends with usage tracking",
254
253
  "usage.not_logged_in": "not logged in", "usage.error_fallback": "error", "usage.no_data": "no data",
255
- "usage.reset.in": "resets in {0}", "usage.reset.soon": "resets soon", "usage.next_resets": "⏳ Next reset",
254
+ "usage.reset.in": "resets in {0}", "usage.reset.soon": "resets soon", "usage.ticket_expiry": "🎫 Nearest expiry: {0} (in {1})",
256
255
  "usage.duration.days_hours": "{0}d {1}h", "usage.duration.hours_minutes": "{0}h {1}m", "usage.duration.minutes": "{0}m",
257
256
  "usage.metric.session": "Session", "usage.metric.weekly": "Weekly", "usage.metric.monthly": "Monthly",
258
257
  "usage.metric.days_window": "{0}-day window", "usage.metric.named": "{0}",
@@ -316,7 +315,7 @@
316
315
  usageResets: "{t}後重置", usageSoon: "即將重置", usageFail: "無法載入用量資料。",
317
316
  "usage.title": "AI 訂閱用量", "usage.title_plain": "AI 訂閱用量", "usage.empty_active": "沒有使用中且支援用量追蹤的 Backend",
318
317
  "usage.not_logged_in": "未登入", "usage.error_fallback": "錯誤", "usage.no_data": "無資料",
319
- "usage.reset.in": "{0} 後重置", "usage.reset.soon": "即將重置", "usage.next_resets": "⏳ 下次重置",
318
+ "usage.reset.in": "{0} 後重置", "usage.reset.soon": "即將重置", "usage.ticket_expiry": "🎫 最近過期:{0}({1} 後)",
320
319
  "usage.duration.days_hours": "{0}d{1}h", "usage.duration.hours_minutes": "{0}h{1}m", "usage.duration.minutes": "{0}m",
321
320
  "usage.metric.session": "Session", "usage.metric.weekly": "每週", "usage.metric.monthly": "每月",
322
321
  "usage.metric.days_window": "{0} 天視窗", "usage.metric.named": "{0}",
@@ -1002,6 +1001,18 @@
1002
1001
  const ms = new Date(iso).getTime() - Date.now();
1003
1002
  if (isNaN(ms)) return "";
1004
1003
  if (ms <= 0) return T("usage.reset.soon");
1004
+ return usageLocalized("", { key: "usage.reset.in", args: [usageDuration(ms)] });
1005
+ }
1006
+
1007
+ // #1244: "🎫 Nearest expiry: 10/22 (in 15d 4h)" — when the soonest reset ticket expires. An expiry, not a reset.
1008
+ function usageExpiryText(iso) {
1009
+ if (!iso) return "";
1010
+ const at = new Date(iso), ms = at.getTime() - Date.now();
1011
+ if (!(ms > 0)) return "";
1012
+ return usageLocalized("", { key: "usage.ticket_expiry", args: [`${at.getMonth() + 1}/${at.getDate()}`, usageDuration(ms)] });
1013
+ }
1014
+
1015
+ function usageDuration(ms) {
1005
1016
  const totalMinutes = Math.max(1, Math.ceil(ms / 60000));
1006
1017
  const d = Math.floor(totalMinutes / 1440), h = Math.floor((totalMinutes % 1440) / 60), m = totalMinutes % 60;
1007
1018
  const duration = totalMinutes >= 2880
@@ -1009,7 +1020,7 @@
1009
1020
  : totalMinutes >= 60
1010
1021
  ? usageLocalized("", { key: "usage.duration.hours_minutes", args: [Math.floor(totalMinutes / 60), m] })
1011
1022
  : usageLocalized("", { key: "usage.duration.minutes", args: [totalMinutes] });
1012
- return usageLocalized("", { key: "usage.reset.in", args: [duration] });
1023
+ return duration;
1013
1024
  }
1014
1025
 
1015
1026
  function usageLocalized(fallback, ref) {
@@ -1040,8 +1051,9 @@
1040
1051
  const value = usageLocalized(m.value ?? "", m.valueI18n);
1041
1052
  const unit = usageLocalized(m.unit ?? "", m.unitI18n);
1042
1053
  const val = `${value} ${unit}`.trim();
1054
+ const sub = [note, usageExpiryText(m.expiresAt)].filter(Boolean).join(" · ");
1043
1055
  return `<div class="u-metric"><div class="u-row"><span class="u-label">${esc(label)}</span><span class="u-val">${esc(val)}</span></div>` +
1044
- (note ? `<div class="u-sub">${esc(note)}</div>` : "") + `</div>`;
1056
+ (sub ? `<div class="u-sub">${esc(sub)}</div>` : "") + `</div>`;
1045
1057
  }
1046
1058
 
1047
1059
  const USAGE_ICON = '<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" aria-hidden="true"><path d="M2.5 13.5h11"/><path d="M4.5 11V8"/><path d="M8 11V4.5"/><path d="M11.5 11V6.5"/></svg>';
@@ -1051,11 +1063,6 @@
1051
1063
  let html = `<h3>${USAGE_ICON}${T("usage.title")}</h3>`;
1052
1064
  const providers = orderedUsageProviders(usageData.providers);
1053
1065
  if (!providers.length) html += `<div class="u-err">${T("usage.empty_active")}</div>`;
1054
- // #1232: each backend's soonest reset, in one line at the top — "⏳ Next reset · Claude resets in 5h 12m · Codex …".
1055
- const nextResets = providers
1056
- .filter(p => p.status === "ok" && p.nextResetAt && new Date(p.nextResetAt).getTime() > Date.now())
1057
- .map(p => `${esc(p.name)} ${esc(usageResetText(p.nextResetAt))}`);
1058
- if (nextResets.length) html += `<div class="u-next">${esc(T("usage.next_resets"))} · ${nextResets.join(" · ")}</div>`;
1059
1066
  for (let index = 0; index < providers.length; index++) {
1060
1067
  const p = providers[index];
1061
1068
  const key = providerKey(p);
@@ -9,7 +9,7 @@ body { display: flex; flex-direction: column; }
9
9
  #gate input { flex: 1; font: 16px ui-monospace, monospace; letter-spacing: 1px; padding: 8px; background: #000; color: #fff; border: 1px solid #555; border-radius: 4px; }
10
10
  #gate button { padding: 8px 16px; background: #246; color: #fff; border: 0; border-radius: 4px; cursor: pointer; }
11
11
  #gate-msg { color: #f88; min-height: 1.5em; }
12
- #term { flex: 1; min-height: 0; padding: 4px; }
12
+ #term { flex: 1; min-height: 0; padding: 4px; overflow: hidden; } /* never drawn over the rows below it (#1242) */
13
13
  #code-row { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; padding: 8px 10px; background: #1c1c1c; border-top: 1px solid #333; }
14
14
  #code-row[hidden] { display: none; }
15
15
  #code-row input { flex: 1; min-width: 12em; font: 16px ui-monospace, monospace; padding: 8px; background: #000; color: #fff; border: 1px solid #555; border-radius: 4px; }
@@ -87,7 +87,11 @@
87
87
  term.onData(function (s) { send(new TextEncoder().encode(s)); });
88
88
  term.onBinary(function (s) { var b = new Uint8Array(s.length); for (var i = 0; i < s.length; i++) b[i] = s.charCodeAt(i) & 255; send(b); });
89
89
  term.onResize(function (size) { if (ws && ws.readyState === 1) ws.send(JSON.stringify({ t: "resize", cols: size.cols, rows: size.rows })); });
90
- window.addEventListener("resize", function () { if (fit) fit.fit(); });
90
+ // Re-fit whenever the terminal's box changes, not only when the window does (#1242): the sign-in code row
91
+ // appears after the first fit (on "hello"), and a terminal fitted to the taller box ran under that row and
92
+ // covered it — the code box was not on screen until a zoom change (a window resize) re-fitted it.
93
+ if (typeof ResizeObserver === "function") new ResizeObserver(function () { if (fit) fit.fit(); }).observe(termEl);
94
+ else window.addEventListener("resize", function () { if (fit) fit.fit(); });
91
95
  } else {
92
96
  term.reset(); // the server replays its buffer on (re)connect
93
97
  }
@@ -7,6 +7,8 @@ import { execFileSync } from "node:child_process";
7
7
  export declare const UPDATE_COMMAND = "agend update";
8
8
  export interface UpdateVersionOptions {
9
9
  version?: string;
10
+ /** The alpha channel (`@alpha`, the next minor's previews, #1259). */
11
+ alpha?: boolean;
10
12
  beta?: boolean;
11
13
  /** Back to the stable line (`@latest`), even from a beta install — may go back a version. */
12
14
  stable?: boolean;
@@ -23,19 +25,26 @@ export declare function isPrereleaseVersion(version: string): boolean;
23
25
  * below alphanumeric ones, which compare in ASCII order.
24
26
  */
25
27
  export declare function compareSemver(a: string, b: string): number | null;
28
+ export type UpdateChannel = "latest" | "beta" | "alpha";
29
+ /**
30
+ * The npm dist-tag an install follows (#1259): an alpha (`x.y.z-alpha.N`) is on
31
+ * `@alpha`, any other prerelease (beta, rc…) on `@beta`, a release on `@latest`.
32
+ * Mirrors what publish.yml publishes each tag to (scripts/npm-dist-tag.mjs).
33
+ */
34
+ export declare function installedChannel(version: string): UpdateChannel;
26
35
  /**
27
36
  * The npm selector `agend update` installs from. An explicit choice wins
28
- * (`--version`, then `--beta`, then `--stable`); with none, the line the
29
- * installed version is on — a prerelease install stays on `@beta`, so a beta
30
- * user is never moved to `@latest` without asking. `installedVersion` is the
37
+ * (`--version`, then `--alpha`, `--beta`, `--stable`); with none, the line the
38
+ * installed version is on — an alpha stays on `@alpha`, a beta on `@beta`, so
39
+ * nobody is moved to another channel without asking. `installedVersion` is the
31
40
  * version of the package being replaced (the CLI's own package.json), never
32
41
  * the version of whatever code happened to call it.
33
42
  */
34
43
  export declare function getUpdateSelector(opts: UpdateVersionOptions, installedVersion: string): string;
35
44
  /**
36
- * Which "update available" line to post. A beta install's `/update` stays on
37
- * the beta channel, so a newer STABLE release needs `--stable` — say so rather
38
- * than "Run: /update", which would not move it there.
45
+ * Which "update available" line to post. A beta or alpha install's `/update`
46
+ * stays on its channel, so a newer STABLE release needs `--stable` — say so
47
+ * rather than "Run: /update", which would not move it there.
39
48
  */
40
49
  export declare function updateNoticeKey(currentVersion: string, targetVersion: string): "update.available_stable" | "update.available_current";
41
50
  /**
@@ -65,27 +65,40 @@ export function compareSemver(a, b) {
65
65
  }
66
66
  return Math.sign(pa.pre.length - pb.pre.length);
67
67
  }
68
+ /**
69
+ * The npm dist-tag an install follows (#1259): an alpha (`x.y.z-alpha.N`) is on
70
+ * `@alpha`, any other prerelease (beta, rc…) on `@beta`, a release on `@latest`.
71
+ * Mirrors what publish.yml publishes each tag to (scripts/npm-dist-tag.mjs).
72
+ */
73
+ export function installedChannel(version) {
74
+ const pre = parseSemver(version)?.pre ?? [];
75
+ if (pre.length === 0)
76
+ return "latest";
77
+ return pre[0] === "alpha" ? "alpha" : "beta";
78
+ }
68
79
  /**
69
80
  * The npm selector `agend update` installs from. An explicit choice wins
70
- * (`--version`, then `--beta`, then `--stable`); with none, the line the
71
- * installed version is on — a prerelease install stays on `@beta`, so a beta
72
- * user is never moved to `@latest` without asking. `installedVersion` is the
81
+ * (`--version`, then `--alpha`, `--beta`, `--stable`); with none, the line the
82
+ * installed version is on — an alpha stays on `@alpha`, a beta on `@beta`, so
83
+ * nobody is moved to another channel without asking. `installedVersion` is the
73
84
  * version of the package being replaced (the CLI's own package.json), never
74
85
  * the version of whatever code happened to call it.
75
86
  */
76
87
  export function getUpdateSelector(opts, installedVersion) {
77
88
  if (opts.version)
78
89
  return opts.version;
90
+ if (opts.alpha)
91
+ return "alpha";
79
92
  if (opts.beta)
80
93
  return "beta";
81
94
  if (opts.stable)
82
95
  return "latest";
83
- return isPrereleaseVersion(installedVersion) ? "beta" : "latest";
96
+ return installedChannel(installedVersion);
84
97
  }
85
98
  /**
86
- * Which "update available" line to post. A beta install's `/update` stays on
87
- * the beta channel, so a newer STABLE release needs `--stable` — say so rather
88
- * than "Run: /update", which would not move it there.
99
+ * Which "update available" line to post. A beta or alpha install's `/update`
100
+ * stays on its channel, so a newer STABLE release needs `--stable` — say so
101
+ * rather than "Run: /update", which would not move it there.
89
102
  */
90
103
  export function updateNoticeKey(currentVersion, targetVersion) {
91
104
  return isPrereleaseVersion(currentVersion) && !isPrereleaseVersion(targetVersion) ? "update.available_stable" : "update.available_current";
@@ -1 +1 @@
1
- {"version":3,"file":"update-check.js","sourceRoot":"","sources":["../src/update-check.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"update-check.js","sourceRoot":"","sources":["../src/update-check.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import { isVisibleUsageMetric } from "./usage-api.js";
2
2
  import { t } from "../locale.js";
3
- import { usageNextResetText, usageResetText, usageText } from "./i18n.js";
3
+ import { usageExpiryText, usageResetText, usageText } from "./i18n.js";
4
4
  const BAR_WIDTH = 10;
5
5
  /** `████░░░░░░` for 40%. Clamped — a vendor "105% used" must not overflow. */
6
6
  export function usageBar(percent) {
@@ -48,7 +48,8 @@ function metricLine(m) {
48
48
  }
49
49
  case "count": {
50
50
  const unit = m.unit ? usageText(m.unit, m.unitI18n) : "";
51
- return { bar: null, text: `${label}: ${m.value ?? "?"}${unit ? ` ${unit}` : ""}${note ? ` (${note})` : ""}` };
51
+ const expiry = usageExpiryText(m.expiresAt);
52
+ return { bar: null, text: `${label}: ${m.value ?? "?"}${unit ? ` ${unit}` : ""}${note ? ` (${note})` : ""}${expiry ? ` · ${expiry}` : ""}` };
52
53
  }
53
54
  case "text": {
54
55
  const value = m.value != null ? usageText(String(m.value), m.valueI18n) : null;
@@ -68,7 +69,6 @@ function toBlocks(payload) {
68
69
  : p.status === "error" ? `⚠️ ${usageText(p.error ?? t("usage.error_fallback"), p.errorI18n)}`
69
70
  : null,
70
71
  okHint: p.status === "ok" && p.hint ? usageText(p.hint, p.hintI18n) : null,
71
- nextReset: p.status === "ok" ? usageNextResetText(p.nextResetAt) || null : null,
72
72
  lines: p.status === "ok"
73
73
  ? p.metrics.filter(isVisibleUsageMetric).map(metricLine).filter((l) => l !== null)
74
74
  : [],
@@ -83,8 +83,6 @@ export function renderUsageMarkdown(payload) {
83
83
  out.push(`> ${b.note}`);
84
84
  continue;
85
85
  }
86
- if (b.nextReset)
87
- out.push(b.nextReset);
88
86
  if (b.lines.length === 0) {
89
87
  out.push(b.okHint ? `> ${b.okHint}` : `> ${t("usage.no_data")}`);
90
88
  continue;
@@ -113,8 +111,6 @@ export function renderUsageHtml(payload) {
113
111
  out.push(escapeHtml(b.note));
114
112
  continue;
115
113
  }
116
- if (b.nextReset)
117
- out.push(escapeHtml(b.nextReset));
118
114
  if (b.lines.length === 0) {
119
115
  out.push(b.okHint ? escapeHtml(b.okHint) : escapeHtml(t("usage.no_data")));
120
116
  continue;
@@ -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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"}
@@ -3,5 +3,5 @@
3
3
  * Keep this list explicit: the parity test rejects a key missing from either
4
4
  * locale surface before a mixed-language release can ship.
5
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.value.unlimited", "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"];
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.ticket_expiry", "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.value.unlimited", "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
7
  export type UsageI18nKey = typeof USAGE_I18N_KEYS[number];
@@ -10,7 +10,7 @@ export const USAGE_I18N_KEYS = [
10
10
  "usage.metric.session", "usage.metric.weekly", "usage.metric.monthly", "usage.metric.days_window",
11
11
  "usage.metric.named", "usage.metric.named_session", "usage.metric.named_weekly",
12
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",
13
+ "usage.metric.rate_limit_resets", "usage.ticket_expiry", "usage.metric.credits", "usage.metric.weekly_limit",
14
14
  "usage.metric.pay_as_you_go", "usage.metric.bonus_credits", "usage.metric.overage_charges",
15
15
  "usage.metric.pay_per_use", "usage.unit.available", "usage.unit.credits",
16
16
  "usage.metric.usage_monthly", "usage.note.used_limit_unit", "usage.note.bonus_codes",
@@ -1 +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,uBAAuB,EAAE,oBAAoB;IACxF,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"}
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,qBAAqB,EAAE,sBAAsB,EAAE,2BAA2B;IAC5G,4BAA4B,EAAE,4BAA4B,EAAE,8BAA8B;IAC1F,0BAA0B,EAAE,sBAAsB,EAAE,oBAAoB;IACxE,4BAA4B,EAAE,4BAA4B,EAAE,wBAAwB;IACpF,sBAAsB,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,oBAAoB;IACxF,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"}
@@ -3,5 +3,8 @@ import type { UsageI18nRef } from "./providers.js";
3
3
  export declare function usageText(fallback: string, ref?: UsageI18nRef): string;
4
4
  /** Minute-precision duration shared by the chat and MCP usage renderers. */
5
5
  export declare function usageResetText(resetsAt?: string | null): string;
6
- /** "⏳ Next reset: 5h 12m" for a provider's nearest reset (#1232); "" when there is none still ahead. */
7
- export declare function usageNextResetText(nextResetAt?: string | null): string;
6
+ /**
7
+ * "🎫 Nearest expiry: 10/22 (in 15d 4h)" — when the soonest of a metric's tickets expires (#1244); "" when none is
8
+ * still ahead. An expiry, never a reset: the ticket is gone, nothing refills.
9
+ */
10
+ export declare function usageExpiryText(expiresAt?: string | null): string;