@poolzin/pool-bot 2026.2.17 → 2026.2.18

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 (469) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/dist/agents/agent-scope.js +4 -0
  3. package/dist/agents/announce-idempotency.js +14 -0
  4. package/dist/agents/auth-profiles.resolve-auth-profile-order.fixtures.js +23 -0
  5. package/dist/agents/bash-tools.exec-runtime.js +438 -0
  6. package/dist/agents/bash-tools.shared.js +6 -0
  7. package/dist/agents/cli-runner/reliability.js +61 -0
  8. package/dist/agents/cli-watchdog-defaults.js +11 -0
  9. package/dist/agents/command-poll-backoff.js +63 -0
  10. package/dist/agents/current-time.js +16 -0
  11. package/dist/agents/model-alias-lines.js +18 -0
  12. package/dist/agents/model-auth-label.js +61 -0
  13. package/dist/agents/models-config.e2e-harness.js +115 -0
  14. package/dist/agents/ollama-stream.js +11 -3
  15. package/dist/agents/openclaw-tools.js +135 -0
  16. package/dist/agents/pi-auth-json.js +118 -0
  17. package/dist/agents/pi-embedded-runner/run.overflow-compaction.mocks.shared.js +147 -0
  18. package/dist/agents/pi-embedded-subscribe.e2e-harness.js +90 -0
  19. package/dist/agents/pi-embedded-subscribe.handlers.compaction.js +63 -0
  20. package/dist/agents/pi-embedded-subscribe.handlers.tools.media.test-helpers.js +30 -0
  21. package/dist/agents/pi-extensions/session-manager-runtime-registry.js +23 -0
  22. package/dist/agents/pi-tools.js +2 -0
  23. package/dist/agents/queued-file-writer.js +22 -0
  24. package/dist/agents/sandbox/docker.js +133 -40
  25. package/dist/agents/sandbox/fs-bridge.js +146 -0
  26. package/dist/agents/sandbox/fs-paths.js +205 -0
  27. package/dist/agents/sandbox/hash.js +4 -0
  28. package/dist/agents/sandbox-paths.js +3 -0
  29. package/dist/agents/session-dirs.js +20 -0
  30. package/dist/agents/skills/filter.js +24 -0
  31. package/dist/agents/skills/tools-dir.js +9 -0
  32. package/dist/agents/skills-install-download.js +290 -0
  33. package/dist/agents/skills-install-output.js +30 -0
  34. package/dist/agents/skills-install.download-test-utils.js +36 -0
  35. package/dist/agents/skills.e2e-test-helpers.js +13 -0
  36. package/dist/agents/subagent-announce-queue.js +59 -15
  37. package/dist/agents/subagent-depth.js +137 -0
  38. package/dist/agents/subagent-registry.js +448 -96
  39. package/dist/agents/subagent-spawn.js +262 -0
  40. package/dist/agents/test-helpers/fast-tool-stubs.js +18 -0
  41. package/dist/agents/test-helpers/host-sandbox-fs-bridge.js +74 -0
  42. package/dist/agents/tool-display-common.js +782 -0
  43. package/dist/agents/tools/image-tool.js +1 -1
  44. package/dist/agents/tools/sessions-access.js +178 -0
  45. package/dist/agents/tools/sessions-resolution.js +206 -0
  46. package/dist/agents/tools/subagents-tool.js +616 -0
  47. package/dist/agents/workspace-dir.js +18 -0
  48. package/dist/agents/workspace-dirs.js +14 -0
  49. package/dist/agents/workspace.js +70 -0
  50. package/dist/auto-reply/heartbeat-reply-payload.js +18 -0
  51. package/dist/auto-reply/reply/commands-export-session.js +163 -0
  52. package/dist/auto-reply/reply/commands-mesh.js +245 -0
  53. package/dist/auto-reply/reply/commands-setunset.js +28 -0
  54. package/dist/auto-reply/reply/commands-slash-parse.js +31 -0
  55. package/dist/auto-reply/reply/commands-system-prompt.js +117 -0
  56. package/dist/auto-reply/reply/directive-handling.levels.js +17 -0
  57. package/dist/auto-reply/reply/directive-handling.params.js +1 -0
  58. package/dist/auto-reply/reply/directive-parsing.js +36 -0
  59. package/dist/auto-reply/reply/dispatcher-registry.js +43 -0
  60. package/dist/auto-reply/reply/elevated-unavailable.js +20 -0
  61. package/dist/auto-reply/reply/reply-delivery.js +92 -0
  62. package/dist/auto-reply/reply/session-reset-prompt.js +1 -0
  63. package/dist/auto-reply/reply/session-run-accounting.js +33 -0
  64. package/dist/auto-reply/reply.directive.directive-behavior.e2e-harness.js +115 -0
  65. package/dist/auto-reply/reply.directive.directive-behavior.e2e-mocks.js +12 -0
  66. package/dist/browser/bridge-auth-registry.js +26 -0
  67. package/dist/browser/client-actions-url.js +10 -0
  68. package/dist/browser/control-auth.js +73 -0
  69. package/dist/browser/csrf.js +64 -0
  70. package/dist/browser/http-auth.js +52 -0
  71. package/dist/browser/paths.js +37 -0
  72. package/dist/browser/proxy-files.js +32 -0
  73. package/dist/browser/pw-ai-state.js +7 -0
  74. package/dist/browser/resolved-config-refresh.js +42 -0
  75. package/dist/browser/routes/path-output.js +1 -0
  76. package/dist/browser/server-context.chrome-test-harness.js +20 -0
  77. package/dist/browser/server-middleware.js +31 -0
  78. package/dist/browser/test-port.js +16 -0
  79. package/dist/build-info.json +3 -3
  80. package/dist/canvas-host/file-resolver.js +43 -0
  81. package/dist/channels/account-summary.js +19 -0
  82. package/dist/channels/draft-stream-loop.js +77 -0
  83. package/dist/channels/plugins/account-helpers.js +26 -0
  84. package/dist/channels/telegram/allow-from.js +10 -0
  85. package/dist/cli/browser-cli-resize.js +22 -0
  86. package/dist/cli/browser-cli-shared.js +8 -0
  87. package/dist/cli/clawbot-cli.js +5 -0
  88. package/dist/cli/completion-cli.js +566 -0
  89. package/dist/cli/config-cli.js +63 -5
  90. package/dist/cli/daemon-cli/lifecycle-core.js +256 -0
  91. package/dist/cli/daemon-cli/register-service-commands.js +60 -0
  92. package/dist/cli/daemon-cli-compat.js +80 -0
  93. package/dist/cli/nodes-cli/pairing-render.js +26 -0
  94. package/dist/cli/program/action-reparse.js +17 -0
  95. package/dist/cli/program/command-registry.js +17 -0
  96. package/dist/cli/program/program-context.js +8 -0
  97. package/dist/cli/program/register.subclis.js +7 -0
  98. package/dist/cli/program/routes.js +233 -0
  99. package/dist/cli/qr-cli.js +132 -0
  100. package/dist/cli/requirements-test-fixtures.js +17 -0
  101. package/dist/cli/respawn-policy.js +4 -0
  102. package/dist/cli/shared/parse-port.js +18 -0
  103. package/dist/cli/skills-cli.format.js +241 -0
  104. package/dist/cli/update-cli/progress.js +121 -0
  105. package/dist/cli/update-cli/restart-helper.js +108 -0
  106. package/dist/cli/update-cli/shared.js +196 -0
  107. package/dist/cli/update-cli/status.js +97 -0
  108. package/dist/cli/update-cli/suppress-deprecations.js +17 -0
  109. package/dist/cli/update-cli/update-command.js +506 -0
  110. package/dist/cli/update-cli/wizard.js +130 -0
  111. package/dist/cli/update-cli.js +3 -9
  112. package/dist/cli/windows-argv.js +69 -0
  113. package/dist/commands/auth-choice-legacy.js +20 -0
  114. package/dist/commands/auth-choice.apply-helpers.js +8 -0
  115. package/dist/commands/channel-test-helpers.js +19 -0
  116. package/dist/commands/cleanup-plan.js +10 -0
  117. package/dist/commands/cleanup-utils.js +7 -0
  118. package/dist/commands/config-validation.js +15 -0
  119. package/dist/commands/doctor-completion.js +112 -0
  120. package/dist/commands/doctor-memory-search.js +119 -0
  121. package/dist/commands/doctor-session-locks.js +73 -0
  122. package/dist/commands/doctor.e2e-harness.js +364 -0
  123. package/dist/commands/gateway-presence.js +19 -0
  124. package/dist/commands/model-default.js +35 -0
  125. package/dist/commands/models/fallbacks-shared.js +102 -0
  126. package/dist/commands/models/shared.js +24 -0
  127. package/dist/commands/onboard-auth.config-gateways.js +64 -0
  128. package/dist/commands/onboard-auth.config-litellm.js +45 -0
  129. package/dist/commands/onboard-auth.config-shared.js +116 -0
  130. package/dist/commands/onboard-config.js +16 -0
  131. package/dist/commands/onboard-non-interactive.test-helpers.js +31 -0
  132. package/dist/commands/onboard-provider-auth-flags.js +136 -0
  133. package/dist/commands/openai-codex-oauth.js +40 -0
  134. package/dist/commands/test-runtime-config-helpers.js +21 -0
  135. package/dist/commands/test-wizard-helpers.js +68 -0
  136. package/dist/commands/vllm-setup.js +66 -0
  137. package/dist/compat/legacy-names.js +2 -0
  138. package/dist/config/backup-rotation.js +19 -0
  139. package/dist/config/env-preserve.js +122 -0
  140. package/dist/config/includes-scan.js +78 -0
  141. package/dist/config/plugins-allowlist.js +13 -0
  142. package/dist/config/schema.help.js +256 -0
  143. package/dist/config/schema.hints.js +189 -0
  144. package/dist/config/schema.irc.js +20 -0
  145. package/dist/config/schema.labels.js +317 -0
  146. package/dist/config/sessions/delivery-info.js +40 -0
  147. package/dist/config/types.irc.js +1 -0
  148. package/dist/config/zod-schema.agent-model.js +10 -0
  149. package/dist/config/zod-schema.allowdeny.js +35 -0
  150. package/dist/config/zod-schema.sensitive.js +4 -0
  151. package/dist/control-ui/assets/index-HRr1grwl.js.map +1 -1
  152. package/dist/cron/isolated-agent/skills-snapshot.js +26 -0
  153. package/dist/cron/isolated-agent/subagent-followup.js +127 -0
  154. package/dist/cron/isolated-agent.mocks.js +12 -0
  155. package/dist/cron/isolated-agent.test-setup.js +22 -0
  156. package/dist/cron/legacy-delivery.js +43 -0
  157. package/dist/cron/webhook-url.js +22 -0
  158. package/dist/daemon/arg-split.js +40 -0
  159. package/dist/daemon/exec-file.js +23 -0
  160. package/dist/daemon/output.js +6 -0
  161. package/dist/daemon/runtime-format.js +31 -0
  162. package/dist/daemon/schtasks-exec.js +4 -0
  163. package/dist/daemon/service-audit.js +22 -0
  164. package/dist/discord/client.js +41 -0
  165. package/dist/discord/components-registry.js +57 -0
  166. package/dist/discord/components.js +816 -0
  167. package/dist/discord/guilds.js +12 -0
  168. package/dist/discord/monitor/gateway-plugin.js +48 -0
  169. package/dist/discord/monitor/presence.js +30 -0
  170. package/dist/discord/send.components.js +115 -0
  171. package/dist/discord/send.shared.js +4 -0
  172. package/dist/discord/ui.js +26 -0
  173. package/dist/discord/voice-message.js +254 -0
  174. package/dist/gateway/agent-event-assistant-text.js +5 -0
  175. package/dist/gateway/agent-prompt.js +33 -0
  176. package/dist/gateway/auth-rate-limit.js +136 -0
  177. package/dist/gateway/channel-health-monitor.js +114 -0
  178. package/dist/gateway/control-ui-contract.js +1 -0
  179. package/dist/gateway/control-ui-csp.js +15 -0
  180. package/dist/gateway/gateway-config-prompts.shared.js +25 -0
  181. package/dist/gateway/http-auth-helpers.js +18 -0
  182. package/dist/gateway/http-common.js +18 -0
  183. package/dist/gateway/http-endpoint-helpers.js +27 -0
  184. package/dist/gateway/node-invoke-sanitize.js +11 -0
  185. package/dist/gateway/node-invoke-system-run-approval.js +205 -0
  186. package/dist/gateway/probe-auth.js +21 -0
  187. package/dist/gateway/protocol/index.js +7 -2
  188. package/dist/gateway/protocol/schema/mesh.js +54 -0
  189. package/dist/gateway/protocol/schema/protocol-schemas.js +7 -0
  190. package/dist/gateway/protocol/schema.js +1 -0
  191. package/dist/gateway/server/ws-connection/auth-messages.js +54 -0
  192. package/dist/gateway/server-channels.js +11 -0
  193. package/dist/gateway/server-methods/attachment-normalize.js +16 -0
  194. package/dist/gateway/server-methods/base-hash.js +8 -0
  195. package/dist/gateway/server-methods/mesh.js +700 -0
  196. package/dist/gateway/server-methods/nodes.handlers.invoke-result.js +55 -0
  197. package/dist/gateway/server-methods/restart-request.js +13 -0
  198. package/dist/gateway/server-methods/validation.js +8 -0
  199. package/dist/gateway/server.agent.gateway-server-agent.mocks.js +35 -0
  200. package/dist/gateway/server.e2e-registry-helpers.js +1 -0
  201. package/dist/gateway/server.e2e-ws-harness.js +20 -0
  202. package/dist/gateway/test-helpers.js +2 -0
  203. package/dist/gateway/test-helpers.server.js +3 -1
  204. package/dist/gateway/test-http-response.js +12 -0
  205. package/dist/gateway/test-openai-responses-model.js +20 -0
  206. package/dist/gateway/test-temp-config.js +30 -0
  207. package/dist/gateway/test-with-server.js +32 -0
  208. package/dist/hooks/bundled/bootstrap-extra-files/handler.js +46 -0
  209. package/dist/imessage/monitor/abort-handler.js +23 -0
  210. package/dist/imessage/monitor/inbound-processing.js +346 -0
  211. package/dist/imessage/monitor/parse-notification.js +64 -0
  212. package/dist/imessage/target-parsing-helpers.js +92 -0
  213. package/dist/infra/archive.js +244 -20
  214. package/dist/infra/detect-package-manager.js +26 -0
  215. package/dist/infra/exec-approvals-allowlist.js +257 -0
  216. package/dist/infra/exec-approvals-analysis.js +770 -0
  217. package/dist/infra/exec-approvals.js +13 -0
  218. package/dist/infra/file-lock.js +1 -0
  219. package/dist/infra/gemini-auth.js +39 -0
  220. package/dist/infra/heartbeat-active-hours.js +85 -0
  221. package/dist/infra/heartbeat-events-filter.js +50 -0
  222. package/dist/infra/heartbeat-runner.test-utils.js +39 -0
  223. package/dist/infra/http-body.js +265 -0
  224. package/dist/infra/install-package-dir.js +50 -0
  225. package/dist/infra/install-safe-path.js +49 -0
  226. package/dist/infra/json-files.js +49 -0
  227. package/dist/infra/jsonl-socket.js +52 -0
  228. package/dist/infra/map-size.js +14 -0
  229. package/dist/infra/net/hostname.js +7 -0
  230. package/dist/infra/npm-registry-spec.js +39 -0
  231. package/dist/infra/openclaw-root.js +109 -0
  232. package/dist/infra/outbound/delivery-queue.js +214 -0
  233. package/dist/infra/outbound/identity.js +23 -0
  234. package/dist/infra/outbound/message-action-params.js +307 -0
  235. package/dist/infra/outbound/tool-payload.js +21 -0
  236. package/dist/infra/package-json.js +23 -0
  237. package/dist/infra/pairing-files.js +19 -0
  238. package/dist/infra/pairing-token.js +9 -0
  239. package/dist/infra/path-prepend.js +51 -0
  240. package/dist/infra/process-respawn.js +49 -0
  241. package/dist/infra/runtime-status.js +16 -0
  242. package/dist/infra/session-cost-usage.types.js +1 -0
  243. package/dist/infra/session-maintenance-warning.js +89 -0
  244. package/dist/infra/system-run-command.js +78 -0
  245. package/dist/infra/tmp-openclaw-dir.js +81 -0
  246. package/dist/infra/tmp-poolbot-dir.js +2 -0
  247. package/dist/infra/update-channels.js +19 -0
  248. package/dist/line/actions.js +45 -0
  249. package/dist/line/channel-access-token.js +9 -0
  250. package/dist/line/flex-templates/basic-cards.js +332 -0
  251. package/dist/line/flex-templates/common.js +18 -0
  252. package/dist/line/flex-templates/media-control-cards.js +453 -0
  253. package/dist/line/flex-templates/message.js +10 -0
  254. package/dist/line/flex-templates/schedule-cards.js +399 -0
  255. package/dist/line/flex-templates/types.js +1 -0
  256. package/dist/line/webhook-node.js +100 -0
  257. package/dist/line/webhook-utils.js +11 -0
  258. package/dist/logging/timestamps.js +14 -0
  259. package/dist/markdown/whatsapp.js +62 -0
  260. package/dist/media/base64.js +34 -0
  261. package/dist/media/local-roots.js +32 -0
  262. package/dist/media/outbound-attachment.js +10 -0
  263. package/dist/media/read-response-with-limit.js +41 -0
  264. package/dist/media/sniff-mime-from-base64.js +19 -0
  265. package/dist/media-understanding/audio-preflight.js +67 -0
  266. package/dist/media-understanding/fs.js +13 -0
  267. package/dist/media-understanding/output-extract.js +26 -0
  268. package/dist/media-understanding/providers/audio.test-helpers.js +34 -0
  269. package/dist/media-understanding/providers/google/inline-data.js +64 -0
  270. package/dist/media-understanding/providers/shared.js +7 -0
  271. package/dist/media-understanding/runner.entries.js +459 -0
  272. package/dist/memory/batch-error-utils.js +11 -0
  273. package/dist/memory/batch-http.js +27 -0
  274. package/dist/memory/batch-output.js +29 -0
  275. package/dist/memory/batch-runner.js +22 -0
  276. package/dist/memory/batch-upload.js +23 -0
  277. package/dist/memory/batch-utils.js +26 -0
  278. package/dist/memory/embeddings-debug.js +11 -0
  279. package/dist/memory/embeddings-remote-client.js +22 -0
  280. package/dist/memory/embeddings-remote-fetch.js +14 -0
  281. package/dist/memory/manager-embedding-ops.js +616 -0
  282. package/dist/memory/manager-sync-ops.js +953 -0
  283. package/dist/memory/qmd-manager.js +1061 -0
  284. package/dist/memory/qmd-query-parser.js +107 -0
  285. package/dist/memory/qmd-scope.js +93 -0
  286. package/dist/memory/search-manager.js +0 -1
  287. package/dist/memory/sync-index.js +21 -0
  288. package/dist/memory/sync-progress.js +22 -0
  289. package/dist/memory/sync-stale.js +30 -0
  290. package/dist/memory/test-embeddings-mock.js +16 -0
  291. package/dist/memory/test-manager-helpers.js +14 -0
  292. package/dist/memory/test-runtime-mocks.js +11 -0
  293. package/dist/node-host/invoke-browser.js +177 -0
  294. package/dist/node-host/invoke.js +685 -0
  295. package/dist/pairing/setup-code.js +285 -0
  296. package/dist/plugin-sdk/account-id.js +1 -0
  297. package/dist/plugin-sdk/agent-media-payload.js +13 -0
  298. package/dist/plugin-sdk/allow-from.js +47 -0
  299. package/dist/plugin-sdk/command-auth.js +23 -0
  300. package/dist/plugin-sdk/config-paths.js +9 -0
  301. package/dist/plugin-sdk/file-lock.js +116 -0
  302. package/dist/plugin-sdk/json-store.js +31 -0
  303. package/dist/plugin-sdk/onboarding.js +28 -0
  304. package/dist/plugin-sdk/provider-auth-result.js +29 -0
  305. package/dist/plugin-sdk/slack-message-actions.js +133 -0
  306. package/dist/plugin-sdk/status-helpers.js +35 -0
  307. package/dist/plugin-sdk/text-chunking.js +31 -0
  308. package/dist/plugin-sdk/tool-send.js +12 -0
  309. package/dist/plugin-sdk/webhook-path.js +27 -0
  310. package/dist/plugin-sdk/webhook-targets.js +34 -0
  311. package/dist/plugins/hooks.test-helpers.js +21 -0
  312. package/dist/plugins/uninstall.js +171 -0
  313. package/dist/process/supervisor/adapters/child.js +143 -0
  314. package/dist/process/supervisor/adapters/env.js +13 -0
  315. package/dist/process/supervisor/adapters/pty.js +148 -0
  316. package/dist/process/supervisor/index.js +10 -0
  317. package/dist/process/supervisor/registry.js +117 -0
  318. package/dist/process/supervisor/supervisor.js +244 -0
  319. package/dist/process/supervisor/types.js +1 -0
  320. package/dist/providers/google-shared.test-helpers.js +75 -0
  321. package/dist/security/audit-channel.js +419 -0
  322. package/dist/security/audit-tool-policy.js +1 -0
  323. package/dist/security/scan-paths.js +12 -0
  324. package/dist/sessions/input-provenance.js +55 -0
  325. package/dist/sessions/session-key-utils.js +7 -0
  326. package/dist/shared/chat-content.js +31 -0
  327. package/dist/shared/chat-envelope.js +45 -0
  328. package/dist/shared/config-eval.js +117 -0
  329. package/dist/shared/device-auth.js +16 -0
  330. package/dist/shared/entry-metadata.js +9 -0
  331. package/dist/shared/entry-status.js +25 -0
  332. package/dist/shared/frontmatter.js +98 -0
  333. package/dist/shared/model-param-b.js +19 -0
  334. package/dist/shared/net/ipv4.js +17 -0
  335. package/dist/shared/node-match.js +53 -0
  336. package/dist/shared/requirements.js +128 -0
  337. package/dist/shared/subagents-format.js +84 -0
  338. package/dist/shared/usage-aggregates.js +28 -0
  339. package/dist/signal/monitor/mentions.js +45 -0
  340. package/dist/signal/rpc-context.js +19 -0
  341. package/dist/slack/blocks-fallback.js +76 -0
  342. package/dist/slack/blocks-input.js +40 -0
  343. package/dist/slack/draft-stream.js +106 -0
  344. package/dist/slack/message-actions.js +51 -0
  345. package/dist/slack/modal-metadata.js +32 -0
  346. package/dist/slack/monitor/events/interactions.js +462 -0
  347. package/dist/slack/monitor/room-context.js +17 -0
  348. package/dist/slack/stream-mode.js +41 -0
  349. package/dist/telegram/bot-native-command-menu.js +64 -0
  350. package/dist/telegram/bot.media.e2e-harness.js +81 -0
  351. package/dist/telegram/button-types.js +1 -0
  352. package/dist/telegram/group-access.js +65 -0
  353. package/dist/telegram/outbound-params.js +21 -0
  354. package/dist/telegram/poll-vote-cache.js +21 -0
  355. package/dist/terminal/health-style.js +36 -0
  356. package/dist/test-utils/chunk-test-helpers.js +21 -0
  357. package/dist/test-utils/env.js +72 -0
  358. package/dist/test-utils/exec-assertions.js +12 -0
  359. package/dist/test-utils/imessage-test-plugin.js +54 -0
  360. package/dist/test-utils/mock-http-response.js +17 -0
  361. package/dist/test-utils/vitest-mock-fn.js +1 -0
  362. package/dist/tts/tts-core.js +550 -0
  363. package/dist/utils/chunk-items.js +10 -0
  364. package/dist/utils/reaction-level.js +52 -0
  365. package/dist/utils/safe-json.js +22 -0
  366. package/dist/utils/with-timeout.js +14 -0
  367. package/dist/web/media.js +17 -5
  368. package/dist/whatsapp/resolve-outbound-target.js +42 -0
  369. package/dist/wizard/onboarding.completion.js +74 -0
  370. package/extensions/bluebubbles/src/account-resolve.ts +29 -0
  371. package/extensions/bluebubbles/src/monitor-normalize.ts +796 -0
  372. package/extensions/bluebubbles/src/monitor-processing.ts +1007 -0
  373. package/extensions/bluebubbles/src/monitor-reply-cache.ts +185 -0
  374. package/extensions/bluebubbles/src/monitor-shared.ts +51 -0
  375. package/extensions/bluebubbles/src/multipart.ts +32 -0
  376. package/extensions/bluebubbles/src/send-helpers.ts +53 -0
  377. package/extensions/bluebubbles/src/test-harness.ts +50 -0
  378. package/extensions/bluebubbles/src/test-mocks.ts +11 -0
  379. package/extensions/device-pair/index.ts +554 -0
  380. package/extensions/discord/src/channel.js +366 -0
  381. package/extensions/discord/src/runtime.js +10 -0
  382. package/extensions/feishu/index.ts +63 -0
  383. package/extensions/feishu/src/accounts.ts +114 -0
  384. package/extensions/feishu/src/bitable.ts +739 -0
  385. package/extensions/feishu/src/bot.ts +965 -0
  386. package/extensions/feishu/src/channel.ts +351 -0
  387. package/extensions/feishu/src/client.ts +118 -0
  388. package/extensions/feishu/src/config-schema.ts +206 -0
  389. package/extensions/feishu/src/dedup.ts +33 -0
  390. package/extensions/feishu/src/directory.ts +177 -0
  391. package/extensions/feishu/src/doc-schema.ts +47 -0
  392. package/extensions/feishu/src/docx.ts +536 -0
  393. package/extensions/feishu/src/drive-schema.ts +46 -0
  394. package/extensions/feishu/src/drive.ts +227 -0
  395. package/extensions/feishu/src/dynamic-agent.ts +131 -0
  396. package/extensions/feishu/src/media.ts +449 -0
  397. package/extensions/feishu/src/mention.ts +126 -0
  398. package/extensions/feishu/src/monitor.ts +330 -0
  399. package/extensions/feishu/src/onboarding.ts +359 -0
  400. package/extensions/feishu/src/outbound.ts +55 -0
  401. package/extensions/feishu/src/perm-schema.ts +52 -0
  402. package/extensions/feishu/src/perm.ts +173 -0
  403. package/extensions/feishu/src/policy.ts +84 -0
  404. package/extensions/feishu/src/probe.ts +44 -0
  405. package/extensions/feishu/src/reactions.ts +160 -0
  406. package/extensions/feishu/src/reply-dispatcher.ts +239 -0
  407. package/extensions/feishu/src/runtime.ts +14 -0
  408. package/extensions/feishu/src/send-result.ts +29 -0
  409. package/extensions/feishu/src/send.ts +335 -0
  410. package/extensions/feishu/src/streaming-card.ts +223 -0
  411. package/extensions/feishu/src/targets.ts +78 -0
  412. package/extensions/feishu/src/tools-config.ts +21 -0
  413. package/extensions/feishu/src/types.ts +81 -0
  414. package/extensions/feishu/src/typing.ts +80 -0
  415. package/extensions/feishu/src/wiki-schema.ts +55 -0
  416. package/extensions/feishu/src/wiki.ts +232 -0
  417. package/extensions/imessage/src/channel.js +253 -0
  418. package/extensions/imessage/src/runtime.js +10 -0
  419. package/extensions/irc/index.ts +17 -0
  420. package/extensions/irc/src/accounts.ts +268 -0
  421. package/extensions/irc/src/channel.ts +367 -0
  422. package/extensions/irc/src/client.ts +439 -0
  423. package/extensions/irc/src/config-schema.ts +97 -0
  424. package/extensions/irc/src/connect-options.ts +30 -0
  425. package/extensions/irc/src/control-chars.ts +22 -0
  426. package/extensions/irc/src/inbound.ts +334 -0
  427. package/extensions/irc/src/monitor.ts +147 -0
  428. package/extensions/irc/src/normalize.ts +117 -0
  429. package/extensions/irc/src/onboarding.ts +479 -0
  430. package/extensions/irc/src/policy.ts +157 -0
  431. package/extensions/irc/src/probe.ts +53 -0
  432. package/extensions/irc/src/protocol.ts +169 -0
  433. package/extensions/irc/src/runtime.ts +14 -0
  434. package/extensions/irc/src/send.ts +88 -0
  435. package/extensions/irc/src/types.ts +93 -0
  436. package/extensions/matrix/src/matrix/client-bootstrap.ts +39 -0
  437. package/extensions/mattermost/src/mattermost/monitor-onchar.ts +25 -0
  438. package/extensions/mattermost/src/mattermost/monitor-websocket.ts +221 -0
  439. package/extensions/mattermost/src/mattermost/reactions.ts +130 -0
  440. package/extensions/mattermost/src/mattermost/reconnect.ts +103 -0
  441. package/extensions/minimax-portal-auth/index.ts +161 -0
  442. package/extensions/minimax-portal-auth/oauth.ts +247 -0
  443. package/extensions/msteams/src/file-lock.ts +1 -0
  444. package/extensions/msteams/src/graph.ts +92 -0
  445. package/extensions/msteams/src/mentions.ts +114 -0
  446. package/extensions/msteams/src/test-runtime.ts +16 -0
  447. package/extensions/openai-codex-auth/index.ts +177 -0
  448. package/extensions/phone-control/index.ts +421 -0
  449. package/extensions/shared/resolve-target-test-helpers.ts +66 -0
  450. package/extensions/signal/src/channel.js +273 -0
  451. package/extensions/signal/src/runtime.js +10 -0
  452. package/extensions/slack/src/channel.js +489 -0
  453. package/extensions/slack/src/runtime.js +10 -0
  454. package/extensions/talk-voice/index.ts +150 -0
  455. package/extensions/telegram/src/channel.js +424 -0
  456. package/extensions/telegram/src/runtime.js +10 -0
  457. package/extensions/thread-ownership/index.ts +133 -0
  458. package/extensions/tlon/src/account-fields.ts +25 -0
  459. package/extensions/tlon/src/urbit/base-url.ts +57 -0
  460. package/extensions/tlon/src/urbit/channel-client.ts +157 -0
  461. package/extensions/tlon/src/urbit/channel-ops.ts +164 -0
  462. package/extensions/tlon/src/urbit/context.ts +47 -0
  463. package/extensions/tlon/src/urbit/errors.ts +51 -0
  464. package/extensions/tlon/src/urbit/fetch.ts +39 -0
  465. package/extensions/twitch/src/test-fixtures.ts +30 -0
  466. package/extensions/voice-call/src/allowlist.ts +19 -0
  467. package/extensions/whatsapp/src/channel.js +429 -0
  468. package/extensions/whatsapp/src/runtime.js +10 -0
  469. package/package.json +1 -1
@@ -0,0 +1,133 @@
1
+ import { readNumberParam, readStringParam } from "../agents/tools/common.js";
2
+ import { parseSlackBlocksInput } from "../slack/blocks-input.js";
3
+ function readSlackBlocksParam(actionParams) {
4
+ return parseSlackBlocksInput(actionParams.blocks);
5
+ }
6
+ export async function handleSlackMessageAction(params) {
7
+ const { providerId, ctx, invoke, normalizeChannelId, includeReadThreadId = false } = params;
8
+ const { action, cfg, params: actionParams } = ctx;
9
+ const accountId = ctx.accountId ?? undefined;
10
+ const resolveChannelId = () => {
11
+ const channelId = readStringParam(actionParams, "channelId") ??
12
+ readStringParam(actionParams, "to", { required: true });
13
+ return normalizeChannelId ? normalizeChannelId(channelId) : channelId;
14
+ };
15
+ if (action === "send") {
16
+ const to = readStringParam(actionParams, "to", { required: true });
17
+ const content = readStringParam(actionParams, "message", {
18
+ required: false,
19
+ allowEmpty: true,
20
+ });
21
+ const mediaUrl = readStringParam(actionParams, "media", { trim: false });
22
+ const blocks = readSlackBlocksParam(actionParams);
23
+ if (!content && !mediaUrl && !blocks) {
24
+ throw new Error("Slack send requires message, blocks, or media.");
25
+ }
26
+ if (mediaUrl && blocks) {
27
+ throw new Error("Slack send does not support blocks with media.");
28
+ }
29
+ const threadId = readStringParam(actionParams, "threadId");
30
+ const replyTo = readStringParam(actionParams, "replyTo");
31
+ return await invoke({
32
+ action: "sendMessage",
33
+ to,
34
+ content: content ?? "",
35
+ mediaUrl: mediaUrl ?? undefined,
36
+ blocks,
37
+ accountId,
38
+ threadTs: threadId ?? replyTo ?? undefined,
39
+ }, cfg, ctx.toolContext);
40
+ }
41
+ if (action === "react") {
42
+ const messageId = readStringParam(actionParams, "messageId", {
43
+ required: true,
44
+ });
45
+ const emoji = readStringParam(actionParams, "emoji", { allowEmpty: true });
46
+ const remove = typeof actionParams.remove === "boolean" ? actionParams.remove : undefined;
47
+ return await invoke({
48
+ action: "react",
49
+ channelId: resolveChannelId(),
50
+ messageId,
51
+ emoji,
52
+ remove,
53
+ accountId,
54
+ }, cfg);
55
+ }
56
+ if (action === "reactions") {
57
+ const messageId = readStringParam(actionParams, "messageId", {
58
+ required: true,
59
+ });
60
+ const limit = readNumberParam(actionParams, "limit", { integer: true });
61
+ return await invoke({
62
+ action: "reactions",
63
+ channelId: resolveChannelId(),
64
+ messageId,
65
+ limit,
66
+ accountId,
67
+ }, cfg);
68
+ }
69
+ if (action === "read") {
70
+ const limit = readNumberParam(actionParams, "limit", { integer: true });
71
+ const readAction = {
72
+ action: "readMessages",
73
+ channelId: resolveChannelId(),
74
+ limit,
75
+ before: readStringParam(actionParams, "before"),
76
+ after: readStringParam(actionParams, "after"),
77
+ accountId,
78
+ };
79
+ if (includeReadThreadId) {
80
+ readAction.threadId = readStringParam(actionParams, "threadId");
81
+ }
82
+ return await invoke(readAction, cfg);
83
+ }
84
+ if (action === "edit") {
85
+ const messageId = readStringParam(actionParams, "messageId", {
86
+ required: true,
87
+ });
88
+ const content = readStringParam(actionParams, "message", { allowEmpty: true });
89
+ const blocks = readSlackBlocksParam(actionParams);
90
+ if (!content && !blocks) {
91
+ throw new Error("Slack edit requires message or blocks.");
92
+ }
93
+ return await invoke({
94
+ action: "editMessage",
95
+ channelId: resolveChannelId(),
96
+ messageId,
97
+ content: content ?? "",
98
+ blocks,
99
+ accountId,
100
+ }, cfg);
101
+ }
102
+ if (action === "delete") {
103
+ const messageId = readStringParam(actionParams, "messageId", {
104
+ required: true,
105
+ });
106
+ return await invoke({
107
+ action: "deleteMessage",
108
+ channelId: resolveChannelId(),
109
+ messageId,
110
+ accountId,
111
+ }, cfg);
112
+ }
113
+ if (action === "pin" || action === "unpin" || action === "list-pins") {
114
+ const messageId = action === "list-pins"
115
+ ? undefined
116
+ : readStringParam(actionParams, "messageId", { required: true });
117
+ return await invoke({
118
+ action: action === "pin" ? "pinMessage" : action === "unpin" ? "unpinMessage" : "listPins",
119
+ channelId: resolveChannelId(),
120
+ messageId,
121
+ accountId,
122
+ }, cfg);
123
+ }
124
+ if (action === "member-info") {
125
+ const userId = readStringParam(actionParams, "userId", { required: true });
126
+ return await invoke({ action: "memberInfo", userId, accountId }, cfg);
127
+ }
128
+ if (action === "emoji-list") {
129
+ const limit = readNumberParam(actionParams, "limit", { integer: true });
130
+ return await invoke({ action: "emojiList", limit, accountId }, cfg);
131
+ }
132
+ throw new Error(`Action ${action} is not supported for provider ${providerId}.`);
133
+ }
@@ -0,0 +1,35 @@
1
+ export function createDefaultChannelRuntimeState(accountId, extra) {
2
+ return {
3
+ accountId,
4
+ running: false,
5
+ lastStartAt: null,
6
+ lastStopAt: null,
7
+ lastError: null,
8
+ ...(extra ?? {}),
9
+ };
10
+ }
11
+ export function buildBaseChannelStatusSummary(snapshot) {
12
+ return {
13
+ configured: snapshot.configured ?? false,
14
+ running: snapshot.running ?? false,
15
+ lastStartAt: snapshot.lastStartAt ?? null,
16
+ lastStopAt: snapshot.lastStopAt ?? null,
17
+ lastError: snapshot.lastError ?? null,
18
+ };
19
+ }
20
+ export function collectStatusIssuesFromLastError(channel, accounts) {
21
+ return accounts.flatMap((account) => {
22
+ const lastError = typeof account.lastError === "string" ? account.lastError.trim() : "";
23
+ if (!lastError) {
24
+ return [];
25
+ }
26
+ return [
27
+ {
28
+ channel,
29
+ accountId: account.accountId,
30
+ kind: "runtime",
31
+ message: `Channel error: ${lastError}`,
32
+ },
33
+ ];
34
+ });
35
+ }
@@ -0,0 +1,31 @@
1
+ export function chunkTextForOutbound(text, limit) {
2
+ if (!text) {
3
+ return [];
4
+ }
5
+ if (limit <= 0 || text.length <= limit) {
6
+ return [text];
7
+ }
8
+ const chunks = [];
9
+ let remaining = text;
10
+ while (remaining.length > limit) {
11
+ const window = remaining.slice(0, limit);
12
+ const lastNewline = window.lastIndexOf("\n");
13
+ const lastSpace = window.lastIndexOf(" ");
14
+ let breakIdx = lastNewline > 0 ? lastNewline : lastSpace;
15
+ if (breakIdx <= 0) {
16
+ breakIdx = limit;
17
+ }
18
+ const rawChunk = remaining.slice(0, breakIdx);
19
+ const chunk = rawChunk.trimEnd();
20
+ if (chunk.length > 0) {
21
+ chunks.push(chunk);
22
+ }
23
+ const brokeOnSeparator = breakIdx < remaining.length && /\s/.test(remaining[breakIdx]);
24
+ const nextStart = Math.min(remaining.length, breakIdx + (brokeOnSeparator ? 1 : 0));
25
+ remaining = remaining.slice(nextStart).trimStart();
26
+ }
27
+ if (remaining.length) {
28
+ chunks.push(remaining);
29
+ }
30
+ return chunks;
31
+ }
@@ -0,0 +1,12 @@
1
+ export function extractToolSend(args, expectedAction = "sendMessage") {
2
+ const action = typeof args.action === "string" ? args.action.trim() : "";
3
+ if (action !== expectedAction) {
4
+ return null;
5
+ }
6
+ const to = typeof args.to === "string" ? args.to : undefined;
7
+ if (!to) {
8
+ return null;
9
+ }
10
+ const accountId = typeof args.accountId === "string" ? args.accountId.trim() : undefined;
11
+ return { to, accountId };
12
+ }
@@ -0,0 +1,27 @@
1
+ export function normalizeWebhookPath(raw) {
2
+ const trimmed = raw.trim();
3
+ if (!trimmed) {
4
+ return "/";
5
+ }
6
+ const withSlash = trimmed.startsWith("/") ? trimmed : `/${trimmed}`;
7
+ if (withSlash.length > 1 && withSlash.endsWith("/")) {
8
+ return withSlash.slice(0, -1);
9
+ }
10
+ return withSlash;
11
+ }
12
+ export function resolveWebhookPath(params) {
13
+ const trimmedPath = params.webhookPath?.trim();
14
+ if (trimmedPath) {
15
+ return normalizeWebhookPath(trimmedPath);
16
+ }
17
+ if (params.webhookUrl?.trim()) {
18
+ try {
19
+ const parsed = new URL(params.webhookUrl);
20
+ return normalizeWebhookPath(parsed.pathname || "/");
21
+ }
22
+ catch {
23
+ return null;
24
+ }
25
+ }
26
+ return params.defaultPath ?? null;
27
+ }
@@ -0,0 +1,34 @@
1
+ import { normalizeWebhookPath } from "./webhook-path.js";
2
+ export function registerWebhookTarget(targetsByPath, target) {
3
+ const key = normalizeWebhookPath(target.path);
4
+ const normalizedTarget = { ...target, path: key };
5
+ const existing = targetsByPath.get(key) ?? [];
6
+ targetsByPath.set(key, [...existing, normalizedTarget]);
7
+ const unregister = () => {
8
+ const updated = (targetsByPath.get(key) ?? []).filter((entry) => entry !== normalizedTarget);
9
+ if (updated.length > 0) {
10
+ targetsByPath.set(key, updated);
11
+ return;
12
+ }
13
+ targetsByPath.delete(key);
14
+ };
15
+ return { target: normalizedTarget, unregister };
16
+ }
17
+ export function resolveWebhookTargets(req, targetsByPath) {
18
+ const url = new URL(req.url ?? "/", "http://localhost");
19
+ const path = normalizeWebhookPath(url.pathname);
20
+ const targets = targetsByPath.get(path);
21
+ if (!targets || targets.length === 0) {
22
+ return null;
23
+ }
24
+ return { path, targets };
25
+ }
26
+ export function rejectNonPostWebhookRequest(req, res) {
27
+ if (req.method === "POST") {
28
+ return false;
29
+ }
30
+ res.statusCode = 405;
31
+ res.setHeader("Allow", "POST");
32
+ res.end("Method Not Allowed");
33
+ return true;
34
+ }
@@ -0,0 +1,21 @@
1
+ export function createMockPluginRegistry(hooks) {
2
+ return {
3
+ hooks: hooks,
4
+ typedHooks: hooks.map((h) => ({
5
+ pluginId: "test-plugin",
6
+ hookName: h.hookName,
7
+ handler: h.handler,
8
+ priority: 0,
9
+ source: "test",
10
+ })),
11
+ tools: [],
12
+ httpHandlers: [],
13
+ httpRoutes: [],
14
+ channelRegistrations: [],
15
+ gatewayHandlers: {},
16
+ cliRegistrars: [],
17
+ services: [],
18
+ providers: [],
19
+ commands: [],
20
+ };
21
+ }
@@ -0,0 +1,171 @@
1
+ import fs from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { resolvePluginInstallDir } from "./install.js";
4
+ import { defaultSlotIdForKey } from "./slots.js";
5
+ export function resolveUninstallDirectoryTarget(params) {
6
+ if (!params.hasInstall) {
7
+ return null;
8
+ }
9
+ if (params.installRecord?.source === "path") {
10
+ return null;
11
+ }
12
+ let defaultPath;
13
+ try {
14
+ defaultPath = resolvePluginInstallDir(params.pluginId, params.extensionsDir);
15
+ }
16
+ catch {
17
+ return null;
18
+ }
19
+ const configuredPath = params.installRecord?.installPath;
20
+ if (!configuredPath) {
21
+ return defaultPath;
22
+ }
23
+ if (path.resolve(configuredPath) === path.resolve(defaultPath)) {
24
+ return configuredPath;
25
+ }
26
+ // Never trust configured installPath blindly for recursive deletes.
27
+ return defaultPath;
28
+ }
29
+ /**
30
+ * Remove plugin references from config (pure config mutation).
31
+ * Returns a new config with the plugin removed from entries, installs, allow, load.paths, and slots.
32
+ */
33
+ export function removePluginFromConfig(cfg, pluginId) {
34
+ const actions = {
35
+ entry: false,
36
+ install: false,
37
+ allowlist: false,
38
+ loadPath: false,
39
+ memorySlot: false,
40
+ };
41
+ const pluginsConfig = cfg.plugins ?? {};
42
+ // Remove from entries
43
+ let entries = pluginsConfig.entries;
44
+ if (entries && pluginId in entries) {
45
+ const { [pluginId]: _, ...rest } = entries;
46
+ entries = Object.keys(rest).length > 0 ? rest : undefined;
47
+ actions.entry = true;
48
+ }
49
+ // Remove from installs
50
+ let installs = pluginsConfig.installs;
51
+ const installRecord = installs?.[pluginId];
52
+ if (installs && pluginId in installs) {
53
+ const { [pluginId]: _, ...rest } = installs;
54
+ installs = Object.keys(rest).length > 0 ? rest : undefined;
55
+ actions.install = true;
56
+ }
57
+ // Remove from allowlist
58
+ let allow = pluginsConfig.allow;
59
+ if (Array.isArray(allow) && allow.includes(pluginId)) {
60
+ allow = allow.filter((id) => id !== pluginId);
61
+ if (allow.length === 0) {
62
+ allow = undefined;
63
+ }
64
+ actions.allowlist = true;
65
+ }
66
+ // Remove linked path from load.paths (for source === "path" plugins)
67
+ let load = pluginsConfig.load;
68
+ if (installRecord?.source === "path" && installRecord.sourcePath) {
69
+ const sourcePath = installRecord.sourcePath;
70
+ const loadPaths = load?.paths;
71
+ if (Array.isArray(loadPaths) && loadPaths.includes(sourcePath)) {
72
+ const nextLoadPaths = loadPaths.filter((p) => p !== sourcePath);
73
+ load = nextLoadPaths.length > 0 ? { ...load, paths: nextLoadPaths } : undefined;
74
+ actions.loadPath = true;
75
+ }
76
+ }
77
+ // Reset memory slot if this plugin was selected
78
+ let slots = pluginsConfig.slots;
79
+ if (slots?.memory === pluginId) {
80
+ slots = {
81
+ ...slots,
82
+ memory: defaultSlotIdForKey("memory"),
83
+ };
84
+ actions.memorySlot = true;
85
+ }
86
+ if (slots && Object.keys(slots).length === 0) {
87
+ slots = undefined;
88
+ }
89
+ const newPlugins = {
90
+ ...pluginsConfig,
91
+ entries,
92
+ installs,
93
+ allow,
94
+ load,
95
+ slots,
96
+ };
97
+ // Clean up undefined properties from newPlugins
98
+ const cleanedPlugins = { ...newPlugins };
99
+ if (cleanedPlugins.entries === undefined) {
100
+ delete cleanedPlugins.entries;
101
+ }
102
+ if (cleanedPlugins.installs === undefined) {
103
+ delete cleanedPlugins.installs;
104
+ }
105
+ if (cleanedPlugins.allow === undefined) {
106
+ delete cleanedPlugins.allow;
107
+ }
108
+ if (cleanedPlugins.load === undefined) {
109
+ delete cleanedPlugins.load;
110
+ }
111
+ if (cleanedPlugins.slots === undefined) {
112
+ delete cleanedPlugins.slots;
113
+ }
114
+ const config = {
115
+ ...cfg,
116
+ plugins: Object.keys(cleanedPlugins).length > 0 ? cleanedPlugins : undefined,
117
+ };
118
+ return { config, actions };
119
+ }
120
+ /**
121
+ * Uninstall a plugin by removing it from config and optionally deleting installed files.
122
+ * Linked plugins (source === "path") never have their source directory deleted.
123
+ */
124
+ export async function uninstallPlugin(params) {
125
+ const { config, pluginId, deleteFiles = true, extensionsDir } = params;
126
+ // Validate plugin exists
127
+ const hasEntry = pluginId in (config.plugins?.entries ?? {});
128
+ const hasInstall = pluginId in (config.plugins?.installs ?? {});
129
+ if (!hasEntry && !hasInstall) {
130
+ return { ok: false, error: `Plugin not found: ${pluginId}` };
131
+ }
132
+ const installRecord = config.plugins?.installs?.[pluginId];
133
+ const isLinked = installRecord?.source === "path";
134
+ // Remove from config
135
+ const { config: newConfig, actions: configActions } = removePluginFromConfig(config, pluginId);
136
+ const actions = {
137
+ ...configActions,
138
+ directory: false,
139
+ };
140
+ const warnings = [];
141
+ const deleteTarget = deleteFiles && !isLinked
142
+ ? resolveUninstallDirectoryTarget({
143
+ pluginId,
144
+ hasInstall,
145
+ installRecord,
146
+ extensionsDir,
147
+ })
148
+ : null;
149
+ // Delete installed directory if requested and safe.
150
+ if (deleteTarget) {
151
+ const existed = (await fs
152
+ .access(deleteTarget)
153
+ .then(() => true)
154
+ .catch(() => false)) ?? false;
155
+ try {
156
+ await fs.rm(deleteTarget, { recursive: true, force: true });
157
+ actions.directory = existed;
158
+ }
159
+ catch (error) {
160
+ warnings.push(`Failed to remove plugin directory ${deleteTarget}: ${error instanceof Error ? error.message : String(error)}`);
161
+ // Directory deletion failure is not fatal; config is the source of truth.
162
+ }
163
+ }
164
+ return {
165
+ ok: true,
166
+ config: newConfig,
167
+ pluginId,
168
+ actions,
169
+ warnings,
170
+ };
171
+ }
@@ -0,0 +1,143 @@
1
+ import { killProcessTree } from "../../kill-tree.js";
2
+ import { spawnWithFallback } from "../../spawn-utils.js";
3
+ import { toStringEnv } from "./env.js";
4
+ function resolveCommand(command) {
5
+ if (process.platform !== "win32") {
6
+ return command;
7
+ }
8
+ const lower = command.toLowerCase();
9
+ if (lower.endsWith(".exe") || lower.endsWith(".cmd") || lower.endsWith(".bat")) {
10
+ return command;
11
+ }
12
+ const basename = lower.split(/[\\/]/).pop() ?? lower;
13
+ if (basename === "npm" || basename === "pnpm" || basename === "yarn" || basename === "npx") {
14
+ return `${command}.cmd`;
15
+ }
16
+ return command;
17
+ }
18
+ export async function createChildAdapter(params) {
19
+ const resolvedArgv = [...params.argv];
20
+ resolvedArgv[0] = resolveCommand(resolvedArgv[0] ?? "");
21
+ const stdinMode = params.stdinMode ?? (params.input !== undefined ? "pipe-closed" : "inherit");
22
+ // On Windows, `detached: true` creates a new process group and can prevent
23
+ // stdout/stderr pipes from connecting when running under a Scheduled Task
24
+ // (headless, no console). Default to `detached: false` on Windows; on
25
+ // POSIX systems keep `detached: true` so the child survives parent exit.
26
+ const useDetached = process.platform !== "win32";
27
+ const options = {
28
+ cwd: params.cwd,
29
+ env: params.env ? toStringEnv(params.env) : undefined,
30
+ stdio: ["pipe", "pipe", "pipe"],
31
+ detached: useDetached,
32
+ windowsHide: true,
33
+ windowsVerbatimArguments: params.windowsVerbatimArguments,
34
+ };
35
+ if (stdinMode === "inherit") {
36
+ options.stdio = ["inherit", "pipe", "pipe"];
37
+ }
38
+ else {
39
+ options.stdio = ["pipe", "pipe", "pipe"];
40
+ }
41
+ const spawned = await spawnWithFallback({
42
+ argv: resolvedArgv,
43
+ options,
44
+ fallbacks: useDetached
45
+ ? [
46
+ {
47
+ label: "no-detach",
48
+ options: { detached: false },
49
+ },
50
+ ]
51
+ : [],
52
+ });
53
+ const child = spawned.child;
54
+ if (child.stdin) {
55
+ if (params.input !== undefined) {
56
+ child.stdin.write(params.input);
57
+ child.stdin.end();
58
+ }
59
+ else if (stdinMode === "pipe-closed") {
60
+ child.stdin.end();
61
+ }
62
+ }
63
+ const stdin = child.stdin
64
+ ? {
65
+ destroyed: false,
66
+ write: (data, cb) => {
67
+ try {
68
+ child.stdin.write(data, cb);
69
+ }
70
+ catch (err) {
71
+ cb?.(err);
72
+ }
73
+ },
74
+ end: () => {
75
+ try {
76
+ child.stdin.end();
77
+ }
78
+ catch {
79
+ // ignore close errors
80
+ }
81
+ },
82
+ destroy: () => {
83
+ try {
84
+ child.stdin.destroy();
85
+ }
86
+ catch {
87
+ // ignore destroy errors
88
+ }
89
+ },
90
+ }
91
+ : undefined;
92
+ const onStdout = (listener) => {
93
+ child.stdout.on("data", (chunk) => {
94
+ listener(chunk.toString());
95
+ });
96
+ };
97
+ const onStderr = (listener) => {
98
+ child.stderr.on("data", (chunk) => {
99
+ listener(chunk.toString());
100
+ });
101
+ };
102
+ const wait = async () => await new Promise((resolve, reject) => {
103
+ child.once("error", reject);
104
+ child.once("close", (code, signal) => {
105
+ resolve({ code, signal });
106
+ });
107
+ });
108
+ const kill = (signal) => {
109
+ const pid = child.pid ?? undefined;
110
+ if (signal === undefined || signal === "SIGKILL") {
111
+ if (pid) {
112
+ killProcessTree(pid);
113
+ }
114
+ else {
115
+ try {
116
+ child.kill("SIGKILL");
117
+ }
118
+ catch {
119
+ // ignore kill errors
120
+ }
121
+ }
122
+ return;
123
+ }
124
+ try {
125
+ child.kill(signal);
126
+ }
127
+ catch {
128
+ // ignore kill errors for non-kill signals
129
+ }
130
+ };
131
+ const dispose = () => {
132
+ child.removeAllListeners();
133
+ };
134
+ return {
135
+ pid: child.pid ?? undefined,
136
+ stdin,
137
+ onStdout,
138
+ onStderr,
139
+ wait,
140
+ kill,
141
+ dispose,
142
+ };
143
+ }
@@ -0,0 +1,13 @@
1
+ export function toStringEnv(env) {
2
+ if (!env) {
3
+ return {};
4
+ }
5
+ const out = {};
6
+ for (const [key, value] of Object.entries(env)) {
7
+ if (value === undefined) {
8
+ continue;
9
+ }
10
+ out[key] = String(value);
11
+ }
12
+ return out;
13
+ }