@withbuddi/buddi 0.1.0-pre.41 → 0.1.0-pre.43

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 (337) hide show
  1. package/extension/background.js +11 -0
  2. package/extension/manifest.json +2 -2
  3. package/extension/popup.html +1 -1
  4. package/extension/popup.js +83 -1
  5. package/node_modules/@buddi/cli/dist/.tsbuildinfo +1 -1
  6. package/node_modules/@buddi/cli/dist/commands.js +2 -2
  7. package/node_modules/@buddi/cli/dist/commands.js.map +1 -1
  8. package/node_modules/@buddi/cli/dist/doctor-probes.d.ts.map +1 -1
  9. package/node_modules/@buddi/cli/dist/doctor-probes.js +10 -1
  10. package/node_modules/@buddi/cli/dist/doctor-probes.js.map +1 -1
  11. package/node_modules/@buddi/cli/dist/doctor.d.ts +9 -0
  12. package/node_modules/@buddi/cli/dist/doctor.d.ts.map +1 -1
  13. package/node_modules/@buddi/cli/dist/doctor.js +21 -3
  14. package/node_modules/@buddi/cli/dist/doctor.js.map +1 -1
  15. package/node_modules/@buddi/cli/package.json +4 -0
  16. package/node_modules/@buddi/core/dist/.tsbuildinfo +1 -1
  17. package/node_modules/@buddi/core/dist/agents/catalog.js +1 -1
  18. package/node_modules/@buddi/core/dist/agents/catalog.js.map +1 -1
  19. package/node_modules/@buddi/core/dist/testing/database-url.d.ts +13 -0
  20. package/node_modules/@buddi/core/dist/testing/database-url.d.ts.map +1 -1
  21. package/node_modules/@buddi/core/dist/testing/database-url.js +34 -0
  22. package/node_modules/@buddi/core/dist/testing/database-url.js.map +1 -1
  23. package/node_modules/@buddi/core/dist/testing/isolated-global-setup.d.ts +2 -0
  24. package/node_modules/@buddi/core/dist/testing/isolated-global-setup.d.ts.map +1 -0
  25. package/node_modules/@buddi/core/dist/testing/isolated-global-setup.js +20 -0
  26. package/node_modules/@buddi/core/dist/testing/isolated-global-setup.js.map +1 -0
  27. package/node_modules/@buddi/core/package.json +4 -0
  28. package/node_modules/@buddi/gateway/dist/.tsbuildinfo +1 -1
  29. package/node_modules/@buddi/gateway/dist/agents/platform.d.ts +8 -0
  30. package/node_modules/@buddi/gateway/dist/agents/platform.d.ts.map +1 -1
  31. package/node_modules/@buddi/gateway/dist/agents/platform.js +48 -22
  32. package/node_modules/@buddi/gateway/dist/agents/platform.js.map +1 -1
  33. package/node_modules/@buddi/gateway/dist/plugins/index.d.ts +1 -0
  34. package/node_modules/@buddi/gateway/dist/plugins/index.d.ts.map +1 -1
  35. package/node_modules/@buddi/gateway/dist/plugins/index.js +1 -0
  36. package/node_modules/@buddi/gateway/dist/plugins/index.js.map +1 -1
  37. package/node_modules/@buddi/gateway/dist/plugins/pages-state.d.ts +37 -0
  38. package/node_modules/@buddi/gateway/dist/plugins/pages-state.d.ts.map +1 -0
  39. package/node_modules/@buddi/gateway/dist/plugins/pages-state.js +98 -0
  40. package/node_modules/@buddi/gateway/dist/plugins/pages-state.js.map +1 -0
  41. package/node_modules/@buddi/gateway/dist/provider-accounts.d.ts +33 -4
  42. package/node_modules/@buddi/gateway/dist/provider-accounts.d.ts.map +1 -1
  43. package/node_modules/@buddi/gateway/dist/provider-accounts.js +81 -18
  44. package/node_modules/@buddi/gateway/dist/provider-accounts.js.map +1 -1
  45. package/node_modules/@buddi/gateway/dist/provider-diagnostics.d.ts +5 -0
  46. package/node_modules/@buddi/gateway/dist/provider-diagnostics.d.ts.map +1 -1
  47. package/node_modules/@buddi/gateway/dist/provider-diagnostics.js +6 -1
  48. package/node_modules/@buddi/gateway/dist/provider-diagnostics.js.map +1 -1
  49. package/node_modules/@buddi/gateway/dist/serve.d.ts.map +1 -1
  50. package/node_modules/@buddi/gateway/dist/serve.js +5 -2
  51. package/node_modules/@buddi/gateway/dist/serve.js.map +1 -1
  52. package/node_modules/@buddi/gateway/dist/web/agent-offers.d.ts +6 -0
  53. package/node_modules/@buddi/gateway/dist/web/agent-offers.d.ts.map +1 -1
  54. package/node_modules/@buddi/gateway/dist/web/agent-offers.js +6 -0
  55. package/node_modules/@buddi/gateway/dist/web/agent-offers.js.map +1 -1
  56. package/node_modules/@buddi/gateway/dist/web/api-routes.d.ts.map +1 -1
  57. package/node_modules/@buddi/gateway/dist/web/api-routes.js +9 -2
  58. package/node_modules/@buddi/gateway/dist/web/api-routes.js.map +1 -1
  59. package/node_modules/@buddi/gateway/dist/web/attention.d.ts +11 -1
  60. package/node_modules/@buddi/gateway/dist/web/attention.d.ts.map +1 -1
  61. package/node_modules/@buddi/gateway/dist/web/attention.js +22 -2
  62. package/node_modules/@buddi/gateway/dist/web/attention.js.map +1 -1
  63. package/node_modules/@buddi/gateway/dist/web/chat.d.ts +0 -2
  64. package/node_modules/@buddi/gateway/dist/web/chat.d.ts.map +1 -1
  65. package/node_modules/@buddi/gateway/dist/web/chat.js +15 -4
  66. package/node_modules/@buddi/gateway/dist/web/chat.js.map +1 -1
  67. package/node_modules/@buddi/gateway/dist/web/extension.d.ts +23 -0
  68. package/node_modules/@buddi/gateway/dist/web/extension.d.ts.map +1 -1
  69. package/node_modules/@buddi/gateway/dist/web/extension.js +116 -10
  70. package/node_modules/@buddi/gateway/dist/web/extension.js.map +1 -1
  71. package/node_modules/@buddi/gateway/dist/web/lock.d.ts +15 -0
  72. package/node_modules/@buddi/gateway/dist/web/lock.d.ts.map +1 -1
  73. package/node_modules/@buddi/gateway/dist/web/lock.js +7 -3
  74. package/node_modules/@buddi/gateway/dist/web/lock.js.map +1 -1
  75. package/node_modules/@buddi/gateway/dist/web/plugins.d.ts.map +1 -1
  76. package/node_modules/@buddi/gateway/dist/web/plugins.js +4 -0
  77. package/node_modules/@buddi/gateway/dist/web/plugins.js.map +1 -1
  78. package/node_modules/@buddi/gateway/dist/web/server.d.ts.map +1 -1
  79. package/node_modules/@buddi/gateway/dist/web/server.js +19 -6
  80. package/node_modules/@buddi/gateway/dist/web/server.js.map +1 -1
  81. package/node_modules/@buddi/gateway/dist/web/signed-out.d.ts +19 -0
  82. package/node_modules/@buddi/gateway/dist/web/signed-out.d.ts.map +1 -1
  83. package/node_modules/@buddi/gateway/dist/web/signed-out.js +61 -3
  84. package/node_modules/@buddi/gateway/dist/web/signed-out.js.map +1 -1
  85. package/node_modules/@buddi/gateway/dist/web/take-on.d.ts +3 -1
  86. package/node_modules/@buddi/gateway/dist/web/take-on.d.ts.map +1 -1
  87. package/node_modules/@buddi/gateway/dist/web/take-on.js +14 -3
  88. package/node_modules/@buddi/gateway/dist/web/take-on.js.map +1 -1
  89. package/node_modules/@buddi/gateway/dist/web/telegram.d.ts.map +1 -1
  90. package/node_modules/@buddi/gateway/dist/web/telegram.js +4 -2
  91. package/node_modules/@buddi/gateway/dist/web/telegram.js.map +1 -1
  92. package/node_modules/@buddi/gateway/dist/web/version.d.ts +10 -0
  93. package/node_modules/@buddi/gateway/dist/web/version.d.ts.map +1 -1
  94. package/node_modules/@buddi/gateway/dist/web/version.js +12 -0
  95. package/node_modules/@buddi/gateway/dist/web/version.js.map +1 -1
  96. package/node_modules/@buddi/gateway/dist/web/widgets.d.ts +2 -0
  97. package/node_modules/@buddi/gateway/dist/web/widgets.d.ts.map +1 -1
  98. package/node_modules/@buddi/gateway/dist/web/widgets.js +47 -13
  99. package/node_modules/@buddi/gateway/dist/web/widgets.js.map +1 -1
  100. package/node_modules/@buddi/install/dist/.tsbuildinfo +1 -1
  101. package/node_modules/@buddi/install/dist/backup.d.ts +12 -0
  102. package/node_modules/@buddi/install/dist/backup.d.ts.map +1 -1
  103. package/node_modules/@buddi/install/dist/backup.js +26 -8
  104. package/node_modules/@buddi/install/dist/backup.js.map +1 -1
  105. package/node_modules/@buddi/install/dist/cli-shim.d.ts +2 -0
  106. package/node_modules/@buddi/install/dist/cli-shim.d.ts.map +1 -1
  107. package/node_modules/@buddi/install/dist/cli-shim.js +4 -0
  108. package/node_modules/@buddi/install/dist/cli-shim.js.map +1 -1
  109. package/node_modules/@buddi/install/dist/doctor-timezone.js +1 -1
  110. package/node_modules/@buddi/install/dist/doctor-timezone.js.map +1 -1
  111. package/node_modules/@buddi/install/dist/kept-data.d.ts.map +1 -1
  112. package/node_modules/@buddi/install/dist/kept-data.js +3 -1
  113. package/node_modules/@buddi/install/dist/kept-data.js.map +1 -1
  114. package/node_modules/@buddi/install/dist/launcher.js +93 -3
  115. package/node_modules/@buddi/install/dist/launcher.js.map +1 -1
  116. package/node_modules/@buddi/install/dist/supervisor.d.ts +43 -0
  117. package/node_modules/@buddi/install/dist/supervisor.d.ts.map +1 -1
  118. package/node_modules/@buddi/install/dist/supervisor.js +97 -9
  119. package/node_modules/@buddi/install/dist/supervisor.js.map +1 -1
  120. package/node_modules/@buddi/install/dist/uninstall.d.ts +17 -0
  121. package/node_modules/@buddi/install/dist/uninstall.d.ts.map +1 -1
  122. package/node_modules/@buddi/install/dist/uninstall.js +90 -49
  123. package/node_modules/@buddi/install/dist/uninstall.js.map +1 -1
  124. package/node_modules/@buddi/install/dist/upgrade.d.ts +2 -0
  125. package/node_modules/@buddi/install/dist/upgrade.d.ts.map +1 -1
  126. package/node_modules/@buddi/install/dist/upgrade.js +3 -2
  127. package/node_modules/@buddi/install/dist/upgrade.js.map +1 -1
  128. package/node_modules/@buddi/runtime/dist/.tsbuildinfo +1 -1
  129. package/node_modules/@buddi/runtime/dist/codex-direct.d.ts +12 -1
  130. package/node_modules/@buddi/runtime/dist/codex-direct.d.ts.map +1 -1
  131. package/node_modules/@buddi/runtime/dist/codex-direct.js +15 -6
  132. package/node_modules/@buddi/runtime/dist/codex-direct.js.map +1 -1
  133. package/node_modules/@buddi/runtime/dist/groups.d.ts +5 -4
  134. package/node_modules/@buddi/runtime/dist/groups.d.ts.map +1 -1
  135. package/node_modules/@buddi/runtime/dist/groups.js +7 -6
  136. package/node_modules/@buddi/runtime/dist/groups.js.map +1 -1
  137. package/node_modules/@buddi/runtime/dist/provider-models.d.ts +4 -0
  138. package/node_modules/@buddi/runtime/dist/provider-models.d.ts.map +1 -1
  139. package/node_modules/@buddi/runtime/dist/provider-models.js.map +1 -1
  140. package/node_modules/@buddi/tool-browser/dist/.tsbuildinfo +1 -1
  141. package/node_modules/@buddi/tool-browser/dist/availability.d.ts +2 -2
  142. package/node_modules/@buddi/tool-browser/dist/availability.d.ts.map +1 -1
  143. package/node_modules/@buddi/tool-browser/dist/availability.js +2 -2
  144. package/node_modules/@buddi/tool-browser/dist/availability.js.map +1 -1
  145. package/node_modules/@buddi/tool-browser/dist/controller.d.ts +1 -1
  146. package/node_modules/@buddi/tool-browser/dist/controller.d.ts.map +1 -1
  147. package/node_modules/@buddi/tool-browser/dist/controller.js +1 -1
  148. package/node_modules/@buddi/tool-browser/dist/controller.js.map +1 -1
  149. package/node_modules/@buddi/tool-email/dist/.tsbuildinfo +1 -1
  150. package/node_modules/@buddi/tool-email/dist/pages/descriptors.d.ts.map +1 -1
  151. package/node_modules/@buddi/tool-email/dist/pages/descriptors.js +42 -0
  152. package/node_modules/@buddi/tool-email/dist/pages/descriptors.js.map +1 -1
  153. package/node_modules/@buddi/tool-email/dist/pages/queries.d.ts +14 -0
  154. package/node_modules/@buddi/tool-email/dist/pages/queries.d.ts.map +1 -1
  155. package/node_modules/@buddi/tool-email/dist/pages/queries.js +95 -8
  156. package/node_modules/@buddi/tool-email/dist/pages/queries.js.map +1 -1
  157. package/node_modules/@buddi/tool-email/dist/sources/inbox-poll.d.ts.map +1 -1
  158. package/node_modules/@buddi/tool-email/dist/sources/inbox-poll.js +5 -0
  159. package/node_modules/@buddi/tool-email/dist/sources/inbox-poll.js.map +1 -1
  160. package/node_modules/@buddi/tool-email/migrations/027_first_contact.sql +13 -0
  161. package/node_modules/@zone-eu/mailsplit/package.json +4 -4
  162. package/node_modules/imapflow/CHANGELOG.md +7 -0
  163. package/node_modules/imapflow/dist/cjs/package-info.d.ts +1 -1
  164. package/node_modules/imapflow/dist/cjs/package-info.js +1 -1
  165. package/node_modules/imapflow/dist/esm/package-info.d.ts +1 -1
  166. package/node_modules/imapflow/dist/esm/package-info.js +1 -1
  167. package/node_modules/imapflow/package.json +4 -4
  168. package/node_modules/libbase64/CHANGELOG.md +7 -0
  169. package/node_modules/libbase64/lib/libbase64.js +110 -58
  170. package/node_modules/libbase64/package.json +1 -1
  171. package/node_modules/libmime/CHANGELOG.md +7 -0
  172. package/node_modules/libmime/package.json +2 -2
  173. package/package.json +2 -2
  174. package/packages/cli/dist/.tsbuildinfo +1 -1
  175. package/packages/cli/dist/commands.js +2 -2
  176. package/packages/cli/dist/commands.js.map +1 -1
  177. package/packages/cli/dist/doctor-probes.d.ts.map +1 -1
  178. package/packages/cli/dist/doctor-probes.js +10 -1
  179. package/packages/cli/dist/doctor-probes.js.map +1 -1
  180. package/packages/cli/dist/doctor.d.ts +9 -0
  181. package/packages/cli/dist/doctor.d.ts.map +1 -1
  182. package/packages/cli/dist/doctor.js +21 -3
  183. package/packages/cli/dist/doctor.js.map +1 -1
  184. package/packages/cli/package.json +4 -0
  185. package/packages/core/dist/.tsbuildinfo +1 -1
  186. package/packages/core/dist/agents/catalog.js +1 -1
  187. package/packages/core/dist/agents/catalog.js.map +1 -1
  188. package/packages/core/dist/testing/database-url.d.ts +13 -0
  189. package/packages/core/dist/testing/database-url.d.ts.map +1 -1
  190. package/packages/core/dist/testing/database-url.js +34 -0
  191. package/packages/core/dist/testing/database-url.js.map +1 -1
  192. package/packages/core/dist/testing/isolated-global-setup.d.ts +2 -0
  193. package/packages/core/dist/testing/isolated-global-setup.d.ts.map +1 -0
  194. package/packages/core/dist/testing/isolated-global-setup.js +20 -0
  195. package/packages/core/dist/testing/isolated-global-setup.js.map +1 -0
  196. package/packages/core/package.json +4 -0
  197. package/packages/gateway/dist/.tsbuildinfo +1 -1
  198. package/packages/gateway/dist/agents/platform.d.ts +8 -0
  199. package/packages/gateway/dist/agents/platform.d.ts.map +1 -1
  200. package/packages/gateway/dist/agents/platform.js +48 -22
  201. package/packages/gateway/dist/agents/platform.js.map +1 -1
  202. package/packages/gateway/dist/plugins/index.d.ts +1 -0
  203. package/packages/gateway/dist/plugins/index.d.ts.map +1 -1
  204. package/packages/gateway/dist/plugins/index.js +1 -0
  205. package/packages/gateway/dist/plugins/index.js.map +1 -1
  206. package/packages/gateway/dist/plugins/pages-state.d.ts +37 -0
  207. package/packages/gateway/dist/plugins/pages-state.d.ts.map +1 -0
  208. package/packages/gateway/dist/plugins/pages-state.js +98 -0
  209. package/packages/gateway/dist/plugins/pages-state.js.map +1 -0
  210. package/packages/gateway/dist/provider-accounts.d.ts +33 -4
  211. package/packages/gateway/dist/provider-accounts.d.ts.map +1 -1
  212. package/packages/gateway/dist/provider-accounts.js +81 -18
  213. package/packages/gateway/dist/provider-accounts.js.map +1 -1
  214. package/packages/gateway/dist/provider-diagnostics.d.ts +5 -0
  215. package/packages/gateway/dist/provider-diagnostics.d.ts.map +1 -1
  216. package/packages/gateway/dist/provider-diagnostics.js +6 -1
  217. package/packages/gateway/dist/provider-diagnostics.js.map +1 -1
  218. package/packages/gateway/dist/serve.d.ts.map +1 -1
  219. package/packages/gateway/dist/serve.js +5 -2
  220. package/packages/gateway/dist/serve.js.map +1 -1
  221. package/packages/gateway/dist/web/agent-offers.d.ts +6 -0
  222. package/packages/gateway/dist/web/agent-offers.d.ts.map +1 -1
  223. package/packages/gateway/dist/web/agent-offers.js +6 -0
  224. package/packages/gateway/dist/web/agent-offers.js.map +1 -1
  225. package/packages/gateway/dist/web/api-routes.d.ts.map +1 -1
  226. package/packages/gateway/dist/web/api-routes.js +9 -2
  227. package/packages/gateway/dist/web/api-routes.js.map +1 -1
  228. package/packages/gateway/dist/web/attention.d.ts +11 -1
  229. package/packages/gateway/dist/web/attention.d.ts.map +1 -1
  230. package/packages/gateway/dist/web/attention.js +22 -2
  231. package/packages/gateway/dist/web/attention.js.map +1 -1
  232. package/packages/gateway/dist/web/chat.d.ts +0 -2
  233. package/packages/gateway/dist/web/chat.d.ts.map +1 -1
  234. package/packages/gateway/dist/web/chat.js +15 -4
  235. package/packages/gateway/dist/web/chat.js.map +1 -1
  236. package/packages/gateway/dist/web/extension.d.ts +23 -0
  237. package/packages/gateway/dist/web/extension.d.ts.map +1 -1
  238. package/packages/gateway/dist/web/extension.js +116 -10
  239. package/packages/gateway/dist/web/extension.js.map +1 -1
  240. package/packages/gateway/dist/web/lock.d.ts +15 -0
  241. package/packages/gateway/dist/web/lock.d.ts.map +1 -1
  242. package/packages/gateway/dist/web/lock.js +7 -3
  243. package/packages/gateway/dist/web/lock.js.map +1 -1
  244. package/packages/gateway/dist/web/plugins.d.ts.map +1 -1
  245. package/packages/gateway/dist/web/plugins.js +4 -0
  246. package/packages/gateway/dist/web/plugins.js.map +1 -1
  247. package/packages/gateway/dist/web/server.d.ts.map +1 -1
  248. package/packages/gateway/dist/web/server.js +19 -6
  249. package/packages/gateway/dist/web/server.js.map +1 -1
  250. package/packages/gateway/dist/web/signed-out.d.ts +19 -0
  251. package/packages/gateway/dist/web/signed-out.d.ts.map +1 -1
  252. package/packages/gateway/dist/web/signed-out.js +61 -3
  253. package/packages/gateway/dist/web/signed-out.js.map +1 -1
  254. package/packages/gateway/dist/web/take-on.d.ts +3 -1
  255. package/packages/gateway/dist/web/take-on.d.ts.map +1 -1
  256. package/packages/gateway/dist/web/take-on.js +14 -3
  257. package/packages/gateway/dist/web/take-on.js.map +1 -1
  258. package/packages/gateway/dist/web/telegram.d.ts.map +1 -1
  259. package/packages/gateway/dist/web/telegram.js +4 -2
  260. package/packages/gateway/dist/web/telegram.js.map +1 -1
  261. package/packages/gateway/dist/web/version.d.ts +10 -0
  262. package/packages/gateway/dist/web/version.d.ts.map +1 -1
  263. package/packages/gateway/dist/web/version.js +12 -0
  264. package/packages/gateway/dist/web/version.js.map +1 -1
  265. package/packages/gateway/dist/web/widgets.d.ts +2 -0
  266. package/packages/gateway/dist/web/widgets.d.ts.map +1 -1
  267. package/packages/gateway/dist/web/widgets.js +47 -13
  268. package/packages/gateway/dist/web/widgets.js.map +1 -1
  269. package/packages/install/dist/.tsbuildinfo +1 -1
  270. package/packages/install/dist/backup.d.ts +12 -0
  271. package/packages/install/dist/backup.d.ts.map +1 -1
  272. package/packages/install/dist/backup.js +26 -8
  273. package/packages/install/dist/backup.js.map +1 -1
  274. package/packages/install/dist/cli-shim.d.ts +2 -0
  275. package/packages/install/dist/cli-shim.d.ts.map +1 -1
  276. package/packages/install/dist/cli-shim.js +4 -0
  277. package/packages/install/dist/cli-shim.js.map +1 -1
  278. package/packages/install/dist/doctor-timezone.js +1 -1
  279. package/packages/install/dist/doctor-timezone.js.map +1 -1
  280. package/packages/install/dist/kept-data.d.ts.map +1 -1
  281. package/packages/install/dist/kept-data.js +3 -1
  282. package/packages/install/dist/kept-data.js.map +1 -1
  283. package/packages/install/dist/launcher.js +93 -3
  284. package/packages/install/dist/launcher.js.map +1 -1
  285. package/packages/install/dist/supervisor.d.ts +43 -0
  286. package/packages/install/dist/supervisor.d.ts.map +1 -1
  287. package/packages/install/dist/supervisor.js +97 -9
  288. package/packages/install/dist/supervisor.js.map +1 -1
  289. package/packages/install/dist/uninstall.d.ts +17 -0
  290. package/packages/install/dist/uninstall.d.ts.map +1 -1
  291. package/packages/install/dist/uninstall.js +90 -49
  292. package/packages/install/dist/uninstall.js.map +1 -1
  293. package/packages/install/dist/upgrade.d.ts +2 -0
  294. package/packages/install/dist/upgrade.d.ts.map +1 -1
  295. package/packages/install/dist/upgrade.js +3 -2
  296. package/packages/install/dist/upgrade.js.map +1 -1
  297. package/packages/runtime/dist/.tsbuildinfo +1 -1
  298. package/packages/runtime/dist/codex-direct.d.ts +12 -1
  299. package/packages/runtime/dist/codex-direct.d.ts.map +1 -1
  300. package/packages/runtime/dist/codex-direct.js +15 -6
  301. package/packages/runtime/dist/codex-direct.js.map +1 -1
  302. package/packages/runtime/dist/groups.d.ts +5 -4
  303. package/packages/runtime/dist/groups.d.ts.map +1 -1
  304. package/packages/runtime/dist/groups.js +7 -6
  305. package/packages/runtime/dist/groups.js.map +1 -1
  306. package/packages/runtime/dist/provider-models.d.ts +4 -0
  307. package/packages/runtime/dist/provider-models.d.ts.map +1 -1
  308. package/packages/runtime/dist/provider-models.js.map +1 -1
  309. package/packages/tools/browser/dist/.tsbuildinfo +1 -1
  310. package/packages/tools/browser/dist/availability.d.ts +2 -2
  311. package/packages/tools/browser/dist/availability.d.ts.map +1 -1
  312. package/packages/tools/browser/dist/availability.js +2 -2
  313. package/packages/tools/browser/dist/availability.js.map +1 -1
  314. package/packages/tools/browser/dist/controller.d.ts +1 -1
  315. package/packages/tools/browser/dist/controller.d.ts.map +1 -1
  316. package/packages/tools/browser/dist/controller.js +1 -1
  317. package/packages/tools/browser/dist/controller.js.map +1 -1
  318. package/packages/tools/email/dist/.tsbuildinfo +1 -1
  319. package/packages/tools/email/dist/pages/descriptors.d.ts.map +1 -1
  320. package/packages/tools/email/dist/pages/descriptors.js +42 -0
  321. package/packages/tools/email/dist/pages/descriptors.js.map +1 -1
  322. package/packages/tools/email/dist/pages/queries.d.ts +14 -0
  323. package/packages/tools/email/dist/pages/queries.d.ts.map +1 -1
  324. package/packages/tools/email/dist/pages/queries.js +95 -8
  325. package/packages/tools/email/dist/pages/queries.js.map +1 -1
  326. package/packages/tools/email/dist/sources/inbox-poll.d.ts.map +1 -1
  327. package/packages/tools/email/dist/sources/inbox-poll.js +5 -0
  328. package/packages/tools/email/dist/sources/inbox-poll.js.map +1 -1
  329. package/packages/tools/email/migrations/027_first_contact.sql +13 -0
  330. package/packages/web/dist/assets/index-BB52n8Fa.js +146 -0
  331. package/packages/web/dist/assets/index-CY4cPN4I.css +1 -0
  332. package/packages/web/dist/assets/{lottie_light-D-P1tn3V.js → lottie_light-CHWAvOde.js} +1 -1
  333. package/packages/web/dist/build.json +1 -1
  334. package/packages/web/dist/index.html +2 -2
  335. package/packages/web/dist/precache.json +4 -4
  336. package/packages/web/dist/assets/index-BkxHX_8g.js +0 -146
  337. package/packages/web/dist/assets/index-D2rOodlH.css +0 -1
@@ -29,4 +29,5 @@ export * from './dev.js';
29
29
  export * from './uninstall.js';
30
30
  export * from './provenance.js';
31
31
  export * from './toggle.js';
32
+ export * from './pages-state.js';
32
33
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/plugins/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,cAAc,eAAe,CAAC;AAC9B,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC;AAC1B,cAAc,UAAU,CAAC;AACzB,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,WAAW,CAAC;AAC1B,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC;AAC1B,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,cAAc,UAAU,CAAC;AACzB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC;AAChC,cAAc,aAAa,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/plugins/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,cAAc,eAAe,CAAC;AAC9B,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC;AAC1B,cAAc,UAAU,CAAC;AACzB,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,WAAW,CAAC;AAC1B,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC;AAC1B,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,cAAc,UAAU,CAAC;AACzB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC;AAChC,cAAc,aAAa,CAAC;AAC5B,cAAc,kBAAkB,CAAC"}
@@ -0,0 +1,37 @@
1
+ export interface PagesState {
2
+ pid: number;
3
+ at: string;
4
+ /** The plugins whose pages `GET /api/pages` lists now, sorted. */
5
+ plugins: string[];
6
+ }
7
+ export declare function pagesStateFile(env?: NodeJS.ProcessEnv): string;
8
+ /** The plugin names of every page a registry serves, each once, sorted. */
9
+ export declare function pagePlugins(registry: {
10
+ pages(): ReadonlyArray<{
11
+ plugin: string;
12
+ }>;
13
+ }): string[];
14
+ /** Write what this process serves. Never throws: the doctor then says it could not tell. */
15
+ export declare function writePagesState(env: NodeJS.ProcessEnv, registry: {
16
+ pages(): ReadonlyArray<{
17
+ plugin: string;
18
+ }>;
19
+ }, now?: Date): void;
20
+ /** A file older than this says nothing about the gateway running now. */
21
+ export declare const PAGES_STATE_MAX_AGE_MS: number;
22
+ /** When a process started, from `ps`; undefined when it cannot say. */
23
+ export declare function processStartedAt(pid: number): Date | undefined;
24
+ /**
25
+ * What the running gateway serves, or undefined when no live gateway wrote it.
26
+ *
27
+ * A pid alone is not enough: after a crash and a reboot the number can belong
28
+ * to any process. So the file is believed only when its writer is alive and
29
+ * ours, it is less than a day old, and it was written after that process
30
+ * started — a file from before the process with its pid began is somebody
31
+ * else's leftover.
32
+ */
33
+ export declare function readPagesState(env?: NodeJS.ProcessEnv, options?: {
34
+ now?: Date;
35
+ startedAt?: (pid: number) => Date | undefined;
36
+ }): PagesState | undefined;
37
+ //# sourceMappingURL=pages-state.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pages-state.d.ts","sourceRoot":"","sources":["../../src/plugins/pages-state.ts"],"names":[],"mappings":"AAiBA,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,EAAE,EAAE,MAAM,CAAC;IACX,kEAAkE;IAClE,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,wBAAgB,cAAc,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,CAE3E;AAED,2EAA2E;AAC3E,wBAAgB,WAAW,CAAC,QAAQ,EAAE;IAAE,KAAK,IAAI,aAAa,CAAC;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,GAAG,MAAM,EAAE,CAE9F;AAED,4FAA4F;AAC5F,wBAAgB,eAAe,CAC7B,GAAG,EAAE,MAAM,CAAC,UAAU,EACtB,QAAQ,EAAE;IAAE,KAAK,IAAI,aAAa,CAAC;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,EACxD,GAAG,GAAE,IAAiB,GACrB,IAAI,CAWN;AAED,yEAAyE;AACzE,eAAO,MAAM,sBAAsB,QAAsB,CAAC;AAgB1D,uEAAuE;AACvE,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAQ9D;AAED;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAC5B,GAAG,GAAE,MAAM,CAAC,UAAwB,EACpC,OAAO,GAAE;IAAE,GAAG,CAAC,EAAE,IAAI,CAAC;IAAC,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,GAAG,SAAS,CAAA;CAAO,GAC1E,UAAU,GAAG,SAAS,CAiBxB"}
@@ -0,0 +1,98 @@
1
+ /**
2
+ * Which plugins have pages in the running gateway, written where `buddi
3
+ * doctor` can read it.
4
+ *
5
+ * The doctor runs in its own process: it can import what is installed, but
6
+ * only the gateway knows what it actually registered. A plugin installed while
7
+ * buddi runs (first run's chapter 3, the catalogue) is loaded live or waits for
8
+ * a restart, and "installed" and "its page is in the rail" are two answers the
9
+ * owner needs side by side. So the gateway writes the names whose pages it
10
+ * serves at start and whenever its registry changes; the doctor reads the file
11
+ * when the process that wrote it is still alive, and the file is that process's.
12
+ */
13
+ import { execFileSync } from 'node:child_process';
14
+ import { mkdirSync, readFileSync, renameSync, statSync, writeFileSync } from 'node:fs';
15
+ import path from 'node:path';
16
+ import { dataDir } from '../web/config.js';
17
+ export function pagesStateFile(env = process.env) {
18
+ return path.join(dataDir(env), 'run', 'pages.json');
19
+ }
20
+ /** The plugin names of every page a registry serves, each once, sorted. */
21
+ export function pagePlugins(registry) {
22
+ return [...new Set(registry.pages().map((p) => p.plugin))].sort();
23
+ }
24
+ /** Write what this process serves. Never throws: the doctor then says it could not tell. */
25
+ export function writePagesState(env, registry, now = new Date()) {
26
+ try {
27
+ const file = pagesStateFile(env);
28
+ mkdirSync(path.dirname(file), { recursive: true });
29
+ const state = { pid: process.pid, at: now.toISOString(), plugins: pagePlugins(registry) };
30
+ const temp = `${file}.${process.pid}.tmp`;
31
+ writeFileSync(temp, `${JSON.stringify(state)}\n`, { mode: 0o600 });
32
+ renameSync(temp, file);
33
+ }
34
+ catch {
35
+ /* Not worth a start or a log line. */
36
+ }
37
+ }
38
+ /** A file older than this says nothing about the gateway running now. */
39
+ export const PAGES_STATE_MAX_AGE_MS = 24 * 60 * 60 * 1000;
40
+ /**
41
+ * Whether the pid is a live process this user owns. EPERM means a process of
42
+ * somebody else's holds the number now — never our gateway, which runs as the
43
+ * owner — so a reused pid is not taken for a live buddi.
44
+ */
45
+ function alive(pid) {
46
+ try {
47
+ process.kill(pid, 0);
48
+ return true;
49
+ }
50
+ catch {
51
+ return false;
52
+ }
53
+ }
54
+ /** When a process started, from `ps`; undefined when it cannot say. */
55
+ export function processStartedAt(pid) {
56
+ try {
57
+ const out = execFileSync('ps', ['-o', 'lstart=', '-p', String(pid)], { encoding: 'utf8', timeout: 3_000, stdio: ['ignore', 'pipe', 'ignore'] }).trim();
58
+ const at = out ? new Date(out) : undefined;
59
+ return at && Number.isFinite(at.getTime()) ? at : undefined;
60
+ }
61
+ catch {
62
+ return undefined;
63
+ }
64
+ }
65
+ /**
66
+ * What the running gateway serves, or undefined when no live gateway wrote it.
67
+ *
68
+ * A pid alone is not enough: after a crash and a reboot the number can belong
69
+ * to any process. So the file is believed only when its writer is alive and
70
+ * ours, it is less than a day old, and it was written after that process
71
+ * started — a file from before the process with its pid began is somebody
72
+ * else's leftover.
73
+ */
74
+ export function readPagesState(env = process.env, options = {}) {
75
+ try {
76
+ const file = pagesStateFile(env);
77
+ const parsed = JSON.parse(readFileSync(file, 'utf8'));
78
+ if (typeof parsed.pid !== 'number' || !Array.isArray(parsed.plugins) || typeof parsed.at !== 'string')
79
+ return undefined;
80
+ const now = (options.now ?? new Date()).getTime();
81
+ const at = Date.parse(parsed.at);
82
+ if (!Number.isFinite(at))
83
+ return undefined;
84
+ if (now - at > PAGES_STATE_MAX_AGE_MS || now - statSync(file).mtimeMs > PAGES_STATE_MAX_AGE_MS)
85
+ return undefined;
86
+ if (!alive(parsed.pid))
87
+ return undefined;
88
+ const started = (options.startedAt ?? processStartedAt)(parsed.pid);
89
+ // `ps` says when to the second; a file written in the same second counts.
90
+ if (started && at < started.getTime() - 1_000)
91
+ return undefined;
92
+ return { pid: parsed.pid, at: parsed.at, plugins: parsed.plugins.filter((p) => typeof p === 'string') };
93
+ }
94
+ catch {
95
+ return undefined;
96
+ }
97
+ }
98
+ //# sourceMappingURL=pages-state.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pages-state.js","sourceRoot":"","sources":["../../src/plugins/pages-state.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { type AgentCatalog, type LoadAgentCatalogOptions, type ProviderAccountsAccess, type ProviderRef, type ResolvedProvider, type Vault } from '@buddi/core';
2
- import { listProviderModels, type AccountModels, type OllamaConnectProtocol, type RuntimeProvider } from '@buddi/runtime';
2
+ import { listProviderModels, type AccountModels, type CompletionResponse, type OllamaConnectProtocol, type RuntimeProvider } from '@buddi/runtime';
3
3
  import type { Pool } from 'pg';
4
4
  import { type ProviderDiagnostic } from './provider-diagnostics.js';
5
5
  import { type AccountRateLimit } from './account-limits.js';
@@ -12,9 +12,22 @@ type Binding = {
12
12
  accountId: string;
13
13
  model: string;
14
14
  };
15
+ /**
16
+ * One connection test: the sentence the owner reads, and what it was made of.
17
+ * `detail` is the provider's own words on a failure, scrubbed of the key and
18
+ * every stored secret — read only under Details, never as the sentence.
19
+ */
15
20
  type TestResult = ProviderDiagnostic & {
16
21
  checkedAt: string;
22
+ model?: string;
23
+ reply?: string;
24
+ elapsedMs?: number;
25
+ tokens?: number;
26
+ billing?: 'key' | 'plan' | null;
27
+ detail?: string | null;
17
28
  };
29
+ /** The one prompt a connection test sends: short, fixed, no conversation, no tools. */
30
+ export declare const READY_PROMPT = "Reply with the single word: ready";
18
31
  declare const legacy: readonly [{
19
32
  readonly id: "legacy-openai-api";
20
33
  readonly name: "OPENAI_API_KEY";
@@ -48,7 +61,8 @@ export declare class ProviderAccounts {
48
61
  catalog: () => AgentCatalog;
49
62
  reload: () => void;
50
63
  vault?: Vault;
51
- test?: (resolved: ResolvedProvider) => Promise<void>;
64
+ /** Replaces the one ready prompt in tests: a recorded answer, or a recorded refusal thrown. */
65
+ test?: (resolved: ResolvedProvider) => Promise<CompletionResponse | void>;
52
66
  listModels?: typeof listProviderModels;
53
67
  /** mlxh's read-only probe, replaceable in tests. */
54
68
  probeMlxh?: typeof probeMlxh;
@@ -71,7 +85,8 @@ export declare class ProviderAccounts {
71
85
  catalog: () => AgentCatalog;
72
86
  reload: () => void;
73
87
  vault?: Vault;
74
- test?: (resolved: ResolvedProvider) => Promise<void>;
88
+ /** Replaces the one ready prompt in tests: a recorded answer, or a recorded refusal thrown. */
89
+ test?: (resolved: ResolvedProvider) => Promise<CompletionResponse | void>;
75
90
  listModels?: typeof listProviderModels;
76
91
  /** mlxh's read-only probe, replaceable in tests. */
77
92
  probeMlxh?: typeof probeMlxh;
@@ -157,7 +172,15 @@ export declare class ProviderAccounts {
157
172
  rateLimit(id: string): AccountRateLimit | null;
158
173
  /** Pins account identity/model for a run; disabling stops its next model call. */
159
174
  provider(ref: ProviderRef): RuntimeProvider;
160
- test(id: string): Promise<TestResult>;
175
+ /**
176
+ * Test an account. `reuseWithinMs` is the route's cooldown: a result this
177
+ * recent, for the account as it stands, is answered again rather than
178
+ * spending another call on the provider.
179
+ */
180
+ test(id: string, options?: {
181
+ reuseWithinMs?: number;
182
+ now?: number;
183
+ }): Promise<TestResult>;
161
184
  /**
162
185
  * What a plugin sees (`CoreToolContext.providerAccounts`): the listing, an HTTP
163
186
  * account resolved as a run resolves it, and a Codex account's profile
@@ -214,5 +237,11 @@ export declare class ProviderAccounts {
214
237
  cancelled?: undefined;
215
238
  }>;
216
239
  }
240
+ /**
241
+ * The sentence for a test that got an answer: what was asked, what came back,
242
+ * how long it took and roughly what it cost. A reasoning model may spend its
243
+ * five tokens thinking and say nothing; the account still works.
244
+ */
245
+ export declare function readyAnswer(model: string, answer: CompletionResponse | undefined, elapsedMs: number, billing: 'key' | 'plan' | null, secret?: string | null): Omit<TestResult, 'checkedAt'>;
217
246
  export {};
218
247
  //# sourceMappingURL=provider-accounts.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"provider-accounts.d.ts","sourceRoot":"","sources":["../src/provider-accounts.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"provider-accounts.d.ts","sourceRoot":"","sources":["../src/provider-accounts.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import { randomUUID } from 'node:crypto';
2
2
  import { setTimeout as delay } from 'node:timers/promises';
3
- import { GEMINI_BASE_URL, GEMINI_KEY_URL, MLXH_DEFAULT_MAX_PROMPT_TOKENS, OLLAMA_CLOUD_ACCOUNT_URL, isMlxhAccount, accountBaseUrl, accountModelProblem, accountProtocol, createVault, providerFromEnv, putOwnerSecret, registerSecretDestination, resolveProviderAccount, useOwnerSecret, vaultState, } from '@buddi/core';
3
+ import { GEMINI_BASE_URL, GEMINI_KEY_URL, MLXH_DEFAULT_MAX_PROMPT_TOKENS, OLLAMA_CLOUD_ACCOUNT_URL, isMlxhAccount, accountBaseUrl, accountModelProblem, accountProtocol, createVault, providerFromEnv, putOwnerSecret, registerSecretDestination, scrubText, scrubValueFrom, resolveProviderAccount, useOwnerSecret, vaultState, } from '@buddi/core';
4
4
  import { contextWindowTokens, createProvider, providerCapabilities, listProviderModels, readAnthropicTokens, readCodexTokens } from '@buddi/runtime';
5
5
  import { z } from 'zod';
6
6
  import { providerDiagnostic } from './provider-diagnostics.js';
@@ -26,6 +26,8 @@ function reportedWindow(map, model) {
26
26
  const tokens = map && Object.hasOwn(map, model) ? map[model] : undefined;
27
27
  return typeof tokens === 'number' && Number.isInteger(tokens) && tokens >= 8_000 && tokens <= 2_000_000 ? tokens : undefined;
28
28
  }
29
+ /** The one prompt a connection test sends: short, fixed, no conversation, no tools. */
30
+ export const READY_PROMPT = 'Reply with the single word: ready';
29
31
  const columns = `id, label, kind, auth, base_url as "baseUrl", default_model as "defaultModel",
30
32
  context_window_tokens as "contextWindowTokens", reported_context_windows as "reportedContextWindows",
31
33
  enabled, deleting, revision, secret_ref as "secretRef", legacy_env as "legacyEnv"`;
@@ -88,6 +90,8 @@ export class ProviderAccounts {
88
90
  #bindings = new Map();
89
91
  #configured = new Map();
90
92
  #tests = new Map();
93
+ /** The account revision each kept test result was made against. */
94
+ #testedRevision = new Map();
91
95
  #testing = new Set();
92
96
  /** Limits a provider set on an account, as of the last load or call. */
93
97
  #limits = new Map();
@@ -325,6 +329,7 @@ export class ProviderAccounts {
325
329
  const current = await this.#row(id);
326
330
  if (current.revision !== row.revision || !current.enabled || current.deleting)
327
331
  throw new ProviderAccountError(409, 'Account changed. Refresh models again.');
332
+ value = { ...value, fetchedAt: new Date().toISOString() };
328
333
  this.#modelLists.set(id, { revision: row.revision, until: Date.now() + 60_000, value });
329
334
  await this.#rememberWindows(current, value).catch(() => { });
330
335
  return value;
@@ -680,38 +685,50 @@ export class ProviderAccounts {
680
685
  },
681
686
  };
682
687
  }
683
- async test(id) {
688
+ /**
689
+ * Test an account. `reuseWithinMs` is the route's cooldown: a result this
690
+ * recent, for the account as it stands, is answered again rather than
691
+ * spending another call on the provider.
692
+ */
693
+ async test(id, options = {}) {
684
694
  if (this.#testing.has(id))
685
695
  throw new ProviderAccountError(409, 'A connection test is already running for this account.');
686
696
  this.#testing.add(id);
687
697
  try {
688
698
  const row = await this.#row(id);
699
+ const recent = this.#tests.get(id);
700
+ if (recent && options.reuseWithinMs && this.#testedRevision.get(id) === row.revision
701
+ && (options.now ?? Date.now()) - Date.parse(recent.checkedAt) < options.reuseWithinMs)
702
+ return recent;
689
703
  if (row.kind === 'codex')
690
704
  throw new ProviderAccountError(400, 'A ChatGPT subscription has no output-token cap for a connection test. Connect and send a test chat instead.');
691
- let diagnostic = { state: 'connected', message: 'Connection succeeded.', httpStatus: null, retryAt: null };
705
+ let result;
706
+ let secret = null;
707
+ const billing = testBilling(row);
692
708
  try {
693
- const resolved = resolveProviderAccount(row, row.defaultModel, await this.#usableSecret(row));
694
- if (this.deps.test)
695
- await this.deps.test(resolved);
696
- else
697
- await createProvider(resolved, { maxTokens: 32, maxStatusRetries: 0 }).complete({
698
- system: 'Reply with OK.', messages: [{ role: 'user', content: [{ type: 'text', text: 'Connection test. Reply OK.' }] }],
699
- // A model on this computer loads on its first request, which can take
700
- // a minute for a large one; a hosted provider answers in seconds or not at all.
701
- tools: [], signal: AbortSignal.timeout(isLocalAccount(row) ? 120_000 : 15_000),
702
- });
709
+ secret = await this.#usableSecret(row);
710
+ const resolved = resolveProviderAccount(row, row.defaultModel, secret);
711
+ const started = performance.now();
712
+ const answer = this.deps.test ? await this.deps.test(resolved) : await createProvider(resolved, { maxTokens: 5, maxStatusRetries: 0 }).complete({
713
+ system: 'You are checking that a connection works.', messages: [{ role: 'user', content: [{ type: 'text', text: READY_PROMPT }] }],
714
+ // A model on this computer loads on its first request, which can take
715
+ // a minute for a large one; a hosted provider answers in seconds or not at all.
716
+ tools: [], signal: AbortSignal.timeout(isLocalAccount(row) ? 120_000 : 15_000),
717
+ });
718
+ result = readyAnswer(row.defaultModel, answer ?? undefined, Math.round(performance.now() - started), billing, secret);
703
719
  }
704
720
  catch (error) {
705
- diagnostic = providerDiagnostic(error, { ...diagnosticContext(row), model: row.defaultModel });
721
+ result = { ...providerDiagnostic(error, { ...diagnosticContext(row), model: row.defaultModel }), model: row.defaultModel, detail: errorDetail(error, secret) };
706
722
  await this.#noteLimit(id, error);
707
723
  }
708
- if (diagnostic.state === 'connected')
724
+ if (result.state === 'connected')
709
725
  await this.#noteLimit(id, null);
710
726
  if ((await this.#row(id)).revision !== row.revision)
711
727
  throw new ProviderAccountError(409, 'Account changed during the test. Test it again.');
712
- const result = { ...diagnostic, checkedAt: new Date().toISOString() };
713
- this.#tests.set(id, result);
714
- return result;
728
+ const tested = { ...result, checkedAt: new Date().toISOString() };
729
+ this.#tests.set(id, tested);
730
+ this.#testedRevision.set(id, row.revision);
731
+ return tested;
715
732
  }
716
733
  finally {
717
734
  this.#testing.delete(id);
@@ -1095,6 +1112,52 @@ export class ProviderAccounts {
1095
1112
  function logRetry(notice) {
1096
1113
  console.error(`provider: ${notice.kind} attempt ${notice.attempt} failed, retrying in ${notice.delayMs}ms — ${notice.detail}`);
1097
1114
  }
1115
+ /** Who pays for a test call, when buddi knows: a key bills itself, a sign-in uses the plan. */
1116
+ function testBilling(row) {
1117
+ if (row.auth === 'anthropic-oauth' || row.auth === 'device-key' || row.auth === 'chatgpt')
1118
+ return 'plan';
1119
+ if (row.auth === 'api-key' && !isLocalAccount(row))
1120
+ return 'key';
1121
+ return null;
1122
+ }
1123
+ /** "1.4 s": one decimal under ten seconds, whole seconds after. */
1124
+ function seconds(ms) {
1125
+ const s = ms / 1000;
1126
+ return s < 10 ? `${s.toFixed(1)} s` : `${Math.round(s)} s`;
1127
+ }
1128
+ /**
1129
+ * The sentence for a test that got an answer: what was asked, what came back,
1130
+ * how long it took and roughly what it cost. A reasoning model may spend its
1131
+ * five tokens thinking and say nothing; the account still works.
1132
+ */
1133
+ export function readyAnswer(model, answer, elapsedMs, billing, secret = null) {
1134
+ // Scrubbed whole, before it is cut: a credential echoed across the cut would
1135
+ // otherwise leave its first characters on the screen.
1136
+ const raw = (answer?.content ?? []).map((b) => (b.type === 'text' ? b.text : '')).join('');
1137
+ const text = scrubbed(raw, secret).replace(/\s+/g, ' ').trim().slice(0, 40);
1138
+ const u = answer?.usage;
1139
+ const tokens = u ? u.input + u.output + (u.cacheRead ?? 0) + (u.cacheWrite ?? 0) : undefined;
1140
+ const said = text ? `it said ‘${text}’ in ${seconds(elapsedMs)}` : `it answered in ${seconds(elapsedMs)}, with no words inside the five-token limit`;
1141
+ const cost = tokens ? ` · about ${tokens} tokens` : '';
1142
+ const who = billing === 'key' ? ', billed to this key' : billing === 'plan' ? ', on your plan' : '';
1143
+ return {
1144
+ state: 'connected', message: `Asked ${model} to say ready → ${said}${cost}${tokens ? who : ''}.`,
1145
+ httpStatus: null, retryAt: null, model, reply: text, elapsedMs, ...(tokens !== undefined ? { tokens } : {}), billing,
1146
+ };
1147
+ }
1148
+ /** The provider's own words for Details: the key and every stored secret scrubbed out, kept short. */
1149
+ function errorDetail(error, secret) {
1150
+ const raw = error instanceof Error ? error.message : typeof error === 'string' ? error : '';
1151
+ if (!raw)
1152
+ return null;
1153
+ const text = scrubbed(raw, secret).replace(/\s+/g, ' ').trim();
1154
+ return text.length > 300 ? `${text.slice(0, 299)}…` : text;
1155
+ }
1156
+ /** A provider's text with the account's credential, every stored secret and anything key-shaped taken out. */
1157
+ function scrubbed(raw, secret) {
1158
+ const text = secret ? scrubValueFrom(secret, 'key', raw).text : raw;
1159
+ return scrubText(text).replace(/\b(sk|sk-ant|AIza|ghp|xox[abp])[-_A-Za-z0-9]{12,}/g, '‹key›');
1160
+ }
1098
1161
  function isLocalAccount(row) {
1099
1162
  if (row.kind !== 'openai-compatible' || !row.baseUrl)
1100
1163
  return false;