profclaw 0.0.1-beta.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 (942) hide show
  1. package/.env.example +215 -0
  2. package/CHANGELOG.md +49 -0
  3. package/CONTRIBUTING.md +119 -0
  4. package/Dockerfile +107 -0
  5. package/LICENSE +661 -0
  6. package/README.md +196 -0
  7. package/config/agents.yml +55 -0
  8. package/config/budget.yml +15 -0
  9. package/config/pricing.yml +46 -0
  10. package/config/settings.yml +168 -0
  11. package/dist/adapters/claude-code.d.ts +46 -0
  12. package/dist/adapters/claude-code.js +215 -0
  13. package/dist/adapters/index.d.ts +4 -0
  14. package/dist/adapters/index.js +4 -0
  15. package/dist/adapters/ollama.d.ts +45 -0
  16. package/dist/adapters/ollama.js +277 -0
  17. package/dist/adapters/openclaw.d.ts +60 -0
  18. package/dist/adapters/openclaw.js +289 -0
  19. package/dist/adapters/registry.d.ts +56 -0
  20. package/dist/adapters/registry.js +163 -0
  21. package/dist/agents/executor.d.ts +78 -0
  22. package/dist/agents/executor.js +657 -0
  23. package/dist/agents/index.d.ts +10 -0
  24. package/dist/agents/index.js +27 -0
  25. package/dist/agents/stop-conditions.d.ts +108 -0
  26. package/dist/agents/stop-conditions.js +299 -0
  27. package/dist/agents/types.d.ts +185 -0
  28. package/dist/agents/types.js +14 -0
  29. package/dist/ai/embedding-service.d.ts +96 -0
  30. package/dist/ai/embedding-service.js +333 -0
  31. package/dist/auth/api-tokens.d.ts +71 -0
  32. package/dist/auth/api-tokens.js +235 -0
  33. package/dist/auth/auth-service.d.ts +75 -0
  34. package/dist/auth/auth-service.js +557 -0
  35. package/dist/auth/device-identity.d.ts +96 -0
  36. package/dist/auth/device-identity.js +250 -0
  37. package/dist/auth/github-oauth.d.ts +20 -0
  38. package/dist/auth/github-oauth.js +59 -0
  39. package/dist/auth/jira-oauth.d.ts +25 -0
  40. package/dist/auth/jira-oauth.js +75 -0
  41. package/dist/auth/linear-oauth.d.ts +21 -0
  42. package/dist/auth/linear-oauth.js +59 -0
  43. package/dist/auth/middleware.d.ts +44 -0
  44. package/dist/auth/middleware.js +190 -0
  45. package/dist/auth/pairing-codes.d.ts +109 -0
  46. package/dist/auth/pairing-codes.js +274 -0
  47. package/dist/auth/password.d.ts +53 -0
  48. package/dist/auth/password.js +126 -0
  49. package/dist/auth/qr-pairing.d.ts +36 -0
  50. package/dist/auth/qr-pairing.js +138 -0
  51. package/dist/auth/slack-oauth.d.ts +31 -0
  52. package/dist/auth/slack-oauth.js +80 -0
  53. package/dist/backup/index.d.ts +50 -0
  54. package/dist/backup/index.js +184 -0
  55. package/dist/browser/adapters.d.ts +25 -0
  56. package/dist/browser/adapters.js +32 -0
  57. package/dist/browser/cli.d.ts +19 -0
  58. package/dist/browser/cli.js +277 -0
  59. package/dist/browser/compression.d.ts +32 -0
  60. package/dist/browser/compression.js +269 -0
  61. package/dist/browser/extensions.d.ts +144 -0
  62. package/dist/browser/extensions.js +251 -0
  63. package/dist/browser/index.d.ts +37 -0
  64. package/dist/browser/index.js +43 -0
  65. package/dist/browser/refs.d.ts +46 -0
  66. package/dist/browser/refs.js +120 -0
  67. package/dist/browser/search.d.ts +36 -0
  68. package/dist/browser/search.js +193 -0
  69. package/dist/browser/service.d.ts +94 -0
  70. package/dist/browser/service.js +358 -0
  71. package/dist/browser/snapshot.d.ts +19 -0
  72. package/dist/browser/snapshot.js +250 -0
  73. package/dist/browser/tools.d.ts +259 -0
  74. package/dist/browser/tools.js +463 -0
  75. package/dist/browser/types.d.ts +134 -0
  76. package/dist/browser/types.js +17 -0
  77. package/dist/chat/agentic-executor.d.ts +108 -0
  78. package/dist/chat/agentic-executor.js +739 -0
  79. package/dist/chat/api-key-detector.d.ts +41 -0
  80. package/dist/chat/api-key-detector.js +290 -0
  81. package/dist/chat/auto-reply.d.ts +90 -0
  82. package/dist/chat/auto-reply.js +272 -0
  83. package/dist/chat/conversations.d.ts +91 -0
  84. package/dist/chat/conversations.js +297 -0
  85. package/dist/chat/execution/audit.d.ts +192 -0
  86. package/dist/chat/execution/audit.js +323 -0
  87. package/dist/chat/execution/executor.d.ts +56 -0
  88. package/dist/chat/execution/executor.js +654 -0
  89. package/dist/chat/execution/guardrails.d.ts +98 -0
  90. package/dist/chat/execution/guardrails.js +571 -0
  91. package/dist/chat/execution/index.d.ts +61 -0
  92. package/dist/chat/execution/index.js +129 -0
  93. package/dist/chat/execution/model-capability.d.ts +34 -0
  94. package/dist/chat/execution/model-capability.js +96 -0
  95. package/dist/chat/execution/process-pool.d.ts +110 -0
  96. package/dist/chat/execution/process-pool.js +290 -0
  97. package/dist/chat/execution/pty.d.ts +92 -0
  98. package/dist/chat/execution/pty.js +285 -0
  99. package/dist/chat/execution/rate-limiter.d.ts +87 -0
  100. package/dist/chat/execution/rate-limiter.js +305 -0
  101. package/dist/chat/execution/registry.d.ts +54 -0
  102. package/dist/chat/execution/registry.js +220 -0
  103. package/dist/chat/execution/sandbox.d.ts +109 -0
  104. package/dist/chat/execution/sandbox.js +684 -0
  105. package/dist/chat/execution/secrets.d.ts +45 -0
  106. package/dist/chat/execution/secrets.js +338 -0
  107. package/dist/chat/execution/security.d.ts +179 -0
  108. package/dist/chat/execution/security.js +739 -0
  109. package/dist/chat/execution/self-correction.d.ts +162 -0
  110. package/dist/chat/execution/self-correction.js +557 -0
  111. package/dist/chat/execution/session-manager.d.ts +79 -0
  112. package/dist/chat/execution/session-manager.js +356 -0
  113. package/dist/chat/execution/session-spawn/config.d.ts +37 -0
  114. package/dist/chat/execution/session-spawn/config.js +83 -0
  115. package/dist/chat/execution/session-spawn/index.d.ts +10 -0
  116. package/dist/chat/execution/session-spawn/index.js +10 -0
  117. package/dist/chat/execution/session-spawn/manager.d.ts +35 -0
  118. package/dist/chat/execution/session-spawn/manager.js +418 -0
  119. package/dist/chat/execution/session-spawn/types.d.ts +117 -0
  120. package/dist/chat/execution/session-spawn/types.js +16 -0
  121. package/dist/chat/execution/smart-prompts.d.ts +34 -0
  122. package/dist/chat/execution/smart-prompts.js +151 -0
  123. package/dist/chat/execution/stream-results.d.ts +65 -0
  124. package/dist/chat/execution/stream-results.js +156 -0
  125. package/dist/chat/execution/tool-router.d.ts +76 -0
  126. package/dist/chat/execution/tool-router.js +296 -0
  127. package/dist/chat/execution/tools/agents-list.d.ts +49 -0
  128. package/dist/chat/execution/tools/agents-list.js +165 -0
  129. package/dist/chat/execution/tools/browser.d.ts +12 -0
  130. package/dist/chat/execution/tools/browser.js +14 -0
  131. package/dist/chat/execution/tools/canvas.d.ts +61 -0
  132. package/dist/chat/execution/tools/canvas.js +150 -0
  133. package/dist/chat/execution/tools/complete-task.d.ts +72 -0
  134. package/dist/chat/execution/tools/complete-task.js +104 -0
  135. package/dist/chat/execution/tools/cron-tool.d.ts +204 -0
  136. package/dist/chat/execution/tools/cron-tool.js +680 -0
  137. package/dist/chat/execution/tools/discord-actions.d.ts +120 -0
  138. package/dist/chat/execution/tools/discord-actions.js +361 -0
  139. package/dist/chat/execution/tools/exec.d.ts +43 -0
  140. package/dist/chat/execution/tools/exec.js +223 -0
  141. package/dist/chat/execution/tools/file-ops.d.ts +175 -0
  142. package/dist/chat/execution/tools/file-ops.js +723 -0
  143. package/dist/chat/execution/tools/git.d.ts +143 -0
  144. package/dist/chat/execution/tools/git.js +395 -0
  145. package/dist/chat/execution/tools/github.d.ts +42 -0
  146. package/dist/chat/execution/tools/github.js +184 -0
  147. package/dist/chat/execution/tools/glinr-ops.d.ts +202 -0
  148. package/dist/chat/execution/tools/glinr-ops.js +694 -0
  149. package/dist/chat/execution/tools/image-analyze.d.ts +29 -0
  150. package/dist/chat/execution/tools/image-analyze.js +127 -0
  151. package/dist/chat/execution/tools/index.d.ts +64 -0
  152. package/dist/chat/execution/tools/index.js +245 -0
  153. package/dist/chat/execution/tools/integrations.d.ts +109 -0
  154. package/dist/chat/execution/tools/integrations.js +237 -0
  155. package/dist/chat/execution/tools/link-understand.d.ts +34 -0
  156. package/dist/chat/execution/tools/link-understand.js +307 -0
  157. package/dist/chat/execution/tools/maintenance.d.ts +29 -0
  158. package/dist/chat/execution/tools/maintenance.js +105 -0
  159. package/dist/chat/execution/tools/memory-tools.d.ts +76 -0
  160. package/dist/chat/execution/tools/memory-tools.js +278 -0
  161. package/dist/chat/execution/tools/openai-image-gen.d.ts +51 -0
  162. package/dist/chat/execution/tools/openai-image-gen.js +212 -0
  163. package/dist/chat/execution/tools/profclaw-ops.d.ts +204 -0
  164. package/dist/chat/execution/tools/profclaw-ops.js +665 -0
  165. package/dist/chat/execution/tools/session-spawn.d.ts +146 -0
  166. package/dist/chat/execution/tools/session-spawn.js +544 -0
  167. package/dist/chat/execution/tools/session-status.d.ts +38 -0
  168. package/dist/chat/execution/tools/session-status.js +185 -0
  169. package/dist/chat/execution/tools/sessions-list.d.ts +49 -0
  170. package/dist/chat/execution/tools/sessions-list.js +153 -0
  171. package/dist/chat/execution/tools/sessions-send.d.ts +48 -0
  172. package/dist/chat/execution/tools/sessions-send.js +207 -0
  173. package/dist/chat/execution/tools/sessions-spawn.d.ts +51 -0
  174. package/dist/chat/execution/tools/sessions-spawn.js +137 -0
  175. package/dist/chat/execution/tools/slack-actions.d.ts +90 -0
  176. package/dist/chat/execution/tools/slack-actions.js +272 -0
  177. package/dist/chat/execution/tools/subagent-orchestrate.d.ts +66 -0
  178. package/dist/chat/execution/tools/subagent-orchestrate.js +313 -0
  179. package/dist/chat/execution/tools/system.d.ts +121 -0
  180. package/dist/chat/execution/tools/system.js +415 -0
  181. package/dist/chat/execution/tools/telegram-actions.d.ts +126 -0
  182. package/dist/chat/execution/tools/telegram-actions.js +339 -0
  183. package/dist/chat/execution/tools/test-run.d.ts +43 -0
  184. package/dist/chat/execution/tools/test-run.js +391 -0
  185. package/dist/chat/execution/tools/tts-speak.d.ts +39 -0
  186. package/dist/chat/execution/tools/tts-speak.js +199 -0
  187. package/dist/chat/execution/tools/web-fetch.d.ts +42 -0
  188. package/dist/chat/execution/tools/web-fetch.js +247 -0
  189. package/dist/chat/execution/tools/web-search.d.ts +53 -0
  190. package/dist/chat/execution/tools/web-search.js +130 -0
  191. package/dist/chat/execution/types.d.ts +337 -0
  192. package/dist/chat/execution/types.js +8 -0
  193. package/dist/chat/execution/workflows/built-in.d.ts +10 -0
  194. package/dist/chat/execution/workflows/built-in.js +249 -0
  195. package/dist/chat/execution/workflows/executor.d.ts +13 -0
  196. package/dist/chat/execution/workflows/executor.js +259 -0
  197. package/dist/chat/execution/workflows/index.d.ts +5 -0
  198. package/dist/chat/execution/workflows/index.js +5 -0
  199. package/dist/chat/execution/workflows/trigger.d.ts +15 -0
  200. package/dist/chat/execution/workflows/trigger.js +111 -0
  201. package/dist/chat/execution/workflows/types.d.ts +80 -0
  202. package/dist/chat/execution/workflows/types.js +2 -0
  203. package/dist/chat/failover/error.d.ts +73 -0
  204. package/dist/chat/failover/error.js +412 -0
  205. package/dist/chat/failover/index.d.ts +10 -0
  206. package/dist/chat/failover/index.js +11 -0
  207. package/dist/chat/failover/model-fallback.d.ts +97 -0
  208. package/dist/chat/failover/model-fallback.js +328 -0
  209. package/dist/chat/failover/types.d.ts +47 -0
  210. package/dist/chat/failover/types.js +8 -0
  211. package/dist/chat/format/chunk.d.ts +59 -0
  212. package/dist/chat/format/chunk.js +253 -0
  213. package/dist/chat/format/index.d.ts +7 -0
  214. package/dist/chat/format/index.js +7 -0
  215. package/dist/chat/format/tool-result-formatter.d.ts +30 -0
  216. package/dist/chat/format/tool-result-formatter.js +177 -0
  217. package/dist/chat/group.d.ts +232 -0
  218. package/dist/chat/group.js +311 -0
  219. package/dist/chat/index.d.ts +21 -0
  220. package/dist/chat/index.js +30 -0
  221. package/dist/chat/memory.d.ts +108 -0
  222. package/dist/chat/memory.js +343 -0
  223. package/dist/chat/message-handler.d.ts +38 -0
  224. package/dist/chat/message-handler.js +274 -0
  225. package/dist/chat/proactive/index.d.ts +167 -0
  226. package/dist/chat/proactive/index.js +721 -0
  227. package/dist/chat/prompt-adapter.d.ts +52 -0
  228. package/dist/chat/prompt-adapter.js +245 -0
  229. package/dist/chat/providers/dingtalk/index.d.ts +69 -0
  230. package/dist/chat/providers/dingtalk/index.js +225 -0
  231. package/dist/chat/providers/discord/index.d.ts +264 -0
  232. package/dist/chat/providers/discord/index.js +657 -0
  233. package/dist/chat/providers/feishu/index.d.ts +97 -0
  234. package/dist/chat/providers/feishu/index.js +362 -0
  235. package/dist/chat/providers/googlechat/index.d.ts +269 -0
  236. package/dist/chat/providers/googlechat/index.js +634 -0
  237. package/dist/chat/providers/imessage/index.d.ts +61 -0
  238. package/dist/chat/providers/imessage/index.js +166 -0
  239. package/dist/chat/providers/index.d.ts +76 -0
  240. package/dist/chat/providers/index.js +430 -0
  241. package/dist/chat/providers/irc/index.d.ts +101 -0
  242. package/dist/chat/providers/irc/index.js +557 -0
  243. package/dist/chat/providers/line/index.d.ts +113 -0
  244. package/dist/chat/providers/line/index.js +434 -0
  245. package/dist/chat/providers/matrix/index.d.ts +161 -0
  246. package/dist/chat/providers/matrix/index.js +559 -0
  247. package/dist/chat/providers/mattermost/index.d.ts +106 -0
  248. package/dist/chat/providers/mattermost/index.js +425 -0
  249. package/dist/chat/providers/msteams/index.d.ts +198 -0
  250. package/dist/chat/providers/msteams/index.js +694 -0
  251. package/dist/chat/providers/nextcloud/index.d.ts +52 -0
  252. package/dist/chat/providers/nextcloud/index.js +156 -0
  253. package/dist/chat/providers/nostr/index.d.ts +60 -0
  254. package/dist/chat/providers/nostr/index.js +200 -0
  255. package/dist/chat/providers/qq/index.d.ts +57 -0
  256. package/dist/chat/providers/qq/index.js +260 -0
  257. package/dist/chat/providers/registry.d.ts +89 -0
  258. package/dist/chat/providers/registry.js +213 -0
  259. package/dist/chat/providers/signal/index.d.ts +88 -0
  260. package/dist/chat/providers/signal/index.js +357 -0
  261. package/dist/chat/providers/slack/index.d.ts +52 -0
  262. package/dist/chat/providers/slack/index.js +477 -0
  263. package/dist/chat/providers/synology/index.d.ts +50 -0
  264. package/dist/chat/providers/synology/index.js +138 -0
  265. package/dist/chat/providers/telegram/index.d.ts +148 -0
  266. package/dist/chat/providers/telegram/index.js +492 -0
  267. package/dist/chat/providers/tlon/index.d.ts +44 -0
  268. package/dist/chat/providers/tlon/index.js +243 -0
  269. package/dist/chat/providers/twitch/index.d.ts +79 -0
  270. package/dist/chat/providers/twitch/index.js +349 -0
  271. package/dist/chat/providers/types.d.ts +437 -0
  272. package/dist/chat/providers/types.js +14 -0
  273. package/dist/chat/providers/webchat/index.d.ts +38 -0
  274. package/dist/chat/providers/webchat/index.js +214 -0
  275. package/dist/chat/providers/wecom/index.d.ts +62 -0
  276. package/dist/chat/providers/wecom/index.js +228 -0
  277. package/dist/chat/providers/whatsapp/index.d.ts +147 -0
  278. package/dist/chat/providers/whatsapp/index.js +396 -0
  279. package/dist/chat/providers/zalo/index.d.ts +54 -0
  280. package/dist/chat/providers/zalo/index.js +158 -0
  281. package/dist/chat/providers/zalo-personal/index.d.ts +53 -0
  282. package/dist/chat/providers/zalo-personal/index.js +212 -0
  283. package/dist/chat/skills.d.ts +82 -0
  284. package/dist/chat/skills.js +410 -0
  285. package/dist/chat/system-prompts.d.ts +76 -0
  286. package/dist/chat/system-prompts.js +407 -0
  287. package/dist/chat/tool-handler.d.ts +57 -0
  288. package/dist/chat/tool-handler.js +336 -0
  289. package/dist/chat/tools.d.ts +373 -0
  290. package/dist/chat/tools.js +512 -0
  291. package/dist/cli/commands/agent.d.ts +3 -0
  292. package/dist/cli/commands/agent.js +108 -0
  293. package/dist/cli/commands/auth.d.ts +12 -0
  294. package/dist/cli/commands/auth.js +301 -0
  295. package/dist/cli/commands/browser.d.ts +3 -0
  296. package/dist/cli/commands/browser.js +138 -0
  297. package/dist/cli/commands/canvas.d.ts +3 -0
  298. package/dist/cli/commands/canvas.js +155 -0
  299. package/dist/cli/commands/channels.d.ts +3 -0
  300. package/dist/cli/commands/channels.js +167 -0
  301. package/dist/cli/commands/chat.d.ts +9 -0
  302. package/dist/cli/commands/chat.js +360 -0
  303. package/dist/cli/commands/completion.d.ts +3 -0
  304. package/dist/cli/commands/completion.js +170 -0
  305. package/dist/cli/commands/config.d.ts +3 -0
  306. package/dist/cli/commands/config.js +193 -0
  307. package/dist/cli/commands/cost.d.ts +3 -0
  308. package/dist/cli/commands/cost.js +134 -0
  309. package/dist/cli/commands/daemon.d.ts +3 -0
  310. package/dist/cli/commands/daemon.js +381 -0
  311. package/dist/cli/commands/devices.d.ts +3 -0
  312. package/dist/cli/commands/devices.js +150 -0
  313. package/dist/cli/commands/doctor.d.ts +3 -0
  314. package/dist/cli/commands/doctor.js +295 -0
  315. package/dist/cli/commands/logs.d.ts +3 -0
  316. package/dist/cli/commands/logs.js +139 -0
  317. package/dist/cli/commands/mcp.d.ts +15 -0
  318. package/dist/cli/commands/mcp.js +157 -0
  319. package/dist/cli/commands/memory.d.ts +3 -0
  320. package/dist/cli/commands/memory.js +170 -0
  321. package/dist/cli/commands/models.d.ts +3 -0
  322. package/dist/cli/commands/models.js +197 -0
  323. package/dist/cli/commands/nodes.d.ts +3 -0
  324. package/dist/cli/commands/nodes.js +193 -0
  325. package/dist/cli/commands/onboard.d.ts +13 -0
  326. package/dist/cli/commands/onboard.js +360 -0
  327. package/dist/cli/commands/plugin.d.ts +15 -0
  328. package/dist/cli/commands/plugin.js +226 -0
  329. package/dist/cli/commands/provider.d.ts +16 -0
  330. package/dist/cli/commands/provider.js +320 -0
  331. package/dist/cli/commands/security.d.ts +3 -0
  332. package/dist/cli/commands/security.js +180 -0
  333. package/dist/cli/commands/serve.d.ts +3 -0
  334. package/dist/cli/commands/serve.js +179 -0
  335. package/dist/cli/commands/session.d.ts +3 -0
  336. package/dist/cli/commands/session.js +172 -0
  337. package/dist/cli/commands/setup.d.ts +13 -0
  338. package/dist/cli/commands/setup.js +636 -0
  339. package/dist/cli/commands/skill.d.ts +15 -0
  340. package/dist/cli/commands/skill.js +191 -0
  341. package/dist/cli/commands/status.d.ts +3 -0
  342. package/dist/cli/commands/status.js +71 -0
  343. package/dist/cli/commands/summary.d.ts +3 -0
  344. package/dist/cli/commands/summary.js +160 -0
  345. package/dist/cli/commands/task.d.ts +3 -0
  346. package/dist/cli/commands/task.js +170 -0
  347. package/dist/cli/commands/ticket.d.ts +3 -0
  348. package/dist/cli/commands/ticket.js +421 -0
  349. package/dist/cli/commands/tools.d.ts +9 -0
  350. package/dist/cli/commands/tools.js +508 -0
  351. package/dist/cli/commands/tui.d.ts +3 -0
  352. package/dist/cli/commands/tui.js +158 -0
  353. package/dist/cli/commands/tunnel.d.ts +3 -0
  354. package/dist/cli/commands/tunnel.js +135 -0
  355. package/dist/cli/commands/webhooks.d.ts +3 -0
  356. package/dist/cli/commands/webhooks.js +191 -0
  357. package/dist/cli/index.d.ts +3 -0
  358. package/dist/cli/index.js +127 -0
  359. package/dist/cli/utils/api.d.ts +17 -0
  360. package/dist/cli/utils/api.js +63 -0
  361. package/dist/cli/utils/config.d.ts +31 -0
  362. package/dist/cli/utils/config.js +81 -0
  363. package/dist/cli/utils/output.d.ts +58 -0
  364. package/dist/cli/utils/output.js +148 -0
  365. package/dist/core/deployment.d.ts +30 -0
  366. package/dist/core/deployment.js +114 -0
  367. package/dist/core/sandbox-config.d.ts +63 -0
  368. package/dist/core/sandbox-config.js +148 -0
  369. package/dist/costs/budget.d.ts +28 -0
  370. package/dist/costs/budget.js +57 -0
  371. package/dist/costs/persistence.d.ts +77 -0
  372. package/dist/costs/persistence.js +210 -0
  373. package/dist/costs/pricing.d.ts +16 -0
  374. package/dist/costs/pricing.js +39 -0
  375. package/dist/costs/token-tracker.d.ts +34 -0
  376. package/dist/costs/token-tracker.js +141 -0
  377. package/dist/cron/heartbeat.d.ts +23 -0
  378. package/dist/cron/heartbeat.js +109 -0
  379. package/dist/cron/index.d.ts +22 -0
  380. package/dist/cron/index.js +37 -0
  381. package/dist/cron/issue-poller.d.ts +15 -0
  382. package/dist/cron/issue-poller.js +174 -0
  383. package/dist/cron/scheduler.d.ts +315 -0
  384. package/dist/cron/scheduler.js +1008 -0
  385. package/dist/cron/stale-checker.d.ts +16 -0
  386. package/dist/cron/stale-checker.js +61 -0
  387. package/dist/cron/templates.d.ts +107 -0
  388. package/dist/cron/templates.js +395 -0
  389. package/dist/diagnostics/exporters.d.ts +21 -0
  390. package/dist/diagnostics/exporters.js +138 -0
  391. package/dist/diagnostics/index.d.ts +10 -0
  392. package/dist/diagnostics/index.js +9 -0
  393. package/dist/diagnostics/middleware.d.ts +12 -0
  394. package/dist/diagnostics/middleware.js +58 -0
  395. package/dist/diagnostics/tracer.d.ts +133 -0
  396. package/dist/diagnostics/tracer.js +257 -0
  397. package/dist/discovery/index.d.ts +8 -0
  398. package/dist/discovery/index.js +7 -0
  399. package/dist/discovery/mdns.d.ts +40 -0
  400. package/dist/discovery/mdns.js +249 -0
  401. package/dist/gateway/index.d.ts +35 -0
  402. package/dist/gateway/index.js +36 -0
  403. package/dist/gateway/router.d.ts +110 -0
  404. package/dist/gateway/router.js +649 -0
  405. package/dist/gateway/types.d.ts +275 -0
  406. package/dist/gateway/types.js +2 -0
  407. package/dist/gateway/workflows.d.ts +37 -0
  408. package/dist/gateway/workflows.js +748 -0
  409. package/dist/hooks/agent-webhook.d.ts +277 -0
  410. package/dist/hooks/agent-webhook.js +197 -0
  411. package/dist/hooks/index.d.ts +13 -0
  412. package/dist/hooks/index.js +15 -0
  413. package/dist/hooks/prompt-submit.d.ts +45 -0
  414. package/dist/hooks/prompt-submit.js +111 -0
  415. package/dist/hooks/schemas.d.ts +563 -0
  416. package/dist/hooks/schemas.js +108 -0
  417. package/dist/hooks/session-end.d.ts +25 -0
  418. package/dist/hooks/session-end.js +153 -0
  419. package/dist/hooks/tool-use.d.ts +41 -0
  420. package/dist/hooks/tool-use.js +201 -0
  421. package/dist/hooks/types.d.ts +76 -0
  422. package/dist/hooks/types.js +7 -0
  423. package/dist/integrations/cloudflare-tunnel.d.ts +78 -0
  424. package/dist/integrations/cloudflare-tunnel.js +268 -0
  425. package/dist/integrations/github-client.d.ts +27 -0
  426. package/dist/integrations/github-client.js +79 -0
  427. package/dist/integrations/github-projects.d.ts +97 -0
  428. package/dist/integrations/github-projects.js +433 -0
  429. package/dist/integrations/github-ticket-sync.d.ts +82 -0
  430. package/dist/integrations/github-ticket-sync.js +352 -0
  431. package/dist/integrations/github.d.ts +11 -0
  432. package/dist/integrations/github.js +241 -0
  433. package/dist/integrations/jira-client.d.ts +30 -0
  434. package/dist/integrations/jira-client.js +67 -0
  435. package/dist/integrations/jira.d.ts +13 -0
  436. package/dist/integrations/jira.js +108 -0
  437. package/dist/integrations/linear-client.d.ts +23 -0
  438. package/dist/integrations/linear-client.js +52 -0
  439. package/dist/integrations/linear.d.ts +15 -0
  440. package/dist/integrations/linear.js +312 -0
  441. package/dist/integrations/tailscale.d.ts +68 -0
  442. package/dist/integrations/tailscale.js +173 -0
  443. package/dist/integrations/web-search.d.ts +112 -0
  444. package/dist/integrations/web-search.js +287 -0
  445. package/dist/intelligence/index.d.ts +8 -0
  446. package/dist/intelligence/index.js +8 -0
  447. package/dist/intelligence/ollama.d.ts +50 -0
  448. package/dist/intelligence/ollama.js +213 -0
  449. package/dist/intelligence/rules.d.ts +39 -0
  450. package/dist/intelligence/rules.js +308 -0
  451. package/dist/labels/index.d.ts +93 -0
  452. package/dist/labels/index.js +248 -0
  453. package/dist/mcp/browser-tools.d.ts +10 -0
  454. package/dist/mcp/browser-tools.js +16 -0
  455. package/dist/mcp/client.d.ts +54 -0
  456. package/dist/mcp/client.js +153 -0
  457. package/dist/mcp/index.d.ts +12 -0
  458. package/dist/mcp/index.js +13 -0
  459. package/dist/mcp/server.d.ts +40 -0
  460. package/dist/mcp/server.js +826 -0
  461. package/dist/mcp/tool-adapter.d.ts +49 -0
  462. package/dist/mcp/tool-adapter.js +193 -0
  463. package/dist/memory/experience-store.d.ts +121 -0
  464. package/dist/memory/experience-store.js +439 -0
  465. package/dist/memory/index.d.ts +8 -0
  466. package/dist/memory/index.js +25 -0
  467. package/dist/memory/memory-service.d.ts +312 -0
  468. package/dist/memory/memory-service.js +1172 -0
  469. package/dist/memory/memory-watcher.d.ts +116 -0
  470. package/dist/memory/memory-watcher.js +239 -0
  471. package/dist/middleware/logging.d.ts +34 -0
  472. package/dist/middleware/logging.js +184 -0
  473. package/dist/middleware/rate-limit.d.ts +29 -0
  474. package/dist/middleware/rate-limit.js +91 -0
  475. package/dist/notifications/in-app.d.ts +28 -0
  476. package/dist/notifications/in-app.js +53 -0
  477. package/dist/notifications/index.d.ts +3 -0
  478. package/dist/notifications/index.js +3 -0
  479. package/dist/notifications/push.d.ts +74 -0
  480. package/dist/notifications/push.js +175 -0
  481. package/dist/notifications/slack.d.ts +32 -0
  482. package/dist/notifications/slack.js +157 -0
  483. package/dist/plugins/clawhub.d.ts +70 -0
  484. package/dist/plugins/clawhub.js +260 -0
  485. package/dist/plugins/loader.d.ts +23 -0
  486. package/dist/plugins/loader.js +140 -0
  487. package/dist/plugins/marketplace.d.ts +77 -0
  488. package/dist/plugins/marketplace.js +275 -0
  489. package/dist/plugins/registry.d.ts +122 -0
  490. package/dist/plugins/registry.js +352 -0
  491. package/dist/plugins/sandbox.d.ts +77 -0
  492. package/dist/plugins/sandbox.js +287 -0
  493. package/dist/plugins/scaffolder.d.ts +28 -0
  494. package/dist/plugins/scaffolder.js +409 -0
  495. package/dist/plugins/sdk.d.ts +35 -0
  496. package/dist/plugins/sdk.js +8 -0
  497. package/dist/plugins/search/brave.d.ts +9 -0
  498. package/dist/plugins/search/brave.js +157 -0
  499. package/dist/plugins/search/duckduckgo.d.ts +9 -0
  500. package/dist/plugins/search/duckduckgo.js +171 -0
  501. package/dist/plugins/search/index.d.ts +13 -0
  502. package/dist/plugins/search/index.js +23 -0
  503. package/dist/plugins/search/searxng.d.ts +9 -0
  504. package/dist/plugins/search/searxng.js +170 -0
  505. package/dist/plugins/search/serper.d.ts +9 -0
  506. package/dist/plugins/search/serper.js +135 -0
  507. package/dist/plugins/search/tavily.d.ts +9 -0
  508. package/dist/plugins/search/tavily.js +146 -0
  509. package/dist/plugins/types.d.ts +174 -0
  510. package/dist/plugins/types.js +8 -0
  511. package/dist/projects/index.d.ts +133 -0
  512. package/dist/projects/index.js +897 -0
  513. package/dist/projects/types.d.ts +444 -0
  514. package/dist/projects/types.js +207 -0
  515. package/dist/providers/adapters/anthropic.d.ts +26 -0
  516. package/dist/providers/adapters/anthropic.js +306 -0
  517. package/dist/providers/adapters/base.d.ts +53 -0
  518. package/dist/providers/adapters/base.js +99 -0
  519. package/dist/providers/adapters/ollama.d.ts +30 -0
  520. package/dist/providers/adapters/ollama.js +292 -0
  521. package/dist/providers/ai-sdk.d.ts +178 -0
  522. package/dist/providers/ai-sdk.js +1552 -0
  523. package/dist/providers/core/index.d.ts +8 -0
  524. package/dist/providers/core/index.js +10 -0
  525. package/dist/providers/core/models.d.ts +31 -0
  526. package/dist/providers/core/models.js +949 -0
  527. package/dist/providers/core/types.d.ts +117 -0
  528. package/dist/providers/core/types.js +83 -0
  529. package/dist/providers/index.d.ts +7 -0
  530. package/dist/providers/index.js +7 -0
  531. package/dist/providers/registry.d.ts +93 -0
  532. package/dist/providers/registry.js +228 -0
  533. package/dist/providers/schema-utils.d.ts +23 -0
  534. package/dist/providers/schema-utils.js +545 -0
  535. package/dist/providers/types.d.ts +609 -0
  536. package/dist/providers/types.js +279 -0
  537. package/dist/queue/failure-handler.d.ts +93 -0
  538. package/dist/queue/failure-handler.js +379 -0
  539. package/dist/queue/index.d.ts +23 -0
  540. package/dist/queue/index.js +86 -0
  541. package/dist/queue/memory-queue.d.ts +30 -0
  542. package/dist/queue/memory-queue.js +429 -0
  543. package/dist/queue/notifications.d.ts +6 -0
  544. package/dist/queue/notifications.js +128 -0
  545. package/dist/queue/task-queue.d.ts +55 -0
  546. package/dist/queue/task-queue.js +518 -0
  547. package/dist/queue/webhook-queue.d.ts +47 -0
  548. package/dist/queue/webhook-queue.js +158 -0
  549. package/dist/routes/agents.d.ts +4 -0
  550. package/dist/routes/agents.js +45 -0
  551. package/dist/routes/auth.d.ts +19 -0
  552. package/dist/routes/auth.js +492 -0
  553. package/dist/routes/backup.d.ts +6 -0
  554. package/dist/routes/backup.js +71 -0
  555. package/dist/routes/chat.d.ts +10 -0
  556. package/dist/routes/chat.js +1678 -0
  557. package/dist/routes/clawhub.d.ts +8 -0
  558. package/dist/routes/clawhub.js +89 -0
  559. package/dist/routes/costs.d.ts +4 -0
  560. package/dist/routes/costs.js +78 -0
  561. package/dist/routes/cron.d.ts +11 -0
  562. package/dist/routes/cron.js +708 -0
  563. package/dist/routes/devices.d.ts +9 -0
  564. package/dist/routes/devices.js +490 -0
  565. package/dist/routes/discord.d.ts +15 -0
  566. package/dist/routes/discord.js +524 -0
  567. package/dist/routes/dlq.d.ts +4 -0
  568. package/dist/routes/dlq.js +64 -0
  569. package/dist/routes/gateway.d.ts +4 -0
  570. package/dist/routes/gateway.js +253 -0
  571. package/dist/routes/health.d.ts +29 -0
  572. package/dist/routes/health.js +296 -0
  573. package/dist/routes/hooks.d.ts +4 -0
  574. package/dist/routes/hooks.js +170 -0
  575. package/dist/routes/import.d.ts +9 -0
  576. package/dist/routes/import.js +540 -0
  577. package/dist/routes/index.d.ts +38 -0
  578. package/dist/routes/index.js +39 -0
  579. package/dist/routes/integrations.d.ts +10 -0
  580. package/dist/routes/integrations.js +200 -0
  581. package/dist/routes/labels.d.ts +8 -0
  582. package/dist/routes/labels.js +240 -0
  583. package/dist/routes/mcp.d.ts +14 -0
  584. package/dist/routes/mcp.js +125 -0
  585. package/dist/routes/memory.d.ts +10 -0
  586. package/dist/routes/memory.js +622 -0
  587. package/dist/routes/notifications.d.ts +9 -0
  588. package/dist/routes/notifications.js +154 -0
  589. package/dist/routes/oobe.d.ts +10 -0
  590. package/dist/routes/oobe.js +405 -0
  591. package/dist/routes/openapi.d.ts +9 -0
  592. package/dist/routes/openapi.js +537 -0
  593. package/dist/routes/plugins.d.ts +8 -0
  594. package/dist/routes/plugins.js +108 -0
  595. package/dist/routes/projects.d.ts +8 -0
  596. package/dist/routes/projects.js +592 -0
  597. package/dist/routes/push.d.ts +8 -0
  598. package/dist/routes/push.js +75 -0
  599. package/dist/routes/search.d.ts +4 -0
  600. package/dist/routes/search.js +189 -0
  601. package/dist/routes/security.d.ts +10 -0
  602. package/dist/routes/security.js +189 -0
  603. package/dist/routes/settings.d.ts +4 -0
  604. package/dist/routes/settings.js +119 -0
  605. package/dist/routes/setup.d.ts +11 -0
  606. package/dist/routes/setup.js +525 -0
  607. package/dist/routes/skills.d.ts +13 -0
  608. package/dist/routes/skills.js +152 -0
  609. package/dist/routes/slack.d.ts +12 -0
  610. package/dist/routes/slack.js +999 -0
  611. package/dist/routes/states.d.ts +8 -0
  612. package/dist/routes/states.js +123 -0
  613. package/dist/routes/stats.d.ts +6 -0
  614. package/dist/routes/stats.js +369 -0
  615. package/dist/routes/summaries.d.ts +4 -0
  616. package/dist/routes/summaries.js +344 -0
  617. package/dist/routes/sync.d.ts +13 -0
  618. package/dist/routes/sync.js +268 -0
  619. package/dist/routes/tasks.d.ts +4 -0
  620. package/dist/routes/tasks.js +473 -0
  621. package/dist/routes/telegram.d.ts +14 -0
  622. package/dist/routes/telegram.js +420 -0
  623. package/dist/routes/tickets.d.ts +4 -0
  624. package/dist/routes/tickets.js +1090 -0
  625. package/dist/routes/tokens.d.ts +4 -0
  626. package/dist/routes/tokens.js +83 -0
  627. package/dist/routes/tools.d.ts +14 -0
  628. package/dist/routes/tools.js +790 -0
  629. package/dist/routes/tunnels.d.ts +8 -0
  630. package/dist/routes/tunnels.js +145 -0
  631. package/dist/routes/users.d.ts +15 -0
  632. package/dist/routes/users.js +998 -0
  633. package/dist/routes/voice.d.ts +8 -0
  634. package/dist/routes/voice.js +127 -0
  635. package/dist/routes/webchat.d.ts +11 -0
  636. package/dist/routes/webchat.js +173 -0
  637. package/dist/routes/webhook-dedup.d.ts +11 -0
  638. package/dist/routes/webhook-dedup.js +49 -0
  639. package/dist/routes/webhooks.d.ts +4 -0
  640. package/dist/routes/webhooks.js +71 -0
  641. package/dist/routes/whatsapp.d.ts +14 -0
  642. package/dist/routes/whatsapp.js +391 -0
  643. package/dist/security/audit-scanner.d.ts +32 -0
  644. package/dist/security/audit-scanner.js +217 -0
  645. package/dist/security/fs-guard.d.ts +41 -0
  646. package/dist/security/fs-guard.js +206 -0
  647. package/dist/security/prompt-guard.d.ts +47 -0
  648. package/dist/security/prompt-guard.js +198 -0
  649. package/dist/security/ssrf-guard.d.ts +38 -0
  650. package/dist/security/ssrf-guard.js +266 -0
  651. package/dist/security/types.d.ts +92 -0
  652. package/dist/security/types.js +8 -0
  653. package/dist/server/route-loader.d.ts +15 -0
  654. package/dist/server/route-loader.js +135 -0
  655. package/dist/server.d.ts +5 -0
  656. package/dist/server.js +835 -0
  657. package/dist/settings/index.d.ts +841 -0
  658. package/dist/settings/index.js +451 -0
  659. package/dist/skills/compiler.d.ts +83 -0
  660. package/dist/skills/compiler.js +358 -0
  661. package/dist/skills/frontmatter.d.ts +33 -0
  662. package/dist/skills/frontmatter.js +175 -0
  663. package/dist/skills/index.d.ts +19 -0
  664. package/dist/skills/index.js +24 -0
  665. package/dist/skills/installer.d.ts +22 -0
  666. package/dist/skills/installer.js +220 -0
  667. package/dist/skills/loader.d.ts +72 -0
  668. package/dist/skills/loader.js +484 -0
  669. package/dist/skills/prompt-builder.d.ts +48 -0
  670. package/dist/skills/prompt-builder.js +135 -0
  671. package/dist/skills/registry.d.ts +115 -0
  672. package/dist/skills/registry.js +225 -0
  673. package/dist/skills/types.d.ts +202 -0
  674. package/dist/skills/types.js +24 -0
  675. package/dist/states/index.d.ts +64 -0
  676. package/dist/states/index.js +142 -0
  677. package/dist/storage/adapter.d.ts +146 -0
  678. package/dist/storage/adapter.js +2 -0
  679. package/dist/storage/index.d.ts +48 -0
  680. package/dist/storage/index.js +135 -0
  681. package/dist/storage/libsql.d.ts +99 -0
  682. package/dist/storage/libsql.js +1873 -0
  683. package/dist/storage/migrations.d.ts +65 -0
  684. package/dist/storage/migrations.js +289 -0
  685. package/dist/storage/schema.d.ts +10185 -0
  686. package/dist/storage/schema.js +1113 -0
  687. package/dist/summaries/extractor.d.ts +56 -0
  688. package/dist/summaries/extractor.js +377 -0
  689. package/dist/summaries/index.d.ts +13 -0
  690. package/dist/summaries/index.js +14 -0
  691. package/dist/summaries/storage.d.ts +51 -0
  692. package/dist/summaries/storage.js +101 -0
  693. package/dist/summaries/templates.d.ts +68 -0
  694. package/dist/summaries/templates.js +245 -0
  695. package/dist/sync/adapters/base.d.ts +42 -0
  696. package/dist/sync/adapters/base.js +142 -0
  697. package/dist/sync/adapters/github.d.ts +45 -0
  698. package/dist/sync/adapters/github.js +445 -0
  699. package/dist/sync/adapters/linear.d.ts +40 -0
  700. package/dist/sync/adapters/linear.js +434 -0
  701. package/dist/sync/config.d.ts +388 -0
  702. package/dist/sync/config.js +281 -0
  703. package/dist/sync/engine.d.ts +112 -0
  704. package/dist/sync/engine.js +623 -0
  705. package/dist/sync/index.d.ts +31 -0
  706. package/dist/sync/index.js +34 -0
  707. package/dist/sync/integration.d.ts +53 -0
  708. package/dist/sync/integration.js +231 -0
  709. package/dist/sync/types.d.ts +249 -0
  710. package/dist/sync/types.js +30 -0
  711. package/dist/tickets/index.d.ts +139 -0
  712. package/dist/tickets/index.js +1406 -0
  713. package/dist/tickets/types.d.ts +817 -0
  714. package/dist/tickets/types.js +310 -0
  715. package/dist/tools/adapters.d.ts +56 -0
  716. package/dist/tools/adapters.js +183 -0
  717. package/dist/tools/index.d.ts +66 -0
  718. package/dist/tools/index.js +105 -0
  719. package/dist/tools/types.d.ts +117 -0
  720. package/dist/tools/types.js +20 -0
  721. package/dist/types/agent.d.ts +101 -0
  722. package/dist/types/agent.js +2 -0
  723. package/dist/types/errors.d.ts +150 -0
  724. package/dist/types/errors.js +338 -0
  725. package/dist/types/index.d.ts +3 -0
  726. package/dist/types/index.js +3 -0
  727. package/dist/types/summary.d.ts +638 -0
  728. package/dist/types/summary.js +137 -0
  729. package/dist/types/task.d.ts +123 -0
  730. package/dist/types/task.js +46 -0
  731. package/dist/utils/ai-cache.d.ts +72 -0
  732. package/dist/utils/ai-cache.js +204 -0
  733. package/dist/utils/ai-inference.d.ts +57 -0
  734. package/dist/utils/ai-inference.js +190 -0
  735. package/dist/utils/ai-responder.d.ts +44 -0
  736. package/dist/utils/ai-responder.js +272 -0
  737. package/dist/utils/circuit-breaker.d.ts +139 -0
  738. package/dist/utils/circuit-breaker.js +281 -0
  739. package/dist/utils/config-loader.d.ts +12 -0
  740. package/dist/utils/config-loader.js +44 -0
  741. package/dist/utils/crypto.d.ts +10 -0
  742. package/dist/utils/crypto.js +59 -0
  743. package/dist/utils/env-validator.d.ts +44 -0
  744. package/dist/utils/env-validator.js +236 -0
  745. package/dist/utils/file-lock.d.ts +85 -0
  746. package/dist/utils/file-lock.js +204 -0
  747. package/dist/utils/logger.d.ts +153 -0
  748. package/dist/utils/logger.js +282 -0
  749. package/dist/utils/metrics.d.ts +183 -0
  750. package/dist/utils/metrics.js +345 -0
  751. package/dist/utils/security.d.ts +90 -0
  752. package/dist/utils/security.js +347 -0
  753. package/dist/voice/index.d.ts +79 -0
  754. package/dist/voice/index.js +144 -0
  755. package/dist/voice/stt/whisper.d.ts +13 -0
  756. package/dist/voice/stt/whisper.js +116 -0
  757. package/dist/voice/tts/elevenlabs.d.ts +18 -0
  758. package/dist/voice/tts/elevenlabs.js +178 -0
  759. package/dist/voice/tts/openai-tts.d.ts +19 -0
  760. package/dist/voice/tts/openai-tts.js +127 -0
  761. package/dist/voice/tts/system.d.ts +26 -0
  762. package/dist/voice/tts/system.js +146 -0
  763. package/dist/voice/wake-word.d.ts +44 -0
  764. package/dist/voice/wake-word.js +145 -0
  765. package/docker-compose.yml +222 -0
  766. package/package.json +154 -0
  767. package/profclaw.mjs +24 -0
  768. package/skills/1password/SKILL.md +155 -0
  769. package/skills/api-tester/SKILL.md +177 -0
  770. package/skills/apple-notes/SKILL.md +167 -0
  771. package/skills/apple-reminders/SKILL.md +178 -0
  772. package/skills/bear-notes/SKILL.md +166 -0
  773. package/skills/blogwatcher/SKILL.md +177 -0
  774. package/skills/camsnap/SKILL.md +130 -0
  775. package/skills/code-generation/SKILL.md +139 -0
  776. package/skills/code-review/SKILL.md +116 -0
  777. package/skills/coding-agent/SKILL.md +184 -0
  778. package/skills/cron-manager/SKILL.md +141 -0
  779. package/skills/debug-helper/SKILL.md +134 -0
  780. package/skills/docker-ops/SKILL.md +246 -0
  781. package/skills/file-manager/SKILL.md +160 -0
  782. package/skills/git-workflow/SKILL.md +171 -0
  783. package/skills/github-issues/SKILL.md +244 -0
  784. package/skills/gog/SKILL.md +191 -0
  785. package/skills/goplaces/SKILL.md +156 -0
  786. package/skills/healthcheck/SKILL.md +270 -0
  787. package/skills/himalaya/SKILL.md +165 -0
  788. package/skills/mcp-discovery/SKILL.md +109 -0
  789. package/skills/memory-manager/SKILL.md +151 -0
  790. package/skills/model-usage/SKILL.md +177 -0
  791. package/skills/nano-banana-pro/SKILL.md +214 -0
  792. package/skills/nano-pdf/SKILL.md +165 -0
  793. package/skills/notion/SKILL.md +147 -0
  794. package/skills/obsidian/SKILL.md +163 -0
  795. package/skills/openai-image-gen/SKILL.md +194 -0
  796. package/skills/openai-whisper/SKILL.md +98 -0
  797. package/skills/openai-whisper-api/SKILL.md +130 -0
  798. package/skills/openhue/SKILL.md +203 -0
  799. package/skills/oracle/SKILL.md +236 -0
  800. package/skills/phone-control/SKILL.md +201 -0
  801. package/skills/profclaw-assistant/SKILL.md +81 -0
  802. package/skills/profclaw-projects/SKILL.md +68 -0
  803. package/skills/profclaw-tickets/SKILL.md +91 -0
  804. package/skills/session-logs/SKILL.md +216 -0
  805. package/skills/sherpa-onnx-tts/SKILL.md +134 -0
  806. package/skills/skill-creator/SKILL.md +183 -0
  807. package/skills/songsee/SKILL.md +170 -0
  808. package/skills/spotify-player/SKILL.md +254 -0
  809. package/skills/summarize/SKILL.md +155 -0
  810. package/skills/system-admin/SKILL.md +179 -0
  811. package/skills/things-mac/SKILL.md +179 -0
  812. package/skills/tmux/SKILL.md +170 -0
  813. package/skills/trello/SKILL.md +154 -0
  814. package/skills/video-frames/SKILL.md +127 -0
  815. package/skills/weather/SKILL.md +186 -0
  816. package/skills/web-research/SKILL.md +128 -0
  817. package/skills/xurl/SKILL.md +198 -0
  818. package/ui/README.md +73 -0
  819. package/ui/dist/assets/ActivityView-CkPgKhwm.js +1 -0
  820. package/ui/dist/assets/AgentList-C3SVdeEz.js +1 -0
  821. package/ui/dist/assets/AnalyticsDashboard-DVU--vlP.js +1 -0
  822. package/ui/dist/assets/AreaChart-B5qMEGWj.js +1 -0
  823. package/ui/dist/assets/CartesianChart-B50bcUJi.js +36 -0
  824. package/ui/dist/assets/ChatView-BZFJs7w_.js +10 -0
  825. package/ui/dist/assets/CostsDashboard-ChfH8BlG.js +1 -0
  826. package/ui/dist/assets/EstimateSelect-CLpB4NQO.js +1 -0
  827. package/ui/dist/assets/FloatingChatbot-CBzBY9a0.js +2 -0
  828. package/ui/dist/assets/InviteCodeManagement-DsbdPa6W.js +2 -0
  829. package/ui/dist/assets/ProjectDetail-BEM3tFXg.js +2 -0
  830. package/ui/dist/assets/ProjectDetail-D1-0B2xV.css +1 -0
  831. package/ui/dist/assets/ProjectIcon-CN1FmFAk.js +1 -0
  832. package/ui/dist/assets/ProjectList-DSDaNhxQ.js +4 -0
  833. package/ui/dist/assets/Settings-dPVcqC_d.js +6 -0
  834. package/ui/dist/assets/StatusIndicator-DA3NAo_b.js +1 -0
  835. package/ui/dist/assets/SummaryDetail-Bjnf9lT8.js +27 -0
  836. package/ui/dist/assets/SummaryList-ENwKDBKW.js +1 -0
  837. package/ui/dist/assets/TaskDetail-DnwG6MzB.js +1 -0
  838. package/ui/dist/assets/TaskList-D9Ug_HiV.js +1 -0
  839. package/ui/dist/assets/TicketBoard-CviH1571.js +1 -0
  840. package/ui/dist/assets/TicketDetail-8Jk8O-33.js +1 -0
  841. package/ui/dist/assets/TicketList-B-iV4rRA.js +1 -0
  842. package/ui/dist/assets/UserManagement-CPZ8s7s2.js +2 -0
  843. package/ui/dist/assets/ViewSwitcher-BUyOOWDI.js +1 -0
  844. package/ui/dist/assets/alert-dialog-BOmnTkN-.js +7 -0
  845. package/ui/dist/assets/archive-D5my9zOG.js +1 -0
  846. package/ui/dist/assets/badge-B4ov81_m.js +1 -0
  847. package/ui/dist/assets/brain-C53ElFLD.js +1 -0
  848. package/ui/dist/assets/bug-D0TJoCYn.js +1 -0
  849. package/ui/dist/assets/calendar-BkWIhKa1.js +1 -0
  850. package/ui/dist/assets/chevron-up-BRTtndUZ.js +1 -0
  851. package/ui/dist/assets/circle-x-BN89YhbS.js +1 -0
  852. package/ui/dist/assets/constants-fc7TFI7u.js +1 -0
  853. package/ui/dist/assets/cpu-B41x1-vV.js +1 -0
  854. package/ui/dist/assets/database-D9Cnfmzj.js +1 -0
  855. package/ui/dist/assets/defineProperty-CoXUr7_6.js +2 -0
  856. package/ui/dist/assets/dialog-DrWB4EYD.js +1 -0
  857. package/ui/dist/assets/element-adapter-DL0DQilL.js +4 -0
  858. package/ui/dist/assets/ellipsis-NuUWekvu.js +1 -0
  859. package/ui/dist/assets/ellipsis-vertical-BueMfuCw.js +1 -0
  860. package/ui/dist/assets/file-code-HR9829Jc.js +1 -0
  861. package/ui/dist/assets/folder-open-C_7oYEqe.js +1 -0
  862. package/ui/dist/assets/funnel-B5gmNXGf.js +1 -0
  863. package/ui/dist/assets/git-branch-BRMiJmV3.js +1 -0
  864. package/ui/dist/assets/git-commit-horizontal-CXOUQeJI.js +1 -0
  865. package/ui/dist/assets/globe-CCspjvus.js +1 -0
  866. package/ui/dist/assets/hash-g3102kPC.js +1 -0
  867. package/ui/dist/assets/history-CNqcBBrV.js +1 -0
  868. package/ui/dist/assets/index-27mTPKuh.js +1 -0
  869. package/ui/dist/assets/index-BMx3fH-e.js +1 -0
  870. package/ui/dist/assets/index-C9jNQXzL.js +1 -0
  871. package/ui/dist/assets/index-CEZ6R2Uw.js +7 -0
  872. package/ui/dist/assets/index-DURTouJI.js +1 -0
  873. package/ui/dist/assets/index-WclMPci1.css +1 -0
  874. package/ui/dist/assets/index-kb4AJXUB.js +67 -0
  875. package/ui/dist/assets/layers-CLXiHN6o.js +1 -0
  876. package/ui/dist/assets/layout-dashboard-B07MFhBs.js +1 -0
  877. package/ui/dist/assets/lightbulb-B2dgG5ks.js +1 -0
  878. package/ui/dist/assets/link-2-BxNmr9hL.js +1 -0
  879. package/ui/dist/assets/markdown-renderer-CjU6hBcW.js +36 -0
  880. package/ui/dist/assets/message-square-Bf2-CVbt.js +1 -0
  881. package/ui/dist/assets/pencil-D096Ey62.js +1 -0
  882. package/ui/dist/assets/play-DfdcSI3x.js +1 -0
  883. package/ui/dist/assets/popover-BV0QJDQq.js +1 -0
  884. package/ui/dist/assets/progress-DjPEDJfI.js +1 -0
  885. package/ui/dist/assets/rocket-CPsTc-5G.js +1 -0
  886. package/ui/dist/assets/select-LsO16slr.js +1 -0
  887. package/ui/dist/assets/send-BDYBZDUZ.js +1 -0
  888. package/ui/dist/assets/server-B3k6noce.js +1 -0
  889. package/ui/dist/assets/settings-2-Cu4xTjhG.js +1 -0
  890. package/ui/dist/assets/sheet-BScLnPKX.js +1 -0
  891. package/ui/dist/assets/shield-check-CQqkwufI.js +1 -0
  892. package/ui/dist/assets/shield-off-ZFruH9KO.js +1 -0
  893. package/ui/dist/assets/skeleton-CtkIA_MU.js +1 -0
  894. package/ui/dist/assets/smartphone-DnoksVkc.js +1 -0
  895. package/ui/dist/assets/square-uD9ZHMfW.js +1 -0
  896. package/ui/dist/assets/switch-MQPnwGJK.js +1 -0
  897. package/ui/dist/assets/table-B8cqlywA.js +1 -0
  898. package/ui/dist/assets/tag-wEJQRWlV.js +1 -0
  899. package/ui/dist/assets/textarea-D5LJCOGl.js +1 -0
  900. package/ui/dist/assets/timer-mbGHegmr.js +1 -0
  901. package/ui/dist/assets/tooltip-Df1CunSp.js +1 -0
  902. package/ui/dist/assets/trash-2-B4oAXsX-.js +1 -0
  903. package/ui/dist/assets/trending-up-BGWxvlmZ.js +1 -0
  904. package/ui/dist/assets/wand-sparkles-CZy4xvL3.js +1 -0
  905. package/ui/dist/assets/wrench-ByZkjO6m.js +1 -0
  906. package/ui/dist/audio-worklets/vad-processor.js +132 -0
  907. package/ui/dist/brand/profclaw-appicon-192.png +0 -0
  908. package/ui/dist/brand/profclaw-appicon-512.png +0 -0
  909. package/ui/dist/brand/profclaw-appicon-shadow.svg +51 -0
  910. package/ui/dist/brand/profclaw-appicon.svg +50 -0
  911. package/ui/dist/brand/profclaw-favicon-coral-bg-128.png +0 -0
  912. package/ui/dist/brand/profclaw-favicon-coral-bg-64.png +0 -0
  913. package/ui/dist/brand/profclaw-favicon-coral-bg.svg +52 -0
  914. package/ui/dist/brand/profclaw-favicon-coral-body-128.png +0 -0
  915. package/ui/dist/brand/profclaw-favicon-coral-body.svg +41 -0
  916. package/ui/dist/brand/profclaw-favicon-shadow-128.png +0 -0
  917. package/ui/dist/brand/profclaw-favicon-shadow-64.png +0 -0
  918. package/ui/dist/brand/profclaw-favicon-shadow.svg +51 -0
  919. package/ui/dist/brand/profclaw-mark-coral-256.png +0 -0
  920. package/ui/dist/brand/profclaw-mark-coral-64.png +0 -0
  921. package/ui/dist/brand/profclaw-mark-coral.svg +31 -0
  922. package/ui/dist/brand/profclaw-mono-white.svg +18 -0
  923. package/ui/dist/brand/profclaw-text-dark.svg +18 -0
  924. package/ui/dist/brand/profclaw-text-light.svg +18 -0
  925. package/ui/dist/brand/profclaw-wordmark-dark.svg +48 -0
  926. package/ui/dist/brand/profclaw-wordmark-light.svg +48 -0
  927. package/ui/dist/brand/safari-pinned-tab.svg +15 -0
  928. package/ui/dist/favicon/android-chrome-192x192.png +0 -0
  929. package/ui/dist/favicon/android-chrome-384x384.png +0 -0
  930. package/ui/dist/favicon/android-chrome-512x512.png +0 -0
  931. package/ui/dist/favicon/apple-touch-icon.png +0 -0
  932. package/ui/dist/favicon/browserconfig.xml +9 -0
  933. package/ui/dist/favicon/favicon-16x16.png +0 -0
  934. package/ui/dist/favicon/favicon-32x32.png +0 -0
  935. package/ui/dist/favicon/favicon.ico +0 -0
  936. package/ui/dist/favicon/mstile-150x150.png +0 -0
  937. package/ui/dist/favicon/safari-pinned-tab.svg +46 -0
  938. package/ui/dist/favicon/site.webmanifest +22 -0
  939. package/ui/dist/index.html +32 -0
  940. package/ui/dist/manifest.json +49 -0
  941. package/ui/dist/sw.js +124 -0
  942. package/ui/dist/vite.svg +1 -0
@@ -0,0 +1,1552 @@
1
+ /**
2
+ * profClaw AI Provider System
3
+ *
4
+ * Built on Vercel AI SDK for production-ready multi-provider support.
5
+ * Supports: Anthropic, OpenAI, Google, Ollama, and more.
6
+ *
7
+ * @see https://sdk.vercel.ai/docs
8
+ */
9
+ import { generateText, streamText, tool as createTool, jsonSchema } from 'ai';
10
+ // Provider SDKs are lazily imported inside ensureProvider() to reduce startup memory
11
+ // (each SDK is ~15MB; loading all 6 at startup costs ~100MB even if unused)
12
+ import { zodToJsonSchema } from 'zod-to-json-schema';
13
+ import { randomUUID } from 'node:crypto';
14
+ import { logger } from '../utils/logger.js';
15
+ import { normalizeToolSchema } from './schema-utils.js';
16
+ // AI provider resilience settings (configurable via env)
17
+ const AI_TIMEOUT_MS = parseInt(process.env['AI_PROVIDER_TIMEOUT_MS'] ?? '120000', 10);
18
+ const AI_MAX_RETRIES = parseInt(process.env['AI_MAX_RETRIES'] ?? '2', 10);
19
+ /**
20
+ * Retry wrapper for transient AI provider failures (429, 503, network errors).
21
+ * Uses exponential backoff with a 10s cap.
22
+ */
23
+ async function withRetry(fn, maxRetries = AI_MAX_RETRIES) {
24
+ for (let attempt = 0; attempt <= maxRetries; attempt++) {
25
+ try {
26
+ return await fn();
27
+ }
28
+ catch (error) {
29
+ const isRetryable = error instanceof Error &&
30
+ (/429|503|rate.limit|too.many|service.unavailable|ECONNRESET|ETIMEDOUT|fetch.failed/i.test(error.message));
31
+ if (!isRetryable || attempt === maxRetries)
32
+ throw error;
33
+ const delay = Math.min(1000 * 2 ** attempt, 10000);
34
+ logger.warn(`[AIProvider] Transient error (attempt ${attempt + 1}/${maxRetries + 1}), retrying in ${delay}ms`, {
35
+ component: 'AIProvider',
36
+ error: error.message,
37
+ });
38
+ await new Promise(r => setTimeout(r, delay));
39
+ }
40
+ }
41
+ throw new Error('Unreachable');
42
+ }
43
+ // Core types & data — single source of truth in core/
44
+ import { ProviderType, PROVIDER_STATUS, } from './core/types.js';
45
+ import { MODEL_ALIASES, MODEL_CATALOG } from './core/models.js';
46
+ // Re-export for consumers that import from providers/ai-sdk or providers/index
47
+ export { ProviderType, PROVIDER_STATUS, MODEL_ALIASES, MODEL_CATALOG, };
48
+ // Pre-compiled regex patterns for performance (avoid recompilation on each call)
49
+ const TOOL_CALL_REGEX = /```tool\s*\n?([\s\S]*?)\n?```/g;
50
+ function asJsonSchemaInput(schema) {
51
+ return schema;
52
+ }
53
+ function toAiMessages(messages) {
54
+ return messages.map((msg) => ({
55
+ role: msg.role,
56
+ content: msg.content,
57
+ }));
58
+ }
59
+ function toToolArguments(args) {
60
+ return typeof args === 'object' && args !== null
61
+ ? args
62
+ : {};
63
+ }
64
+ function getToolResultMessage(result) {
65
+ if (typeof result === 'object' && result !== null && typeof result.message === 'string') {
66
+ return result.message;
67
+ }
68
+ return JSON.stringify(result);
69
+ }
70
+ function buildNativeToolSchema(parameters, normalizeForAzure) {
71
+ if (!normalizeForAzure) {
72
+ return parameters;
73
+ }
74
+ const rawJsonSchema = zodToJsonSchema(parameters, {
75
+ $refStrategy: 'none',
76
+ target: 'openAi',
77
+ });
78
+ const normalizedSchema = normalizeToolSchema(rawJsonSchema);
79
+ return jsonSchema(asJsonSchemaInput(normalizedSchema));
80
+ }
81
+ // Provider priority for auto-selection (prefer cloud providers over local)
82
+ const PROVIDER_PRIORITY = [
83
+ 'anthropic', // Claude - best for tools/reasoning
84
+ 'openai', // GPT-4 - excellent all-around
85
+ 'azure', // Azure OpenAI - enterprise
86
+ 'google', // Gemini - good multimodal
87
+ 'groq', // Fast inference
88
+ 'xai', // Grok
89
+ 'mistral', // Mistral
90
+ 'deepseek', // DeepSeek R1
91
+ 'together', // Together AI
92
+ 'fireworks', // Fireworks
93
+ 'cerebras', // Cerebras
94
+ 'openrouter', // OpenRouter (many models)
95
+ 'cohere', // Cohere
96
+ 'perplexity', // Perplexity (search-focused)
97
+ 'copilot', // GitHub Copilot proxy
98
+ 'bedrock', // AWS Bedrock
99
+ 'zhipu', // Zhipu AI (GLM series)
100
+ 'moonshot', // Moonshot AI (Kimi)
101
+ 'qwen', // Qwen (Alibaba Cloud)
102
+ 'replicate', // Replicate
103
+ 'github-models', // GitHub Models
104
+ 'volcengine', // Bytedance Doubao
105
+ 'byteplus', // BytePlus
106
+ 'qianfan', // Baidu Qianfan
107
+ 'modelstudio', // ModelStudio
108
+ 'minimax', // Minimax
109
+ 'xiaomi', // Xiaomi MiLM
110
+ 'huggingface', // HuggingFace Inference
111
+ 'nvidia-nim', // NVIDIA NIM
112
+ 'watsonx', // IBM Watsonx
113
+ 'vercel-ai', // Vercel AI Gateway
114
+ 'cloudflare-ai', // Cloudflare AI Gateway
115
+ 'venice', // Venice AI
116
+ 'kilocode', // Kilocode
117
+ 'ollama', // Local - lowest priority (often doesn't support tools)
118
+ ];
119
+ class AIProviderManager {
120
+ providers = {};
121
+ configs = new Map();
122
+ defaultProvider = 'ollama';
123
+ constructor() {
124
+ // Initialize with environment variables
125
+ this.initFromEnv();
126
+ // Auto-select best provider as default
127
+ this.autoSelectDefaultProvider();
128
+ }
129
+ initFromEnv() {
130
+ // Anthropic
131
+ if (process.env.ANTHROPIC_API_KEY) {
132
+ this.configure('anthropic', {
133
+ type: 'anthropic',
134
+ apiKey: process.env.ANTHROPIC_API_KEY,
135
+ enabled: true,
136
+ });
137
+ }
138
+ // OpenAI
139
+ if (process.env.OPENAI_API_KEY) {
140
+ this.configure('openai', {
141
+ type: 'openai',
142
+ apiKey: process.env.OPENAI_API_KEY,
143
+ enabled: true,
144
+ });
145
+ }
146
+ // Google (supports multiple env var names)
147
+ const googleKey = process.env.GOOGLE_GENERATIVE_AI_API_KEY || process.env.GOOGLE_API_KEY || process.env.GEMINI_API_KEY;
148
+ if (googleKey) {
149
+ this.configure('google', {
150
+ type: 'google',
151
+ apiKey: googleKey,
152
+ enabled: true,
153
+ });
154
+ }
155
+ // Azure OpenAI (supports both standard and Foundry modes)
156
+ if (process.env.AZURE_OPENAI_API_KEY) {
157
+ // Check if using Foundry (custom base URL) or standard (resource name)
158
+ const baseUrl = process.env.AZURE_OPENAI_BASE_URL || process.env.AZURE_OPENAI_ENDPOINT;
159
+ const resourceName = process.env.AZURE_OPENAI_RESOURCE_NAME;
160
+ if (baseUrl || resourceName) {
161
+ this.configure('azure', {
162
+ type: 'azure',
163
+ apiKey: process.env.AZURE_OPENAI_API_KEY,
164
+ baseUrl: baseUrl,
165
+ resourceName: resourceName,
166
+ deploymentName: process.env.AZURE_OPENAI_DEPLOYMENT_NAME,
167
+ apiVersion: process.env.AZURE_OPENAI_API_VERSION,
168
+ enabled: true,
169
+ });
170
+ }
171
+ }
172
+ // Groq (fast inference)
173
+ if (process.env.GROQ_API_KEY) {
174
+ this.configure('groq', {
175
+ type: 'groq',
176
+ apiKey: process.env.GROQ_API_KEY,
177
+ enabled: true,
178
+ });
179
+ }
180
+ // xAI (Grok)
181
+ if (process.env.XAI_API_KEY) {
182
+ this.configure('xai', {
183
+ type: 'xai',
184
+ apiKey: process.env.XAI_API_KEY,
185
+ enabled: true,
186
+ });
187
+ }
188
+ // Mistral
189
+ if (process.env.MISTRAL_API_KEY) {
190
+ this.configure('mistral', {
191
+ type: 'mistral',
192
+ apiKey: process.env.MISTRAL_API_KEY,
193
+ enabled: true,
194
+ });
195
+ }
196
+ // Cohere
197
+ if (process.env.COHERE_API_KEY) {
198
+ this.configure('cohere', {
199
+ type: 'cohere',
200
+ apiKey: process.env.COHERE_API_KEY,
201
+ enabled: true,
202
+ });
203
+ }
204
+ // Perplexity
205
+ if (process.env.PERPLEXITY_API_KEY) {
206
+ this.configure('perplexity', {
207
+ type: 'perplexity',
208
+ apiKey: process.env.PERPLEXITY_API_KEY,
209
+ enabled: true,
210
+ });
211
+ }
212
+ // DeepSeek
213
+ if (process.env.DEEPSEEK_API_KEY) {
214
+ this.configure('deepseek', {
215
+ type: 'deepseek',
216
+ apiKey: process.env.DEEPSEEK_API_KEY,
217
+ enabled: true,
218
+ });
219
+ }
220
+ // Together AI
221
+ if (process.env.TOGETHER_API_KEY) {
222
+ this.configure('together', {
223
+ type: 'together',
224
+ apiKey: process.env.TOGETHER_API_KEY,
225
+ enabled: true,
226
+ });
227
+ }
228
+ // Cerebras
229
+ if (process.env.CEREBRAS_API_KEY) {
230
+ this.configure('cerebras', {
231
+ type: 'cerebras',
232
+ apiKey: process.env.CEREBRAS_API_KEY,
233
+ enabled: true,
234
+ });
235
+ }
236
+ // Zhipu AI (BigModel / GLM series)
237
+ const zhipuKey = process.env.BIGMODEL_API_KEY || process.env.ZHIPU_API_KEY;
238
+ if (zhipuKey) {
239
+ this.configure('zhipu', {
240
+ type: 'zhipu',
241
+ apiKey: zhipuKey,
242
+ enabled: true,
243
+ });
244
+ }
245
+ // Fireworks
246
+ if (process.env.FIREWORKS_API_KEY) {
247
+ this.configure('fireworks', {
248
+ type: 'fireworks',
249
+ apiKey: process.env.FIREWORKS_API_KEY,
250
+ enabled: true,
251
+ });
252
+ }
253
+ // OpenRouter (100+ models via one API)
254
+ if (process.env.OPENROUTER_API_KEY) {
255
+ this.configure('openrouter', {
256
+ type: 'openrouter',
257
+ apiKey: process.env.OPENROUTER_API_KEY,
258
+ enabled: true,
259
+ });
260
+ }
261
+ // Ollama (always enabled for local usage)
262
+ this.configure('ollama', {
263
+ type: 'ollama',
264
+ baseUrl: process.env.OLLAMA_BASE_URL || 'http://localhost:11434',
265
+ enabled: true,
266
+ });
267
+ // GitHub Copilot proxy (experimental - requires local copilot-api server)
268
+ // See: https://github.com/ericc-ch/copilot-api
269
+ if (process.env.COPILOT_API_URL) {
270
+ this.configure('copilot', {
271
+ type: 'copilot',
272
+ baseUrl: process.env.COPILOT_API_URL,
273
+ enabled: true,
274
+ });
275
+ }
276
+ // Volcengine (Bytedance Doubao)
277
+ if (process.env.VOLCENGINE_API_KEY) {
278
+ this.configure('volcengine', {
279
+ type: 'volcengine',
280
+ apiKey: process.env.VOLCENGINE_API_KEY,
281
+ enabled: true,
282
+ });
283
+ }
284
+ // BytePlus (international Bytedance)
285
+ if (process.env.BYTEPLUS_API_KEY) {
286
+ this.configure('byteplus', {
287
+ type: 'byteplus',
288
+ apiKey: process.env.BYTEPLUS_API_KEY,
289
+ enabled: true,
290
+ });
291
+ }
292
+ // Baidu Qianfan
293
+ if (process.env.QIANFAN_API_KEY) {
294
+ this.configure('qianfan', {
295
+ type: 'qianfan',
296
+ apiKey: process.env.QIANFAN_API_KEY,
297
+ enabled: true,
298
+ });
299
+ }
300
+ // ModelStudio (Alibaba DashScope compatible mode)
301
+ if (process.env.MODELSTUDIO_API_KEY) {
302
+ this.configure('modelstudio', {
303
+ type: 'modelstudio',
304
+ apiKey: process.env.MODELSTUDIO_API_KEY,
305
+ enabled: true,
306
+ });
307
+ }
308
+ // Minimax
309
+ if (process.env.MINIMAX_API_KEY) {
310
+ this.configure('minimax', {
311
+ type: 'minimax',
312
+ apiKey: process.env.MINIMAX_API_KEY,
313
+ enabled: true,
314
+ });
315
+ }
316
+ // Xiaomi MiLM
317
+ if (process.env.XIAOMI_API_KEY) {
318
+ this.configure('xiaomi', {
319
+ type: 'xiaomi',
320
+ apiKey: process.env.XIAOMI_API_KEY,
321
+ enabled: true,
322
+ });
323
+ }
324
+ // HuggingFace Inference
325
+ if (process.env.HUGGINGFACE_API_TOKEN) {
326
+ this.configure('huggingface', {
327
+ type: 'huggingface',
328
+ apiKey: process.env.HUGGINGFACE_API_TOKEN,
329
+ enabled: true,
330
+ });
331
+ }
332
+ // NVIDIA NIM
333
+ if (process.env.NVIDIA_NIM_API_KEY) {
334
+ this.configure('nvidia-nim', {
335
+ type: 'nvidia-nim',
336
+ apiKey: process.env.NVIDIA_NIM_API_KEY,
337
+ enabled: true,
338
+ });
339
+ }
340
+ // Venice AI
341
+ if (process.env.VENICE_API_KEY) {
342
+ this.configure('venice', {
343
+ type: 'venice',
344
+ apiKey: process.env.VENICE_API_KEY,
345
+ enabled: true,
346
+ });
347
+ }
348
+ // Kilocode
349
+ if (process.env.KILOCODE_API_KEY) {
350
+ this.configure('kilocode', {
351
+ type: 'kilocode',
352
+ apiKey: process.env.KILOCODE_API_KEY,
353
+ enabled: true,
354
+ });
355
+ }
356
+ // Vercel AI Gateway
357
+ if (process.env.VERCEL_AI_API_KEY) {
358
+ this.configure('vercel-ai', {
359
+ type: 'vercel-ai',
360
+ apiKey: process.env.VERCEL_AI_API_KEY,
361
+ enabled: true,
362
+ });
363
+ }
364
+ // Cloudflare AI Gateway
365
+ if (process.env.CLOUDFLARE_AI_API_KEY || process.env.CLOUDFLARE_AI_TOKEN) {
366
+ const accountId = process.env.CLOUDFLARE_ACCOUNT_ID;
367
+ this.configure('cloudflare-ai', {
368
+ type: 'cloudflare-ai',
369
+ apiKey: process.env.CLOUDFLARE_AI_API_KEY || process.env.CLOUDFLARE_AI_TOKEN,
370
+ baseUrl: accountId
371
+ ? `https://api.cloudflare.com/client/v4/accounts/${accountId}/ai/v1`
372
+ : undefined,
373
+ enabled: true,
374
+ });
375
+ }
376
+ // IBM Watsonx
377
+ if (process.env.WATSONX_API_KEY) {
378
+ this.configure('watsonx', {
379
+ type: 'watsonx',
380
+ apiKey: process.env.WATSONX_API_KEY,
381
+ baseUrl: process.env.WATSONX_URL || 'https://us-south.ml.cloud.ibm.com/ml/v1',
382
+ defaultModel: process.env.WATSONX_PROJECT_ID,
383
+ enabled: true,
384
+ });
385
+ }
386
+ }
387
+ configure(type, config) {
388
+ this.configs.set(type, config);
389
+ // Invalidate cached provider instance so ensureProvider() recreates it on next use
390
+ const key = this.providerKey(type);
391
+ delete this.providers[key];
392
+ logger.info(`[AIProvider] Configured ${type}`);
393
+ }
394
+ /** Map hyphenated provider types to camelCase keys for the providers record */
395
+ providerKey(type) {
396
+ const keyMap = {
397
+ 'github-models': 'githubModels',
398
+ 'nvidia-nim': 'nvidiaNim',
399
+ 'vercel-ai': 'vercelAi',
400
+ 'cloudflare-ai': 'cloudflareAi',
401
+ };
402
+ return keyMap[type] ?? type;
403
+ }
404
+ /**
405
+ * Lazily import and instantiate the SDK for a provider on first use.
406
+ * Each SDK is ~15MB; this avoids loading all of them at startup.
407
+ */
408
+ async ensureProvider(type) {
409
+ const key = this.providerKey(type);
410
+ if (this.providers[key])
411
+ return;
412
+ const config = this.configs.get(type);
413
+ if (!config?.enabled && type !== 'ollama')
414
+ return;
415
+ switch (type) {
416
+ case 'anthropic': {
417
+ if (!config?.apiKey)
418
+ return;
419
+ const { createAnthropic } = await import('@ai-sdk/anthropic');
420
+ this.providers.anthropic = createAnthropic({
421
+ apiKey: config.apiKey,
422
+ baseURL: config.baseUrl,
423
+ });
424
+ break;
425
+ }
426
+ case 'openai': {
427
+ if (!config?.apiKey)
428
+ return;
429
+ const { createOpenAI } = await import('@ai-sdk/openai');
430
+ this.providers.openai = createOpenAI({
431
+ apiKey: config.apiKey,
432
+ baseURL: config.baseUrl,
433
+ });
434
+ break;
435
+ }
436
+ case 'google': {
437
+ if (!config?.apiKey)
438
+ return;
439
+ const { createGoogleGenerativeAI } = await import('@ai-sdk/google');
440
+ this.providers.google = createGoogleGenerativeAI({
441
+ apiKey: config.apiKey,
442
+ baseURL: config.baseUrl,
443
+ });
444
+ break;
445
+ }
446
+ case 'azure': {
447
+ if (!config?.apiKey)
448
+ return;
449
+ const { createAzure } = await import('@ai-sdk/azure');
450
+ const apiVersion = config.apiVersion || '2024-10-21';
451
+ logger.info(`[AIProvider] Azure using API version: ${apiVersion}`);
452
+ if (config.resourceName) {
453
+ this.providers.azure = createAzure({
454
+ apiKey: config.apiKey,
455
+ resourceName: config.resourceName,
456
+ apiVersion,
457
+ });
458
+ logger.info(`[AIProvider] Azure configured with resource: ${config.resourceName}`);
459
+ }
460
+ else if (config.baseUrl) {
461
+ const endpoint = config.baseUrl.replace(/\/$/, '');
462
+ this.providers.azure = createAzure({
463
+ apiKey: config.apiKey,
464
+ baseURL: endpoint,
465
+ apiVersion,
466
+ useDeploymentBasedUrls: true,
467
+ });
468
+ logger.info(`[AIProvider] Azure configured with endpoint: ${endpoint}`);
469
+ }
470
+ else {
471
+ logger.warn('[AIProvider] Azure API key provided but no endpoint or resource name');
472
+ }
473
+ if (config.defaultModel) {
474
+ logger.info(`[AIProvider] Azure default deployment: ${config.defaultModel}`);
475
+ }
476
+ break;
477
+ }
478
+ case 'ollama': {
479
+ const { createOllama } = await import('ai-sdk-ollama');
480
+ this.providers.ollama = createOllama({
481
+ baseURL: config?.baseUrl || 'http://localhost:11434',
482
+ });
483
+ break;
484
+ }
485
+ // All OpenAI-compatible providers share the same SDK
486
+ case 'groq':
487
+ case 'xai':
488
+ case 'mistral':
489
+ case 'cohere':
490
+ case 'perplexity':
491
+ case 'deepseek':
492
+ case 'together':
493
+ case 'cerebras':
494
+ case 'fireworks':
495
+ case 'openrouter':
496
+ case 'zhipu':
497
+ case 'moonshot': {
498
+ if (!config?.apiKey)
499
+ return;
500
+ const { createOpenAI } = await import('@ai-sdk/openai');
501
+ const baseURLs = {
502
+ groq: 'https://api.groq.com/openai/v1',
503
+ xai: 'https://api.x.ai/v1',
504
+ mistral: 'https://api.mistral.ai/v1',
505
+ cohere: 'https://api.cohere.ai/v1',
506
+ perplexity: 'https://api.perplexity.ai',
507
+ deepseek: 'https://api.deepseek.com/v1',
508
+ together: 'https://api.together.xyz/v1',
509
+ cerebras: 'https://api.cerebras.ai/v1',
510
+ fireworks: 'https://api.fireworks.ai/inference/v1',
511
+ openrouter: 'https://openrouter.ai/api/v1',
512
+ zhipu: 'https://open.bigmodel.cn/api/paas/v4',
513
+ moonshot: 'https://api.moonshot.cn/v1',
514
+ };
515
+ this.providers[key] = createOpenAI({
516
+ apiKey: config.apiKey,
517
+ baseURL: baseURLs[type],
518
+ });
519
+ break;
520
+ }
521
+ case 'copilot': {
522
+ if (!config?.baseUrl)
523
+ return;
524
+ const { createOpenAI } = await import('@ai-sdk/openai');
525
+ this.providers.copilot = createOpenAI({
526
+ apiKey: 'copilot',
527
+ baseURL: config.baseUrl,
528
+ });
529
+ break;
530
+ }
531
+ case 'github-models': {
532
+ if (!config?.apiKey)
533
+ return;
534
+ const { createOpenAI } = await import('@ai-sdk/openai');
535
+ this.providers.githubModels = createOpenAI({
536
+ apiKey: config.apiKey,
537
+ baseURL: 'https://models.inference.ai.azure.com',
538
+ });
539
+ break;
540
+ }
541
+ case 'replicate': {
542
+ if (!config?.apiKey)
543
+ return;
544
+ const { createOpenAI } = await import('@ai-sdk/openai');
545
+ this.providers.replicate = createOpenAI({
546
+ apiKey: config.apiKey,
547
+ baseURL: 'https://openai-proxy.replicate.com/v1',
548
+ });
549
+ break;
550
+ }
551
+ // New OpenAI-compatible providers
552
+ case 'volcengine':
553
+ case 'byteplus':
554
+ case 'qianfan':
555
+ case 'modelstudio':
556
+ case 'minimax':
557
+ case 'xiaomi':
558
+ case 'huggingface':
559
+ case 'nvidia-nim':
560
+ case 'venice':
561
+ case 'kilocode':
562
+ case 'vercel-ai':
563
+ case 'cloudflare-ai':
564
+ case 'watsonx': {
565
+ if (!config?.apiKey)
566
+ return;
567
+ const { createOpenAI } = await import('@ai-sdk/openai');
568
+ const newProviderBaseURLs = {
569
+ volcengine: 'https://ark.cn-beijing.volces.com/api/v3',
570
+ byteplus: 'https://ark.byteplush.com/api/v3',
571
+ qianfan: 'https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxin',
572
+ modelstudio: 'https://dashscope.aliyuncs.com/compatible-mode/v1',
573
+ minimax: 'https://api.minimax.chat/v1',
574
+ xiaomi: 'https://api.xiaomi.com/ai/v1',
575
+ huggingface: 'https://api-inference.huggingface.co/v1',
576
+ 'nvidia-nim': 'https://integrate.api.nvidia.com/v1',
577
+ venice: 'https://api.venice.ai/api/v1',
578
+ kilocode: 'https://api.kilocode.ai/v1',
579
+ 'vercel-ai': 'https://gateway.ai.vercel.com/v1',
580
+ watsonx: 'https://us-south.ml.cloud.ibm.com/ml/v1',
581
+ };
582
+ // Cloudflare uses a dynamic URL based on account ID (set during configure)
583
+ const baseURL = type === 'cloudflare-ai'
584
+ ? (config.baseUrl || 'https://api.cloudflare.com/client/v4/accounts/unknown/ai/v1')
585
+ : (config.baseUrl || newProviderBaseURLs[type]);
586
+ this.providers[key] = createOpenAI({
587
+ apiKey: config.apiKey,
588
+ baseURL,
589
+ });
590
+ break;
591
+ }
592
+ }
593
+ }
594
+ setDefaultProvider(type) {
595
+ this.defaultProvider = type;
596
+ }
597
+ getDefaultProvider() {
598
+ return this.defaultProvider;
599
+ }
600
+ /**
601
+ * Auto-select the best configured provider as default.
602
+ * Prioritizes cloud providers (that support tools) over Ollama.
603
+ */
604
+ autoSelectDefaultProvider() {
605
+ for (const provider of PROVIDER_PRIORITY) {
606
+ const config = this.configs.get(provider);
607
+ if (config?.enabled) {
608
+ // For providers that need API keys, verify they have one
609
+ if (provider !== 'ollama' && provider !== 'copilot') {
610
+ if (!config.apiKey && !config.baseUrl)
611
+ continue;
612
+ }
613
+ this.defaultProvider = provider;
614
+ logger.info(`[AIProvider] Auto-selected default provider: ${provider}`);
615
+ return;
616
+ }
617
+ }
618
+ // Fallback to ollama if nothing else is configured
619
+ this.defaultProvider = 'ollama';
620
+ logger.info('[AIProvider] Using ollama as default (no cloud providers configured)');
621
+ }
622
+ isConfigured(type) {
623
+ const config = this.configs.get(type);
624
+ return config?.enabled ?? false;
625
+ }
626
+ getConfiguredProviders() {
627
+ return Array.from(this.configs.entries())
628
+ .filter(([, config]) => config.enabled)
629
+ .map(([type]) => type);
630
+ }
631
+ /**
632
+ * Load saved provider configurations from storage
633
+ * Call this after storage is initialized
634
+ */
635
+ async loadSavedConfigs(loader) {
636
+ try {
637
+ const savedConfigs = await loader();
638
+ let loaded = 0;
639
+ for (const saved of savedConfigs) {
640
+ // Skip if already configured from env with higher priority
641
+ const existing = this.configs.get(saved.type);
642
+ if (existing?.apiKey && saved.type !== 'ollama') {
643
+ logger.info(`[AI] Skipping saved config for ${saved.type} (already configured from env)`);
644
+ continue;
645
+ }
646
+ // Configure the provider
647
+ this.configure(saved.type, {
648
+ type: saved.type,
649
+ apiKey: saved.apiKey,
650
+ baseUrl: saved.baseUrl,
651
+ resourceName: saved.resourceName,
652
+ deploymentName: saved.deploymentName,
653
+ apiVersion: saved.apiVersion,
654
+ defaultModel: saved.defaultModel,
655
+ enabled: saved.enabled ?? true,
656
+ });
657
+ logger.info(`[AI] Loaded saved config for ${saved.type}`);
658
+ loaded++;
659
+ }
660
+ // Re-evaluate default provider after loading saved configs
661
+ if (loaded > 0) {
662
+ this.autoSelectDefaultProvider();
663
+ }
664
+ return loaded;
665
+ }
666
+ catch (error) {
667
+ logger.error('[AI] Failed to load saved configs:', error instanceof Error ? error : undefined);
668
+ return 0;
669
+ }
670
+ }
671
+ resolveModel(modelOrAlias) {
672
+ // Check if it's a full provider/model path
673
+ if (modelOrAlias.includes('/')) {
674
+ const [provider, model] = modelOrAlias.split('/');
675
+ return { provider: provider, model };
676
+ }
677
+ // Check aliases
678
+ const alias = MODEL_ALIASES[modelOrAlias.toLowerCase()];
679
+ if (alias) {
680
+ // For Azure, use the configured deployment name instead of the default alias model
681
+ if (alias.provider === 'azure') {
682
+ const azureConfig = this.configs.get('azure');
683
+ if (azureConfig?.defaultModel) {
684
+ return { provider: 'azure', model: azureConfig.defaultModel };
685
+ }
686
+ }
687
+ return alias;
688
+ }
689
+ // Try to find in catalog
690
+ const catalogModel = MODEL_CATALOG.find((m) => m.id === modelOrAlias);
691
+ if (catalogModel) {
692
+ return { provider: catalogModel.provider, model: catalogModel.id };
693
+ }
694
+ // Default to the auto-selected default provider
695
+ // Use the provider's default model if configured, otherwise use the given model name
696
+ const defaultConfig = this.configs.get(this.defaultProvider);
697
+ const defaultModel = defaultConfig?.defaultModel || modelOrAlias;
698
+ return { provider: this.defaultProvider, model: defaultModel };
699
+ }
700
+ async getModel(provider, modelId) {
701
+ await this.ensureProvider(provider);
702
+ const key = this.providerKey(provider);
703
+ const instance = this.providers[key];
704
+ if (!instance) {
705
+ const envHints = {
706
+ anthropic: 'Set ANTHROPIC_API_KEY.',
707
+ openai: 'Set OPENAI_API_KEY.',
708
+ google: 'Set GOOGLE_API_KEY.',
709
+ azure: 'Set AZURE_OPENAI_API_KEY and AZURE_OPENAI_RESOURCE_NAME.',
710
+ groq: 'Set GROQ_API_KEY.',
711
+ ollama: 'Check Ollama is running.',
712
+ xai: 'Set XAI_API_KEY.',
713
+ mistral: 'Set MISTRAL_API_KEY.',
714
+ cohere: 'Set COHERE_API_KEY.',
715
+ perplexity: 'Set PERPLEXITY_API_KEY.',
716
+ deepseek: 'Set DEEPSEEK_API_KEY.',
717
+ together: 'Set TOGETHER_API_KEY.',
718
+ cerebras: 'Set CEREBRAS_API_KEY.',
719
+ fireworks: 'Set FIREWORKS_API_KEY.',
720
+ openrouter: 'Set OPENROUTER_API_KEY.',
721
+ copilot: 'Set COPILOT_API_URL.',
722
+ volcengine: 'Set VOLCENGINE_API_KEY.',
723
+ byteplus: 'Set BYTEPLUS_API_KEY.',
724
+ qianfan: 'Set QIANFAN_API_KEY.',
725
+ modelstudio: 'Set MODELSTUDIO_API_KEY.',
726
+ minimax: 'Set MINIMAX_API_KEY.',
727
+ xiaomi: 'Set XIAOMI_API_KEY.',
728
+ huggingface: 'Set HUGGINGFACE_API_TOKEN.',
729
+ 'nvidia-nim': 'Set NVIDIA_NIM_API_KEY.',
730
+ venice: 'Set VENICE_API_KEY.',
731
+ kilocode: 'Set KILOCODE_API_KEY.',
732
+ 'vercel-ai': 'Set VERCEL_AI_API_KEY.',
733
+ 'cloudflare-ai': 'Set CLOUDFLARE_AI_API_KEY and CLOUDFLARE_ACCOUNT_ID.',
734
+ watsonx: 'Set WATSONX_API_KEY.',
735
+ };
736
+ throw new Error(`${provider} not configured. ${envHints[provider] || ''}`);
737
+ }
738
+ // Azure uses .chat() method for deployment-based access
739
+ if (provider === 'azure') {
740
+ let deployment = modelId;
741
+ if (modelId === 'default') {
742
+ const azureConfig = this.configs.get('azure');
743
+ deployment = azureConfig?.defaultModel || modelId;
744
+ if (deployment === 'default') {
745
+ throw new Error('Azure deployment not configured. Set defaultModel in Azure config or AZURE_OPENAI_DEPLOYMENT_NAME.');
746
+ }
747
+ }
748
+ return instance.chat(deployment);
749
+ }
750
+ // OpenAI-compatible providers must use .chat() - the default instance() call
751
+ // uses the Responses API which third-party providers don't support
752
+ const OPENAI_COMPAT_PROVIDERS = new Set([
753
+ 'openai', 'groq', 'xai', 'mistral', 'cohere', 'perplexity',
754
+ 'deepseek', 'together', 'cerebras', 'fireworks', 'openrouter', 'copilot',
755
+ 'zhipu', 'moonshot',
756
+ ]);
757
+ if (OPENAI_COMPAT_PROVIDERS.has(provider) && typeof instance.chat === 'function') {
758
+ return instance.chat(modelId);
759
+ }
760
+ return instance(modelId);
761
+ }
762
+ getModelInfo(modelId) {
763
+ return MODEL_CATALOG.find((m) => m.id === modelId);
764
+ }
765
+ getModelsForProvider(provider) {
766
+ return MODEL_CATALOG.filter((m) => m.provider === provider);
767
+ }
768
+ getAllModels() {
769
+ return [...MODEL_CATALOG];
770
+ }
771
+ async chat(request) {
772
+ const startTime = Date.now();
773
+ // Resolve model
774
+ const modelRef = request.model
775
+ ? this.resolveModel(request.model)
776
+ : { provider: this.defaultProvider, model: 'llama3.2' };
777
+ const model = await this.getModel(modelRef.provider, modelRef.model);
778
+ // Convert messages to AI SDK format
779
+ const messages = request.messages.map((msg) => ({
780
+ role: msg.role,
781
+ content: msg.content,
782
+ }));
783
+ // Add system prompt if provided
784
+ if (request.systemPrompt) {
785
+ messages.unshift({ role: 'system', content: request.systemPrompt });
786
+ }
787
+ try {
788
+ const result = await withRetry(() => generateText({
789
+ model,
790
+ messages,
791
+ temperature: request.temperature ?? 0.7,
792
+ maxOutputTokens: request.maxTokens ?? 4096,
793
+ abortSignal: AbortSignal.timeout(AI_TIMEOUT_MS),
794
+ }));
795
+ const duration = Date.now() - startTime;
796
+ const modelInfo = this.getModelInfo(modelRef.model);
797
+ // Calculate cost - AI SDK v6 uses usage.totalTokens and similar
798
+ const promptTokens = result.usage?.promptTokens ??
799
+ result.usage?.inputTokens ?? 0;
800
+ const completionTokens = result.usage?.completionTokens ??
801
+ result.usage?.outputTokens ?? 0;
802
+ const cost = modelInfo
803
+ ? (promptTokens / 1_000_000) * modelInfo.costPer1MInput +
804
+ (completionTokens / 1_000_000) * modelInfo.costPer1MOutput
805
+ : 0;
806
+ return {
807
+ id: randomUUID(),
808
+ provider: modelRef.provider,
809
+ model: modelRef.model,
810
+ content: result.text,
811
+ finishReason: result.finishReason === 'stop' ? 'stop' : 'length',
812
+ usage: {
813
+ promptTokens,
814
+ completionTokens,
815
+ totalTokens: promptTokens + completionTokens,
816
+ cost,
817
+ },
818
+ duration,
819
+ };
820
+ }
821
+ catch (error) {
822
+ logger.error(`[AIProvider] Chat error:`, error instanceof Error ? error : undefined);
823
+ throw error;
824
+ }
825
+ }
826
+ // Streaming configuration for performance (configurable via env vars)
827
+ static CHUNK_BATCH_SIZE = parseInt(process.env.STREAM_CHUNK_BATCH_SIZE || '64', 10);
828
+ static CHUNK_BATCH_TIME_MS = parseInt(process.env.STREAM_CHUNK_BATCH_TIME_MS || '30', 10);
829
+ async chatStream(request, onChunk) {
830
+ const startTime = Date.now();
831
+ // Resolve model
832
+ const modelRef = request.model
833
+ ? this.resolveModel(request.model)
834
+ : { provider: this.defaultProvider, model: 'llama3.2' };
835
+ const model = await this.getModel(modelRef.provider, modelRef.model);
836
+ // Convert messages
837
+ const messages = request.messages.map((msg) => ({
838
+ role: msg.role,
839
+ content: msg.content,
840
+ }));
841
+ if (request.systemPrompt) {
842
+ messages.unshift({ role: 'system', content: request.systemPrompt });
843
+ }
844
+ try {
845
+ const result = streamText({
846
+ model,
847
+ messages,
848
+ temperature: request.temperature ?? 0.7,
849
+ maxOutputTokens: request.maxTokens ?? 4096,
850
+ abortSignal: AbortSignal.timeout(AI_TIMEOUT_MS),
851
+ });
852
+ // Collect text with batched chunk emission for better performance
853
+ const textParts = [];
854
+ let chunkBuffer = '';
855
+ let lastFlushTime = Date.now();
856
+ for await (const chunk of result.textStream) {
857
+ textParts.push(chunk);
858
+ chunkBuffer += chunk;
859
+ const now = Date.now();
860
+ const shouldFlush = chunkBuffer.length >= AIProviderManager.CHUNK_BATCH_SIZE ||
861
+ now - lastFlushTime >= AIProviderManager.CHUNK_BATCH_TIME_MS;
862
+ if (shouldFlush && chunkBuffer) {
863
+ onChunk(chunkBuffer); // Non-blocking callback
864
+ chunkBuffer = '';
865
+ lastFlushTime = now;
866
+ }
867
+ }
868
+ // Flush any remaining buffer
869
+ if (chunkBuffer) {
870
+ onChunk(chunkBuffer);
871
+ }
872
+ const fullText = textParts.join(''); // O(n) join instead of O(n²) concatenation
873
+ // Get usage (already available from stream result)
874
+ const usage = await result.usage;
875
+ const duration = Date.now() - startTime;
876
+ const modelInfo = this.getModelInfo(modelRef.model);
877
+ const promptTokens = usage?.promptTokens ??
878
+ usage?.inputTokens ?? 0;
879
+ const completionTokens = usage?.completionTokens ??
880
+ usage?.outputTokens ?? 0;
881
+ const cost = modelInfo
882
+ ? (promptTokens / 1_000_000) * modelInfo.costPer1MInput +
883
+ (completionTokens / 1_000_000) * modelInfo.costPer1MOutput
884
+ : 0;
885
+ return {
886
+ id: randomUUID(),
887
+ provider: modelRef.provider,
888
+ model: modelRef.model,
889
+ content: fullText,
890
+ finishReason: 'stop',
891
+ usage: {
892
+ promptTokens,
893
+ completionTokens,
894
+ totalTokens: promptTokens + completionTokens,
895
+ cost,
896
+ },
897
+ duration,
898
+ };
899
+ }
900
+ catch (error) {
901
+ logger.error(`[AIProvider] Stream error:`, error instanceof Error ? error : undefined);
902
+ throw error;
903
+ }
904
+ }
905
+ /**
906
+ * Chat with tool calling support
907
+ * Handles tool detection and execution manually for better control
908
+ */
909
+ async chatWithTools(request) {
910
+ const startTime = Date.now();
911
+ // Resolve model
912
+ const modelRef = request.model
913
+ ? this.resolveModel(request.model)
914
+ : { provider: this.defaultProvider, model: 'llama3.2' };
915
+ const model = await this.getModel(modelRef.provider, modelRef.model);
916
+ // Check if model supports native tools
917
+ const toolSupport = this.modelSupportsTools(modelRef.model || modelRef.provider + '/' + modelRef.model);
918
+ const useNativeTools = toolSupport.supported && request.tools && request.tools.length > 0;
919
+ // Build system prompt (skip manual tool instructions if using native tools)
920
+ let systemPrompt = request.systemPrompt || '';
921
+ const toolResults = [];
922
+ const detectedToolCalls = [];
923
+ // Convert tools for native AI SDK usage
924
+ const aiSdkTools = {};
925
+ if (useNativeTools && request.tools) {
926
+ // Add a reinforcement prompt for local models to ensure they provide arguments
927
+ const toolReminders = request.tools.map(t => `- ${t.name}`).join(', ');
928
+ systemPrompt += `\n\nYou have access to these tools: ${toolReminders}. When using them, YOU MUST PROVIDE ALL REQUIRED ARGUMENTS (like 'url' for web_fetch, 'query' for web_search). Do not call tools with empty arguments.`;
929
+ request.tools.forEach((t) => {
930
+ // Convert Zod schema to JSON Schema for AI SDK v5+
931
+ const rawJsonSchema = zodToJsonSchema(t.parameters, {
932
+ $refStrategy: 'none',
933
+ });
934
+ aiSdkTools[t.name] = createTool({
935
+ description: t.description,
936
+ inputSchema: jsonSchema(asJsonSchemaInput(rawJsonSchema)),
937
+ });
938
+ });
939
+ }
940
+ else if (request.tools && request.tools.length > 0) {
941
+ // Fallback: Manual tool prompting
942
+ const toolDescriptions = request.tools.map((t) => {
943
+ const params = t.parameters;
944
+ const shape = params?._def?.shape ?? params?.shape ?? {};
945
+ const paramList = Object.entries(shape)
946
+ .map(([key, val]) => ` - ${key}: ${val?._def?.description || 'string'}`)
947
+ .join('\n');
948
+ return `**${t.name}**: ${t.description}\nParameters:\n${paramList}`;
949
+ }).join('\n\n');
950
+ systemPrompt += `\n\n## Available Tools\n\nYou can call the following tools by responding with a JSON block in this exact format:\n\`\`\`tool\n{"tool": "toolName", "args": {"param1": "value1"}}\n\`\`\`\n\nExample:\n\`\`\`tool\n{"tool": "web_search", "args": {"query": "latest typescript features"}}\n\`\`\`\n\n${toolDescriptions}\n\nWhen you need to use a tool, include the tool call in your response. After the tool executes, continue with your response.`;
951
+ }
952
+ // Convert messages to AI SDK format
953
+ const messages = request.messages.map((msg) => ({
954
+ role: msg.role,
955
+ content: msg.content,
956
+ }));
957
+ if (systemPrompt) {
958
+ messages.unshift({ role: 'system', content: systemPrompt });
959
+ }
960
+ try {
961
+ const result = await withRetry(() => generateText({
962
+ model,
963
+ messages,
964
+ temperature: request.temperature ?? 0.7,
965
+ maxOutputTokens: request.maxTokens ?? 4096,
966
+ tools: useNativeTools ? aiSdkTools : undefined,
967
+ abortSignal: AbortSignal.timeout(AI_TIMEOUT_MS),
968
+ }));
969
+ let finalContent = result.text;
970
+ // Handle native tool calls
971
+ if (useNativeTools && result.toolCalls && result.toolCalls.length > 0) {
972
+ for (const toolCall of result.toolCalls) {
973
+ if (request.executeTools) {
974
+ const args = toToolArguments(toolCall.input);
975
+ detectedToolCalls.push({
976
+ id: toolCall.toolCallId,
977
+ name: toolCall.toolName,
978
+ arguments: args,
979
+ });
980
+ // Execute the tool
981
+ const toolResult = await request.executeTools(toolCall.toolName, args);
982
+ toolResults.push({
983
+ toolCallId: toolCall.toolCallId,
984
+ toolName: toolCall.toolName,
985
+ result: toolResult,
986
+ });
987
+ // For native tools, we don't need to replace content text as the tool calls are structured
988
+ }
989
+ }
990
+ }
991
+ // Handle manual tool calls (fallback path)
992
+ else if (!useNativeTools) {
993
+ // Parse tool calls from the response (using pre-compiled regex)
994
+ TOOL_CALL_REGEX.lastIndex = 0; // Reset regex state
995
+ let match;
996
+ while ((match = TOOL_CALL_REGEX.exec(result.text)) !== null) {
997
+ try {
998
+ const toolCall = JSON.parse(match[1]);
999
+ if (toolCall.tool && request.executeTools) {
1000
+ const toolCallId = randomUUID();
1001
+ detectedToolCalls.push({
1002
+ id: toolCallId,
1003
+ name: toolCall.tool,
1004
+ arguments: toolCall.args || {},
1005
+ });
1006
+ // Execute the tool
1007
+ const toolResult = await request.executeTools(toolCall.tool, toolCall.args || {});
1008
+ toolResults.push({
1009
+ toolCallId,
1010
+ toolName: toolCall.tool,
1011
+ result: toolResult,
1012
+ });
1013
+ // Replace the tool call block with the result
1014
+ const resultMessage = getToolResultMessage(toolResult);
1015
+ finalContent = finalContent.replace(match[0], `\n✅ **${toolCall.tool}**: ${resultMessage}\n`);
1016
+ }
1017
+ }
1018
+ catch {
1019
+ // Invalid JSON, skip
1020
+ }
1021
+ }
1022
+ }
1023
+ const duration = Date.now() - startTime;
1024
+ const modelInfo = this.getModelInfo(modelRef.model);
1025
+ const promptTokens = result.usage?.promptTokens ??
1026
+ result.usage?.inputTokens ?? 0;
1027
+ const completionTokens = result.usage?.completionTokens ??
1028
+ result.usage?.outputTokens ?? 0;
1029
+ const cost = modelInfo
1030
+ ? (promptTokens / 1_000_000) * modelInfo.costPer1MInput +
1031
+ (completionTokens / 1_000_000) * modelInfo.costPer1MOutput
1032
+ : 0;
1033
+ return {
1034
+ id: randomUUID(),
1035
+ provider: modelRef.provider,
1036
+ model: modelRef.model,
1037
+ content: finalContent,
1038
+ finishReason: detectedToolCalls.length > 0 ? 'tool-calls' : (result.finishReason === 'stop' ? 'stop' : 'length'),
1039
+ usage: {
1040
+ promptTokens,
1041
+ completionTokens,
1042
+ totalTokens: promptTokens + completionTokens,
1043
+ cost,
1044
+ },
1045
+ duration,
1046
+ toolCalls: detectedToolCalls.length > 0 ? detectedToolCalls : undefined,
1047
+ toolResults: toolResults.length > 0 ? toolResults : undefined,
1048
+ };
1049
+ }
1050
+ catch (error) {
1051
+ logger.error(`[AIProvider] Chat with tools error:`, error instanceof Error ? error : undefined);
1052
+ throw error;
1053
+ }
1054
+ }
1055
+ /**
1056
+ * Check if a model supports native tool calling
1057
+ */
1058
+ modelSupportsTools(modelOrAlias) {
1059
+ const modelRef = modelOrAlias
1060
+ ? this.resolveModel(modelOrAlias)
1061
+ : { provider: this.defaultProvider, model: 'llama3.2' };
1062
+ // Azure OpenAI: All GPT-4, GPT-4o, and GPT-3.5-turbo models support function calling
1063
+ // We check provider first since Azure deployment names won't be in MODEL_CATALOG
1064
+ if (modelRef.provider === 'azure') {
1065
+ logger.debug(`[AIProvider] Azure model detected, assuming tool support`, {
1066
+ component: 'AIProvider',
1067
+ model: modelRef.model,
1068
+ provider: modelRef.provider,
1069
+ });
1070
+ return {
1071
+ supported: true,
1072
+ model: modelRef.model,
1073
+ provider: modelRef.provider,
1074
+ };
1075
+ }
1076
+ const modelInfo = this.getModelInfo(modelRef.model);
1077
+ const supportsTools = modelInfo?.supportsTools ?? false;
1078
+ // Build recommendation for unsupported models
1079
+ let recommendation;
1080
+ if (!supportsTools) {
1081
+ // Find similar models that support tools
1082
+ const alternatives = MODEL_CATALOG.filter(m => m.supportsTools && m.provider !== 'ollama').slice(0, 3);
1083
+ if (alternatives.length > 0) {
1084
+ recommendation = `This model doesn't support tools. Try: ${alternatives.map(a => a.name).join(', ')}`;
1085
+ }
1086
+ }
1087
+ return {
1088
+ supported: supportsTools,
1089
+ model: modelRef.model,
1090
+ provider: modelRef.provider,
1091
+ recommendation,
1092
+ };
1093
+ }
1094
+ /**
1095
+ * Chat with native tool calling using Vercel AI SDK
1096
+ * This uses the native tool() function for proper multi-step execution
1097
+ *
1098
+ * NOTE: If the model doesn't support native tool calling, tools will be
1099
+ * skipped and a warning will be included in the response.
1100
+ */
1101
+ async chatWithNativeTools(request) {
1102
+ const startTime = Date.now();
1103
+ // Resolve model
1104
+ const modelRef = request.model
1105
+ ? this.resolveModel(request.model)
1106
+ : { provider: this.defaultProvider, model: 'llama3.2' };
1107
+ const model = await this.getModel(modelRef.provider, modelRef.model);
1108
+ // Check if model supports native tool calling
1109
+ const toolSupport = this.modelSupportsTools(request.model);
1110
+ const shouldUseTools = toolSupport.supported && (request.tools?.length ?? 0) > 0;
1111
+ // Log warning if tools are requested but not supported
1112
+ if ((request.tools?.length ?? 0) > 0 && !toolSupport.supported) {
1113
+ logger.warn(`[AIProvider] Model ${modelRef.model} doesn't support native tool calling. Tools disabled.`, {
1114
+ component: 'AIProvider',
1115
+ model: modelRef.model,
1116
+ provider: modelRef.provider,
1117
+ });
1118
+ }
1119
+ // Convert messages to AI SDK format
1120
+ const messages = toAiMessages(request.messages);
1121
+ // Add system prompt if provided
1122
+ if (request.systemPrompt) {
1123
+ messages.unshift({ role: 'system', content: request.systemPrompt });
1124
+ }
1125
+ // Track tool calls and results
1126
+ const toolCallHistory = [];
1127
+ const toolResultHistory = [];
1128
+ // Convert tool definitions to AI SDK format with execute handlers
1129
+ // Only build tools if the model supports them
1130
+ const tools = {};
1131
+ // Check if provider is Azure - needs normalized JSON Schema
1132
+ const isAzureProvider = modelRef.provider === 'azure';
1133
+ if (shouldUseTools) {
1134
+ for (const toolDef of request.tools || []) {
1135
+ // For Azure, convert Zod schemas to normalized JSON Schema
1136
+ // Azure has stricter schema validation requirements
1137
+ let inputSchema = toolDef.parameters;
1138
+ if (isAzureProvider && toolDef.parameters) {
1139
+ try {
1140
+ inputSchema = buildNativeToolSchema(toolDef.parameters, true);
1141
+ logger.debug(`[AIProvider] Normalized schema for Azure tool: ${toolDef.name}`, {
1142
+ component: 'AIProvider',
1143
+ });
1144
+ }
1145
+ catch (schemaError) {
1146
+ logger.warn(`[AIProvider] Failed to normalize schema for ${toolDef.name}, using original`, {
1147
+ component: 'AIProvider',
1148
+ error: schemaError instanceof Error ? schemaError.message : String(schemaError),
1149
+ });
1150
+ }
1151
+ }
1152
+ // AI SDK v5+ uses inputSchema instead of parameters
1153
+ tools[toolDef.name] = createTool({
1154
+ description: toolDef.description,
1155
+ inputSchema,
1156
+ execute: async (args) => {
1157
+ const toolCallId = randomUUID();
1158
+ const toolArgs = toToolArguments(args);
1159
+ // Record the tool call
1160
+ toolCallHistory.push({
1161
+ id: toolCallId,
1162
+ name: toolDef.name,
1163
+ arguments: toolArgs,
1164
+ });
1165
+ // Execute through the provided handler (which goes through security)
1166
+ if (request.onToolCall) {
1167
+ try {
1168
+ const result = await request.onToolCall(toolDef.name, args, toolCallId);
1169
+ // Handle approval required case
1170
+ if (result.approvalRequired) {
1171
+ toolResultHistory.push({
1172
+ toolCallId,
1173
+ toolName: toolDef.name,
1174
+ result: {
1175
+ pending: true,
1176
+ approvalId: result.approvalId,
1177
+ message: `Awaiting approval for ${toolDef.name}`
1178
+ },
1179
+ approvalRequired: true,
1180
+ approvalId: result.approvalId,
1181
+ });
1182
+ return {
1183
+ pending: true,
1184
+ message: `Tool ${toolDef.name} requires approval. Approval ID: ${result.approvalId}`
1185
+ };
1186
+ }
1187
+ // Record successful result
1188
+ toolResultHistory.push({
1189
+ toolCallId,
1190
+ toolName: toolDef.name,
1191
+ result: result.result,
1192
+ });
1193
+ return result.result;
1194
+ }
1195
+ catch (error) {
1196
+ const errorResult = {
1197
+ success: false,
1198
+ error: error instanceof Error ? error.message : 'Tool execution failed',
1199
+ };
1200
+ toolResultHistory.push({
1201
+ toolCallId,
1202
+ toolName: toolDef.name,
1203
+ result: errorResult,
1204
+ });
1205
+ return errorResult;
1206
+ }
1207
+ }
1208
+ // No handler provided, return placeholder
1209
+ return { error: 'No tool execution handler provided' };
1210
+ },
1211
+ });
1212
+ }
1213
+ } // end if (shouldUseTools)
1214
+ try {
1215
+ const result = await withRetry(() => generateText({
1216
+ model,
1217
+ messages,
1218
+ tools: Object.keys(tools).length > 0 ? tools : undefined,
1219
+ temperature: request.temperature ?? 0.7,
1220
+ maxOutputTokens: request.maxTokens ?? 4096,
1221
+ maxSteps: request.maxToolRoundtrips ?? 5,
1222
+ abortSignal: AbortSignal.timeout(AI_TIMEOUT_MS),
1223
+ }));
1224
+ const duration = Date.now() - startTime;
1225
+ const modelInfo = this.getModelInfo(modelRef.model);
1226
+ // Calculate usage
1227
+ const promptTokens = result.usage?.promptTokens ??
1228
+ result.usage?.inputTokens ?? 0;
1229
+ const completionTokens = result.usage?.completionTokens ??
1230
+ result.usage?.outputTokens ?? 0;
1231
+ const cost = modelInfo
1232
+ ? (promptTokens / 1_000_000) * modelInfo.costPer1MInput +
1233
+ (completionTokens / 1_000_000) * modelInfo.costPer1MOutput
1234
+ : 0;
1235
+ // Check if any tool calls require approval
1236
+ const pendingApprovals = toolResultHistory.filter(r => r.approvalRequired);
1237
+ return {
1238
+ id: randomUUID(),
1239
+ provider: modelRef.provider,
1240
+ model: modelRef.model,
1241
+ content: result.text,
1242
+ finishReason: pendingApprovals.length > 0
1243
+ ? 'approval-required'
1244
+ : toolCallHistory.length > 0
1245
+ ? 'tool-calls'
1246
+ : (result.finishReason === 'stop' ? 'stop' : 'length'),
1247
+ usage: {
1248
+ promptTokens,
1249
+ completionTokens,
1250
+ totalTokens: promptTokens + completionTokens,
1251
+ cost,
1252
+ },
1253
+ duration,
1254
+ toolCalls: toolCallHistory.length > 0 ? toolCallHistory : undefined,
1255
+ toolResults: toolResultHistory.length > 0 ? toolResultHistory : undefined,
1256
+ pendingApprovals: pendingApprovals.length > 0 ? pendingApprovals : undefined,
1257
+ steps: result.steps?.length ?? 1,
1258
+ // Tool support info for UI warnings
1259
+ toolSupport: {
1260
+ requested: (request.tools?.length ?? 0) > 0,
1261
+ supported: toolSupport.supported,
1262
+ used: shouldUseTools,
1263
+ recommendation: toolSupport.recommendation,
1264
+ },
1265
+ };
1266
+ }
1267
+ catch (error) {
1268
+ logger.error(`[AIProvider] Native tool calling error:`, error instanceof Error ? error : undefined);
1269
+ throw error;
1270
+ }
1271
+ }
1272
+ /**
1273
+ * Stream chat with native tool calling
1274
+ */
1275
+ async streamWithNativeTools(request, onChunk, onToolCall, onToolResult) {
1276
+ const startTime = Date.now();
1277
+ // Resolve model
1278
+ const modelRef = request.model
1279
+ ? this.resolveModel(request.model)
1280
+ : { provider: this.defaultProvider, model: 'llama3.2' };
1281
+ const model = await this.getModel(modelRef.provider, modelRef.model);
1282
+ // Convert messages
1283
+ const messages = toAiMessages(request.messages);
1284
+ if (request.systemPrompt) {
1285
+ messages.unshift({ role: 'system', content: request.systemPrompt });
1286
+ }
1287
+ // Track tool calls
1288
+ const toolCallHistory = [];
1289
+ const toolResultHistory = [];
1290
+ // Build tools with execute handlers
1291
+ const tools = {};
1292
+ // Check if provider is Azure - needs normalized JSON Schema
1293
+ const isAzureProvider = modelRef.provider === 'azure';
1294
+ for (const toolDef of request.tools || []) {
1295
+ // For Azure, convert Zod schemas to normalized JSON Schema
1296
+ let inputSchema = toolDef.parameters;
1297
+ if (isAzureProvider && toolDef.parameters) {
1298
+ try {
1299
+ inputSchema = buildNativeToolSchema(toolDef.parameters, true);
1300
+ }
1301
+ catch {
1302
+ // Fall back to original schema
1303
+ }
1304
+ }
1305
+ // AI SDK v5+ uses inputSchema instead of parameters
1306
+ tools[toolDef.name] = createTool({
1307
+ description: toolDef.description,
1308
+ inputSchema,
1309
+ execute: async (args) => {
1310
+ const toolCallId = randomUUID();
1311
+ const toolArgs = toToolArguments(args);
1312
+ toolCallHistory.push({
1313
+ id: toolCallId,
1314
+ name: toolDef.name,
1315
+ arguments: toolArgs,
1316
+ });
1317
+ // Notify about tool call
1318
+ onToolCall?.(toolDef.name, args);
1319
+ if (request.onToolCall) {
1320
+ try {
1321
+ const result = await request.onToolCall(toolDef.name, args, toolCallId);
1322
+ if (result.approvalRequired) {
1323
+ toolResultHistory.push({
1324
+ toolCallId,
1325
+ toolName: toolDef.name,
1326
+ result: { pending: true, approvalId: result.approvalId },
1327
+ approvalRequired: true,
1328
+ approvalId: result.approvalId,
1329
+ });
1330
+ onToolResult?.(toolDef.name, { pending: true, approvalRequired: true });
1331
+ return { pending: true, message: `Awaiting approval` };
1332
+ }
1333
+ toolResultHistory.push({
1334
+ toolCallId,
1335
+ toolName: toolDef.name,
1336
+ result: result.result,
1337
+ });
1338
+ onToolResult?.(toolDef.name, result.result);
1339
+ return result.result;
1340
+ }
1341
+ catch (error) {
1342
+ const errorResult = {
1343
+ success: false,
1344
+ error: error instanceof Error ? error.message : 'Failed'
1345
+ };
1346
+ toolResultHistory.push({
1347
+ toolCallId,
1348
+ toolName: toolDef.name,
1349
+ result: errorResult,
1350
+ });
1351
+ onToolResult?.(toolDef.name, errorResult);
1352
+ return errorResult;
1353
+ }
1354
+ }
1355
+ return { error: 'No handler' };
1356
+ },
1357
+ });
1358
+ }
1359
+ try {
1360
+ const result = streamText({
1361
+ model,
1362
+ messages,
1363
+ tools: Object.keys(tools).length > 0 ? tools : undefined,
1364
+ temperature: request.temperature ?? 0.7,
1365
+ maxOutputTokens: request.maxTokens ?? 4096,
1366
+ maxSteps: request.maxToolRoundtrips ?? 5,
1367
+ abortSignal: AbortSignal.timeout(AI_TIMEOUT_MS),
1368
+ });
1369
+ let fullText = '';
1370
+ for await (const chunk of result.textStream) {
1371
+ fullText += chunk;
1372
+ onChunk(chunk);
1373
+ }
1374
+ const usage = await result.usage;
1375
+ const duration = Date.now() - startTime;
1376
+ const modelInfo = this.getModelInfo(modelRef.model);
1377
+ const promptTokens = usage?.promptTokens ??
1378
+ usage?.inputTokens ?? 0;
1379
+ const completionTokens = usage?.completionTokens ??
1380
+ usage?.outputTokens ?? 0;
1381
+ const cost = modelInfo
1382
+ ? (promptTokens / 1_000_000) * modelInfo.costPer1MInput +
1383
+ (completionTokens / 1_000_000) * modelInfo.costPer1MOutput
1384
+ : 0;
1385
+ const pendingApprovals = toolResultHistory.filter(r => r.approvalRequired);
1386
+ return {
1387
+ id: randomUUID(),
1388
+ provider: modelRef.provider,
1389
+ model: modelRef.model,
1390
+ content: fullText,
1391
+ finishReason: pendingApprovals.length > 0
1392
+ ? 'approval-required'
1393
+ : toolCallHistory.length > 0
1394
+ ? 'tool-calls'
1395
+ : 'stop',
1396
+ usage: {
1397
+ promptTokens,
1398
+ completionTokens,
1399
+ totalTokens: promptTokens + completionTokens,
1400
+ cost,
1401
+ },
1402
+ duration,
1403
+ toolCalls: toolCallHistory.length > 0 ? toolCallHistory : undefined,
1404
+ toolResults: toolResultHistory.length > 0 ? toolResultHistory : undefined,
1405
+ pendingApprovals: pendingApprovals.length > 0 ? pendingApprovals : undefined,
1406
+ steps: 1,
1407
+ };
1408
+ }
1409
+ catch (error) {
1410
+ logger.error(`[AIProvider] Stream with tools error:`, error instanceof Error ? error : undefined);
1411
+ throw error;
1412
+ }
1413
+ }
1414
+ async healthCheck(provider) {
1415
+ const results = [];
1416
+ const providers = provider
1417
+ ? [provider]
1418
+ : this.getConfiguredProviders();
1419
+ for (const p of providers) {
1420
+ const start = Date.now();
1421
+ try {
1422
+ if (p === 'ollama') {
1423
+ // Check Ollama server
1424
+ const config = this.configs.get('ollama');
1425
+ const baseUrl = config?.baseUrl || 'http://localhost:11434';
1426
+ const response = await fetch(`${baseUrl}/api/tags`, {
1427
+ signal: AbortSignal.timeout(5000),
1428
+ });
1429
+ if (response.ok) {
1430
+ results.push({
1431
+ provider: p,
1432
+ healthy: true,
1433
+ message: 'Ollama server is running',
1434
+ latencyMs: Date.now() - start,
1435
+ });
1436
+ }
1437
+ else {
1438
+ results.push({
1439
+ provider: p,
1440
+ healthy: false,
1441
+ message: `Ollama returned ${response.status}`,
1442
+ latencyMs: Date.now() - start,
1443
+ });
1444
+ }
1445
+ }
1446
+ else if (p === 'groq') {
1447
+ // Check Groq API
1448
+ const config = this.configs.get('groq');
1449
+ if (config?.apiKey) {
1450
+ try {
1451
+ const response = await fetch('https://api.groq.com/openai/v1/models', {
1452
+ headers: { Authorization: `Bearer ${config.apiKey}` },
1453
+ signal: AbortSignal.timeout(5000),
1454
+ });
1455
+ results.push({
1456
+ provider: p,
1457
+ healthy: response.ok,
1458
+ message: response.ok ? 'Groq API is accessible' : `Groq returned ${response.status}`,
1459
+ latencyMs: Date.now() - start,
1460
+ });
1461
+ }
1462
+ catch {
1463
+ results.push({
1464
+ provider: p,
1465
+ healthy: false,
1466
+ message: 'Groq API unreachable',
1467
+ latencyMs: Date.now() - start,
1468
+ });
1469
+ }
1470
+ }
1471
+ else {
1472
+ results.push({
1473
+ provider: p,
1474
+ healthy: false,
1475
+ message: 'Groq not configured',
1476
+ });
1477
+ }
1478
+ }
1479
+ else if (p === 'azure') {
1480
+ // Azure OpenAI - check if configured (supports both baseUrl and resourceName modes)
1481
+ const config = this.configs.get('azure');
1482
+ const hasValidConfig = !!(config?.apiKey && (config?.baseUrl || config?.resourceName));
1483
+ results.push({
1484
+ provider: p,
1485
+ healthy: hasValidConfig,
1486
+ message: hasValidConfig
1487
+ ? `Azure OpenAI configured${config?.baseUrl ? ` (${config.baseUrl})` : config?.resourceName ? ` (${config.resourceName})` : ''}`
1488
+ : 'Azure OpenAI not configured',
1489
+ latencyMs: Date.now() - start,
1490
+ });
1491
+ }
1492
+ else {
1493
+ // For cloud providers, we assume they're healthy if configured
1494
+ results.push({
1495
+ provider: p,
1496
+ healthy: this.isConfigured(p),
1497
+ message: this.isConfigured(p)
1498
+ ? `${p} is configured`
1499
+ : `${p} not configured`,
1500
+ });
1501
+ }
1502
+ }
1503
+ catch (error) {
1504
+ results.push({
1505
+ provider: p,
1506
+ healthy: false,
1507
+ message: error instanceof Error ? error.message : 'Health check failed',
1508
+ latencyMs: Date.now() - start,
1509
+ });
1510
+ }
1511
+ }
1512
+ return results;
1513
+ }
1514
+ }
1515
+ // === Singleton Export ===
1516
+ export const aiProvider = new AIProviderManager();
1517
+ export async function chat(prompt, options) {
1518
+ const response = await aiProvider.chat({
1519
+ messages: [
1520
+ {
1521
+ id: randomUUID(),
1522
+ role: 'user',
1523
+ content: prompt,
1524
+ timestamp: new Date().toISOString(),
1525
+ },
1526
+ ],
1527
+ model: options?.model,
1528
+ systemPrompt: options?.systemPrompt,
1529
+ temperature: options?.temperature,
1530
+ });
1531
+ return response.content;
1532
+ }
1533
+ /**
1534
+ * Stream chat function
1535
+ */
1536
+ export async function chatStream(prompt, onChunk, options) {
1537
+ const response = await aiProvider.chatStream({
1538
+ messages: [
1539
+ {
1540
+ id: randomUUID(),
1541
+ role: 'user',
1542
+ content: prompt,
1543
+ timestamp: new Date().toISOString(),
1544
+ },
1545
+ ],
1546
+ model: options?.model,
1547
+ systemPrompt: options?.systemPrompt,
1548
+ temperature: options?.temperature,
1549
+ }, onChunk);
1550
+ return response.content;
1551
+ }
1552
+ //# sourceMappingURL=ai-sdk.js.map