@rubytech/create-maxy-code 0.1.550 → 0.1.551

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 (48) hide show
  1. package/package.json +1 -1
  2. package/payload/platform/lib/agent-dispatch-rule/dist/index.d.ts +22 -8
  3. package/payload/platform/lib/agent-dispatch-rule/dist/index.d.ts.map +1 -1
  4. package/payload/platform/lib/agent-dispatch-rule/dist/index.js +47 -13
  5. package/payload/platform/lib/agent-dispatch-rule/dist/index.js.map +1 -1
  6. package/payload/platform/lib/agent-dispatch-rule/src/__tests__/rule.test.ts +68 -9
  7. package/payload/platform/lib/agent-dispatch-rule/src/index.ts +60 -16
  8. package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +3 -3
  9. package/payload/platform/plugins/admin/skills/whats-new/SKILL.md +4 -0
  10. package/payload/platform/plugins/docs/references/admin-ui.md +2 -2
  11. package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/agent-dispatch.test.js +2 -2
  12. package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/agent-dispatch.test.js.map +1 -1
  13. package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/connector-sync-provision.test.js +2 -2
  14. package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/connector-sync-provision.test.js.map +1 -1
  15. package/payload/platform/plugins/scheduling/mcp/dist/lib/connector-sync-provision.d.ts.map +1 -1
  16. package/payload/platform/plugins/scheduling/mcp/dist/lib/connector-sync-provision.js +21 -8
  17. package/payload/platform/plugins/scheduling/mcp/dist/lib/connector-sync-provision.js.map +1 -1
  18. package/payload/platform/plugins/telegram/.claude-plugin/plugin.json +1 -1
  19. package/payload/platform/plugins/telegram/PLUGIN.md +6 -4
  20. package/payload/platform/plugins/telegram/mcp/dist/index.js +62 -38
  21. package/payload/platform/plugins/telegram/mcp/dist/index.js.map +1 -1
  22. package/payload/platform/plugins/telegram/mcp/dist/lib/account-token.d.ts +18 -5
  23. package/payload/platform/plugins/telegram/mcp/dist/lib/account-token.d.ts.map +1 -1
  24. package/payload/platform/plugins/telegram/mcp/dist/lib/account-token.js +34 -6
  25. package/payload/platform/plugins/telegram/mcp/dist/lib/account-token.js.map +1 -1
  26. package/payload/platform/plugins/telegram/mcp/dist/lib/account-write.d.ts +25 -8
  27. package/payload/platform/plugins/telegram/mcp/dist/lib/account-write.d.ts.map +1 -1
  28. package/payload/platform/plugins/telegram/mcp/dist/lib/account-write.js +28 -16
  29. package/payload/platform/plugins/telegram/mcp/dist/lib/account-write.js.map +1 -1
  30. package/payload/platform/plugins/telegram/mcp/dist/lib/agent-active.d.ts +12 -0
  31. package/payload/platform/plugins/telegram/mcp/dist/lib/agent-active.d.ts.map +1 -0
  32. package/payload/platform/plugins/telegram/mcp/dist/lib/agent-active.js +26 -0
  33. package/payload/platform/plugins/telegram/mcp/dist/lib/agent-active.js.map +1 -0
  34. package/payload/platform/plugins/telegram/mcp/dist/lib/secret-path.d.ts +16 -13
  35. package/payload/platform/plugins/telegram/mcp/dist/lib/secret-path.d.ts.map +1 -1
  36. package/payload/platform/plugins/telegram/mcp/dist/lib/secret-path.js +19 -23
  37. package/payload/platform/plugins/telegram/mcp/dist/lib/secret-path.js.map +1 -1
  38. package/payload/platform/plugins/telegram/mcp/dist/lib/webhook-url.d.ts +9 -7
  39. package/payload/platform/plugins/telegram/mcp/dist/lib/webhook-url.d.ts.map +1 -1
  40. package/payload/platform/plugins/telegram/mcp/dist/lib/webhook-url.js +11 -8
  41. package/payload/platform/plugins/telegram/mcp/dist/lib/webhook-url.js.map +1 -1
  42. package/payload/platform/plugins/telegram/mcp/dist/tools/message.d.ts +4 -0
  43. package/payload/platform/plugins/telegram/mcp/dist/tools/message.d.ts.map +1 -1
  44. package/payload/platform/plugins/telegram/mcp/dist/tools/message.js +13 -3
  45. package/payload/platform/plugins/telegram/mcp/dist/tools/message.js.map +1 -1
  46. package/payload/platform/plugins/telegram/references/setup-guide.md +16 -8
  47. package/payload/platform/plugins/telegram/skills/configure/SKILL.md +30 -32
  48. package/payload/server/server.js +510 -240
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rubytech/create-maxy-code",
3
- "version": "0.1.550",
3
+ "version": "0.1.551",
4
4
  "description": "Install Maxy — AI for Productive People",
5
5
  "bin": {
6
6
  "create-maxy-code": "./dist/index.js"
@@ -24,6 +24,18 @@ export type DestinationValidity = {
24
24
  export declare function normalizeE164(value: string): string;
25
25
  /** Normalized equality, non-empty. */
26
26
  export declare function phonesMatch(a: string, b: string): boolean;
27
+ export interface TelegramAdmins {
28
+ /** Every numeric id admitted on ANY of this account's admin bots. */
29
+ adminUsers: number[];
30
+ /** The same set, split by the bot that admits it. Task 2368 — a destination
31
+ * in bot A's list is not dispatchable on bot B, so the picker and the
32
+ * dispatch both need to know which bot owns it, not just that the account
33
+ * does. */
34
+ byBot: Array<{
35
+ botId: string;
36
+ adminUsers: number[];
37
+ }>;
38
+ }
27
39
  interface WhatsAppAdmins {
28
40
  adminPhones: string[];
29
41
  /** Manager phone to the sub-account it is bound to. */
@@ -33,9 +45,7 @@ interface WhatsAppAdmins {
33
45
  * malformed config yields empty lists (a fail-closed default: no destination
34
46
  * validates against empty config). */
35
47
  export declare function readChannelAdmins(accountDir: string, channel: "whatsapp"): WhatsAppAdmins;
36
- export declare function readChannelAdmins(accountDir: string, channel: "telegram"): {
37
- adminUsers: number[];
38
- };
48
+ export declare function readChannelAdmins(accountDir: string, channel: "telegram"): TelegramAdmins;
39
49
  /**
40
50
  * The account a WhatsApp `destination` is registered to on the HOUSE's lists,
41
51
  * or null if it is in neither list. A manager binding wins over an admin match:
@@ -63,11 +73,12 @@ export declare function boundSubAccountFor(accountDir: string, destination: stri
63
73
  * owns the single line and may target any registered admin/manager) OR the
64
74
  * registered account equals the creating account. Any other case is
65
75
  * `cross-account`.
66
- * - telegram: house-only. Reads the creating account's own
67
- * `telegram.adminUsers`; there is no manager surface and thus no
68
- * cross-account concept — an integer chat id present in the list is valid,
69
- * anything else is `not-registered`. `houseAccountId` is unused on this
70
- * branch, which is why a telegram caller need not resolve one.
76
+ * - telegram: house-only. Reads the creating account's own admin bot entries,
77
+ * unioned across every one of them (Task 2368); there is no manager surface
78
+ * and thus no cross-account concept — an integer chat id present in ANY of
79
+ * that account's admin bots is valid, anything else is `not-registered`.
80
+ * `houseAccountId` is unused on this branch, which is why a telegram caller
81
+ * need not resolve one.
71
82
  */
72
83
  export declare function validateAgentDestination(accountsDir: string, houseAccountId: string, creatingAccountId: string, channel: AgentChannel, destination: string): DestinationValidity;
73
84
  /** Which authoritative list an offered destination came from. Not a name: no
@@ -78,6 +89,9 @@ export interface DispatchDestination {
78
89
  channel: AgentChannel;
79
90
  destination: string;
80
91
  label: DispatchLabel;
92
+ /** Task 2368 — which of the account's bots admits this destination. Absent on
93
+ * WhatsApp, which has no bot concept. */
94
+ botId?: string;
81
95
  /** Task 2204 — a display-only person name, attached by a CALLER that has a
82
96
  * graph to read. `listDispatchDestinations` never sets it: this module reads
83
97
  * account.json and nothing else, and `validateAgentDestination` never
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AA0BA,MAAM,MAAM,YAAY,GAAG,UAAU,GAAG,UAAU,CAAC;AAEnD;;;;;;;;GAQG;AACH,MAAM,MAAM,mBAAmB,GAC3B;IAAE,KAAK,EAAE,IAAI,CAAA;CAAE,GACf;IAAE,KAAK,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,gBAAgB,CAAA;CAAE,GAC1C;IAAE,KAAK,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,eAAe,CAAC;IAAC,kBAAkB,EAAE,MAAM,CAAC;IAAC,eAAe,EAAE,MAAM,CAAA;CAAE,CAAC;AAEnG;wCACwC;AACxC,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAOnD;AAED,sCAAsC;AACtC,wBAAgB,WAAW,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAIzD;AAED,UAAU,cAAc;IACtB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,uDAAuD;IACvD,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACzC;AAED;;uCAEuC;AACvC,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,GAAG,cAAc,CAAC;AAC3F,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,GAAG;IAAE,UAAU,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC;AAwDrG;;;;;;GAMG;AACH,wBAAgB,+BAA+B,CAC7C,QAAQ,EAAE,MAAM,EAChB,cAAc,EAAE,MAAM,EACtB,WAAW,EAAE,MAAM,GAClB,MAAM,GAAG,IAAI,CAOf;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAMzF;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,wBAAwB,CACtC,WAAW,EAAE,MAAM,EACnB,cAAc,EAAE,MAAM,EACtB,iBAAiB,EAAE,MAAM,EACzB,OAAO,EAAE,YAAY,EACrB,WAAW,EAAE,MAAM,GAClB,mBAAmB,CAkBrB;AAED;;uDAEuD;AACvD,MAAM,MAAM,aAAa,GAAG,aAAa,GAAG,iBAAiB,GAAG,gBAAgB,CAAC;AAEjF,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,YAAY,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,aAAa,CAAC;IACrB;;;iFAG6E;IAC7E,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE;IAC9C,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,SAAS,EAAE,MAAM,CAAC;CACnB,GAAG,mBAAmB,EAAE,CAsCxB"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AA0BA,MAAM,MAAM,YAAY,GAAG,UAAU,GAAG,UAAU,CAAC;AAEnD;;;;;;;;GAQG;AACH,MAAM,MAAM,mBAAmB,GAC3B;IAAE,KAAK,EAAE,IAAI,CAAA;CAAE,GACf;IAAE,KAAK,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,gBAAgB,CAAA;CAAE,GAC1C;IAAE,KAAK,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,eAAe,CAAC;IAAC,kBAAkB,EAAE,MAAM,CAAC;IAAC,eAAe,EAAE,MAAM,CAAA;CAAE,CAAC;AAEnG;wCACwC;AACxC,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAOnD;AAED,sCAAsC;AACtC,wBAAgB,WAAW,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAIzD;AAED,MAAM,WAAW,cAAc;IAC7B,qEAAqE;IACrE,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB;;;gBAGY;IACZ,KAAK,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;CACvD;AAED,UAAU,cAAc;IACtB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,uDAAuD;IACvD,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACzC;AAED;;uCAEuC;AACvC,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,GAAG,cAAc,CAAC;AAC3F,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,GAAG,cAAc,CAAC;AA6E3F;;;;;;GAMG;AACH,wBAAgB,+BAA+B,CAC7C,QAAQ,EAAE,MAAM,EAChB,cAAc,EAAE,MAAM,EACtB,WAAW,EAAE,MAAM,GAClB,MAAM,GAAG,IAAI,CAOf;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAMzF;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,wBAAwB,CACtC,WAAW,EAAE,MAAM,EACnB,cAAc,EAAE,MAAM,EACtB,iBAAiB,EAAE,MAAM,EACzB,OAAO,EAAE,YAAY,EACrB,WAAW,EAAE,MAAM,GAClB,mBAAmB,CAkBrB;AAED;;uDAEuD;AACvD,MAAM,MAAM,aAAa,GAAG,aAAa,GAAG,iBAAiB,GAAG,gBAAgB,CAAC;AAEjF,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,YAAY,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,aAAa,CAAC;IACrB;8CAC0C;IAC1C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;iFAG6E;IAC7E,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE;IAC9C,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,SAAS,EAAE,MAAM,CAAC;CACnB,GAAG,mBAAmB,EAAE,CA+CxB"}
@@ -98,11 +98,35 @@ function readChannelAdmins(accountDir, channel) {
98
98
  }
99
99
  return { adminPhones, accountManagers };
100
100
  }
101
+ // Task 2368 — the bots array. The two-slot `telegram.adminUsers` is deleted,
102
+ // so it is not read here: an install still holding it reads as empty until the
103
+ // boot converter rewrites it, which is the fail-closed default this function
104
+ // already applies to a missing config. A public entry has no adminUsers
105
+ // surface at all, so only admin entries contribute.
101
106
  const tg = config.telegram ?? {};
102
- const adminUsers = Array.isArray(tg.adminUsers)
103
- ? tg.adminUsers.filter((u) => typeof u === "number")
104
- : [];
105
- return { adminUsers };
107
+ const byBot = [];
108
+ const seen = new Set();
109
+ const adminUsers = [];
110
+ if (Array.isArray(tg.bots)) {
111
+ for (const raw of tg.bots) {
112
+ if (!raw || typeof raw !== "object")
113
+ continue;
114
+ const b = raw;
115
+ if (b.role !== "admin" || typeof b.id !== "string" || b.id.length === 0)
116
+ continue;
117
+ const users = Array.isArray(b.adminUsers)
118
+ ? b.adminUsers.filter((u) => typeof u === "number")
119
+ : [];
120
+ byBot.push({ botId: b.id, adminUsers: users });
121
+ for (const u of users) {
122
+ if (seen.has(u))
123
+ continue;
124
+ seen.add(u);
125
+ adminUsers.push(u);
126
+ }
127
+ }
128
+ }
129
+ return { adminUsers, byBot };
106
130
  }
107
131
  /**
108
132
  * The account a WhatsApp `destination` is registered to on the HOUSE's lists,
@@ -147,11 +171,12 @@ function boundSubAccountFor(accountDir, destination) {
147
171
  * owns the single line and may target any registered admin/manager) OR the
148
172
  * registered account equals the creating account. Any other case is
149
173
  * `cross-account`.
150
- * - telegram: house-only. Reads the creating account's own
151
- * `telegram.adminUsers`; there is no manager surface and thus no
152
- * cross-account concept — an integer chat id present in the list is valid,
153
- * anything else is `not-registered`. `houseAccountId` is unused on this
154
- * branch, which is why a telegram caller need not resolve one.
174
+ * - telegram: house-only. Reads the creating account's own admin bot entries,
175
+ * unioned across every one of them (Task 2368); there is no manager surface
176
+ * and thus no cross-account concept — an integer chat id present in ANY of
177
+ * that account's admin bots is valid, anything else is `not-registered`.
178
+ * `houseAccountId` is unused on this branch, which is why a telegram caller
179
+ * need not resolve one.
155
180
  */
156
181
  function validateAgentDestination(accountsDir, houseAccountId, creatingAccountId, channel, destination) {
157
182
  if (channel === "whatsapp") {
@@ -218,10 +243,19 @@ function listDispatchDestinations(input) {
218
243
  admins.push({ channel: "whatsapp", destination: phone, label: "House admin" });
219
244
  }
220
245
  }
221
- const { adminUsers } = readChannelAdmins((0, node_path_1.resolve)(accountsDir, accountId), "telegram");
222
- const telegram = [...adminUsers]
223
- .sort((a, b) => a - b)
224
- .map((id) => ({ channel: "telegram", destination: String(id), label: "Telegram admin" }));
246
+ // Task 2368 one offer per (bot, destination) pair. A destination in bot A's
247
+ // list cannot be dispatched on bot B, so the label alone no longer identifies
248
+ // where the message would go.
249
+ const { byBot } = readChannelAdmins((0, node_path_1.resolve)(accountsDir, accountId), "telegram");
250
+ const telegram = byBot
251
+ .flatMap((b) => b.adminUsers.map((id) => ({ botId: b.botId, id })))
252
+ .sort((a, b) => a.id - b.id || a.botId.localeCompare(b.botId))
253
+ .map(({ botId, id }) => ({
254
+ channel: "telegram",
255
+ destination: String(id),
256
+ label: "Telegram admin",
257
+ botId,
258
+ }));
225
259
  const byDestination = (a, b) => a.destination.localeCompare(b.destination);
226
260
  return [...managers.sort(byDestination), ...admins.sort(byDestination), ...telegram];
227
261
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -170,7 +170,7 @@ describe("readChannelAdmins", () => {
170
170
 
171
171
  it("keeps only numeric telegram adminUsers", () => {
172
172
  const accountsDir = makeAccountsDir((d) => {
173
- seedAccount(d, SUB_A, { telegram: { adminUsers: [123, "456", 789] } });
173
+ seedAccount(d, SUB_A, { telegram: { bots: [{ id: "111", token: "111:A", role: "admin", adminUsers: [123, "456", 789] }] } });
174
174
  });
175
175
  expect(readChannelAdmins(join(accountsDir, SUB_A), "telegram").adminUsers).toEqual([123, 789]);
176
176
  });
@@ -239,7 +239,7 @@ describe("validateAgentDestination", () => {
239
239
  function houseWith(managers: Record<string, unknown>, adminPhones: string[] = ["+447700900111"]): string {
240
240
  return makeAccountsDir((d) => {
241
241
  seedAccount(d, HOUSE, { role: "house", whatsapp: { adminPhones, accountManagers: managers } });
242
- seedAccount(d, SUB_A, { telegram: { adminUsers: [555001] } });
242
+ seedAccount(d, SUB_A, { telegram: { bots: [{ id: "111", token: "111:A", role: "admin", adminUsers: [555001] }] } });
243
243
  seedAccount(d, SUB_B, {});
244
244
  });
245
245
  }
@@ -317,9 +317,9 @@ describe("listDispatchDestinations", () => {
317
317
  "+447700900444": { managesAccount: SUB_B, mode: "active" },
318
318
  },
319
319
  },
320
- telegram: { adminUsers: [900001] },
320
+ telegram: { bots: [{ id: "900", token: "900:H", role: "admin", adminUsers: [900001] }] },
321
321
  });
322
- seedAccount(d, SUB_A, { telegram: { adminUsers: [555002, 555001] } });
322
+ seedAccount(d, SUB_A, { telegram: { bots: [{ id: "111", token: "111:A", role: "admin", adminUsers: [555002, 555001] }] } });
323
323
  seedAccount(d, SUB_B, {});
324
324
  });
325
325
  }
@@ -330,7 +330,7 @@ describe("listDispatchDestinations", () => {
330
330
  { channel: "whatsapp", destination: "+447700900222", label: "Account manager" },
331
331
  { channel: "whatsapp", destination: "+447700900444", label: "Account manager" },
332
332
  { channel: "whatsapp", destination: "+447700900111", label: "House admin" },
333
- { channel: "telegram", destination: "900001", label: "Telegram admin" },
333
+ { channel: "telegram", destination: "900001", label: "Telegram admin", botId: "900" },
334
334
  ]);
335
335
  });
336
336
 
@@ -347,8 +347,8 @@ describe("listDispatchDestinations", () => {
347
347
  const dir = seeded();
348
348
  expect(listDispatchDestinations({ accountsDir: dir, houseAccountId: HOUSE, accountId: SUB_A })).toEqual([
349
349
  { channel: "whatsapp", destination: "+447700900222", label: "Account manager" },
350
- { channel: "telegram", destination: "555001", label: "Telegram admin" },
351
- { channel: "telegram", destination: "555002", label: "Telegram admin" },
350
+ { channel: "telegram", destination: "555001", label: "Telegram admin", botId: "111" },
351
+ { channel: "telegram", destination: "555002", label: "Telegram admin", botId: "111" },
352
352
  ]);
353
353
  });
354
354
 
@@ -364,8 +364,8 @@ describe("listDispatchDestinations", () => {
364
364
  it("drops every WhatsApp entry when the house cannot be resolved, keeping telegram", () => {
365
365
  const dir = seeded();
366
366
  expect(listDispatchDestinations({ accountsDir: dir, houseAccountId: null, accountId: SUB_A })).toEqual([
367
- { channel: "telegram", destination: "555001", label: "Telegram admin" },
368
- { channel: "telegram", destination: "555002", label: "Telegram admin" },
367
+ { channel: "telegram", destination: "555001", label: "Telegram admin", botId: "111" },
368
+ { channel: "telegram", destination: "555002", label: "Telegram admin", botId: "111" },
369
369
  ]);
370
370
  });
371
371
 
@@ -382,3 +382,62 @@ describe("listDispatchDestinations", () => {
382
382
  expect(listDispatchDestinations({ accountsDir: dir, houseAccountId: HOUSE, accountId: stranger })).toEqual([]);
383
383
  });
384
384
  });
385
+
386
+ describe("Task 2368 — telegram bots array", () => {
387
+ it("unions adminUsers across admin entries and ignores public entries", () => {
388
+ const accountsDir = makeAccountsDir((d) => {
389
+ seedAccount(d, SUB_A, { telegram: { bots: [
390
+ { id: "111", token: "111:A", role: "admin", adminUsers: [1, 2] },
391
+ { id: "222", token: "222:B", role: "admin", adminUsers: [2, 3] },
392
+ { id: "333", token: "333:C", role: "public", agent: "beagle", allowFrom: [99] },
393
+ ] } });
394
+ });
395
+ expect(readChannelAdmins(join(accountsDir, SUB_A), "telegram").adminUsers).toEqual([1, 2, 3]);
396
+ });
397
+
398
+ it("reports which bot each destination belongs to", () => {
399
+ const accountsDir = makeAccountsDir((d) => {
400
+ seedAccount(d, SUB_A, { telegram: { bots: [
401
+ { id: "111", token: "111:A", role: "admin", adminUsers: [1] },
402
+ { id: "222", token: "222:B", role: "admin", adminUsers: [2] },
403
+ ] } });
404
+ });
405
+ expect(readChannelAdmins(join(accountsDir, SUB_A), "telegram").byBot).toEqual([
406
+ { botId: "111", adminUsers: [1] },
407
+ { botId: "222", adminUsers: [2] },
408
+ ]);
409
+ });
410
+
411
+ it("labels each offered destination with its bot", () => {
412
+ const accountsDir = makeAccountsDir((d) => {
413
+ seedAccount(d, SUB_A, { telegram: { bots: [
414
+ { id: "111", token: "111:A", role: "admin", adminUsers: [1] },
415
+ { id: "222", token: "222:B", role: "admin", adminUsers: [2] },
416
+ ] } });
417
+ });
418
+ expect(listDispatchDestinations({ accountsDir, houseAccountId: null, accountId: SUB_A })).toEqual([
419
+ { channel: "telegram", destination: "1", label: "Telegram admin", botId: "111" },
420
+ { channel: "telegram", destination: "2", label: "Telegram admin", botId: "222" },
421
+ ]);
422
+ });
423
+
424
+ it("validates a destination held by ANY admin entry", () => {
425
+ const accountsDir = makeAccountsDir((d) => {
426
+ seedAccount(d, SUB_A, { telegram: { bots: [
427
+ { id: "111", token: "111:A", role: "admin", adminUsers: [1] },
428
+ { id: "222", token: "222:B", role: "admin", adminUsers: [2] },
429
+ ] } });
430
+ });
431
+ expect(validateAgentDestination(accountsDir, HOUSE, SUB_A, "telegram", "2")).toEqual({ valid: true });
432
+ expect(validateAgentDestination(accountsDir, HOUSE, SUB_A, "telegram", "9")).toEqual({
433
+ valid: false, reason: "not-registered",
434
+ });
435
+ });
436
+
437
+ it("reads nothing from the deleted two-slot shape", () => {
438
+ const accountsDir = makeAccountsDir((d) => {
439
+ seedAccount(d, SUB_A, { telegram: { adminUsers: [1, 2] } });
440
+ });
441
+ expect(readChannelAdmins(join(accountsDir, SUB_A), "telegram").adminUsers).toEqual([]);
442
+ });
443
+ });
@@ -58,6 +58,16 @@ export function phonesMatch(a: string, b: string): boolean {
58
58
  return na.length > 0 && na === nb;
59
59
  }
60
60
 
61
+ export interface TelegramAdmins {
62
+ /** Every numeric id admitted on ANY of this account's admin bots. */
63
+ adminUsers: number[];
64
+ /** The same set, split by the bot that admits it. Task 2368 — a destination
65
+ * in bot A's list is not dispatchable on bot B, so the picker and the
66
+ * dispatch both need to know which bot owns it, not just that the account
67
+ * does. */
68
+ byBot: Array<{ botId: string; adminUsers: number[] }>;
69
+ }
70
+
61
71
  interface WhatsAppAdmins {
62
72
  adminPhones: string[];
63
73
  /** Manager phone to the sub-account it is bound to. */
@@ -68,11 +78,11 @@ interface WhatsAppAdmins {
68
78
  * malformed config yields empty lists (a fail-closed default: no destination
69
79
  * validates against empty config). */
70
80
  export function readChannelAdmins(accountDir: string, channel: "whatsapp"): WhatsAppAdmins;
71
- export function readChannelAdmins(accountDir: string, channel: "telegram"): { adminUsers: number[] };
81
+ export function readChannelAdmins(accountDir: string, channel: "telegram"): TelegramAdmins;
72
82
  export function readChannelAdmins(
73
83
  accountDir: string,
74
84
  channel: AgentChannel,
75
- ): WhatsAppAdmins | { adminUsers: number[] } {
85
+ ): WhatsAppAdmins | TelegramAdmins {
76
86
  let config: Record<string, unknown> = {};
77
87
  try {
78
88
  config = JSON.parse(readFileSync(resolve(accountDir, "account.json"), "utf-8"));
@@ -117,11 +127,32 @@ export function readChannelAdmins(
117
127
  }
118
128
  return { adminPhones, accountManagers };
119
129
  }
120
- const tg = (config.telegram as Record<string, unknown> | undefined) ?? {};
121
- const adminUsers = Array.isArray(tg.adminUsers)
122
- ? tg.adminUsers.filter((u): u is number => typeof u === "number")
123
- : [];
124
- return { adminUsers };
130
+ // Task 2368 the bots array. The two-slot `telegram.adminUsers` is deleted,
131
+ // so it is not read here: an install still holding it reads as empty until the
132
+ // boot converter rewrites it, which is the fail-closed default this function
133
+ // already applies to a missing config. A public entry has no adminUsers
134
+ // surface at all, so only admin entries contribute.
135
+ const tg = (config.telegram as { bots?: unknown } | undefined) ?? {};
136
+ const byBot: Array<{ botId: string; adminUsers: number[] }> = [];
137
+ const seen = new Set<number>();
138
+ const adminUsers: number[] = [];
139
+ if (Array.isArray(tg.bots)) {
140
+ for (const raw of tg.bots) {
141
+ if (!raw || typeof raw !== "object") continue;
142
+ const b = raw as { id?: unknown; role?: unknown; adminUsers?: unknown };
143
+ if (b.role !== "admin" || typeof b.id !== "string" || b.id.length === 0) continue;
144
+ const users = Array.isArray(b.adminUsers)
145
+ ? b.adminUsers.filter((u): u is number => typeof u === "number")
146
+ : [];
147
+ byBot.push({ botId: b.id, adminUsers: users });
148
+ for (const u of users) {
149
+ if (seen.has(u)) continue;
150
+ seen.add(u);
151
+ adminUsers.push(u);
152
+ }
153
+ }
154
+ }
155
+ return { adminUsers, byBot };
125
156
  }
126
157
 
127
158
  /**
@@ -170,11 +201,12 @@ export function boundSubAccountFor(accountDir: string, destination: string): str
170
201
  * owns the single line and may target any registered admin/manager) OR the
171
202
  * registered account equals the creating account. Any other case is
172
203
  * `cross-account`.
173
- * - telegram: house-only. Reads the creating account's own
174
- * `telegram.adminUsers`; there is no manager surface and thus no
175
- * cross-account concept — an integer chat id present in the list is valid,
176
- * anything else is `not-registered`. `houseAccountId` is unused on this
177
- * branch, which is why a telegram caller need not resolve one.
204
+ * - telegram: house-only. Reads the creating account's own admin bot entries,
205
+ * unioned across every one of them (Task 2368); there is no manager surface
206
+ * and thus no cross-account concept — an integer chat id present in ANY of
207
+ * that account's admin bots is valid, anything else is `not-registered`.
208
+ * `houseAccountId` is unused on this branch, which is why a telegram caller
209
+ * need not resolve one.
178
210
  */
179
211
  export function validateAgentDestination(
180
212
  accountsDir: string,
@@ -211,6 +243,9 @@ export interface DispatchDestination {
211
243
  channel: AgentChannel;
212
244
  destination: string;
213
245
  label: DispatchLabel;
246
+ /** Task 2368 — which of the account's bots admits this destination. Absent on
247
+ * WhatsApp, which has no bot concept. */
248
+ botId?: string;
214
249
  /** Task 2204 — a display-only person name, attached by a CALLER that has a
215
250
  * graph to read. `listDispatchDestinations` never sets it: this module reads
216
251
  * account.json and nothing else, and `validateAgentDestination` never
@@ -263,10 +298,19 @@ export function listDispatchDestinations(input: {
263
298
  }
264
299
  }
265
300
 
266
- const { adminUsers } = readChannelAdmins(resolve(accountsDir, accountId), "telegram");
267
- const telegram: DispatchDestination[] = [...adminUsers]
268
- .sort((a, b) => a - b)
269
- .map((id) => ({ channel: "telegram" as const, destination: String(id), label: "Telegram admin" as const }));
301
+ // Task 2368 one offer per (bot, destination) pair. A destination in bot A's
302
+ // list cannot be dispatched on bot B, so the label alone no longer identifies
303
+ // where the message would go.
304
+ const { byBot } = readChannelAdmins(resolve(accountsDir, accountId), "telegram");
305
+ const telegram: DispatchDestination[] = byBot
306
+ .flatMap((b) => b.adminUsers.map((id) => ({ botId: b.botId, id })))
307
+ .sort((a, b) => a.id - b.id || a.botId.localeCompare(b.botId))
308
+ .map(({ botId, id }) => ({
309
+ channel: "telegram" as const,
310
+ destination: String(id),
311
+ label: "Telegram admin" as const,
312
+ botId,
313
+ }));
270
314
 
271
315
  const byDestination = (a: DispatchDestination, b: DispatchDestination) =>
272
316
  a.destination.localeCompare(b.destination);
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: platform-architecture
3
3
  description: Use when grounding any documented-surface claim about what Maxy ships — plugins, skills, specialists, install/deploy flows, internals. This is the install catalogue, not evidence of what is enabled on the current account. For install state on this account, call `capabilities-here`; for documented surface, cite the `Source:` URL inline.
4
- content-hash: sha256:67fd64d3983bd1c788d6945201c05ee4afeb63fd02fb033123b63e364e915430
4
+ content-hash: sha256:b20c0cc4943d42c84f0e324403b1da911481214c3834ff2c778daf1f5f6db086
5
5
  brand: maxy-code
6
6
  product-name: Maxy
7
7
  ---
@@ -3441,7 +3441,7 @@ either is a regression.
3441
3441
  |---|---|---|
3442
3442
  | `/session` | Admin cookie session: PIN-gated mint, validate, rotate. | `GET /`, `POST /` |
3443
3443
  | `/sessions` | Legacy admin-server conversation routes. No UI consumer remains after the ConversationsModal was retired; the surviving handlers are deletion candidates and not described here. | (legacy, no live caller) |
3444
- | `/sidebar-sessions` | Sole data path for the sidebar Sessions list. One JSONL on disk equals one row. The row's delete button is the only way a row disappears. Each row carries `sessionId`, `title`, `startedAt`, `live`, `isSubagent`, `pid: number \| null` (basename of the matched `sessions/<pid>.json`), and `projectDir` (the directory holding the JSONL — consumed by the delete route). The payload also carries top-level `accountId` so the pane renders the full UUID label whose first ~8 chars prefix-match the truncated Remote Control daemon entry in claude.ai/code. The legacy `rcUrl` field is gone — the row's external-link affordance now POSTs `/session-rc-spawn` to start a fresh local `claude --remote-control <name> --session-id <sid>` PTY on every click. **WhatsApp and Telegram sessions (admin + public) appear in this list**, colour-coded by channel (WhatsApp green `#25D366`, Telegram blue `#229ED9`, via a `conv-channel-*` left accent bar) and carrying the standard row kebab (Usage & cost, Reset/re-seat, Rename, Archive, Delete) so the operator can inspect and re-seat a channel session's params. Each row's `channel` is the authoritative `.meta.json` sidecar value (`whatsapp`/`telegram`/`webchat`/`browser`/null), not the JSONL-envelope channel. Each row also carries its sidecar `senderId`. For a WhatsApp/Telegram row with a `senderId` and no operator rename or ai-title (`titleSource:'prefix'`), the route resolves a contact `personName` and the sidebar renders the reader panel's `"<name> <number>"` label via the shared `operatorConvName`, degrading to the number alone then the stripped title on a miss. On a `whatsapp` row the number is printed in international form (`+44 7504 472444`, `+33 7 68 24 30 67`) by `formatSenderPhone` — `normalizeE164` then libphonenumber-js `formatInternational`, gated on `isPossible` so an unresolved LID prints raw; a `telegram` senderId is a Telegram user id and a `webchat` one is `session:<id>`, so neither is regrouped. The formatting is display-only: row identity, matching, and store keys stay on the normalized digits. Because the label function is shared, a Sessions row and that conversation's reader-panel row read identically. A channel row name has two sources, in precedence order. First the shared `resolveOperatorNamesBySender` helper the WhatsApp reader also calls, which matches the sender phone against the account's admins — that names an admin WhatsApp session and every Telegram session. Second, for a `whatsapp` row only, the WhatsApp pushName from the account's on-disk message store (`storePushNamesBySender` over `readConversationSummaries`, keyed by `normalizeE164` of the counterparty phone so a `+44 7…` sender matches a `447…` store key). The store is consulted only when the resolver reports **no binding** for that sender. That is typically a public WhatsApp customer, the case this exists for — such a sender has no admin record and so can only be named by the store, and without it those rows degraded to the bare number while the reader panel named them — though an admin missing from `users.json` qualifies too. A resolver miss caused by Neo4j being unreachable deliberately does NOT qualify: that is an outage rather than an absent binding, so the row degrades to the number and still logs `reason=neo4j-down`, keeping the outage signal intact. Telegram has no message store and is never looked up. The store read is guarded: a corrupt or absent store degrades to no pushName and logs `op=store-unreadable`, never 500s the list. Both sources are the ones the reader itself uses, so the two surfaces cannot drift; a renamed or ai-titled channel row keeps its own title. The Sessions list reads the viewed account's own store only. An account-manager's thread persists under the house account rather than the sub-account it manages, so on a multi-account install viewing a sub-account that row is not named here even though the reader panel names it — the reader additionally consults the house store, filtered to manager phones bound to that sub. The only role/channel excluded from the list is `public`+`webchat` (its dedicated reader is the sole surface); the exclusion predicate is `isSessionListExcluded`, decoupled from the reader's inclusion predicate `isReaderChannelSession` (unchanged), so the WhatsApp/Telegram reader panels are unaffected — a store-only WhatsApp conversation with no session JSONL stays reader-only. Observability rides `[admin-sessions-list] … channelInList=whatsapp:<n>,telegram:<n>,webchat:<n> channelNameCandidates=<n> channelNamesResolved=<n> (operator=<n> store=<n>) unknownChannel=<n> excludedPublicWebchat=<n>`, and each unresolved channel name logs one `[admin-sessions-list] op=channel-name-unresolved sessionId=<id8> channel=<whatsapp\|telegram> senderId=<id> reason=<no-senderId\|classify-miss\|neo4j-down>` line — emitted only when **both** sources miss, so a residual shortfall means a genuinely nameless sender rather than the expected public-customer floor, and the `operator=`/`store=` split says which source is carrying the names. | `GET /` |
3444
+ | `/sidebar-sessions` | Sole data path for the sidebar Sessions list. One JSONL on disk equals one row. The row's delete button is the only way a row disappears. Each row carries `sessionId`, `title`, `startedAt`, `live`, `isSubagent`, `pid: number \| null` (basename of the matched `sessions/<pid>.json`), and `projectDir` (the directory holding the JSONL — consumed by the delete route). The payload also carries top-level `accountId` so the pane renders the full UUID label whose first ~8 chars prefix-match the truncated Remote Control daemon entry in claude.ai/code. The legacy `rcUrl` field is gone — the row's external-link affordance now POSTs `/session-rc-spawn` to start a fresh local `claude --remote-control <name> --session-id <sid>` PTY on every click. **WhatsApp and Telegram sessions (admin + public) appear in this list**, colour-coded by channel (WhatsApp green `#25D366`, Telegram blue `#229ED9`, via a `conv-channel-*` left accent bar) and carrying the standard row kebab (Usage & cost, Reset/re-seat, Rename, Archive, Delete) so the operator can inspect and re-seat a channel session's params. Each row's `channel` is the authoritative `.meta.json` sidecar value (`whatsapp`/`telegram`/`webchat`/`browser`/null), not the JSONL-envelope channel. Each row also carries its sidecar `senderId`. For a WhatsApp/Telegram row with a `senderId` and no operator rename or ai-title (`titleSource:'prefix'`), the route resolves a contact `personName` and the sidebar renders the reader panel's `"<name> <number>"` label via the shared `operatorConvName`, degrading to the number alone then the stripped title on a miss. On a `whatsapp` row the number is printed in international form (`+44 7504 472444`, `+33 7 68 24 30 67`) by `formatSenderPhone` — `normalizeE164` then libphonenumber-js `formatInternational`, gated on `isPossible` so an unresolved LID prints raw; a `telegram` senderId is the sender half of that row's `<botId>:<senderId>` channel key (the route splits it; the sidecar stores the composite) and a `webchat` one is `session:<id>`, so neither is regrouped. The formatting is display-only: row identity, matching, and store keys stay on the normalized digits. Because the label function is shared, a Sessions row and that conversation's reader-panel row read identically. A channel row name has two sources, in precedence order. First the shared `resolveOperatorNamesBySender` helper the WhatsApp reader also calls, which matches the sender phone against the account's admins — that names an admin WhatsApp session and every Telegram session. Second, for a `whatsapp` row only, the WhatsApp pushName from the account's on-disk message store (`storePushNamesBySender` over `readConversationSummaries`, keyed by `normalizeE164` of the counterparty phone so a `+44 7…` sender matches a `447…` store key). The store is consulted only when the resolver reports **no binding** for that sender. That is typically a public WhatsApp customer, the case this exists for — such a sender has no admin record and so can only be named by the store, and without it those rows degraded to the bare number while the reader panel named them — though an admin missing from `users.json` qualifies too. A resolver miss caused by Neo4j being unreachable deliberately does NOT qualify: that is an outage rather than an absent binding, so the row degrades to the number and still logs `reason=neo4j-down`, keeping the outage signal intact. Telegram has no message store and is never looked up. The store read is guarded: a corrupt or absent store degrades to no pushName and logs `op=store-unreadable`, never 500s the list. Both sources are the ones the reader itself uses, so the two surfaces cannot drift; a renamed or ai-titled channel row keeps its own title. The Sessions list reads the viewed account's own store only. An account-manager's thread persists under the house account rather than the sub-account it manages, so on a multi-account install viewing a sub-account that row is not named here even though the reader panel names it — the reader additionally consults the house store, filtered to manager phones bound to that sub. The only role/channel excluded from the list is `public`+`webchat` (its dedicated reader is the sole surface); the exclusion predicate is `isSessionListExcluded`, decoupled from the reader's inclusion predicate `isReaderChannelSession` (unchanged), so the WhatsApp/Telegram reader panels are unaffected — a store-only WhatsApp conversation with no session JSONL stays reader-only. Observability rides `[admin-sessions-list] … channelInList=whatsapp:<n>,telegram:<n>,webchat:<n> channelNameCandidates=<n> channelNamesResolved=<n> (operator=<n> store=<n>) unknownChannel=<n> excludedPublicWebchat=<n>`, and each unresolved channel name logs one `[admin-sessions-list] op=channel-name-unresolved sessionId=<id8> channel=<whatsapp\|telegram> senderId=<id> reason=<no-senderId\|classify-miss\|neo4j-down>` line — emitted only when **both** sources miss, so a residual shortfall means a genuinely nameless sender rather than the expected public-customer floor, and the `operator=`/`store=` split says which source is carrying the names. | `GET /` |
3445
3445
  | `/session-delete` | POST `{ sessionId }`. Thin proxy over the manager: POST `/:id/stop` (idempotent) then DELETE `/:id`. Sends **no** accountId. The manager resolves the session by scanning every slug under `projects/` for its JSONL (`slugForExistingJsonl`, covering `archive/`), exactly as the sidebar list enumerates rows, and gates on file existence alone — so any session the operator can see is deletable. This replaces the earlier accountId-derived slug and the `!row` term, which narrowed resolution below the list and left a session under a non-house slug with no watcher row (e.g. a legacy `-home-admin` session on a single-account install) listed yet un-deletable. Account scope is a view filter, not a delete gate — admin access is install-wide, so there is nothing to scope against. The sibling `/session-stop` (the standalone End control) resolves identically and also forwards no accountId. | `POST /` |
3446
3446
  | `/session-rc-spawn` | POST `{ sessionId?, name?, title?, model?, effort? }`. Fire-and-forget `claude --remote-control [name] [--session-id <sid>]`. Present `sessionId` resumes; absent starts a fresh session (also used by the sidebar's "New session" button — it no longer opens claude.ai/code directly). Proxies to the manager's `/rc-spawn`, which waits up to **60 s** (raised from 12 s) for the spawned PTY to bind and returns `{ spawnedPid, sessionId, bridgeSessionId, slug, outcome, reason }`. For a webchat-bound spawn (every admin-gated host's "New session", returning a same-origin `/chat?session=<id>` target — `resolveRcSpawnOutcome` → `sameOrigin:true`) the Sidebar navigates the **current** tab via `window.location.assign`, replacing the dashboard in place (back returns to it); only a claude.ai/code slug (`sameOrigin:false`, the bare-admin resume bridge, never a new-session outcome) navigates a separately-opened tab. On `timeout` or `spawn-failed` it shows an error modal (reason + sessionId) and **never** opens a bare claude.ai/code tab. The new process registers itself as its own Remote Control entry in claude.ai/code. **Naming.** `title` is the operator's name for a NEW session, typed in the naming modal that gates all four New-session controls (sidebar CTA, composer popover, zero-sessions splash, Conversations flyout); nothing is POSTed until the operator confirms it, and the modal prefills `New session: <date, time>`. `resolveSpawnPlan` trims it, it never rides the manager spawn payload, and this route writes it to the user-title store through the manager's `POST /:id/rename` **before it answers**, so the client cannot navigate ahead of the write; the response gains `titleSource: 'user' \| 'none'`. A resume carries no title. A rejected or unreachable rename leaves the spawn intact and returns `'none'`. Lifeline: `[chat-spawn] op=title spawnReqId=… sessionId=… titleLen=… source=modal\|absent outcome=applied\|rejected\|failed`, where `source=absent` on a new spawn is the standing signal that a control bypassed the modal. | `POST /` |
3447
3447
  | `/claude-sessions` | **Spawn surface only**. `POST /` is the Sidebar new-session-with-prompt path, cookie-auth only (the recorder loopback caller was removed; LinkedIn ingest moved to `/rc-spawn`). The former UI-facing handlers (SSE row feed, list, resume, stop, rename, archive, delete, `/:id/meta`, `/:id/input`, `/:id/log`) were removed — the maxy dashboard no longer manages or displays sessions. | `POST /` |
@@ -3691,7 +3691,7 @@ destination is separate and equally required: `chooseDispatchMode` returns
3691
3691
  `{kind:'none'}` unless `agentChannel`, `agentDestination` and `agentPrompt` are
3692
3692
  all present, and a destination cannot be seeded because
3693
3693
  `validateAgentDestination` is fail-closed against the account's
3694
- `whatsapp.adminPhones` / `telegram.adminUsers`, both empty on a fresh install.
3694
+ `whatsapp.adminPhones` and the `adminUsers` of each entry in `telegram.bots[]`, all empty on a fresh install.
3695
3695
 
3696
3696
  The seed re-runs on every upgrade and never writes `eventStatus`,
3697
3697
  `agentChannel`, `agentDestination`, `recurrence` or `timezone` on a row that
@@ -9,6 +9,10 @@ Invoked by the admin agent directly.
9
9
 
10
10
  This is the platform's release timeline, newest first. Each entry shows the date it shipped and the version it shipped in, so you can tell the operator how current their install is. To compare, read the installed version from `capabilities-here` and match it against the versions below. Keep answers high level and in plain English; this is a summary, not a full commit log.
11
11
 
12
+ ## 2026-08-02 (0.1.551)
13
+
14
+ - You can now run as many Telegram bots as you like, each paired to its own agent, with its own access list, secret and conversations kept apart. Existing setups are converted automatically, the sidebar splits by bot, and a standing check reports each one.
15
+
12
16
  ## 2026-08-02 (0.1.550)
13
17
 
14
18
  - A Telegram conversation now starts with its channel attached, so the assistant can reply on it rather than the session coming up unable to answer.
@@ -56,7 +56,7 @@ either is a regression.
56
56
  |---|---|---|
57
57
  | `/session` | Admin cookie session: PIN-gated mint, validate, rotate. | `GET /`, `POST /` |
58
58
  | `/sessions` | Legacy admin-server conversation routes. No UI consumer remains after the ConversationsModal was retired; the surviving handlers are deletion candidates and not described here. | (legacy, no live caller) |
59
- | `/sidebar-sessions` | Sole data path for the sidebar Sessions list. One JSONL on disk equals one row. The row's delete button is the only way a row disappears. Each row carries `sessionId`, `title`, `startedAt`, `live`, `isSubagent`, `pid: number \| null` (basename of the matched `sessions/<pid>.json`), and `projectDir` (the directory holding the JSONL — consumed by the delete route). The payload also carries top-level `accountId` so the pane renders the full UUID label whose first ~8 chars prefix-match the truncated Remote Control daemon entry in claude.ai/code. The legacy `rcUrl` field is gone — the row's external-link affordance now POSTs `/session-rc-spawn` to start a fresh local `claude --remote-control <name> --session-id <sid>` PTY on every click. **WhatsApp and Telegram sessions (admin + public) appear in this list**, colour-coded by channel (WhatsApp green `#25D366`, Telegram blue `#229ED9`, via a `conv-channel-*` left accent bar) and carrying the standard row kebab (Usage & cost, Reset/re-seat, Rename, Archive, Delete) so the operator can inspect and re-seat a channel session's params. Each row's `channel` is the authoritative `.meta.json` sidecar value (`whatsapp`/`telegram`/`webchat`/`browser`/null), not the JSONL-envelope channel. Each row also carries its sidecar `senderId`. For a WhatsApp/Telegram row with a `senderId` and no operator rename or ai-title (`titleSource:'prefix'`), the route resolves a contact `personName` and the sidebar renders the reader panel's `"<name> <number>"` label via the shared `operatorConvName`, degrading to the number alone then the stripped title on a miss. On a `whatsapp` row the number is printed in international form (`+44 7504 472444`, `+33 7 68 24 30 67`) by `formatSenderPhone` — `normalizeE164` then libphonenumber-js `formatInternational`, gated on `isPossible` so an unresolved LID prints raw; a `telegram` senderId is a Telegram user id and a `webchat` one is `session:<id>`, so neither is regrouped. The formatting is display-only: row identity, matching, and store keys stay on the normalized digits. Because the label function is shared, a Sessions row and that conversation's reader-panel row read identically. A channel row name has two sources, in precedence order. First the shared `resolveOperatorNamesBySender` helper the WhatsApp reader also calls, which matches the sender phone against the account's admins — that names an admin WhatsApp session and every Telegram session. Second, for a `whatsapp` row only, the WhatsApp pushName from the account's on-disk message store (`storePushNamesBySender` over `readConversationSummaries`, keyed by `normalizeE164` of the counterparty phone so a `+44 7…` sender matches a `447…` store key). The store is consulted only when the resolver reports **no binding** for that sender. That is typically a public WhatsApp customer, the case this exists for — such a sender has no admin record and so can only be named by the store, and without it those rows degraded to the bare number while the reader panel named them — though an admin missing from `users.json` qualifies too. A resolver miss caused by Neo4j being unreachable deliberately does NOT qualify: that is an outage rather than an absent binding, so the row degrades to the number and still logs `reason=neo4j-down`, keeping the outage signal intact. Telegram has no message store and is never looked up. The store read is guarded: a corrupt or absent store degrades to no pushName and logs `op=store-unreadable`, never 500s the list. Both sources are the ones the reader itself uses, so the two surfaces cannot drift; a renamed or ai-titled channel row keeps its own title. The Sessions list reads the viewed account's own store only. An account-manager's thread persists under the house account rather than the sub-account it manages, so on a multi-account install viewing a sub-account that row is not named here even though the reader panel names it — the reader additionally consults the house store, filtered to manager phones bound to that sub. The only role/channel excluded from the list is `public`+`webchat` (its dedicated reader is the sole surface); the exclusion predicate is `isSessionListExcluded`, decoupled from the reader's inclusion predicate `isReaderChannelSession` (unchanged), so the WhatsApp/Telegram reader panels are unaffected — a store-only WhatsApp conversation with no session JSONL stays reader-only. Observability rides `[admin-sessions-list] … channelInList=whatsapp:<n>,telegram:<n>,webchat:<n> channelNameCandidates=<n> channelNamesResolved=<n> (operator=<n> store=<n>) unknownChannel=<n> excludedPublicWebchat=<n>`, and each unresolved channel name logs one `[admin-sessions-list] op=channel-name-unresolved sessionId=<id8> channel=<whatsapp\|telegram> senderId=<id> reason=<no-senderId\|classify-miss\|neo4j-down>` line — emitted only when **both** sources miss, so a residual shortfall means a genuinely nameless sender rather than the expected public-customer floor, and the `operator=`/`store=` split says which source is carrying the names. | `GET /` |
59
+ | `/sidebar-sessions` | Sole data path for the sidebar Sessions list. One JSONL on disk equals one row. The row's delete button is the only way a row disappears. Each row carries `sessionId`, `title`, `startedAt`, `live`, `isSubagent`, `pid: number \| null` (basename of the matched `sessions/<pid>.json`), and `projectDir` (the directory holding the JSONL — consumed by the delete route). The payload also carries top-level `accountId` so the pane renders the full UUID label whose first ~8 chars prefix-match the truncated Remote Control daemon entry in claude.ai/code. The legacy `rcUrl` field is gone — the row's external-link affordance now POSTs `/session-rc-spawn` to start a fresh local `claude --remote-control <name> --session-id <sid>` PTY on every click. **WhatsApp and Telegram sessions (admin + public) appear in this list**, colour-coded by channel (WhatsApp green `#25D366`, Telegram blue `#229ED9`, via a `conv-channel-*` left accent bar) and carrying the standard row kebab (Usage & cost, Reset/re-seat, Rename, Archive, Delete) so the operator can inspect and re-seat a channel session's params. Each row's `channel` is the authoritative `.meta.json` sidecar value (`whatsapp`/`telegram`/`webchat`/`browser`/null), not the JSONL-envelope channel. Each row also carries its sidecar `senderId`. For a WhatsApp/Telegram row with a `senderId` and no operator rename or ai-title (`titleSource:'prefix'`), the route resolves a contact `personName` and the sidebar renders the reader panel's `"<name> <number>"` label via the shared `operatorConvName`, degrading to the number alone then the stripped title on a miss. On a `whatsapp` row the number is printed in international form (`+44 7504 472444`, `+33 7 68 24 30 67`) by `formatSenderPhone` — `normalizeE164` then libphonenumber-js `formatInternational`, gated on `isPossible` so an unresolved LID prints raw; a `telegram` senderId is the sender half of that row's `<botId>:<senderId>` channel key (the route splits it; the sidecar stores the composite) and a `webchat` one is `session:<id>`, so neither is regrouped. The formatting is display-only: row identity, matching, and store keys stay on the normalized digits. Because the label function is shared, a Sessions row and that conversation's reader-panel row read identically. A channel row name has two sources, in precedence order. First the shared `resolveOperatorNamesBySender` helper the WhatsApp reader also calls, which matches the sender phone against the account's admins — that names an admin WhatsApp session and every Telegram session. Second, for a `whatsapp` row only, the WhatsApp pushName from the account's on-disk message store (`storePushNamesBySender` over `readConversationSummaries`, keyed by `normalizeE164` of the counterparty phone so a `+44 7…` sender matches a `447…` store key). The store is consulted only when the resolver reports **no binding** for that sender. That is typically a public WhatsApp customer, the case this exists for — such a sender has no admin record and so can only be named by the store, and without it those rows degraded to the bare number while the reader panel named them — though an admin missing from `users.json` qualifies too. A resolver miss caused by Neo4j being unreachable deliberately does NOT qualify: that is an outage rather than an absent binding, so the row degrades to the number and still logs `reason=neo4j-down`, keeping the outage signal intact. Telegram has no message store and is never looked up. The store read is guarded: a corrupt or absent store degrades to no pushName and logs `op=store-unreadable`, never 500s the list. Both sources are the ones the reader itself uses, so the two surfaces cannot drift; a renamed or ai-titled channel row keeps its own title. The Sessions list reads the viewed account's own store only. An account-manager's thread persists under the house account rather than the sub-account it manages, so on a multi-account install viewing a sub-account that row is not named here even though the reader panel names it — the reader additionally consults the house store, filtered to manager phones bound to that sub. The only role/channel excluded from the list is `public`+`webchat` (its dedicated reader is the sole surface); the exclusion predicate is `isSessionListExcluded`, decoupled from the reader's inclusion predicate `isReaderChannelSession` (unchanged), so the WhatsApp/Telegram reader panels are unaffected — a store-only WhatsApp conversation with no session JSONL stays reader-only. Observability rides `[admin-sessions-list] … channelInList=whatsapp:<n>,telegram:<n>,webchat:<n> channelNameCandidates=<n> channelNamesResolved=<n> (operator=<n> store=<n>) unknownChannel=<n> excludedPublicWebchat=<n>`, and each unresolved channel name logs one `[admin-sessions-list] op=channel-name-unresolved sessionId=<id8> channel=<whatsapp\|telegram> senderId=<id> reason=<no-senderId\|classify-miss\|neo4j-down>` line — emitted only when **both** sources miss, so a residual shortfall means a genuinely nameless sender rather than the expected public-customer floor, and the `operator=`/`store=` split says which source is carrying the names. | `GET /` |
60
60
  | `/session-delete` | POST `{ sessionId }`. Thin proxy over the manager: POST `/:id/stop` (idempotent) then DELETE `/:id`. Sends **no** accountId. The manager resolves the session by scanning every slug under `projects/` for its JSONL (`slugForExistingJsonl`, covering `archive/`), exactly as the sidebar list enumerates rows, and gates on file existence alone — so any session the operator can see is deletable. This replaces the earlier accountId-derived slug and the `!row` term, which narrowed resolution below the list and left a session under a non-house slug with no watcher row (e.g. a legacy `-home-admin` session on a single-account install) listed yet un-deletable. Account scope is a view filter, not a delete gate — admin access is install-wide, so there is nothing to scope against. The sibling `/session-stop` (the standalone End control) resolves identically and also forwards no accountId. | `POST /` |
61
61
  | `/session-rc-spawn` | POST `{ sessionId?, name?, title?, model?, effort? }`. Fire-and-forget `claude --remote-control [name] [--session-id <sid>]`. Present `sessionId` resumes; absent starts a fresh session (also used by the sidebar's "New session" button — it no longer opens claude.ai/code directly). Proxies to the manager's `/rc-spawn`, which waits up to **60 s** (raised from 12 s) for the spawned PTY to bind and returns `{ spawnedPid, sessionId, bridgeSessionId, slug, outcome, reason }`. For a webchat-bound spawn (every admin-gated host's "New session", returning a same-origin `/chat?session=<id>` target — `resolveRcSpawnOutcome` → `sameOrigin:true`) the Sidebar navigates the **current** tab via `window.location.assign`, replacing the dashboard in place (back returns to it); only a claude.ai/code slug (`sameOrigin:false`, the bare-admin resume bridge, never a new-session outcome) navigates a separately-opened tab. On `timeout` or `spawn-failed` it shows an error modal (reason + sessionId) and **never** opens a bare claude.ai/code tab. The new process registers itself as its own Remote Control entry in claude.ai/code. **Naming.** `title` is the operator's name for a NEW session, typed in the naming modal that gates all four New-session controls (sidebar CTA, composer popover, zero-sessions splash, Conversations flyout); nothing is POSTed until the operator confirms it, and the modal prefills `New session: <date, time>`. `resolveSpawnPlan` trims it, it never rides the manager spawn payload, and this route writes it to the user-title store through the manager's `POST /:id/rename` **before it answers**, so the client cannot navigate ahead of the write; the response gains `titleSource: 'user' \| 'none'`. A resume carries no title. A rejected or unreachable rename leaves the spawn intact and returns `'none'`. Lifeline: `[chat-spawn] op=title spawnReqId=… sessionId=… titleLen=… source=modal\|absent outcome=applied\|rejected\|failed`, where `source=absent` on a new spawn is the standing signal that a control bypassed the modal. | `POST /` |
62
62
  | `/claude-sessions` | **Spawn surface only**. `POST /` is the Sidebar new-session-with-prompt path, cookie-auth only (the recorder loopback caller was removed; LinkedIn ingest moved to `/rc-spawn`). The former UI-facing handlers (SSE row feed, list, resume, stop, rename, archive, delete, `/:id/meta`, `/:id/input`, `/:id/log`) were removed — the maxy dashboard no longer manages or displays sessions. | `POST /` |
@@ -306,7 +306,7 @@ destination is separate and equally required: `chooseDispatchMode` returns
306
306
  `{kind:'none'}` unless `agentChannel`, `agentDestination` and `agentPrompt` are
307
307
  all present, and a destination cannot be seeded because
308
308
  `validateAgentDestination` is fail-closed against the account's
309
- `whatsapp.adminPhones` / `telegram.adminUsers`, both empty on a fresh install.
309
+ `whatsapp.adminPhones` and the `adminUsers` of each entry in `telegram.bots[]`, all empty on a fresh install.
310
310
 
311
311
  The seed re-runs on every upgrade and never writes `eventStatus`,
312
312
  `agentChannel`, `agentDestination`, `recurrence` or `timezone` on a row that
@@ -126,12 +126,12 @@ describe("validateAgentDestination — telegram unchanged (creating-account dir,
126
126
  dirs = [];
127
127
  });
128
128
  it("accepts a chat id in the creating account's telegram.adminUsers", () => {
129
- const acc = makeAccountsDir((a) => seedAccount(a, HOUSE, { role: "house", telegram: { adminUsers: [12345678] } }));
129
+ const acc = makeAccountsDir((a) => seedAccount(a, HOUSE, { role: "house", telegram: { bots: [{ id: "111", token: "111:A", role: "admin", adminUsers: [12345678] }] } }));
130
130
  dirs.push(acc);
131
131
  expect(validateAgentDestination(acc, HOUSE, "telegram", "12345678")).toEqual({ valid: true });
132
132
  });
133
133
  it("rejects a chat id absent from adminUsers as not-registered", () => {
134
- const acc = makeAccountsDir((a) => seedAccount(a, HOUSE, { role: "house", telegram: { adminUsers: [12345678] } }));
134
+ const acc = makeAccountsDir((a) => seedAccount(a, HOUSE, { role: "house", telegram: { bots: [{ id: "111", token: "111:A", role: "admin", adminUsers: [12345678] }] } }));
135
135
  dirs.push(acc);
136
136
  expect(validateAgentDestination(acc, HOUSE, "telegram", "99999999")).toEqual({
137
137
  valid: false,
@@ -1 +1 @@
1
- {"version":3,"file":"agent-dispatch.test.js","sourceRoot":"","sources":["../../../src/lib/__tests__/agent-dispatch.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"agent-dispatch.test.js","sourceRoot":"","sources":["../../../src/lib/__tests__/agent-dispatch.test.ts"],"names":[],"mappings":"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"}