shadok-ai 0.1.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.
- package/README.md +196 -0
- package/dist/args.d.ts +8 -0
- package/dist/args.js +17 -0
- package/dist/args.js.map +1 -0
- package/dist/channels.d.ts +61 -0
- package/dist/channels.js +169 -0
- package/dist/channels.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +100 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +31 -0
- package/dist/config.js +59 -0
- package/dist/config.js.map +1 -0
- package/dist/detect.d.ts +17 -0
- package/dist/detect.js +41 -0
- package/dist/detect.js.map +1 -0
- package/dist/extract.d.ts +55 -0
- package/dist/extract.js +269 -0
- package/dist/extract.js.map +1 -0
- package/dist/main.d.ts +2 -0
- package/dist/main.js +90 -0
- package/dist/main.js.map +1 -0
- package/dist/pace.d.ts +33 -0
- package/dist/pace.js +53 -0
- package/dist/pace.js.map +1 -0
- package/dist/retry.d.ts +15 -0
- package/dist/retry.js +40 -0
- package/dist/retry.js.map +1 -0
- package/dist/secrets.d.ts +21 -0
- package/dist/secrets.js +71 -0
- package/dist/secrets.js.map +1 -0
- package/dist/server.d.ts +1 -0
- package/dist/server.js +854 -0
- package/dist/server.js.map +1 -0
- package/dist/session.d.ts +74 -0
- package/dist/session.js +244 -0
- package/dist/session.js.map +1 -0
- package/dist/setup-prompt.d.ts +6 -0
- package/dist/setup-prompt.js +25 -0
- package/dist/setup-prompt.js.map +1 -0
- package/dist/supervisor.d.ts +55 -0
- package/dist/supervisor.js +61 -0
- package/dist/supervisor.js.map +1 -0
- package/dist/tail.d.ts +66 -0
- package/dist/tail.js +244 -0
- package/dist/tail.js.map +1 -0
- package/dist/telegram.d.ts +48 -0
- package/dist/telegram.js +565 -0
- package/dist/telegram.js.map +1 -0
- package/dist/tmux.d.ts +69 -0
- package/dist/tmux.js +267 -0
- package/dist/tmux.js.map +1 -0
- package/dist/update-flag.d.ts +13 -0
- package/dist/update-flag.js +36 -0
- package/dist/update-flag.js.map +1 -0
- package/dist/updater.d.ts +18 -0
- package/dist/updater.js +45 -0
- package/dist/updater.js.map +1 -0
- package/dist/usage.d.ts +23 -0
- package/dist/usage.js +125 -0
- package/dist/usage.js.map +1 -0
- package/dist/worktree.d.ts +63 -0
- package/dist/worktree.js +153 -0
- package/dist/worktree.js.map +1 -0
- package/package.json +44 -0
- package/public/index.html +2583 -0
package/dist/telegram.js
ADDED
|
@@ -0,0 +1,565 @@
|
|
|
1
|
+
import WebSocket from "ws";
|
|
2
|
+
import { loadChannels, upsertChannel, removeChannel, channelForTelegram, loadTgGroup, saveTgGroup, } from "./channels.js";
|
|
3
|
+
import { resolveRepo, secretKeys, setSecret, deleteSecret } from "./secrets.js";
|
|
4
|
+
import { readAndClearUpdateResult } from "./update-flag.js";
|
|
5
|
+
import { UPDATE_EXIT_CODE } from "./supervisor.js";
|
|
6
|
+
/**
|
|
7
|
+
* Telegram control bridge. Runs inside the server process (only when
|
|
8
|
+
* TELEGRAM_BOT_TOKEN is set) and connects to the server's own /ws as a plain
|
|
9
|
+
* client — so a Telegram-driven session is the same Live session the web UI
|
|
10
|
+
* sees. See docs/superpowers/specs/2026-07-23-telegram-design.md.
|
|
11
|
+
*
|
|
12
|
+
* Increment 1: DMs (1 chat = 1 session), text prompt → streamed reply,
|
|
13
|
+
* /new /end /list, binding persistence. Topics + dialogs come next.
|
|
14
|
+
*/
|
|
15
|
+
const MSG_LIMIT = 4000; // Telegram hard limit is 4096; leave headroom.
|
|
16
|
+
// ── Pure helpers (unit-tested) ───────────────────────────────────────────
|
|
17
|
+
/** The binding key for a chat + optional forum topic thread. */
|
|
18
|
+
export function bindKey(chat, threadId) {
|
|
19
|
+
if (chat.type === "private")
|
|
20
|
+
return `private:${chat.id}`;
|
|
21
|
+
return threadId ? `topic:${chat.id}:${threadId}` : `group:${chat.id}`;
|
|
22
|
+
}
|
|
23
|
+
/** Split text into Telegram-sized chunks, preferring line boundaries. */
|
|
24
|
+
export function chunk(text, max = MSG_LIMIT) {
|
|
25
|
+
const out = [];
|
|
26
|
+
let rest = text;
|
|
27
|
+
while (rest.length > max) {
|
|
28
|
+
let cut = rest.lastIndexOf("\n", max);
|
|
29
|
+
if (cut < max * 0.5)
|
|
30
|
+
cut = max; // no nearby newline: hard cut
|
|
31
|
+
out.push(rest.slice(0, cut));
|
|
32
|
+
rest = rest.slice(cut).replace(/^\n/, "");
|
|
33
|
+
}
|
|
34
|
+
if (rest)
|
|
35
|
+
out.push(rest);
|
|
36
|
+
return out;
|
|
37
|
+
}
|
|
38
|
+
/** Parse a leading bot command: "/spawn foo" → {cmd:"spawn", arg:"foo"}. */
|
|
39
|
+
export function parseCommand(text) {
|
|
40
|
+
const m = text.match(/^\/([a-z]+)(?:@\w+)?\s*(.*)$/is);
|
|
41
|
+
return m ? { cmd: m[1].toLowerCase(), arg: m[2].trim() } : null;
|
|
42
|
+
}
|
|
43
|
+
/** Telegram's "typing…" indicator lives ~5 s per sendChatAction and dies on
|
|
44
|
+
* every sendMessage — a single beat can't cover a turn that runs for minutes.
|
|
45
|
+
* This keeps it alive: an immediate beat, then one every `intervalMs` until
|
|
46
|
+
* stop(). start() while beating is a no-op; stop() is idempotent. */
|
|
47
|
+
export function makeTyping(beat, intervalMs = 4000) {
|
|
48
|
+
let timer = null;
|
|
49
|
+
return {
|
|
50
|
+
start() {
|
|
51
|
+
if (timer)
|
|
52
|
+
return;
|
|
53
|
+
beat();
|
|
54
|
+
timer = setInterval(beat, intervalMs);
|
|
55
|
+
timer.unref?.(); // never keep the process alive for an indicator
|
|
56
|
+
},
|
|
57
|
+
stop() {
|
|
58
|
+
if (timer)
|
|
59
|
+
clearInterval(timer);
|
|
60
|
+
timer = null;
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
/** Inline keyboard for a TUI dialog. Single-select → one button per option
|
|
65
|
+
* (choose); multi-select → toggle buttons (with ☑/☐) + a Submit row. */
|
|
66
|
+
export function dialogKeyboard(d) {
|
|
67
|
+
const rows = d.options.map((o) => [
|
|
68
|
+
{
|
|
69
|
+
text: (d.multi ? (o.checked ? "☑ " : "☐ ") : "") + `${o.n}. ${o.label}`.slice(0, 60),
|
|
70
|
+
callback_data: (d.multi ? "t:" : "d:") + o.n,
|
|
71
|
+
},
|
|
72
|
+
]);
|
|
73
|
+
if (d.multi)
|
|
74
|
+
rows.push([{ text: "✅ Submit", callback_data: "s" }]);
|
|
75
|
+
return { inline_keyboard: rows };
|
|
76
|
+
}
|
|
77
|
+
/** Parse a dialog callback_data → an action for the WS. */
|
|
78
|
+
export function parseCallback(data) {
|
|
79
|
+
if (data === "s")
|
|
80
|
+
return { kind: "confirm" };
|
|
81
|
+
const m = data.match(/^([dt]):(\d+)$/);
|
|
82
|
+
if (!m)
|
|
83
|
+
return null;
|
|
84
|
+
return { kind: m[1] === "d" ? "choose" : "toggle", n: Number(m[2]) };
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Rename a Telegram forum topic to match a channel renamed elsewhere (the web
|
|
88
|
+
* UI). Wired up by startTelegram; a no-op when Telegram is off. Lets the server
|
|
89
|
+
* push a web-side rename to Telegram without importing its token/closure.
|
|
90
|
+
*/
|
|
91
|
+
let renameTopicImpl = null;
|
|
92
|
+
export function renameTelegramTopic(chatId, threadId, name) {
|
|
93
|
+
renameTopicImpl?.(chatId, threadId, name);
|
|
94
|
+
}
|
|
95
|
+
/** Close (archive) a Telegram forum topic when its session ends elsewhere. */
|
|
96
|
+
let closeTopicImpl = null;
|
|
97
|
+
export function closeTelegramTopic(chatId, threadId) {
|
|
98
|
+
closeTopicImpl?.(chatId, threadId);
|
|
99
|
+
}
|
|
100
|
+
export function startTelegram(port) {
|
|
101
|
+
const token = process.env.TELEGRAM_BOT_TOKEN;
|
|
102
|
+
if (!token)
|
|
103
|
+
return;
|
|
104
|
+
const api = `https://api.telegram.org/bot${token}`;
|
|
105
|
+
const allowed = (process.env.TELEGRAM_ALLOWED_CHATS ?? "")
|
|
106
|
+
.split(",")
|
|
107
|
+
.map((s) => s.trim())
|
|
108
|
+
.filter(Boolean);
|
|
109
|
+
const bridges = new Map();
|
|
110
|
+
// Names of topics we've seen created/renamed (chatId:threadId → name), so a
|
|
111
|
+
// manually-created topic keeps its name instead of the GUI defaulting it.
|
|
112
|
+
const topicNames = new Map();
|
|
113
|
+
const tg = async (method, params) => {
|
|
114
|
+
try {
|
|
115
|
+
const r = await fetch(`${api}/${method}`, {
|
|
116
|
+
method: "POST",
|
|
117
|
+
headers: { "content-type": "application/json" },
|
|
118
|
+
body: JSON.stringify(params),
|
|
119
|
+
});
|
|
120
|
+
return await r.json();
|
|
121
|
+
}
|
|
122
|
+
catch {
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
// Web-side rename → rename the matching Telegram topic (best effort).
|
|
127
|
+
renameTopicImpl = (chatId, threadId, name) => {
|
|
128
|
+
tg("editForumTopic", { chat_id: chatId, message_thread_id: threadId, name: name.slice(0, 128) });
|
|
129
|
+
};
|
|
130
|
+
// Session ended elsewhere → delete its topic so it disappears from the group
|
|
131
|
+
// (the bot created it, so it can). Irreversible; ignore errors.
|
|
132
|
+
closeTopicImpl = (chatId, threadId) => {
|
|
133
|
+
tg("deleteForumTopic", { chat_id: chatId, message_thread_id: threadId });
|
|
134
|
+
};
|
|
135
|
+
const send = async (b, text) => {
|
|
136
|
+
for (const part of chunk(text)) {
|
|
137
|
+
await tg("sendMessage", {
|
|
138
|
+
chat_id: b.chatId,
|
|
139
|
+
...(b.threadId ? { message_thread_id: b.threadId } : {}),
|
|
140
|
+
text: part,
|
|
141
|
+
disable_web_page_preview: true,
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
// Fold each bridge into the ONE registry: its session becomes a channel
|
|
146
|
+
// carrying the Telegram binding, so it shows up (and is pilotable) in the web
|
|
147
|
+
// UI too. The server fills cwd/branch on ready; here we own the binding.
|
|
148
|
+
const persist = () => {
|
|
149
|
+
for (const b of bridges.values()) {
|
|
150
|
+
if (!b.sessionId)
|
|
151
|
+
continue;
|
|
152
|
+
const existing = channelForTelegram(b.chatId, b.threadId);
|
|
153
|
+
upsertChannel({
|
|
154
|
+
sessionId: b.sessionId,
|
|
155
|
+
// Seed the name from the topic once; never override a later rename.
|
|
156
|
+
...(b.name && !existing?.name ? { name: b.name } : {}),
|
|
157
|
+
telegram: { chatId: b.chatId, ...(b.threadId ? { threadId: b.threadId } : {}) },
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
/** Open (or resume) a session for a chat/topic and wire its events to Telegram. */
|
|
162
|
+
const openBridge = (key, chatId, threadId, opts = {}) => {
|
|
163
|
+
const ws = new WebSocket(`ws://127.0.0.1:${port}/ws`);
|
|
164
|
+
const b = {
|
|
165
|
+
key,
|
|
166
|
+
chatId,
|
|
167
|
+
threadId,
|
|
168
|
+
ws,
|
|
169
|
+
sessionId: opts.resumeId ?? null,
|
|
170
|
+
ready: false,
|
|
171
|
+
pending: [],
|
|
172
|
+
pendingActions: [],
|
|
173
|
+
worktree: opts.worktree,
|
|
174
|
+
name: opts.name,
|
|
175
|
+
typing: makeTyping(() => tg("sendChatAction", {
|
|
176
|
+
chat_id: chatId,
|
|
177
|
+
...(threadId ? { message_thread_id: threadId } : {}),
|
|
178
|
+
action: "typing",
|
|
179
|
+
})),
|
|
180
|
+
};
|
|
181
|
+
bridges.set(key, b);
|
|
182
|
+
ws.on("open", () => {
|
|
183
|
+
ws.send(JSON.stringify(opts.resumeId
|
|
184
|
+
? { type: "start", resume: opts.resumeId, cwd: process.cwd() }
|
|
185
|
+
: { type: "start", cwd: process.cwd(), worktree: !!opts.worktree }));
|
|
186
|
+
});
|
|
187
|
+
ws.on("message", (raw) => {
|
|
188
|
+
let m;
|
|
189
|
+
try {
|
|
190
|
+
m = JSON.parse(String(raw));
|
|
191
|
+
}
|
|
192
|
+
catch {
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
switch (m.type) {
|
|
196
|
+
case "ready":
|
|
197
|
+
b.sessionId = m.sessionId;
|
|
198
|
+
b.ready = true;
|
|
199
|
+
persist();
|
|
200
|
+
for (const p of b.pending.splice(0))
|
|
201
|
+
ws.send(JSON.stringify({ type: "prompt", text: p }));
|
|
202
|
+
for (const a of b.pendingActions.splice(0))
|
|
203
|
+
ws.send(JSON.stringify(a));
|
|
204
|
+
break;
|
|
205
|
+
case "working":
|
|
206
|
+
// Heartbeat, not a one-shot: Telegram's indicator dies after ~5 s
|
|
207
|
+
// (and on every message we send) while a turn runs for minutes.
|
|
208
|
+
b.typing.start();
|
|
209
|
+
break;
|
|
210
|
+
case "stream-text":
|
|
211
|
+
if (m.text?.trim())
|
|
212
|
+
send(b, m.text);
|
|
213
|
+
break;
|
|
214
|
+
case "stream-tool":
|
|
215
|
+
send(b, "→ " + m.name + (m.summary ? " " + m.summary : ""));
|
|
216
|
+
break;
|
|
217
|
+
case "dialog":
|
|
218
|
+
// The turn is suspended on a question — Claude isn't "typing",
|
|
219
|
+
// it's waiting for the user. Stop the heartbeat.
|
|
220
|
+
b.typing.stop();
|
|
221
|
+
// A TUI question → inline keyboard. On multi-select toggles the
|
|
222
|
+
// server re-sends the dialog; edit the existing keyboard in place.
|
|
223
|
+
if (b.dialogMsgId) {
|
|
224
|
+
tg("editMessageReplyMarkup", {
|
|
225
|
+
chat_id: b.chatId,
|
|
226
|
+
message_id: b.dialogMsgId,
|
|
227
|
+
reply_markup: dialogKeyboard(m),
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
else {
|
|
231
|
+
tg("sendMessage", {
|
|
232
|
+
chat_id: b.chatId,
|
|
233
|
+
...(b.threadId ? { message_thread_id: b.threadId } : {}),
|
|
234
|
+
text: m.question || "Choisis :",
|
|
235
|
+
reply_markup: dialogKeyboard(m),
|
|
236
|
+
}).then((r) => {
|
|
237
|
+
if (r?.ok)
|
|
238
|
+
b.dialogMsgId = r.result.message_id;
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
break;
|
|
242
|
+
case "turn-done":
|
|
243
|
+
b.typing.stop();
|
|
244
|
+
b.dialogMsgId = undefined; // any dialog is resolved once the turn ends
|
|
245
|
+
break;
|
|
246
|
+
case "pace-blocked":
|
|
247
|
+
// The prompt was refused by the pace guard (there is no "force"
|
|
248
|
+
// button here) — say so instead of staying silent, and drop the
|
|
249
|
+
// optimistic typing started at message receipt.
|
|
250
|
+
b.typing.stop();
|
|
251
|
+
send(b, "⏸️ pace guard: " + (m.reason ?? "over the ideal pace") + "\nYour message was not sent — retry later.");
|
|
252
|
+
break;
|
|
253
|
+
case "error":
|
|
254
|
+
// No typing.stop() here: fail() errors ("a response is already in
|
|
255
|
+
// progress") don't end the running turn — turn-done/exited will.
|
|
256
|
+
send(b, "⚠️ " + m.message);
|
|
257
|
+
break;
|
|
258
|
+
case "exited":
|
|
259
|
+
b.typing.stop();
|
|
260
|
+
send(b, "— session ended —");
|
|
261
|
+
break;
|
|
262
|
+
}
|
|
263
|
+
});
|
|
264
|
+
ws.on("close", () => {
|
|
265
|
+
b.typing.stop();
|
|
266
|
+
if (bridges.get(key) === b)
|
|
267
|
+
bridges.delete(key);
|
|
268
|
+
});
|
|
269
|
+
ws.on("error", () => { });
|
|
270
|
+
return b;
|
|
271
|
+
};
|
|
272
|
+
const bridgeFor = (key, chatId, threadId, name) => {
|
|
273
|
+
const existing = bridges.get(key);
|
|
274
|
+
if (existing && existing.ws.readyState <= WebSocket.OPEN)
|
|
275
|
+
return existing;
|
|
276
|
+
const saved = channelForTelegram(chatId, threadId);
|
|
277
|
+
return openBridge(key, chatId, threadId, { resumeId: saved?.sessionId, name });
|
|
278
|
+
};
|
|
279
|
+
const promptTo = (b, text) => {
|
|
280
|
+
if (b.ready && b.ws.readyState === WebSocket.OPEN)
|
|
281
|
+
b.ws.send(JSON.stringify({ type: "prompt", text }));
|
|
282
|
+
else
|
|
283
|
+
b.pending.push(text);
|
|
284
|
+
};
|
|
285
|
+
const reply = (chatId, threadId, text, extra = {}) => tg("sendMessage", {
|
|
286
|
+
chat_id: chatId,
|
|
287
|
+
...(threadId ? { message_thread_id: threadId } : {}),
|
|
288
|
+
text,
|
|
289
|
+
disable_web_page_preview: true,
|
|
290
|
+
...extra,
|
|
291
|
+
});
|
|
292
|
+
const endBinding = (key, chatId, threadId) => {
|
|
293
|
+
const b = bridges.get(key);
|
|
294
|
+
if (b) {
|
|
295
|
+
b.ws.send(JSON.stringify({ type: "stop" }));
|
|
296
|
+
b.ws.close();
|
|
297
|
+
bridges.delete(key);
|
|
298
|
+
}
|
|
299
|
+
// The session is stopped → drop it from the one registry (removes it from
|
|
300
|
+
// the web UI too).
|
|
301
|
+
const ch = channelForTelegram(chatId, threadId);
|
|
302
|
+
if (ch)
|
|
303
|
+
removeChannel(ch.sessionId);
|
|
304
|
+
};
|
|
305
|
+
const handleMessage = async (msg) => {
|
|
306
|
+
if (typeof msg.text !== "string")
|
|
307
|
+
return;
|
|
308
|
+
const chat = msg.chat;
|
|
309
|
+
if (allowed.length && !allowed.includes(String(chat.id))) {
|
|
310
|
+
await reply(chat.id, msg.message_thread_id, "⛔ this bot is restricted.");
|
|
311
|
+
return;
|
|
312
|
+
}
|
|
313
|
+
const threadId = msg.message_thread_id;
|
|
314
|
+
const isGroup = chat.type === "group" || chat.type === "supergroup";
|
|
315
|
+
const cmd = parseCommand(msg.text);
|
|
316
|
+
// One board per instance: a group must be the bound group.
|
|
317
|
+
if (isGroup) {
|
|
318
|
+
const bound = loadTgGroup();
|
|
319
|
+
if (bound === null) {
|
|
320
|
+
if (cmd?.cmd === "setup") {
|
|
321
|
+
saveTgGroup(chat.id);
|
|
322
|
+
await reply(chat.id, threadId, "✅ This group is now shadok-ai's board. Use /spawn <name> to create an agent (a forum topic). Enable Topics + make me admin if /spawn fails.");
|
|
323
|
+
}
|
|
324
|
+
else {
|
|
325
|
+
await reply(chat.id, threadId, "Run /setup here to bind this group as shadok-ai's board (one group per instance).");
|
|
326
|
+
}
|
|
327
|
+
return;
|
|
328
|
+
}
|
|
329
|
+
if (bound !== chat.id) {
|
|
330
|
+
await reply(chat.id, threadId, "⛔ This shadok-ai instance is bound to another group.");
|
|
331
|
+
return;
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
const key = bindKey(chat, threadId);
|
|
335
|
+
if (cmd) {
|
|
336
|
+
switch (cmd.cmd) {
|
|
337
|
+
case "start":
|
|
338
|
+
case "help":
|
|
339
|
+
await reply(chat.id, threadId, "shadok-ai — talk to your agent by sending a message.\n/spawn <name> — new agent in a topic (groups)\n/new — reset · /end — stop · /list — bindings\n/secrets — list · /secret KEY value — set · /unsecret KEY");
|
|
340
|
+
return;
|
|
341
|
+
case "setup":
|
|
342
|
+
if (isGroup)
|
|
343
|
+
await reply(chat.id, threadId, "✅ already this instance's board.");
|
|
344
|
+
return;
|
|
345
|
+
case "spawn": {
|
|
346
|
+
if (!isGroup) {
|
|
347
|
+
await reply(chat.id, threadId, "/spawn works in the board group. In a DM just send a message.");
|
|
348
|
+
return;
|
|
349
|
+
}
|
|
350
|
+
const name = cmd.arg || "agent";
|
|
351
|
+
const t = await tg("createForumTopic", { chat_id: chat.id, name: name.slice(0, 128) });
|
|
352
|
+
if (!t?.ok) {
|
|
353
|
+
const why = t?.description ? ` (Telegram: ${t.description})` : "";
|
|
354
|
+
console.log(`telegram: createForumTopic failed for ${chat.id}:`, t?.description ?? t);
|
|
355
|
+
await reply(chat.id, threadId, `⚠️ Couldn't create a topic${why}.\nMake sure this is a supergroup with Topics enabled, and that I'm an admin with 'Manage topics'.`);
|
|
356
|
+
return;
|
|
357
|
+
}
|
|
358
|
+
const newThread = t.result.message_thread_id;
|
|
359
|
+
// A group agent is isolated in its own worktree (a board of agents).
|
|
360
|
+
openBridge(bindKey(chat, newThread), chat.id, newThread, { worktree: true, name });
|
|
361
|
+
await reply(chat.id, newThread, `🤖 Agent « ${name} » ready (isolated worktree). Send it a task.`);
|
|
362
|
+
return;
|
|
363
|
+
}
|
|
364
|
+
case "new":
|
|
365
|
+
case "end":
|
|
366
|
+
endBinding(key, chat.id, threadId);
|
|
367
|
+
await reply(chat.id, threadId, cmd.cmd === "new" ? "🔄 fresh session — send a message." : "🛑 session ended.");
|
|
368
|
+
return;
|
|
369
|
+
case "list": {
|
|
370
|
+
const lines = loadChannels()
|
|
371
|
+
.filter((c) => c.telegram)
|
|
372
|
+
.map((c) => {
|
|
373
|
+
const where = c.telegram.threadId ? `topic ${c.telegram.threadId}` : "here";
|
|
374
|
+
return `• ${c.name ?? c.sessionId.slice(0, 8)} (${where})`;
|
|
375
|
+
});
|
|
376
|
+
await reply(chat.id, threadId, lines.length ? lines.join("\n") : "no sessions bound yet.");
|
|
377
|
+
return;
|
|
378
|
+
}
|
|
379
|
+
case "update": {
|
|
380
|
+
// Powerful (npm install + respawn): board group only. The allowlist,
|
|
381
|
+
// if set, was already enforced at the top of handleMessage.
|
|
382
|
+
if (!isGroup) {
|
|
383
|
+
await reply(chat.id, threadId, "/update runs in the board group.");
|
|
384
|
+
return;
|
|
385
|
+
}
|
|
386
|
+
await reply(chat.id, threadId, "🔄 updating… I'll be back in a moment.");
|
|
387
|
+
// Ask the supervisor to fetch @latest and respawn us.
|
|
388
|
+
process.exit(UPDATE_EXIT_CODE);
|
|
389
|
+
}
|
|
390
|
+
case "secrets": {
|
|
391
|
+
const repo = resolveRepo(channelForTelegram(chat.id, threadId)?.cwd || process.cwd());
|
|
392
|
+
const keys = secretKeys(repo);
|
|
393
|
+
await reply(chat.id, threadId, `🔐 secrets for ${repo}:\n${keys.length ? keys.map((k) => "• " + k).join("\n") : "(none)"}\n\nSet: /secret KEY value · remove: /unsecret KEY`);
|
|
394
|
+
return;
|
|
395
|
+
}
|
|
396
|
+
case "secret": {
|
|
397
|
+
// /secret KEY value — store then DELETE the message so the value
|
|
398
|
+
// doesn't linger in the chat history.
|
|
399
|
+
const sp = cmd.arg.indexOf(" ");
|
|
400
|
+
const skey = sp === -1 ? cmd.arg : cmd.arg.slice(0, sp);
|
|
401
|
+
const sval = sp === -1 ? "" : cmd.arg.slice(sp + 1);
|
|
402
|
+
if (!skey || !sval) {
|
|
403
|
+
await reply(chat.id, threadId, "Usage: /secret KEY value");
|
|
404
|
+
return;
|
|
405
|
+
}
|
|
406
|
+
const repo = resolveRepo(channelForTelegram(chat.id, threadId)?.cwd || process.cwd());
|
|
407
|
+
setSecret(repo, skey.trim(), sval);
|
|
408
|
+
const del = await tg("deleteMessage", { chat_id: chat.id, message_id: msg.message_id });
|
|
409
|
+
await reply(chat.id, threadId, `🔐 ${skey.trim()} saved for ${repo}.${del?.ok ? " (your message was deleted)" : "\n⚠️ I couldn't delete your message — remove it manually; the value is exposed in history."} Applies to newly spawned/restarted agents.`);
|
|
410
|
+
return;
|
|
411
|
+
}
|
|
412
|
+
case "unsecret": {
|
|
413
|
+
const skey = cmd.arg.trim();
|
|
414
|
+
if (!skey) {
|
|
415
|
+
await reply(chat.id, threadId, "Usage: /unsecret KEY");
|
|
416
|
+
return;
|
|
417
|
+
}
|
|
418
|
+
const repo = resolveRepo(channelForTelegram(chat.id, threadId)?.cwd || process.cwd());
|
|
419
|
+
deleteSecret(repo, skey);
|
|
420
|
+
await reply(chat.id, threadId, `🔐 ${skey} removed for ${repo}.`);
|
|
421
|
+
return;
|
|
422
|
+
}
|
|
423
|
+
case "restart": {
|
|
424
|
+
// Re-spawn this topic's agent so it picks up freshly-added secrets.
|
|
425
|
+
const rb = bridgeFor(key, chat.id, threadId);
|
|
426
|
+
const rmsg = { type: "restart" };
|
|
427
|
+
if (rb.ready && rb.ws.readyState === WebSocket.OPEN)
|
|
428
|
+
rb.ws.send(JSON.stringify(rmsg));
|
|
429
|
+
else
|
|
430
|
+
rb.pendingActions.push(rmsg);
|
|
431
|
+
await reply(chat.id, threadId, "♻️ restarting the agent to apply secrets…");
|
|
432
|
+
return;
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
// A manually-created topic keeps its own name: take it from the cache
|
|
437
|
+
// (forum_topic_created) or the topic's root message, so the channel isn't
|
|
438
|
+
// named after the cwd. Only used to seed a nameless channel (see persist).
|
|
439
|
+
const topicName = threadId != null
|
|
440
|
+
? topicNames.get(key) ?? msg.reply_to_message?.forum_topic_created?.name
|
|
441
|
+
: undefined;
|
|
442
|
+
// Optimistic typing: start the heartbeat now, before the server confirms
|
|
443
|
+
// anything — spawning/resuming a session can take tens of seconds and the
|
|
444
|
+
// first "working" only arrives after it. Every terminal outcome stops it
|
|
445
|
+
// (turn-done, dialog, pace-blocked, exited, ws close).
|
|
446
|
+
const b = bridgeFor(key, chat.id, threadId, topicName);
|
|
447
|
+
b.typing.start();
|
|
448
|
+
promptTo(b, msg.text);
|
|
449
|
+
};
|
|
450
|
+
const handleCallback = async (cq) => {
|
|
451
|
+
const action = parseCallback(cq.data ?? "");
|
|
452
|
+
const msg = cq.message;
|
|
453
|
+
if (!action || !msg)
|
|
454
|
+
return;
|
|
455
|
+
await tg("answerCallbackQuery", { callback_query_id: cq.id }); // stop the client spinner
|
|
456
|
+
const wsMsg = action.kind === "confirm" ? { type: "confirm" } : { type: action.kind, n: action.n };
|
|
457
|
+
// Resume the bridge if the server was restarted since the dialog was shown
|
|
458
|
+
// (otherwise a click on an orphaned keyboard would silently do nothing).
|
|
459
|
+
const b = bridgeFor(bindKey(msg.chat, msg.message_thread_id), msg.chat.id, msg.message_thread_id);
|
|
460
|
+
if (b.ready && b.ws.readyState === WebSocket.OPEN)
|
|
461
|
+
b.ws.send(JSON.stringify(wsMsg));
|
|
462
|
+
else
|
|
463
|
+
b.pendingActions.push(wsMsg);
|
|
464
|
+
};
|
|
465
|
+
// A topic created in Telegram → spawn its agent right away, so the channel
|
|
466
|
+
// shows up in the GUI before anyone writes. Creating a topic = creating an
|
|
467
|
+
// agent (the board model). Skips topics already bound (e.g. the bot's own
|
|
468
|
+
// /spawn, which opened the bridge before this event arrived).
|
|
469
|
+
const handleTopicCreated = (msg) => {
|
|
470
|
+
const name = msg.forum_topic_created?.name;
|
|
471
|
+
const threadId = msg.message_thread_id;
|
|
472
|
+
const key = bindKey(msg.chat, threadId);
|
|
473
|
+
if (typeof name === "string" && name)
|
|
474
|
+
topicNames.set(key, name);
|
|
475
|
+
if (msg.chat.id !== loadTgGroup())
|
|
476
|
+
return; // only the bound board group
|
|
477
|
+
const ch = channelForTelegram(msg.chat.id, threadId);
|
|
478
|
+
if (bridges.has(key) || ch) {
|
|
479
|
+
if (ch && !ch.name && name)
|
|
480
|
+
upsertChannel({ sessionId: ch.sessionId, name });
|
|
481
|
+
return;
|
|
482
|
+
}
|
|
483
|
+
openBridge(key, msg.chat.id, threadId, { worktree: true, name });
|
|
484
|
+
reply(msg.chat.id, threadId, `🤖 Agent « ${name ?? "agent"} » ready (isolated worktree). Send it a task.`);
|
|
485
|
+
};
|
|
486
|
+
// A topic renamed in Telegram → update the one registry so the web tab follows.
|
|
487
|
+
const handleTopicEdited = (msg) => {
|
|
488
|
+
const name = msg.forum_topic_edited?.name;
|
|
489
|
+
if (typeof name !== "string" || !name)
|
|
490
|
+
return;
|
|
491
|
+
topicNames.set(bindKey(msg.chat, msg.message_thread_id), name);
|
|
492
|
+
const ch = channelForTelegram(msg.chat.id, msg.message_thread_id);
|
|
493
|
+
if (ch)
|
|
494
|
+
upsertChannel({ sessionId: ch.sessionId, name });
|
|
495
|
+
};
|
|
496
|
+
// A topic closed/deleted in Telegram → end its session everywhere. Sending
|
|
497
|
+
// `stop` lets the server tear down + drop it from the registry (which removes
|
|
498
|
+
// the web tab via the sync poll). No bridge → just unbind.
|
|
499
|
+
const handleTopicClosed = (msg) => {
|
|
500
|
+
const ch = channelForTelegram(msg.chat.id, msg.message_thread_id);
|
|
501
|
+
if (!ch)
|
|
502
|
+
return;
|
|
503
|
+
const key = bindKey(msg.chat, msg.message_thread_id);
|
|
504
|
+
const b = bridges.get(key);
|
|
505
|
+
if (b?.ws.readyState === WebSocket.OPEN)
|
|
506
|
+
b.ws.send(JSON.stringify({ type: "stop" }));
|
|
507
|
+
else
|
|
508
|
+
removeChannel(ch.sessionId);
|
|
509
|
+
bridges.delete(key);
|
|
510
|
+
};
|
|
511
|
+
const handleUpdate = async (u) => {
|
|
512
|
+
if (u.callback_query)
|
|
513
|
+
return handleCallback(u.callback_query);
|
|
514
|
+
if (u.message?.forum_topic_created)
|
|
515
|
+
return handleTopicCreated(u.message);
|
|
516
|
+
if (u.message?.forum_topic_edited)
|
|
517
|
+
return handleTopicEdited(u.message);
|
|
518
|
+
if (u.message?.forum_topic_closed || u.message?.forum_topic_deleted)
|
|
519
|
+
return handleTopicClosed(u.message);
|
|
520
|
+
if (u.message)
|
|
521
|
+
return handleMessage(u.message);
|
|
522
|
+
};
|
|
523
|
+
// Long-poll loop — no webhook / public URL needed.
|
|
524
|
+
let offset = 0;
|
|
525
|
+
const poll = async () => {
|
|
526
|
+
const res = await tg("getUpdates", { offset, timeout: 30, allowed_updates: ["message", "callback_query"] });
|
|
527
|
+
if (res?.ok && Array.isArray(res.result)) {
|
|
528
|
+
for (const u of res.result) {
|
|
529
|
+
offset = u.update_id + 1;
|
|
530
|
+
handleUpdate(u).catch(() => { });
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
setTimeout(poll, res ? 0 : 3000); // back off on network error
|
|
534
|
+
};
|
|
535
|
+
// Connect, retrying transient failures with backoff. A single network hiccup
|
|
536
|
+
// on getMe used to leave Telegram dead for the whole run; only a real 401
|
|
537
|
+
// (bad token) stops us now.
|
|
538
|
+
const connect = async (attempt = 0) => {
|
|
539
|
+
const me = await tg("getMe", {});
|
|
540
|
+
if (me?.ok) {
|
|
541
|
+
console.log(`telegram: bot @${me.result.username} connected (long-polling)`);
|
|
542
|
+
poll();
|
|
543
|
+
announceUpdateResult();
|
|
544
|
+
return;
|
|
545
|
+
}
|
|
546
|
+
if (me && me.error_code === 401) {
|
|
547
|
+
console.log("telegram: unauthorized — check TELEGRAM_BOT_TOKEN");
|
|
548
|
+
return;
|
|
549
|
+
}
|
|
550
|
+
const delay = Math.min(30_000, 2_000 * 2 ** attempt);
|
|
551
|
+
console.log(`telegram: getMe failed (transient), retrying in ${delay / 1000}s`);
|
|
552
|
+
setTimeout(() => connect(attempt + 1), delay);
|
|
553
|
+
};
|
|
554
|
+
connect();
|
|
555
|
+
/** After a supervisor-driven /update, tell the board group how it went. */
|
|
556
|
+
function announceUpdateResult() {
|
|
557
|
+
const r = readAndClearUpdateResult();
|
|
558
|
+
const group = loadTgGroup();
|
|
559
|
+
if (!r || group === null)
|
|
560
|
+
return;
|
|
561
|
+
const text = r.ok ? `✅ updated to v${r.version}` : `⚠️ update failed: ${r.error}`;
|
|
562
|
+
tg("sendMessage", { chat_id: group, text });
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
//# sourceMappingURL=telegram.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telegram.js","sourceRoot":"","sources":["../src/telegram.ts"],"names":[],"mappings":"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"}
|