@nodetool-ai/telegram 0.8.1

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 (59) hide show
  1. package/README.md +49 -0
  2. package/dist/.nodetool-build-stamp +1 -0
  3. package/dist/bot-api.d.ts +115 -0
  4. package/dist/bot-api.d.ts.map +1 -0
  5. package/dist/bot-api.js +145 -0
  6. package/dist/bot-api.js.map +1 -0
  7. package/dist/chunk.d.ts +36 -0
  8. package/dist/chunk.d.ts.map +1 -0
  9. package/dist/chunk.js +280 -0
  10. package/dist/chunk.js.map +1 -0
  11. package/dist/cli.d.ts +10 -0
  12. package/dist/cli.d.ts.map +1 -0
  13. package/dist/cli.js +62 -0
  14. package/dist/cli.js.map +1 -0
  15. package/dist/commands.d.ts +83 -0
  16. package/dist/commands.d.ts.map +1 -0
  17. package/dist/commands.js +191 -0
  18. package/dist/commands.js.map +1 -0
  19. package/dist/config.d.ts +65 -0
  20. package/dist/config.d.ts.map +1 -0
  21. package/dist/config.js +139 -0
  22. package/dist/config.js.map +1 -0
  23. package/dist/frame-renderer.d.ts +135 -0
  24. package/dist/frame-renderer.d.ts.map +1 -0
  25. package/dist/frame-renderer.js +407 -0
  26. package/dist/frame-renderer.js.map +1 -0
  27. package/dist/identity-client.d.ts +132 -0
  28. package/dist/identity-client.d.ts.map +1 -0
  29. package/dist/identity-client.js +204 -0
  30. package/dist/identity-client.js.map +1 -0
  31. package/dist/index.d.ts +56 -0
  32. package/dist/index.d.ts.map +1 -0
  33. package/dist/index.js +90 -0
  34. package/dist/index.js.map +1 -0
  35. package/dist/markdown-html.d.ts +32 -0
  36. package/dist/markdown-html.d.ts.map +1 -0
  37. package/dist/markdown-html.js +251 -0
  38. package/dist/markdown-html.js.map +1 -0
  39. package/dist/nodetool-client.d.ts +32 -0
  40. package/dist/nodetool-client.d.ts.map +1 -0
  41. package/dist/nodetool-client.js +127 -0
  42. package/dist/nodetool-client.js.map +1 -0
  43. package/dist/register-commands.d.ts +24 -0
  44. package/dist/register-commands.d.ts.map +1 -0
  45. package/dist/register-commands.js +29 -0
  46. package/dist/register-commands.js.map +1 -0
  47. package/dist/strings.d.ts +7 -0
  48. package/dist/strings.d.ts.map +1 -0
  49. package/dist/strings.js +13 -0
  50. package/dist/strings.js.map +1 -0
  51. package/dist/telegram-adapter.d.ts +100 -0
  52. package/dist/telegram-adapter.d.ts.map +1 -0
  53. package/dist/telegram-adapter.js +366 -0
  54. package/dist/telegram-adapter.js.map +1 -0
  55. package/dist/turn-router.d.ts +167 -0
  56. package/dist/turn-router.d.ts.map +1 -0
  57. package/dist/turn-router.js +360 -0
  58. package/dist/turn-router.js.map +1 -0
  59. package/package.json +68 -0
@@ -0,0 +1,360 @@
1
+ /**
2
+ * TurnRouter — one turn at a time per conversation, one socket per user
3
+ * (design §6).
4
+ *
5
+ * The router is where identity, the chat socket and the pure frame renderer
6
+ * meet. It owns three things the other modules deliberately do not:
7
+ *
8
+ * - **Whose socket.** A Telegram user's turns run on a `ChatSocket` opened
9
+ * with that user's delegated token, so every turn is the server's own
10
+ * tenant-isolated path. Two users never share a socket.
11
+ * - **Turn order.** A private chat is one conversation: a second message while
12
+ * a turn runs queues behind it (capped), mirroring the server's per-thread
13
+ * turn lock instead of racing it.
14
+ * - **The clock.** `foldFrame` is clockless by construction; this layer is
15
+ * where `Date.now()` enters, which keeps the renderer's throttling rules
16
+ * exercisable by scripted tests.
17
+ *
18
+ * Nothing here imports the Telegram API or the NodeTool SDK: the socket, the
19
+ * thread listing and the delivery of render ops are all injected.
20
+ */
21
+ import { createHash } from "node:crypto";
22
+ import { createRendererState, foldFrame } from "./frame-renderer.js";
23
+ /** Frames carry `chat_seq` on the wire; the renderer reads `seq`. */
24
+ function normalizeFrame(frame) {
25
+ const carried = frame.chat_seq;
26
+ if (typeof carried === "number" && typeof frame.seq !== "number") {
27
+ return { ...frame, seq: carried };
28
+ }
29
+ return frame;
30
+ }
31
+ function threadIdOf(frame) {
32
+ const value = frame.thread_id;
33
+ return typeof value === "string" && value.length > 0 ? value : null;
34
+ }
35
+ /** `telegram-<chatId>-<uid8>-<n>`. */
36
+ export function deriveThreadId(chatId, uid8, index) {
37
+ return `telegram-${chatId}-${uid8}-${index}`;
38
+ }
39
+ /** The short user hash that keeps two tenants' derived ids disjoint. */
40
+ export function userHash8(userId) {
41
+ return createHash("sha256").update(userId).digest("hex").slice(0, 8);
42
+ }
43
+ /** Highest `n` among ids already in this chat's series, or 0 when there is none. */
44
+ export function highestThreadIndex(threadIds, chatId, uid8) {
45
+ const prefix = `telegram-${chatId}-${uid8}-`;
46
+ let highest = 0;
47
+ for (const id of threadIds) {
48
+ if (!id.startsWith(prefix)) {
49
+ continue;
50
+ }
51
+ const index = Number.parseInt(id.slice(prefix.length), 10);
52
+ if (Number.isInteger(index) && index > highest) {
53
+ highest = index;
54
+ }
55
+ }
56
+ return highest;
57
+ }
58
+ // ---------------------------------------------------------------------------
59
+ // Router
60
+ // ---------------------------------------------------------------------------
61
+ export class TurnRouter {
62
+ identity;
63
+ makeClient;
64
+ config;
65
+ executeOps;
66
+ now;
67
+ sessions = new Map();
68
+ conversations = new Map();
69
+ byThread = new Map();
70
+ constructor(options) {
71
+ this.identity = options.identity;
72
+ this.makeClient = options.makeClient;
73
+ this.config = options.config;
74
+ this.executeOps = options.executeOps;
75
+ this.now = options.nowMs ?? Date.now;
76
+ }
77
+ /**
78
+ * Take one inbound message. Starts a turn when the conversation is idle,
79
+ * queues it when a turn is running, and answers busy when the queue is full.
80
+ */
81
+ async submit(input) {
82
+ const resolution = await this.identity.resolve(input.telegramUserId);
83
+ if (resolution.unlinked) {
84
+ return {
85
+ status: "unlinked",
86
+ reason: resolution.reason,
87
+ message: resolution.message
88
+ };
89
+ }
90
+ const session = this.ensureSession(input.telegramUserId, resolution.token, resolution.userId);
91
+ const conversation = await this.ensureConversation(session, input.chatId);
92
+ if (conversation.running !== null) {
93
+ if (conversation.queue.length >= this.config.maxQueuedTurns) {
94
+ return { status: "busy", depth: conversation.queue.length };
95
+ }
96
+ conversation.queue.push({ text: input.text });
97
+ return {
98
+ status: "queued",
99
+ threadId: deriveThreadId(conversation.chatId, session.uid8, conversation.threadIndex),
100
+ depth: conversation.queue.length
101
+ };
102
+ }
103
+ const threadId = this.startTurn(session, conversation, input.text);
104
+ return { status: "started", threadId };
105
+ }
106
+ /** Cancel the in-flight turn in this chat. False when nothing was running. */
107
+ stop(chatId) {
108
+ const conversation = this.conversations.get(chatId);
109
+ if (!conversation || conversation.running === null) {
110
+ return false;
111
+ }
112
+ const session = this.sessions.get(conversation.telegramUserId);
113
+ if (!session) {
114
+ return false;
115
+ }
116
+ session.client.socket.stop(conversation.running.threadId);
117
+ return true;
118
+ }
119
+ /**
120
+ * Rotate this chat onto a fresh thread (`/new`). Anything queued behind the
121
+ * current turn is dropped: the user asked for a clean slate, and delivering
122
+ * old messages into a new thread would be the opposite.
123
+ */
124
+ newThread(chatId) {
125
+ const conversation = this.conversations.get(chatId);
126
+ const session = conversation ? this.sessions.get(conversation.telegramUserId) : undefined;
127
+ if (!conversation || !session) {
128
+ return null;
129
+ }
130
+ conversation.queue.length = 0;
131
+ if (conversation.running !== null) {
132
+ this.byThread.delete(conversation.running.threadId);
133
+ conversation.running = null;
134
+ }
135
+ conversation.threadIndex += 1;
136
+ return deriveThreadId(chatId, session.uid8, conversation.threadIndex);
137
+ }
138
+ /** Current thread id for a chat, when one has been established. */
139
+ currentThreadId(chatId) {
140
+ const conversation = this.conversations.get(chatId);
141
+ const session = conversation ? this.sessions.get(conversation.telegramUserId) : undefined;
142
+ if (!conversation || !session) {
143
+ return null;
144
+ }
145
+ return deriveThreadId(chatId, session.uid8, conversation.threadIndex);
146
+ }
147
+ /** Messages waiting behind the in-flight turn, for `/status`. */
148
+ queueDepth(chatId) {
149
+ return this.conversations.get(chatId)?.queue.length ?? 0;
150
+ }
151
+ /** Whether a turn is in flight in this chat. */
152
+ isRunning(chatId) {
153
+ return this.conversations.get(chatId)?.running != null;
154
+ }
155
+ /**
156
+ * Drop a user's session and cached token after the server rejects it. The
157
+ * next turn mints a fresh token and opens a new socket, rather than retrying
158
+ * a credential the server has already refused.
159
+ */
160
+ invalidateSession(telegramUserId) {
161
+ const session = this.sessions.get(telegramUserId);
162
+ if (!session) {
163
+ return;
164
+ }
165
+ session.dispose();
166
+ session.client.socket.disconnect();
167
+ this.sessions.delete(telegramUserId);
168
+ this.identity.invalidate(telegramUserId);
169
+ }
170
+ /** Close every socket. */
171
+ close() {
172
+ for (const session of this.sessions.values()) {
173
+ session.dispose();
174
+ session.client.socket.disconnect();
175
+ }
176
+ this.sessions.clear();
177
+ this.conversations.clear();
178
+ this.byThread.clear();
179
+ }
180
+ // -------------------------------------------------------------------------
181
+ ensureSession(telegramUserId, token, userId) {
182
+ const existing = this.sessions.get(telegramUserId);
183
+ if (existing && existing.token === token && existing.userId === userId) {
184
+ return existing;
185
+ }
186
+ if (existing) {
187
+ // A re-minted token means a new socket: the old one authenticated with
188
+ // a credential that is on its way out.
189
+ existing.dispose();
190
+ existing.client.socket.disconnect();
191
+ this.sessions.delete(telegramUserId);
192
+ }
193
+ const client = this.makeClient({ token, userId });
194
+ const unsubscribers = [];
195
+ const session = {
196
+ telegramUserId,
197
+ userId,
198
+ token,
199
+ uid8: userHash8(userId),
200
+ client,
201
+ dispose: () => {
202
+ for (const off of unsubscribers) {
203
+ off();
204
+ }
205
+ },
206
+ recovered: existing?.recovered ?? new Set()
207
+ };
208
+ unsubscribers.push(client.socket.onFrame((frame) => this.handleFrame(session, frame)));
209
+ unsubscribers.push(client.socket.onStateChange((state) => {
210
+ if (state === "connected") {
211
+ this.resumeRunningTurns(session);
212
+ }
213
+ }));
214
+ client.socket.connect();
215
+ this.sessions.set(telegramUserId, session);
216
+ return session;
217
+ }
218
+ async ensureConversation(session, chatId) {
219
+ let conversation = this.conversations.get(chatId);
220
+ if (!conversation) {
221
+ conversation = {
222
+ chatId,
223
+ telegramUserId: session.telegramUserId,
224
+ threadIndex: 1,
225
+ queue: [],
226
+ running: null,
227
+ chain: Promise.resolve()
228
+ };
229
+ this.conversations.set(chatId, conversation);
230
+ }
231
+ if (session.recovered.has(chatId)) {
232
+ return conversation;
233
+ }
234
+ session.recovered.add(chatId);
235
+ try {
236
+ const ids = await session.client.listThreadIds();
237
+ const highest = highestThreadIndex(ids, chatId, session.uid8);
238
+ if (highest > 0) {
239
+ conversation.threadIndex = highest;
240
+ }
241
+ }
242
+ catch {
243
+ // The bridge keeps no conversation state, so a failed listing costs the
244
+ // user a new thread, not a broken turn.
245
+ }
246
+ return conversation;
247
+ }
248
+ startTurn(session, conversation, text) {
249
+ const threadId = deriveThreadId(conversation.chatId, session.uid8, conversation.threadIndex);
250
+ const running = {
251
+ threadId,
252
+ renderer: createRendererState({ editThrottleMs: this.config.editThrottleMs }),
253
+ lastSeq: 0,
254
+ sent: false
255
+ };
256
+ conversation.running = running;
257
+ this.byThread.set(threadId, conversation);
258
+ session.client.socket.send({
259
+ threadId,
260
+ text,
261
+ provider: this.config.provider ?? null,
262
+ model: this.config.model ?? null,
263
+ agentMode: true,
264
+ permissionMode: this.config.permissionMode ?? "auto"
265
+ });
266
+ running.sent = true;
267
+ return threadId;
268
+ }
269
+ resumeRunningTurns(session) {
270
+ for (const conversation of this.conversations.values()) {
271
+ if (conversation.telegramUserId !== session.telegramUserId) {
272
+ continue;
273
+ }
274
+ const running = conversation.running;
275
+ if (running === null || !running.sent) {
276
+ continue;
277
+ }
278
+ // The renderer suppresses any replayed frame it has already applied, so
279
+ // asking for one seq too many costs nothing and asking for one too few
280
+ // would lose text.
281
+ session.client.socket.resume(running.threadId, running.lastSeq);
282
+ }
283
+ }
284
+ handleFrame(session, raw) {
285
+ const frame = normalizeFrame(raw);
286
+ const conversation = this.locateConversation(session, frame);
287
+ if (!conversation) {
288
+ return;
289
+ }
290
+ const running = conversation.running;
291
+ if (running === null) {
292
+ return;
293
+ }
294
+ const result = foldFrame(running.renderer, frame, this.now());
295
+ running.renderer = result.state;
296
+ if (typeof result.state.lastSeq === "number") {
297
+ running.lastSeq = result.state.lastSeq;
298
+ }
299
+ if (result.ops.length > 0) {
300
+ const context = {
301
+ chatId: conversation.chatId,
302
+ telegramUserId: session.telegramUserId,
303
+ userId: session.userId,
304
+ threadId: running.threadId,
305
+ token: session.token
306
+ };
307
+ this.deliver(conversation, context, result.ops);
308
+ }
309
+ if (result.state.ended) {
310
+ this.finishTurn(session, conversation);
311
+ }
312
+ }
313
+ locateConversation(session, frame) {
314
+ const threadId = threadIdOf(frame);
315
+ if (threadId !== null) {
316
+ return this.byThread.get(threadId) ?? null;
317
+ }
318
+ // Frames the server does not stamp with a thread belong to the one turn
319
+ // this user has in flight; with several, guessing would put text in the
320
+ // wrong chat, so nothing is rendered.
321
+ let candidate = null;
322
+ for (const conversation of this.conversations.values()) {
323
+ if (conversation.telegramUserId !== session.telegramUserId) {
324
+ continue;
325
+ }
326
+ if (conversation.running === null) {
327
+ continue;
328
+ }
329
+ if (candidate !== null) {
330
+ return null;
331
+ }
332
+ candidate = conversation;
333
+ }
334
+ return candidate;
335
+ }
336
+ deliver(conversation, context, ops) {
337
+ conversation.chain = conversation.chain.then(async () => {
338
+ try {
339
+ await this.executeOps(context, ops);
340
+ }
341
+ catch (err) {
342
+ // One failed Bot API call must not stall every later op in the chat.
343
+ console.error("[telegram] failed to deliver render ops:", err);
344
+ }
345
+ });
346
+ }
347
+ finishTurn(session, conversation) {
348
+ const running = conversation.running;
349
+ if (running !== null) {
350
+ this.byThread.delete(running.threadId);
351
+ }
352
+ conversation.running = null;
353
+ const next = conversation.queue.shift();
354
+ if (next === undefined) {
355
+ return;
356
+ }
357
+ this.startTurn(session, conversation, next.text);
358
+ }
359
+ }
360
+ //# sourceMappingURL=turn-router.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"turn-router.js","sourceRoot":"","sources":["../src/turn-router.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,68 @@
1
+ {
2
+ "name": "@nodetool-ai/telegram",
3
+ "version": "0.8.1",
4
+ "type": "module",
5
+ "engines": {
6
+ "node": ">=22.0.0"
7
+ },
8
+ "main": "dist/index.js",
9
+ "types": "dist/index.d.ts",
10
+ "bin": {
11
+ "nodetool-telegram": "dist/cli.js"
12
+ },
13
+ "scripts": {
14
+ "build": "node ../../scripts/build-typescript-workspace.mjs",
15
+ "test": "node ../../scripts/run-vitest.mjs run",
16
+ "test:watch": "node ../../scripts/run-vitest.mjs",
17
+ "lint": "node ../../scripts/run-tsc.mjs --noEmit"
18
+ },
19
+ "dependencies": {
20
+ "@nodetool-ai/protocol": "^0.8.1",
21
+ "@nodetool-ai/sdk": "^0.8.1",
22
+ "ws": "^8.18.0",
23
+ "zod": "^4.0.0"
24
+ },
25
+ "devDependencies": {
26
+ "@types/node": "^22.0.0",
27
+ "@types/ws": "^8.5.13",
28
+ "typescript": "npm:@typescript/typescript6@6.0.2",
29
+ "vitest": "^5.0.1"
30
+ },
31
+ "exports": {
32
+ ".": {
33
+ "nodetool-dev": "./src/index.ts",
34
+ "types": "./dist/index.d.ts",
35
+ "import": "./dist/index.js",
36
+ "default": "./dist/index.js"
37
+ }
38
+ },
39
+ "license": "MIT",
40
+ "repository": {
41
+ "type": "git",
42
+ "url": "https://github.com/nodetool-ai/nodetool.git",
43
+ "directory": "packages/telegram"
44
+ },
45
+ "homepage": "https://nodetool.ai",
46
+ "bugs": {
47
+ "url": "https://github.com/nodetool-ai/nodetool/issues"
48
+ },
49
+ "publishConfig": {
50
+ "access": "public"
51
+ },
52
+ "files": [
53
+ "dist",
54
+ "README.md"
55
+ ],
56
+ "description": "Telegram bridge for NodeTool — private-chat turns onto the server's unified agent loop",
57
+ "keywords": [
58
+ "nodetool",
59
+ "ai",
60
+ "workflow",
61
+ "workflow-automation",
62
+ "typescript",
63
+ "telegram",
64
+ "bot",
65
+ "chatbot",
66
+ "bridge"
67
+ ]
68
+ }