@poolzin/pool-bot 2026.2.20 → 2026.2.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (388) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/dist/agents/api-key-rotation.js +47 -0
  3. package/dist/agents/apply-patch-update.js +19 -9
  4. package/dist/agents/apply-patch.js +72 -47
  5. package/dist/agents/bash-tools.exec.js +141 -559
  6. package/dist/agents/cli-backends.js +49 -6
  7. package/dist/agents/cli-runner/helpers.js +69 -152
  8. package/dist/agents/cli-runner.js +70 -19
  9. package/dist/agents/identity.js +20 -1
  10. package/dist/agents/image-sanitization.js +9 -0
  11. package/dist/agents/live-auth-keys.js +123 -26
  12. package/dist/agents/live-model-filter.js +13 -4
  13. package/dist/agents/model-auth.js +12 -0
  14. package/dist/agents/model-catalog.js +40 -9
  15. package/dist/agents/model-fallback.js +24 -0
  16. package/dist/agents/model-forward-compat.js +60 -23
  17. package/dist/agents/model-selection.js +134 -41
  18. package/dist/agents/pi-auth-json.js +2 -2
  19. package/dist/agents/pi-embedded-helpers/bootstrap.js +65 -15
  20. package/dist/agents/pi-embedded-helpers/errors.js +140 -15
  21. package/dist/agents/pi-embedded-helpers/images.js +22 -12
  22. package/dist/agents/pi-embedded-helpers.js +2 -2
  23. package/dist/agents/pi-embedded-runner/abort.js +10 -3
  24. package/dist/agents/pi-embedded-runner/compact.js +230 -32
  25. package/dist/agents/pi-embedded-runner/extra-params.js +203 -12
  26. package/dist/agents/pi-embedded-runner/google.js +109 -19
  27. package/dist/agents/pi-embedded-runner/history.js +35 -17
  28. package/dist/agents/pi-embedded-runner/run/attempt.js +386 -80
  29. package/dist/agents/pi-embedded-runner/run/images.js +81 -55
  30. package/dist/agents/pi-embedded-runner/run/payloads.js +89 -39
  31. package/dist/agents/pi-embedded-runner/run.js +193 -25
  32. package/dist/agents/pi-embedded-runner/run.overflow-compaction.mocks.shared.js +2 -2
  33. package/dist/agents/pi-embedded-runner/runs.js +17 -8
  34. package/dist/agents/pi-embedded-runner/tool-result-context-guard.js +262 -0
  35. package/dist/agents/pi-embedded-runner.js +1 -1
  36. package/dist/agents/pi-embedded-subscribe.handlers.tools.js +180 -10
  37. package/dist/agents/pi-embedded-subscribe.js +37 -0
  38. package/dist/agents/pi-embedded-subscribe.tools.js +127 -30
  39. package/dist/agents/pi-model-discovery.js +9 -2
  40. package/dist/agents/pi-tool-definition-adapter.js +60 -8
  41. package/dist/agents/pi-tools.before-tool-call.js +1 -1
  42. package/dist/agents/pi-tools.js +113 -94
  43. package/dist/agents/pi-tools.read.js +337 -38
  44. package/dist/agents/poolbot-tools.js +14 -5
  45. package/dist/agents/provider/config-loader.js +76 -0
  46. package/dist/agents/provider/index.js +15 -0
  47. package/dist/agents/provider/integration.js +136 -0
  48. package/dist/agents/provider/models-dev.js +129 -0
  49. package/dist/agents/provider/rate-limits.js +458 -0
  50. package/dist/agents/provider/request-monitor.js +449 -0
  51. package/dist/agents/provider/session-binding.js +376 -0
  52. package/dist/agents/provider/token-pool.js +541 -0
  53. package/dist/agents/sandbox/docker.js +10 -5
  54. package/dist/agents/sandbox/registry.js +96 -46
  55. package/dist/agents/sandbox/sanitize-env-vars.js +82 -0
  56. package/dist/agents/sandbox-paths.js +43 -10
  57. package/dist/agents/session-tool-result-guard-wrapper.js +23 -11
  58. package/dist/agents/session-tool-result-guard.js +39 -39
  59. package/dist/agents/session-transcript-repair.js +36 -33
  60. package/dist/agents/session-write-lock.js +62 -44
  61. package/dist/agents/skills/frontmatter.js +49 -88
  62. package/dist/agents/skills/workspace.js +335 -28
  63. package/dist/agents/subagent-announce.js +508 -174
  64. package/dist/agents/subagent-registry.js +45 -4
  65. package/dist/agents/subagent-spawn.js +16 -33
  66. package/dist/agents/system-prompt-report.js +27 -10
  67. package/dist/agents/system-prompt.js +26 -32
  68. package/dist/agents/tool-call-id.js +69 -17
  69. package/dist/agents/tool-display-common.js +1 -1
  70. package/dist/agents/tool-images.js +64 -31
  71. package/dist/agents/tools/canvas-tool.js +17 -11
  72. package/dist/agents/tools/common.js +37 -19
  73. package/dist/agents/tools/cron-tool.js +40 -38
  74. package/dist/agents/tools/gateway.js +70 -2
  75. package/dist/agents/tools/message-tool.js +181 -40
  76. package/dist/agents/tools/nodes-tool.js +128 -36
  77. package/dist/agents/tools/nodes-utils.js +12 -38
  78. package/dist/agents/tools/session-status-tool.js +24 -71
  79. package/dist/agents/tools/sessions-helpers.js +38 -210
  80. package/dist/agents/tools/sessions-spawn-tool.js +28 -198
  81. package/dist/agents/tools/telegram-actions.js +58 -7
  82. package/dist/agents/tools/web-fetch-utils.js +112 -7
  83. package/dist/agents/tools/web-fetch.js +279 -175
  84. package/dist/agents/tools/web-shared.js +71 -8
  85. package/dist/agents/usage.js +25 -16
  86. package/dist/auto-reply/commands-registry.data.js +85 -11
  87. package/dist/auto-reply/dispatch.js +40 -21
  88. package/dist/auto-reply/reply/abort.js +102 -33
  89. package/dist/auto-reply/reply/commands-core.js +82 -33
  90. package/dist/auto-reply/reply/commands-export-session.js +1 -1
  91. package/dist/auto-reply/reply/commands-info.js +41 -12
  92. package/dist/auto-reply/reply/commands-subagents.js +352 -100
  93. package/dist/auto-reply/reply/commands-system-prompt.js +2 -2
  94. package/dist/auto-reply/reply/dispatch-from-config.js +100 -29
  95. package/dist/auto-reply/reply/elevated-unavailable.js +1 -1
  96. package/dist/auto-reply/reply/inbound-meta.js +12 -1
  97. package/dist/auto-reply/reply/mentions.js +18 -11
  98. package/dist/auto-reply/reply/normalize-reply.js +17 -8
  99. package/dist/auto-reply/reply/reply-dispatcher.js +62 -10
  100. package/dist/auto-reply/reply/session.js +102 -21
  101. package/dist/auto-reply/reply/streaming-directives.js +16 -5
  102. package/dist/auto-reply/status.js +73 -50
  103. package/dist/browser/extension-relay.js +3 -3
  104. package/dist/browser/http-auth.js +1 -1
  105. package/dist/browser/paths.js +2 -2
  106. package/dist/build-info.json +3 -3
  107. package/dist/channels/allowlist-match.js +20 -0
  108. package/dist/channels/allowlists/resolve-utils.js +65 -2
  109. package/dist/channels/chat-type.js +8 -4
  110. package/dist/channels/dock.js +127 -35
  111. package/dist/channels/draft-stream-loop.js +6 -2
  112. package/dist/channels/plugins/actions/telegram.js +42 -18
  113. package/dist/channels/plugins/allowlist-match.js +1 -1
  114. package/dist/channels/plugins/group-mentions.js +51 -41
  115. package/dist/channels/plugins/message-action-names.js +2 -0
  116. package/dist/channels/plugins/message-actions.js +24 -5
  117. package/dist/channels/plugins/normalize/discord.js +26 -4
  118. package/dist/channels/plugins/normalize/signal.js +35 -22
  119. package/dist/channels/plugins/onboarding/helpers.js +8 -26
  120. package/dist/channels/plugins/outbound/imessage.js +15 -14
  121. package/dist/channels/registry.js +20 -7
  122. package/dist/cli/acp-cli.js +7 -5
  123. package/dist/cli/browser-cli-extension.js +25 -12
  124. package/dist/cli/browser-cli-state.cookies-storage.js +25 -6
  125. package/dist/cli/browser-cli-state.js +101 -145
  126. package/dist/cli/command-options.js +28 -0
  127. package/dist/cli/completion-cli.js +6 -6
  128. package/dist/cli/cron-cli/register.cron-add.js +25 -1
  129. package/dist/cli/cron-cli/register.cron-edit.js +44 -0
  130. package/dist/cli/cron-cli/shared.js +7 -1
  131. package/dist/cli/daemon-cli/lifecycle-core.js +23 -21
  132. package/dist/cli/daemon-cli/lifecycle.js +23 -247
  133. package/dist/cli/daemon-cli/register-service-commands.js +25 -4
  134. package/dist/cli/daemon-cli.js +1 -0
  135. package/dist/cli/devices-cli.js +33 -20
  136. package/dist/cli/gateway-cli/register.js +37 -105
  137. package/dist/cli/gateway-cli/run.js +49 -11
  138. package/dist/cli/nodes-camera.js +59 -4
  139. package/dist/cli/nodes-cli/register.camera.js +27 -24
  140. package/dist/cli/nodes-cli/rpc.js +21 -38
  141. package/dist/cli/qr-cli.js +2 -2
  142. package/dist/cli/skills-cli.format.js +2 -2
  143. package/dist/cli/update-cli/progress.js +2 -2
  144. package/dist/cli/update-cli/restart-helper.js +28 -7
  145. package/dist/cli/update-cli/shared.js +7 -7
  146. package/dist/cli/update-cli/status.js +1 -1
  147. package/dist/cli/update-cli/update-command.js +14 -8
  148. package/dist/cli/update-cli/wizard.js +2 -2
  149. package/dist/cli/update-cli.js +21 -1027
  150. package/dist/commands/auth-choice.apply.anthropic.js +10 -2
  151. package/dist/commands/channels/add-mutators.js +3 -35
  152. package/dist/commands/channels/add.js +39 -51
  153. package/dist/commands/config-validation.js +1 -1
  154. package/dist/commands/configure.gateway-auth.js +52 -15
  155. package/dist/commands/configure.gateway.js +84 -40
  156. package/dist/commands/doctor-completion.js +3 -3
  157. package/dist/commands/doctor-config-flow.js +536 -16
  158. package/dist/commands/doctor-gateway-services.js +103 -79
  159. package/dist/commands/doctor-memory-search.js +9 -9
  160. package/dist/commands/doctor-platform-notes.js +57 -30
  161. package/dist/commands/doctor-prompter.js +26 -15
  162. package/dist/commands/doctor-session-locks.js +1 -1
  163. package/dist/commands/doctor.js +21 -9
  164. package/dist/commands/model-picker.js +120 -95
  165. package/dist/commands/models/set.js +2 -21
  166. package/dist/commands/models/shared.js +65 -37
  167. package/dist/commands/onboard-helpers.js +81 -39
  168. package/dist/commands/openai-codex-oauth.js +1 -1
  169. package/dist/commands/sessions.js +52 -53
  170. package/dist/commands/status.summary.js +52 -34
  171. package/dist/commands/test-wizard-helpers.js +2 -2
  172. package/dist/config/defaults.js +79 -42
  173. package/dist/config/group-policy.js +50 -18
  174. package/dist/config/includes.js +37 -10
  175. package/dist/config/schema.help.js +5 -4
  176. package/dist/config/schema.hints.js +2 -2
  177. package/dist/config/schema.labels.js +1 -0
  178. package/dist/config/sessions/group.js +12 -11
  179. package/dist/config/sessions/paths.js +137 -11
  180. package/dist/config/sessions/store.js +185 -65
  181. package/dist/config/sessions/types.js +15 -1
  182. package/dist/config/sessions.js +1 -0
  183. package/dist/config/telegram-custom-commands.js +3 -2
  184. package/dist/config/types.js +2 -0
  185. package/dist/config/zod-schema.agent-defaults.js +6 -27
  186. package/dist/config/zod-schema.agent-runtime.js +171 -79
  187. package/dist/config/zod-schema.providers-core.js +138 -65
  188. package/dist/config/zod-schema.session.js +49 -22
  189. package/dist/control-ui/assets/index-HRr1grwl.js.map +1 -1
  190. package/dist/cron/isolated-agent/run.js +224 -57
  191. package/dist/cron/normalize.js +48 -45
  192. package/dist/cron/run-log.js +14 -0
  193. package/dist/cron/service/jobs.js +190 -28
  194. package/dist/cron/service/normalize.js +29 -11
  195. package/dist/cron/service/store.js +30 -44
  196. package/dist/cron/service/timer.js +182 -96
  197. package/dist/cron/service.js +3 -0
  198. package/dist/cron/stagger.js +37 -0
  199. package/dist/daemon/inspect.js +132 -92
  200. package/dist/daemon/runtime-paths.js +25 -4
  201. package/dist/daemon/service-audit.js +47 -16
  202. package/dist/discord/accounts.js +23 -20
  203. package/dist/discord/monitor/agent-components.js +1115 -219
  204. package/dist/discord/monitor/allow-list.js +114 -34
  205. package/dist/discord/monitor/listeners.js +204 -97
  206. package/dist/discord/monitor/message-handler.js +21 -10
  207. package/dist/discord/monitor/message-handler.preflight.js +195 -101
  208. package/dist/discord/monitor/message-handler.process.js +384 -123
  209. package/dist/discord/monitor/message-utils.js +86 -23
  210. package/dist/discord/monitor/native-command.js +77 -57
  211. package/dist/discord/monitor/provider.js +122 -117
  212. package/dist/discord/monitor/reply-context.js +20 -16
  213. package/dist/discord/monitor/reply-delivery.js +40 -8
  214. package/dist/discord/monitor/rest-fetch.js +22 -0
  215. package/dist/discord/monitor/threading.js +117 -24
  216. package/dist/discord/send.js +2 -1
  217. package/dist/discord/send.outbound.js +124 -11
  218. package/dist/discord/send.shared.js +112 -72
  219. package/dist/discord/voice-message.js +3 -3
  220. package/dist/gateway/auth.js +119 -44
  221. package/dist/gateway/call.js +76 -34
  222. package/dist/gateway/channel-health-monitor.js +57 -50
  223. package/dist/gateway/client.js +63 -29
  224. package/dist/gateway/control-ui-contract.js +1 -1
  225. package/dist/gateway/gateway-config-prompts.shared.js +2 -2
  226. package/dist/gateway/net.js +109 -1
  227. package/dist/gateway/protocol/index.js +5 -8
  228. package/dist/gateway/protocol/schema/agent.js +19 -1
  229. package/dist/gateway/protocol/schema/channels.js +21 -0
  230. package/dist/gateway/protocol/schema/cron.js +43 -30
  231. package/dist/gateway/protocol/schema/protocol-schemas.js +6 -11
  232. package/dist/gateway/protocol/schema/sessions.js +5 -1
  233. package/dist/gateway/protocol/schema.js +0 -1
  234. package/dist/gateway/server/presence-events.js +12 -0
  235. package/dist/gateway/server/ws-connection/message-handler.js +203 -212
  236. package/dist/gateway/server/ws-connection.js +58 -21
  237. package/dist/gateway/server-broadcast.js +18 -13
  238. package/dist/gateway/server-cron.js +177 -10
  239. package/dist/gateway/server-methods/agent-job.js +131 -38
  240. package/dist/gateway/server-methods/send.js +60 -14
  241. package/dist/gateway/server-methods/sessions.js +160 -96
  242. package/dist/gateway/server-methods/system.js +5 -7
  243. package/dist/gateway/server-methods-list.js +8 -0
  244. package/dist/gateway/server-methods.js +24 -8
  245. package/dist/gateway/server-node-events.js +278 -68
  246. package/dist/gateway/session-utils.fs.js +316 -75
  247. package/dist/gateway/session-utils.js +224 -70
  248. package/dist/gateway/sessions-patch.js +63 -20
  249. package/dist/gateway/test-temp-config.js +1 -1
  250. package/dist/gateway/tools-invoke-http.js +118 -70
  251. package/dist/gateway/ws-log.js +135 -107
  252. package/dist/hooks/frontmatter.js +36 -82
  253. package/dist/hooks/install.js +149 -139
  254. package/dist/hooks/internal-hooks.js +29 -4
  255. package/dist/hooks/plugin-hooks.js +2 -1
  256. package/dist/imessage/monitor/deliver.js +10 -4
  257. package/dist/imessage/monitor/monitor-provider.js +138 -375
  258. package/dist/imessage/monitor/runtime.js +4 -8
  259. package/dist/imessage/send.js +65 -19
  260. package/dist/infra/exec-approvals-allowlist.js +7 -0
  261. package/dist/infra/exec-approvals.js +35 -920
  262. package/dist/infra/exec-safe-bin-trust.js +64 -0
  263. package/dist/infra/heartbeat-runner.js +207 -134
  264. package/dist/infra/heartbeat-wake.js +183 -22
  265. package/dist/infra/install-source-utils.js +47 -0
  266. package/dist/infra/net/ssrf.js +170 -36
  267. package/dist/infra/outbound/deliver.js +224 -58
  268. package/dist/infra/outbound/message-action-spec.js +12 -5
  269. package/dist/infra/outbound/outbound-session.js +27 -25
  270. package/dist/infra/poolbot-root.js +32 -22
  271. package/dist/infra/ports.js +14 -11
  272. package/dist/infra/skills-remote.js +48 -37
  273. package/dist/infra/system-events.js +25 -11
  274. package/dist/infra/system-presence.js +26 -33
  275. package/dist/infra/tmp-poolbot-dir.js +81 -2
  276. package/dist/infra/wsl.js +37 -1
  277. package/dist/line/bot-message-context.js +163 -191
  278. package/dist/logging/subsystem.js +59 -22
  279. package/dist/markdown/ir.js +124 -50
  280. package/dist/media/store.js +1 -1
  281. package/dist/media-understanding/runner.entries.js +42 -25
  282. package/dist/media-understanding/runner.js +53 -488
  283. package/dist/memory/embeddings-gemini.js +53 -38
  284. package/dist/memory/manager-embedding-ops.js +48 -69
  285. package/dist/pairing/pairing-store.js +178 -119
  286. package/dist/plugin-sdk/index.js +34 -6
  287. package/dist/plugins/hooks.js +135 -14
  288. package/dist/plugins/install.js +190 -152
  289. package/dist/polls.js +11 -0
  290. package/dist/routing/resolve-route.js +190 -56
  291. package/dist/routing/session-key.js +38 -22
  292. package/dist/runtime.js +35 -9
  293. package/dist/security/audit-channel.js +1 -1
  294. package/dist/sessions/session-key-utils.js +29 -11
  295. package/dist/shared/frontmatter.js +5 -5
  296. package/dist/shared/node-list-types.js +1 -0
  297. package/dist/shared/string-normalization.js +15 -0
  298. package/dist/signal/monitor/event-handler.js +68 -36
  299. package/dist/signal/send.js +29 -37
  300. package/dist/slack/monitor/allow-list.js +10 -11
  301. package/dist/slack/monitor/commands.js +14 -3
  302. package/dist/slack/monitor/events/interactions.js +4 -4
  303. package/dist/slack/monitor/media.js +224 -16
  304. package/dist/slack/monitor/message-handler/dispatch.js +247 -13
  305. package/dist/slack/monitor/message-handler/prepare.js +128 -45
  306. package/dist/slack/monitor/slash.js +357 -144
  307. package/dist/slack/streaming.js +77 -0
  308. package/dist/telegram/accounts.js +40 -13
  309. package/dist/telegram/allowed-updates.js +3 -0
  310. package/dist/telegram/bot/delivery.js +129 -66
  311. package/dist/telegram/bot/helpers.js +136 -122
  312. package/dist/telegram/bot-handlers.js +600 -339
  313. package/dist/telegram/bot-message-context.js +115 -73
  314. package/dist/telegram/bot-message-dispatch.js +235 -104
  315. package/dist/telegram/bot-native-command-menu.js +3 -1
  316. package/dist/telegram/bot-native-commands.js +213 -193
  317. package/dist/telegram/bot.js +24 -132
  318. package/dist/telegram/draft-stream.js +84 -75
  319. package/dist/telegram/format.js +150 -6
  320. package/dist/telegram/send.js +415 -255
  321. package/dist/telegram/targets.js +21 -2
  322. package/dist/telegram/update-offset-store.js +19 -3
  323. package/dist/terminal/restore.js +5 -2
  324. package/dist/test-utils/fetch-mock.js +5 -0
  325. package/dist/version.js +18 -5
  326. package/dist/web/auto-reply/monitor/broadcast.js +7 -3
  327. package/dist/web/auto-reply/monitor/on-message.js +6 -3
  328. package/dist/web/inbound/media.js +34 -8
  329. package/dist/web/inbound/monitor.js +34 -17
  330. package/dist/web/inbound/send-api.js +18 -17
  331. package/dist/web/outbound.js +12 -5
  332. package/dist/wizard/clack-prompter.js +40 -7
  333. package/extensions/bluebubbles/package.json +1 -1
  334. package/extensions/copilot-proxy/package.json +1 -1
  335. package/extensions/diagnostics-otel/package.json +1 -1
  336. package/extensions/discord/package.json +1 -1
  337. package/extensions/feishu/package.json +1 -1
  338. package/extensions/google-antigravity-auth/package.json +1 -1
  339. package/extensions/google-gemini-cli-auth/package.json +1 -1
  340. package/extensions/googlechat/package.json +1 -1
  341. package/extensions/imessage/package.json +1 -1
  342. package/extensions/irc/package.json +1 -1
  343. package/extensions/line/package.json +1 -1
  344. package/extensions/llm-task/package.json +1 -1
  345. package/extensions/lobster/package.json +1 -1
  346. package/extensions/matrix/CHANGELOG.md +5 -0
  347. package/extensions/matrix/package.json +1 -1
  348. package/extensions/mattermost/package.json +1 -1
  349. package/extensions/memory-core/package.json +1 -1
  350. package/extensions/memory-lancedb/package.json +1 -1
  351. package/extensions/minimax-portal-auth/package.json +1 -1
  352. package/extensions/msteams/CHANGELOG.md +5 -0
  353. package/extensions/msteams/package.json +1 -1
  354. package/extensions/nextcloud-talk/package.json +1 -1
  355. package/extensions/nostr/CHANGELOG.md +5 -0
  356. package/extensions/nostr/package.json +1 -1
  357. package/extensions/open-prose/package.json +1 -1
  358. package/extensions/openai-codex-auth/package.json +1 -1
  359. package/extensions/signal/package.json +1 -1
  360. package/extensions/slack/package.json +1 -1
  361. package/extensions/telegram/package.json +1 -1
  362. package/extensions/tlon/package.json +1 -1
  363. package/extensions/twitch/CHANGELOG.md +5 -0
  364. package/extensions/twitch/package.json +1 -1
  365. package/extensions/voice-call/CHANGELOG.md +5 -0
  366. package/extensions/voice-call/package.json +1 -1
  367. package/extensions/whatsapp/package.json +1 -1
  368. package/extensions/zalo/CHANGELOG.md +5 -0
  369. package/extensions/zalo/package.json +1 -1
  370. package/extensions/zalouser/CHANGELOG.md +5 -0
  371. package/extensions/zalouser/package.json +1 -1
  372. package/package.json +1 -1
  373. package/skills/apple-reminders/SKILL.md +100 -49
  374. package/skills/coding-agent/SKILL.md +34 -28
  375. package/skills/github/SKILL.md +131 -16
  376. package/skills/imsg/SKILL.md +112 -15
  377. package/skills/openhue/SKILL.md +101 -19
  378. package/skills/plcode-controller/SKILL.md +156 -0
  379. package/skills/plcode-controller/assets/operator-prompts.md +65 -0
  380. package/skills/plcode-controller/references/command-cheatsheet.md +53 -0
  381. package/skills/plcode-controller/references/failure-handling.md +60 -0
  382. package/skills/plcode-controller/references/model-selection.md +57 -0
  383. package/skills/plcode-controller/references/plan-vs-build.md +52 -0
  384. package/skills/plcode-controller/references/question-handling.md +40 -0
  385. package/skills/plcode-controller/references/session-management.md +63 -0
  386. package/skills/plcode-controller/references/workflow.md +35 -0
  387. package/skills/tmux/SKILL.md +111 -79
  388. package/skills/weather/SKILL.md +88 -25
@@ -5,26 +5,47 @@ import { loadModelCatalog } from "../agents/model-catalog.js";
5
5
  import { buildAllowedModelSet, buildModelAliasIndex, modelKey, normalizeProviderId, resolveConfiguredModelRef, } from "../agents/model-selection.js";
6
6
  import { formatTokenK } from "./models/shared.js";
7
7
  import { OPENAI_CODEX_DEFAULT_MODEL } from "./openai-codex-model-default.js";
8
+ import { promptAndConfigureVllm } from "./vllm-setup.js";
8
9
  const KEEP_VALUE = "__keep__";
9
10
  const MANUAL_VALUE = "__manual__";
11
+ const VLLM_VALUE = "__vllm__";
10
12
  const PROVIDER_FILTER_THRESHOLD = 30;
11
13
  // Models that are internal routing features and should not be shown in selection lists.
12
14
  // These may be valid as defaults (e.g., set automatically during auth flow) but are not
13
15
  // directly callable via API and would cause "Unknown model" errors if selected manually.
14
16
  const HIDDEN_ROUTER_MODELS = new Set(["openrouter/auto"]);
15
17
  function hasAuthForProvider(provider, cfg, store) {
16
- if (listProfilesForProvider(store, provider).length > 0)
18
+ if (listProfilesForProvider(store, provider).length > 0) {
17
19
  return true;
18
- if (resolveEnvApiKey(provider))
20
+ }
21
+ if (resolveEnvApiKey(provider)) {
19
22
  return true;
20
- if (getCustomProviderApiKey(cfg, provider))
23
+ }
24
+ if (getCustomProviderApiKey(cfg, provider)) {
21
25
  return true;
26
+ }
22
27
  return false;
23
28
  }
29
+ function createProviderAuthChecker(params) {
30
+ const authStore = ensureAuthProfileStore(params.agentDir, {
31
+ allowKeychainPrompt: false,
32
+ });
33
+ const authCache = new Map();
34
+ return (provider) => {
35
+ const cached = authCache.get(provider);
36
+ if (cached !== undefined) {
37
+ return cached;
38
+ }
39
+ const value = hasAuthForProvider(provider, params.cfg, authStore);
40
+ authCache.set(provider, value);
41
+ return value;
42
+ };
43
+ }
24
44
  function resolveConfiguredModelRaw(cfg) {
25
45
  const raw = cfg.agents?.defaults?.model;
26
- if (typeof raw === "string")
46
+ if (typeof raw === "string") {
27
47
  return raw.trim();
48
+ }
28
49
  return raw?.primary?.trim() ?? "";
29
50
  }
30
51
  function resolveConfiguredModelKeys(cfg) {
@@ -38,13 +59,52 @@ function normalizeModelKeys(values) {
38
59
  const next = [];
39
60
  for (const raw of values) {
40
61
  const value = String(raw ?? "").trim();
41
- if (!value || seen.has(value))
62
+ if (!value || seen.has(value)) {
42
63
  continue;
64
+ }
43
65
  seen.add(value);
44
66
  next.push(value);
45
67
  }
46
68
  return next;
47
69
  }
70
+ function addModelSelectOption(params) {
71
+ const key = modelKey(params.entry.provider, params.entry.id);
72
+ if (params.seen.has(key)) {
73
+ return;
74
+ }
75
+ // Skip internal router models that can't be directly called via API.
76
+ if (HIDDEN_ROUTER_MODELS.has(key)) {
77
+ return;
78
+ }
79
+ const hints = [];
80
+ if (params.entry.name && params.entry.name !== params.entry.id) {
81
+ hints.push(params.entry.name);
82
+ }
83
+ if (params.entry.contextWindow) {
84
+ hints.push(`ctx ${formatTokenK(params.entry.contextWindow)}`);
85
+ }
86
+ if (params.entry.reasoning) {
87
+ hints.push("reasoning");
88
+ }
89
+ const aliases = params.aliasIndex.byKey.get(key);
90
+ if (aliases?.length) {
91
+ hints.push(`alias: ${aliases.join(", ")}`);
92
+ }
93
+ if (!params.hasAuth(params.entry.provider)) {
94
+ hints.push("auth missing");
95
+ }
96
+ params.options.push({
97
+ value: key,
98
+ label: key,
99
+ hint: hints.length > 0 ? hints.join(" · ") : undefined,
100
+ });
101
+ params.seen.add(key);
102
+ }
103
+ function isAnthropicLegacyModel(entry) {
104
+ return (entry.provider === "anthropic" &&
105
+ typeof entry.id === "string" &&
106
+ entry.id.toLowerCase().startsWith("claude-3"));
107
+ }
48
108
  async function promptManualModel(params) {
49
109
  const modelInput = await params.prompter.text({
50
110
  message: params.allowBlank ? "Default model (blank to keep)" : "Default model",
@@ -53,14 +113,16 @@ async function promptManualModel(params) {
53
113
  validate: params.allowBlank ? undefined : (value) => (value?.trim() ? undefined : "Required"),
54
114
  });
55
115
  const model = String(modelInput ?? "").trim();
56
- if (!model)
116
+ if (!model) {
57
117
  return {};
118
+ }
58
119
  return { model };
59
120
  }
60
121
  export async function promptDefaultModel(params) {
61
122
  const cfg = params.config;
62
123
  const allowKeep = params.allowKeep ?? true;
63
124
  const includeManual = params.includeManual ?? true;
125
+ const includeVllm = params.includeVllm ?? false;
64
126
  const ignoreAllowlist = params.ignoreAllowlist ?? false;
65
127
  const preferredProviderRaw = params.preferredProvider?.trim();
66
128
  const preferredProvider = preferredProviderRaw
@@ -102,7 +164,7 @@ export async function promptDefaultModel(params) {
102
164
  initialValue: configuredRaw || resolvedKey || undefined,
103
165
  });
104
166
  }
105
- const providers = Array.from(new Set(models.map((entry) => entry.provider))).sort((a, b) => a.localeCompare(b));
167
+ const providers = Array.from(new Set(models.map((entry) => entry.provider))).toSorted((a, b) => a.localeCompare(b));
106
168
  const hasPreferredProvider = preferredProvider ? providers.includes(preferredProvider) : false;
107
169
  const shouldPromptProvider = !hasPreferredProvider && providers.length > 1 && models.length > PROVIDER_FILTER_THRESHOLD;
108
170
  if (shouldPromptProvider) {
@@ -126,19 +188,12 @@ export async function promptDefaultModel(params) {
126
188
  }
127
189
  if (hasPreferredProvider && preferredProvider) {
128
190
  models = models.filter((entry) => entry.provider === preferredProvider);
191
+ if (preferredProvider === "anthropic") {
192
+ models = models.filter((entry) => !isAnthropicLegacyModel(entry));
193
+ }
129
194
  }
130
- const authStore = ensureAuthProfileStore(params.agentDir, {
131
- allowKeychainPrompt: false,
132
- });
133
- const authCache = new Map();
134
- const hasAuth = (provider) => {
135
- const cached = authCache.get(provider);
136
- if (cached !== undefined)
137
- return cached;
138
- const value = hasAuthForProvider(provider, cfg, authStore);
139
- authCache.set(provider, value);
140
- return value;
141
- };
195
+ const agentDir = params.agentDir;
196
+ const hasAuth = createProviderAuthChecker({ cfg, agentDir });
142
197
  const options = [];
143
198
  if (allowKeep) {
144
199
  options.push({
@@ -152,35 +207,17 @@ export async function promptDefaultModel(params) {
152
207
  if (includeManual) {
153
208
  options.push({ value: MANUAL_VALUE, label: "Enter model manually" });
154
209
  }
155
- const seen = new Set();
156
- const addModelOption = (entry) => {
157
- const key = modelKey(entry.provider, entry.id);
158
- if (seen.has(key))
159
- return;
160
- // Skip internal router models that can't be directly called via API.
161
- if (HIDDEN_ROUTER_MODELS.has(key))
162
- return;
163
- const hints = [];
164
- if (entry.name && entry.name !== entry.id)
165
- hints.push(entry.name);
166
- if (entry.contextWindow)
167
- hints.push(`ctx ${formatTokenK(entry.contextWindow)}`);
168
- if (entry.reasoning)
169
- hints.push("reasoning");
170
- const aliases = aliasIndex.byKey.get(key);
171
- if (aliases?.length)
172
- hints.push(`alias: ${aliases.join(", ")}`);
173
- if (!hasAuth(entry.provider))
174
- hints.push("auth missing");
210
+ if (includeVllm && agentDir) {
175
211
  options.push({
176
- value: key,
177
- label: key,
178
- hint: hints.length > 0 ? hints.join(" · ") : undefined,
212
+ value: VLLM_VALUE,
213
+ label: "vLLM (custom)",
214
+ hint: "Enter vLLM URL + API key + model",
179
215
  });
180
- seen.add(key);
181
- };
182
- for (const entry of models)
183
- addModelOption(entry);
216
+ }
217
+ const seen = new Set();
218
+ for (const entry of models) {
219
+ addModelSelectOption({ entry, options, seen, aliasIndex, hasAuth });
220
+ }
184
221
  if (configuredKey && !seen.has(configuredKey)) {
185
222
  options.push({
186
223
  value: configuredKey,
@@ -203,8 +240,9 @@ export async function promptDefaultModel(params) {
203
240
  options,
204
241
  initialValue,
205
242
  });
206
- if (selection === KEEP_VALUE)
243
+ if (selection === KEEP_VALUE) {
207
244
  return {};
245
+ }
208
246
  if (selection === MANUAL_VALUE) {
209
247
  return promptManualModel({
210
248
  prompter: params.prompter,
@@ -212,6 +250,18 @@ export async function promptDefaultModel(params) {
212
250
  initialValue: configuredRaw || resolvedKey || undefined,
213
251
  });
214
252
  }
253
+ if (selection === VLLM_VALUE) {
254
+ if (!agentDir) {
255
+ await params.prompter.note("vLLM setup requires an agent directory context.", "vLLM not available");
256
+ return {};
257
+ }
258
+ const { config: nextConfig, modelRef } = await promptAndConfigureVllm({
259
+ cfg,
260
+ prompter: params.prompter,
261
+ agentDir,
262
+ });
263
+ return { model: modelRef, config: nextConfig };
264
+ }
215
265
  return { model: String(selection) };
216
266
  }
217
267
  export async function promptModelAllowlist(params) {
@@ -245,62 +295,29 @@ export async function promptModelAllowlist(params) {
245
295
  .split(",")
246
296
  .map((value) => value.trim())
247
297
  .filter((value) => value.length > 0);
248
- if (parsed.length === 0)
298
+ if (parsed.length === 0) {
249
299
  return {};
300
+ }
250
301
  return { models: normalizeModelKeys(parsed) };
251
302
  }
252
303
  const aliasIndex = buildModelAliasIndex({
253
304
  cfg,
254
305
  defaultProvider: DEFAULT_PROVIDER,
255
306
  });
256
- const authStore = ensureAuthProfileStore(params.agentDir, {
257
- allowKeychainPrompt: false,
258
- });
259
- const authCache = new Map();
260
- const hasAuth = (provider) => {
261
- const cached = authCache.get(provider);
262
- if (cached !== undefined)
263
- return cached;
264
- const value = hasAuthForProvider(provider, cfg, authStore);
265
- authCache.set(provider, value);
266
- return value;
267
- };
307
+ const hasAuth = createProviderAuthChecker({ cfg, agentDir: params.agentDir });
268
308
  const options = [];
269
309
  const seen = new Set();
270
- const addModelOption = (entry) => {
271
- const key = modelKey(entry.provider, entry.id);
272
- if (seen.has(key))
273
- return;
274
- if (HIDDEN_ROUTER_MODELS.has(key))
275
- return;
276
- const hints = [];
277
- if (entry.name && entry.name !== entry.id)
278
- hints.push(entry.name);
279
- if (entry.contextWindow)
280
- hints.push(`ctx ${formatTokenK(entry.contextWindow)}`);
281
- if (entry.reasoning)
282
- hints.push("reasoning");
283
- const aliases = aliasIndex.byKey.get(key);
284
- if (aliases?.length)
285
- hints.push(`alias: ${aliases.join(", ")}`);
286
- if (!hasAuth(entry.provider))
287
- hints.push("auth missing");
288
- options.push({
289
- value: key,
290
- label: key,
291
- hint: hints.length > 0 ? hints.join(" · ") : undefined,
292
- });
293
- seen.add(key);
294
- };
295
310
  const filteredCatalog = allowedKeySet
296
311
  ? catalog.filter((entry) => allowedKeySet.has(modelKey(entry.provider, entry.id)))
297
312
  : catalog;
298
- for (const entry of filteredCatalog)
299
- addModelOption(entry);
313
+ for (const entry of filteredCatalog) {
314
+ addModelSelectOption({ entry, options, seen, aliasIndex, hasAuth });
315
+ }
300
316
  const supplementalKeys = allowedKeySet ? allowedKeys : existingKeys;
301
317
  for (const key of supplementalKeys) {
302
- if (seen.has(key))
318
+ if (seen.has(key)) {
303
319
  continue;
320
+ }
304
321
  options.push({
305
322
  value: key,
306
323
  label: key,
@@ -308,24 +325,29 @@ export async function promptModelAllowlist(params) {
308
325
  });
309
326
  seen.add(key);
310
327
  }
311
- if (options.length === 0)
328
+ if (options.length === 0) {
312
329
  return {};
330
+ }
313
331
  const selection = await params.prompter.multiselect({
314
332
  message: params.message ?? "Models in /model picker (multi-select)",
315
333
  options,
316
334
  initialValues: initialKeys.length > 0 ? initialKeys : undefined,
335
+ searchable: true,
317
336
  });
318
337
  const selected = normalizeModelKeys(selection.map((value) => String(value)));
319
- if (selected.length > 0)
338
+ if (selected.length > 0) {
320
339
  return { models: selected };
321
- if (existingKeys.length === 0)
340
+ }
341
+ if (existingKeys.length === 0) {
322
342
  return { models: [] };
343
+ }
323
344
  const confirmClear = await params.prompter.confirm({
324
345
  message: "Clear the model allowlist? (shows all models)",
325
346
  initialValue: false,
326
347
  });
327
- if (!confirmClear)
348
+ if (!confirmClear) {
328
349
  return {};
350
+ }
329
351
  return { models: [] };
330
352
  }
331
353
  export function applyPrimaryModel(cfg, model) {
@@ -357,8 +379,9 @@ export function applyModelAllowlist(cfg, models) {
357
379
  const defaults = cfg.agents?.defaults;
358
380
  const normalized = normalizeModelKeys(models);
359
381
  if (normalized.length === 0) {
360
- if (!defaults?.models)
382
+ if (!defaults?.models) {
361
383
  return cfg;
384
+ }
362
385
  const { models: _ignored, ...restDefaults } = defaults;
363
386
  return {
364
387
  ...cfg,
@@ -386,16 +409,18 @@ export function applyModelAllowlist(cfg, models) {
386
409
  }
387
410
  export function applyModelFallbacksFromSelection(cfg, selection) {
388
411
  const normalized = normalizeModelKeys(selection);
389
- if (normalized.length <= 1)
412
+ if (normalized.length <= 1) {
390
413
  return cfg;
414
+ }
391
415
  const resolved = resolveConfiguredModelRef({
392
416
  cfg,
393
417
  defaultProvider: DEFAULT_PROVIDER,
394
418
  defaultModel: DEFAULT_MODEL,
395
419
  });
396
420
  const resolvedKey = modelKey(resolved.provider, resolved.model);
397
- if (!normalized.includes(resolvedKey))
421
+ if (!normalized.includes(resolvedKey)) {
398
422
  return cfg;
423
+ }
399
424
  const defaults = cfg.agents?.defaults;
400
425
  const existingModel = defaults?.model;
401
426
  const existingPrimary = typeof existingModel === "string"
@@ -1,27 +1,8 @@
1
1
  import { logConfigUpdated } from "../../config/logging.js";
2
- import { resolveModelTarget, updateConfig } from "./shared.js";
2
+ import { applyDefaultModelPrimaryUpdate, updateConfig } from "./shared.js";
3
3
  export async function modelsSetCommand(modelRaw, runtime) {
4
4
  const updated = await updateConfig((cfg) => {
5
- const resolved = resolveModelTarget({ raw: modelRaw, cfg });
6
- const key = `${resolved.provider}/${resolved.model}`;
7
- const nextModels = { ...cfg.agents?.defaults?.models };
8
- if (!nextModels[key])
9
- nextModels[key] = {};
10
- const existingModel = cfg.agents?.defaults?.model;
11
- return {
12
- ...cfg,
13
- agents: {
14
- ...cfg.agents,
15
- defaults: {
16
- ...cfg.agents?.defaults,
17
- model: {
18
- ...(existingModel?.fallbacks ? { fallbacks: existingModel.fallbacks } : undefined),
19
- primary: key,
20
- },
21
- models: nextModels,
22
- },
23
- },
24
- };
5
+ return applyDefaultModelPrimaryUpdate({ cfg, modelRaw, field: "model" });
25
6
  });
26
7
  logConfigUpdated(runtime);
27
8
  runtime.log(`Default model: ${updated.agents?.defaults?.model?.primary ?? modelRaw}`);
@@ -10,21 +10,40 @@ export const ensureFlagCompatibility = (opts) => {
10
10
  }
11
11
  };
12
12
  export const formatTokenK = (value) => {
13
- if (!value || !Number.isFinite(value))
13
+ if (!value || !Number.isFinite(value)) {
14
14
  return "-";
15
- if (value < 1024)
15
+ }
16
+ if (value < 1024) {
16
17
  return `${Math.round(value)}`;
18
+ }
17
19
  return `${Math.round(value / 1024)}k`;
18
20
  };
19
21
  export const formatMs = (value) => {
20
- if (value === null || value === undefined)
22
+ if (value === null || value === undefined) {
21
23
  return "-";
22
- if (!Number.isFinite(value))
24
+ }
25
+ if (!Number.isFinite(value)) {
23
26
  return "-";
24
- if (value < 1000)
27
+ }
28
+ if (value < 1000) {
25
29
  return `${Math.round(value)}ms`;
30
+ }
26
31
  return `${Math.round(value / 100) / 10}s`;
27
32
  };
33
+ export const isLocalBaseUrl = (baseUrl) => {
34
+ try {
35
+ const url = new URL(baseUrl);
36
+ const host = url.hostname.toLowerCase();
37
+ return (host === "localhost" ||
38
+ host === "127.0.0.1" ||
39
+ host === "0.0.0.0" ||
40
+ host === "::1" ||
41
+ host.endsWith(".local"));
42
+ }
43
+ catch {
44
+ return false;
45
+ }
46
+ };
28
47
  export async function updateConfig(mutator) {
29
48
  const snapshot = await readConfigFileSnapshot();
30
49
  if (!snapshot.valid) {
@@ -50,21 +69,37 @@ export function resolveModelTarget(params) {
50
69
  }
51
70
  return resolved.ref;
52
71
  }
72
+ export function resolveModelKeysFromEntries(params) {
73
+ const aliasIndex = buildModelAliasIndex({
74
+ cfg: params.cfg,
75
+ defaultProvider: DEFAULT_PROVIDER,
76
+ });
77
+ return params.entries
78
+ .map((entry) => resolveModelRefFromString({
79
+ raw: entry,
80
+ defaultProvider: DEFAULT_PROVIDER,
81
+ aliasIndex,
82
+ }))
83
+ .filter((entry) => Boolean(entry))
84
+ .map((entry) => modelKey(entry.ref.provider, entry.ref.model));
85
+ }
53
86
  export function buildAllowlistSet(cfg) {
54
87
  const allowed = new Set();
55
88
  const models = cfg.agents?.defaults?.models ?? {};
56
89
  for (const raw of Object.keys(models)) {
57
90
  const parsed = parseModelRef(String(raw ?? ""), DEFAULT_PROVIDER);
58
- if (!parsed)
91
+ if (!parsed) {
59
92
  continue;
93
+ }
60
94
  allowed.add(modelKey(parsed.provider, parsed.model));
61
95
  }
62
96
  return allowed;
63
97
  }
64
98
  export function normalizeAlias(alias) {
65
99
  const trimmed = alias.trim();
66
- if (!trimmed)
100
+ if (!trimmed) {
67
101
  throw new Error("Alias cannot be empty.");
102
+ }
68
103
  if (!/^[A-Za-z0-9_.:-]+$/.test(trimmed)) {
69
104
  throw new Error("Alias must use letters, numbers, dots, underscores, colons, or dashes.");
70
105
  }
@@ -82,36 +117,6 @@ export function resolveKnownAgentId(params) {
82
117
  }
83
118
  return agentId;
84
119
  }
85
- export const isLocalBaseUrl = (baseUrl) => {
86
- try {
87
- const url = new URL(baseUrl);
88
- const host = url.hostname.toLowerCase();
89
- return (host === "localhost" ||
90
- host === "127.0.0.1" ||
91
- host === "0.0.0.0" ||
92
- host === "::1" ||
93
- host.endsWith(".local"));
94
- }
95
- catch {
96
- return false;
97
- }
98
- };
99
- export { modelKey };
100
- export { DEFAULT_MODEL, DEFAULT_PROVIDER };
101
- export function resolveModelKeysFromEntries(params) {
102
- const aliasIndex = buildModelAliasIndex({
103
- cfg: params.cfg,
104
- defaultProvider: DEFAULT_PROVIDER,
105
- });
106
- return params.entries
107
- .map((entry) => resolveModelRefFromString({
108
- raw: entry,
109
- defaultProvider: DEFAULT_PROVIDER,
110
- aliasIndex,
111
- }))
112
- .filter((entry) => Boolean(entry))
113
- .map((entry) => modelKey(entry.ref.provider, entry.ref.model));
114
- }
115
120
  export function mergePrimaryFallbackConfig(existing, patch) {
116
121
  const next = { ...existing };
117
122
  if (patch.primary !== undefined) {
@@ -122,6 +127,29 @@ export function mergePrimaryFallbackConfig(existing, patch) {
122
127
  }
123
128
  return next;
124
129
  }
130
+ export function applyDefaultModelPrimaryUpdate(params) {
131
+ const resolved = resolveModelTarget({ raw: params.modelRaw, cfg: params.cfg });
132
+ const key = `${resolved.provider}/${resolved.model}`;
133
+ const nextModels = { ...params.cfg.agents?.defaults?.models };
134
+ if (!nextModels[key]) {
135
+ nextModels[key] = {};
136
+ }
137
+ const defaults = params.cfg.agents?.defaults ?? {};
138
+ const existing = defaults[params.field];
139
+ return {
140
+ ...params.cfg,
141
+ agents: {
142
+ ...params.cfg.agents,
143
+ defaults: {
144
+ ...defaults,
145
+ [params.field]: mergePrimaryFallbackConfig(existing, { primary: key }),
146
+ models: nextModels,
147
+ },
148
+ },
149
+ };
150
+ }
151
+ export { modelKey };
152
+ export { DEFAULT_MODEL, DEFAULT_PROVIDER };
125
153
  /**
126
154
  * Model key format: "provider/model"
127
155
  *