@poolzin/pool-bot 2026.2.21 → 2026.2.22

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 (369) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/dist/agents/api-key-rotation.js +47 -0
  3. package/dist/agents/apply-patch-update.js +19 -9
  4. package/dist/agents/apply-patch.js +72 -47
  5. package/dist/agents/bash-tools.exec.js +141 -559
  6. package/dist/agents/cli-backends.js +49 -6
  7. package/dist/agents/cli-runner/helpers.js +69 -152
  8. package/dist/agents/cli-runner.js +70 -19
  9. package/dist/agents/identity.js +20 -1
  10. package/dist/agents/image-sanitization.js +9 -0
  11. package/dist/agents/live-auth-keys.js +123 -26
  12. package/dist/agents/live-model-filter.js +13 -4
  13. package/dist/agents/model-catalog.js +40 -9
  14. package/dist/agents/model-forward-compat.js +60 -23
  15. package/dist/agents/model-selection.js +134 -41
  16. package/dist/agents/pi-auth-json.js +2 -2
  17. package/dist/agents/pi-embedded-helpers/bootstrap.js +65 -15
  18. package/dist/agents/pi-embedded-helpers/errors.js +140 -15
  19. package/dist/agents/pi-embedded-helpers/images.js +22 -12
  20. package/dist/agents/pi-embedded-helpers.js +2 -2
  21. package/dist/agents/pi-embedded-runner/abort.js +10 -3
  22. package/dist/agents/pi-embedded-runner/compact.js +230 -32
  23. package/dist/agents/pi-embedded-runner/extra-params.js +203 -12
  24. package/dist/agents/pi-embedded-runner/google.js +109 -19
  25. package/dist/agents/pi-embedded-runner/history.js +35 -17
  26. package/dist/agents/pi-embedded-runner/run/attempt.js +386 -95
  27. package/dist/agents/pi-embedded-runner/run/images.js +81 -55
  28. package/dist/agents/pi-embedded-runner/run/payloads.js +89 -39
  29. package/dist/agents/pi-embedded-runner/run.js +193 -25
  30. package/dist/agents/pi-embedded-runner/run.overflow-compaction.mocks.shared.js +2 -2
  31. package/dist/agents/pi-embedded-runner/runs.js +17 -8
  32. package/dist/agents/pi-embedded-runner/tool-result-context-guard.js +262 -0
  33. package/dist/agents/pi-embedded-runner.js +1 -1
  34. package/dist/agents/pi-embedded-subscribe.handlers.tools.js +180 -10
  35. package/dist/agents/pi-embedded-subscribe.js +37 -0
  36. package/dist/agents/pi-embedded-subscribe.tools.js +127 -30
  37. package/dist/agents/pi-model-discovery.js +9 -2
  38. package/dist/agents/pi-tool-definition-adapter.js +60 -8
  39. package/dist/agents/pi-tools.before-tool-call.js +1 -1
  40. package/dist/agents/pi-tools.js +113 -94
  41. package/dist/agents/pi-tools.read.js +337 -38
  42. package/dist/agents/poolbot-tools.js +14 -5
  43. package/dist/agents/sandbox/docker.js +10 -5
  44. package/dist/agents/sandbox/registry.js +96 -46
  45. package/dist/agents/sandbox/sanitize-env-vars.js +82 -0
  46. package/dist/agents/sandbox-paths.js +43 -10
  47. package/dist/agents/session-tool-result-guard-wrapper.js +23 -11
  48. package/dist/agents/session-tool-result-guard.js +39 -39
  49. package/dist/agents/session-transcript-repair.js +36 -33
  50. package/dist/agents/session-write-lock.js +62 -44
  51. package/dist/agents/skills/frontmatter.js +49 -88
  52. package/dist/agents/skills/workspace.js +335 -28
  53. package/dist/agents/subagent-announce.js +508 -174
  54. package/dist/agents/subagent-registry.js +45 -4
  55. package/dist/agents/subagent-spawn.js +16 -33
  56. package/dist/agents/system-prompt-report.js +27 -10
  57. package/dist/agents/system-prompt.js +26 -32
  58. package/dist/agents/tool-call-id.js +69 -17
  59. package/dist/agents/tool-display-common.js +1 -1
  60. package/dist/agents/tool-images.js +64 -31
  61. package/dist/agents/tools/canvas-tool.js +17 -11
  62. package/dist/agents/tools/common.js +37 -19
  63. package/dist/agents/tools/cron-tool.js +40 -38
  64. package/dist/agents/tools/gateway.js +70 -2
  65. package/dist/agents/tools/message-tool.js +181 -40
  66. package/dist/agents/tools/nodes-tool.js +128 -36
  67. package/dist/agents/tools/nodes-utils.js +12 -38
  68. package/dist/agents/tools/session-status-tool.js +24 -71
  69. package/dist/agents/tools/sessions-helpers.js +38 -210
  70. package/dist/agents/tools/sessions-spawn-tool.js +28 -198
  71. package/dist/agents/tools/telegram-actions.js +58 -7
  72. package/dist/agents/tools/web-fetch-utils.js +112 -7
  73. package/dist/agents/tools/web-fetch.js +279 -175
  74. package/dist/agents/tools/web-shared.js +71 -8
  75. package/dist/agents/usage.js +25 -16
  76. package/dist/auto-reply/commands-registry.data.js +85 -11
  77. package/dist/auto-reply/dispatch.js +40 -21
  78. package/dist/auto-reply/reply/abort.js +102 -33
  79. package/dist/auto-reply/reply/commands-core.js +82 -33
  80. package/dist/auto-reply/reply/commands-export-session.js +1 -1
  81. package/dist/auto-reply/reply/commands-info.js +41 -12
  82. package/dist/auto-reply/reply/commands-subagents.js +352 -100
  83. package/dist/auto-reply/reply/commands-system-prompt.js +2 -2
  84. package/dist/auto-reply/reply/dispatch-from-config.js +100 -29
  85. package/dist/auto-reply/reply/elevated-unavailable.js +1 -1
  86. package/dist/auto-reply/reply/inbound-meta.js +12 -1
  87. package/dist/auto-reply/reply/mentions.js +18 -11
  88. package/dist/auto-reply/reply/normalize-reply.js +17 -8
  89. package/dist/auto-reply/reply/reply-dispatcher.js +62 -10
  90. package/dist/auto-reply/reply/session.js +102 -21
  91. package/dist/auto-reply/reply/streaming-directives.js +16 -5
  92. package/dist/auto-reply/status.js +73 -50
  93. package/dist/browser/extension-relay.js +3 -3
  94. package/dist/browser/http-auth.js +1 -1
  95. package/dist/browser/paths.js +2 -2
  96. package/dist/build-info.json +3 -3
  97. package/dist/channels/allowlist-match.js +20 -0
  98. package/dist/channels/allowlists/resolve-utils.js +65 -2
  99. package/dist/channels/chat-type.js +8 -4
  100. package/dist/channels/dock.js +127 -35
  101. package/dist/channels/draft-stream-loop.js +6 -2
  102. package/dist/channels/plugins/actions/telegram.js +42 -18
  103. package/dist/channels/plugins/allowlist-match.js +1 -1
  104. package/dist/channels/plugins/group-mentions.js +51 -41
  105. package/dist/channels/plugins/message-action-names.js +2 -0
  106. package/dist/channels/plugins/message-actions.js +24 -5
  107. package/dist/channels/plugins/normalize/discord.js +26 -4
  108. package/dist/channels/plugins/normalize/signal.js +35 -22
  109. package/dist/channels/plugins/onboarding/helpers.js +8 -26
  110. package/dist/channels/plugins/outbound/imessage.js +15 -14
  111. package/dist/channels/registry.js +20 -7
  112. package/dist/cli/acp-cli.js +7 -5
  113. package/dist/cli/browser-cli-extension.js +25 -12
  114. package/dist/cli/browser-cli-state.cookies-storage.js +25 -6
  115. package/dist/cli/browser-cli-state.js +101 -145
  116. package/dist/cli/command-options.js +28 -0
  117. package/dist/cli/completion-cli.js +6 -6
  118. package/dist/cli/cron-cli/register.cron-add.js +25 -1
  119. package/dist/cli/cron-cli/register.cron-edit.js +44 -0
  120. package/dist/cli/cron-cli/shared.js +7 -1
  121. package/dist/cli/daemon-cli/lifecycle-core.js +23 -21
  122. package/dist/cli/daemon-cli/lifecycle.js +23 -247
  123. package/dist/cli/daemon-cli/register-service-commands.js +25 -4
  124. package/dist/cli/daemon-cli.js +1 -0
  125. package/dist/cli/devices-cli.js +33 -20
  126. package/dist/cli/gateway-cli/register.js +37 -105
  127. package/dist/cli/gateway-cli/run.js +49 -11
  128. package/dist/cli/nodes-camera.js +59 -4
  129. package/dist/cli/nodes-cli/register.camera.js +27 -24
  130. package/dist/cli/nodes-cli/rpc.js +21 -38
  131. package/dist/cli/qr-cli.js +2 -2
  132. package/dist/cli/skills-cli.format.js +2 -2
  133. package/dist/cli/update-cli/progress.js +2 -2
  134. package/dist/cli/update-cli/restart-helper.js +28 -7
  135. package/dist/cli/update-cli/shared.js +7 -7
  136. package/dist/cli/update-cli/status.js +1 -1
  137. package/dist/cli/update-cli/update-command.js +14 -8
  138. package/dist/cli/update-cli/wizard.js +2 -2
  139. package/dist/cli/update-cli.js +21 -1027
  140. package/dist/commands/auth-choice.apply.anthropic.js +10 -2
  141. package/dist/commands/channels/add-mutators.js +3 -35
  142. package/dist/commands/channels/add.js +39 -51
  143. package/dist/commands/config-validation.js +1 -1
  144. package/dist/commands/configure.gateway-auth.js +52 -15
  145. package/dist/commands/configure.gateway.js +84 -40
  146. package/dist/commands/doctor-completion.js +3 -3
  147. package/dist/commands/doctor-config-flow.js +536 -16
  148. package/dist/commands/doctor-gateway-services.js +103 -79
  149. package/dist/commands/doctor-memory-search.js +9 -9
  150. package/dist/commands/doctor-platform-notes.js +57 -30
  151. package/dist/commands/doctor-prompter.js +26 -15
  152. package/dist/commands/doctor-session-locks.js +1 -1
  153. package/dist/commands/doctor.js +21 -9
  154. package/dist/commands/model-picker.js +120 -95
  155. package/dist/commands/models/set.js +2 -21
  156. package/dist/commands/models/shared.js +65 -37
  157. package/dist/commands/onboard-helpers.js +81 -39
  158. package/dist/commands/openai-codex-oauth.js +1 -1
  159. package/dist/commands/sessions.js +52 -53
  160. package/dist/commands/status.summary.js +52 -34
  161. package/dist/commands/test-wizard-helpers.js +2 -2
  162. package/dist/config/defaults.js +79 -42
  163. package/dist/config/group-policy.js +50 -18
  164. package/dist/config/includes.js +37 -10
  165. package/dist/config/schema.help.js +5 -4
  166. package/dist/config/schema.hints.js +2 -2
  167. package/dist/config/schema.labels.js +1 -0
  168. package/dist/config/sessions/group.js +12 -11
  169. package/dist/config/sessions/paths.js +137 -11
  170. package/dist/config/sessions/store.js +185 -65
  171. package/dist/config/sessions/types.js +15 -1
  172. package/dist/config/sessions.js +1 -0
  173. package/dist/config/telegram-custom-commands.js +3 -2
  174. package/dist/config/types.js +2 -0
  175. package/dist/config/zod-schema.agent-defaults.js +6 -27
  176. package/dist/config/zod-schema.agent-runtime.js +171 -79
  177. package/dist/config/zod-schema.providers-core.js +138 -65
  178. package/dist/config/zod-schema.session.js +49 -22
  179. package/dist/control-ui/assets/index-HRr1grwl.js.map +1 -1
  180. package/dist/cron/isolated-agent/run.js +224 -57
  181. package/dist/cron/normalize.js +48 -45
  182. package/dist/cron/run-log.js +14 -0
  183. package/dist/cron/service/jobs.js +190 -28
  184. package/dist/cron/service/normalize.js +29 -11
  185. package/dist/cron/service/store.js +30 -44
  186. package/dist/cron/service/timer.js +182 -96
  187. package/dist/cron/service.js +3 -0
  188. package/dist/cron/stagger.js +37 -0
  189. package/dist/daemon/inspect.js +132 -92
  190. package/dist/daemon/runtime-paths.js +25 -4
  191. package/dist/daemon/service-audit.js +47 -16
  192. package/dist/discord/accounts.js +23 -20
  193. package/dist/discord/monitor/agent-components.js +1115 -219
  194. package/dist/discord/monitor/allow-list.js +114 -34
  195. package/dist/discord/monitor/listeners.js +204 -97
  196. package/dist/discord/monitor/message-handler.js +21 -10
  197. package/dist/discord/monitor/message-handler.preflight.js +195 -101
  198. package/dist/discord/monitor/message-handler.process.js +384 -123
  199. package/dist/discord/monitor/message-utils.js +86 -23
  200. package/dist/discord/monitor/native-command.js +77 -57
  201. package/dist/discord/monitor/provider.js +122 -117
  202. package/dist/discord/monitor/reply-context.js +20 -16
  203. package/dist/discord/monitor/reply-delivery.js +40 -8
  204. package/dist/discord/monitor/rest-fetch.js +22 -0
  205. package/dist/discord/monitor/threading.js +117 -24
  206. package/dist/discord/send.js +2 -1
  207. package/dist/discord/send.outbound.js +124 -11
  208. package/dist/discord/send.shared.js +112 -72
  209. package/dist/discord/voice-message.js +3 -3
  210. package/dist/gateway/auth.js +119 -44
  211. package/dist/gateway/call.js +76 -34
  212. package/dist/gateway/channel-health-monitor.js +57 -50
  213. package/dist/gateway/client.js +63 -29
  214. package/dist/gateway/control-ui-contract.js +1 -1
  215. package/dist/gateway/gateway-config-prompts.shared.js +2 -2
  216. package/dist/gateway/net.js +109 -1
  217. package/dist/gateway/protocol/index.js +5 -8
  218. package/dist/gateway/protocol/schema/agent.js +19 -1
  219. package/dist/gateway/protocol/schema/channels.js +21 -0
  220. package/dist/gateway/protocol/schema/cron.js +43 -30
  221. package/dist/gateway/protocol/schema/protocol-schemas.js +6 -11
  222. package/dist/gateway/protocol/schema/sessions.js +5 -1
  223. package/dist/gateway/protocol/schema.js +0 -1
  224. package/dist/gateway/server/presence-events.js +12 -0
  225. package/dist/gateway/server/ws-connection/message-handler.js +203 -212
  226. package/dist/gateway/server/ws-connection.js +58 -21
  227. package/dist/gateway/server-broadcast.js +18 -13
  228. package/dist/gateway/server-cron.js +177 -10
  229. package/dist/gateway/server-methods/agent-job.js +131 -38
  230. package/dist/gateway/server-methods/send.js +60 -14
  231. package/dist/gateway/server-methods/sessions.js +160 -96
  232. package/dist/gateway/server-methods/system.js +5 -7
  233. package/dist/gateway/server-methods-list.js +8 -0
  234. package/dist/gateway/server-methods.js +24 -8
  235. package/dist/gateway/server-node-events.js +278 -68
  236. package/dist/gateway/session-utils.fs.js +316 -75
  237. package/dist/gateway/session-utils.js +224 -70
  238. package/dist/gateway/sessions-patch.js +63 -20
  239. package/dist/gateway/test-temp-config.js +1 -1
  240. package/dist/gateway/tools-invoke-http.js +118 -70
  241. package/dist/gateway/ws-log.js +135 -107
  242. package/dist/hooks/frontmatter.js +36 -82
  243. package/dist/hooks/install.js +149 -139
  244. package/dist/hooks/internal-hooks.js +29 -4
  245. package/dist/hooks/plugin-hooks.js +2 -1
  246. package/dist/imessage/monitor/deliver.js +10 -4
  247. package/dist/imessage/monitor/monitor-provider.js +138 -375
  248. package/dist/imessage/monitor/runtime.js +4 -8
  249. package/dist/imessage/send.js +65 -19
  250. package/dist/infra/exec-approvals-allowlist.js +7 -0
  251. package/dist/infra/exec-approvals.js +35 -920
  252. package/dist/infra/exec-safe-bin-trust.js +64 -0
  253. package/dist/infra/heartbeat-runner.js +207 -134
  254. package/dist/infra/heartbeat-wake.js +183 -22
  255. package/dist/infra/install-source-utils.js +47 -0
  256. package/dist/infra/net/ssrf.js +170 -36
  257. package/dist/infra/outbound/deliver.js +224 -58
  258. package/dist/infra/outbound/message-action-spec.js +12 -5
  259. package/dist/infra/outbound/outbound-session.js +27 -25
  260. package/dist/infra/poolbot-root.js +32 -22
  261. package/dist/infra/ports.js +14 -11
  262. package/dist/infra/skills-remote.js +48 -37
  263. package/dist/infra/system-events.js +25 -11
  264. package/dist/infra/system-presence.js +26 -33
  265. package/dist/infra/tmp-poolbot-dir.js +81 -2
  266. package/dist/infra/wsl.js +37 -1
  267. package/dist/line/bot-message-context.js +163 -191
  268. package/dist/logging/subsystem.js +59 -22
  269. package/dist/markdown/ir.js +124 -50
  270. package/dist/media/store.js +1 -1
  271. package/dist/media-understanding/runner.entries.js +42 -25
  272. package/dist/media-understanding/runner.js +53 -488
  273. package/dist/memory/embeddings-gemini.js +53 -38
  274. package/dist/memory/manager-embedding-ops.js +48 -69
  275. package/dist/pairing/pairing-store.js +178 -119
  276. package/dist/plugin-sdk/index.js +34 -6
  277. package/dist/plugins/hooks.js +135 -14
  278. package/dist/plugins/install.js +190 -152
  279. package/dist/polls.js +11 -0
  280. package/dist/routing/resolve-route.js +190 -56
  281. package/dist/routing/session-key.js +38 -22
  282. package/dist/runtime.js +35 -9
  283. package/dist/security/audit-channel.js +1 -1
  284. package/dist/sessions/session-key-utils.js +29 -11
  285. package/dist/shared/frontmatter.js +5 -5
  286. package/dist/shared/node-list-types.js +1 -0
  287. package/dist/shared/string-normalization.js +15 -0
  288. package/dist/signal/monitor/event-handler.js +68 -36
  289. package/dist/signal/send.js +29 -37
  290. package/dist/slack/monitor/allow-list.js +10 -11
  291. package/dist/slack/monitor/commands.js +14 -3
  292. package/dist/slack/monitor/events/interactions.js +4 -4
  293. package/dist/slack/monitor/media.js +224 -16
  294. package/dist/slack/monitor/message-handler/dispatch.js +247 -13
  295. package/dist/slack/monitor/message-handler/prepare.js +128 -45
  296. package/dist/slack/monitor/slash.js +357 -144
  297. package/dist/slack/streaming.js +77 -0
  298. package/dist/telegram/accounts.js +40 -13
  299. package/dist/telegram/allowed-updates.js +3 -0
  300. package/dist/telegram/bot/delivery.js +129 -66
  301. package/dist/telegram/bot/helpers.js +136 -122
  302. package/dist/telegram/bot-handlers.js +600 -339
  303. package/dist/telegram/bot-message-context.js +115 -73
  304. package/dist/telegram/bot-message-dispatch.js +235 -104
  305. package/dist/telegram/bot-native-command-menu.js +3 -1
  306. package/dist/telegram/bot-native-commands.js +213 -193
  307. package/dist/telegram/bot.js +24 -132
  308. package/dist/telegram/draft-stream.js +84 -75
  309. package/dist/telegram/format.js +150 -6
  310. package/dist/telegram/send.js +415 -255
  311. package/dist/telegram/targets.js +21 -2
  312. package/dist/telegram/update-offset-store.js +19 -3
  313. package/dist/terminal/restore.js +5 -2
  314. package/dist/test-utils/fetch-mock.js +5 -0
  315. package/dist/version.js +18 -5
  316. package/dist/web/auto-reply/monitor/broadcast.js +7 -3
  317. package/dist/web/auto-reply/monitor/on-message.js +6 -3
  318. package/dist/web/inbound/media.js +34 -8
  319. package/dist/web/inbound/monitor.js +34 -17
  320. package/dist/web/inbound/send-api.js +18 -17
  321. package/dist/web/outbound.js +12 -5
  322. package/dist/wizard/clack-prompter.js +40 -7
  323. package/extensions/bluebubbles/package.json +1 -1
  324. package/extensions/copilot-proxy/package.json +1 -1
  325. package/extensions/diagnostics-otel/package.json +1 -1
  326. package/extensions/discord/package.json +1 -1
  327. package/extensions/feishu/package.json +1 -1
  328. package/extensions/google-antigravity-auth/package.json +1 -1
  329. package/extensions/google-gemini-cli-auth/package.json +1 -1
  330. package/extensions/googlechat/package.json +1 -1
  331. package/extensions/imessage/package.json +1 -1
  332. package/extensions/irc/package.json +1 -1
  333. package/extensions/line/package.json +1 -1
  334. package/extensions/llm-task/package.json +1 -1
  335. package/extensions/lobster/package.json +1 -1
  336. package/extensions/matrix/CHANGELOG.md +5 -0
  337. package/extensions/matrix/package.json +1 -1
  338. package/extensions/mattermost/package.json +1 -1
  339. package/extensions/memory-core/package.json +1 -1
  340. package/extensions/memory-lancedb/package.json +1 -1
  341. package/extensions/minimax-portal-auth/package.json +1 -1
  342. package/extensions/msteams/CHANGELOG.md +5 -0
  343. package/extensions/msteams/package.json +1 -1
  344. package/extensions/nextcloud-talk/package.json +1 -1
  345. package/extensions/nostr/CHANGELOG.md +5 -0
  346. package/extensions/nostr/package.json +1 -1
  347. package/extensions/open-prose/package.json +1 -1
  348. package/extensions/openai-codex-auth/package.json +1 -1
  349. package/extensions/signal/package.json +1 -1
  350. package/extensions/slack/package.json +1 -1
  351. package/extensions/telegram/package.json +1 -1
  352. package/extensions/tlon/package.json +1 -1
  353. package/extensions/twitch/CHANGELOG.md +5 -0
  354. package/extensions/twitch/package.json +1 -1
  355. package/extensions/voice-call/CHANGELOG.md +5 -0
  356. package/extensions/voice-call/package.json +1 -1
  357. package/extensions/whatsapp/package.json +1 -1
  358. package/extensions/zalo/CHANGELOG.md +5 -0
  359. package/extensions/zalo/package.json +1 -1
  360. package/extensions/zalouser/CHANGELOG.md +5 -0
  361. package/extensions/zalouser/package.json +1 -1
  362. package/package.json +1 -1
  363. package/skills/apple-reminders/SKILL.md +100 -49
  364. package/skills/coding-agent/SKILL.md +34 -28
  365. package/skills/github/SKILL.md +131 -16
  366. package/skills/imsg/SKILL.md +112 -15
  367. package/skills/openhue/SKILL.md +101 -19
  368. package/skills/tmux/SKILL.md +111 -79
  369. package/skills/weather/SKILL.md +88 -25
@@ -2,9 +2,11 @@ import crypto from "node:crypto";
2
2
  import fs from "node:fs";
3
3
  import os from "node:os";
4
4
  import path from "node:path";
5
- import lockfile from "proper-lockfile";
6
5
  import { getPairingAdapter } from "../channels/plugins/pairing.js";
7
6
  import { resolveOAuthDir, resolveStateDir } from "../config/paths.js";
7
+ import { withFileLock as withPathLock } from "../infra/file-lock.js";
8
+ import { resolveRequiredHomeDir } from "../infra/home-dir.js";
9
+ import { readJsonFileWithFallback, writeJsonFileAtomically } from "../plugin-sdk/json-store.js";
8
10
  const PAIRING_CODE_LENGTH = 8;
9
11
  const PAIRING_CODE_ALPHABET = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789";
10
12
  const PAIRING_PENDING_TTL_MS = 60 * 60 * 1000;
@@ -20,57 +22,58 @@ const PAIRING_STORE_LOCK_OPTIONS = {
20
22
  stale: 30_000,
21
23
  };
22
24
  function resolveCredentialsDir(env = process.env) {
23
- const stateDir = resolveStateDir(env, os.homedir);
25
+ const stateDir = resolveStateDir(env, () => resolveRequiredHomeDir(env, os.homedir));
24
26
  return resolveOAuthDir(env, stateDir);
25
27
  }
26
28
  /** Sanitize channel ID for use in filenames (prevent path traversal). */
27
29
  function safeChannelKey(channel) {
28
30
  const raw = String(channel).trim().toLowerCase();
29
- if (!raw)
31
+ if (!raw) {
30
32
  throw new Error("invalid pairing channel");
33
+ }
31
34
  const safe = raw.replace(/[\\/:*?"<>|]/g, "_").replace(/\.\./g, "_");
32
- if (!safe || safe === "_")
35
+ if (!safe || safe === "_") {
33
36
  throw new Error("invalid pairing channel");
37
+ }
34
38
  return safe;
35
39
  }
36
40
  function resolvePairingPath(channel, env = process.env) {
37
41
  return path.join(resolveCredentialsDir(env), `${safeChannelKey(channel)}-pairing.json`);
38
42
  }
39
- function resolveAllowFromPath(channel, env = process.env) {
40
- return path.join(resolveCredentialsDir(env), `${safeChannelKey(channel)}-allowFrom.json`);
41
- }
42
- function safeParseJson(raw) {
43
- try {
44
- return JSON.parse(raw);
43
+ function safeAccountKey(accountId) {
44
+ const raw = String(accountId).trim().toLowerCase();
45
+ if (!raw) {
46
+ throw new Error("invalid pairing account id");
45
47
  }
46
- catch {
47
- return null;
48
+ const safe = raw.replace(/[\\/:*?"<>|]/g, "_").replace(/\.\./g, "_");
49
+ if (!safe || safe === "_") {
50
+ throw new Error("invalid pairing account id");
48
51
  }
52
+ return safe;
49
53
  }
50
- async function readJsonFile(filePath, fallback) {
51
- try {
52
- const raw = await fs.promises.readFile(filePath, "utf-8");
53
- const parsed = safeParseJson(raw);
54
- if (parsed == null)
55
- return { value: fallback, exists: true };
56
- return { value: parsed, exists: true };
57
- }
58
- catch (err) {
59
- const code = err.code;
60
- if (code === "ENOENT")
61
- return { value: fallback, exists: false };
62
- return { value: fallback, exists: false };
54
+ function resolveAllowFromPath(channel, env = process.env, accountId) {
55
+ const base = safeChannelKey(channel);
56
+ const normalizedAccountId = typeof accountId === "string" ? accountId.trim() : "";
57
+ if (!normalizedAccountId) {
58
+ return path.join(resolveCredentialsDir(env), `${base}-allowFrom.json`);
63
59
  }
60
+ return path.join(resolveCredentialsDir(env), `${base}-${safeAccountKey(normalizedAccountId)}-allowFrom.json`);
61
+ }
62
+ async function readJsonFile(filePath, fallback) {
63
+ return await readJsonFileWithFallback(filePath, fallback);
64
64
  }
65
65
  async function writeJsonFile(filePath, value) {
66
- const dir = path.dirname(filePath);
67
- await fs.promises.mkdir(dir, { recursive: true, mode: 0o700 });
68
- const tmp = path.join(dir, `${path.basename(filePath)}.${crypto.randomUUID()}.tmp`);
69
- await fs.promises.writeFile(tmp, `${JSON.stringify(value, null, 2)}\n`, {
70
- encoding: "utf-8",
66
+ await writeJsonFileAtomically(filePath, value);
67
+ }
68
+ async function readPairingRequests(filePath) {
69
+ const { value } = await readJsonFile(filePath, {
70
+ version: 1,
71
+ requests: [],
71
72
  });
72
- await fs.promises.chmod(tmp, 0o600);
73
- await fs.promises.rename(tmp, filePath);
73
+ return Array.isArray(value.requests) ? value.requests : [];
74
+ }
75
+ async function readPrunedPairingRequests(filePath) {
76
+ return pruneExpiredRequests(await readPairingRequests(filePath), Date.now());
74
77
  }
75
78
  async function ensureJsonFile(filePath, fallback) {
76
79
  try {
@@ -82,34 +85,25 @@ async function ensureJsonFile(filePath, fallback) {
82
85
  }
83
86
  async function withFileLock(filePath, fallback, fn) {
84
87
  await ensureJsonFile(filePath, fallback);
85
- let release;
86
- try {
87
- release = await lockfile.lock(filePath, PAIRING_STORE_LOCK_OPTIONS);
88
+ return await withPathLock(filePath, PAIRING_STORE_LOCK_OPTIONS, async () => {
88
89
  return await fn();
89
- }
90
- finally {
91
- if (release) {
92
- try {
93
- await release();
94
- }
95
- catch {
96
- // ignore unlock errors
97
- }
98
- }
99
- }
90
+ });
100
91
  }
101
92
  function parseTimestamp(value) {
102
- if (!value)
93
+ if (!value) {
103
94
  return null;
95
+ }
104
96
  const parsed = Date.parse(value);
105
- if (!Number.isFinite(parsed))
97
+ if (!Number.isFinite(parsed)) {
106
98
  return null;
99
+ }
107
100
  return parsed;
108
101
  }
109
102
  function isExpired(entry, nowMs) {
110
103
  const createdAt = parseTimestamp(entry.createdAt);
111
- if (!createdAt)
104
+ if (!createdAt) {
112
105
  return true;
106
+ }
113
107
  return nowMs - createdAt > PAIRING_PENDING_TTL_MS;
114
108
  }
115
109
  function pruneExpiredRequests(reqs, nowMs) {
@@ -131,7 +125,7 @@ function pruneExcessRequests(reqs, maxPending) {
131
125
  if (maxPending <= 0 || reqs.length <= maxPending) {
132
126
  return { requests: reqs, removed: false };
133
127
  }
134
- const sorted = reqs.slice().sort((a, b) => resolveLastSeenAt(a) - resolveLastSeenAt(b));
128
+ const sorted = reqs.slice().toSorted((a, b) => resolveLastSeenAt(a) - resolveLastSeenAt(b));
135
129
  return { requests: sorted.slice(-maxPending), removed: true };
136
130
  }
137
131
  function randomCode() {
@@ -146,91 +140,150 @@ function randomCode() {
146
140
  function generateUniqueCode(existing) {
147
141
  for (let attempt = 0; attempt < 500; attempt += 1) {
148
142
  const code = randomCode();
149
- if (!existing.has(code))
143
+ if (!existing.has(code)) {
150
144
  return code;
145
+ }
151
146
  }
152
147
  throw new Error("failed to generate unique pairing code");
153
148
  }
149
+ function normalizePairingAccountId(accountId) {
150
+ return accountId?.trim().toLowerCase() || "";
151
+ }
152
+ function requestMatchesAccountId(entry, normalizedAccountId) {
153
+ if (!normalizedAccountId) {
154
+ return true;
155
+ }
156
+ return (String(entry.meta?.accountId ?? "")
157
+ .trim()
158
+ .toLowerCase() === normalizedAccountId);
159
+ }
154
160
  function normalizeId(value) {
155
161
  return String(value).trim();
156
162
  }
157
163
  function normalizeAllowEntry(channel, entry) {
158
164
  const trimmed = entry.trim();
159
- if (!trimmed)
165
+ if (!trimmed) {
160
166
  return "";
161
- if (trimmed === "*")
167
+ }
168
+ if (trimmed === "*") {
162
169
  return "";
170
+ }
163
171
  const adapter = getPairingAdapter(channel);
164
172
  const normalized = adapter?.normalizeAllowEntry ? adapter.normalizeAllowEntry(trimmed) : trimmed;
165
173
  return String(normalized).trim();
166
174
  }
167
- export async function readChannelAllowFromStore(channel, env = process.env) {
168
- const filePath = resolveAllowFromPath(channel, env);
175
+ function normalizeAllowFromList(channel, store) {
176
+ const list = Array.isArray(store.allowFrom) ? store.allowFrom : [];
177
+ return list.map((v) => normalizeAllowEntry(channel, String(v))).filter(Boolean);
178
+ }
179
+ function normalizeAllowFromInput(channel, entry) {
180
+ return normalizeAllowEntry(channel, normalizeId(entry));
181
+ }
182
+ function dedupePreserveOrder(entries) {
183
+ const seen = new Set();
184
+ const out = [];
185
+ for (const entry of entries) {
186
+ const normalized = String(entry).trim();
187
+ if (!normalized || seen.has(normalized)) {
188
+ continue;
189
+ }
190
+ seen.add(normalized);
191
+ out.push(normalized);
192
+ }
193
+ return out;
194
+ }
195
+ async function readAllowFromStateForPath(channel, filePath) {
169
196
  const { value } = await readJsonFile(filePath, {
170
197
  version: 1,
171
198
  allowFrom: [],
172
199
  });
173
- const list = Array.isArray(value.allowFrom) ? value.allowFrom : [];
174
- return list.map((v) => normalizeAllowEntry(channel, String(v))).filter(Boolean);
200
+ return normalizeAllowFromList(channel, value);
175
201
  }
176
- export async function addChannelAllowFromStoreEntry(params) {
202
+ async function readAllowFromState(params) {
203
+ const { value } = await readJsonFile(params.filePath, {
204
+ version: 1,
205
+ allowFrom: [],
206
+ });
207
+ const current = normalizeAllowFromList(params.channel, value);
208
+ const normalized = normalizeAllowFromInput(params.channel, params.entry);
209
+ return { current, normalized: normalized || null };
210
+ }
211
+ async function writeAllowFromState(filePath, allowFrom) {
212
+ await writeJsonFile(filePath, {
213
+ version: 1,
214
+ allowFrom,
215
+ });
216
+ }
217
+ async function updateAllowFromStoreEntry(params) {
177
218
  const env = params.env ?? process.env;
178
- const filePath = resolveAllowFromPath(params.channel, env);
219
+ const filePath = resolveAllowFromPath(params.channel, env, params.accountId);
179
220
  return await withFileLock(filePath, { version: 1, allowFrom: [] }, async () => {
180
- const { value } = await readJsonFile(filePath, {
181
- version: 1,
182
- allowFrom: [],
221
+ const { current, normalized } = await readAllowFromState({
222
+ channel: params.channel,
223
+ entry: params.entry,
224
+ filePath,
183
225
  });
184
- const current = (Array.isArray(value.allowFrom) ? value.allowFrom : [])
185
- .map((v) => normalizeAllowEntry(params.channel, String(v)))
186
- .filter(Boolean);
187
- const normalized = normalizeAllowEntry(params.channel, normalizeId(params.entry));
188
- if (!normalized)
226
+ if (!normalized) {
189
227
  return { changed: false, allowFrom: current };
190
- if (current.includes(normalized))
228
+ }
229
+ const next = params.apply(current, normalized);
230
+ if (!next) {
191
231
  return { changed: false, allowFrom: current };
192
- const next = [...current, normalized];
193
- await writeJsonFile(filePath, {
194
- version: 1,
195
- allowFrom: next,
196
- });
232
+ }
233
+ await writeAllowFromState(filePath, next);
197
234
  return { changed: true, allowFrom: next };
198
235
  });
199
236
  }
237
+ export async function readChannelAllowFromStore(channel, env = process.env, accountId) {
238
+ const normalizedAccountId = accountId?.trim().toLowerCase() ?? "";
239
+ if (!normalizedAccountId) {
240
+ const filePath = resolveAllowFromPath(channel, env);
241
+ return await readAllowFromStateForPath(channel, filePath);
242
+ }
243
+ const scopedPath = resolveAllowFromPath(channel, env, accountId);
244
+ const scopedEntries = await readAllowFromStateForPath(channel, scopedPath);
245
+ // Backward compatibility: legacy channel-level allowFrom store was unscoped.
246
+ // Keep honoring it alongside account-scoped files to prevent re-pair prompts after upgrades.
247
+ const legacyPath = resolveAllowFromPath(channel, env);
248
+ const legacyEntries = await readAllowFromStateForPath(channel, legacyPath);
249
+ return dedupePreserveOrder([...scopedEntries, ...legacyEntries]);
250
+ }
251
+ async function updateChannelAllowFromStore(params) {
252
+ return await updateAllowFromStoreEntry({
253
+ channel: params.channel,
254
+ entry: params.entry,
255
+ accountId: params.accountId,
256
+ env: params.env,
257
+ apply: params.apply,
258
+ });
259
+ }
260
+ export async function addChannelAllowFromStoreEntry(params) {
261
+ return await updateChannelAllowFromStore({
262
+ ...params,
263
+ apply: (current, normalized) => {
264
+ if (current.includes(normalized)) {
265
+ return null;
266
+ }
267
+ return [...current, normalized];
268
+ },
269
+ });
270
+ }
200
271
  export async function removeChannelAllowFromStoreEntry(params) {
201
- const env = params.env ?? process.env;
202
- const filePath = resolveAllowFromPath(params.channel, env);
203
- return await withFileLock(filePath, { version: 1, allowFrom: [] }, async () => {
204
- const { value } = await readJsonFile(filePath, {
205
- version: 1,
206
- allowFrom: [],
207
- });
208
- const current = (Array.isArray(value.allowFrom) ? value.allowFrom : [])
209
- .map((v) => normalizeAllowEntry(params.channel, String(v)))
210
- .filter(Boolean);
211
- const normalized = normalizeAllowEntry(params.channel, normalizeId(params.entry));
212
- if (!normalized)
213
- return { changed: false, allowFrom: current };
214
- const next = current.filter((entry) => entry !== normalized);
215
- if (next.length === current.length)
216
- return { changed: false, allowFrom: current };
217
- await writeJsonFile(filePath, {
218
- version: 1,
219
- allowFrom: next,
220
- });
221
- return { changed: true, allowFrom: next };
272
+ return await updateChannelAllowFromStore({
273
+ ...params,
274
+ apply: (current, normalized) => {
275
+ const next = current.filter((entry) => entry !== normalized);
276
+ if (next.length === current.length) {
277
+ return null;
278
+ }
279
+ return next;
280
+ },
222
281
  });
223
282
  }
224
- export async function listChannelPairingRequests(channel, env = process.env) {
283
+ export async function listChannelPairingRequests(channel, env = process.env, accountId) {
225
284
  const filePath = resolvePairingPath(channel, env);
226
285
  return await withFileLock(filePath, { version: 1, requests: [] }, async () => {
227
- const { value } = await readJsonFile(filePath, {
228
- version: 1,
229
- requests: [],
230
- });
231
- const reqs = Array.isArray(value.requests) ? value.requests : [];
232
- const nowMs = Date.now();
233
- const { requests: prunedExpired, removed: expiredRemoved } = pruneExpiredRequests(reqs, nowMs);
286
+ const { requests: prunedExpired, removed: expiredRemoved } = await readPrunedPairingRequests(filePath);
234
287
  const { requests: pruned, removed: cappedRemoved } = pruneExcessRequests(prunedExpired, PAIRING_PENDING_MAX);
235
288
  if (expiredRemoved || cappedRemoved) {
236
289
  await writeJsonFile(filePath, {
@@ -238,32 +291,34 @@ export async function listChannelPairingRequests(channel, env = process.env) {
238
291
  requests: pruned,
239
292
  });
240
293
  }
241
- return pruned
294
+ const normalizedAccountId = normalizePairingAccountId(accountId);
295
+ const filtered = normalizedAccountId
296
+ ? pruned.filter((entry) => requestMatchesAccountId(entry, normalizedAccountId))
297
+ : pruned;
298
+ return filtered
242
299
  .filter((r) => r &&
243
300
  typeof r.id === "string" &&
244
301
  typeof r.code === "string" &&
245
302
  typeof r.createdAt === "string")
246
303
  .slice()
247
- .sort((a, b) => a.createdAt.localeCompare(b.createdAt));
304
+ .toSorted((a, b) => a.createdAt.localeCompare(b.createdAt));
248
305
  });
249
306
  }
250
307
  export async function upsertChannelPairingRequest(params) {
251
308
  const env = params.env ?? process.env;
252
309
  const filePath = resolvePairingPath(params.channel, env);
253
310
  return await withFileLock(filePath, { version: 1, requests: [] }, async () => {
254
- const { value } = await readJsonFile(filePath, {
255
- version: 1,
256
- requests: [],
257
- });
258
311
  const now = new Date().toISOString();
259
312
  const nowMs = Date.now();
260
313
  const id = normalizeId(params.id);
261
- const meta = params.meta && typeof params.meta === "object"
314
+ const normalizedAccountId = params.accountId?.trim();
315
+ const baseMeta = params.meta && typeof params.meta === "object"
262
316
  ? Object.fromEntries(Object.entries(params.meta)
263
317
  .map(([k, v]) => [k, String(v ?? "").trim()])
264
318
  .filter(([_, v]) => Boolean(v)))
265
319
  : undefined;
266
- let reqs = Array.isArray(value.requests) ? value.requests : [];
320
+ const meta = normalizedAccountId ? { ...baseMeta, accountId: normalizedAccountId } : baseMeta;
321
+ let reqs = await readPairingRequests(filePath);
267
322
  const { requests: prunedExpired, removed: expiredRemoved } = pruneExpiredRequests(reqs, nowMs);
268
323
  reqs = prunedExpired;
269
324
  const existingIdx = reqs.findIndex((r) => r.id === id);
@@ -318,18 +373,19 @@ export async function upsertChannelPairingRequest(params) {
318
373
  export async function approveChannelPairingCode(params) {
319
374
  const env = params.env ?? process.env;
320
375
  const code = params.code.trim().toUpperCase();
321
- if (!code)
376
+ if (!code) {
322
377
  return null;
378
+ }
323
379
  const filePath = resolvePairingPath(params.channel, env);
324
380
  return await withFileLock(filePath, { version: 1, requests: [] }, async () => {
325
- const { value } = await readJsonFile(filePath, {
326
- version: 1,
327
- requests: [],
381
+ const { requests: pruned, removed } = await readPrunedPairingRequests(filePath);
382
+ const normalizedAccountId = normalizePairingAccountId(params.accountId);
383
+ const idx = pruned.findIndex((r) => {
384
+ if (String(r.code ?? "").toUpperCase() !== code) {
385
+ return false;
386
+ }
387
+ return requestMatchesAccountId(r, normalizedAccountId);
328
388
  });
329
- const reqs = Array.isArray(value.requests) ? value.requests : [];
330
- const nowMs = Date.now();
331
- const { requests: pruned, removed } = pruneExpiredRequests(reqs, nowMs);
332
- const idx = pruned.findIndex((r) => String(r.code ?? "").toUpperCase() === code);
333
389
  if (idx < 0) {
334
390
  if (removed) {
335
391
  await writeJsonFile(filePath, {
@@ -340,16 +396,19 @@ export async function approveChannelPairingCode(params) {
340
396
  return null;
341
397
  }
342
398
  const entry = pruned[idx];
343
- if (!entry)
399
+ if (!entry) {
344
400
  return null;
401
+ }
345
402
  pruned.splice(idx, 1);
346
403
  await writeJsonFile(filePath, {
347
404
  version: 1,
348
405
  requests: pruned,
349
406
  });
407
+ const entryAccountId = String(entry.meta?.accountId ?? "").trim() || undefined;
350
408
  await addChannelAllowFromStoreEntry({
351
409
  channel: params.channel,
352
410
  entry: entry.id,
411
+ accountId: params.accountId?.trim() || entryAccountId,
353
412
  env,
354
413
  });
355
414
  return { id: entry.id, entry };
@@ -1,23 +1,46 @@
1
+ export { createAccountListHelpers } from "../channels/plugins/account-helpers.js";
1
2
  export { CHANNEL_MESSAGE_ACTION_NAMES } from "../channels/plugins/message-action-names.js";
2
3
  export { BLUEBUBBLES_ACTIONS, BLUEBUBBLES_ACTION_NAMES, BLUEBUBBLES_GROUP_ACTIONS, } from "../channels/plugins/bluebubbles-actions.js";
3
4
  export { normalizePluginHttpPath } from "../plugins/http-path.js";
4
5
  export { registerPluginHttpRoute } from "../plugins/http-registry.js";
5
6
  export { emptyPluginConfigSchema } from "../plugins/config-schema.js";
7
+ export { acquireFileLock, withFileLock } from "./file-lock.js";
8
+ export { normalizeWebhookPath, resolveWebhookPath } from "./webhook-path.js";
9
+ export { registerWebhookTarget, rejectNonPostWebhookRequest, resolveWebhookTargets, } from "./webhook-targets.js";
10
+ export { buildAgentMediaPayload } from "./agent-media-payload.js";
11
+ export { buildBaseChannelStatusSummary, collectStatusIssuesFromLastError, createDefaultChannelRuntimeState, } from "./status-helpers.js";
12
+ export { buildOauthProviderAuthResult } from "./provider-auth-result.js";
6
13
  export { getChatChannelMeta } from "../channels/registry.js";
7
14
  export { DiscordConfigSchema, GoogleChatConfigSchema, IMessageConfigSchema, MSTeamsConfigSchema, SignalConfigSchema, SlackConfigSchema, TelegramConfigSchema, } from "../config/zod-schema.providers-core.js";
8
15
  export { WhatsAppConfigSchema } from "../config/zod-schema.providers-whatsapp.js";
9
- export { BlockStreamingCoalesceSchema, DmConfigSchema, DmPolicySchema, GroupPolicySchema, MarkdownConfigSchema, MarkdownTableModeSchema, normalizeAllowFrom, requireOpenAllowFrom, } from "../config/zod-schema.core.js";
16
+ export { BlockStreamingCoalesceSchema, DmConfigSchema, DmPolicySchema, GroupPolicySchema, MarkdownConfigSchema, MarkdownTableModeSchema, normalizeAllowFrom, requireOpenAllowFrom, TtsAutoSchema, TtsConfigSchema, TtsModeSchema, TtsProviderSchema, } from "../config/zod-schema.core.js";
10
17
  export { ToolPolicySchema } from "../config/zod-schema.agent-runtime.js";
11
18
  export { DEFAULT_ACCOUNT_ID, normalizeAccountId } from "../routing/session-key.js";
19
+ export { formatAllowFromLowercase, isAllowedParsedChatSender } from "./allow-from.js";
20
+ export { resolveSenderCommandAuthorization } from "./command-auth.js";
21
+ export { handleSlackMessageAction } from "./slack-message-actions.js";
22
+ export { extractToolSend } from "./tool-send.js";
23
+ export { resolveChannelAccountConfigBasePath } from "./config-paths.js";
24
+ export { chunkTextForOutbound } from "./text-chunking.js";
25
+ export { readJsonFileWithFallback, writeJsonFileAtomically } from "./json-store.js";
12
26
  export { resolveAckReaction } from "../agents/identity.js";
13
27
  export { SILENT_REPLY_TOKEN, isSilentReplyText } from "../auto-reply/tokens.js";
28
+ export { approveDevicePairing, listDevicePairing, rejectDevicePairing, } from "../infra/device-pairing.js";
29
+ export { createDedupeCache } from "../infra/dedupe.js";
30
+ export { formatErrorMessage } from "../infra/errors.js";
31
+ export { DEFAULT_WEBHOOK_BODY_TIMEOUT_MS, DEFAULT_WEBHOOK_MAX_BODY_BYTES, RequestBodyLimitError, installRequestBodyLimitGuard, isRequestBodyLimitError, readJsonBodyWithLimit, readRequestBodyWithLimit, requestBodyErrorToText, } from "../infra/http-body.js";
32
+ export { fetchWithSsrFGuard } from "../infra/net/fetch-guard.js";
33
+ export { SsrFBlockedError, isBlockedHostname, isPrivateIpAddress } from "../infra/net/ssrf.js";
34
+ export { rawDataToString } from "../infra/ws.js";
35
+ export { isWSLSync, isWSL2Sync, isWSLEnv } from "../infra/wsl.js";
36
+ export { isTruthyEnvValue } from "../infra/env.js";
14
37
  export { resolveToolsBySender } from "../config/group-policy.js";
15
38
  export { buildPendingHistoryContextFromMap, clearHistoryEntries, clearHistoryEntriesIfEnabled, DEFAULT_GROUP_HISTORY_LIMIT, recordPendingHistoryEntry, recordPendingHistoryEntryIfEnabled, } from "../auto-reply/reply/history.js";
16
39
  export { mergeAllowlist, summarizeMapping } from "../channels/allowlists/resolve-utils.js";
17
40
  export { resolveMentionGating, resolveMentionGatingWithBypass, } from "../channels/mention-gating.js";
18
41
  export { removeAckReactionAfterReply, shouldAckReaction, shouldAckReactionForWhatsApp, } from "../channels/ack-reactions.js";
19
42
  export { createTypingCallbacks } from "../channels/typing.js";
20
- export { createReplyPrefixContext } from "../channels/reply-prefix.js";
43
+ export { createReplyPrefixContext, createReplyPrefixOptions } from "../channels/reply-prefix.js";
21
44
  export { logAckFailure, logInboundDrop, logTypingFailure } from "../channels/logging.js";
22
45
  export { resolveChannelMediaMaxBytes } from "../channels/plugins/media-limits.js";
23
46
  export { formatLocationText, toLocationContext } from "../channels/location.js";
@@ -26,18 +49,19 @@ export { resolveBlueBubblesGroupRequireMention, resolveDiscordGroupRequireMentio
26
49
  export { recordInboundSession } from "../channels/session.js";
27
50
  export { buildChannelKeyCandidates, normalizeChannelSlug, resolveChannelEntryMatch, resolveChannelEntryMatchWithFallback, resolveNestedAllowlistDecision, } from "../channels/plugins/channel-config.js";
28
51
  export { listDiscordDirectoryGroupsFromConfig, listDiscordDirectoryPeersFromConfig, listSlackDirectoryGroupsFromConfig, listSlackDirectoryPeersFromConfig, listTelegramDirectoryGroupsFromConfig, listTelegramDirectoryPeersFromConfig, listWhatsAppDirectoryGroupsFromConfig, listWhatsAppDirectoryPeersFromConfig, } from "../channels/plugins/directory-config.js";
29
- export { formatAllowlistMatchMeta } from "../channels/plugins/allowlist-match.js";
52
+ export { formatAllowlistMatchMeta, resolveAllowlistMatchSimple, } from "../channels/plugins/allowlist-match.js";
30
53
  export { optionalStringEnum, stringEnum } from "../agents/schema/typebox.js";
31
54
  export { buildChannelConfigSchema } from "../channels/plugins/config-schema.js";
32
55
  export { deleteAccountFromConfigSection, setAccountEnabledInConfigSection, } from "../channels/plugins/config-helpers.js";
33
56
  export { applyAccountNameToChannelSection, migrateBaseNameToDefaultAccount, } from "../channels/plugins/setup-helpers.js";
34
57
  export { formatPairingApproveHint } from "../channels/plugins/helpers.js";
35
58
  export { PAIRING_APPROVED_MESSAGE } from "../channels/plugins/pairing-message.js";
36
- export { addWildcardAllowFrom, promptAccountId } from "../channels/plugins/onboarding/helpers.js";
59
+ export { addWildcardAllowFrom, mergeAllowFromEntries, promptAccountId, } from "../channels/plugins/onboarding/helpers.js";
37
60
  export { promptChannelAccessConfig } from "../channels/plugins/onboarding/channel-access.js";
38
61
  export { createActionGate, jsonResult, readNumberParam, readReactionParams, readStringParam, } from "../agents/tools/common.js";
39
62
  export { formatDocsLink } from "../terminal/links.js";
40
- export { normalizeE164 } from "../utils.js";
63
+ export { clamp, escapeRegExp, normalizeE164, safeParseJson, sleep } from "../utils.js";
64
+ export { stripAnsi } from "../terminal/ansi.js";
41
65
  export { missingTargetError } from "../infra/outbound/target-errors.js";
42
66
  export { registerLogTransport } from "../logging/logger.js";
43
67
  export { emitDiagnosticEvent, isDiagnosticsEnabled, onDiagnosticEvent, } from "../infra/diagnostic-events.js";
@@ -47,14 +71,16 @@ export { extractOriginalFilename } from "../media/store.js";
47
71
  export { listDiscordAccountIds, resolveDefaultDiscordAccountId, resolveDiscordAccount, } from "../discord/accounts.js";
48
72
  export { collectDiscordAuditChannelIds } from "../discord/audit.js";
49
73
  export { discordOnboardingAdapter } from "../channels/plugins/onboarding/discord.js";
50
- export { looksLikeDiscordTargetId, normalizeDiscordMessagingTarget, } from "../channels/plugins/normalize/discord.js";
74
+ export { looksLikeDiscordTargetId, normalizeDiscordMessagingTarget, normalizeDiscordOutboundTarget, } from "../channels/plugins/normalize/discord.js";
51
75
  export { collectDiscordStatusIssues } from "../channels/plugins/status-issues/discord.js";
52
76
  // Channel: iMessage
53
77
  export { listIMessageAccountIds, resolveDefaultIMessageAccountId, resolveIMessageAccount, } from "../imessage/accounts.js";
54
78
  export { imessageOnboardingAdapter } from "../channels/plugins/onboarding/imessage.js";
55
79
  export { looksLikeIMessageTargetId, normalizeIMessageMessagingTarget, } from "../channels/plugins/normalize/imessage.js";
80
+ export { parseChatAllowTargetPrefixes, parseChatTargetPrefixesOrThrow, resolveServicePrefixedAllowTarget, resolveServicePrefixedTarget, } from "../imessage/target-parsing-helpers.js";
56
81
  // Channel: Slack
57
82
  export { listEnabledSlackAccounts, listSlackAccountIds, resolveDefaultSlackAccountId, resolveSlackAccount, resolveSlackReplyToMode, } from "../slack/accounts.js";
83
+ export { extractSlackToolSend, listSlackMessageActions } from "../slack/message-actions.js";
58
84
  export { slackOnboardingAdapter } from "../channels/plugins/onboarding/slack.js";
59
85
  export { looksLikeSlackTargetId, normalizeSlackMessagingTarget, } from "../channels/plugins/normalize/slack.js";
60
86
  export { buildSlackThreadingToolContext } from "../slack/threading-tool-context.js";
@@ -63,6 +89,7 @@ export { listTelegramAccountIds, resolveDefaultTelegramAccountId, resolveTelegra
63
89
  export { telegramOnboardingAdapter } from "../channels/plugins/onboarding/telegram.js";
64
90
  export { looksLikeTelegramTargetId, normalizeTelegramMessagingTarget, } from "../channels/plugins/normalize/telegram.js";
65
91
  export { collectTelegramStatusIssues } from "../channels/plugins/status-issues/telegram.js";
92
+ export { parseTelegramReplyToMessageId, parseTelegramThreadId, } from "../telegram/outbound-params.js";
66
93
  // Channel: Signal
67
94
  export { listSignalAccountIds, resolveDefaultSignalAccountId, resolveSignalAccount, } from "../signal/accounts.js";
68
95
  export { signalOnboardingAdapter } from "../channels/plugins/onboarding/signal.js";
@@ -70,6 +97,7 @@ export { looksLikeSignalTargetId, normalizeSignalMessagingTarget, } from "../cha
70
97
  // Channel: WhatsApp
71
98
  export { listWhatsAppAccountIds, resolveDefaultWhatsAppAccountId, resolveWhatsAppAccount, } from "../web/accounts.js";
72
99
  export { isWhatsAppGroupJid, normalizeWhatsAppTarget } from "../whatsapp/normalize.js";
100
+ export { resolveWhatsAppOutboundTarget } from "../whatsapp/resolve-outbound-target.js";
73
101
  export { whatsappOnboardingAdapter } from "../channels/plugins/onboarding/whatsapp.js";
74
102
  export { resolveWhatsAppHeartbeatRecipients } from "../channels/plugins/whatsapp-heartbeat.js";
75
103
  export { looksLikeWhatsAppTargetId, normalizeWhatsAppMessagingTarget, } from "../channels/plugins/normalize/whatsapp.js";