@songsid/agend 2.2.0-beta.10 → 2.2.0-beta.12
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.
- package/dist/agent-endpoint.js +3 -0
- package/dist/agent-endpoint.js.map +1 -1
- package/dist/agent-whats-new.js +4 -0
- package/dist/agent-whats-new.js.map +1 -1
- package/dist/auth-api.d.ts +3 -1
- package/dist/auth-api.js +15 -1
- package/dist/auth-api.js.map +1 -1
- package/dist/backend/antigravity.d.ts +5 -0
- package/dist/backend/antigravity.js +27 -13
- package/dist/backend/antigravity.js.map +1 -1
- package/dist/backend/effort-metadata.d.ts +36 -0
- package/dist/backend/effort-metadata.js +83 -13
- package/dist/backend/effort-metadata.js.map +1 -1
- package/dist/backend/launch-effort.d.ts +29 -1
- package/dist/backend/launch-effort.js +53 -6
- package/dist/backend/launch-effort.js.map +1 -1
- package/dist/backend/types.d.ts +14 -0
- package/dist/backend/types.js +10 -0
- package/dist/backend/types.js.map +1 -1
- package/dist/channel/adapters/discord.d.ts +12 -0
- package/dist/channel/adapters/discord.js +39 -2
- package/dist/channel/adapters/discord.js.map +1 -1
- package/dist/channel/adapters/telegram.d.ts +18 -0
- package/dist/channel/adapters/telegram.js +24 -3
- package/dist/channel/adapters/telegram.js.map +1 -1
- package/dist/channel/mcp-tools.js +2 -0
- package/dist/channel/mcp-tools.js.map +1 -1
- package/dist/channel/tool-router.d.ts +2 -0
- package/dist/channel/tool-router.js +1 -1
- package/dist/channel/tool-router.js.map +1 -1
- package/dist/channel/types.d.ts +16 -0
- package/dist/cli.js +34 -11
- package/dist/cli.js.map +1 -1
- package/dist/daemon.js +9 -0
- package/dist/daemon.js.map +1 -1
- package/dist/delivery-outbox.d.ts +8 -1
- package/dist/delivery-outbox.js +6 -2
- package/dist/delivery-outbox.js.map +1 -1
- package/dist/fleet-manager.d.ts +59 -3
- package/dist/fleet-manager.js +157 -22
- package/dist/fleet-manager.js.map +1 -1
- package/dist/general-knowledge/skills/model-discovery/SKILL.md +4 -1
- package/dist/instructions.js +2 -2
- package/dist/instructions.js.map +1 -1
- package/dist/locale.js +26 -0
- package/dist/locale.js.map +1 -1
- package/dist/outbound-handlers.js +21 -1
- package/dist/outbound-handlers.js.map +1 -1
- package/dist/outbound-schemas.d.ts +12 -0
- package/dist/outbound-schemas.js +12 -1
- package/dist/outbound-schemas.js.map +1 -1
- package/dist/public-web-gateway.js +3 -0
- package/dist/public-web-gateway.js.map +1 -1
- package/dist/reply-buttons-controller.d.ts +86 -5
- package/dist/reply-buttons-controller.js +271 -7
- package/dist/reply-buttons-controller.js.map +1 -1
- package/dist/reply-buttons.d.ts +48 -3
- package/dist/reply-buttons.js +105 -10
- package/dist/reply-buttons.js.map +1 -1
- package/dist/reply-polls.d.ts +85 -0
- package/dist/reply-polls.js +154 -0
- package/dist/reply-polls.js.map +1 -0
- package/dist/tool-permissions.js +3 -3
- package/dist/tool-permissions.js.map +1 -1
- package/dist/topic-commands.js +9 -4
- package/dist/topic-commands.js.map +1 -1
- package/dist/ui/chat-render.js +19 -2
- package/dist/ui/chat-store.js +35 -1
- package/dist/ui/chat-strings.js +2 -0
- package/dist/ui/chat-thread.js +42 -0
- package/dist/ui/panel-chat.js +2 -0
- package/dist/ui/panel-log.js +2 -2
- package/dist/ui/panel-settings.js +48 -1
- package/dist/ui/settings-strings.js +10 -0
- package/dist/ui/shared/app-i18n.js +1 -1
- package/dist/ui/shared/app-stream.js +4 -1
- package/dist/ui/shared/app.css +28 -5
- package/dist/ui/shared/header-tools.js +12 -4
- package/dist/ui/shared/instance-switch.js +5 -2
- package/dist/ui/shared/view-strings.js +2 -2
- package/dist/update-check.d.ts +31 -0
- package/dist/update-check.js +47 -0
- package/dist/update-check.js.map +1 -1
- package/dist/update-launch.d.ts +46 -1
- package/dist/update-launch.js +146 -3
- package/dist/update-launch.js.map +1 -1
- package/dist/web-api.d.ts +40 -2
- package/dist/web-api.js +130 -14
- package/dist/web-api.js.map +1 -1
- package/dist/web-chat-history.d.ts +12 -1
- package/dist/web-chat-history.js +29 -7
- package/dist/web-chat-history.js.map +1 -1
- package/dist/web-login.d.ts +14 -0
- package/dist/web-login.js +4 -2
- package/dist/web-login.js.map +1 -1
- package/dist/web-prefs.d.ts +18 -0
- package/dist/web-prefs.js +36 -4
- package/dist/web-prefs.js.map +1 -1
- package/dist/web-profile.d.ts +32 -0
- package/dist/web-profile.js +132 -0
- package/dist/web-profile.js.map +1 -0
- package/dist/web-session.d.ts +14 -0
- package/dist/web-session.js +10 -0
- package/dist/web-session.js.map +1 -1
- package/package.json +1 -1
|
@@ -293,7 +293,8 @@ export function DeviceSection() {
|
|
|
293
293
|
setTimeout(go, 0);
|
|
294
294
|
};
|
|
295
295
|
const publicLink = typeof document !== "undefined" && document.body && document.body.dataset.publicLink === "1";
|
|
296
|
-
return html
|
|
296
|
+
return html`<${ProfileCard} />
|
|
297
|
+
<section class="card s-device s-synced"><h3>${tn("syncedTitle")}</h3>
|
|
297
298
|
<p class="sub">${publicLink ? tn("syncedPublicLink") : tn("syncedLead")}</p>
|
|
298
299
|
<${DevicePrefs} labels=${true} />
|
|
299
300
|
${P() ? html`<label class="check"><input type="checkbox" checked=${on} onChange=${(e) => { const want = e.target.checked; setPreviewOptIn(want).then(setOn); }} />
|
|
@@ -305,6 +306,52 @@ export function DeviceSection() {
|
|
|
305
306
|
</section>`;
|
|
306
307
|
}
|
|
307
308
|
|
|
309
|
+
/**
|
|
310
|
+
* #1827: who agents see when this person writes from the web. Signed in with a code sent to their Discord or Telegram
|
|
311
|
+
* account, they are that account — its user id, and its name unless they choose another (it follows them to every
|
|
312
|
+
* device, the public link included). Otherwise "web-user", as before. The host checks a name in full and says why it
|
|
313
|
+
* refuses one; this only shows what it says.
|
|
314
|
+
*/
|
|
315
|
+
const view = (b) => ({ phase: "ready", name: b.name || "", shown: b.shown || "", id: b.id || "", bound: b.bound === true, platform: b.platform_name || "", error: "" });
|
|
316
|
+
export function ProfileCard() {
|
|
317
|
+
const [state, setState] = useState({ phase: "loading", name: "", shown: "", id: "", bound: false, platform: "", error: "" });
|
|
318
|
+
const [draft, setDraft] = useState("");
|
|
319
|
+
const lease = useLease();
|
|
320
|
+
useEffect(() => {
|
|
321
|
+
let live = true;
|
|
322
|
+
api("/ui/profile").then((r) => {
|
|
323
|
+
if (!live) return;
|
|
324
|
+
if (!r.ok || !r.body) { setState((s) => ({ ...s, phase: "unavailable" })); return; }
|
|
325
|
+
setState(view(r.body));
|
|
326
|
+
setDraft(r.body.name || "");
|
|
327
|
+
}).catch(() => { if (live) setState((s) => ({ ...s, phase: "unavailable" })); });
|
|
328
|
+
return () => { live = false; };
|
|
329
|
+
}, []);
|
|
330
|
+
if (state.phase === "unavailable") return null;
|
|
331
|
+
const save = (clear) => {
|
|
332
|
+
setState((s) => ({ ...s, phase: "saving", error: "" }));
|
|
333
|
+
api("/ui/profile", { method: "POST", body: JSON.stringify({ name: clear ? null : draft }) }).then((r) => {
|
|
334
|
+
if (lease && !lease.current()) return;
|
|
335
|
+
if (!r.ok) { setState((s) => ({ ...s, phase: "ready", error: (r.body && r.body.error) || tn("profileFailed") })); return; }
|
|
336
|
+
setState(view(r.body));
|
|
337
|
+
setDraft(r.body.name || "");
|
|
338
|
+
toast(tn("profileSaved", r.body.shown || "web-user"));
|
|
339
|
+
}).catch(() => setState((s) => ({ ...s, phase: "ready", error: tn("profileFailed") })));
|
|
340
|
+
};
|
|
341
|
+
const busy = state.phase !== "ready";
|
|
342
|
+
const changed = draft.trim() !== state.name;
|
|
343
|
+
return html`<section class="card s-device s-profile"><h3>${tn("profileTitle")}</h3>
|
|
344
|
+
<p class="sub">${state.bound ? tn("profileLeadBound") : tn("profileLeadUnbound")}</p>
|
|
345
|
+
<div class="field"><label for="profile-name">${tn("profileName")}</label>
|
|
346
|
+
<input id="profile-name" type="text" maxlength="200" autocomplete="nickname" value=${draft} disabled=${busy}
|
|
347
|
+
placeholder=${state.platform || "web-user"} aria-invalid=${state.error ? "true" : "false"} aria-describedby="profile-help"
|
|
348
|
+
onInput=${(e) => setDraft(e.target.value)} onKeyDown=${(e) => { if (e.key === "Enter" && changed && draft.trim()) save(false); }} />
|
|
349
|
+
<p class="sub" id="profile-help">${state.error ? html`<span class="err" role="alert">${state.error}</span>` : tn("profileHelp", state.shown || "web-user", state.id)}</p></div>
|
|
350
|
+
<div class="s-device-row"><button type="button" class="btn primary" disabled=${busy || !changed || !draft.trim()} onClick=${() => save(false)}>${tn("profileSave")}</button>
|
|
351
|
+
${state.name ? html`<button type="button" class="btn" disabled=${busy} onClick=${() => save(true)}>${state.bound ? tn("profileUseAccount", state.platform || "web-user") : tn("profileClear")}</button>` : null}</div>
|
|
352
|
+
</section>`;
|
|
353
|
+
}
|
|
354
|
+
|
|
308
355
|
/** The operation in hand still owns Apply: its writes and job, or a restart of AgEnD from the press to its end. */
|
|
309
356
|
const opBusy = (op) => !!op && (["writing", "posting", "watching"].includes(op.phase) || op.restart === "busy");
|
|
310
357
|
function dropSecrets(staged) { for (const c of staged.values()) if (c.connectionSecret) c.connectionSecret.secret = ""; }
|
|
@@ -219,6 +219,11 @@ register("settings", {
|
|
|
219
219
|
staggerRange: "Must be between 0 and 30000",
|
|
220
220
|
staggerWarning: "Very low values can cause startup spikes",
|
|
221
221
|
sec_device: "Preferences", syncedTitle: "Synced across your devices", syncedLead: "Changes here apply on every device where you are signed in.",
|
|
222
|
+
profileTitle: "Your name",
|
|
223
|
+
profileLeadBound: "Agents see your web messages as the Discord or Telegram account your sign-in code was sent to: its id, and its name unless you choose another here. It follows you to every device you sign in on. It is for recognition only: it grants nothing.",
|
|
224
|
+
profileLeadUnbound: "This browser was not signed in with a code sent to your Discord or Telegram account, so agents see your web messages as \"web-user\" (or the name you set here). Sign in with a code from /web to be recognised as your account.",
|
|
225
|
+
profileName: "Name", profileHelp: "Agents see: {0} · id {1}", profileSave: "Save", profileClear: "Use web-user", profileUseAccount: "Use {0}",
|
|
226
|
+
profileSaved: "Agents now see you as {0}", profileFailed: "Could not save the name",
|
|
222
227
|
syncedPublicLink: "On the public link these are read-only: a change here stays in this browser.",
|
|
223
228
|
deviceTitle: "This device only", deviceLead: "The tour, text size, view fit, the sidebar shown or hidden, panel widths and desktop notifications stay on each device.",
|
|
224
229
|
sec_agents: "Agents",
|
|
@@ -585,6 +590,11 @@ register("settings", {
|
|
|
585
590
|
staggerRange: "必須介於 0 到 30000",
|
|
586
591
|
staggerWarning: "數值太低可能造成啟動尖峰",
|
|
587
592
|
sec_device: "偏好設定", syncedTitle: "在你所有的裝置同步", syncedLead: "這裡的變更會套用到你登入的每一台裝置。",
|
|
593
|
+
profileTitle: "你的名字",
|
|
594
|
+
profileLeadBound: "agent 會把你從網頁送出的訊息,認成收到登入驗證碼的那個 Discord 或 Telegram 帳號:用它的 id,名字也用它的,除非你在這裡另外取名。它會跟著你到每一台登入的裝置。這只用來辨認,不代表任何權限。",
|
|
595
|
+
profileLeadUnbound: "這個瀏覽器不是用私訊到你 Discord 或 Telegram 帳號的驗證碼登入的,所以 agent 會把你的網頁訊息看成「web-user」(或你在這裡設定的名字)。用 /web 的驗證碼登入,就能被認成你的帳號。",
|
|
596
|
+
profileName: "名字", profileHelp: "agent 看到:{0} · id {1}", profileSave: "儲存", profileClear: "改回 web-user", profileUseAccount: "改用 {0}",
|
|
597
|
+
profileSaved: "agent 現在會看到你是 {0}", profileFailed: "無法儲存名字",
|
|
588
598
|
syncedPublicLink: "公開連結只能讀取這些設定:在這裡變更只會留在這個瀏覽器。",
|
|
589
599
|
deviceTitle: "只限這台裝置", deviceLead: "導覽、文字大小、視圖寬度、側欄顯示或隱藏、面板寬度與桌面通知,每台裝置各自保留。",
|
|
590
600
|
sec_agents: "Agent",
|
|
@@ -98,7 +98,7 @@ register("app", {
|
|
|
98
98
|
theme: "主題", themeSystem: "跟隨系統", themeLight: "淺色", themeDark: "深色", language: "語言",
|
|
99
99
|
previews: "允許預覽 HTML", tour: "導覽", tourTitle: "再看一次網頁聊天導覽",
|
|
100
100
|
needsYou: "等你回應", approxNote: "從終端畫面判讀,僅供參考", chat: "聊天", details: "詳細資訊", log: "紀錄", instanceViews: "{0} 的檢視",
|
|
101
|
-
textSize: "字級:{0}", textSize_s: "小", textSize_m: "中", textSize_l: "大", textSize_fit: "
|
|
101
|
+
textSize: "字級:{0}", textSize_s: "小", textSize_m: "中", textSize_l: "大", textSize_fit: "填滿", usage: "用量", usageHide: "隱藏用量",
|
|
102
102
|
statusRunning: "執行中", statusStopped: "已停止", statusPaused: "已暫停", statusCrashed: "已當掉", statusWorking: "工作中", statusStuck: "似乎卡住", statusIdle: "閒置",
|
|
103
103
|
connReconnecting: "連不上 AgEnD——可能正在重新啟動。正在重新連線…", connReconnectingIn: "連不上 AgEnD——可能正在重新啟動。{0} 秒後再試。",
|
|
104
104
|
hydrating: "正在載入目前的狀態…", hydrateFailed: "無法載入目前的狀態(提示、送達標記)。",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
// - suspend()/resume(): the page is leaving (pagehide) / came back from the back-forward cache.
|
|
31
31
|
|
|
32
32
|
// #1218: steps_tick — an instance's transcript moved while a Log watches it (SSE only: a poll page asks the Log itself).
|
|
33
|
-
const EVENTS = ["status", "message", "delivery", "deliveries", "prompt", "prompts", "prompt_resolved", "activity", "needs", "reply_buttons", "steps_tick"];
|
|
33
|
+
const EVENTS = ["status", "message", "delivery", "deliveries", "prompt", "prompts", "prompt_resolved", "activity", "needs", "reply_buttons", "steps_tick", "clock"];
|
|
34
34
|
const MAX_HELD = 1000; // live events held during one catch-up read; more → read again afterwards
|
|
35
35
|
const RETRY_DELAYS = [1000, 2000, 4000]; // after the first failed catch-up read; then it waits for Retry
|
|
36
36
|
const POLL_LIMIT_MS = 10000; // a poll that has not answered by then counts as failed
|
|
@@ -114,6 +114,7 @@ export function createStream(opts) {
|
|
|
114
114
|
if (closed || mine !== pollSeq || !r.ok) return false;
|
|
115
115
|
const d = await r.json();
|
|
116
116
|
if (closed || mine !== pollSeq) return false;
|
|
117
|
+
if (typeof d.now === "number") emit("clock", { now: d.now }); // #1823: read just now, handed over at once
|
|
117
118
|
if (d.status) emit("status", d.status);
|
|
118
119
|
for (const m of d.messages || []) emit("message", m);
|
|
119
120
|
if (typeof d.cursor === "string") state.cursor = d.cursor;
|
|
@@ -209,6 +210,8 @@ export function createStream(opts) {
|
|
|
209
210
|
try { data = JSON.parse(e.data); } catch { return; }
|
|
210
211
|
if (!spoke) { spoke = true; alive(); if (again) catchUp(); }
|
|
211
212
|
else alive();
|
|
213
|
+
// #1823: a clock reading is about now, not about order: it is never held behind a catch-up (it would be stale).
|
|
214
|
+
if (name === "clock") { emit(name, data); return; }
|
|
212
215
|
live(name, data, name === "message" ? e.lastEventId : null);
|
|
213
216
|
});
|
|
214
217
|
}
|
package/dist/ui/shared/app.css
CHANGED
|
@@ -69,10 +69,12 @@ html:has(.shell), html:has(.shell) body { overflow: hidden; }
|
|
|
69
69
|
.sidebar {
|
|
70
70
|
width: var(--sidebar-w); flex-shrink: 0; display: flex; flex-direction: column; background: var(--bg-sidebar);
|
|
71
71
|
position: relative; /* #1722: the resize handle sits on its right edge (the width above: tokens.css, or this device's) */
|
|
72
|
-
padding:
|
|
72
|
+
padding: 0 0 env(safe-area-inset-bottom) env(safe-area-inset-left); /* the top inset is the head's, as the page header's is */
|
|
73
73
|
}
|
|
74
74
|
.sb-collapsed .sidebar { display: none; }
|
|
75
|
-
|
|
75
|
+
/* The brand row is the page header's row: the same height, padding and centre line (--header-h; .panel-head, .panel-title). */
|
|
76
|
+
.side-head { display: flex; align-items: center; gap: var(--s-1); box-sizing: content-box; min-height: calc(var(--header-h) - 2 * var(--s-1));
|
|
77
|
+
padding: max(var(--s-1), env(safe-area-inset-top)) var(--s-2) var(--s-1) var(--s-4); }
|
|
76
78
|
.brand { flex: 1; font-size: var(--fs-lg); font-weight: var(--fw-semibold); letter-spacing: -0.01em; }
|
|
77
79
|
.side-nav { display: flex; flex-direction: column; padding: var(--s-1) var(--s-2); gap: 1px; }
|
|
78
80
|
.side-row {
|
|
@@ -150,6 +152,10 @@ html:has(.shell), html:has(.shell) body { overflow: hidden; }
|
|
|
150
152
|
.s-device { display: flex; flex-direction: column; gap: var(--s-3); }
|
|
151
153
|
.s-device .sub { margin: 0; color: var(--text-3); font-size: var(--fs-sm); }
|
|
152
154
|
.s-device-row { display: flex; gap: var(--s-2); }
|
|
155
|
+
/* #1827: the person's web name — its field takes the card's width; a refusal reads in the danger colour. */
|
|
156
|
+
.s-profile .field { display: flex; flex-direction: column; gap: var(--s-1); }
|
|
157
|
+
.s-profile .field input { max-width: 24rem; }
|
|
158
|
+
.s-profile .err { color: var(--danger); }
|
|
153
159
|
/* #1620: Settings → Web — the lead, and the read-only list of what is set in fleet.yaml. */
|
|
154
160
|
.s-web .sub { margin: 0; color: var(--text-3); font-size: var(--fs-sm); }
|
|
155
161
|
.s-web-fields:disabled select { opacity: 0.6; } /* over the public link: dimmed like the inputs (.field input:disabled) */
|
|
@@ -195,14 +201,17 @@ html:has(.shell), html:has(.shell) body { overflow: hidden; }
|
|
|
195
201
|
}
|
|
196
202
|
.panel-head .sb-open { display: none; }
|
|
197
203
|
.sb-collapsed .panel-head .sb-open { display: inline-flex; }
|
|
198
|
-
|
|
204
|
+
/* One row of --header-h on every page (a phone's instance tabs wrap below it): the title, its status and badges on one centre line. */
|
|
205
|
+
.panel-title { flex: 1; min-width: 0; display: flex; align-items: center; gap: var(--s-3); min-height: calc(var(--header-h) - 2 * var(--s-1)); }
|
|
199
206
|
.panel-title h1 { font-size: var(--fs-lg); line-height: var(--lh-lg); font-weight: var(--fw-semibold); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; outline: none; }
|
|
200
207
|
.panel-sub { color: var(--text-2); font-size: var(--fs-sm); white-space: nowrap; }
|
|
201
208
|
.status { display: inline-flex; align-items: center; gap: 6px; }
|
|
202
209
|
.panel-actions { display: flex; align-items: center; gap: var(--s-1); }
|
|
203
210
|
/* #1523 N2: the instance view switch — beside the title on a wide screen; on a phone, a row of tabs under the header. */
|
|
204
211
|
.inst-switch.seg { padding: 0; margin: 0; width: auto; max-width: none; flex-shrink: 0; }
|
|
205
|
-
.inst-switch .seg-item { min-height: 30px; }
|
|
212
|
+
.inst-switch .seg-item { min-height: 30px; flex-direction: column; justify-content: center; gap: 0; }
|
|
213
|
+
/* The label again in the current tab's weight, taking width but no height and never seen: the bar's size does not change with the tab. */
|
|
214
|
+
.inst-switch .seg-item::after { content: attr(data-label); font-weight: var(--fw-semibold); height: 0; overflow: hidden; visibility: hidden; pointer-events: none; user-select: none; }
|
|
206
215
|
/* #1523 N3 (Q2 = A): the text size, one custom property from the root's data-text-size (header-tools.js). The chat's
|
|
207
216
|
messages, Details and the Fleet tabs scale the type tokens by it; View's terminal scales itself (VIEW_SCALE). */
|
|
208
217
|
:root { --text-scale: 1; }
|
|
@@ -248,6 +257,10 @@ html:has(.shell), html:has(.shell) body { overflow: hidden; }
|
|
|
248
257
|
.p-log .log-older, .p-log .log-start { text-align: center; margin: var(--s-2) 0; }
|
|
249
258
|
.p-log .log-off { padding: var(--s-6) var(--s-4); }
|
|
250
259
|
.p-details .d-edit { display: flex; align-items: center; justify-content: space-between; gap: var(--s-2); flex-wrap: wrap; margin-top: var(--s-2); }
|
|
260
|
+
/* The header's controls are one height, the icon buttons' (36 px): its small buttons, and the instance tabs when they share
|
|
261
|
+
its row (a phone puts them on a row of their own, under it). */
|
|
262
|
+
.panel-head .btn-sm { min-height: 36px; }
|
|
263
|
+
@media (min-width: 900px) { .panel-head .inst-switch .seg-item { min-height: 36px; } }
|
|
251
264
|
@media (max-width: 899px) {
|
|
252
265
|
.panel-head:has(.inst-switch) { flex-wrap: wrap; }
|
|
253
266
|
.inst-switch.seg { order: 3; flex-basis: 100%; display: grid; grid-template-columns: repeat(4, 1fr); padding: 0 0 var(--s-1); }
|
|
@@ -526,6 +539,10 @@ html.lb-open .scroller { overflow: hidden; }
|
|
|
526
539
|
.rb-btn { max-width: 100%; white-space: normal; text-align: left; }
|
|
527
540
|
.rb-btn.chosen, .rb-btn.chosen:disabled { border-color: var(--ok); color: var(--text); background: color-mix(in srgb, var(--ok) 14%, transparent); font-weight: var(--fw-semibold); opacity: 1; }
|
|
528
541
|
.rb-btn:disabled:not(.chosen) { opacity: 0.55; }
|
|
542
|
+
/* #1823: a poll — its closed buttons show the tally, so they stay readable; the time left keeps its width. */
|
|
543
|
+
.rb-row.poll .rb-btn:disabled { opacity: 0.85; }
|
|
544
|
+
.rb-row.poll .poll-left { font-variant-numeric: tabular-nums; }
|
|
545
|
+
.poll-voters { margin: var(--s-1) 0 0; padding-left: var(--s-4); color: var(--text-2); font-size: var(--fs-sm); }
|
|
529
546
|
.rb-note { font-size: var(--fs-xs); color: var(--text-3); }
|
|
530
547
|
.pv-menu { position: relative; }
|
|
531
548
|
.pv-menu > summary { list-style: none; cursor: pointer; padding: 2px var(--s-2); border-radius: var(--r-sm); color: var(--text-3); }
|
|
@@ -714,7 +731,13 @@ body.side-resizing, body.side-resizing * { cursor: col-resize !important; user-s
|
|
|
714
731
|
.nav-chip { display: flex; align-items: center; gap: var(--s-2); cursor: pointer; color: var(--text); }
|
|
715
732
|
.nav-facet-reset { font-size: var(--fs-xs); }
|
|
716
733
|
|
|
717
|
-
|
|
734
|
+
/* One gap on every page (View's, #1448): the header's controls are the same size on every tab. */
|
|
735
|
+
.panel-actions .btn { gap: var(--s-1); }
|
|
736
|
+
/* Aa's names share one cell, only the current one shown: the button is as wide as its widest name on every page. */
|
|
737
|
+
.hd-text-names { display: inline-grid; }
|
|
738
|
+
.hd-text-names > span { grid-area: 1 / 1; visibility: hidden; }
|
|
739
|
+
.hd-text-names > .on { visibility: visible; }
|
|
740
|
+
.hd-slot { visibility: hidden; pointer-events: none; }
|
|
718
741
|
.v-term { flex: 1; min-height: 0; overflow: auto; scrollbar-gutter: stable; padding: 5px 6px; background: #000000; position: relative; }
|
|
719
742
|
.v-pre { margin: 0; min-width: 100%; min-height: 100%; font-family: var(--font-mono); line-height: 1.2; white-space: pre; color: #d0d0d0; }
|
|
720
743
|
.v-pre .ansi[data-b] { font-weight: var(--fw-bold); }
|
|
@@ -58,7 +58,10 @@ export function setTextSize(size) {
|
|
|
58
58
|
}
|
|
59
59
|
export function setViewFit() { write(VIEW_FIT_KEY, "1"); textSizeStore.set((s) => ({ ...s, viewFit: true })); }
|
|
60
60
|
|
|
61
|
-
/**
|
|
61
|
+
/**
|
|
62
|
+
* Aa: S → M → L → S; on View, Fit → S → M → L → Fit. Every page's button is as wide as its widest name (Fit's
|
|
63
|
+
* included): switching pages or sizes never moves the controls beside it.
|
|
64
|
+
*/
|
|
62
65
|
export function TextSizeButton({ view = false }) {
|
|
63
66
|
const st = useStore(textSizeStore);
|
|
64
67
|
const cur = view && st.viewFit ? "fit" : st.size;
|
|
@@ -67,7 +70,8 @@ export function TextSizeButton({ view = false }) {
|
|
|
67
70
|
const name = t(`app.textSize_${cur}`);
|
|
68
71
|
const label = t("app.textSize", name);
|
|
69
72
|
return html`<button type="button" class="btn btn-ghost btn-sm hd-text" onClick=${() => (next === "fit" ? setViewFit() : setTextSize(next))}
|
|
70
|
-
title=${label} aria-label=${label}><${Icon} name="type" size=${16} /><span class="hide-narrow" aria-hidden="true">${
|
|
73
|
+
title=${label} aria-label=${label}><${Icon} name="type" size=${16} /><span class="hide-narrow" aria-hidden="true"><span class="hd-text-names">${
|
|
74
|
+
["fit", ...TEXT_SIZES].map(k => html`<span key=${k} class=${k === cur ? "on" : undefined}>${t(`app.textSize_${k}`)}</span>`)}</span></span></button>`;
|
|
71
75
|
}
|
|
72
76
|
|
|
73
77
|
/** Whether the fleet serves the usage panel: the page says so (data-usage-panel); "0" only when turned off. */
|
|
@@ -79,8 +83,8 @@ export function usageOffered() {
|
|
|
79
83
|
// hidden is this device's choice (agend_usage_rail; "0" = hidden, else shown) — a layout choice, not synced (#1665).
|
|
80
84
|
export const RAIL_MEDIA = "(min-width: 1200px)";
|
|
81
85
|
export const RAIL_KEY = "agend_usage_rail";
|
|
82
|
-
/** The pages whose header has ◔ — the rail is theirs. */
|
|
83
|
-
export const RAIL_PANELS = ["chat", "view", "details", "fleet"];
|
|
86
|
+
/** The pages whose header has ◔ — the rail is theirs (Log's too: one frame on every tab of an instance). */
|
|
87
|
+
export const RAIL_PANELS = ["chat", "view", "log", "details", "fleet"];
|
|
84
88
|
export const usageRailStore = createStore({ open: true });
|
|
85
89
|
/** A page load: this device's choice. */
|
|
86
90
|
export function initUsageRail() { usageRailStore.set({ open: read(RAIL_KEY) !== "0" }); }
|
|
@@ -141,3 +145,7 @@ export function UsageButton({ navKey }) {
|
|
|
141
145
|
export function HeaderTools({ view = false, navKey }) {
|
|
142
146
|
return html`<${TextSizeButton} view=${view} /><${UsageButton} navKey=${navKey} />`;
|
|
143
147
|
}
|
|
148
|
+
/** Where a page with no control of its own after the shared ones (Log) keeps the room Chat's ⋯ takes: the same box on every tab. */
|
|
149
|
+
export function HeaderSlot() {
|
|
150
|
+
return html`<span class="icon-btn hd-slot" aria-hidden="true"></span>`;
|
|
151
|
+
}
|
|
@@ -6,10 +6,13 @@ import { html } from "./app-html.js";
|
|
|
6
6
|
import { t } from "./app-i18n.js";
|
|
7
7
|
import { chatPath, detailsPath, logPath, viewPath } from "./app-route.js";
|
|
8
8
|
|
|
9
|
-
/**
|
|
9
|
+
/**
|
|
10
|
+
* current: "chat" | "view" | "log" | "details". #1218: Log sits between View and Details. `data-label`: each tab is as
|
|
11
|
+
* wide as its label in the current tab's weight (app.css), so the bar keeps its size whichever tab is current.
|
|
12
|
+
*/
|
|
10
13
|
export function InstanceSwitch({ name, current }) {
|
|
11
14
|
const seg = (key, href, label) => html`<a key=${key} class=${`seg-item${current === key ? " active" : ""}`} href=${href}
|
|
12
|
-
aria-current=${current === key ? "page" : undefined}>${label}</a>`;
|
|
15
|
+
aria-current=${current === key ? "page" : undefined} data-label=${label}>${label}</a>`;
|
|
13
16
|
return html`<nav class="inst-switch seg" aria-label=${t("app.instanceViews", name)}>
|
|
14
17
|
${seg("chat", chatPath(name), t("app.chat"))}${seg("view", viewPath(name), t("app.view"))}${seg("log", logPath(name), t("app.log"))}${seg("details", detailsPath(name), t("app.details"))}
|
|
15
18
|
</nav>`;
|
|
@@ -202,8 +202,8 @@ register("view", {
|
|
|
202
202
|
"help1": "在清單裡選一個 instance:它的即時終端畫面會顯示在這裡。",
|
|
203
203
|
"help2": "點群組名稱可以收合或展開。",
|
|
204
204
|
"help3": "「編輯個人資料」可修改顯示名稱、角色、描述和頭像。",
|
|
205
|
-
"help5": "
|
|
206
|
-
"densityFit": "
|
|
205
|
+
"help5": "「字級」會在填滿 → 小 → 中 → 大之間切換。小、中、大是所有頁面共用的字級;填滿讓終端畫面符合框的大小。",
|
|
206
|
+
"densityFit": "填滿",
|
|
207
207
|
"densityComfortable": "舒適",
|
|
208
208
|
"densityCompact": "精簡",
|
|
209
209
|
"densityLabel": "字級密度",
|
package/dist/update-check.d.ts
CHANGED
|
@@ -80,6 +80,37 @@ export declare function runningFleetPredatesInstall(opts: {
|
|
|
80
80
|
isFleetProcess: (pid: number) => boolean;
|
|
81
81
|
marginMs?: number;
|
|
82
82
|
}): boolean;
|
|
83
|
+
/**
|
|
84
|
+
* #1829 review: what fleet.pid says, as evidence — "missing" only when the file is not there (ENOENT), "valid" for a
|
|
85
|
+
* whole positive pid, "unknown" for anything else (unreadable, a directory, empty, malformed). Unknown is never read
|
|
86
|
+
* as a stopped fleet.
|
|
87
|
+
*/
|
|
88
|
+
export declare function readFleetPidEvidence(path: string, read?: (path: string) => string): {
|
|
89
|
+
kind: "missing";
|
|
90
|
+
} | {
|
|
91
|
+
kind: "valid";
|
|
92
|
+
pid: number;
|
|
93
|
+
} | {
|
|
94
|
+
kind: "unknown";
|
|
95
|
+
};
|
|
96
|
+
/** The largest pid `process.kill` accepts (a signed 32-bit integer). */
|
|
97
|
+
export declare const MAX_PID = 2147483647;
|
|
98
|
+
/**
|
|
99
|
+
* Whether `pid` may be alive: only ESRCH ("no such process") proves it gone. EPERM is a live process of another
|
|
100
|
+
* user, and any other failure (an argument the call refused, for one) proves nothing — so: alive.
|
|
101
|
+
*/
|
|
102
|
+
export declare function pidAlive(pid: number, kill?: (pid: number, signal: 0) => unknown): boolean;
|
|
103
|
+
/**
|
|
104
|
+
* #1829 ⑥: whether the fleet is PROVEN not running — no fleet.pid (a fleet removes it when it stops), a pid that no
|
|
105
|
+
* longer exists, or a live pid whose readable command line is not a fleet's (a recycled pid). A command line that
|
|
106
|
+
* cannot be read proves nothing either way: not stopped.
|
|
107
|
+
*/
|
|
108
|
+
export declare function fleetProvenStopped(opts: {
|
|
109
|
+
pid: number | null;
|
|
110
|
+
alive: (pid: number) => boolean;
|
|
111
|
+
commandLine: (pid: number) => string;
|
|
112
|
+
isFleetProcess: (commandLine: string) => boolean;
|
|
113
|
+
}): boolean;
|
|
83
114
|
/** Start time of a live process, via `ps -o lstart=` (Linux and macOS); null if gone. */
|
|
84
115
|
export declare function processStartMs(pid: number, run?: (args: string[]) => string): number | null;
|
|
85
116
|
interface UpdateOutput {
|
package/dist/update-check.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { execFileSync } from "node:child_process";
|
|
2
|
+
import { readFileSync } from "node:fs";
|
|
2
3
|
import { SYSTEMD_RESTART_INDETERMINATE_EXIT_CODE } from "./service-restart-selection.js";
|
|
3
4
|
/**
|
|
4
5
|
* What a chat `/update` (Discord slash or Telegram) runs: no channel flag, ever.
|
|
@@ -160,6 +161,52 @@ export function runningFleetPredatesInstall(opts) {
|
|
|
160
161
|
return false;
|
|
161
162
|
return started < opts.installedAtMs - (opts.marginMs ?? 2_000);
|
|
162
163
|
}
|
|
164
|
+
/**
|
|
165
|
+
* #1829 review: what fleet.pid says, as evidence — "missing" only when the file is not there (ENOENT), "valid" for a
|
|
166
|
+
* whole positive pid, "unknown" for anything else (unreadable, a directory, empty, malformed). Unknown is never read
|
|
167
|
+
* as a stopped fleet.
|
|
168
|
+
*/
|
|
169
|
+
export function readFleetPidEvidence(path, read = p => readFileSync(p, "utf-8")) {
|
|
170
|
+
let raw;
|
|
171
|
+
try {
|
|
172
|
+
raw = read(path);
|
|
173
|
+
}
|
|
174
|
+
catch (err) {
|
|
175
|
+
return err?.code === "ENOENT" ? { kind: "missing" } : { kind: "unknown" };
|
|
176
|
+
}
|
|
177
|
+
const text = raw.trim();
|
|
178
|
+
const pid = /^[1-9][0-9]{0,9}$/.test(text) ? Number(text) : Number.NaN;
|
|
179
|
+
// process.kill takes a signed 32-bit pid (review): anything above is not a pid it can ask about.
|
|
180
|
+
return pid <= MAX_PID ? { kind: "valid", pid } : { kind: "unknown" };
|
|
181
|
+
}
|
|
182
|
+
/** The largest pid `process.kill` accepts (a signed 32-bit integer). */
|
|
183
|
+
export const MAX_PID = 2_147_483_647;
|
|
184
|
+
/**
|
|
185
|
+
* Whether `pid` may be alive: only ESRCH ("no such process") proves it gone. EPERM is a live process of another
|
|
186
|
+
* user, and any other failure (an argument the call refused, for one) proves nothing — so: alive.
|
|
187
|
+
*/
|
|
188
|
+
export function pidAlive(pid, kill = (p, s) => process.kill(p, s)) {
|
|
189
|
+
try {
|
|
190
|
+
kill(pid, 0);
|
|
191
|
+
return true;
|
|
192
|
+
}
|
|
193
|
+
catch (err) {
|
|
194
|
+
return err?.code !== "ESRCH";
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* #1829 ⑥: whether the fleet is PROVEN not running — no fleet.pid (a fleet removes it when it stops), a pid that no
|
|
199
|
+
* longer exists, or a live pid whose readable command line is not a fleet's (a recycled pid). A command line that
|
|
200
|
+
* cannot be read proves nothing either way: not stopped.
|
|
201
|
+
*/
|
|
202
|
+
export function fleetProvenStopped(opts) {
|
|
203
|
+
if (opts.pid === null)
|
|
204
|
+
return true;
|
|
205
|
+
if (!opts.alive(opts.pid))
|
|
206
|
+
return true;
|
|
207
|
+
const line = opts.commandLine(opts.pid);
|
|
208
|
+
return line !== "" && !opts.isFleetProcess(line);
|
|
209
|
+
}
|
|
163
210
|
/** Start time of a live process, via `ps -o lstart=` (Linux and macOS); null if gone. */
|
|
164
211
|
export function processStartMs(pid, run = args => execFileSync("ps", args, { encoding: "utf8", env: { ...process.env, LC_ALL: "C", TZ: process.env.TZ }, stdio: ["ignore", "pipe", "ignore"], timeout: 5000 })) {
|
|
165
212
|
try {
|
package/dist/update-check.js.map
CHANGED
|
@@ -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":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,uCAAuC,EAAE,MAAM,gCAAgC,CAAC;AAEzF;;;;GAIG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,cAAc,CAAC;AAY7C;;;;;GAKG;AACH,MAAM,GAAG,GAAG,iBAAiB,CAAC;AAC9B,MAAM,MAAM,GAAG,MAAM,GAAG,8BAA8B,CAAC;AACvD,MAAM,QAAQ,GAAG,eAAe,CAAC;AACjC,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC,OAAO,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,MAAM,SAAS,MAAM,cAAc,QAAQ,SAAS,QAAQ,OAAO,CAAC,CAAC;AAIxI,SAAS,WAAW,CAAC,OAAe;IAClC,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;IACtC,IAAI,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IACpB,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;AACxE,CAAC;AAED,qEAAqE;AACrE,MAAM,UAAU,cAAc,CAAC,OAAe;IAC5C,OAAO,WAAW,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC;AACvC,CAAC;AAED,oHAAoH;AACpH,MAAM,UAAU,mBAAmB,CAAC,OAAe;IACjD,OAAO,CAAC,WAAW,CAAC,OAAO,CAAC,EAAE,GAAG,CAAC,MAAM,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;AACrD,CAAC;AAED,mGAAmG;AACnG,SAAS,cAAc,CAAC,CAAS,EAAE,CAAS;IAC1C,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM;QAAE,OAAO,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/D,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACtC,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAAC,CAAS,EAAE,CAAS;IAChD,MAAM,EAAE,GAAG,WAAW,CAAC,CAAC,CAAC,EAAE,EAAE,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC;IAC/C,IAAI,CAAC,EAAE,IAAI,CAAC,EAAE;QAAE,OAAO,IAAI,CAAC;IAC5B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC3B,MAAM,KAAK,GAAG,cAAc,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QACrD,IAAI,KAAK,KAAK,CAAC;YAAE,OAAO,KAAK,CAAC;IAChC,CAAC;IACD,IAAI,EAAE,CAAC,GAAG,CAAC,MAAM,KAAK,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAChG,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAChE,MAAM,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QACnC,IAAI,CAAC,KAAK,CAAC;YAAE,SAAS;QACtB,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACjD,IAAI,EAAE,IAAI,EAAE;YAAE,OAAO,cAAc,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAC1C,IAAI,EAAE,KAAK,EAAE;YAAE,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAClC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACxB,CAAC;IACD,OAAO,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;AAClD,CAAC;AAID;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,OAAe;IAC9C,MAAM,GAAG,GAAG,WAAW,CAAC,OAAO,CAAC,EAAE,GAAG,IAAI,EAAE,CAAC;IAC5C,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,QAAQ,CAAC;IACtC,OAAO,GAAG,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC;AAC/C,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,iBAAiB,CAAC,IAA0B,EAAE,gBAAwB;IACpF,IAAI,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC,OAAO,CAAC;IACtC,IAAI,IAAI,CAAC,KAAK;QAAE,OAAO,OAAO,CAAC;IAC/B,IAAI,IAAI,CAAC,IAAI;QAAE,OAAO,MAAM,CAAC;IAC7B,IAAI,IAAI,CAAC,MAAM;QAAE,OAAO,QAAQ,CAAC;IACjC,OAAO,gBAAgB,CAAC,gBAAgB,CAAC,CAAC;AAC5C,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,cAAsB,EAAE,aAAqB;IAC3E,OAAO,mBAAmB,CAAC,cAAc,CAAC,IAAI,CAAC,mBAAmB,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,yBAAyB,CAAC,CAAC,CAAC,0BAA0B,CAAC;AAC7I,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,sBAAsB,CAAC,gBAAwB,EAAE,aAA4B,EAAE,IAA0B;IACvH,IAAI,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,MAAM,IAAI,aAAa,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IACtF,MAAM,KAAK,GAAG,aAAa,CAAC,aAAa,EAAE,gBAAgB,CAAC,CAAC;IAC7D,OAAO,KAAK,KAAK,IAAI,IAAI,KAAK,GAAG,CAAC,CAAC;AACrC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CACjC,QAAgB,EAChB,MAA2B,YAAY;IAEvC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,GAAG,CAChB,KAAK,EACL,CAAC,MAAM,EAAE,kBAAkB,QAAQ,EAAE,EAAE,SAAS,CAAC,EACjD;YACE,QAAQ,EAAE,OAAO;YACjB,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC;YACnC,OAAO,EAAE,MAAM;SAChB,CACF,CAAC;QACF,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;QACtC,OAAO,OAAO,IAAI,IAAI,CAAC;IACzB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAS,gBAAgB,CAAC,OAAe;IACvC,OAAO,OAAO,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;AAC3C,CAAC;AAED,MAAM,UAAU,gBAAgB,CAC9B,cAAsB,EACtB,aAA4B,EAC5B,KAAK,GAAG,KAAK;IAEb,OAAO,CAAC,KAAK;WACR,aAAa,KAAK,IAAI;WACtB,gBAAgB,CAAC,cAAc,CAAC,KAAK,gBAAgB,CAAC,aAAa,CAAC,CAAC;AAC5E,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,2BAA2B,CAAC,IAW3C;IACC,IAAI,IAAI,CAAC,GAAG,KAAK,IAAI,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,aAAa,CAAC;QAAE,OAAO,KAAK,CAAC;IAC5E,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,GAAG,CAAC;QAAE,OAAO,KAAK,CAAC;IACjD,MAAM,OAAO,GAAG,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC9C,IAAI,OAAO,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IACnC,OAAO,OAAO,GAAG,IAAI,CAAC,aAAa,GAAG,CAAC,IAAI,CAAC,QAAQ,IAAI,KAAK,CAAC,CAAC;AACjE,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,oBAAoB,CAAC,IAAY,EAAE,OAAiC,CAAC,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC,EAAE,OAAO,CAAC;IAE/G,IAAI,GAAW,CAAC;IAChB,IAAI,CAAC;QAAC,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC;IAAC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACrC,OAAQ,GAA6B,EAAE,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;IACvG,CAAC;IACD,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;IACxB,MAAM,GAAG,GAAG,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;IACvE,iGAAiG;IACjG,OAAO,GAAG,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;AACvE,CAAC;AAED,wEAAwE;AACxE,MAAM,CAAC,MAAM,OAAO,GAAG,aAAa,CAAC;AAErC;;;GAGG;AACH,MAAM,UAAU,QAAQ,CAAC,GAAW,EAAE,OAA4C,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC;IAC5G,IAAI,CAAC;QAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QAAC,OAAO,IAAI,CAAC;IAAC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QAAC,OAAQ,GAA6B,EAAE,IAAI,KAAK,OAAO,CAAC;IAAC,CAAC;AAC7G,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAAC,IAKlC;IACC,IAAI,IAAI,CAAC,GAAG,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IACnC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IACvC,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACxC,OAAO,IAAI,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;AACnD,CAAC;AAED,yFAAyF;AACzF,MAAM,UAAU,cAAc,CAAC,GAAW,EAAE,MAAkC,IAAI,CAAC,EAAE,CACnF,YAAY,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE,EAAE,OAAO,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAE5J,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,GAAG,CAAC,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAC9D,IAAI,CAAC,IAAI;YAAE,OAAO,IAAI,CAAC;QACvB,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC5B,OAAO,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;IACzC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAOD;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CACjC,MAAqB,EACrB,SAAuB,OAAO;IAE9B,IAAI,MAAM,KAAK,CAAC,EAAE,CAAC;QACjB,MAAM,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC;QACpC,OAAO,WAAW,CAAC;IACrB,CAAC;IACD,IAAI,MAAM,KAAK,uCAAuC,EAAE,CAAC;QACvD,MAAM,CAAC,GAAG,CAAC,sGAAsG,CAAC,CAAC;QACnH,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,kDAAkD,CAAC,CAAC;IACjE,MAAM,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAC;IACnC,MAAM,CAAC,KAAK,CAAC,kCAAkC,CAAC,CAAC;IACjD,OAAO,QAAQ,CAAC;AAClB,CAAC"}
|
package/dist/update-launch.d.ts
CHANGED
|
@@ -1,3 +1,44 @@
|
|
|
1
|
+
/** Chat updates must survive the fleet's service cgroup being stopped (#1490 row 37). */
|
|
2
|
+
import { type ChildProcess } from "node:child_process";
|
|
3
|
+
/** How many bytes to cap the update.log file at (across all runs). */
|
|
4
|
+
export declare const UPDATE_LOG_FILE_CAP: number;
|
|
5
|
+
/**
|
|
6
|
+
* Path of the update log file (mode 0600; raw updater output is written directly — secrets are
|
|
7
|
+
* masked only when extracting the short cause shown in chat; the file itself is owner-readable only).
|
|
8
|
+
*/
|
|
9
|
+
export declare function updateLogPath(dataDir: string): string;
|
|
10
|
+
/**
|
|
11
|
+
* Extract a short human-readable cause from raw updater output.
|
|
12
|
+
* Prefers the last `npm ERR!`/`npm error` summary line or the last `✗` line.
|
|
13
|
+
* Falls back to the last non-blank line. Masks secrets and caps at ~300 chars.
|
|
14
|
+
*/
|
|
15
|
+
export declare function extractUpdateCause(output: string): string | null;
|
|
16
|
+
/**
|
|
17
|
+
* #1829: the one-line fix for a failure AgEnD knows, from this run's output (a small lookup; anything else: null).
|
|
18
|
+
* - `agendGone`: the launched `agend` is no longer there (an install that removed it and did not put it back).
|
|
19
|
+
* - npm `ENOTEMPTY` on its rename: a staging directory left by an interrupted install. npm names the same one on every
|
|
20
|
+
* retry, so the retry fails the same way until it is removed — only that exact directory, and only when it is one of
|
|
21
|
+
* AgEnD's own (`@songsid/.agend…`), never a pattern.
|
|
22
|
+
* - "systemd does not know …": the activation proof could not read the user manager (#1804): the one-time manual hop.
|
|
23
|
+
*/
|
|
24
|
+
export declare function updateFixHint(output: string, opts?: {
|
|
25
|
+
agendGone?: boolean;
|
|
26
|
+
}): string | null;
|
|
27
|
+
/**
|
|
28
|
+
* Rotate the log file if needed, write a run header, and return an open file descriptor
|
|
29
|
+
* for the child process to write to directly — not a pipe.
|
|
30
|
+
*
|
|
31
|
+
* Using an fd instead of a pipe means the updater can keep writing after the fleet process
|
|
32
|
+
* that spawned it has been stopped: there is no read end to close, so no EPIPE.
|
|
33
|
+
* The caller must closeSync(fd) after spawn so the parent's copy of the fd is released.
|
|
34
|
+
*
|
|
35
|
+
* Returns `null` when the log file cannot be opened (dataDir unwritable, disk full, etc.).
|
|
36
|
+
* In that case the caller should fall back to `stdio: "ignore"` and omit the log note.
|
|
37
|
+
*/
|
|
38
|
+
export declare function openUpdateLog(logPath: string, header: string): {
|
|
39
|
+
fd: number;
|
|
40
|
+
offset: number;
|
|
41
|
+
} | null;
|
|
1
42
|
export interface UpdateLaunchDeps {
|
|
2
43
|
platform: string;
|
|
3
44
|
cgroup(): Promise<string>;
|
|
@@ -19,4 +60,8 @@ export type UpdateLaunch = {
|
|
|
19
60
|
/** Same UID, no privileged or remote manager, no credentials in argv. No unsafe detached fallback. */
|
|
20
61
|
export declare function resolveUpdateLaunch(agend: string, deps?: UpdateLaunchDeps): Promise<UpdateLaunch>;
|
|
21
62
|
/** Spawn/manager refusal and nonzero updater exit are visible; exit 75 is the existing pending hand-off. */
|
|
22
|
-
export declare function watchUpdateLaunch(child: Pick<
|
|
63
|
+
export declare function watchUpdateLaunch(child: Pick<ChildProcess, "once">, fail: (message: string) => void, logPath?: string,
|
|
64
|
+
/** Byte offset into the log file at which this run's output begins. */
|
|
65
|
+
logOffset?: number,
|
|
66
|
+
/** The `agend` the updater runs: there at launch and gone after a failure → reinstalling is the fix (#1829). */
|
|
67
|
+
agendPath?: string): void;
|