@spinabot/brigade 1.1.0 → 1.2.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.
Files changed (139) hide show
  1. package/convex/channels.d.ts +5 -5
  2. package/convex/schema.d.ts +2 -2
  3. package/dist/agents/agent-loop.d.ts.map +1 -1
  4. package/dist/agents/agent-loop.js +27 -4
  5. package/dist/agents/agent-loop.js.map +1 -1
  6. package/dist/agents/channels/approval-callback-codec.d.ts +107 -0
  7. package/dist/agents/channels/approval-callback-codec.d.ts.map +1 -0
  8. package/dist/agents/channels/approval-callback-codec.js +173 -0
  9. package/dist/agents/channels/approval-callback-codec.js.map +1 -0
  10. package/dist/agents/channels/approval-router.d.ts +77 -20
  11. package/dist/agents/channels/approval-router.d.ts.map +1 -1
  12. package/dist/agents/channels/approval-router.js +163 -37
  13. package/dist/agents/channels/approval-router.js.map +1 -1
  14. package/dist/agents/channels/backoff.d.ts +55 -0
  15. package/dist/agents/channels/backoff.d.ts.map +1 -0
  16. package/dist/agents/channels/backoff.js +47 -0
  17. package/dist/agents/channels/backoff.js.map +1 -0
  18. package/dist/agents/channels/channel-secrets.d.ts +45 -0
  19. package/dist/agents/channels/channel-secrets.d.ts.map +1 -0
  20. package/dist/agents/channels/channel-secrets.js +69 -0
  21. package/dist/agents/channels/channel-secrets.js.map +1 -0
  22. package/dist/agents/channels/inbound-pipeline.d.ts.map +1 -1
  23. package/dist/agents/channels/inbound-pipeline.js +67 -3
  24. package/dist/agents/channels/inbound-pipeline.js.map +1 -1
  25. package/dist/agents/channels/last-sent-message.d.ts +46 -0
  26. package/dist/agents/channels/last-sent-message.d.ts.map +1 -0
  27. package/dist/agents/channels/last-sent-message.js +55 -0
  28. package/dist/agents/channels/last-sent-message.js.map +1 -0
  29. package/dist/agents/channels/manager.d.ts +52 -0
  30. package/dist/agents/channels/manager.d.ts.map +1 -1
  31. package/dist/agents/channels/manager.js +141 -31
  32. package/dist/agents/channels/manager.js.map +1 -1
  33. package/dist/agents/channels/plugin-channel-manager-facade.d.ts +13 -2
  34. package/dist/agents/channels/plugin-channel-manager-facade.d.ts.map +1 -1
  35. package/dist/agents/channels/plugin-channel-manager-facade.js +21 -0
  36. package/dist/agents/channels/plugin-channel-manager-facade.js.map +1 -1
  37. package/dist/agents/channels/sdk.d.ts +426 -0
  38. package/dist/agents/channels/sdk.d.ts.map +1 -0
  39. package/dist/agents/channels/sdk.js +274 -0
  40. package/dist/agents/channels/sdk.js.map +1 -0
  41. package/dist/agents/channels/telegram/account-config.d.ts +92 -0
  42. package/dist/agents/channels/telegram/account-config.d.ts.map +1 -0
  43. package/dist/agents/channels/telegram/account-config.js +192 -0
  44. package/dist/agents/channels/telegram/account-config.js.map +1 -0
  45. package/dist/agents/channels/telegram/adapter.d.ts +79 -0
  46. package/dist/agents/channels/telegram/adapter.d.ts.map +1 -0
  47. package/dist/agents/channels/telegram/adapter.js +475 -0
  48. package/dist/agents/channels/telegram/adapter.js.map +1 -0
  49. package/dist/agents/channels/telegram/allowed-updates.d.ts +44 -0
  50. package/dist/agents/channels/telegram/allowed-updates.d.ts.map +1 -0
  51. package/dist/agents/channels/telegram/allowed-updates.js +52 -0
  52. package/dist/agents/channels/telegram/allowed-updates.js.map +1 -0
  53. package/dist/agents/channels/telegram/approval-authorize.d.ts +41 -0
  54. package/dist/agents/channels/telegram/approval-authorize.d.ts.map +1 -0
  55. package/dist/agents/channels/telegram/approval-authorize.js +69 -0
  56. package/dist/agents/channels/telegram/approval-authorize.js.map +1 -0
  57. package/dist/agents/channels/telegram/approval-native.d.ts +68 -0
  58. package/dist/agents/channels/telegram/approval-native.d.ts.map +1 -0
  59. package/dist/agents/channels/telegram/approval-native.js +94 -0
  60. package/dist/agents/channels/telegram/approval-native.js.map +1 -0
  61. package/dist/agents/channels/telegram/command-menu.d.ts +35 -0
  62. package/dist/agents/channels/telegram/command-menu.d.ts.map +1 -0
  63. package/dist/agents/channels/telegram/command-menu.js +59 -0
  64. package/dist/agents/channels/telegram/command-menu.js.map +1 -0
  65. package/dist/agents/channels/telegram/connection.d.ts +359 -0
  66. package/dist/agents/channels/telegram/connection.d.ts.map +1 -0
  67. package/dist/agents/channels/telegram/connection.js +865 -0
  68. package/dist/agents/channels/telegram/connection.js.map +1 -0
  69. package/dist/agents/channels/telegram/format.d.ts +48 -0
  70. package/dist/agents/channels/telegram/format.d.ts.map +1 -0
  71. package/dist/agents/channels/telegram/format.js +256 -0
  72. package/dist/agents/channels/telegram/format.js.map +1 -0
  73. package/dist/agents/channels/telegram/inbound-extras.d.ts +73 -0
  74. package/dist/agents/channels/telegram/inbound-extras.d.ts.map +1 -0
  75. package/dist/agents/channels/telegram/inbound-extras.js +231 -0
  76. package/dist/agents/channels/telegram/inbound-extras.js.map +1 -0
  77. package/dist/agents/channels/telegram/index.d.ts +14 -0
  78. package/dist/agents/channels/telegram/index.d.ts.map +1 -0
  79. package/dist/agents/channels/telegram/index.js +14 -0
  80. package/dist/agents/channels/telegram/index.js.map +1 -0
  81. package/dist/agents/channels/telegram/media.d.ts +68 -0
  82. package/dist/agents/channels/telegram/media.d.ts.map +1 -0
  83. package/dist/agents/channels/telegram/media.js +143 -0
  84. package/dist/agents/channels/telegram/media.js.map +1 -0
  85. package/dist/agents/channels/telegram/module.d.ts +15 -0
  86. package/dist/agents/channels/telegram/module.d.ts.map +1 -0
  87. package/dist/agents/channels/telegram/module.js +36 -0
  88. package/dist/agents/channels/telegram/module.js.map +1 -0
  89. package/dist/agents/channels/telegram/plugin.d.ts +76 -0
  90. package/dist/agents/channels/telegram/plugin.d.ts.map +1 -0
  91. package/dist/agents/channels/telegram/plugin.js +314 -0
  92. package/dist/agents/channels/telegram/plugin.js.map +1 -0
  93. package/dist/agents/channels/telegram/probe.d.ts +54 -0
  94. package/dist/agents/channels/telegram/probe.d.ts.map +1 -0
  95. package/dist/agents/channels/telegram/probe.js +95 -0
  96. package/dist/agents/channels/telegram/probe.js.map +1 -0
  97. package/dist/agents/channels/telegram/webhook.d.ts +55 -0
  98. package/dist/agents/channels/telegram/webhook.d.ts.map +1 -0
  99. package/dist/agents/channels/telegram/webhook.js +141 -0
  100. package/dist/agents/channels/telegram/webhook.js.map +1 -0
  101. package/dist/agents/extensions/modules/index.d.ts.map +1 -1
  102. package/dist/agents/extensions/modules/index.js +4 -0
  103. package/dist/agents/extensions/modules/index.js.map +1 -1
  104. package/dist/agents/extensions/types.d.ts +72 -2
  105. package/dist/agents/extensions/types.d.ts.map +1 -1
  106. package/dist/agents/extensions/types.js.map +1 -1
  107. package/dist/agents/tools/connect-channel-tool.d.ts +86 -0
  108. package/dist/agents/tools/connect-channel-tool.d.ts.map +1 -0
  109. package/dist/agents/tools/connect-channel-tool.js +398 -0
  110. package/dist/agents/tools/connect-channel-tool.js.map +1 -0
  111. package/dist/agents/tools/message-action-tool.d.ts +67 -0
  112. package/dist/agents/tools/message-action-tool.d.ts.map +1 -0
  113. package/dist/agents/tools/message-action-tool.js +216 -0
  114. package/dist/agents/tools/message-action-tool.js.map +1 -0
  115. package/dist/agents/tools/registry.d.ts.map +1 -1
  116. package/dist/agents/tools/registry.js +19 -0
  117. package/dist/agents/tools/registry.js.map +1 -1
  118. package/dist/buildstamp.json +1 -1
  119. package/dist/cli/commands/channels.d.ts.map +1 -1
  120. package/dist/cli/commands/channels.js +27 -2
  121. package/dist/cli/commands/channels.js.map +1 -1
  122. package/dist/core/server.d.ts.map +1 -1
  123. package/dist/core/server.js +77 -27
  124. package/dist/core/server.js.map +1 -1
  125. package/dist/cron/service/state.d.ts +10 -0
  126. package/dist/cron/service/state.d.ts.map +1 -1
  127. package/dist/cron/service/state.js.map +1 -1
  128. package/dist/cron/service/timer.d.ts.map +1 -1
  129. package/dist/cron/service/timer.js +43 -14
  130. package/dist/cron/service/timer.js.map +1 -1
  131. package/dist/cron/session-reaper.d.ts +27 -0
  132. package/dist/cron/session-reaper.d.ts.map +1 -1
  133. package/dist/cron/session-reaper.js +81 -0
  134. package/dist/cron/session-reaper.js.map +1 -1
  135. package/dist/system-prompt/assembler.d.ts +14 -0
  136. package/dist/system-prompt/assembler.d.ts.map +1 -1
  137. package/dist/system-prompt/assembler.js +36 -14
  138. package/dist/system-prompt/assembler.js.map +1 -1
  139. package/package.json +16 -3
@@ -48,6 +48,8 @@ import { startChannels } from "../agents/channels/manager.js";
48
48
  import { createChannelPluginManager, } from "../agents/channels/channel-plugin-manager.js";
49
49
  import { listWhatsAppAccountIds, whatsappChannelEnabled } from "../agents/channels/whatsapp/account-config.js";
50
50
  import { createWhatsAppPlugin } from "../agents/channels/whatsapp/plugin.js";
51
+ import { listTelegramAccountIds, telegramChannelEnabled, telegramThreadIdleTtlMs, } from "../agents/channels/telegram/account-config.js";
52
+ import { createTelegramPlugin } from "../agents/channels/telegram/plugin.js";
51
53
  import { createPluginChannelManagerFacade } from "../agents/channels/plugin-channel-manager-facade.js";
52
54
  import { makeOpQueue, withTimeout } from "./extension-lifecycle.js";
53
55
  import { resolveModelNeverMiss } from "../agents/model-resolution.js";
@@ -1696,6 +1698,22 @@ async function continueBoot(args) {
1696
1698
  * check" rather than blocking ALL cron adds.
1697
1699
  */
1698
1700
  listKnownChannelIds: () => channelManager?.started ?? [],
1701
+ /**
1702
+ * Idle channel-thread TTL for the session-reaper's thread sweep — read
1703
+ * live from `channels.telegram.threadIdleTtlMs` so an idle Telegram
1704
+ * forum-topic session gets aged out. `null` (default / unset) leaves
1705
+ * thread sessions untouched; the isolated-cron-run reaper is unaffected.
1706
+ */
1707
+ resolveThreadIdleTtlMs: () => {
1708
+ try {
1709
+ // `loadConfig` is synchronous + cheap; reading fresh keeps the TTL
1710
+ // live across config reloads without threading a mutable holder.
1711
+ return telegramThreadIdleTtlMs(loadConfig());
1712
+ }
1713
+ catch {
1714
+ return null;
1715
+ }
1716
+ },
1699
1717
  /**
1700
1718
  * Heartbeat trigger for `wakeMode: "now"` crons. Fires a synthetic
1701
1719
  * agent turn on the operator's main session that drains any
@@ -4512,6 +4530,16 @@ async function continueBoot(args) {
4512
4530
  httpRoutes = [...registry.httpRoutes];
4513
4531
  // Channels — inbound runs through the SAME serialized turn queue as TUI
4514
4532
  // prompts (`runGatewayTurn`), so a channel turn never overlaps a TUI turn.
4533
+ //
4534
+ // The manager is mounted UNCONDITIONALLY (even when zero channels are
4535
+ // configured at boot) so the owner-gated `connect_channel` tool can
4536
+ // start the FIRST channel LIVE via `getActiveChannelManager().startChannel(id)`
4537
+ // without a gateway restart. The manager captures the FULL adapter
4538
+ // catalog (`registry.channels`), so a channel that isn't started at boot
4539
+ // is still reachable for a later live start. Bundled modules guarantee
4540
+ // `registry.channels` is non-empty in normal installs; the guard stays
4541
+ // only so a build that trims every channel module doesn't construct an
4542
+ // empty manager.
4515
4543
  if (registry.channels.length > 0) {
4516
4544
  channelManager = await startChannels({
4517
4545
  adapters: registry.channels,
@@ -4528,10 +4556,11 @@ async function continueBoot(args) {
4528
4556
  },
4529
4557
  });
4530
4558
  // Mount the channel manager as a process-wide singleton so the
4531
- // `send_message` agent tool (+ future channel-action tools) can
4532
- // reach the started adapters. Without this the tool registry's
4533
- // `getActiveChannelManager()` returns null and `send_message`
4534
- // quietly stays out of the surface.
4559
+ // `send_message` + `connect_channel` agent tools (+ future
4560
+ // channel-action tools) can reach the started adapters AND start /
4561
+ // stop a single channel live. Without this the tool registry's
4562
+ // `getActiveChannelManager()` returns null and those tools quietly
4563
+ // stay out of the surface (or can't perform a live connect).
4535
4564
  setActiveChannelManager(channelManager);
4536
4565
  if (channelManager.started.length > 0)
4537
4566
  bootLog(`channels: ${channelManager.started.join(", ")}`);
@@ -4544,21 +4573,43 @@ async function continueBoot(args) {
4544
4573
  const whatsappAccounts = whatsappChannelEnabled(cfg)
4545
4574
  ? listWhatsAppAccountIds(cfg)
4546
4575
  : [];
4547
- const wantMultiAccount = whatsappAccounts.length > 1;
4548
- if (wantMultiAccount) {
4549
- const whatsappPlugin = createWhatsAppPlugin({
4550
- defaultAgentId: agentId,
4551
- loadConfig: () => cfg,
4552
- runTurn: (turn) => runGatewayTurn(turn),
4553
- onPairing: (channelId, accountId, info) => {
4554
- const line = info.kind === "qr"
4555
- ? `[${channelId}/${accountId}] scan the QR code shown in the gateway logs to link your account`
4556
- : `[${channelId}/${accountId}] pairing code: ${info.value}`;
4557
- bootLog(line);
4558
- broadcast("log", { level: "info", message: line, at: Date.now() });
4559
- },
4560
- });
4561
- bundledChannelPlugins = [whatsappPlugin];
4576
+ const telegramAccounts = telegramChannelEnabled(cfg)
4577
+ ? listTelegramAccountIds(cfg)
4578
+ : [];
4579
+ const wantWhatsAppMulti = whatsappAccounts.length > 1;
4580
+ const wantTelegramMulti = telegramAccounts.length > 1;
4581
+ if (wantWhatsAppMulti || wantTelegramMulti) {
4582
+ // Fresh list each (re)start so a reload doesn't accumulate stale plugins.
4583
+ bundledChannelPlugins = [];
4584
+ const facadeHandles = [];
4585
+ const multiAccountSummary = [];
4586
+ if (wantWhatsAppMulti) {
4587
+ const whatsappPlugin = createWhatsAppPlugin({
4588
+ defaultAgentId: agentId,
4589
+ loadConfig: () => cfg,
4590
+ runTurn: (turn) => runGatewayTurn(turn),
4591
+ onPairing: (channelId, accountId, info) => {
4592
+ const line = info.kind === "qr"
4593
+ ? `[${channelId}/${accountId}] scan the QR code shown in the gateway logs to link your account`
4594
+ : `[${channelId}/${accountId}] pairing code: ${info.value}`;
4595
+ bootLog(line);
4596
+ broadcast("log", { level: "info", message: line, at: Date.now() });
4597
+ },
4598
+ });
4599
+ bundledChannelPlugins.push(whatsappPlugin);
4600
+ facadeHandles.push(whatsappPlugin);
4601
+ multiAccountSummary.push(`whatsapp x${whatsappAccounts.length}`);
4602
+ }
4603
+ if (wantTelegramMulti) {
4604
+ const telegramPlugin = createTelegramPlugin({
4605
+ defaultAgentId: agentId,
4606
+ loadConfig: () => cfg,
4607
+ runTurn: (turn) => runGatewayTurn(turn),
4608
+ });
4609
+ bundledChannelPlugins.push(telegramPlugin);
4610
+ facadeHandles.push(telegramPlugin);
4611
+ multiAccountSummary.push(`telegram x${telegramAccounts.length}`);
4612
+ }
4562
4613
  const pluginById = new Map(bundledChannelPlugins.map((p) => [p.id, p]));
4563
4614
  channelPluginManager = createChannelPluginManager({
4564
4615
  loadConfig: () => cfg,
@@ -4566,16 +4617,15 @@ async function continueBoot(args) {
4566
4617
  getChannelPlugin: (id) => pluginById.get(id),
4567
4618
  });
4568
4619
  await channelPluginManager.startChannels();
4569
- // Mount a thin manager facade so the `send_message` agent tool's
4570
- // `getActiveChannelManager().adapter("whatsapp")` lookup returns a
4571
- // working per-account adapter on multi-account installs. Without
4572
- // this the tool quietly hid from the surface because the legacy
4573
- // `startChannels` manager only runs when there's <= 1 account.
4574
- const whatsappHandles = [whatsappPlugin];
4620
+ // Mount a thin manager facade so the `send_message` + `message_action`
4621
+ // agent tools' `getActiveChannelManager().adapter(id)` lookup returns a
4622
+ // working per-account adapter on multi-account installs. Without this
4623
+ // those tools quietly hid because the legacy `startChannels` manager
4624
+ // only runs when there's <= 1 account per channel.
4575
4625
  if (!channelManager) {
4576
- setActiveChannelManager(createPluginChannelManagerFacade({ plugins: whatsappHandles }));
4626
+ setActiveChannelManager(createPluginChannelManagerFacade({ plugins: facadeHandles }));
4577
4627
  }
4578
- bootLog(`channels (multi-account): whatsapp x${whatsappAccounts.length}`);
4628
+ bootLog(`channels (multi-account): ${multiAccountSummary.join(", ")}`);
4579
4629
  }
4580
4630
  // Background services — start each; a failing one is skipped, not fatal.
4581
4631
  if (registry.services.length > 0) {