@ebowwa/coder 0.7.63 → 0.7.65

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 (364) hide show
  1. package/dist/core/__tests__/permissions.test.d.ts +12 -0
  2. package/dist/core/__tests__/permissions.test.d.ts.map +1 -0
  3. package/dist/core/__tests__/permissions.test.js +851 -0
  4. package/dist/core/agent-loop/__tests__/compaction.test.d.ts +5 -0
  5. package/dist/core/agent-loop/__tests__/compaction.test.d.ts.map +1 -0
  6. package/dist/core/agent-loop/__tests__/compaction.test.js +209 -0
  7. package/dist/core/agent-loop/__tests__/formatters.test.d.ts +5 -0
  8. package/dist/core/agent-loop/__tests__/formatters.test.d.ts.map +1 -0
  9. package/dist/core/agent-loop/__tests__/formatters.test.js +195 -0
  10. package/dist/core/agent-loop/__tests__/index.test.d.ts +5 -0
  11. package/dist/core/agent-loop/__tests__/index.test.d.ts.map +1 -0
  12. package/dist/core/agent-loop/__tests__/index.test.js +121 -0
  13. package/dist/core/agent-loop/__tests__/loop-state.test.d.ts +5 -0
  14. package/dist/core/agent-loop/__tests__/loop-state.test.d.ts.map +1 -0
  15. package/dist/core/agent-loop/__tests__/loop-state.test.js +340 -0
  16. package/dist/core/agent-loop/__tests__/message-builder.test.d.ts +5 -0
  17. package/dist/core/agent-loop/__tests__/message-builder.test.d.ts.map +1 -0
  18. package/dist/core/agent-loop/__tests__/message-builder.test.js +178 -0
  19. package/dist/core/agent-loop/__tests__/tool-executor.test.d.ts +5 -0
  20. package/dist/core/agent-loop/__tests__/tool-executor.test.d.ts.map +1 -0
  21. package/dist/core/agent-loop/__tests__/tool-executor.test.js +331 -0
  22. package/dist/core/agent-loop/compaction.d.ts +39 -0
  23. package/dist/core/agent-loop/compaction.d.ts.map +1 -0
  24. package/dist/core/agent-loop/compaction.js +51 -0
  25. package/dist/core/agent-loop/formatters.d.ts +21 -0
  26. package/dist/core/agent-loop/formatters.d.ts.map +1 -0
  27. package/dist/core/agent-loop/formatters.js +42 -0
  28. package/dist/core/agent-loop/index.d.ts +25 -0
  29. package/dist/core/agent-loop/index.d.ts.map +1 -0
  30. package/dist/core/agent-loop/index.js +83 -0
  31. package/dist/core/agent-loop/loop-state.d.ts +74 -0
  32. package/dist/core/agent-loop/loop-state.d.ts.map +1 -0
  33. package/dist/core/agent-loop/loop-state.js +147 -0
  34. package/dist/core/agent-loop/message-builder.d.ts +13 -0
  35. package/dist/core/agent-loop/message-builder.d.ts.map +1 -0
  36. package/dist/core/agent-loop/message-builder.js +49 -0
  37. package/dist/core/agent-loop/tool-executor.d.ts +23 -0
  38. package/dist/core/agent-loop/tool-executor.d.ts.map +1 -0
  39. package/dist/core/agent-loop/tool-executor.js +152 -0
  40. package/dist/core/agent-loop/turn-executor.d.ts +57 -0
  41. package/dist/core/agent-loop/turn-executor.d.ts.map +1 -0
  42. package/dist/core/agent-loop/turn-executor.js +124 -0
  43. package/dist/core/agent-loop/types.d.ts +141 -0
  44. package/dist/core/agent-loop/types.d.ts.map +1 -0
  45. package/dist/core/agent-loop/types.js +4 -0
  46. package/dist/core/agent-loop.d.ts +17 -0
  47. package/dist/core/agent-loop.d.ts.map +1 -0
  48. package/dist/core/agent-loop.js +16 -0
  49. package/dist/core/api-client-impl.d.ts +62 -0
  50. package/dist/core/api-client-impl.d.ts.map +1 -0
  51. package/dist/core/api-client-impl.js +479 -0
  52. package/dist/core/api-client.d.ts +6 -0
  53. package/dist/core/api-client.d.ts.map +1 -0
  54. package/dist/core/api-client.js +5 -0
  55. package/dist/core/checkpoints.d.ts +128 -0
  56. package/dist/core/checkpoints.d.ts.map +1 -0
  57. package/dist/core/checkpoints.js +438 -0
  58. package/dist/core/claude-md.d.ts +71 -0
  59. package/dist/core/claude-md.d.ts.map +1 -0
  60. package/dist/core/claude-md.js +198 -0
  61. package/dist/core/cognitive-security/hooks.d.ts +138 -0
  62. package/dist/core/cognitive-security/hooks.d.ts.map +1 -0
  63. package/dist/core/cognitive-security/hooks.js +389 -0
  64. package/dist/core/cognitive-security/index.d.ts +751 -0
  65. package/dist/core/cognitive-security/index.d.ts.map +1 -0
  66. package/dist/core/cognitive-security/index.js +1123 -0
  67. package/dist/core/cognitive-security/middleware.d.ts +136 -0
  68. package/dist/core/cognitive-security/middleware.d.ts.map +1 -0
  69. package/dist/core/cognitive-security/middleware.js +376 -0
  70. package/dist/core/config-loader.d.ts +127 -0
  71. package/dist/core/config-loader.d.ts.map +1 -0
  72. package/dist/core/config-loader.js +219 -0
  73. package/dist/core/context-compaction.d.ts +87 -0
  74. package/dist/core/context-compaction.d.ts.map +1 -0
  75. package/dist/core/context-compaction.js +428 -0
  76. package/dist/core/git-status.d.ts +25 -0
  77. package/dist/core/git-status.d.ts.map +1 -0
  78. package/dist/core/git-status.js +204 -0
  79. package/dist/core/image.d.ts +69 -0
  80. package/dist/core/image.d.ts.map +1 -0
  81. package/dist/core/image.js +290 -0
  82. package/dist/core/image.test.d.ts +2 -0
  83. package/dist/core/image.test.d.ts.map +1 -0
  84. package/dist/core/image.test.js +149 -0
  85. package/dist/core/models.d.ts +123 -0
  86. package/dist/core/models.d.ts.map +1 -0
  87. package/dist/core/models.js +325 -0
  88. package/dist/core/permissions.d.ts +81 -0
  89. package/dist/core/permissions.d.ts.map +1 -0
  90. package/dist/core/permissions.js +327 -0
  91. package/dist/core/retry.d.ts +25 -0
  92. package/dist/core/retry.d.ts.map +1 -0
  93. package/dist/core/retry.js +121 -0
  94. package/dist/core/session-store.d.ts +9 -0
  95. package/dist/core/session-store.d.ts.map +1 -0
  96. package/dist/core/session-store.js +10 -0
  97. package/dist/core/sessions/export.d.ts +47 -0
  98. package/dist/core/sessions/export.d.ts.map +1 -0
  99. package/dist/core/sessions/export.js +256 -0
  100. package/dist/core/sessions/index.d.ts +132 -0
  101. package/dist/core/sessions/index.d.ts.map +1 -0
  102. package/dist/core/sessions/index.js +442 -0
  103. package/dist/core/sessions/metadata.d.ts +77 -0
  104. package/dist/core/sessions/metadata.d.ts.map +1 -0
  105. package/dist/core/sessions/metadata.js +233 -0
  106. package/dist/core/sessions/persistence.d.ts +72 -0
  107. package/dist/core/sessions/persistence.d.ts.map +1 -0
  108. package/dist/core/sessions/persistence.js +201 -0
  109. package/dist/core/sessions/types.d.ts +110 -0
  110. package/dist/core/sessions/types.d.ts.map +1 -0
  111. package/dist/core/sessions/types.js +4 -0
  112. package/dist/core/stream-highlighter.d.ts +18 -0
  113. package/dist/core/stream-highlighter.d.ts.map +1 -0
  114. package/dist/core/stream-highlighter.js +916 -0
  115. package/dist/core/system-reminders.d.ts +89 -0
  116. package/dist/core/system-reminders.d.ts.map +1 -0
  117. package/dist/core/system-reminders.js +285 -0
  118. package/dist/ecosystem/hooks/__tests__/index.test.d.ts +5 -0
  119. package/dist/ecosystem/hooks/__tests__/index.test.d.ts.map +1 -0
  120. package/dist/ecosystem/hooks/__tests__/index.test.js +458 -0
  121. package/dist/ecosystem/hooks/index.d.ts +59 -0
  122. package/dist/ecosystem/hooks/index.d.ts.map +1 -0
  123. package/dist/ecosystem/hooks/index.js +294 -0
  124. package/dist/ecosystem/hooks/prompt-evaluator.d.ts +32 -0
  125. package/dist/ecosystem/hooks/prompt-evaluator.d.ts.map +1 -0
  126. package/dist/ecosystem/hooks/prompt-evaluator.js +229 -0
  127. package/dist/ecosystem/skills/index.d.ts +55 -0
  128. package/dist/ecosystem/skills/index.d.ts.map +1 -0
  129. package/dist/ecosystem/skills/index.js +258 -0
  130. package/dist/ecosystem/tools/__tests__/index.test.d.ts +7 -0
  131. package/dist/ecosystem/tools/__tests__/index.test.d.ts.map +1 -0
  132. package/dist/ecosystem/tools/__tests__/index.test.js +856 -0
  133. package/dist/ecosystem/tools/index.d.ts +24 -0
  134. package/dist/ecosystem/tools/index.d.ts.map +1 -0
  135. package/dist/ecosystem/tools/index.js +1709 -0
  136. package/dist/index.d.ts +24 -0
  137. package/dist/index.d.ts.map +1 -0
  138. package/dist/index.js +33688 -49712
  139. package/dist/interfaces/mcp/client.d.ts +40 -0
  140. package/dist/interfaces/mcp/client.d.ts.map +1 -0
  141. package/dist/interfaces/mcp/client.js +309 -0
  142. package/dist/interfaces/ui/index.d.ts +36 -0
  143. package/dist/interfaces/ui/index.d.ts.map +1 -0
  144. package/dist/interfaces/ui/index.js +61 -0
  145. package/dist/interfaces/ui/spinner.d.ts +140 -0
  146. package/dist/interfaces/ui/spinner.d.ts.map +1 -0
  147. package/dist/interfaces/ui/spinner.js +342 -0
  148. package/dist/interfaces/ui/terminal/cli/index.d.ts +12 -0
  149. package/dist/interfaces/ui/terminal/cli/index.d.ts.map +1 -0
  150. package/dist/interfaces/ui/terminal/cli/index.js +32012 -50526
  151. package/dist/interfaces/ui/terminal/native/README.md +53 -0
  152. package/dist/interfaces/ui/terminal/native/claude_code_native.darwin-x64.node +0 -0
  153. package/dist/interfaces/ui/terminal/native/claude_code_native.dylib +0 -0
  154. package/dist/interfaces/ui/terminal/native/index.d.ts +0 -0
  155. package/dist/interfaces/ui/terminal/native/index.darwin-arm64.node +0 -0
  156. package/dist/interfaces/ui/terminal/native/index.js +43 -0
  157. package/dist/interfaces/ui/terminal/native/index.node +0 -0
  158. package/dist/interfaces/ui/terminal/native/package.json +34 -0
  159. package/dist/interfaces/ui/terminal/shared/args.d.ts +39 -0
  160. package/dist/interfaces/ui/terminal/shared/args.d.ts.map +1 -0
  161. package/dist/interfaces/ui/terminal/shared/args.js +176 -0
  162. package/dist/interfaces/ui/terminal/shared/index.d.ts +11 -0
  163. package/dist/interfaces/ui/terminal/shared/index.d.ts.map +1 -0
  164. package/dist/interfaces/ui/terminal/shared/index.js +16 -0
  165. package/dist/interfaces/ui/terminal/shared/loading-state.d.ts +124 -0
  166. package/dist/interfaces/ui/terminal/shared/loading-state.d.ts.map +1 -0
  167. package/dist/interfaces/ui/terminal/shared/loading-state.js +246 -0
  168. package/dist/interfaces/ui/terminal/shared/query.d.ts +22 -0
  169. package/dist/interfaces/ui/terminal/shared/query.d.ts.map +1 -0
  170. package/dist/interfaces/ui/terminal/shared/query.js +100 -0
  171. package/dist/interfaces/ui/terminal/shared/setup.d.ts +33 -0
  172. package/dist/interfaces/ui/terminal/shared/setup.d.ts.map +1 -0
  173. package/dist/interfaces/ui/terminal/shared/setup.js +226 -0
  174. package/dist/interfaces/ui/terminal/shared/status-line.d.ts +117 -0
  175. package/dist/interfaces/ui/terminal/shared/status-line.d.ts.map +1 -0
  176. package/dist/interfaces/ui/terminal/shared/status-line.js +267 -0
  177. package/dist/interfaces/ui/terminal/shared/system-prompt.d.ts +38 -0
  178. package/dist/interfaces/ui/terminal/shared/system-prompt.d.ts.map +1 -0
  179. package/dist/interfaces/ui/terminal/shared/system-prompt.js +102 -0
  180. package/dist/interfaces/ui/terminal/tui/HelpPanel.d.ts +39 -0
  181. package/dist/interfaces/ui/terminal/tui/HelpPanel.d.ts.map +1 -0
  182. package/dist/interfaces/ui/terminal/tui/HelpPanel.js +215 -0
  183. package/dist/interfaces/ui/terminal/tui/InputContext.d.ts +91 -0
  184. package/dist/interfaces/ui/terminal/tui/InputContext.d.ts.map +1 -0
  185. package/dist/interfaces/ui/terminal/tui/InputContext.js +154 -0
  186. package/dist/interfaces/ui/terminal/tui/InputField.d.ts +18 -0
  187. package/dist/interfaces/ui/terminal/tui/InputField.d.ts.map +1 -0
  188. package/dist/interfaces/ui/terminal/tui/InputField.js +41 -0
  189. package/dist/interfaces/ui/terminal/tui/InteractiveTUI.d.ts +16 -0
  190. package/dist/interfaces/ui/terminal/tui/InteractiveTUI.d.ts.map +1 -0
  191. package/dist/interfaces/ui/terminal/tui/InteractiveTUI.js +451 -0
  192. package/dist/interfaces/ui/terminal/tui/MessageArea.d.ts +10 -0
  193. package/dist/interfaces/ui/terminal/tui/MessageArea.d.ts.map +1 -0
  194. package/dist/interfaces/ui/terminal/tui/MessageArea.js +91 -0
  195. package/dist/interfaces/ui/terminal/tui/MessageStore.d.ts +48 -0
  196. package/dist/interfaces/ui/terminal/tui/MessageStore.d.ts.map +1 -0
  197. package/dist/interfaces/ui/terminal/tui/MessageStore.js +151 -0
  198. package/dist/interfaces/ui/terminal/tui/StatusBar.d.ts +9 -0
  199. package/dist/interfaces/ui/terminal/tui/StatusBar.d.ts.map +1 -0
  200. package/dist/interfaces/ui/terminal/tui/StatusBar.js +36 -0
  201. package/dist/interfaces/ui/terminal/tui/commands.d.ts +21 -0
  202. package/dist/interfaces/ui/terminal/tui/commands.d.ts.map +1 -0
  203. package/dist/interfaces/ui/terminal/tui/commands.js +359 -0
  204. package/dist/interfaces/ui/terminal/tui/components/InteractiveElements.d.ts +115 -0
  205. package/dist/interfaces/ui/terminal/tui/components/InteractiveElements.d.ts.map +1 -0
  206. package/dist/interfaces/ui/terminal/tui/components/InteractiveElements.js +306 -0
  207. package/dist/interfaces/ui/terminal/tui/components/MultilineInput.d.ts +92 -0
  208. package/dist/interfaces/ui/terminal/tui/components/MultilineInput.d.ts.map +1 -0
  209. package/dist/interfaces/ui/terminal/tui/components/MultilineInput.js +399 -0
  210. package/dist/interfaces/ui/terminal/tui/components/PaneManager.d.ts +59 -0
  211. package/dist/interfaces/ui/terminal/tui/components/PaneManager.d.ts.map +1 -0
  212. package/dist/interfaces/ui/terminal/tui/components/PaneManager.js +139 -0
  213. package/dist/interfaces/ui/terminal/tui/components/Sidebar.d.ts +68 -0
  214. package/dist/interfaces/ui/terminal/tui/components/Sidebar.d.ts.map +1 -0
  215. package/dist/interfaces/ui/terminal/tui/components/Sidebar.js +340 -0
  216. package/dist/interfaces/ui/terminal/tui/components/index.d.ts +23 -0
  217. package/dist/interfaces/ui/terminal/tui/components/index.d.ts.map +1 -0
  218. package/dist/interfaces/ui/terminal/tui/components/index.js +51 -0
  219. package/dist/interfaces/ui/terminal/tui/console.d.ts +20 -0
  220. package/dist/interfaces/ui/terminal/tui/console.d.ts.map +1 -0
  221. package/dist/interfaces/ui/terminal/tui/console.js +46 -0
  222. package/dist/interfaces/ui/terminal/tui/index.d.ts +20 -0
  223. package/dist/interfaces/ui/terminal/tui/index.d.ts.map +1 -0
  224. package/dist/interfaces/ui/terminal/tui/index.js +28 -0
  225. package/dist/interfaces/ui/terminal/tui/run.d.ts +13 -0
  226. package/dist/interfaces/ui/terminal/tui/run.d.ts.map +1 -0
  227. package/dist/interfaces/ui/terminal/tui/run.js +31 -0
  228. package/dist/interfaces/ui/terminal/tui/spinner.d.ts +44 -0
  229. package/dist/interfaces/ui/terminal/tui/spinner.d.ts.map +1 -0
  230. package/dist/interfaces/ui/terminal/tui/spinner.js +59 -0
  231. package/dist/interfaces/ui/terminal/tui/tui-app.d.ts +39 -0
  232. package/dist/interfaces/ui/terminal/tui/tui-app.d.ts.map +1 -0
  233. package/dist/interfaces/ui/terminal/tui/tui-app.js +198 -0
  234. package/dist/interfaces/ui/terminal/tui/tui-footer.d.ts +167 -0
  235. package/dist/interfaces/ui/terminal/tui/tui-footer.d.ts.map +1 -0
  236. package/dist/interfaces/ui/terminal/tui/tui-footer.js +330 -0
  237. package/dist/interfaces/ui/terminal/tui/types.d.ts +165 -0
  238. package/dist/interfaces/ui/terminal/tui/types.d.ts.map +1 -0
  239. package/dist/interfaces/ui/terminal/tui/types.js +5 -0
  240. package/dist/interfaces/ui/terminal/tui/useInputHandler.d.ts +23 -0
  241. package/dist/interfaces/ui/terminal/tui/useInputHandler.d.ts.map +1 -0
  242. package/dist/interfaces/ui/terminal/tui/useInputHandler.js +72 -0
  243. package/dist/interfaces/ui/terminal/tui/useNativeInput.d.ts +90 -0
  244. package/dist/interfaces/ui/terminal/tui/useNativeInput.d.ts.map +1 -0
  245. package/dist/interfaces/ui/terminal/tui/useNativeInput.js +188 -0
  246. package/dist/native/README.md +53 -0
  247. package/dist/native/claude_code_native.darwin-x64.node +0 -0
  248. package/dist/native/claude_code_native.dylib +0 -0
  249. package/dist/native/index.d.ts +0 -0
  250. package/dist/native/index.d.ts.map +1 -0
  251. package/dist/native/index.darwin-arm64.node +0 -0
  252. package/dist/native/index.js +43 -0
  253. package/dist/native/index.node +0 -0
  254. package/dist/native/package.json +34 -0
  255. package/dist/teammates/index.d.ts +161 -0
  256. package/dist/teammates/index.d.ts.map +1 -0
  257. package/dist/teammates/index.js +827 -0
  258. package/dist/types/index.d.ts +482 -0
  259. package/dist/types/index.d.ts.map +1 -0
  260. package/dist/types/index.js +52 -0
  261. package/native/index.darwin-arm64.node +0 -0
  262. package/native/index.js +33 -19
  263. package/package.json +6 -3
  264. package/packages/src/core/__tests__/permissions.test.ts +1091 -0
  265. package/packages/src/core/agent-loop/__tests__/compaction.test.ts +283 -0
  266. package/packages/src/core/agent-loop/__tests__/formatters.test.ts +234 -0
  267. package/packages/src/core/agent-loop/__tests__/index.test.ts +162 -0
  268. package/packages/src/core/agent-loop/__tests__/loop-state.test.ts +413 -0
  269. package/packages/src/core/agent-loop/__tests__/message-builder.test.ts +229 -0
  270. package/packages/src/core/agent-loop/__tests__/tool-executor.test.ts +457 -0
  271. package/packages/src/core/agent-loop/compaction.ts +92 -0
  272. package/packages/src/core/agent-loop/formatters.ts +50 -0
  273. package/packages/src/core/agent-loop/index.ts +137 -0
  274. package/packages/src/core/agent-loop/loop-state.ts +187 -0
  275. package/packages/src/core/agent-loop/message-builder.ts +62 -0
  276. package/packages/src/core/agent-loop/tool-executor.ts +211 -0
  277. package/packages/src/core/agent-loop/turn-executor.ts +226 -0
  278. package/packages/src/core/agent-loop/types.ts +152 -0
  279. package/packages/src/core/agent-loop.ts +18 -0
  280. package/packages/src/core/api-client-impl.ts +729 -0
  281. package/packages/src/core/api-client.ts +6 -0
  282. package/packages/src/core/checkpoints.ts +606 -0
  283. package/packages/src/core/claude-md.ts +272 -0
  284. package/packages/src/core/cognitive-security/hooks.ts +591 -0
  285. package/packages/src/core/cognitive-security/index.ts +2041 -0
  286. package/packages/src/core/cognitive-security/middleware.ts +536 -0
  287. package/packages/src/core/config/todo +7 -0
  288. package/packages/src/core/config-loader.ts +324 -0
  289. package/packages/src/core/context/__tests__/integration.test.ts +334 -0
  290. package/packages/src/core/context/compaction.ts +170 -0
  291. package/packages/src/core/context/constants.ts +58 -0
  292. package/packages/src/core/context/extraction.ts +85 -0
  293. package/packages/src/core/context/index.ts +66 -0
  294. package/packages/src/core/context/summarization.ts +251 -0
  295. package/packages/src/core/context/token-estimation.ts +98 -0
  296. package/packages/src/core/context/types.ts +59 -0
  297. package/packages/src/core/git-status.ts +262 -0
  298. package/packages/src/core/image.test.ts +180 -0
  299. package/packages/src/core/image.ts +350 -0
  300. package/packages/src/core/lmdb.db +0 -0
  301. package/packages/src/core/lmdb.db-lock +0 -0
  302. package/packages/src/core/models.ts +507 -0
  303. package/packages/src/core/normalizers/todo +8 -0
  304. package/packages/src/core/permissions.ts +431 -0
  305. package/packages/src/core/providers/README.md +230 -0
  306. package/packages/src/core/providers/__tests__/providers.test.ts +135 -0
  307. package/packages/src/core/providers/index.ts +419 -0
  308. package/packages/src/core/providers/types.ts +132 -0
  309. package/packages/src/core/retry.ts +180 -0
  310. package/packages/src/core/session-store.ts +36 -0
  311. package/packages/src/core/sessions/export.ts +329 -0
  312. package/packages/src/core/sessions/index.ts +587 -0
  313. package/packages/src/core/sessions/metadata.ts +309 -0
  314. package/packages/src/core/sessions/persistence.ts +244 -0
  315. package/packages/src/core/sessions/types.ts +169 -0
  316. package/packages/src/core/stream-highlighter.ts +1123 -0
  317. package/packages/src/core/system-reminders.ts +402 -0
  318. package/packages/src/core/todo +8 -0
  319. package/packages/src/ecosystem/hooks/__tests__/index.test.ts +561 -0
  320. package/packages/src/ecosystem/hooks/index.ts +341 -0
  321. package/packages/src/ecosystem/hooks/prompt-evaluator.ts +300 -0
  322. package/packages/src/ecosystem/skills/index.ts +295 -0
  323. package/packages/src/ecosystem/tools/__tests__/index.test.ts +1335 -0
  324. package/packages/src/ecosystem/tools/index.ts +2051 -0
  325. package/packages/src/index.ts +141 -0
  326. package/packages/src/interfaces/mcp/client.ts +389 -0
  327. package/packages/src/interfaces/ui/index.ts +158 -0
  328. package/packages/src/interfaces/ui/lmdb.db +0 -0
  329. package/packages/src/interfaces/ui/lmdb.db-lock +0 -0
  330. package/packages/src/interfaces/ui/spinner.ts +451 -0
  331. package/packages/src/interfaces/ui/terminal/bridge/index.ts +370 -0
  332. package/packages/src/interfaces/ui/terminal/bridge/ipc.ts +829 -0
  333. package/packages/src/interfaces/ui/terminal/bridge/screen-export.ts +968 -0
  334. package/packages/src/interfaces/ui/terminal/bridge/types.ts +226 -0
  335. package/packages/src/interfaces/ui/terminal/bridge/useBridge.ts +210 -0
  336. package/packages/src/interfaces/ui/terminal/cli/bootstrap.ts +132 -0
  337. package/packages/src/interfaces/ui/terminal/cli/index.ts +415 -0
  338. package/packages/src/interfaces/ui/terminal/cli/interactive/index.ts +110 -0
  339. package/packages/src/interfaces/ui/terminal/cli/interactive/input-handler.ts +393 -0
  340. package/packages/src/interfaces/ui/terminal/cli/interactive/interactive-runner.ts +820 -0
  341. package/packages/src/interfaces/ui/terminal/cli/interactive/message-store.ts +299 -0
  342. package/packages/src/interfaces/ui/terminal/cli/interactive/types.ts +274 -0
  343. package/packages/src/interfaces/ui/terminal/lmdb.db +0 -0
  344. package/packages/src/interfaces/ui/terminal/lmdb.db-lock +0 -0
  345. package/packages/src/interfaces/ui/terminal/shared/args.ts +222 -0
  346. package/packages/src/interfaces/ui/terminal/shared/index.ts +84 -0
  347. package/packages/src/interfaces/ui/terminal/shared/loading-state.ts +322 -0
  348. package/packages/src/interfaces/ui/terminal/shared/query.ts +152 -0
  349. package/packages/src/interfaces/ui/terminal/shared/setup.ts +299 -0
  350. package/packages/src/interfaces/ui/terminal/shared/spinner-frames.ts +73 -0
  351. package/packages/src/interfaces/ui/terminal/shared/status-line.ts +366 -0
  352. package/packages/src/interfaces/ui/terminal/shared/system-prompt.ts +146 -0
  353. package/packages/src/lmdb.db +0 -0
  354. package/packages/src/lmdb.db-lock +0 -0
  355. package/packages/src/native/index.ts +2722 -0
  356. package/packages/src/native/tui_v2_types.ts +39 -0
  357. package/packages/src/teammates/coordination.test.ts +279 -0
  358. package/packages/src/teammates/coordination.ts +646 -0
  359. package/packages/src/teammates/index.ts +1052 -0
  360. package/packages/src/teammates/integration.test.ts +272 -0
  361. package/packages/src/teammates/runner.test.ts +235 -0
  362. package/packages/src/teammates/runner.ts +750 -0
  363. package/packages/src/teammates/schemas.ts +673 -0
  364. package/packages/src/types/index.ts +723 -0
@@ -0,0 +1,729 @@
1
+ /**
2
+ * API Client - SSE streaming for LLM APIs
3
+ *
4
+ * Supports multiple providers:
5
+ * - Zhipu (Z.AI / GLM models) - OpenAI format
6
+ * - MiniMax (M2.5) - Anthropic format
7
+ * - OpenAI (future)
8
+ */
9
+
10
+ import type {
11
+ Message,
12
+ ContentBlock,
13
+ ToolUseBlock,
14
+ UsageMetrics,
15
+ APIRequest,
16
+ APIResponse,
17
+ APITool,
18
+ JSONSchema,
19
+ CacheConfig,
20
+ CacheControl,
21
+ CacheMetrics,
22
+ SystemBlock,
23
+ ThinkingConfig,
24
+ ExtendedThinkingConfig,
25
+ EffortLevel,
26
+ RedactedThinkingBlock,
27
+ StopReason,
28
+ } from "../types/index.js";
29
+ import {
30
+ DEFAULT_CACHE_CONFIG,
31
+ calculateBudgetTokens,
32
+ supportsExtendedThinking as supportsThinkingType,
33
+ EFFORT_TO_BUDGET,
34
+ } from "../types/index.js";
35
+ import { withRetry, parseRetryAfter, type RetryOptions } from "./retry.js";
36
+ import {
37
+ calculateCost as calculateModelCost,
38
+ DEFAULT_MODEL,
39
+ supportsExtendedThinking,
40
+ } from "./models.js";
41
+ import {
42
+ resolveProvider,
43
+ getProviderForModel,
44
+ recordProviderSuccess,
45
+ recordProviderFailure,
46
+ type ProviderName,
47
+ type ProviderConfig,
48
+ } from "./providers/index.js";
49
+
50
+ /**
51
+ * Convert Anthropic-style tools to OpenAI-style tools
52
+ * Anthropic: { name, description, input_schema }
53
+ * OpenAI: { type: "function", function: { name, description, parameters } }
54
+ */
55
+ function convertToolsToOpenAIFormat(tools: APITool[]): unknown[] {
56
+ return tools.map((tool) => ({
57
+ type: "function",
58
+ function: {
59
+ name: tool.name,
60
+ description: tool.description,
61
+ parameters: tool.input_schema,
62
+ },
63
+ }));
64
+ }
65
+
66
+ export interface StreamOptions {
67
+ apiKey: string;
68
+ model?: string;
69
+ maxTokens?: number;
70
+ tools?: APITool[];
71
+ systemPrompt?: string | SystemBlock[];
72
+ cacheConfig?: CacheConfig;
73
+ /** Legacy thinking config (budget_tokens) */
74
+ thinking?: ThinkingConfig;
75
+ /** Extended thinking config (effort levels) */
76
+ extendedThinking?: ExtendedThinkingConfig;
77
+ onToken?: (text: string) => void;
78
+ onThinking?: (thinking: string) => void;
79
+ /** Called when redacted thinking is received (data is base64) */
80
+ onRedactedThinking?: (data: string) => void;
81
+ onToolUse?: (toolUse: { id: string; name: string; input: unknown }) => void;
82
+ /** Called when a retry is about to start - UI should reset streaming state */
83
+ onRetryStart?: () => void;
84
+ signal?: AbortSignal;
85
+ }
86
+
87
+ export interface StreamResult {
88
+ message: APIResponse;
89
+ usage: UsageMetrics;
90
+ cacheMetrics?: CacheMetrics;
91
+ costUSD: number;
92
+ durationMs: number;
93
+ ttftMs: number;
94
+ /** Thinking tokens used (if extended thinking was enabled) */
95
+ thinkingTokens?: number;
96
+ }
97
+
98
+ /**
99
+ * Calculate cost for API usage including cache metrics
100
+ * Delegates to models.ts for centralized pricing
101
+ */
102
+ export function calculateCost(
103
+ model: string,
104
+ usage: UsageMetrics
105
+ ): { costUSD: number; estimatedSavingsUSD: number } {
106
+ return calculateModelCost(model, usage);
107
+ }
108
+
109
+ /**
110
+ * Build system prompt with cache control
111
+ */
112
+ export function buildSystemPrompt(
113
+ systemPrompt: string | SystemBlock[] | undefined,
114
+ cacheConfig: CacheConfig
115
+ ): string | SystemBlock[] | undefined {
116
+ if (!systemPrompt || !cacheConfig.enabled || !cacheConfig.cacheSystemPrompt) {
117
+ return typeof systemPrompt === "string" ? systemPrompt : undefined;
118
+ }
119
+
120
+ // If already in block format, add cache_control to the last block
121
+ if (Array.isArray(systemPrompt)) {
122
+ const blocks = [...systemPrompt];
123
+ if (blocks.length > 0) {
124
+ const lastBlock = blocks[blocks.length - 1];
125
+ if (lastBlock && lastBlock.type === "text") {
126
+ blocks[blocks.length - 1] = {
127
+ type: "text" as const,
128
+ text: lastBlock.text,
129
+ cache_control: { type: "ephemeral" as const, ttl: cacheConfig.ttl },
130
+ };
131
+ }
132
+ }
133
+ return blocks;
134
+ }
135
+
136
+ // Convert string to block format with cache_control
137
+ return [
138
+ {
139
+ type: "text",
140
+ text: systemPrompt,
141
+ cache_control: { type: "ephemeral", ttl: cacheConfig.ttl },
142
+ },
143
+ ];
144
+ }
145
+
146
+ /**
147
+ * Build messages with cache control for long context blocks
148
+ */
149
+ export function buildCachedMessages(
150
+ messages: Message[],
151
+ cacheConfig: CacheConfig
152
+ ): Message[] {
153
+ if (!cacheConfig.enabled) {
154
+ return messages;
155
+ }
156
+
157
+ const result: Message[] = [];
158
+
159
+ for (let i = 0; i < messages.length; i++) {
160
+ const msg = messages[i]!;
161
+
162
+ // Convert string content to content blocks array
163
+ const contentBlocks: ContentBlock[] = typeof msg.content === "string"
164
+ ? [{ type: "text", text: msg.content }]
165
+ : msg.content;
166
+
167
+ const cachedContent: ContentBlock[] = [];
168
+
169
+ for (let j = 0; j < contentBlocks.length; j++) {
170
+ const block = contentBlocks[j]!;
171
+ const isLastBlock = j === contentBlocks.length - 1;
172
+ const isLastMessage = i === messages.length - 1;
173
+
174
+ // Add cache_control to large text blocks (especially in user messages)
175
+ if (
176
+ block.type === "text" &&
177
+ block.text.length >= cacheConfig.minTokensForCache * 4 && // Approximate chars per token
178
+ !block.cache_control &&
179
+ (isLastBlock || isLastMessage)
180
+ ) {
181
+ cachedContent.push({
182
+ ...block,
183
+ cache_control: { type: "ephemeral", ttl: cacheConfig.ttl },
184
+ });
185
+ } else {
186
+ cachedContent.push(block);
187
+ }
188
+ }
189
+
190
+ result.push({ ...msg, content: cachedContent });
191
+ }
192
+
193
+ // Ensure the last message has cache_control on its last content block
194
+ if (result.length > 0 && cacheConfig.enabled) {
195
+ const lastMsg = result[result.length - 1]!;
196
+ const lastBlock = lastMsg.content[lastMsg.content.length - 1];
197
+ if (lastBlock && !("cache_control" in lastBlock)) {
198
+ lastMsg.content[lastMsg.content.length - 1] = {
199
+ ...lastBlock,
200
+ cache_control: { type: "ephemeral", ttl: cacheConfig.ttl },
201
+ } as ContentBlock;
202
+ }
203
+ }
204
+
205
+ return result;
206
+ }
207
+
208
+ /**
209
+ * Calculate cache metrics from usage
210
+ */
211
+ export function calculateCacheMetrics(usage: UsageMetrics): CacheMetrics {
212
+ const cacheReadTokens = usage.cache_read_input_tokens ?? 0;
213
+ const cacheWriteTokens = usage.cache_creation_input_tokens ?? 0;
214
+ const totalCacheTokens = cacheReadTokens + cacheWriteTokens;
215
+
216
+ const cacheHits = cacheReadTokens > 0 ? 1 : 0;
217
+ const cacheMisses = cacheWriteTokens > 0 ? 1 : 0;
218
+ const total = cacheHits + cacheMisses;
219
+
220
+ return {
221
+ cacheHits,
222
+ cacheMisses,
223
+ totalCacheReadTokens: cacheReadTokens,
224
+ totalCacheWriteTokens: cacheWriteTokens,
225
+ cacheHitRate: total > 0 ? cacheHits / total : 0,
226
+ estimatedSavingsUSD: 0, // Will be calculated after pricing lookup
227
+ };
228
+ }
229
+
230
+ /**
231
+ * Callbacks to emit during streaming (passed in, not buffered)
232
+ */
233
+ interface StreamCallbacks {
234
+ onToken?: (text: string) => void;
235
+ onThinking?: (thinking: string) => void;
236
+ onRedactedThinking?: (data: string) => void;
237
+ onToolUse?: (toolUse: { id: string; name: string; input: unknown }) => void;
238
+ onRetryStart?: () => void;
239
+ }
240
+
241
+ /**
242
+ * Internal result from a single stream attempt
243
+ */
244
+ interface StreamAttemptResult {
245
+ message: APIResponse | null;
246
+ content: ContentBlock[];
247
+ usage: UsageMetrics;
248
+ thinkingTokens: number;
249
+ ttftMs: number;
250
+ }
251
+
252
+ /**
253
+ * Execute a single streaming API attempt
254
+ * Emits callbacks in real-time for streaming display
255
+ */
256
+ async function executeStreamAttempt(
257
+ request: APIRequest,
258
+ headers: Record<string, string>,
259
+ apiEndpoint: string,
260
+ signal: AbortSignal | undefined,
261
+ model: string,
262
+ retryableStatusCodes: number[],
263
+ startTime: number,
264
+ callbacks: StreamCallbacks
265
+ ): Promise<StreamAttemptResult> {
266
+ const response = await fetch(apiEndpoint, {
267
+ method: "POST",
268
+ headers,
269
+ body: JSON.stringify(request),
270
+ signal,
271
+ });
272
+
273
+ // Throw for retryable status codes so withRetry can handle them
274
+ if (!response.ok) {
275
+ const errorText = await response.text();
276
+ if (retryableStatusCodes.includes(response.status)) {
277
+ throw new Error(`API error: ${response.status} - ${errorText}`);
278
+ }
279
+ throw new Error(`API error: ${response.status} - ${errorText}`);
280
+ }
281
+
282
+ if (!response.body) {
283
+ throw new Error("No response body");
284
+ }
285
+
286
+ // Parse SSE stream
287
+ const reader = response.body.getReader();
288
+ const decoder = new TextDecoder();
289
+
290
+ let message: APIResponse | null = null;
291
+ let currentContent: ContentBlock[] = [];
292
+ let usage: UsageMetrics = { input_tokens: 0, output_tokens: 0 };
293
+ let currentTextBlock: { type: "text"; text: string } | null = null;
294
+ let currentThinkingBlock: { type: "thinking"; thinking: string } | null = null;
295
+ let currentRedactedThinkingBlock: { type: "redacted_thinking"; data: string } | null = null;
296
+ let currentToolUseBlock: ToolUseBlock | null = null;
297
+ let toolUseInput = "";
298
+
299
+ let ttft = 0;
300
+ let firstToken = true;
301
+ let totalThinkingTokens = 0;
302
+
303
+ try {
304
+ let buffer = "";
305
+
306
+ while (true) {
307
+ const { done, value } = await reader.read();
308
+ if (done) break;
309
+
310
+ buffer += decoder.decode(value, { stream: true });
311
+ const lines = buffer.split("\n");
312
+ buffer = lines.pop() || "";
313
+
314
+ for (const line of lines) {
315
+ if (!line.startsWith("data: ")) continue;
316
+
317
+ const data = line.slice(6);
318
+ if (!data) continue;
319
+
320
+ // Debug: Log all SSE data when debug enabled
321
+ if (process.env.DEBUG_API === '1') {
322
+ console.log('\x1b[90m[DEBUG] SSE data:\x1b[0m', data.substring(0, 200));
323
+ }
324
+
325
+ try {
326
+ const event = JSON.parse(data) as Record<string, unknown>;
327
+
328
+ // Debug: Log event types
329
+ if (process.env.DEBUG_API === '1' && event.type) {
330
+ console.log('\x1b[90m[DEBUG] SSE event type:\x1b[0m', event.type);
331
+ }
332
+
333
+ switch (event.type) {
334
+ case "error": {
335
+ // API returned an error - surface it
336
+ const errorEvent = event as { error?: { type?: string; message?: string } };
337
+ const errorMsg = errorEvent.error?.message || errorEvent.error?.type || "Unknown API error";
338
+ console.error(`API error: ${errorMsg}`);
339
+ // Include more details in debug mode
340
+ if (process.env.DEBUG_API === '1') {
341
+ console.log('\x1b[91m[DEBUG] API error event:', JSON.stringify(errorEvent, null, 255));
342
+ }
343
+ throw new Error(`API error: ${errorMsg}`);
344
+ }
345
+
346
+ case "message_start": {
347
+ const msg = event.message as APIResponse;
348
+ message = msg;
349
+ usage = msg.usage;
350
+ break;
351
+ }
352
+
353
+ case "content_block_start": {
354
+ const block = (event as { content_block: Record<string, unknown> }).content_block;
355
+ if (block.type === "text") {
356
+ currentTextBlock = { type: "text", text: "" };
357
+ } else if (block.type === "thinking") {
358
+ currentThinkingBlock = { type: "thinking", thinking: "" };
359
+ } else if (block.type === "redacted_thinking") {
360
+ currentRedactedThinkingBlock = { type: "redacted_thinking", data: "" };
361
+ } else if (block.type === "tool_use") {
362
+ currentToolUseBlock = {
363
+ type: "tool_use",
364
+ id: block.id as string,
365
+ name: block.name as string,
366
+ input: {},
367
+ };
368
+ toolUseInput = "";
369
+ }
370
+ break;
371
+ }
372
+
373
+ case "content_block_delta": {
374
+ const delta = (event as { delta: Record<string, unknown> }).delta;
375
+ if (delta.type === "text_delta" && currentTextBlock) {
376
+ const text = delta.text as string;
377
+ currentTextBlock.text += text;
378
+ callbacks.onToken?.(text); // Emit in real-time
379
+
380
+ if (firstToken) {
381
+ ttft = Date.now() - startTime;
382
+ firstToken = false;
383
+ }
384
+ } else if (delta.type === "thinking_delta" && currentThinkingBlock) {
385
+ const thinking = delta.thinking as string;
386
+ currentThinkingBlock.thinking += thinking;
387
+ callbacks.onThinking?.(thinking); // Emit in real-time
388
+ totalThinkingTokens += Math.ceil(thinking.length / 4);
389
+ } else if (delta.type === "redacted_thinking_delta" && currentRedactedThinkingBlock) {
390
+ const redactedData = delta.data as string;
391
+ currentRedactedThinkingBlock.data += redactedData;
392
+ callbacks.onRedactedThinking?.(redactedData); // Emit in real-time
393
+ totalThinkingTokens += Math.ceil(redactedData.length / 4);
394
+ } else if (delta.type === "input_json_delta" && currentToolUseBlock) {
395
+ toolUseInput += delta.partial_json as string;
396
+ }
397
+ break;
398
+ }
399
+
400
+ case "content_block_stop": {
401
+ if (currentTextBlock !== null) {
402
+ currentContent.push(currentTextBlock);
403
+ currentTextBlock = null;
404
+ } else if (currentThinkingBlock !== null) {
405
+ currentContent.push(currentThinkingBlock);
406
+ currentThinkingBlock = null;
407
+ } else if (currentRedactedThinkingBlock !== null) {
408
+ currentContent.push(currentRedactedThinkingBlock);
409
+ currentRedactedThinkingBlock = null;
410
+ } else if (currentToolUseBlock !== null) {
411
+ try {
412
+ currentToolUseBlock.input = JSON.parse(toolUseInput);
413
+ } catch {
414
+ currentToolUseBlock.input = {};
415
+ }
416
+ currentContent.push(currentToolUseBlock);
417
+ callbacks.onToolUse?.({
418
+ id: currentToolUseBlock.id,
419
+ name: currentToolUseBlock.name,
420
+ input: currentToolUseBlock.input,
421
+ }); // Emit in real-time
422
+ currentToolUseBlock = null;
423
+ toolUseInput = "";
424
+ }
425
+ break;
426
+ }
427
+
428
+ case "message_delta": {
429
+ const evt = event as { usage?: { output_tokens: number }; delta?: { stop_reason: string } };
430
+ if (evt.usage) {
431
+ usage.output_tokens = evt.usage.output_tokens;
432
+ }
433
+ if (message && evt.delta?.stop_reason) {
434
+ message.stop_reason = evt.delta.stop_reason as "end_turn" | "max_tokens" | "stop_sequence" | "tool_use";
435
+ }
436
+ break;
437
+ }
438
+
439
+ case "message_stop":
440
+ break;
441
+
442
+ // OpenAI/Z.AI compatible format (for GLM-5, etc.)
443
+ default: {
444
+ if (event.choices && Array.isArray(event.choices)) {
445
+ const choice = event.choices[0] as { delta?: { content?: string }; finish_reason?: string } | undefined;
446
+ if (choice?.delta?.content) {
447
+ const text = choice.delta.content;
448
+ if (currentTextBlock) {
449
+ currentTextBlock.text += text;
450
+ } else {
451
+ currentTextBlock = { type: "text", text };
452
+ }
453
+ callbacks.onToken?.(text); // Emit in real-time
454
+ if (firstToken) {
455
+ ttft = Date.now() - startTime;
456
+ firstToken = false;
457
+ }
458
+ }
459
+ if (choice?.finish_reason) {
460
+ if (currentTextBlock) {
461
+ currentContent.push(currentTextBlock);
462
+ currentTextBlock = null;
463
+ }
464
+ if (!message) {
465
+ message = {
466
+ id: `msg-${Date.now()}`,
467
+ type: "message",
468
+ role: "assistant",
469
+ content: currentContent,
470
+ model: model,
471
+ stop_reason: (choice.finish_reason === "stop" ? "end_turn" : choice.finish_reason === "length" ? "max_tokens" : "end_turn") as StopReason,
472
+ stop_sequence: null,
473
+ usage: { input_tokens: 0, output_tokens: 0 },
474
+ };
475
+ } else {
476
+ message.stop_reason = (choice.finish_reason === "stop" ? "end_turn" : choice.finish_reason === "length" ? "max_tokens" : "end_turn") as StopReason;
477
+ }
478
+ }
479
+ }
480
+ if (event.usage) {
481
+ const openaiUsage = event.usage as { prompt_tokens?: number; completion_tokens?: number; total_tokens?: number };
482
+ usage.input_tokens = openaiUsage.prompt_tokens || 0;
483
+ usage.output_tokens = openaiUsage.completion_tokens || 0;
484
+ }
485
+ break;
486
+ }
487
+ }
488
+ } catch (err: unknown) {
489
+ // Only rethrow if it's an API error, not a JSON parse error
490
+ if (err instanceof Error && err.message.startsWith("API error:")) {
491
+ throw err;
492
+ }
493
+ if (process.env.DEBUG_API === '1') {
494
+ console.error('\x1b[91m[DEBUG] JSON parse error:', err);
495
+ console.error('\x1b[91m[DEBUG] Error parsing SSE data:', data.substring(0, 200));
496
+ }
497
+ }
498
+ }
499
+ }
500
+ } finally {
501
+ reader.releaseLock();
502
+ }
503
+
504
+ // Handle "No message received" case - this is retryable
505
+ if (!message) {
506
+ if (currentContent.length > 0) {
507
+ message = {
508
+ id: `msg-${Date.now()}`,
509
+ type: "message",
510
+ role: "assistant",
511
+ content: currentContent,
512
+ model: model,
513
+ stop_reason: "end_turn",
514
+ stop_sequence: null,
515
+ usage: { input_tokens: 0, output_tokens: 0 },
516
+ };
517
+ } else {
518
+ // This is a transient error - throw to trigger retry
519
+ throw new Error("No message received from API");
520
+ }
521
+ }
522
+
523
+ return {
524
+ message,
525
+ content: currentContent,
526
+ usage,
527
+ thinkingTokens: totalThinkingTokens,
528
+ ttftMs: ttft,
529
+ };
530
+ }
531
+
532
+ /**
533
+ * Create a streaming message request to Anthropic API
534
+ * Full retry support including stream parsing errors
535
+ */
536
+ export async function createMessageStream(
537
+ messages: Message[],
538
+ options: StreamOptions
539
+ ): Promise<StreamResult> {
540
+ const {
541
+ apiKey,
542
+ model = "claude-sonnet-4-6",
543
+ maxTokens = 4096,
544
+ tools,
545
+ systemPrompt,
546
+ cacheConfig = DEFAULT_CACHE_CONFIG,
547
+ thinking,
548
+ extendedThinking,
549
+ onToken,
550
+ onThinking,
551
+ onRedactedThinking,
552
+ onToolUse,
553
+ onRetryStart,
554
+ signal,
555
+ } = options;
556
+
557
+ const startTime = Date.now();
558
+
559
+ // Build cached messages
560
+ const cachedMessages = buildCachedMessages(messages, cacheConfig);
561
+
562
+ // Build system prompt with cache control
563
+ const cachedSystemPrompt = buildSystemPrompt(systemPrompt, cacheConfig);
564
+
565
+ // Build request
566
+ const request: APIRequest = {
567
+ model,
568
+ max_tokens: maxTokens,
569
+ messages: cachedMessages.map((m) => ({
570
+ role: m.role,
571
+ content: m.content,
572
+ })),
573
+ stream: true,
574
+ };
575
+
576
+ if (cachedSystemPrompt) {
577
+ request.system = cachedSystemPrompt;
578
+ }
579
+
580
+ // Tools will be set after determining API format (for format conversion)
581
+
582
+ // Resolve provider based on model name
583
+ const providerInfo = resolveProvider(model);
584
+
585
+ // Determine API endpoint and headers based on provider
586
+ let apiEndpoint: string;
587
+ let headers: Record<string, string>;
588
+ let apiFormat: "anthropic" | "openai";
589
+
590
+ if (providerInfo) {
591
+ // Use provider-specific configuration
592
+ apiEndpoint = providerInfo.endpoint;
593
+ apiFormat = providerInfo.config.format;
594
+
595
+ if (apiFormat === "anthropic") {
596
+ // Anthropic/MiniMax format
597
+ headers = {
598
+ "Content-Type": "application/json",
599
+ [providerInfo.config.authHeader]: providerInfo.apiKey,
600
+ "anthropic-version": "2023-06-01",
601
+ };
602
+ } else {
603
+ // OpenAI/Zhipu format
604
+ headers = {
605
+ "Content-Type": "application/json",
606
+ [providerInfo.config.authHeader]: `Bearer ${providerInfo.apiKey}`,
607
+ };
608
+ }
609
+ } else {
610
+ // Fallback to environment-based configuration (legacy)
611
+ const baseUrl = process.env.ANTHROPIC_BASE_URL || "https://api.anthropic.com";
612
+ apiEndpoint = `${baseUrl}/v1/messages`;
613
+ apiFormat = "anthropic";
614
+
615
+ headers = {
616
+ "Content-Type": "application/json",
617
+ "x-api-key": apiKey,
618
+ "anthropic-version": "2023-06-01",
619
+ };
620
+ }
621
+
622
+ // Set tools with format conversion if needed
623
+ if (tools && tools.length > 0) {
624
+ if (apiFormat === "openai") {
625
+ // Convert Anthropic-style tools to OpenAI format
626
+ // Cast needed because OpenAI format differs from APITool
627
+ (request as unknown as Record<string, unknown>).tools = convertToolsToOpenAIFormat(tools);
628
+ } else {
629
+ // Keep Anthropic format as-is
630
+ request.tools = tools;
631
+ }
632
+ }
633
+
634
+ const shouldUseExtendedThinking =
635
+ (extendedThinking?.enabled ?? false) ||
636
+ (thinking && thinking.type !== "disabled");
637
+
638
+ if (shouldUseExtendedThinking && supportsExtendedThinking(model)) {
639
+ let budgetTokens: number;
640
+
641
+ if (extendedThinking?.budgetTokens) {
642
+ budgetTokens = extendedThinking.budgetTokens;
643
+ } else if (thinking?.type === "enabled") {
644
+ budgetTokens = thinking.budget_tokens;
645
+ } else {
646
+ const effort = extendedThinking?.effort || "medium";
647
+ budgetTokens = calculateBudgetTokens(
648
+ { enabled: true, effort, modelMultiplier: model.includes("opus") ? 2 : 1 },
649
+ model
650
+ );
651
+ }
652
+
653
+ budgetTokens = Math.max(1024, Math.min(budgetTokens, 100000));
654
+
655
+ request.thinking = { type: "enabled", budget_tokens: budgetTokens };
656
+
657
+ const betaFeatures: string[] = ["extended-thinking-2025-01-24"];
658
+ if (extendedThinking?.interleaved !== false) {
659
+ betaFeatures.push("interleaved-thinking-2025-01-24");
660
+ }
661
+ headers["anthropic-beta"] = betaFeatures.join(",");
662
+ } else if (apiFormat === "anthropic") {
663
+ headers["anthropic-beta"] = "max-tokens-3-5-sonnet-2024-07-15";
664
+ }
665
+
666
+ // Retry options - now covers entire stream parsing
667
+ const retryOptions: RetryOptions = {
668
+ maxRetries: 10,
669
+ baseDelayMs: 1000,
670
+ maxDelayMs: 60000,
671
+ retryableStatusCodes: [429, 500, 502, 503, 504, 529],
672
+ onRetry: (attempt, error, delayMs) => {
673
+ console.log(`\x1b[33mAPI retry ${attempt}/10 after ${delayMs}ms: ${error.message}\x1b[0m`);
674
+ // Notify UI to reset streaming state before retry
675
+ onRetryStart?.();
676
+ // Track provider failure on retry
677
+ const providerName = getProviderForModel(model);
678
+ if (providerName) {
679
+ recordProviderFailure(providerName);
680
+ }
681
+ },
682
+ };
683
+
684
+ // Execute with retry - wraps entire fetch + stream parsing
685
+ // Callbacks are emitted in real-time during streaming
686
+ const result = await withRetry(
687
+ () => executeStreamAttempt(
688
+ request,
689
+ headers,
690
+ apiEndpoint,
691
+ signal,
692
+ model,
693
+ retryOptions.retryableStatusCodes ?? [],
694
+ startTime,
695
+ { onToken, onThinking, onRedactedThinking, onToolUse }
696
+ ),
697
+ retryOptions
698
+ );
699
+
700
+ // Build final message
701
+ const message = result.message!;
702
+ message.content = result.content;
703
+
704
+ // Calculate cost and cache metrics
705
+ const { costUSD, estimatedSavingsUSD } = calculateCost(model, result.usage);
706
+ const cacheMetrics = calculateCacheMetrics(result.usage);
707
+ cacheMetrics.estimatedSavingsUSD = estimatedSavingsUSD;
708
+
709
+ const durationMs = Date.now() - startTime;
710
+
711
+ // Track provider health on success
712
+ const providerName = getProviderForModel(model);
713
+ if (providerName) {
714
+ recordProviderSuccess(providerName, durationMs);
715
+ }
716
+
717
+ return {
718
+ message,
719
+ usage: result.usage,
720
+ cacheMetrics,
721
+ costUSD,
722
+ durationMs,
723
+ ttftMs: result.ttftMs || durationMs,
724
+ thinkingTokens: result.thinkingTokens,
725
+ };
726
+ }
727
+
728
+ // Re-export types
729
+ export type { StreamOptions as StreamOptionsType, StreamResult as StreamResultType };