@poolzin/pool-bot 2026.2.24 → 2026.2.26

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (646) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/dist/acp/client.js +207 -18
  3. package/dist/acp/event-mapper.js +87 -22
  4. package/dist/acp/meta.js +12 -6
  5. package/dist/acp/secret-file.js +22 -0
  6. package/dist/agents/agent-paths.js +8 -9
  7. package/dist/agents/agent-scope.js +17 -5
  8. package/dist/agents/auth-profiles/oauth.js +148 -64
  9. package/dist/agents/auth-profiles/session-override.js +13 -7
  10. package/dist/agents/bash-process-registry.test-helpers.js +29 -0
  11. package/dist/agents/bash-tools.exec-approval-request.js +20 -0
  12. package/dist/agents/bash-tools.exec-host-gateway.js +240 -0
  13. package/dist/agents/bash-tools.exec-host-node.js +235 -0
  14. package/dist/agents/bash-tools.exec-runtime.js +2 -25
  15. package/dist/agents/bash-tools.exec-types.js +1 -0
  16. package/dist/agents/bash-tools.process.js +224 -218
  17. package/dist/agents/bedrock-discovery.js +3 -1
  18. package/dist/agents/byteplus-models.js +97 -0
  19. package/dist/agents/chutes-oauth.js +1 -0
  20. package/dist/agents/cli-runner/helpers.js +4 -0
  21. package/dist/agents/compaction.js +41 -14
  22. package/dist/agents/content-blocks.js +16 -0
  23. package/dist/agents/doubao-models.js +121 -0
  24. package/dist/agents/failover-error.js +2 -0
  25. package/dist/agents/huggingface-models.js +5 -3
  26. package/dist/agents/live-model-filter.js +5 -0
  27. package/dist/agents/minimax-vlm.js +10 -8
  28. package/dist/agents/model-auth.js +6 -0
  29. package/dist/agents/model-catalog.js +3 -1
  30. package/dist/agents/model-fallback.js +96 -101
  31. package/dist/agents/model-selection.js +7 -1
  32. package/dist/agents/models-config.providers.js +364 -165
  33. package/dist/agents/ollama-stream.js +117 -4
  34. package/dist/agents/opencode-zen-models.js +22 -11
  35. package/dist/agents/pi-embedded-helpers/errors.js +55 -33
  36. package/dist/agents/pi-embedded-helpers/messaging-dedupe.js +10 -5
  37. package/dist/agents/pi-embedded-helpers/thinking.js +10 -5
  38. package/dist/agents/pi-embedded-helpers.js +1 -1
  39. package/dist/agents/pi-embedded-payloads.js +1 -0
  40. package/dist/agents/pi-embedded-runner/compact.js +29 -7
  41. package/dist/agents/pi-embedded-runner/extensions.js +28 -26
  42. package/dist/agents/pi-embedded-runner/google.js +20 -8
  43. package/dist/agents/pi-embedded-runner/run/attempt.js +95 -36
  44. package/dist/agents/pi-embedded-runner/run.js +71 -12
  45. package/dist/agents/pi-embedded-runner/run.overflow-compaction.fixture.js +34 -0
  46. package/dist/agents/pi-embedded-runner/run.overflow-compaction.mocks.shared.js +11 -2
  47. package/dist/agents/pi-embedded-runner/session-manager-cache.js +11 -7
  48. package/dist/agents/pi-embedded-runner/system-prompt.js +2 -0
  49. package/dist/agents/pi-embedded-runner/thinking.js +42 -0
  50. package/dist/agents/pi-embedded-runner/tool-name-allowlist.js +19 -0
  51. package/dist/agents/pi-embedded-runner/utils.js +7 -10
  52. package/dist/agents/pi-embedded-subscribe.handlers.lifecycle.js +45 -56
  53. package/dist/agents/pi-embedded-subscribe.handlers.tools.js +2 -2
  54. package/dist/agents/pi-embedded-subscribe.js +9 -4
  55. package/dist/agents/pi-embedded-subscribe.tools.js +68 -14
  56. package/dist/agents/pi-embedded-utils.js +3 -0
  57. package/dist/agents/pi-extensions/compaction-safeguard-runtime.js +4 -20
  58. package/dist/agents/pi-extensions/compaction-safeguard.js +75 -33
  59. package/dist/agents/pi-settings.js +40 -0
  60. package/dist/agents/pi-tools.policy.js +2 -1
  61. package/dist/agents/provider/config-loader.js +1 -1
  62. package/dist/agents/sandbox/browser.js +170 -33
  63. package/dist/agents/sandbox/config-hash.js +14 -27
  64. package/dist/agents/sandbox/config.js +21 -2
  65. package/dist/agents/sandbox/constants.js +2 -0
  66. package/dist/agents/sandbox/docker.js +16 -2
  67. package/dist/agents/sandbox/novnc-auth.js +62 -0
  68. package/dist/agents/sandbox/sanitize-env-vars.js +1 -1
  69. package/dist/agents/sandbox/shared.js +10 -6
  70. package/dist/agents/sandbox-paths.js +24 -11
  71. package/dist/agents/schema/clean-for-gemini.js +132 -85
  72. package/dist/agents/session-slug.js +10 -5
  73. package/dist/agents/session-tool-result-guard-wrapper.js +1 -0
  74. package/dist/agents/session-tool-result-guard.js +3 -1
  75. package/dist/agents/session-transcript-repair.js +40 -6
  76. package/dist/agents/skills/bundled-dir.js +19 -5
  77. package/dist/agents/skills/env-overrides.js +124 -43
  78. package/dist/agents/skills/frontmatter.js +6 -6
  79. package/dist/agents/skills/plugin-skills.js +14 -7
  80. package/dist/agents/skills/workspace.js +1 -0
  81. package/dist/agents/skills.test-helpers.js +13 -0
  82. package/dist/agents/stable-stringify.js +12 -0
  83. package/dist/agents/subagent-announce.js +251 -49
  84. package/dist/agents/subagent-lifecycle-events.js +19 -0
  85. package/dist/agents/subagent-registry-cleanup.js +31 -0
  86. package/dist/agents/subagent-registry-completion.js +68 -0
  87. package/dist/agents/subagent-registry-queries.js +117 -0
  88. package/dist/agents/subagent-registry-state.js +46 -0
  89. package/dist/agents/subagent-registry.js +252 -221
  90. package/dist/agents/subagent-registry.mocks.shared.js +12 -0
  91. package/dist/agents/subagent-registry.store.js +1 -0
  92. package/dist/agents/subagent-registry.types.js +1 -0
  93. package/dist/agents/subagent-spawn.js +195 -7
  94. package/dist/agents/system-prompt.js +22 -6
  95. package/dist/agents/test-helpers/assistant-message-fixtures.js +29 -0
  96. package/dist/agents/test-helpers/fast-coding-tools.js +1 -18
  97. package/dist/agents/test-helpers/fast-core-tools.js +1 -17
  98. package/dist/agents/test-helpers/pi-tools-sandbox-context.js +27 -0
  99. package/dist/agents/timeout.js +18 -6
  100. package/dist/agents/tool-call-id.js +1 -1
  101. package/dist/agents/tool-display-common.js +162 -29
  102. package/dist/agents/tool-images.js +82 -9
  103. package/dist/agents/tool-policy-shared.js +108 -0
  104. package/dist/agents/tool-policy.js +51 -26
  105. package/dist/agents/tools/browser-tool.js +160 -54
  106. package/dist/agents/tools/canvas-tool.js +27 -1
  107. package/dist/agents/tools/common.js +45 -0
  108. package/dist/agents/tools/cron-tool.test-helpers.js +12 -0
  109. package/dist/agents/tools/discord-actions-guild.js +4 -1
  110. package/dist/agents/tools/discord-actions-moderation-shared.js +27 -0
  111. package/dist/agents/tools/gateway-tool.js +3 -1
  112. package/dist/agents/tools/image-tool.js +214 -99
  113. package/dist/agents/tools/nodes-utils.js +1 -10
  114. package/dist/agents/tools/sessions-history-tool.js +140 -108
  115. package/dist/agents/tools/sessions-send-helpers.js +12 -6
  116. package/dist/agents/tools/sessions-spawn-tool.js +8 -2
  117. package/dist/agents/tools/subagents-tool.js +2 -1
  118. package/dist/agents/tools/whatsapp-actions.js +10 -2
  119. package/dist/agents/tools/whatsapp-target-auth.js +18 -0
  120. package/dist/agents/transcript-policy.js +22 -8
  121. package/dist/agents/venice-models.js +11 -3
  122. package/dist/agents/workspace.js +222 -46
  123. package/dist/auto-reply/commands-registry.data.js +51 -0
  124. package/dist/auto-reply/commands-registry.js +19 -21
  125. package/dist/auto-reply/fallback-state.js +114 -0
  126. package/dist/auto-reply/group-activation.js +10 -5
  127. package/dist/auto-reply/inbound-debounce.js +10 -5
  128. package/dist/auto-reply/model-runtime.js +68 -0
  129. package/dist/auto-reply/reply/abort.js +1 -1
  130. package/dist/auto-reply/reply/agent-runner-execution.js +40 -5
  131. package/dist/auto-reply/reply/agent-runner.js +165 -39
  132. package/dist/auto-reply/reply/bash-command.js +41 -39
  133. package/dist/auto-reply/reply/command-gates.js +25 -0
  134. package/dist/auto-reply/reply/commands-allowlist.js +111 -72
  135. package/dist/auto-reply/reply/commands-bash.js +6 -5
  136. package/dist/auto-reply/reply/commands-config.js +30 -28
  137. package/dist/auto-reply/reply/commands-core.js +2 -1
  138. package/dist/auto-reply/reply/commands-info.js +1 -0
  139. package/dist/auto-reply/reply/commands-models.js +65 -14
  140. package/dist/auto-reply/reply/commands-session.js +237 -82
  141. package/dist/auto-reply/reply/commands-setunset-standard.js +13 -0
  142. package/dist/auto-reply/reply/commands-setunset.js +45 -0
  143. package/dist/auto-reply/reply/commands-subagents/action-agents.js +44 -0
  144. package/dist/auto-reply/reply/commands-subagents/action-focus.js +64 -0
  145. package/dist/auto-reply/reply/commands-subagents/action-help.js +4 -0
  146. package/dist/auto-reply/reply/commands-subagents/action-info.js +45 -0
  147. package/dist/auto-reply/reply/commands-subagents/action-kill.js +60 -0
  148. package/dist/auto-reply/reply/commands-subagents/action-list.js +44 -0
  149. package/dist/auto-reply/reply/commands-subagents/action-log.js +29 -0
  150. package/dist/auto-reply/reply/commands-subagents/action-send.js +119 -0
  151. package/dist/auto-reply/reply/commands-subagents/action-spawn.js +52 -0
  152. package/dist/auto-reply/reply/commands-subagents/action-unfocus.js +30 -0
  153. package/dist/auto-reply/reply/commands-subagents/shared.js +303 -0
  154. package/dist/auto-reply/reply/commands-subagents.js +51 -587
  155. package/dist/auto-reply/reply/commands-tts.js +10 -5
  156. package/dist/auto-reply/reply/config-value.js +10 -5
  157. package/dist/auto-reply/reply/directive-handling.model-picker.js +12 -6
  158. package/dist/auto-reply/reply/directive-handling.persist.js +9 -21
  159. package/dist/auto-reply/reply/directive-handling.shared.js +24 -4
  160. package/dist/auto-reply/reply/followup-runner.js +1 -0
  161. package/dist/auto-reply/reply/get-reply-directives-utils.js +23 -14
  162. package/dist/auto-reply/reply/get-reply-directives.js +17 -28
  163. package/dist/auto-reply/reply/get-reply-inline-actions.js +1 -0
  164. package/dist/auto-reply/reply/get-reply.js +71 -12
  165. package/dist/auto-reply/reply/model-selection.js +80 -39
  166. package/dist/auto-reply/reply/queue/enqueue.js +10 -5
  167. package/dist/auto-reply/reply/queue/state.js +13 -12
  168. package/dist/auto-reply/reply/reply-payloads.js +67 -36
  169. package/dist/auto-reply/reply/reply-reference.js +9 -8
  170. package/dist/auto-reply/reply/route-reply.js +15 -8
  171. package/dist/auto-reply/reply/session-reset-prompt.js +1 -1
  172. package/dist/auto-reply/reply/session.js +22 -6
  173. package/dist/auto-reply/reply/strip-inbound-meta.js +147 -0
  174. package/dist/auto-reply/reply/subagents-utils.js +56 -30
  175. package/dist/auto-reply/reply/typing.js +46 -21
  176. package/dist/auto-reply/send-policy.js +14 -7
  177. package/dist/auto-reply/status.js +140 -16
  178. package/dist/auto-reply/templating.js +10 -5
  179. package/dist/auto-reply/thinking.js +7 -16
  180. package/dist/auto-reply/tokens.js +21 -5
  181. package/dist/browser/bridge-server.js +36 -20
  182. package/dist/browser/cdp.helpers.js +7 -14
  183. package/dist/browser/cdp.js +35 -15
  184. package/dist/browser/chrome.profile-decoration.js +7 -4
  185. package/dist/browser/config.js +30 -0
  186. package/dist/browser/extension-relay-auth.js +55 -0
  187. package/dist/browser/extension-relay.js +74 -29
  188. package/dist/browser/navigation-guard.js +39 -0
  189. package/dist/browser/paths.js +77 -0
  190. package/dist/browser/profiles.js +13 -8
  191. package/dist/browser/pw-ai-module.js +10 -5
  192. package/dist/browser/pw-session.js +76 -39
  193. package/dist/browser/pw-tools-core.interactions.js +14 -7
  194. package/dist/browser/pw-tools-core.state.js +12 -6
  195. package/dist/browser/routes/agent.act.js +431 -424
  196. package/dist/browser/routes/agent.shared.js +47 -3
  197. package/dist/browser/routes/agent.snapshot.js +122 -116
  198. package/dist/browser/routes/agent.storage.js +303 -297
  199. package/dist/browser/routes/tabs.js +154 -100
  200. package/dist/browser/server-context.js +7 -0
  201. package/dist/browser/server-lifecycle.js +37 -0
  202. package/dist/build-info.json +3 -3
  203. package/dist/channels/allow-from.js +26 -0
  204. package/dist/channels/allowlists/resolve-utils.js +43 -19
  205. package/dist/channels/channel-config.js +14 -7
  206. package/dist/channels/draft-stream-loop.js +7 -0
  207. package/dist/channels/model-overrides.js +82 -0
  208. package/dist/channels/plugins/account-action-gate.js +13 -0
  209. package/dist/channels/plugins/message-actions.js +10 -0
  210. package/dist/channels/plugins/normalize/imessage.js +14 -7
  211. package/dist/channels/plugins/normalize/slack.js +10 -5
  212. package/dist/channels/plugins/normalize/telegram.js +14 -7
  213. package/dist/channels/plugins/outbound/discord.js +80 -8
  214. package/dist/channels/plugins/outbound/signal.js +11 -11
  215. package/dist/channels/plugins/setup-helpers.js +10 -5
  216. package/dist/channels/sender-label.js +14 -7
  217. package/dist/channels/session.js +4 -2
  218. package/dist/channels/status-reactions.js +297 -0
  219. package/dist/channels/telegram/api.js +18 -0
  220. package/dist/cli/argv.js +84 -21
  221. package/dist/cli/banner.js +3 -2
  222. package/dist/cli/browser-cli-actions-input/register.files-downloads.js +65 -56
  223. package/dist/cli/cli-name.js +11 -11
  224. package/dist/cli/cli-utils.js +13 -3
  225. package/dist/cli/command-format.js +1 -1
  226. package/dist/cli/config-cli.js +1 -1
  227. package/dist/cli/daemon-cli/lifecycle-core.js +31 -19
  228. package/dist/cli/daemon-cli/lifecycle.js +64 -2
  229. package/dist/cli/daemon-cli/restart-health.js +126 -0
  230. package/dist/cli/daemon-cli/status.gather.js +9 -13
  231. package/dist/cli/daemon-cli/status.print.js +2 -10
  232. package/dist/cli/deps.js +27 -22
  233. package/dist/cli/exec-approvals-cli.js +92 -124
  234. package/dist/cli/gateway-cli/run-loop.js +23 -5
  235. package/dist/cli/memory-cli.js +158 -61
  236. package/dist/cli/node-cli/register.js +14 -5
  237. package/dist/cli/nodes-cli/register.push.js +63 -0
  238. package/dist/cli/nodes-media-utils.js +26 -0
  239. package/dist/cli/outbound-send-deps.js +2 -9
  240. package/dist/cli/outbound-send-mapping.js +11 -0
  241. package/dist/cli/pairing-cli.js +40 -14
  242. package/dist/cli/plugins-cli.js +250 -73
  243. package/dist/cli/ports.js +11 -10
  244. package/dist/cli/program/build-program.js +3 -1
  245. package/dist/cli/program/command-registry.js +214 -136
  246. package/dist/cli/program/command-tree.js +16 -0
  247. package/dist/cli/program/help.js +43 -12
  248. package/dist/cli/program/preaction.js +13 -9
  249. package/dist/cli/program/register.configure.js +3 -18
  250. package/dist/cli/program/register.maintenance.js +2 -2
  251. package/dist/cli/program/register.onboard.js +2 -0
  252. package/dist/cli/program/register.status-health-sessions.js +16 -17
  253. package/dist/cli/program/register.subclis.js +93 -52
  254. package/dist/cli/route.js +12 -8
  255. package/dist/cli/system-cli.js +36 -46
  256. package/dist/cli/test-runtime-capture.js +24 -0
  257. package/dist/cli/update-cli/shared.js +22 -9
  258. package/dist/cli/update-cli/update-command.js +89 -14
  259. package/dist/cli/update-cli/wizard.js +6 -12
  260. package/dist/commands/agent/run-context.js +18 -5
  261. package/dist/commands/agent/session-store.js +17 -4
  262. package/dist/commands/agent.js +185 -89
  263. package/dist/commands/agents.bindings.js +14 -7
  264. package/dist/commands/agents.commands.add.js +13 -9
  265. package/dist/commands/agents.commands.identity.js +12 -6
  266. package/dist/commands/agents.commands.list.js +11 -6
  267. package/dist/commands/agents.config.js +8 -10
  268. package/dist/commands/agents.providers.js +12 -6
  269. package/dist/commands/auth-choice-options.js +103 -75
  270. package/dist/commands/auth-choice.apply.byteplus.js +55 -0
  271. package/dist/commands/auth-choice.apply.js +4 -0
  272. package/dist/commands/auth-choice.apply.minimax.js +61 -13
  273. package/dist/commands/auth-choice.apply.openai.js +3 -1
  274. package/dist/commands/auth-choice.apply.volcengine.js +55 -0
  275. package/dist/commands/auth-choice.preferred-provider.js +2 -0
  276. package/dist/commands/channels/remove.js +13 -6
  277. package/dist/commands/channels/shared.js +4 -14
  278. package/dist/commands/channels.mock-harness.js +23 -0
  279. package/dist/commands/configure.commands.js +14 -0
  280. package/dist/commands/configure.gateway.js +2 -4
  281. package/dist/commands/configure.js +1 -1
  282. package/dist/commands/configure.shared.js +11 -0
  283. package/dist/commands/daemon-install-helpers.js +2 -2
  284. package/dist/commands/daemon-install-runtime-warning.js +11 -0
  285. package/dist/commands/dashboard.js +12 -10
  286. package/dist/commands/docs.js +14 -8
  287. package/dist/commands/doctor-config-flow.js +11 -9
  288. package/dist/commands/doctor-legacy-config.js +281 -0
  289. package/dist/commands/doctor-state-integrity.js +99 -23
  290. package/dist/commands/doctor-update.js +12 -9
  291. package/dist/commands/models/list.list-command.js +7 -5
  292. package/dist/commands/models/set-image.js +2 -21
  293. package/dist/commands/node-daemon-install-helpers.js +10 -8
  294. package/dist/commands/onboard-auth.config-minimax.js +54 -80
  295. package/dist/commands/onboard-auth.config-opencode.js +2 -18
  296. package/dist/commands/onboard-auth.credentials.js +90 -13
  297. package/dist/commands/onboard-auth.js +1 -1
  298. package/dist/commands/onboard-auth.models.js +6 -5
  299. package/dist/commands/onboard-hooks.js +1 -1
  300. package/dist/commands/onboard-non-interactive/api-keys.js +14 -7
  301. package/dist/commands/onboard-non-interactive/local/auth-choice.js +64 -49
  302. package/dist/commands/onboard-provider-auth-flags.js +14 -0
  303. package/dist/commands/onboard-remote.js +14 -7
  304. package/dist/commands/onboard.js +11 -13
  305. package/dist/commands/sandbox-display.js +6 -5
  306. package/dist/commands/sessions.test-helpers.js +61 -0
  307. package/dist/commands/status-all/diagnosis.js +14 -10
  308. package/dist/commands/status-all/format.js +1 -0
  309. package/dist/commands/status.gateway-probe.js +1 -16
  310. package/dist/commands/systemd-linger.js +12 -6
  311. package/dist/config/agent-limits.js +2 -0
  312. package/dist/config/commands.js +32 -15
  313. package/dist/config/config-paths.js +9 -11
  314. package/dist/config/config.js +1 -1
  315. package/dist/config/defaults.js +22 -2
  316. package/dist/config/discord-preview-streaming.js +104 -0
  317. package/dist/config/env-substitution.js +62 -34
  318. package/dist/config/env-vars.js +45 -7
  319. package/dist/config/includes.js +4 -0
  320. package/dist/config/io.js +656 -171
  321. package/dist/config/legacy.migrations.part-1.js +189 -78
  322. package/dist/config/legacy.shared.js +3 -1
  323. package/dist/config/merge-patch.js +54 -4
  324. package/dist/config/prototype-keys.js +4 -0
  325. package/dist/config/redact-snapshot.js +404 -76
  326. package/dist/config/schema.help.js +44 -7
  327. package/dist/config/schema.js +58 -570
  328. package/dist/config/schema.labels.js +38 -6
  329. package/dist/config/sessions/delivery-info.js +10 -3
  330. package/dist/config/sessions/main-session.js +10 -5
  331. package/dist/config/sessions/session-file.js +33 -0
  332. package/dist/config/sessions/session-key.js +10 -5
  333. package/dist/config/sessions/store.js +1 -1
  334. package/dist/config/sessions.js +1 -0
  335. package/dist/config/validation.js +140 -85
  336. package/dist/config/zod-schema.agent-runtime.js +11 -0
  337. package/dist/config/zod-schema.hooks.js +40 -11
  338. package/dist/config/zod-schema.installs.js +20 -0
  339. package/dist/config/zod-schema.js +156 -20
  340. package/dist/config/zod-schema.providers-core.js +78 -4
  341. package/dist/config/zod-schema.providers.js +6 -1
  342. package/dist/config/zod-schema.session.js +41 -2
  343. package/dist/cron/run-log.js +3 -0
  344. package/dist/cron/schedule.js +21 -10
  345. package/dist/cron/service/ops.js +35 -21
  346. package/dist/cron/service/timer.js +116 -16
  347. package/dist/cron/stagger.js +3 -1
  348. package/dist/daemon/cmd-argv.js +21 -0
  349. package/dist/daemon/cmd-set.js +58 -0
  350. package/dist/daemon/service-types.js +1 -0
  351. package/dist/discord/api.js +12 -6
  352. package/dist/discord/draft-chunking.js +22 -0
  353. package/dist/discord/draft-stream.js +124 -0
  354. package/dist/discord/monitor/agent-components.js +1 -1
  355. package/dist/discord/monitor/commands.js +5 -0
  356. package/dist/discord/monitor/exec-approvals.js +357 -162
  357. package/dist/discord/monitor/gateway-plugin.js +2 -1
  358. package/dist/discord/monitor/listeners.js +37 -27
  359. package/dist/discord/monitor/message-handler.js +4 -1
  360. package/dist/discord/monitor/message-handler.preflight.js +65 -8
  361. package/dist/discord/monitor/message-handler.process.js +246 -217
  362. package/dist/discord/monitor/message-utils.js +143 -6
  363. package/dist/discord/monitor/model-picker-preferences.js +143 -0
  364. package/dist/discord/monitor/model-picker.js +651 -0
  365. package/dist/discord/monitor/native-command.js +573 -16
  366. package/dist/discord/monitor/provider.allowlist.js +223 -0
  367. package/dist/discord/monitor/provider.js +275 -347
  368. package/dist/discord/monitor/provider.lifecycle.js +100 -0
  369. package/dist/discord/monitor/reply-delivery.js +123 -16
  370. package/dist/discord/monitor/thread-bindings.discord-api.js +215 -0
  371. package/dist/discord/monitor/thread-bindings.js +4 -0
  372. package/dist/discord/monitor/thread-bindings.lifecycle.js +177 -0
  373. package/dist/discord/monitor/thread-bindings.manager.js +423 -0
  374. package/dist/discord/monitor/thread-bindings.messages.js +55 -0
  375. package/dist/discord/monitor/thread-bindings.state.js +358 -0
  376. package/dist/discord/monitor/thread-bindings.types.js +6 -0
  377. package/dist/discord/resolve-users.js +33 -21
  378. package/dist/discord/send.channels.js +15 -0
  379. package/dist/discord/send.js +3 -2
  380. package/dist/discord/send.outbound.js +82 -26
  381. package/dist/discord/send.permissions.js +83 -30
  382. package/dist/discord/send.reactions.js +8 -4
  383. package/dist/discord/token.js +10 -5
  384. package/dist/discord/voice/command.js +263 -0
  385. package/dist/discord/voice/manager.js +531 -0
  386. package/dist/gateway/auth.js +72 -13
  387. package/dist/gateway/call.js +152 -83
  388. package/dist/gateway/canvas-capability.js +75 -0
  389. package/dist/gateway/client.js +28 -4
  390. package/dist/gateway/config-reload.js +3 -4
  391. package/dist/gateway/control-plane-audit.js +28 -0
  392. package/dist/gateway/control-plane-rate-limit.js +53 -0
  393. package/dist/gateway/control-ui.js +219 -96
  394. package/dist/gateway/events.js +1 -0
  395. package/dist/gateway/hooks-mapping.js +88 -38
  396. package/dist/gateway/hooks.js +109 -54
  397. package/dist/gateway/http-auth-helpers.js +3 -2
  398. package/dist/gateway/http-common.js +22 -0
  399. package/dist/gateway/http-endpoint-helpers.js +1 -0
  400. package/dist/gateway/method-scopes.js +169 -0
  401. package/dist/gateway/net.js +74 -9
  402. package/dist/gateway/node-invoke-system-run-approval.js +14 -35
  403. package/dist/gateway/node-registry.js +10 -5
  404. package/dist/gateway/openai-http.js +1 -0
  405. package/dist/gateway/openresponses-http.js +121 -110
  406. package/dist/gateway/origin-check.js +1 -18
  407. package/dist/gateway/probe-auth.js +2 -0
  408. package/dist/gateway/protocol/index.js +4 -2
  409. package/dist/gateway/protocol/schema/cron.js +1 -0
  410. package/dist/gateway/protocol/schema/devices.js +1 -0
  411. package/dist/gateway/protocol/schema/protocol-schemas.js +4 -1
  412. package/dist/gateway/protocol/schema/push.js +18 -0
  413. package/dist/gateway/protocol/schema/sessions.js +6 -0
  414. package/dist/gateway/protocol/schema.js +1 -0
  415. package/dist/gateway/role-policy.js +17 -0
  416. package/dist/gateway/server/ws-connection/connect-policy.js +37 -0
  417. package/dist/gateway/server/ws-connection/message-handler.js +175 -148
  418. package/dist/gateway/server-chat.js +83 -25
  419. package/dist/gateway/server-constants.js +10 -9
  420. package/dist/gateway/server-cron.js +1 -0
  421. package/dist/gateway/server-http.js +247 -54
  422. package/dist/gateway/server-maintenance.js +20 -5
  423. package/dist/gateway/server-methods/agent.js +162 -24
  424. package/dist/gateway/server-methods/chat.js +465 -130
  425. package/dist/gateway/server-methods/config.js +193 -152
  426. package/dist/gateway/server-methods/devices.js +17 -3
  427. package/dist/gateway/server-methods/models.js +11 -1
  428. package/dist/gateway/server-methods/nodes.helpers.js +12 -0
  429. package/dist/gateway/server-methods/nodes.js +251 -69
  430. package/dist/gateway/server-methods/push.js +53 -0
  431. package/dist/gateway/server-methods/sessions.js +64 -8
  432. package/dist/gateway/server-methods/usage.js +162 -75
  433. package/dist/gateway/server-node-events.js +29 -0
  434. package/dist/gateway/server-reload-handlers.js +2 -3
  435. package/dist/gateway/server-runtime-config.js +39 -13
  436. package/dist/gateway/server-runtime-state.js +2 -0
  437. package/dist/gateway/server-startup-memory.js +17 -11
  438. package/dist/gateway/server-ws-runtime.js +1 -0
  439. package/dist/gateway/server.impl.js +296 -139
  440. package/dist/gateway/session-preview.test-helpers.js +11 -0
  441. package/dist/gateway/session-utils.fs.js +32 -34
  442. package/dist/gateway/sessions-resolve.js +17 -5
  443. package/dist/gateway/startup-auth.js +126 -0
  444. package/dist/gateway/test-helpers.agent-results.js +15 -0
  445. package/dist/gateway/test-helpers.mocks.js +37 -14
  446. package/dist/gateway/test-helpers.openai-mock.js +14 -7
  447. package/dist/gateway/test-helpers.server.js +161 -77
  448. package/dist/gateway/tools-invoke-http.js +21 -10
  449. package/dist/hooks/bundled/bootstrap-extra-files/handler.js +3 -1
  450. package/dist/hooks/bundled/command-logger/handler.js +7 -2
  451. package/dist/hooks/bundled/session-memory/handler.js +170 -38
  452. package/dist/hooks/frontmatter.js +6 -6
  453. package/dist/hooks/gmail-watcher-lifecycle.js +23 -0
  454. package/dist/hooks/gmail-watcher.js +11 -6
  455. package/dist/hooks/internal-hooks.js +11 -1
  456. package/dist/hooks/llm-slug-generator.js +4 -1
  457. package/dist/hooks/workspace.js +47 -17
  458. package/dist/imessage/accounts.js +9 -20
  459. package/dist/imessage/monitor/inbound-processing.js +2 -1
  460. package/dist/infra/archive-path.js +49 -0
  461. package/dist/infra/archive.js +174 -73
  462. package/dist/infra/control-ui-assets.js +14 -6
  463. package/dist/infra/device-pairing.js +204 -144
  464. package/dist/infra/env.js +10 -5
  465. package/dist/infra/exec-approvals-allowlist.js +141 -70
  466. package/dist/infra/exec-approvals-analysis.js +78 -20
  467. package/dist/infra/exec-approvals.js +5 -17
  468. package/dist/infra/exec-safe-bin-policy.js +277 -0
  469. package/dist/infra/fixed-window-rate-limit.js +33 -0
  470. package/dist/infra/fs-safe.js +71 -39
  471. package/dist/infra/gateway-lock.js +6 -2
  472. package/dist/infra/git-root.js +61 -0
  473. package/dist/infra/heartbeat-active-hours.js +2 -2
  474. package/dist/infra/heartbeat-reason.js +40 -0
  475. package/dist/infra/heartbeat-runner.js +72 -32
  476. package/dist/infra/heartbeat-wake.js +6 -12
  477. package/dist/infra/host-env-security-policy.json +19 -0
  478. package/dist/infra/host-env-security.js +66 -0
  479. package/dist/infra/install-source-utils.js +91 -7
  480. package/dist/infra/net/ssrf.js +131 -38
  481. package/dist/infra/node-pairing.js +50 -105
  482. package/dist/infra/npm-integrity.js +45 -0
  483. package/dist/infra/npm-pack-install.js +40 -0
  484. package/dist/infra/outbound/bound-delivery-router.js +88 -0
  485. package/dist/infra/outbound/channel-adapters.js +20 -7
  486. package/dist/infra/outbound/channel-selection.js +12 -6
  487. package/dist/infra/outbound/envelope.js +1 -1
  488. package/dist/infra/outbound/format.js +12 -6
  489. package/dist/infra/outbound/message-action-runner.js +107 -327
  490. package/dist/infra/outbound/message.js +59 -36
  491. package/dist/infra/outbound/outbound-policy.js +52 -25
  492. package/dist/infra/outbound/outbound-send-service.js +58 -71
  493. package/dist/infra/outbound/payloads.js +14 -7
  494. package/dist/infra/outbound/session-binding-service.js +123 -0
  495. package/dist/infra/pairing-files.js +10 -0
  496. package/dist/infra/path-guards.js +25 -0
  497. package/dist/infra/plain-object.js +9 -0
  498. package/dist/infra/provider-usage.fetch.codex.js +7 -15
  499. package/dist/infra/provider-usage.fetch.gemini.js +14 -11
  500. package/dist/infra/provider-usage.fetch.shared.js +30 -1
  501. package/dist/infra/provider-usage.fetch.zai.js +10 -9
  502. package/dist/infra/push-apns.js +365 -0
  503. package/dist/infra/restart-sentinel.js +16 -1
  504. package/dist/infra/restart.js +229 -26
  505. package/dist/infra/retry-policy.js +4 -2
  506. package/dist/infra/retry.js +9 -5
  507. package/dist/infra/scp-host.js +54 -0
  508. package/dist/infra/session-cost-usage.js +107 -59
  509. package/dist/infra/session-maintenance-warning.js +3 -1
  510. package/dist/infra/shell-env.js +98 -34
  511. package/dist/infra/ssh-config.js +12 -6
  512. package/dist/infra/system-run-command.js +49 -4
  513. package/dist/infra/update-channels.js +10 -5
  514. package/dist/infra/update-startup.js +86 -9
  515. package/dist/line/accounts.js +5 -7
  516. package/dist/line/bot-access.js +8 -20
  517. package/dist/line/bot-handlers.js +3 -1
  518. package/dist/link-understanding/detect.js +15 -7
  519. package/dist/media/constants.js +15 -6
  520. package/dist/media/image-ops.js +7 -0
  521. package/dist/media/inbound-path-policy.js +114 -0
  522. package/dist/media/input-files.js +16 -0
  523. package/dist/media/local-roots.js +3 -2
  524. package/dist/media-understanding/apply.js +4 -1
  525. package/dist/media-understanding/concurrency.js +8 -20
  526. package/dist/memory/backend-config.js +45 -6
  527. package/dist/memory/embeddings.js +10 -4
  528. package/dist/memory/fs-utils.js +23 -0
  529. package/dist/memory/manager-search.js +12 -6
  530. package/dist/memory/manager-sync-ops.js +12 -2
  531. package/dist/memory/qmd-manager.js +466 -53
  532. package/dist/memory/query-expansion.js +167 -3
  533. package/dist/memory/status-format.js +10 -5
  534. package/dist/memory/sync-memory-files.js +1 -1
  535. package/dist/memory/test-manager.js +8 -0
  536. package/dist/node-host/invoke-system-run.js +281 -0
  537. package/dist/node-host/invoke.js +55 -337
  538. package/dist/pairing/pairing-store.js +22 -0
  539. package/dist/plugin-sdk/allow-from.js +1 -1
  540. package/dist/plugin-sdk/command-auth.js +3 -1
  541. package/dist/plugin-sdk/index.js +6 -3
  542. package/dist/plugin-sdk/temp-path.js +47 -0
  543. package/dist/plugin-sdk/webhook-targets.js +32 -0
  544. package/dist/plugins/bundled-dir.js +9 -6
  545. package/dist/plugins/discovery.js +217 -23
  546. package/dist/plugins/hook-runner-global.js +16 -0
  547. package/dist/plugins/hooks.js +50 -0
  548. package/dist/plugins/install.js +28 -16
  549. package/dist/plugins/loader.js +192 -26
  550. package/dist/plugins/logger.js +8 -0
  551. package/dist/plugins/manifest-registry.js +3 -0
  552. package/dist/plugins/path-safety.js +34 -0
  553. package/dist/plugins/registry.js +5 -2
  554. package/dist/plugins/runtime/index.js +271 -206
  555. package/dist/plugins/runtime.js +3 -17
  556. package/dist/plugins/update.js +78 -12
  557. package/dist/process/spawn-utils.js +14 -7
  558. package/dist/providers/github-copilot-models.js +4 -1
  559. package/dist/providers/github-copilot-token.js +11 -6
  560. package/dist/providers/qwen-portal-oauth.js +14 -6
  561. package/dist/routing/account-id.js +30 -0
  562. package/dist/routing/resolve-route.js +3 -7
  563. package/dist/routing/session-key.js +2 -16
  564. package/dist/security/audit-channel.js +100 -20
  565. package/dist/security/audit-extra.async.js +505 -179
  566. package/dist/security/audit-extra.js +12 -2
  567. package/dist/security/audit-extra.sync.js +421 -35
  568. package/dist/security/audit-fs.js +31 -13
  569. package/dist/security/audit.js +180 -370
  570. package/dist/security/dm-policy-shared.js +68 -0
  571. package/dist/security/external-content.js +46 -14
  572. package/dist/security/fix.js +49 -85
  573. package/dist/security/scan-paths.js +20 -0
  574. package/dist/security/secret-equal.js +3 -7
  575. package/dist/security/windows-acl.js +30 -15
  576. package/dist/shared/entry-status.js +6 -0
  577. package/dist/shared/frontmatter.js +5 -5
  578. package/dist/shared/node-list-parse.js +13 -0
  579. package/dist/shared/node-match.js +11 -4
  580. package/dist/shared/operator-scope-compat.js +42 -0
  581. package/dist/shared/text-chunking.js +29 -0
  582. package/dist/signal/accounts.js +7 -20
  583. package/dist/signal/monitor/event-handler.js +3 -1
  584. package/dist/slack/accounts.js +6 -19
  585. package/dist/slack/actions.js +11 -3
  586. package/dist/slack/blocks.test-helpers.js +31 -0
  587. package/dist/slack/monitor/auth.js +1 -1
  588. package/dist/slack/monitor/message-handler/dispatch.js +50 -29
  589. package/dist/slack/monitor/mrkdwn.js +8 -0
  590. package/dist/slack/monitor/replies.js +15 -7
  591. package/dist/slack/monitor/slash.js +22 -13
  592. package/dist/slack/resolve-channels.js +10 -5
  593. package/dist/slack/send.js +102 -12
  594. package/dist/slack/stream-mode.js +10 -0
  595. package/dist/slack/streaming.js +4 -2
  596. package/dist/telegram/accounts.js +19 -14
  597. package/dist/telegram/bot/helpers.js +3 -5
  598. package/dist/telegram/bot-access.js +35 -36
  599. package/dist/telegram/bot-handlers.js +120 -148
  600. package/dist/telegram/bot-message-context.js +68 -9
  601. package/dist/telegram/bot-message-dispatch.js +477 -210
  602. package/dist/telegram/bot-native-commands.js +16 -0
  603. package/dist/telegram/draft-stream.js +44 -8
  604. package/dist/telegram/inline-buttons.js +5 -15
  605. package/dist/telegram/monitor.js +11 -7
  606. package/dist/telegram/network-config.js +19 -7
  607. package/dist/telegram/reasoning-lane-coordinator.js +128 -0
  608. package/dist/telegram/send.js +3 -2
  609. package/dist/telegram/sent-message-cache.js +5 -6
  610. package/dist/telegram/status-reaction-variants.js +208 -0
  611. package/dist/telegram/sticker-cache.js +11 -9
  612. package/dist/terminal/prompt-select-styled.js +9 -0
  613. package/dist/terminal/theme.js +12 -12
  614. package/dist/test-utils/command-runner.js +6 -0
  615. package/dist/test-utils/internal-hook-event-payload.js +10 -0
  616. package/dist/test-utils/model-auth-mock.js +12 -0
  617. package/dist/test-utils/provider-usage-fetch.js +14 -0
  618. package/dist/test-utils/temp-home.js +33 -0
  619. package/dist/tts/tts.js +80 -567
  620. package/dist/tui/components/chat-log.js +50 -8
  621. package/dist/tui/theme/theme.js +10 -12
  622. package/dist/tui/tui-command-handlers.js +36 -27
  623. package/dist/tui/tui-event-handlers.js +122 -32
  624. package/dist/tui/tui-local-shell.js +16 -6
  625. package/dist/tui/tui.js +236 -48
  626. package/dist/utils/account-id.js +2 -4
  627. package/dist/utils/boolean.js +10 -5
  628. package/dist/utils/directive-tags.js +11 -0
  629. package/dist/utils/mask-api-key.js +10 -0
  630. package/dist/utils/queue-helpers.js +67 -12
  631. package/dist/utils/run-with-concurrency.js +39 -0
  632. package/dist/web/auto-reply/deliver-reply.js +8 -4
  633. package/dist/web/auto-reply/mentions.js +10 -5
  634. package/dist/web/auto-reply/monitor/group-members.js +14 -7
  635. package/dist/web/auto-reply/monitor/process-message.js +45 -24
  636. package/dist/web/inbound/access-control.js +5 -2
  637. package/dist/web/login-qr.js +12 -6
  638. package/dist/web/media.js +126 -15
  639. package/docs/tools/slash-commands.md +5 -1
  640. package/extensions/bluebubbles/src/monitor-processing.ts +580 -139
  641. package/extensions/bluebubbles/src/monitor.ts +208 -1950
  642. package/extensions/feishu/src/external-keys.ts +19 -0
  643. package/extensions/lobster/src/windows-spawn.ts +193 -0
  644. package/extensions/matrix/src/matrix/actions/limits.ts +6 -0
  645. package/extensions/mattermost/src/mattermost/reactions.test-helpers.ts +83 -0
  646. package/package.json +1 -1
@@ -1,26 +1,30 @@
1
1
  /**
2
2
  * Session memory hook handler
3
3
  *
4
- * Saves session context to memory when /new command is triggered
4
+ * Saves session context to memory when /new or /reset command is triggered
5
5
  * Creates a new dated memory file with LLM-generated slug
6
6
  */
7
7
  import fs from "node:fs/promises";
8
- import path from "node:path";
9
8
  import os from "node:os";
9
+ import path from "node:path";
10
10
  import { resolveAgentWorkspaceDir } from "../../../agents/agent-scope.js";
11
+ import { resolveStateDir } from "../../../config/paths.js";
12
+ import { createSubsystemLogger } from "../../../logging/subsystem.js";
11
13
  import { resolveAgentIdFromSessionKey } from "../../../routing/session-key.js";
14
+ import { hasInterSessionUserProvenance } from "../../../sessions/input-provenance.js";
15
+ import { resolveHookConfig } from "../../config.js";
16
+ import { generateSlugViaLLM } from "../../llm-slug-generator.js";
17
+ const log = createSubsystemLogger("hooks/session-memory");
12
18
  /**
13
19
  * Read recent messages from session file for slug generation
14
20
  */
15
- async function getRecentSessionContent(sessionFilePath) {
21
+ async function getRecentSessionContent(sessionFilePath, messageCount = 15) {
16
22
  try {
17
23
  const content = await fs.readFile(sessionFilePath, "utf-8");
18
24
  const lines = content.trim().split("\n");
19
- // Get last 15 lines (recent conversation)
20
- const recentLines = lines.slice(-15);
21
- // Parse JSONL and extract messages
22
- const messages = [];
23
- for (const line of recentLines) {
25
+ // Parse JSONL and extract user/assistant messages first
26
+ const allMessages = [];
27
+ for (const line of lines) {
24
28
  try {
25
29
  const entry = JSON.parse(line);
26
30
  // Session files have entries with type="message" containing a nested message object
@@ -28,12 +32,16 @@ async function getRecentSessionContent(sessionFilePath) {
28
32
  const msg = entry.message;
29
33
  const role = msg.role;
30
34
  if ((role === "user" || role === "assistant") && msg.content) {
35
+ if (role === "user" && hasInterSessionUserProvenance(msg)) {
36
+ continue;
37
+ }
31
38
  // Extract text content
32
39
  const text = Array.isArray(msg.content)
33
- ? msg.content.find((c) => c.type === "text")?.text
40
+ ? // biome-ignore lint/suspicious/noExplicitAny: required
41
+ msg.content.find((c) => c.type === "text")?.text
34
42
  : msg.content;
35
43
  if (text && !text.startsWith("/")) {
36
- messages.push(`${role}: ${text}`);
44
+ allMessages.push(`${role}: ${text}`);
37
45
  }
38
46
  }
39
47
  }
@@ -42,71 +50,186 @@ async function getRecentSessionContent(sessionFilePath) {
42
50
  // Skip invalid JSON lines
43
51
  }
44
52
  }
45
- return messages.join("\n");
53
+ // Then slice to get exactly messageCount messages
54
+ const recentMessages = allMessages.slice(-messageCount);
55
+ return recentMessages.join("\n");
46
56
  }
47
57
  catch {
48
58
  return null;
49
59
  }
50
60
  }
51
61
  /**
52
- * Save session context to memory when /new command is triggered
62
+ * Try the active transcript first; if /new already rotated it,
63
+ * fallback to the latest .jsonl.reset.* sibling.
64
+ */
65
+ async function getRecentSessionContentWithResetFallback(sessionFilePath, messageCount = 15) {
66
+ const primary = await getRecentSessionContent(sessionFilePath, messageCount);
67
+ if (primary) {
68
+ return primary;
69
+ }
70
+ try {
71
+ const dir = path.dirname(sessionFilePath);
72
+ const base = path.basename(sessionFilePath);
73
+ const resetPrefix = `${base}.reset.`;
74
+ const files = await fs.readdir(dir);
75
+ const resetCandidates = files.filter((name) => name.startsWith(resetPrefix)).toSorted();
76
+ if (resetCandidates.length === 0) {
77
+ return primary;
78
+ }
79
+ const latestResetPath = path.join(dir, resetCandidates[resetCandidates.length - 1]);
80
+ const fallback = await getRecentSessionContent(latestResetPath, messageCount);
81
+ if (fallback) {
82
+ log.debug("Loaded session content from reset fallback", {
83
+ sessionFilePath,
84
+ latestResetPath,
85
+ });
86
+ }
87
+ return fallback || primary;
88
+ }
89
+ catch {
90
+ return primary;
91
+ }
92
+ }
93
+ function stripResetSuffix(fileName) {
94
+ const resetIndex = fileName.indexOf(".reset.");
95
+ return resetIndex === -1 ? fileName : fileName.slice(0, resetIndex);
96
+ }
97
+ async function findPreviousSessionFile(params) {
98
+ try {
99
+ const files = await fs.readdir(params.sessionsDir);
100
+ const fileSet = new Set(files);
101
+ const baseFromReset = params.currentSessionFile
102
+ ? stripResetSuffix(path.basename(params.currentSessionFile))
103
+ : undefined;
104
+ if (baseFromReset && fileSet.has(baseFromReset)) {
105
+ return path.join(params.sessionsDir, baseFromReset);
106
+ }
107
+ const trimmedSessionId = params.sessionId?.trim();
108
+ if (trimmedSessionId) {
109
+ const canonicalFile = `${trimmedSessionId}.jsonl`;
110
+ if (fileSet.has(canonicalFile)) {
111
+ return path.join(params.sessionsDir, canonicalFile);
112
+ }
113
+ const topicVariants = files
114
+ .filter((name) => name.startsWith(`${trimmedSessionId}-topic-`) &&
115
+ name.endsWith(".jsonl") &&
116
+ !name.includes(".reset."))
117
+ .toSorted()
118
+ .toReversed();
119
+ if (topicVariants.length > 0) {
120
+ return path.join(params.sessionsDir, topicVariants[0]);
121
+ }
122
+ }
123
+ if (!params.currentSessionFile) {
124
+ return undefined;
125
+ }
126
+ const nonResetJsonl = files
127
+ .filter((name) => name.endsWith(".jsonl") && !name.includes(".reset."))
128
+ .toSorted()
129
+ .toReversed();
130
+ if (nonResetJsonl.length > 0) {
131
+ return path.join(params.sessionsDir, nonResetJsonl[0]);
132
+ }
133
+ }
134
+ catch {
135
+ // Ignore directory read errors.
136
+ }
137
+ return undefined;
138
+ }
139
+ /**
140
+ * Save session context to memory when /new or /reset command is triggered
53
141
  */
54
142
  const saveSessionToMemory = async (event) => {
55
- // Only trigger on 'new' command
56
- if (event.type !== "command" || event.action !== "new") {
143
+ // Only trigger on reset/new commands
144
+ const isResetCommand = event.action === "new" || event.action === "reset";
145
+ if (event.type !== "command" || !isResetCommand) {
57
146
  return;
58
147
  }
59
148
  try {
60
- console.log("[session-memory] Hook triggered for /new command");
149
+ log.debug("Hook triggered for reset/new command", { action: event.action });
61
150
  const context = event.context || {};
62
151
  const cfg = context.cfg;
63
152
  const agentId = resolveAgentIdFromSessionKey(event.sessionKey);
64
153
  const workspaceDir = cfg
65
154
  ? resolveAgentWorkspaceDir(cfg, agentId)
66
- : path.join(os.homedir(), "clawd");
155
+ : path.join(resolveStateDir(process.env, os.homedir), "workspace");
67
156
  const memoryDir = path.join(workspaceDir, "memory");
68
157
  await fs.mkdir(memoryDir, { recursive: true });
69
158
  // Get today's date for filename
70
159
  const now = new Date(event.timestamp);
71
160
  const dateStr = now.toISOString().split("T")[0]; // YYYY-MM-DD
72
161
  // Generate descriptive slug from session using LLM
162
+ // Prefer previousSessionEntry (old session before /new) over current (which may be empty)
73
163
  const sessionEntry = (context.previousSessionEntry || context.sessionEntry || {});
74
164
  const currentSessionId = sessionEntry.sessionId;
75
- const currentSessionFile = sessionEntry.sessionFile;
76
- console.log("[session-memory] Current sessionId:", currentSessionId);
77
- console.log("[session-memory] Current sessionFile:", currentSessionFile);
78
- console.log("[session-memory] cfg present:", !!cfg);
165
+ let currentSessionFile = sessionEntry.sessionFile || undefined;
166
+ // If sessionFile is empty or looks like a new/reset file, try to find the previous session file.
167
+ if (!currentSessionFile || currentSessionFile.includes(".reset.")) {
168
+ const sessionsDirs = new Set();
169
+ if (currentSessionFile) {
170
+ sessionsDirs.add(path.dirname(currentSessionFile));
171
+ }
172
+ sessionsDirs.add(path.join(workspaceDir, "sessions"));
173
+ for (const sessionsDir of sessionsDirs) {
174
+ const recoveredSessionFile = await findPreviousSessionFile({
175
+ sessionsDir,
176
+ currentSessionFile,
177
+ sessionId: currentSessionId,
178
+ });
179
+ if (!recoveredSessionFile) {
180
+ continue;
181
+ }
182
+ currentSessionFile = recoveredSessionFile;
183
+ log.debug("Found previous session file", { file: currentSessionFile });
184
+ break;
185
+ }
186
+ }
187
+ log.debug("Session context resolved", {
188
+ sessionId: currentSessionId,
189
+ sessionFile: currentSessionFile,
190
+ hasCfg: Boolean(cfg),
191
+ });
79
192
  const sessionFile = currentSessionFile || undefined;
193
+ // Read message count from hook config (default: 15)
194
+ const hookConfig = resolveHookConfig(cfg, "session-memory");
195
+ const messageCount = typeof hookConfig?.messages === "number" && hookConfig.messages > 0
196
+ ? hookConfig.messages
197
+ : 15;
80
198
  let slug = null;
81
199
  let sessionContent = null;
82
200
  if (sessionFile) {
83
- // Get recent conversation content
84
- sessionContent = await getRecentSessionContent(sessionFile);
85
- console.log("[session-memory] sessionContent length:", sessionContent?.length || 0);
86
- if (sessionContent && cfg) {
87
- console.log("[session-memory] Calling generateSlugViaLLM...");
88
- // Dynamically import the LLM slug generator (avoids module caching issues)
89
- // When compiled, handler is at dist/hooks/bundled/session-memory/handler.js
90
- // Going up ../.. puts us at dist/hooks/, so just add llm-slug-generator.js
91
- const poolbotRoot = path.resolve(path.dirname(import.meta.url.replace("file://", "")), "../..");
92
- const slugGenPath = path.join(poolbotRoot, "llm-slug-generator.js");
93
- const { generateSlugViaLLM } = await import(slugGenPath);
201
+ // Get recent conversation content, with fallback to rotated reset transcript.
202
+ sessionContent = await getRecentSessionContentWithResetFallback(sessionFile, messageCount);
203
+ log.debug("Session content loaded", {
204
+ length: sessionContent?.length ?? 0,
205
+ messageCount,
206
+ });
207
+ // Avoid calling the model provider in unit tests; keep hooks fast and deterministic.
208
+ const isTestEnv = process.env.POOLBOT_TEST_FAST === "1" ||
209
+ process.env.VITEST === "true" ||
210
+ process.env.VITEST === "1" ||
211
+ process.env.NODE_ENV === "test";
212
+ const allowLlmSlug = !isTestEnv && hookConfig?.llmSlug !== false;
213
+ if (sessionContent && cfg && allowLlmSlug) {
214
+ log.debug("Calling generateSlugViaLLM...");
94
215
  // Use LLM to generate a descriptive slug
95
216
  slug = await generateSlugViaLLM({ sessionContent, cfg });
96
- console.log("[session-memory] Generated slug:", slug);
217
+ log.debug("Generated slug", { slug });
97
218
  }
98
219
  }
99
220
  // If no slug, use timestamp
100
221
  if (!slug) {
101
222
  const timeSlug = now.toISOString().split("T")[1].split(".")[0].replace(/:/g, "");
102
223
  slug = timeSlug.slice(0, 4); // HHMM
103
- console.log("[session-memory] Using fallback timestamp slug:", slug);
224
+ log.debug("Using fallback timestamp slug", { slug });
104
225
  }
105
226
  // Create filename with date and slug
106
227
  const filename = `${dateStr}-${slug}.md`;
107
228
  const memoryFilePath = path.join(memoryDir, filename);
108
- console.log("[session-memory] Generated filename:", filename);
109
- console.log("[session-memory] Full path:", memoryFilePath);
229
+ log.debug("Memory file path resolved", {
230
+ filename,
231
+ path: memoryFilePath.replace(os.homedir(), "~"),
232
+ });
110
233
  // Format time as HH:MM:SS UTC
111
234
  const timeStr = now.toISOString().split("T")[1].split(".")[0];
112
235
  // Extract context details
@@ -128,13 +251,22 @@ const saveSessionToMemory = async (event) => {
128
251
  const entry = entryParts.join("\n");
129
252
  // Write to new memory file
130
253
  await fs.writeFile(memoryFilePath, entry, "utf-8");
131
- console.log("[session-memory] Memory file written successfully");
254
+ log.debug("Memory file written successfully");
132
255
  // Log completion (but don't send user-visible confirmation - it's internal housekeeping)
133
256
  const relPath = memoryFilePath.replace(os.homedir(), "~");
134
- console.log(`[session-memory] Session context saved to ${relPath}`);
257
+ log.info(`Session context saved to ${relPath}`);
135
258
  }
136
259
  catch (err) {
137
- console.error("[session-memory] Failed to save session memory:", err instanceof Error ? err.message : String(err));
260
+ if (err instanceof Error) {
261
+ log.error("Failed to save session memory", {
262
+ errorName: err.name,
263
+ errorMessage: err.message,
264
+ stack: err.stack,
265
+ });
266
+ }
267
+ else {
268
+ log.error("Failed to save session memory", { error: String(err) });
269
+ }
138
270
  }
139
271
  };
140
272
  export default saveSessionToMemory;
@@ -1,10 +1,10 @@
1
1
  import { parseFrontmatterBlock } from "../markdown/frontmatter.js";
2
- import { getFrontmatterString, normalizeStringList, parsePoolbotManifestInstallBase, parseFrontmatterBool, resolvePoolbotManifestBlock, resolvePoolbotManifestInstall, resolvePoolbotManifestOs, resolvePoolbotManifestRequires, } from "../shared/frontmatter.js";
2
+ import { getFrontmatterString, normalizeStringList, parsePoolBotManifestInstallBase, parseFrontmatterBool, resolvePoolBotManifestBlock, resolvePoolBotManifestInstall, resolvePoolBotManifestOs, resolvePoolBotManifestRequires, } from "../shared/frontmatter.js";
3
3
  export function parseFrontmatter(content) {
4
4
  return parseFrontmatterBlock(content);
5
5
  }
6
6
  function parseInstallSpec(input) {
7
- const parsed = parsePoolbotManifestInstallBase(input, ["bundled", "npm", "git"]);
7
+ const parsed = parsePoolBotManifestInstallBase(input, ["bundled", "npm", "git"]);
8
8
  if (!parsed) {
9
9
  return undefined;
10
10
  }
@@ -30,13 +30,13 @@ function parseInstallSpec(input) {
30
30
  return spec;
31
31
  }
32
32
  export function resolvePoolbotMetadata(frontmatter) {
33
- const metadataObj = resolvePoolbotManifestBlock({ frontmatter });
33
+ const metadataObj = resolvePoolBotManifestBlock({ frontmatter });
34
34
  if (!metadataObj) {
35
35
  return undefined;
36
36
  }
37
- const requires = resolvePoolbotManifestRequires(metadataObj);
38
- const install = resolvePoolbotManifestInstall(metadataObj, parseInstallSpec);
39
- const osRaw = resolvePoolbotManifestOs(metadataObj);
37
+ const requires = resolvePoolBotManifestRequires(metadataObj);
38
+ const install = resolvePoolBotManifestInstall(metadataObj, parseInstallSpec);
39
+ const osRaw = resolvePoolBotManifestOs(metadataObj);
40
40
  const eventsRaw = normalizeStringList(metadataObj.events);
41
41
  return {
42
42
  always: typeof metadataObj.always === "boolean" ? metadataObj.always : undefined,
@@ -0,0 +1,23 @@
1
+ import { isTruthyEnvValue } from "../infra/env.js";
2
+ import { startGmailWatcher } from "./gmail-watcher.js";
3
+ export async function startGmailWatcherWithLogs(params) {
4
+ if (isTruthyEnvValue(process.env.CLAWDBOT_SKIP_GMAIL_WATCHER)) {
5
+ params.onSkipped?.();
6
+ return;
7
+ }
8
+ try {
9
+ const gmailResult = await startGmailWatcher(params.cfg);
10
+ if (gmailResult.started) {
11
+ params.log.info("gmail watcher started");
12
+ return;
13
+ }
14
+ if (gmailResult.reason &&
15
+ gmailResult.reason !== "hooks not enabled" &&
16
+ gmailResult.reason !== "no gmail account configured") {
17
+ params.log.warn(`gmail watcher not started: ${gmailResult.reason}`);
18
+ }
19
+ }
20
+ catch (err) {
21
+ params.log.error(`gmail watcher failed to start: ${String(err)}`);
22
+ }
23
+ }
@@ -8,8 +8,8 @@ import { spawn } from "node:child_process";
8
8
  import { hasBinary } from "../agents/skills.js";
9
9
  import { createSubsystemLogger } from "../logging/subsystem.js";
10
10
  import { runCommandWithTimeout } from "../process/exec.js";
11
- import { buildGogWatchServeArgs, buildGogWatchStartArgs, resolveGmailHookRuntimeConfig, } from "./gmail.js";
12
11
  import { ensureTailscaleEndpoint } from "./gmail-setup-utils.js";
12
+ import { buildGogWatchServeArgs, buildGogWatchStartArgs, resolveGmailHookRuntimeConfig, } from "./gmail.js";
13
13
  const log = createSubsystemLogger("gmail-watcher");
14
14
  const ADDRESS_IN_USE_RE = /address already in use|EADDRINUSE/i;
15
15
  export function isAddressInUseError(line) {
@@ -58,13 +58,15 @@ function spawnGogServe(cfg) {
58
58
  });
59
59
  child.stdout?.on("data", (data) => {
60
60
  const line = data.toString().trim();
61
- if (line)
61
+ if (line) {
62
62
  log.info(`[gog] ${line}`);
63
+ }
63
64
  });
64
65
  child.stderr?.on("data", (data) => {
65
66
  const line = data.toString().trim();
66
- if (!line)
67
+ if (!line) {
67
68
  return;
69
+ }
68
70
  if (isAddressInUseError(line)) {
69
71
  addressInUse = true;
70
72
  }
@@ -74,8 +76,9 @@ function spawnGogServe(cfg) {
74
76
  log.error(`gog process error: ${String(err)}`);
75
77
  });
76
78
  child.on("exit", (code, signal) => {
77
- if (shuttingDown)
79
+ if (shuttingDown) {
78
80
  return;
81
+ }
79
82
  if (addressInUse) {
80
83
  log.warn("gog serve failed to bind (address already in use); stopping restarts. " +
81
84
  "Another watcher is likely running. Set POOLBOT_SKIP_GMAIL_WATCHER=1 or stop the other process.");
@@ -85,8 +88,9 @@ function spawnGogServe(cfg) {
85
88
  log.warn(`gog exited (code=${code}, signal=${signal}); restarting in 5s`);
86
89
  watcherProcess = null;
87
90
  setTimeout(() => {
88
- if (shuttingDown || !currentConfig)
91
+ if (shuttingDown || !currentConfig) {
89
92
  return;
93
+ }
90
94
  watcherProcess = spawnGogServe(currentConfig);
91
95
  }, 5000);
92
96
  });
@@ -146,8 +150,9 @@ export async function startGmailWatcher(cfg) {
146
150
  // Set up renewal interval
147
151
  const renewMs = runtimeConfig.renewEveryMinutes * 60_000;
148
152
  renewInterval = setInterval(() => {
149
- if (shuttingDown)
153
+ if (shuttingDown) {
150
154
  return;
155
+ }
151
156
  void startGmailWatch(runtimeConfig);
152
157
  }, renewMs);
153
158
  log.info(`gmail watcher started for ${runtimeConfig.account} (renew every ${runtimeConfig.renewEveryMinutes}m)`);
@@ -4,8 +4,10 @@
4
4
  * Provides an extensible event-driven hook system for agent events
5
5
  * like command processing, session lifecycle, etc.
6
6
  */
7
+ import { createSubsystemLogger } from "../logging/subsystem.js";
7
8
  /** Registry of hook handlers by event key */
8
9
  const handlers = new Map();
10
+ const log = createSubsystemLogger("internal-hooks");
9
11
  /**
10
12
  * Register a hook handler for a specific event type or event:action combination
11
13
  *
@@ -87,7 +89,8 @@ export async function triggerInternalHook(event) {
87
89
  await handler(event);
88
90
  }
89
91
  catch (err) {
90
- console.error(`Hook error [${event.type}:${event.action}]:`, err instanceof Error ? err.message : String(err));
92
+ const message = err instanceof Error ? err.message : String(err);
93
+ log.error(`Hook error [${event.type}:${event.action}]: ${message}`);
91
94
  }
92
95
  }
93
96
  }
@@ -122,6 +125,13 @@ export function isAgentBootstrapEvent(event) {
122
125
  }
123
126
  return Array.isArray(context.bootstrapFiles);
124
127
  }
128
+ export function isGatewayStartupEvent(event) {
129
+ if (event.type !== "gateway" || event.action !== "startup") {
130
+ return false;
131
+ }
132
+ const context = event.context;
133
+ return Boolean(context && typeof context === "object");
134
+ }
125
135
  export function isMessageReceivedEvent(event) {
126
136
  if (event.type !== "message" || event.action !== "received") {
127
137
  return false;
@@ -6,6 +6,8 @@ import os from "node:os";
6
6
  import path from "node:path";
7
7
  import { runEmbeddedPiAgent } from "../agents/pi-embedded.js";
8
8
  import { resolveDefaultAgentId, resolveAgentWorkspaceDir, resolveAgentDir, } from "../agents/agent-scope.js";
9
+ import { createSubsystemLogger } from "../logging/subsystem.js";
10
+ const log = createSubsystemLogger("llm-slug-generator");
9
11
  /**
10
12
  * Generate a short 1-2 word filename slug from session content using LLM
11
13
  */
@@ -53,7 +55,8 @@ Reply with ONLY the slug, nothing else. Examples: "vendor-pitch", "api-design",
53
55
  return null;
54
56
  }
55
57
  catch (err) {
56
- console.error("[llm-slug-generator] Failed to generate slug:", err);
58
+ const message = err instanceof Error ? (err.stack ?? err.message) : String(err);
59
+ log.error(`Failed to generate slug: ${message}`);
57
60
  return null;
58
61
  }
59
62
  finally {
@@ -1,17 +1,21 @@
1
1
  import fs from "node:fs";
2
2
  import path from "node:path";
3
- import { LEGACY_MANIFEST_KEY } from "../compat/legacy-names.js";
3
+ import { MANIFEST_KEY } from "../compat/legacy-names.js";
4
+ import { createSubsystemLogger } from "../logging/subsystem.js";
5
+ import { isPathInsideWithRealpath } from "../security/scan-paths.js";
4
6
  import { CONFIG_DIR, resolveUserPath } from "../utils.js";
5
7
  import { resolveBundledHooksDir } from "./bundled-dir.js";
6
8
  import { shouldIncludeHook } from "./config.js";
7
9
  import { parseFrontmatter, resolvePoolbotMetadata, resolveHookInvocationPolicy, } from "./frontmatter.js";
10
+ const log = createSubsystemLogger("hooks/workspace");
8
11
  function filterHookEntries(entries, config, eligibility) {
9
12
  return entries.filter((entry) => shouldIncludeHook({ entry, config, eligibility }));
10
13
  }
11
14
  function readHookPackageManifest(dir) {
12
15
  const manifestPath = path.join(dir, "package.json");
13
- if (!fs.existsSync(manifestPath))
16
+ if (!fs.existsSync(manifestPath)) {
14
17
  return null;
18
+ }
15
19
  try {
16
20
  const raw = fs.readFileSync(manifestPath, "utf-8");
17
21
  return JSON.parse(raw);
@@ -21,15 +25,27 @@ function readHookPackageManifest(dir) {
21
25
  }
22
26
  }
23
27
  function resolvePackageHooks(manifest) {
24
- const raw = manifest.poolbot?.hooks ?? manifest[LEGACY_MANIFEST_KEY]?.hooks;
25
- if (!Array.isArray(raw))
28
+ const raw = manifest[MANIFEST_KEY]?.hooks;
29
+ if (!Array.isArray(raw)) {
26
30
  return [];
31
+ }
27
32
  return raw.map((entry) => (typeof entry === "string" ? entry.trim() : "")).filter(Boolean);
28
33
  }
34
+ function resolveContainedDir(baseDir, targetDir) {
35
+ const base = path.resolve(baseDir);
36
+ const resolved = path.resolve(baseDir, targetDir);
37
+ if (!isPathInsideWithRealpath(base, resolved, {
38
+ requireRealpath: true,
39
+ })) {
40
+ return null;
41
+ }
42
+ return resolved;
43
+ }
29
44
  function loadHookFromDir(params) {
30
45
  const hookMdPath = path.join(params.hookDir, "HOOK.md");
31
- if (!fs.existsSync(hookMdPath))
46
+ if (!fs.existsSync(hookMdPath)) {
32
47
  return null;
48
+ }
33
49
  try {
34
50
  const content = fs.readFileSync(hookMdPath, "utf-8");
35
51
  const frontmatter = parseFrontmatter(content);
@@ -45,7 +61,7 @@ function loadHookFromDir(params) {
45
61
  }
46
62
  }
47
63
  if (!handlerPath) {
48
- console.warn(`[hooks] Hook "${name}" has HOOK.md but no handler file in ${params.hookDir}`);
64
+ log.warn(`Hook "${name}" has HOOK.md but no handler file in ${params.hookDir}`);
49
65
  return null;
50
66
  }
51
67
  return {
@@ -59,7 +75,8 @@ function loadHookFromDir(params) {
59
75
  };
60
76
  }
61
77
  catch (err) {
62
- console.warn(`[hooks] Failed to load hook from ${params.hookDir}:`, err);
78
+ const message = err instanceof Error ? (err.stack ?? err.message) : String(err);
79
+ log.warn(`Failed to load hook from ${params.hookDir}: ${message}`);
63
80
  return null;
64
81
  }
65
82
  }
@@ -68,30 +85,38 @@ function loadHookFromDir(params) {
68
85
  */
69
86
  function loadHooksFromDir(params) {
70
87
  const { dir, source, pluginId } = params;
71
- if (!fs.existsSync(dir))
88
+ if (!fs.existsSync(dir)) {
72
89
  return [];
90
+ }
73
91
  const stat = fs.statSync(dir);
74
- if (!stat.isDirectory())
92
+ if (!stat.isDirectory()) {
75
93
  return [];
94
+ }
76
95
  const hooks = [];
77
96
  const entries = fs.readdirSync(dir, { withFileTypes: true });
78
97
  for (const entry of entries) {
79
- if (!entry.isDirectory())
98
+ if (!entry.isDirectory()) {
80
99
  continue;
100
+ }
81
101
  const hookDir = path.join(dir, entry.name);
82
102
  const manifest = readHookPackageManifest(hookDir);
83
103
  const packageHooks = manifest ? resolvePackageHooks(manifest) : [];
84
104
  if (packageHooks.length > 0) {
85
105
  for (const hookPath of packageHooks) {
86
- const resolvedHookDir = path.resolve(hookDir, hookPath);
106
+ const resolvedHookDir = resolveContainedDir(hookDir, hookPath);
107
+ if (!resolvedHookDir) {
108
+ log.warn(`Ignoring out-of-package hook path "${hookPath}" in ${hookDir} (must be within package directory)`);
109
+ continue;
110
+ }
87
111
  const hook = loadHookFromDir({
88
112
  hookDir: resolvedHookDir,
89
113
  source,
90
114
  pluginId,
91
115
  nameHint: path.basename(resolvedHookDir),
92
116
  });
93
- if (hook)
117
+ if (hook) {
94
118
  hooks.push(hook);
119
+ }
95
120
  }
96
121
  continue;
97
122
  }
@@ -101,8 +126,9 @@ function loadHooksFromDir(params) {
101
126
  pluginId,
102
127
  nameHint: entry.name,
103
128
  });
104
- if (hook)
129
+ if (hook) {
105
130
  hooks.push(hook);
131
+ }
106
132
  }
107
133
  return hooks;
108
134
  }
@@ -165,14 +191,18 @@ function loadHookEntries(workspaceDir, opts) {
165
191
  });
166
192
  const merged = new Map();
167
193
  // Precedence: extra < bundled < managed < workspace (workspace wins)
168
- for (const hook of extraHooks)
194
+ for (const hook of extraHooks) {
169
195
  merged.set(hook.name, hook);
170
- for (const hook of bundledHooks)
196
+ }
197
+ for (const hook of bundledHooks) {
171
198
  merged.set(hook.name, hook);
172
- for (const hook of managedHooks)
199
+ }
200
+ for (const hook of managedHooks) {
173
201
  merged.set(hook.name, hook);
174
- for (const hook of workspaceHooks)
202
+ }
203
+ for (const hook of workspaceHooks) {
175
204
  merged.set(hook.name, hook);
205
+ }
176
206
  return Array.from(merged.values()).map((hook) => {
177
207
  let frontmatter = {};
178
208
  try {
@@ -1,26 +1,13 @@
1
- import { DEFAULT_ACCOUNT_ID, normalizeAccountId } from "../routing/session-key.js";
2
- function listConfiguredAccountIds(cfg) {
3
- const accounts = cfg.channels?.imessage?.accounts;
4
- if (!accounts || typeof accounts !== "object")
5
- return [];
6
- return Object.keys(accounts).filter(Boolean);
7
- }
8
- export function listIMessageAccountIds(cfg) {
9
- const ids = listConfiguredAccountIds(cfg);
10
- if (ids.length === 0)
11
- return [DEFAULT_ACCOUNT_ID];
12
- return ids.sort((a, b) => a.localeCompare(b));
13
- }
14
- export function resolveDefaultIMessageAccountId(cfg) {
15
- const ids = listIMessageAccountIds(cfg);
16
- if (ids.includes(DEFAULT_ACCOUNT_ID))
17
- return DEFAULT_ACCOUNT_ID;
18
- return ids[0] ?? DEFAULT_ACCOUNT_ID;
19
- }
1
+ import { createAccountListHelpers } from "../channels/plugins/account-helpers.js";
2
+ import { normalizeAccountId } from "../routing/session-key.js";
3
+ const { listAccountIds, resolveDefaultAccountId } = createAccountListHelpers("imessage");
4
+ export const listIMessageAccountIds = listAccountIds;
5
+ export const resolveDefaultIMessageAccountId = resolveDefaultAccountId;
20
6
  function resolveAccountConfig(cfg, accountId) {
21
7
  const accounts = cfg.channels?.imessage?.accounts;
22
- if (!accounts || typeof accounts !== "object")
8
+ if (!accounts || typeof accounts !== "object") {
23
9
  return undefined;
10
+ }
24
11
  return accounts[accountId];
25
12
  }
26
13
  function mergeIMessageAccountConfig(cfg, accountId) {
@@ -43,6 +30,8 @@ export function resolveIMessageAccount(params) {
43
30
  merged.dmPolicy ||
44
31
  merged.groupPolicy ||
45
32
  typeof merged.includeAttachments === "boolean" ||
33
+ (merged.attachmentRoots && merged.attachmentRoots.length > 0) ||
34
+ (merged.remoteAttachmentRoots && merged.remoteAttachmentRoots.length > 0) ||
46
35
  typeof merged.mediaMaxMb === "number" ||
47
36
  typeof merged.textChunkLimit === "number" ||
48
37
  (merged.groups && Object.keys(merged.groups).length > 0));