@suzuke/agend 1.2.0 → 1.3.0

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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"instance-lifecycle.js","sourceRoot":"","sources":["../src/instance-lifecycle.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ import type { FleetConfig, InstanceConfig } from "./types.js";
2
+ import type { ChannelAdapter } from "./channel/types.js";
3
+ import type { IpcClient } from "./channel/ipc-bridge.js";
4
+ import type { Logger } from "./logger.js";
5
+ import type { RoutingEngine } from "./routing-engine.js";
6
+ import type { InstanceLifecycle } from "./instance-lifecycle.js";
7
+ /** Shared context available to all outbound tool handlers. */
8
+ export interface OutboundContext {
9
+ readonly fleetConfig: FleetConfig | null;
10
+ readonly adapter: ChannelAdapter | null;
11
+ readonly logger: Logger;
12
+ readonly routing: RoutingEngine;
13
+ readonly instanceIpcClients: Map<string, IpcClient>;
14
+ readonly lifecycle: InstanceLifecycle;
15
+ readonly sessionRegistry: Map<string, string>;
16
+ lastActivityMs(name: string): number;
17
+ startInstance(name: string, config: InstanceConfig, topicMode: boolean): Promise<void>;
18
+ connectIpcToInstance(name: string): Promise<void>;
19
+ }
20
+ /** Metadata extracted from the raw outbound message. */
21
+ export interface OutboundMeta {
22
+ instanceName: string;
23
+ requestId: number | undefined;
24
+ fleetRequestId: string | undefined;
25
+ senderSessionName: string | undefined;
26
+ }
27
+ type Respond = (result: unknown, error?: string) => void;
28
+ type Handler = (ctx: OutboundContext, args: Record<string, unknown>, respond: Respond, meta: OutboundMeta) => Promise<void> | void;
29
+ export declare const outboundHandlers: Map<string, Handler>;
30
+ export {};
@@ -0,0 +1,206 @@
1
+ // ── Handler implementations ─────────────────────────────────────────────
2
+ const sendToInstance = (ctx, args, respond, meta) => {
3
+ const targetName = args.instance_name;
4
+ const message = args.message;
5
+ if (!targetName) {
6
+ respond(null, "send_to_instance: missing required argument 'instance_name'");
7
+ return;
8
+ }
9
+ if (!message) {
10
+ respond(null, "send_to_instance: missing required argument 'message'");
11
+ return;
12
+ }
13
+ const senderLabel = meta.senderSessionName ?? meta.instanceName;
14
+ const isExternalSender = meta.senderSessionName != null && meta.senderSessionName !== meta.instanceName;
15
+ let targetIpc = ctx.instanceIpcClients.get(targetName);
16
+ let targetSession = targetName;
17
+ let targetInstanceName = targetName;
18
+ if (!targetIpc) {
19
+ const hostInstance = ctx.sessionRegistry.get(targetName);
20
+ if (hostInstance) {
21
+ targetIpc = ctx.instanceIpcClients.get(hostInstance);
22
+ targetSession = targetName;
23
+ targetInstanceName = hostInstance;
24
+ }
25
+ }
26
+ if (!targetIpc) {
27
+ const existsInConfig = targetName in (ctx.fleetConfig?.instances ?? {});
28
+ if (existsInConfig) {
29
+ respond(null, `Instance '${targetName}' is stopped. Use start_instance('${targetName}') to start it first.`);
30
+ }
31
+ else {
32
+ respond(null, `Instance or session not found: ${targetName}`);
33
+ }
34
+ return;
35
+ }
36
+ const correlationId = args.correlation_id || `cid-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
37
+ const ipcMeta = {
38
+ chat_id: "",
39
+ message_id: `xmsg-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
40
+ user: `instance:${senderLabel}`,
41
+ user_id: `instance:${senderLabel}`,
42
+ ts: new Date().toISOString(),
43
+ thread_id: "",
44
+ from_instance: senderLabel,
45
+ correlation_id: correlationId,
46
+ };
47
+ if (args.request_kind)
48
+ ipcMeta.request_kind = args.request_kind;
49
+ if (args.requires_reply != null)
50
+ ipcMeta.requires_reply = String(args.requires_reply);
51
+ if (args.task_summary)
52
+ ipcMeta.task_summary = args.task_summary;
53
+ if (args.working_directory)
54
+ ipcMeta.working_directory = args.working_directory;
55
+ if (args.branch)
56
+ ipcMeta.branch = args.branch;
57
+ targetIpc.send({ type: "fleet_inbound", targetSession, content: message, meta: ipcMeta });
58
+ // Post to channel topics for visibility
59
+ const groupId = ctx.fleetConfig?.channel?.group_id;
60
+ if (groupId && ctx.adapter) {
61
+ const senderTopicId = ctx.fleetConfig?.instances[meta.instanceName]?.topic_id;
62
+ const targetTopicId = ctx.fleetConfig?.instances[targetInstanceName]?.topic_id;
63
+ if (senderTopicId && !isExternalSender) {
64
+ ctx.adapter.sendText(String(groupId), `→ ${targetName}:\n${message}`, {
65
+ threadId: String(senderTopicId),
66
+ }).catch(e => ctx.logger.warn({ err: e }, "Failed to post cross-instance notification"));
67
+ }
68
+ if (targetTopicId && !ctx.sessionRegistry.has(targetName)) {
69
+ ctx.adapter.sendText(String(groupId), `← ${senderLabel}:\n${message}`, {
70
+ threadId: String(targetTopicId),
71
+ }).catch(e => ctx.logger.warn({ err: e }, "Failed to post cross-instance notification"));
72
+ }
73
+ }
74
+ ctx.logger.info(`✉ ${senderLabel} → ${targetName}: ${(message ?? "").slice(0, 100)}`);
75
+ respond({ sent: true, target: targetName, correlation_id: correlationId });
76
+ };
77
+ const listInstances = (ctx, _args, respond, meta) => {
78
+ const senderLabel = meta.senderSessionName ?? meta.instanceName;
79
+ const allInstances = Object.entries(ctx.fleetConfig?.instances ?? {})
80
+ .filter(([name]) => name !== meta.instanceName && name !== senderLabel)
81
+ .map(([name, config]) => ({
82
+ name,
83
+ type: "instance",
84
+ status: ctx.lifecycle.daemons.has(name) ? "running" : "stopped",
85
+ working_directory: config.working_directory,
86
+ topic_id: config.topic_id ?? null,
87
+ description: config.description ?? null,
88
+ tags: config.tags ?? [],
89
+ last_activity: ctx.lastActivityMs(name) ? new Date(ctx.lastActivityMs(name)).toISOString() : null,
90
+ }));
91
+ const externalSessions = [...ctx.sessionRegistry.entries()]
92
+ .filter(([sessName]) => sessName !== senderLabel)
93
+ .map(([sessName, hostInstance]) => ({ name: sessName, type: "session", host: hostInstance }));
94
+ respond({ instances: allInstances, external_sessions: externalSessions });
95
+ };
96
+ const describeInstance = (ctx, args, respond) => {
97
+ const targetName = args.name;
98
+ const config = ctx.fleetConfig?.instances[targetName];
99
+ if (config) {
100
+ respond({
101
+ name: targetName,
102
+ type: "instance",
103
+ description: config.description ?? null,
104
+ tags: config.tags ?? [],
105
+ working_directory: config.working_directory,
106
+ status: ctx.lifecycle.daemons.has(targetName) ? "running" : "stopped",
107
+ topic_id: config.topic_id ?? null,
108
+ model: config.model ?? null,
109
+ last_activity: ctx.lastActivityMs(targetName) ? new Date(ctx.lastActivityMs(targetName)).toISOString() : null,
110
+ worktree_source: config.worktree_source ?? null,
111
+ });
112
+ return;
113
+ }
114
+ const hostInstance = ctx.sessionRegistry.get(targetName);
115
+ if (hostInstance) {
116
+ respond({ name: targetName, type: "session", host: hostInstance, status: "running" });
117
+ return;
118
+ }
119
+ respond(null, `Instance or session '${targetName}' not found`);
120
+ };
121
+ const startInstance = async (ctx, args, respond) => {
122
+ const targetName = args.name;
123
+ if (ctx.lifecycle.daemons.has(targetName)) {
124
+ respond({ success: true, status: "already_running" });
125
+ return;
126
+ }
127
+ const targetConfig = ctx.fleetConfig?.instances[targetName];
128
+ if (!targetConfig) {
129
+ respond(null, `Instance '${targetName}' not found in fleet config`);
130
+ return;
131
+ }
132
+ try {
133
+ await ctx.startInstance(targetName, targetConfig, true);
134
+ await ctx.connectIpcToInstance(targetName);
135
+ respond({ success: true, status: "started" });
136
+ }
137
+ catch (err) {
138
+ respond(null, `Failed to start instance '${targetName}': ${err.message}`);
139
+ }
140
+ };
141
+ /** Wrap send_to_instance with pre-filled metadata fields. */
142
+ function wrapAsSend(buildArgs, warnMissing) {
143
+ return (ctx, args, respond, meta) => {
144
+ if (warnMissing)
145
+ warnMissing(ctx, args, meta);
146
+ const { targetName, body, kind, reply, summary } = buildArgs(args);
147
+ const newArgs = { ...args, instance_name: targetName, message: body, request_kind: kind, requires_reply: reply, task_summary: summary };
148
+ // Re-dispatch through the handler map
149
+ return sendToInstance(ctx, newArgs, respond, meta);
150
+ };
151
+ }
152
+ const requestInformation = wrapAsSend((args) => {
153
+ const targetName = args.target_instance;
154
+ const question = args.question;
155
+ const context = args.context;
156
+ return {
157
+ targetName,
158
+ body: context ? `${question}\n\nContext: ${context}` : question,
159
+ kind: "query", reply: true,
160
+ summary: question.slice(0, 120),
161
+ };
162
+ });
163
+ const delegateTask = wrapAsSend((args) => {
164
+ const targetName = args.target_instance;
165
+ const task = args.task;
166
+ const criteria = args.success_criteria;
167
+ const context = args.context;
168
+ let body = task;
169
+ if (criteria)
170
+ body += `\n\nSuccess criteria: ${criteria}`;
171
+ if (context)
172
+ body += `\n\nContext: ${context}`;
173
+ return { targetName, body, kind: "task", reply: true, summary: task.slice(0, 120) };
174
+ });
175
+ const reportResult = wrapAsSend((args) => {
176
+ const targetName = args.target_instance;
177
+ const summary = args.summary;
178
+ const artifacts = args.artifacts;
179
+ let body = summary;
180
+ if (artifacts)
181
+ body += `\n\nArtifacts: ${artifacts}`;
182
+ return { targetName, body, kind: "report", reply: false, summary: summary.slice(0, 120) };
183
+ }, (ctx, args, meta) => {
184
+ if (!args.correlation_id) {
185
+ ctx.logger.warn({ instanceName: meta.instanceName, targetName: args.target_instance }, "report_result called without correlation_id");
186
+ }
187
+ });
188
+ const createInstance = async (ctx, args, respond) => {
189
+ await ctx.lifecycle.handleCreate(args, respond);
190
+ };
191
+ const deleteInstance = async (ctx, args, respond) => {
192
+ await ctx.lifecycle.handleDelete(args, respond);
193
+ };
194
+ // ── Registry ────────────────────────────────────────────────────────────
195
+ export const outboundHandlers = new Map([
196
+ ["send_to_instance", sendToInstance],
197
+ ["list_instances", listInstances],
198
+ ["request_information", requestInformation],
199
+ ["delegate_task", delegateTask],
200
+ ["report_result", reportResult],
201
+ ["describe_instance", describeInstance],
202
+ ["start_instance", startInstance],
203
+ ["create_instance", createInstance],
204
+ ["delete_instance", deleteInstance],
205
+ ]);
206
+ //# sourceMappingURL=outbound-handlers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"outbound-handlers.js","sourceRoot":"","sources":["../src/outbound-handlers.ts"],"names":[],"mappings":"AAgCA,2EAA2E;AAE3E,MAAM,cAAc,GAAY,CAAC,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE;IAC3D,MAAM,UAAU,GAAG,IAAI,CAAC,aAAuB,CAAC;IAChD,MAAM,OAAO,GAAG,IAAI,CAAC,OAA6B,CAAC;IACnD,IAAI,CAAC,UAAU,EAAE,CAAC;QAAC,OAAO,CAAC,IAAI,EAAE,6DAA6D,CAAC,CAAC;QAAC,OAAO;IAAC,CAAC;IAC1G,IAAI,CAAC,OAAO,EAAE,CAAC;QAAC,OAAO,CAAC,IAAI,EAAE,uDAAuD,CAAC,CAAC;QAAC,OAAO;IAAC,CAAC;IACjG,MAAM,WAAW,GAAG,IAAI,CAAC,iBAAiB,IAAI,IAAI,CAAC,YAAY,CAAC;IAChE,MAAM,gBAAgB,GAAG,IAAI,CAAC,iBAAiB,IAAI,IAAI,IAAI,IAAI,CAAC,iBAAiB,KAAK,IAAI,CAAC,YAAY,CAAC;IAExG,IAAI,SAAS,GAAG,GAAG,CAAC,kBAAkB,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IACvD,IAAI,aAAa,GAAW,UAAU,CAAC;IACvC,IAAI,kBAAkB,GAAG,UAAU,CAAC;IAEpC,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,YAAY,GAAG,GAAG,CAAC,eAAe,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QACzD,IAAI,YAAY,EAAE,CAAC;YACjB,SAAS,GAAG,GAAG,CAAC,kBAAkB,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;YACrD,aAAa,GAAG,UAAU,CAAC;YAC3B,kBAAkB,GAAG,YAAY,CAAC;QACpC,CAAC;IACH,CAAC;IAED,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,cAAc,GAAG,UAAU,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,SAAS,IAAI,EAAE,CAAC,CAAC;QACxE,IAAI,cAAc,EAAE,CAAC;YACnB,OAAO,CAAC,IAAI,EAAE,aAAa,UAAU,qCAAqC,UAAU,uBAAuB,CAAC,CAAC;QAC/G,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,IAAI,EAAE,kCAAkC,UAAU,EAAE,CAAC,CAAC;QAChE,CAAC;QACD,OAAO;IACT,CAAC;IAED,MAAM,aAAa,GAAI,IAAI,CAAC,cAAyB,IAAI,OAAO,IAAI,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;IACvH,MAAM,OAAO,GAA2B;QACtC,OAAO,EAAE,EAAE;QACX,UAAU,EAAE,QAAQ,IAAI,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE;QAC1E,IAAI,EAAE,YAAY,WAAW,EAAE;QAC/B,OAAO,EAAE,YAAY,WAAW,EAAE;QAClC,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QAC5B,SAAS,EAAE,EAAE;QACb,aAAa,EAAE,WAAW;QAC1B,cAAc,EAAE,aAAa;KAC9B,CAAC;IACF,IAAI,IAAI,CAAC,YAAY;QAAE,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,YAAsB,CAAC;IAC1E,IAAI,IAAI,CAAC,cAAc,IAAI,IAAI;QAAE,OAAO,CAAC,cAAc,GAAG,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IACtF,IAAI,IAAI,CAAC,YAAY;QAAE,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,YAAsB,CAAC;IAC1E,IAAI,IAAI,CAAC,iBAAiB;QAAE,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC,iBAA2B,CAAC;IACzF,IAAI,IAAI,CAAC,MAAM;QAAE,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,MAAgB,CAAC;IAExD,SAAS,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,eAAe,EAAE,aAAa,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;IAE1F,wCAAwC;IACxC,MAAM,OAAO,GAAG,GAAG,CAAC,WAAW,EAAE,OAAO,EAAE,QAAQ,CAAC;IACnD,IAAI,OAAO,IAAI,GAAG,CAAC,OAAO,EAAE,CAAC;QAC3B,MAAM,aAAa,GAAG,GAAG,CAAC,WAAW,EAAE,SAAS,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,QAAQ,CAAC;QAC9E,MAAM,aAAa,GAAG,GAAG,CAAC,WAAW,EAAE,SAAS,CAAC,kBAAkB,CAAC,EAAE,QAAQ,CAAC;QAC/E,IAAI,aAAa,IAAI,CAAC,gBAAgB,EAAE,CAAC;YACvC,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,KAAK,UAAU,MAAM,OAAO,EAAE,EAAE;gBACpE,QAAQ,EAAE,MAAM,CAAC,aAAa,CAAC;aAChC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,EAAE,4CAA4C,CAAC,CAAC,CAAC;QAC3F,CAAC;QACD,IAAI,aAAa,IAAI,CAAC,GAAG,CAAC,eAAe,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC;YAC1D,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,KAAK,WAAW,MAAM,OAAO,EAAE,EAAE;gBACrE,QAAQ,EAAE,MAAM,CAAC,aAAa,CAAC;aAChC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,EAAE,4CAA4C,CAAC,CAAC,CAAC;QAC3F,CAAC;IACH,CAAC;IAED,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,WAAW,MAAM,UAAU,KAAK,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;IACtF,OAAO,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,cAAc,EAAE,aAAa,EAAE,CAAC,CAAC;AAC7E,CAAC,CAAC;AAEF,MAAM,aAAa,GAAY,CAAC,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE;IAC3D,MAAM,WAAW,GAAG,IAAI,CAAC,iBAAiB,IAAI,IAAI,CAAC,YAAY,CAAC;IAChE,MAAM,YAAY,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,EAAE,SAAS,IAAI,EAAE,CAAC;SAClE,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,IAAI,KAAK,IAAI,CAAC,YAAY,IAAI,IAAI,KAAK,WAAW,CAAC;SACtE,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC;QACxB,IAAI;QACJ,IAAI,EAAE,UAAmB;QACzB,MAAM,EAAE,GAAG,CAAC,SAAS,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS;QAC/D,iBAAiB,EAAE,MAAM,CAAC,iBAAiB;QAC3C,QAAQ,EAAE,MAAM,CAAC,QAAQ,IAAI,IAAI;QACjC,WAAW,EAAE,MAAM,CAAC,WAAW,IAAI,IAAI;QACvC,IAAI,EAAE,MAAM,CAAC,IAAI,IAAI,EAAE;QACvB,aAAa,EAAE,GAAG,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,IAAI;KAClG,CAAC,CAAC,CAAC;IACN,MAAM,gBAAgB,GAAG,CAAC,GAAG,GAAG,CAAC,eAAe,CAAC,OAAO,EAAE,CAAC;SACxD,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC,QAAQ,KAAK,WAAW,CAAC;SAChD,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE,YAAY,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAkB,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC;IACzG,OAAO,CAAC,EAAE,SAAS,EAAE,YAAY,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,CAAC,CAAC;AAC5E,CAAC,CAAC;AAEF,MAAM,gBAAgB,GAAY,CAAC,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE;IACvD,MAAM,UAAU,GAAG,IAAI,CAAC,IAAc,CAAC;IACvC,MAAM,MAAM,GAAG,GAAG,CAAC,WAAW,EAAE,SAAS,CAAC,UAAU,CAAC,CAAC;IACtD,IAAI,MAAM,EAAE,CAAC;QACX,OAAO,CAAC;YACN,IAAI,EAAE,UAAU;YAChB,IAAI,EAAE,UAAU;YAChB,WAAW,EAAE,MAAM,CAAC,WAAW,IAAI,IAAI;YACvC,IAAI,EAAE,MAAM,CAAC,IAAI,IAAI,EAAE;YACvB,iBAAiB,EAAE,MAAM,CAAC,iBAAiB;YAC3C,MAAM,EAAE,GAAG,CAAC,SAAS,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS;YACrE,QAAQ,EAAE,MAAM,CAAC,QAAQ,IAAI,IAAI;YACjC,KAAK,EAAE,MAAM,CAAC,KAAK,IAAI,IAAI;YAC3B,aAAa,EAAE,GAAG,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,IAAI;YAC7G,eAAe,EAAE,MAAM,CAAC,eAAe,IAAI,IAAI;SAChD,CAAC,CAAC;QACH,OAAO;IACT,CAAC;IACD,MAAM,YAAY,GAAG,GAAG,CAAC,eAAe,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IACzD,IAAI,YAAY,EAAE,CAAC;QACjB,OAAO,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC;QACtF,OAAO;IACT,CAAC;IACD,OAAO,CAAC,IAAI,EAAE,wBAAwB,UAAU,aAAa,CAAC,CAAC;AACjE,CAAC,CAAC;AAEF,MAAM,aAAa,GAAY,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE;IAC1D,MAAM,UAAU,GAAG,IAAI,CAAC,IAAc,CAAC;IACvC,IAAI,GAAG,CAAC,SAAS,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC;QAC1C,OAAO,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,iBAAiB,EAAE,CAAC,CAAC;QACtD,OAAO;IACT,CAAC;IACD,MAAM,YAAY,GAAG,GAAG,CAAC,WAAW,EAAE,SAAS,CAAC,UAAU,CAAC,CAAC;IAC5D,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,OAAO,CAAC,IAAI,EAAE,aAAa,UAAU,6BAA6B,CAAC,CAAC;QACpE,OAAO;IACT,CAAC;IACD,IAAI,CAAC;QACH,MAAM,GAAG,CAAC,aAAa,CAAC,UAAU,EAAE,YAAY,EAAE,IAAI,CAAC,CAAC;QACxD,MAAM,GAAG,CAAC,oBAAoB,CAAC,UAAU,CAAC,CAAC;QAC3C,OAAO,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC;IAChD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,IAAI,EAAE,6BAA6B,UAAU,MAAO,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC;IACvF,CAAC;AACH,CAAC,CAAC;AAEF,6DAA6D;AAC7D,SAAS,UAAU,CACjB,SAAiI,EACjI,WAA+F;IAE/F,OAAO,CAAC,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE;QAClC,IAAI,WAAW;YAAE,WAAW,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;QAC9C,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;QACnE,MAAM,OAAO,GAAG,EAAE,GAAG,IAAI,EAAE,aAAa,EAAE,UAAU,EAAE,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,cAAc,EAAE,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,CAAC;QACxI,sCAAsC;QACtC,OAAO,cAAc,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;IACrD,CAAC,CAAC;AACJ,CAAC;AAED,MAAM,kBAAkB,GAAG,UAAU,CAAC,CAAC,IAAI,EAAE,EAAE;IAC7C,MAAM,UAAU,GAAG,IAAI,CAAC,eAAyB,CAAC;IAClD,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAkB,CAAC;IACzC,MAAM,OAAO,GAAG,IAAI,CAAC,OAA6B,CAAC;IACnD,OAAO;QACL,UAAU;QACV,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,QAAQ,gBAAgB,OAAO,EAAE,CAAC,CAAC,CAAC,QAAQ;QAC/D,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI;QAC1B,OAAO,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC;KAChC,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,MAAM,YAAY,GAAG,UAAU,CAAC,CAAC,IAAI,EAAE,EAAE;IACvC,MAAM,UAAU,GAAG,IAAI,CAAC,eAAyB,CAAC;IAClD,MAAM,IAAI,GAAG,IAAI,CAAC,IAAc,CAAC;IACjC,MAAM,QAAQ,GAAG,IAAI,CAAC,gBAAsC,CAAC;IAC7D,MAAM,OAAO,GAAG,IAAI,CAAC,OAA6B,CAAC;IACnD,IAAI,IAAI,GAAG,IAAI,CAAC;IAChB,IAAI,QAAQ;QAAE,IAAI,IAAI,yBAAyB,QAAQ,EAAE,CAAC;IAC1D,IAAI,OAAO;QAAE,IAAI,IAAI,gBAAgB,OAAO,EAAE,CAAC;IAC/C,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC;AACtF,CAAC,CAAC,CAAC;AAEH,MAAM,YAAY,GAAG,UAAU,CAC7B,CAAC,IAAI,EAAE,EAAE;IACP,MAAM,UAAU,GAAG,IAAI,CAAC,eAAyB,CAAC;IAClD,MAAM,OAAO,GAAG,IAAI,CAAC,OAAiB,CAAC;IACvC,MAAM,SAAS,GAAG,IAAI,CAAC,SAA+B,CAAC;IACvD,IAAI,IAAI,GAAG,OAAO,CAAC;IACnB,IAAI,SAAS;QAAE,IAAI,IAAI,kBAAkB,SAAS,EAAE,CAAC;IACrD,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC;AAC5F,CAAC,EACD,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE;IAClB,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC;QACzB,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,YAAY,EAAE,IAAI,CAAC,YAAY,EAAE,UAAU,EAAE,IAAI,CAAC,eAAe,EAAE,EAAE,6CAA6C,CAAC,CAAC;IACxI,CAAC;AACH,CAAC,CACF,CAAC;AAEF,MAAM,cAAc,GAAY,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE;IAC3D,MAAM,GAAG,CAAC,SAAS,CAAC,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;AAClD,CAAC,CAAC;AAEF,MAAM,cAAc,GAAY,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE;IAC3D,MAAM,GAAG,CAAC,SAAS,CAAC,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;AAClD,CAAC,CAAC;AAEF,2EAA2E;AAE3E,MAAM,CAAC,MAAM,gBAAgB,GAAG,IAAI,GAAG,CAAkB;IACvD,CAAC,kBAAkB,EAAE,cAAc,CAAC;IACpC,CAAC,gBAAgB,EAAE,aAAa,CAAC;IACjC,CAAC,qBAAqB,EAAE,kBAAkB,CAAC;IAC3C,CAAC,eAAe,EAAE,YAAY,CAAC;IAC/B,CAAC,eAAe,EAAE,YAAY,CAAC;IAC/B,CAAC,mBAAmB,EAAE,gBAAgB,CAAC;IACvC,CAAC,gBAAgB,EAAE,aAAa,CAAC;IACjC,CAAC,iBAAiB,EAAE,cAAc,CAAC;IACnC,CAAC,iBAAiB,EAAE,cAAc,CAAC;CACpC,CAAC,CAAC"}
@@ -0,0 +1,22 @@
1
+ import type { FleetConfig } from "./types.js";
2
+ import { type RouteTarget } from "./fleet-context.js";
3
+ /**
4
+ * Manages the topic→instance routing table.
5
+ * All topic IDs are normalized to strings to avoid snowflake precision loss.
6
+ */
7
+ export declare class RoutingEngine {
8
+ private table;
9
+ /** Rebuild routing table from fleet config. Returns summary string for logging. */
10
+ rebuild(config: FleetConfig): string;
11
+ /** Resolve a thread ID to a route target. */
12
+ resolve(threadId: string): RouteTarget | undefined;
13
+ /** Register a new topic→instance mapping. */
14
+ register(topicId: number | string, target: RouteTarget): void;
15
+ /** Remove a topic from the routing table. */
16
+ unregister(topicId: number | string): void;
17
+ /** Iterate over all routes. */
18
+ entries(): IterableIterator<[string, RouteTarget]>;
19
+ /** Get the underlying map (for FleetContext compatibility). */
20
+ get map(): Map<string, RouteTarget>;
21
+ get size(): number;
22
+ }
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Manages the topic→instance routing table.
3
+ * All topic IDs are normalized to strings to avoid snowflake precision loss.
4
+ */
5
+ export class RoutingEngine {
6
+ table = new Map();
7
+ /** Rebuild routing table from fleet config. Returns summary string for logging. */
8
+ rebuild(config) {
9
+ this.table.clear();
10
+ for (const [name, inst] of Object.entries(config.instances)) {
11
+ if (inst.topic_id != null) {
12
+ this.table.set(String(inst.topic_id), {
13
+ kind: inst.general_topic ? "general" : "instance",
14
+ name,
15
+ });
16
+ }
17
+ }
18
+ return [...this.table.entries()].map(([tid, t]) => `#${tid}→${t.name}`).join(", ");
19
+ }
20
+ /** Resolve a thread ID to a route target. */
21
+ resolve(threadId) {
22
+ return this.table.get(threadId);
23
+ }
24
+ /** Register a new topic→instance mapping. */
25
+ register(topicId, target) {
26
+ this.table.set(String(topicId), target);
27
+ }
28
+ /** Remove a topic from the routing table. */
29
+ unregister(topicId) {
30
+ this.table.delete(String(topicId));
31
+ }
32
+ /** Iterate over all routes. */
33
+ entries() {
34
+ return this.table.entries();
35
+ }
36
+ /** Get the underlying map (for FleetContext compatibility). */
37
+ get map() {
38
+ return this.table;
39
+ }
40
+ get size() {
41
+ return this.table.size;
42
+ }
43
+ }
44
+ //# sourceMappingURL=routing-engine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routing-engine.js","sourceRoot":"","sources":["../src/routing-engine.ts"],"names":[],"mappings":"AAGA;;;GAGG;AACH,MAAM,OAAO,aAAa;IAChB,KAAK,GAAG,IAAI,GAAG,EAAuB,CAAC;IAE/C,mFAAmF;IACnF,OAAO,CAAC,MAAmB;QACzB,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QACnB,KAAK,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC;YAC5D,IAAI,IAAI,CAAC,QAAQ,IAAI,IAAI,EAAE,CAAC;gBAC1B,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE;oBACpC,IAAI,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,UAAU;oBACjD,IAAI;iBACL,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QACD,OAAO,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACrF,CAAC;IAED,6CAA6C;IAC7C,OAAO,CAAC,QAAgB;QACtB,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAClC,CAAC;IAED,6CAA6C;IAC7C,QAAQ,CAAC,OAAwB,EAAE,MAAmB;QACpD,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,CAAC;IAC1C,CAAC;IAED,6CAA6C;IAC7C,UAAU,CAAC,OAAwB;QACjC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;IACrC,CAAC;IAED,+BAA+B;IAC/B,OAAO;QACL,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;IAC9B,CAAC;IAED,+DAA+D;IAC/D,IAAI,GAAG;QACL,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;IAED,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;IACzB,CAAC;CACF"}
@@ -0,0 +1,32 @@
1
+ import type { CostGuard } from "./cost-guard.js";
2
+ import type { Logger } from "./logger.js";
3
+ export interface RateLimitData {
4
+ five_hour_pct: number;
5
+ seven_day_pct: number;
6
+ }
7
+ export interface StatuslineWatcherContext {
8
+ readonly logger: Logger;
9
+ readonly costGuard: CostGuard | null;
10
+ getInstanceDir(name: string): string;
11
+ notifyInstanceTopic(name: string, text: string): void;
12
+ checkModelFailover(name: string, fiveHourPct: number): void;
13
+ }
14
+ /**
15
+ * Periodically reads statusline.json for each instance to track
16
+ * cost usage and rate limit status.
17
+ */
18
+ export declare class StatuslineWatcher {
19
+ private ctx;
20
+ private watchers;
21
+ private rateLimits;
22
+ private static readonly POLL_MS;
23
+ constructor(ctx: StatuslineWatcherContext);
24
+ /** Start watching an instance's statusline.json. */
25
+ watch(name: string): void;
26
+ /** Get rate limit data for an instance. */
27
+ getRateLimits(name: string): RateLimitData | undefined;
28
+ /** Check if an instance has an active watcher. */
29
+ has(name: string): boolean;
30
+ /** Stop all watchers and clear data. */
31
+ stopAll(): void;
32
+ }
@@ -0,0 +1,64 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ /**
4
+ * Periodically reads statusline.json for each instance to track
5
+ * cost usage and rate limit status.
6
+ */
7
+ export class StatuslineWatcher {
8
+ ctx;
9
+ watchers = new Map();
10
+ rateLimits = new Map();
11
+ static POLL_MS = 10_000;
12
+ constructor(ctx) {
13
+ this.ctx = ctx;
14
+ }
15
+ /** Start watching an instance's statusline.json. */
16
+ watch(name) {
17
+ if (this.watchers.has(name))
18
+ return;
19
+ const statusFile = join(this.ctx.getInstanceDir(name), "statusline.json");
20
+ const timer = setInterval(() => {
21
+ try {
22
+ const data = JSON.parse(readFileSync(statusFile, "utf-8"));
23
+ // Cost tracking
24
+ if (data.cost?.total_cost_usd != null) {
25
+ this.ctx.costGuard?.updateCost(name, data.cost.total_cost_usd);
26
+ }
27
+ // Rate limit tracking
28
+ const rl = data.rate_limits;
29
+ if (rl) {
30
+ const prev = this.rateLimits.get(name);
31
+ const newSevenDay = rl.seven_day?.used_percentage ?? 0;
32
+ // Notify on recovery
33
+ if (prev?.seven_day_pct === 100 && newSevenDay < 100) {
34
+ this.ctx.notifyInstanceTopic(name, `✅ ${name} weekly usage limit has reset — instance is available again.`);
35
+ this.ctx.logger.info({ name }, "Weekly rate limit recovered");
36
+ }
37
+ this.rateLimits.set(name, {
38
+ five_hour_pct: rl.five_hour?.used_percentage ?? 0,
39
+ seven_day_pct: newSevenDay,
40
+ });
41
+ this.ctx.checkModelFailover(name, rl.five_hour?.used_percentage ?? 0);
42
+ }
43
+ }
44
+ catch { /* file may not exist yet or be mid-write */ }
45
+ }, StatuslineWatcher.POLL_MS);
46
+ this.watchers.set(name, timer);
47
+ }
48
+ /** Get rate limit data for an instance. */
49
+ getRateLimits(name) {
50
+ return this.rateLimits.get(name);
51
+ }
52
+ /** Check if an instance has an active watcher. */
53
+ has(name) {
54
+ return this.watchers.has(name);
55
+ }
56
+ /** Stop all watchers and clear data. */
57
+ stopAll() {
58
+ for (const [, timer] of this.watchers)
59
+ clearInterval(timer);
60
+ this.watchers.clear();
61
+ this.rateLimits.clear();
62
+ }
63
+ }
64
+ //# sourceMappingURL=statusline-watcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"statusline-watcher.js","sourceRoot":"","sources":["../src/statusline-watcher.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ import type { FleetConfig } from "./types.js";
2
+ import type { ChannelAdapter } from "./channel/types.js";
3
+ import type { Logger } from "./logger.js";
4
+ export interface ArchiverContext {
5
+ readonly fleetConfig: FleetConfig | null;
6
+ readonly adapter: ChannelAdapter | null;
7
+ readonly logger: Logger;
8
+ getInstanceStatus(name: string): "running" | "stopped" | "crashed";
9
+ lastActivityMs(name: string): number;
10
+ setTopicIcon(name: string, state: "green" | "blue" | "red" | "remove"): void;
11
+ touchActivity(name: string): void;
12
+ }
13
+ /**
14
+ * Manages automatic archival (close) and reopening of idle forum topics.
15
+ */
16
+ export declare class TopicArchiver {
17
+ private ctx;
18
+ private archived;
19
+ private timer;
20
+ static readonly IDLE_MS: number;
21
+ private static readonly POLL_MS;
22
+ constructor(ctx: ArchiverContext);
23
+ /** Is this topic currently archived? */
24
+ isArchived(topicId: string): boolean;
25
+ /** Start periodic idle check. */
26
+ startPoller(): void;
27
+ /** Stop the poller and clean up. */
28
+ stop(): void;
29
+ /** Close topics that have been idle beyond threshold. */
30
+ archiveIdle(): Promise<void>;
31
+ /** Reopen an archived topic and restore icon. */
32
+ reopen(topicId: string, instanceName: string): Promise<void>;
33
+ }
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Manages automatic archival (close) and reopening of idle forum topics.
3
+ */
4
+ export class TopicArchiver {
5
+ ctx;
6
+ archived = new Set();
7
+ timer = null;
8
+ static IDLE_MS = 24 * 60 * 60 * 1000; // 24 hours
9
+ static POLL_MS = 30 * 60_000; // check every 30 minutes
10
+ constructor(ctx) {
11
+ this.ctx = ctx;
12
+ }
13
+ /** Is this topic currently archived? */
14
+ isArchived(topicId) {
15
+ return this.archived.has(topicId);
16
+ }
17
+ /** Start periodic idle check. */
18
+ startPoller() {
19
+ this.timer = setInterval(() => {
20
+ this.archiveIdle().catch((err) => this.ctx.logger.debug({ err }, "Archive idle check failed"));
21
+ }, TopicArchiver.POLL_MS);
22
+ }
23
+ /** Stop the poller and clean up. */
24
+ stop() {
25
+ if (this.timer) {
26
+ clearInterval(this.timer);
27
+ this.timer = null;
28
+ }
29
+ }
30
+ /** Close topics that have been idle beyond threshold. */
31
+ async archiveIdle() {
32
+ if (!this.ctx.adapter?.closeForumTopic || !this.ctx.fleetConfig)
33
+ return;
34
+ const now = Date.now();
35
+ for (const [name, config] of Object.entries(this.ctx.fleetConfig.instances)) {
36
+ const topicId = config.topic_id;
37
+ if (topicId == null || config.general_topic)
38
+ continue;
39
+ const topicIdStr = String(topicId);
40
+ if (this.archived.has(topicIdStr))
41
+ continue;
42
+ const status = this.ctx.getInstanceStatus(name);
43
+ if (status !== "running")
44
+ continue;
45
+ const last = this.ctx.lastActivityMs(name);
46
+ if (last === 0)
47
+ continue; // never active → skip
48
+ if (now - last < TopicArchiver.IDLE_MS)
49
+ continue;
50
+ this.ctx.logger.info({ name, topicId, idleHours: Math.round((now - last) / 3600000) }, "Archiving idle topic");
51
+ this.archived.add(topicIdStr);
52
+ this.ctx.setTopicIcon(name, "remove");
53
+ await this.ctx.adapter.closeForumTopic(topicId);
54
+ }
55
+ }
56
+ /** Reopen an archived topic and restore icon. */
57
+ async reopen(topicId, instanceName) {
58
+ if (!this.archived.has(topicId))
59
+ return;
60
+ this.archived.delete(topicId);
61
+ if (this.ctx.adapter?.reopenForumTopic) {
62
+ await this.ctx.adapter.reopenForumTopic(topicId);
63
+ }
64
+ this.ctx.setTopicIcon(instanceName, "green");
65
+ this.ctx.touchActivity(instanceName);
66
+ this.ctx.logger.info({ instanceName, topicId }, "Reopened archived topic");
67
+ }
68
+ }
69
+ //# sourceMappingURL=topic-archiver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"topic-archiver.js","sourceRoot":"","sources":["../src/topic-archiver.ts"],"names":[],"mappings":"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"}
@@ -9,6 +9,7 @@ export declare class TopicCommands {
9
9
  handleGeneralCommand(msg: InboundMessage): Promise<boolean>;
10
10
  private handleReloadCommand;
11
11
  private handleStatusCommand;
12
+ private handleSysInfoCommand;
12
13
  /** Reply with redirect when message arrives in an unbound topic */
13
14
  handleUnboundTopic(msg: InboundMessage): Promise<void>;
14
15
  /** Handle topic deletion — stop daemon and remove from config */
@@ -25,6 +25,11 @@ export class TopicCommands {
25
25
  await this.handleReloadCommand(msg);
26
26
  return true;
27
27
  }
28
+ if (text === "/sysinfo" || text === "/sysinfo@" || text.startsWith("/sysinfo@")
29
+ || text === "/sys-info" || text === "/sys_info") {
30
+ await this.handleSysInfoCommand(msg);
31
+ return true;
32
+ }
28
33
  return false;
29
34
  }
30
35
  async handleReloadCommand(msg) {
@@ -74,6 +79,34 @@ export class TopicCommands {
74
79
  }
75
80
  await this.ctx.adapter.sendText(msg.chatId, lines.join("\n"));
76
81
  }
82
+ async handleSysInfoCommand(msg) {
83
+ if (!this.ctx.adapter)
84
+ return;
85
+ const info = this.ctx.getSysInfo();
86
+ const upHours = Math.floor(info.uptime_seconds / 3600);
87
+ const upMins = Math.floor((info.uptime_seconds % 3600) / 60);
88
+ const lines = [
89
+ `⚙️ System Info`,
90
+ `Uptime: ${upHours}h ${upMins}m`,
91
+ `Memory: ${info.memory_mb.rss} MB RSS, ${info.memory_mb.heapUsed}/${info.memory_mb.heapTotal} MB heap`,
92
+ "",
93
+ "Instances:",
94
+ ];
95
+ for (const inst of info.instances) {
96
+ const icon = inst.status === "running" ? "🟢" : inst.status === "crashed" ? "🔴" : "⚪";
97
+ const ipc = inst.ipc ? "✓" : "✗";
98
+ let detail = `${icon} ${inst.name} [IPC:${ipc}] ${formatCents(inst.costCents)}`;
99
+ if (inst.rateLimits) {
100
+ detail += ` (5h:${inst.rateLimits.five_hour_pct}% 7d:${inst.rateLimits.seven_day_pct}%)`;
101
+ }
102
+ lines.push(detail);
103
+ }
104
+ if (info.fleet_cost_limit_cents > 0) {
105
+ lines.push("");
106
+ lines.push(`Fleet cost: ${formatCents(info.fleet_cost_cents)} / ${formatCents(info.fleet_cost_limit_cents)} daily`);
107
+ }
108
+ await this.ctx.adapter.sendText(msg.chatId, lines.join("\n"), { threadId: msg.threadId });
109
+ }
77
110
  /** Reply with redirect when message arrives in an unbound topic */
78
111
  async handleUnboundTopic(msg) {
79
112
  if (!this.ctx.adapter)