@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,431 @@
1
+ /**
2
+ * Permission System - Interactive permission prompts
3
+ */
4
+
5
+ import * as readline from "readline";
6
+
7
+ // ============================================
8
+ // TYPES
9
+ // ============================================
10
+
11
+ export type PermissionMode =
12
+ | "default"
13
+ | "acceptEdits"
14
+ | "bypassPermissions"
15
+ | "dontAsk"
16
+ | "interactive"
17
+ | "plan";
18
+
19
+ export type PermissionDecision =
20
+ | "allow"
21
+ | "deny"
22
+ | "allowAlways"
23
+ | "denyAlways";
24
+
25
+ export interface PermissionRequest {
26
+ toolName: string;
27
+ toolInput: Record<string, unknown>;
28
+ riskLevel: "low" | "medium" | "high" | "critical";
29
+ description: string;
30
+ file?: string;
31
+ command?: string;
32
+ }
33
+
34
+ export interface PermissionResult {
35
+ decision: PermissionDecision;
36
+ reason?: string;
37
+ }
38
+
39
+ export interface PermissionCache {
40
+ [key: string]: {
41
+ decision: PermissionDecision;
42
+ timestamp: number;
43
+ };
44
+ }
45
+
46
+ export type PermissionPromptCallback = (
47
+ request: PermissionRequest
48
+ ) => Promise<PermissionResult>;
49
+
50
+ // ============================================
51
+ // RISK LEVEL ASSESSMENT
52
+ // ============================================
53
+
54
+ const TOOL_RISK_LEVELS: Record<string, "low" | "medium" | "high" | "critical"> = {
55
+ // Low risk - read-only, non-destructive
56
+ Read: "low",
57
+ Glob: "low",
58
+ Grep: "low",
59
+ Task: "low",
60
+
61
+ // Medium risk - modifies files but reversible
62
+ Write: "medium",
63
+ Edit: "medium",
64
+ NotebookEdit: "medium",
65
+
66
+ // Bash is assessed dynamically based on command
67
+ // Default to medium, elevated to high/critical by assessRiskLevel
68
+ Bash: "medium",
69
+
70
+ // Critical risk - irreversible operations
71
+ // (handled by input analysis)
72
+ };
73
+
74
+ // Read-only commands that are safe to auto-approve
75
+ const READ_ONLY_COMMANDS = [
76
+ /^date\b/,
77
+ /^ls\b/,
78
+ /^cat\b/,
79
+ /^head\b/,
80
+ /^tail\b/,
81
+ /^echo\b/,
82
+ /^pwd\b/,
83
+ /^whoami\b/,
84
+ /^which\b/,
85
+ /^uname\b/,
86
+ /^hostname\b/,
87
+ /^id\b/,
88
+ /^printenv\b/,
89
+ /^env\b/,
90
+ /^git\s+status\b/,
91
+ /^git\s+log\b/,
92
+ /^git\s+diff\b/,
93
+ /^git\s+branch\b/,
94
+ /^git\s+remote\b/,
95
+ /^git\s+rev-parse\b/,
96
+ /^git\s+show\b/,
97
+ /^npm\s+list\b/,
98
+ /^bun\s+--version\b/,
99
+ /^bun\s+-v\b/,
100
+ /^node\s+--version\b/,
101
+ /^node\s+-v\b/,
102
+ /^python\s+--version\b/,
103
+ /^python3\s+--version\b/,
104
+ /^uv\s+--version\b/,
105
+ /^doppler\s+\w+\s+--help\b/,
106
+ ];
107
+
108
+ const CRITICAL_PATTERNS = [
109
+ /\brm\s+-rf\b/,
110
+ /\brm\s+-r\b/,
111
+ /\brm\s+[^-]/,
112
+ /\bgit\s+push\s+--force\b/,
113
+ /\bgit\s+reset\s+--hard\b/,
114
+ /\bgit\s+clean\s+-fd\b/,
115
+ /\bdrop\b/i,
116
+ /\bdelete\b/i,
117
+ /\btruncate\b/i,
118
+ /\bformat\b/i,
119
+ /\bdd\s+if=/,
120
+ /\bshred\b/,
121
+ /\b:\(\)\{\s*:\|:\s*&\s*\};\s*:\b/, // Fork bomb
122
+ ];
123
+
124
+ /**
125
+ * Assess risk level for a tool operation
126
+ */
127
+ export function assessRiskLevel(
128
+ toolName: string,
129
+ toolInput: Record<string, unknown>
130
+ ): "low" | "medium" | "high" | "critical" {
131
+ // Start with base risk level
132
+ let riskLevel = TOOL_RISK_LEVELS[toolName] ?? "medium";
133
+
134
+ // Check for critical patterns in Bash commands
135
+ if (toolName === "Bash") {
136
+ const command = String(toolInput.command ?? "");
137
+
138
+ for (const pattern of CRITICAL_PATTERNS) {
139
+ if (pattern.test(command)) {
140
+ return "critical";
141
+ }
142
+ }
143
+
144
+ // Elevated commands increase risk
145
+ if (/\bsudo\b/.test(command) || /\bchmod\b/.test(command)) {
146
+ riskLevel = "high";
147
+ }
148
+ }
149
+
150
+ // Write to sensitive files increases risk
151
+ if (toolName === "Write" || toolName === "Edit") {
152
+ const filePath = String(toolInput.file_path ?? toolInput.path ?? "");
153
+
154
+ if (/\.(env|pem|key|secret|credentials)/.test(filePath)) {
155
+ riskLevel = "high";
156
+ }
157
+ if (/\/\.ssh\//.test(filePath) || /\/\.gnupg\//.test(filePath)) {
158
+ riskLevel = "critical";
159
+ }
160
+ }
161
+
162
+ return riskLevel;
163
+ }
164
+
165
+ /**
166
+ * Generate a human-readable description of the tool operation
167
+ */
168
+ export function generateDescription(
169
+ toolName: string,
170
+ toolInput: Record<string, unknown>
171
+ ): string {
172
+ switch (toolName) {
173
+ case "Read":
174
+ return `Read file: ${toolInput.file_path ?? "unknown"}`;
175
+ case "Write":
176
+ return `Write file: ${toolInput.file_path ?? "unknown"} (${String(toolInput.content ?? "").length} chars)`;
177
+ case "Edit":
178
+ return `Edit file: ${toolInput.file_path ?? "unknown"}`;
179
+ case "Bash":
180
+ return `Execute: ${String(toolInput.command ?? "").slice(0, 100)}${String(toolInput.command ?? "").length > 100 ? "..." : ""}`;
181
+ case "Glob":
182
+ return `Find files: ${toolInput.pattern ?? "*"}`;
183
+ case "Grep":
184
+ return `Search: "${toolInput.pattern ?? ""}" in ${toolInput.path ?? "."}`;
185
+ case "Task":
186
+ return `Spawn agent: ${toolInput.subagent_type ?? "unknown"}`;
187
+ default:
188
+ return `Use tool: ${toolName}`;
189
+ }
190
+ }
191
+
192
+ // ============================================
193
+ // PERMISSION MANAGER
194
+ // ============================================
195
+
196
+ export class PermissionManager {
197
+ private cache: PermissionCache = {};
198
+ private cacheTimeout = 5 * 60 * 1000; // 5 minutes
199
+ private promptCallback: PermissionPromptCallback;
200
+ private mode: PermissionMode;
201
+
202
+ constructor(
203
+ mode: PermissionMode = "default",
204
+ promptCallback?: PermissionPromptCallback
205
+ ) {
206
+ this.mode = mode;
207
+ this.promptCallback = promptCallback ?? this.defaultPrompt.bind(this);
208
+ }
209
+
210
+ /**
211
+ * Check if a tool operation is permitted
212
+ */
213
+ async checkPermission(
214
+ toolName: string,
215
+ toolInput: Record<string, unknown>
216
+ ): Promise<PermissionResult> {
217
+ // Bypass mode - always allow
218
+ if (this.mode === "bypassPermissions") {
219
+ return { decision: "allow" };
220
+ }
221
+
222
+ // DontAsk mode - always deny
223
+ if (this.mode === "dontAsk") {
224
+ return { decision: "deny", reason: "Permission mode is dontAsk" };
225
+ }
226
+
227
+ // AcceptEdits mode - allow file operations and non-critical Bash commands
228
+ if (this.mode === "acceptEdits") {
229
+ const fileTools = ["Read", "Write", "Edit", "Glob", "Grep"];
230
+ if (fileTools.includes(toolName)) {
231
+ return { decision: "allow" };
232
+ }
233
+ // Also allow non-critical Bash commands (low/medium risk)
234
+ if (toolName === "Bash") {
235
+ const riskLevel = assessRiskLevel(toolName, toolInput);
236
+ if (riskLevel === "low" || riskLevel === "medium") {
237
+ return { decision: "allow" };
238
+ }
239
+ }
240
+ }
241
+
242
+ // Plan mode - deny all write operations
243
+ if (this.mode === "plan") {
244
+ const readOnlyTools = ["Read", "Glob", "Grep", "Task"];
245
+ if (readOnlyTools.includes(toolName)) {
246
+ return { decision: "allow" };
247
+ }
248
+ return { decision: "deny", reason: "Plan mode - write operations disabled" };
249
+ }
250
+
251
+ // Check cache for "always" decisions
252
+ const cacheKey = this.getCacheKey(toolName, toolInput);
253
+ const cached = this.cache[cacheKey];
254
+
255
+ if (cached && Date.now() - cached.timestamp < this.cacheTimeout) {
256
+ if (cached.decision === "allowAlways") {
257
+ return { decision: "allow", reason: "Previously approved (always)" };
258
+ }
259
+ if (cached.decision === "denyAlways") {
260
+ return { decision: "deny", reason: "Previously denied (always)" };
261
+ }
262
+ }
263
+
264
+ // Assess risk level
265
+ const riskLevel = assessRiskLevel(toolName, toolInput);
266
+ const description = generateDescription(toolName, toolInput);
267
+
268
+ // Create permission request
269
+ const request: PermissionRequest = {
270
+ toolName,
271
+ toolInput,
272
+ riskLevel,
273
+ description,
274
+ file: (toolInput.file_path ?? toolInput.path) as string | undefined,
275
+ command: toolName === "Bash" ? toolInput.command as string : undefined,
276
+ };
277
+
278
+ // Prompt user for interactive/default modes
279
+ if (this.mode === "interactive" || this.mode === "default") {
280
+ const result = await this.promptCallback(request);
281
+
282
+ // Cache "always" decisions
283
+ if (result.decision === "allowAlways" || result.decision === "denyAlways") {
284
+ this.cache[cacheKey] = {
285
+ decision: result.decision,
286
+ timestamp: Date.now(),
287
+ };
288
+ }
289
+
290
+ return result;
291
+ }
292
+
293
+ // Default to allow for unknown modes
294
+ return { decision: "allow" };
295
+ }
296
+
297
+ /**
298
+ * Generate cache key for permission
299
+ */
300
+ private getCacheKey(toolName: string, toolInput: Record<string, unknown>): string {
301
+ // For file operations, key on file path
302
+ if (["Read", "Write", "Edit"].includes(toolName)) {
303
+ return `${toolName}:${toolInput.file_path ?? toolInput.path ?? "unknown"}`;
304
+ }
305
+
306
+ // For bash, key on command (first 100 chars)
307
+ if (toolName === "Bash") {
308
+ const cmd = String(toolInput.command ?? "").slice(0, 100);
309
+ return `${toolName}:${cmd}`;
310
+ }
311
+
312
+ // Default: key on tool name only
313
+ return toolName;
314
+ }
315
+
316
+ /**
317
+ * Default prompt implementation using readline
318
+ */
319
+ private async defaultPrompt(request: PermissionRequest): Promise<PermissionResult> {
320
+ return new Promise((resolve) => {
321
+ const rl = readline.createInterface({
322
+ input: process.stdin,
323
+ output: process.stdout,
324
+ });
325
+
326
+ // Format risk level with color
327
+ const riskColors: Record<string, string> = {
328
+ low: "\x1b[32m", // Green
329
+ medium: "\x1b[33m", // Yellow
330
+ high: "\x1b[31m", // Red
331
+ critical: "\x1b[35m", // Magenta
332
+ };
333
+ const riskColor = riskColors[request.riskLevel] ?? "\x1b[0m";
334
+ const reset = "\x1b[0m";
335
+
336
+ console.log("");
337
+ console.log(`\x1b[36m━━━ Permission Required ━━━\x1b[0m`);
338
+ console.log(`Tool: \x1b[1m${request.toolName}\x1b[0m`);
339
+ console.log(`Risk: ${riskColor}${request.riskLevel.toUpperCase()}${reset}`);
340
+ console.log(`Action: ${request.description}`);
341
+
342
+ if (request.file) {
343
+ console.log(`File: ${request.file}`);
344
+ }
345
+ if (request.command) {
346
+ console.log(`Command: ${request.command.slice(0, 200)}${request.command.length > 200 ? "..." : ""}`);
347
+ }
348
+
349
+ console.log("");
350
+
351
+ const options = "[y]es / [n]o / [a]lways / [d]eny always";
352
+ rl.question(`Allow? ${options}: `, (answer) => {
353
+ rl.close();
354
+
355
+ const input = answer.trim().toLowerCase();
356
+
357
+ switch (input) {
358
+ case "y":
359
+ case "yes":
360
+ resolve({ decision: "allow" });
361
+ break;
362
+ case "a":
363
+ case "always":
364
+ resolve({ decision: "allowAlways" });
365
+ break;
366
+ case "d":
367
+ case "deny":
368
+ case "deny always":
369
+ resolve({ decision: "denyAlways" });
370
+ break;
371
+ case "n":
372
+ case "no":
373
+ default:
374
+ resolve({ decision: "deny" });
375
+ break;
376
+ }
377
+ });
378
+ });
379
+ }
380
+
381
+ /**
382
+ * Clear permission cache
383
+ */
384
+ clearCache(): void {
385
+ this.cache = {};
386
+ }
387
+
388
+ /**
389
+ * Set permission mode
390
+ */
391
+ setMode(mode: PermissionMode): void {
392
+ this.mode = mode;
393
+ // Clear cache when mode changes
394
+ this.clearCache();
395
+ }
396
+ }
397
+
398
+ // ============================================
399
+ // PERMISSION CATEGORIES
400
+ // ============================================
401
+
402
+ /**
403
+ * Tool categories for permission decisions
404
+ */
405
+ export const TOOL_CATEGORIES = {
406
+ readOnly: ["Read", "Glob", "Grep", "Task"],
407
+ fileEdit: ["Write", "Edit", "NotebookEdit"],
408
+ system: ["Bash"],
409
+ network: [], // Future: HTTP requests, etc.
410
+ } as const;
411
+
412
+ /**
413
+ * Check if tool is read-only
414
+ */
415
+ export function isReadOnlyTool(toolName: string): boolean {
416
+ return TOOL_CATEGORIES.readOnly.includes(toolName as typeof TOOL_CATEGORIES.readOnly[number]);
417
+ }
418
+
419
+ /**
420
+ * Check if tool modifies files
421
+ */
422
+ export function isFileEditTool(toolName: string): boolean {
423
+ return TOOL_CATEGORIES.fileEdit.includes(toolName as typeof TOOL_CATEGORIES.fileEdit[number]);
424
+ }
425
+
426
+ /**
427
+ * Check if tool executes system commands
428
+ */
429
+ export function isSystemTool(toolName: string): boolean {
430
+ return TOOL_CATEGORIES.system.includes(toolName as typeof TOOL_CATEGORIES.system[number]);
431
+ }
@@ -0,0 +1,230 @@
1
+ # Provider System
2
+
3
+ Multi-provider architecture for Coder CLI supporting multiple LLM backends.
4
+
5
+ ## Supported Providers
6
+
7
+ | Provider | Models | Format | Endpoint |
8
+ |----------|--------|--------|----------|
9
+ | **Zhipu (Z.AI)** | GLM-5, GLM-4.7, GLM-4.6, GLM-4.5V, GLM-4.5, GLM-4.5-air | OpenAI | `https://api.z.ai/api/coding/paas/v4` |
10
+ | **MiniMax** | MiniMax-M2.5 | Anthropic | `https://api.minimax.io/anthropic` |
11
+ | **OpenAI** | GPT-4, GPT-4-turbo | OpenAI | `https://api.openai.com/v1` |
12
+ | **Anthropic** | Claude Opus 4.6, Sonnet 4.6 | Anthropic | *Not implemented (stub)* |
13
+
14
+ ## Z.AI Endpoints
15
+
16
+ Z.AI provides **two different endpoints**:
17
+
18
+ | Endpoint | Format | Auth | Use Case |
19
+ |----------|--------|------|----------|
20
+ | `https://api.z.ai/api/coding/paas/v4` | OpenAI | `Z_AI_API_KEY` | **Coding plan** (default) |
21
+ | `https://api.z.ai/api/anthropic` | Anthropic | `ANTHROPIC_AUTH_TOKEN` | Anthropic-compatible |
22
+
23
+ Our implementation uses the **coding plan endpoint** with shared quotas.
24
+
25
+ ### GLM Models (Coding Plan - Shared Quota)
26
+
27
+ | Model | Context | Max Output | Vision | Thinking | Quota |
28
+ |-------|---------|------------|--------|----------|-------|
29
+ | **GLM-5** | 200K | 128K | Yes | Yes | 3x peak, 2x off-peak |
30
+ | **GLM-4.7** | 128K | 8K | Yes | Yes | 1x |
31
+ | **GLM-4.6** | 128K | 8K | Yes | Yes | 1x |
32
+ | **GLM-4.5V** | 128K | 4K | Yes | No | 1x |
33
+ | **GLM-4.5** | 128K | 4K | No | No | 1x |
34
+ | **GLM-4.5-Air** | 128K | 4K | No | No | 1x (fast/cheap) |
35
+
36
+ ## Configuration
37
+
38
+ ### Environment Variables
39
+
40
+ ```bash
41
+ # Z.AI / GLM (Coding Plan)
42
+ Z_AI_API_KEY=xxx # Single key
43
+ Z_AI_API_KEYS='["key1","key2"]' # Rolling keys (JSON array)
44
+ ZHIPU_BASE_URL=https://api.z.ai/api/coding/paas/v4 # Optional override
45
+
46
+ # MiniMax
47
+ MINIMAX_API_KEY=xxx
48
+ MINIMAX_BASE_URL=https://api.minimax.io/anthropic # Optional: use minimaxi.com for China
49
+
50
+ # OpenAI (Future)
51
+ OPENAI_API_KEY=xxx
52
+ ```
53
+
54
+ ### Doppler Configuration
55
+
56
+ Add keys to your Doppler project:
57
+
58
+ ```bash
59
+ doppler secrets set Z_AI_API_KEY=xxx
60
+ doppler secrets set Z_AI_API_KEYS='["key1","key2"]' # For rolling keys
61
+ doppler secrets set MINIMAX_API_KEY=xxx
62
+ ```
63
+
64
+ ## Usage
65
+
66
+ ### Model Selection
67
+
68
+ ```bash
69
+ # Use GLM-5 (Zhipu)
70
+ coder --model glm-5
71
+
72
+ # Use MiniMax M2.5
73
+ coder --model minimax-m2.5
74
+
75
+ # Use GLM-4.5-air (fast/cheap)
76
+ coder --model glm-4.5-air
77
+ ```
78
+
79
+ ### Model Aliases
80
+
81
+ ```typescript
82
+ // In code
83
+ import { MODEL_ALIASES } from "@ebowwa/coder";
84
+
85
+ MODEL_ALIASES.glm // → "glm-5"
86
+ MODEL_ALIASES.glm4 // → "glm-4.5-air"
87
+ MODEL_ALIASES.minimax // → "minimax-m2.5"
88
+ MODEL_ALIASES.m25 // → "minimax-m2.5"
89
+ MODEL_ALIASES.fast // → "glm-4.5-air"
90
+ ```
91
+
92
+ ### Provider Resolution
93
+
94
+ ```typescript
95
+ import { resolveProvider, getProviderForModel } from "@ebowwa/coder";
96
+
97
+ // Detect provider from model name
98
+ const provider = getProviderForModel("glm-5"); // → "zhipu"
99
+
100
+ // Resolve full provider info
101
+ const resolved = resolveProvider("glm-5");
102
+ // {
103
+ // config: ProviderConfig,
104
+ // apiKey: string,
105
+ // endpoint: string,
106
+ // model: string
107
+ // }
108
+ ```
109
+
110
+ ### Health Tracking
111
+
112
+ ```typescript
113
+ import {
114
+ isProviderHealthy,
115
+ getHealthyProviders,
116
+ recordProviderSuccess,
117
+ recordProviderFailure,
118
+ } from "@ebowwa/coder";
119
+
120
+ // Check if provider is healthy
121
+ if (isProviderHealthy("zhipu")) {
122
+ // Use zhipu
123
+ }
124
+
125
+ // Get all healthy providers
126
+ const healthy = getHealthyProviders(); // ["zhipu", "minimax"]
127
+
128
+ // Track success (auto-called by API client)
129
+ recordProviderSuccess("zhipu", 1500); // 1.5s latency
130
+
131
+ // Track failure (auto-called on retry)
132
+ recordProviderFailure("zhipu");
133
+ ```
134
+
135
+ ## Architecture
136
+
137
+ ```
138
+ ┌─────────────────────────────────────────────────────┐
139
+ │ Model Request │
140
+ │ (model: "glm-5") │
141
+ └─────────────────────────────────────────────────────┘
142
+
143
+
144
+ ┌─────────────────────────┐
145
+ │ resolveProvider() │
146
+ │ - Detect from name │
147
+ │ - Load API key │
148
+ │ - Build endpoint │
149
+ └─────────────────────────┘
150
+
151
+ ┌───────────┴───────────┐
152
+ │ │
153
+ ▼ ▼
154
+ ┌───────────────┐ ┌───────────────┐
155
+ │ Zhipu (Z.AI) │ │ MiniMax │
156
+ │ OpenAI format │ │ Anthropic fmt │
157
+ │ /chat/ │ │ /v1/messages │
158
+ │ completions │ │ │
159
+ └───────────────┘ └───────────────┘
160
+ │ │
161
+ └───────────┬───────────┘
162
+
163
+ ┌─────────────────────────┐
164
+ │ Health Tracking │
165
+ │ - Latency metrics │
166
+ │ - Failure backoff │
167
+ │ - Rolling key rotation │
168
+ └─────────────────────────┘
169
+ ```
170
+
171
+ ## Rolling Keys
172
+
173
+ The provider system supports multiple API keys with round-robin rotation:
174
+
175
+ ```bash
176
+ # Set multiple keys as JSON array
177
+ Z_AI_API_KEYS='["key1","key2","key3"]'
178
+ ```
179
+
180
+ Features:
181
+ - **Round-robin rotation** - Cycles through keys on each request
182
+ - **Exponential backoff** - Keys that fail are temporarily disabled
183
+ - **Health tracking** - Keys are tracked per-provider
184
+
185
+ ## Fallback Chain
186
+
187
+ Default fallback order:
188
+ 1. `zhipu` (Z.AI / GLM)
189
+ 2. `minimax` (MiniMax)
190
+
191
+ Configure via environment:
192
+ ```bash
193
+ MODEL_FALLBACK_CHAIN='["zhipu","minimax","openai"]'
194
+ ```
195
+
196
+ ## Adding New Providers
197
+
198
+ 1. Add provider config to `providers/index.ts`:
199
+ ```typescript
200
+ PROVIDERS.newprovider = {
201
+ name: "newprovider",
202
+ displayName: "New Provider",
203
+ endpoint: "https://api.newprovider.com/v1",
204
+ authHeader: "Authorization",
205
+ apiKeyEnv: ["NEWPROVIDER_API_KEY"],
206
+ format: "openai", // or "anthropic"
207
+ defaultModel: "newprovider-1",
208
+ models: ["newprovider-1", "newprovider-2"],
209
+ supportsStreaming: true,
210
+ supportsToolCalling: true,
211
+ supportsVision: true,
212
+ supportsThinking: false,
213
+ };
214
+ ```
215
+
216
+ 2. Add model to `models.ts`:
217
+ ```typescript
218
+ "newprovider-1": {
219
+ id: "newprovider-1",
220
+ name: "NP-1",
221
+ fullName: "NewProvider 1",
222
+ provider: "newprovider",
223
+ // ...
224
+ }
225
+ ```
226
+
227
+ 3. Add to fallback chain (optional):
228
+ ```typescript
229
+ DEFAULT_ROUTING_CONFIG.fallbackChain.push("newprovider");
230
+ ```