@poolzin/pool-bot 2026.1.39 → 2026.2.1

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 (511) hide show
  1. package/assets/chrome-extension/README.md +3 -3
  2. package/assets/chrome-extension/background.js +5 -5
  3. package/assets/chrome-extension/manifest.json +3 -3
  4. package/assets/chrome-extension/options.html +4 -4
  5. package/assets/chrome-extension/options.js +1 -1
  6. package/dist/acp/client.js +3 -3
  7. package/dist/acp/types.js +1 -1
  8. package/dist/agents/agent-paths.js +3 -3
  9. package/dist/agents/auth-profiles/paths.js +3 -3
  10. package/dist/agents/bash-tools.exec.js +76 -25
  11. package/dist/agents/cli-runner/helpers.js +10 -12
  12. package/dist/agents/cli-runner.js +2 -2
  13. package/dist/agents/cloudflare-ai-gateway.js +31 -0
  14. package/dist/agents/compaction.js +16 -2
  15. package/dist/agents/context-window-guard.js +13 -10
  16. package/dist/agents/context.js +4 -4
  17. package/dist/agents/docs-path.js +1 -1
  18. package/dist/agents/identity.js +47 -7
  19. package/dist/agents/memory-search.js +25 -8
  20. package/dist/agents/minimax-vlm.js +1 -1
  21. package/dist/agents/model-auth.js +12 -1
  22. package/dist/agents/model-catalog.js +4 -4
  23. package/dist/agents/model-selection.js +31 -4
  24. package/dist/agents/models-config.js +3 -3
  25. package/dist/agents/models-config.providers.js +147 -39
  26. package/dist/agents/pi-embedded-block-chunker.js +117 -42
  27. package/dist/agents/pi-embedded-helpers/errors.js +183 -78
  28. package/dist/agents/pi-embedded-helpers/openai.js +1 -1
  29. package/dist/agents/pi-embedded-helpers.js +1 -1
  30. package/dist/agents/pi-embedded-runner/compact.js +9 -8
  31. package/dist/agents/pi-embedded-runner/model.js +63 -4
  32. package/dist/agents/pi-embedded-runner/run/attempt.js +27 -17
  33. package/dist/agents/pi-embedded-runner/run.js +203 -50
  34. package/dist/agents/pi-embedded-runner/system-prompt.js +10 -2
  35. package/dist/agents/pi-embedded-runner/tool-result-truncation.js +275 -0
  36. package/dist/agents/pi-embedded-runner/utils.js +1 -1
  37. package/dist/agents/pi-embedded-subscribe.js +118 -29
  38. package/dist/agents/pi-model-discovery.js +10 -0
  39. package/dist/agents/pi-tool-definition-adapter.js +50 -9
  40. package/dist/agents/pi-tools.before-tool-call.js +67 -0
  41. package/dist/agents/pi-tools.js +20 -10
  42. package/dist/agents/pi-tools.read.js +2 -2
  43. package/dist/agents/poolbot-tools.js +15 -10
  44. package/dist/agents/sandbox-paths.js +31 -0
  45. package/dist/agents/session-file-repair.js +83 -0
  46. package/dist/agents/session-tool-result-guard.js +94 -15
  47. package/dist/agents/session-transcript-repair.js +68 -0
  48. package/dist/agents/shell-utils.js +51 -0
  49. package/dist/agents/skills/bundled-context.js +23 -0
  50. package/dist/agents/skills/bundled-dir.js +41 -7
  51. package/dist/agents/skills/frontmatter.js +1 -1
  52. package/dist/agents/skills/workspace.js +2 -2
  53. package/dist/agents/skills-install.js +60 -23
  54. package/dist/agents/subagent-announce.js +79 -34
  55. package/dist/agents/system-prompt.js +28 -4
  56. package/dist/agents/together-models.js +127 -0
  57. package/dist/agents/tool-images.js +1 -1
  58. package/dist/agents/tool-policy.conformance.js +14 -0
  59. package/dist/agents/tool-policy.js +25 -1
  60. package/dist/agents/tools/browser-tool.js +3 -3
  61. package/dist/agents/tools/cron-tool.js +166 -19
  62. package/dist/agents/tools/discord-actions-presence.js +78 -0
  63. package/dist/agents/tools/image-tool.js +2 -2
  64. package/dist/agents/tools/memory-tool.js +93 -5
  65. package/dist/agents/tools/message-tool.js +56 -2
  66. package/dist/agents/tools/sessions-history-tool.js +69 -1
  67. package/dist/agents/tools/web-search.js +211 -42
  68. package/dist/agents/usage.js +23 -1
  69. package/dist/agents/workspace-run.js +67 -0
  70. package/dist/agents/workspace-templates.js +44 -0
  71. package/dist/auto-reply/command-auth.js +121 -6
  72. package/dist/auto-reply/commands-registry.data.js +1 -1
  73. package/dist/auto-reply/envelope.js +50 -72
  74. package/dist/auto-reply/reply/commands-compact.js +1 -0
  75. package/dist/auto-reply/reply/commands-context-report.js +3 -2
  76. package/dist/auto-reply/reply/commands-context.js +1 -0
  77. package/dist/auto-reply/reply/commands-models.js +107 -60
  78. package/dist/auto-reply/reply/commands-ptt.js +171 -0
  79. package/dist/auto-reply/reply/commands-session.js +2 -2
  80. package/dist/auto-reply/reply/get-reply-run.js +16 -5
  81. package/dist/auto-reply/reply/groups.js +1 -1
  82. package/dist/auto-reply/reply/inbound-context.js +9 -1
  83. package/dist/auto-reply/reply/inbound-meta.js +130 -0
  84. package/dist/auto-reply/reply/model-selection.js +3 -3
  85. package/dist/auto-reply/reply/untrusted-context.js +15 -0
  86. package/dist/auto-reply/status.js +1 -1
  87. package/dist/auto-reply/thinking.js +88 -43
  88. package/dist/browser/bridge-server.js +13 -0
  89. package/dist/browser/cdp.helpers.js +38 -24
  90. package/dist/browser/client-fetch.js +51 -8
  91. package/dist/browser/config.js +2 -11
  92. package/dist/browser/extension-relay.js +104 -43
  93. package/dist/browser/pw-ai.js +1 -1
  94. package/dist/browser/pw-session.js +143 -8
  95. package/dist/browser/pw-tools-core.interactions.js +125 -27
  96. package/dist/browser/pw-tools-core.responses.js +1 -1
  97. package/dist/browser/pw-tools-core.state.js +1 -1
  98. package/dist/browser/routes/agent.act.js +86 -41
  99. package/dist/browser/routes/dispatcher.js +4 -4
  100. package/dist/browser/screenshot.js +1 -1
  101. package/dist/browser/server-context.js +2 -2
  102. package/dist/browser/server.js +13 -0
  103. package/dist/build-info.json +3 -3
  104. package/dist/canvas-host/a2ui.js +3 -3
  105. package/dist/channels/plugins/catalog.js +2 -2
  106. package/dist/channels/plugins/onboarding/imessage.js +1 -1
  107. package/dist/channels/plugins/onboarding/signal.js +1 -1
  108. package/dist/channels/plugins/onboarding/slack.js +4 -4
  109. package/dist/channels/plugins/onboarding/whatsapp.js +3 -3
  110. package/dist/channels/plugins/pairing-message.js +1 -1
  111. package/dist/channels/reply-prefix.js +8 -1
  112. package/dist/cli/browser-cli-extension.js +2 -2
  113. package/dist/cli/cron-cli/register.cron-add.js +61 -40
  114. package/dist/cli/cron-cli/register.cron-edit.js +60 -34
  115. package/dist/cli/cron-cli/shared.js +56 -41
  116. package/dist/cli/dns-cli.js +26 -14
  117. package/dist/cli/docs-cli.js +1 -1
  118. package/dist/cli/gateway-cli/dev.js +1 -1
  119. package/dist/cli/gateway-cli/register.js +37 -19
  120. package/dist/cli/memory-cli.js +30 -20
  121. package/dist/cli/nodes-cli/register.canvas.js +1 -1
  122. package/dist/cli/parse-bytes.js +37 -0
  123. package/dist/cli/plugins-cli.js +1 -1
  124. package/dist/cli/run-main.js +2 -2
  125. package/dist/cli/security-cli.js +1 -1
  126. package/dist/cli/tagline.js +1 -1
  127. package/dist/cli/update-cli.js +173 -52
  128. package/dist/cli/webhooks-cli.js +5 -5
  129. package/dist/commands/agent.js +1 -0
  130. package/dist/commands/agents.commands.add.js +1 -1
  131. package/dist/commands/auth-choice.apply.api-providers.js +305 -17
  132. package/dist/commands/auth-choice.apply.js +4 -1
  133. package/dist/commands/auth-choice.apply.plugin-provider.js +2 -2
  134. package/dist/commands/auth-choice.apply.xai.js +63 -0
  135. package/dist/commands/auth-choice.preferred-provider.js +7 -1
  136. package/dist/commands/configure.wizard.js +1 -1
  137. package/dist/commands/dashboard.js +1 -1
  138. package/dist/commands/docs.js +1 -1
  139. package/dist/commands/doctor-config-flow.js +61 -5
  140. package/dist/commands/doctor-gateway-services.js +3 -3
  141. package/dist/commands/doctor-state-migrations.js +1 -1
  142. package/dist/commands/doctor-update.js +3 -3
  143. package/dist/commands/doctor.js +1 -1
  144. package/dist/commands/health.js +1 -1
  145. package/dist/commands/model-allowlist.js +29 -0
  146. package/dist/commands/model-picker.js +2 -1
  147. package/dist/commands/models/list.probe.js +2 -2
  148. package/dist/commands/models/list.registry.js +4 -4
  149. package/dist/commands/models/list.status-command.js +44 -24
  150. package/dist/commands/models/shared.js +15 -0
  151. package/dist/commands/onboard-auth.config-core.js +366 -28
  152. package/dist/commands/onboard-auth.credentials.js +71 -9
  153. package/dist/commands/onboard-auth.js +3 -3
  154. package/dist/commands/onboard-auth.models.js +26 -24
  155. package/dist/commands/onboard-custom.js +384 -0
  156. package/dist/commands/onboard-non-interactive/local/auth-choice-inference.js +35 -0
  157. package/dist/commands/onboard-non-interactive/local/auth-choice.js +146 -9
  158. package/dist/commands/onboard-skills.js +63 -38
  159. package/dist/commands/openai-model-default.js +41 -0
  160. package/dist/commands/status-all/report-lines.js +1 -1
  161. package/dist/commands/status.command.js +1 -1
  162. package/dist/commands/uninstall.js +3 -3
  163. package/dist/compat/legacy-names.js +1 -1
  164. package/dist/config/defaults.js +3 -2
  165. package/dist/config/io.js +3 -3
  166. package/dist/config/paths.js +136 -35
  167. package/dist/config/plugin-auto-enable.js +21 -5
  168. package/dist/config/redact-snapshot.js +153 -0
  169. package/dist/config/schema.field-metadata.js +590 -0
  170. package/dist/config/schema.js +3 -3
  171. package/dist/config/sessions/store.js +291 -23
  172. package/dist/config/types.memory.js +1 -0
  173. package/dist/config/version.js +4 -4
  174. package/dist/config/zod-schema.agent-defaults.js +3 -0
  175. package/dist/config/zod-schema.agent-runtime.js +13 -2
  176. package/dist/config/zod-schema.providers-core.js +142 -0
  177. package/dist/config/zod-schema.session.js +3 -0
  178. package/dist/cron/delivery.js +57 -0
  179. package/dist/cron/isolated-agent/delivery-target.js +18 -3
  180. package/dist/cron/isolated-agent/helpers.js +22 -5
  181. package/dist/cron/isolated-agent/run.js +171 -63
  182. package/dist/cron/isolated-agent/session.js +2 -0
  183. package/dist/cron/normalize.js +356 -28
  184. package/dist/cron/parse.js +10 -5
  185. package/dist/cron/run-log.js +35 -10
  186. package/dist/cron/schedule.js +41 -6
  187. package/dist/cron/service/jobs.js +208 -35
  188. package/dist/cron/service/ops.js +72 -16
  189. package/dist/cron/service/state.js +2 -0
  190. package/dist/cron/service/store.js +386 -14
  191. package/dist/cron/service/timer.js +390 -147
  192. package/dist/cron/session-reaper.js +86 -0
  193. package/dist/cron/store.js +23 -8
  194. package/dist/cron/validate-timestamp.js +43 -0
  195. package/dist/daemon/constants.js +7 -7
  196. package/dist/daemon/inspect.js +6 -6
  197. package/dist/daemon/systemd-unit.js +1 -1
  198. package/dist/discord/monitor/agent-components.js +438 -0
  199. package/dist/discord/monitor/allow-list.js +28 -5
  200. package/dist/discord/monitor/gateway-registry.js +29 -0
  201. package/dist/discord/monitor/native-command.js +44 -23
  202. package/dist/discord/monitor/sender-identity.js +45 -0
  203. package/dist/discord/pluralkit.js +27 -0
  204. package/dist/discord/send.outbound.js +92 -5
  205. package/dist/discord/send.shared.js +60 -23
  206. package/dist/discord/targets.js +84 -1
  207. package/dist/entry.js +15 -9
  208. package/dist/extensionAPI.js +8 -0
  209. package/dist/gateway/control-ui.js +8 -1
  210. package/dist/gateway/hooks-mapping.js +3 -0
  211. package/dist/gateway/hooks.js +65 -0
  212. package/dist/gateway/live-image-probe.js +1 -66
  213. package/dist/gateway/net.js +96 -31
  214. package/dist/gateway/node-command-policy.js +50 -15
  215. package/dist/gateway/openai-http.js +2 -2
  216. package/dist/gateway/openresponses-http.js +4 -4
  217. package/dist/gateway/origin-check.js +56 -0
  218. package/dist/gateway/protocol/client-info.js +9 -0
  219. package/dist/gateway/protocol/index.js +9 -2
  220. package/dist/gateway/protocol/schema/agents-models-skills.js +71 -1
  221. package/dist/gateway/protocol/schema/cron.js +22 -10
  222. package/dist/gateway/protocol/schema/protocol-schemas.js +16 -2
  223. package/dist/gateway/protocol/schema/sessions.js +12 -0
  224. package/dist/gateway/server/hooks.js +1 -1
  225. package/dist/gateway/server-broadcast.js +26 -9
  226. package/dist/gateway/server-chat.js +112 -23
  227. package/dist/gateway/server-discovery-runtime.js +10 -2
  228. package/dist/gateway/server-discovery.js +2 -2
  229. package/dist/gateway/server-http.js +110 -12
  230. package/dist/gateway/server-methods/agent-timestamp.js +60 -0
  231. package/dist/gateway/server-methods/agents.js +321 -2
  232. package/dist/gateway/server-methods/usage.js +559 -16
  233. package/dist/gateway/server-runtime-state.js +22 -8
  234. package/dist/gateway/server-startup-memory.js +16 -0
  235. package/dist/gateway/server.impl.js +7 -3
  236. package/dist/gateway/session-utils.fs.js +23 -25
  237. package/dist/gateway/session-utils.js +20 -10
  238. package/dist/gateway/sessions-patch.js +7 -22
  239. package/dist/gateway/test-helpers.server.js +35 -2
  240. package/dist/hooks/frontmatter.js +1 -1
  241. package/dist/hooks/hooks-status.js +1 -1
  242. package/dist/hooks/install.js +2 -2
  243. package/dist/hooks/loader.js +1 -1
  244. package/dist/hooks/workspace.js +3 -3
  245. package/dist/imessage/constants.js +2 -0
  246. package/dist/imessage/monitor/deliver.js +4 -1
  247. package/dist/imessage/monitor/monitor-provider.js +51 -1
  248. package/dist/index.js +2 -2
  249. package/dist/infra/bonjour-discovery.js +131 -70
  250. package/dist/infra/bonjour.js +3 -3
  251. package/dist/infra/control-ui-assets.js +134 -12
  252. package/dist/infra/errors.js +12 -0
  253. package/dist/infra/exec-approvals.js +266 -57
  254. package/dist/infra/format-time/format-datetime.js +79 -0
  255. package/dist/infra/format-time/format-duration.js +81 -0
  256. package/dist/infra/format-time/format-relative.js +80 -0
  257. package/dist/infra/heartbeat-runner.js +140 -49
  258. package/dist/infra/home-dir.js +54 -0
  259. package/dist/infra/net/fetch-guard.js +122 -0
  260. package/dist/infra/net/ssrf.js +65 -29
  261. package/dist/infra/outbound/abort.js +14 -0
  262. package/dist/infra/outbound/message-action-runner.js +77 -13
  263. package/dist/infra/outbound/outbound-session.js +143 -37
  264. package/dist/infra/path-env.js +3 -3
  265. package/dist/infra/poolbot-root.js +43 -1
  266. package/dist/infra/provider-usage.fetch.minimax.js +1 -1
  267. package/dist/infra/restart.js +1 -1
  268. package/dist/infra/session-cost-usage.js +631 -41
  269. package/dist/infra/state-migrations.js +317 -47
  270. package/dist/infra/tailscale.js +1 -1
  271. package/dist/infra/update-global.js +35 -0
  272. package/dist/infra/update-runner.js +149 -43
  273. package/dist/infra/warning-filter.js +65 -0
  274. package/dist/infra/widearea-dns.js +30 -9
  275. package/dist/logging/redact-identifier.js +12 -0
  276. package/dist/macos/relay.js +2 -2
  277. package/dist/media/fetch.js +81 -58
  278. package/dist/media/input-files.js +1 -1
  279. package/dist/media/mime.js +4 -0
  280. package/dist/media/png-encode.js +74 -0
  281. package/dist/media-understanding/apply.js +403 -3
  282. package/dist/media-understanding/attachments.js +38 -27
  283. package/dist/media-understanding/defaults.js +16 -0
  284. package/dist/media-understanding/providers/deepgram/audio.js +22 -14
  285. package/dist/media-understanding/providers/google/audio.js +24 -17
  286. package/dist/media-understanding/providers/google/video.js +24 -17
  287. package/dist/media-understanding/providers/image.js +4 -4
  288. package/dist/media-understanding/providers/index.js +4 -1
  289. package/dist/media-understanding/providers/openai/audio.js +22 -14
  290. package/dist/media-understanding/providers/shared.js +16 -11
  291. package/dist/media-understanding/providers/zai/index.js +6 -0
  292. package/dist/media-understanding/runner.js +158 -90
  293. package/dist/memory/backend-config.js +207 -0
  294. package/dist/memory/batch-voyage.js +277 -0
  295. package/dist/memory/embeddings-voyage.js +75 -0
  296. package/dist/memory/embeddings.js +29 -17
  297. package/dist/memory/internal.js +101 -18
  298. package/dist/memory/manager.js +155 -48
  299. package/dist/memory/search-manager.js +173 -0
  300. package/dist/memory/session-files.js +9 -3
  301. package/dist/memory/types.js +1 -0
  302. package/dist/node-host/runner.js +36 -26
  303. package/dist/node-host/with-timeout.js +27 -0
  304. package/dist/pairing/pairing-messages.js +1 -1
  305. package/dist/plugins/commands.js +5 -1
  306. package/dist/plugins/config-state.js +86 -7
  307. package/dist/plugins/discovery.js +1 -1
  308. package/dist/plugins/install.js +2 -2
  309. package/dist/plugins/source-display.js +51 -0
  310. package/dist/plugins/update.js +1 -1
  311. package/dist/process/exec.js +20 -2
  312. package/dist/routing/resolve-route.js +12 -0
  313. package/dist/routing/session-key.js +15 -0
  314. package/dist/runtime.js +2 -0
  315. package/dist/security/audit-extra.async.js +601 -0
  316. package/dist/security/audit-extra.js +2 -830
  317. package/dist/security/audit-extra.sync.js +505 -0
  318. package/dist/security/audit.js +2 -2
  319. package/dist/security/channel-metadata.js +34 -0
  320. package/dist/security/external-content.js +88 -6
  321. package/dist/security/skill-scanner.js +330 -0
  322. package/dist/sessions/session-key-utils.js +7 -0
  323. package/dist/shared/text/reasoning-tags.js +52 -7
  324. package/dist/signal/monitor/event-handler.js +80 -1
  325. package/dist/slack/monitor/media.js +85 -15
  326. package/dist/tailscale/detect.js +145 -0
  327. package/dist/telegram/bot/helpers.js +109 -28
  328. package/dist/telegram/bot-handlers.js +144 -3
  329. package/dist/telegram/bot-message-context.js +38 -11
  330. package/dist/telegram/bot-message-dispatch.js +48 -15
  331. package/dist/telegram/bot-native-commands.js +86 -29
  332. package/dist/telegram/bot.js +30 -29
  333. package/dist/telegram/model-buttons.js +163 -0
  334. package/dist/telegram/monitor.js +110 -85
  335. package/dist/telegram/send.js +129 -47
  336. package/dist/terminal/restore.js +45 -0
  337. package/dist/test-helpers/state-dir-env.js +16 -0
  338. package/dist/test-helpers/workspace.js +11 -0
  339. package/dist/test-utils/channel-plugins.js +82 -0
  340. package/dist/test-utils/ports.js +73 -0
  341. package/dist/tts/tts.js +12 -6
  342. package/dist/tui/tui-session-actions.js +166 -54
  343. package/dist/utils/fetch-timeout.js +20 -0
  344. package/dist/utils/normalize-secret-input.js +19 -0
  345. package/dist/utils/shell-argv.js +61 -0
  346. package/dist/utils/transcript-tools.js +58 -0
  347. package/dist/utils.js +55 -14
  348. package/dist/version.js +42 -5
  349. package/dist/web/qr-image.js +1 -61
  350. package/dist/wizard/onboarding.finalize.js +7 -7
  351. package/dist/wizard/onboarding.js +3 -3
  352. package/docs/RELEASE_WORKFOTS_COMPARISON.md +3 -3
  353. package/docs/_config.yml +2 -2
  354. package/docs/_layouts/default.html +9 -9
  355. package/docs/concepts/typebox.md +1 -1
  356. package/docs/docs.json +1 -1
  357. package/docs/northflank.mdx +7 -7
  358. package/docs/railway.mdx +3 -3
  359. package/docs/render.mdx +5 -5
  360. package/docs/start/lore.md +2 -2
  361. package/extensions/bluebubbles/index.ts +2 -2
  362. package/extensions/bluebubbles/package.json +1 -1
  363. package/extensions/bluebubbles/src/accounts.ts +8 -8
  364. package/extensions/bluebubbles/src/actions.test.ts +22 -22
  365. package/extensions/bluebubbles/src/actions.ts +5 -5
  366. package/extensions/bluebubbles/src/attachments.ts +2 -2
  367. package/extensions/bluebubbles/src/channel.ts +16 -16
  368. package/extensions/bluebubbles/src/chat.ts +2 -2
  369. package/extensions/bluebubbles/src/media-send.ts +2 -2
  370. package/extensions/bluebubbles/src/monitor.test.ts +46 -46
  371. package/extensions/bluebubbles/src/monitor.ts +5 -5
  372. package/extensions/bluebubbles/src/onboarding.ts +7 -7
  373. package/extensions/bluebubbles/src/reactions.ts +2 -2
  374. package/extensions/bluebubbles/src/send.ts +2 -2
  375. package/extensions/copilot-proxy/README.md +1 -1
  376. package/extensions/copilot-proxy/package.json +1 -1
  377. package/extensions/diagnostics-otel/index.ts +2 -2
  378. package/extensions/diagnostics-otel/package.json +1 -1
  379. package/extensions/diagnostics-otel/src/service.ts +3 -3
  380. package/extensions/discord/index.ts +2 -2
  381. package/extensions/discord/package.json +1 -1
  382. package/extensions/google-antigravity-auth/README.md +1 -1
  383. package/extensions/google-antigravity-auth/index.ts +1 -1
  384. package/extensions/google-antigravity-auth/package.json +1 -1
  385. package/extensions/google-gemini-cli-auth/README.md +1 -1
  386. package/extensions/google-gemini-cli-auth/oauth.ts +1 -1
  387. package/extensions/google-gemini-cli-auth/package.json +1 -1
  388. package/extensions/googlechat/index.ts +3 -3
  389. package/extensions/googlechat/package.json +1 -1
  390. package/extensions/googlechat/src/accounts.ts +8 -8
  391. package/extensions/googlechat/src/actions.ts +6 -6
  392. package/extensions/googlechat/src/channel.ts +21 -21
  393. package/extensions/googlechat/src/monitor.ts +8 -8
  394. package/extensions/googlechat/src/onboarding.ts +10 -10
  395. package/extensions/imessage/index.ts +2 -2
  396. package/extensions/imessage/package.json +1 -1
  397. package/extensions/line/index.ts +2 -2
  398. package/extensions/line/package.json +1 -1
  399. package/extensions/line/src/card-command.ts +2 -2
  400. package/extensions/line/src/channel.logout.test.ts +4 -4
  401. package/extensions/line/src/channel.sendPayload.test.ts +8 -8
  402. package/extensions/line/src/channel.ts +3 -3
  403. package/extensions/llm-task/README.md +3 -3
  404. package/extensions/llm-task/index.ts +2 -2
  405. package/extensions/llm-task/package.json +1 -1
  406. package/extensions/llm-task/src/llm-task-tool.ts +4 -4
  407. package/extensions/lobster/README.md +6 -6
  408. package/extensions/lobster/index.ts +2 -2
  409. package/extensions/lobster/src/lobster-tool.test.ts +4 -4
  410. package/extensions/lobster/src/lobster-tool.ts +2 -2
  411. package/extensions/matrix/index.ts +2 -2
  412. package/extensions/matrix/package.json +1 -1
  413. package/extensions/matrix/src/matrix/client/config.ts +1 -1
  414. package/extensions/matrix/src/matrix/monitor/handler.ts +1 -1
  415. package/extensions/matrix/src/onboarding.ts +1 -1
  416. package/extensions/mattermost/index.ts +2 -2
  417. package/extensions/mattermost/package.json +1 -1
  418. package/extensions/mattermost/src/mattermost/accounts.ts +8 -8
  419. package/extensions/mattermost/src/mattermost/monitor-helpers.ts +5 -5
  420. package/extensions/mattermost/src/mattermost/monitor.ts +2 -2
  421. package/extensions/mattermost/src/onboarding-helpers.ts +3 -3
  422. package/extensions/mattermost/src/onboarding.ts +2 -2
  423. package/extensions/memory-core/index.ts +2 -2
  424. package/extensions/memory-core/package.json +1 -1
  425. package/extensions/memory-lancedb/index.ts +3 -3
  426. package/extensions/memory-lancedb/package.json +1 -1
  427. package/extensions/msteams/index.ts +2 -2
  428. package/extensions/msteams/package.json +1 -1
  429. package/extensions/msteams/src/channel.directory.test.ts +2 -2
  430. package/extensions/msteams/src/channel.ts +2 -2
  431. package/extensions/msteams/src/graph-upload.ts +4 -4
  432. package/extensions/msteams/src/monitor-handler.ts +2 -2
  433. package/extensions/msteams/src/monitor.ts +2 -2
  434. package/extensions/msteams/src/onboarding.ts +9 -9
  435. package/extensions/msteams/src/reply-dispatcher.ts +2 -2
  436. package/extensions/msteams/src/send-context.ts +2 -2
  437. package/extensions/msteams/src/send.ts +4 -4
  438. package/extensions/nextcloud-talk/index.ts +2 -2
  439. package/extensions/nextcloud-talk/package.json +1 -1
  440. package/extensions/nextcloud-talk/src/channel.ts +7 -7
  441. package/extensions/nextcloud-talk/src/inbound.ts +7 -7
  442. package/extensions/nextcloud-talk/src/onboarding.ts +1 -1
  443. package/extensions/nostr/README.md +2 -2
  444. package/extensions/nostr/index.ts +5 -5
  445. package/extensions/nostr/package.json +1 -1
  446. package/extensions/nostr/src/types.ts +4 -4
  447. package/extensions/open-prose/index.ts +2 -2
  448. package/extensions/qwen-portal-auth/README.md +1 -1
  449. package/extensions/signal/index.ts +2 -2
  450. package/extensions/signal/package.json +1 -1
  451. package/extensions/slack/index.ts +2 -2
  452. package/extensions/slack/package.json +1 -1
  453. package/extensions/telegram/index.ts +2 -2
  454. package/extensions/telegram/package.json +1 -1
  455. package/extensions/telegram/src/channel.ts +2 -2
  456. package/extensions/tlon/README.md +2 -2
  457. package/extensions/tlon/index.ts +2 -2
  458. package/extensions/tlon/package.json +1 -1
  459. package/extensions/tlon/src/channel.ts +13 -13
  460. package/extensions/tlon/src/monitor/index.ts +3 -3
  461. package/extensions/tlon/src/onboarding.ts +3 -3
  462. package/extensions/tlon/src/types.ts +3 -3
  463. package/extensions/twitch/README.md +1 -1
  464. package/extensions/twitch/index.ts +2 -2
  465. package/extensions/twitch/package.json +1 -1
  466. package/extensions/twitch/src/config.ts +3 -3
  467. package/extensions/twitch/src/monitor.ts +3 -3
  468. package/extensions/twitch/src/onboarding.ts +9 -9
  469. package/extensions/twitch/src/outbound.test.ts +2 -2
  470. package/extensions/twitch/src/plugin.test.ts +2 -2
  471. package/extensions/twitch/src/plugin.ts +8 -8
  472. package/extensions/twitch/src/send.test.ts +2 -2
  473. package/extensions/twitch/src/send.ts +4 -4
  474. package/extensions/twitch/src/token.test.ts +8 -8
  475. package/extensions/twitch/src/token.ts +3 -3
  476. package/extensions/twitch/src/twitch-client.ts +3 -3
  477. package/extensions/twitch/src/types.ts +3 -3
  478. package/extensions/twitch/src/utils/markdown.ts +1 -1
  479. package/extensions/voice-call/README.md +3 -3
  480. package/extensions/voice-call/package.json +1 -1
  481. package/extensions/voice-call/src/core-bridge.ts +2 -2
  482. package/extensions/voice-call/src/response-generator.ts +1 -1
  483. package/extensions/whatsapp/index.ts +2 -2
  484. package/extensions/whatsapp/package.json +1 -1
  485. package/extensions/zalo/README.md +1 -1
  486. package/extensions/zalo/index.ts +2 -2
  487. package/extensions/zalo/package.json +1 -1
  488. package/extensions/zalo/src/accounts.ts +8 -8
  489. package/extensions/zalo/src/actions.ts +4 -4
  490. package/extensions/zalo/src/channel.directory.test.ts +2 -2
  491. package/extensions/zalo/src/channel.ts +18 -18
  492. package/extensions/zalo/src/monitor.ts +9 -9
  493. package/extensions/zalo/src/monitor.webhook.test.ts +2 -2
  494. package/extensions/zalo/src/onboarding.ts +24 -24
  495. package/extensions/zalo/src/send.ts +2 -2
  496. package/extensions/zalouser/README.md +2 -2
  497. package/extensions/zalouser/index.ts +2 -2
  498. package/extensions/zalouser/package.json +1 -1
  499. package/extensions/zalouser/src/accounts.ts +9 -9
  500. package/extensions/zalouser/src/channel.ts +24 -24
  501. package/extensions/zalouser/src/monitor.ts +4 -4
  502. package/extensions/zalouser/src/onboarding.ts +28 -28
  503. package/package.json +13 -251
  504. package/skills/nano-banana-pro/scripts/generate_image.py +1 -1
  505. package/skills/tmux/scripts/find-sessions.sh +1 -1
  506. package/CHANGELOG.md +0 -102
  507. package/README-header.png +0 -0
  508. package/git-hooks/pre-commit +0 -4
  509. package/scripts/format-staged.js +0 -148
  510. package/scripts/postinstall.js +0 -300
  511. package/scripts/setup-git-hooks.js +0 -96
@@ -0,0 +1,45 @@
1
+ import { clearActiveProgressLine } from "./progress-line.js";
2
+ const RESET_SEQUENCE = "\x1b[0m\x1b[?25h\x1b[?1000l\x1b[?1002l\x1b[?1003l\x1b[?1006l\x1b[?2004l";
3
+ function reportRestoreFailure(scope, err, reason) {
4
+ const suffix = reason ? ` (${reason})` : "";
5
+ const message = `[terminal] restore ${scope} failed${suffix}: ${String(err)}`;
6
+ try {
7
+ process.stderr.write(`${message}\n`);
8
+ }
9
+ catch (writeErr) {
10
+ console.error(`[terminal] restore reporting failed${suffix}: ${String(writeErr)}`);
11
+ }
12
+ }
13
+ export function restoreTerminalState(reason) {
14
+ try {
15
+ clearActiveProgressLine();
16
+ }
17
+ catch (err) {
18
+ reportRestoreFailure("progress line", err, reason);
19
+ }
20
+ const stdin = process.stdin;
21
+ if (stdin.isTTY && typeof stdin.setRawMode === "function") {
22
+ try {
23
+ stdin.setRawMode(false);
24
+ }
25
+ catch (err) {
26
+ reportRestoreFailure("raw mode", err, reason);
27
+ }
28
+ if (typeof stdin.isPaused === "function" && stdin.isPaused()) {
29
+ try {
30
+ stdin.resume();
31
+ }
32
+ catch (err) {
33
+ reportRestoreFailure("stdin resume", err, reason);
34
+ }
35
+ }
36
+ }
37
+ if (process.stdout.isTTY) {
38
+ try {
39
+ process.stdout.write(RESET_SEQUENCE);
40
+ }
41
+ catch (err) {
42
+ reportRestoreFailure("stdout reset", err, reason);
43
+ }
44
+ }
45
+ }
@@ -0,0 +1,16 @@
1
+ export function snapshotStateDirEnv() {
2
+ return {
3
+ clawdbotStateDir: process.env.CLAWDBOT_STATE_DIR,
4
+ };
5
+ }
6
+ export function restoreStateDirEnv(snapshot) {
7
+ if (snapshot.clawdbotStateDir === undefined) {
8
+ delete process.env.CLAWDBOT_STATE_DIR;
9
+ }
10
+ else {
11
+ process.env.CLAWDBOT_STATE_DIR = snapshot.clawdbotStateDir;
12
+ }
13
+ }
14
+ export function setStateDirEnv(stateDir) {
15
+ process.env.CLAWDBOT_STATE_DIR = stateDir;
16
+ }
@@ -0,0 +1,11 @@
1
+ import fs from "node:fs/promises";
2
+ import os from "node:os";
3
+ import path from "node:path";
4
+ export async function makeTempWorkspace(prefix = "poolbot-workspace-") {
5
+ return fs.mkdtemp(path.join(os.tmpdir(), prefix));
6
+ }
7
+ export async function writeWorkspaceFile(params) {
8
+ const filePath = path.join(params.dir, params.name);
9
+ await fs.writeFile(filePath, params.content, "utf-8");
10
+ return filePath;
11
+ }
@@ -0,0 +1,82 @@
1
+ import { imessageOutbound } from "../channels/plugins/outbound/imessage.js";
2
+ import { normalizeIMessageHandle } from "../imessage/targets.js";
3
+ export const createTestRegistry = (channels = []) => ({
4
+ plugins: [],
5
+ tools: [],
6
+ hooks: [],
7
+ typedHooks: [],
8
+ channels,
9
+ providers: [],
10
+ gatewayHandlers: {},
11
+ httpHandlers: [],
12
+ httpRoutes: [],
13
+ cliRegistrars: [],
14
+ services: [],
15
+ commands: [],
16
+ diagnostics: [],
17
+ });
18
+ export const createIMessageTestPlugin = (params) => ({
19
+ id: "imessage",
20
+ meta: {
21
+ id: "imessage",
22
+ label: "iMessage",
23
+ selectionLabel: "iMessage (imsg)",
24
+ docsPath: "/channels/imessage",
25
+ blurb: "iMessage test stub.",
26
+ aliases: ["imsg"],
27
+ },
28
+ capabilities: { chatTypes: ["direct", "group"], media: true },
29
+ config: {
30
+ listAccountIds: () => [],
31
+ resolveAccount: () => ({}),
32
+ },
33
+ status: {
34
+ collectStatusIssues: (accounts) => accounts.flatMap((account) => {
35
+ const lastError = typeof account.lastError === "string" ? account.lastError.trim() : "";
36
+ if (!lastError)
37
+ return [];
38
+ return [
39
+ {
40
+ channel: "imessage",
41
+ accountId: account.accountId,
42
+ kind: "runtime",
43
+ message: `Channel error: ${lastError}`,
44
+ },
45
+ ];
46
+ }),
47
+ },
48
+ outbound: params?.outbound ?? imessageOutbound,
49
+ messaging: {
50
+ targetResolver: {
51
+ looksLikeId: (raw) => {
52
+ const trimmed = raw.trim();
53
+ if (!trimmed)
54
+ return false;
55
+ if (/^(imessage:|sms:|auto:|chat_id:|chat_guid:|chat_identifier:)/i.test(trimmed)) {
56
+ return true;
57
+ }
58
+ if (trimmed.includes("@"))
59
+ return true;
60
+ return /^\+?\d{3,}$/.test(trimmed);
61
+ },
62
+ hint: "<handle|chat_id:ID>",
63
+ },
64
+ normalizeTarget: (raw) => normalizeIMessageHandle(raw),
65
+ },
66
+ });
67
+ export const createOutboundTestPlugin = (params) => ({
68
+ id: params.id,
69
+ meta: {
70
+ id: params.id,
71
+ label: params.label ?? String(params.id),
72
+ selectionLabel: params.label ?? String(params.id),
73
+ docsPath: params.docsPath ?? `/channels/${params.id}`,
74
+ blurb: "test stub.",
75
+ },
76
+ capabilities: params.capabilities ?? { chatTypes: ["direct"] },
77
+ config: {
78
+ listAccountIds: () => [],
79
+ resolveAccount: () => ({}),
80
+ },
81
+ outbound: params.outbound,
82
+ });
@@ -0,0 +1,73 @@
1
+ import { createServer } from "node:net";
2
+ import { isMainThread, threadId } from "node:worker_threads";
3
+ async function isPortFree(port) {
4
+ if (!Number.isFinite(port) || port <= 0 || port > 65535)
5
+ return false;
6
+ return await new Promise((resolve) => {
7
+ const server = createServer();
8
+ server.once("error", () => resolve(false));
9
+ server.listen(port, "127.0.0.1", () => {
10
+ server.close(() => resolve(true));
11
+ });
12
+ });
13
+ }
14
+ async function getOsFreePort() {
15
+ return await new Promise((resolve, reject) => {
16
+ const server = createServer();
17
+ server.once("error", reject);
18
+ server.listen(0, "127.0.0.1", () => {
19
+ const addr = server.address();
20
+ if (!addr || typeof addr === "string") {
21
+ server.close();
22
+ reject(new Error("failed to acquire free port"));
23
+ return;
24
+ }
25
+ const port = addr.port;
26
+ server.close((err) => (err ? reject(err) : resolve(port)));
27
+ });
28
+ });
29
+ }
30
+ let nextTestPortOffset = 0;
31
+ /**
32
+ * Allocate a deterministic per-worker port block.
33
+ *
34
+ * Motivation: many tests spin up gateway + related services that use derived ports
35
+ * (e.g. +1/+2/+3/+4). If each test just grabs an OS free port, parallel test runs
36
+ * can collide on derived ports and get flaky EADDRINUSE.
37
+ */
38
+ export async function getDeterministicFreePortBlock(params) {
39
+ const offsets = params?.offsets ?? [0, 1, 2, 3, 4];
40
+ const maxOffset = Math.max(...offsets);
41
+ const workerIdRaw = process.env.VITEST_WORKER_ID ?? process.env.VITEST_POOL_ID ?? "";
42
+ const workerId = Number.parseInt(workerIdRaw, 10);
43
+ const shard = Number.isFinite(workerId)
44
+ ? Math.max(0, workerId)
45
+ : isMainThread
46
+ ? Math.abs(process.pid)
47
+ : Math.abs(threadId);
48
+ const rangeSize = 1000;
49
+ const shardCount = 30;
50
+ const base = 30_000 + (Math.abs(shard) % shardCount) * rangeSize; // <= 59_999
51
+ const usable = rangeSize - maxOffset;
52
+ // Allocate in blocks to avoid derived-port overlaps (e.g. port+3).
53
+ const blockSize = Math.max(maxOffset + 1, 8);
54
+ for (let attempt = 0; attempt < usable; attempt += 1) {
55
+ const start = base + ((nextTestPortOffset + attempt) % usable);
56
+ // eslint-disable-next-line no-await-in-loop
57
+ const ok = (await Promise.all(offsets.map((offset) => isPortFree(start + offset)))).every(Boolean);
58
+ if (!ok)
59
+ continue;
60
+ nextTestPortOffset = (nextTestPortOffset + attempt + blockSize) % usable;
61
+ return start;
62
+ }
63
+ // Fallback: let the OS pick a port block (best effort).
64
+ for (let attempt = 0; attempt < 25; attempt += 1) {
65
+ // eslint-disable-next-line no-await-in-loop
66
+ const port = await getOsFreePort();
67
+ // eslint-disable-next-line no-await-in-loop
68
+ const ok = (await Promise.all(offsets.map((offset) => isPortFree(port + offset)))).every(Boolean);
69
+ if (ok)
70
+ return port;
71
+ }
72
+ throw new Error("failed to acquire a free port block");
73
+ }
package/dist/tts/tts.js CHANGED
@@ -579,9 +579,15 @@ export const OPENAI_TTS_MODELS = ["gpt-4o-mini-tts", "tts-1", "tts-1-hd"];
579
579
  * Custom OpenAI-compatible TTS endpoint.
580
580
  * When set, model/voice validation is relaxed to allow non-OpenAI models.
581
581
  * Example: OPENAI_TTS_BASE_URL=http://localhost:8880/v1
582
+ *
583
+ * Note: Read at runtime (not module load) to support config.env loading.
582
584
  */
583
- const OPENAI_TTS_BASE_URL = (process.env.OPENAI_TTS_BASE_URL?.trim() || "https://api.openai.com/v1").replace(/\/+$/, "");
584
- const isCustomOpenAIEndpoint = OPENAI_TTS_BASE_URL !== "https://api.openai.com/v1";
585
+ function getOpenAITtsBaseUrl() {
586
+ return (process.env.OPENAI_TTS_BASE_URL?.trim() || "https://api.openai.com/v1").replace(/\/+$/, "");
587
+ }
588
+ function isCustomOpenAIEndpoint() {
589
+ return getOpenAITtsBaseUrl() !== "https://api.openai.com/v1";
590
+ }
585
591
  export const OPENAI_TTS_VOICES = [
586
592
  "alloy",
587
593
  "ash",
@@ -595,13 +601,13 @@ export const OPENAI_TTS_VOICES = [
595
601
  ];
596
602
  function isValidOpenAIModel(model) {
597
603
  // Allow any model when using custom endpoint (e.g., Kokoro, LocalAI)
598
- if (isCustomOpenAIEndpoint)
604
+ if (isCustomOpenAIEndpoint())
599
605
  return true;
600
606
  return OPENAI_TTS_MODELS.includes(model);
601
607
  }
602
608
  function isValidOpenAIVoice(voice) {
603
609
  // Allow any voice when using custom endpoint (e.g., Kokoro Chinese voices)
604
- if (isCustomOpenAIEndpoint)
610
+ if (isCustomOpenAIEndpoint())
605
611
  return true;
606
612
  return OPENAI_TTS_VOICES.includes(voice);
607
613
  }
@@ -679,7 +685,7 @@ async function summarizeText(params) {
679
685
  catch (err) {
680
686
  const error = err;
681
687
  if (error.name === "AbortError") {
682
- throw new Error("Summarization timed out");
688
+ throw new Error("Summarization timed out", { cause: err });
683
689
  }
684
690
  throw err;
685
691
  }
@@ -754,7 +760,7 @@ async function openaiTTS(params) {
754
760
  const controller = new AbortController();
755
761
  const timeout = setTimeout(() => controller.abort(), timeoutMs);
756
762
  try {
757
- const response = await fetch(`${OPENAI_TTS_BASE_URL}/audio/speech`, {
763
+ const response = await fetch(`${getOpenAITtsBaseUrl()}/audio/speech`, {
758
764
  method: "POST",
759
765
  headers: {
760
766
  Authorization: `Bearer ${apiKey}`,
@@ -1,8 +1,9 @@
1
1
  import { normalizeAgentId, normalizeMainKey, parseAgentSessionKey, } from "../routing/session-key.js";
2
2
  import { asString, extractTextFromMessage, isCommandMessage } from "./tui-formatters.js";
3
3
  export function createSessionActions(context) {
4
- const { client, chatLog, tui, opts, state, agentNames, initialSessionInput, initialSessionAgentId, resolveSessionKey, updateHeader, updateFooter, updateAutocompleteProvider, setActivityStatus, } = context;
5
- let refreshSessionInfoPromise = null;
4
+ const { client, chatLog, tui, opts, state, agentNames, initialSessionInput, initialSessionAgentId, resolveSessionKey, updateHeader, updateFooter, updateAutocompleteProvider, setActivityStatus, clearLocalRunIds, } = context;
5
+ let refreshSessionInfoPromise = Promise.resolve();
6
+ let lastSessionDefaults = null;
6
7
  const applyAgentsResult = (result) => {
7
8
  state.agentDefaultId = normalizeAgentId(result.defaultId);
8
9
  state.sessionMainKey = normalizeMainKey(result.mainKey);
@@ -13,8 +14,9 @@ export function createSessionActions(context) {
13
14
  }));
14
15
  agentNames.clear();
15
16
  for (const agent of state.agents) {
16
- if (agent.name)
17
+ if (agent.name) {
17
18
  agentNames.set(agent.id, agent.name);
19
+ }
18
20
  }
19
21
  if (!state.initialSessionApplied) {
20
22
  if (initialSessionAgentId) {
@@ -50,62 +52,161 @@ export function createSessionActions(context) {
50
52
  };
51
53
  const updateAgentFromSessionKey = (key) => {
52
54
  const parsed = parseAgentSessionKey(key);
53
- if (!parsed)
55
+ if (!parsed) {
54
56
  return;
57
+ }
55
58
  const next = normalizeAgentId(parsed.agentId);
56
59
  if (next !== state.currentAgentId) {
57
60
  state.currentAgentId = next;
58
61
  }
59
62
  };
60
- const refreshSessionInfo = async () => {
61
- if (refreshSessionInfoPromise)
62
- return refreshSessionInfoPromise;
63
- refreshSessionInfoPromise = (async () => {
64
- try {
65
- const listAgentId = state.currentSessionKey === "global" || state.currentSessionKey === "unknown"
66
- ? undefined
67
- : state.currentAgentId;
68
- const result = await client.listSessions({
69
- includeGlobal: false,
70
- includeUnknown: false,
71
- agentId: listAgentId,
72
- });
73
- const entry = result.sessions.find((row) => {
74
- // Exact match
75
- if (row.key === state.currentSessionKey)
76
- return true;
77
- // Also match canonical keys like "agent:default:main" against "main"
78
- const parsed = parseAgentSessionKey(row.key);
79
- return parsed?.rest === state.currentSessionKey;
80
- });
81
- state.sessionInfo = {
82
- thinkingLevel: entry?.thinkingLevel,
83
- verboseLevel: entry?.verboseLevel,
84
- reasoningLevel: entry?.reasoningLevel,
85
- model: entry?.model ?? result.defaults?.model ?? undefined,
86
- modelProvider: entry?.modelProvider ?? result.defaults?.modelProvider ?? undefined,
87
- contextTokens: entry?.contextTokens ?? result.defaults?.contextTokens,
88
- inputTokens: entry?.inputTokens ?? null,
89
- outputTokens: entry?.outputTokens ?? null,
90
- totalTokens: entry?.totalTokens ?? null,
91
- responseUsage: entry?.responseUsage,
92
- updatedAt: entry?.updatedAt ?? null,
93
- displayName: entry?.displayName,
94
- };
95
- }
96
- catch (err) {
97
- chatLog.addSystem(`sessions list failed: ${String(err)}`);
98
- }
99
- updateAutocompleteProvider();
100
- updateFooter();
101
- tui.requestRender();
102
- })();
63
+ const resolveModelSelection = (entry) => {
64
+ if (entry?.modelProvider || entry?.model) {
65
+ return {
66
+ modelProvider: entry.modelProvider ?? state.sessionInfo.modelProvider,
67
+ model: entry.model ?? state.sessionInfo.model,
68
+ };
69
+ }
70
+ const overrideModel = entry?.modelOverride?.trim();
71
+ if (overrideModel) {
72
+ const overrideProvider = entry?.providerOverride?.trim() || state.sessionInfo.modelProvider;
73
+ return { modelProvider: overrideProvider, model: overrideModel };
74
+ }
75
+ return {
76
+ modelProvider: state.sessionInfo.modelProvider,
77
+ model: state.sessionInfo.model,
78
+ };
79
+ };
80
+ const applySessionInfo = (params) => {
81
+ const entry = params.entry ?? undefined;
82
+ const defaults = params.defaults ?? lastSessionDefaults ?? undefined;
83
+ const previousDefaults = lastSessionDefaults;
84
+ const defaultsChanged = params.defaults
85
+ ? previousDefaults?.model !== params.defaults.model ||
86
+ previousDefaults?.modelProvider !== params.defaults.modelProvider ||
87
+ previousDefaults?.contextTokens !== params.defaults.contextTokens
88
+ : false;
89
+ if (params.defaults) {
90
+ lastSessionDefaults = params.defaults;
91
+ }
92
+ const entryUpdatedAt = entry?.updatedAt ?? null;
93
+ const currentUpdatedAt = state.sessionInfo.updatedAt ?? null;
94
+ const modelChanged = (entry?.modelProvider !== undefined &&
95
+ entry.modelProvider !== state.sessionInfo.modelProvider) ||
96
+ (entry?.model !== undefined && entry.model !== state.sessionInfo.model);
97
+ if (!params.force &&
98
+ entryUpdatedAt !== null &&
99
+ currentUpdatedAt !== null &&
100
+ entryUpdatedAt < currentUpdatedAt &&
101
+ !defaultsChanged &&
102
+ !modelChanged) {
103
+ return;
104
+ }
105
+ const next = { ...state.sessionInfo };
106
+ if (entry?.thinkingLevel !== undefined) {
107
+ next.thinkingLevel = entry.thinkingLevel;
108
+ }
109
+ if (entry?.verboseLevel !== undefined) {
110
+ next.verboseLevel = entry.verboseLevel;
111
+ }
112
+ if (entry?.reasoningLevel !== undefined) {
113
+ next.reasoningLevel = entry.reasoningLevel;
114
+ }
115
+ if (entry?.responseUsage !== undefined) {
116
+ next.responseUsage = entry.responseUsage;
117
+ }
118
+ if (entry?.inputTokens !== undefined) {
119
+ next.inputTokens = entry.inputTokens;
120
+ }
121
+ if (entry?.outputTokens !== undefined) {
122
+ next.outputTokens = entry.outputTokens;
123
+ }
124
+ if (entry?.totalTokens !== undefined) {
125
+ next.totalTokens = entry.totalTokens;
126
+ }
127
+ if (entry?.contextTokens !== undefined || defaults?.contextTokens !== undefined) {
128
+ next.contextTokens =
129
+ entry?.contextTokens ?? defaults?.contextTokens ?? state.sessionInfo.contextTokens;
130
+ }
131
+ if (entry?.displayName !== undefined) {
132
+ next.displayName = entry.displayName;
133
+ }
134
+ if (entry?.updatedAt !== undefined) {
135
+ next.updatedAt = entry.updatedAt;
136
+ }
137
+ const selection = resolveModelSelection(entry);
138
+ if (selection.modelProvider !== undefined) {
139
+ next.modelProvider = selection.modelProvider;
140
+ }
141
+ if (selection.model !== undefined) {
142
+ next.model = selection.model;
143
+ }
144
+ state.sessionInfo = next;
145
+ updateAutocompleteProvider();
146
+ updateFooter();
147
+ tui.requestRender();
148
+ };
149
+ const runRefreshSessionInfo = async () => {
103
150
  try {
104
- await refreshSessionInfoPromise;
151
+ const resolveListAgentId = () => {
152
+ if (state.currentSessionKey === "global" || state.currentSessionKey === "unknown") {
153
+ return undefined;
154
+ }
155
+ const parsed = parseAgentSessionKey(state.currentSessionKey);
156
+ return parsed?.agentId ? normalizeAgentId(parsed.agentId) : state.currentAgentId;
157
+ };
158
+ const listAgentId = resolveListAgentId();
159
+ const result = await client.listSessions({
160
+ includeGlobal: false,
161
+ includeUnknown: false,
162
+ agentId: listAgentId,
163
+ });
164
+ const normalizeMatchKey = (key) => parseAgentSessionKey(key)?.rest ?? key;
165
+ const currentMatchKey = normalizeMatchKey(state.currentSessionKey);
166
+ const entry = result.sessions.find((row) => {
167
+ // Exact match
168
+ if (row.key === state.currentSessionKey) {
169
+ return true;
170
+ }
171
+ // Also match canonical keys like "agent:default:main" against "main"
172
+ return normalizeMatchKey(row.key) === currentMatchKey;
173
+ });
174
+ if (entry?.key && entry.key !== state.currentSessionKey) {
175
+ updateAgentFromSessionKey(entry.key);
176
+ state.currentSessionKey = entry.key;
177
+ updateHeader();
178
+ }
179
+ applySessionInfo({
180
+ entry,
181
+ defaults: result.defaults,
182
+ });
183
+ }
184
+ catch (err) {
185
+ chatLog.addSystem(`sessions list failed: ${String(err)}`);
186
+ }
187
+ };
188
+ const refreshSessionInfo = async () => {
189
+ refreshSessionInfoPromise = refreshSessionInfoPromise.then(runRefreshSessionInfo, runRefreshSessionInfo);
190
+ await refreshSessionInfoPromise;
191
+ };
192
+ const applySessionInfoFromPatch = (result) => {
193
+ if (!result?.entry) {
194
+ return;
105
195
  }
106
- finally {
107
- refreshSessionInfoPromise = null;
196
+ if (result.key && result.key !== state.currentSessionKey) {
197
+ updateAgentFromSessionKey(result.key);
198
+ state.currentSessionKey = result.key;
199
+ updateHeader();
108
200
  }
201
+ const resolved = result.resolved;
202
+ const entry = resolved && (resolved.modelProvider || resolved.model)
203
+ ? {
204
+ ...result.entry,
205
+ modelProvider: resolved.modelProvider ?? result.entry.modelProvider,
206
+ model: resolved.model ?? result.entry.model,
207
+ }
208
+ : result.entry;
209
+ applySessionInfo({ entry, force: true });
109
210
  };
110
211
  const loadHistory = async () => {
111
212
  try {
@@ -116,33 +217,42 @@ export function createSessionActions(context) {
116
217
  const record = history;
117
218
  state.currentSessionId = typeof record.sessionId === "string" ? record.sessionId : null;
118
219
  state.sessionInfo.thinkingLevel = record.thinkingLevel ?? state.sessionInfo.thinkingLevel;
220
+ state.sessionInfo.verboseLevel = record.verboseLevel ?? state.sessionInfo.verboseLevel;
221
+ const showTools = (state.sessionInfo.verboseLevel ?? "off") !== "off";
119
222
  chatLog.clearAll();
120
223
  chatLog.addSystem(`session ${state.currentSessionKey}`);
121
224
  for (const entry of record.messages ?? []) {
122
- if (!entry || typeof entry !== "object")
225
+ if (!entry || typeof entry !== "object") {
123
226
  continue;
227
+ }
124
228
  const message = entry;
125
229
  if (isCommandMessage(message)) {
126
230
  const text = extractTextFromMessage(message);
127
- if (text)
231
+ if (text) {
128
232
  chatLog.addSystem(text);
233
+ }
129
234
  continue;
130
235
  }
131
236
  if (message.role === "user") {
132
237
  const text = extractTextFromMessage(message);
133
- if (text)
238
+ if (text) {
134
239
  chatLog.addUser(text);
240
+ }
135
241
  continue;
136
242
  }
137
243
  if (message.role === "assistant") {
138
244
  const text = extractTextFromMessage(message, {
139
245
  includeThinking: state.showThinking,
140
246
  });
141
- if (text)
247
+ if (text) {
142
248
  chatLog.finalizeAssistant(text);
249
+ }
143
250
  continue;
144
251
  }
145
252
  if (message.role === "toolResult") {
253
+ if (!showTools) {
254
+ continue;
255
+ }
146
256
  const toolCallId = asString(message.toolCallId, "");
147
257
  const toolName = asString(message.toolName, "tool");
148
258
  const component = chatLog.startTool(toolCallId, toolName, {});
@@ -171,6 +281,7 @@ export function createSessionActions(context) {
171
281
  state.activeChatRunId = null;
172
282
  state.currentSessionId = null;
173
283
  state.historyLoaded = false;
284
+ clearLocalRunIds?.();
174
285
  updateHeader();
175
286
  updateFooter();
176
287
  await loadHistory();
@@ -198,6 +309,7 @@ export function createSessionActions(context) {
198
309
  applyAgentsResult,
199
310
  refreshAgents,
200
311
  refreshSessionInfo,
312
+ applySessionInfoFromPatch,
201
313
  loadHistory,
202
314
  setSession,
203
315
  abortActive,
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Fetch wrapper that adds timeout support via AbortController.
3
+ *
4
+ * @param url - The URL to fetch
5
+ * @param init - RequestInit options (headers, method, body, etc.)
6
+ * @param timeoutMs - Timeout in milliseconds
7
+ * @param fetchFn - The fetch implementation to use (defaults to global fetch)
8
+ * @returns The fetch Response
9
+ * @throws AbortError if the request times out
10
+ */
11
+ export async function fetchWithTimeout(url, init, timeoutMs, fetchFn = fetch) {
12
+ const controller = new AbortController();
13
+ const timer = setTimeout(() => controller.abort(), Math.max(1, timeoutMs));
14
+ try {
15
+ return await fetchFn(url, { ...init, signal: controller.signal });
16
+ }
17
+ finally {
18
+ clearTimeout(timer);
19
+ }
20
+ }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Secret normalization for copy/pasted credentials.
3
+ *
4
+ * Common footgun: line breaks (especially `\r`) embedded in API keys/tokens.
5
+ * We strip line breaks anywhere, then trim whitespace at the ends.
6
+ *
7
+ * Intentionally does NOT remove ordinary spaces inside the string to avoid
8
+ * silently altering "Bearer <token>" style values.
9
+ */
10
+ export function normalizeSecretInput(value) {
11
+ if (typeof value !== "string") {
12
+ return "";
13
+ }
14
+ return value.replace(/[\r\n\u2028\u2029]+/g, "").trim();
15
+ }
16
+ export function normalizeOptionalSecretInput(value) {
17
+ const normalized = normalizeSecretInput(value);
18
+ return normalized ? normalized : undefined;
19
+ }