@poolzin/pool-bot 2026.2.11 → 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 (535) hide show
  1. package/CHANGELOG.md +34 -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/usage.js +22 -0
  5. package/dist/agents/auth-profiles.js +1 -1
  6. package/dist/agents/auth-profiles.resolve-auth-profile-order.fixtures.js +23 -0
  7. package/dist/agents/bash-tools.exec-runtime.js +438 -0
  8. package/dist/agents/bash-tools.shared.js +6 -0
  9. package/dist/agents/cli-runner/reliability.js +61 -0
  10. package/dist/agents/cli-watchdog-defaults.js +11 -0
  11. package/dist/agents/command-poll-backoff.js +63 -0
  12. package/dist/agents/current-time.js +16 -0
  13. package/dist/agents/glob-pattern.js +42 -0
  14. package/dist/agents/memory-search.js +33 -0
  15. package/dist/agents/model-alias-lines.js +18 -0
  16. package/dist/agents/model-auth-label.js +61 -0
  17. package/dist/agents/model-fallback.js +59 -8
  18. package/dist/agents/models-config.e2e-harness.js +115 -0
  19. package/dist/agents/ollama-stream.js +11 -3
  20. package/dist/agents/openclaw-tools.js +135 -0
  21. package/dist/agents/pi-auth-json.js +118 -0
  22. package/dist/agents/pi-embedded-runner/run.overflow-compaction.mocks.shared.js +147 -0
  23. package/dist/agents/pi-embedded-subscribe.e2e-harness.js +90 -0
  24. package/dist/agents/pi-embedded-subscribe.handlers.compaction.js +63 -0
  25. package/dist/agents/pi-embedded-subscribe.handlers.tools.media.test-helpers.js +30 -0
  26. package/dist/agents/pi-extensions/session-manager-runtime-registry.js +23 -0
  27. package/dist/agents/pi-tools.before-tool-call.js +145 -4
  28. package/dist/agents/pi-tools.js +29 -9
  29. package/dist/agents/pi-tools.policy.js +85 -92
  30. package/dist/agents/pi-tools.schema.js +54 -27
  31. package/dist/agents/queued-file-writer.js +22 -0
  32. package/dist/agents/sandbox/docker.js +133 -40
  33. package/dist/agents/sandbox/fs-bridge.js +146 -0
  34. package/dist/agents/sandbox/fs-paths.js +205 -0
  35. package/dist/agents/sandbox/hash.js +4 -0
  36. package/dist/agents/sandbox/validate-sandbox-security.js +157 -0
  37. package/dist/agents/sandbox-paths.js +3 -0
  38. package/dist/agents/sandbox-tool-policy.js +26 -0
  39. package/dist/agents/sanitize-for-prompt.js +18 -0
  40. package/dist/agents/session-dirs.js +20 -0
  41. package/dist/agents/session-write-lock.js +203 -39
  42. package/dist/agents/skills/filter.js +24 -0
  43. package/dist/agents/skills/tools-dir.js +9 -0
  44. package/dist/agents/skills-install-download.js +290 -0
  45. package/dist/agents/skills-install-output.js +30 -0
  46. package/dist/agents/skills-install.download-test-utils.js +36 -0
  47. package/dist/agents/skills.e2e-test-helpers.js +13 -0
  48. package/dist/agents/subagent-announce-queue.js +59 -15
  49. package/dist/agents/subagent-depth.js +137 -0
  50. package/dist/agents/subagent-registry.js +448 -96
  51. package/dist/agents/subagent-spawn.js +262 -0
  52. package/dist/agents/system-prompt.js +52 -10
  53. package/dist/agents/test-helpers/fast-tool-stubs.js +18 -0
  54. package/dist/agents/test-helpers/host-sandbox-fs-bridge.js +74 -0
  55. package/dist/agents/tool-display-common.js +782 -0
  56. package/dist/agents/tool-loop-detection.js +466 -0
  57. package/dist/agents/tool-policy.js +6 -0
  58. package/dist/agents/tools/image-tool.js +1 -1
  59. package/dist/agents/tools/sessions-access.js +178 -0
  60. package/dist/agents/tools/sessions-resolution.js +206 -0
  61. package/dist/agents/tools/subagents-tool.js +616 -0
  62. package/dist/agents/workspace-dir.js +18 -0
  63. package/dist/agents/workspace-dirs.js +14 -0
  64. package/dist/agents/workspace.js +70 -0
  65. package/dist/auto-reply/heartbeat-reply-payload.js +18 -0
  66. package/dist/auto-reply/reply/commands-export-session.js +163 -0
  67. package/dist/auto-reply/reply/commands-mesh.js +245 -0
  68. package/dist/auto-reply/reply/commands-setunset.js +28 -0
  69. package/dist/auto-reply/reply/commands-slash-parse.js +31 -0
  70. package/dist/auto-reply/reply/commands-system-prompt.js +117 -0
  71. package/dist/auto-reply/reply/directive-handling.levels.js +17 -0
  72. package/dist/auto-reply/reply/directive-handling.params.js +1 -0
  73. package/dist/auto-reply/reply/directive-parsing.js +36 -0
  74. package/dist/auto-reply/reply/dispatcher-registry.js +43 -0
  75. package/dist/auto-reply/reply/elevated-unavailable.js +20 -0
  76. package/dist/auto-reply/reply/post-compaction-audit.js +96 -0
  77. package/dist/auto-reply/reply/post-compaction-context.js +98 -0
  78. package/dist/auto-reply/reply/reply-delivery.js +92 -0
  79. package/dist/auto-reply/reply/session-reset-prompt.js +1 -0
  80. package/dist/auto-reply/reply/session-run-accounting.js +33 -0
  81. package/dist/auto-reply/reply.directive.directive-behavior.e2e-harness.js +115 -0
  82. package/dist/auto-reply/reply.directive.directive-behavior.e2e-mocks.js +12 -0
  83. package/dist/browser/bridge-auth-registry.js +26 -0
  84. package/dist/browser/client-actions-url.js +10 -0
  85. package/dist/browser/control-auth.js +73 -0
  86. package/dist/browser/csrf.js +64 -0
  87. package/dist/browser/http-auth.js +52 -0
  88. package/dist/browser/paths.js +37 -0
  89. package/dist/browser/proxy-files.js +32 -0
  90. package/dist/browser/pw-ai-state.js +7 -0
  91. package/dist/browser/resolved-config-refresh.js +42 -0
  92. package/dist/browser/routes/path-output.js +1 -0
  93. package/dist/browser/server-context.chrome-test-harness.js +20 -0
  94. package/dist/browser/server-middleware.js +31 -0
  95. package/dist/browser/test-port.js +16 -0
  96. package/dist/build-info.json +3 -3
  97. package/dist/canvas-host/file-resolver.js +43 -0
  98. package/dist/channels/account-summary.js +19 -0
  99. package/dist/channels/draft-stream-loop.js +77 -0
  100. package/dist/channels/plugins/account-helpers.js +26 -0
  101. package/dist/channels/telegram/allow-from.js +10 -0
  102. package/dist/cli/browser-cli-resize.js +22 -0
  103. package/dist/cli/browser-cli-shared.js +8 -0
  104. package/dist/cli/clawbot-cli.js +5 -0
  105. package/dist/cli/completion-cli.js +566 -0
  106. package/dist/cli/config-cli.js +63 -5
  107. package/dist/cli/daemon-cli/lifecycle-core.js +256 -0
  108. package/dist/cli/daemon-cli/register-service-commands.js +60 -0
  109. package/dist/cli/daemon-cli-compat.js +80 -0
  110. package/dist/cli/nodes-cli/pairing-render.js +26 -0
  111. package/dist/cli/program/action-reparse.js +17 -0
  112. package/dist/cli/program/command-registry.js +17 -0
  113. package/dist/cli/program/program-context.js +8 -0
  114. package/dist/cli/program/register.subclis.js +7 -0
  115. package/dist/cli/program/routes.js +233 -0
  116. package/dist/cli/qr-cli.js +132 -0
  117. package/dist/cli/requirements-test-fixtures.js +17 -0
  118. package/dist/cli/respawn-policy.js +4 -0
  119. package/dist/cli/shared/parse-port.js +18 -0
  120. package/dist/cli/skills-cli.format.js +241 -0
  121. package/dist/cli/update-cli/progress.js +121 -0
  122. package/dist/cli/update-cli/restart-helper.js +108 -0
  123. package/dist/cli/update-cli/shared.js +196 -0
  124. package/dist/cli/update-cli/status.js +97 -0
  125. package/dist/cli/update-cli/suppress-deprecations.js +17 -0
  126. package/dist/cli/update-cli/update-command.js +506 -0
  127. package/dist/cli/update-cli/wizard.js +130 -0
  128. package/dist/cli/update-cli.js +3 -9
  129. package/dist/cli/windows-argv.js +69 -0
  130. package/dist/commands/auth-choice-legacy.js +20 -0
  131. package/dist/commands/auth-choice.apply-helpers.js +8 -0
  132. package/dist/commands/channel-test-helpers.js +19 -0
  133. package/dist/commands/cleanup-plan.js +10 -0
  134. package/dist/commands/cleanup-utils.js +7 -0
  135. package/dist/commands/config-validation.js +15 -0
  136. package/dist/commands/doctor-completion.js +112 -0
  137. package/dist/commands/doctor-memory-search.js +119 -0
  138. package/dist/commands/doctor-session-locks.js +73 -0
  139. package/dist/commands/doctor.e2e-harness.js +364 -0
  140. package/dist/commands/gateway-presence.js +19 -0
  141. package/dist/commands/model-default.js +35 -0
  142. package/dist/commands/models/fallbacks-shared.js +102 -0
  143. package/dist/commands/models/shared.js +24 -0
  144. package/dist/commands/onboard-auth.config-gateways.js +64 -0
  145. package/dist/commands/onboard-auth.config-litellm.js +45 -0
  146. package/dist/commands/onboard-auth.config-shared.js +116 -0
  147. package/dist/commands/onboard-config.js +16 -0
  148. package/dist/commands/onboard-non-interactive.test-helpers.js +31 -0
  149. package/dist/commands/onboard-provider-auth-flags.js +136 -0
  150. package/dist/commands/openai-codex-oauth.js +40 -0
  151. package/dist/commands/test-runtime-config-helpers.js +21 -0
  152. package/dist/commands/test-wizard-helpers.js +68 -0
  153. package/dist/commands/vllm-setup.js +66 -0
  154. package/dist/compat/legacy-names.js +2 -0
  155. package/dist/config/backup-rotation.js +19 -0
  156. package/dist/config/env-preserve.js +122 -0
  157. package/dist/config/includes-scan.js +78 -0
  158. package/dist/config/plugins-allowlist.js +13 -0
  159. package/dist/config/schema.help.js +256 -0
  160. package/dist/config/schema.hints.js +189 -0
  161. package/dist/config/schema.irc.js +20 -0
  162. package/dist/config/schema.labels.js +317 -0
  163. package/dist/config/sessions/delivery-info.js +40 -0
  164. package/dist/config/types.irc.js +1 -0
  165. package/dist/config/zod-schema.agent-defaults.js +14 -0
  166. package/dist/config/zod-schema.agent-model.js +10 -0
  167. package/dist/config/zod-schema.agent-runtime.js +14 -0
  168. package/dist/config/zod-schema.allowdeny.js +35 -0
  169. package/dist/config/zod-schema.sensitive.js +4 -0
  170. package/dist/control-ui/assets/index-HRr1grwl.js.map +1 -1
  171. package/dist/cron/isolated-agent/skills-snapshot.js +26 -0
  172. package/dist/cron/isolated-agent/subagent-followup.js +127 -0
  173. package/dist/cron/isolated-agent.mocks.js +12 -0
  174. package/dist/cron/isolated-agent.test-setup.js +22 -0
  175. package/dist/cron/legacy-delivery.js +43 -0
  176. package/dist/cron/webhook-url.js +22 -0
  177. package/dist/daemon/arg-split.js +40 -0
  178. package/dist/daemon/exec-file.js +23 -0
  179. package/dist/daemon/output.js +6 -0
  180. package/dist/daemon/runtime-format.js +31 -0
  181. package/dist/daemon/schtasks-exec.js +4 -0
  182. package/dist/daemon/service-audit.js +22 -0
  183. package/dist/discord/client.js +41 -0
  184. package/dist/discord/components-registry.js +57 -0
  185. package/dist/discord/components.js +816 -0
  186. package/dist/discord/guilds.js +12 -0
  187. package/dist/discord/monitor/gateway-plugin.js +48 -0
  188. package/dist/discord/monitor/presence.js +30 -0
  189. package/dist/discord/send.components.js +115 -0
  190. package/dist/discord/send.shared.js +4 -0
  191. package/dist/discord/ui.js +26 -0
  192. package/dist/discord/voice-message.js +254 -0
  193. package/dist/gateway/agent-event-assistant-text.js +5 -0
  194. package/dist/gateway/agent-prompt.js +33 -0
  195. package/dist/gateway/auth-rate-limit.js +136 -0
  196. package/dist/gateway/channel-health-monitor.js +114 -0
  197. package/dist/gateway/control-ui-contract.js +1 -0
  198. package/dist/gateway/control-ui-csp.js +15 -0
  199. package/dist/gateway/gateway-config-prompts.shared.js +25 -0
  200. package/dist/gateway/http-auth-helpers.js +18 -0
  201. package/dist/gateway/http-common.js +18 -0
  202. package/dist/gateway/http-endpoint-helpers.js +27 -0
  203. package/dist/gateway/node-invoke-sanitize.js +11 -0
  204. package/dist/gateway/node-invoke-system-run-approval.js +205 -0
  205. package/dist/gateway/probe-auth.js +21 -0
  206. package/dist/gateway/protocol/index.js +7 -2
  207. package/dist/gateway/protocol/schema/mesh.js +54 -0
  208. package/dist/gateway/protocol/schema/protocol-schemas.js +7 -0
  209. package/dist/gateway/protocol/schema.js +1 -0
  210. package/dist/gateway/server/ws-connection/auth-messages.js +54 -0
  211. package/dist/gateway/server-channels.js +11 -0
  212. package/dist/gateway/server-methods/attachment-normalize.js +16 -0
  213. package/dist/gateway/server-methods/base-hash.js +8 -0
  214. package/dist/gateway/server-methods/mesh.js +700 -0
  215. package/dist/gateway/server-methods/nodes.handlers.invoke-result.js +55 -0
  216. package/dist/gateway/server-methods/restart-request.js +13 -0
  217. package/dist/gateway/server-methods/validation.js +8 -0
  218. package/dist/gateway/server.agent.gateway-server-agent.mocks.js +35 -0
  219. package/dist/gateway/server.e2e-registry-helpers.js +1 -0
  220. package/dist/gateway/server.e2e-ws-harness.js +20 -0
  221. package/dist/gateway/test-helpers.js +2 -0
  222. package/dist/gateway/test-helpers.server.js +3 -1
  223. package/dist/gateway/test-http-response.js +12 -0
  224. package/dist/gateway/test-openai-responses-model.js +20 -0
  225. package/dist/gateway/test-temp-config.js +30 -0
  226. package/dist/gateway/test-with-server.js +32 -0
  227. package/dist/hooks/bundled/bootstrap-extra-files/handler.js +46 -0
  228. package/dist/imessage/monitor/abort-handler.js +23 -0
  229. package/dist/imessage/monitor/inbound-processing.js +346 -0
  230. package/dist/imessage/monitor/parse-notification.js +64 -0
  231. package/dist/imessage/target-parsing-helpers.js +92 -0
  232. package/dist/infra/archive.js +244 -20
  233. package/dist/infra/detect-package-manager.js +26 -0
  234. package/dist/infra/exec-approvals-allowlist.js +257 -0
  235. package/dist/infra/exec-approvals-analysis.js +770 -0
  236. package/dist/infra/exec-approvals.js +13 -0
  237. package/dist/infra/file-lock.js +1 -0
  238. package/dist/infra/gemini-auth.js +39 -0
  239. package/dist/infra/heartbeat-active-hours.js +85 -0
  240. package/dist/infra/heartbeat-events-filter.js +50 -0
  241. package/dist/infra/heartbeat-runner.test-utils.js +39 -0
  242. package/dist/infra/http-body.js +265 -0
  243. package/dist/infra/install-package-dir.js +50 -0
  244. package/dist/infra/install-safe-path.js +49 -0
  245. package/dist/infra/json-files.js +49 -0
  246. package/dist/infra/jsonl-socket.js +52 -0
  247. package/dist/infra/map-size.js +14 -0
  248. package/dist/infra/net/hostname.js +7 -0
  249. package/dist/infra/npm-registry-spec.js +39 -0
  250. package/dist/infra/openclaw-root.js +109 -0
  251. package/dist/infra/outbound/delivery-queue.js +214 -0
  252. package/dist/infra/outbound/identity.js +23 -0
  253. package/dist/infra/outbound/message-action-params.js +307 -0
  254. package/dist/infra/outbound/tool-payload.js +21 -0
  255. package/dist/infra/package-json.js +23 -0
  256. package/dist/infra/pairing-files.js +19 -0
  257. package/dist/infra/pairing-token.js +9 -0
  258. package/dist/infra/path-prepend.js +51 -0
  259. package/dist/infra/path-safety.js +16 -0
  260. package/dist/infra/process-respawn.js +49 -0
  261. package/dist/infra/runtime-status.js +16 -0
  262. package/dist/infra/session-cost-usage.types.js +1 -0
  263. package/dist/infra/session-maintenance-warning.js +89 -0
  264. package/dist/infra/system-run-command.js +78 -0
  265. package/dist/infra/tmp-openclaw-dir.js +81 -0
  266. package/dist/infra/tmp-poolbot-dir.js +2 -0
  267. package/dist/infra/update-channels.js +19 -0
  268. package/dist/line/actions.js +45 -0
  269. package/dist/line/channel-access-token.js +9 -0
  270. package/dist/line/flex-templates/basic-cards.js +332 -0
  271. package/dist/line/flex-templates/common.js +18 -0
  272. package/dist/line/flex-templates/media-control-cards.js +453 -0
  273. package/dist/line/flex-templates/message.js +10 -0
  274. package/dist/line/flex-templates/schedule-cards.js +399 -0
  275. package/dist/line/flex-templates/types.js +1 -0
  276. package/dist/line/webhook-node.js +100 -0
  277. package/dist/line/webhook-utils.js +11 -0
  278. package/dist/logging/diagnostic-session-state.js +73 -0
  279. package/dist/logging/diagnostic.js +22 -0
  280. package/dist/logging/timestamps.js +14 -0
  281. package/dist/markdown/whatsapp.js +62 -0
  282. package/dist/media/base64.js +34 -0
  283. package/dist/media/local-roots.js +32 -0
  284. package/dist/media/outbound-attachment.js +10 -0
  285. package/dist/media/read-response-with-limit.js +41 -0
  286. package/dist/media/sniff-mime-from-base64.js +19 -0
  287. package/dist/media-understanding/audio-preflight.js +67 -0
  288. package/dist/media-understanding/fs.js +13 -0
  289. package/dist/media-understanding/output-extract.js +26 -0
  290. package/dist/media-understanding/providers/audio.test-helpers.js +34 -0
  291. package/dist/media-understanding/providers/google/inline-data.js +64 -0
  292. package/dist/media-understanding/providers/shared.js +7 -0
  293. package/dist/media-understanding/runner.entries.js +459 -0
  294. package/dist/memory/batch-error-utils.js +11 -0
  295. package/dist/memory/batch-http.js +27 -0
  296. package/dist/memory/batch-output.js +29 -0
  297. package/dist/memory/batch-runner.js +22 -0
  298. package/dist/memory/batch-upload.js +23 -0
  299. package/dist/memory/batch-utils.js +26 -0
  300. package/dist/memory/embeddings-debug.js +11 -0
  301. package/dist/memory/embeddings-remote-client.js +22 -0
  302. package/dist/memory/embeddings-remote-fetch.js +14 -0
  303. package/dist/memory/embeddings.js +36 -9
  304. package/dist/memory/hybrid.js +24 -5
  305. package/dist/memory/manager-embedding-ops.js +616 -0
  306. package/dist/memory/manager-sync-ops.js +953 -0
  307. package/dist/memory/manager.js +76 -28
  308. package/dist/memory/mmr.js +164 -0
  309. package/dist/memory/qmd-manager.js +1061 -0
  310. package/dist/memory/qmd-query-parser.js +107 -0
  311. package/dist/memory/qmd-scope.js +93 -0
  312. package/dist/memory/query-expansion.js +331 -0
  313. package/dist/memory/search-manager.js +0 -1
  314. package/dist/memory/sync-index.js +21 -0
  315. package/dist/memory/sync-progress.js +22 -0
  316. package/dist/memory/sync-stale.js +30 -0
  317. package/dist/memory/temporal-decay.js +119 -0
  318. package/dist/memory/test-embeddings-mock.js +16 -0
  319. package/dist/memory/test-manager-helpers.js +14 -0
  320. package/dist/memory/test-runtime-mocks.js +11 -0
  321. package/dist/node-host/invoke-browser.js +177 -0
  322. package/dist/node-host/invoke.js +685 -0
  323. package/dist/pairing/setup-code.js +285 -0
  324. package/dist/plugin-sdk/account-id.js +1 -0
  325. package/dist/plugin-sdk/agent-media-payload.js +13 -0
  326. package/dist/plugin-sdk/allow-from.js +47 -0
  327. package/dist/plugin-sdk/command-auth.js +23 -0
  328. package/dist/plugin-sdk/config-paths.js +9 -0
  329. package/dist/plugin-sdk/file-lock.js +116 -0
  330. package/dist/plugin-sdk/json-store.js +31 -0
  331. package/dist/plugin-sdk/onboarding.js +28 -0
  332. package/dist/plugin-sdk/provider-auth-result.js +29 -0
  333. package/dist/plugin-sdk/slack-message-actions.js +133 -0
  334. package/dist/plugin-sdk/status-helpers.js +35 -0
  335. package/dist/plugin-sdk/text-chunking.js +31 -0
  336. package/dist/plugin-sdk/tool-send.js +12 -0
  337. package/dist/plugin-sdk/webhook-path.js +27 -0
  338. package/dist/plugin-sdk/webhook-targets.js +34 -0
  339. package/dist/plugins/hooks.test-helpers.js +21 -0
  340. package/dist/plugins/uninstall.js +171 -0
  341. package/dist/process/kill-tree.js +98 -0
  342. package/dist/process/supervisor/adapters/child.js +143 -0
  343. package/dist/process/supervisor/adapters/env.js +13 -0
  344. package/dist/process/supervisor/adapters/pty.js +148 -0
  345. package/dist/process/supervisor/index.js +10 -0
  346. package/dist/process/supervisor/registry.js +117 -0
  347. package/dist/process/supervisor/supervisor.js +244 -0
  348. package/dist/process/supervisor/types.js +1 -0
  349. package/dist/providers/google-shared.test-helpers.js +75 -0
  350. package/dist/security/audit-channel.js +419 -0
  351. package/dist/security/audit-tool-policy.js +1 -0
  352. package/dist/security/scan-paths.js +12 -0
  353. package/dist/sessions/input-provenance.js +55 -0
  354. package/dist/sessions/session-key-utils.js +7 -0
  355. package/dist/shared/chat-content.js +31 -0
  356. package/dist/shared/chat-envelope.js +45 -0
  357. package/dist/shared/config-eval.js +117 -0
  358. package/dist/shared/device-auth.js +16 -0
  359. package/dist/shared/entry-metadata.js +9 -0
  360. package/dist/shared/entry-status.js +25 -0
  361. package/dist/shared/frontmatter.js +98 -0
  362. package/dist/shared/model-param-b.js +19 -0
  363. package/dist/shared/net/ipv4.js +17 -0
  364. package/dist/shared/node-match.js +53 -0
  365. package/dist/shared/pid-alive.js +12 -0
  366. package/dist/shared/process-scoped-map.js +10 -0
  367. package/dist/shared/requirements.js +128 -0
  368. package/dist/shared/subagents-format.js +84 -0
  369. package/dist/shared/usage-aggregates.js +28 -0
  370. package/dist/signal/monitor/mentions.js +45 -0
  371. package/dist/signal/rpc-context.js +19 -0
  372. package/dist/slack/blocks-fallback.js +76 -0
  373. package/dist/slack/blocks-input.js +40 -0
  374. package/dist/slack/draft-stream.js +106 -0
  375. package/dist/slack/message-actions.js +51 -0
  376. package/dist/slack/modal-metadata.js +32 -0
  377. package/dist/slack/monitor/events/interactions.js +462 -0
  378. package/dist/slack/monitor/room-context.js +17 -0
  379. package/dist/slack/stream-mode.js +41 -0
  380. package/dist/telegram/bot-native-command-menu.js +64 -0
  381. package/dist/telegram/bot.media.e2e-harness.js +81 -0
  382. package/dist/telegram/button-types.js +1 -0
  383. package/dist/telegram/group-access.js +65 -0
  384. package/dist/telegram/outbound-params.js +21 -0
  385. package/dist/telegram/poll-vote-cache.js +21 -0
  386. package/dist/terminal/health-style.js +36 -0
  387. package/dist/test-utils/chunk-test-helpers.js +21 -0
  388. package/dist/test-utils/env.js +72 -0
  389. package/dist/test-utils/exec-assertions.js +12 -0
  390. package/dist/test-utils/imessage-test-plugin.js +54 -0
  391. package/dist/test-utils/mock-http-response.js +17 -0
  392. package/dist/test-utils/vitest-mock-fn.js +1 -0
  393. package/dist/tts/tts-core.js +550 -0
  394. package/dist/utils/chunk-items.js +10 -0
  395. package/dist/utils/reaction-level.js +52 -0
  396. package/dist/utils/safe-json.js +22 -0
  397. package/dist/utils/with-timeout.js +14 -0
  398. package/dist/web/media.js +17 -5
  399. package/dist/whatsapp/resolve-outbound-target.js +42 -0
  400. package/dist/wizard/onboarding.completion.js +74 -0
  401. package/extensions/bluebubbles/package.json +1 -1
  402. package/extensions/bluebubbles/src/account-resolve.ts +29 -0
  403. package/extensions/bluebubbles/src/monitor-normalize.ts +796 -0
  404. package/extensions/bluebubbles/src/monitor-processing.ts +1007 -0
  405. package/extensions/bluebubbles/src/monitor-reply-cache.ts +185 -0
  406. package/extensions/bluebubbles/src/monitor-shared.ts +51 -0
  407. package/extensions/bluebubbles/src/multipart.ts +32 -0
  408. package/extensions/bluebubbles/src/send-helpers.ts +53 -0
  409. package/extensions/bluebubbles/src/test-harness.ts +50 -0
  410. package/extensions/bluebubbles/src/test-mocks.ts +11 -0
  411. package/extensions/copilot-proxy/package.json +1 -1
  412. package/extensions/device-pair/index.ts +554 -0
  413. package/extensions/diagnostics-otel/package.json +1 -1
  414. package/extensions/discord/package.json +1 -1
  415. package/extensions/discord/src/channel.js +366 -0
  416. package/extensions/discord/src/runtime.js +10 -0
  417. package/extensions/feishu/index.ts +63 -0
  418. package/extensions/feishu/src/accounts.ts +114 -0
  419. package/extensions/feishu/src/bitable.ts +739 -0
  420. package/extensions/feishu/src/bot.ts +965 -0
  421. package/extensions/feishu/src/channel.ts +351 -0
  422. package/extensions/feishu/src/client.ts +118 -0
  423. package/extensions/feishu/src/config-schema.ts +206 -0
  424. package/extensions/feishu/src/dedup.ts +33 -0
  425. package/extensions/feishu/src/directory.ts +177 -0
  426. package/extensions/feishu/src/doc-schema.ts +47 -0
  427. package/extensions/feishu/src/docx.ts +536 -0
  428. package/extensions/feishu/src/drive-schema.ts +46 -0
  429. package/extensions/feishu/src/drive.ts +227 -0
  430. package/extensions/feishu/src/dynamic-agent.ts +131 -0
  431. package/extensions/feishu/src/media.ts +449 -0
  432. package/extensions/feishu/src/mention.ts +126 -0
  433. package/extensions/feishu/src/monitor.ts +330 -0
  434. package/extensions/feishu/src/onboarding.ts +359 -0
  435. package/extensions/feishu/src/outbound.ts +55 -0
  436. package/extensions/feishu/src/perm-schema.ts +52 -0
  437. package/extensions/feishu/src/perm.ts +173 -0
  438. package/extensions/feishu/src/policy.ts +84 -0
  439. package/extensions/feishu/src/probe.ts +44 -0
  440. package/extensions/feishu/src/reactions.ts +160 -0
  441. package/extensions/feishu/src/reply-dispatcher.ts +239 -0
  442. package/extensions/feishu/src/runtime.ts +14 -0
  443. package/extensions/feishu/src/send-result.ts +29 -0
  444. package/extensions/feishu/src/send.ts +335 -0
  445. package/extensions/feishu/src/streaming-card.ts +223 -0
  446. package/extensions/feishu/src/targets.ts +78 -0
  447. package/extensions/feishu/src/tools-config.ts +21 -0
  448. package/extensions/feishu/src/types.ts +81 -0
  449. package/extensions/feishu/src/typing.ts +80 -0
  450. package/extensions/feishu/src/wiki-schema.ts +55 -0
  451. package/extensions/feishu/src/wiki.ts +232 -0
  452. package/extensions/google-antigravity-auth/package.json +1 -1
  453. package/extensions/google-gemini-cli-auth/package.json +1 -1
  454. package/extensions/googlechat/package.json +1 -1
  455. package/extensions/imessage/package.json +1 -1
  456. package/extensions/imessage/src/channel.js +253 -0
  457. package/extensions/imessage/src/runtime.js +10 -0
  458. package/extensions/irc/index.ts +17 -0
  459. package/extensions/irc/src/accounts.ts +268 -0
  460. package/extensions/irc/src/channel.ts +367 -0
  461. package/extensions/irc/src/client.ts +439 -0
  462. package/extensions/irc/src/config-schema.ts +97 -0
  463. package/extensions/irc/src/connect-options.ts +30 -0
  464. package/extensions/irc/src/control-chars.ts +22 -0
  465. package/extensions/irc/src/inbound.ts +334 -0
  466. package/extensions/irc/src/monitor.ts +147 -0
  467. package/extensions/irc/src/normalize.ts +117 -0
  468. package/extensions/irc/src/onboarding.ts +479 -0
  469. package/extensions/irc/src/policy.ts +157 -0
  470. package/extensions/irc/src/probe.ts +53 -0
  471. package/extensions/irc/src/protocol.ts +169 -0
  472. package/extensions/irc/src/runtime.ts +14 -0
  473. package/extensions/irc/src/send.ts +88 -0
  474. package/extensions/irc/src/types.ts +93 -0
  475. package/extensions/line/package.json +1 -1
  476. package/extensions/llm-task/package.json +1 -1
  477. package/extensions/lobster/package.json +1 -1
  478. package/extensions/matrix/CHANGELOG.md +5 -0
  479. package/extensions/matrix/package.json +1 -1
  480. package/extensions/matrix/src/matrix/client-bootstrap.ts +39 -0
  481. package/extensions/mattermost/package.json +1 -1
  482. package/extensions/mattermost/src/mattermost/monitor-onchar.ts +25 -0
  483. package/extensions/mattermost/src/mattermost/monitor-websocket.ts +221 -0
  484. package/extensions/mattermost/src/mattermost/reactions.ts +130 -0
  485. package/extensions/mattermost/src/mattermost/reconnect.ts +103 -0
  486. package/extensions/memory-core/package.json +1 -1
  487. package/extensions/memory-lancedb/package.json +1 -1
  488. package/extensions/minimax-portal-auth/index.ts +161 -0
  489. package/extensions/minimax-portal-auth/oauth.ts +247 -0
  490. package/extensions/msteams/CHANGELOG.md +5 -0
  491. package/extensions/msteams/package.json +1 -1
  492. package/extensions/msteams/src/file-lock.ts +1 -0
  493. package/extensions/msteams/src/graph.ts +92 -0
  494. package/extensions/msteams/src/mentions.ts +114 -0
  495. package/extensions/msteams/src/test-runtime.ts +16 -0
  496. package/extensions/nextcloud-talk/package.json +1 -1
  497. package/extensions/nostr/CHANGELOG.md +5 -0
  498. package/extensions/nostr/package.json +1 -1
  499. package/extensions/open-prose/package.json +1 -1
  500. package/extensions/openai-codex-auth/index.ts +177 -0
  501. package/extensions/phone-control/index.ts +421 -0
  502. package/extensions/shared/resolve-target-test-helpers.ts +66 -0
  503. package/extensions/signal/package.json +1 -1
  504. package/extensions/signal/src/channel.js +273 -0
  505. package/extensions/signal/src/runtime.js +10 -0
  506. package/extensions/slack/package.json +1 -1
  507. package/extensions/slack/src/channel.js +489 -0
  508. package/extensions/slack/src/runtime.js +10 -0
  509. package/extensions/talk-voice/index.ts +150 -0
  510. package/extensions/telegram/package.json +1 -1
  511. package/extensions/telegram/src/channel.js +424 -0
  512. package/extensions/telegram/src/runtime.js +10 -0
  513. package/extensions/thread-ownership/index.ts +133 -0
  514. package/extensions/tlon/package.json +1 -1
  515. package/extensions/tlon/src/account-fields.ts +25 -0
  516. package/extensions/tlon/src/urbit/base-url.ts +57 -0
  517. package/extensions/tlon/src/urbit/channel-client.ts +157 -0
  518. package/extensions/tlon/src/urbit/channel-ops.ts +164 -0
  519. package/extensions/tlon/src/urbit/context.ts +47 -0
  520. package/extensions/tlon/src/urbit/errors.ts +51 -0
  521. package/extensions/tlon/src/urbit/fetch.ts +39 -0
  522. package/extensions/twitch/CHANGELOG.md +5 -0
  523. package/extensions/twitch/package.json +1 -1
  524. package/extensions/twitch/src/test-fixtures.ts +30 -0
  525. package/extensions/voice-call/CHANGELOG.md +5 -0
  526. package/extensions/voice-call/package.json +1 -1
  527. package/extensions/voice-call/src/allowlist.ts +19 -0
  528. package/extensions/whatsapp/package.json +1 -1
  529. package/extensions/whatsapp/src/channel.js +429 -0
  530. package/extensions/whatsapp/src/runtime.js +10 -0
  531. package/extensions/zalo/CHANGELOG.md +5 -0
  532. package/extensions/zalo/package.json +1 -1
  533. package/extensions/zalouser/CHANGELOG.md +5 -0
  534. package/extensions/zalouser/package.json +1 -1
  535. package/package.json +1 -1
@@ -0,0 +1,63 @@
1
+ // Exponential backoff schedule for command polling
2
+ const BACKOFF_SCHEDULE_MS = [5000, 10000, 30000, 60000];
3
+ /**
4
+ * Calculate suggested retry delay based on consecutive no-output poll count.
5
+ * Implements exponential backoff schedule: 5s → 10s → 30s → 60s (capped).
6
+ */
7
+ export function calculateBackoffMs(consecutiveNoOutputPolls) {
8
+ const index = Math.min(consecutiveNoOutputPolls, BACKOFF_SCHEDULE_MS.length - 1);
9
+ return BACKOFF_SCHEDULE_MS[index] ?? 60000;
10
+ }
11
+ /**
12
+ * Record a command poll and return suggested retry delay.
13
+ * @param state Session state to track polling in
14
+ * @param commandId Unique identifier for the command being polled
15
+ * @param hasNewOutput Whether this poll returned new output
16
+ * @returns Suggested delay in milliseconds before next poll
17
+ */
18
+ export function recordCommandPoll(state, commandId, hasNewOutput) {
19
+ if (!state.commandPollCounts) {
20
+ state.commandPollCounts = new Map();
21
+ }
22
+ const existing = state.commandPollCounts.get(commandId);
23
+ const now = Date.now();
24
+ if (hasNewOutput) {
25
+ state.commandPollCounts.set(commandId, { count: 0, lastPollAt: now });
26
+ return BACKOFF_SCHEDULE_MS[0] ?? 5000;
27
+ }
28
+ const newCount = (existing?.count ?? -1) + 1;
29
+ state.commandPollCounts.set(commandId, { count: newCount, lastPollAt: now });
30
+ return calculateBackoffMs(newCount);
31
+ }
32
+ /**
33
+ * Get current suggested backoff for a command without modifying state.
34
+ * Useful for checking current backoff level.
35
+ */
36
+ export function getCommandPollSuggestion(state, commandId) {
37
+ const pollData = state.commandPollCounts?.get(commandId);
38
+ if (!pollData) {
39
+ return undefined;
40
+ }
41
+ return calculateBackoffMs(pollData.count);
42
+ }
43
+ /**
44
+ * Reset poll count for a command (e.g., when command completes).
45
+ */
46
+ export function resetCommandPollCount(state, commandId) {
47
+ state.commandPollCounts?.delete(commandId);
48
+ }
49
+ /**
50
+ * Prune stale command poll records (older than 1 hour).
51
+ * Call periodically to prevent memory bloat.
52
+ */
53
+ export function pruneStaleCommandPolls(state, maxAgeMs = 3600000) {
54
+ if (!state.commandPollCounts) {
55
+ return;
56
+ }
57
+ const now = Date.now();
58
+ for (const [commandId, data] of state.commandPollCounts.entries()) {
59
+ if (now - data.lastPollAt > maxAgeMs) {
60
+ state.commandPollCounts.delete(commandId);
61
+ }
62
+ }
63
+ }
@@ -0,0 +1,16 @@
1
+ import { formatUserTime, resolveUserTimeFormat, resolveUserTimezone, } from "./date-time.js";
2
+ export function resolveCronStyleNow(cfg, nowMs) {
3
+ const userTimezone = resolveUserTimezone(cfg.agents?.defaults?.userTimezone);
4
+ const userTimeFormat = resolveUserTimeFormat(cfg.agents?.defaults?.timeFormat);
5
+ const formattedTime = formatUserTime(new Date(nowMs), userTimezone, userTimeFormat) ?? new Date(nowMs).toISOString();
6
+ const timeLine = `Current time: ${formattedTime} (${userTimezone})`;
7
+ return { userTimezone, formattedTime, timeLine };
8
+ }
9
+ export function appendCronStyleCurrentTimeLine(text, cfg, nowMs) {
10
+ const base = text.trimEnd();
11
+ if (!base || base.includes("Current time:")) {
12
+ return base;
13
+ }
14
+ const { timeLine } = resolveCronStyleNow(cfg, nowMs);
15
+ return `${base}\n${timeLine}`;
16
+ }
@@ -0,0 +1,42 @@
1
+ function escapeRegex(value) {
2
+ // Standard "escape string for regex literal" pattern.
3
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
4
+ }
5
+ export function compileGlobPattern(params) {
6
+ const normalized = params.normalize(params.raw);
7
+ if (!normalized) {
8
+ return { kind: "exact", value: "" };
9
+ }
10
+ if (normalized === "*") {
11
+ return { kind: "all" };
12
+ }
13
+ if (!normalized.includes("*")) {
14
+ return { kind: "exact", value: normalized };
15
+ }
16
+ return {
17
+ kind: "regex",
18
+ value: new RegExp(`^${escapeRegex(normalized).replaceAll("\\*", ".*")}$`),
19
+ };
20
+ }
21
+ export function compileGlobPatterns(params) {
22
+ if (!Array.isArray(params.raw)) {
23
+ return [];
24
+ }
25
+ return params.raw
26
+ .map((raw) => compileGlobPattern({ raw, normalize: params.normalize }))
27
+ .filter((pattern) => pattern.kind !== "exact" || pattern.value);
28
+ }
29
+ export function matchesAnyGlobPattern(value, patterns) {
30
+ for (const pattern of patterns) {
31
+ if (pattern.kind === "all") {
32
+ return true;
33
+ }
34
+ if (pattern.kind === "exact" && value === pattern.value) {
35
+ return true;
36
+ }
37
+ if (pattern.kind === "regex" && pattern.value.test(value)) {
38
+ return true;
39
+ }
40
+ }
41
+ return false;
42
+ }
@@ -17,6 +17,10 @@ const DEFAULT_HYBRID_ENABLED = true;
17
17
  const DEFAULT_HYBRID_VECTOR_WEIGHT = 0.7;
18
18
  const DEFAULT_HYBRID_TEXT_WEIGHT = 0.3;
19
19
  const DEFAULT_HYBRID_CANDIDATE_MULTIPLIER = 4;
20
+ const DEFAULT_MMR_ENABLED = false;
21
+ const DEFAULT_MMR_LAMBDA = 0.7;
22
+ const DEFAULT_TEMPORAL_DECAY_ENABLED = false;
23
+ const DEFAULT_TEMPORAL_DECAY_HALF_LIFE_DAYS = 30;
20
24
  const DEFAULT_CACHE_ENABLED = true;
21
25
  const DEFAULT_SOURCES = ["memory"];
22
26
  function normalizeSources(sources, sessionMemoryEnabled) {
@@ -141,6 +145,22 @@ function mergeConfig(defaults, overrides, agentId) {
141
145
  candidateMultiplier: overrides?.query?.hybrid?.candidateMultiplier ??
142
146
  defaults?.query?.hybrid?.candidateMultiplier ??
143
147
  DEFAULT_HYBRID_CANDIDATE_MULTIPLIER,
148
+ mmr: {
149
+ enabled: overrides?.query?.hybrid?.mmr?.enabled ??
150
+ defaults?.query?.hybrid?.mmr?.enabled ??
151
+ DEFAULT_MMR_ENABLED,
152
+ lambda: overrides?.query?.hybrid?.mmr?.lambda ??
153
+ defaults?.query?.hybrid?.mmr?.lambda ??
154
+ DEFAULT_MMR_LAMBDA,
155
+ },
156
+ temporalDecay: {
157
+ enabled: overrides?.query?.hybrid?.temporalDecay?.enabled ??
158
+ defaults?.query?.hybrid?.temporalDecay?.enabled ??
159
+ DEFAULT_TEMPORAL_DECAY_ENABLED,
160
+ halfLifeDays: overrides?.query?.hybrid?.temporalDecay?.halfLifeDays ??
161
+ defaults?.query?.hybrid?.temporalDecay?.halfLifeDays ??
162
+ DEFAULT_TEMPORAL_DECAY_HALF_LIFE_DAYS,
163
+ },
144
164
  };
145
165
  const cache = {
146
166
  enabled: overrides?.cache?.enabled ?? defaults?.cache?.enabled ?? DEFAULT_CACHE_ENABLED,
@@ -154,6 +174,9 @@ function mergeConfig(defaults, overrides, agentId) {
154
174
  const normalizedVectorWeight = sum > 0 ? vectorWeight / sum : DEFAULT_HYBRID_VECTOR_WEIGHT;
155
175
  const normalizedTextWeight = sum > 0 ? textWeight / sum : DEFAULT_HYBRID_TEXT_WEIGHT;
156
176
  const candidateMultiplier = clampInt(hybrid.candidateMultiplier, 1, 20);
177
+ const temporalDecayHalfLifeDays = Math.max(1, Math.floor(Number.isFinite(hybrid.temporalDecay.halfLifeDays)
178
+ ? hybrid.temporalDecay.halfLifeDays
179
+ : DEFAULT_TEMPORAL_DECAY_HALF_LIFE_DAYS));
157
180
  const deltaBytes = clampInt(sync.sessions.deltaBytes, 0, Number.MAX_SAFE_INTEGER);
158
181
  const deltaMessages = clampInt(sync.sessions.deltaMessages, 0, Number.MAX_SAFE_INTEGER);
159
182
  return {
@@ -185,6 +208,16 @@ function mergeConfig(defaults, overrides, agentId) {
185
208
  vectorWeight: normalizedVectorWeight,
186
209
  textWeight: normalizedTextWeight,
187
210
  candidateMultiplier,
211
+ mmr: {
212
+ enabled: Boolean(hybrid.mmr.enabled),
213
+ lambda: Number.isFinite(hybrid.mmr.lambda)
214
+ ? Math.max(0, Math.min(1, hybrid.mmr.lambda))
215
+ : DEFAULT_MMR_LAMBDA,
216
+ },
217
+ temporalDecay: {
218
+ enabled: Boolean(hybrid.temporalDecay.enabled),
219
+ halfLifeDays: temporalDecayHalfLifeDays,
220
+ },
188
221
  },
189
222
  },
190
223
  cache: {
@@ -0,0 +1,18 @@
1
+ export function buildModelAliasLines(cfg) {
2
+ const models = cfg?.agents?.defaults?.models ?? {};
3
+ const entries = [];
4
+ for (const [keyRaw, entryRaw] of Object.entries(models)) {
5
+ const model = String(keyRaw ?? "").trim();
6
+ if (!model) {
7
+ continue;
8
+ }
9
+ const alias = String(entryRaw?.alias ?? "").trim();
10
+ if (!alias) {
11
+ continue;
12
+ }
13
+ entries.push({ alias, model });
14
+ }
15
+ return entries
16
+ .toSorted((a, b) => a.alias.localeCompare(b.alias))
17
+ .map((entry) => `- ${entry.alias}: ${entry.model}`);
18
+ }
@@ -0,0 +1,61 @@
1
+ import { ensureAuthProfileStore, resolveAuthProfileDisplayLabel, resolveAuthProfileOrder, } from "./auth-profiles.js";
2
+ import { getCustomProviderApiKey, resolveEnvApiKey } from "./model-auth.js";
3
+ import { normalizeProviderId } from "./model-selection.js";
4
+ function formatApiKeySnippet(apiKey) {
5
+ const compact = apiKey.replace(/\s+/g, "");
6
+ if (!compact) {
7
+ return "unknown";
8
+ }
9
+ const edge = compact.length >= 12 ? 6 : 4;
10
+ const head = compact.slice(0, edge);
11
+ const tail = compact.slice(-edge);
12
+ return `${head}…${tail}`;
13
+ }
14
+ export function resolveModelAuthLabel(params) {
15
+ const resolvedProvider = params.provider?.trim();
16
+ if (!resolvedProvider) {
17
+ return undefined;
18
+ }
19
+ const providerKey = normalizeProviderId(resolvedProvider);
20
+ const store = ensureAuthProfileStore(params.agentDir, {
21
+ allowKeychainPrompt: false,
22
+ });
23
+ const profileOverride = params.sessionEntry?.authProfileOverride?.trim();
24
+ const order = resolveAuthProfileOrder({
25
+ cfg: params.cfg,
26
+ store,
27
+ provider: providerKey,
28
+ preferredProfile: profileOverride,
29
+ });
30
+ const candidates = [profileOverride, ...order].filter(Boolean);
31
+ for (const profileId of candidates) {
32
+ const profile = store.profiles[profileId];
33
+ if (!profile || normalizeProviderId(profile.provider) !== providerKey) {
34
+ continue;
35
+ }
36
+ const label = resolveAuthProfileDisplayLabel({
37
+ cfg: params.cfg,
38
+ store,
39
+ profileId,
40
+ });
41
+ if (profile.type === "oauth") {
42
+ return `oauth${label ? ` (${label})` : ""}`;
43
+ }
44
+ if (profile.type === "token") {
45
+ return `token ${formatApiKeySnippet(profile.token)}${label ? ` (${label})` : ""}`;
46
+ }
47
+ return `api-key ${formatApiKeySnippet(profile.key ?? "")}${label ? ` (${label})` : ""}`;
48
+ }
49
+ const envKey = resolveEnvApiKey(providerKey);
50
+ if (envKey?.apiKey) {
51
+ if (envKey.source.includes("OAUTH_TOKEN")) {
52
+ return `oauth (${envKey.source})`;
53
+ }
54
+ return `api-key ${formatApiKeySnippet(envKey.apiKey)} (${envKey.source})`;
55
+ }
56
+ const customKey = getCustomProviderApiKey(params.cfg, providerKey);
57
+ if (customKey) {
58
+ return `api-key ${formatApiKeySnippet(customKey)} (models.json)`;
59
+ }
60
+ return "unknown";
61
+ }
@@ -1,7 +1,7 @@
1
1
  import { DEFAULT_MODEL, DEFAULT_PROVIDER } from "./defaults.js";
2
2
  import { coerceToFailoverError, describeFailoverError, isFailoverError, isTimeoutError, } from "./failover-error.js";
3
3
  import { buildModelAliasIndex, modelKey, parseModelRef, resolveConfiguredModelRef, resolveModelRefFromString, } from "./model-selection.js";
4
- import { ensureAuthProfileStore, isProfileInCooldown, resolveAuthProfileOrder, } from "./auth-profiles.js";
4
+ import { ensureAuthProfileStore, getSoonestCooldownExpiry, isProfileInCooldown, resolveAuthProfileOrder, } from "./auth-profiles.js";
5
5
  function isAbortError(err) {
6
6
  if (!err || typeof err !== "object")
7
7
  return false;
@@ -135,6 +135,36 @@ function resolveFallbackCandidates(params) {
135
135
  }
136
136
  return candidates;
137
137
  }
138
+ const lastProbeAttempt = new Map();
139
+ const MIN_PROBE_INTERVAL_MS = 30_000; // 30 seconds between probes per key
140
+ const PROBE_MARGIN_MS = 2 * 60 * 1000;
141
+ const PROBE_SCOPE_DELIMITER = "::";
142
+ function resolveProbeThrottleKey(provider, agentDir) {
143
+ const scope = String(agentDir ?? "").trim();
144
+ return scope ? `${scope}${PROBE_SCOPE_DELIMITER}${provider}` : provider;
145
+ }
146
+ function shouldProbePrimaryDuringCooldown(params) {
147
+ if (!params.isPrimary || !params.hasFallbackCandidates) {
148
+ return false;
149
+ }
150
+ const lastProbe = lastProbeAttempt.get(params.throttleKey) ?? 0;
151
+ if (params.now - lastProbe < MIN_PROBE_INTERVAL_MS) {
152
+ return false;
153
+ }
154
+ const soonest = getSoonestCooldownExpiry(params.authStore, params.profileIds);
155
+ if (soonest === null || !Number.isFinite(soonest)) {
156
+ return true;
157
+ }
158
+ // Probe when cooldown already expired or within the configured margin.
159
+ return params.now >= soonest - PROBE_MARGIN_MS;
160
+ }
161
+ /** @internal – exposed for unit tests only */
162
+ export const _probeThrottleInternals = {
163
+ lastProbeAttempt,
164
+ MIN_PROBE_INTERVAL_MS,
165
+ PROBE_MARGIN_MS,
166
+ resolveProbeThrottleKey,
167
+ };
138
168
  export async function runWithModelFallback(params) {
139
169
  const candidates = resolveFallbackCandidates({
140
170
  cfg: params.cfg,
@@ -146,6 +176,7 @@ export async function runWithModelFallback(params) {
146
176
  ? ensureAuthProfileStore(params.agentDir, { allowKeychainPrompt: false })
147
177
  : null;
148
178
  const attempts = [];
179
+ const hasFallbackCandidates = candidates.length > 1;
149
180
  let lastError;
150
181
  for (let i = 0; i < candidates.length; i += 1) {
151
182
  const candidate = candidates[i];
@@ -157,14 +188,34 @@ export async function runWithModelFallback(params) {
157
188
  });
158
189
  const isAnyProfileAvailable = profileIds.some((id) => !isProfileInCooldown(authStore, id));
159
190
  if (profileIds.length > 0 && !isAnyProfileAvailable) {
160
- // All profiles for this provider are in cooldown; skip without attempting
161
- attempts.push({
162
- provider: candidate.provider,
163
- model: candidate.model,
164
- error: `Provider ${candidate.provider} is in cooldown (all profiles unavailable)`,
165
- reason: "rate_limit",
191
+ // All profiles for this provider are in cooldown.
192
+ // For the primary model (i === 0), probe it if the soonest cooldown
193
+ // expiry is close or already past. This avoids staying on a fallback
194
+ // model long after the real rate-limit window clears.
195
+ const now = Date.now();
196
+ const probeThrottleKey = resolveProbeThrottleKey(candidate.provider, params.agentDir);
197
+ const shouldProbe = shouldProbePrimaryDuringCooldown({
198
+ isPrimary: i === 0,
199
+ hasFallbackCandidates,
200
+ now,
201
+ throttleKey: probeThrottleKey,
202
+ authStore,
203
+ profileIds,
166
204
  });
167
- continue;
205
+ if (!shouldProbe) {
206
+ // Skip without attempting
207
+ attempts.push({
208
+ provider: candidate.provider,
209
+ model: candidate.model,
210
+ error: `Provider ${candidate.provider} is in cooldown (all profiles unavailable)`,
211
+ reason: "rate_limit",
212
+ });
213
+ continue;
214
+ }
215
+ // Primary model probe: attempt it despite cooldown to detect recovery.
216
+ // If it fails, the error is caught below and we fall through to the
217
+ // next candidate as usual.
218
+ lastProbeAttempt.set(probeThrottleKey, now);
168
219
  }
169
220
  }
170
221
  try {
@@ -0,0 +1,115 @@
1
+ import { withTempHome as withTempHomeBase } from "../../test/helpers/temp-home.js";
2
+ import { afterEach, beforeEach, vi } from "vitest";
3
+ export async function withModelsTempHome(fn) {
4
+ return withTempHomeBase(fn, { prefix: "openclaw-models-" });
5
+ }
6
+ export function installModelsConfigTestHooks(opts) {
7
+ let previousHome;
8
+ const originalFetch = globalThis.fetch;
9
+ beforeEach(() => {
10
+ previousHome = process.env.HOME;
11
+ });
12
+ afterEach(() => {
13
+ process.env.HOME = previousHome;
14
+ if (opts?.restoreFetch && originalFetch) {
15
+ globalThis.fetch = originalFetch;
16
+ }
17
+ });
18
+ }
19
+ export async function withTempEnv(vars, fn) {
20
+ const previous = {};
21
+ for (const envVar of vars) {
22
+ previous[envVar] = process.env[envVar];
23
+ }
24
+ try {
25
+ return await fn();
26
+ }
27
+ finally {
28
+ for (const envVar of vars) {
29
+ const value = previous[envVar];
30
+ if (value === undefined) {
31
+ delete process.env[envVar];
32
+ }
33
+ else {
34
+ process.env[envVar] = value;
35
+ }
36
+ }
37
+ }
38
+ }
39
+ export function unsetEnv(vars) {
40
+ for (const envVar of vars) {
41
+ delete process.env[envVar];
42
+ }
43
+ }
44
+ export const COPILOT_TOKEN_ENV_VARS = ["COPILOT_GITHUB_TOKEN", "GH_TOKEN", "GITHUB_TOKEN"];
45
+ export async function withUnsetCopilotTokenEnv(fn) {
46
+ return withTempEnv(COPILOT_TOKEN_ENV_VARS, async () => {
47
+ unsetEnv(COPILOT_TOKEN_ENV_VARS);
48
+ return fn();
49
+ });
50
+ }
51
+ export function mockCopilotTokenExchangeSuccess() {
52
+ const fetchMock = vi.fn().mockResolvedValue({
53
+ ok: true,
54
+ status: 200,
55
+ json: async () => ({
56
+ token: "copilot-token;proxy-ep=proxy.copilot.example",
57
+ expires_at: Math.floor(Date.now() / 1000) + 3600,
58
+ }),
59
+ });
60
+ globalThis.fetch = fetchMock;
61
+ return fetchMock;
62
+ }
63
+ export const MODELS_CONFIG_IMPLICIT_ENV_VARS = [
64
+ "CLOUDFLARE_AI_GATEWAY_API_KEY",
65
+ "COPILOT_GITHUB_TOKEN",
66
+ "GH_TOKEN",
67
+ "GITHUB_TOKEN",
68
+ "HF_TOKEN",
69
+ "HUGGINGFACE_HUB_TOKEN",
70
+ "MINIMAX_API_KEY",
71
+ "MOONSHOT_API_KEY",
72
+ "NVIDIA_API_KEY",
73
+ "OLLAMA_API_KEY",
74
+ "POOLBOT_AGENT_DIR",
75
+ "PI_CODING_AGENT_DIR",
76
+ "QIANFAN_API_KEY",
77
+ "SYNTHETIC_API_KEY",
78
+ "TOGETHER_API_KEY",
79
+ "VENICE_API_KEY",
80
+ "VLLM_API_KEY",
81
+ "XIAOMI_API_KEY",
82
+ // Avoid ambient AWS creds unintentionally enabling Bedrock discovery.
83
+ "AWS_ACCESS_KEY_ID",
84
+ "AWS_CONFIG_FILE",
85
+ "AWS_BEARER_TOKEN_BEDROCK",
86
+ "AWS_DEFAULT_REGION",
87
+ "AWS_PROFILE",
88
+ "AWS_REGION",
89
+ "AWS_SESSION_TOKEN",
90
+ "AWS_SECRET_ACCESS_KEY",
91
+ "AWS_SHARED_CREDENTIALS_FILE",
92
+ ];
93
+ export const CUSTOM_PROXY_MODELS_CONFIG = {
94
+ models: {
95
+ providers: {
96
+ "custom-proxy": {
97
+ baseUrl: "http://localhost:4000/v1",
98
+ apiKey: "TEST_KEY",
99
+ api: "openai-completions",
100
+ models: [
101
+ {
102
+ id: "llama-3.1-8b",
103
+ name: "Llama 3.1 8B (Proxy)",
104
+ api: "openai-completions",
105
+ reasoning: false,
106
+ input: ["text"],
107
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
108
+ contextWindow: 128000,
109
+ maxTokens: 32000,
110
+ },
111
+ ],
112
+ },
113
+ },
114
+ },
115
+ };
@@ -1,5 +1,5 @@
1
- import { createAssistantMessageEventStream } from "@mariozechner/pi-ai";
2
1
  import { randomUUID } from "node:crypto";
2
+ import { createAssistantMessageEventStream } from "@mariozechner/pi-ai";
3
3
  export const OLLAMA_NATIVE_BASE_URL = "http://127.0.0.1:11434";
4
4
  function extractTextContent(content) {
5
5
  if (typeof content === "string") {
@@ -102,8 +102,12 @@ function extractOllamaTools(tools) {
102
102
  // ── Response conversion ─────────────────────────────────────────────────────
103
103
  export function buildAssistantMessage(response, modelInfo) {
104
104
  const content = [];
105
- if (response.message.content) {
106
- content.push({ type: "text", text: response.message.content });
105
+ // Qwen 3 (and potentially other reasoning models) may return their final
106
+ // answer in a `reasoning` field with an empty `content`. Fall back to
107
+ // `reasoning` so the response isn't silently dropped.
108
+ const text = response.message.content || response.message.reasoning || "";
109
+ if (text) {
110
+ content.push({ type: "text", text });
107
111
  }
108
112
  const toolCalls = response.message.tool_calls;
109
113
  if (toolCalls && toolCalls.length > 0) {
@@ -230,6 +234,10 @@ export function createOllamaStreamFn(baseUrl) {
230
234
  if (chunk.message?.content) {
231
235
  accumulatedContent += chunk.message.content;
232
236
  }
237
+ else if (chunk.message?.reasoning) {
238
+ // Qwen 3 reasoning mode: content may be empty, output in reasoning
239
+ accumulatedContent += chunk.message.reasoning;
240
+ }
233
241
  // Ollama sends tool_calls in intermediate (done:false) chunks,
234
242
  // NOT in the final done:true chunk. Collect from all chunks.
235
243
  if (chunk.message?.tool_calls) {
@@ -0,0 +1,135 @@
1
+ import { resolvePluginTools } from "../plugins/tools.js";
2
+ import { resolveSessionAgentId } from "./agent-scope.js";
3
+ import { createAgentsListTool } from "./tools/agents-list-tool.js";
4
+ import { createBrowserTool } from "./tools/browser-tool.js";
5
+ import { createCanvasTool } from "./tools/canvas-tool.js";
6
+ import { createCronTool } from "./tools/cron-tool.js";
7
+ import { createGatewayTool } from "./tools/gateway-tool.js";
8
+ import { createImageTool } from "./tools/image-tool.js";
9
+ import { createMessageTool } from "./tools/message-tool.js";
10
+ import { createNodesTool } from "./tools/nodes-tool.js";
11
+ import { createSessionStatusTool } from "./tools/session-status-tool.js";
12
+ import { createSessionsHistoryTool } from "./tools/sessions-history-tool.js";
13
+ import { createSessionsListTool } from "./tools/sessions-list-tool.js";
14
+ import { createSessionsSendTool } from "./tools/sessions-send-tool.js";
15
+ import { createSessionsSpawnTool } from "./tools/sessions-spawn-tool.js";
16
+ import { createSubagentsTool } from "./tools/subagents-tool.js";
17
+ import { createTtsTool } from "./tools/tts-tool.js";
18
+ import { createWebFetchTool, createWebSearchTool } from "./tools/web-tools.js";
19
+ import { resolveWorkspaceRoot } from "./workspace-dir.js";
20
+ export function createOpenClawTools(options) {
21
+ const workspaceDir = resolveWorkspaceRoot(options?.workspaceDir);
22
+ const imageTool = options?.agentDir?.trim()
23
+ ? createImageTool({
24
+ config: options?.config,
25
+ agentDir: options.agentDir,
26
+ workspaceDir,
27
+ sandbox: options?.sandboxRoot && options?.sandboxFsBridge
28
+ ? { root: options.sandboxRoot, bridge: options.sandboxFsBridge }
29
+ : undefined,
30
+ modelHasVision: options?.modelHasVision,
31
+ })
32
+ : null;
33
+ const webSearchTool = createWebSearchTool({
34
+ config: options?.config,
35
+ sandboxed: options?.sandboxed,
36
+ });
37
+ const webFetchTool = createWebFetchTool({
38
+ config: options?.config,
39
+ sandboxed: options?.sandboxed,
40
+ });
41
+ const messageTool = options?.disableMessageTool
42
+ ? null
43
+ : createMessageTool({
44
+ agentAccountId: options?.agentAccountId,
45
+ agentSessionKey: options?.agentSessionKey,
46
+ config: options?.config,
47
+ currentChannelId: options?.currentChannelId,
48
+ currentChannelProvider: options?.agentChannel,
49
+ currentThreadTs: options?.currentThreadTs,
50
+ replyToMode: options?.replyToMode,
51
+ hasRepliedRef: options?.hasRepliedRef,
52
+ sandboxRoot: options?.sandboxRoot,
53
+ requireExplicitTarget: options?.requireExplicitMessageTarget,
54
+ });
55
+ const tools = [
56
+ createBrowserTool({
57
+ sandboxBridgeUrl: options?.sandboxBrowserBridgeUrl,
58
+ allowHostControl: options?.allowHostBrowserControl,
59
+ }),
60
+ createCanvasTool(),
61
+ createNodesTool({
62
+ agentSessionKey: options?.agentSessionKey,
63
+ config: options?.config,
64
+ }),
65
+ createCronTool({
66
+ agentSessionKey: options?.agentSessionKey,
67
+ }),
68
+ ...(messageTool ? [messageTool] : []),
69
+ createTtsTool({
70
+ agentChannel: options?.agentChannel,
71
+ config: options?.config,
72
+ }),
73
+ createGatewayTool({
74
+ agentSessionKey: options?.agentSessionKey,
75
+ config: options?.config,
76
+ }),
77
+ createAgentsListTool({
78
+ agentSessionKey: options?.agentSessionKey,
79
+ requesterAgentIdOverride: options?.requesterAgentIdOverride,
80
+ }),
81
+ createSessionsListTool({
82
+ agentSessionKey: options?.agentSessionKey,
83
+ sandboxed: options?.sandboxed,
84
+ }),
85
+ createSessionsHistoryTool({
86
+ agentSessionKey: options?.agentSessionKey,
87
+ sandboxed: options?.sandboxed,
88
+ }),
89
+ createSessionsSendTool({
90
+ agentSessionKey: options?.agentSessionKey,
91
+ agentChannel: options?.agentChannel,
92
+ sandboxed: options?.sandboxed,
93
+ }),
94
+ createSessionsSpawnTool({
95
+ agentSessionKey: options?.agentSessionKey,
96
+ agentChannel: options?.agentChannel,
97
+ agentAccountId: options?.agentAccountId,
98
+ agentTo: options?.agentTo,
99
+ agentThreadId: options?.agentThreadId,
100
+ agentGroupId: options?.agentGroupId,
101
+ agentGroupChannel: options?.agentGroupChannel,
102
+ agentGroupSpace: options?.agentGroupSpace,
103
+ sandboxed: options?.sandboxed,
104
+ requesterAgentIdOverride: options?.requesterAgentIdOverride,
105
+ }),
106
+ createSubagentsTool({
107
+ agentSessionKey: options?.agentSessionKey,
108
+ }),
109
+ createSessionStatusTool({
110
+ agentSessionKey: options?.agentSessionKey,
111
+ config: options?.config,
112
+ }),
113
+ ...(webSearchTool ? [webSearchTool] : []),
114
+ ...(webFetchTool ? [webFetchTool] : []),
115
+ ...(imageTool ? [imageTool] : []),
116
+ ];
117
+ const pluginTools = resolvePluginTools({
118
+ context: {
119
+ config: options?.config,
120
+ workspaceDir,
121
+ agentDir: options?.agentDir,
122
+ agentId: resolveSessionAgentId({
123
+ sessionKey: options?.agentSessionKey,
124
+ config: options?.config,
125
+ }),
126
+ sessionKey: options?.agentSessionKey,
127
+ messageChannel: options?.agentChannel,
128
+ agentAccountId: options?.agentAccountId,
129
+ sandboxed: options?.sandboxed,
130
+ },
131
+ existingToolNames: new Set(tools.map((tool) => tool.name)),
132
+ toolAllowlist: options?.pluginToolAllowlist,
133
+ });
134
+ return [...tools, ...pluginTools];
135
+ }