@songsid/agend 2.1.11-beta.3 → 2.1.11-beta.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 (47) hide show
  1. package/dist/backend/codex.d.ts +2 -0
  2. package/dist/backend/codex.js +55 -14
  3. package/dist/backend/codex.js.map +1 -1
  4. package/dist/backend/muse.d.ts +50 -5
  5. package/dist/backend/muse.js +166 -32
  6. package/dist/backend/muse.js.map +1 -1
  7. package/dist/backend/types.d.ts +39 -1
  8. package/dist/backend/types.js.map +1 -1
  9. package/dist/command-table.d.ts +33 -0
  10. package/dist/command-table.js +45 -0
  11. package/dist/command-table.js.map +1 -1
  12. package/dist/daemon.d.ts +93 -1
  13. package/dist/daemon.js +456 -31
  14. package/dist/daemon.js.map +1 -1
  15. package/dist/darwin-memory.d.ts +34 -0
  16. package/dist/darwin-memory.js +160 -0
  17. package/dist/darwin-memory.js.map +1 -0
  18. package/dist/fleet-manager.d.ts +10 -0
  19. package/dist/fleet-manager.js +30 -7
  20. package/dist/fleet-manager.js.map +1 -1
  21. package/dist/host-memory.d.ts +3 -2
  22. package/dist/host-memory.js +14 -0
  23. package/dist/host-memory.js.map +1 -1
  24. package/dist/instance-lifecycle.d.ts +11 -0
  25. package/dist/instance-lifecycle.js +45 -8
  26. package/dist/instance-lifecycle.js.map +1 -1
  27. package/dist/locale.js +11 -0
  28. package/dist/locale.js.map +1 -1
  29. package/dist/memory-pressure.d.ts +20 -1
  30. package/dist/memory-pressure.js +87 -6
  31. package/dist/memory-pressure.js.map +1 -1
  32. package/dist/resource-report.d.ts +1 -1
  33. package/dist/resource-report.js +5 -4
  34. package/dist/resource-report.js.map +1 -1
  35. package/dist/spawn-gate.d.ts +4 -0
  36. package/dist/spawn-gate.js +36 -8
  37. package/dist/spawn-gate.js.map +1 -1
  38. package/dist/tmux-manager.d.ts +7 -0
  39. package/dist/tmux-manager.js +19 -0
  40. package/dist/tmux-manager.js.map +1 -1
  41. package/dist/topic-commands.d.ts +16 -2
  42. package/dist/topic-commands.js +85 -94
  43. package/dist/topic-commands.js.map +1 -1
  44. package/dist/turn-reply-guard.d.ts +3 -0
  45. package/dist/turn-reply-guard.js +12 -2
  46. package/dist/turn-reply-guard.js.map +1 -1
  47. package/package.json +1 -1
@@ -0,0 +1,34 @@
1
+ import type { HostMemory } from "./host-memory.js";
2
+ export declare const DARWIN_MEMORY_DEADLINE_MS = 2000;
3
+ export declare const DARWIN_MEMORY_CACHE_MS = 30000;
4
+ export declare function unknownDarwinMemory(totalBytes: number): HostMemory;
5
+ /** vm_stat's printed free count excludes speculative pages. Purgeable can overlap inactive. */
6
+ export declare function parseDarwinAvailable(text: string, totalBytes: number): number | null;
7
+ /** sysctl prints binary MiB to two decimals, including the valid unallocated 0/0 pool. */
8
+ export declare function parseDarwinSwap(text: string): Pick<HostMemory, "swapTotalBytes" | "swapFreeBytes">;
9
+ export interface MemoryCommand {
10
+ result: Promise<string | null>;
11
+ /** Physical child close, independent of logical timeout/result. */
12
+ stopped: Promise<void>;
13
+ kill(): void;
14
+ }
15
+ export type MemoryCommandRunner = (file: string, args: string[]) => MemoryCommand;
16
+ export declare const runMemoryCommand: MemoryCommandRunner;
17
+ interface Options {
18
+ run?: MemoryCommandRunner;
19
+ totalmem?: () => number;
20
+ now?: () => number;
21
+ }
22
+ /** One bounded logical read and at most one physical pair, even across stop/restart. */
23
+ export declare class DarwinMemoryProbe {
24
+ private readonly run;
25
+ private readonly total;
26
+ private readonly now;
27
+ private flight;
28
+ private cache;
29
+ private epoch;
30
+ constructor(options?: Options);
31
+ read(): Promise<HostMemory>;
32
+ stop(): void;
33
+ }
34
+ export {};
@@ -0,0 +1,160 @@
1
+ import { execFile } from "node:child_process";
2
+ import { totalmem } from "node:os";
3
+ export const DARWIN_MEMORY_DEADLINE_MS = 2_000;
4
+ export const DARWIN_MEMORY_CACHE_MS = 30_000;
5
+ const MAX_OUTPUT = 32 * 1024;
6
+ export function unknownDarwinMemory(totalBytes) {
7
+ return { totalBytes, availableBytes: null, availableKind: "unknown", swapTotalBytes: null, swapFreeBytes: null };
8
+ }
9
+ /** vm_stat's printed free count excludes speculative pages. Purgeable can overlap inactive. */
10
+ export function parseDarwinAvailable(text, totalBytes) {
11
+ const headers = [...text.matchAll(/^Mach Virtual Memory Statistics: \(page size of (\d+) bytes\)\s*$/gm)];
12
+ if (headers.length !== 1 || [...text.matchAll(/^Mach Virtual Memory Statistics:/gm)].length !== 1)
13
+ return null;
14
+ const pageSize = Number(headers[0][1]);
15
+ if (!Number.isSafeInteger(pageSize) || pageSize < 1024 || pageSize > 1024 * 1024 || Math.log2(pageSize) % 1 !== 0)
16
+ return null;
17
+ const counts = [];
18
+ for (const name of ["free", "speculative", "inactive", "purgeable"]) {
19
+ const rows = [...text.matchAll(new RegExp(`^Pages ${name}:\\s+(\\d+)\\.\\s*$`, "gm"))];
20
+ if (rows.length !== 1 || [...text.matchAll(new RegExp(`^Pages ${name}:`, "gm"))].length !== 1)
21
+ return null;
22
+ const count = Number(rows[0][1]);
23
+ if (!Number.isSafeInteger(count) || count < 0)
24
+ return null;
25
+ counts.push(count);
26
+ }
27
+ const [free, speculative, inactive, purgeable] = counts;
28
+ const bytes = (free + speculative + Math.max(inactive, purgeable)) * pageSize;
29
+ return Number.isSafeInteger(bytes) && Number.isFinite(totalBytes) && totalBytes > 0 && bytes <= totalBytes ? bytes : null;
30
+ }
31
+ /** sysctl prints binary MiB to two decimals, including the valid unallocated 0/0 pool. */
32
+ export function parseDarwinSwap(text) {
33
+ const unknown = { swapTotalBytes: null, swapFreeBytes: null };
34
+ const rows = [...text.matchAll(/^vm\.swapusage:\s+total = (\d+(?:\.\d+)?)M\s+used = (\d+(?:\.\d+)?)M\s+free = (\d+(?:\.\d+)?)M\s*(?:\(encrypted\))?\s*$/gm)];
35
+ if (rows.length !== 1)
36
+ return unknown;
37
+ const [total, used, free] = rows[0].slice(1).map(Number);
38
+ if (![total, used, free].every(Number.isFinite) || free > total || used > total || Math.abs(total - used - free) > 0.02)
39
+ return unknown;
40
+ const totalBytes = Math.round(total * 1024 ** 2), freeBytes = Math.round(free * 1024 ** 2);
41
+ if (!Number.isSafeInteger(totalBytes) || !Number.isSafeInteger(freeBytes))
42
+ return unknown;
43
+ return { swapTotalBytes: totalBytes, swapFreeBytes: freeBytes };
44
+ }
45
+ export const runMemoryCommand = (file, args) => {
46
+ let resolveResult;
47
+ let resolveStopped;
48
+ const result = new Promise(resolve => { resolveResult = resolve; });
49
+ const stopped = new Promise(resolve => { resolveStopped = resolve; });
50
+ try {
51
+ const child = execFile(file, args, {
52
+ encoding: "utf8", env: { ...process.env, LC_ALL: "C", LANG: "C" },
53
+ timeout: 1_500, killSignal: "SIGKILL", maxBuffer: MAX_OUTPUT,
54
+ }, (error, stdout) => resolveResult(error ? null : stdout));
55
+ child.once("close", resolveStopped);
56
+ // A spawn error normally also emits close. Keep the physical reservation until then.
57
+ child.once("error", () => resolveResult(null));
58
+ return { result, stopped, kill: () => { try {
59
+ child.kill("SIGKILL");
60
+ }
61
+ catch { /* wait for close */ } } };
62
+ }
63
+ catch {
64
+ resolveResult(null);
65
+ resolveStopped();
66
+ return { result, stopped, kill: () => { } };
67
+ }
68
+ };
69
+ /** One bounded logical read and at most one physical pair, even across stop/restart. */
70
+ export class DarwinMemoryProbe {
71
+ run;
72
+ total;
73
+ now;
74
+ flight = null;
75
+ cache = null;
76
+ epoch = 0;
77
+ constructor(options = {}) {
78
+ this.run = options.run ?? runMemoryCommand;
79
+ this.total = options.totalmem ?? totalmem;
80
+ this.now = options.now ?? (() => performance.now());
81
+ }
82
+ read() {
83
+ if (this.cache && this.now() - this.cache.at < DARWIN_MEMORY_CACHE_MS)
84
+ return Promise.resolve({ ...this.cache.memory });
85
+ // A timed-out or cancelled pair still owns its physical reservation.
86
+ if (this.flight) {
87
+ const flight = this.flight;
88
+ if (flight.completed)
89
+ return Promise.resolve(unknownDarwinMemory(this.total()));
90
+ return flight.result.then(value => flight.epoch === this.epoch ? { ...value } : unknownDarwinMemory(this.total()));
91
+ }
92
+ const epoch = ++this.epoch, totalBytes = this.total(), deadlineAt = this.now() + DARWIN_MEMORY_DEADLINE_MS;
93
+ const unknown = unknownDarwinMemory(totalBytes);
94
+ const commands = [];
95
+ let settle;
96
+ let completed = false;
97
+ let timer = null;
98
+ const result = new Promise(resolve => { settle = resolve; });
99
+ const finish = (value) => {
100
+ if (completed)
101
+ return;
102
+ completed = true;
103
+ flight.completed = true;
104
+ if (timer)
105
+ clearTimeout(timer);
106
+ if (epoch === this.epoch)
107
+ this.cache = { at: this.now(), memory: { ...value } };
108
+ settle(value);
109
+ };
110
+ const cancel = () => {
111
+ finish(unknown);
112
+ for (const command of commands) {
113
+ try {
114
+ command.kill();
115
+ }
116
+ catch { /* retain until close */ }
117
+ }
118
+ };
119
+ const flight = { completed: false, epoch, result, cancel };
120
+ this.flight = flight;
121
+ // Start the deadline before either constructor; a slow constructor cannot earn extra time.
122
+ timer = setTimeout(cancel, DARWIN_MEMORY_DEADLINE_MS);
123
+ timer.unref?.();
124
+ for (const [file, args] of [["/usr/bin/vm_stat", []], ["/usr/sbin/sysctl", ["vm.swapusage"]]]) {
125
+ if (this.now() >= deadlineAt) {
126
+ cancel();
127
+ break;
128
+ }
129
+ try {
130
+ commands.push(this.run(file, [...args]));
131
+ }
132
+ catch {
133
+ commands.push({ result: Promise.resolve(null), stopped: Promise.resolve(), kill: () => { } });
134
+ }
135
+ }
136
+ void Promise.all(commands.map(command => command.result.catch(() => null))).then(outputs => {
137
+ if (completed)
138
+ return;
139
+ if (epoch !== this.epoch || this.now() >= deadlineAt) {
140
+ cancel();
141
+ return;
142
+ }
143
+ const available = outputs[0] === null || outputs[0] === undefined ? null : parseDarwinAvailable(outputs[0], totalBytes);
144
+ finish(available === null ? unknown : { totalBytes, availableBytes: available, availableKind: "available",
145
+ ...parseDarwinSwap(outputs[1] ?? "") });
146
+ });
147
+ // Never release on kill request/result alone. Rejected cleanup remains reserved.
148
+ void Promise.all(commands.map(command => command.stopped.catch(() => new Promise(() => { })))).then(() => {
149
+ if (this.flight === flight)
150
+ this.flight = null;
151
+ });
152
+ return result.then(value => ({ ...value }));
153
+ }
154
+ stop() {
155
+ this.epoch++;
156
+ this.cache = null;
157
+ this.flight?.cancel();
158
+ }
159
+ }
160
+ //# sourceMappingURL=darwin-memory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"darwin-memory.js","sourceRoot":"","sources":["../src/darwin-memory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAGnC,MAAM,CAAC,MAAM,yBAAyB,GAAG,KAAK,CAAC;AAC/C,MAAM,CAAC,MAAM,sBAAsB,GAAG,MAAM,CAAC;AAC7C,MAAM,UAAU,GAAG,EAAE,GAAG,IAAI,CAAC;AAE7B,MAAM,UAAU,mBAAmB,CAAC,UAAkB;IACpD,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,IAAI,EAAE,aAAa,EAAE,SAAS,EAAE,cAAc,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC;AACnH,CAAC;AAED,+FAA+F;AAC/F,MAAM,UAAU,oBAAoB,CAAC,IAAY,EAAE,UAAkB;IACnE,MAAM,OAAO,GAAG,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,qEAAqE,CAAC,CAAC,CAAC;IAC1G,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,oCAAoC,CAAC,CAAC,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAC/G,MAAM,QAAQ,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACvC,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,QAAQ,CAAC,IAAI,QAAQ,GAAG,IAAI,IAAI,QAAQ,GAAG,IAAI,GAAG,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAC/H,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,KAAK,MAAM,IAAI,IAAI,CAAC,MAAM,EAAE,aAAa,EAAE,UAAU,EAAE,WAAW,CAAC,EAAE,CAAC;QACpE,MAAM,IAAI,GAAG,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,MAAM,CAAC,UAAU,IAAI,qBAAqB,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC;QACvF,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,MAAM,CAAC,UAAU,IAAI,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,IAAI,CAAC;QAC3G,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACjC,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC;YAAE,OAAO,IAAI,CAAC;QAC3D,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACrB,CAAC;IACD,MAAM,CAAC,IAAI,EAAE,WAAW,EAAE,QAAQ,EAAE,SAAS,CAAC,GAAG,MAAM,CAAC;IACxD,MAAM,KAAK,GAAG,CAAC,IAAI,GAAG,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC,GAAG,QAAQ,CAAC;IAC9E,OAAO,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,UAAU,GAAG,CAAC,IAAI,KAAK,IAAI,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;AAC5H,CAAC;AAED,0FAA0F;AAC1F,MAAM,UAAU,eAAe,CAAC,IAAY;IAC1C,MAAM,OAAO,GAAG,EAAE,cAAc,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC;IAC9D,MAAM,IAAI,GAAG,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,2HAA2H,CAAC,CAAC,CAAC;IAC7J,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,OAAO,CAAC;IACtC,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACzD,IAAI,CAAC,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,GAAG,IAAI,GAAG,IAAI,CAAC,GAAG,IAAI;QAAE,OAAO,OAAO,CAAC;IACxI,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,IAAI,IAAI,CAAC,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC;IAC3F,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,SAAS,CAAC;QAAE,OAAO,OAAO,CAAC;IAC1F,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,aAAa,EAAE,SAAS,EAAE,CAAC;AAClE,CAAC;AAUD,MAAM,CAAC,MAAM,gBAAgB,GAAwB,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE;IAClE,IAAI,aAA8C,CAAC;IACnD,IAAI,cAA2B,CAAC;IAChC,MAAM,MAAM,GAAG,IAAI,OAAO,CAAgB,OAAO,CAAC,EAAE,GAAG,aAAa,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;IACnF,MAAM,OAAO,GAAG,IAAI,OAAO,CAAO,OAAO,CAAC,EAAE,GAAG,cAAc,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;IAC5E,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,EAAE,IAAI,EAAE;YACjC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE;YACjE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,SAAS,EAAE,UAAU;SAC7D,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;QAC5D,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC;QACpC,qFAAqF;QACrF,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC;QAC/C,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;gBAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YAAC,CAAC;YAAC,MAAM,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAC5G,CAAC;IAAC,MAAM,CAAC;QACP,aAAa,CAAC,IAAI,CAAC,CAAC;QAAC,cAAc,EAAE,CAAC;QACtC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,GAAE,CAAC,EAAE,CAAC;IAC7C,CAAC;AACH,CAAC,CAAC;AAcF,wFAAwF;AACxF,MAAM,OAAO,iBAAiB;IACX,GAAG,CAAsB;IACzB,KAAK,CAAe;IACpB,GAAG,CAAe;IAC3B,MAAM,GAAkB,IAAI,CAAC;IAC7B,KAAK,GAA8C,IAAI,CAAC;IACxD,KAAK,GAAG,CAAC,CAAC;IAElB,YAAY,UAAmB,EAAE;QAC/B,IAAI,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,gBAAgB,CAAC;QAC3C,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC,QAAQ,IAAI,QAAQ,CAAC;QAC1C,IAAI,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,GAAG,EAAE,CAAC,CAAC;IACtD,CAAC;IAED,IAAI;QACF,IAAI,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,sBAAsB;YAAE,OAAO,OAAO,CAAC,OAAO,CAAC,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;QACxH,qEAAqE;QACrE,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChB,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;YAC3B,IAAI,MAAM,CAAC,SAAS;gBAAE,OAAO,OAAO,CAAC,OAAO,CAAC,mBAAmB,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;YAChF,OAAO,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,MAAM,CAAC,KAAK,KAAK,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,mBAAmB,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;QACrH,CAAC;QACD,MAAM,KAAK,GAAG,EAAE,IAAI,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI,CAAC,KAAK,EAAE,EAAE,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,yBAAyB,CAAC;QAC3G,MAAM,OAAO,GAAG,mBAAmB,CAAC,UAAU,CAAC,CAAC;QAChD,MAAM,QAAQ,GAAoB,EAAE,CAAC;QACrC,IAAI,MAAoC,CAAC;QACzC,IAAI,SAAS,GAAG,KAAK,CAAC;QACtB,IAAI,KAAK,GAAyC,IAAI,CAAC;QACvD,MAAM,MAAM,GAAG,IAAI,OAAO,CAAa,OAAO,CAAC,EAAE,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;QACzE,MAAM,MAAM,GAAG,CAAC,KAAiB,EAAE,EAAE;YACnC,IAAI,SAAS;gBAAE,OAAO;YACtB,SAAS,GAAG,IAAI,CAAC;YACjB,MAAM,CAAC,SAAS,GAAG,IAAI,CAAC;YACxB,IAAI,KAAK;gBAAE,YAAY,CAAC,KAAK,CAAC,CAAC;YAC/B,IAAI,KAAK,KAAK,IAAI,CAAC,KAAK;gBAAE,IAAI,CAAC,KAAK,GAAG,EAAE,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,EAAE,GAAG,KAAK,EAAE,EAAE,CAAC;YAChF,MAAM,CAAC,KAAK,CAAC,CAAC;QAChB,CAAC,CAAC;QACF,MAAM,MAAM,GAAG,GAAG,EAAE;YAClB,MAAM,CAAC,OAAO,CAAC,CAAC;YAChB,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;gBAAC,IAAI,CAAC;oBAAC,OAAO,CAAC,IAAI,EAAE,CAAC;gBAAC,CAAC;gBAAC,MAAM,CAAC,CAAC,wBAAwB,CAAC,CAAC;YAAC,CAAC;QAChG,CAAC,CAAC;QACF,MAAM,MAAM,GAAW,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;QACnE,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,2FAA2F;QAC3F,KAAK,GAAG,UAAU,CAAC,MAAM,EAAE,yBAAyB,CAAC,CAAC;QACtD,KAAK,CAAC,KAAK,EAAE,EAAE,CAAC;QAChB,KAAK,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,kBAAkB,EAAE,EAAE,CAAC,EAAE,CAAC,kBAAkB,EAAE,CAAC,cAAc,CAAC,CAAC,CAAU,EAAE,CAAC;YACvG,IAAI,IAAI,CAAC,GAAG,EAAE,IAAI,UAAU,EAAE,CAAC;gBAAC,MAAM,EAAE,CAAC;gBAAC,MAAM;YAAC,CAAC;YAClD,IAAI,CAAC;gBAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;YAAC,CAAC;YACjD,MAAM,CAAC;gBAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,GAAE,CAAC,EAAE,CAAC,CAAC;YAAC,CAAC;QACzG,CAAC;QACD,KAAK,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE;YACzF,IAAI,SAAS;gBAAE,OAAO;YACtB,IAAI,KAAK,KAAK,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,GAAG,EAAE,IAAI,UAAU,EAAE,CAAC;gBAAC,MAAM,EAAE,CAAC;gBAAC,OAAO;YAAC,CAAC;YAC3E,MAAM,SAAS,GAAG,OAAO,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,OAAO,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,oBAAoB,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC;YACxH,MAAM,CAAC,SAAS,KAAK,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,cAAc,EAAE,SAAS,EAAE,aAAa,EAAE,WAAW;gBACvG,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC;QAC5C,CAAC,CAAC,CAAC;QACH,iFAAiF;QACjF,KAAK,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,OAAO,CAAO,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE;YAC5G,IAAI,IAAI,CAAC,MAAM,KAAK,MAAM;gBAAE,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;QACjD,CAAC,CAAC,CAAC;QACH,OAAO,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,EAAE,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC;IAC9C,CAAC;IAED,IAAI;QACF,IAAI,CAAC,KAAK,EAAE,CAAC;QACb,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QAClB,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC;IACxB,CAAC;CACF"}
@@ -955,6 +955,11 @@ export declare class FleetManager implements FleetContext, LifecycleContext, Arc
955
955
  };
956
956
  /** Start the primary adapter (backward-compatible, sets this.adapter) */
957
957
  private startSingleAdapter;
958
+ /**
959
+ * Register a Telegram connection's command menus; any other kind of channel has none to register. Started, not
960
+ * awaited: a slow api.telegram.org must never hold up the adapter's login (each call has its own timeout). Never fatal.
961
+ */
962
+ private registerTelegramCommandsFor;
958
963
  /** Start an additional (non-primary) adapter */
959
964
  private startAdditionalAdapter;
960
965
  /** Connect IPC to a single instance with all handlers */
@@ -2131,6 +2136,11 @@ export declare class FleetManager implements FleetContext, LifecycleContext, Arc
2131
2136
  private effortSuffix;
2132
2137
  /** Read recent chat log for agent context */
2133
2138
  private getRecentChatLog;
2139
+ /**
2140
+ * The ClassicBot /start replies say how to talk to the agent, and that differs by platform (#1196): on Telegram
2141
+ * you @mention the bot; on Discord, @mention or `/chat`. The chat's platform is the adapter it came through.
2142
+ */
2143
+ private classicStartKey;
2134
2144
  /** Return a user-facing blocker without mutating ClassicBot state. */
2135
2145
  private validateClassicStart;
2136
2146
  private isBackendInstalled;
@@ -988,6 +988,10 @@ export class FleetManager {
988
988
  this.logger.debug({ hostMemory: snapshot }, "Host memory sample");
989
989
  }
990
990
  const changed = snapshot.level !== this.memoryLogLevel;
991
+ if (this.memoryPressure.allowsUnknown(snapshot)) {
992
+ this.memoryLogLevel = snapshot.level;
993
+ return;
994
+ }
991
995
  if (snapshot.level === "normal") {
992
996
  if (this.memoryLogLevel === "critical" || this.memoryLogLevel === "elevated") {
993
997
  this.logger.info({ hostMemory: snapshot }, "Host memory recovered");
@@ -2790,10 +2794,8 @@ export class FleetManager {
2790
2794
  // it before lifecycle.start() can turn a crash-loop daemon's dead pane into
2791
2795
  // a falsely running instance when lifecycle.start() returns early.
2792
2796
  this.instanceProcessStatus.delete(name);
2793
- try {
2794
- unlinkSync(join(this.getInstanceDir(name), "crash-state.json"));
2795
- }
2796
- catch { /* consumed or absent */ }
2797
+ // Recovery intent belongs to Daemon.start. lifecycle.start can return
2798
+ // before reaching it, so an await here is not proof the marker was read.
2797
2799
  // Auto-connect IPC — daemon.start() ensures socket is ready before resolving
2798
2800
  await this.connectIpcToInstance(name);
2799
2801
  this.requestDiscordUsagePresenceRefresh();
@@ -4513,7 +4515,8 @@ export class FleetManager {
4513
4515
  return;
4514
4516
  await this.dispatchSlash(data, adapterId, adapter);
4515
4517
  }, this.logger, "adapter.slash_command"));
4516
- await this.topicCommands.registerBotCommands().catch(e => this.logger.warn({ err: e }, "registerBotCommands failed (non-fatal)"));
4518
+ // This adapter's own Telegram menus — each Telegram adapter registers its own when it starts (#1191).
4519
+ this.registerTelegramCommandsFor(channelConfig);
4517
4520
  // Background-probe each backend's CLI env (version/models) → cli-env cache.
4518
4521
  // Non-blocking: /model & status views read the cache; never delays startup.
4519
4522
  this.probeCliEnvs();
@@ -4568,6 +4571,15 @@ export class FleetManager {
4568
4571
  this.pruneStaleExternalSessions().catch(err => this.logger.debug({ err }, "Session prune failed"));
4569
4572
  }, 5 * 60 * 1000);
4570
4573
  }
4574
+ /**
4575
+ * Register a Telegram connection's command menus; any other kind of channel has none to register. Started, not
4576
+ * awaited: a slow api.telegram.org must never hold up the adapter's login (each call has its own timeout). Never fatal.
4577
+ */
4578
+ registerTelegramCommandsFor(channelConfig) {
4579
+ if (channelConfig.type !== "telegram")
4580
+ return;
4581
+ void this.topicCommands.registerBotCommands(channelConfig).catch(e => this.logger.warn({ err: e, adapterId: channelConfig.id ?? channelConfig.type }, "registerBotCommands failed (non-fatal)"));
4582
+ }
4571
4583
  /** Start an additional (non-primary) adapter */
4572
4584
  async startAdditionalAdapter(channelConfig, registerCommands = true, onStarted) {
4573
4585
  const adapterId = channelConfig.id ?? channelConfig.type;
@@ -4643,6 +4655,9 @@ export class FleetManager {
4643
4655
  this.logger.error({ err, adapterId }, "Additional adapter fatal error");
4644
4656
  this.restartAdapter(adapter, adapterId).catch(() => { });
4645
4657
  });
4658
+ // A secondary Telegram connection (a ClassicBot next to a Discord fleet, say) has menus of its own to register —
4659
+ // at fleet start, on retry, and when Settings rebinds it or rotates its token: all of them start it here (#1191).
4660
+ this.registerTelegramCommandsFor(channelConfig);
4646
4661
  // Register lifecycle listeners before login; a fast ready/error must not be lost.
4647
4662
  await adapter.start();
4648
4663
  if (channelConfig.group_id) {
@@ -11919,6 +11934,14 @@ Plus the operational skills (fleet-health, instance-lifecycle, scheduling, sessi
11919
11934
  return undefined;
11920
11935
  }
11921
11936
  }
11937
+ /**
11938
+ * The ClassicBot /start replies say how to talk to the agent, and that differs by platform (#1196): on Telegram
11939
+ * you @mention the bot; on Discord, @mention or `/chat`. The chat's platform is the adapter it came through.
11940
+ */
11941
+ classicStartKey(key, adapterId) {
11942
+ const adapter = (adapterId ? this.worlds.get(adapterId)?.adapter : undefined) ?? this.adapter;
11943
+ return adapter?.type === "telegram" ? `${key}.telegram` : key;
11944
+ }
11922
11945
  /** Return a user-facing blocker without mutating ClassicBot state. */
11923
11946
  validateClassicStart(channelId, userId, guildId, adapterId) {
11924
11947
  if (!this.classicChannels)
@@ -11940,7 +11963,7 @@ Plus the operational skills (fleet-health, instance-lifecycle, scheduling, sessi
11940
11963
  return t("classic.not_authorized_guild");
11941
11964
  }
11942
11965
  if (this.classicChannels.isClassicChannel(channelId, adapterId))
11943
- return t("classic.already_active");
11966
+ return t(this.classicStartKey("classic.already_active", adapterId));
11944
11967
  if (this.routing.resolve(channelId))
11945
11968
  return t("classic.topic_bound");
11946
11969
  return undefined;
@@ -12127,7 +12150,7 @@ Plus the operational skills (fleet-health, instance-lifecycle, scheduling, sessi
12127
12150
  classicChannels.toggleCollab(channelId, adapterId);
12128
12151
  }
12129
12152
  this.logger.info({ channelId, adapterId, instanceName, userId }, "Classic channel started");
12130
- return t("classic.started");
12153
+ return t(this.classicStartKey("classic.started", adapterId));
12131
12154
  }
12132
12155
  /** Handle /stop slash command — unregister classic channel */
12133
12156
  async handleClassicStop(channelId, adapterId) {