@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,413 @@
1
+ import { listDiscordAccountIds, resolveDefaultDiscordAccountId, resolveDiscordAccount, } from "../../../discord/accounts.js";
2
+ import { normalizeDiscordSlug } from "../../../discord/monitor/allow-list.js";
3
+ import { resolveDiscordUserAllowlist } from "../../../discord/resolve-users.js";
4
+ import { resolveDiscordChannelAllowlist, } from "../../../discord/resolve-channels.js";
5
+ import { DEFAULT_ACCOUNT_ID, normalizeAccountId } from "../../../routing/session-key.js";
6
+ import { formatDocsLink } from "../../../terminal/links.js";
7
+ import { promptChannelAccessConfig } from "./channel-access.js";
8
+ import { addWildcardAllowFrom, promptAccountId } from "./helpers.js";
9
+ const channel = "discord";
10
+ function setDiscordDmPolicy(cfg, dmPolicy) {
11
+ const allowFrom = dmPolicy === "open" ? addWildcardAllowFrom(cfg.channels?.discord?.dm?.allowFrom) : undefined;
12
+ return {
13
+ ...cfg,
14
+ channels: {
15
+ ...cfg.channels,
16
+ discord: {
17
+ ...cfg.channels?.discord,
18
+ dm: {
19
+ ...cfg.channels?.discord?.dm,
20
+ enabled: cfg.channels?.discord?.dm?.enabled ?? true,
21
+ policy: dmPolicy,
22
+ ...(allowFrom ? { allowFrom } : {}),
23
+ },
24
+ },
25
+ },
26
+ };
27
+ }
28
+ async function noteDiscordTokenHelp(prompter) {
29
+ await prompter.note([
30
+ "1) Discord Developer Portal → Applications → New Application",
31
+ "2) Bot → Add Bot → Reset Token → copy token",
32
+ "3) OAuth2 → URL Generator → scope 'bot' → invite to your server",
33
+ "Tip: enable Message Content Intent if you need message text. (Bot → Privileged Gateway Intents → Message Content Intent)",
34
+ `Docs: ${formatDocsLink("/discord", "discord")}`,
35
+ ].join("\n"), "Discord bot token");
36
+ }
37
+ function setDiscordGroupPolicy(cfg, accountId, groupPolicy) {
38
+ if (accountId === DEFAULT_ACCOUNT_ID) {
39
+ return {
40
+ ...cfg,
41
+ channels: {
42
+ ...cfg.channels,
43
+ discord: {
44
+ ...cfg.channels?.discord,
45
+ enabled: true,
46
+ groupPolicy,
47
+ },
48
+ },
49
+ };
50
+ }
51
+ return {
52
+ ...cfg,
53
+ channels: {
54
+ ...cfg.channels,
55
+ discord: {
56
+ ...cfg.channels?.discord,
57
+ enabled: true,
58
+ accounts: {
59
+ ...cfg.channels?.discord?.accounts,
60
+ [accountId]: {
61
+ ...cfg.channels?.discord?.accounts?.[accountId],
62
+ enabled: cfg.channels?.discord?.accounts?.[accountId]?.enabled ?? true,
63
+ groupPolicy,
64
+ },
65
+ },
66
+ },
67
+ },
68
+ };
69
+ }
70
+ function setDiscordGuildChannelAllowlist(cfg, accountId, entries) {
71
+ const baseGuilds = accountId === DEFAULT_ACCOUNT_ID
72
+ ? (cfg.channels?.discord?.guilds ?? {})
73
+ : (cfg.channels?.discord?.accounts?.[accountId]?.guilds ?? {});
74
+ const guilds = { ...baseGuilds };
75
+ for (const entry of entries) {
76
+ const guildKey = entry.guildKey || "*";
77
+ const existing = guilds[guildKey] ?? {};
78
+ if (entry.channelKey) {
79
+ const channels = { ...existing.channels };
80
+ channels[entry.channelKey] = { allow: true };
81
+ guilds[guildKey] = { ...existing, channels };
82
+ }
83
+ else {
84
+ guilds[guildKey] = existing;
85
+ }
86
+ }
87
+ if (accountId === DEFAULT_ACCOUNT_ID) {
88
+ return {
89
+ ...cfg,
90
+ channels: {
91
+ ...cfg.channels,
92
+ discord: {
93
+ ...cfg.channels?.discord,
94
+ enabled: true,
95
+ guilds,
96
+ },
97
+ },
98
+ };
99
+ }
100
+ return {
101
+ ...cfg,
102
+ channels: {
103
+ ...cfg.channels,
104
+ discord: {
105
+ ...cfg.channels?.discord,
106
+ enabled: true,
107
+ accounts: {
108
+ ...cfg.channels?.discord?.accounts,
109
+ [accountId]: {
110
+ ...cfg.channels?.discord?.accounts?.[accountId],
111
+ enabled: cfg.channels?.discord?.accounts?.[accountId]?.enabled ?? true,
112
+ guilds,
113
+ },
114
+ },
115
+ },
116
+ },
117
+ };
118
+ }
119
+ function setDiscordAllowFrom(cfg, allowFrom) {
120
+ return {
121
+ ...cfg,
122
+ channels: {
123
+ ...cfg.channels,
124
+ discord: {
125
+ ...cfg.channels?.discord,
126
+ dm: {
127
+ ...cfg.channels?.discord?.dm,
128
+ enabled: cfg.channels?.discord?.dm?.enabled ?? true,
129
+ allowFrom,
130
+ },
131
+ },
132
+ },
133
+ };
134
+ }
135
+ function parseDiscordAllowFromInput(raw) {
136
+ return raw
137
+ .split(/[\n,;]+/g)
138
+ .map((entry) => entry.trim())
139
+ .filter(Boolean);
140
+ }
141
+ async function promptDiscordAllowFrom(params) {
142
+ const accountId = params.accountId && normalizeAccountId(params.accountId)
143
+ ? (normalizeAccountId(params.accountId) ?? DEFAULT_ACCOUNT_ID)
144
+ : resolveDefaultDiscordAccountId(params.cfg);
145
+ const resolved = resolveDiscordAccount({ cfg: params.cfg, accountId });
146
+ const token = resolved.token;
147
+ const existing = params.cfg.channels?.discord?.dm?.allowFrom ?? [];
148
+ await params.prompter.note([
149
+ "Allowlist Discord DMs by username (we resolve to user ids).",
150
+ "Examples:",
151
+ "- 123456789012345678",
152
+ "- @alice",
153
+ "- alice#1234",
154
+ "Multiple entries: comma-separated.",
155
+ `Docs: ${formatDocsLink("/discord", "discord")}`,
156
+ ].join("\n"), "Discord allowlist");
157
+ const parseInputs = (value) => parseDiscordAllowFromInput(value);
158
+ const parseId = (value) => {
159
+ const trimmed = value.trim();
160
+ if (!trimmed)
161
+ return null;
162
+ const mention = trimmed.match(/^<@!?(\d+)>$/);
163
+ if (mention)
164
+ return mention[1];
165
+ const prefixed = trimmed.replace(/^(user:|discord:)/i, "");
166
+ if (/^\d+$/.test(prefixed))
167
+ return prefixed;
168
+ return null;
169
+ };
170
+ while (true) {
171
+ const entry = await params.prompter.text({
172
+ message: "Discord allowFrom (usernames or ids)",
173
+ placeholder: "@alice, 123456789012345678",
174
+ initialValue: existing[0] ? String(existing[0]) : undefined,
175
+ validate: (value) => (String(value ?? "").trim() ? undefined : "Required"),
176
+ });
177
+ const parts = parseInputs(String(entry));
178
+ if (!token) {
179
+ const ids = parts.map(parseId).filter(Boolean);
180
+ if (ids.length !== parts.length) {
181
+ await params.prompter.note("Bot token missing; use numeric user ids (or mention form) only.", "Discord allowlist");
182
+ continue;
183
+ }
184
+ const unique = [...new Set([...existing.map((v) => String(v).trim()), ...ids])].filter(Boolean);
185
+ return setDiscordAllowFrom(params.cfg, unique);
186
+ }
187
+ const results = await resolveDiscordUserAllowlist({
188
+ token,
189
+ entries: parts,
190
+ }).catch(() => null);
191
+ if (!results) {
192
+ await params.prompter.note("Failed to resolve usernames. Try again.", "Discord allowlist");
193
+ continue;
194
+ }
195
+ const unresolved = results.filter((res) => !res.resolved || !res.id);
196
+ if (unresolved.length > 0) {
197
+ await params.prompter.note(`Could not resolve: ${unresolved.map((res) => res.input).join(", ")}`, "Discord allowlist");
198
+ continue;
199
+ }
200
+ const ids = results.map((res) => res.id);
201
+ const unique = [...new Set([...existing.map((v) => String(v).trim()).filter(Boolean), ...ids])];
202
+ return setDiscordAllowFrom(params.cfg, unique);
203
+ }
204
+ }
205
+ const dmPolicy = {
206
+ label: "Discord",
207
+ channel,
208
+ policyKey: "channels.discord.dm.policy",
209
+ allowFromKey: "channels.discord.dm.allowFrom",
210
+ getCurrent: (cfg) => cfg.channels?.discord?.dm?.policy ?? "pairing",
211
+ setPolicy: (cfg, policy) => setDiscordDmPolicy(cfg, policy),
212
+ promptAllowFrom: promptDiscordAllowFrom,
213
+ };
214
+ export const discordOnboardingAdapter = {
215
+ channel,
216
+ getStatus: async ({ cfg }) => {
217
+ const configured = listDiscordAccountIds(cfg).some((accountId) => Boolean(resolveDiscordAccount({ cfg, accountId }).token));
218
+ return {
219
+ channel,
220
+ configured,
221
+ statusLines: [`Discord: ${configured ? "configured" : "needs token"}`],
222
+ selectionHint: configured ? "configured" : "needs token",
223
+ quickstartScore: configured ? 2 : 1,
224
+ };
225
+ },
226
+ configure: async ({ cfg, prompter, accountOverrides, shouldPromptAccountIds }) => {
227
+ const discordOverride = accountOverrides.discord?.trim();
228
+ const defaultDiscordAccountId = resolveDefaultDiscordAccountId(cfg);
229
+ let discordAccountId = discordOverride
230
+ ? normalizeAccountId(discordOverride)
231
+ : defaultDiscordAccountId;
232
+ if (shouldPromptAccountIds && !discordOverride) {
233
+ discordAccountId = await promptAccountId({
234
+ cfg,
235
+ prompter,
236
+ label: "Discord",
237
+ currentId: discordAccountId,
238
+ listAccountIds: listDiscordAccountIds,
239
+ defaultAccountId: defaultDiscordAccountId,
240
+ });
241
+ }
242
+ let next = cfg;
243
+ const resolvedAccount = resolveDiscordAccount({
244
+ cfg: next,
245
+ accountId: discordAccountId,
246
+ });
247
+ const accountConfigured = Boolean(resolvedAccount.token);
248
+ const allowEnv = discordAccountId === DEFAULT_ACCOUNT_ID;
249
+ const canUseEnv = allowEnv && Boolean(process.env.DISCORD_BOT_TOKEN?.trim());
250
+ const hasConfigToken = Boolean(resolvedAccount.config.token);
251
+ let token = null;
252
+ if (!accountConfigured) {
253
+ await noteDiscordTokenHelp(prompter);
254
+ }
255
+ if (canUseEnv && !resolvedAccount.config.token) {
256
+ const keepEnv = await prompter.confirm({
257
+ message: "DISCORD_BOT_TOKEN detected. Use env var?",
258
+ initialValue: true,
259
+ });
260
+ if (keepEnv) {
261
+ next = {
262
+ ...next,
263
+ channels: {
264
+ ...next.channels,
265
+ discord: { ...next.channels?.discord, enabled: true },
266
+ },
267
+ };
268
+ }
269
+ else {
270
+ token = String(await prompter.text({
271
+ message: "Enter Discord bot token",
272
+ validate: (value) => (value?.trim() ? undefined : "Required"),
273
+ })).trim();
274
+ }
275
+ }
276
+ else if (hasConfigToken) {
277
+ const keep = await prompter.confirm({
278
+ message: "Discord token already configured. Keep it?",
279
+ initialValue: true,
280
+ });
281
+ if (!keep) {
282
+ token = String(await prompter.text({
283
+ message: "Enter Discord bot token",
284
+ validate: (value) => (value?.trim() ? undefined : "Required"),
285
+ })).trim();
286
+ }
287
+ }
288
+ else {
289
+ token = String(await prompter.text({
290
+ message: "Enter Discord bot token",
291
+ validate: (value) => (value?.trim() ? undefined : "Required"),
292
+ })).trim();
293
+ }
294
+ if (token) {
295
+ if (discordAccountId === DEFAULT_ACCOUNT_ID) {
296
+ next = {
297
+ ...next,
298
+ channels: {
299
+ ...next.channels,
300
+ discord: { ...next.channels?.discord, enabled: true, token },
301
+ },
302
+ };
303
+ }
304
+ else {
305
+ next = {
306
+ ...next,
307
+ channels: {
308
+ ...next.channels,
309
+ discord: {
310
+ ...next.channels?.discord,
311
+ enabled: true,
312
+ accounts: {
313
+ ...next.channels?.discord?.accounts,
314
+ [discordAccountId]: {
315
+ ...next.channels?.discord?.accounts?.[discordAccountId],
316
+ enabled: next.channels?.discord?.accounts?.[discordAccountId]?.enabled ?? true,
317
+ token,
318
+ },
319
+ },
320
+ },
321
+ },
322
+ };
323
+ }
324
+ }
325
+ const currentEntries = Object.entries(resolvedAccount.config.guilds ?? {}).flatMap(([guildKey, value]) => {
326
+ const channels = value?.channels ?? {};
327
+ const channelKeys = Object.keys(channels);
328
+ if (channelKeys.length === 0)
329
+ return [guildKey];
330
+ return channelKeys.map((channelKey) => `${guildKey}/${channelKey}`);
331
+ });
332
+ const accessConfig = await promptChannelAccessConfig({
333
+ prompter,
334
+ label: "Discord channels",
335
+ currentPolicy: resolvedAccount.config.groupPolicy ?? "allowlist",
336
+ currentEntries,
337
+ placeholder: "My Server/#general, guildId/channelId, #support",
338
+ updatePrompt: Boolean(resolvedAccount.config.guilds),
339
+ });
340
+ if (accessConfig) {
341
+ if (accessConfig.policy !== "allowlist") {
342
+ next = setDiscordGroupPolicy(next, discordAccountId, accessConfig.policy);
343
+ }
344
+ else {
345
+ const accountWithTokens = resolveDiscordAccount({
346
+ cfg: next,
347
+ accountId: discordAccountId,
348
+ });
349
+ let resolved = accessConfig.entries.map((input) => ({
350
+ input,
351
+ resolved: false,
352
+ }));
353
+ if (accountWithTokens.token && accessConfig.entries.length > 0) {
354
+ try {
355
+ resolved = await resolveDiscordChannelAllowlist({
356
+ token: accountWithTokens.token,
357
+ entries: accessConfig.entries,
358
+ });
359
+ const resolvedChannels = resolved.filter((entry) => entry.resolved && entry.channelId);
360
+ const resolvedGuilds = resolved.filter((entry) => entry.resolved && entry.guildId && !entry.channelId);
361
+ const unresolved = resolved
362
+ .filter((entry) => !entry.resolved)
363
+ .map((entry) => entry.input);
364
+ if (resolvedChannels.length > 0 || resolvedGuilds.length > 0 || unresolved.length > 0) {
365
+ const summary = [];
366
+ if (resolvedChannels.length > 0) {
367
+ summary.push(`Resolved channels: ${resolvedChannels
368
+ .map((entry) => entry.channelId)
369
+ .filter(Boolean)
370
+ .join(", ")}`);
371
+ }
372
+ if (resolvedGuilds.length > 0) {
373
+ summary.push(`Resolved guilds: ${resolvedGuilds
374
+ .map((entry) => entry.guildId)
375
+ .filter(Boolean)
376
+ .join(", ")}`);
377
+ }
378
+ if (unresolved.length > 0) {
379
+ summary.push(`Unresolved (kept as typed): ${unresolved.join(", ")}`);
380
+ }
381
+ await prompter.note(summary.join("\n"), "Discord channels");
382
+ }
383
+ }
384
+ catch (err) {
385
+ await prompter.note(`Channel lookup failed; keeping entries as typed. ${String(err)}`, "Discord channels");
386
+ }
387
+ }
388
+ const allowlistEntries = [];
389
+ for (const entry of resolved) {
390
+ const guildKey = entry.guildId ??
391
+ (entry.guildName ? normalizeDiscordSlug(entry.guildName) : undefined) ??
392
+ "*";
393
+ const channelKey = entry.channelId ??
394
+ (entry.channelName ? normalizeDiscordSlug(entry.channelName) : undefined);
395
+ if (!channelKey && guildKey === "*")
396
+ continue;
397
+ allowlistEntries.push({ guildKey, ...(channelKey ? { channelKey } : {}) });
398
+ }
399
+ next = setDiscordGroupPolicy(next, discordAccountId, "allowlist");
400
+ next = setDiscordGuildChannelAllowlist(next, discordAccountId, allowlistEntries);
401
+ }
402
+ }
403
+ return { cfg: next, accountId: discordAccountId };
404
+ },
405
+ dmPolicy,
406
+ disable: (cfg) => ({
407
+ ...cfg,
408
+ channels: {
409
+ ...cfg.channels,
410
+ discord: { ...cfg.channels?.discord, enabled: false },
411
+ },
412
+ }),
413
+ };