@poolzin/pool-bot 2026.2.20 → 2026.2.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (388) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/dist/agents/api-key-rotation.js +47 -0
  3. package/dist/agents/apply-patch-update.js +19 -9
  4. package/dist/agents/apply-patch.js +72 -47
  5. package/dist/agents/bash-tools.exec.js +141 -559
  6. package/dist/agents/cli-backends.js +49 -6
  7. package/dist/agents/cli-runner/helpers.js +69 -152
  8. package/dist/agents/cli-runner.js +70 -19
  9. package/dist/agents/identity.js +20 -1
  10. package/dist/agents/image-sanitization.js +9 -0
  11. package/dist/agents/live-auth-keys.js +123 -26
  12. package/dist/agents/live-model-filter.js +13 -4
  13. package/dist/agents/model-auth.js +12 -0
  14. package/dist/agents/model-catalog.js +40 -9
  15. package/dist/agents/model-fallback.js +24 -0
  16. package/dist/agents/model-forward-compat.js +60 -23
  17. package/dist/agents/model-selection.js +134 -41
  18. package/dist/agents/pi-auth-json.js +2 -2
  19. package/dist/agents/pi-embedded-helpers/bootstrap.js +65 -15
  20. package/dist/agents/pi-embedded-helpers/errors.js +140 -15
  21. package/dist/agents/pi-embedded-helpers/images.js +22 -12
  22. package/dist/agents/pi-embedded-helpers.js +2 -2
  23. package/dist/agents/pi-embedded-runner/abort.js +10 -3
  24. package/dist/agents/pi-embedded-runner/compact.js +230 -32
  25. package/dist/agents/pi-embedded-runner/extra-params.js +203 -12
  26. package/dist/agents/pi-embedded-runner/google.js +109 -19
  27. package/dist/agents/pi-embedded-runner/history.js +35 -17
  28. package/dist/agents/pi-embedded-runner/run/attempt.js +386 -80
  29. package/dist/agents/pi-embedded-runner/run/images.js +81 -55
  30. package/dist/agents/pi-embedded-runner/run/payloads.js +89 -39
  31. package/dist/agents/pi-embedded-runner/run.js +193 -25
  32. package/dist/agents/pi-embedded-runner/run.overflow-compaction.mocks.shared.js +2 -2
  33. package/dist/agents/pi-embedded-runner/runs.js +17 -8
  34. package/dist/agents/pi-embedded-runner/tool-result-context-guard.js +262 -0
  35. package/dist/agents/pi-embedded-runner.js +1 -1
  36. package/dist/agents/pi-embedded-subscribe.handlers.tools.js +180 -10
  37. package/dist/agents/pi-embedded-subscribe.js +37 -0
  38. package/dist/agents/pi-embedded-subscribe.tools.js +127 -30
  39. package/dist/agents/pi-model-discovery.js +9 -2
  40. package/dist/agents/pi-tool-definition-adapter.js +60 -8
  41. package/dist/agents/pi-tools.before-tool-call.js +1 -1
  42. package/dist/agents/pi-tools.js +113 -94
  43. package/dist/agents/pi-tools.read.js +337 -38
  44. package/dist/agents/poolbot-tools.js +14 -5
  45. package/dist/agents/provider/config-loader.js +76 -0
  46. package/dist/agents/provider/index.js +15 -0
  47. package/dist/agents/provider/integration.js +136 -0
  48. package/dist/agents/provider/models-dev.js +129 -0
  49. package/dist/agents/provider/rate-limits.js +458 -0
  50. package/dist/agents/provider/request-monitor.js +449 -0
  51. package/dist/agents/provider/session-binding.js +376 -0
  52. package/dist/agents/provider/token-pool.js +541 -0
  53. package/dist/agents/sandbox/docker.js +10 -5
  54. package/dist/agents/sandbox/registry.js +96 -46
  55. package/dist/agents/sandbox/sanitize-env-vars.js +82 -0
  56. package/dist/agents/sandbox-paths.js +43 -10
  57. package/dist/agents/session-tool-result-guard-wrapper.js +23 -11
  58. package/dist/agents/session-tool-result-guard.js +39 -39
  59. package/dist/agents/session-transcript-repair.js +36 -33
  60. package/dist/agents/session-write-lock.js +62 -44
  61. package/dist/agents/skills/frontmatter.js +49 -88
  62. package/dist/agents/skills/workspace.js +335 -28
  63. package/dist/agents/subagent-announce.js +508 -174
  64. package/dist/agents/subagent-registry.js +45 -4
  65. package/dist/agents/subagent-spawn.js +16 -33
  66. package/dist/agents/system-prompt-report.js +27 -10
  67. package/dist/agents/system-prompt.js +26 -32
  68. package/dist/agents/tool-call-id.js +69 -17
  69. package/dist/agents/tool-display-common.js +1 -1
  70. package/dist/agents/tool-images.js +64 -31
  71. package/dist/agents/tools/canvas-tool.js +17 -11
  72. package/dist/agents/tools/common.js +37 -19
  73. package/dist/agents/tools/cron-tool.js +40 -38
  74. package/dist/agents/tools/gateway.js +70 -2
  75. package/dist/agents/tools/message-tool.js +181 -40
  76. package/dist/agents/tools/nodes-tool.js +128 -36
  77. package/dist/agents/tools/nodes-utils.js +12 -38
  78. package/dist/agents/tools/session-status-tool.js +24 -71
  79. package/dist/agents/tools/sessions-helpers.js +38 -210
  80. package/dist/agents/tools/sessions-spawn-tool.js +28 -198
  81. package/dist/agents/tools/telegram-actions.js +58 -7
  82. package/dist/agents/tools/web-fetch-utils.js +112 -7
  83. package/dist/agents/tools/web-fetch.js +279 -175
  84. package/dist/agents/tools/web-shared.js +71 -8
  85. package/dist/agents/usage.js +25 -16
  86. package/dist/auto-reply/commands-registry.data.js +85 -11
  87. package/dist/auto-reply/dispatch.js +40 -21
  88. package/dist/auto-reply/reply/abort.js +102 -33
  89. package/dist/auto-reply/reply/commands-core.js +82 -33
  90. package/dist/auto-reply/reply/commands-export-session.js +1 -1
  91. package/dist/auto-reply/reply/commands-info.js +41 -12
  92. package/dist/auto-reply/reply/commands-subagents.js +352 -100
  93. package/dist/auto-reply/reply/commands-system-prompt.js +2 -2
  94. package/dist/auto-reply/reply/dispatch-from-config.js +100 -29
  95. package/dist/auto-reply/reply/elevated-unavailable.js +1 -1
  96. package/dist/auto-reply/reply/inbound-meta.js +12 -1
  97. package/dist/auto-reply/reply/mentions.js +18 -11
  98. package/dist/auto-reply/reply/normalize-reply.js +17 -8
  99. package/dist/auto-reply/reply/reply-dispatcher.js +62 -10
  100. package/dist/auto-reply/reply/session.js +102 -21
  101. package/dist/auto-reply/reply/streaming-directives.js +16 -5
  102. package/dist/auto-reply/status.js +73 -50
  103. package/dist/browser/extension-relay.js +3 -3
  104. package/dist/browser/http-auth.js +1 -1
  105. package/dist/browser/paths.js +2 -2
  106. package/dist/build-info.json +3 -3
  107. package/dist/channels/allowlist-match.js +20 -0
  108. package/dist/channels/allowlists/resolve-utils.js +65 -2
  109. package/dist/channels/chat-type.js +8 -4
  110. package/dist/channels/dock.js +127 -35
  111. package/dist/channels/draft-stream-loop.js +6 -2
  112. package/dist/channels/plugins/actions/telegram.js +42 -18
  113. package/dist/channels/plugins/allowlist-match.js +1 -1
  114. package/dist/channels/plugins/group-mentions.js +51 -41
  115. package/dist/channels/plugins/message-action-names.js +2 -0
  116. package/dist/channels/plugins/message-actions.js +24 -5
  117. package/dist/channels/plugins/normalize/discord.js +26 -4
  118. package/dist/channels/plugins/normalize/signal.js +35 -22
  119. package/dist/channels/plugins/onboarding/helpers.js +8 -26
  120. package/dist/channels/plugins/outbound/imessage.js +15 -14
  121. package/dist/channels/registry.js +20 -7
  122. package/dist/cli/acp-cli.js +7 -5
  123. package/dist/cli/browser-cli-extension.js +25 -12
  124. package/dist/cli/browser-cli-state.cookies-storage.js +25 -6
  125. package/dist/cli/browser-cli-state.js +101 -145
  126. package/dist/cli/command-options.js +28 -0
  127. package/dist/cli/completion-cli.js +6 -6
  128. package/dist/cli/cron-cli/register.cron-add.js +25 -1
  129. package/dist/cli/cron-cli/register.cron-edit.js +44 -0
  130. package/dist/cli/cron-cli/shared.js +7 -1
  131. package/dist/cli/daemon-cli/lifecycle-core.js +23 -21
  132. package/dist/cli/daemon-cli/lifecycle.js +23 -247
  133. package/dist/cli/daemon-cli/register-service-commands.js +25 -4
  134. package/dist/cli/daemon-cli.js +1 -0
  135. package/dist/cli/devices-cli.js +33 -20
  136. package/dist/cli/gateway-cli/register.js +37 -105
  137. package/dist/cli/gateway-cli/run.js +49 -11
  138. package/dist/cli/nodes-camera.js +59 -4
  139. package/dist/cli/nodes-cli/register.camera.js +27 -24
  140. package/dist/cli/nodes-cli/rpc.js +21 -38
  141. package/dist/cli/qr-cli.js +2 -2
  142. package/dist/cli/skills-cli.format.js +2 -2
  143. package/dist/cli/update-cli/progress.js +2 -2
  144. package/dist/cli/update-cli/restart-helper.js +28 -7
  145. package/dist/cli/update-cli/shared.js +7 -7
  146. package/dist/cli/update-cli/status.js +1 -1
  147. package/dist/cli/update-cli/update-command.js +14 -8
  148. package/dist/cli/update-cli/wizard.js +2 -2
  149. package/dist/cli/update-cli.js +21 -1027
  150. package/dist/commands/auth-choice.apply.anthropic.js +10 -2
  151. package/dist/commands/channels/add-mutators.js +3 -35
  152. package/dist/commands/channels/add.js +39 -51
  153. package/dist/commands/config-validation.js +1 -1
  154. package/dist/commands/configure.gateway-auth.js +52 -15
  155. package/dist/commands/configure.gateway.js +84 -40
  156. package/dist/commands/doctor-completion.js +3 -3
  157. package/dist/commands/doctor-config-flow.js +536 -16
  158. package/dist/commands/doctor-gateway-services.js +103 -79
  159. package/dist/commands/doctor-memory-search.js +9 -9
  160. package/dist/commands/doctor-platform-notes.js +57 -30
  161. package/dist/commands/doctor-prompter.js +26 -15
  162. package/dist/commands/doctor-session-locks.js +1 -1
  163. package/dist/commands/doctor.js +21 -9
  164. package/dist/commands/model-picker.js +120 -95
  165. package/dist/commands/models/set.js +2 -21
  166. package/dist/commands/models/shared.js +65 -37
  167. package/dist/commands/onboard-helpers.js +81 -39
  168. package/dist/commands/openai-codex-oauth.js +1 -1
  169. package/dist/commands/sessions.js +52 -53
  170. package/dist/commands/status.summary.js +52 -34
  171. package/dist/commands/test-wizard-helpers.js +2 -2
  172. package/dist/config/defaults.js +79 -42
  173. package/dist/config/group-policy.js +50 -18
  174. package/dist/config/includes.js +37 -10
  175. package/dist/config/schema.help.js +5 -4
  176. package/dist/config/schema.hints.js +2 -2
  177. package/dist/config/schema.labels.js +1 -0
  178. package/dist/config/sessions/group.js +12 -11
  179. package/dist/config/sessions/paths.js +137 -11
  180. package/dist/config/sessions/store.js +185 -65
  181. package/dist/config/sessions/types.js +15 -1
  182. package/dist/config/sessions.js +1 -0
  183. package/dist/config/telegram-custom-commands.js +3 -2
  184. package/dist/config/types.js +2 -0
  185. package/dist/config/zod-schema.agent-defaults.js +6 -27
  186. package/dist/config/zod-schema.agent-runtime.js +171 -79
  187. package/dist/config/zod-schema.providers-core.js +138 -65
  188. package/dist/config/zod-schema.session.js +49 -22
  189. package/dist/control-ui/assets/index-HRr1grwl.js.map +1 -1
  190. package/dist/cron/isolated-agent/run.js +224 -57
  191. package/dist/cron/normalize.js +48 -45
  192. package/dist/cron/run-log.js +14 -0
  193. package/dist/cron/service/jobs.js +190 -28
  194. package/dist/cron/service/normalize.js +29 -11
  195. package/dist/cron/service/store.js +30 -44
  196. package/dist/cron/service/timer.js +182 -96
  197. package/dist/cron/service.js +3 -0
  198. package/dist/cron/stagger.js +37 -0
  199. package/dist/daemon/inspect.js +132 -92
  200. package/dist/daemon/runtime-paths.js +25 -4
  201. package/dist/daemon/service-audit.js +47 -16
  202. package/dist/discord/accounts.js +23 -20
  203. package/dist/discord/monitor/agent-components.js +1115 -219
  204. package/dist/discord/monitor/allow-list.js +114 -34
  205. package/dist/discord/monitor/listeners.js +204 -97
  206. package/dist/discord/monitor/message-handler.js +21 -10
  207. package/dist/discord/monitor/message-handler.preflight.js +195 -101
  208. package/dist/discord/monitor/message-handler.process.js +384 -123
  209. package/dist/discord/monitor/message-utils.js +86 -23
  210. package/dist/discord/monitor/native-command.js +77 -57
  211. package/dist/discord/monitor/provider.js +122 -117
  212. package/dist/discord/monitor/reply-context.js +20 -16
  213. package/dist/discord/monitor/reply-delivery.js +40 -8
  214. package/dist/discord/monitor/rest-fetch.js +22 -0
  215. package/dist/discord/monitor/threading.js +117 -24
  216. package/dist/discord/send.js +2 -1
  217. package/dist/discord/send.outbound.js +124 -11
  218. package/dist/discord/send.shared.js +112 -72
  219. package/dist/discord/voice-message.js +3 -3
  220. package/dist/gateway/auth.js +119 -44
  221. package/dist/gateway/call.js +76 -34
  222. package/dist/gateway/channel-health-monitor.js +57 -50
  223. package/dist/gateway/client.js +63 -29
  224. package/dist/gateway/control-ui-contract.js +1 -1
  225. package/dist/gateway/gateway-config-prompts.shared.js +2 -2
  226. package/dist/gateway/net.js +109 -1
  227. package/dist/gateway/protocol/index.js +5 -8
  228. package/dist/gateway/protocol/schema/agent.js +19 -1
  229. package/dist/gateway/protocol/schema/channels.js +21 -0
  230. package/dist/gateway/protocol/schema/cron.js +43 -30
  231. package/dist/gateway/protocol/schema/protocol-schemas.js +6 -11
  232. package/dist/gateway/protocol/schema/sessions.js +5 -1
  233. package/dist/gateway/protocol/schema.js +0 -1
  234. package/dist/gateway/server/presence-events.js +12 -0
  235. package/dist/gateway/server/ws-connection/message-handler.js +203 -212
  236. package/dist/gateway/server/ws-connection.js +58 -21
  237. package/dist/gateway/server-broadcast.js +18 -13
  238. package/dist/gateway/server-cron.js +177 -10
  239. package/dist/gateway/server-methods/agent-job.js +131 -38
  240. package/dist/gateway/server-methods/send.js +60 -14
  241. package/dist/gateway/server-methods/sessions.js +160 -96
  242. package/dist/gateway/server-methods/system.js +5 -7
  243. package/dist/gateway/server-methods-list.js +8 -0
  244. package/dist/gateway/server-methods.js +24 -8
  245. package/dist/gateway/server-node-events.js +278 -68
  246. package/dist/gateway/session-utils.fs.js +316 -75
  247. package/dist/gateway/session-utils.js +224 -70
  248. package/dist/gateway/sessions-patch.js +63 -20
  249. package/dist/gateway/test-temp-config.js +1 -1
  250. package/dist/gateway/tools-invoke-http.js +118 -70
  251. package/dist/gateway/ws-log.js +135 -107
  252. package/dist/hooks/frontmatter.js +36 -82
  253. package/dist/hooks/install.js +149 -139
  254. package/dist/hooks/internal-hooks.js +29 -4
  255. package/dist/hooks/plugin-hooks.js +2 -1
  256. package/dist/imessage/monitor/deliver.js +10 -4
  257. package/dist/imessage/monitor/monitor-provider.js +138 -375
  258. package/dist/imessage/monitor/runtime.js +4 -8
  259. package/dist/imessage/send.js +65 -19
  260. package/dist/infra/exec-approvals-allowlist.js +7 -0
  261. package/dist/infra/exec-approvals.js +35 -920
  262. package/dist/infra/exec-safe-bin-trust.js +64 -0
  263. package/dist/infra/heartbeat-runner.js +207 -134
  264. package/dist/infra/heartbeat-wake.js +183 -22
  265. package/dist/infra/install-source-utils.js +47 -0
  266. package/dist/infra/net/ssrf.js +170 -36
  267. package/dist/infra/outbound/deliver.js +224 -58
  268. package/dist/infra/outbound/message-action-spec.js +12 -5
  269. package/dist/infra/outbound/outbound-session.js +27 -25
  270. package/dist/infra/poolbot-root.js +32 -22
  271. package/dist/infra/ports.js +14 -11
  272. package/dist/infra/skills-remote.js +48 -37
  273. package/dist/infra/system-events.js +25 -11
  274. package/dist/infra/system-presence.js +26 -33
  275. package/dist/infra/tmp-poolbot-dir.js +81 -2
  276. package/dist/infra/wsl.js +37 -1
  277. package/dist/line/bot-message-context.js +163 -191
  278. package/dist/logging/subsystem.js +59 -22
  279. package/dist/markdown/ir.js +124 -50
  280. package/dist/media/store.js +1 -1
  281. package/dist/media-understanding/runner.entries.js +42 -25
  282. package/dist/media-understanding/runner.js +53 -488
  283. package/dist/memory/embeddings-gemini.js +53 -38
  284. package/dist/memory/manager-embedding-ops.js +48 -69
  285. package/dist/pairing/pairing-store.js +178 -119
  286. package/dist/plugin-sdk/index.js +34 -6
  287. package/dist/plugins/hooks.js +135 -14
  288. package/dist/plugins/install.js +190 -152
  289. package/dist/polls.js +11 -0
  290. package/dist/routing/resolve-route.js +190 -56
  291. package/dist/routing/session-key.js +38 -22
  292. package/dist/runtime.js +35 -9
  293. package/dist/security/audit-channel.js +1 -1
  294. package/dist/sessions/session-key-utils.js +29 -11
  295. package/dist/shared/frontmatter.js +5 -5
  296. package/dist/shared/node-list-types.js +1 -0
  297. package/dist/shared/string-normalization.js +15 -0
  298. package/dist/signal/monitor/event-handler.js +68 -36
  299. package/dist/signal/send.js +29 -37
  300. package/dist/slack/monitor/allow-list.js +10 -11
  301. package/dist/slack/monitor/commands.js +14 -3
  302. package/dist/slack/monitor/events/interactions.js +4 -4
  303. package/dist/slack/monitor/media.js +224 -16
  304. package/dist/slack/monitor/message-handler/dispatch.js +247 -13
  305. package/dist/slack/monitor/message-handler/prepare.js +128 -45
  306. package/dist/slack/monitor/slash.js +357 -144
  307. package/dist/slack/streaming.js +77 -0
  308. package/dist/telegram/accounts.js +40 -13
  309. package/dist/telegram/allowed-updates.js +3 -0
  310. package/dist/telegram/bot/delivery.js +129 -66
  311. package/dist/telegram/bot/helpers.js +136 -122
  312. package/dist/telegram/bot-handlers.js +600 -339
  313. package/dist/telegram/bot-message-context.js +115 -73
  314. package/dist/telegram/bot-message-dispatch.js +235 -104
  315. package/dist/telegram/bot-native-command-menu.js +3 -1
  316. package/dist/telegram/bot-native-commands.js +213 -193
  317. package/dist/telegram/bot.js +24 -132
  318. package/dist/telegram/draft-stream.js +84 -75
  319. package/dist/telegram/format.js +150 -6
  320. package/dist/telegram/send.js +415 -255
  321. package/dist/telegram/targets.js +21 -2
  322. package/dist/telegram/update-offset-store.js +19 -3
  323. package/dist/terminal/restore.js +5 -2
  324. package/dist/test-utils/fetch-mock.js +5 -0
  325. package/dist/version.js +18 -5
  326. package/dist/web/auto-reply/monitor/broadcast.js +7 -3
  327. package/dist/web/auto-reply/monitor/on-message.js +6 -3
  328. package/dist/web/inbound/media.js +34 -8
  329. package/dist/web/inbound/monitor.js +34 -17
  330. package/dist/web/inbound/send-api.js +18 -17
  331. package/dist/web/outbound.js +12 -5
  332. package/dist/wizard/clack-prompter.js +40 -7
  333. package/extensions/bluebubbles/package.json +1 -1
  334. package/extensions/copilot-proxy/package.json +1 -1
  335. package/extensions/diagnostics-otel/package.json +1 -1
  336. package/extensions/discord/package.json +1 -1
  337. package/extensions/feishu/package.json +1 -1
  338. package/extensions/google-antigravity-auth/package.json +1 -1
  339. package/extensions/google-gemini-cli-auth/package.json +1 -1
  340. package/extensions/googlechat/package.json +1 -1
  341. package/extensions/imessage/package.json +1 -1
  342. package/extensions/irc/package.json +1 -1
  343. package/extensions/line/package.json +1 -1
  344. package/extensions/llm-task/package.json +1 -1
  345. package/extensions/lobster/package.json +1 -1
  346. package/extensions/matrix/CHANGELOG.md +5 -0
  347. package/extensions/matrix/package.json +1 -1
  348. package/extensions/mattermost/package.json +1 -1
  349. package/extensions/memory-core/package.json +1 -1
  350. package/extensions/memory-lancedb/package.json +1 -1
  351. package/extensions/minimax-portal-auth/package.json +1 -1
  352. package/extensions/msteams/CHANGELOG.md +5 -0
  353. package/extensions/msteams/package.json +1 -1
  354. package/extensions/nextcloud-talk/package.json +1 -1
  355. package/extensions/nostr/CHANGELOG.md +5 -0
  356. package/extensions/nostr/package.json +1 -1
  357. package/extensions/open-prose/package.json +1 -1
  358. package/extensions/openai-codex-auth/package.json +1 -1
  359. package/extensions/signal/package.json +1 -1
  360. package/extensions/slack/package.json +1 -1
  361. package/extensions/telegram/package.json +1 -1
  362. package/extensions/tlon/package.json +1 -1
  363. package/extensions/twitch/CHANGELOG.md +5 -0
  364. package/extensions/twitch/package.json +1 -1
  365. package/extensions/voice-call/CHANGELOG.md +5 -0
  366. package/extensions/voice-call/package.json +1 -1
  367. package/extensions/whatsapp/package.json +1 -1
  368. package/extensions/zalo/CHANGELOG.md +5 -0
  369. package/extensions/zalo/package.json +1 -1
  370. package/extensions/zalouser/CHANGELOG.md +5 -0
  371. package/extensions/zalouser/package.json +1 -1
  372. package/package.json +1 -1
  373. package/skills/apple-reminders/SKILL.md +100 -49
  374. package/skills/coding-agent/SKILL.md +34 -28
  375. package/skills/github/SKILL.md +131 -16
  376. package/skills/imsg/SKILL.md +112 -15
  377. package/skills/openhue/SKILL.md +101 -19
  378. package/skills/plcode-controller/SKILL.md +156 -0
  379. package/skills/plcode-controller/assets/operator-prompts.md +65 -0
  380. package/skills/plcode-controller/references/command-cheatsheet.md +53 -0
  381. package/skills/plcode-controller/references/failure-handling.md +60 -0
  382. package/skills/plcode-controller/references/model-selection.md +57 -0
  383. package/skills/plcode-controller/references/plan-vs-build.md +52 -0
  384. package/skills/plcode-controller/references/question-handling.md +40 -0
  385. package/skills/plcode-controller/references/session-management.md +63 -0
  386. package/skills/plcode-controller/references/workflow.md +35 -0
  387. package/skills/tmux/SKILL.md +111 -79
  388. package/skills/weather/SKILL.md +88 -25
@@ -3,16 +3,26 @@ import fs from "node:fs/promises";
3
3
  import path from "node:path";
4
4
  import { isPidAlive } from "../shared/pid-alive.js";
5
5
  import { resolveProcessScopedMap } from "../shared/process-scoped-map.js";
6
+ const CLEANUP_SIGNALS = ["SIGINT", "SIGTERM", "SIGQUIT", "SIGABRT"];
7
+ const CLEANUP_STATE_KEY = Symbol.for("poolbot.sessionWriteLockCleanupState");
6
8
  const HELD_LOCKS_KEY = Symbol.for("poolbot.sessionWriteLockHeldLocks");
7
9
  const WATCHDOG_STATE_KEY = Symbol.for("poolbot.sessionWriteLockWatchdogState");
8
- const CLEANUP_SIGNALS = ["SIGINT", "SIGTERM", "SIGQUIT", "SIGABRT"];
9
10
  const DEFAULT_STALE_MS = 30 * 60 * 1000;
10
11
  const DEFAULT_MAX_HOLD_MS = 5 * 60 * 1000;
11
12
  const DEFAULT_WATCHDOG_INTERVAL_MS = 60_000;
12
13
  const DEFAULT_TIMEOUT_GRACE_MS = 2 * 60 * 1000;
13
14
  const MAX_LOCK_HOLD_MS = 2_147_000_000;
14
- const cleanupHandlers = new Map();
15
15
  const HELD_LOCKS = resolveProcessScopedMap(HELD_LOCKS_KEY);
16
+ function resolveCleanupState() {
17
+ const proc = process;
18
+ if (!proc[CLEANUP_STATE_KEY]) {
19
+ proc[CLEANUP_STATE_KEY] = {
20
+ registered: false,
21
+ cleanupHandlers: new Map(),
22
+ };
23
+ }
24
+ return proc[CLEANUP_STATE_KEY];
25
+ }
16
26
  function resolveWatchdogState() {
17
27
  const proc = process;
18
28
  if (!proc[WATCHDOG_STATE_KEY]) {
@@ -79,11 +89,11 @@ async function releaseHeldLock(normalizedSessionFile, held, opts = {}) {
79
89
  })();
80
90
  try {
81
91
  await held.releasePromise;
92
+ return true;
82
93
  }
83
94
  finally {
84
95
  held.releasePromise = undefined;
85
96
  }
86
- return true;
87
97
  }
88
98
  /**
89
99
  * Synchronously release all held locks.
@@ -92,8 +102,8 @@ async function releaseHeldLock(normalizedSessionFile, held, opts = {}) {
92
102
  function releaseAllLocksSync() {
93
103
  for (const [sessionFile, held] of HELD_LOCKS) {
94
104
  try {
95
- if (typeof held.handle.fd === "number") {
96
- fsSync.closeSync(held.handle.fd);
105
+ if (typeof held.handle.close === "function") {
106
+ void held.handle.close().catch(() => { });
97
107
  }
98
108
  }
99
109
  catch {
@@ -108,42 +118,6 @@ function releaseAllLocksSync() {
108
118
  HELD_LOCKS.delete(sessionFile);
109
119
  }
110
120
  }
111
- let cleanupRegistered = false;
112
- function handleTerminationSignal(signal) {
113
- releaseAllLocksSync();
114
- const shouldReraise = process.listenerCount(signal) === 1;
115
- if (shouldReraise) {
116
- const handler = cleanupHandlers.get(signal);
117
- if (handler)
118
- process.off(signal, handler);
119
- try {
120
- process.kill(process.pid, signal);
121
- }
122
- catch {
123
- // Ignore errors during shutdown
124
- }
125
- }
126
- }
127
- function registerCleanupHandlers() {
128
- if (cleanupRegistered)
129
- return;
130
- cleanupRegistered = true;
131
- // Cleanup on normal exit and process.exit() calls
132
- process.on("exit", () => {
133
- releaseAllLocksSync();
134
- });
135
- // Handle termination signals
136
- for (const signal of CLEANUP_SIGNALS) {
137
- try {
138
- const handler = () => handleTerminationSignal(signal);
139
- cleanupHandlers.set(signal, handler);
140
- process.on(signal, handler);
141
- }
142
- catch {
143
- // Ignore unsupported signals on this platform.
144
- }
145
- }
146
- }
147
121
  async function runLockWatchdogCheck(nowMs = Date.now()) {
148
122
  let released = 0;
149
123
  for (const [sessionFile, held] of HELD_LOCKS.entries()) {
@@ -174,6 +148,49 @@ function ensureWatchdogStarted(intervalMs) {
174
148
  }, intervalMs);
175
149
  watchdogState.timer.unref?.();
176
150
  }
151
+ function handleTerminationSignal(signal) {
152
+ releaseAllLocksSync();
153
+ const cleanupState = resolveCleanupState();
154
+ const shouldReraise = process.listenerCount(signal) === 1;
155
+ if (shouldReraise) {
156
+ const handler = cleanupState.cleanupHandlers.get(signal);
157
+ if (handler) {
158
+ process.off(signal, handler);
159
+ cleanupState.cleanupHandlers.delete(signal);
160
+ }
161
+ try {
162
+ process.kill(process.pid, signal);
163
+ }
164
+ catch {
165
+ // Ignore errors during shutdown
166
+ }
167
+ }
168
+ }
169
+ function registerCleanupHandlers() {
170
+ const cleanupState = resolveCleanupState();
171
+ if (!cleanupState.registered) {
172
+ cleanupState.registered = true;
173
+ // Cleanup on normal exit and process.exit() calls
174
+ process.on("exit", () => {
175
+ releaseAllLocksSync();
176
+ });
177
+ }
178
+ ensureWatchdogStarted(DEFAULT_WATCHDOG_INTERVAL_MS);
179
+ // Handle termination signals
180
+ for (const signal of CLEANUP_SIGNALS) {
181
+ if (cleanupState.cleanupHandlers.has(signal)) {
182
+ continue;
183
+ }
184
+ try {
185
+ const handler = () => handleTerminationSignal(signal);
186
+ cleanupState.cleanupHandlers.set(signal, handler);
187
+ process.on(signal, handler);
188
+ }
189
+ catch {
190
+ // Ignore unsupported signals on this platform.
191
+ }
192
+ }
193
+ }
177
194
  async function readLockPayload(lockPath) {
178
195
  try {
179
196
  const raw = await fs.readFile(lockPath, "utf8");
@@ -261,7 +278,6 @@ export async function cleanStaleLockFiles(params) {
261
278
  }
262
279
  export async function acquireSessionWriteLock(params) {
263
280
  registerCleanupHandlers();
264
- ensureWatchdogStarted(DEFAULT_WATCHDOG_INTERVAL_MS);
265
281
  const timeoutMs = resolvePositiveMs(params.timeoutMs, 10_000, { allowInfinity: true });
266
282
  const staleMs = resolvePositiveMs(params.staleMs, DEFAULT_STALE_MS);
267
283
  const maxHoldMs = resolvePositiveMs(params.maxHoldMs, DEFAULT_MAX_HOLD_MS);
@@ -277,8 +293,9 @@ export async function acquireSessionWriteLock(params) {
277
293
  }
278
294
  const normalizedSessionFile = path.join(normalizedDir, path.basename(sessionFile));
279
295
  const lockPath = `${normalizedSessionFile}.lock`;
296
+ const allowReentrant = params.allowReentrant ?? true;
280
297
  const held = HELD_LOCKS.get(normalizedSessionFile);
281
- if (held) {
298
+ if (allowReentrant && held) {
282
299
  held.count += 1;
283
300
  return {
284
301
  release: async () => {
@@ -310,8 +327,9 @@ export async function acquireSessionWriteLock(params) {
310
327
  }
311
328
  catch (err) {
312
329
  const code = err.code;
313
- if (code !== "EEXIST")
330
+ if (code !== "EEXIST") {
314
331
  throw err;
332
+ }
315
333
  const payload = await readLockPayload(lockPath);
316
334
  const inspected = inspectLockPayload(payload, staleMs, Date.now());
317
335
  if (inspected.stale) {
@@ -1,118 +1,79 @@
1
- import JSON5 from "json5";
2
- import { LEGACY_MANIFEST_KEY } from "../../compat/legacy-names.js";
3
1
  import { parseFrontmatterBlock } from "../../markdown/frontmatter.js";
4
- import { parseBooleanValue } from "../../utils/boolean.js";
2
+ import { getFrontmatterString, normalizeStringList, parsePoolbotManifestInstallBase, parseFrontmatterBool, resolvePoolbotManifestBlock, resolvePoolbotManifestInstall, resolvePoolbotManifestOs, resolvePoolbotManifestRequires, } from "../../shared/frontmatter.js";
5
3
  export function parseFrontmatter(content) {
6
4
  return parseFrontmatterBlock(content);
7
5
  }
8
- function normalizeStringList(input) {
9
- if (!input)
10
- return [];
11
- if (Array.isArray(input)) {
12
- return input.map((value) => String(value).trim()).filter(Boolean);
13
- }
14
- if (typeof input === "string") {
15
- return input
16
- .split(",")
17
- .map((value) => value.trim())
18
- .filter(Boolean);
19
- }
20
- return [];
21
- }
22
6
  function parseInstallSpec(input) {
23
- if (!input || typeof input !== "object")
24
- return undefined;
25
- const raw = input;
26
- const kindRaw = typeof raw.kind === "string" ? raw.kind : typeof raw.type === "string" ? raw.type : "";
27
- const kind = kindRaw.trim().toLowerCase();
28
- if (kind !== "brew" && kind !== "node" && kind !== "go" && kind !== "uv" && kind !== "download") {
7
+ const parsed = parsePoolbotManifestInstallBase(input, ["brew", "node", "go", "uv", "download"]);
8
+ if (!parsed) {
29
9
  return undefined;
30
10
  }
11
+ const { raw } = parsed;
31
12
  const spec = {
32
- kind: kind,
13
+ kind: parsed.kind,
33
14
  };
34
- if (typeof raw.id === "string")
35
- spec.id = raw.id;
36
- if (typeof raw.label === "string")
37
- spec.label = raw.label;
38
- const bins = normalizeStringList(raw.bins);
39
- if (bins.length > 0)
40
- spec.bins = bins;
15
+ if (parsed.id) {
16
+ spec.id = parsed.id;
17
+ }
18
+ if (parsed.label) {
19
+ spec.label = parsed.label;
20
+ }
21
+ if (parsed.bins) {
22
+ spec.bins = parsed.bins;
23
+ }
41
24
  const osList = normalizeStringList(raw.os);
42
- if (osList.length > 0)
25
+ if (osList.length > 0) {
43
26
  spec.os = osList;
44
- if (typeof raw.formula === "string")
27
+ }
28
+ if (typeof raw.formula === "string") {
45
29
  spec.formula = raw.formula;
46
- if (typeof raw.package === "string")
30
+ }
31
+ if (typeof raw.package === "string") {
47
32
  spec.package = raw.package;
48
- if (typeof raw.module === "string")
33
+ }
34
+ if (typeof raw.module === "string") {
49
35
  spec.module = raw.module;
50
- if (typeof raw.url === "string")
36
+ }
37
+ if (typeof raw.url === "string") {
51
38
  spec.url = raw.url;
52
- if (typeof raw.archive === "string")
39
+ }
40
+ if (typeof raw.archive === "string") {
53
41
  spec.archive = raw.archive;
54
- if (typeof raw.extract === "boolean")
42
+ }
43
+ if (typeof raw.extract === "boolean") {
55
44
  spec.extract = raw.extract;
56
- if (typeof raw.stripComponents === "number")
45
+ }
46
+ if (typeof raw.stripComponents === "number") {
57
47
  spec.stripComponents = raw.stripComponents;
58
- if (typeof raw.targetDir === "string")
48
+ }
49
+ if (typeof raw.targetDir === "string") {
59
50
  spec.targetDir = raw.targetDir;
51
+ }
60
52
  return spec;
61
53
  }
62
- function getFrontmatterValue(frontmatter, key) {
63
- const raw = frontmatter[key];
64
- return typeof raw === "string" ? raw : undefined;
65
- }
66
- function parseFrontmatterBool(value, fallback) {
67
- const parsed = parseBooleanValue(value);
68
- return parsed === undefined ? fallback : parsed;
69
- }
70
54
  export function resolvePoolbotMetadata(frontmatter) {
71
- const raw = getFrontmatterValue(frontmatter, "metadata");
72
- if (!raw)
73
- return undefined;
74
- try {
75
- const parsed = JSON5.parse(raw);
76
- if (!parsed || typeof parsed !== "object")
77
- return undefined;
78
- const metadataRaw = parsed.poolbot ?? parsed[LEGACY_MANIFEST_KEY];
79
- if (!metadataRaw || typeof metadataRaw !== "object")
80
- return undefined;
81
- const metadataObj = metadataRaw;
82
- const requiresRaw = typeof metadataObj.requires === "object" && metadataObj.requires !== null
83
- ? metadataObj.requires
84
- : undefined;
85
- const installRaw = Array.isArray(metadataObj.install) ? metadataObj.install : [];
86
- const install = installRaw
87
- .map((entry) => parseInstallSpec(entry))
88
- .filter((entry) => Boolean(entry));
89
- const osRaw = normalizeStringList(metadataObj.os);
90
- return {
91
- always: typeof metadataObj.always === "boolean" ? metadataObj.always : undefined,
92
- emoji: typeof metadataObj.emoji === "string" ? metadataObj.emoji : undefined,
93
- homepage: typeof metadataObj.homepage === "string" ? metadataObj.homepage : undefined,
94
- skillKey: typeof metadataObj.skillKey === "string" ? metadataObj.skillKey : undefined,
95
- primaryEnv: typeof metadataObj.primaryEnv === "string" ? metadataObj.primaryEnv : undefined,
96
- os: osRaw.length > 0 ? osRaw : undefined,
97
- requires: requiresRaw
98
- ? {
99
- bins: normalizeStringList(requiresRaw.bins),
100
- anyBins: normalizeStringList(requiresRaw.anyBins),
101
- env: normalizeStringList(requiresRaw.env),
102
- config: normalizeStringList(requiresRaw.config),
103
- }
104
- : undefined,
105
- install: install.length > 0 ? install : undefined,
106
- };
107
- }
108
- catch {
55
+ const metadataObj = resolvePoolbotManifestBlock({ frontmatter });
56
+ if (!metadataObj) {
109
57
  return undefined;
110
58
  }
59
+ const requires = resolvePoolbotManifestRequires(metadataObj);
60
+ const install = resolvePoolbotManifestInstall(metadataObj, parseInstallSpec);
61
+ const osRaw = resolvePoolbotManifestOs(metadataObj);
62
+ return {
63
+ always: typeof metadataObj.always === "boolean" ? metadataObj.always : undefined,
64
+ emoji: typeof metadataObj.emoji === "string" ? metadataObj.emoji : undefined,
65
+ homepage: typeof metadataObj.homepage === "string" ? metadataObj.homepage : undefined,
66
+ skillKey: typeof metadataObj.skillKey === "string" ? metadataObj.skillKey : undefined,
67
+ primaryEnv: typeof metadataObj.primaryEnv === "string" ? metadataObj.primaryEnv : undefined,
68
+ os: osRaw.length > 0 ? osRaw : undefined,
69
+ requires: requires,
70
+ install: install.length > 0 ? install : undefined,
71
+ };
111
72
  }
112
73
  export function resolveSkillInvocationPolicy(frontmatter) {
113
74
  return {
114
- userInvocable: parseFrontmatterBool(getFrontmatterValue(frontmatter, "user-invocable"), true),
115
- disableModelInvocation: parseFrontmatterBool(getFrontmatterValue(frontmatter, "disable-model-invocation"), false),
75
+ userInvocable: parseFrontmatterBool(getFrontmatterString(frontmatter, "user-invocable"), true),
76
+ disableModelInvocation: parseFrontmatterBool(getFrontmatterString(frontmatter, "disable-model-invocation"), false),
116
77
  };
117
78
  }
118
79
  export function resolveSkillKey(skill, entry) {