@poolzin/pool-bot 2026.3.25 → 2026.3.27

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 +32 -257
  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,78 @@
1
+ const SLACK_AUTH_ERROR_RE = /account_inactive|invalid_auth|token_revoked|token_expired|not_authed|org_login_required|team_access_not_granted|missing_scope|cannot_find_service|invalid_token/i;
2
+ export const SLACK_SOCKET_RECONNECT_POLICY = {
3
+ initialMs: 2_000,
4
+ maxMs: 30_000,
5
+ factor: 1.8,
6
+ jitter: 0.25,
7
+ maxAttempts: 12,
8
+ };
9
+ export function getSocketEmitter(app) {
10
+ const receiver = app.receiver;
11
+ const client = receiver && typeof receiver === "object"
12
+ ? receiver.client
13
+ : undefined;
14
+ if (!client || typeof client !== "object") {
15
+ return null;
16
+ }
17
+ const on = client.on;
18
+ const off = client.off;
19
+ if (typeof on !== "function" || typeof off !== "function") {
20
+ return null;
21
+ }
22
+ return {
23
+ on: (event, listener) => on.call(client, event, listener),
24
+ off: (event, listener) => off.call(client, event, listener),
25
+ };
26
+ }
27
+ export function waitForSlackSocketDisconnect(app, abortSignal) {
28
+ return new Promise((resolve) => {
29
+ const emitter = getSocketEmitter(app);
30
+ if (!emitter) {
31
+ abortSignal?.addEventListener("abort", () => resolve({ event: "disconnect" }), {
32
+ once: true,
33
+ });
34
+ return;
35
+ }
36
+ const disconnectListener = () => resolveOnce({ event: "disconnect" });
37
+ const startFailListener = (error) => resolveOnce({ event: "unable_to_socket_mode_start", error });
38
+ const errorListener = (error) => resolveOnce({ event: "error", error });
39
+ const abortListener = () => resolveOnce({ event: "disconnect" });
40
+ const cleanup = () => {
41
+ emitter.off("disconnected", disconnectListener);
42
+ emitter.off("unable_to_socket_mode_start", startFailListener);
43
+ emitter.off("error", errorListener);
44
+ abortSignal?.removeEventListener("abort", abortListener);
45
+ };
46
+ const resolveOnce = (value) => {
47
+ cleanup();
48
+ resolve(value);
49
+ };
50
+ emitter.on("disconnected", disconnectListener);
51
+ emitter.on("unable_to_socket_mode_start", startFailListener);
52
+ emitter.on("error", errorListener);
53
+ abortSignal?.addEventListener("abort", abortListener, { once: true });
54
+ });
55
+ }
56
+ /**
57
+ * Detect non-recoverable Slack API / auth errors that should NOT be retried.
58
+ * These indicate permanent credential problems (revoked bot, deactivated account, etc.)
59
+ * and retrying will never succeed — continuing to retry blocks the entire gateway.
60
+ */
61
+ export function isNonRecoverableSlackAuthError(error) {
62
+ const msg = error instanceof Error ? error.message : typeof error === "string" ? error : "";
63
+ return SLACK_AUTH_ERROR_RE.test(msg);
64
+ }
65
+ export function formatUnknownError(error) {
66
+ if (error instanceof Error) {
67
+ return error.message;
68
+ }
69
+ if (typeof error === "string") {
70
+ return error;
71
+ }
72
+ try {
73
+ return JSON.stringify(error);
74
+ }
75
+ catch {
76
+ return "unknown error";
77
+ }
78
+ }
@@ -0,0 +1 @@
1
+ export { buildCommandTextFromArgs, findCommandByNativeName, listNativeCommandSpecsForConfig, parseCommandArgs, resolveCommandArgMenu, } from "../../../../src/auto-reply/commands-registry.js";
@@ -0,0 +1,9 @@
1
+ export { resolveChunkMode } from "../../../../src/auto-reply/chunk.js";
2
+ export { finalizeInboundContext } from "../../../../src/auto-reply/reply/inbound-context.js";
3
+ export { dispatchReplyWithDispatcher } from "../../../../src/auto-reply/reply/provider-dispatcher.js";
4
+ export { resolveConversationLabel } from "../../../../src/channels/conversation-label.js";
5
+ export { createReplyPrefixOptions } from "../../../../src/channels/reply-prefix.js";
6
+ export { recordInboundSessionMetaSafe } from "../../../../src/channels/session-meta.js";
7
+ export { resolveMarkdownTableMode } from "../../../../src/config/markdown-tables.js";
8
+ export { resolveAgentRoute } from "../../../../src/routing/resolve-route.js";
9
+ export { deliverSlackSlashReplies } from "./replies.js";
@@ -0,0 +1 @@
1
+ export { listSkillCommandsForAgents } from "../../../../src/auto-reply/skill-commands.js";
@@ -0,0 +1,36 @@
1
+ function readSlackNextCursor(response) {
2
+ const next = response.response_metadata?.next_cursor?.trim();
3
+ return next ? next : undefined;
4
+ }
5
+ export async function collectSlackCursorItems(params) {
6
+ const items = [];
7
+ let cursor;
8
+ do {
9
+ const response = await params.fetchPage(cursor);
10
+ items.push(...params.collectPageItems(response));
11
+ cursor = readSlackNextCursor(response);
12
+ } while (cursor);
13
+ return items;
14
+ }
15
+ export function resolveSlackAllowlistEntries(params) {
16
+ const results = [];
17
+ for (const input of params.entries) {
18
+ const parsed = params.parseInput(input);
19
+ if (parsed.id) {
20
+ const match = params.findById(params.lookup, parsed.id);
21
+ results.push(params.buildIdResolved({ input, parsed, match }));
22
+ continue;
23
+ }
24
+ const resolved = params.resolveNonId({
25
+ input,
26
+ parsed,
27
+ lookup: params.lookup,
28
+ });
29
+ if (resolved) {
30
+ results.push(resolved);
31
+ continue;
32
+ }
33
+ results.push(params.buildUnresolved(input));
34
+ }
35
+ return results;
36
+ }
@@ -0,0 +1,3 @@
1
+ import { createPluginRuntimeStore } from "openclaw/plugin-sdk/compat";
2
+ const { setRuntime: setSlackRuntime, getRuntime: getSlackRuntime } = createPluginRuntimeStore("Slack runtime not initialized");
3
+ export { getSlackRuntime, setSlackRuntime };
@@ -0,0 +1,61 @@
1
+ import { resolveGlobalMap } from "../../../src/shared/global-singleton.js";
2
+ /**
3
+ * In-memory cache of Slack threads the bot has participated in.
4
+ * Used to auto-respond in threads without requiring @mention after the first reply.
5
+ * Follows a similar TTL pattern to the MS Teams and Telegram sent-message caches.
6
+ */
7
+ const TTL_MS = 24 * 60 * 60 * 1000; // 24 hours
8
+ const MAX_ENTRIES = 5000;
9
+ /**
10
+ * Keep Slack thread participation shared across bundled chunks so thread
11
+ * auto-reply gating does not diverge between prepare/dispatch call paths.
12
+ */
13
+ const SLACK_THREAD_PARTICIPATION_KEY = Symbol.for("openclaw.slackThreadParticipation");
14
+ const threadParticipation = resolveGlobalMap(SLACK_THREAD_PARTICIPATION_KEY);
15
+ function makeKey(accountId, channelId, threadTs) {
16
+ return `${accountId}:${channelId}:${threadTs}`;
17
+ }
18
+ function evictExpired() {
19
+ const now = Date.now();
20
+ for (const [key, timestamp] of threadParticipation) {
21
+ if (now - timestamp > TTL_MS) {
22
+ threadParticipation.delete(key);
23
+ }
24
+ }
25
+ }
26
+ function evictOldest() {
27
+ const oldest = threadParticipation.keys().next().value;
28
+ if (oldest) {
29
+ threadParticipation.delete(oldest);
30
+ }
31
+ }
32
+ export function recordSlackThreadParticipation(accountId, channelId, threadTs) {
33
+ if (!accountId || !channelId || !threadTs) {
34
+ return;
35
+ }
36
+ if (threadParticipation.size >= MAX_ENTRIES) {
37
+ evictExpired();
38
+ }
39
+ if (threadParticipation.size >= MAX_ENTRIES) {
40
+ evictOldest();
41
+ }
42
+ threadParticipation.set(makeKey(accountId, channelId, threadTs), Date.now());
43
+ }
44
+ export function hasSlackThreadParticipation(accountId, channelId, threadTs) {
45
+ if (!accountId || !channelId || !threadTs) {
46
+ return false;
47
+ }
48
+ const key = makeKey(accountId, channelId, threadTs);
49
+ const timestamp = threadParticipation.get(key);
50
+ if (timestamp == null) {
51
+ return false;
52
+ }
53
+ if (Date.now() - timestamp > TTL_MS) {
54
+ threadParticipation.delete(key);
55
+ return false;
56
+ }
57
+ return true;
58
+ }
59
+ export function clearSlackThreadParticipationCache() {
60
+ threadParticipation.clear();
61
+ }
@@ -0,0 +1,10 @@
1
+ export function truncateSlackText(value, max) {
2
+ const trimmed = value.trim();
3
+ if (trimmed.length <= max) {
4
+ return trimmed;
5
+ }
6
+ if (max <= 1) {
7
+ return trimmed.slice(0, max);
8
+ }
9
+ return `${trimmed.slice(0, max - 1)}…`;
10
+ }
@@ -0,0 +1,175 @@
1
+ import { coerceSecretRef, hasConfiguredSecretInput, normalizeSecretInputString, } from "../../../src/config/types.secrets.js";
2
+ import { tryReadSecretFileSync } from "../../../src/infra/secret-file.js";
3
+ import { resolveAccountWithDefaultFallback } from "../../../src/plugin-sdk/account-resolution.js";
4
+ import { DEFAULT_ACCOUNT_ID, normalizeAccountId } from "../../../src/routing/session-key.js";
5
+ import { resolveDefaultSecretProviderAlias } from "../../../src/secrets/ref-contract.js";
6
+ import { mergeTelegramAccountConfig, resolveDefaultTelegramAccountId, resolveTelegramAccountConfig, } from "./accounts.js";
7
+ function inspectTokenFile(pathValue) {
8
+ const tokenFile = typeof pathValue === "string" ? pathValue.trim() : "";
9
+ if (!tokenFile) {
10
+ return null;
11
+ }
12
+ const token = tryReadSecretFileSync(tokenFile, "Telegram bot token", {
13
+ rejectSymlink: true,
14
+ });
15
+ return {
16
+ token: token ?? "",
17
+ tokenSource: "tokenFile",
18
+ tokenStatus: token ? "available" : "configured_unavailable",
19
+ };
20
+ }
21
+ function canResolveEnvSecretRefInReadOnlyPath(params) {
22
+ const providerConfig = params.cfg.secrets?.providers?.[params.provider];
23
+ if (!providerConfig) {
24
+ return params.provider === resolveDefaultSecretProviderAlias(params.cfg, "env");
25
+ }
26
+ if (providerConfig.source !== "env") {
27
+ return false;
28
+ }
29
+ const allowlist = providerConfig.allowlist;
30
+ return !allowlist || allowlist.includes(params.id);
31
+ }
32
+ function inspectTokenValue(params) {
33
+ // Try to resolve env-based SecretRefs from process.env for read-only inspection
34
+ const ref = coerceSecretRef(params.value, params.cfg.secrets?.defaults);
35
+ if (ref?.source === "env") {
36
+ if (!canResolveEnvSecretRefInReadOnlyPath({
37
+ cfg: params.cfg,
38
+ provider: ref.provider,
39
+ id: ref.id,
40
+ })) {
41
+ return {
42
+ token: "",
43
+ tokenSource: "env",
44
+ tokenStatus: "configured_unavailable",
45
+ };
46
+ }
47
+ const envValue = process.env[ref.id];
48
+ if (envValue && envValue.trim()) {
49
+ return {
50
+ token: envValue.trim(),
51
+ tokenSource: "env",
52
+ tokenStatus: "available",
53
+ };
54
+ }
55
+ return {
56
+ token: "",
57
+ tokenSource: "env",
58
+ tokenStatus: "configured_unavailable",
59
+ };
60
+ }
61
+ const token = normalizeSecretInputString(params.value);
62
+ if (token) {
63
+ return {
64
+ token,
65
+ tokenSource: "config",
66
+ tokenStatus: "available",
67
+ };
68
+ }
69
+ if (hasConfiguredSecretInput(params.value, params.cfg.secrets?.defaults)) {
70
+ return {
71
+ token: "",
72
+ tokenSource: "config",
73
+ tokenStatus: "configured_unavailable",
74
+ };
75
+ }
76
+ return null;
77
+ }
78
+ function inspectTelegramAccountPrimary(params) {
79
+ const accountId = normalizeAccountId(params.accountId);
80
+ const merged = mergeTelegramAccountConfig(params.cfg, accountId);
81
+ const enabled = params.cfg.channels?.telegram?.enabled !== false && merged.enabled !== false;
82
+ const accountConfig = resolveTelegramAccountConfig(params.cfg, accountId);
83
+ const accountTokenFile = inspectTokenFile(accountConfig?.tokenFile);
84
+ if (accountTokenFile) {
85
+ return {
86
+ accountId,
87
+ enabled,
88
+ name: merged.name?.trim() || undefined,
89
+ token: accountTokenFile.token,
90
+ tokenSource: accountTokenFile.tokenSource,
91
+ tokenStatus: accountTokenFile.tokenStatus,
92
+ configured: accountTokenFile.tokenStatus !== "missing",
93
+ config: merged,
94
+ };
95
+ }
96
+ const accountToken = inspectTokenValue({ cfg: params.cfg, value: accountConfig?.botToken });
97
+ if (accountToken) {
98
+ return {
99
+ accountId,
100
+ enabled,
101
+ name: merged.name?.trim() || undefined,
102
+ token: accountToken.token,
103
+ tokenSource: accountToken.tokenSource,
104
+ tokenStatus: accountToken.tokenStatus,
105
+ configured: accountToken.tokenStatus !== "missing",
106
+ config: merged,
107
+ };
108
+ }
109
+ const channelTokenFile = inspectTokenFile(params.cfg.channels?.telegram?.tokenFile);
110
+ if (channelTokenFile) {
111
+ return {
112
+ accountId,
113
+ enabled,
114
+ name: merged.name?.trim() || undefined,
115
+ token: channelTokenFile.token,
116
+ tokenSource: channelTokenFile.tokenSource,
117
+ tokenStatus: channelTokenFile.tokenStatus,
118
+ configured: channelTokenFile.tokenStatus !== "missing",
119
+ config: merged,
120
+ };
121
+ }
122
+ const channelToken = inspectTokenValue({
123
+ cfg: params.cfg,
124
+ value: params.cfg.channels?.telegram?.botToken,
125
+ });
126
+ if (channelToken) {
127
+ return {
128
+ accountId,
129
+ enabled,
130
+ name: merged.name?.trim() || undefined,
131
+ token: channelToken.token,
132
+ tokenSource: channelToken.tokenSource,
133
+ tokenStatus: channelToken.tokenStatus,
134
+ configured: channelToken.tokenStatus !== "missing",
135
+ config: merged,
136
+ };
137
+ }
138
+ const allowEnv = accountId === DEFAULT_ACCOUNT_ID;
139
+ const envToken = allowEnv ? (params.envToken ?? process.env.TELEGRAM_BOT_TOKEN)?.trim() : "";
140
+ if (envToken) {
141
+ return {
142
+ accountId,
143
+ enabled,
144
+ name: merged.name?.trim() || undefined,
145
+ token: envToken,
146
+ tokenSource: "env",
147
+ tokenStatus: "available",
148
+ configured: true,
149
+ config: merged,
150
+ };
151
+ }
152
+ return {
153
+ accountId,
154
+ enabled,
155
+ name: merged.name?.trim() || undefined,
156
+ token: "",
157
+ tokenSource: "none",
158
+ tokenStatus: "missing",
159
+ configured: false,
160
+ config: merged,
161
+ };
162
+ }
163
+ export function inspectTelegramAccount(params) {
164
+ return resolveAccountWithDefaultFallback({
165
+ accountId: params.accountId,
166
+ normalizeAccountId,
167
+ resolvePrimary: (accountId) => inspectTelegramAccountPrimary({
168
+ cfg: params.cfg,
169
+ accountId,
170
+ envToken: params.envToken,
171
+ }),
172
+ hasCredential: (account) => account.tokenSource !== "none",
173
+ resolveDefaultAccountId: () => resolveDefaultTelegramAccountId(params.cfg),
174
+ });
175
+ }
@@ -0,0 +1,10 @@
1
+ export function normalizeTelegramAllowFromEntry(raw) {
2
+ const base = typeof raw === "string" ? raw : typeof raw === "number" ? String(raw) : "";
3
+ return base
4
+ .trim()
5
+ .replace(/^(telegram|tg):/i, "")
6
+ .trim();
7
+ }
8
+ export function isNumericTelegramUserId(raw) {
9
+ return /^-?\d+$/.test(raw);
10
+ }
@@ -0,0 +1,18 @@
1
+ export async function fetchTelegramChatId(params) {
2
+ const url = `https://api.telegram.org/bot${params.token}/getChat?chat_id=${encodeURIComponent(params.chatId)}`;
3
+ try {
4
+ const res = await fetch(url, params.signal ? { signal: params.signal } : undefined);
5
+ if (!res.ok) {
6
+ return null;
7
+ }
8
+ const data = (await res.json().catch(() => null));
9
+ const id = data?.ok ? data?.result?.id : undefined;
10
+ if (typeof id === "number" || typeof id === "string") {
11
+ return String(id);
12
+ }
13
+ return null;
14
+ }
15
+ catch {
16
+ return null;
17
+ }
18
+ }
@@ -0,0 +1,30 @@
1
+ const MAX_CALLBACK_DATA_BYTES = 64;
2
+ function fitsCallbackData(value) {
3
+ return Buffer.byteLength(value, "utf8") <= MAX_CALLBACK_DATA_BYTES;
4
+ }
5
+ export function buildTelegramExecApprovalButtons(approvalId) {
6
+ return buildTelegramExecApprovalButtonsForDecisions(approvalId, [
7
+ "allow-once",
8
+ "allow-always",
9
+ "deny",
10
+ ]);
11
+ }
12
+ function buildTelegramExecApprovalButtonsForDecisions(approvalId, allowedDecisions) {
13
+ const allowOnce = `/approve ${approvalId} allow-once`;
14
+ if (!allowedDecisions.includes("allow-once") || !fitsCallbackData(allowOnce)) {
15
+ return undefined;
16
+ }
17
+ const primaryRow = [
18
+ { text: "Allow Once", callback_data: allowOnce },
19
+ ];
20
+ const allowAlways = `/approve ${approvalId} allow-always`;
21
+ if (allowedDecisions.includes("allow-always") && fitsCallbackData(allowAlways)) {
22
+ primaryRow.push({ text: "Allow Always", callback_data: allowAlways });
23
+ }
24
+ const rows = [primaryRow];
25
+ const deny = `/approve ${approvalId} deny`;
26
+ if (allowedDecisions.includes("deny") && fitsCallbackData(deny)) {
27
+ rows.push([{ text: "Deny", callback_data: deny }]);
28
+ }
29
+ return rows;
30
+ }
@@ -0,0 +1,61 @@
1
+ import { isRecord } from "../../../src/utils.js";
2
+ import { fetchWithTimeout } from "../../../src/utils/fetch-timeout.js";
3
+ import { resolveTelegramFetch } from "./fetch.js";
4
+ import { makeProxyFetch } from "./proxy.js";
5
+ const TELEGRAM_API_BASE = "https://api.telegram.org";
6
+ export async function auditTelegramGroupMembershipImpl(params) {
7
+ const proxyFetch = params.proxyUrl ? makeProxyFetch(params.proxyUrl) : undefined;
8
+ const fetcher = resolveTelegramFetch(proxyFetch, { network: params.network });
9
+ const base = `${TELEGRAM_API_BASE}/bot${params.token}`;
10
+ const groups = [];
11
+ for (const chatId of params.groupIds) {
12
+ try {
13
+ const url = `${base}/getChatMember?chat_id=${encodeURIComponent(chatId)}&user_id=${encodeURIComponent(String(params.botId))}`;
14
+ const res = await fetchWithTimeout(url, {}, params.timeoutMs, fetcher);
15
+ const json = (await res.json());
16
+ if (!res.ok || !isRecord(json) || !json.ok) {
17
+ const desc = isRecord(json) && !json.ok && typeof json.description === "string"
18
+ ? json.description
19
+ : `getChatMember failed (${res.status})`;
20
+ groups.push({
21
+ chatId,
22
+ ok: false,
23
+ status: null,
24
+ error: desc,
25
+ matchKey: chatId,
26
+ matchSource: "id",
27
+ });
28
+ continue;
29
+ }
30
+ const status = isRecord(json.result)
31
+ ? (json.result.status ?? null)
32
+ : null;
33
+ const ok = status === "creator" || status === "administrator" || status === "member";
34
+ groups.push({
35
+ chatId,
36
+ ok,
37
+ status,
38
+ error: ok ? null : "bot not in group",
39
+ matchKey: chatId,
40
+ matchSource: "id",
41
+ });
42
+ }
43
+ catch (err) {
44
+ groups.push({
45
+ chatId,
46
+ ok: false,
47
+ status: null,
48
+ error: err instanceof Error ? err.message : String(err),
49
+ matchKey: chatId,
50
+ matchSource: "id",
51
+ });
52
+ }
53
+ }
54
+ return {
55
+ ok: groups.every((g) => g.ok),
56
+ checkedGroups: groups.length,
57
+ unresolvedGroups: 0,
58
+ hasWildcardUnmentionedGroups: false,
59
+ groups,
60
+ };
61
+ }