@poolzin/pool-bot 2026.3.25 → 2026.3.26

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 (271) hide show
  1. package/dist/agents/model-fallback.js +5 -4
  2. package/dist/agents/tools/common.js +16 -201
  3. package/dist/auto-reply/auto-reply/reply/agent-runner-execution.js +502 -0
  4. package/dist/auto-reply/auto-reply/reply/agent-runner-helpers.js +65 -0
  5. package/dist/auto-reply/auto-reply/reply/agent-runner-memory.js +160 -0
  6. package/dist/auto-reply/auto-reply/reply/agent-runner-payloads.js +85 -0
  7. package/dist/auto-reply/auto-reply/reply/agent-runner-utils.js +101 -0
  8. package/dist/auto-reply/auto-reply/reply/bash-command.js +338 -0
  9. package/dist/auto-reply/auto-reply/reply/block-streaming.js +91 -0
  10. package/dist/auto-reply/auto-reply/reply/commands-approve.js +88 -0
  11. package/dist/auto-reply/auto-reply/reply/commands-bash.js +26 -0
  12. package/dist/auto-reply/auto-reply/reply/commands-compact.js +107 -0
  13. package/dist/auto-reply/auto-reply/reply/commands-config.js +241 -0
  14. package/dist/auto-reply/auto-reply/reply/commands-context-report.js +295 -0
  15. package/dist/auto-reply/auto-reply/reply/commands-context.js +30 -0
  16. package/dist/auto-reply/auto-reply/reply/commands-core.js +151 -0
  17. package/dist/auto-reply/auto-reply/reply/commands-export-session.js +163 -0
  18. package/dist/auto-reply/auto-reply/reply/commands-info.js +184 -0
  19. package/dist/auto-reply/auto-reply/reply/commands-models.js +299 -0
  20. package/dist/auto-reply/auto-reply/reply/commands-plugin.js +35 -0
  21. package/dist/auto-reply/auto-reply/reply/commands-ptt.js +171 -0
  22. package/dist/auto-reply/auto-reply/reply/commands-setunset-standard.js +13 -0
  23. package/dist/auto-reply/auto-reply/reply/commands-setunset.js +73 -0
  24. package/dist/auto-reply/auto-reply/reply/commands-slash-parse.js +31 -0
  25. package/dist/auto-reply/auto-reply/reply/commands-status.js +178 -0
  26. package/dist/auto-reply/auto-reply/reply/commands-subagents.js +73 -0
  27. package/dist/auto-reply/auto-reply/reply/commands-system-prompt.js +117 -0
  28. package/dist/auto-reply/auto-reply/reply/commands-tts.js +231 -0
  29. package/dist/auto-reply/auto-reply/reply/directive-handling.impl.js +380 -0
  30. package/dist/auto-reply/auto-reply/reply/followup-runner.js +227 -0
  31. package/dist/auto-reply/auto-reply/reply/get-reply-directives-apply.js +201 -0
  32. package/dist/auto-reply/auto-reply/reply/get-reply-directives-utils.js +54 -0
  33. package/dist/auto-reply/auto-reply/reply/get-reply-directives.js +332 -0
  34. package/dist/auto-reply/auto-reply/reply/get-reply-inline-actions.js +258 -0
  35. package/dist/auto-reply/auto-reply/reply/get-reply-run.js +297 -0
  36. package/dist/auto-reply/auto-reply/reply/groups.js +102 -0
  37. package/dist/auto-reply/auto-reply/reply/mentions.js +129 -0
  38. package/dist/auto-reply/auto-reply/reply/reply-delivery.js +92 -0
  39. package/dist/auto-reply/auto-reply/reply/reply-directives.js +30 -0
  40. package/dist/auto-reply/auto-reply/reply/reply-dispatcher.js +152 -0
  41. package/dist/auto-reply/auto-reply/reply/reply-elevated.js +166 -0
  42. package/dist/auto-reply/auto-reply/reply/reply-inline.js +28 -0
  43. package/dist/auto-reply/auto-reply/reply/reply-payloads.js +114 -0
  44. package/dist/auto-reply/auto-reply/reply/reply-reference.js +36 -0
  45. package/dist/auto-reply/auto-reply/reply/reply-tags.js +13 -0
  46. package/dist/auto-reply/auto-reply/reply/reply-threading.js +41 -0
  47. package/dist/auto-reply/auto-reply/reply/session-updates.js +233 -0
  48. package/dist/auto-reply/auto-reply/reply/stage-sandbox-media.js +146 -0
  49. package/dist/build-info.json +3 -3
  50. package/dist/canvas-host/a2ui/.bundle.hash +1 -1
  51. package/dist/canvas-host/a2ui/a2ui.bundle.js +2 -17772
  52. package/dist/canvas-host/a2ui/index.html +1 -307
  53. package/dist/channels/channels/directory-config.js +185 -0
  54. package/dist/channels/channels/discord/handle-action.guild-admin.js +332 -0
  55. package/dist/channels/channels/discord/handle-action.js +165 -0
  56. package/dist/channels/channels/discord.js +413 -0
  57. package/dist/channels/channels/dock.js +436 -0
  58. package/dist/channels/channels/index.js +51 -0
  59. package/dist/channels/channels/plugins/outbound/discord.js +101 -0
  60. package/dist/channels/channels/whatsapp.js +17 -0
  61. package/dist/channels/plugins/types.js +1 -1
  62. package/dist/channels/run-state-machine.js +7 -0
  63. package/dist/commands/models/auth.js +47 -1
  64. package/dist/commands-subagents/action-agents.js +44 -0
  65. package/dist/commands-subagents/action-focus.js +64 -0
  66. package/dist/commands-subagents/action-help.js +4 -0
  67. package/dist/commands-subagents/action-info.js +45 -0
  68. package/dist/commands-subagents/action-kill.js +60 -0
  69. package/dist/commands-subagents/action-list.js +44 -0
  70. package/dist/commands-subagents/action-log.js +29 -0
  71. package/dist/commands-subagents/action-send.js +119 -0
  72. package/dist/commands-subagents/action-spawn.js +52 -0
  73. package/dist/commands-subagents/action-unfocus.js +30 -0
  74. package/dist/commands-subagents/shared.js +303 -0
  75. package/dist/config/config.js +1 -8
  76. package/dist/config/types.secrets.js +61 -0
  77. package/dist/control-ui/assets/{index-D7shnQwQ.js → index-umCsvrWy.js} +884 -741
  78. package/dist/control-ui/assets/index-umCsvrWy.js.map +1 -0
  79. package/dist/control-ui/assets/pt-BR-DedEVAvY.js +2 -0
  80. package/dist/control-ui/assets/pt-BR-DedEVAvY.js.map +1 -0
  81. package/dist/control-ui/assets/zh-CN-CDzeklK-.js +2 -0
  82. package/dist/control-ui/assets/zh-CN-CDzeklK-.js.map +1 -0
  83. package/dist/control-ui/assets/zh-TW-BJCRYNWH.js +2 -0
  84. package/dist/control-ui/assets/zh-TW-BJCRYNWH.js.map +1 -0
  85. package/dist/control-ui/index.html +1 -1
  86. package/dist/gateway/method-scopes.js +9 -1
  87. package/dist/gateway/node-pending-work.js +142 -0
  88. package/dist/gateway/protocol/index.js +5 -1
  89. package/dist/gateway/protocol/schema/nodes.js +18 -0
  90. package/dist/gateway/server-methods/nodes-pending.js +96 -0
  91. package/dist/gateway/server-methods-list.js +4 -0
  92. package/dist/gateway/server-methods.js +2 -0
  93. package/dist/imessage/channel.js +253 -0
  94. package/dist/imessage/monitor/echo-cache.js +70 -0
  95. package/dist/imessage/monitor/loop-rate-limiter.js +51 -0
  96. package/dist/imessage/monitor/reflection-guard.js +50 -0
  97. package/dist/imessage/monitor/sanitize-outbound.js +25 -0
  98. package/dist/imessage/monitor/self-chat-cache.js +75 -0
  99. package/dist/imessage/runtime.js +3 -0
  100. package/dist/infra/exec-approval-reply.js +7 -0
  101. package/dist/infra/tmp-openclaw-dir.js +84 -0
  102. package/dist/pairing/pairing-challenge.js +15 -0
  103. package/dist/plugin-sdk/account-id.d.ts +1 -0
  104. package/dist/plugin-sdk/agent-media-payload.d.ts +12 -0
  105. package/dist/plugin-sdk/allow-from.d.ts +27 -0
  106. package/dist/plugin-sdk/command-auth.d.ts +25 -0
  107. package/dist/plugin-sdk/command-auth.js +3 -1
  108. package/dist/plugin-sdk/config-paths.d.ts +6 -0
  109. package/dist/plugin-sdk/file-lock.d.ts +16 -0
  110. package/dist/plugin-sdk/index.d.ts +428 -0
  111. package/dist/plugin-sdk/index.js +237 -103
  112. package/dist/plugin-sdk/json-store.d.ts +5 -0
  113. package/dist/plugin-sdk/keyed-async-queue.d.ts +12 -0
  114. package/dist/plugin-sdk/onboarding.d.ts +11 -0
  115. package/dist/plugin-sdk/provider-auth-result.d.ts +14 -0
  116. package/dist/plugin-sdk/slack-message-actions.d.ts +11 -0
  117. package/dist/plugin-sdk/status-helpers.d.ts +25 -0
  118. package/dist/plugin-sdk/temp-path.d.ts +12 -0
  119. package/dist/plugin-sdk/text-chunking.d.ts +1 -0
  120. package/dist/plugin-sdk/tool-send.d.ts +4 -0
  121. package/dist/plugin-sdk/webhook-path.d.ts +6 -0
  122. package/dist/plugin-sdk/webhook-targets.d.ts +23 -0
  123. package/dist/plugin-sdk/windows-spawn.d.ts +39 -0
  124. package/dist/plugin-sdk-internal/accounts.js +6 -0
  125. package/dist/plugin-sdk-internal/discord.js +23 -0
  126. package/dist/plugin-sdk-internal/imessage.js +13 -0
  127. package/dist/plugin-sdk-internal/setup.js +9 -0
  128. package/dist/plugin-sdk-internal/signal.js +13 -0
  129. package/dist/plugin-sdk-internal/slack.js +22 -0
  130. package/dist/plugin-sdk-internal/telegram.js +32 -0
  131. package/dist/plugin-sdk-internal/whatsapp.js +29 -0
  132. package/dist/routing/session-key.js +4 -185
  133. package/dist/shared/pid-alive.js +2 -61
  134. package/dist/shared/process-scoped-map.js +5 -7
  135. package/dist/signal/channel.js +264 -0
  136. package/dist/signal/monitor/access-policy.js +60 -0
  137. package/dist/signal/runtime.js +3 -0
  138. package/dist/slack/account-inspect.js +135 -0
  139. package/dist/slack/blocks-input.js +7 -38
  140. package/dist/slack/channel.js +394 -0
  141. package/dist/slack/interactive-replies.js +28 -0
  142. package/dist/slack/monitor/channel-type.js +31 -0
  143. package/dist/slack/monitor/dm-auth.js +49 -0
  144. package/dist/slack/monitor/events/interactions.modal.js +137 -0
  145. package/dist/slack/monitor/events/message-subtype-handlers.js +68 -0
  146. package/dist/slack/monitor/events/system-event-context.js +29 -0
  147. package/dist/slack/monitor/events/system-event-test-harness.js +41 -0
  148. package/dist/slack/monitor/external-arg-menu-store.js +46 -0
  149. package/dist/slack/monitor/message-handler/prepare-content.js +69 -0
  150. package/dist/slack/monitor/message-handler/prepare-thread-context.js +91 -0
  151. package/dist/slack/monitor/message-handler/prepare.test-helpers.js +55 -0
  152. package/dist/slack/monitor/reconnect-policy.js +78 -0
  153. package/dist/slack/monitor/slash-commands.runtime.js +1 -0
  154. package/dist/slack/monitor/slash-dispatch.runtime.js +9 -0
  155. package/dist/slack/monitor/slash-skill-commands.runtime.js +1 -0
  156. package/dist/slack/resolve-allowlist-common.js +36 -0
  157. package/dist/slack/runtime.js +3 -0
  158. package/dist/slack/sent-thread-cache.js +61 -0
  159. package/dist/slack/truncate.js +10 -0
  160. package/dist/telegram/account-inspect.js +175 -0
  161. package/dist/telegram/allow-from.js +10 -0
  162. package/dist/telegram/api-fetch.js +18 -0
  163. package/dist/telegram/approval-buttons.js +30 -0
  164. package/dist/telegram/audit-membership-runtime.js +61 -0
  165. package/dist/telegram/bot/delivery.replies.js +508 -0
  166. package/dist/telegram/bot/delivery.resolve-media.js +227 -0
  167. package/dist/telegram/bot/delivery.send.js +132 -0
  168. package/dist/telegram/bot/reply-threading.js +46 -0
  169. package/dist/telegram/bot-message-context.body.js +186 -0
  170. package/dist/telegram/bot-message-context.session.js +207 -0
  171. package/dist/telegram/bot-message-context.types.js +1 -0
  172. package/dist/telegram/bot-native-commands.test-helpers.js +117 -0
  173. package/dist/telegram/bot.media.e2e-harness.js +81 -0
  174. package/dist/telegram/bot.media.test-utils.js +81 -0
  175. package/dist/telegram/channel-actions.js +225 -0
  176. package/dist/telegram/channel.js +515 -0
  177. package/dist/telegram/conversation-route.js +107 -0
  178. package/dist/telegram/delivery.js +2 -0
  179. package/dist/telegram/delivery.replies.js +508 -0
  180. package/dist/telegram/dm-access.js +86 -0
  181. package/dist/telegram/draft-stream.test-helpers.js +62 -0
  182. package/dist/telegram/exec-approvals-handler.js +281 -0
  183. package/dist/telegram/exec-approvals.js +62 -0
  184. package/dist/telegram/forum-service-message.js +22 -0
  185. package/dist/telegram/group-config-helpers.js +10 -0
  186. package/dist/telegram/lane-delivery-state.js +19 -0
  187. package/dist/telegram/lane-delivery-text-deliverer.js +357 -0
  188. package/dist/telegram/lane-delivery.js +2 -0
  189. package/dist/telegram/normalize.js +37 -0
  190. package/dist/telegram/onboarding.js +192 -0
  191. package/dist/telegram/outbound-adapter.js +100 -0
  192. package/dist/telegram/polling-session.js +275 -0
  193. package/dist/telegram/runtime.js +3 -0
  194. package/dist/telegram/sendchataction-401-backoff.js +71 -0
  195. package/dist/telegram/sequential-key.js +46 -0
  196. package/dist/telegram/status-issues.js +105 -0
  197. package/dist/telegram/target-writeback.js +165 -0
  198. package/dist/telegram/thread-bindings.js +560 -0
  199. package/dist/utils.js +10 -276
  200. package/dist/wizard/prompts.js +5 -5
  201. package/extensions/feishu/src/policy.ts +1 -1
  202. package/extensions/firecrawl/index.test.ts +82 -0
  203. package/extensions/firecrawl/index.ts +20 -0
  204. package/extensions/firecrawl/openclaw.plugin.json +8 -0
  205. package/extensions/firecrawl/package.json +12 -0
  206. package/extensions/firecrawl/src/config.ts +159 -0
  207. package/extensions/firecrawl/src/firecrawl-client.ts +446 -0
  208. package/extensions/firecrawl/src/firecrawl-scrape-tool.ts +89 -0
  209. package/extensions/firecrawl/src/firecrawl-search-provider.ts +63 -0
  210. package/extensions/firecrawl/src/firecrawl-search-tool.ts +76 -0
  211. package/package.json +1 -1
  212. package/dist/.buildstamp +0 -1
  213. package/dist/acp/bindings-store.js +0 -209
  214. package/dist/acp/control-plane/runtime-cache.js +0 -54
  215. package/dist/acp/control-plane/runtime-options.js +0 -215
  216. package/dist/acp/control-plane/session-actor-queue.js +0 -36
  217. package/dist/acp/index.js +0 -2
  218. package/dist/acp/runtime/errors.js +0 -47
  219. package/dist/acp/runtime/registry.js +0 -86
  220. package/dist/acp/secret-file.js +0 -22
  221. package/dist/agents/auth-profiles.resolve-auth-profile-order.fixtures.js +0 -23
  222. package/dist/agents/bash-process-registry.test-helpers.js +0 -29
  223. package/dist/agents/bash-tools.exec-approval-request.js +0 -20
  224. package/dist/agents/bash-tools.exec-host-gateway.js +0 -240
  225. package/dist/agents/bash-tools.exec-host-node.js +0 -235
  226. package/dist/agents/checkpoint-manager.js +0 -290
  227. package/dist/agents/claude-cli-runner.js +0 -3
  228. package/dist/agents/error-classifier.js +0 -251
  229. package/dist/agents/live-model-filter.js +0 -84
  230. package/dist/agents/nvidia-models.js +0 -228
  231. package/dist/agents/pi-embedded-runner/run.overflow-compaction.fixture.js +0 -34
  232. package/dist/agents/pi-embedded-runner/run.overflow-compaction.mocks.shared.js +0 -156
  233. package/dist/agents/pi-embedded-subscribe.handlers.tools.media.test-helpers.js +0 -30
  234. package/dist/agents/provider/config-loader.js +0 -76
  235. package/dist/agents/provider/index.js +0 -15
  236. package/dist/agents/provider/models-dev.js +0 -129
  237. package/dist/agents/provider/session-binding.js +0 -376
  238. package/dist/agents/queued-file-writer.js +0 -22
  239. package/dist/agents/skills/bundled-context.js +0 -23
  240. package/dist/agents/skills/security.js +0 -211
  241. package/dist/agents/skills/tools-dir.js +0 -9
  242. package/dist/agents/skills-install-download.js +0 -290
  243. package/dist/agents/skills-install-output.js +0 -30
  244. package/dist/agents/skills-install.download-test-utils.js +0 -36
  245. package/dist/agents/skills.test-helpers.js +0 -13
  246. package/dist/agents/subagent-announce-reliability.js +0 -160
  247. package/dist/agents/subagent-registry.mocks.shared.js +0 -12
  248. package/dist/agents/test-helpers/assistant-message-fixtures.js +0 -29
  249. package/dist/agents/test-helpers/fast-coding-tools.js +0 -1
  250. package/dist/agents/test-helpers/fast-core-tools.js +0 -8
  251. package/dist/agents/test-helpers/fast-tool-stubs.js +0 -18
  252. package/dist/agents/test-helpers/host-sandbox-fs-bridge.js +0 -74
  253. package/dist/agents/test-helpers/pi-tools-sandbox-context.js +0 -27
  254. package/dist/agents/tool-display-common.js +0 -915
  255. package/dist/agents/tool-policy-shared.js +0 -108
  256. package/dist/agents/tool-policy.conformance.js +0 -14
  257. package/dist/agents/tool-result-truncation.js +0 -299
  258. package/dist/agents/tools/cron-tool.test-helpers.js +0 -12
  259. package/dist/agents/tools/discord-actions-moderation-shared.js +0 -27
  260. package/dist/agents/tools/discord-actions-presence.js +0 -78
  261. package/dist/control-ui/assets/index-D7shnQwQ.js.map +0 -1
  262. package/dist/discord/discord-improvements.js +0 -167
  263. package/dist/discord/index.js +0 -2
  264. package/dist/hooks/bundled/boot-md/HOOK.md +0 -19
  265. package/dist/hooks/bundled/command-logger/HOOK.md +0 -122
  266. package/dist/hooks/bundled/session-memory/HOOK.md +0 -86
  267. package/dist/hooks/bundled/soul-evil/HOOK.md +0 -71
  268. package/dist/whatsapp/normalize.js +0 -66
  269. package/dist/whatsapp/resolve-outbound-target.js +0 -42
  270. /package/dist/{acp/runtime/types.js → auto-reply/auto-reply/reply/commands-types.js} +0 -0
  271. /package/dist/{agents/pi-embedded-payloads.js → slack/account-surface-fields.js} +0 -0
@@ -0,0 +1,281 @@
1
+ import { createOperatorApprovalsGatewayClient } from "../../../src/gateway/operator-approvals-client.js";
2
+ import { resolveExecApprovalCommandDisplay } from "../../../src/infra/exec-approval-command-display.js";
3
+ import { buildExecApprovalPendingReplyPayload, } from "../../../src/infra/exec-approval-reply.js";
4
+ import { resolveExecApprovalSessionTarget } from "../../../src/infra/exec-approval-session-target.js";
5
+ import { createSubsystemLogger } from "../../../src/logging/subsystem.js";
6
+ import { normalizeAccountId, parseAgentSessionKey } from "../../../src/routing/session-key.js";
7
+ import { compileSafeRegex, testRegexWithBoundedInput } from "../../../src/security/safe-regex.js";
8
+ import { buildTelegramExecApprovalButtons } from "./approval-buttons.js";
9
+ import { getTelegramExecApprovalApprovers, resolveTelegramExecApprovalConfig, resolveTelegramExecApprovalTarget, } from "./exec-approvals.js";
10
+ import { editMessageReplyMarkupTelegram, sendMessageTelegram, sendTypingTelegram } from "./send.js";
11
+ const log = createSubsystemLogger("telegram/exec-approvals");
12
+ function matchesFilters(params) {
13
+ const config = resolveTelegramExecApprovalConfig({
14
+ cfg: params.cfg,
15
+ accountId: params.accountId,
16
+ });
17
+ if (!config?.enabled) {
18
+ return false;
19
+ }
20
+ const approvers = getTelegramExecApprovalApprovers({
21
+ cfg: params.cfg,
22
+ accountId: params.accountId,
23
+ });
24
+ if (approvers.length === 0) {
25
+ return false;
26
+ }
27
+ if (config.agentFilter?.length) {
28
+ const agentId = params.request.request.agentId ??
29
+ parseAgentSessionKey(params.request.request.sessionKey)?.agentId;
30
+ if (!agentId || !config.agentFilter.includes(agentId)) {
31
+ return false;
32
+ }
33
+ }
34
+ if (config.sessionFilter?.length) {
35
+ const sessionKey = params.request.request.sessionKey;
36
+ if (!sessionKey) {
37
+ return false;
38
+ }
39
+ const matches = config.sessionFilter.some((pattern) => {
40
+ if (sessionKey.includes(pattern)) {
41
+ return true;
42
+ }
43
+ const regex = compileSafeRegex(pattern);
44
+ return regex ? testRegexWithBoundedInput(regex, sessionKey) : false;
45
+ });
46
+ if (!matches) {
47
+ return false;
48
+ }
49
+ }
50
+ return true;
51
+ }
52
+ function isHandlerConfigured(params) {
53
+ const config = resolveTelegramExecApprovalConfig({
54
+ cfg: params.cfg,
55
+ accountId: params.accountId,
56
+ });
57
+ if (!config?.enabled) {
58
+ return false;
59
+ }
60
+ return (getTelegramExecApprovalApprovers({
61
+ cfg: params.cfg,
62
+ accountId: params.accountId,
63
+ }).length > 0);
64
+ }
65
+ function resolveRequestSessionTarget(params) {
66
+ return resolveExecApprovalSessionTarget({
67
+ cfg: params.cfg,
68
+ request: params.request,
69
+ turnSourceChannel: params.request.request.turnSourceChannel ?? undefined,
70
+ turnSourceTo: params.request.request.turnSourceTo ?? undefined,
71
+ turnSourceAccountId: params.request.request.turnSourceAccountId ?? undefined,
72
+ turnSourceThreadId: params.request.request.turnSourceThreadId ?? undefined,
73
+ });
74
+ }
75
+ function resolveTelegramSourceTarget(params) {
76
+ const turnSourceChannel = params.request.request.turnSourceChannel?.trim().toLowerCase() || "";
77
+ const turnSourceTo = params.request.request.turnSourceTo?.trim() || "";
78
+ const turnSourceAccountId = params.request.request.turnSourceAccountId?.trim() || "";
79
+ if (turnSourceChannel === "telegram" && turnSourceTo) {
80
+ if (turnSourceAccountId &&
81
+ normalizeAccountId(turnSourceAccountId) !== normalizeAccountId(params.accountId)) {
82
+ return null;
83
+ }
84
+ const threadId = typeof params.request.request.turnSourceThreadId === "number"
85
+ ? params.request.request.turnSourceThreadId
86
+ : typeof params.request.request.turnSourceThreadId === "string"
87
+ ? Number.parseInt(params.request.request.turnSourceThreadId, 10)
88
+ : undefined;
89
+ return { to: turnSourceTo, threadId: Number.isFinite(threadId) ? threadId : undefined };
90
+ }
91
+ const sessionTarget = resolveRequestSessionTarget(params);
92
+ if (!sessionTarget || sessionTarget.channel !== "telegram") {
93
+ return null;
94
+ }
95
+ if (sessionTarget.accountId &&
96
+ normalizeAccountId(sessionTarget.accountId) !== normalizeAccountId(params.accountId)) {
97
+ return null;
98
+ }
99
+ return {
100
+ to: sessionTarget.to,
101
+ threadId: sessionTarget.threadId,
102
+ };
103
+ }
104
+ function dedupeTargets(targets) {
105
+ const seen = new Set();
106
+ const deduped = [];
107
+ for (const target of targets) {
108
+ const key = `${target.to}:${target.threadId ?? ""}`;
109
+ if (seen.has(key)) {
110
+ continue;
111
+ }
112
+ seen.add(key);
113
+ deduped.push(target);
114
+ }
115
+ return deduped;
116
+ }
117
+ export class TelegramExecApprovalHandler {
118
+ opts;
119
+ gatewayClient = null;
120
+ pending = new Map();
121
+ started = false;
122
+ nowMs;
123
+ sendTyping;
124
+ sendMessage;
125
+ editReplyMarkup;
126
+ constructor(opts, deps = {}) {
127
+ this.opts = opts;
128
+ this.nowMs = deps.nowMs ?? Date.now;
129
+ this.sendTyping = deps.sendTyping ?? sendTypingTelegram;
130
+ this.sendMessage = deps.sendMessage ?? sendMessageTelegram;
131
+ this.editReplyMarkup = deps.editReplyMarkup ?? editMessageReplyMarkupTelegram;
132
+ }
133
+ shouldHandle(request) {
134
+ return matchesFilters({
135
+ cfg: this.opts.cfg,
136
+ accountId: this.opts.accountId,
137
+ request,
138
+ });
139
+ }
140
+ async start() {
141
+ if (this.started) {
142
+ return;
143
+ }
144
+ this.started = true;
145
+ if (!isHandlerConfigured({ cfg: this.opts.cfg, accountId: this.opts.accountId })) {
146
+ return;
147
+ }
148
+ this.gatewayClient = await createOperatorApprovalsGatewayClient({
149
+ config: this.opts.cfg,
150
+ gatewayUrl: this.opts.gatewayUrl,
151
+ clientDisplayName: `Telegram Exec Approvals (${this.opts.accountId})`,
152
+ onEvent: (evt) => this.handleGatewayEvent(evt),
153
+ onConnectError: (err) => {
154
+ log.error(`telegram exec approvals: connect error: ${err.message}`);
155
+ },
156
+ });
157
+ this.gatewayClient.start();
158
+ }
159
+ async stop() {
160
+ if (!this.started) {
161
+ return;
162
+ }
163
+ this.started = false;
164
+ for (const pending of this.pending.values()) {
165
+ clearTimeout(pending.timeoutId);
166
+ }
167
+ this.pending.clear();
168
+ this.gatewayClient?.stop();
169
+ this.gatewayClient = null;
170
+ }
171
+ async handleRequested(request) {
172
+ if (!this.shouldHandle(request)) {
173
+ return;
174
+ }
175
+ const targetMode = resolveTelegramExecApprovalTarget({
176
+ cfg: this.opts.cfg,
177
+ accountId: this.opts.accountId,
178
+ });
179
+ const targets = [];
180
+ const sourceTarget = resolveTelegramSourceTarget({
181
+ cfg: this.opts.cfg,
182
+ accountId: this.opts.accountId,
183
+ request,
184
+ });
185
+ let fallbackToDm = false;
186
+ if (targetMode === "channel" || targetMode === "both") {
187
+ if (sourceTarget) {
188
+ targets.push(sourceTarget);
189
+ }
190
+ else {
191
+ fallbackToDm = true;
192
+ }
193
+ }
194
+ if (targetMode === "dm" || targetMode === "both" || fallbackToDm) {
195
+ for (const approver of getTelegramExecApprovalApprovers({
196
+ cfg: this.opts.cfg,
197
+ accountId: this.opts.accountId,
198
+ })) {
199
+ targets.push({ to: approver });
200
+ }
201
+ }
202
+ const resolvedTargets = dedupeTargets(targets);
203
+ if (resolvedTargets.length === 0) {
204
+ return;
205
+ }
206
+ const payloadParams = {
207
+ approvalId: request.id,
208
+ approvalSlug: request.id.slice(0, 8),
209
+ approvalCommandId: request.id,
210
+ command: resolveExecApprovalCommandDisplay(request.request).commandText,
211
+ cwd: request.request.cwd ?? undefined,
212
+ host: request.request.host === "node" ? "node" : "gateway",
213
+ nodeId: request.request.nodeId ?? undefined,
214
+ expiresAtMs: request.expiresAtMs,
215
+ nowMs: this.nowMs(),
216
+ };
217
+ const payload = buildExecApprovalPendingReplyPayload(payloadParams);
218
+ const buttons = buildTelegramExecApprovalButtons(request.id);
219
+ const sentMessages = [];
220
+ for (const target of resolvedTargets) {
221
+ try {
222
+ await this.sendTyping(target.to, {
223
+ cfg: this.opts.cfg,
224
+ token: this.opts.token,
225
+ accountId: this.opts.accountId,
226
+ ...(typeof target.threadId === "number" ? { messageThreadId: target.threadId } : {}),
227
+ }).catch(() => { });
228
+ const result = await this.sendMessage(target.to, payload.text ?? "", {
229
+ cfg: this.opts.cfg,
230
+ token: this.opts.token,
231
+ accountId: this.opts.accountId,
232
+ buttons,
233
+ ...(typeof target.threadId === "number" ? { messageThreadId: target.threadId } : {}),
234
+ });
235
+ sentMessages.push({
236
+ chatId: result.chatId,
237
+ messageId: result.messageId,
238
+ });
239
+ }
240
+ catch (err) {
241
+ log.error(`telegram exec approvals: failed to send request ${request.id}: ${String(err)}`);
242
+ }
243
+ }
244
+ if (sentMessages.length === 0) {
245
+ return;
246
+ }
247
+ const timeoutMs = Math.max(0, request.expiresAtMs - this.nowMs());
248
+ const timeoutId = setTimeout(() => {
249
+ void this.handleResolved({ id: request.id, decision: "deny", ts: Date.now() });
250
+ }, timeoutMs);
251
+ timeoutId.unref?.();
252
+ this.pending.set(request.id, {
253
+ timeoutId,
254
+ messages: sentMessages,
255
+ });
256
+ }
257
+ async handleResolved(resolved) {
258
+ const pending = this.pending.get(resolved.id);
259
+ if (!pending) {
260
+ return;
261
+ }
262
+ clearTimeout(pending.timeoutId);
263
+ this.pending.delete(resolved.id);
264
+ await Promise.allSettled(pending.messages.map(async (message) => {
265
+ await this.editReplyMarkup(message.chatId, message.messageId, [], {
266
+ cfg: this.opts.cfg,
267
+ token: this.opts.token,
268
+ accountId: this.opts.accountId,
269
+ });
270
+ }));
271
+ }
272
+ handleGatewayEvent(evt) {
273
+ if (evt.event === "exec.approval.requested") {
274
+ void this.handleRequested(evt.payload);
275
+ return;
276
+ }
277
+ if (evt.event === "exec.approval.resolved") {
278
+ void this.handleResolved(evt.payload);
279
+ }
280
+ }
281
+ }
@@ -0,0 +1,62 @@
1
+ import { getExecApprovalReplyMetadata } from "../../../src/infra/exec-approval-reply.js";
2
+ import { resolveTelegramAccount } from "./accounts.js";
3
+ import { resolveTelegramTargetChatType } from "./targets.js";
4
+ function normalizeApproverId(value) {
5
+ return String(value).trim();
6
+ }
7
+ export function resolveTelegramExecApprovalConfig(params) {
8
+ return resolveTelegramAccount(params).config.execApprovals;
9
+ }
10
+ export function getTelegramExecApprovalApprovers(params) {
11
+ return (resolveTelegramExecApprovalConfig(params)?.approvers ?? [])
12
+ .map(normalizeApproverId)
13
+ .filter(Boolean);
14
+ }
15
+ export function isTelegramExecApprovalClientEnabled(params) {
16
+ const config = resolveTelegramExecApprovalConfig(params);
17
+ return Boolean(config?.enabled && getTelegramExecApprovalApprovers(params).length > 0);
18
+ }
19
+ export function isTelegramExecApprovalApprover(params) {
20
+ const senderId = params.senderId?.trim();
21
+ if (!senderId) {
22
+ return false;
23
+ }
24
+ const approvers = getTelegramExecApprovalApprovers(params);
25
+ return approvers.includes(senderId);
26
+ }
27
+ export function resolveTelegramExecApprovalTarget(params) {
28
+ return resolveTelegramExecApprovalConfig(params)?.target ?? "dm";
29
+ }
30
+ export function shouldInjectTelegramExecApprovalButtons(params) {
31
+ if (!isTelegramExecApprovalClientEnabled(params)) {
32
+ return false;
33
+ }
34
+ const target = resolveTelegramExecApprovalTarget(params);
35
+ const chatType = resolveTelegramTargetChatType(params.to);
36
+ if (chatType === "direct") {
37
+ return target === "dm" || target === "both";
38
+ }
39
+ if (chatType === "group") {
40
+ return target === "channel" || target === "both";
41
+ }
42
+ return target === "both";
43
+ }
44
+ function resolveExecApprovalButtonsExplicitlyDisabled(params) {
45
+ const capabilities = resolveTelegramAccount(params).config.capabilities;
46
+ if (!capabilities || Array.isArray(capabilities) || typeof capabilities !== "object") {
47
+ return false;
48
+ }
49
+ const inlineButtons = capabilities.inlineButtons;
50
+ return typeof inlineButtons === "string" && inlineButtons.trim().toLowerCase() === "off";
51
+ }
52
+ export function shouldEnableTelegramExecApprovalButtons(params) {
53
+ if (!shouldInjectTelegramExecApprovalButtons(params)) {
54
+ return false;
55
+ }
56
+ return !resolveExecApprovalButtonsExplicitlyDisabled(params);
57
+ }
58
+ export function shouldSuppressLocalTelegramExecApprovalPrompt(params) {
59
+ void params.cfg;
60
+ void params.accountId;
61
+ return getExecApprovalReplyMetadata(params.payload) !== null;
62
+ }
@@ -0,0 +1,22 @@
1
+ /** Telegram forum-topic service-message fields (Bot API). */
2
+ export const TELEGRAM_FORUM_SERVICE_FIELDS = [
3
+ "forum_topic_created",
4
+ "forum_topic_edited",
5
+ "forum_topic_closed",
6
+ "forum_topic_reopened",
7
+ "general_forum_topic_hidden",
8
+ "general_forum_topic_unhidden",
9
+ ];
10
+ /**
11
+ * Returns `true` when the message is a Telegram forum service message (e.g.
12
+ * "Topic created"). These auto-generated messages carry one of the
13
+ * `forum_topic_*` / `general_forum_topic_*` fields and should not count as
14
+ * regular bot replies for implicit-mention purposes.
15
+ */
16
+ export function isTelegramForumServiceMessage(msg) {
17
+ if (!msg || typeof msg !== "object") {
18
+ return false;
19
+ }
20
+ const record = msg;
21
+ return TELEGRAM_FORUM_SERVICE_FIELDS.some((field) => record[field] != null);
22
+ }
@@ -0,0 +1,10 @@
1
+ import { firstDefined } from "./bot-access.js";
2
+ export function resolveTelegramGroupPromptSettings(params) {
3
+ const skillFilter = firstDefined(params.topicConfig?.skills, params.groupConfig?.skills);
4
+ const systemPromptParts = [
5
+ params.groupConfig?.systemPrompt?.trim() || null,
6
+ params.topicConfig?.systemPrompt?.trim() || null,
7
+ ].filter((entry) => Boolean(entry));
8
+ const groupSystemPrompt = systemPromptParts.length > 0 ? systemPromptParts.join("\n\n") : undefined;
9
+ return { skillFilter, groupSystemPrompt };
10
+ }
@@ -0,0 +1,19 @@
1
+ export function createLaneDeliveryStateTracker() {
2
+ const state = {
3
+ delivered: false,
4
+ skippedNonSilent: 0,
5
+ failedNonSilent: 0,
6
+ };
7
+ return {
8
+ markDelivered: () => {
9
+ state.delivered = true;
10
+ },
11
+ markNonSilentSkip: () => {
12
+ state.skippedNonSilent += 1;
13
+ },
14
+ markNonSilentFailure: () => {
15
+ state.failedNonSilent += 1;
16
+ },
17
+ snapshot: () => ({ ...state }),
18
+ };
19
+ }