aemeathcli 1.0.11 → 1.0.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 (218) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +620 -609
  3. package/dist/{App-YAHJUWCX.js → App-JQ622M66.js} +209 -52
  4. package/dist/App-JQ622M66.js.map +1 -0
  5. package/dist/agent-store/architect.md +32 -32
  6. package/dist/agent-store/debugger.md +32 -32
  7. package/dist/agent-store/developer.md +29 -29
  8. package/dist/agent-store/documenter.md +30 -30
  9. package/dist/agent-store/researcher.md +31 -31
  10. package/dist/agent-store/reviewer.md +28 -28
  11. package/dist/agent-store/supervisor.md +37 -37
  12. package/dist/agent-store/tester.md +30 -30
  13. package/dist/api-key-fallback-RJLPM3KH.js +11 -0
  14. package/dist/{api-key-fallback-UN3TJEOO.js.map → api-key-fallback-RJLPM3KH.js.map} +1 -1
  15. package/dist/auth-status-JQJOKUPF.js +13 -0
  16. package/dist/{auth-status-EIM5A5KL.js.map → auth-status-JQJOKUPF.js.map} +1 -1
  17. package/dist/{chunk-P66WDACW.js → chunk-2KMA5RBC.js} +18 -42
  18. package/dist/chunk-2KMA5RBC.js.map +1 -0
  19. package/dist/{chunk-2GKOK6T7.js → chunk-2Y7TR6BS.js} +2 -2
  20. package/dist/chunk-2Y7TR6BS.js.map +1 -0
  21. package/dist/{chunk-ONQ4WCUI.js → chunk-2ZYK5IJG.js} +6 -6
  22. package/dist/chunk-2ZYK5IJG.js.map +1 -0
  23. package/dist/{chunk-OCJPQFOR.js → chunk-36RXCZOV.js} +4 -4
  24. package/dist/chunk-36RXCZOV.js.map +1 -0
  25. package/dist/{chunk-H2SYKIMI.js → chunk-7EBLXPL4.js} +10 -10
  26. package/dist/chunk-7EBLXPL4.js.map +1 -0
  27. package/dist/{chunk-IARA5XYP.js → chunk-BIMQL4AG.js} +4 -4
  28. package/dist/chunk-BIMQL4AG.js.map +1 -0
  29. package/dist/{chunk-BY4DAKUU.js → chunk-D275MCIH.js} +2 -2
  30. package/dist/chunk-D275MCIH.js.map +1 -0
  31. package/dist/{chunk-SOQFMNQC.js → chunk-FFS4T7BZ.js} +5 -5
  32. package/dist/chunk-FFS4T7BZ.js.map +1 -0
  33. package/dist/{chunk-LDVY5ELP.js → chunk-GXAJGP2T.js} +5 -5
  34. package/dist/chunk-GXAJGP2T.js.map +1 -0
  35. package/dist/{chunk-62HSGYQD.js → chunk-HCIHOHLX.js} +2 -2
  36. package/dist/chunk-HCIHOHLX.js.map +1 -0
  37. package/dist/{chunk-6GUD7QIM.js → chunk-HESQLCLU.js} +4 -4
  38. package/dist/chunk-HESQLCLU.js.map +1 -0
  39. package/dist/{chunk-HEKFAKVH.js → chunk-IR5HLBMH.js} +2 -2
  40. package/dist/chunk-IR5HLBMH.js.map +1 -0
  41. package/dist/{chunk-2LF7ALGR.js → chunk-K2FCMRXH.js} +4 -4
  42. package/dist/chunk-K2FCMRXH.js.map +1 -0
  43. package/dist/{chunk-2NWNIKBK.js → chunk-KIC7UI5U.js} +4 -4
  44. package/dist/chunk-KIC7UI5U.js.map +1 -0
  45. package/dist/{chunk-YPFOE2QJ.js → chunk-KMOAJRDE.js} +5 -5
  46. package/dist/chunk-KMOAJRDE.js.map +1 -0
  47. package/dist/{chunk-RP2TAL3J.js → chunk-LQBALETG.js} +2 -2
  48. package/dist/chunk-LQBALETG.js.map +1 -0
  49. package/dist/{chunk-CC7MGWYY.js → chunk-M3FPQSRU.js} +2 -2
  50. package/dist/chunk-M3FPQSRU.js.map +1 -0
  51. package/dist/{chunk-3TSPZRGM.js → chunk-NQEUK763.js} +3 -3
  52. package/dist/chunk-NQEUK763.js.map +1 -0
  53. package/dist/{chunk-VBLLDY4R.js → chunk-OPWAFS6Y.js} +2 -2
  54. package/dist/chunk-OPWAFS6Y.js.map +1 -0
  55. package/dist/{chunk-RYOB3TLZ.js → chunk-PS4WEFW6.js} +6 -6
  56. package/dist/chunk-PS4WEFW6.js.map +1 -0
  57. package/dist/{chunk-LCYH4T6N.js → chunk-QK7TKNHV.js} +6 -6
  58. package/dist/chunk-QK7TKNHV.js.map +1 -0
  59. package/dist/{chunk-QCRK4QEL.js → chunk-RADJSEG5.js} +3 -3
  60. package/dist/chunk-RADJSEG5.js.map +1 -0
  61. package/dist/{chunk-AQ23TYSQ.js → chunk-SNWPI6XJ.js} +4 -4
  62. package/dist/chunk-SNWPI6XJ.js.map +1 -0
  63. package/dist/{chunk-TDFTX32B.js → chunk-UM7MSLOV.js} +4 -4
  64. package/dist/chunk-UM7MSLOV.js.map +1 -0
  65. package/dist/{chunk-FIC7AK4Q.js → chunk-VNZ3YTQD.js} +5 -5
  66. package/dist/chunk-VNZ3YTQD.js.map +1 -0
  67. package/dist/{chunk-5XFSV6PF.js → chunk-WXIN65UG.js} +6 -6
  68. package/dist/chunk-WXIN65UG.js.map +1 -0
  69. package/dist/{chunk-WC72BRHR.js → chunk-XEXWX7C7.js} +3 -3
  70. package/dist/chunk-XEXWX7C7.js.map +1 -0
  71. package/dist/{chunk-VJNQJALF.js → chunk-YCCYXDW7.js} +4 -4
  72. package/dist/chunk-YCCYXDW7.js.map +1 -0
  73. package/dist/{chunk-ROJPFPJ7.js → chunk-YL5XFHR3.js} +2 -2
  74. package/dist/chunk-YL5XFHR3.js.map +1 -0
  75. package/dist/{chunk-GU33WKPG.js → chunk-YPQ2MLAV.js} +5 -5
  76. package/dist/chunk-YPQ2MLAV.js.map +1 -0
  77. package/dist/{chunk-WAYSJMPS.js → chunk-ZCOVMVK4.js} +2 -2
  78. package/dist/chunk-ZCOVMVK4.js.map +1 -0
  79. package/dist/{chunk-473JN6M5.js → chunk-ZGOHARPV.js} +2 -2
  80. package/dist/chunk-ZGOHARPV.js.map +1 -0
  81. package/dist/{claude-login-IS5WTBMP.js → claude-login-AIFIWTYF.js} +10 -10
  82. package/dist/claude-login-AIFIWTYF.js.map +1 -0
  83. package/dist/cli.js +30 -30
  84. package/dist/cli.js.map +1 -1
  85. package/dist/{codex-login-GMPF64MR.js → codex-login-LW5X7GAM.js} +10 -10
  86. package/dist/codex-login-LW5X7GAM.js.map +1 -0
  87. package/dist/config-store-NF56VHFU.js +7 -0
  88. package/dist/{config-store-POB6I37G.js.map → config-store-NF56VHFU.js.map} +1 -1
  89. package/dist/conversation-store-7GRDQZD2.js +4 -0
  90. package/dist/{conversation-store-PRBHWQMJ.js.map → conversation-store-7GRDQZD2.js.map} +1 -1
  91. package/dist/detect-providers-QICJ5U3R.js +4 -0
  92. package/dist/{detect-providers-C4SVQHFF.js.map → detect-providers-QICJ5U3R.js.map} +1 -1
  93. package/dist/executor-FTABX2AW.js +4 -0
  94. package/dist/{executor-RUX7VK3T.js.map → executor-FTABX2AW.js.map} +1 -1
  95. package/dist/{first-run-GDEVRFPO.js → first-run-ADROZVYF.js} +13 -13
  96. package/dist/first-run-ADROZVYF.js.map +1 -0
  97. package/dist/{gemini-login-KE224MSW.js → gemini-login-TST454MX.js} +10 -10
  98. package/dist/gemini-login-TST454MX.js.map +1 -0
  99. package/dist/index.d.ts +2 -56
  100. package/dist/index.js +30 -34
  101. package/dist/index.js.map +1 -1
  102. package/dist/{input-history-MIOO3FIW.js → input-history-BEICE7PT.js} +3 -3
  103. package/dist/input-history-BEICE7PT.js.map +1 -0
  104. package/dist/kimi-adapter-7FYOAKOI.js +6 -0
  105. package/dist/{kimi-adapter-UODMNX6K.js.map → kimi-adapter-7FYOAKOI.js.map} +1 -1
  106. package/dist/{kimi-login-DNT5YBKX.js → kimi-login-3IGVOBJI.js} +10 -10
  107. package/dist/kimi-login-3IGVOBJI.js.map +1 -0
  108. package/dist/logger-KGHUQ4VE.js +3 -0
  109. package/dist/{logger-PLPDWACQ.js.map → logger-KGHUQ4VE.js.map} +1 -1
  110. package/dist/model-discovery-AAJDHRFO.js +6 -0
  111. package/dist/{model-discovery-O64ZWPX5.js.map → model-discovery-AAJDHRFO.js.map} +1 -1
  112. package/dist/native-cli-adapters-CLONTZOA.js +8 -0
  113. package/dist/{native-cli-adapters-JMZX2C2C.js.map → native-cli-adapters-CLONTZOA.js.map} +1 -1
  114. package/dist/ollama-adapter-2N5OQIEV.js +5 -0
  115. package/dist/{ollama-adapter-GE67BNSS.js.map → ollama-adapter-2N5OQIEV.js.map} +1 -1
  116. package/dist/{pathResolver-A6IXQQFE.js → pathResolver-UVAB2FCW.js} +3 -3
  117. package/dist/{pathResolver-A6IXQQFE.js.map → pathResolver-UVAB2FCW.js.map} +1 -1
  118. package/dist/{profile-loader-TNAXBLDX.js → profile-loader-EMLV4J7S.js} +4 -4
  119. package/dist/profile-loader-EMLV4J7S.js.map +1 -0
  120. package/dist/registry-LRURZVUL.js +5 -0
  121. package/dist/{registry-3NHVCXCZ.js.map → registry-LRURZVUL.js.map} +1 -1
  122. package/dist/registry-MVNSXCEF.js +6 -0
  123. package/dist/{registry-7CQ3NCAD.js.map → registry-MVNSXCEF.js.map} +1 -1
  124. package/dist/server-manager-THGZBBZB.js +5 -0
  125. package/dist/{server-manager-DES23IBQ.js.map → server-manager-THGZBBZB.js.map} +1 -1
  126. package/dist/session-manager-X3DXT53M.js +12 -0
  127. package/dist/{session-manager-EHD7GWM2.js.map → session-manager-X3DXT53M.js.map} +1 -1
  128. package/dist/skills/built-in/code-review/SKILL.md +85 -85
  129. package/dist/skills/built-in/commit/SKILL.md +83 -83
  130. package/dist/skills/built-in/debug/SKILL.md +119 -119
  131. package/dist/skills/built-in/plan/SKILL.md +123 -123
  132. package/dist/skills/built-in/refactor/SKILL.md +132 -132
  133. package/dist/skills/built-in/test/SKILL.md +128 -128
  134. package/dist/sqlite-store-7OECRTXM.js +5 -0
  135. package/dist/{sqlite-store-7ZIVOUNI.js.map → sqlite-store-7OECRTXM.js.map} +1 -1
  136. package/dist/team-manager-2VSMALAA.js +11 -0
  137. package/dist/{team-manager-6DCNLGTC.js.map → team-manager-2VSMALAA.js.map} +1 -1
  138. package/dist/team-state-HZNVMQHT.js +3 -0
  139. package/dist/{team-state-R2D7DT5M.js.map → team-state-HZNVMQHT.js.map} +1 -1
  140. package/dist/tmux-manager-57QCUVHU.js +6 -0
  141. package/dist/{tmux-manager-WBKHUHDT.js.map → tmux-manager-57QCUVHU.js.map} +1 -1
  142. package/dist/tools-KWFSYT56.js +6 -0
  143. package/dist/{tools-I6XCTEZY.js.map → tools-KWFSYT56.js.map} +1 -1
  144. package/package.json +89 -93
  145. package/dist/App-YAHJUWCX.js.map +0 -1
  146. package/dist/api-key-fallback-UN3TJEOO.js +0 -11
  147. package/dist/auth-status-EIM5A5KL.js +0 -13
  148. package/dist/chunk-25UNNEHN.js +0 -140
  149. package/dist/chunk-25UNNEHN.js.map +0 -1
  150. package/dist/chunk-2GKOK6T7.js.map +0 -1
  151. package/dist/chunk-2LF7ALGR.js.map +0 -1
  152. package/dist/chunk-2NWNIKBK.js.map +0 -1
  153. package/dist/chunk-3TSPZRGM.js.map +0 -1
  154. package/dist/chunk-473JN6M5.js.map +0 -1
  155. package/dist/chunk-5XFSV6PF.js.map +0 -1
  156. package/dist/chunk-62HSGYQD.js.map +0 -1
  157. package/dist/chunk-6GUD7QIM.js.map +0 -1
  158. package/dist/chunk-AQ23TYSQ.js.map +0 -1
  159. package/dist/chunk-BY4DAKUU.js.map +0 -1
  160. package/dist/chunk-CC7MGWYY.js.map +0 -1
  161. package/dist/chunk-CTFZTARK.js +0 -155
  162. package/dist/chunk-CTFZTARK.js.map +0 -1
  163. package/dist/chunk-FIC7AK4Q.js.map +0 -1
  164. package/dist/chunk-GU33WKPG.js.map +0 -1
  165. package/dist/chunk-H2SYKIMI.js.map +0 -1
  166. package/dist/chunk-HEKFAKVH.js.map +0 -1
  167. package/dist/chunk-IARA5XYP.js.map +0 -1
  168. package/dist/chunk-LCYH4T6N.js.map +0 -1
  169. package/dist/chunk-LDVY5ELP.js.map +0 -1
  170. package/dist/chunk-OCJPQFOR.js.map +0 -1
  171. package/dist/chunk-ODBY7S4X.js +0 -141
  172. package/dist/chunk-ODBY7S4X.js.map +0 -1
  173. package/dist/chunk-ONQ4WCUI.js.map +0 -1
  174. package/dist/chunk-P5TKZM3T.js +0 -159
  175. package/dist/chunk-P5TKZM3T.js.map +0 -1
  176. package/dist/chunk-P66WDACW.js.map +0 -1
  177. package/dist/chunk-QCRK4QEL.js.map +0 -1
  178. package/dist/chunk-ROJPFPJ7.js.map +0 -1
  179. package/dist/chunk-RP2TAL3J.js.map +0 -1
  180. package/dist/chunk-RYOB3TLZ.js.map +0 -1
  181. package/dist/chunk-SOQFMNQC.js.map +0 -1
  182. package/dist/chunk-TDFTX32B.js.map +0 -1
  183. package/dist/chunk-VBLLDY4R.js.map +0 -1
  184. package/dist/chunk-VJNQJALF.js.map +0 -1
  185. package/dist/chunk-WAYSJMPS.js.map +0 -1
  186. package/dist/chunk-WC72BRHR.js.map +0 -1
  187. package/dist/chunk-YPFOE2QJ.js.map +0 -1
  188. package/dist/claude-adapter-6P4SJH7P.js +0 -7
  189. package/dist/claude-adapter-6P4SJH7P.js.map +0 -1
  190. package/dist/claude-login-IS5WTBMP.js.map +0 -1
  191. package/dist/codex-login-GMPF64MR.js.map +0 -1
  192. package/dist/config-store-POB6I37G.js +0 -7
  193. package/dist/conversation-store-PRBHWQMJ.js +0 -4
  194. package/dist/detect-providers-C4SVQHFF.js +0 -4
  195. package/dist/executor-RUX7VK3T.js +0 -4
  196. package/dist/first-run-GDEVRFPO.js.map +0 -1
  197. package/dist/gemini-adapter-MV3U4QFH.js +0 -7
  198. package/dist/gemini-adapter-MV3U4QFH.js.map +0 -1
  199. package/dist/gemini-login-KE224MSW.js.map +0 -1
  200. package/dist/input-history-MIOO3FIW.js.map +0 -1
  201. package/dist/kimi-adapter-UODMNX6K.js +0 -6
  202. package/dist/kimi-login-DNT5YBKX.js.map +0 -1
  203. package/dist/logger-PLPDWACQ.js +0 -3
  204. package/dist/model-discovery-O64ZWPX5.js +0 -6
  205. package/dist/native-cli-adapters-JMZX2C2C.js +0 -8
  206. package/dist/ollama-adapter-GE67BNSS.js +0 -5
  207. package/dist/openai-adapter-SHPLK77L.js +0 -7
  208. package/dist/openai-adapter-SHPLK77L.js.map +0 -1
  209. package/dist/profile-loader-TNAXBLDX.js.map +0 -1
  210. package/dist/registry-3NHVCXCZ.js +0 -6
  211. package/dist/registry-7CQ3NCAD.js +0 -5
  212. package/dist/server-manager-DES23IBQ.js +0 -5
  213. package/dist/session-manager-EHD7GWM2.js +0 -12
  214. package/dist/sqlite-store-7ZIVOUNI.js +0 -5
  215. package/dist/team-manager-6DCNLGTC.js +0 -11
  216. package/dist/team-state-R2D7DT5M.js +0 -3
  217. package/dist/tmux-manager-WBKHUHDT.js +0 -6
  218. package/dist/tools-I6XCTEZY.js +0 -6
@@ -1,11 +0,0 @@
1
- export { ApiKeyFallback, getEnvKeyName, resolveProviderName } from './chunk-6GUD7QIM.js';
2
- import './chunk-AQ23TYSQ.js';
3
- import './chunk-VJNQJALF.js';
4
- import './chunk-VBLLDY4R.js';
5
- import './chunk-2GKOK6T7.js';
6
- import './chunk-473JN6M5.js';
7
- import './chunk-62HSGYQD.js';
8
- import './chunk-HEKFAKVH.js';
9
- import './chunk-BY4DAKUU.js';
10
- //# sourceMappingURL=api-key-fallback-UN3TJEOO.js.map
11
- //# sourceMappingURL=api-key-fallback-UN3TJEOO.js.map
@@ -1,13 +0,0 @@
1
- export { LOGIN_PROVIDERS, formatCompactAuthStatusLine, formatDetailedAuthStatusLine, getAuthStatusRecord, getAuthStatusRecords } from './chunk-OCJPQFOR.js';
2
- import './chunk-H2SYKIMI.js';
3
- import './chunk-6GUD7QIM.js';
4
- import './chunk-AQ23TYSQ.js';
5
- import './chunk-VJNQJALF.js';
6
- import './chunk-VBLLDY4R.js';
7
- import './chunk-2GKOK6T7.js';
8
- import './chunk-473JN6M5.js';
9
- import './chunk-62HSGYQD.js';
10
- import './chunk-HEKFAKVH.js';
11
- import './chunk-BY4DAKUU.js';
12
- //# sourceMappingURL=auth-status-EIM5A5KL.js.map
13
- //# sourceMappingURL=auth-status-EIM5A5KL.js.map
@@ -1,140 +0,0 @@
1
- import { buildModelMessages, buildAiSdkTools, extractAiSdkToolCalls, buildTokenUsage, mapAiSdkFinishReason } from './chunk-ODBY7S4X.js';
2
- import { ModelNotFoundError, AuthenticationError, RateLimitError } from './chunk-473JN6M5.js';
3
- import { SUPPORTED_MODELS } from './chunk-62HSGYQD.js';
4
- import { logger } from './chunk-HEKFAKVH.js';
5
- import { generateText, streamText } from 'ai';
6
- import { createGoogleGenerativeAI } from '@ai-sdk/google';
7
-
8
- var PROVIDER_NAME = "google";
9
- var GEMINI_MODELS = [
10
- "gemini-3-pro-preview",
11
- "gemini-3-flash-preview",
12
- "gemini-2.5-pro",
13
- "gemini-2.5-flash",
14
- "gemini-2.5-flash-lite"
15
- ];
16
- var CHARS_PER_TOKEN_ESTIMATE = 4;
17
- function classifyError(error, model) {
18
- const message = error instanceof Error ? error.message : String(error);
19
- const lower = message.toLowerCase();
20
- if (lower.includes("401") || lower.includes("403") || lower.includes("unauthorized") || lower.includes("invalid api key")) {
21
- throw new AuthenticationError(PROVIDER_NAME, message);
22
- }
23
- if (lower.includes("429") || lower.includes("rate limit") || lower.includes("resource exhausted")) {
24
- const match = /(\d+)\s*s/i.exec(message);
25
- const retryMs = match?.[1] !== void 0 ? parseInt(match[1], 10) * 1e3 : 6e4;
26
- throw new RateLimitError(PROVIDER_NAME, retryMs);
27
- }
28
- if (lower.includes("model") && lower.includes("not found")) {
29
- throw new ModelNotFoundError(model);
30
- }
31
- throw error instanceof Error ? error : new Error(message);
32
- }
33
- var GeminiAdapter = class {
34
- name = PROVIDER_NAME;
35
- supportedModels = GEMINI_MODELS;
36
- supportsToolCalling = true;
37
- google;
38
- constructor(options) {
39
- const apiKey = options?.apiKey ?? process.env["GOOGLE_API_KEY"];
40
- this.google = createGoogleGenerativeAI({
41
- ...apiKey !== void 0 ? { apiKey } : {},
42
- ...options?.baseUrl !== void 0 ? { baseURL: options.baseUrl } : {}
43
- });
44
- }
45
- async chat(request) {
46
- const modelInfo = this.getModelInfo(request.model);
47
- const messages = buildModelMessages(request.messages);
48
- const tools = buildAiSdkTools(request.tools);
49
- try {
50
- const result = await generateText({
51
- model: this.google(request.model),
52
- messages,
53
- ...request.system !== void 0 ? { system: request.system } : {},
54
- ...tools !== void 0 ? { tools } : {},
55
- maxOutputTokens: request.maxTokens ?? modelInfo.maxOutputTokens,
56
- ...request.temperature !== void 0 ? { temperature: request.temperature } : {}
57
- });
58
- const toolCalls = extractAiSdkToolCalls(result.toolCalls);
59
- const usage = buildTokenUsage(modelInfo, result.usage);
60
- const responseMessage = {
61
- id: result.response.id,
62
- role: "assistant",
63
- content: result.text,
64
- model: request.model,
65
- provider: PROVIDER_NAME,
66
- toolCalls: toolCalls.length > 0 ? toolCalls : void 0,
67
- tokenUsage: usage,
68
- createdAt: /* @__PURE__ */ new Date()
69
- };
70
- return {
71
- id: result.response.id,
72
- model: request.model,
73
- provider: PROVIDER_NAME,
74
- message: responseMessage,
75
- usage,
76
- finishReason: mapAiSdkFinishReason(result.finishReason)
77
- };
78
- } catch (error) {
79
- classifyError(error, request.model);
80
- }
81
- }
82
- async *stream(request) {
83
- const modelInfo = this.getModelInfo(request.model);
84
- const messages = buildModelMessages(request.messages);
85
- const tools = buildAiSdkTools(request.tools);
86
- try {
87
- const result = streamText({
88
- model: this.google(request.model),
89
- messages,
90
- ...request.system !== void 0 ? { system: request.system } : {},
91
- ...tools !== void 0 ? { tools } : {},
92
- maxOutputTokens: request.maxTokens ?? modelInfo.maxOutputTokens,
93
- ...request.temperature !== void 0 ? { temperature: request.temperature } : {}
94
- });
95
- for await (const part of result.fullStream) {
96
- if (part.type === "text-delta") {
97
- yield { type: "text", content: part.text };
98
- } else if (part.type === "tool-call") {
99
- const [toolCall] = extractAiSdkToolCalls([{
100
- toolCallId: part.toolCallId,
101
- toolName: part.toolName,
102
- input: part.input
103
- }]);
104
- if (toolCall === void 0) {
105
- continue;
106
- }
107
- yield { type: "tool_call", toolCall };
108
- } else if (part.type === "finish") {
109
- yield {
110
- type: "usage",
111
- usage: buildTokenUsage(modelInfo, part.totalUsage)
112
- };
113
- } else if (part.type === "error") {
114
- const errMsg = part.error instanceof Error ? part.error.message : String(part.error);
115
- yield { type: "error", error: errMsg };
116
- }
117
- }
118
- yield { type: "done" };
119
- } catch (error) {
120
- const errMsg = error instanceof Error ? error.message : String(error);
121
- logger.error({ error: errMsg, model: request.model }, "Gemini stream error");
122
- yield { type: "error", error: errMsg };
123
- yield { type: "done" };
124
- }
125
- }
126
- countTokens(text, _model) {
127
- return Promise.resolve(Math.ceil(text.length / CHARS_PER_TOKEN_ESTIMATE));
128
- }
129
- getModelInfo(model) {
130
- const info = SUPPORTED_MODELS[model];
131
- if (info === void 0 || info.provider !== PROVIDER_NAME) {
132
- throw new ModelNotFoundError(model);
133
- }
134
- return info;
135
- }
136
- };
137
-
138
- export { GeminiAdapter };
139
- //# sourceMappingURL=chunk-25UNNEHN.js.map
140
- //# sourceMappingURL=chunk-25UNNEHN.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/providers/gemini-adapter.ts"],"names":[],"mappings":"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","file":"chunk-25UNNEHN.js","sourcesContent":["/**\r\n * Gemini (Google) adapter via Vercel AI SDK per PRD section 7.1\r\n * Supports Gemini 2.5 Pro, Gemini 2.5 Flash\r\n */\r\n\r\nimport { generateText, streamText } from \"ai\";\r\nimport { createGoogleGenerativeAI } from \"@ai-sdk/google\";\r\nimport { logger } from \"../utils/logger.js\";\r\nimport {\r\n AuthenticationError,\r\n RateLimitError,\r\n ModelNotFoundError,\r\n} from \"../types/errors.js\";\r\nimport { SUPPORTED_MODELS } from \"../types/model.js\";\r\nimport type { IModelInfo, ProviderName } from \"../types/model.js\";\r\nimport type {\r\n IChatRequest,\r\n IChatResponse,\r\n IChatMessage,\r\n IStreamChunk,\r\n} from \"../types/message.js\";\r\nimport {\r\n buildAiSdkTools,\r\n buildModelMessages,\r\n buildTokenUsage,\r\n extractAiSdkToolCalls,\r\n mapAiSdkFinishReason,\r\n} from \"./ai-sdk-shared.js\";\r\nimport type { IModelProvider, IProviderOptions } from \"./types.js\";\r\n\r\nconst PROVIDER_NAME: ProviderName = \"google\";\r\n\r\nconst GEMINI_MODELS: readonly string[] = [\r\n \"gemini-3-pro-preview\",\r\n \"gemini-3-flash-preview\",\r\n \"gemini-2.5-pro\",\r\n \"gemini-2.5-flash\",\r\n \"gemini-2.5-flash-lite\",\r\n] as const;\r\n\r\nconst CHARS_PER_TOKEN_ESTIMATE = 4;\r\n\r\nfunction classifyError(error: unknown, model: string): never {\r\n const message = error instanceof Error ? error.message : String(error);\r\n const lower = message.toLowerCase();\r\n if (lower.includes(\"401\") || lower.includes(\"403\") || lower.includes(\"unauthorized\") || lower.includes(\"invalid api key\")) {\r\n throw new AuthenticationError(PROVIDER_NAME, message);\r\n }\r\n if (lower.includes(\"429\") || lower.includes(\"rate limit\") || lower.includes(\"resource exhausted\")) {\r\n const match = /(\\d+)\\s*s/i.exec(message);\r\n const retryMs = match?.[1] !== undefined ? parseInt(match[1], 10) * 1000 : 60_000;\r\n throw new RateLimitError(PROVIDER_NAME, retryMs);\r\n }\r\n if (lower.includes(\"model\") && lower.includes(\"not found\")) {\r\n throw new ModelNotFoundError(model);\r\n }\r\n throw error instanceof Error ? error : new Error(message);\r\n}\r\n\r\nexport class GeminiAdapter implements IModelProvider {\r\n readonly name = PROVIDER_NAME;\r\n readonly supportedModels = GEMINI_MODELS;\r\n readonly supportsToolCalling = true;\r\n private readonly google: ReturnType<typeof createGoogleGenerativeAI>;\r\n\r\n constructor(options?: IProviderOptions) {\r\n const apiKey = options?.apiKey ?? process.env[\"GOOGLE_API_KEY\"];\r\n this.google = createGoogleGenerativeAI({\r\n ...(apiKey !== undefined ? { apiKey } : {}),\r\n ...(options?.baseUrl !== undefined ? { baseURL: options.baseUrl } : {}),\r\n });\r\n }\r\n\r\n async chat(request: IChatRequest): Promise<IChatResponse> {\r\n const modelInfo = this.getModelInfo(request.model);\r\n const messages = buildModelMessages(request.messages);\r\n const tools = buildAiSdkTools(request.tools);\r\n try {\r\n const result = await generateText({\r\n model: this.google(request.model),\r\n messages,\r\n ...(request.system !== undefined ? { system: request.system } : {}),\r\n ...(tools !== undefined ? { tools } : {}),\r\n maxOutputTokens: request.maxTokens ?? modelInfo.maxOutputTokens,\r\n ...(request.temperature !== undefined ? { temperature: request.temperature } : {}),\r\n });\r\n const toolCalls = extractAiSdkToolCalls(result.toolCalls);\r\n const usage = buildTokenUsage(modelInfo, result.usage);\r\n const responseMessage: IChatMessage = {\r\n id: result.response.id,\r\n role: \"assistant\",\r\n content: result.text,\r\n model: request.model,\r\n provider: PROVIDER_NAME,\r\n toolCalls: toolCalls.length > 0 ? toolCalls : undefined,\r\n tokenUsage: usage,\r\n createdAt: new Date(),\r\n };\r\n return {\r\n id: result.response.id,\r\n model: request.model,\r\n provider: PROVIDER_NAME,\r\n message: responseMessage,\r\n usage,\r\n finishReason: mapAiSdkFinishReason(result.finishReason),\r\n };\r\n } catch (error: unknown) {\r\n classifyError(error, request.model);\r\n }\r\n }\r\n\r\n async *stream(request: IChatRequest): AsyncIterable<IStreamChunk> {\r\n const modelInfo = this.getModelInfo(request.model);\r\n const messages = buildModelMessages(request.messages);\r\n const tools = buildAiSdkTools(request.tools);\r\n try {\r\n const result = streamText({\r\n model: this.google(request.model),\r\n messages,\r\n ...(request.system !== undefined ? { system: request.system } : {}),\r\n ...(tools !== undefined ? { tools } : {}),\r\n maxOutputTokens: request.maxTokens ?? modelInfo.maxOutputTokens,\r\n ...(request.temperature !== undefined ? { temperature: request.temperature } : {}),\r\n });\r\n for await (const part of result.fullStream) {\r\n if (part.type === \"text-delta\") {\r\n yield { type: \"text\", content: part.text };\r\n } else if (part.type === \"tool-call\") {\r\n const [toolCall] = extractAiSdkToolCalls([{\r\n toolCallId: part.toolCallId,\r\n toolName: part.toolName,\r\n input: part.input,\r\n }]);\r\n if (toolCall === undefined) {\r\n continue;\r\n }\r\n yield { type: \"tool_call\", toolCall };\r\n } else if (part.type === \"finish\") {\r\n yield {\r\n type: \"usage\",\r\n usage: buildTokenUsage(modelInfo, part.totalUsage),\r\n };\r\n } else if (part.type === \"error\") {\r\n const errMsg = part.error instanceof Error ? part.error.message : String(part.error);\r\n yield { type: \"error\", error: errMsg };\r\n }\r\n }\r\n yield { type: \"done\" };\r\n } catch (error: unknown) {\r\n const errMsg = error instanceof Error ? error.message : String(error);\r\n logger.error({ error: errMsg, model: request.model }, \"Gemini stream error\");\r\n yield { type: \"error\", error: errMsg };\r\n yield { type: \"done\" };\r\n }\r\n }\r\n\r\n countTokens(text: string, _model: string): Promise<number> {\r\n return Promise.resolve(Math.ceil(text.length / CHARS_PER_TOKEN_ESTIMATE));\r\n }\r\n\r\n getModelInfo(model: string): IModelInfo {\r\n const info = SUPPORTED_MODELS[model];\r\n if (info === undefined || info.provider !== PROVIDER_NAME) {\r\n throw new ModelNotFoundError(model);\r\n }\r\n return info;\r\n }\r\n}\r\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/version.ts","../src/types/config.ts"],"names":[],"mappings":";;;;AAOA,IAAM,gBAAA,GAAmB,OAAA;AAEzB,SAAS,kBAAA,GAA6B;AACpC,EAAA,IAAI;AACF,IAAA,MAAM,kBAAkB,aAAA,CAAc,IAAI,IAAI,iBAAA,EAAmB,MAAA,CAAA,IAAA,CAAY,GAAG,CAAC,CAAA;AACjF,IAAA,MAAM,GAAA,GAAM,YAAA,CAAa,eAAA,EAAiB,OAAO,CAAA;AACjD,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,KAAA,CAAM,GAAG,CAAA;AAC7B,IAAA,OAAO,OAAO,OAAA,IAAW,gBAAA;AAAA,EAC3B,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,gBAAA;AAAA,EACT;AACF;AAEO,IAAM,kBAAkB,kBAAA;;;ACwHxB,IAAM,cAAA,GAAgC;AAAA,EAC3C,OAAA,EAAS,eAAA;AAAA,EACT,YAAA,EAAc,mBAAA;AAAA,EACd,KAAA,EAAO;AAAA,IACL,QAAA,EAAU,EAAE,OAAA,EAAS,iBAAA,EAAmB,UAAU,CAAC,SAAA,EAAW,gBAAgB,CAAA,EAAE;AAAA,IAChF,MAAA,EAAQ,EAAE,OAAA,EAAS,mBAAA,EAAqB,UAAU,CAAC,SAAA,EAAW,kBAAkB,CAAA,EAAE;AAAA,IAClF,QAAQ,EAAE,OAAA,EAAS,mBAAmB,QAAA,EAAU,CAAC,gBAAgB,CAAA,EAAE;AAAA,IACnE,SAAS,EAAE,OAAA,EAAS,oBAAoB,QAAA,EAAU,CAAC,kBAAkB,CAAA,EAAE;AAAA,IACvE,QAAQ,EAAE,OAAA,EAAS,qBAAqB,QAAA,EAAU,CAAC,SAAS,CAAA,EAAE;AAAA,IAC9D,eAAe,EAAE,OAAA,EAAS,oBAAoB,QAAA,EAAU,CAAC,kBAAkB,CAAA;AAAE,GAC/E;AAAA,EACA,SAAA,EAAW;AAAA,IACT,SAAA,EAAW,EAAE,OAAA,EAAS,IAAA,EAAK;AAAA,IAC3B,MAAA,EAAQ,EAAE,OAAA,EAAS,IAAA,EAAK;AAAA,IACxB,MAAA,EAAQ,EAAE,OAAA,EAAS,IAAA,EAAK;AAAA,IACxB,IAAA,EAAM,EAAE,OAAA,EAAS,KAAA,EAAM;AAAA,IACvB,MAAA,EAAQ,EAAE,OAAA,EAAS,KAAA,EAAO,SAAS,wBAAA;AAAyB,GAC9D;AAAA,EACA,WAAA,EAAa;AAAA,IACX,IAAA,EAAM,UAAA;AAAA,IACN,YAAA,EAAc,CAAC,IAAI,CAAA;AAAA,IACnB,eAAA,EAAiB,CAAC,UAAA,EAAY,kBAAkB;AAAA,GAClD;AAAA,EACA,UAAA,EAAY;AAAA,IACV,OAAA,EAAS,IAAA;AAAA,IACT,OAAA,EAAS,MAAA;AAAA,IACT,aAAA,EAAe,WAAA;AAAA,IACf,QAAA,EAAU;AAAA,GACZ;AAAA,EACA,KAAA,EAAO;AAAA,IACL,kBAAA,EAAoB,KAAA;AAAA,IACpB,mBAAmB,EAAC;AAAA,IACpB,qBAAA,EAAuB,MAAA;AAAA,IACvB,yBAAyB;AAAC,GAC5B;AAAA,EACA,IAAA,EAAM;AAAA,IACJ,aAAA,EAAe,CAAA;AAAA,IACf,cAAA,EAAgB,EAAA;AAAA,IAChB,QAAA,EAAU;AAAA,GACZ;AAAA,EACA,SAAA,EAAW;AAAA,IACT,OAAA,EAAS,KAAA;AAAA,IACT,UAAA,EAAY;AAAA;AAEhB","file":"chunk-2GKOK6T7.js","sourcesContent":["import { readFileSync } from \"node:fs\";\r\nimport { fileURLToPath } from \"node:url\";\r\n\r\ninterface PackageJsonShape {\r\n version?: string;\r\n}\r\n\r\nconst FALLBACK_VERSION = \"0.0.0\";\r\n\r\nfunction loadPackageVersion(): string {\r\n try {\r\n const packageJsonPath = fileURLToPath(new URL(\"../package.json\", import.meta.url));\r\n const raw = readFileSync(packageJsonPath, \"utf-8\");\r\n const parsed = JSON.parse(raw) as PackageJsonShape;\r\n return parsed.version ?? FALLBACK_VERSION;\r\n } catch {\r\n return FALLBACK_VERSION;\r\n }\r\n}\r\n\r\nexport const PACKAGE_VERSION = loadPackageVersion();\r\n","/**\r\n * Configuration types per PRD section 17.3\r\n */\r\n\r\nimport type { ProviderName, ModelRole, IRoleConfig } from \"./model.js\";\r\nimport type { PermissionMode } from \"./tool.js\";\r\nimport type { PaneLayout } from \"./team.js\";\r\nimport type { CliProviderType } from \"../orchestrator/constants.js\";\r\nimport { PACKAGE_VERSION } from \"../version.js\";\r\n\r\n// ── Provider Configuration ───────────────────────────────────────────────\r\n\r\nexport interface IProviderConfig {\r\n readonly enabled: boolean;\r\n readonly baseUrl?: string | undefined;\r\n}\r\n\r\n// ── Permission Configuration ─────────────────────────────────────────────\r\n\r\nexport interface IPermissionConfig {\r\n readonly mode: PermissionMode;\r\n readonly allowedPaths: readonly string[];\r\n readonly blockedCommands: readonly string[];\r\n}\r\n\r\n// ── Split Panel Configuration ────────────────────────────────────────────\r\n\r\nexport type PaneBackend = \"tmux\" | \"iterm2\";\r\n\r\nexport interface ISplitPanelConfig {\r\n readonly enabled: boolean;\r\n readonly backend: PaneBackend;\r\n readonly defaultLayout: PaneLayout;\r\n readonly maxPanes: number;\r\n}\r\n\r\n// ── Swarm / Orchestrator Preferences ────────────────────────────────────\r\n\r\nexport interface ISwarmConfig {\r\n readonly onboardingComplete: boolean;\r\n readonly detectedProviders: readonly CliProviderType[];\r\n readonly primaryMasterProvider?: CliProviderType | undefined;\r\n readonly fallbackMasterProviders: readonly CliProviderType[];\r\n}\r\n\r\n// ── Cost Configuration ───────────────────────────────────────────────────\r\n\r\nexport interface ICostConfig {\r\n readonly budgetWarning: number;\r\n readonly budgetHardStop: number;\r\n readonly currency: string;\r\n}\r\n\r\n// ── Telemetry Configuration ──────────────────────────────────────────────\r\n\r\nexport interface ITelemetryConfig {\r\n readonly enabled: boolean;\r\n readonly anonymized: boolean;\r\n}\r\n\r\n// ── OAuth Provider Configuration ─────────────────────────────────────────\r\n\r\nexport interface IOAuthProviderConfig {\r\n readonly clientId: string;\r\n readonly clientSecret?: string | undefined;\r\n readonly authorizeUrl?: string | undefined;\r\n readonly tokenUrl?: string | undefined;\r\n readonly scope?: string | undefined;\r\n}\r\n\r\nexport interface IOAuthConfig {\r\n readonly anthropic?: IOAuthProviderConfig | undefined;\r\n readonly openai?: IOAuthProviderConfig | undefined;\r\n readonly google?: IOAuthProviderConfig | undefined;\r\n readonly kimi?: IOAuthProviderConfig | undefined;\r\n}\r\n\r\n// ── Global Configuration (PRD section 17.3) ──────────────────────────────\r\n\r\nexport interface IGlobalConfig {\r\n readonly version: string;\r\n readonly defaultModel: string;\r\n readonly roles: Partial<Record<ModelRole, IRoleConfig>>;\r\n readonly providers: Partial<Record<ProviderName, IProviderConfig>>;\r\n readonly permissions: IPermissionConfig;\r\n readonly splitPanel: ISplitPanelConfig;\r\n readonly swarm: ISwarmConfig;\r\n readonly cost: ICostConfig;\r\n readonly telemetry: ITelemetryConfig;\r\n readonly oauth?: IOAuthConfig | undefined;\r\n}\r\n\r\n// ── MCP Server Configuration (PRD section 11.2) ─────────────────────────\r\n\r\nexport interface IMCPServerConfig {\r\n readonly command: string;\r\n readonly args: readonly string[];\r\n readonly env?: Readonly<Record<string, string>> | undefined;\r\n}\r\n\r\nexport interface IMCPConfig {\r\n readonly mcpServers: Readonly<Record<string, IMCPServerConfig>>;\r\n}\r\n\r\n// ── Skill Configuration (PRD section 10.2) ───────────────────────────────\r\n\r\nexport interface ISkillFrontmatter {\r\n readonly name: string;\r\n readonly description: string;\r\n readonly version: string;\r\n readonly \"allowed-tools\"?: readonly string[] | undefined;\r\n readonly triggers: readonly string[];\r\n readonly \"model-requirements\"?: {\r\n readonly \"preferred-role\"?: ModelRole | undefined;\r\n readonly \"min-context\"?: number | undefined;\r\n } | undefined;\r\n}\r\n\r\nexport interface ISkillDefinition {\r\n readonly frontmatter: ISkillFrontmatter;\r\n readonly body: string;\r\n readonly filePath: string;\r\n}\r\n\r\n// ── Auth Credential Types (PRD section 13) ───────────────────────────────\r\n\r\nexport type AuthMethod = \"native_login\" | \"api_key\" | \"env_variable\" | \"credential_helper\";\r\n\r\nexport interface ICredential {\r\n readonly provider: ProviderName;\r\n readonly method: AuthMethod;\r\n readonly token?: string | undefined;\r\n readonly refreshToken?: string | undefined;\r\n readonly expiresAt?: Date | undefined;\r\n readonly email?: string | undefined;\r\n readonly plan?: string | undefined;\r\n}\r\n\r\n// ── Default Configuration ────────────────────────────────────────────────\r\n\r\nexport const DEFAULT_CONFIG: IGlobalConfig = {\r\n version: PACKAGE_VERSION,\r\n defaultModel: \"claude-sonnet-4-6\",\r\n roles: {\r\n planning: { primary: \"claude-opus-4-6\", fallback: [\"gpt-5.2\", \"gemini-2.5-pro\"] },\r\n coding: { primary: \"claude-sonnet-4-6\", fallback: [\"gpt-5.2\", \"gemini-2.5-flash\"] },\r\n review: { primary: \"claude-opus-4-6\", fallback: [\"gemini-2.5-pro\"] },\r\n testing: { primary: \"claude-haiku-4-5\", fallback: [\"gemini-2.5-flash\"] },\r\n bugfix: { primary: \"claude-sonnet-4-6\", fallback: [\"gpt-5.2\"] },\r\n documentation: { primary: \"gemini-2.5-flash\", fallback: [\"claude-haiku-4-5\"] },\r\n },\r\n providers: {\r\n anthropic: { enabled: true },\r\n openai: { enabled: true },\r\n google: { enabled: true },\r\n kimi: { enabled: false },\r\n ollama: { enabled: false, baseUrl: \"http://localhost:11434\" },\r\n },\r\n permissions: {\r\n mode: \"standard\",\r\n allowedPaths: [\"./\"],\r\n blockedCommands: [\"rm -rf /\", \"git push --force\"],\r\n },\r\n splitPanel: {\r\n enabled: true,\r\n backend: \"tmux\",\r\n defaultLayout: \"hub-spoke\",\r\n maxPanes: 6,\r\n },\r\n swarm: {\r\n onboardingComplete: false,\r\n detectedProviders: [],\r\n primaryMasterProvider: undefined,\r\n fallbackMasterProviders: [],\r\n },\r\n cost: {\r\n budgetWarning: 5.0,\r\n budgetHardStop: 20.0,\r\n currency: \"USD\",\r\n },\r\n telemetry: {\r\n enabled: false,\r\n anonymized: true,\r\n },\r\n};\r\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/mcp/client.ts","../src/mcp/server-manager.ts"],"names":[],"mappings":"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","file":"chunk-2LF7ALGR.js","sourcesContent":["/**\r\n * MCP client per PRD section 11.1\r\n * Wraps @modelcontextprotocol/sdk Client with typed, transport-agnostic interface.\r\n * Supports stdio (local servers) and Streamable HTTP (remote servers).\r\n */\r\n\r\nimport { Client } from \"@modelcontextprotocol/sdk/client/index.js\";\r\nimport { StdioClientTransport } from \"@modelcontextprotocol/sdk/client/stdio.js\";\r\nimport type { Transport } from \"@modelcontextprotocol/sdk/shared/transport.js\";\r\nimport { logger } from \"../utils/logger.js\";\r\nimport { ServerConnectionError, ToolCallError } from \"../types/errors.js\";\r\n\r\n// ── Exported Types ──────────────────────────────────────────────────────\r\n\r\nexport interface IMCPToolSchema {\r\n readonly name: string;\r\n readonly description: string;\r\n readonly inputSchema: Readonly<Record<string, unknown>>;\r\n}\r\n\r\nexport interface IMCPCallResult {\r\n readonly content: string;\r\n readonly isError: boolean;\r\n}\r\n\r\nexport interface IMCPResource {\r\n readonly uri: string;\r\n readonly name: string;\r\n readonly description: string;\r\n readonly mimeType: string;\r\n}\r\n\r\n// ── Transport Configuration ─────────────────────────────────────────────\r\n\r\nexport interface IStdioTransportConfig {\r\n readonly type: \"stdio\";\r\n readonly command: string;\r\n readonly args: readonly string[];\r\n readonly env?: Readonly<Record<string, string>>;\r\n}\r\n\r\nexport interface IHttpTransportConfig {\r\n readonly type: \"streamable-http\";\r\n readonly url: string;\r\n}\r\n\r\nexport type MCPTransportConfig = IStdioTransportConfig | IHttpTransportConfig;\r\n\r\n// ── Client Options ──────────────────────────────────────────────────────\r\n\r\nexport interface IMCPClientOptions {\r\n readonly serverName: string;\r\n readonly transport: MCPTransportConfig;\r\n readonly connectionTimeoutMs?: number;\r\n}\r\n\r\n// ── Constants ───────────────────────────────────────────────────────────\r\n\r\nconst DEFAULT_TIMEOUT_MS = 30_000;\r\nconst CLIENT_NAME = \"aemeathcli\";\r\nconst CLIENT_VERSION = \"1.0.0\";\r\n\r\n// ── Content Helpers ─────────────────────────────────────────────────────\r\n\r\ninterface IContentItem {\r\n readonly type: string;\r\n readonly text?: string;\r\n}\r\n\r\nfunction extractText(content: unknown): string {\r\n if (!Array.isArray(content)) {\r\n return \"No output\";\r\n }\r\n const parts: string[] = [];\r\n for (const item of content as ReadonlyArray<IContentItem>) {\r\n if (item.type === \"text\" && typeof item.text === \"string\") {\r\n parts.push(item.text);\r\n }\r\n }\r\n return parts.length > 0 ? parts.join(\"\\n\") : \"No output\";\r\n}\r\n\r\n// ── MCPClient ───────────────────────────────────────────────────────────\r\n\r\nexport class MCPClient {\r\n private client: Client | undefined;\r\n private connected = false;\r\n private readonly serverName: string;\r\n private readonly transportConfig: MCPTransportConfig;\r\n private readonly connectionTimeoutMs: number;\r\n\r\n constructor(options: IMCPClientOptions) {\r\n this.serverName = options.serverName;\r\n this.transportConfig = options.transport;\r\n this.connectionTimeoutMs = options.connectionTimeoutMs ?? DEFAULT_TIMEOUT_MS;\r\n }\r\n\r\n get isConnected(): boolean {\r\n return this.connected;\r\n }\r\n\r\n get name(): string {\r\n return this.serverName;\r\n }\r\n\r\n /** Establish connection to the MCP server. */\r\n async connect(): Promise<void> {\r\n if (this.connected) {\r\n return;\r\n }\r\n\r\n logger.info({ server: this.serverName }, \"Connecting to MCP server\");\r\n\r\n try {\r\n this.client = new Client(\r\n { name: CLIENT_NAME, version: CLIENT_VERSION },\r\n { capabilities: { sampling: {} } },\r\n );\r\n\r\n await this.connectWithTimeout();\r\n this.connected = true;\r\n logger.info({ server: this.serverName }, \"Connected to MCP server\");\r\n } catch (error: unknown) {\r\n this.connected = false;\r\n this.client = undefined;\r\n const msg = error instanceof Error ? error.message : String(error);\r\n throw new ServerConnectionError(this.serverName, msg);\r\n }\r\n }\r\n\r\n /** Gracefully close the MCP connection. */\r\n async disconnect(): Promise<void> {\r\n if (!this.connected || !this.client) {\r\n return;\r\n }\r\n\r\n logger.info({ server: this.serverName }, \"Disconnecting from MCP server\");\r\n\r\n try {\r\n await this.client.close();\r\n } catch (error: unknown) {\r\n logger.warn({ server: this.serverName, error }, \"Error during MCP disconnect\");\r\n } finally {\r\n this.connected = false;\r\n this.client = undefined;\r\n }\r\n }\r\n\r\n /** Disconnect then reconnect to the server. */\r\n async reconnect(): Promise<void> {\r\n await this.disconnect();\r\n await this.connect();\r\n }\r\n\r\n /** List all tools exposed by this MCP server. */\r\n async listTools(): Promise<readonly IMCPToolSchema[]> {\r\n const client = this.requireConnected();\r\n\r\n try {\r\n const result = await client.listTools();\r\n return result.tools.map((tool) => ({\r\n name: tool.name,\r\n description: typeof tool.description === \"string\" ? tool.description : \"\",\r\n inputSchema: tool.inputSchema as Readonly<Record<string, unknown>>,\r\n }));\r\n } catch (error: unknown) {\r\n const msg = error instanceof Error ? error.message : String(error);\r\n throw new ServerConnectionError(this.serverName, `listTools failed: ${msg}`);\r\n }\r\n }\r\n\r\n /** Call a tool on this MCP server with the given arguments. */\r\n async callTool(\r\n toolName: string,\r\n args: Record<string, unknown>,\r\n ): Promise<IMCPCallResult> {\r\n const client = this.requireConnected();\r\n\r\n try {\r\n const result = await client.callTool({ name: toolName, arguments: args });\r\n return {\r\n content: extractText(result.content),\r\n isError: result.isError === true,\r\n };\r\n } catch (error: unknown) {\r\n const msg = error instanceof Error ? error.message : String(error);\r\n throw new ToolCallError(toolName, msg);\r\n }\r\n }\r\n\r\n /** List resources exposed by this MCP server. */\r\n async listResources(): Promise<readonly IMCPResource[]> {\r\n const client = this.requireConnected();\r\n\r\n try {\r\n const result = await client.listResources();\r\n return result.resources.map((r) => ({\r\n uri: r.uri,\r\n name: typeof r.name === \"string\" ? r.name : r.uri,\r\n description: \"\",\r\n mimeType: typeof r.mimeType === \"string\" ? r.mimeType : \"application/octet-stream\",\r\n }));\r\n } catch (error: unknown) {\r\n const msg = error instanceof Error ? error.message : String(error);\r\n throw new ServerConnectionError(\r\n this.serverName,\r\n `listResources failed: ${msg}`,\r\n );\r\n }\r\n }\r\n\r\n /** Read a specific resource by URI. */\r\n async readResource(uri: string): Promise<string> {\r\n const client = this.requireConnected();\r\n\r\n try {\r\n const result = await client.readResource({ uri });\r\n return extractText(result.contents);\r\n } catch (error: unknown) {\r\n const msg = error instanceof Error ? error.message : String(error);\r\n throw new ServerConnectionError(\r\n this.serverName,\r\n `readResource(${uri}) failed: ${msg}`,\r\n );\r\n }\r\n }\r\n\r\n // ── Private Helpers ─────────────────────────────────────────────────\r\n\r\n private async connectWithTimeout(): Promise<void> {\r\n const client = this.client;\r\n if (!client) {\r\n throw new Error(\"Client not initialised\");\r\n }\r\n\r\n const timeoutPromise = new Promise<never>((_resolve, reject) => {\r\n setTimeout(\r\n () => {\r\n reject(new Error(`Connection timed out after ${this.connectionTimeoutMs}ms`));\r\n },\r\n this.connectionTimeoutMs,\r\n );\r\n });\r\n\r\n if (this.transportConfig.type === \"stdio\") {\r\n const transport = new StdioClientTransport({\r\n command: this.transportConfig.command,\r\n args: [...this.transportConfig.args],\r\n ...(this.transportConfig.env !== undefined\r\n ? { env: { ...this.transportConfig.env } }\r\n : {}),\r\n });\r\n await Promise.race([client.connect(transport), timeoutPromise]);\r\n return;\r\n }\r\n\r\n else {\r\n const { StreamableHTTPClientTransport } = await import(\r\n \"@modelcontextprotocol/sdk/client/streamableHttp.js\"\r\n );\r\n const transport = new StreamableHTTPClientTransport(\r\n new URL(this.transportConfig.url),\r\n );\r\n await Promise.race([client.connect(transport as Transport), timeoutPromise]);\r\n return;\r\n }\r\n }\r\n\r\n private requireConnected(): Client {\r\n if (!this.connected || !this.client) {\r\n throw new ServerConnectionError(this.serverName, \"Not connected\");\r\n }\r\n return this.client;\r\n }\r\n}\r\n","/**\r\n * MCP server lifecycle manager per PRD section 11.1\r\n * Manages multiple MCP server connections: start, stop, health-check, restart, rate-limit.\r\n */\r\n\r\nimport { logger } from \"../utils/logger.js\";\r\nimport { ServerConnectionError } from \"../types/errors.js\";\r\nimport { MCPClient } from \"./client.js\";\r\nimport type { IMCPClientOptions, IMCPToolSchema, IStdioTransportConfig } from \"./client.js\";\r\nimport type { IMCPConfig, IMCPServerConfig } from \"../types/config.js\";\r\n\r\n// ── Server State ────────────────────────────────────────────────────────\r\n\r\ntype ServerStatus = \"stopped\" | \"connecting\" | \"connected\" | \"error\";\r\n\r\ninterface IServerEntry {\r\n readonly client: MCPClient;\r\n status: ServerStatus;\r\n lastHealthCheck: number;\r\n consecutiveFailures: number;\r\n readonly rateLimit: IRateLimitState;\r\n}\r\n\r\n// ── Rate Limiting ───────────────────────────────────────────────────────\r\n\r\ninterface IRateLimitState {\r\n callTimestamps: number[];\r\n maxCallsPerMinute: number;\r\n}\r\n\r\nexport interface IRateLimitConfig {\r\n readonly maxCallsPerMinute: number;\r\n}\r\n\r\n// ── Manager Options ─────────────────────────────────────────────────────\r\n\r\nexport interface IServerManagerOptions {\r\n readonly connectionTimeoutMs?: number;\r\n readonly healthCheckIntervalMs?: number;\r\n readonly maxConsecutiveFailures?: number;\r\n readonly defaultRateLimit?: IRateLimitConfig | undefined;\r\n readonly rateLimits?: Readonly<Record<string, IRateLimitConfig>> | undefined;\r\n}\r\n\r\n// ── Constants ───────────────────────────────────────────────────────────\r\n\r\nconst DEFAULT_HEALTH_INTERVAL_MS = 60_000;\r\nconst DEFAULT_MAX_FAILURES = 3;\r\nconst DEFAULT_MAX_CALLS_PER_MINUTE = 60;\r\nconst RATE_LIMIT_WINDOW_MS = 60_000;\r\n\r\n// ── MCPServerManager ────────────────────────────────────────────────────\r\n\r\nexport class MCPServerManager {\r\n private readonly servers = new Map<string, IServerEntry>();\r\n private readonly options: Required<\r\n Pick<IServerManagerOptions, \"connectionTimeoutMs\" | \"healthCheckIntervalMs\" | \"maxConsecutiveFailures\">\r\n > & Pick<IServerManagerOptions, \"defaultRateLimit\" | \"rateLimits\">;\r\n private healthCheckTimer: ReturnType<typeof setInterval> | undefined;\r\n\r\n constructor(options?: IServerManagerOptions) {\r\n this.options = {\r\n connectionTimeoutMs: options?.connectionTimeoutMs ?? 30_000,\r\n healthCheckIntervalMs: options?.healthCheckIntervalMs ?? DEFAULT_HEALTH_INTERVAL_MS,\r\n maxConsecutiveFailures: options?.maxConsecutiveFailures ?? DEFAULT_MAX_FAILURES,\r\n defaultRateLimit: options?.defaultRateLimit,\r\n rateLimits: options?.rateLimits,\r\n };\r\n }\r\n\r\n /** Start all servers defined in the MCP config. */\r\n async startAll(config: IMCPConfig): Promise<void> {\r\n const entries = Object.entries(config.mcpServers);\r\n if (entries.length === 0) {\r\n logger.info(\"No MCP servers configured\");\r\n return;\r\n }\r\n\r\n logger.info({ count: entries.length }, \"Starting MCP servers\");\r\n\r\n const results = await Promise.allSettled(\r\n entries.map(([name, serverConfig]) => this.startServer(name, serverConfig)),\r\n );\r\n\r\n let successCount = 0;\r\n for (const result of results) {\r\n if (result.status === \"fulfilled\") {\r\n successCount++;\r\n }\r\n }\r\n\r\n logger.info(\r\n { total: entries.length, connected: successCount },\r\n \"MCP server startup complete\",\r\n );\r\n\r\n this.startHealthChecks();\r\n }\r\n\r\n /** Start a single MCP server by name and config. */\r\n async startServer(name: string, serverConfig: IMCPServerConfig): Promise<void> {\r\n if (this.servers.has(name)) {\r\n logger.warn({ server: name }, \"MCP server already registered, stopping first\");\r\n await this.stopServer(name);\r\n }\r\n\r\n logger.info({ server: name, command: serverConfig.command }, \"Starting MCP server\");\r\n\r\n const transportConfig: IStdioTransportConfig = {\r\n type: \"stdio\",\r\n command: serverConfig.command,\r\n args: [...serverConfig.args],\r\n ...(serverConfig.env !== undefined ? { env: { ...serverConfig.env } } : {}),\r\n };\r\n\r\n const clientOptions: IMCPClientOptions = {\r\n serverName: name,\r\n transport: transportConfig,\r\n connectionTimeoutMs: this.options.connectionTimeoutMs,\r\n };\r\n\r\n const client = new MCPClient(clientOptions);\r\n const maxCalls = this.getMaxCallsPerMinute(name);\r\n\r\n const entry: IServerEntry = {\r\n client,\r\n status: \"connecting\",\r\n lastHealthCheck: Date.now(),\r\n consecutiveFailures: 0,\r\n rateLimit: { callTimestamps: [], maxCallsPerMinute: maxCalls },\r\n };\r\n\r\n this.servers.set(name, entry);\r\n\r\n try {\r\n await client.connect();\r\n entry.status = \"connected\";\r\n logger.info({ server: name }, \"MCP server connected\");\r\n } catch (error: unknown) {\r\n entry.status = \"error\";\r\n entry.consecutiveFailures = 1;\r\n const msg = error instanceof Error ? error.message : String(error);\r\n logger.error({ server: name, error: msg }, \"Failed to start MCP server\");\r\n throw new ServerConnectionError(name, msg);\r\n }\r\n }\r\n\r\n /** Stop a single server by name. */\r\n async stopServer(name: string): Promise<void> {\r\n const entry = this.servers.get(name);\r\n if (!entry) {\r\n return;\r\n }\r\n\r\n logger.info({ server: name }, \"Stopping MCP server\");\r\n\r\n try {\r\n await entry.client.disconnect();\r\n } catch (error: unknown) {\r\n logger.warn({ server: name, error }, \"Error stopping MCP server\");\r\n }\r\n\r\n entry.status = \"stopped\";\r\n this.servers.delete(name);\r\n }\r\n\r\n /** Stop all managed servers and clean up. */\r\n async stopAll(): Promise<void> {\r\n this.stopHealthChecks();\r\n\r\n const names = [...this.servers.keys()];\r\n logger.info({ count: names.length }, \"Stopping all MCP servers\");\r\n\r\n await Promise.allSettled(names.map((name) => this.stopServer(name)));\r\n }\r\n\r\n /** Get a connected client by server name. */\r\n getClient(name: string): MCPClient | undefined {\r\n const entry = this.servers.get(name);\r\n if (!entry || entry.status !== \"connected\") {\r\n return undefined;\r\n }\r\n return entry.client;\r\n }\r\n\r\n /** Get all connected server names. */\r\n getConnectedServers(): readonly string[] {\r\n const connected: string[] = [];\r\n for (const [name, entry] of this.servers) {\r\n if (entry.status === \"connected\") {\r\n connected.push(name);\r\n }\r\n }\r\n return connected;\r\n }\r\n\r\n /** Get the status of a server. */\r\n getServerStatus(name: string): ServerStatus | undefined {\r\n return this.servers.get(name)?.status;\r\n }\r\n\r\n /** List tools from a specific server (with rate-limit check). */\r\n async listServerTools(name: string): Promise<readonly IMCPToolSchema[]> {\r\n const entry = this.requireServer(name);\r\n this.checkRateLimit(entry, name);\r\n return entry.client.listTools();\r\n }\r\n\r\n /** Check rate limit before allowing a call to the given server. Throws on exceeded. */\r\n checkRateLimitFor(name: string): void {\r\n const entry = this.requireServer(name);\r\n this.checkRateLimit(entry, name);\r\n }\r\n\r\n /** Record a tool call for rate-limiting purposes. */\r\n recordCall(name: string): void {\r\n const entry = this.servers.get(name);\r\n if (entry) {\r\n entry.rateLimit.callTimestamps.push(Date.now());\r\n }\r\n }\r\n\r\n // ── Health Checking ─────────────────────────────────────────────────\r\n\r\n private startHealthChecks(): void {\r\n this.stopHealthChecks();\r\n\r\n this.healthCheckTimer = setInterval(() => {\r\n void this.runHealthChecks();\r\n }, this.options.healthCheckIntervalMs);\r\n\r\n // Prevent the timer from keeping the process alive\r\n if (typeof this.healthCheckTimer === \"object\" && \"unref\" in this.healthCheckTimer) {\r\n this.healthCheckTimer.unref();\r\n }\r\n }\r\n\r\n private stopHealthChecks(): void {\r\n if (this.healthCheckTimer !== undefined) {\r\n clearInterval(this.healthCheckTimer);\r\n this.healthCheckTimer = undefined;\r\n }\r\n }\r\n\r\n private async runHealthChecks(): Promise<void> {\r\n for (const [name, entry] of this.servers) {\r\n if (entry.status === \"stopped\") {\r\n continue;\r\n }\r\n\r\n try {\r\n await entry.client.listTools();\r\n entry.status = \"connected\";\r\n entry.consecutiveFailures = 0;\r\n entry.lastHealthCheck = Date.now();\r\n } catch {\r\n entry.consecutiveFailures++;\r\n entry.status = \"error\";\r\n logger.warn(\r\n { server: name, failures: entry.consecutiveFailures },\r\n \"MCP health check failed\",\r\n );\r\n\r\n if (entry.consecutiveFailures >= this.options.maxConsecutiveFailures) {\r\n logger.info({ server: name }, \"Attempting MCP server restart\");\r\n void this.restartServer(name, entry);\r\n }\r\n }\r\n }\r\n }\r\n\r\n private async restartServer(name: string, entry: IServerEntry): Promise<void> {\r\n try {\r\n await entry.client.reconnect();\r\n entry.status = \"connected\";\r\n entry.consecutiveFailures = 0;\r\n logger.info({ server: name }, \"MCP server restarted successfully\");\r\n } catch (error: unknown) {\r\n entry.status = \"error\";\r\n const msg = error instanceof Error ? error.message : String(error);\r\n logger.error({ server: name, error: msg }, \"MCP server restart failed\");\r\n }\r\n }\r\n\r\n // ── Rate Limiting ─────────────────────────────────────────────────\r\n\r\n private checkRateLimit(entry: IServerEntry, serverName: string): void {\r\n const now = Date.now();\r\n const windowStart = now - RATE_LIMIT_WINDOW_MS;\r\n\r\n // Prune timestamps outside the window\r\n entry.rateLimit.callTimestamps = entry.rateLimit.callTimestamps.filter(\r\n (ts) => ts > windowStart,\r\n );\r\n\r\n if (entry.rateLimit.callTimestamps.length >= entry.rateLimit.maxCallsPerMinute) {\r\n throw new ServerConnectionError(\r\n serverName,\r\n `Rate limit exceeded: ${entry.rateLimit.maxCallsPerMinute} calls/minute`,\r\n );\r\n }\r\n }\r\n\r\n private getMaxCallsPerMinute(serverName: string): number {\r\n const perServer = this.options.rateLimits?.[serverName];\r\n if (perServer) {\r\n return perServer.maxCallsPerMinute;\r\n }\r\n return this.options.defaultRateLimit?.maxCallsPerMinute ?? DEFAULT_MAX_CALLS_PER_MINUTE;\r\n }\r\n\r\n // ── Helpers ───────────────────────────────────────────────────────\r\n\r\n private requireServer(name: string): IServerEntry {\r\n const entry = this.servers.get(name);\r\n if (!entry || entry.status !== \"connected\") {\r\n throw new ServerConnectionError(name, \"Server not connected\");\r\n }\r\n return entry;\r\n }\r\n}\r\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/providers/ollama-adapter.ts"],"names":[],"mappings":"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","file":"chunk-2NWNIKBK.js","sourcesContent":["/**\r\n * Ollama adapter — custom HTTP for local models per PRD section 7.1\r\n * Uses OpenAI-compatible API format at localhost:11434.\r\n * Dynamic model listing from Ollama API.\r\n */\r\n\r\nimport { logger } from \"../utils/logger.js\";\r\nimport { SUPPORTED_MODELS } from \"../types/model.js\";\r\nimport type { IModelInfo, ProviderName, ModelRole } from \"../types/model.js\";\r\nimport type {\r\n IChatRequest,\r\n IChatResponse,\r\n IChatMessage,\r\n IStreamChunk,\r\n IToolCall,\r\n IToolDefinition,\r\n ITokenUsage,\r\n} from \"../types/message.js\";\r\nimport type { IModelProvider, IProviderOptions } from \"./types.js\";\r\n\r\nconst PROVIDER_NAME: ProviderName = \"ollama\";\r\nconst DEFAULT_BASE_URL = \"http://localhost:11434\";\r\nconst CHARS_PER_TOKEN_ESTIMATE = 4;\r\n\r\ninterface OllamaListResponse { models: Array<{ name: string; size: number }> }\r\ninterface OpenAIStandardMessage {\r\n role: \"system\" | \"user\" | \"assistant\";\r\n content: string | null;\r\n tool_calls?: readonly OllamaToolCallRef[] | undefined;\r\n}\r\ninterface OpenAIToolResultMessage {\r\n role: \"tool\";\r\n content: string;\r\n tool_call_id: string;\r\n name: string;\r\n}\r\ntype OpenAIMessage = OpenAIStandardMessage | OpenAIToolResultMessage;\r\ninterface OpenAITool { type: \"function\"; function: { name: string; description: string; parameters: Record<string, unknown> } }\r\ninterface OllamaToolCallRef { id: string; type: string; function: { name: string; arguments: string } }\r\ninterface OllamaChoice {\r\n index: number;\r\n message: { role: string; content: string | null; tool_calls?: readonly OllamaToolCallRef[] };\r\n finish_reason: string;\r\n}\r\ninterface OllamaUsage { prompt_tokens: number; completion_tokens: number; total_tokens: number }\r\ninterface OllamaChatResponse { id: string; choices: OllamaChoice[]; usage?: OllamaUsage }\r\n\r\nfunction convertMessages(messages: readonly IChatMessage[]): OpenAIMessage[] {\r\n const converted: OpenAIMessage[] = [];\r\n\r\n for (const msg of messages) {\r\n if (msg.role === \"assistant\" && msg.toolCalls !== undefined && msg.toolCalls.length > 0) {\r\n converted.push({\r\n role: \"assistant\" as const,\r\n content: msg.content.length > 0 ? msg.content : null,\r\n tool_calls: msg.toolCalls.map((toolCall) => ({\r\n id: toolCall.id,\r\n type: \"function\",\r\n function: {\r\n name: toolCall.name,\r\n arguments: JSON.stringify(toolCall.arguments),\r\n },\r\n })),\r\n });\r\n continue;\r\n }\r\n\r\n if (msg.role === \"tool\") {\r\n const toolCall = msg.toolCalls?.[0];\r\n if (toolCall !== undefined) {\r\n converted.push({\r\n role: \"tool\" as const,\r\n content: msg.content,\r\n tool_call_id: toolCall.id,\r\n name: toolCall.name,\r\n });\r\n continue;\r\n }\r\n }\r\n\r\n converted.push({\r\n role: msg.role as \"system\" | \"user\" | \"assistant\",\r\n content: msg.content,\r\n });\r\n }\r\n\r\n return converted;\r\n}\r\n\r\nfunction convertTools(tools: readonly IToolDefinition[] | undefined): OpenAITool[] | undefined {\r\n if (tools === undefined || tools.length === 0) {\r\n return undefined;\r\n }\r\n return tools.map((tool) => {\r\n const properties: Record<string, unknown> = {};\r\n const required: string[] = [];\r\n for (const param of tool.parameters) {\r\n properties[param.name] = { type: param.type, description: param.description };\r\n if (param.required) {\r\n required.push(param.name);\r\n }\r\n }\r\n return {\r\n type: \"function\" as const,\r\n function: {\r\n name: tool.name,\r\n description: tool.description,\r\n parameters: { type: \"object\", properties, required },\r\n },\r\n };\r\n });\r\n}\r\n\r\nfunction makeOllamaModelInfo(modelName: string): IModelInfo {\r\n return {\r\n id: modelName,\r\n name: modelName,\r\n provider: PROVIDER_NAME,\r\n contextWindow: 128_000,\r\n maxOutputTokens: 8_192,\r\n inputPricePerMToken: 0,\r\n outputPricePerMToken: 0,\r\n supportsStreaming: true,\r\n supportsToolCalling: true,\r\n supportedRoles: [\"coding\", \"bugfix\", \"testing\", \"documentation\"] as readonly ModelRole[],\r\n };\r\n}\r\n\r\nexport class OllamaAdapter implements IModelProvider {\r\n readonly name = PROVIDER_NAME;\r\n readonly supportsToolCalling = true;\r\n\r\n private readonly baseUrl: string;\r\n private cachedModels: string[] | undefined;\r\n\r\n constructor(options?: IProviderOptions) {\r\n this.baseUrl = options?.baseUrl ?? DEFAULT_BASE_URL;\r\n }\r\n\r\n get supportedModels(): readonly string[] {\r\n return this.cachedModels ?? [];\r\n }\r\n\r\n /**\r\n * Refresh available models from Ollama API.\r\n * Call once during initialization.\r\n */\r\n async refreshModels(): Promise<readonly string[]> {\r\n try {\r\n const response = await fetch(`${this.baseUrl}/api/tags`);\r\n if (!response.ok) {\r\n logger.warn({ status: response.status }, \"Failed to list Ollama models\");\r\n this.cachedModels = [];\r\n return [];\r\n }\r\n const data = (await response.json()) as OllamaListResponse;\r\n this.cachedModels = data.models.map((m) => m.name);\r\n logger.debug({ models: this.cachedModels }, \"Ollama models discovered\");\r\n return this.cachedModels;\r\n } catch (error: unknown) {\r\n const errMsg = error instanceof Error ? error.message : String(error);\r\n logger.warn({ error: errMsg }, \"Ollama not reachable\");\r\n this.cachedModels = [];\r\n return [];\r\n }\r\n }\r\n\r\n async chat(request: IChatRequest): Promise<IChatResponse> {\r\n this.getModelInfo(request.model);\r\n const messages = convertMessages(request.messages);\r\n const tools = convertTools(request.tools);\r\n\r\n if (request.system !== undefined) {\r\n messages.unshift({ role: \"system\", content: request.system });\r\n }\r\n\r\n const body: Record<string, unknown> = {\r\n model: request.model,\r\n messages,\r\n stream: false,\r\n };\r\n if (request.maxTokens !== undefined) {\r\n body[\"max_tokens\"] = request.maxTokens;\r\n }\r\n if (request.temperature !== undefined) {\r\n body[\"temperature\"] = request.temperature;\r\n }\r\n if (tools !== undefined) {\r\n body[\"tools\"] = tools;\r\n }\r\n\r\n const response = await fetch(`${this.baseUrl}/v1/chat/completions`, {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify(body),\r\n });\r\n\r\n if (!response.ok) {\r\n const text = await response.text();\r\n throw new Error(`Ollama API error (${response.status}): ${text}`);\r\n }\r\n\r\n const data = (await response.json()) as OllamaChatResponse;\r\n const choice = data.choices[0];\r\n if (choice === undefined) {\r\n throw new Error(\"Ollama API returned empty choices\");\r\n }\r\n\r\n const toolCalls = extractToolCalls(choice);\r\n const inputTokens = data.usage?.prompt_tokens ?? 0;\r\n const outputTokens = data.usage?.completion_tokens ?? 0;\r\n\r\n const usage: ITokenUsage = {\r\n inputTokens,\r\n outputTokens,\r\n totalTokens: inputTokens + outputTokens,\r\n costUsd: 0,\r\n };\r\n\r\n const responseMessage: IChatMessage = {\r\n id: data.id,\r\n role: \"assistant\",\r\n content: choice.message.content ?? \"\",\r\n model: request.model,\r\n provider: PROVIDER_NAME,\r\n toolCalls: toolCalls.length > 0 ? toolCalls : undefined,\r\n tokenUsage: usage,\r\n createdAt: new Date(),\r\n };\r\n\r\n return {\r\n id: data.id,\r\n model: request.model,\r\n provider: PROVIDER_NAME,\r\n message: responseMessage,\r\n usage,\r\n finishReason: mapFinishReason(choice.finish_reason),\r\n };\r\n }\r\n\r\n async *stream(request: IChatRequest): AsyncIterable<IStreamChunk> {\r\n const modelInfo = this.getModelInfo(request.model);\r\n const messages = convertMessages(request.messages);\r\n const tools = convertTools(request.tools);\r\n\r\n if (request.system !== undefined) {\r\n messages.unshift({ role: \"system\", content: request.system });\r\n }\r\n\r\n const body: Record<string, unknown> = {\r\n model: request.model,\r\n messages,\r\n stream: true,\r\n };\r\n if (request.maxTokens !== undefined) {\r\n body[\"max_tokens\"] = request.maxTokens;\r\n }\r\n if (request.temperature !== undefined) {\r\n body[\"temperature\"] = request.temperature;\r\n }\r\n if (tools !== undefined) {\r\n body[\"tools\"] = tools;\r\n }\r\n\r\n const response = await fetch(`${this.baseUrl}/v1/chat/completions`, {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify(body),\r\n });\r\n\r\n if (!response.ok) {\r\n const text = await response.text();\r\n yield { type: \"error\", error: `Ollama API error (${response.status}): ${text}` };\r\n yield { type: \"done\" };\r\n return;\r\n }\r\n\r\n if (response.body === null) {\r\n yield { type: \"error\", error: \"Ollama returned empty stream body\" };\r\n yield { type: \"done\" };\r\n return;\r\n }\r\n\r\n try {\r\n yield* this.parseSSEStream(response.body, modelInfo);\r\n yield { type: \"done\" };\r\n } catch (error: unknown) {\r\n const errMsg = error instanceof Error ? error.message : String(error);\r\n logger.error({ error: errMsg, model: request.model }, \"Ollama stream error\");\r\n yield { type: \"error\", error: errMsg };\r\n yield { type: \"done\" };\r\n }\r\n }\r\n\r\n countTokens(text: string, _model: string): Promise<number> {\r\n return Promise.resolve(Math.ceil(text.length / CHARS_PER_TOKEN_ESTIMATE));\r\n }\r\n\r\n getModelInfo(model: string): IModelInfo {\r\n const staticInfo = SUPPORTED_MODELS[model];\r\n if (staticInfo !== undefined && staticInfo.provider === PROVIDER_NAME) {\r\n return staticInfo;\r\n }\r\n if (this.cachedModels !== undefined && this.cachedModels.includes(model)) {\r\n return makeOllamaModelInfo(model);\r\n }\r\n return makeOllamaModelInfo(model);\r\n }\r\n\r\n async listAvailableModels(): Promise<readonly string[]> {\r\n const models = await this.refreshModels();\r\n return models;\r\n }\r\n\r\n private async *parseSSEStream(\r\n body: ReadableStream<Uint8Array>,\r\n _modelInfo: IModelInfo,\r\n ): AsyncIterable<IStreamChunk> {\r\n const reader = body.getReader();\r\n const decoder = new TextDecoder();\r\n let buffer = \"\";\r\n\r\n try {\r\n for (;;) {\r\n const { done, value } = await reader.read();\r\n if (done) {\r\n break;\r\n }\r\n\r\n buffer += decoder.decode(value, { stream: true });\r\n const lines = buffer.split(\"\\n\");\r\n buffer = lines.pop() ?? \"\";\r\n\r\n for (const line of lines) {\r\n const trimmed = line.trim();\r\n if (trimmed === \"\" || trimmed === \"data: [DONE]\") {\r\n continue;\r\n }\r\n if (!trimmed.startsWith(\"data: \")) {\r\n continue;\r\n }\r\n\r\n const jsonStr = trimmed.slice(6);\r\n let parsed: {\r\n choices?: Array<{\r\n delta?: {\r\n content?: string;\r\n tool_calls?: Array<{\r\n id?: string;\r\n function?: { name?: string; arguments?: string };\r\n }>;\r\n };\r\n }>;\r\n usage?: OllamaUsage;\r\n };\r\n\r\n try {\r\n parsed = JSON.parse(jsonStr) as typeof parsed;\r\n } catch {\r\n continue;\r\n }\r\n\r\n const delta = parsed.choices?.[0]?.delta;\r\n if (delta?.content !== undefined && delta.content !== \"\") {\r\n yield { type: \"text\", content: delta.content };\r\n }\r\n\r\n if (delta?.tool_calls !== undefined) {\r\n for (const tc of delta.tool_calls) {\r\n if (tc.id !== undefined && tc.function?.name !== undefined) {\r\n let args: Record<string, unknown> = {};\r\n if (tc.function.arguments !== undefined) {\r\n try {\r\n args = JSON.parse(tc.function.arguments) as Record<string, unknown>;\r\n } catch {\r\n args = {};\r\n }\r\n }\r\n yield {\r\n type: \"tool_call\",\r\n toolCall: { id: tc.id, name: tc.function.name, arguments: args },\r\n };\r\n }\r\n }\r\n }\r\n\r\n if (parsed.usage !== undefined) {\r\n yield {\r\n type: \"usage\",\r\n usage: {\r\n inputTokens: parsed.usage.prompt_tokens,\r\n outputTokens: parsed.usage.completion_tokens,\r\n totalTokens: parsed.usage.total_tokens,\r\n costUsd: 0,\r\n },\r\n };\r\n }\r\n }\r\n }\r\n } finally {\r\n reader.releaseLock();\r\n }\r\n }\r\n}\r\n\r\nfunction extractToolCalls(choice: OllamaChoice): IToolCall[] {\r\n if (choice.message.tool_calls === undefined || choice.message.tool_calls.length === 0) {\r\n return [];\r\n }\r\n return choice.message.tool_calls.map((tc) => {\r\n let args: Record<string, unknown> = {};\r\n try {\r\n args = JSON.parse(tc.function.arguments) as Record<string, unknown>;\r\n } catch {\r\n args = {};\r\n }\r\n return { id: tc.id, name: tc.function.name, arguments: args };\r\n });\r\n}\r\n\r\nfunction mapFinishReason(\r\n reason: string,\r\n): \"stop\" | \"tool_calls\" | \"max_tokens\" | \"error\" {\r\n switch (reason) {\r\n case \"stop\":\r\n return \"stop\";\r\n case \"tool_calls\":\r\n return \"tool_calls\";\r\n case \"length\":\r\n return \"max_tokens\";\r\n default:\r\n return \"stop\";\r\n }\r\n}\r\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/orchestrator/utils/detect-providers.ts"],"names":[],"mappings":";;;AAsBO,SAAS,wBAAA,GAA8C;AAC5D,EAAA,MAAM,YAA+B,EAAC;AAEtC,EAAA,KAAA,MAAW,YAAY,kBAAA,EAAoB;AACzC,IAAA,IAAI;AACF,MAAA,MAAM,KAAA,GAAQ,oBAAoB,QAAQ,CAAA;AAC1C,MAAA,MAAM,IAAA,GAAO,CAAC,WAAW,CAAA;AACzB,MAAA,MAAM,MAAA,GAAS,SAAA,CAAU,KAAA,CAAM,MAAA,EAAQ,IAAA,EAAM;AAAA,QAC3C,KAAA,EAAO,QAAA;AAAA,QACP,OAAA,EAAS,GAAA;AAAA,QACT,KAAA,EAAO,QAAQ,QAAA,KAAa;AAAA,OAC7B,CAAA;AACD,MAAA,IAAI,MAAA,CAAO,WAAW,CAAA,EAAG;AACvB,QAAA,SAAA,CAAU,KAAK,QAAQ,CAAA;AAAA,MACzB;AAAA,IACF,CAAA,CAAA,MAAQ;AAAA,IAER;AAAA,EACF;AAEA,EAAA,OAAO,SAAA;AACT","file":"chunk-3TSPZRGM.js","sourcesContent":["/**\r\n * Cross-platform CLI provider detection utility.\r\n *\r\n * Probes the system PATH for known AI CLI tools by running\r\n * `<tool> --version` with a 5-second timeout. Returns a list\r\n * of provider types that are available on the current machine.\r\n *\r\n * @see IMPLEMENT_PLAN.md Section 10\r\n */\r\n\r\nimport { spawnSync } from \"node:child_process\";\r\nimport type { CliProviderType } from \"../constants.js\";\r\nimport { CLI_PROVIDER_ORDER, getCliProviderEntry } from \"./provider-catalog.js\";\r\n\r\n/**\r\n * Detect which CLI AI providers are installed on the system.\r\n *\r\n * Each provider is checked by running its version command. Only\r\n * providers that exit with status 0 are included in the result.\r\n *\r\n * @returns Array of installed CLI provider types.\r\n */\r\nexport function detectInstalledProviders(): CliProviderType[] {\r\n const available: CliProviderType[] = [];\r\n\r\n for (const provider of CLI_PROVIDER_ORDER) {\r\n try {\r\n const entry = getCliProviderEntry(provider);\r\n const args = [\"--version\"];\r\n const result = spawnSync(entry.binary, args, {\r\n stdio: \"ignore\",\r\n timeout: 5000,\r\n shell: process.platform === \"win32\",\r\n });\r\n if (result.status === 0) {\r\n available.push(provider);\r\n }\r\n } catch {\r\n // Not installed — skip\r\n }\r\n }\r\n\r\n return available;\r\n}\r\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/types/errors.ts"],"names":[],"mappings":"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","file":"chunk-473JN6M5.js","sourcesContent":["/**\r\n * AemeathCLI Typed Error Hierarchy\r\n * Per PRD section 15.5: Every error includes code, user message, diagnostic, recovery action\r\n */\r\n\r\nexport interface IErrorContext {\r\n readonly code: string;\r\n readonly userMessage: string;\r\n readonly diagnosticMessage?: string | undefined;\r\n readonly suggestedRecovery?: string | undefined;\r\n}\r\n\r\nexport abstract class AemeathError extends Error {\r\n abstract readonly code: string;\r\n abstract readonly userMessage: string;\r\n diagnosticMessage?: string | undefined;\r\n suggestedRecovery?: string | undefined;\r\n\r\n constructor(message: string, context?: Partial<IErrorContext>) {\r\n super(message);\r\n this.name = this.constructor.name;\r\n this.diagnosticMessage = context?.diagnosticMessage;\r\n this.suggestedRecovery = context?.suggestedRecovery;\r\n }\r\n}\r\n\r\n// ── Provider Errors ──────────────────────────────────────────────────────\r\n\r\nexport class AuthenticationError extends AemeathError {\r\n readonly code = \"AEMEATH_PROVIDER_AUTH_001\" as const;\r\n readonly userMessage: string;\r\n\r\n constructor(provider: string, message?: string) {\r\n super(message ?? `Authentication failed for provider: ${provider}`);\r\n this.userMessage = `Authentication failed for ${provider}. Please re-login with: aemeathcli auth login ${provider}`;\r\n }\r\n}\r\n\r\nexport class RateLimitError extends AemeathError {\r\n readonly code = \"AEMEATH_PROVIDER_RATE_001\" as const;\r\n readonly userMessage: string;\r\n readonly retryAfterMs: number;\r\n\r\n constructor(provider: string, retryAfterMs: number) {\r\n super(`Rate limited by ${provider}`);\r\n this.retryAfterMs = retryAfterMs;\r\n this.userMessage = `Rate limited by ${provider}. Retry in ${Math.ceil(retryAfterMs / 1000)}s.`;\r\n this.suggestedRecovery = \"Wait and retry, or switch to a different provider.\";\r\n }\r\n}\r\n\r\nexport class ContextOverflowError extends AemeathError {\r\n readonly code = \"AEMEATH_PROVIDER_CTX_001\" as const;\r\n readonly userMessage: string;\r\n\r\n constructor(model: string, maxTokens: number, currentTokens: number) {\r\n super(`Context overflow for ${model}: ${currentTokens}/${maxTokens}`);\r\n this.userMessage = `Context window exceeded for ${model}. Use /compact to compress context.`;\r\n }\r\n}\r\n\r\nexport class ModelNotFoundError extends AemeathError {\r\n readonly code = \"AEMEATH_PROVIDER_MODEL_001\" as const;\r\n readonly userMessage: string;\r\n\r\n constructor(model: string) {\r\n super(`Model not found: ${model}`);\r\n this.userMessage = `Model \"${model}\" not found. Use /model list to see available models.`;\r\n }\r\n}\r\n\r\n// ── Config Errors ────────────────────────────────────────────────────────\r\n\r\nexport class MissingConfigError extends AemeathError {\r\n readonly code = \"AEMEATH_CONFIG_MISS_001\" as const;\r\n readonly userMessage: string;\r\n\r\n constructor(key: string) {\r\n super(`Missing configuration: ${key}`);\r\n this.userMessage = `Missing configuration \"${key}\". Run aemeathcli config to set up.`;\r\n }\r\n}\r\n\r\nexport class InvalidConfigError extends AemeathError {\r\n readonly code = \"AEMEATH_CONFIG_INVALID_001\" as const;\r\n readonly userMessage: string;\r\n\r\n constructor(key: string, reason: string) {\r\n super(`Invalid configuration for ${key}: ${reason}`);\r\n this.userMessage = `Invalid configuration \"${key}\": ${reason}`;\r\n }\r\n}\r\n\r\n// ── Tool Errors ──────────────────────────────────────────────────────────\r\n\r\nexport class FileNotFoundError extends AemeathError {\r\n readonly code = \"AEMEATH_TOOL_FILE_001\" as const;\r\n readonly userMessage: string;\r\n\r\n constructor(filePath: string) {\r\n super(`File not found: ${filePath}`);\r\n this.userMessage = `File not found: ${filePath}`;\r\n }\r\n}\r\n\r\nexport class PermissionDeniedError extends AemeathError {\r\n readonly code = \"AEMEATH_TOOL_PERM_001\" as const;\r\n readonly userMessage: string;\r\n\r\n constructor(operation: string, resource: string) {\r\n super(`Permission denied: ${operation} on ${resource}`);\r\n this.userMessage = `Permission denied for ${operation} on ${resource}. Check your permission mode.`;\r\n }\r\n}\r\n\r\nexport class ExecutionTimeoutError extends AemeathError {\r\n readonly code = \"AEMEATH_TOOL_TIMEOUT_001\" as const;\r\n readonly userMessage: string;\r\n\r\n constructor(command: string, timeoutMs: number) {\r\n super(`Execution timeout: ${command} after ${timeoutMs}ms`);\r\n this.userMessage = `Command timed out after ${Math.ceil(timeoutMs / 1000)}s.`;\r\n }\r\n}\r\n\r\n// ── Team Errors ──────────────────────────────────────────────────────────\r\n\r\nexport class AgentSpawnError extends AemeathError {\r\n readonly code = \"AEMEATH_TEAM_SPAWN_001\" as const;\r\n readonly userMessage: string;\r\n\r\n constructor(agentName: string, reason: string) {\r\n super(`Failed to spawn agent ${agentName}: ${reason}`);\r\n this.userMessage = `Failed to start agent \"${agentName}\": ${reason}`;\r\n }\r\n}\r\n\r\nexport class IPCError extends AemeathError {\r\n readonly code = \"AEMEATH_TEAM_IPC_001\" as const;\r\n readonly userMessage: string;\r\n\r\n constructor(message: string) {\r\n super(`IPC error: ${message}`);\r\n this.userMessage = `Inter-agent communication error: ${message}`;\r\n }\r\n}\r\n\r\n// ── MCP Errors ───────────────────────────────────────────────────────────\r\n\r\nexport class ServerConnectionError extends AemeathError {\r\n readonly code = \"AEMEATH_MCP_CONN_001\" as const;\r\n readonly userMessage: string;\r\n\r\n constructor(serverName: string, reason: string) {\r\n super(`MCP server connection failed: ${serverName} - ${reason}`);\r\n this.userMessage = `Cannot connect to MCP server \"${serverName}\": ${reason}`;\r\n }\r\n}\r\n\r\nexport class ToolCallError extends AemeathError {\r\n readonly code = \"AEMEATH_MCP_TOOL_001\" as const;\r\n readonly userMessage: string;\r\n\r\n constructor(toolName: string, reason: string) {\r\n super(`MCP tool call failed: ${toolName} - ${reason}`);\r\n this.userMessage = `Tool \"${toolName}\" failed: ${reason}`;\r\n }\r\n}\r\n\r\n// ── Discriminated Error Union ────────────────────────────────────────────\r\n\r\nexport type ProviderError =\r\n | AuthenticationError\r\n | RateLimitError\r\n | ContextOverflowError\r\n | ModelNotFoundError;\r\n\r\nexport type ConfigError =\r\n | MissingConfigError\r\n | InvalidConfigError;\r\n\r\nexport type ToolError =\r\n | FileNotFoundError\r\n | PermissionDeniedError\r\n | ExecutionTimeoutError;\r\n\r\nexport type TeamError =\r\n | AgentSpawnError\r\n | IPCError;\r\n\r\nexport type MCPError =\r\n | ServerConnectionError\r\n | ToolCallError;\r\n\r\nexport type AnyAemeathError =\r\n | ProviderError\r\n | ConfigError\r\n | ToolError\r\n | TeamError\r\n | MCPError;\r\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/storage/config-store.ts"],"names":[],"mappings":"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","file":"chunk-5XFSV6PF.js","sourcesContent":["/**\r\n * Configuration store — PRD sections 17.2, 17.3\r\n * Loads/saves global and project config with Zod validation.\r\n * Merges project config over global config.\r\n * Watches for config file changes.\r\n */\r\n\r\nimport { readFileSync, writeFileSync, watchFile, unwatchFile } from \"node:fs\";\r\nimport { existsSync } from \"node:fs\";\r\nimport { dirname } from \"node:path\";\r\nimport { z } from \"zod\";\r\nimport { logger } from \"../utils/logger.js\";\r\nimport {\r\n getConfigPath,\r\n getProjectConfigPath,\r\n ensureDirectory,\r\n} from \"../utils/pathResolver.js\";\r\nimport { DEFAULT_CONFIG } from \"../types/config.js\";\r\nimport type { IGlobalConfig } from \"../types/config.js\";\r\nimport { CLI_PROVIDERS, type CliProviderType } from \"../orchestrator/constants.js\";\r\n\r\n// ── Zod Schemas ─────────────────────────────────────────────────────────\r\n\r\nconst ProviderConfigSchema = z.object({\r\n enabled: z.boolean(),\r\n baseUrl: z.string().optional(),\r\n}).strict();\r\n\r\nconst PermissionConfigSchema = z.object({\r\n mode: z.enum([\"strict\", \"standard\", \"permissive\"]),\r\n allowedPaths: z.array(z.string()),\r\n blockedCommands: z.array(z.string()),\r\n}).strict();\r\n\r\nconst SplitPanelConfigSchema = z.object({\r\n enabled: z.boolean(),\r\n backend: z.enum([\"tmux\", \"iterm2\"]),\r\n defaultLayout: z.enum([\"auto\", \"horizontal\", \"vertical\", \"grid\", \"hub-spoke\"]),\r\n maxPanes: z.number().int().min(1).max(16),\r\n}).strict();\r\n\r\nconst CLI_PROVIDER_ENUM_VALUES = [...CLI_PROVIDERS] as [\r\n CliProviderType,\r\n ...CliProviderType[],\r\n];\r\n\r\nconst SwarmConfigSchema = z.object({\r\n onboardingComplete: z.boolean(),\r\n detectedProviders: z.array(z.enum(CLI_PROVIDER_ENUM_VALUES)),\r\n primaryMasterProvider: z.enum(CLI_PROVIDER_ENUM_VALUES).optional(),\r\n fallbackMasterProviders: z.array(z.enum(CLI_PROVIDER_ENUM_VALUES)),\r\n}).strict();\r\n\r\nconst CostConfigSchema = z.object({\r\n budgetWarning: z.number().nonnegative(),\r\n budgetHardStop: z.number().nonnegative(),\r\n currency: z.string(),\r\n}).strict();\r\n\r\nconst TelemetryConfigSchema = z.object({\r\n enabled: z.boolean(),\r\n anonymized: z.boolean(),\r\n}).strict();\r\n\r\nconst RoleConfigSchema = z.object({\r\n primary: z.string(),\r\n fallback: z.array(z.string()),\r\n}).strict();\r\n\r\nconst OAuthProviderConfigSchema = z.object({\r\n clientId: z.string(),\r\n clientSecret: z.string().optional(),\r\n authorizeUrl: z.string().optional(),\r\n tokenUrl: z.string().optional(),\r\n scope: z.string().optional(),\r\n}).strict();\r\n\r\nconst OAuthConfigSchema = z.object({\r\n anthropic: OAuthProviderConfigSchema.optional(),\r\n openai: OAuthProviderConfigSchema.optional(),\r\n google: OAuthProviderConfigSchema.optional(),\r\n kimi: OAuthProviderConfigSchema.optional(),\r\n}).strict();\r\n\r\nconst GlobalConfigSchema = z.object({\r\n version: z.string(),\r\n defaultModel: z.string(),\r\n roles: z.record(z.string(), RoleConfigSchema).optional(),\r\n providers: z.record(z.string(), ProviderConfigSchema).optional(),\r\n permissions: PermissionConfigSchema.optional(),\r\n splitPanel: SplitPanelConfigSchema.optional(),\r\n swarm: SwarmConfigSchema.optional(),\r\n cost: CostConfigSchema.optional(),\r\n telemetry: TelemetryConfigSchema.optional(),\r\n oauth: OAuthConfigSchema.optional(),\r\n}).strict();\r\n\r\nfunction formatValidationError(error: z.ZodError): string {\r\n return error.issues\r\n .map((issue) => `${issue.path.join(\".\") || \"<root>\"}: ${issue.message}`)\r\n .join(\"; \");\r\n}\r\n\r\ntype ConfigChangeCallback = (config: IGlobalConfig) => void;\r\n\r\nexport class ConfigStore {\r\n private globalConfig: IGlobalConfig = DEFAULT_CONFIG;\r\n private projectConfig: Partial<IGlobalConfig> | undefined;\r\n private mergedConfig: IGlobalConfig = DEFAULT_CONFIG;\r\n private watchers: Array<{ path: string; active: boolean }> = [];\r\n private changeCallbacks: ConfigChangeCallback[] = [];\r\n\r\n get config(): IGlobalConfig {\r\n return this.mergedConfig;\r\n }\r\n\r\n loadGlobal(configPath?: string): IGlobalConfig {\r\n const resolvedPath = configPath ?? getConfigPath();\r\n\r\n if (!existsSync(resolvedPath)) {\r\n logger.info(\r\n { path: resolvedPath },\r\n \"Global config not found, using defaults\",\r\n );\r\n this.globalConfig = DEFAULT_CONFIG;\r\n this.rebuildMergedConfig();\r\n return this.mergedConfig;\r\n }\r\n\r\n let parsed: unknown;\r\n try {\r\n const raw = readFileSync(resolvedPath, \"utf-8\");\r\n parsed = JSON.parse(raw);\r\n } catch (error: unknown) {\r\n const message = error instanceof Error ? error.message : String(error);\r\n logger.warn({ error: message, path: resolvedPath }, \"Global config parse failed, using defaults\");\r\n this.globalConfig = DEFAULT_CONFIG;\r\n this.rebuildMergedConfig();\r\n return this.mergedConfig;\r\n }\r\n const validated = GlobalConfigSchema.safeParse(parsed);\r\n\r\n if (!validated.success) {\r\n logger.warn(\r\n { errors: validated.error.issues },\r\n \"Global config validation failed, using defaults\",\r\n );\r\n this.globalConfig = DEFAULT_CONFIG;\r\n this.rebuildMergedConfig();\r\n return this.mergedConfig;\r\n }\r\n\r\n this.globalConfig = this.applyDefaults(validated.data);\r\n this.rebuildMergedConfig();\r\n\r\n logger.info({ path: resolvedPath }, \"Global config loaded\");\r\n return this.mergedConfig;\r\n }\r\n\r\n loadProject(projectRoot: string): IGlobalConfig {\r\n const resolvedPath = getProjectConfigPath(projectRoot);\r\n\r\n if (!existsSync(resolvedPath)) {\r\n logger.debug(\r\n { path: resolvedPath },\r\n \"Project config not found, using global only\",\r\n );\r\n this.projectConfig = undefined;\r\n this.rebuildMergedConfig();\r\n return this.mergedConfig;\r\n }\r\n\r\n let parsed: unknown;\r\n try {\r\n const raw = readFileSync(resolvedPath, \"utf-8\");\r\n parsed = JSON.parse(raw);\r\n } catch (error: unknown) {\r\n const message = error instanceof Error ? error.message : String(error);\r\n logger.warn({ error: message, path: resolvedPath }, \"Project config parse failed, ignoring\");\r\n this.projectConfig = undefined;\r\n this.rebuildMergedConfig();\r\n return this.mergedConfig;\r\n }\r\n const validated = GlobalConfigSchema.partial().safeParse(parsed);\r\n\r\n if (!validated.success) {\r\n logger.warn(\r\n { errors: validated.error.issues },\r\n \"Project config validation failed, ignoring\",\r\n );\r\n this.projectConfig = undefined;\r\n this.rebuildMergedConfig();\r\n return this.mergedConfig;\r\n }\r\n\r\n this.projectConfig = validated.data as Partial<IGlobalConfig>;\r\n this.rebuildMergedConfig();\r\n\r\n logger.info({ path: resolvedPath }, \"Project config loaded\");\r\n return this.mergedConfig;\r\n }\r\n\r\n saveGlobal(\r\n config?: IGlobalConfig,\r\n configPath?: string,\r\n ): void {\r\n const resolvedPath = configPath ?? getConfigPath();\r\n const configToSave = config ?? this.globalConfig;\r\n const validated = GlobalConfigSchema.safeParse(configToSave);\r\n\r\n if (!validated.success) {\r\n throw new Error(`Invalid global config: ${formatValidationError(validated.error)}`);\r\n }\r\n\r\n ensureDirectory(dirname(resolvedPath));\r\n const json = JSON.stringify(validated.data, null, 2);\r\n writeFileSync(resolvedPath, json, { encoding: \"utf-8\", mode: 0o600 });\r\n\r\n logger.info({ path: resolvedPath }, \"Global config saved\");\r\n\r\n if (config) {\r\n this.globalConfig = this.applyDefaults(validated.data);\r\n this.rebuildMergedConfig();\r\n }\r\n }\r\n\r\n saveProject(\r\n projectRoot: string,\r\n config: Partial<IGlobalConfig>,\r\n ): void {\r\n const resolvedPath = getProjectConfigPath(projectRoot);\r\n const validated = GlobalConfigSchema.partial().safeParse(config);\r\n\r\n if (!validated.success) {\r\n throw new Error(`Invalid project config: ${formatValidationError(validated.error)}`);\r\n }\r\n\r\n ensureDirectory(dirname(resolvedPath));\r\n const json = JSON.stringify(validated.data, null, 2);\r\n writeFileSync(resolvedPath, json, { encoding: \"utf-8\", mode: 0o600 });\r\n\r\n this.projectConfig = validated.data as Partial<IGlobalConfig>;\r\n this.rebuildMergedConfig();\r\n\r\n logger.info({ path: resolvedPath }, \"Project config saved\");\r\n }\r\n\r\n watchGlobal(configPath?: string): void {\r\n const resolvedPath = configPath ?? getConfigPath();\r\n this.watchConfigFile(resolvedPath, () => {\r\n this.loadGlobal(resolvedPath);\r\n });\r\n }\r\n\r\n watchProject(projectRoot: string): void {\r\n const resolvedPath = getProjectConfigPath(projectRoot);\r\n this.watchConfigFile(resolvedPath, () => {\r\n this.loadProject(projectRoot);\r\n });\r\n }\r\n\r\n onChange(callback: ConfigChangeCallback): void {\r\n this.changeCallbacks.push(callback);\r\n }\r\n\r\n stopWatching(): void {\r\n for (const watcher of this.watchers) {\r\n if (watcher.active) {\r\n unwatchFile(watcher.path);\r\n watcher.active = false;\r\n }\r\n }\r\n this.watchers = [];\r\n }\r\n\r\n private watchConfigFile(filePath: string, onUpdate: () => void): void {\r\n if (!existsSync(filePath)) {\r\n return;\r\n }\r\n\r\n const entry = { path: filePath, active: true };\r\n this.watchers.push(entry);\r\n\r\n watchFile(filePath, { interval: 2000 }, () => {\r\n if (!entry.active) {\r\n return;\r\n }\r\n logger.info({ path: filePath }, \"Config file changed, reloading\");\r\n try {\r\n onUpdate();\r\n } catch (error: unknown) {\r\n const message =\r\n error instanceof Error ? error.message : String(error);\r\n logger.error({ error: message }, \"Failed to reload config\");\r\n }\r\n });\r\n }\r\n\r\n private rebuildMergedConfig(): void {\r\n if (!this.projectConfig) {\r\n this.mergedConfig = { ...this.globalConfig };\r\n } else {\r\n this.mergedConfig = {\r\n ...this.globalConfig,\r\n ...this.projectConfig,\r\n roles: {\r\n ...this.globalConfig.roles,\r\n ...(this.projectConfig.roles ?? {}),\r\n },\r\n providers: {\r\n ...this.globalConfig.providers,\r\n ...(this.projectConfig.providers ?? {}),\r\n },\r\n permissions: {\r\n ...this.globalConfig.permissions,\r\n ...(this.projectConfig.permissions ?? {}),\r\n },\r\n splitPanel: {\r\n ...this.globalConfig.splitPanel,\r\n ...(this.projectConfig.splitPanel ?? {}),\r\n },\r\n swarm: {\r\n ...this.globalConfig.swarm,\r\n ...(this.projectConfig.swarm ?? {}),\r\n },\r\n cost: {\r\n ...this.globalConfig.cost,\r\n ...(this.projectConfig.cost ?? {}),\r\n },\r\n telemetry: {\r\n ...this.globalConfig.telemetry,\r\n ...(this.projectConfig.telemetry ?? {}),\r\n },\r\n oauth: this.projectConfig.oauth ?? this.globalConfig.oauth,\r\n };\r\n }\r\n\r\n for (const cb of this.changeCallbacks) {\r\n try {\r\n cb(this.mergedConfig);\r\n } catch (error: unknown) {\r\n const message =\r\n error instanceof Error ? error.message : String(error);\r\n logger.error({ error: message }, \"Config change callback failed\");\r\n }\r\n }\r\n }\r\n\r\n private applyDefaults(\r\n partial: z.infer<typeof GlobalConfigSchema>,\r\n ): IGlobalConfig {\r\n return {\r\n version: partial.version,\r\n defaultModel: partial.defaultModel,\r\n roles: {\r\n ...DEFAULT_CONFIG.roles,\r\n ...(partial.roles as IGlobalConfig[\"roles\"] | undefined),\r\n },\r\n providers: {\r\n ...DEFAULT_CONFIG.providers,\r\n ...(partial.providers as IGlobalConfig[\"providers\"] | undefined),\r\n },\r\n permissions: partial.permissions\r\n ? (partial.permissions as IGlobalConfig[\"permissions\"])\r\n : DEFAULT_CONFIG.permissions,\r\n splitPanel: partial.splitPanel\r\n ? (partial.splitPanel as IGlobalConfig[\"splitPanel\"])\r\n : DEFAULT_CONFIG.splitPanel,\r\n swarm: partial.swarm\r\n ? (partial.swarm as IGlobalConfig[\"swarm\"])\r\n : DEFAULT_CONFIG.swarm,\r\n cost: partial.cost\r\n ? (partial.cost as IGlobalConfig[\"cost\"])\r\n : DEFAULT_CONFIG.cost,\r\n telemetry: partial.telemetry\r\n ? (partial.telemetry as IGlobalConfig[\"telemetry\"])\r\n : DEFAULT_CONFIG.telemetry,\r\n oauth: partial.oauth\r\n ? (partial.oauth as IGlobalConfig[\"oauth\"])\r\n : undefined,\r\n };\r\n }\r\n}\r\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/types/model.ts"],"names":[],"mappings":"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","file":"chunk-62HSGYQD.js","sourcesContent":["/**\r\n * Model-related types per PRD sections 7.1-7.5\r\n */\r\n\r\n// ── Provider Identifiers ─────────────────────────────────────────────────\r\n\r\nexport type ProviderName = \"anthropic\" | \"openai\" | \"google\" | \"kimi\" | \"ollama\";\r\n\r\n// ── Model Roles (PRD section 7.2) ───────────────────────────────────────\r\n\r\nexport type ModelRole =\r\n | \"planning\"\r\n | \"coding\"\r\n | \"review\"\r\n | \"testing\"\r\n | \"bugfix\"\r\n | \"documentation\";\r\n\r\n// ── Provider-specific Thinking / Reasoning Configuration ─────────────────\r\n\r\nexport interface IThinkingOption {\r\n readonly value: string;\r\n readonly label: string;\r\n readonly description: string;\r\n}\r\n\r\nexport interface IProviderThinkingConfig {\r\n readonly method: string;\r\n readonly options: readonly IThinkingOption[];\r\n readonly defaultValue: string;\r\n}\r\n\r\n/**\r\n * Provider-specific thinking configurations.\r\n *\r\n * Anthropic → Extended Thinking (budget_tokens: 1024–model max)\r\n * OpenAI → Reasoning Effort (low | medium | high)\r\n * Google 2.5 → Thinking Budget (0–24576, -1 = dynamic)\r\n * Google 3 → Thinking Level (minimal | low | medium | high)\r\n * Kimi → Thinking Mode (enabled | disabled)\r\n */\r\nexport const PROVIDER_THINKING_CONFIGS: Readonly<Record<string, IProviderThinkingConfig>> = {\r\n anthropic: {\r\n method: \"extended_thinking\",\r\n options: [\r\n { value: \"off\", label: \"Off\", description: \"No extended thinking\" },\r\n { value: \"low\", label: \"Low (1K tokens)\", description: \"budget_tokens: 1024\" },\r\n { value: \"medium\", label: \"Medium (8K tokens)\", description: \"budget_tokens: 8192\" },\r\n { value: \"high\", label: \"High (16K tokens)\", description: \"budget_tokens: 16384\" },\r\n { value: \"max\", label: \"Max (model limit)\", description: \"budget_tokens: max_output_tokens\" },\r\n ],\r\n defaultValue: \"medium\",\r\n },\r\n openai: {\r\n method: \"reasoning_effort\",\r\n options: [\r\n { value: \"low\", label: \"Low\", description: \"Fewer reasoning tokens, faster\" },\r\n { value: \"medium\", label: \"Medium\", description: \"Balanced reasoning (default)\" },\r\n { value: \"high\", label: \"High\", description: \"Thorough reasoning, more tokens\" },\r\n ],\r\n defaultValue: \"medium\",\r\n },\r\n \"google:gemini-2.5\": {\r\n method: \"thinking_budget\",\r\n options: [\r\n { value: \"off\", label: \"Off\", description: \"Disable thinking (budget: 0)\" },\r\n { value: \"dynamic\", label: \"Dynamic\", description: \"Auto-adjust based on complexity (budget: -1)\" },\r\n { value: \"low\", label: \"Low (4K tokens)\", description: \"thinkingBudget: 4096\" },\r\n { value: \"medium\", label: \"Medium (12K tokens)\", description: \"thinkingBudget: 12288\" },\r\n { value: \"high\", label: \"High (24K tokens)\", description: \"thinkingBudget: 24576\" },\r\n ],\r\n defaultValue: \"dynamic\",\r\n },\r\n \"google:gemini-3\": {\r\n method: \"thinking_level\",\r\n options: [\r\n { value: \"minimal\", label: \"Minimal\", description: \"Minimal thinking\" },\r\n { value: \"low\", label: \"Low\", description: \"Light thinking\" },\r\n { value: \"medium\", label: \"Medium\", description: \"Balanced thinking\" },\r\n { value: \"high\", label: \"High\", description: \"Deep thinking\" },\r\n ],\r\n defaultValue: \"medium\",\r\n },\r\n kimi: {\r\n method: \"thinking_mode\",\r\n options: [\r\n { value: \"enabled\", label: \"Enabled\", description: \"Include reasoning traces\" },\r\n { value: \"disabled\", label: \"Disabled\", description: \"Direct responses only\" },\r\n ],\r\n defaultValue: \"enabled\",\r\n },\r\n};\r\n\r\n/**\r\n * Look up the thinking configuration for a specific model.\r\n * Handles Google's model-family split (Gemini 2.5 vs Gemini 3).\r\n */\r\nexport function getThinkingConfigForModel(modelId: string): IProviderThinkingConfig | undefined {\r\n const modelInfo = SUPPORTED_MODELS[modelId];\r\n if (modelInfo === undefined) return undefined;\r\n\r\n if (modelInfo.provider === \"google\") {\r\n if (modelId.startsWith(\"gemini-3\")) {\r\n return PROVIDER_THINKING_CONFIGS[\"google:gemini-3\"];\r\n }\r\n return PROVIDER_THINKING_CONFIGS[\"google:gemini-2.5\"];\r\n }\r\n\r\n return PROVIDER_THINKING_CONFIGS[modelInfo.provider];\r\n}\r\n\r\n// ── Model Information ────────────────────────────────────────────────────\r\n\r\nexport interface IModelInfo {\r\n readonly id: string;\r\n readonly name: string;\r\n readonly provider: ProviderName;\r\n readonly contextWindow: number;\r\n readonly maxOutputTokens: number;\r\n readonly inputPricePerMToken: number;\r\n readonly outputPricePerMToken: number;\r\n readonly supportsStreaming: boolean;\r\n readonly supportsToolCalling: boolean;\r\n readonly supportedRoles: readonly ModelRole[];\r\n readonly description?: string | undefined;\r\n}\r\n\r\n// ── Model Display Entry (for /model selection UI) ────────────────────────\r\n\r\nexport interface IModelDisplayEntry {\r\n readonly id: string;\r\n readonly label: string;\r\n readonly description: string;\r\n readonly isDefault?: boolean | undefined;\r\n}\r\n\r\n// ── Role Configuration (PRD section 7.2) ─────────────────────────────────\r\n\r\nexport interface IRoleConfig {\r\n readonly primary: string;\r\n readonly fallback: readonly string[];\r\n}\r\n\r\n// ── Model Router Resolution (PRD section 7.2) ────────────────────────────\r\n\r\nexport type ModelResolutionSource =\r\n | \"user_override\"\r\n | \"role_config\"\r\n | \"fallback_chain\"\r\n | \"system_default\";\r\n\r\nexport interface IModelResolution {\r\n readonly modelId: string;\r\n readonly provider: ProviderName;\r\n readonly source: ModelResolutionSource;\r\n readonly role?: ModelRole | undefined;\r\n}\r\n\r\n// ── Token Usage ──────────────────────────────────────────────────────────\r\n\r\nexport interface ITokenUsage {\r\n readonly inputTokens: number;\r\n readonly outputTokens: number;\r\n readonly totalTokens: number;\r\n readonly costUsd: number;\r\n}\r\n\r\n// ── Supported Models Registry (PRD section 7.3) ─────────────────────────\r\n\r\nexport const SUPPORTED_MODELS: Record<string, IModelInfo> = {\r\n // ── Anthropic / Claude ─────────────────────────────────────────────────\r\n \"claude-opus-4-6\": {\r\n id: \"claude-opus-4-6\",\r\n name: \"Claude Opus 4.6\",\r\n provider: \"anthropic\",\r\n contextWindow: 200_000,\r\n maxOutputTokens: 32_000,\r\n inputPricePerMToken: 15,\r\n outputPricePerMToken: 75,\r\n supportsStreaming: true,\r\n supportsToolCalling: true,\r\n supportedRoles: [\"planning\", \"review\", \"bugfix\", \"coding\"],\r\n description: \"Most capable for complex work\",\r\n },\r\n \"claude-opus-4-6-1m\": {\r\n id: \"claude-opus-4-6-1m\",\r\n name: \"Claude Opus 4.6 (1M context)\",\r\n provider: \"anthropic\",\r\n contextWindow: 1_000_000,\r\n maxOutputTokens: 32_000,\r\n inputPricePerMToken: 10,\r\n outputPricePerMToken: 37.5,\r\n supportsStreaming: true,\r\n supportsToolCalling: true,\r\n supportedRoles: [\"planning\", \"review\", \"bugfix\", \"coding\"],\r\n description: \"Opus 4.6 with 1M context\",\r\n },\r\n \"claude-sonnet-4-6\": {\r\n id: \"claude-sonnet-4-6\",\r\n name: \"Claude Sonnet 4.6\",\r\n provider: \"anthropic\",\r\n contextWindow: 200_000,\r\n maxOutputTokens: 16_000,\r\n inputPricePerMToken: 3,\r\n outputPricePerMToken: 15,\r\n supportsStreaming: true,\r\n supportsToolCalling: true,\r\n supportedRoles: [\"coding\", \"bugfix\", \"documentation\", \"review\"],\r\n description: \"Best for everyday tasks\",\r\n },\r\n \"claude-sonnet-4-6-1m\": {\r\n id: \"claude-sonnet-4-6-1m\",\r\n name: \"Claude Sonnet 4.6 (1M context)\",\r\n provider: \"anthropic\",\r\n contextWindow: 1_000_000,\r\n maxOutputTokens: 16_000,\r\n inputPricePerMToken: 6,\r\n outputPricePerMToken: 22.5,\r\n supportsStreaming: true,\r\n supportsToolCalling: true,\r\n supportedRoles: [\"coding\", \"bugfix\", \"documentation\", \"review\"],\r\n description: \"Sonnet 4.6 with 1M context\",\r\n },\r\n \"claude-haiku-4-5\": {\r\n id: \"claude-haiku-4-5\",\r\n name: \"Claude Haiku 4.5\",\r\n provider: \"anthropic\",\r\n contextWindow: 200_000,\r\n maxOutputTokens: 8_192,\r\n inputPricePerMToken: 0.8,\r\n outputPricePerMToken: 4,\r\n supportsStreaming: true,\r\n supportsToolCalling: true,\r\n supportedRoles: [\"testing\", \"documentation\"],\r\n description: \"Fastest for quick answers\",\r\n },\r\n\r\n // ── OpenAI / Codex ─────────────────────────────────────────────────────\r\n \"gpt-5.3-codex\": {\r\n id: \"gpt-5.3-codex\",\r\n name: \"GPT-5.3 Codex\",\r\n provider: \"openai\",\r\n contextWindow: 256_000,\r\n maxOutputTokens: 32_000,\r\n inputPricePerMToken: 2.5,\r\n outputPricePerMToken: 10,\r\n supportsStreaming: true,\r\n supportsToolCalling: true,\r\n supportedRoles: [\"planning\", \"coding\", \"review\", \"bugfix\"],\r\n description: \"Latest frontier agentic coding model\",\r\n },\r\n \"gpt-5.3-codex-spark\": {\r\n id: \"gpt-5.3-codex-spark\",\r\n name: \"GPT-5.3 Codex Spark\",\r\n provider: \"openai\",\r\n contextWindow: 256_000,\r\n maxOutputTokens: 16_384,\r\n inputPricePerMToken: 0.15,\r\n outputPricePerMToken: 0.6,\r\n supportsStreaming: true,\r\n supportsToolCalling: true,\r\n supportedRoles: [\"coding\", \"testing\", \"documentation\"],\r\n description: \"Ultra-fast coding model\",\r\n },\r\n \"gpt-5.2-codex\": {\r\n id: \"gpt-5.2-codex\",\r\n name: \"GPT-5.2 Codex\",\r\n provider: \"openai\",\r\n contextWindow: 256_000,\r\n maxOutputTokens: 32_000,\r\n inputPricePerMToken: 2.5,\r\n outputPricePerMToken: 10,\r\n supportsStreaming: true,\r\n supportsToolCalling: true,\r\n supportedRoles: [\"planning\", \"coding\", \"review\", \"bugfix\"],\r\n description: \"Frontier agentic coding model\",\r\n },\r\n \"gpt-5.1-codex-max\": {\r\n id: \"gpt-5.1-codex-max\",\r\n name: \"GPT-5.1 Codex Max\",\r\n provider: \"openai\",\r\n contextWindow: 256_000,\r\n maxOutputTokens: 100_000,\r\n inputPricePerMToken: 10,\r\n outputPricePerMToken: 40,\r\n supportsStreaming: true,\r\n supportsToolCalling: true,\r\n supportedRoles: [\"planning\", \"review\", \"coding\"],\r\n description: \"Codex-optimized flagship for deep and fast reasoning\",\r\n },\r\n \"gpt-5.2\": {\r\n id: \"gpt-5.2\",\r\n name: \"GPT-5.2\",\r\n provider: \"openai\",\r\n contextWindow: 256_000,\r\n maxOutputTokens: 32_000,\r\n inputPricePerMToken: 2.5,\r\n outputPricePerMToken: 10,\r\n supportsStreaming: true,\r\n supportsToolCalling: true,\r\n supportedRoles: [\"planning\", \"coding\", \"review\", \"bugfix\"],\r\n description: \"Latest frontier model with improvements across knowledge, reasoning and coding\",\r\n },\r\n \"gpt-5.1-codex-mini\": {\r\n id: \"gpt-5.1-codex-mini\",\r\n name: \"GPT-5.1 Codex Mini\",\r\n provider: \"openai\",\r\n contextWindow: 256_000,\r\n maxOutputTokens: 16_384,\r\n inputPricePerMToken: 0.15,\r\n outputPricePerMToken: 0.6,\r\n supportsStreaming: true,\r\n supportsToolCalling: true,\r\n supportedRoles: [\"testing\", \"documentation\", \"coding\"],\r\n description: \"Optimized for codex. Cheaper, faster, but less capable\",\r\n },\r\n\r\n // ── Google / Gemini ────────────────────────────────────────────────────\r\n \"gemini-3-pro-preview\": {\r\n id: \"gemini-3-pro-preview\",\r\n name: \"Gemini 3 Pro Preview\",\r\n provider: \"google\",\r\n contextWindow: 2_000_000,\r\n maxOutputTokens: 65_536,\r\n inputPricePerMToken: 1.25,\r\n outputPricePerMToken: 10,\r\n supportsStreaming: true,\r\n supportsToolCalling: true,\r\n supportedRoles: [\"planning\", \"review\", \"coding\"],\r\n description: \"Next-gen Gemini Pro preview\",\r\n },\r\n \"gemini-3-flash-preview\": {\r\n id: \"gemini-3-flash-preview\",\r\n name: \"Gemini 3 Flash Preview\",\r\n provider: \"google\",\r\n contextWindow: 2_000_000,\r\n maxOutputTokens: 65_536,\r\n inputPricePerMToken: 0.15,\r\n outputPricePerMToken: 0.6,\r\n supportsStreaming: true,\r\n supportsToolCalling: true,\r\n supportedRoles: [\"coding\", \"testing\", \"documentation\"],\r\n description: \"Next-gen Gemini Flash preview\",\r\n },\r\n \"gemini-2.5-pro\": {\r\n id: \"gemini-2.5-pro\",\r\n name: \"Gemini 2.5 Pro\",\r\n provider: \"google\",\r\n contextWindow: 2_000_000,\r\n maxOutputTokens: 65_536,\r\n inputPricePerMToken: 1.25,\r\n outputPricePerMToken: 10,\r\n supportsStreaming: true,\r\n supportsToolCalling: true,\r\n supportedRoles: [\"planning\", \"review\", \"coding\"],\r\n description: \"Gemini 2.5 Pro stable\",\r\n },\r\n \"gemini-2.5-flash\": {\r\n id: \"gemini-2.5-flash\",\r\n name: \"Gemini 2.5 Flash\",\r\n provider: \"google\",\r\n contextWindow: 2_000_000,\r\n maxOutputTokens: 65_536,\r\n inputPricePerMToken: 0.15,\r\n outputPricePerMToken: 0.6,\r\n supportsStreaming: true,\r\n supportsToolCalling: true,\r\n supportedRoles: [\"testing\", \"documentation\", \"coding\"],\r\n description: \"Gemini 2.5 Flash stable\",\r\n },\r\n \"gemini-2.5-flash-lite\": {\r\n id: \"gemini-2.5-flash-lite\",\r\n name: \"Gemini 2.5 Flash Lite\",\r\n provider: \"google\",\r\n contextWindow: 1_000_000,\r\n maxOutputTokens: 32_768,\r\n inputPricePerMToken: 0.075,\r\n outputPricePerMToken: 0.3,\r\n supportsStreaming: true,\r\n supportsToolCalling: true,\r\n supportedRoles: [\"testing\", \"documentation\"],\r\n description: \"Gemini 2.5 Flash Lite\",\r\n },\r\n\r\n // ── Moonshot / Kimi ────────────────────────────────────────────────────\r\n \"kimi-for-coding\": {\r\n id: \"kimi-for-coding\",\r\n name: \"Kimi Code\",\r\n provider: \"kimi\",\r\n contextWindow: 128_000,\r\n maxOutputTokens: 8_192,\r\n inputPricePerMToken: 0.5,\r\n outputPricePerMToken: 2,\r\n supportsStreaming: true,\r\n supportsToolCalling: true,\r\n supportedRoles: [\"coding\", \"bugfix\"],\r\n description: \"Kimi for coding\",\r\n },\r\n};\r\n\r\n// ── Ordered Model Lists Per Provider (for /model selection UI) ───────────\r\n\r\nexport const PROVIDER_MODEL_ORDER: Readonly<Record<string, readonly IModelDisplayEntry[]>> = {\r\n anthropic: [\r\n { id: \"claude-opus-4-6\", label: \"Default (recommended)\", description: \"Opus 4.6 · Most capable for complex work\", isDefault: true },\r\n { id: \"claude-opus-4-6-1m\", label: \"Opus (1M context)\", description: \"Opus 4.6 with 1M context · Billed as extra usage · $10/$37.50 per Mtok\" },\r\n { id: \"claude-sonnet-4-6\", label: \"Sonnet\", description: \"Sonnet 4.6 · Best for everyday tasks\" },\r\n { id: \"claude-sonnet-4-6-1m\", label: \"Sonnet (1M context)\", description: \"Sonnet 4.6 with 1M context · Billed as extra usage · $6/$22.50 per Mtok\" },\r\n { id: \"claude-haiku-4-5\", label: \"Haiku\", description: \"Haiku 4.5 · Fastest for quick answers\" },\r\n ],\r\n openai: [\r\n { id: \"gpt-5.3-codex\", label: \"gpt-5.3-codex\", description: \"Latest frontier agentic coding model\", isDefault: true },\r\n { id: \"gpt-5.3-codex-spark\", label: \"gpt-5.3-codex-spark\", description: \"Ultra-fast coding model\" },\r\n { id: \"gpt-5.2-codex\", label: \"gpt-5.2-codex\", description: \"Frontier agentic coding model\" },\r\n { id: \"gpt-5.1-codex-max\", label: \"gpt-5.1-codex-max\", description: \"Codex-optimized flagship for deep and fast reasoning\" },\r\n { id: \"gpt-5.2\", label: \"gpt-5.2\", description: \"Latest frontier model with improvements across knowledge, reasoning and coding\" },\r\n { id: \"gpt-5.1-codex-mini\", label: \"gpt-5.1-codex-mini\", description: \"Optimized for codex. Cheaper, faster, but less capable\" },\r\n ],\r\n google: [\r\n { id: \"gemini-3-pro-preview\", label: \"gemini-3-pro-preview\", description: \"Next-gen Gemini Pro preview\", isDefault: true },\r\n { id: \"gemini-3-flash-preview\", label: \"gemini-3-flash-preview\", description: \"Next-gen Gemini Flash preview\" },\r\n { id: \"gemini-2.5-pro\", label: \"gemini-2.5-pro\", description: \"Gemini 2.5 Pro stable\" },\r\n { id: \"gemini-2.5-flash\", label: \"gemini-2.5-flash\", description: \"Gemini 2.5 Flash stable\" },\r\n { id: \"gemini-2.5-flash-lite\", label: \"gemini-2.5-flash-lite\", description: \"Gemini 2.5 Flash Lite\" },\r\n ],\r\n kimi: [\r\n { id: \"kimi-for-coding\", label: \"kimi-for-coding (Kimi Code)\", description: \"Kimi for coding\", isDefault: true },\r\n ],\r\n};\r\n\r\nexport const DEFAULT_MODEL_ID = \"claude-sonnet-4-6\";\r\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/auth/api-key-fallback.ts"],"names":[],"mappings":"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","file":"chunk-6GUD7QIM.js","sourcesContent":["/**\r\n * API Key Fallback — store/retrieve/validate API keys per provider\r\n * Per PRD section 13.5 — optional fallback for CI/headless environments\r\n */\r\n\r\nimport type { ProviderName, ICredential } from \"../types/index.js\";\r\nimport { CredentialStore } from \"./credential-store.js\";\r\nimport { logger } from \"../utils/index.js\";\r\n\r\n// ── Environment Variable Mapping ─────────────────────────────────────────\r\n\r\nconst ENV_KEY_MAP: Readonly<Record<ProviderName, string | undefined>> = {\r\n anthropic: \"ANTHROPIC_API_KEY\",\r\n openai: \"OPENAI_API_KEY\",\r\n google: \"GOOGLE_API_KEY\",\r\n kimi: \"MOONSHOT_API_KEY\",\r\n ollama: undefined,\r\n} as const;\r\n\r\n// ── CLI-Friendly Provider Names ──────────────────────────────────────────\r\n\r\nconst CLI_PROVIDER_MAP: Readonly<Record<string, ProviderName>> = {\r\n claude: \"anthropic\",\r\n anthropic: \"anthropic\",\r\n openai: \"openai\",\r\n codex: \"openai\",\r\n google: \"google\",\r\n gemini: \"google\",\r\n kimi: \"kimi\",\r\n moonshot: \"kimi\",\r\n} as const;\r\n\r\n// ── API Key Validation Patterns ──────────────────────────────────────────\r\n\r\nconst KEY_PATTERNS: Readonly<Record<ProviderName, RegExp | undefined>> = {\r\n anthropic: /^sk-ant-api\\d{2}-[A-Za-z0-9_-]{20,}$/,\r\n openai: /^sk-[A-Za-z0-9_-]{20,}$/,\r\n google: /^AIza[A-Za-z0-9_-]{30,}$/,\r\n kimi: /^sk-[A-Za-z0-9_-]{20,}$/,\r\n ollama: undefined,\r\n} as const;\r\n\r\nconst API_KEY_CREDENTIAL_PREFIX = \"apikey:\";\r\n\r\n// ── Public Helpers ───────────────────────────────────────────────────────\r\n\r\nexport function resolveProviderName(alias: string): ProviderName | undefined {\r\n const normalized = alias.toLowerCase().trim();\r\n return CLI_PROVIDER_MAP[normalized];\r\n}\r\n\r\nexport function getEnvKeyName(provider: ProviderName): string | undefined {\r\n return ENV_KEY_MAP[provider];\r\n}\r\n\r\n// ── ApiKeyFallback Class ─────────────────────────────────────────────────\r\n\r\nexport class ApiKeyFallback {\r\n private readonly store: CredentialStore;\r\n\r\n constructor(store?: CredentialStore) {\r\n this.store = store ?? new CredentialStore();\r\n }\r\n\r\n /**\r\n * Validate an API key format for a given provider.\r\n */\r\n validateKeyFormat(provider: ProviderName, key: string): boolean {\r\n const pattern = KEY_PATTERNS[provider];\r\n if (pattern === undefined) {\r\n return key.length > 0;\r\n }\r\n return pattern.test(key);\r\n }\r\n\r\n /**\r\n * Store an API key for a provider via the credential store.\r\n */\r\n async setKey(provider: ProviderName, key: string): Promise<void> {\r\n if (!this.validateKeyFormat(provider, key)) {\r\n logger.warn({ provider }, \"API key format does not match expected pattern — storing anyway\");\r\n }\r\n\r\n const credential: ICredential = {\r\n provider,\r\n method: \"api_key\",\r\n token: `${API_KEY_CREDENTIAL_PREFIX}${key}`,\r\n };\r\n\r\n await this.store.set(provider, credential);\r\n logger.info({ provider }, \"API key stored\");\r\n }\r\n\r\n /**\r\n * Retrieve a stored API key credential for a provider.\r\n * Only returns credentials stored via setKey (not native login tokens).\r\n */\r\n async getCredential(provider: ProviderName): Promise<ICredential | undefined> {\r\n const stored = await this.store.get(provider);\r\n if (stored === undefined) return undefined;\r\n\r\n if (stored.method !== \"api_key\") return undefined;\r\n\r\n // Strip the internal prefix\r\n if (stored.token?.startsWith(API_KEY_CREDENTIAL_PREFIX)) {\r\n return {\r\n ...stored,\r\n token: stored.token.slice(API_KEY_CREDENTIAL_PREFIX.length),\r\n };\r\n }\r\n\r\n return stored;\r\n }\r\n\r\n /**\r\n * Get an API key from environment variables.\r\n */\r\n getFromEnvironment(provider: ProviderName): ICredential | undefined {\r\n const envKey = ENV_KEY_MAP[provider];\r\n if (envKey === undefined) return undefined;\r\n\r\n const value = process.env[envKey];\r\n if (value === undefined || value.length === 0) return undefined;\r\n\r\n return {\r\n provider,\r\n method: \"env_variable\",\r\n token: value,\r\n };\r\n }\r\n\r\n /**\r\n * Delete a stored API key for a provider.\r\n */\r\n async deleteKey(provider: ProviderName): Promise<void> {\r\n const stored = await this.store.get(provider);\r\n if (stored !== undefined && stored.method === \"api_key\") {\r\n await this.store.delete(provider);\r\n logger.info({ provider }, \"API key deleted\");\r\n }\r\n }\r\n\r\n /**\r\n * Check if an API key is available (stored or env) for a provider.\r\n */\r\n async hasKey(provider: ProviderName): Promise<boolean> {\r\n const stored = await this.getCredential(provider);\r\n if (stored !== undefined) return true;\r\n return this.getFromEnvironment(provider) !== undefined;\r\n }\r\n}\r\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/auth/credential-store.ts"],"names":[],"mappings":"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","file":"chunk-AQ23TYSQ.js","sourcesContent":["/**\r\n * Credential storage per PRD section 13.6\r\n * Primary: OS keychain via node-keytar\r\n * Fallback: AES-256-GCM encrypted file\r\n */\r\n\r\nimport { createCipheriv, createDecipheriv, randomBytes, scryptSync } from \"node:crypto\";\r\nimport { readFileSync, writeFileSync, existsSync, chmodSync } from \"node:fs\";\r\nimport type * as Keytar from \"keytar\";\r\nimport type { ProviderName, ICredential } from \"../types/index.js\";\r\nimport { getCredentialsPath, ensureSecureDirectory, getAemeathHome } from \"../utils/index.js\";\r\nimport { logger } from \"../utils/index.js\";\r\n\r\nconst SERVICE_PREFIX = \"com.aemeathcli\";\r\nconst ALGORITHM = \"aes-256-gcm\";\r\nconst KEY_LENGTH = 32;\r\nconst IV_LENGTH = 16;\r\nconst TAG_LENGTH = 16;\r\nconst SALT_LENGTH = 32;\r\n\r\nfunction getServiceName(provider: ProviderName): string {\r\n return `${SERVICE_PREFIX}.${provider}`;\r\n}\r\n\r\nexport class CredentialStore {\r\n private keytarAvailable: boolean | undefined;\r\n\r\n /**\r\n * Store a credential for a provider.\r\n */\r\n async set(provider: ProviderName, credential: ICredential): Promise<void> {\r\n const data = JSON.stringify(credential);\r\n const service = getServiceName(provider);\r\n\r\n if (await this.isKeytarAvailable()) {\r\n try {\r\n const keytar = await this.getKeytar();\r\n await keytar.setPassword(service, provider, data);\r\n logger.info({ provider }, \"Credential stored in OS keychain\");\r\n return;\r\n } catch {\r\n logger.warn({ provider }, \"OS keychain store failed, using encrypted fallback\");\r\n }\r\n }\r\n\r\n // Fallback: encrypted file\r\n this.storeEncrypted(provider, data);\r\n }\r\n\r\n /**\r\n * Get a credential for a provider.\r\n */\r\n async get(provider: ProviderName): Promise<ICredential | undefined> {\r\n const service = getServiceName(provider);\r\n\r\n if (await this.isKeytarAvailable()) {\r\n try {\r\n const keytar = await this.getKeytar();\r\n const data = await keytar.getPassword(service, provider);\r\n if (data) {\r\n return JSON.parse(data) as ICredential;\r\n }\r\n } catch {\r\n // Try fallback\r\n }\r\n }\r\n\r\n // Fallback: encrypted file\r\n return this.loadEncrypted(provider);\r\n }\r\n\r\n /**\r\n * Delete a credential for a provider.\r\n */\r\n async delete(provider: ProviderName): Promise<void> {\r\n const service = getServiceName(provider);\r\n\r\n if (await this.isKeytarAvailable()) {\r\n try {\r\n const keytar = await this.getKeytar();\r\n await keytar.deletePassword(service, provider);\r\n } catch {\r\n // Ignore\r\n }\r\n }\r\n\r\n // Also clean fallback\r\n this.deleteEncrypted(provider);\r\n }\r\n\r\n /**\r\n * Check if a credential exists for a provider.\r\n */\r\n async has(provider: ProviderName): Promise<boolean> {\r\n const credential = await this.get(provider);\r\n return credential !== undefined;\r\n }\r\n\r\n // ── Encrypted File Fallback ────────────────────────────────────────────\r\n\r\n private getEncryptionKey(salt: Buffer): Buffer {\r\n // Derive key from machine-specific data + random salt using scrypt with high cost\r\n const machineId = process.env[\"USER\"] ?? process.env[\"USERNAME\"] ?? \"aemeathcli\";\r\n const homedir = process.env[\"HOME\"] ?? process.env[\"USERPROFILE\"] ?? \"/\";\r\n const password = `aemeathcli-${machineId}-${homedir}`;\r\n return scryptSync(password, salt, KEY_LENGTH, {\r\n N: 32768,\r\n r: 8,\r\n p: 1,\r\n maxmem: 64 * 1024 * 1024,\r\n });\r\n }\r\n\r\n private storeEncrypted(provider: ProviderName, data: string): void {\r\n const credPath = getCredentialsPath();\r\n ensureSecureDirectory(getAemeathHome());\r\n\r\n let store: Record<string, string> = {};\r\n if (existsSync(credPath)) {\r\n try {\r\n const existing = this.decryptFile(credPath);\r\n store = JSON.parse(existing) as Record<string, string>;\r\n } catch {\r\n store = {};\r\n }\r\n }\r\n\r\n store[provider] = data;\r\n this.encryptFile(credPath, JSON.stringify(store));\r\n chmodSync(credPath, 0o600);\r\n logger.info({ provider }, \"Credential stored in encrypted fallback\");\r\n }\r\n\r\n private loadEncrypted(provider: ProviderName): ICredential | undefined {\r\n const credPath = getCredentialsPath();\r\n if (!existsSync(credPath)) {\r\n return undefined;\r\n }\r\n\r\n try {\r\n const content = this.decryptFile(credPath);\r\n const store = JSON.parse(content) as Record<string, string>;\r\n const data = store[provider];\r\n if (data) {\r\n return JSON.parse(data) as ICredential;\r\n }\r\n } catch {\r\n return undefined;\r\n }\r\n\r\n return undefined;\r\n }\r\n\r\n private deleteEncrypted(provider: ProviderName): void {\r\n const credPath = getCredentialsPath();\r\n if (!existsSync(credPath)) {\r\n return;\r\n }\r\n\r\n try {\r\n const content = this.decryptFile(credPath);\r\n const store = JSON.parse(content) as Record<string, string>;\r\n const { [provider]: _deletedCredential, ...remainingStore } = store;\r\n this.encryptFile(credPath, JSON.stringify(remainingStore));\r\n } catch {\r\n // Ignore\r\n }\r\n }\r\n\r\n private encryptFile(filePath: string, plaintext: string): void {\r\n const salt = randomBytes(SALT_LENGTH);\r\n const key = this.getEncryptionKey(salt);\r\n const iv = randomBytes(IV_LENGTH);\r\n const cipher = createCipheriv(ALGORITHM, key, iv);\r\n const encrypted = Buffer.concat([cipher.update(plaintext, \"utf-8\"), cipher.final()]);\r\n const tag = cipher.getAuthTag();\r\n\r\n // Format: salt(32) + iv(16) + tag(16) + encrypted\r\n const output = Buffer.concat([salt, iv, tag, encrypted]);\r\n writeFileSync(filePath, output);\r\n }\r\n\r\n private decryptFile(filePath: string): string {\r\n const fileContent = readFileSync(filePath);\r\n\r\n // Handle legacy format without salt (iv(16) + tag(16) + encrypted)\r\n const hasStoredSalt = fileContent.length > SALT_LENGTH + IV_LENGTH + TAG_LENGTH;\r\n let salt: Buffer;\r\n let dataOffset: number;\r\n\r\n if (hasStoredSalt) {\r\n salt = fileContent.subarray(0, SALT_LENGTH);\r\n dataOffset = SALT_LENGTH;\r\n } else {\r\n // Legacy fallback: derive salt from username (for backward compatibility)\r\n const machineId = process.env[\"USER\"] ?? process.env[\"USERNAME\"] ?? \"aemeathcli\";\r\n salt = Buffer.from(`aemeathcli-${machineId}`.padEnd(SALT_LENGTH, \"\\0\").slice(0, SALT_LENGTH));\r\n dataOffset = 0;\r\n }\r\n\r\n const key = this.getEncryptionKey(salt);\r\n const iv = fileContent.subarray(dataOffset, dataOffset + IV_LENGTH);\r\n const tag = fileContent.subarray(dataOffset + IV_LENGTH, dataOffset + IV_LENGTH + TAG_LENGTH);\r\n const encrypted = fileContent.subarray(dataOffset + IV_LENGTH + TAG_LENGTH);\r\n\r\n const decipher = createDecipheriv(ALGORITHM, key, iv);\r\n decipher.setAuthTag(tag);\r\n const decrypted = Buffer.concat([decipher.update(encrypted), decipher.final()]);\r\n\r\n return decrypted.toString(\"utf-8\");\r\n }\r\n\r\n // ── Keytar Detection ───────────────────────────────────────────────────\r\n\r\n private async isKeytarAvailable(): Promise<boolean> {\r\n if (this.keytarAvailable !== undefined) {\r\n return this.keytarAvailable;\r\n }\r\n\r\n try {\r\n await import(\"keytar\");\r\n this.keytarAvailable = true;\r\n } catch {\r\n this.keytarAvailable = false;\r\n }\r\n\r\n return this.keytarAvailable;\r\n }\r\n\r\n private async getKeytar(): Promise<typeof Keytar> {\r\n return import(\"keytar\");\r\n }\r\n}\r\n"]}