@songsid/agend 2.2.0-alpha.3 → 2.2.0-alpha.5

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 (74) hide show
  1. package/dist/auth-api.js +4 -0
  2. package/dist/auth-api.js.map +1 -1
  3. package/dist/discord-general.d.ts +15 -0
  4. package/dist/discord-general.js +24 -0
  5. package/dist/discord-general.js.map +1 -0
  6. package/dist/fleet-manager.d.ts +9 -0
  7. package/dist/fleet-manager.js +22 -15
  8. package/dist/fleet-manager.js.map +1 -1
  9. package/dist/locale.js +8 -2
  10. package/dist/locale.js.map +1 -1
  11. package/dist/public-link-progress.d.ts +3 -1
  12. package/dist/public-link-progress.js +15 -1
  13. package/dist/public-link-progress.js.map +1 -1
  14. package/dist/public-web-gateway.js +3 -0
  15. package/dist/public-web-gateway.js.map +1 -1
  16. package/dist/public-web-link.d.ts +4 -2
  17. package/dist/public-web-link.js +10 -8
  18. package/dist/public-web-link.js.map +1 -1
  19. package/dist/quickstart-api.js +4 -1
  20. package/dist/quickstart-api.js.map +1 -1
  21. package/dist/topic-commands.js +4 -2
  22. package/dist/topic-commands.js.map +1 -1
  23. package/dist/tunnel/cloudflared-install.d.ts +25 -1
  24. package/dist/tunnel/cloudflared-install.js +181 -10
  25. package/dist/tunnel/cloudflared-install.js.map +1 -1
  26. package/dist/tunnel/deb-extract.d.ts +9 -0
  27. package/dist/tunnel/deb-extract.js +94 -0
  28. package/dist/tunnel/deb-extract.js.map +1 -0
  29. package/dist/ui/app.html +3 -0
  30. package/dist/ui/chat-strings.js +50 -0
  31. package/dist/ui/chat-thread.js +16 -1
  32. package/dist/ui/icons/apple-touch-icon.png +0 -0
  33. package/dist/ui/icons/favicon.ico +0 -0
  34. package/dist/ui/icons/favicon.svg +8 -0
  35. package/dist/ui/image-lightbox.js +104 -0
  36. package/dist/ui/panel-chat.js +16 -54
  37. package/dist/ui/panel-details.js +146 -0
  38. package/dist/ui/panel-fleet.js +2 -1
  39. package/dist/ui/panel-settings.js +18 -0
  40. package/dist/ui/preview-panel.js +9 -4
  41. package/dist/ui/preview.js +36 -13
  42. package/dist/ui/settings-request.js +9 -0
  43. package/dist/ui/shared/app-i18n.js +4 -2
  44. package/dist/ui/shared/app-route.js +7 -2
  45. package/dist/ui/shared/app-shell.js +22 -8
  46. package/dist/ui/shared/app.css +43 -0
  47. package/dist/ui/shared/app.js +6 -0
  48. package/dist/ui/shared/header-tools.js +93 -0
  49. package/dist/ui/shared/instance-nav.js +7 -4
  50. package/dist/ui/shared/instance-switch.js +16 -0
  51. package/dist/ui/shared/panel-view.js +14 -153
  52. package/dist/ui/shared/read-stream.js +26 -0
  53. package/dist/ui/shared/ui-icons.js +1 -0
  54. package/dist/ui/shared/usage-dialog.js +125 -0
  55. package/dist/ui/shared/view-strings.js +2 -2
  56. package/dist/ui/signin.html +3 -0
  57. package/dist/update-install.js +3 -1
  58. package/dist/update-install.js.map +1 -1
  59. package/dist/web-api.d.ts +16 -0
  60. package/dist/web-api.js +31 -4
  61. package/dist/web-api.js.map +1 -1
  62. package/dist/web-icons.d.ts +21 -0
  63. package/dist/web-icons.js +38 -0
  64. package/dist/web-icons.js.map +1 -0
  65. package/dist/web-preview.d.ts +9 -0
  66. package/dist/web-preview.js +15 -9
  67. package/dist/web-preview.js.map +1 -1
  68. package/dist/web-shell-routes.d.ts +4 -0
  69. package/dist/web-shell-routes.js +9 -0
  70. package/dist/web-shell-routes.js.map +1 -1
  71. package/launcher/old-updater-note.cjs +48 -0
  72. package/launcher/postinstall.cjs +8 -1
  73. package/package.json +1 -1
  74. package/scripts/preinstall-guard.cjs +5 -2
@@ -11,6 +11,11 @@ import { t } from "./app-i18n.js";
11
11
  import { appStore, createStore, useStore } from "./app-store.js";
12
12
  import { useLease } from "./app-ctx.js";
13
13
  import { PanelHeader, setTitle, onPanelKey, signInHref } from "./app-shell.js";
14
+ import { InstanceSwitch } from "./instance-switch.js";
15
+ import { HeaderTools, VIEW_SCALE, textSizeStore } from "./header-tools.js";
16
+ import { readStream } from "./read-stream.js";
17
+ // The usage dialog's metric row lives with the dialog now (usage-dialog.js); re-exported for what imported it here.
18
+ export { UsageMetric } from "./usage-dialog.js";
14
19
  import { backendLabel, STATUS_KEYS } from "./instance-nav.js";
15
20
  import { viewStore } from "./view-roster-store.js";
16
21
  import { navigate } from "./app-nav.js";
@@ -97,32 +102,7 @@ export { viewStore };
97
102
 
98
103
  // ── The panel ──
99
104
 
100
- /**
101
- * One stream of reads under a lease (the pane, the roster, usage): one at a time, and only the newest may land. A tick
102
- * while a read is on its way is skipped; a forced read (Refresh), or one started after the last has hung STUCK_MS,
103
- * supersedes it — and a superseded read's answer is dropped at every step: its response, its body, its commit
104
- * (#1448 review: an interval alone starts overlapping reads, and lease.current() only tells navigations apart).
105
- */
106
- const STUCK_MS = 10_000;
107
- const clock = () => (typeof performance !== "undefined" ? performance.now() : Date.now());
108
- export function readStream(lease) {
109
- let gen = 0, busy = false, since = 0;
110
- return {
111
- /** A token for a new read, or 0 when this one should not start. */
112
- begin(force = false) {
113
- const at = clock();
114
- if (busy && !force && at - since < STUCK_MS) return 0;
115
- busy = true; since = at;
116
- return ++gen;
117
- },
118
- /** May this read still land? */
119
- live: (token) => token === gen && lease.current(),
120
- end(token) { if (token === gen) busy = false; },
121
- };
122
- }
123
-
124
- const DENSITY = { fit: 1, comfortable: 1.25, compact: 0.8 };
125
- const DENSITY_ORDER = ["fit", "comfortable", "compact"];
105
+ // readStream: one stream of reads under a lease (read-stream.js; View's pane and roster use it).
126
106
  const MIN_PX = 12, MAX_PX = 22;
127
107
 
128
108
  export function ViewPanel({ route, navKey }) {
@@ -134,8 +114,9 @@ export function ViewPanel({ route, navKey }) {
134
114
  const [dialog, setDialogState] = useState(null);
135
115
  const setDialog = (kind) => setDialogState(kind ? { kind, key: navKey } : null);
136
116
  const open = dialog && dialog.key === navKey ? dialog.kind : null;
137
- const [usageAvailable, setUsageAvailable] = useState(false);
138
- const [density, setDensity] = useState(DENSITY[stored("agend_view_density")] ? stored("agend_view_density") : "fit");
117
+ // #1523 N3: the text size is the page's one setting (header-tools.js); View's own extra choice is Fit.
118
+ const ts = useStore(textSizeStore);
119
+ const density = ts.viewFit ? "fit" : ts.size;
139
120
  const name = route.instance;
140
121
  const it = name ? v.roster.find((r) => r.instance_name === name) : null;
141
122
 
@@ -164,13 +145,6 @@ export function ViewPanel({ route, navKey }) {
164
145
  lease.interval(load, 5000);
165
146
  lease.on(document, "visibilitychange", () => { if (!document.hidden) load(); });
166
147
  }, [lease]);
167
- // Usage: whether the fleet offers it (a 404 means off). The read also warms the server's 5-minute cache.
168
- useEffect(() => {
169
- (async () => {
170
- try { const r = await lease.fetch("/api/ai-usage"); if (lease.current()) setUsageAvailable(r.status !== 404); }
171
- catch { /* stays hidden */ }
172
- })();
173
- }, [lease]);
174
148
  // /view on its own: the instance this browser looked at last, else the first one.
175
149
  useEffect(() => {
176
150
  if (name || !v.loaded || !v.roster.length) return;
@@ -187,15 +161,8 @@ export function ViewPanel({ route, navKey }) {
187
161
  if (f) { e.preventDefault(); f.focus(); }
188
162
  })), [lease]);
189
163
 
190
- const cycleDensity = () => {
191
- const next = DENSITY_ORDER[(DENSITY_ORDER.indexOf(density) + 1) % DENSITY_ORDER.length];
192
- store("agend_view_density", next);
193
- setDensity(next);
194
- };
195
- const densityName = tn(`density${density.charAt(0).toUpperCase()}${density.slice(1)}`);
196
- const actions = html`
197
- <button type="button" class="btn btn-ghost btn-sm" onClick=${cycleDensity} title=${tn("textSize", { size: densityName })} aria-label=${tn("textSize", { size: densityName })}><${Icon} name="type" size=${16} /><span class="hide-narrow" aria-hidden="true">${densityName}</span></button>
198
- ${usageAvailable ? html`<button type="button" class="btn btn-ghost btn-sm" onClick=${() => setDialog("usage")} aria-label=${tn("usageButton")} title=${tn("usageButton")}><${Icon} name="chart" size=${16} /><span class="hide-narrow" aria-hidden="true">${tn("usageButton")}</span></button>` : null}
164
+ // Aa and ◔ are every page's (HeaderTools); Help is View's own.
165
+ const actions = html`<${HeaderTools} view=${true} navKey=${navKey} />
199
166
  <button type="button" class="icon-btn" onClick=${() => setDialog("help")} aria-label=${tn("helpButton")} title=${tn("helpButton")}><${Icon} name="info" /></button>`;
200
167
 
201
168
  let body;
@@ -209,10 +176,10 @@ export function ViewPanel({ route, navKey }) {
209
176
 
210
177
  return html`<div class="panel p-view">
211
178
  <${PanelHeader} title=${it ? (it.display_name || it.instance_name) : tn("title")}
212
- sub=${it ? html`<span class="status"><span class=${`dot ${it.status === "running" ? "ok" : it.status === "crashed" ? "bad" : "off"}`} aria-hidden="true"></span>${tn(STATUS_KEYS[it.status] || "statusUnknown")}</span>` : null}>${actions}</${PanelHeader}>
179
+ sub=${it ? html`<span class="status"><span class=${`dot ${it.status === "running" ? "ok" : it.status === "crashed" ? "bad" : "off"}`} aria-hidden="true"></span>${tn(STATUS_KEYS[it.status] || "statusUnknown")}</span>` : null}
180
+ nav=${it && !viewOnly ? html`<${InstanceSwitch} name=${name} current="view" />` : null}>${actions}</${PanelHeader}>
213
181
  ${body}
214
182
  ${open === "edit" && it ? html`<${EditProfile} key=${navKey} it=${it} onClose=${() => setDialog(null)} />` : null}
215
- ${open === "usage" ? html`<${UsageDialog} onClose=${() => setDialog(null)} />` : null}
216
183
  ${open === "help" ? html`<${HelpDialog} onClose=${() => setDialog(null)} />` : null}
217
184
  </div>`;
218
185
  }
@@ -234,7 +201,7 @@ function Terminal({ name, lease, density }) {
234
201
  const lh = parseFloat(pcs.lineHeight) / parseFloat(pcs.fontSize);
235
202
  const lineH = Number.isFinite(lh) && lh > 0 ? lh : 1.2;
236
203
  let size = Math.min(innerW / (g.cols * glyphRatio(p)), innerH / (g.rows * lineH)) * 0.995;
237
- size = Math.max(MIN_PX, Math.min(size, MAX_PX)) * (DENSITY[density] || 1);
204
+ size = Math.max(MIN_PX, Math.min(size, MAX_PX)) * (density === "fit" ? 1 : VIEW_SCALE[density] || 1);
238
205
  size = Math.max(8, Math.min(size, 32));
239
206
  g.key = key;
240
207
  if (Math.abs(size - g.applied) < 0.75) return;
@@ -369,109 +336,3 @@ function HelpDialog({ onClose }) {
369
336
  <ul class="help-list">${["help1", "help2", "help3", "help4", "help5", "help6"].map((k) => html`<li key=${k}>${tn(k)}</li>`)}</ul>
370
337
  </${Dialog}>`;
371
338
  }
372
-
373
- // ── AI usage ── Every provider the fleet's logins report; refreshed every 60 s while this dialog is open (passive).
374
- const USAGE_ORDER_KEY = "agend_view_usage_order";
375
- function usageText(fallback, ref) {
376
- if (!ref || typeof ref.key !== "string") return fallback == null ? "" : String(fallback);
377
- return (Array.isArray(ref.args) ? ref.args : []).reduce((text, value, i) => text.split(`{${i}}`).join(String(value)), t(`view.${ref.key}`));
378
- }
379
- function usageDuration(ms) {
380
- const total = Math.max(1, Math.ceil(ms / 60000));
381
- const d = Math.floor(total / 1440), h = Math.floor((total % 1440) / 60), m = total % 60;
382
- if (total >= 2880) return usageText("", { key: "usage.duration.days_hours", args: [d, h] });
383
- if (total >= 60) return usageText("", { key: "usage.duration.hours_minutes", args: [Math.floor(total / 60), m] });
384
- return usageText("", { key: "usage.duration.minutes", args: [total] });
385
- }
386
- function resetText(iso) {
387
- if (!iso) return "";
388
- const ms = new Date(iso).getTime() - Date.now();
389
- if (Number.isNaN(ms)) return "";
390
- if (ms <= 0) return tn("usage.reset.soon");
391
- return usageText("", { key: "usage.reset.in", args: [usageDuration(ms)] });
392
- }
393
- function expiryText(iso) {
394
- if (!iso) return "";
395
- const at = new Date(iso), ms = at.getTime() - Date.now();
396
- if (!(ms > 0)) return "";
397
- return usageText("", { key: "usage.ticket_expiry", args: [`${at.getMonth() + 1}/${at.getDate()}`, usageDuration(ms)] });
398
- }
399
- export function UsageMetric({ m }) {
400
- const bar = useRef(null);
401
- const label = usageText(m.label, m.labelI18n);
402
- const note = m.note ? usageText(m.note, m.noteI18n) : "";
403
- const pct = m.type === "percent" ? Math.min(100, Math.max(0, m.used ?? 0)) : 0;
404
- useLayoutEffect(() => { if (bar.current) bar.current.style.width = `${pct}%`; }, [pct]); // CSSOM (#1300)
405
- if (m.type === "percent") {
406
- const cls = pct >= 90 ? "crit" : pct >= 70 ? "warn" : "";
407
- const word = pct >= 90 ? tn("usageNear") : pct >= 70 ? tn("usageHigh") : "";
408
- const sub = [note, resetText(m.resetsAt)].filter(Boolean).join(" · ");
409
- return html`<div class="u-metric"><div class="u-row"><span class="u-label">${label}</span>${word ? html`<span class=${`u-status ${cls}`}>${word}</span>` : null}
410
- <span class=${`u-pct ${cls}`}>${pct.toFixed(0)}<span class="u-unit">%</span></span></div>
411
- <div class="u-meter"><div ref=${bar} class=${`u-fill ${cls}`}></div></div>${sub ? html`<div class="u-sub">${sub}</div>` : null}</div>`;
412
- }
413
- if (m.type === "dollars") {
414
- const val = m.limit ? `$${(m.used ?? 0).toFixed(2)} / $${m.limit.toFixed(2)}` : `$${(m.used ?? 0).toFixed(2)}`;
415
- return html`<div class="u-metric"><div class="u-row"><span class="u-label">${label}</span><span class="u-val">${val}</span></div>${note ? html`<div class="u-sub">${note}</div>` : null}</div>`;
416
- }
417
- const val = `${usageText(m.value ?? "", m.valueI18n)} ${usageText(m.unit ?? "", m.unitI18n)}`.trim();
418
- const sub = [note, expiryText(m.expiresAt)].filter(Boolean).join(" · ");
419
- return html`<div class="u-metric"><div class="u-row"><span class="u-label">${label}</span><span class="u-val">${val}</span></div>${sub ? html`<div class="u-sub">${sub}</div>` : null}</div>`;
420
- }
421
- function UsageDialog({ onClose }) {
422
- const lease = useLease("usage-dialog");
423
- const [data, setData] = useState(undefined); // undefined: loading; null: failed
424
- const [order, setOrder] = useState(() => { try { const a = JSON.parse(stored(USAGE_ORDER_KEY) || "[]"); return Array.isArray(a) ? a.filter((x) => typeof x === "string") : []; } catch { return []; } });
425
- const reads = useMemo(() => readStream(lease), [lease]);
426
- // Refresh (force) supersedes a read on its way; the minute's tick waits for it.
427
- const load = async (force) => {
428
- const token = reads.begin(force);
429
- if (!token) return;
430
- try {
431
- const r = await lease.fetch(`/api/ai-usage${force ? "?force=1" : ""}`);
432
- if (!reads.live(token)) return;
433
- const d = await r.json();
434
- if (reads.live(token)) setData(d);
435
- } catch { if (reads.live(token)) setData(null); }
436
- finally { reads.end(token); }
437
- };
438
- useEffect(() => { load(false); lease.interval(() => load(false), 60_000); }, [lease]);
439
- const key = (p) => String(p.id || p.name || "");
440
- const ordered = (providers) => {
441
- const rank = new Map(order.map((id, i) => [id, i]));
442
- return providers.map((p, i) => ({ p, i })).sort((a, b) => {
443
- const ar = rank.has(key(a.p)) ? rank.get(key(a.p)) : Infinity, br = rank.has(key(b.p)) ? rank.get(key(b.p)) : Infinity;
444
- return ar === br ? a.i - b.i : ar - br;
445
- }).map((e) => e.p);
446
- };
447
- const move = (id, delta, providers) => {
448
- const ids = ordered(providers).map(key);
449
- const from = ids.indexOf(id), to = from + delta;
450
- if (from < 0 || to < 0 || to >= ids.length) return;
451
- [ids[from], ids[to]] = [ids[to], ids[from]];
452
- setOrder(ids); store(USAGE_ORDER_KEY, JSON.stringify(ids));
453
- };
454
- let content;
455
- if (data === undefined) content = html`<${Skeleton} lines=${4} />`;
456
- else if (!data || !Array.isArray(data.providers)) content = html`<${ErrorState} message=${tn("usageFail")} onRetry=${() => load(true)} />`;
457
- else {
458
- const providers = ordered(data.providers);
459
- content = html`${!providers.length ? html`<p class="note">${tn("usage.empty_active")}</p>` : null}
460
- ${providers.map((p, i) => html`<section key=${key(p)} class="u-provider">
461
- <div class="u-head"><strong>${p.name}</strong>${p.plan ? html`<span class="pill">${p.plan}</span>` : null}
462
- <span class="u-order">
463
- <button type="button" class="icon-btn" disabled=${i === 0} aria-label=${tn("usageMoveUp")} title=${tn("usageMoveUp")} onClick=${() => move(key(p), -1, data.providers)}><${Icon} name="up" size=${14} /></button>
464
- <button type="button" class="icon-btn" disabled=${i === providers.length - 1} aria-label=${tn("usageMoveDown")} title=${tn("usageMoveDown")} onClick=${() => move(key(p), 1, data.providers)}><${Icon} name="down" size=${14} /></button>
465
- </span></div>
466
- ${p.stale ? html`<p class="note">${usageText(p.hint || "", p.hintI18n)}</p>` : null}
467
- ${p.status === "error" && !p.transient ? html`<p class="u-err">${usageText(p.error || tn("usage.error_fallback"), p.errorI18n)}</p>`
468
- : p.status === "error" && p.transient ? html`<p class="note">${usageText(p.error || tn("usage.error_fallback"), p.errorI18n)}</p>`
469
- : p.status === "no-credentials" ? html`<p class="note">${tn("usage.not_logged_in")}</p>${p.hint ? html`<p class="note">${usageText(p.hint, p.hintI18n)}</p>` : null}`
470
- : html`${(p.metrics || []).map((m, j) => html`<${UsageMetric} key=${j} m=${m} />`)}
471
- ${!p.stale && p.hint ? html`<p class="note">${usageText(p.hint, p.hintI18n)}</p>` : !(p.metrics || []).length ? html`<p class="note">${tn("usage.no_data")}</p>` : null}`}
472
- </section>`)}
473
- <div class="u-foot"><span class="note">${tn("usageUpdated")} ${new Date(data.fetchedAt).toLocaleTimeString()}</span>
474
- <button type="button" class="btn btn-sm" onClick=${() => load(true)}>${tn("usageRefresh")}</button></div>`;
475
- }
476
- return html`<${Dialog} title=${tn("usage.title")} onClose=${onClose} wide=${true}>${content}</${Dialog}>`;
477
- }
@@ -0,0 +1,26 @@
1
+ // One stream of reads under a lease (moved from panel-view.js for #1523 N3: View's pane and roster, and the usage
2
+ // dialog every page's header opens, share it).
3
+ /**
4
+ * One stream of reads under a lease (the pane, the roster, usage): one at a time, and only the newest may land. A tick
5
+ * while a read is on its way is skipped; a forced read (Refresh), or one started after the last has hung STUCK_MS,
6
+ * supersedes it — and a superseded read's answer is dropped at every step: its response, its body, its commit
7
+ * (#1448 review: an interval alone starts overlapping reads, and lease.current() only tells navigations apart).
8
+ */
9
+ const STUCK_MS = 10_000;
10
+ const clock = () => (typeof performance !== "undefined" ? performance.now() : Date.now());
11
+ export function readStream(lease) {
12
+ let gen = 0, busy = false, since = 0;
13
+ return {
14
+ /** A token for a new read, or 0 when this one should not start. */
15
+ begin(force = false) {
16
+ const at = clock();
17
+ if (busy && !force && at - since < STUCK_MS) return 0;
18
+ busy = true; since = at;
19
+ return ++gen;
20
+ },
21
+ /** May this read still land? */
22
+ live: (token) => token === gen && lease.current(),
23
+ end(token) { if (token === gen) busy = false; },
24
+ };
25
+ }
26
+
@@ -52,6 +52,7 @@ const P = {
52
52
  org: () => html`<rect x="9" y="2" width="6" height="5" rx="1"/><rect x="2" y="17" width="6" height="5" rx="1"/><rect x="16" y="17" width="6" height="5" rx="1"/><path d="M12 7v5M5 17v-5h14v5"/>`,
53
53
  panel: () => html`<rect x="3" y="4" width="18" height="16" rx="2"/><path d="M14 4v16"/>`,
54
54
  back: () => html`<path d="M19 12H5M12 19l-7-7 7-7"/>`,
55
+ forward: () => html`<path d="M5 12h14M12 5l7 7-7 7"/>`,
55
56
  external: () => html`<path d="M14 4h6v6M20 4l-9 9"/><path d="M18 14v5a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1h5"/>`,
56
57
  };
57
58
 
@@ -0,0 +1,125 @@
1
+ // #1523 N3 (§3.4): the AI usage dialog, opened from every page's header (◔). Moved from panel-view.js. Public
2
+ // (/assets/): View's anonymous reader opens it too. It reads /api/ai-usage every 60 s while open (passive, #1374).
3
+ import { html, useEffect, useLayoutEffect, useMemo, useRef, useState } from "./app-html.js";
4
+ import { t } from "./app-i18n.js";
5
+ import { useLease } from "./app-ctx.js";
6
+ import { readStream } from "./read-stream.js";
7
+ import { Dialog } from "./ui-dialog.js";
8
+ import { ErrorState, Skeleton } from "./ui-states.js";
9
+ import { Icon } from "./ui-icons.js";
10
+ import "./view-strings.js";
11
+
12
+ function tn(key, values = {}) {
13
+ let s = t(`view.${key}`);
14
+ for (const [k, v] of Object.entries(values)) s = s.split(`{${k}}`).join(String(v));
15
+ return s;
16
+ }
17
+ const stored = (k) => { try { return localStorage.getItem(k); } catch { return null; } };
18
+ const store = (k, v) => { try { localStorage.setItem(k, v); } catch { /* this page only */ } };
19
+
20
+ // ── AI usage ── Every provider the fleet's logins report; refreshed every 60 s while this dialog is open (passive).
21
+ const USAGE_ORDER_KEY = "agend_view_usage_order";
22
+ function usageText(fallback, ref) {
23
+ if (!ref || typeof ref.key !== "string") return fallback == null ? "" : String(fallback);
24
+ return (Array.isArray(ref.args) ? ref.args : []).reduce((text, value, i) => text.split(`{${i}}`).join(String(value)), t(`view.${ref.key}`));
25
+ }
26
+ function usageDuration(ms) {
27
+ const total = Math.max(1, Math.ceil(ms / 60000));
28
+ const d = Math.floor(total / 1440), h = Math.floor((total % 1440) / 60), m = total % 60;
29
+ if (total >= 2880) return usageText("", { key: "usage.duration.days_hours", args: [d, h] });
30
+ if (total >= 60) return usageText("", { key: "usage.duration.hours_minutes", args: [Math.floor(total / 60), m] });
31
+ return usageText("", { key: "usage.duration.minutes", args: [total] });
32
+ }
33
+ function resetText(iso) {
34
+ if (!iso) return "";
35
+ const ms = new Date(iso).getTime() - Date.now();
36
+ if (Number.isNaN(ms)) return "";
37
+ if (ms <= 0) return tn("usage.reset.soon");
38
+ return usageText("", { key: "usage.reset.in", args: [usageDuration(ms)] });
39
+ }
40
+ function expiryText(iso) {
41
+ if (!iso) return "";
42
+ const at = new Date(iso), ms = at.getTime() - Date.now();
43
+ if (!(ms > 0)) return "";
44
+ return usageText("", { key: "usage.ticket_expiry", args: [`${at.getMonth() + 1}/${at.getDate()}`, usageDuration(ms)] });
45
+ }
46
+ export function UsageMetric({ m }) {
47
+ const bar = useRef(null);
48
+ const label = usageText(m.label, m.labelI18n);
49
+ const note = m.note ? usageText(m.note, m.noteI18n) : "";
50
+ const pct = m.type === "percent" ? Math.min(100, Math.max(0, m.used ?? 0)) : 0;
51
+ useLayoutEffect(() => { if (bar.current) bar.current.style.width = `${pct}%`; }, [pct]); // CSSOM (#1300)
52
+ if (m.type === "percent") {
53
+ const cls = pct >= 90 ? "crit" : pct >= 70 ? "warn" : "";
54
+ const word = pct >= 90 ? tn("usageNear") : pct >= 70 ? tn("usageHigh") : "";
55
+ const sub = [note, resetText(m.resetsAt)].filter(Boolean).join(" · ");
56
+ return html`<div class="u-metric"><div class="u-row"><span class="u-label">${label}</span>${word ? html`<span class=${`u-status ${cls}`}>${word}</span>` : null}
57
+ <span class=${`u-pct ${cls}`}>${pct.toFixed(0)}<span class="u-unit">%</span></span></div>
58
+ <div class="u-meter"><div ref=${bar} class=${`u-fill ${cls}`}></div></div>${sub ? html`<div class="u-sub">${sub}</div>` : null}</div>`;
59
+ }
60
+ if (m.type === "dollars") {
61
+ const val = m.limit ? `$${(m.used ?? 0).toFixed(2)} / $${m.limit.toFixed(2)}` : `$${(m.used ?? 0).toFixed(2)}`;
62
+ return html`<div class="u-metric"><div class="u-row"><span class="u-label">${label}</span><span class="u-val">${val}</span></div>${note ? html`<div class="u-sub">${note}</div>` : null}</div>`;
63
+ }
64
+ const val = `${usageText(m.value ?? "", m.valueI18n)} ${usageText(m.unit ?? "", m.unitI18n)}`.trim();
65
+ const sub = [note, expiryText(m.expiresAt)].filter(Boolean).join(" · ");
66
+ return html`<div class="u-metric"><div class="u-row"><span class="u-label">${label}</span><span class="u-val">${val}</span></div>${sub ? html`<div class="u-sub">${sub}</div>` : null}</div>`;
67
+ }
68
+ /** `owner`: the navigation that opened it — its reads and the minute's timer live and end with it. */
69
+ export function UsageDialog({ onClose, owner = "" }) {
70
+ const lease = useLease(`usage-dialog:${owner}`);
71
+ const [data, setData] = useState(undefined); // undefined: loading; null: failed
72
+ const [order, setOrder] = useState(() => { try { const a = JSON.parse(stored(USAGE_ORDER_KEY) || "[]"); return Array.isArray(a) ? a.filter((x) => typeof x === "string") : []; } catch { return []; } });
73
+ const reads = useMemo(() => readStream(lease), [lease]);
74
+ // Refresh (force) supersedes a read on its way; the minute's tick waits for it.
75
+ const load = async (force) => {
76
+ const token = reads.begin(force);
77
+ if (!token) return;
78
+ try {
79
+ const r = await lease.fetch(`/api/ai-usage${force ? "?force=1" : ""}`);
80
+ if (!reads.live(token)) return;
81
+ const d = await r.json();
82
+ if (reads.live(token)) setData(d);
83
+ } catch { if (reads.live(token)) setData(null); }
84
+ finally { reads.end(token); }
85
+ };
86
+ useEffect(() => { load(false); lease.interval(() => load(false), 60_000); }, [lease]);
87
+ const key = (p) => String(p.id || p.name || "");
88
+ const ordered = (providers) => {
89
+ const rank = new Map(order.map((id, i) => [id, i]));
90
+ return providers.map((p, i) => ({ p, i })).sort((a, b) => {
91
+ const ar = rank.has(key(a.p)) ? rank.get(key(a.p)) : Infinity, br = rank.has(key(b.p)) ? rank.get(key(b.p)) : Infinity;
92
+ return ar === br ? a.i - b.i : ar - br;
93
+ }).map((e) => e.p);
94
+ };
95
+ const move = (id, delta, providers) => {
96
+ const ids = ordered(providers).map(key);
97
+ const from = ids.indexOf(id), to = from + delta;
98
+ if (from < 0 || to < 0 || to >= ids.length) return;
99
+ [ids[from], ids[to]] = [ids[to], ids[from]];
100
+ setOrder(ids); store(USAGE_ORDER_KEY, JSON.stringify(ids));
101
+ };
102
+ let content;
103
+ if (data === undefined) content = html`<${Skeleton} lines=${4} />`;
104
+ else if (!data || !Array.isArray(data.providers)) content = html`<${ErrorState} message=${tn("usageFail")} onRetry=${() => load(true)} />`;
105
+ else {
106
+ const providers = ordered(data.providers);
107
+ content = html`${!providers.length ? html`<p class="note">${tn("usage.empty_active")}</p>` : null}
108
+ ${providers.map((p, i) => html`<section key=${key(p)} class="u-provider">
109
+ <div class="u-head"><strong>${p.name}</strong>${p.plan ? html`<span class="pill">${p.plan}</span>` : null}
110
+ <span class="u-order">
111
+ <button type="button" class="icon-btn" disabled=${i === 0} aria-label=${tn("usageMoveUp")} title=${tn("usageMoveUp")} onClick=${() => move(key(p), -1, data.providers)}><${Icon} name="up" size=${14} /></button>
112
+ <button type="button" class="icon-btn" disabled=${i === providers.length - 1} aria-label=${tn("usageMoveDown")} title=${tn("usageMoveDown")} onClick=${() => move(key(p), 1, data.providers)}><${Icon} name="down" size=${14} /></button>
113
+ </span></div>
114
+ ${p.stale ? html`<p class="note">${usageText(p.hint || "", p.hintI18n)}</p>` : null}
115
+ ${p.status === "error" && !p.transient ? html`<p class="u-err">${usageText(p.error || tn("usage.error_fallback"), p.errorI18n)}</p>`
116
+ : p.status === "error" && p.transient ? html`<p class="note">${usageText(p.error || tn("usage.error_fallback"), p.errorI18n)}</p>`
117
+ : p.status === "no-credentials" ? html`<p class="note">${tn("usage.not_logged_in")}</p>${p.hint ? html`<p class="note">${usageText(p.hint, p.hintI18n)}</p>` : null}`
118
+ : html`${(p.metrics || []).map((m, j) => html`<${UsageMetric} key=${j} m=${m} />`)}
119
+ ${!p.stale && p.hint ? html`<p class="note">${usageText(p.hint, p.hintI18n)}</p>` : !(p.metrics || []).length ? html`<p class="note">${tn("usage.no_data")}</p>` : null}`}
120
+ </section>`)}
121
+ <div class="u-foot"><span class="note">${tn("usageUpdated")} ${new Date(data.fetchedAt).toLocaleTimeString()}</span>
122
+ <button type="button" class="btn btn-sm" onClick=${() => load(true)}>${tn("usageRefresh")}</button></div>`;
123
+ }
124
+ return html`<${Dialog} title=${tn("usage.title")} onClose=${onClose} wide=${true}>${content}</${Dialog}>`;
125
+ }
@@ -23,7 +23,7 @@ register("view", {
23
23
  "help1": "Pick an instance in the list: its live terminal shows here.",
24
24
  "help2": "Click a group's name to fold it or open it again.",
25
25
  "help3": "Edit profile changes the display name, role, description and avatar.",
26
- "help5": "Text size cycles Fit → Comfortable → Compact.",
26
+ "help5": "Text size cycles Fit → S → M → L. S, M and L are the size every page shares; Fit sizes the terminal to its box.",
27
27
  "densityFit": "Fit",
28
28
  "densityComfortable": "Comfortable",
29
29
  "densityCompact": "Compact",
@@ -180,7 +180,7 @@ register("view", {
180
180
  "help1": "在清單裡選一個 instance:它的即時終端畫面會顯示在這裡。",
181
181
  "help2": "點群組名稱可以收合或展開。",
182
182
  "help3": "「編輯個人資料」可修改顯示名稱、角色、描述和頭像。",
183
- "help5": "「字級」會在剛好填滿 → 舒適 → 精簡之間切換。",
183
+ "help5": "「字級」會在剛好填滿 → 小 → 中 → 大之間切換。小、中、大是所有頁面共用的字級;剛好填滿讓終端畫面符合框的大小。",
184
184
  "densityFit": "剛好填滿",
185
185
  "densityComfortable": "舒適",
186
186
  "densityCompact": "精簡",
@@ -6,6 +6,9 @@
6
6
  <meta name="referrer" content="no-referrer">
7
7
  <meta name="robots" content="noindex">
8
8
  <title>AgEnD — Sign in</title>
9
+ <link rel="icon" href="/favicon.ico" sizes="16x16 32x32 64x64">
10
+ <link rel="icon" href="/favicon.svg" type="image/svg+xml" sizes="any">
11
+ <link rel="apple-touch-icon" href="/apple-touch-icon.png" sizes="180x180">
9
12
  <script src="/assets/theme.js"></script>
10
13
  <link rel="stylesheet" href="/assets/tokens.css">
11
14
  <style>
@@ -198,7 +198,9 @@ export function runUpdateInstall(plan, runner) {
198
198
  // every npm call uses the same binary that will be recorded in the outcome.
199
199
  const npmBin = resolvedNpmPath ?? "npm";
200
200
  // C1: lock the prefix npm is about to change — read in the install environment, as npm itself sees it — before npm.
201
- const env = {};
201
+ // #1487: this updater never unlinks first, so a refused install keeps the previous one; the install hooks read this to
202
+ // tell that apart from AgEnD 2.1's updater, which removes it before installing (launcher/old-updater-note.cjs).
203
+ const env = { AGEND_UPDATE_KEEPS_PREVIOUS: "1" };
202
204
  let rollback;
203
205
  if (plan.lock) {
204
206
  const prefix = inInstallEnv(runner, plan, [npmBin, "prefix", "-g"], { timeoutMs: 15_000 });
@@ -1 +1 @@
1
- {"version":3,"file":"update-install.js","sourceRoot":"","sources":["../src/update-install.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"update-install.js","sourceRoot":"","sources":["../src/update-install.ts"],"names":[],"mappings":"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"}
package/dist/web-api.d.ts CHANGED
@@ -33,6 +33,7 @@ export interface WebApiContext {
33
33
  };
34
34
  web?: {
35
35
  echo_to_channel?: boolean;
36
+ usage_panel?: boolean;
36
37
  };
37
38
  defaults?: {
38
39
  backend?: string;
@@ -81,6 +82,15 @@ export interface WebApiContext {
81
82
  getInstanceStatus(name: string): "running" | "paused" | "stopped" | "crashed";
82
83
  /** A ClassicBot room (registered in classicBot.yaml, not fleet.yaml) — shown on the dashboard like any instance. */
83
84
  isClassicInstance?(name: string): boolean;
85
+ /** #1523 N2: a ClassicBot room's own summary for Details (classicBot.yaml, not fleet.yaml), or null. */
86
+ classicRoomFor?(name: string): {
87
+ name: string;
88
+ channel_id: string;
89
+ adapter_id: string | null;
90
+ backend: string;
91
+ display_name: string | null;
92
+ description: string | null;
93
+ } | null;
84
94
  /**
85
95
  * Post an owner web-chat echo to `instance`'s opted-in ClassicBot channels
86
96
  * (#1320 part B). Resolves the entries and adapters itself; returns how
@@ -197,6 +207,12 @@ export interface AppShellContext {
197
207
  previewForUi?(hostHeader: string | undefined, secure: boolean): (PreviewAvailability & {
198
208
  boot: string | null;
199
209
  }) | null;
210
+ /** #1523 N3: `web.usage_panel` — the header's ◔ is offered unless it is false (the page needs no probe read for it). */
211
+ readonly fleetConfig?: {
212
+ web?: {
213
+ usage_panel?: boolean;
214
+ };
215
+ } | null;
200
216
  }
201
217
  export type AppShellMode = "full" | "view-only";
202
218
  /** The app shell page for one entry, under the panels' CSP; it may frame exactly <preview origin>/frame, and only
package/dist/web-api.js CHANGED
@@ -621,11 +621,16 @@ export function handleWebRequest(req, res, url, ctx) {
621
621
  const detailMatch = path.match(/^\/ui\/instance\/(.+)$/);
622
622
  if (method === "GET" && detailMatch) {
623
623
  const name = decodeURIComponent(detailMatch[1]);
624
- const config = ctx.fleetConfig?.instances[name];
625
- if (!config) {
624
+ // An own key only: an inherited name ("constructor") is no instance. #1523 N2: a ClassicBot room is one too — its
625
+ // own summary (classicBot.yaml), never read as a fleet.yaml agent.
626
+ const instances = ctx.fleetConfig?.instances ?? {};
627
+ const fleetConfig = Object.prototype.hasOwnProperty.call(instances, name) ? instances[name] : undefined;
628
+ const room = fleetConfig ? null : ctx.classicRoomFor?.(name) ?? null;
629
+ if (!fleetConfig && !room) {
626
630
  json(res, 404, { error: `Instance not found: ${name}` });
627
631
  return true;
628
632
  }
633
+ const config = fleetConfig ?? { working_directory: "", backend: room.backend, display_name: room.display_name ?? undefined, description: room.description ?? undefined };
629
634
  const statusFile = join(ctx.getInstanceDir(name), "statusline.json");
630
635
  let statusline = {};
631
636
  try {
@@ -650,12 +655,30 @@ export function handleWebRequest(req, res, url, ctx) {
650
655
  const effortResolved = ctx.resolveInstanceEffort?.(name);
651
656
  const effort = (effortStrategy === "unsupported" || isAgy) ? null : (effortResolved?.effort ?? null);
652
657
  const effort_source = (effortStrategy === "unsupported" || isAgy) ? null : (effortResolved?.source ?? "unset");
658
+ // The instance's other fleet.yaml fields this read shows (the context's type names only the ones it always needed).
659
+ const more = config;
660
+ // Where it is bound, as the fleet resolves it (getInstanceAdapterId): no channel_id means the first connection —
661
+ // "web only" only when the fleet has none (#1561 review).
662
+ const fc = ctx.fleetConfig;
663
+ const connections = fc?.channels ?? (fc?.channel ? [fc.channel] : []);
664
+ const first = connections[0] ? (connections[0].id ?? connections[0].type ?? null) : null;
665
+ const explicit = typeof more.channel_id === "string" ? more.channel_id : null;
653
666
  json(res, 200, {
654
667
  name,
655
668
  status: ctx.getInstanceStatus(name),
656
669
  description: config.description,
657
670
  display_name: config.display_name,
658
- working_directory: config.working_directory,
671
+ working_directory: room ? null : config.working_directory,
672
+ // #1523 N2 (Q1 = B): the read-only config summary on Details — tags and where it is bound. Nothing secret.
673
+ kind: room ? "classic" : "agent",
674
+ tags: room ? ["classic"] : Array.isArray(more.tags) ? more.tags.filter((x) => typeof x === "string") : [],
675
+ binding: room ? null : {
676
+ channel_id: explicit ?? first,
677
+ implicit: explicit === null && first !== null, // bound to the first connection by default
678
+ topic_id: config.topic_id != null ? String(config.topic_id) : null,
679
+ general_topic: more.general_topic === true,
680
+ },
681
+ ...(room ? { room: { name: room.name, channel_id: room.channel_id, adapter_id: room.adapter_id } } : {}),
659
682
  backend,
660
683
  context_pct,
661
684
  model,
@@ -1184,7 +1207,11 @@ function shellBodyTag(req, ctx, mode) {
1184
1207
  const p = shellPreview(req, ctx, mode);
1185
1208
  const attr = (v) => String(v ?? "").replace(/[&<>"']/g, c => `&#${c.charCodeAt(0)};`);
1186
1209
  return `<body data-mode="${mode}"${mode === "full" && gatewayRequestContext(req) ? ' data-web-transport="poll"' : ""} data-dashboard-origin="${attr(p?.dashboardOrigin)}" data-preview-origin="${attr(p?.previewOrigin)}"`
1187
- + ` data-preview-boot="${attr(p?.previewOrigin ? p.boot : "")}" data-preview-reason="${attr(p ? p.reason : "Previews are not available on this fleet.")}">`;
1210
+ + ` data-preview-boot="${attr(p?.previewOrigin ? p.boot : "")}" data-preview-reason="${attr(p ? p.reason : "Previews are not available on this fleet.")}"`
1211
+ // #1554: no availability asked (the public link, or not the full app) still says why, in the page's language.
1212
+ + ` data-preview-reason-code="${attr(p ? p.code ?? "" : gatewayRequestContext(req) ? "publicLink" : "notOffered")}"`
1213
+ // #1523 N3: whether the fleet serves /api/ai-usage (web.usage_panel), for every page's ◔.
1214
+ + ` data-usage-panel="${ctx.fleetConfig?.web?.usage_panel === false ? "0" : "1"}">`;
1188
1215
  }
1189
1216
  /** The app shell page for one entry, under the panels' CSP; it may frame exactly <preview origin>/frame, and only
1190
1217
  * when this load chose one. */