@poolzin/pool-bot 2026.1.39 → 2026.2.1

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 (511) hide show
  1. package/assets/chrome-extension/README.md +3 -3
  2. package/assets/chrome-extension/background.js +5 -5
  3. package/assets/chrome-extension/manifest.json +3 -3
  4. package/assets/chrome-extension/options.html +4 -4
  5. package/assets/chrome-extension/options.js +1 -1
  6. package/dist/acp/client.js +3 -3
  7. package/dist/acp/types.js +1 -1
  8. package/dist/agents/agent-paths.js +3 -3
  9. package/dist/agents/auth-profiles/paths.js +3 -3
  10. package/dist/agents/bash-tools.exec.js +76 -25
  11. package/dist/agents/cli-runner/helpers.js +10 -12
  12. package/dist/agents/cli-runner.js +2 -2
  13. package/dist/agents/cloudflare-ai-gateway.js +31 -0
  14. package/dist/agents/compaction.js +16 -2
  15. package/dist/agents/context-window-guard.js +13 -10
  16. package/dist/agents/context.js +4 -4
  17. package/dist/agents/docs-path.js +1 -1
  18. package/dist/agents/identity.js +47 -7
  19. package/dist/agents/memory-search.js +25 -8
  20. package/dist/agents/minimax-vlm.js +1 -1
  21. package/dist/agents/model-auth.js +12 -1
  22. package/dist/agents/model-catalog.js +4 -4
  23. package/dist/agents/model-selection.js +31 -4
  24. package/dist/agents/models-config.js +3 -3
  25. package/dist/agents/models-config.providers.js +147 -39
  26. package/dist/agents/pi-embedded-block-chunker.js +117 -42
  27. package/dist/agents/pi-embedded-helpers/errors.js +183 -78
  28. package/dist/agents/pi-embedded-helpers/openai.js +1 -1
  29. package/dist/agents/pi-embedded-helpers.js +1 -1
  30. package/dist/agents/pi-embedded-runner/compact.js +9 -8
  31. package/dist/agents/pi-embedded-runner/model.js +63 -4
  32. package/dist/agents/pi-embedded-runner/run/attempt.js +27 -17
  33. package/dist/agents/pi-embedded-runner/run.js +203 -50
  34. package/dist/agents/pi-embedded-runner/system-prompt.js +10 -2
  35. package/dist/agents/pi-embedded-runner/tool-result-truncation.js +275 -0
  36. package/dist/agents/pi-embedded-runner/utils.js +1 -1
  37. package/dist/agents/pi-embedded-subscribe.js +118 -29
  38. package/dist/agents/pi-model-discovery.js +10 -0
  39. package/dist/agents/pi-tool-definition-adapter.js +50 -9
  40. package/dist/agents/pi-tools.before-tool-call.js +67 -0
  41. package/dist/agents/pi-tools.js +20 -10
  42. package/dist/agents/pi-tools.read.js +2 -2
  43. package/dist/agents/poolbot-tools.js +15 -10
  44. package/dist/agents/sandbox-paths.js +31 -0
  45. package/dist/agents/session-file-repair.js +83 -0
  46. package/dist/agents/session-tool-result-guard.js +94 -15
  47. package/dist/agents/session-transcript-repair.js +68 -0
  48. package/dist/agents/shell-utils.js +51 -0
  49. package/dist/agents/skills/bundled-context.js +23 -0
  50. package/dist/agents/skills/bundled-dir.js +41 -7
  51. package/dist/agents/skills/frontmatter.js +1 -1
  52. package/dist/agents/skills/workspace.js +2 -2
  53. package/dist/agents/skills-install.js +60 -23
  54. package/dist/agents/subagent-announce.js +79 -34
  55. package/dist/agents/system-prompt.js +28 -4
  56. package/dist/agents/together-models.js +127 -0
  57. package/dist/agents/tool-images.js +1 -1
  58. package/dist/agents/tool-policy.conformance.js +14 -0
  59. package/dist/agents/tool-policy.js +25 -1
  60. package/dist/agents/tools/browser-tool.js +3 -3
  61. package/dist/agents/tools/cron-tool.js +166 -19
  62. package/dist/agents/tools/discord-actions-presence.js +78 -0
  63. package/dist/agents/tools/image-tool.js +2 -2
  64. package/dist/agents/tools/memory-tool.js +93 -5
  65. package/dist/agents/tools/message-tool.js +56 -2
  66. package/dist/agents/tools/sessions-history-tool.js +69 -1
  67. package/dist/agents/tools/web-search.js +211 -42
  68. package/dist/agents/usage.js +23 -1
  69. package/dist/agents/workspace-run.js +67 -0
  70. package/dist/agents/workspace-templates.js +44 -0
  71. package/dist/auto-reply/command-auth.js +121 -6
  72. package/dist/auto-reply/commands-registry.data.js +1 -1
  73. package/dist/auto-reply/envelope.js +50 -72
  74. package/dist/auto-reply/reply/commands-compact.js +1 -0
  75. package/dist/auto-reply/reply/commands-context-report.js +3 -2
  76. package/dist/auto-reply/reply/commands-context.js +1 -0
  77. package/dist/auto-reply/reply/commands-models.js +107 -60
  78. package/dist/auto-reply/reply/commands-ptt.js +171 -0
  79. package/dist/auto-reply/reply/commands-session.js +2 -2
  80. package/dist/auto-reply/reply/get-reply-run.js +16 -5
  81. package/dist/auto-reply/reply/groups.js +1 -1
  82. package/dist/auto-reply/reply/inbound-context.js +9 -1
  83. package/dist/auto-reply/reply/inbound-meta.js +130 -0
  84. package/dist/auto-reply/reply/model-selection.js +3 -3
  85. package/dist/auto-reply/reply/untrusted-context.js +15 -0
  86. package/dist/auto-reply/status.js +1 -1
  87. package/dist/auto-reply/thinking.js +88 -43
  88. package/dist/browser/bridge-server.js +13 -0
  89. package/dist/browser/cdp.helpers.js +38 -24
  90. package/dist/browser/client-fetch.js +51 -8
  91. package/dist/browser/config.js +2 -11
  92. package/dist/browser/extension-relay.js +104 -43
  93. package/dist/browser/pw-ai.js +1 -1
  94. package/dist/browser/pw-session.js +143 -8
  95. package/dist/browser/pw-tools-core.interactions.js +125 -27
  96. package/dist/browser/pw-tools-core.responses.js +1 -1
  97. package/dist/browser/pw-tools-core.state.js +1 -1
  98. package/dist/browser/routes/agent.act.js +86 -41
  99. package/dist/browser/routes/dispatcher.js +4 -4
  100. package/dist/browser/screenshot.js +1 -1
  101. package/dist/browser/server-context.js +2 -2
  102. package/dist/browser/server.js +13 -0
  103. package/dist/build-info.json +3 -3
  104. package/dist/canvas-host/a2ui.js +3 -3
  105. package/dist/channels/plugins/catalog.js +2 -2
  106. package/dist/channels/plugins/onboarding/imessage.js +1 -1
  107. package/dist/channels/plugins/onboarding/signal.js +1 -1
  108. package/dist/channels/plugins/onboarding/slack.js +4 -4
  109. package/dist/channels/plugins/onboarding/whatsapp.js +3 -3
  110. package/dist/channels/plugins/pairing-message.js +1 -1
  111. package/dist/channels/reply-prefix.js +8 -1
  112. package/dist/cli/browser-cli-extension.js +2 -2
  113. package/dist/cli/cron-cli/register.cron-add.js +61 -40
  114. package/dist/cli/cron-cli/register.cron-edit.js +60 -34
  115. package/dist/cli/cron-cli/shared.js +56 -41
  116. package/dist/cli/dns-cli.js +26 -14
  117. package/dist/cli/docs-cli.js +1 -1
  118. package/dist/cli/gateway-cli/dev.js +1 -1
  119. package/dist/cli/gateway-cli/register.js +37 -19
  120. package/dist/cli/memory-cli.js +30 -20
  121. package/dist/cli/nodes-cli/register.canvas.js +1 -1
  122. package/dist/cli/parse-bytes.js +37 -0
  123. package/dist/cli/plugins-cli.js +1 -1
  124. package/dist/cli/run-main.js +2 -2
  125. package/dist/cli/security-cli.js +1 -1
  126. package/dist/cli/tagline.js +1 -1
  127. package/dist/cli/update-cli.js +173 -52
  128. package/dist/cli/webhooks-cli.js +5 -5
  129. package/dist/commands/agent.js +1 -0
  130. package/dist/commands/agents.commands.add.js +1 -1
  131. package/dist/commands/auth-choice.apply.api-providers.js +305 -17
  132. package/dist/commands/auth-choice.apply.js +4 -1
  133. package/dist/commands/auth-choice.apply.plugin-provider.js +2 -2
  134. package/dist/commands/auth-choice.apply.xai.js +63 -0
  135. package/dist/commands/auth-choice.preferred-provider.js +7 -1
  136. package/dist/commands/configure.wizard.js +1 -1
  137. package/dist/commands/dashboard.js +1 -1
  138. package/dist/commands/docs.js +1 -1
  139. package/dist/commands/doctor-config-flow.js +61 -5
  140. package/dist/commands/doctor-gateway-services.js +3 -3
  141. package/dist/commands/doctor-state-migrations.js +1 -1
  142. package/dist/commands/doctor-update.js +3 -3
  143. package/dist/commands/doctor.js +1 -1
  144. package/dist/commands/health.js +1 -1
  145. package/dist/commands/model-allowlist.js +29 -0
  146. package/dist/commands/model-picker.js +2 -1
  147. package/dist/commands/models/list.probe.js +2 -2
  148. package/dist/commands/models/list.registry.js +4 -4
  149. package/dist/commands/models/list.status-command.js +44 -24
  150. package/dist/commands/models/shared.js +15 -0
  151. package/dist/commands/onboard-auth.config-core.js +366 -28
  152. package/dist/commands/onboard-auth.credentials.js +71 -9
  153. package/dist/commands/onboard-auth.js +3 -3
  154. package/dist/commands/onboard-auth.models.js +26 -24
  155. package/dist/commands/onboard-custom.js +384 -0
  156. package/dist/commands/onboard-non-interactive/local/auth-choice-inference.js +35 -0
  157. package/dist/commands/onboard-non-interactive/local/auth-choice.js +146 -9
  158. package/dist/commands/onboard-skills.js +63 -38
  159. package/dist/commands/openai-model-default.js +41 -0
  160. package/dist/commands/status-all/report-lines.js +1 -1
  161. package/dist/commands/status.command.js +1 -1
  162. package/dist/commands/uninstall.js +3 -3
  163. package/dist/compat/legacy-names.js +1 -1
  164. package/dist/config/defaults.js +3 -2
  165. package/dist/config/io.js +3 -3
  166. package/dist/config/paths.js +136 -35
  167. package/dist/config/plugin-auto-enable.js +21 -5
  168. package/dist/config/redact-snapshot.js +153 -0
  169. package/dist/config/schema.field-metadata.js +590 -0
  170. package/dist/config/schema.js +3 -3
  171. package/dist/config/sessions/store.js +291 -23
  172. package/dist/config/types.memory.js +1 -0
  173. package/dist/config/version.js +4 -4
  174. package/dist/config/zod-schema.agent-defaults.js +3 -0
  175. package/dist/config/zod-schema.agent-runtime.js +13 -2
  176. package/dist/config/zod-schema.providers-core.js +142 -0
  177. package/dist/config/zod-schema.session.js +3 -0
  178. package/dist/cron/delivery.js +57 -0
  179. package/dist/cron/isolated-agent/delivery-target.js +18 -3
  180. package/dist/cron/isolated-agent/helpers.js +22 -5
  181. package/dist/cron/isolated-agent/run.js +171 -63
  182. package/dist/cron/isolated-agent/session.js +2 -0
  183. package/dist/cron/normalize.js +356 -28
  184. package/dist/cron/parse.js +10 -5
  185. package/dist/cron/run-log.js +35 -10
  186. package/dist/cron/schedule.js +41 -6
  187. package/dist/cron/service/jobs.js +208 -35
  188. package/dist/cron/service/ops.js +72 -16
  189. package/dist/cron/service/state.js +2 -0
  190. package/dist/cron/service/store.js +386 -14
  191. package/dist/cron/service/timer.js +390 -147
  192. package/dist/cron/session-reaper.js +86 -0
  193. package/dist/cron/store.js +23 -8
  194. package/dist/cron/validate-timestamp.js +43 -0
  195. package/dist/daemon/constants.js +7 -7
  196. package/dist/daemon/inspect.js +6 -6
  197. package/dist/daemon/systemd-unit.js +1 -1
  198. package/dist/discord/monitor/agent-components.js +438 -0
  199. package/dist/discord/monitor/allow-list.js +28 -5
  200. package/dist/discord/monitor/gateway-registry.js +29 -0
  201. package/dist/discord/monitor/native-command.js +44 -23
  202. package/dist/discord/monitor/sender-identity.js +45 -0
  203. package/dist/discord/pluralkit.js +27 -0
  204. package/dist/discord/send.outbound.js +92 -5
  205. package/dist/discord/send.shared.js +60 -23
  206. package/dist/discord/targets.js +84 -1
  207. package/dist/entry.js +15 -9
  208. package/dist/extensionAPI.js +8 -0
  209. package/dist/gateway/control-ui.js +8 -1
  210. package/dist/gateway/hooks-mapping.js +3 -0
  211. package/dist/gateway/hooks.js +65 -0
  212. package/dist/gateway/live-image-probe.js +1 -66
  213. package/dist/gateway/net.js +96 -31
  214. package/dist/gateway/node-command-policy.js +50 -15
  215. package/dist/gateway/openai-http.js +2 -2
  216. package/dist/gateway/openresponses-http.js +4 -4
  217. package/dist/gateway/origin-check.js +56 -0
  218. package/dist/gateway/protocol/client-info.js +9 -0
  219. package/dist/gateway/protocol/index.js +9 -2
  220. package/dist/gateway/protocol/schema/agents-models-skills.js +71 -1
  221. package/dist/gateway/protocol/schema/cron.js +22 -10
  222. package/dist/gateway/protocol/schema/protocol-schemas.js +16 -2
  223. package/dist/gateway/protocol/schema/sessions.js +12 -0
  224. package/dist/gateway/server/hooks.js +1 -1
  225. package/dist/gateway/server-broadcast.js +26 -9
  226. package/dist/gateway/server-chat.js +112 -23
  227. package/dist/gateway/server-discovery-runtime.js +10 -2
  228. package/dist/gateway/server-discovery.js +2 -2
  229. package/dist/gateway/server-http.js +110 -12
  230. package/dist/gateway/server-methods/agent-timestamp.js +60 -0
  231. package/dist/gateway/server-methods/agents.js +321 -2
  232. package/dist/gateway/server-methods/usage.js +559 -16
  233. package/dist/gateway/server-runtime-state.js +22 -8
  234. package/dist/gateway/server-startup-memory.js +16 -0
  235. package/dist/gateway/server.impl.js +7 -3
  236. package/dist/gateway/session-utils.fs.js +23 -25
  237. package/dist/gateway/session-utils.js +20 -10
  238. package/dist/gateway/sessions-patch.js +7 -22
  239. package/dist/gateway/test-helpers.server.js +35 -2
  240. package/dist/hooks/frontmatter.js +1 -1
  241. package/dist/hooks/hooks-status.js +1 -1
  242. package/dist/hooks/install.js +2 -2
  243. package/dist/hooks/loader.js +1 -1
  244. package/dist/hooks/workspace.js +3 -3
  245. package/dist/imessage/constants.js +2 -0
  246. package/dist/imessage/monitor/deliver.js +4 -1
  247. package/dist/imessage/monitor/monitor-provider.js +51 -1
  248. package/dist/index.js +2 -2
  249. package/dist/infra/bonjour-discovery.js +131 -70
  250. package/dist/infra/bonjour.js +3 -3
  251. package/dist/infra/control-ui-assets.js +134 -12
  252. package/dist/infra/errors.js +12 -0
  253. package/dist/infra/exec-approvals.js +266 -57
  254. package/dist/infra/format-time/format-datetime.js +79 -0
  255. package/dist/infra/format-time/format-duration.js +81 -0
  256. package/dist/infra/format-time/format-relative.js +80 -0
  257. package/dist/infra/heartbeat-runner.js +140 -49
  258. package/dist/infra/home-dir.js +54 -0
  259. package/dist/infra/net/fetch-guard.js +122 -0
  260. package/dist/infra/net/ssrf.js +65 -29
  261. package/dist/infra/outbound/abort.js +14 -0
  262. package/dist/infra/outbound/message-action-runner.js +77 -13
  263. package/dist/infra/outbound/outbound-session.js +143 -37
  264. package/dist/infra/path-env.js +3 -3
  265. package/dist/infra/poolbot-root.js +43 -1
  266. package/dist/infra/provider-usage.fetch.minimax.js +1 -1
  267. package/dist/infra/restart.js +1 -1
  268. package/dist/infra/session-cost-usage.js +631 -41
  269. package/dist/infra/state-migrations.js +317 -47
  270. package/dist/infra/tailscale.js +1 -1
  271. package/dist/infra/update-global.js +35 -0
  272. package/dist/infra/update-runner.js +149 -43
  273. package/dist/infra/warning-filter.js +65 -0
  274. package/dist/infra/widearea-dns.js +30 -9
  275. package/dist/logging/redact-identifier.js +12 -0
  276. package/dist/macos/relay.js +2 -2
  277. package/dist/media/fetch.js +81 -58
  278. package/dist/media/input-files.js +1 -1
  279. package/dist/media/mime.js +4 -0
  280. package/dist/media/png-encode.js +74 -0
  281. package/dist/media-understanding/apply.js +403 -3
  282. package/dist/media-understanding/attachments.js +38 -27
  283. package/dist/media-understanding/defaults.js +16 -0
  284. package/dist/media-understanding/providers/deepgram/audio.js +22 -14
  285. package/dist/media-understanding/providers/google/audio.js +24 -17
  286. package/dist/media-understanding/providers/google/video.js +24 -17
  287. package/dist/media-understanding/providers/image.js +4 -4
  288. package/dist/media-understanding/providers/index.js +4 -1
  289. package/dist/media-understanding/providers/openai/audio.js +22 -14
  290. package/dist/media-understanding/providers/shared.js +16 -11
  291. package/dist/media-understanding/providers/zai/index.js +6 -0
  292. package/dist/media-understanding/runner.js +158 -90
  293. package/dist/memory/backend-config.js +207 -0
  294. package/dist/memory/batch-voyage.js +277 -0
  295. package/dist/memory/embeddings-voyage.js +75 -0
  296. package/dist/memory/embeddings.js +29 -17
  297. package/dist/memory/internal.js +101 -18
  298. package/dist/memory/manager.js +155 -48
  299. package/dist/memory/search-manager.js +173 -0
  300. package/dist/memory/session-files.js +9 -3
  301. package/dist/memory/types.js +1 -0
  302. package/dist/node-host/runner.js +36 -26
  303. package/dist/node-host/with-timeout.js +27 -0
  304. package/dist/pairing/pairing-messages.js +1 -1
  305. package/dist/plugins/commands.js +5 -1
  306. package/dist/plugins/config-state.js +86 -7
  307. package/dist/plugins/discovery.js +1 -1
  308. package/dist/plugins/install.js +2 -2
  309. package/dist/plugins/source-display.js +51 -0
  310. package/dist/plugins/update.js +1 -1
  311. package/dist/process/exec.js +20 -2
  312. package/dist/routing/resolve-route.js +12 -0
  313. package/dist/routing/session-key.js +15 -0
  314. package/dist/runtime.js +2 -0
  315. package/dist/security/audit-extra.async.js +601 -0
  316. package/dist/security/audit-extra.js +2 -830
  317. package/dist/security/audit-extra.sync.js +505 -0
  318. package/dist/security/audit.js +2 -2
  319. package/dist/security/channel-metadata.js +34 -0
  320. package/dist/security/external-content.js +88 -6
  321. package/dist/security/skill-scanner.js +330 -0
  322. package/dist/sessions/session-key-utils.js +7 -0
  323. package/dist/shared/text/reasoning-tags.js +52 -7
  324. package/dist/signal/monitor/event-handler.js +80 -1
  325. package/dist/slack/monitor/media.js +85 -15
  326. package/dist/tailscale/detect.js +145 -0
  327. package/dist/telegram/bot/helpers.js +109 -28
  328. package/dist/telegram/bot-handlers.js +144 -3
  329. package/dist/telegram/bot-message-context.js +38 -11
  330. package/dist/telegram/bot-message-dispatch.js +48 -15
  331. package/dist/telegram/bot-native-commands.js +86 -29
  332. package/dist/telegram/bot.js +30 -29
  333. package/dist/telegram/model-buttons.js +163 -0
  334. package/dist/telegram/monitor.js +110 -85
  335. package/dist/telegram/send.js +129 -47
  336. package/dist/terminal/restore.js +45 -0
  337. package/dist/test-helpers/state-dir-env.js +16 -0
  338. package/dist/test-helpers/workspace.js +11 -0
  339. package/dist/test-utils/channel-plugins.js +82 -0
  340. package/dist/test-utils/ports.js +73 -0
  341. package/dist/tts/tts.js +12 -6
  342. package/dist/tui/tui-session-actions.js +166 -54
  343. package/dist/utils/fetch-timeout.js +20 -0
  344. package/dist/utils/normalize-secret-input.js +19 -0
  345. package/dist/utils/shell-argv.js +61 -0
  346. package/dist/utils/transcript-tools.js +58 -0
  347. package/dist/utils.js +55 -14
  348. package/dist/version.js +42 -5
  349. package/dist/web/qr-image.js +1 -61
  350. package/dist/wizard/onboarding.finalize.js +7 -7
  351. package/dist/wizard/onboarding.js +3 -3
  352. package/docs/RELEASE_WORKFOTS_COMPARISON.md +3 -3
  353. package/docs/_config.yml +2 -2
  354. package/docs/_layouts/default.html +9 -9
  355. package/docs/concepts/typebox.md +1 -1
  356. package/docs/docs.json +1 -1
  357. package/docs/northflank.mdx +7 -7
  358. package/docs/railway.mdx +3 -3
  359. package/docs/render.mdx +5 -5
  360. package/docs/start/lore.md +2 -2
  361. package/extensions/bluebubbles/index.ts +2 -2
  362. package/extensions/bluebubbles/package.json +1 -1
  363. package/extensions/bluebubbles/src/accounts.ts +8 -8
  364. package/extensions/bluebubbles/src/actions.test.ts +22 -22
  365. package/extensions/bluebubbles/src/actions.ts +5 -5
  366. package/extensions/bluebubbles/src/attachments.ts +2 -2
  367. package/extensions/bluebubbles/src/channel.ts +16 -16
  368. package/extensions/bluebubbles/src/chat.ts +2 -2
  369. package/extensions/bluebubbles/src/media-send.ts +2 -2
  370. package/extensions/bluebubbles/src/monitor.test.ts +46 -46
  371. package/extensions/bluebubbles/src/monitor.ts +5 -5
  372. package/extensions/bluebubbles/src/onboarding.ts +7 -7
  373. package/extensions/bluebubbles/src/reactions.ts +2 -2
  374. package/extensions/bluebubbles/src/send.ts +2 -2
  375. package/extensions/copilot-proxy/README.md +1 -1
  376. package/extensions/copilot-proxy/package.json +1 -1
  377. package/extensions/diagnostics-otel/index.ts +2 -2
  378. package/extensions/diagnostics-otel/package.json +1 -1
  379. package/extensions/diagnostics-otel/src/service.ts +3 -3
  380. package/extensions/discord/index.ts +2 -2
  381. package/extensions/discord/package.json +1 -1
  382. package/extensions/google-antigravity-auth/README.md +1 -1
  383. package/extensions/google-antigravity-auth/index.ts +1 -1
  384. package/extensions/google-antigravity-auth/package.json +1 -1
  385. package/extensions/google-gemini-cli-auth/README.md +1 -1
  386. package/extensions/google-gemini-cli-auth/oauth.ts +1 -1
  387. package/extensions/google-gemini-cli-auth/package.json +1 -1
  388. package/extensions/googlechat/index.ts +3 -3
  389. package/extensions/googlechat/package.json +1 -1
  390. package/extensions/googlechat/src/accounts.ts +8 -8
  391. package/extensions/googlechat/src/actions.ts +6 -6
  392. package/extensions/googlechat/src/channel.ts +21 -21
  393. package/extensions/googlechat/src/monitor.ts +8 -8
  394. package/extensions/googlechat/src/onboarding.ts +10 -10
  395. package/extensions/imessage/index.ts +2 -2
  396. package/extensions/imessage/package.json +1 -1
  397. package/extensions/line/index.ts +2 -2
  398. package/extensions/line/package.json +1 -1
  399. package/extensions/line/src/card-command.ts +2 -2
  400. package/extensions/line/src/channel.logout.test.ts +4 -4
  401. package/extensions/line/src/channel.sendPayload.test.ts +8 -8
  402. package/extensions/line/src/channel.ts +3 -3
  403. package/extensions/llm-task/README.md +3 -3
  404. package/extensions/llm-task/index.ts +2 -2
  405. package/extensions/llm-task/package.json +1 -1
  406. package/extensions/llm-task/src/llm-task-tool.ts +4 -4
  407. package/extensions/lobster/README.md +6 -6
  408. package/extensions/lobster/index.ts +2 -2
  409. package/extensions/lobster/src/lobster-tool.test.ts +4 -4
  410. package/extensions/lobster/src/lobster-tool.ts +2 -2
  411. package/extensions/matrix/index.ts +2 -2
  412. package/extensions/matrix/package.json +1 -1
  413. package/extensions/matrix/src/matrix/client/config.ts +1 -1
  414. package/extensions/matrix/src/matrix/monitor/handler.ts +1 -1
  415. package/extensions/matrix/src/onboarding.ts +1 -1
  416. package/extensions/mattermost/index.ts +2 -2
  417. package/extensions/mattermost/package.json +1 -1
  418. package/extensions/mattermost/src/mattermost/accounts.ts +8 -8
  419. package/extensions/mattermost/src/mattermost/monitor-helpers.ts +5 -5
  420. package/extensions/mattermost/src/mattermost/monitor.ts +2 -2
  421. package/extensions/mattermost/src/onboarding-helpers.ts +3 -3
  422. package/extensions/mattermost/src/onboarding.ts +2 -2
  423. package/extensions/memory-core/index.ts +2 -2
  424. package/extensions/memory-core/package.json +1 -1
  425. package/extensions/memory-lancedb/index.ts +3 -3
  426. package/extensions/memory-lancedb/package.json +1 -1
  427. package/extensions/msteams/index.ts +2 -2
  428. package/extensions/msteams/package.json +1 -1
  429. package/extensions/msteams/src/channel.directory.test.ts +2 -2
  430. package/extensions/msteams/src/channel.ts +2 -2
  431. package/extensions/msteams/src/graph-upload.ts +4 -4
  432. package/extensions/msteams/src/monitor-handler.ts +2 -2
  433. package/extensions/msteams/src/monitor.ts +2 -2
  434. package/extensions/msteams/src/onboarding.ts +9 -9
  435. package/extensions/msteams/src/reply-dispatcher.ts +2 -2
  436. package/extensions/msteams/src/send-context.ts +2 -2
  437. package/extensions/msteams/src/send.ts +4 -4
  438. package/extensions/nextcloud-talk/index.ts +2 -2
  439. package/extensions/nextcloud-talk/package.json +1 -1
  440. package/extensions/nextcloud-talk/src/channel.ts +7 -7
  441. package/extensions/nextcloud-talk/src/inbound.ts +7 -7
  442. package/extensions/nextcloud-talk/src/onboarding.ts +1 -1
  443. package/extensions/nostr/README.md +2 -2
  444. package/extensions/nostr/index.ts +5 -5
  445. package/extensions/nostr/package.json +1 -1
  446. package/extensions/nostr/src/types.ts +4 -4
  447. package/extensions/open-prose/index.ts +2 -2
  448. package/extensions/qwen-portal-auth/README.md +1 -1
  449. package/extensions/signal/index.ts +2 -2
  450. package/extensions/signal/package.json +1 -1
  451. package/extensions/slack/index.ts +2 -2
  452. package/extensions/slack/package.json +1 -1
  453. package/extensions/telegram/index.ts +2 -2
  454. package/extensions/telegram/package.json +1 -1
  455. package/extensions/telegram/src/channel.ts +2 -2
  456. package/extensions/tlon/README.md +2 -2
  457. package/extensions/tlon/index.ts +2 -2
  458. package/extensions/tlon/package.json +1 -1
  459. package/extensions/tlon/src/channel.ts +13 -13
  460. package/extensions/tlon/src/monitor/index.ts +3 -3
  461. package/extensions/tlon/src/onboarding.ts +3 -3
  462. package/extensions/tlon/src/types.ts +3 -3
  463. package/extensions/twitch/README.md +1 -1
  464. package/extensions/twitch/index.ts +2 -2
  465. package/extensions/twitch/package.json +1 -1
  466. package/extensions/twitch/src/config.ts +3 -3
  467. package/extensions/twitch/src/monitor.ts +3 -3
  468. package/extensions/twitch/src/onboarding.ts +9 -9
  469. package/extensions/twitch/src/outbound.test.ts +2 -2
  470. package/extensions/twitch/src/plugin.test.ts +2 -2
  471. package/extensions/twitch/src/plugin.ts +8 -8
  472. package/extensions/twitch/src/send.test.ts +2 -2
  473. package/extensions/twitch/src/send.ts +4 -4
  474. package/extensions/twitch/src/token.test.ts +8 -8
  475. package/extensions/twitch/src/token.ts +3 -3
  476. package/extensions/twitch/src/twitch-client.ts +3 -3
  477. package/extensions/twitch/src/types.ts +3 -3
  478. package/extensions/twitch/src/utils/markdown.ts +1 -1
  479. package/extensions/voice-call/README.md +3 -3
  480. package/extensions/voice-call/package.json +1 -1
  481. package/extensions/voice-call/src/core-bridge.ts +2 -2
  482. package/extensions/voice-call/src/response-generator.ts +1 -1
  483. package/extensions/whatsapp/index.ts +2 -2
  484. package/extensions/whatsapp/package.json +1 -1
  485. package/extensions/zalo/README.md +1 -1
  486. package/extensions/zalo/index.ts +2 -2
  487. package/extensions/zalo/package.json +1 -1
  488. package/extensions/zalo/src/accounts.ts +8 -8
  489. package/extensions/zalo/src/actions.ts +4 -4
  490. package/extensions/zalo/src/channel.directory.test.ts +2 -2
  491. package/extensions/zalo/src/channel.ts +18 -18
  492. package/extensions/zalo/src/monitor.ts +9 -9
  493. package/extensions/zalo/src/monitor.webhook.test.ts +2 -2
  494. package/extensions/zalo/src/onboarding.ts +24 -24
  495. package/extensions/zalo/src/send.ts +2 -2
  496. package/extensions/zalouser/README.md +2 -2
  497. package/extensions/zalouser/index.ts +2 -2
  498. package/extensions/zalouser/package.json +1 -1
  499. package/extensions/zalouser/src/accounts.ts +9 -9
  500. package/extensions/zalouser/src/channel.ts +24 -24
  501. package/extensions/zalouser/src/monitor.ts +4 -4
  502. package/extensions/zalouser/src/onboarding.ts +28 -28
  503. package/package.json +13 -251
  504. package/skills/nano-banana-pro/scripts/generate_image.py +1 -1
  505. package/skills/tmux/scripts/find-sessions.sh +1 -1
  506. package/CHANGELOG.md +0 -102
  507. package/README-header.png +0 -0
  508. package/git-hooks/pre-commit +0 -4
  509. package/scripts/format-staged.js +0 -148
  510. package/scripts/postinstall.js +0 -300
  511. package/scripts/setup-git-hooks.js +0 -96
@@ -0,0 +1,330 @@
1
+ import fs from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { hasErrnoCode } from "../infra/errors.js";
4
+ // ---------------------------------------------------------------------------
5
+ // Scannable extensions
6
+ // ---------------------------------------------------------------------------
7
+ const SCANNABLE_EXTENSIONS = new Set([
8
+ ".js",
9
+ ".ts",
10
+ ".mjs",
11
+ ".cjs",
12
+ ".mts",
13
+ ".cts",
14
+ ".jsx",
15
+ ".tsx",
16
+ ]);
17
+ const DEFAULT_MAX_SCAN_FILES = 500;
18
+ const DEFAULT_MAX_FILE_BYTES = 1024 * 1024;
19
+ export function isScannable(filePath) {
20
+ return SCANNABLE_EXTENSIONS.has(path.extname(filePath).toLowerCase());
21
+ }
22
+ const LINE_RULES = [
23
+ {
24
+ ruleId: "dangerous-exec",
25
+ severity: "critical",
26
+ message: "Shell command execution detected (child_process)",
27
+ pattern: /\b(exec|execSync|spawn|spawnSync|execFile|execFileSync)\s*\(/,
28
+ requiresContext: /child_process/,
29
+ },
30
+ {
31
+ ruleId: "dynamic-code-execution",
32
+ severity: "critical",
33
+ message: "Dynamic code execution detected",
34
+ pattern: /\beval\s*\(|new\s+Function\s*\(/,
35
+ },
36
+ {
37
+ ruleId: "crypto-mining",
38
+ severity: "critical",
39
+ message: "Possible crypto-mining reference detected",
40
+ pattern: /stratum\+tcp|stratum\+ssl|coinhive|cryptonight|xmrig/i,
41
+ },
42
+ {
43
+ ruleId: "suspicious-network",
44
+ severity: "warn",
45
+ message: "WebSocket connection to non-standard port",
46
+ pattern: /new\s+WebSocket\s*\(\s*["']wss?:\/\/[^"']*:(\d+)/,
47
+ },
48
+ ];
49
+ const STANDARD_PORTS = new Set([80, 443, 8080, 8443, 3000]);
50
+ const SOURCE_RULES = [
51
+ {
52
+ ruleId: "potential-exfiltration",
53
+ severity: "warn",
54
+ message: "File read combined with network send — possible data exfiltration",
55
+ pattern: /readFileSync|readFile/,
56
+ requiresContext: /\bfetch\b|\bpost\b|http\.request/i,
57
+ },
58
+ {
59
+ ruleId: "obfuscated-code",
60
+ severity: "warn",
61
+ message: "Hex-encoded string sequence detected (possible obfuscation)",
62
+ pattern: /(\\x[0-9a-fA-F]{2}){6,}/,
63
+ },
64
+ {
65
+ ruleId: "obfuscated-code",
66
+ severity: "warn",
67
+ message: "Large base64 payload with decode call detected (possible obfuscation)",
68
+ pattern: /(?:atob|Buffer\.from)\s*\(\s*["'][A-Za-z0-9+/=]{200,}["']/,
69
+ },
70
+ {
71
+ ruleId: "env-harvesting",
72
+ severity: "critical",
73
+ message: "Environment variable access combined with network send — possible credential harvesting",
74
+ pattern: /process\.env/,
75
+ requiresContext: /\bfetch\b|\bpost\b|http\.request/i,
76
+ },
77
+ ];
78
+ // ---------------------------------------------------------------------------
79
+ // Core scanner
80
+ // ---------------------------------------------------------------------------
81
+ function truncateEvidence(evidence, maxLen = 120) {
82
+ if (evidence.length <= maxLen) {
83
+ return evidence;
84
+ }
85
+ return `${evidence.slice(0, maxLen)}…`;
86
+ }
87
+ export function scanSource(source, filePath) {
88
+ const findings = [];
89
+ const lines = source.split("\n");
90
+ const matchedLineRules = new Set();
91
+ // --- Line rules ---
92
+ for (const rule of LINE_RULES) {
93
+ if (matchedLineRules.has(rule.ruleId)) {
94
+ continue;
95
+ }
96
+ // Skip rule entirely if context requirement not met
97
+ if (rule.requiresContext && !rule.requiresContext.test(source)) {
98
+ continue;
99
+ }
100
+ for (let i = 0; i < lines.length; i++) {
101
+ const line = lines[i];
102
+ const match = rule.pattern.exec(line);
103
+ if (!match) {
104
+ continue;
105
+ }
106
+ // Special handling for suspicious-network: check port
107
+ if (rule.ruleId === "suspicious-network") {
108
+ const port = parseInt(match[1], 10);
109
+ if (STANDARD_PORTS.has(port)) {
110
+ continue;
111
+ }
112
+ }
113
+ findings.push({
114
+ ruleId: rule.ruleId,
115
+ severity: rule.severity,
116
+ file: filePath,
117
+ line: i + 1,
118
+ message: rule.message,
119
+ evidence: truncateEvidence(line.trim()),
120
+ });
121
+ matchedLineRules.add(rule.ruleId);
122
+ break; // one finding per line-rule per file
123
+ }
124
+ }
125
+ // --- Source rules ---
126
+ const matchedSourceRules = new Set();
127
+ for (const rule of SOURCE_RULES) {
128
+ // Allow multiple findings for different messages with the same ruleId
129
+ // but deduplicate exact (ruleId+message) combos
130
+ const ruleKey = `${rule.ruleId}::${rule.message}`;
131
+ if (matchedSourceRules.has(ruleKey)) {
132
+ continue;
133
+ }
134
+ if (!rule.pattern.test(source)) {
135
+ continue;
136
+ }
137
+ if (rule.requiresContext && !rule.requiresContext.test(source)) {
138
+ continue;
139
+ }
140
+ // Find the first matching line for evidence + line number
141
+ let matchLine = 0;
142
+ let matchEvidence = "";
143
+ for (let i = 0; i < lines.length; i++) {
144
+ if (rule.pattern.test(lines[i])) {
145
+ matchLine = i + 1;
146
+ matchEvidence = lines[i].trim();
147
+ break;
148
+ }
149
+ }
150
+ // For source rules, if we can't find a line match the pattern might span
151
+ // lines. Report line 0 with truncated source as evidence.
152
+ if (matchLine === 0) {
153
+ matchLine = 1;
154
+ matchEvidence = source.slice(0, 120);
155
+ }
156
+ findings.push({
157
+ ruleId: rule.ruleId,
158
+ severity: rule.severity,
159
+ file: filePath,
160
+ line: matchLine,
161
+ message: rule.message,
162
+ evidence: truncateEvidence(matchEvidence),
163
+ });
164
+ matchedSourceRules.add(ruleKey);
165
+ }
166
+ return findings;
167
+ }
168
+ // ---------------------------------------------------------------------------
169
+ // Directory scanner
170
+ // ---------------------------------------------------------------------------
171
+ function normalizeScanOptions(opts) {
172
+ return {
173
+ includeFiles: opts?.includeFiles ?? [],
174
+ maxFiles: Math.max(1, opts?.maxFiles ?? DEFAULT_MAX_SCAN_FILES),
175
+ maxFileBytes: Math.max(1, opts?.maxFileBytes ?? DEFAULT_MAX_FILE_BYTES),
176
+ };
177
+ }
178
+ function isPathInside(basePath, candidatePath) {
179
+ const base = path.resolve(basePath);
180
+ const candidate = path.resolve(candidatePath);
181
+ const rel = path.relative(base, candidate);
182
+ return rel === "" || (!rel.startsWith(`..${path.sep}`) && rel !== ".." && !path.isAbsolute(rel));
183
+ }
184
+ async function walkDirWithLimit(dirPath, maxFiles) {
185
+ const files = [];
186
+ const stack = [dirPath];
187
+ while (stack.length > 0 && files.length < maxFiles) {
188
+ const currentDir = stack.pop();
189
+ if (!currentDir) {
190
+ break;
191
+ }
192
+ const entries = await fs.readdir(currentDir, { withFileTypes: true });
193
+ for (const entry of entries) {
194
+ if (files.length >= maxFiles) {
195
+ break;
196
+ }
197
+ // Skip hidden dirs and node_modules
198
+ if (entry.name.startsWith(".") || entry.name === "node_modules") {
199
+ continue;
200
+ }
201
+ const fullPath = path.join(currentDir, entry.name);
202
+ if (entry.isDirectory()) {
203
+ stack.push(fullPath);
204
+ }
205
+ else if (isScannable(entry.name)) {
206
+ files.push(fullPath);
207
+ }
208
+ }
209
+ }
210
+ return files;
211
+ }
212
+ async function resolveForcedFiles(params) {
213
+ if (params.includeFiles.length === 0) {
214
+ return [];
215
+ }
216
+ const seen = new Set();
217
+ const out = [];
218
+ for (const rawIncludePath of params.includeFiles) {
219
+ const includePath = path.resolve(params.rootDir, rawIncludePath);
220
+ if (!isPathInside(params.rootDir, includePath)) {
221
+ continue;
222
+ }
223
+ if (!isScannable(includePath)) {
224
+ continue;
225
+ }
226
+ if (seen.has(includePath)) {
227
+ continue;
228
+ }
229
+ let st = null;
230
+ try {
231
+ st = await fs.stat(includePath);
232
+ }
233
+ catch (err) {
234
+ if (hasErrnoCode(err, "ENOENT")) {
235
+ continue;
236
+ }
237
+ throw err;
238
+ }
239
+ if (!st?.isFile()) {
240
+ continue;
241
+ }
242
+ out.push(includePath);
243
+ seen.add(includePath);
244
+ }
245
+ return out;
246
+ }
247
+ async function collectScannableFiles(dirPath, opts) {
248
+ const forcedFiles = await resolveForcedFiles({
249
+ rootDir: dirPath,
250
+ includeFiles: opts.includeFiles,
251
+ });
252
+ if (forcedFiles.length >= opts.maxFiles) {
253
+ return forcedFiles.slice(0, opts.maxFiles);
254
+ }
255
+ const walkedFiles = await walkDirWithLimit(dirPath, opts.maxFiles);
256
+ const seen = new Set(forcedFiles.map((f) => path.resolve(f)));
257
+ const out = [...forcedFiles];
258
+ for (const walkedFile of walkedFiles) {
259
+ if (out.length >= opts.maxFiles) {
260
+ break;
261
+ }
262
+ const resolved = path.resolve(walkedFile);
263
+ if (seen.has(resolved)) {
264
+ continue;
265
+ }
266
+ out.push(walkedFile);
267
+ seen.add(resolved);
268
+ }
269
+ return out;
270
+ }
271
+ async function readScannableSource(filePath, maxFileBytes) {
272
+ let st = null;
273
+ try {
274
+ st = await fs.stat(filePath);
275
+ }
276
+ catch (err) {
277
+ if (hasErrnoCode(err, "ENOENT")) {
278
+ return null;
279
+ }
280
+ throw err;
281
+ }
282
+ if (!st?.isFile() || st.size > maxFileBytes) {
283
+ return null;
284
+ }
285
+ try {
286
+ return await fs.readFile(filePath, "utf-8");
287
+ }
288
+ catch (err) {
289
+ if (hasErrnoCode(err, "ENOENT")) {
290
+ return null;
291
+ }
292
+ throw err;
293
+ }
294
+ }
295
+ export async function scanDirectory(dirPath, opts) {
296
+ const scanOptions = normalizeScanOptions(opts);
297
+ const files = await collectScannableFiles(dirPath, scanOptions);
298
+ const allFindings = [];
299
+ for (const file of files) {
300
+ const source = await readScannableSource(file, scanOptions.maxFileBytes);
301
+ if (source == null) {
302
+ continue;
303
+ }
304
+ const findings = scanSource(source, file);
305
+ allFindings.push(...findings);
306
+ }
307
+ return allFindings;
308
+ }
309
+ export async function scanDirectoryWithSummary(dirPath, opts) {
310
+ const scanOptions = normalizeScanOptions(opts);
311
+ const files = await collectScannableFiles(dirPath, scanOptions);
312
+ const allFindings = [];
313
+ let scannedFiles = 0;
314
+ for (const file of files) {
315
+ const source = await readScannableSource(file, scanOptions.maxFileBytes);
316
+ if (source == null) {
317
+ continue;
318
+ }
319
+ scannedFiles += 1;
320
+ const findings = scanSource(source, file);
321
+ allFindings.push(...findings);
322
+ }
323
+ return {
324
+ scannedFiles,
325
+ critical: allFindings.filter((f) => f.severity === "critical").length,
326
+ warn: allFindings.filter((f) => f.severity === "warn").length,
327
+ info: allFindings.filter((f) => f.severity === "info").length,
328
+ findings: allFindings,
329
+ };
330
+ }
@@ -13,6 +13,13 @@ export function parseAgentSessionKey(sessionKey) {
13
13
  return null;
14
14
  return { agentId, rest };
15
15
  }
16
+ export function isCronRunSessionKey(sessionKey) {
17
+ const parsed = parseAgentSessionKey(sessionKey);
18
+ if (!parsed) {
19
+ return false;
20
+ }
21
+ return /^cron:[^:]+:run:[^:]+$/.test(parsed.rest);
22
+ }
16
23
  export function isSubagentSessionKey(sessionKey) {
17
24
  const raw = (sessionKey ?? "").trim();
18
25
  if (!raw)
@@ -1,28 +1,70 @@
1
1
  const QUICK_TAG_RE = /<\s*\/?\s*(?:think(?:ing)?|thought|antthinking|final)\b/i;
2
- const FINAL_TAG_RE = /<\s*\/?\s*final\b[^>]*>/gi;
3
- const THINKING_TAG_RE = /<\s*(\/?)\s*(?:think(?:ing)?|thought|antthinking)\b[^>]*>/gi;
2
+ const FINAL_TAG_RE = /<\s*\/?\s*final\b[^<>]*>/gi;
3
+ const THINKING_TAG_RE = /<\s*(\/?)\s*(?:think(?:ing)?|thought|antthinking)\b[^<>]*>/gi;
4
+ function findCodeRegions(text) {
5
+ const regions = [];
6
+ const fencedRe = /(^|\n)(```|~~~)[^\n]*\n[\s\S]*?(?:\n\2(?:\n|$)|$)/g;
7
+ for (const match of text.matchAll(fencedRe)) {
8
+ const start = (match.index ?? 0) + match[1].length;
9
+ regions.push({ start, end: start + match[0].length - match[1].length });
10
+ }
11
+ const inlineRe = /`+[^`]+`+/g;
12
+ for (const match of text.matchAll(inlineRe)) {
13
+ const start = match.index ?? 0;
14
+ const end = start + match[0].length;
15
+ const insideFenced = regions.some((r) => start >= r.start && end <= r.end);
16
+ if (!insideFenced) {
17
+ regions.push({ start, end });
18
+ }
19
+ }
20
+ regions.sort((a, b) => a.start - b.start);
21
+ return regions;
22
+ }
23
+ function isInsideCode(pos, regions) {
24
+ return regions.some((r) => pos >= r.start && pos < r.end);
25
+ }
4
26
  function applyTrim(value, mode) {
5
- if (mode === "none")
27
+ if (mode === "none") {
6
28
  return value;
7
- if (mode === "start")
29
+ }
30
+ if (mode === "start") {
8
31
  return value.trimStart();
32
+ }
9
33
  return value.trim();
10
34
  }
11
35
  export function stripReasoningTagsFromText(text, options) {
12
- if (!text)
36
+ if (!text) {
13
37
  return text;
14
- if (!QUICK_TAG_RE.test(text))
38
+ }
39
+ if (!QUICK_TAG_RE.test(text)) {
15
40
  return text;
41
+ }
16
42
  const mode = options?.mode ?? "strict";
17
43
  const trimMode = options?.trim ?? "both";
18
44
  let cleaned = text;
19
45
  if (FINAL_TAG_RE.test(cleaned)) {
20
46
  FINAL_TAG_RE.lastIndex = 0;
21
- cleaned = cleaned.replace(FINAL_TAG_RE, "");
47
+ const finalMatches = [];
48
+ const preCodeRegions = findCodeRegions(cleaned);
49
+ for (const match of cleaned.matchAll(FINAL_TAG_RE)) {
50
+ const start = match.index ?? 0;
51
+ finalMatches.push({
52
+ start,
53
+ length: match[0].length,
54
+ inCode: isInsideCode(start, preCodeRegions),
55
+ });
56
+ }
57
+ for (let i = finalMatches.length - 1; i >= 0; i--) {
58
+ const m = finalMatches[i];
59
+ if (!m.inCode) {
60
+ cleaned = cleaned.slice(0, m.start) + cleaned.slice(m.start + m.length);
61
+ }
62
+ }
22
63
  }
23
64
  else {
24
65
  FINAL_TAG_RE.lastIndex = 0;
25
66
  }
67
+ const codeRegions = findCodeRegions(cleaned);
26
68
  THINKING_TAG_RE.lastIndex = 0;
27
69
  let result = "";
28
70
  let lastIndex = 0;
@@ -30,6 +72,9 @@ export function stripReasoningTagsFromText(text, options) {
30
72
  for (const match of cleaned.matchAll(THINKING_TAG_RE)) {
31
73
  const idx = match.index ?? 0;
32
74
  const isClose = match[1] === "/";
75
+ if (isInsideCode(idx, codeRegions)) {
76
+ continue;
77
+ }
33
78
  if (!inThinking) {
34
79
  result += cleaned.slice(lastIndex, idx);
35
80
  if (!isClose) {
@@ -3,14 +3,17 @@ import { hasControlCommand } from "../../auto-reply/command-detection.js";
3
3
  import { formatInboundEnvelope, formatInboundFromLabel, resolveEnvelopeFormatOptions, } from "../../auto-reply/envelope.js";
4
4
  import { createInboundDebouncer, resolveInboundDebounceMs, } from "../../auto-reply/inbound-debounce.js";
5
5
  import { dispatchInboundMessage } from "../../auto-reply/dispatch.js";
6
- import { buildPendingHistoryContextFromMap, clearHistoryEntriesIfEnabled, } from "../../auto-reply/reply/history.js";
6
+ import { buildPendingHistoryContextFromMap, clearHistoryEntriesIfEnabled, recordPendingHistoryEntryIfEnabled, } from "../../auto-reply/reply/history.js";
7
+ import { buildMentionRegexes, matchesMentionPatterns } from "../../auto-reply/reply/mentions.js";
7
8
  import { finalizeInboundContext } from "../../auto-reply/reply/inbound-context.js";
8
9
  import { createReplyDispatcherWithTyping } from "../../auto-reply/reply/reply-dispatcher.js";
9
10
  import { logInboundDrop, logTypingFailure } from "../../channels/logging.js";
11
+ import { resolveMentionGatingWithBypass } from "../../channels/mention-gating.js";
10
12
  import { createReplyPrefixContext } from "../../channels/reply-prefix.js";
11
13
  import { recordInboundSession } from "../../channels/session.js";
12
14
  import { createTypingCallbacks } from "../../channels/typing.js";
13
15
  import { readSessionUpdatedAt, resolveStorePath } from "../../config/sessions.js";
16
+ import { resolveChannelGroupRequireMention } from "../../config/group-policy.js";
14
17
  import { danger, logVerbose, shouldLogVerbose } from "../../globals.js";
15
18
  import { enqueueSystemEvent } from "../../infra/system-events.js";
16
19
  import { mediaKindFromMime } from "../../media/constants.js";
@@ -79,8 +82,17 @@ export function createSignalEventHandler(deps) {
79
82
  });
80
83
  }
81
84
  const signalTo = entry.isGroup ? `group:${entry.groupId}` : `signal:${entry.senderRecipient}`;
85
+ const inboundHistory = entry.isGroup && historyKey && deps.historyLimit > 0
86
+ ? (deps.groupHistories.get(historyKey) ?? []).map((historyEntry) => ({
87
+ sender: historyEntry.sender,
88
+ body: historyEntry.body,
89
+ timestamp: historyEntry.timestamp,
90
+ }))
91
+ : undefined;
82
92
  const ctxPayload = finalizeInboundContext({
83
93
  Body: combinedBody,
94
+ BodyForAgent: entry.bodyText,
95
+ InboundHistory: inboundHistory,
84
96
  RawBody: entry.bodyText,
85
97
  CommandBody: entry.bodyText,
86
98
  From: entry.isGroup
@@ -101,6 +113,7 @@ export function createSignalEventHandler(deps) {
101
113
  MediaPath: entry.mediaPath,
102
114
  MediaType: entry.mediaType,
103
115
  MediaUrl: entry.mediaPath,
116
+ WasMentioned: entry.isGroup ? entry.wasMentioned === true : undefined,
104
117
  CommandAuthorized: entry.commandAuthorized,
105
118
  OriginatingChannel: "signal",
106
119
  OriginatingTo: signalTo,
@@ -417,6 +430,71 @@ export function createSignalEventHandler(deps) {
417
430
  });
418
431
  return;
419
432
  }
433
+ const route = resolveAgentRoute({
434
+ cfg: deps.cfg,
435
+ channel: "signal",
436
+ accountId: deps.accountId,
437
+ peer: {
438
+ kind: isGroup ? "group" : "dm",
439
+ id: isGroup ? (groupId ?? "unknown") : senderPeerId,
440
+ },
441
+ });
442
+ const mentionRegexes = buildMentionRegexes(deps.cfg, route.agentId);
443
+ const wasMentioned = isGroup && matchesMentionPatterns(messageText, mentionRegexes);
444
+ const requireMention = isGroup &&
445
+ resolveChannelGroupRequireMention({
446
+ cfg: deps.cfg,
447
+ channel: "signal",
448
+ groupId,
449
+ accountId: deps.accountId,
450
+ });
451
+ const canDetectMention = mentionRegexes.length > 0;
452
+ const mentionGate = resolveMentionGatingWithBypass({
453
+ isGroup,
454
+ requireMention: Boolean(requireMention),
455
+ canDetectMention,
456
+ wasMentioned,
457
+ implicitMention: false,
458
+ hasAnyMention: false,
459
+ allowTextCommands: true,
460
+ hasControlCommand: hasControlCommandInMessage,
461
+ commandAuthorized,
462
+ });
463
+ const effectiveWasMentioned = mentionGate.effectiveWasMentioned;
464
+ if (isGroup && requireMention && canDetectMention && mentionGate.shouldSkip) {
465
+ logInboundDrop({
466
+ log: logVerbose,
467
+ channel: "signal",
468
+ reason: "no mention",
469
+ target: senderDisplay,
470
+ });
471
+ const quoteText = dataMessage.quote?.text?.trim() || "";
472
+ const pendingPlaceholder = (() => {
473
+ if (!dataMessage.attachments?.length) {
474
+ return "";
475
+ }
476
+ if (deps.ignoreAttachments) {
477
+ return "<media:attachment>";
478
+ }
479
+ const firstContentType = dataMessage.attachments?.[0]?.contentType;
480
+ const pendingKind = mediaKindFromMime(firstContentType ?? undefined);
481
+ return pendingKind ? `<media:${pendingKind}>` : "<media:attachment>";
482
+ })();
483
+ const pendingBodyText = messageText || pendingPlaceholder || quoteText;
484
+ const historyKey = groupId ?? "unknown";
485
+ recordPendingHistoryEntryIfEnabled({
486
+ historyMap: deps.groupHistories,
487
+ historyKey,
488
+ limit: deps.historyLimit,
489
+ entry: {
490
+ sender: envelope.sourceName ?? senderDisplay,
491
+ body: pendingBodyText,
492
+ timestamp: envelope.timestamp ?? undefined,
493
+ messageId: typeof envelope.timestamp === "number" ? String(envelope.timestamp) : undefined,
494
+ },
495
+ });
496
+ return;
497
+ }
420
498
  let mediaPath;
421
499
  let mediaType;
422
500
  let placeholder = "";
@@ -487,6 +565,7 @@ export function createSignalEventHandler(deps) {
487
565
  mediaPath,
488
566
  mediaType,
489
567
  commandAuthorized,
568
+ wasMentioned: effectiveWasMentioned,
490
569
  });
491
570
  };
492
571
  }