orquesta-cli 0.1.12

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 (851) hide show
  1. package/.eslintrc.json +26 -0
  2. package/.prettierrc.json +10 -0
  3. package/CLAUDE.md +199 -0
  4. package/LICENSE +21 -0
  5. package/README.md +280 -0
  6. package/SECURITY.md +290 -0
  7. package/TEST_LOCAL.md +245 -0
  8. package/dist/agents/base/base-agent.d.ts +38 -0
  9. package/dist/agents/base/base-agent.d.ts.map +1 -0
  10. package/dist/agents/base/base-agent.js +69 -0
  11. package/dist/agents/base/base-agent.js.map +1 -0
  12. package/dist/agents/docs-search/index.d.ts +33 -0
  13. package/dist/agents/docs-search/index.d.ts.map +1 -0
  14. package/dist/agents/docs-search/index.js +244 -0
  15. package/dist/agents/docs-search/index.js.map +1 -0
  16. package/dist/agents/index.d.ts +4 -0
  17. package/dist/agents/index.d.ts.map +1 -0
  18. package/dist/agents/index.js +4 -0
  19. package/dist/agents/index.js.map +1 -0
  20. package/dist/agents/planner/index.d.ts +17 -0
  21. package/dist/agents/planner/index.d.ts.map +1 -0
  22. package/dist/agents/planner/index.js +250 -0
  23. package/dist/agents/planner/index.js.map +1 -0
  24. package/dist/cli.d.ts +3 -0
  25. package/dist/cli.d.ts.map +1 -0
  26. package/dist/cli.js +144 -0
  27. package/dist/cli.js.map +1 -0
  28. package/dist/constants.d.ts +8 -0
  29. package/dist/constants.d.ts.map +1 -0
  30. package/dist/constants.js +10 -0
  31. package/dist/constants.js.map +1 -0
  32. package/dist/core/compact/compact-manager.d.ts +22 -0
  33. package/dist/core/compact/compact-manager.d.ts.map +1 -0
  34. package/dist/core/compact/compact-manager.js +75 -0
  35. package/dist/core/compact/compact-manager.js.map +1 -0
  36. package/dist/core/compact/compact-prompts.d.ts +11 -0
  37. package/dist/core/compact/compact-prompts.d.ts.map +1 -0
  38. package/dist/core/compact/compact-prompts.js +90 -0
  39. package/dist/core/compact/compact-prompts.js.map +1 -0
  40. package/dist/core/compact/context-tracker.d.ts +28 -0
  41. package/dist/core/compact/context-tracker.d.ts.map +1 -0
  42. package/dist/core/compact/context-tracker.js +71 -0
  43. package/dist/core/compact/context-tracker.js.map +1 -0
  44. package/dist/core/compact/index.d.ts +4 -0
  45. package/dist/core/compact/index.d.ts.map +1 -0
  46. package/dist/core/compact/index.js +4 -0
  47. package/dist/core/compact/index.js.map +1 -0
  48. package/dist/core/config/config-manager.d.ts +44 -0
  49. package/dist/core/config/config-manager.d.ts.map +1 -0
  50. package/dist/core/config/config-manager.js +259 -0
  51. package/dist/core/config/config-manager.js.map +1 -0
  52. package/dist/core/config/index.d.ts +2 -0
  53. package/dist/core/config/index.d.ts.map +1 -0
  54. package/dist/core/config/index.js +2 -0
  55. package/dist/core/config/index.js.map +1 -0
  56. package/dist/core/docs-manager.d.ts +46 -0
  57. package/dist/core/docs-manager.d.ts.map +1 -0
  58. package/dist/core/docs-manager.js +475 -0
  59. package/dist/core/docs-manager.js.map +1 -0
  60. package/dist/core/git-auto-updater.d.ts +58 -0
  61. package/dist/core/git-auto-updater.d.ts.map +1 -0
  62. package/dist/core/git-auto-updater.js +374 -0
  63. package/dist/core/git-auto-updater.js.map +1 -0
  64. package/dist/core/llm/index.d.ts +2 -0
  65. package/dist/core/llm/index.d.ts.map +1 -0
  66. package/dist/core/llm/index.js +2 -0
  67. package/dist/core/llm/index.js.map +1 -0
  68. package/dist/core/llm/llm-client.d.ts +97 -0
  69. package/dist/core/llm/llm-client.d.ts.map +1 -0
  70. package/dist/core/llm/llm-client.js +1000 -0
  71. package/dist/core/llm/llm-client.js.map +1 -0
  72. package/dist/core/session/index.d.ts +2 -0
  73. package/dist/core/session/index.d.ts.map +1 -0
  74. package/dist/core/session/index.js +2 -0
  75. package/dist/core/session/index.js.map +1 -0
  76. package/dist/core/session/session-manager.d.ts +71 -0
  77. package/dist/core/session/session-manager.d.ts.map +1 -0
  78. package/dist/core/session/session-manager.js +250 -0
  79. package/dist/core/session/session-manager.js.map +1 -0
  80. package/dist/core/slash-command-handler.d.ts +31 -0
  81. package/dist/core/slash-command-handler.d.ts.map +1 -0
  82. package/dist/core/slash-command-handler.js +302 -0
  83. package/dist/core/slash-command-handler.js.map +1 -0
  84. package/dist/core/usage-tracker.d.ts +70 -0
  85. package/dist/core/usage-tracker.d.ts.map +1 -0
  86. package/dist/core/usage-tracker.js +251 -0
  87. package/dist/core/usage-tracker.js.map +1 -0
  88. package/dist/errors/base.d.ts +22 -0
  89. package/dist/errors/base.d.ts.map +1 -0
  90. package/dist/errors/base.js +43 -0
  91. package/dist/errors/base.js.map +1 -0
  92. package/dist/errors/file.d.ts +31 -0
  93. package/dist/errors/file.d.ts.map +1 -0
  94. package/dist/errors/file.js +110 -0
  95. package/dist/errors/file.js.map +1 -0
  96. package/dist/errors/index.d.ts +10 -0
  97. package/dist/errors/index.d.ts.map +1 -0
  98. package/dist/errors/index.js +41 -0
  99. package/dist/errors/index.js.map +1 -0
  100. package/dist/errors/llm.d.ts +26 -0
  101. package/dist/errors/llm.d.ts.map +1 -0
  102. package/dist/errors/llm.js +86 -0
  103. package/dist/errors/llm.js.map +1 -0
  104. package/dist/errors/network.d.ts +19 -0
  105. package/dist/errors/network.d.ts.map +1 -0
  106. package/dist/errors/network.js +82 -0
  107. package/dist/errors/network.js.map +1 -0
  108. package/dist/errors/validation.d.ts +19 -0
  109. package/dist/errors/validation.d.ts.map +1 -0
  110. package/dist/errors/validation.js +62 -0
  111. package/dist/errors/validation.js.map +1 -0
  112. package/dist/eval/eval-runner.d.ts +24 -0
  113. package/dist/eval/eval-runner.d.ts.map +1 -0
  114. package/dist/eval/eval-runner.js +309 -0
  115. package/dist/eval/eval-runner.js.map +1 -0
  116. package/dist/eval/index.d.ts +3 -0
  117. package/dist/eval/index.d.ts.map +1 -0
  118. package/dist/eval/index.js +3 -0
  119. package/dist/eval/index.js.map +1 -0
  120. package/dist/eval/types.d.ts +77 -0
  121. package/dist/eval/types.d.ts.map +1 -0
  122. package/dist/eval/types.js +2 -0
  123. package/dist/eval/types.js.map +1 -0
  124. package/dist/index.d.ts +4 -0
  125. package/dist/index.d.ts.map +1 -0
  126. package/dist/index.js +6 -0
  127. package/dist/index.js.map +1 -0
  128. package/dist/orchestration/index.d.ts +4 -0
  129. package/dist/orchestration/index.d.ts.map +1 -0
  130. package/dist/orchestration/index.js +3 -0
  131. package/dist/orchestration/index.js.map +1 -0
  132. package/dist/orchestration/plan-executor.d.ts +28 -0
  133. package/dist/orchestration/plan-executor.d.ts.map +1 -0
  134. package/dist/orchestration/plan-executor.js +382 -0
  135. package/dist/orchestration/plan-executor.js.map +1 -0
  136. package/dist/orchestration/types.d.ts +66 -0
  137. package/dist/orchestration/types.d.ts.map +1 -0
  138. package/dist/orchestration/types.js +2 -0
  139. package/dist/orchestration/types.js.map +1 -0
  140. package/dist/orchestration/utils.d.ts +13 -0
  141. package/dist/orchestration/utils.d.ts.map +1 -0
  142. package/dist/orchestration/utils.js +78 -0
  143. package/dist/orchestration/utils.js.map +1 -0
  144. package/dist/orquesta/connection.d.ts +35 -0
  145. package/dist/orquesta/connection.d.ts.map +1 -0
  146. package/dist/orquesta/connection.js +189 -0
  147. package/dist/orquesta/connection.js.map +1 -0
  148. package/dist/prompts/agents/docs-search-decision.d.ts +6 -0
  149. package/dist/prompts/agents/docs-search-decision.d.ts.map +1 -0
  150. package/dist/prompts/agents/docs-search-decision.js +46 -0
  151. package/dist/prompts/agents/docs-search-decision.js.map +1 -0
  152. package/dist/prompts/agents/docs-search.d.ts +4 -0
  153. package/dist/prompts/agents/docs-search.d.ts.map +1 -0
  154. package/dist/prompts/agents/docs-search.js +70 -0
  155. package/dist/prompts/agents/docs-search.js.map +1 -0
  156. package/dist/prompts/agents/planning.d.ts +4 -0
  157. package/dist/prompts/agents/planning.d.ts.map +1 -0
  158. package/dist/prompts/agents/planning.js +119 -0
  159. package/dist/prompts/agents/planning.js.map +1 -0
  160. package/dist/prompts/index.d.ts +10 -0
  161. package/dist/prompts/index.d.ts.map +1 -0
  162. package/dist/prompts/index.js +10 -0
  163. package/dist/prompts/index.js.map +1 -0
  164. package/dist/prompts/shared/codebase-rules.d.ts +4 -0
  165. package/dist/prompts/shared/codebase-rules.d.ts.map +1 -0
  166. package/dist/prompts/shared/codebase-rules.js +16 -0
  167. package/dist/prompts/shared/codebase-rules.js.map +1 -0
  168. package/dist/prompts/shared/git-rules.d.ts +2 -0
  169. package/dist/prompts/shared/git-rules.d.ts.map +1 -0
  170. package/dist/prompts/shared/git-rules.js +87 -0
  171. package/dist/prompts/shared/git-rules.js.map +1 -0
  172. package/dist/prompts/shared/language-rules.d.ts +4 -0
  173. package/dist/prompts/shared/language-rules.d.ts.map +1 -0
  174. package/dist/prompts/shared/language-rules.js +22 -0
  175. package/dist/prompts/shared/language-rules.js.map +1 -0
  176. package/dist/prompts/shared/tool-usage.d.ts +12 -0
  177. package/dist/prompts/shared/tool-usage.d.ts.map +1 -0
  178. package/dist/prompts/shared/tool-usage.js +51 -0
  179. package/dist/prompts/shared/tool-usage.js.map +1 -0
  180. package/dist/prompts/system/compact.d.ts +3 -0
  181. package/dist/prompts/system/compact.d.ts.map +1 -0
  182. package/dist/prompts/system/compact.js +73 -0
  183. package/dist/prompts/system/compact.js.map +1 -0
  184. package/dist/prompts/system/plan-execute.d.ts +3 -0
  185. package/dist/prompts/system/plan-execute.d.ts.map +1 -0
  186. package/dist/prompts/system/plan-execute.js +83 -0
  187. package/dist/prompts/system/plan-execute.js.map +1 -0
  188. package/dist/tools/browser/browser-client.d.ts +107 -0
  189. package/dist/tools/browser/browser-client.d.ts.map +1 -0
  190. package/dist/tools/browser/browser-client.js +958 -0
  191. package/dist/tools/browser/browser-client.js.map +1 -0
  192. package/dist/tools/browser/browser-tools.d.ts +17 -0
  193. package/dist/tools/browser/browser-tools.d.ts.map +1 -0
  194. package/dist/tools/browser/browser-tools.js +972 -0
  195. package/dist/tools/browser/browser-tools.js.map +1 -0
  196. package/dist/tools/browser/index.d.ts +7 -0
  197. package/dist/tools/browser/index.d.ts.map +1 -0
  198. package/dist/tools/browser/index.js +17 -0
  199. package/dist/tools/browser/index.js.map +1 -0
  200. package/dist/tools/index.d.ts +4 -0
  201. package/dist/tools/index.d.ts.map +1 -0
  202. package/dist/tools/index.js +4 -0
  203. package/dist/tools/index.js.map +1 -0
  204. package/dist/tools/llm/agents/docs-search-tools.d.ts +17 -0
  205. package/dist/tools/llm/agents/docs-search-tools.d.ts.map +1 -0
  206. package/dist/tools/llm/agents/docs-search-tools.js +265 -0
  207. package/dist/tools/llm/agents/docs-search-tools.js.map +1 -0
  208. package/dist/tools/llm/agents/index.d.ts +4 -0
  209. package/dist/tools/llm/agents/index.d.ts.map +1 -0
  210. package/dist/tools/llm/agents/index.js +3 -0
  211. package/dist/tools/llm/agents/index.js.map +1 -0
  212. package/dist/tools/llm/index.d.ts +3 -0
  213. package/dist/tools/llm/index.d.ts.map +1 -0
  214. package/dist/tools/llm/index.js +3 -0
  215. package/dist/tools/llm/index.js.map +1 -0
  216. package/dist/tools/llm/simple/ask-user-tool.d.ts +5 -0
  217. package/dist/tools/llm/simple/ask-user-tool.d.ts.map +1 -0
  218. package/dist/tools/llm/simple/ask-user-tool.js +7 -0
  219. package/dist/tools/llm/simple/ask-user-tool.js.map +1 -0
  220. package/dist/tools/llm/simple/background-bash-tool.d.ts +30 -0
  221. package/dist/tools/llm/simple/background-bash-tool.d.ts.map +1 -0
  222. package/dist/tools/llm/simple/background-bash-tool.js +323 -0
  223. package/dist/tools/llm/simple/background-bash-tool.js.map +1 -0
  224. package/dist/tools/llm/simple/background-powershell-tool.d.ts +30 -0
  225. package/dist/tools/llm/simple/background-powershell-tool.d.ts.map +1 -0
  226. package/dist/tools/llm/simple/background-powershell-tool.js +305 -0
  227. package/dist/tools/llm/simple/background-powershell-tool.js.map +1 -0
  228. package/dist/tools/llm/simple/bash-tool.d.ts +4 -0
  229. package/dist/tools/llm/simple/bash-tool.d.ts.map +1 -0
  230. package/dist/tools/llm/simple/bash-tool.js +178 -0
  231. package/dist/tools/llm/simple/bash-tool.js.map +1 -0
  232. package/dist/tools/llm/simple/docs-search-agent-tool.d.ts +6 -0
  233. package/dist/tools/llm/simple/docs-search-agent-tool.d.ts.map +1 -0
  234. package/dist/tools/llm/simple/docs-search-agent-tool.js +104 -0
  235. package/dist/tools/llm/simple/docs-search-agent-tool.js.map +1 -0
  236. package/dist/tools/llm/simple/file-tools.d.ts +13 -0
  237. package/dist/tools/llm/simple/file-tools.d.ts.map +1 -0
  238. package/dist/tools/llm/simple/file-tools.js +785 -0
  239. package/dist/tools/llm/simple/file-tools.js.map +1 -0
  240. package/dist/tools/llm/simple/final-response-tool.d.ts +12 -0
  241. package/dist/tools/llm/simple/final-response-tool.d.ts.map +1 -0
  242. package/dist/tools/llm/simple/final-response-tool.js +107 -0
  243. package/dist/tools/llm/simple/final-response-tool.js.map +1 -0
  244. package/dist/tools/llm/simple/index.d.ts +11 -0
  245. package/dist/tools/llm/simple/index.d.ts.map +1 -0
  246. package/dist/tools/llm/simple/index.js +20 -0
  247. package/dist/tools/llm/simple/index.js.map +1 -0
  248. package/dist/tools/llm/simple/planning-tools.d.ts +5 -0
  249. package/dist/tools/llm/simple/planning-tools.d.ts.map +1 -0
  250. package/dist/tools/llm/simple/planning-tools.js +117 -0
  251. package/dist/tools/llm/simple/planning-tools.js.map +1 -0
  252. package/dist/tools/llm/simple/powershell-tool.d.ts +4 -0
  253. package/dist/tools/llm/simple/powershell-tool.d.ts.map +1 -0
  254. package/dist/tools/llm/simple/powershell-tool.js +178 -0
  255. package/dist/tools/llm/simple/powershell-tool.js.map +1 -0
  256. package/dist/tools/llm/simple/simple-tool-executor.d.ts +38 -0
  257. package/dist/tools/llm/simple/simple-tool-executor.d.ts.map +1 -0
  258. package/dist/tools/llm/simple/simple-tool-executor.js +134 -0
  259. package/dist/tools/llm/simple/simple-tool-executor.js.map +1 -0
  260. package/dist/tools/llm/simple/todo-tools.d.ts +15 -0
  261. package/dist/tools/llm/simple/todo-tools.d.ts.map +1 -0
  262. package/dist/tools/llm/simple/todo-tools.js +145 -0
  263. package/dist/tools/llm/simple/todo-tools.js.map +1 -0
  264. package/dist/tools/llm/simple/user-interaction-tools.d.ts +22 -0
  265. package/dist/tools/llm/simple/user-interaction-tools.d.ts.map +1 -0
  266. package/dist/tools/llm/simple/user-interaction-tools.js +168 -0
  267. package/dist/tools/llm/simple/user-interaction-tools.js.map +1 -0
  268. package/dist/tools/office/common/constants.d.ts +194 -0
  269. package/dist/tools/office/common/constants.d.ts.map +1 -0
  270. package/dist/tools/office/common/constants.js +169 -0
  271. package/dist/tools/office/common/constants.js.map +1 -0
  272. package/dist/tools/office/common/index.d.ts +4 -0
  273. package/dist/tools/office/common/index.d.ts.map +1 -0
  274. package/dist/tools/office/common/index.js +3 -0
  275. package/dist/tools/office/common/index.js.map +1 -0
  276. package/dist/tools/office/common/types.d.ts +82 -0
  277. package/dist/tools/office/common/types.d.ts.map +1 -0
  278. package/dist/tools/office/common/types.js +2 -0
  279. package/dist/tools/office/common/types.js.map +1 -0
  280. package/dist/tools/office/common/utils.d.ts +14 -0
  281. package/dist/tools/office/common/utils.d.ts.map +1 -0
  282. package/dist/tools/office/common/utils.js +58 -0
  283. package/dist/tools/office/common/utils.js.map +1 -0
  284. package/dist/tools/office/excel-client.d.ts +123 -0
  285. package/dist/tools/office/excel-client.d.ts.map +1 -0
  286. package/dist/tools/office/excel-client.js +1037 -0
  287. package/dist/tools/office/excel-client.js.map +1 -0
  288. package/dist/tools/office/excel-tools/cells.d.ts +10 -0
  289. package/dist/tools/office/excel-tools/cells.d.ts.map +1 -0
  290. package/dist/tools/office/excel-tools/cells.js +279 -0
  291. package/dist/tools/office/excel-tools/cells.js.map +1 -0
  292. package/dist/tools/office/excel-tools/charts.d.ts +6 -0
  293. package/dist/tools/office/excel-tools/charts.d.ts.map +1 -0
  294. package/dist/tools/office/excel-tools/charts.js +124 -0
  295. package/dist/tools/office/excel-tools/charts.js.map +1 -0
  296. package/dist/tools/office/excel-tools/comments.d.ts +6 -0
  297. package/dist/tools/office/excel-tools/comments.d.ts.map +1 -0
  298. package/dist/tools/office/excel-tools/comments.js +114 -0
  299. package/dist/tools/office/excel-tools/comments.js.map +1 -0
  300. package/dist/tools/office/excel-tools/data-ops.d.ts +10 -0
  301. package/dist/tools/office/excel-tools/data-ops.d.ts.map +1 -0
  302. package/dist/tools/office/excel-tools/data-ops.js +266 -0
  303. package/dist/tools/office/excel-tools/data-ops.js.map +1 -0
  304. package/dist/tools/office/excel-tools/export.d.ts +5 -0
  305. package/dist/tools/office/excel-tools/export.d.ts.map +1 -0
  306. package/dist/tools/office/excel-tools/export.js +75 -0
  307. package/dist/tools/office/excel-tools/export.js.map +1 -0
  308. package/dist/tools/office/excel-tools/formatting.d.ts +10 -0
  309. package/dist/tools/office/excel-tools/formatting.d.ts.map +1 -0
  310. package/dist/tools/office/excel-tools/formatting.js +276 -0
  311. package/dist/tools/office/excel-tools/formatting.js.map +1 -0
  312. package/dist/tools/office/excel-tools/index.d.ts +16 -0
  313. package/dist/tools/office/excel-tools/index.d.ts.map +1 -0
  314. package/dist/tools/office/excel-tools/index.js +42 -0
  315. package/dist/tools/office/excel-tools/index.js.map +1 -0
  316. package/dist/tools/office/excel-tools/launch.d.ts +10 -0
  317. package/dist/tools/office/excel-tools/launch.d.ts.map +1 -0
  318. package/dist/tools/office/excel-tools/launch.js +248 -0
  319. package/dist/tools/office/excel-tools/launch.js.map +1 -0
  320. package/dist/tools/office/excel-tools/media.d.ts +5 -0
  321. package/dist/tools/office/excel-tools/media.d.ts.map +1 -0
  322. package/dist/tools/office/excel-tools/media.js +84 -0
  323. package/dist/tools/office/excel-tools/media.js.map +1 -0
  324. package/dist/tools/office/excel-tools/named-ranges.d.ts +6 -0
  325. package/dist/tools/office/excel-tools/named-ranges.d.ts.map +1 -0
  326. package/dist/tools/office/excel-tools/named-ranges.js +113 -0
  327. package/dist/tools/office/excel-tools/named-ranges.js.map +1 -0
  328. package/dist/tools/office/excel-tools/protection.d.ts +5 -0
  329. package/dist/tools/office/excel-tools/protection.d.ts.map +1 -0
  330. package/dist/tools/office/excel-tools/protection.js +75 -0
  331. package/dist/tools/office/excel-tools/protection.js.map +1 -0
  332. package/dist/tools/office/excel-tools/rows-columns.d.ts +11 -0
  333. package/dist/tools/office/excel-tools/rows-columns.d.ts.map +1 -0
  334. package/dist/tools/office/excel-tools/rows-columns.js +293 -0
  335. package/dist/tools/office/excel-tools/rows-columns.js.map +1 -0
  336. package/dist/tools/office/excel-tools/sheets.d.ts +8 -0
  337. package/dist/tools/office/excel-tools/sheets.d.ts.map +1 -0
  338. package/dist/tools/office/excel-tools/sheets.js +177 -0
  339. package/dist/tools/office/excel-tools/sheets.js.map +1 -0
  340. package/dist/tools/office/excel-tools/validation.d.ts +7 -0
  341. package/dist/tools/office/excel-tools/validation.d.ts.map +1 -0
  342. package/dist/tools/office/excel-tools/validation.js +175 -0
  343. package/dist/tools/office/excel-tools/validation.js.map +1 -0
  344. package/dist/tools/office/excel-tools.d.ts +3 -0
  345. package/dist/tools/office/excel-tools.d.ts.map +1 -0
  346. package/dist/tools/office/excel-tools.js +3 -0
  347. package/dist/tools/office/excel-tools.js.map +1 -0
  348. package/dist/tools/office/index.d.ts +6 -0
  349. package/dist/tools/office/index.d.ts.map +1 -0
  350. package/dist/tools/office/index.js +9 -0
  351. package/dist/tools/office/index.js.map +1 -0
  352. package/dist/tools/office/office-client-base.d.ts +31 -0
  353. package/dist/tools/office/office-client-base.d.ts.map +1 -0
  354. package/dist/tools/office/office-client-base.js +154 -0
  355. package/dist/tools/office/office-client-base.js.map +1 -0
  356. package/dist/tools/office/office-client.d.ts +196 -0
  357. package/dist/tools/office/office-client.d.ts.map +1 -0
  358. package/dist/tools/office/office-client.js +200 -0
  359. package/dist/tools/office/office-client.js.map +1 -0
  360. package/dist/tools/office/powerpoint-client.d.ts +135 -0
  361. package/dist/tools/office/powerpoint-client.d.ts.map +1 -0
  362. package/dist/tools/office/powerpoint-client.js +1136 -0
  363. package/dist/tools/office/powerpoint-client.js.map +1 -0
  364. package/dist/tools/office/powerpoint-tools/effects.d.ts +9 -0
  365. package/dist/tools/office/powerpoint-tools/effects.d.ts.map +1 -0
  366. package/dist/tools/office/powerpoint-tools/effects.js +246 -0
  367. package/dist/tools/office/powerpoint-tools/effects.js.map +1 -0
  368. package/dist/tools/office/powerpoint-tools/export.d.ts +6 -0
  369. package/dist/tools/office/powerpoint-tools/export.d.ts.map +1 -0
  370. package/dist/tools/office/powerpoint-tools/export.js +108 -0
  371. package/dist/tools/office/powerpoint-tools/export.js.map +1 -0
  372. package/dist/tools/office/powerpoint-tools/index.d.ts +13 -0
  373. package/dist/tools/office/powerpoint-tools/index.d.ts.map +1 -0
  374. package/dist/tools/office/powerpoint-tools/index.js +33 -0
  375. package/dist/tools/office/powerpoint-tools/index.js.map +1 -0
  376. package/dist/tools/office/powerpoint-tools/launch.d.ts +9 -0
  377. package/dist/tools/office/powerpoint-tools/launch.d.ts.map +1 -0
  378. package/dist/tools/office/powerpoint-tools/launch.js +214 -0
  379. package/dist/tools/office/powerpoint-tools/launch.js.map +1 -0
  380. package/dist/tools/office/powerpoint-tools/media.d.ts +8 -0
  381. package/dist/tools/office/powerpoint-tools/media.d.ts.map +1 -0
  382. package/dist/tools/office/powerpoint-tools/media.js +211 -0
  383. package/dist/tools/office/powerpoint-tools/media.js.map +1 -0
  384. package/dist/tools/office/powerpoint-tools/notes.d.ts +8 -0
  385. package/dist/tools/office/powerpoint-tools/notes.d.ts.map +1 -0
  386. package/dist/tools/office/powerpoint-tools/notes.js +171 -0
  387. package/dist/tools/office/powerpoint-tools/notes.js.map +1 -0
  388. package/dist/tools/office/powerpoint-tools/sections.d.ts +6 -0
  389. package/dist/tools/office/powerpoint-tools/sections.d.ts.map +1 -0
  390. package/dist/tools/office/powerpoint-tools/sections.js +104 -0
  391. package/dist/tools/office/powerpoint-tools/sections.js.map +1 -0
  392. package/dist/tools/office/powerpoint-tools/shapes.d.ts +22 -0
  393. package/dist/tools/office/powerpoint-tools/shapes.d.ts.map +1 -0
  394. package/dist/tools/office/powerpoint-tools/shapes.js +681 -0
  395. package/dist/tools/office/powerpoint-tools/shapes.js.map +1 -0
  396. package/dist/tools/office/powerpoint-tools/slides.d.ts +11 -0
  397. package/dist/tools/office/powerpoint-tools/slides.d.ts.map +1 -0
  398. package/dist/tools/office/powerpoint-tools/slides.js +283 -0
  399. package/dist/tools/office/powerpoint-tools/slides.js.map +1 -0
  400. package/dist/tools/office/powerpoint-tools/tables.d.ts +6 -0
  401. package/dist/tools/office/powerpoint-tools/tables.d.ts.map +1 -0
  402. package/dist/tools/office/powerpoint-tools/tables.js +132 -0
  403. package/dist/tools/office/powerpoint-tools/tables.js.map +1 -0
  404. package/dist/tools/office/powerpoint-tools/text.d.ts +12 -0
  405. package/dist/tools/office/powerpoint-tools/text.d.ts.map +1 -0
  406. package/dist/tools/office/powerpoint-tools/text.js +366 -0
  407. package/dist/tools/office/powerpoint-tools/text.js.map +1 -0
  408. package/dist/tools/office/powerpoint-tools.d.ts +3 -0
  409. package/dist/tools/office/powerpoint-tools.d.ts.map +1 -0
  410. package/dist/tools/office/powerpoint-tools.js +3 -0
  411. package/dist/tools/office/powerpoint-tools.js.map +1 -0
  412. package/dist/tools/office/word-client.d.ts +147 -0
  413. package/dist/tools/office/word-client.d.ts.map +1 -0
  414. package/dist/tools/office/word-client.js +1341 -0
  415. package/dist/tools/office/word-client.js.map +1 -0
  416. package/dist/tools/office/word-tools/bookmarks.d.ts +7 -0
  417. package/dist/tools/office/word-tools/bookmarks.d.ts.map +1 -0
  418. package/dist/tools/office/word-tools/bookmarks.js +146 -0
  419. package/dist/tools/office/word-tools/bookmarks.js.map +1 -0
  420. package/dist/tools/office/word-tools/comments.d.ts +7 -0
  421. package/dist/tools/office/word-tools/comments.d.ts.map +1 -0
  422. package/dist/tools/office/word-tools/comments.js +146 -0
  423. package/dist/tools/office/word-tools/comments.js.map +1 -0
  424. package/dist/tools/office/word-tools/content.d.ts +7 -0
  425. package/dist/tools/office/word-tools/content.d.ts.map +1 -0
  426. package/dist/tools/office/word-tools/content.js +168 -0
  427. package/dist/tools/office/word-tools/content.js.map +1 -0
  428. package/dist/tools/office/word-tools/export.d.ts +5 -0
  429. package/dist/tools/office/word-tools/export.d.ts.map +1 -0
  430. package/dist/tools/office/word-tools/export.js +73 -0
  431. package/dist/tools/office/word-tools/export.js.map +1 -0
  432. package/dist/tools/office/word-tools/formatting.d.ts +6 -0
  433. package/dist/tools/office/word-tools/formatting.d.ts.map +1 -0
  434. package/dist/tools/office/word-tools/formatting.js +129 -0
  435. package/dist/tools/office/word-tools/formatting.js.map +1 -0
  436. package/dist/tools/office/word-tools/headers-footers.d.ts +6 -0
  437. package/dist/tools/office/word-tools/headers-footers.d.ts.map +1 -0
  438. package/dist/tools/office/word-tools/headers-footers.js +117 -0
  439. package/dist/tools/office/word-tools/headers-footers.js.map +1 -0
  440. package/dist/tools/office/word-tools/index.d.ts +16 -0
  441. package/dist/tools/office/word-tools/index.d.ts.map +1 -0
  442. package/dist/tools/office/word-tools/index.js +45 -0
  443. package/dist/tools/office/word-tools/index.js.map +1 -0
  444. package/dist/tools/office/word-tools/launch.d.ts +10 -0
  445. package/dist/tools/office/word-tools/launch.d.ts.map +1 -0
  446. package/dist/tools/office/word-tools/launch.js +255 -0
  447. package/dist/tools/office/word-tools/launch.js.map +1 -0
  448. package/dist/tools/office/word-tools/lists.d.ts +5 -0
  449. package/dist/tools/office/word-tools/lists.d.ts.map +1 -0
  450. package/dist/tools/office/word-tools/lists.js +73 -0
  451. package/dist/tools/office/word-tools/lists.js.map +1 -0
  452. package/dist/tools/office/word-tools/navigation.d.ts +5 -0
  453. package/dist/tools/office/word-tools/navigation.d.ts.map +1 -0
  454. package/dist/tools/office/word-tools/navigation.js +85 -0
  455. package/dist/tools/office/word-tools/navigation.js.map +1 -0
  456. package/dist/tools/office/word-tools/page-setup.d.ts +7 -0
  457. package/dist/tools/office/word-tools/page-setup.d.ts.map +1 -0
  458. package/dist/tools/office/word-tools/page-setup.js +152 -0
  459. package/dist/tools/office/word-tools/page-setup.js.map +1 -0
  460. package/dist/tools/office/word-tools/tables.d.ts +8 -0
  461. package/dist/tools/office/word-tools/tables.d.ts.map +1 -0
  462. package/dist/tools/office/word-tools/tables.js +197 -0
  463. package/dist/tools/office/word-tools/tables.js.map +1 -0
  464. package/dist/tools/office/word-tools/text.d.ts +9 -0
  465. package/dist/tools/office/word-tools/text.d.ts.map +1 -0
  466. package/dist/tools/office/word-tools/text.js +235 -0
  467. package/dist/tools/office/word-tools/text.js.map +1 -0
  468. package/dist/tools/office/word-tools/undo-redo.d.ts +5 -0
  469. package/dist/tools/office/word-tools/undo-redo.d.ts.map +1 -0
  470. package/dist/tools/office/word-tools/undo-redo.js +73 -0
  471. package/dist/tools/office/word-tools/undo-redo.js.map +1 -0
  472. package/dist/tools/office/word-tools/watermarks.d.ts +5 -0
  473. package/dist/tools/office/word-tools/watermarks.d.ts.map +1 -0
  474. package/dist/tools/office/word-tools/watermarks.js +81 -0
  475. package/dist/tools/office/word-tools/watermarks.js.map +1 -0
  476. package/dist/tools/office/word-tools.d.ts +3 -0
  477. package/dist/tools/office/word-tools.d.ts.map +1 -0
  478. package/dist/tools/office/word-tools.js +3 -0
  479. package/dist/tools/office/word-tools.js.map +1 -0
  480. package/dist/tools/registry.d.ts +53 -0
  481. package/dist/tools/registry.d.ts.map +1 -0
  482. package/dist/tools/registry.js +278 -0
  483. package/dist/tools/registry.js.map +1 -0
  484. package/dist/tools/types.d.ts +88 -0
  485. package/dist/tools/types.d.ts.map +1 -0
  486. package/dist/tools/types.js +19 -0
  487. package/dist/tools/types.js.map +1 -0
  488. package/dist/types/index.d.ts +126 -0
  489. package/dist/types/index.d.ts.map +1 -0
  490. package/dist/types/index.js +2 -0
  491. package/dist/types/index.js.map +1 -0
  492. package/dist/ui/PlanExecuteView.d.ts +11 -0
  493. package/dist/ui/PlanExecuteView.d.ts.map +1 -0
  494. package/dist/ui/PlanExecuteView.js +29 -0
  495. package/dist/ui/PlanExecuteView.js.map +1 -0
  496. package/dist/ui/TodoPanel.d.ts +13 -0
  497. package/dist/ui/TodoPanel.d.ts.map +1 -0
  498. package/dist/ui/TodoPanel.js +135 -0
  499. package/dist/ui/TodoPanel.js.map +1 -0
  500. package/dist/ui/UpdateNotification.d.ts +13 -0
  501. package/dist/ui/UpdateNotification.d.ts.map +1 -0
  502. package/dist/ui/UpdateNotification.js +42 -0
  503. package/dist/ui/UpdateNotification.js.map +1 -0
  504. package/dist/ui/components/ActivityIndicator.d.ts +25 -0
  505. package/dist/ui/components/ActivityIndicator.d.ts.map +1 -0
  506. package/dist/ui/components/ActivityIndicator.js +115 -0
  507. package/dist/ui/components/ActivityIndicator.js.map +1 -0
  508. package/dist/ui/components/CommandBrowser.d.ts +10 -0
  509. package/dist/ui/components/CommandBrowser.d.ts.map +1 -0
  510. package/dist/ui/components/CommandBrowser.js +53 -0
  511. package/dist/ui/components/CommandBrowser.js.map +1 -0
  512. package/dist/ui/components/CustomTextInput.d.ts +13 -0
  513. package/dist/ui/components/CustomTextInput.d.ts.map +1 -0
  514. package/dist/ui/components/CustomTextInput.js +245 -0
  515. package/dist/ui/components/CustomTextInput.js.map +1 -0
  516. package/dist/ui/components/DocsSearchProgress.d.ts +13 -0
  517. package/dist/ui/components/DocsSearchProgress.d.ts.map +1 -0
  518. package/dist/ui/components/DocsSearchProgress.js +37 -0
  519. package/dist/ui/components/DocsSearchProgress.js.map +1 -0
  520. package/dist/ui/components/FileBrowser.d.ts +11 -0
  521. package/dist/ui/components/FileBrowser.d.ts.map +1 -0
  522. package/dist/ui/components/FileBrowser.js +45 -0
  523. package/dist/ui/components/FileBrowser.js.map +1 -0
  524. package/dist/ui/components/LLMSetupWizard.d.ts +8 -0
  525. package/dist/ui/components/LLMSetupWizard.d.ts.map +1 -0
  526. package/dist/ui/components/LLMSetupWizard.js +192 -0
  527. package/dist/ui/components/LLMSetupWizard.js.map +1 -0
  528. package/dist/ui/components/Logo.d.ts +19 -0
  529. package/dist/ui/components/Logo.d.ts.map +1 -0
  530. package/dist/ui/components/Logo.js +55 -0
  531. package/dist/ui/components/Logo.js.map +1 -0
  532. package/dist/ui/components/MarkdownRenderer.d.ts +9 -0
  533. package/dist/ui/components/MarkdownRenderer.d.ts.map +1 -0
  534. package/dist/ui/components/MarkdownRenderer.js +198 -0
  535. package/dist/ui/components/MarkdownRenderer.js.map +1 -0
  536. package/dist/ui/components/ModelSelector.d.ts +8 -0
  537. package/dist/ui/components/ModelSelector.d.ts.map +1 -0
  538. package/dist/ui/components/ModelSelector.js +111 -0
  539. package/dist/ui/components/ModelSelector.js.map +1 -0
  540. package/dist/ui/components/PlanExecuteApp.d.ts +23 -0
  541. package/dist/ui/components/PlanExecuteApp.d.ts.map +1 -0
  542. package/dist/ui/components/PlanExecuteApp.js +1324 -0
  543. package/dist/ui/components/PlanExecuteApp.js.map +1 -0
  544. package/dist/ui/components/ProgressBar.d.ts +10 -0
  545. package/dist/ui/components/ProgressBar.d.ts.map +1 -0
  546. package/dist/ui/components/ProgressBar.js +26 -0
  547. package/dist/ui/components/ProgressBar.js.map +1 -0
  548. package/dist/ui/components/StatusBar.d.ts +23 -0
  549. package/dist/ui/components/StatusBar.d.ts.map +1 -0
  550. package/dist/ui/components/StatusBar.js +162 -0
  551. package/dist/ui/components/StatusBar.js.map +1 -0
  552. package/dist/ui/components/ThinkingIndicator.d.ts +14 -0
  553. package/dist/ui/components/ThinkingIndicator.d.ts.map +1 -0
  554. package/dist/ui/components/ThinkingIndicator.js +63 -0
  555. package/dist/ui/components/ThinkingIndicator.js.map +1 -0
  556. package/dist/ui/components/TodoListView.d.ts +11 -0
  557. package/dist/ui/components/TodoListView.d.ts.map +1 -0
  558. package/dist/ui/components/TodoListView.js +69 -0
  559. package/dist/ui/components/TodoListView.js.map +1 -0
  560. package/dist/ui/components/ToolSelector.d.ts +7 -0
  561. package/dist/ui/components/ToolSelector.d.ts.map +1 -0
  562. package/dist/ui/components/ToolSelector.js +111 -0
  563. package/dist/ui/components/ToolSelector.js.map +1 -0
  564. package/dist/ui/components/dialogs/ApprovalDialog.d.ts +13 -0
  565. package/dist/ui/components/dialogs/ApprovalDialog.d.ts.map +1 -0
  566. package/dist/ui/components/dialogs/ApprovalDialog.js +173 -0
  567. package/dist/ui/components/dialogs/ApprovalDialog.js.map +1 -0
  568. package/dist/ui/components/dialogs/AskUserDialog.d.ts +9 -0
  569. package/dist/ui/components/dialogs/AskUserDialog.d.ts.map +1 -0
  570. package/dist/ui/components/dialogs/AskUserDialog.js +111 -0
  571. package/dist/ui/components/dialogs/AskUserDialog.js.map +1 -0
  572. package/dist/ui/components/dialogs/DocsBrowser.d.ts +8 -0
  573. package/dist/ui/components/dialogs/DocsBrowser.d.ts.map +1 -0
  574. package/dist/ui/components/dialogs/DocsBrowser.js +127 -0
  575. package/dist/ui/components/dialogs/DocsBrowser.js.map +1 -0
  576. package/dist/ui/components/dialogs/SettingsDialog.d.ts +10 -0
  577. package/dist/ui/components/dialogs/SettingsDialog.d.ts.map +1 -0
  578. package/dist/ui/components/dialogs/SettingsDialog.js +563 -0
  579. package/dist/ui/components/dialogs/SettingsDialog.js.map +1 -0
  580. package/dist/ui/components/dialogs/index.d.ts +4 -0
  581. package/dist/ui/components/dialogs/index.d.ts.map +1 -0
  582. package/dist/ui/components/dialogs/index.js +4 -0
  583. package/dist/ui/components/dialogs/index.js.map +1 -0
  584. package/dist/ui/components/index.d.ts +12 -0
  585. package/dist/ui/components/index.d.ts.map +1 -0
  586. package/dist/ui/components/index.js +9 -0
  587. package/dist/ui/components/index.js.map +1 -0
  588. package/dist/ui/components/panels/LogPanel.d.ts +7 -0
  589. package/dist/ui/components/panels/LogPanel.d.ts.map +1 -0
  590. package/dist/ui/components/panels/LogPanel.js +280 -0
  591. package/dist/ui/components/panels/LogPanel.js.map +1 -0
  592. package/dist/ui/components/panels/SessionPanel.d.ts +8 -0
  593. package/dist/ui/components/panels/SessionPanel.d.ts.map +1 -0
  594. package/dist/ui/components/panels/SessionPanel.js +81 -0
  595. package/dist/ui/components/panels/SessionPanel.js.map +1 -0
  596. package/dist/ui/components/panels/index.d.ts +4 -0
  597. package/dist/ui/components/panels/index.d.ts.map +1 -0
  598. package/dist/ui/components/panels/index.js +4 -0
  599. package/dist/ui/components/panels/index.js.map +1 -0
  600. package/dist/ui/components/views/ChatView.d.ts +12 -0
  601. package/dist/ui/components/views/ChatView.d.ts.map +1 -0
  602. package/dist/ui/components/views/ChatView.js +289 -0
  603. package/dist/ui/components/views/ChatView.js.map +1 -0
  604. package/dist/ui/components/views/index.d.ts +2 -0
  605. package/dist/ui/components/views/index.d.ts.map +1 -0
  606. package/dist/ui/components/views/index.js +2 -0
  607. package/dist/ui/components/views/index.js.map +1 -0
  608. package/dist/ui/contexts/TokenContext.d.ts +29 -0
  609. package/dist/ui/contexts/TokenContext.d.ts.map +1 -0
  610. package/dist/ui/contexts/TokenContext.js +79 -0
  611. package/dist/ui/contexts/TokenContext.js.map +1 -0
  612. package/dist/ui/hooks/atFileProcessor.d.ts +15 -0
  613. package/dist/ui/hooks/atFileProcessor.d.ts.map +1 -0
  614. package/dist/ui/hooks/atFileProcessor.js +88 -0
  615. package/dist/ui/hooks/atFileProcessor.js.map +1 -0
  616. package/dist/ui/hooks/index.d.ts +8 -0
  617. package/dist/ui/hooks/index.d.ts.map +1 -0
  618. package/dist/ui/hooks/index.js +8 -0
  619. package/dist/ui/hooks/index.js.map +1 -0
  620. package/dist/ui/hooks/slashCommandProcessor.d.ts +21 -0
  621. package/dist/ui/hooks/slashCommandProcessor.d.ts.map +1 -0
  622. package/dist/ui/hooks/slashCommandProcessor.js +100 -0
  623. package/dist/ui/hooks/slashCommandProcessor.js.map +1 -0
  624. package/dist/ui/hooks/useCommandBrowserState.d.ts +12 -0
  625. package/dist/ui/hooks/useCommandBrowserState.d.ts.map +1 -0
  626. package/dist/ui/hooks/useCommandBrowserState.js +66 -0
  627. package/dist/ui/hooks/useCommandBrowserState.js.map +1 -0
  628. package/dist/ui/hooks/useFileBrowserState.d.ts +15 -0
  629. package/dist/ui/hooks/useFileBrowserState.d.ts.map +1 -0
  630. package/dist/ui/hooks/useFileBrowserState.js +80 -0
  631. package/dist/ui/hooks/useFileBrowserState.js.map +1 -0
  632. package/dist/ui/hooks/useFileList.d.ts +20 -0
  633. package/dist/ui/hooks/useFileList.d.ts.map +1 -0
  634. package/dist/ui/hooks/useFileList.js +57 -0
  635. package/dist/ui/hooks/useFileList.js.map +1 -0
  636. package/dist/ui/hooks/useInputHistory.d.ts +9 -0
  637. package/dist/ui/hooks/useInputHistory.d.ts.map +1 -0
  638. package/dist/ui/hooks/useInputHistory.js +68 -0
  639. package/dist/ui/hooks/useInputHistory.js.map +1 -0
  640. package/dist/ui/hooks/usePlanExecution.d.ts +8 -0
  641. package/dist/ui/hooks/usePlanExecution.d.ts.map +1 -0
  642. package/dist/ui/hooks/usePlanExecution.js +214 -0
  643. package/dist/ui/hooks/usePlanExecution.js.map +1 -0
  644. package/dist/ui/index.d.ts +7 -0
  645. package/dist/ui/index.d.ts.map +1 -0
  646. package/dist/ui/index.js +7 -0
  647. package/dist/ui/index.js.map +1 -0
  648. package/dist/ui/ink-entry.d.ts +3 -0
  649. package/dist/ui/ink-entry.d.ts.map +1 -0
  650. package/dist/ui/ink-entry.js +22 -0
  651. package/dist/ui/ink-entry.js.map +1 -0
  652. package/dist/utils/env-filter.d.ts +4 -0
  653. package/dist/utils/env-filter.d.ts.map +1 -0
  654. package/dist/utils/env-filter.js +101 -0
  655. package/dist/utils/env-filter.js.map +1 -0
  656. package/dist/utils/file-system.d.ts +9 -0
  657. package/dist/utils/file-system.d.ts.map +1 -0
  658. package/dist/utils/file-system.js +99 -0
  659. package/dist/utils/file-system.js.map +1 -0
  660. package/dist/utils/git-utils.d.ts +2 -0
  661. package/dist/utils/git-utils.d.ts.map +1 -0
  662. package/dist/utils/git-utils.js +16 -0
  663. package/dist/utils/git-utils.js.map +1 -0
  664. package/dist/utils/json-stream-logger.d.ts +74 -0
  665. package/dist/utils/json-stream-logger.d.ts.map +1 -0
  666. package/dist/utils/json-stream-logger.js +808 -0
  667. package/dist/utils/json-stream-logger.js.map +1 -0
  668. package/dist/utils/logger.d.ts +152 -0
  669. package/dist/utils/logger.d.ts.map +1 -0
  670. package/dist/utils/logger.js +1672 -0
  671. package/dist/utils/logger.js.map +1 -0
  672. package/dist/utils/platform-utils.d.ts +19 -0
  673. package/dist/utils/platform-utils.d.ts.map +1 -0
  674. package/dist/utils/platform-utils.js +134 -0
  675. package/dist/utils/platform-utils.js.map +1 -0
  676. package/dist/utils/wsl-utils.d.ts +4 -0
  677. package/dist/utils/wsl-utils.d.ts.map +1 -0
  678. package/dist/utils/wsl-utils.js +72 -0
  679. package/dist/utils/wsl-utils.js.map +1 -0
  680. package/electron.vite.config.ts +63 -0
  681. package/google374b9eba0c52b043.html +1 -0
  682. package/package.json +122 -0
  683. package/src/agents/base/base-agent.ts +159 -0
  684. package/src/agents/docs-search/index.ts +365 -0
  685. package/src/agents/index.ts +34 -0
  686. package/src/agents/planner/index.ts +544 -0
  687. package/src/cli.ts +201 -0
  688. package/src/constants.ts +47 -0
  689. package/src/core/compact/compact-manager.ts +160 -0
  690. package/src/core/compact/compact-prompts.ts +150 -0
  691. package/src/core/compact/context-tracker.ts +164 -0
  692. package/src/core/compact/index.ts +25 -0
  693. package/src/core/config/config-manager.ts +460 -0
  694. package/src/core/config/index.ts +5 -0
  695. package/src/core/docs-manager.ts +678 -0
  696. package/src/core/llm/index.ts +7 -0
  697. package/src/core/llm/llm-client.ts +1550 -0
  698. package/src/core/session/index.ts +5 -0
  699. package/src/core/session/session-manager.ts +464 -0
  700. package/src/core/slash-command-handler.ts +410 -0
  701. package/src/core/usage-tracker.ts +438 -0
  702. package/src/errors/base.ts +81 -0
  703. package/src/errors/file.ts +183 -0
  704. package/src/errors/index.ts +95 -0
  705. package/src/errors/llm.ts +151 -0
  706. package/src/errors/network.ts +124 -0
  707. package/src/errors/validation.ts +111 -0
  708. package/src/eval/eval-runner.ts +456 -0
  709. package/src/eval/index.ts +8 -0
  710. package/src/eval/types.ts +139 -0
  711. package/src/index.ts +22 -0
  712. package/src/orchestration/index.ts +30 -0
  713. package/src/orchestration/plan-executor.ts +652 -0
  714. package/src/orchestration/types.ts +127 -0
  715. package/src/orchestration/utils.ts +119 -0
  716. package/src/orquesta/connection.ts +291 -0
  717. package/src/prompts/agents/docs-search-decision.ts +74 -0
  718. package/src/prompts/agents/docs-search.ts +84 -0
  719. package/src/prompts/agents/planning.ts +143 -0
  720. package/src/prompts/index.ts +31 -0
  721. package/src/prompts/shared/codebase-rules.ts +29 -0
  722. package/src/prompts/shared/git-rules.ts +94 -0
  723. package/src/prompts/shared/language-rules.ts +36 -0
  724. package/src/prompts/shared/tool-usage.ts +72 -0
  725. package/src/prompts/system/compact.ts +80 -0
  726. package/src/prompts/system/plan-execute.ts +89 -0
  727. package/src/tools/browser/browser-client.ts +1363 -0
  728. package/src/tools/browser/browser-tools.ts +1139 -0
  729. package/src/tools/browser/index.ts +65 -0
  730. package/src/tools/index.ts +23 -0
  731. package/src/tools/llm/agents/docs-search-tools.ts +368 -0
  732. package/src/tools/llm/agents/index.ts +22 -0
  733. package/src/tools/llm/index.ts +11 -0
  734. package/src/tools/llm/simple/ask-user-tool.ts +25 -0
  735. package/src/tools/llm/simple/background-bash-tool.ts +443 -0
  736. package/src/tools/llm/simple/background-powershell-tool.ts +421 -0
  737. package/src/tools/llm/simple/bash-tool.ts +238 -0
  738. package/src/tools/llm/simple/docs-search-agent-tool.ts +146 -0
  739. package/src/tools/llm/simple/file-tools.ts +1051 -0
  740. package/src/tools/llm/simple/final-response-tool.ts +180 -0
  741. package/src/tools/llm/simple/index.ts +42 -0
  742. package/src/tools/llm/simple/planning-tools.ts +143 -0
  743. package/src/tools/llm/simple/powershell-tool.ts +241 -0
  744. package/src/tools/llm/simple/simple-tool-executor.ts +279 -0
  745. package/src/tools/llm/simple/todo-tools.ts +207 -0
  746. package/src/tools/llm/simple/user-interaction-tools.ts +277 -0
  747. package/src/tools/office/common/constants.ts +335 -0
  748. package/src/tools/office/common/index.ts +133 -0
  749. package/src/tools/office/common/types.ts +286 -0
  750. package/src/tools/office/common/utils.ts +116 -0
  751. package/src/tools/office/excel-client.ts +1336 -0
  752. package/src/tools/office/excel-tools/cells.ts +359 -0
  753. package/src/tools/office/excel-tools/charts.ts +166 -0
  754. package/src/tools/office/excel-tools/comments.ts +155 -0
  755. package/src/tools/office/excel-tools/data-ops.ts +349 -0
  756. package/src/tools/office/excel-tools/export.ts +105 -0
  757. package/src/tools/office/excel-tools/formatting.ts +357 -0
  758. package/src/tools/office/excel-tools/index.ts +55 -0
  759. package/src/tools/office/excel-tools/launch.ts +303 -0
  760. package/src/tools/office/excel-tools/media.ts +117 -0
  761. package/src/tools/office/excel-tools/named-ranges.ts +148 -0
  762. package/src/tools/office/excel-tools/protection.ts +105 -0
  763. package/src/tools/office/excel-tools/rows-columns.ts +386 -0
  764. package/src/tools/office/excel-tools/sheets.ts +228 -0
  765. package/src/tools/office/excel-tools/validation.ts +226 -0
  766. package/src/tools/office/excel-tools.ts +9 -0
  767. package/src/tools/office/index.ts +259 -0
  768. package/src/tools/office/office-client-base.ts +242 -0
  769. package/src/tools/office/office-client.ts +377 -0
  770. package/src/tools/office/powerpoint-client.ts +1498 -0
  771. package/src/tools/office/powerpoint-tools/effects.ts +315 -0
  772. package/src/tools/office/powerpoint-tools/export.ts +138 -0
  773. package/src/tools/office/powerpoint-tools/index.ts +45 -0
  774. package/src/tools/office/powerpoint-tools/launch.ts +263 -0
  775. package/src/tools/office/powerpoint-tools/media.ts +291 -0
  776. package/src/tools/office/powerpoint-tools/notes.ts +220 -0
  777. package/src/tools/office/powerpoint-tools/sections.ts +140 -0
  778. package/src/tools/office/powerpoint-tools/shapes.ts +870 -0
  779. package/src/tools/office/powerpoint-tools/slides.ts +350 -0
  780. package/src/tools/office/powerpoint-tools/tables.ts +182 -0
  781. package/src/tools/office/powerpoint-tools/text.ts +473 -0
  782. package/src/tools/office/powerpoint-tools.ts +9 -0
  783. package/src/tools/office/word-client.ts +1697 -0
  784. package/src/tools/office/word-tools/bookmarks.ts +186 -0
  785. package/src/tools/office/word-tools/comments.ts +185 -0
  786. package/src/tools/office/word-tools/content.ts +229 -0
  787. package/src/tools/office/word-tools/export.ts +97 -0
  788. package/src/tools/office/word-tools/formatting.ts +161 -0
  789. package/src/tools/office/word-tools/headers-footers.ts +155 -0
  790. package/src/tools/office/word-tools/index.ts +57 -0
  791. package/src/tools/office/word-tools/launch.ts +312 -0
  792. package/src/tools/office/word-tools/lists.ts +97 -0
  793. package/src/tools/office/word-tools/navigation.ts +114 -0
  794. package/src/tools/office/word-tools/page-setup.ts +195 -0
  795. package/src/tools/office/word-tools/tables.ts +262 -0
  796. package/src/tools/office/word-tools/text.ts +294 -0
  797. package/src/tools/office/word-tools/undo-redo.ts +97 -0
  798. package/src/tools/office/word-tools/watermarks.ts +105 -0
  799. package/src/tools/office/word-tools.ts +9 -0
  800. package/src/tools/registry.ts +527 -0
  801. package/src/tools/types.ts +231 -0
  802. package/src/types/index.ts +181 -0
  803. package/src/ui/PlanExecuteView.tsx +119 -0
  804. package/src/ui/TodoPanel.tsx +240 -0
  805. package/src/ui/UpdateNotification.tsx +105 -0
  806. package/src/ui/components/ActivityIndicator.tsx +234 -0
  807. package/src/ui/components/CommandBrowser.tsx +114 -0
  808. package/src/ui/components/CustomTextInput.tsx +389 -0
  809. package/src/ui/components/DocsSearchProgress.tsx +85 -0
  810. package/src/ui/components/FileBrowser.tsx +93 -0
  811. package/src/ui/components/LLMSetupWizard.tsx +333 -0
  812. package/src/ui/components/Logo.tsx +125 -0
  813. package/src/ui/components/MarkdownRenderer.tsx +358 -0
  814. package/src/ui/components/ModelSelector.tsx +203 -0
  815. package/src/ui/components/PlanExecuteApp.tsx +2007 -0
  816. package/src/ui/components/ProgressBar.tsx +51 -0
  817. package/src/ui/components/StatusBar.tsx +302 -0
  818. package/src/ui/components/ThinkingIndicator.tsx +120 -0
  819. package/src/ui/components/TodoListView.tsx +140 -0
  820. package/src/ui/components/ToolSelector.tsx +215 -0
  821. package/src/ui/components/dialogs/ApprovalDialog.tsx +259 -0
  822. package/src/ui/components/dialogs/AskUserDialog.tsx +159 -0
  823. package/src/ui/components/dialogs/DocsBrowser.tsx +222 -0
  824. package/src/ui/components/dialogs/SettingsDialog.tsx +939 -0
  825. package/src/ui/components/dialogs/index.ts +13 -0
  826. package/src/ui/components/index.ts +27 -0
  827. package/src/ui/components/panels/LogPanel.tsx +385 -0
  828. package/src/ui/components/panels/SessionPanel.tsx +146 -0
  829. package/src/ui/components/panels/index.ts +13 -0
  830. package/src/ui/components/views/ChatView.tsx +447 -0
  831. package/src/ui/components/views/index.ts +5 -0
  832. package/src/ui/contexts/TokenContext.tsx +139 -0
  833. package/src/ui/hooks/atFileProcessor.ts +167 -0
  834. package/src/ui/hooks/index.ts +11 -0
  835. package/src/ui/hooks/slashCommandProcessor.ts +174 -0
  836. package/src/ui/hooks/useCommandBrowserState.ts +97 -0
  837. package/src/ui/hooks/useFileBrowserState.ts +116 -0
  838. package/src/ui/hooks/useFileList.ts +132 -0
  839. package/src/ui/hooks/useInputHistory.ts +89 -0
  840. package/src/ui/hooks/usePlanExecution.ts +339 -0
  841. package/src/ui/index.ts +10 -0
  842. package/src/ui/ink-entry.tsx +36 -0
  843. package/src/utils/env-filter.ts +164 -0
  844. package/src/utils/file-system.ts +133 -0
  845. package/src/utils/git-utils.ts +30 -0
  846. package/src/utils/json-stream-logger.ts +1259 -0
  847. package/src/utils/logger.ts +2767 -0
  848. package/src/utils/platform-utils.ts +256 -0
  849. package/src/utils/wsl-utils.ts +113 -0
  850. package/tsconfig.electron.json +39 -0
  851. package/tsconfig.json +64 -0
@@ -0,0 +1,1550 @@
1
+ /**
2
+ * LLM Client
3
+ *
4
+ * OpenAI Compatible API client
5
+ * Supports Gemini (HTTPS) and LiteLLM (HTTP)
6
+ *
7
+ * Logger usage guide:
8
+ * - This file already uses logger.httpRequest(), logger.httpResponse(), logger.error(), etc.
9
+ * - Additional improvements: Add logger.enter/exit to main public functions
10
+ * - Example: logger.enter('sendMessage', { messageLength: userMessage.length });
11
+ * - For detailed usage, see docs/LOGGER_USAGE_KR.md
12
+ */
13
+
14
+ import axios, { AxiosInstance, AxiosError } from 'axios';
15
+ import { Message, LLMRequestOptions } from '../../types/index.js';
16
+ import { configManager } from '../config/config-manager.js';
17
+ import {
18
+ NetworkError,
19
+ APIError,
20
+ TimeoutError,
21
+ ConnectionError,
22
+ } from '../../errors/network.js';
23
+ import {
24
+ LLMError,
25
+ TokenLimitError,
26
+ RateLimitError,
27
+ ContextLengthError,
28
+ } from '../../errors/llm.js';
29
+ import { logger, isLLMLogEnabled } from '../../utils/logger.js';
30
+ import { usageTracker } from '../usage-tracker.js';
31
+
32
+ /**
33
+ * LLM response interface (OpenAI Compatible)
34
+ */
35
+ export interface LLMResponse {
36
+ id: string;
37
+ object: string;
38
+ created: number;
39
+ model: string;
40
+ choices: Array<{
41
+ index: number;
42
+ message: Message & {
43
+ reasoning?: string;
44
+ };
45
+ finish_reason: string | null;
46
+ }>;
47
+ usage?: {
48
+ prompt_tokens: number;
49
+ completion_tokens: number;
50
+ total_tokens: number;
51
+ };
52
+ }
53
+
54
+ /**
55
+ * Streaming chunk interface
56
+ */
57
+ export interface LLMStreamChunk {
58
+ id: string;
59
+ object: string;
60
+ created: number;
61
+ model: string;
62
+ choices: Array<{
63
+ index: number;
64
+ delta: {
65
+ role?: string;
66
+ content?: string;
67
+ reasoning?: string;
68
+ };
69
+ finish_reason: string | null;
70
+ }>;
71
+ }
72
+
73
+ /**
74
+ * Retry configuration interface
75
+ */
76
+ export interface RetryConfig {
77
+ /** Maximum retry attempts (default: 3) */
78
+ maxRetries?: number;
79
+ /** Current attempt number (internal use) */
80
+ currentAttempt?: number;
81
+ /** Whether retry is disabled */
82
+ disableRetry?: boolean;
83
+ }
84
+
85
+ /**
86
+ * LLM Client class
87
+ */
88
+ export class LLMClient {
89
+ private axiosInstance: AxiosInstance;
90
+ private baseUrl: string;
91
+ private apiKey: string;
92
+ private model: string;
93
+ private modelName: string;
94
+ private currentAbortController: AbortController | null = null;
95
+ private isInterrupted: boolean = false;
96
+
97
+ /** Default maximum retry attempts */
98
+ private static readonly DEFAULT_MAX_RETRIES = 3;
99
+
100
+ constructor() {
101
+ // Get current settings from ConfigManager
102
+ const endpoint = configManager.getCurrentEndpoint();
103
+ const currentModel = configManager.getCurrentModel();
104
+
105
+ if (!endpoint || !currentModel) {
106
+ throw new Error('No endpoint or model configured. Run: open config init');
107
+ }
108
+
109
+ this.baseUrl = endpoint.baseUrl;
110
+ this.apiKey = endpoint.apiKey || '';
111
+ this.model = currentModel.id;
112
+ this.modelName = currentModel.name;
113
+
114
+ // Create Axios instance
115
+ this.axiosInstance = axios.create({
116
+ baseURL: this.baseUrl,
117
+ headers: {
118
+ 'Content-Type': 'application/json',
119
+ ...(this.apiKey && { Authorization: `Bearer ${this.apiKey}` }),
120
+ },
121
+ timeout: 600000, // 600 seconds (10 minutes)
122
+ });
123
+ }
124
+
125
+ /**
126
+ * Preprocess messages for model-specific requirements
127
+ *
128
+ * Handles:
129
+ * 1. reasoning_content → content conversion (for reasoning LLM responses)
130
+ * 2. Harmony format for gpt-oss models
131
+ */
132
+ private preprocessMessages(messages: Message[], modelId: string): Message[] {
133
+ return messages.map((msg) => {
134
+ // Skip non-assistant messages
135
+ if (msg.role !== 'assistant') {
136
+ return msg;
137
+ }
138
+
139
+ const msgAny = msg as any;
140
+ let processedMsg = { ...msg };
141
+
142
+ // Handle reasoning_content from reasoning LLMs (DeepSeek-V3, etc.)
143
+ // When switching between reasoning LLM and regular LLM, content field is required
144
+ if (msgAny.reasoning_content && (!msg.content || msg.content.trim() === '')) {
145
+ processedMsg.content = msgAny.reasoning_content;
146
+ // Remove reasoning_content to avoid confusion
147
+ delete (processedMsg as any).reasoning_content;
148
+ }
149
+
150
+ // gpt-oss-120b / gpt-oss-20b: Harmony format handling
151
+ // These models require content field even when tool_calls are present
152
+ if (/^gpt-oss-(120b|20b)$/i.test(modelId)) {
153
+ if (msg.tool_calls && msg.tool_calls.length > 0) {
154
+ if (!processedMsg.content || processedMsg.content.trim() === '') {
155
+ const toolNames = msg.tool_calls.map(tc => tc.function.name).join(', ');
156
+ processedMsg.content = msgAny.reasoning || `Calling tools: ${toolNames}`;
157
+ }
158
+ }
159
+ }
160
+
161
+ // Ensure content is at least empty string for assistant messages
162
+ if (processedMsg.content === undefined || processedMsg.content === null) {
163
+ processedMsg.content = '';
164
+ }
165
+
166
+ return processedMsg;
167
+ });
168
+ }
169
+
170
+ /**
171
+ * Chat Completion API call (Non-streaming)
172
+ * Retries up to 3 times by default, errors not shown in UI during retry
173
+ */
174
+ async chatCompletion(
175
+ options: Partial<LLMRequestOptions>,
176
+ retryConfig?: RetryConfig
177
+ ): Promise<LLMResponse> {
178
+ const maxRetries = retryConfig?.disableRetry ? 1 : (retryConfig?.maxRetries ?? LLMClient.DEFAULT_MAX_RETRIES);
179
+ const currentAttempt = retryConfig?.currentAttempt ?? 1;
180
+
181
+ logger.enter('chatCompletion', {
182
+ model: options.model || this.model,
183
+ messagesCount: options.messages?.length || 0,
184
+ hasTools: !!options.tools,
185
+ attempt: currentAttempt,
186
+ maxRetries
187
+ });
188
+
189
+ const url = '/chat/completions';
190
+
191
+ try {
192
+ logger.flow('Starting message preprocessing');
193
+ // Preprocess messages for model-specific requirements
194
+ const modelId = options.model || this.model;
195
+ const processedMessages = options.messages ?
196
+ this.preprocessMessages(options.messages, modelId) : [];
197
+
198
+ logger.vars(
199
+ { name: 'modelId', value: modelId },
200
+ { name: 'originalMessages', value: options.messages?.length || 0 },
201
+ { name: 'processedMessages', value: processedMessages.length },
202
+ { name: 'temperature', value: options.temperature ?? 0.7 }
203
+ );
204
+
205
+ const requestBody = {
206
+ model: modelId,
207
+ messages: processedMessages,
208
+ temperature: options.temperature ?? 0.7,
209
+ max_tokens: options.max_tokens,
210
+ stream: false,
211
+ ...(options.tools && {
212
+ tools: options.tools,
213
+ parallel_tool_calls: false, // Enforce one tool at a time via API
214
+ ...(options.tool_choice && { tool_choice: options.tool_choice }),
215
+ }),
216
+ };
217
+
218
+ logger.flow('API request preparation complete');
219
+
220
+ // Log request
221
+ logger.httpRequest('POST', `${this.baseUrl}${url}`, {
222
+ model: modelId,
223
+ messages: `${processedMessages.length} messages`,
224
+ temperature: requestBody.temperature,
225
+ max_tokens: requestBody.max_tokens,
226
+ tools: options.tools ? `${options.tools.length} tools` : 'none',
227
+ });
228
+
229
+ logger.verbose('Full Request Body', requestBody);
230
+
231
+ // LLM Log mode: Log request
232
+ if (isLLMLogEnabled()) {
233
+ logger.llmRequest(processedMessages, modelId, options.tools);
234
+ }
235
+
236
+ logger.startTimer('llm-api-call');
237
+
238
+ // Create AbortController for this request
239
+ this.currentAbortController = new AbortController();
240
+
241
+ const response = await this.axiosInstance.post<LLMResponse>(url, requestBody, {
242
+ signal: this.currentAbortController.signal,
243
+ });
244
+
245
+ this.currentAbortController = null;
246
+ const elapsed = logger.endTimer('llm-api-call');
247
+
248
+ logger.flow('API response received');
249
+
250
+ // Validate response structure
251
+ if (!response.data.choices || !Array.isArray(response.data.choices)) {
252
+ logger.error('Invalid response structure - missing choices array', response.data);
253
+ throw new Error('Invalid LLM response format. Missing choices array.');
254
+ }
255
+
256
+ // Log response
257
+ logger.httpResponse(response.status, response.statusText, {
258
+ choices: response.data.choices.length,
259
+ usage: response.data.usage,
260
+ });
261
+
262
+ logger.verbose('Full Response', response.data);
263
+
264
+ logger.vars(
265
+ { name: 'responseChoices', value: response.data.choices.length },
266
+ { name: 'tokensUsed', value: response.data.usage?.total_tokens || 0 },
267
+ { name: 'responseTime', value: elapsed }
268
+ );
269
+
270
+ // LLM Log mode: Log response
271
+ if (isLLMLogEnabled()) {
272
+ const responseContent = response.data.choices[0]?.message?.content || '';
273
+ const toolCalls = response.data.choices[0]?.message?.tool_calls;
274
+ logger.llmResponse(responseContent, toolCalls);
275
+ }
276
+
277
+ // Emit reasoning if present (extended thinking from o1 models)
278
+ // Only emit for user-facing responses (skip internal classifier calls)
279
+ const reasoningContent = response.data.choices[0]?.message?.reasoning;
280
+ const maxTokens = options.max_tokens;
281
+ const isInternalCall = maxTokens && maxTokens < 500; // Internal calls use small max_tokens
282
+
283
+ if (reasoningContent && !isInternalCall) {
284
+ const { emitReasoning } = await import('../../tools/llm/simple/file-tools.js');
285
+ emitReasoning(reasoningContent, false);
286
+ logger.debug('Reasoning content emitted', { length: reasoningContent.length });
287
+ } else if (reasoningContent && isInternalCall) {
288
+ logger.debug('Reasoning skipped (internal call)', { maxTokens, length: reasoningContent.length });
289
+ }
290
+
291
+ // Track token usage (Phase 3) + context tracking for auto-compact
292
+ if (response.data.usage) {
293
+ const promptTokens = response.data.usage.prompt_tokens || 0;
294
+ usageTracker.recordUsage(
295
+ this.model,
296
+ promptTokens,
297
+ response.data.usage.completion_tokens || 0,
298
+ undefined, // sessionId
299
+ promptTokens // lastPromptTokens for context tracking
300
+ );
301
+ }
302
+
303
+ logger.exit('chatCompletion', {
304
+ success: true,
305
+ choices: response.data.choices.length,
306
+ elapsed
307
+ });
308
+
309
+ return response.data;
310
+ } catch (error) {
311
+ this.currentAbortController = null;
312
+
313
+ // Check if this was an abort/cancel
314
+ if (axios.isCancel(error) || (error instanceof Error && error.name === 'CanceledError')) {
315
+ logger.flow('API call canceled (user interrupt)');
316
+ logger.exit('chatCompletion', { success: false, aborted: true });
317
+ throw new Error('INTERRUPTED');
318
+ }
319
+
320
+ // If retryable error and retries remaining, retry
321
+ if (currentAttempt < maxRetries && this.isRetryableError(error)) {
322
+ // During retry, only log at debug level (not shown in UI)
323
+ const delay = Math.pow(2, currentAttempt - 1) * 1000; // Exponential backoff: 1s, 2s, 4s
324
+ logger.debug(`LLM call failed (${currentAttempt}/${maxRetries}), retrying after ${delay}ms...`, {
325
+ error: (error as Error).message,
326
+ attempt: currentAttempt,
327
+ maxRetries,
328
+ delay
329
+ });
330
+
331
+ await this.sleep(delay);
332
+
333
+ // Retry recursively
334
+ return this.chatCompletion(options, {
335
+ maxRetries,
336
+ currentAttempt: currentAttempt + 1,
337
+ });
338
+ }
339
+
340
+ // Final failure: Log error and throw
341
+ logger.flow('API call failed - Error handling');
342
+ if (currentAttempt > 1) {
343
+ // Only show error log if final failure after retries
344
+ logger.error(`LLM call final failure after ${maxRetries} retries`, {
345
+ error: (error as Error).message,
346
+ attempts: currentAttempt
347
+ });
348
+ }
349
+ logger.exit('chatCompletion', { success: false, error: (error as Error).message, attempts: currentAttempt });
350
+ throw this.handleError(error, {
351
+ method: 'POST',
352
+ url,
353
+ body: options,
354
+ });
355
+ }
356
+ }
357
+
358
+ /**
359
+ * Abort current LLM request and set interrupt flag (for ESC interrupt)
360
+ */
361
+ abort(): void {
362
+ logger.flow('LLM interrupt - Stopping all operations');
363
+ this.isInterrupted = true;
364
+
365
+ if (this.currentAbortController) {
366
+ this.currentAbortController.abort();
367
+ this.currentAbortController = null;
368
+ }
369
+ }
370
+
371
+ /**
372
+ * Check if interrupted
373
+ */
374
+ checkInterrupted(): boolean {
375
+ return this.isInterrupted;
376
+ }
377
+
378
+ /**
379
+ * Reset interrupt flag (call before starting new operation)
380
+ */
381
+ resetInterrupt(): void {
382
+ this.isInterrupted = false;
383
+ }
384
+
385
+ /**
386
+ * Check if there's an active request
387
+ */
388
+ isRequestActive(): boolean {
389
+ return this.currentAbortController !== null;
390
+ }
391
+
392
+ /**
393
+ * Check if error is retryable
394
+ * - 5xx server errors
395
+ * - Network errors (ECONNREFUSED, ETIMEDOUT, ECONNRESET, etc.)
396
+ * - Rate Limit (429)
397
+ * - Tool argument parsing errors are not retried (LLM response issue)
398
+ */
399
+ private isRetryableError(error: unknown): boolean {
400
+ // Do not retry user interrupts
401
+ if (error instanceof Error && error.message === 'INTERRUPTED') {
402
+ return false;
403
+ }
404
+
405
+ if (axios.isAxiosError(error)) {
406
+ const axiosError = error as AxiosError;
407
+
408
+ // Network error (no response)
409
+ if (!axiosError.response) {
410
+ const retryableCodes = ['ECONNREFUSED', 'ETIMEDOUT', 'ECONNRESET', 'ECONNABORTED', 'ENOTFOUND', 'EHOSTUNREACH'];
411
+ if (axiosError.code && retryableCodes.includes(axiosError.code)) {
412
+ return true;
413
+ }
414
+ // Timeout
415
+ if (axiosError.message.includes('timeout')) {
416
+ return true;
417
+ }
418
+ return true; // Retry other network errors too
419
+ }
420
+
421
+ const status = axiosError.response.status;
422
+
423
+ // Rate Limit (429)
424
+ if (status === 429) {
425
+ return true;
426
+ }
427
+
428
+ // Server error (5xx)
429
+ if (status >= 500) {
430
+ return true;
431
+ }
432
+
433
+ // Do not retry auth/permission errors (401, 403)
434
+ // Do not retry bad requests (400)
435
+ // Do not retry Context Length exceeded
436
+ return false;
437
+ }
438
+
439
+ // Do not retry other errors
440
+ return false;
441
+ }
442
+
443
+ /**
444
+ * Wait for specified time (for retry)
445
+ */
446
+ private sleep(ms: number): Promise<void> {
447
+ return new Promise(resolve => setTimeout(resolve, ms));
448
+ }
449
+
450
+ /**
451
+ * Chat Completion API call (Streaming)
452
+ */
453
+ async *chatCompletionStream(
454
+ options: Partial<LLMRequestOptions>
455
+ ): AsyncGenerator<LLMStreamChunk, void, unknown> {
456
+ const url = '/chat/completions';
457
+
458
+ try {
459
+ // Preprocess messages for model-specific requirements
460
+ const modelId = options.model || this.model;
461
+ const processedMessages = options.messages ?
462
+ this.preprocessMessages(options.messages, modelId) : [];
463
+
464
+ const requestBody = {
465
+ model: modelId,
466
+ messages: processedMessages,
467
+ temperature: options.temperature ?? 0.7,
468
+ max_tokens: options.max_tokens,
469
+ stream: true,
470
+ ...(options.tools && {
471
+ tools: options.tools,
472
+ ...(options.tool_choice && { tool_choice: options.tool_choice }),
473
+ }),
474
+ };
475
+
476
+ // Log request
477
+ logger.httpRequest('POST (stream)', `${this.baseUrl}${url}`, {
478
+ model: modelId,
479
+ messages: `${processedMessages.length} messages`,
480
+ temperature: requestBody.temperature,
481
+ max_tokens: requestBody.max_tokens,
482
+ });
483
+
484
+ logger.verbose('Full Streaming Request Body', requestBody);
485
+
486
+ // Create AbortController for streaming request
487
+ this.currentAbortController = new AbortController();
488
+
489
+ const response = await this.axiosInstance.post(url, requestBody, {
490
+ responseType: 'stream',
491
+ signal: this.currentAbortController.signal,
492
+ });
493
+
494
+ logger.debug('Streaming response started', { status: response.status });
495
+
496
+ // SSE (Server-Sent Events) parsing
497
+ const stream = response.data as AsyncIterable<Buffer>;
498
+ let buffer = '';
499
+ let chunkCount = 0;
500
+
501
+ // Check if this is an internal call (skip reasoning for classifier calls)
502
+ const maxTokens = options.max_tokens;
503
+ const isInternalCall = maxTokens && maxTokens < 500;
504
+
505
+ // Import emitReasoning once before loop
506
+ const { emitReasoning } = await import('../../tools/llm/simple/file-tools.js');
507
+
508
+ try {
509
+ for await (const chunk of stream) {
510
+ // Check for interrupt at the start of each chunk
511
+ if (this.isInterrupted) {
512
+ logger.flow('Interrupt detected during streaming - stopping');
513
+ throw new Error('INTERRUPTED');
514
+ }
515
+
516
+ buffer += chunk.toString();
517
+ const lines = buffer.split('\n');
518
+ buffer = lines.pop() || '';
519
+
520
+ for (const line of lines) {
521
+ const trimmed = line.trim();
522
+ if (!trimmed || trimmed === 'data: [DONE]') continue;
523
+
524
+ if (trimmed.startsWith('data: ')) {
525
+ try {
526
+ const jsonStr = trimmed.slice(6);
527
+ const data = JSON.parse(jsonStr) as LLMStreamChunk;
528
+ chunkCount++;
529
+
530
+ // Emit reasoning if present in stream (extended thinking)
531
+ // Skip for internal classifier calls
532
+ const reasoningDelta = data.choices[0]?.delta?.reasoning;
533
+ if (reasoningDelta && !isInternalCall) {
534
+ emitReasoning(reasoningDelta, true);
535
+ logger.debug('Reasoning delta emitted', { length: reasoningDelta.length });
536
+ } else if (reasoningDelta && isInternalCall) {
537
+ logger.debug('Reasoning delta skipped (internal call)', { maxTokens });
538
+ }
539
+
540
+ yield data;
541
+ } catch (parseError) {
542
+ // Ignore JSON parsing error (incomplete chunk)
543
+ logger.debug('Skipping invalid chunk', { line: trimmed });
544
+ continue;
545
+ }
546
+ }
547
+ }
548
+ }
549
+ } finally {
550
+ // Clear abort controller after streaming completes
551
+ this.currentAbortController = null;
552
+ }
553
+
554
+ logger.debug('Streaming response completed', { chunkCount });
555
+
556
+ } catch (error) {
557
+ throw this.handleError(error, {
558
+ method: 'POST (stream)',
559
+ url,
560
+ body: options,
561
+ });
562
+ }
563
+ }
564
+
565
+ /**
566
+ * Send simple chat message (helper method)
567
+ */
568
+ async sendMessage(userMessage: string, systemPrompt?: string): Promise<string> {
569
+ logger.enter('sendMessage', {
570
+ messageLength: userMessage.length,
571
+ hasSystemPrompt: !!systemPrompt
572
+ });
573
+
574
+ logger.flow('Constructing message array');
575
+ const messages: Message[] = [];
576
+
577
+ if (systemPrompt) {
578
+ logger.vars({ name: 'systemPrompt', value: systemPrompt.substring(0, 100) + (systemPrompt.length > 100 ? '...' : '') });
579
+ messages.push({
580
+ role: 'system',
581
+ content: systemPrompt,
582
+ });
583
+ }
584
+
585
+ messages.push({
586
+ role: 'user',
587
+ content: userMessage,
588
+ });
589
+
590
+ logger.vars(
591
+ { name: 'totalMessages', value: messages.length },
592
+ { name: 'userMessage', value: userMessage.substring(0, 100) + (userMessage.length > 100 ? '...' : '') }
593
+ );
594
+
595
+ logger.flow('Calling LLM API');
596
+ logger.startTimer('sendMessage-api');
597
+
598
+ const response = await this.chatCompletion({ messages });
599
+
600
+ const elapsed = logger.endTimer('sendMessage-api');
601
+
602
+ logger.flow('Processing response');
603
+ if (response.choices.length === 0) {
604
+ logger.flow('No response - Error occurred');
605
+ logger.exit('sendMessage', { success: false, reason: 'No response from LLM' });
606
+ throw new Error('No response from LLM');
607
+ }
608
+
609
+ const responseContent = response.choices[0]?.message.content || '';
610
+
611
+ logger.vars(
612
+ { name: 'responseLength', value: responseContent.length },
613
+ { name: 'apiTime', value: elapsed }
614
+ );
615
+
616
+ logger.exit('sendMessage', {
617
+ success: true,
618
+ responseLength: responseContent.length,
619
+ elapsed
620
+ });
621
+
622
+ return responseContent;
623
+ }
624
+
625
+ /**
626
+ * Send streaming chat message
627
+ */
628
+ async *sendMessageStream(
629
+ userMessage: string,
630
+ systemPrompt?: string
631
+ ): AsyncGenerator<string, void, unknown> {
632
+ const messages: Message[] = [];
633
+
634
+ if (systemPrompt) {
635
+ messages.push({
636
+ role: 'system',
637
+ content: systemPrompt,
638
+ });
639
+ }
640
+
641
+ messages.push({
642
+ role: 'user',
643
+ content: userMessage,
644
+ });
645
+
646
+ for await (const chunk of this.chatCompletionStream({ messages })) {
647
+ const content = chunk.choices[0]?.delta?.content;
648
+ if (content) {
649
+ yield content;
650
+ }
651
+ }
652
+ }
653
+
654
+ /**
655
+ * Chat Completion with Tools (maintain conversation history)
656
+ * Used in Interactive Mode - supports tool calling with full conversation history
657
+ * No iteration limit - continues until LLM stops calling tools
658
+ *
659
+ * @param messages - Conversation history
660
+ * @param tools - Available tools
661
+ * @param options - Additional options
662
+ * @param options.getPendingMessage - Callback to get pending user message
663
+ * @param options.clearPendingMessage - Callback to clear pending message after processing
664
+ */
665
+ async chatCompletionWithTools(
666
+ messages: Message[],
667
+ tools: import('../../types/index.js').ToolDefinition[],
668
+ options?: {
669
+ getPendingMessage?: () => string | null;
670
+ clearPendingMessage?: () => void;
671
+ }
672
+ ): Promise<{
673
+ message: Message;
674
+ toolCalls: Array<{ tool: string; args: unknown; result: string }>;
675
+ allMessages: Message[];
676
+ }> {
677
+ let workingMessages = [...messages];
678
+ const toolCallHistory: Array<{ tool: string; args: unknown; result: string }> = [];
679
+ let iterations = 0;
680
+ let contextLengthRecoveryAttempted = false; // Prevent infinite recovery loop
681
+ let noToolCallRetries = 0; // Prevent infinite loop when LLM doesn't use tools
682
+ let finalResponseFailures = 0; // Prevent infinite loop when final_response keeps failing
683
+ const MAX_NO_TOOL_CALL_RETRIES = 3; // Max retries for enforcing tool usage
684
+ const MAX_FINAL_RESPONSE_FAILURES = 3; // Max retries for final_response failures
685
+
686
+ while (true) {
687
+ // Check for interrupt at start of each iteration
688
+ if (this.isInterrupted) {
689
+ logger.flow('Interrupt detected - stopping tool loop');
690
+ throw new Error('INTERRUPTED');
691
+ }
692
+
693
+ iterations++;
694
+
695
+ // Check for pending user message and inject it
696
+ if (options?.getPendingMessage && options?.clearPendingMessage) {
697
+ const pendingMsg = options.getPendingMessage();
698
+ if (pendingMsg) {
699
+ logger.flow('Injecting pending user message into conversation');
700
+ workingMessages.push({ role: 'user' as const, content: pendingMsg });
701
+ options.clearPendingMessage();
702
+ }
703
+ }
704
+
705
+ // Call LLM (with tools) - with ContextLengthError recovery
706
+ // tool_choice: 'required' forces LLM to always use a tool (use final_response for final answer)
707
+ let response: LLMResponse;
708
+ try {
709
+ response = await this.chatCompletion({
710
+ messages: workingMessages,
711
+ tools,
712
+ tool_choice: 'required',
713
+ });
714
+ } catch (error) {
715
+ // ContextLengthError recovery: rollback last tool + compact + retry
716
+ if (error instanceof ContextLengthError && !contextLengthRecoveryAttempted) {
717
+ contextLengthRecoveryAttempted = true;
718
+ logger.flow('ContextLengthError detected - attempting recovery with compact');
719
+
720
+ // Rollback: remove last tool results and assistant message with tool_calls
721
+ let rollbackIdx = workingMessages.length - 1;
722
+ while (rollbackIdx >= 0 && workingMessages[rollbackIdx]?.role === 'tool') {
723
+ rollbackIdx--;
724
+ }
725
+ // rollbackIdx now points to last assistant message (with tool_calls)
726
+ if (rollbackIdx >= 0 && workingMessages[rollbackIdx]?.tool_calls) {
727
+ workingMessages = workingMessages.slice(0, rollbackIdx);
728
+ logger.debug('Rolled back messages to before last tool execution', {
729
+ removedCount: workingMessages.length - rollbackIdx,
730
+ });
731
+ }
732
+
733
+ // Execute compact
734
+ const { CompactManager } = await import('../compact/compact-manager.js');
735
+ const { buildCompactedMessages } = await import('../compact/compact-prompts.js');
736
+ const compactManager = new CompactManager(this);
737
+
738
+ const compactResult = await compactManager.compact(workingMessages, {
739
+ workingDirectory: process.cwd(),
740
+ });
741
+
742
+ if (compactResult.success && compactResult.compactedSummary) {
743
+ // Replace workingMessages with compacted result
744
+ const compactedMessages = buildCompactedMessages(compactResult.compactedSummary, {
745
+ workingDirectory: process.cwd(),
746
+ });
747
+ workingMessages = [...compactedMessages];
748
+ logger.flow('Compact completed, retrying with reduced context', {
749
+ originalCount: compactResult.originalMessageCount,
750
+ newCount: compactedMessages.length,
751
+ });
752
+
753
+ // Retry loop
754
+ continue;
755
+ } else {
756
+ // Compact failed - throw original error
757
+ logger.error('Compact failed during recovery', { error: compactResult.error });
758
+ throw error;
759
+ }
760
+ }
761
+
762
+ // Other errors or second ContextLengthError - rethrow
763
+ throw error;
764
+ }
765
+
766
+ // Check for interrupt after LLM call
767
+ if (this.isInterrupted) {
768
+ logger.flow('Interrupt detected after LLM call - stopping');
769
+ throw new Error('INTERRUPTED');
770
+ }
771
+
772
+ const choice = response.choices[0];
773
+ if (!choice) {
774
+ throw new Error('Cannot find choice in response.');
775
+ }
776
+
777
+ const assistantMessage = choice.message;
778
+ workingMessages.push(assistantMessage);
779
+
780
+ // Check tool calls
781
+ if (assistantMessage.tool_calls && assistantMessage.tool_calls.length > 0) {
782
+ // Multi-tool detection logging
783
+ if (assistantMessage.tool_calls.length > 1) {
784
+ const toolNames = assistantMessage.tool_calls.map(tc => tc.function.name).join(', ');
785
+ logger.warn(`[MULTI-TOOL DETECTED] LLM returned ${assistantMessage.tool_calls.length} tools: ${toolNames}`);
786
+ }
787
+
788
+ // Execute tool calls (parallel_tool_calls: false ensures single tool from API)
789
+ for (const toolCall of assistantMessage.tool_calls) {
790
+ const toolName = toolCall.function.name;
791
+ let toolArgs: Record<string, unknown>;
792
+
793
+ try {
794
+ toolArgs = JSON.parse(toolCall.function.arguments) as Record<string, unknown>;
795
+ } catch (parseError) {
796
+ const errorMsg = `Tool argument parsing failed for ${toolName}`;
797
+ logger.error(errorMsg, parseError);
798
+ logger.debug('Raw arguments', { raw: toolCall.function.arguments });
799
+
800
+ workingMessages.push({
801
+ role: 'tool',
802
+ content: `Error: Failed to parse tool arguments - ${parseError instanceof Error ? parseError.message : 'Unknown error'}`,
803
+ tool_call_id: toolCall.id,
804
+ });
805
+
806
+ toolCallHistory.push({
807
+ tool: toolName,
808
+ args: { raw: toolCall.function.arguments },
809
+ result: `Error: Argument parsing failed`,
810
+ });
811
+
812
+ continue;
813
+ }
814
+
815
+ // Execute tool
816
+ const { executeFileTool, requestToolApproval } = await import('../../tools/llm/simple/file-tools.js');
817
+
818
+ // Supervised Mode: Request user approval before tool execution
819
+ const approvalResult = await requestToolApproval(toolName, toolArgs);
820
+
821
+ if (approvalResult && typeof approvalResult === 'object' && approvalResult.reject) {
822
+ // User rejected the tool execution
823
+ logger.flow(`Tool rejected by user: ${toolName}`);
824
+
825
+ const rejectMessage = approvalResult.comment
826
+ ? `Tool execution rejected by user. Reason: ${approvalResult.comment}`
827
+ : 'Tool execution rejected by user.';
828
+
829
+ workingMessages.push({
830
+ role: 'tool',
831
+ content: rejectMessage,
832
+ tool_call_id: toolCall.id,
833
+ });
834
+
835
+ toolCallHistory.push({
836
+ tool: toolName,
837
+ args: toolArgs,
838
+ result: rejectMessage,
839
+ });
840
+
841
+ continue;
842
+ }
843
+
844
+ logger.debug(`Executing tool: ${toolName}`, toolArgs);
845
+
846
+ let result: { success: boolean; result?: string; error?: string; metadata?: Record<string, unknown> };
847
+
848
+ try {
849
+ result = await executeFileTool(toolName, toolArgs);
850
+ logger.toolExecution(toolName, toolArgs, result);
851
+
852
+ // LLM Log mode: Log tool result
853
+ if (isLLMLogEnabled()) {
854
+ logger.llmToolResult(toolName, result.result || '', result.success);
855
+ }
856
+
857
+ // Handle final_response tool
858
+ if (toolName === 'final_response') {
859
+ if (result.success && result.metadata?.['isFinalResponse']) {
860
+ // Success - return immediately
861
+ // Note: emitAssistantResponse is already called via finalResponseCallback in final-response-tool.ts
862
+ logger.flow('final_response tool executed successfully - returning');
863
+
864
+ // Add tool result to messages for completeness
865
+ workingMessages.push({
866
+ role: 'tool',
867
+ content: result.result || '',
868
+ tool_call_id: toolCall.id,
869
+ });
870
+
871
+ // Add to history
872
+ toolCallHistory.push({
873
+ tool: toolName,
874
+ args: toolArgs,
875
+ result: result.result || '',
876
+ });
877
+
878
+ // Return final response
879
+ return {
880
+ message: {
881
+ role: 'assistant' as const,
882
+ content: result.result || '',
883
+ },
884
+ toolCalls: toolCallHistory,
885
+ allMessages: workingMessages,
886
+ };
887
+ } else {
888
+ // Failure - track attempts to prevent infinite loop
889
+ finalResponseFailures++;
890
+ logger.flow(`final_response failed (attempt ${finalResponseFailures}/${MAX_FINAL_RESPONSE_FAILURES}): ${result.error}`);
891
+
892
+ if (finalResponseFailures >= MAX_FINAL_RESPONSE_FAILURES) {
893
+ logger.warn('Max final_response failures exceeded - forcing completion');
894
+ const fallbackMessage = (toolArgs['message'] as string) || 'Task completed with incomplete TODOs.';
895
+
896
+ // Emit as assistant response
897
+ const { emitAssistantResponse } = await import('../../tools/llm/simple/file-tools.js');
898
+ emitAssistantResponse(fallbackMessage);
899
+
900
+ return {
901
+ message: { role: 'assistant' as const, content: fallbackMessage },
902
+ toolCalls: toolCallHistory,
903
+ allMessages: workingMessages,
904
+ };
905
+ }
906
+ }
907
+ }
908
+ } catch (toolError) {
909
+ logger.toolExecution(toolName, toolArgs, undefined, toolError as Error);
910
+
911
+ // LLM Log mode: Log tool error
912
+ if (isLLMLogEnabled()) {
913
+ const errorMsg = toolError instanceof Error ? toolError.message : String(toolError);
914
+ logger.llmToolResult(toolName, `Error: ${errorMsg}`, false);
915
+ }
916
+
917
+ result = {
918
+ success: false,
919
+ error: toolError instanceof Error ? toolError.message : String(toolError),
920
+ };
921
+ }
922
+
923
+ // Add result to messages
924
+ workingMessages.push({
925
+ role: 'tool',
926
+ content: result.success ? result.result || '' : `Error: ${result.error}`,
927
+ tool_call_id: toolCall.id,
928
+ });
929
+
930
+ // Add to history
931
+ toolCallHistory.push({
932
+ tool: toolName,
933
+ args: toolArgs,
934
+ result: result.success ? result.result || '' : `Error: ${result.error}`,
935
+ });
936
+
937
+ // Check for interrupt after tool execution
938
+ if (this.isInterrupted) {
939
+ logger.flow('Interrupt detected after tool execution - stopping');
940
+ throw new Error('INTERRUPTED');
941
+ }
942
+ }
943
+
944
+ // Tool execution complete - Continue calling LLM (continue)
945
+ // Loop continues until LLM returns finish_reason: stop
946
+ continue;
947
+ } else {
948
+ // No tool call - Force tool call
949
+ // LLM must use tools (including final_response)
950
+ noToolCallRetries++;
951
+ logger.flow(`No tool call - enforcing tool usage (attempt ${noToolCallRetries}/${MAX_NO_TOOL_CALL_RETRIES})`);
952
+
953
+ // Max retries exceeded - return content as final response to prevent infinite loop
954
+ if (noToolCallRetries > MAX_NO_TOOL_CALL_RETRIES) {
955
+ logger.warn('Max no-tool-call retries exceeded - returning content as final response');
956
+ const fallbackContent = assistantMessage.content || 'Task completed.';
957
+
958
+ // Emit as assistant response
959
+ const { emitAssistantResponse } = await import('../../tools/llm/simple/file-tools.js');
960
+ emitAssistantResponse(fallbackContent);
961
+
962
+ return {
963
+ message: { role: 'assistant' as const, content: fallbackContent },
964
+ toolCalls: toolCallHistory,
965
+ allMessages: workingMessages,
966
+ };
967
+ }
968
+
969
+ // Check for malformed tool call patterns in content
970
+ const hasMalformedToolCall = assistantMessage.content &&
971
+ (/<tool_call>/i.test(assistantMessage.content) ||
972
+ /<arg_key>/i.test(assistantMessage.content) ||
973
+ /<arg_value>/i.test(assistantMessage.content) ||
974
+ /<\/tool_call>/i.test(assistantMessage.content) ||
975
+ /bash<arg_key>/i.test(assistantMessage.content));
976
+
977
+ const retryMessage = hasMalformedToolCall
978
+ ? 'Your previous response contained a malformed tool call (XML tags in content). You MUST use the proper tool_calls API format. Use final_response tool to deliver your message to the user.'
979
+ : 'You must use tools for all actions. Use final_response tool to deliver your final message to the user after completing all tasks.';
980
+
981
+ // Add assistant message (to preserve context) and retry instruction
982
+ workingMessages.push({
983
+ role: 'user',
984
+ content: retryMessage,
985
+ });
986
+
987
+ logger.debug('Enforcing tool call - added retry message');
988
+
989
+ // Continue loop to retry
990
+ continue;
991
+ }
992
+ }
993
+ }
994
+
995
+ /**
996
+ * Get current model information
997
+ */
998
+ getModelInfo(): { model: string; endpoint: string } {
999
+ return {
1000
+ model: this.modelName,
1001
+ endpoint: this.baseUrl,
1002
+ };
1003
+ }
1004
+
1005
+ /**
1006
+ * Enhanced error handler with detailed logging
1007
+ */
1008
+ private handleError(error: unknown, requestContext?: { method?: string; url?: string; body?: unknown }): Error {
1009
+ // Log the error with context
1010
+ logger.error('LLM Client Error', error);
1011
+
1012
+ if (requestContext) {
1013
+ logger.debug('Request Context', requestContext);
1014
+ }
1015
+
1016
+ if (axios.isAxiosError(error)) {
1017
+ const axiosError = error as AxiosError;
1018
+
1019
+ // Timeout error
1020
+ if (axiosError.code === 'ECONNABORTED' || axiosError.message.includes('timeout')) {
1021
+ logger.error('Request Timeout', {
1022
+ timeout: this.axiosInstance.defaults.timeout,
1023
+ endpoint: this.baseUrl,
1024
+ });
1025
+ return new TimeoutError(
1026
+ this.axiosInstance.defaults.timeout || 60000,
1027
+ {
1028
+ cause: axiosError,
1029
+ details: {
1030
+ endpoint: this.baseUrl,
1031
+ method: requestContext?.method,
1032
+ url: requestContext?.url,
1033
+ },
1034
+ }
1035
+ );
1036
+ }
1037
+
1038
+ if (axiosError.response) {
1039
+ // Server responded with error status (4xx, 5xx)
1040
+ const status = axiosError.response.status;
1041
+ const data = axiosError.response.data as any;
1042
+ const errorMessage = data?.error?.message || data?.message || axiosError.message;
1043
+ const errorType = data?.error?.type || 'unknown';
1044
+ const errorCode = data?.error?.code || data?.code;
1045
+
1046
+ // Enhanced error logging for debugging
1047
+ logger.error('=== API ERROR DETAILS ===', {
1048
+ status,
1049
+ statusText: axiosError.response.statusText,
1050
+ endpoint: this.baseUrl,
1051
+ model: this.model,
1052
+ errorMessage,
1053
+ errorType,
1054
+ errorCode,
1055
+ // Full API response body
1056
+ responseBody: JSON.stringify(data, null, 2),
1057
+ // Request info
1058
+ requestMethod: requestContext?.method,
1059
+ requestUrl: requestContext?.url,
1060
+ // Request body (truncated for large payloads)
1061
+ requestBody: requestContext?.body
1062
+ ? JSON.stringify(requestContext.body, null, 2).substring(0, 5000)
1063
+ : undefined,
1064
+ // Response headers
1065
+ responseHeaders: axiosError.response.headers,
1066
+ });
1067
+
1068
+ logger.httpResponse(status, axiosError.response.statusText, data);
1069
+
1070
+ // Context length exceeded (common OpenAI error)
1071
+ if (
1072
+ errorType === 'invalid_request_error' &&
1073
+ (errorMessage.includes('context_length_exceeded') ||
1074
+ errorMessage.includes('maximum context length') ||
1075
+ errorCode === 'context_length_exceeded')
1076
+ ) {
1077
+ const maxLength = data?.error?.param?.max_tokens || 'unknown';
1078
+ logger.error('Context Length Exceeded', {
1079
+ maxLength,
1080
+ errorMessage,
1081
+ model: this.model,
1082
+ });
1083
+
1084
+ return new ContextLengthError(
1085
+ typeof maxLength === 'number' ? maxLength : 0,
1086
+ undefined,
1087
+ {
1088
+ cause: axiosError,
1089
+ details: {
1090
+ model: this.model,
1091
+ endpoint: this.baseUrl,
1092
+ errorType,
1093
+ fullError: data,
1094
+ },
1095
+ }
1096
+ );
1097
+ }
1098
+
1099
+ // Token limit error
1100
+ if (
1101
+ errorMessage.includes('token') &&
1102
+ (errorMessage.includes('limit') || errorMessage.includes('exceeded'))
1103
+ ) {
1104
+ logger.error('Token Limit Error', {
1105
+ errorMessage,
1106
+ model: this.model,
1107
+ });
1108
+
1109
+ return new TokenLimitError(
1110
+ 0, // We don't know the exact limit from error message
1111
+ undefined,
1112
+ {
1113
+ cause: axiosError,
1114
+ details: {
1115
+ model: this.model,
1116
+ endpoint: this.baseUrl,
1117
+ fullError: data,
1118
+ },
1119
+ userMessage: errorMessage,
1120
+ }
1121
+ );
1122
+ }
1123
+
1124
+ // Rate limit (429)
1125
+ if (status === 429) {
1126
+ const retryAfter = axiosError.response.headers['retry-after'];
1127
+ const retrySeconds = retryAfter ? parseInt(retryAfter) : undefined;
1128
+
1129
+ logger.error('Rate Limit Exceeded', {
1130
+ retryAfter: retrySeconds,
1131
+ errorMessage,
1132
+ });
1133
+
1134
+ return new RateLimitError(retrySeconds, {
1135
+ cause: axiosError,
1136
+ details: {
1137
+ endpoint: this.baseUrl,
1138
+ model: this.model,
1139
+ fullError: data,
1140
+ },
1141
+ });
1142
+ }
1143
+
1144
+ // Authentication error (401)
1145
+ if (status === 401) {
1146
+ logger.error('Authentication Failed', {
1147
+ endpoint: this.baseUrl,
1148
+ errorMessage,
1149
+ });
1150
+
1151
+ return new APIError(
1152
+ `Authentication failed: ${errorMessage}`,
1153
+ status,
1154
+ this.baseUrl,
1155
+ {
1156
+ cause: axiosError,
1157
+ details: {
1158
+ apiKeyProvided: !!this.apiKey,
1159
+ apiKeyLength: this.apiKey?.length || 0,
1160
+ fullError: data,
1161
+ },
1162
+ isRecoverable: false,
1163
+ userMessage: `Invalid API key. Please check your settings.\nDetails: ${errorMessage}`,
1164
+ }
1165
+ );
1166
+ }
1167
+
1168
+ // Forbidden (403)
1169
+ if (status === 403) {
1170
+ logger.error('Access Forbidden', {
1171
+ endpoint: this.baseUrl,
1172
+ errorMessage,
1173
+ });
1174
+
1175
+ return new APIError(
1176
+ `Access denied: ${errorMessage}`,
1177
+ status,
1178
+ this.baseUrl,
1179
+ {
1180
+ cause: axiosError,
1181
+ details: {
1182
+ fullError: data,
1183
+ },
1184
+ isRecoverable: false,
1185
+ }
1186
+ );
1187
+ }
1188
+
1189
+ // Not found (404)
1190
+ if (status === 404) {
1191
+ logger.error('Endpoint Not Found', {
1192
+ endpoint: this.baseUrl,
1193
+ url: requestContext?.url,
1194
+ errorMessage,
1195
+ });
1196
+
1197
+ return new APIError(
1198
+ `Endpoint not found: ${errorMessage}`,
1199
+ status,
1200
+ this.baseUrl,
1201
+ {
1202
+ cause: axiosError,
1203
+ details: {
1204
+ url: requestContext?.url,
1205
+ fullError: data,
1206
+ },
1207
+ isRecoverable: false,
1208
+ userMessage: `API endpoint does not exist.\nURL: ${this.baseUrl}${requestContext?.url || ''}\nDetails: ${errorMessage}`,
1209
+ }
1210
+ );
1211
+ }
1212
+
1213
+ // Server error (5xx)
1214
+ if (status >= 500) {
1215
+ logger.error('Server Error', {
1216
+ status,
1217
+ endpoint: this.baseUrl,
1218
+ errorMessage,
1219
+ });
1220
+
1221
+ return new APIError(
1222
+ `Server error (${status}): ${errorMessage}`,
1223
+ status,
1224
+ this.baseUrl,
1225
+ {
1226
+ cause: axiosError,
1227
+ details: {
1228
+ fullError: data,
1229
+ },
1230
+ isRecoverable: true, // Server errors are usually temporary
1231
+ }
1232
+ );
1233
+ }
1234
+
1235
+ // Other API errors (4xx)
1236
+ logger.error('API Error', {
1237
+ status,
1238
+ endpoint: this.baseUrl,
1239
+ errorMessage,
1240
+ errorType,
1241
+ errorCode,
1242
+ });
1243
+
1244
+ return new APIError(
1245
+ `API error (${status}): ${errorMessage}`,
1246
+ status,
1247
+ this.baseUrl,
1248
+ {
1249
+ cause: axiosError,
1250
+ details: {
1251
+ errorType,
1252
+ errorCode,
1253
+ fullError: data,
1254
+ },
1255
+ userMessage: `API request failed (${status}):\n${errorMessage}\n\nError type: ${errorType}\nError code: ${errorCode}`,
1256
+ }
1257
+ );
1258
+
1259
+ } else if (axiosError.request) {
1260
+ // Request sent but no response received (network error)
1261
+ const errorCode = axiosError.code;
1262
+
1263
+ logger.error('Network Error - No Response', {
1264
+ code: errorCode,
1265
+ endpoint: this.baseUrl,
1266
+ message: axiosError.message,
1267
+ });
1268
+
1269
+ // Connection refused, host not found, etc.
1270
+ if (
1271
+ errorCode === 'ECONNREFUSED' ||
1272
+ errorCode === 'ENOTFOUND' ||
1273
+ errorCode === 'ECONNRESET' ||
1274
+ errorCode === 'EHOSTUNREACH'
1275
+ ) {
1276
+ return new ConnectionError(this.baseUrl, {
1277
+ cause: axiosError,
1278
+ details: {
1279
+ code: errorCode,
1280
+ message: axiosError.message,
1281
+ },
1282
+ userMessage: `Cannot connect to server.\nEndpoint: ${this.baseUrl}\nError code: ${errorCode}\nDetails: ${axiosError.message}\n\nPlease check network connection and endpoint URL.`,
1283
+ });
1284
+ }
1285
+
1286
+ // General network error
1287
+ return new NetworkError(
1288
+ `Network error: ${axiosError.message}`,
1289
+ {
1290
+ cause: axiosError,
1291
+ details: {
1292
+ code: errorCode,
1293
+ endpoint: this.baseUrl,
1294
+ },
1295
+ userMessage: `Network connection failed.\nEndpoint: ${this.baseUrl}\nError: ${axiosError.message}`,
1296
+ }
1297
+ );
1298
+ }
1299
+
1300
+ // Axios error without response or request
1301
+ logger.error('Axios Error', {
1302
+ code: axiosError.code,
1303
+ message: axiosError.message,
1304
+ });
1305
+
1306
+ return new LLMError(
1307
+ `LLM client error: ${axiosError.message}`,
1308
+ {
1309
+ cause: axiosError,
1310
+ details: {
1311
+ code: axiosError.code,
1312
+ },
1313
+ }
1314
+ );
1315
+ }
1316
+
1317
+ // Non-axios error
1318
+ if (error instanceof Error) {
1319
+ logger.error('Unexpected Error', error);
1320
+ return new LLMError(
1321
+ `Unexpected error: ${error.message}`,
1322
+ {
1323
+ cause: error,
1324
+ userMessage: `An error occurred:\n${error.message}\n\nStack:\n${error.stack}`,
1325
+ }
1326
+ );
1327
+ }
1328
+
1329
+ // Unknown error type
1330
+ logger.error('Unknown Error Type', { error });
1331
+ return new LLMError('An unknown error occurred.', {
1332
+ details: { unknownError: error },
1333
+ });
1334
+ }
1335
+
1336
+ /**
1337
+ * Chat Completion with retry logic
1338
+ * @deprecated chatCompletion now performs retry by default
1339
+ */
1340
+ async chatCompletionWithRetry(
1341
+ options: Partial<LLMRequestOptions>,
1342
+ maxRetries = 3
1343
+ ): Promise<LLMResponse> {
1344
+ // Call directly as chatCompletion now performs retry internally
1345
+ return this.chatCompletion(options, { maxRetries });
1346
+ }
1347
+
1348
+ /**
1349
+ * Health check for currently configured endpoint
1350
+ */
1351
+ async healthCheck(): Promise<{
1352
+ success: boolean;
1353
+ latency?: number;
1354
+ error?: string;
1355
+ }> {
1356
+ const endpoint = configManager.getCurrentEndpoint();
1357
+ const model = configManager.getCurrentModel();
1358
+
1359
+ if (!endpoint || !model) {
1360
+ return { success: false, error: 'No endpoint or model configured' };
1361
+ }
1362
+
1363
+ const startTime = Date.now();
1364
+
1365
+ try {
1366
+ const response = await this.axiosInstance.post<LLMResponse>('/chat/completions', {
1367
+ model: model.id,
1368
+ messages: [{ role: 'user', content: 'ping' }],
1369
+ max_tokens: 5,
1370
+ });
1371
+
1372
+ const latency = Date.now() - startTime;
1373
+
1374
+ if (response.status === 200 && response.data.choices?.[0]?.message) {
1375
+ return { success: true, latency };
1376
+ } else {
1377
+ return { success: false, latency, error: 'Invalid response format' };
1378
+ }
1379
+ } catch (error) {
1380
+ const latency = Date.now() - startTime;
1381
+ const axiosError = error as AxiosError;
1382
+
1383
+ if (axiosError.response) {
1384
+ const status = axiosError.response.status;
1385
+ return { success: false, latency, error: `HTTP ${status}` };
1386
+ } else if (axiosError.request) {
1387
+ return { success: false, latency, error: 'Connection failed' };
1388
+ } else {
1389
+ return { success: false, latency, error: axiosError.message || 'Unknown error' };
1390
+ }
1391
+ }
1392
+ }
1393
+
1394
+ /**
1395
+ * Bulk health check for all registered endpoints
1396
+ */
1397
+ static async healthCheckAll(): Promise<
1398
+ Map<string, { modelId: string; healthy: boolean; latency?: number; error?: string }[]>
1399
+ > {
1400
+ const endpoints = configManager.getAllEndpoints();
1401
+ const results = new Map<
1402
+ string,
1403
+ { modelId: string; healthy: boolean; latency?: number; error?: string }[]
1404
+ >();
1405
+
1406
+ for (const endpoint of endpoints) {
1407
+ const modelResults: { modelId: string; healthy: boolean; latency?: number; error?: string }[] = [];
1408
+
1409
+ for (const model of endpoint.models) {
1410
+ if (!model.enabled) {
1411
+ modelResults.push({
1412
+ modelId: model.id,
1413
+ healthy: false,
1414
+ error: 'Model disabled',
1415
+ });
1416
+ continue;
1417
+ }
1418
+
1419
+ const startTime = Date.now();
1420
+
1421
+ try {
1422
+ const axiosInstance = axios.create({
1423
+ baseURL: endpoint.baseUrl,
1424
+ headers: {
1425
+ 'Content-Type': 'application/json',
1426
+ ...(endpoint.apiKey && { Authorization: `Bearer ${endpoint.apiKey}` }),
1427
+ },
1428
+ timeout: 30000, // 30 second timeout
1429
+ });
1430
+
1431
+ const response = await axiosInstance.post<LLMResponse>('/chat/completions', {
1432
+ model: model.id,
1433
+ messages: [{ role: 'user', content: 'ping' }],
1434
+ max_tokens: 5,
1435
+ });
1436
+
1437
+ const latency = Date.now() - startTime;
1438
+
1439
+ if (response.status === 200 && response.data.choices?.[0]?.message) {
1440
+ modelResults.push({ modelId: model.id, healthy: true, latency });
1441
+ } else {
1442
+ modelResults.push({
1443
+ modelId: model.id,
1444
+ healthy: false,
1445
+ latency,
1446
+ error: 'Invalid response',
1447
+ });
1448
+ }
1449
+ } catch (error) {
1450
+ const latency = Date.now() - startTime;
1451
+ const axiosError = error as AxiosError;
1452
+
1453
+ let errorMessage = 'Unknown error';
1454
+ if (axiosError.response) {
1455
+ errorMessage = `HTTP ${axiosError.response.status}`;
1456
+ } else if (axiosError.code === 'ECONNREFUSED') {
1457
+ errorMessage = 'Connection refused';
1458
+ } else if (axiosError.code === 'ETIMEDOUT' || axiosError.code === 'ECONNABORTED') {
1459
+ errorMessage = 'Timeout';
1460
+ } else if (axiosError.request) {
1461
+ errorMessage = 'Network error';
1462
+ }
1463
+
1464
+ modelResults.push({
1465
+ modelId: model.id,
1466
+ healthy: false,
1467
+ latency,
1468
+ error: errorMessage,
1469
+ });
1470
+ }
1471
+ }
1472
+
1473
+ results.set(endpoint.id, modelResults);
1474
+ }
1475
+
1476
+ return results;
1477
+ }
1478
+
1479
+ /**
1480
+ * Endpoint connection test (Static)
1481
+ * Static method for use during config init
1482
+ */
1483
+ static async testConnection(
1484
+ baseUrl: string,
1485
+ apiKey: string,
1486
+ model: string
1487
+ ): Promise<{ success: boolean; latency?: number; error?: string }> {
1488
+ const startTime = Date.now();
1489
+
1490
+ try {
1491
+ const axiosInstance = axios.create({
1492
+ baseURL: baseUrl,
1493
+ headers: {
1494
+ 'Content-Type': 'application/json',
1495
+ ...(apiKey && { Authorization: `Bearer ${apiKey}` }),
1496
+ },
1497
+ timeout: 60000, // 60 second timeout
1498
+ });
1499
+
1500
+ // Verify connection with simple test message
1501
+ const response = await axiosInstance.post<LLMResponse>('/chat/completions', {
1502
+ model: model,
1503
+ messages: [
1504
+ {
1505
+ role: 'user',
1506
+ content: 'test',
1507
+ },
1508
+ ],
1509
+ max_tokens: 10,
1510
+ });
1511
+
1512
+ const latency = Date.now() - startTime;
1513
+
1514
+ if (response.status === 200 && response.data.choices?.[0]?.message) {
1515
+ return { success: true, latency };
1516
+ } else {
1517
+ return { success: false, latency, error: 'Invalid response format' };
1518
+ }
1519
+ } catch (error) {
1520
+ const latency = Date.now() - startTime;
1521
+ const axiosError = error as AxiosError;
1522
+
1523
+ if (axiosError.response) {
1524
+ const status = axiosError.response.status;
1525
+ const data = axiosError.response.data as { error?: { message?: string } };
1526
+ const message = data?.error?.message || axiosError.message;
1527
+
1528
+ if (status === 401) {
1529
+ return { success: false, latency, error: 'Invalid API key.' };
1530
+ } else if (status === 404) {
1531
+ return { success: false, latency, error: 'Endpoint or model not found.' };
1532
+ } else {
1533
+ return { success: false, latency, error: `API error (${status}): ${message}` };
1534
+ }
1535
+ } else if (axiosError.request) {
1536
+ return { success: false, latency, error: `Network error: Cannot connect to endpoint.` };
1537
+ } else {
1538
+ return { success: false, latency, error: axiosError.message || 'Unknown error' };
1539
+ }
1540
+ }
1541
+ }
1542
+ }
1543
+
1544
+ /**
1545
+ * LLMClient singleton instance
1546
+ * Available after ConfigManager initialization
1547
+ */
1548
+ export function createLLMClient(): LLMClient {
1549
+ return new LLMClient();
1550
+ }