aemeathcli 1.0.10 → 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 (184) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +66 -54
  3. package/dist/App-JQ622M66.js +4431 -0
  4. package/dist/App-JQ622M66.js.map +1 -0
  5. package/dist/agent-store/architect.md +32 -0
  6. package/dist/agent-store/debugger.md +32 -0
  7. package/dist/agent-store/developer.md +29 -0
  8. package/dist/agent-store/documenter.md +30 -0
  9. package/dist/agent-store/researcher.md +31 -0
  10. package/dist/agent-store/reviewer.md +28 -0
  11. package/dist/agent-store/supervisor.md +37 -0
  12. package/dist/agent-store/tester.md +30 -0
  13. package/dist/api-key-fallback-RJLPM3KH.js +11 -0
  14. package/dist/{api-key-fallback-YQQBOQIL.js.map → api-key-fallback-RJLPM3KH.js.map} +1 -1
  15. package/dist/auth-status-JQJOKUPF.js +13 -0
  16. package/dist/auth-status-JQJOKUPF.js.map +1 -0
  17. package/dist/{chunk-RWCNNAL7.js → chunk-2KMA5RBC.js} +25 -48
  18. package/dist/chunk-2KMA5RBC.js.map +1 -0
  19. package/dist/{chunk-CYQNBB25.js → chunk-2Y7TR6BS.js} +28 -5
  20. package/dist/chunk-2Y7TR6BS.js.map +1 -0
  21. package/dist/{chunk-DAHGLHNR.js → chunk-2ZYK5IJG.js} +6 -141
  22. package/dist/chunk-2ZYK5IJG.js.map +1 -0
  23. package/dist/chunk-36RXCZOV.js +88 -0
  24. package/dist/chunk-36RXCZOV.js.map +1 -0
  25. package/dist/{chunk-DMBPX3RG.js → chunk-7EBLXPL4.js} +9 -9
  26. package/dist/{chunk-DMBPX3RG.js.map → chunk-7EBLXPL4.js.map} +1 -1
  27. package/dist/chunk-BIMQL4AG.js +186 -0
  28. package/dist/chunk-BIMQL4AG.js.map +1 -0
  29. package/dist/{chunk-NBR3GHMT.js → chunk-D275MCIH.js} +39 -7
  30. package/dist/chunk-D275MCIH.js.map +1 -0
  31. package/dist/{chunk-Y5XVD2CD.js → chunk-FFS4T7BZ.js} +109 -82
  32. package/dist/chunk-FFS4T7BZ.js.map +1 -0
  33. package/dist/{chunk-CARHU3DO.js → chunk-GXAJGP2T.js} +64 -16
  34. package/dist/chunk-GXAJGP2T.js.map +1 -0
  35. package/dist/{chunk-I5PZ4JTS.js → chunk-HESQLCLU.js} +4 -4
  36. package/dist/{chunk-I5PZ4JTS.js.map → chunk-HESQLCLU.js.map} +1 -1
  37. package/dist/{chunk-JAXXTYID.js → chunk-IR5HLBMH.js} +2 -2
  38. package/dist/{chunk-JAXXTYID.js.map → chunk-IR5HLBMH.js.map} +1 -1
  39. package/dist/{chunk-MFBHNWGV.js → chunk-K2FCMRXH.js} +11 -19
  40. package/dist/chunk-K2FCMRXH.js.map +1 -0
  41. package/dist/{chunk-H66O5Z2V.js → chunk-KIC7UI5U.js} +41 -6
  42. package/dist/chunk-KIC7UI5U.js.map +1 -0
  43. package/dist/{chunk-MXZSI3AY.js → chunk-KMOAJRDE.js} +42 -10
  44. package/dist/chunk-KMOAJRDE.js.map +1 -0
  45. package/dist/chunk-LQBALETG.js +71 -0
  46. package/dist/chunk-LQBALETG.js.map +1 -0
  47. package/dist/chunk-M3FPQSRU.js +12 -0
  48. package/dist/chunk-M3FPQSRU.js.map +1 -0
  49. package/dist/chunk-NQEUK763.js +26 -0
  50. package/dist/chunk-NQEUK763.js.map +1 -0
  51. package/dist/chunk-OPWAFS6Y.js +38 -0
  52. package/dist/chunk-OPWAFS6Y.js.map +1 -0
  53. package/dist/{chunk-6PDJ45T4.js → chunk-PS4WEFW6.js} +50 -25
  54. package/dist/chunk-PS4WEFW6.js.map +1 -0
  55. package/dist/{chunk-HMJRPNPZ.js → chunk-QK7TKNHV.js} +93 -21
  56. package/dist/chunk-QK7TKNHV.js.map +1 -0
  57. package/dist/{chunk-LSOYPSAT.js → chunk-RADJSEG5.js} +4 -4
  58. package/dist/chunk-RADJSEG5.js.map +1 -0
  59. package/dist/{chunk-4IJD72YB.js → chunk-SNWPI6XJ.js} +7 -7
  60. package/dist/chunk-SNWPI6XJ.js.map +1 -0
  61. package/dist/{chunk-TEVZS4FA.js → chunk-UM7MSLOV.js} +16 -9
  62. package/dist/chunk-UM7MSLOV.js.map +1 -0
  63. package/dist/chunk-VNZ3YTQD.js +232 -0
  64. package/dist/chunk-VNZ3YTQD.js.map +1 -0
  65. package/dist/{chunk-IYW62KKR.js → chunk-WXIN65UG.js} +66 -23
  66. package/dist/chunk-WXIN65UG.js.map +1 -0
  67. package/dist/chunk-XEXWX7C7.js +241 -0
  68. package/dist/chunk-XEXWX7C7.js.map +1 -0
  69. package/dist/{chunk-CGEV3ARR.js → chunk-YCCYXDW7.js} +3 -3
  70. package/dist/chunk-YCCYXDW7.js.map +1 -0
  71. package/dist/chunk-YPQ2MLAV.js +140 -0
  72. package/dist/chunk-YPQ2MLAV.js.map +1 -0
  73. package/dist/chunk-ZCOVMVK4.js +26 -0
  74. package/dist/chunk-ZCOVMVK4.js.map +1 -0
  75. package/dist/{claude-login-5WELXPKT.js → claude-login-AIFIWTYF.js} +9 -9
  76. package/dist/{claude-login-5WELXPKT.js.map → claude-login-AIFIWTYF.js.map} +1 -1
  77. package/dist/cli.js +370 -171
  78. package/dist/cli.js.map +1 -1
  79. package/dist/{codex-login-GZIFXUWD.js → codex-login-LW5X7GAM.js} +10 -10
  80. package/dist/codex-login-LW5X7GAM.js.map +1 -0
  81. package/dist/config-store-NF56VHFU.js +7 -0
  82. package/dist/{config-store-W6FBCQAQ.js.map → config-store-NF56VHFU.js.map} +1 -1
  83. package/dist/conversation-store-7GRDQZD2.js +4 -0
  84. package/dist/conversation-store-7GRDQZD2.js.map +1 -0
  85. package/dist/detect-providers-QICJ5U3R.js +4 -0
  86. package/dist/detect-providers-QICJ5U3R.js.map +1 -0
  87. package/dist/executor-FTABX2AW.js +4 -0
  88. package/dist/{executor-6RIKIGXK.js.map → executor-FTABX2AW.js.map} +1 -1
  89. package/dist/first-run-ADROZVYF.js +230 -0
  90. package/dist/first-run-ADROZVYF.js.map +1 -0
  91. package/dist/{gemini-login-AZGL3CE7.js → gemini-login-TST454MX.js} +9 -9
  92. package/dist/{gemini-login-AZGL3CE7.js.map → gemini-login-TST454MX.js.map} +1 -1
  93. package/dist/index.d.ts +46 -70
  94. package/dist/index.js +79 -468
  95. package/dist/index.js.map +1 -1
  96. package/dist/input-history-BEICE7PT.js +57 -0
  97. package/dist/input-history-BEICE7PT.js.map +1 -0
  98. package/dist/kimi-adapter-7FYOAKOI.js +6 -0
  99. package/dist/{kimi-adapter-JN4HFFHU.js.map → kimi-adapter-7FYOAKOI.js.map} +1 -1
  100. package/dist/{kimi-login-6LUWB7P6.js → kimi-login-3IGVOBJI.js} +9 -9
  101. package/dist/{kimi-login-6LUWB7P6.js.map → kimi-login-3IGVOBJI.js.map} +1 -1
  102. package/dist/logger-KGHUQ4VE.js +3 -0
  103. package/dist/logger-KGHUQ4VE.js.map +1 -0
  104. package/dist/model-discovery-AAJDHRFO.js +6 -0
  105. package/dist/model-discovery-AAJDHRFO.js.map +1 -0
  106. package/dist/native-cli-adapters-CLONTZOA.js +8 -0
  107. package/dist/{native-cli-adapters-OLW3XX57.js.map → native-cli-adapters-CLONTZOA.js.map} +1 -1
  108. package/dist/ollama-adapter-2N5OQIEV.js +5 -0
  109. package/dist/{ollama-adapter-OJQ3FKWK.js.map → ollama-adapter-2N5OQIEV.js.map} +1 -1
  110. package/dist/pathResolver-UVAB2FCW.js +3 -0
  111. package/dist/pathResolver-UVAB2FCW.js.map +1 -0
  112. package/dist/profile-loader-EMLV4J7S.js +162 -0
  113. package/dist/profile-loader-EMLV4J7S.js.map +1 -0
  114. package/dist/registry-LRURZVUL.js +5 -0
  115. package/dist/{registry-AZ2LOHHJ.js.map → registry-LRURZVUL.js.map} +1 -1
  116. package/dist/registry-MVNSXCEF.js +6 -0
  117. package/dist/{registry-H7B3AHPQ.js.map → registry-MVNSXCEF.js.map} +1 -1
  118. package/dist/server-manager-THGZBBZB.js +5 -0
  119. package/dist/{server-manager-PTGBHCLS.js.map → server-manager-THGZBBZB.js.map} +1 -1
  120. package/dist/session-manager-X3DXT53M.js +12 -0
  121. package/dist/{session-manager-XOMDMC77.js.map → session-manager-X3DXT53M.js.map} +1 -1
  122. package/dist/skills/built-in/code-review/SKILL.md +85 -0
  123. package/dist/skills/built-in/commit/SKILL.md +83 -0
  124. package/dist/skills/built-in/debug/SKILL.md +119 -0
  125. package/dist/skills/built-in/plan/SKILL.md +123 -0
  126. package/dist/skills/built-in/refactor/SKILL.md +132 -0
  127. package/dist/skills/built-in/test/SKILL.md +128 -0
  128. package/dist/sqlite-store-7OECRTXM.js +5 -0
  129. package/dist/sqlite-store-7OECRTXM.js.map +1 -0
  130. package/dist/team-manager-2VSMALAA.js +11 -0
  131. package/dist/{team-manager-HC4XGCFY.js.map → team-manager-2VSMALAA.js.map} +1 -1
  132. package/dist/team-state-HZNVMQHT.js +3 -0
  133. package/dist/team-state-HZNVMQHT.js.map +1 -0
  134. package/dist/tmux-manager-57QCUVHU.js +6 -0
  135. package/dist/{tmux-manager-GPYZ3WQH.js.map → tmux-manager-57QCUVHU.js.map} +1 -1
  136. package/dist/tools-KWFSYT56.js +6 -0
  137. package/dist/{tools-TSMXMHIF.js.map → tools-KWFSYT56.js.map} +1 -1
  138. package/package.json +11 -11
  139. package/dist/App-FKRSMFMB.js +0 -2789
  140. package/dist/App-FKRSMFMB.js.map +0 -1
  141. package/dist/api-key-fallback-YQQBOQIL.js +0 -11
  142. package/dist/chunk-4IJD72YB.js.map +0 -1
  143. package/dist/chunk-6PDJ45T4.js.map +0 -1
  144. package/dist/chunk-CARHU3DO.js.map +0 -1
  145. package/dist/chunk-CGEV3ARR.js.map +0 -1
  146. package/dist/chunk-CS5X3BWX.js +0 -27
  147. package/dist/chunk-CS5X3BWX.js.map +0 -1
  148. package/dist/chunk-CYQNBB25.js.map +0 -1
  149. package/dist/chunk-DAHGLHNR.js.map +0 -1
  150. package/dist/chunk-H66O5Z2V.js.map +0 -1
  151. package/dist/chunk-HMJRPNPZ.js.map +0 -1
  152. package/dist/chunk-IYW62KKR.js.map +0 -1
  153. package/dist/chunk-LSOYPSAT.js.map +0 -1
  154. package/dist/chunk-MFBHNWGV.js.map +0 -1
  155. package/dist/chunk-MXZSI3AY.js.map +0 -1
  156. package/dist/chunk-NBR3GHMT.js.map +0 -1
  157. package/dist/chunk-RWCNNAL7.js.map +0 -1
  158. package/dist/chunk-TEVZS4FA.js.map +0 -1
  159. package/dist/chunk-UY2SYSEZ.js +0 -211
  160. package/dist/chunk-UY2SYSEZ.js.map +0 -1
  161. package/dist/chunk-WAHVZH7V.js +0 -260
  162. package/dist/chunk-WAHVZH7V.js.map +0 -1
  163. package/dist/chunk-WPP3PEDE.js +0 -234
  164. package/dist/chunk-WPP3PEDE.js.map +0 -1
  165. package/dist/chunk-Y5XVD2CD.js.map +0 -1
  166. package/dist/claude-adapter-QMLFMSP3.js +0 -6
  167. package/dist/claude-adapter-QMLFMSP3.js.map +0 -1
  168. package/dist/codex-login-GZIFXUWD.js.map +0 -1
  169. package/dist/config-store-W6FBCQAQ.js +0 -6
  170. package/dist/executor-6RIKIGXK.js +0 -4
  171. package/dist/gemini-adapter-6JIHZ7WI.js +0 -6
  172. package/dist/gemini-adapter-6JIHZ7WI.js.map +0 -1
  173. package/dist/kimi-adapter-JN4HFFHU.js +0 -6
  174. package/dist/native-cli-adapters-OLW3XX57.js +0 -6
  175. package/dist/ollama-adapter-OJQ3FKWK.js +0 -6
  176. package/dist/openai-adapter-XU46EN7B.js +0 -6
  177. package/dist/openai-adapter-XU46EN7B.js.map +0 -1
  178. package/dist/registry-AZ2LOHHJ.js +0 -6
  179. package/dist/registry-H7B3AHPQ.js +0 -5
  180. package/dist/server-manager-PTGBHCLS.js +0 -5
  181. package/dist/session-manager-XOMDMC77.js +0 -12
  182. package/dist/team-manager-HC4XGCFY.js +0 -11
  183. package/dist/tmux-manager-GPYZ3WQH.js +0 -6
  184. package/dist/tools-TSMXMHIF.js +0 -6
@@ -0,0 +1,232 @@
1
+ import { SUPPORTED_MODELS, PROVIDER_MODEL_ORDER } from './chunk-HCIHOHLX.js';
2
+ import { logger } from './chunk-IR5HLBMH.js';
3
+ import { getAemeathHome } from './chunk-D275MCIH.js';
4
+ import { readFile } from 'fs/promises';
5
+ import { join, dirname } from 'path';
6
+ import { homedir } from 'os';
7
+ import { existsSync } from 'fs';
8
+ import { execa } from 'execa';
9
+
10
+ var discoveryComplete = false;
11
+ var dynamicModels = {};
12
+ var dynamicDisplayOrder = {};
13
+ function makeModelInfo(id, name, provider, description, contextWindow) {
14
+ return {
15
+ id,
16
+ name,
17
+ provider,
18
+ contextWindow: contextWindow ?? 2e5,
19
+ maxOutputTokens: 16384,
20
+ inputPricePerMToken: 0,
21
+ outputPricePerMToken: 0,
22
+ supportsStreaming: true,
23
+ supportsToolCalling: true,
24
+ supportedRoles: ["coding"],
25
+ description
26
+ };
27
+ }
28
+ async function discoverCodexModels() {
29
+ const configPath = join(homedir(), ".codex", "config.toml");
30
+ let currentModel;
31
+ try {
32
+ const raw = await readFile(configPath, "utf-8");
33
+ const match = raw.match(/^model\s*=\s*"([^"]+)"/m);
34
+ if (match?.[1]) {
35
+ currentModel = match[1];
36
+ }
37
+ } catch {
38
+ }
39
+ try {
40
+ const { stdout } = await execa("codex", ["exec", "--help"], {
41
+ timeout: 5e3,
42
+ stdin: "ignore",
43
+ env: { ...process.env, NO_COLOR: "1" }
44
+ });
45
+ const modelRefs = stdout.matchAll(/model="([^"]+)"/g);
46
+ for (const m of modelRefs) {
47
+ const id = m[1];
48
+ if (id && !SUPPORTED_MODELS[id] && !dynamicModels[id]) {
49
+ addModel(id, id, "openai");
50
+ }
51
+ }
52
+ } catch {
53
+ }
54
+ if (currentModel && !SUPPORTED_MODELS[currentModel] && !dynamicModels[currentModel]) {
55
+ addModel(currentModel, currentModel, "openai", `User's current Codex model`);
56
+ }
57
+ const knownCodexModels = [
58
+ { id: "gpt-5.4", name: "GPT-5.4", desc: "Latest frontier agentic coding model" },
59
+ { id: "gpt-5.4-mini", name: "GPT-5.4 Mini", desc: "Smaller frontier agentic coding model" },
60
+ { id: "o3", name: "o3", desc: "OpenAI o3 reasoning model" },
61
+ { id: "o4-mini", name: "o4-mini", desc: "OpenAI o4-mini reasoning model" }
62
+ ];
63
+ for (const m of knownCodexModels) {
64
+ if (!SUPPORTED_MODELS[m.id] && !dynamicModels[m.id]) {
65
+ addModel(m.id, m.name, "openai", m.desc);
66
+ }
67
+ }
68
+ }
69
+ async function discoverGeminiModels() {
70
+ const geminiModelsPath = await findGeminiModelsFile();
71
+ if (geminiModelsPath) {
72
+ try {
73
+ const source = await readFile(geminiModelsPath, "utf-8");
74
+ const modelMatches = source.matchAll(/['"]([^'"]*gemini[^'"]+)['"]/g);
75
+ for (const m of modelMatches) {
76
+ const id = m[1];
77
+ if (id && !id.includes("embedding") && !id.includes("auto-") && !id.includes("customtools") && !SUPPORTED_MODELS[id] && !dynamicModels[id]) {
78
+ const name = id.replace(/-preview$/, " Preview").replace(/-lite$/, " Lite").split("-").map((s) => s.charAt(0).toUpperCase() + s.slice(1)).join(" ");
79
+ addModel(id, name, "google", void 0, 2e6);
80
+ }
81
+ }
82
+ } catch {
83
+ logger.debug("Failed to read Gemini CLI models source");
84
+ }
85
+ }
86
+ const knownGeminiModels = [
87
+ { id: "gemini-3.1-pro-preview", name: "Gemini 3.1 Pro Preview", desc: "Latest Gemini Pro preview" },
88
+ { id: "gemini-3.1-flash-lite-preview", name: "Gemini 3.1 Flash Lite Preview", desc: "Latest Flash Lite preview" },
89
+ { id: "gemini-3-flash-preview", name: "Gemini 3 Flash Preview", desc: "Gemini 3 Flash preview" }
90
+ ];
91
+ for (const m of knownGeminiModels) {
92
+ if (!SUPPORTED_MODELS[m.id] && !dynamicModels[m.id]) {
93
+ addModel(m.id, m.name, "google", m.desc, 2e6);
94
+ }
95
+ }
96
+ }
97
+ async function findGeminiModelsFile() {
98
+ try {
99
+ const { stdout } = await execa("which", ["gemini"], {
100
+ stdin: "ignore",
101
+ timeout: 5e3,
102
+ env: { ...process.env, NO_COLOR: "1" }
103
+ });
104
+ const whichResult = stdout.trim();
105
+ if (whichResult) {
106
+ const binDir = dirname(whichResult);
107
+ const modelsPath = join(
108
+ binDir,
109
+ "..",
110
+ "lib",
111
+ "node_modules",
112
+ "@google",
113
+ "gemini-cli",
114
+ "node_modules",
115
+ "@google",
116
+ "gemini-cli-core",
117
+ "dist",
118
+ "src",
119
+ "config",
120
+ "models.js"
121
+ );
122
+ if (existsSync(modelsPath)) {
123
+ return modelsPath;
124
+ }
125
+ }
126
+ } catch {
127
+ }
128
+ return void 0;
129
+ }
130
+ async function discoverClaudeModels() {
131
+ try {
132
+ await execa("claude", ["--version"], {
133
+ timeout: 5e3,
134
+ stdin: "ignore",
135
+ env: { ...process.env, NO_COLOR: "1" }
136
+ });
137
+ } catch {
138
+ logger.debug("Claude CLI not available");
139
+ }
140
+ }
141
+ async function loadUserModels() {
142
+ const modelsPath = join(getAemeathHome(), "models.json");
143
+ try {
144
+ const raw = await readFile(modelsPath, "utf-8");
145
+ const parsed = JSON.parse(raw);
146
+ if (!Array.isArray(parsed)) return;
147
+ for (const entry of parsed) {
148
+ if (typeof entry === "object" && entry !== null && typeof entry.id === "string" && typeof entry.name === "string" && typeof entry.provider === "string") {
149
+ const e = entry;
150
+ addModel(
151
+ e.id,
152
+ e.name,
153
+ e.provider,
154
+ e.description,
155
+ e.contextWindow
156
+ );
157
+ }
158
+ }
159
+ } catch {
160
+ }
161
+ }
162
+ function addModel(id, name, provider, description, contextWindow) {
163
+ dynamicModels[id] = makeModelInfo(id, name, provider, description, contextWindow);
164
+ if (!dynamicDisplayOrder[provider]) {
165
+ dynamicDisplayOrder[provider] = [];
166
+ }
167
+ if (!dynamicDisplayOrder[provider].some((e) => e.id === id)) {
168
+ dynamicDisplayOrder[provider].push({
169
+ id,
170
+ label: name,
171
+ description: description ?? ""
172
+ });
173
+ }
174
+ }
175
+ async function discoverModels() {
176
+ if (discoveryComplete) return;
177
+ await Promise.allSettled([
178
+ loadUserModels(),
179
+ discoverClaudeModels(),
180
+ discoverCodexModels(),
181
+ discoverGeminiModels()
182
+ ]);
183
+ discoveryComplete = true;
184
+ const count = Object.keys(dynamicModels).length;
185
+ if (count > 0) {
186
+ logger.info({ count }, "Discovered additional models at runtime");
187
+ }
188
+ }
189
+ function registerModel(model) {
190
+ dynamicModels[model.id] = model;
191
+ const provider = model.provider;
192
+ if (!dynamicDisplayOrder[provider]) {
193
+ dynamicDisplayOrder[provider] = [];
194
+ }
195
+ if (!dynamicDisplayOrder[provider].some((e) => e.id === model.id)) {
196
+ dynamicDisplayOrder[provider].push({
197
+ id: model.id,
198
+ label: model.name,
199
+ description: model.description ?? ""
200
+ });
201
+ }
202
+ }
203
+ function getModelInfo(modelId) {
204
+ return dynamicModels[modelId] ?? SUPPORTED_MODELS[modelId];
205
+ }
206
+ function getAllModels() {
207
+ return { ...SUPPORTED_MODELS, ...dynamicModels };
208
+ }
209
+ function getDisplayOrder() {
210
+ const result = {};
211
+ for (const [provider, entries] of Object.entries(PROVIDER_MODEL_ORDER)) {
212
+ result[provider] = [...entries];
213
+ }
214
+ for (const [provider, entries] of Object.entries(dynamicDisplayOrder)) {
215
+ if (!result[provider]) {
216
+ result[provider] = [];
217
+ }
218
+ for (const entry of entries) {
219
+ if (!result[provider].some((e) => e.id === entry.id)) {
220
+ result[provider].unshift(entry);
221
+ }
222
+ }
223
+ }
224
+ return result;
225
+ }
226
+ function isKnownModel(modelId) {
227
+ return modelId in SUPPORTED_MODELS || modelId in dynamicModels;
228
+ }
229
+
230
+ export { discoverModels, getAllModels, getDisplayOrder, getModelInfo, isKnownModel, registerModel };
231
+ //# sourceMappingURL=chunk-VNZ3YTQD.js.map
232
+ //# sourceMappingURL=chunk-VNZ3YTQD.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/providers/model-discovery.ts"],"names":[],"mappings":"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","file":"chunk-VNZ3YTQD.js","sourcesContent":["/**\n * Runtime model discovery — reads real model lists from provider CLIs\n * and user config. Merges with the hardcoded fallback registry.\n */\n\nimport { readFile } from \"node:fs/promises\";\nimport { dirname, join } from \"node:path\";\nimport { homedir } from \"node:os\";\nimport { existsSync } from \"node:fs\";\nimport { execa } from \"execa\";\nimport { logger } from \"../utils/logger.js\";\nimport { getAemeathHome } from \"../utils/pathResolver.js\";\nimport {\n SUPPORTED_MODELS,\n PROVIDER_MODEL_ORDER,\n type IModelInfo,\n type IModelDisplayEntry,\n type ProviderName,\n} from \"../types/model.js\";\n\n// ── Cache ────────────────────────────────────────────────────────────────\n\nlet discoveryComplete = false;\nconst dynamicModels: Record<string, IModelInfo> = {};\nconst dynamicDisplayOrder: Record<string, IModelDisplayEntry[]> = {};\n\n// ── Helper to create a model entry with defaults ────────────────────────\n\nfunction makeModelInfo(\n id: string,\n name: string,\n provider: ProviderName,\n description?: string,\n contextWindow?: number,\n): IModelInfo {\n return {\n id,\n name,\n provider,\n contextWindow: contextWindow ?? 200_000,\n maxOutputTokens: 16_384,\n inputPricePerMToken: 0,\n outputPricePerMToken: 0,\n supportsStreaming: true,\n supportsToolCalling: true,\n supportedRoles: [\"coding\"],\n description,\n };\n}\n\n// ── Codex (OpenAI) discovery ────────────────────────────────────────────\n\nasync function discoverCodexModels(): Promise<void> {\n // 1. Read user's current model from ~/.codex/config.toml\n const configPath = join(homedir(), \".codex\", \"config.toml\");\n let currentModel: string | undefined;\n try {\n const raw = await readFile(configPath, \"utf-8\");\n const match = raw.match(/^model\\s*=\\s*\"([^\"]+)\"/m);\n if (match?.[1]) {\n currentModel = match[1];\n }\n } catch {\n // No config file\n }\n\n // 2. Try to get the interactive model list via `codex model` (needs TTY, may fail)\n // Fallback: run `codex exec --help` and extract model references\n try {\n const { stdout } = await execa(\"codex\", [\"exec\", \"--help\"], {\n timeout: 5000,\n stdin: \"ignore\",\n env: { ...process.env, NO_COLOR: \"1\" },\n });\n // Extract model IDs from help text (e.g. model=\"o3\")\n const modelRefs = stdout.matchAll(/model=\"([^\"]+)\"/g);\n for (const m of modelRefs) {\n const id = m[1];\n if (id && !SUPPORTED_MODELS[id] && !dynamicModels[id]) {\n addModel(id, id, \"openai\");\n }\n }\n } catch {\n // Codex not installed\n }\n\n // 3. If the user's current model isn't in our list, add it\n if (currentModel && !SUPPORTED_MODELS[currentModel] && !dynamicModels[currentModel]) {\n addModel(currentModel, currentModel, \"openai\", `User's current Codex model`);\n }\n\n // 4. Probe for known recent Codex models that may not be in our hardcoded list\n const knownCodexModels = [\n { id: \"gpt-5.4\", name: \"GPT-5.4\", desc: \"Latest frontier agentic coding model\" },\n { id: \"gpt-5.4-mini\", name: \"GPT-5.4 Mini\", desc: \"Smaller frontier agentic coding model\" },\n { id: \"o3\", name: \"o3\", desc: \"OpenAI o3 reasoning model\" },\n { id: \"o4-mini\", name: \"o4-mini\", desc: \"OpenAI o4-mini reasoning model\" },\n ];\n for (const m of knownCodexModels) {\n if (!SUPPORTED_MODELS[m.id] && !dynamicModels[m.id]) {\n addModel(m.id, m.name, \"openai\", m.desc);\n }\n }\n}\n\n// ── Gemini (Google) discovery ───────────────────────────────────────────\n\nasync function discoverGeminiModels(): Promise<void> {\n // 1. Read the Gemini CLI's models.js source for VALID_GEMINI_MODELS\n const geminiModelsPath = await findGeminiModelsFile();\n if (geminiModelsPath) {\n try {\n const source = await readFile(geminiModelsPath, \"utf-8\");\n\n // Extract model IDs from export const statements and Set entries\n const modelMatches = source.matchAll(/['\"]([^'\"]*gemini[^'\"]+)['\"]/g);\n for (const m of modelMatches) {\n const id = m[1];\n if (\n id &&\n !id.includes(\"embedding\") &&\n !id.includes(\"auto-\") &&\n !id.includes(\"customtools\") &&\n !SUPPORTED_MODELS[id] &&\n !dynamicModels[id]\n ) {\n const name = id\n .replace(/-preview$/, \" Preview\")\n .replace(/-lite$/, \" Lite\")\n .split(\"-\")\n .map((s) => s.charAt(0).toUpperCase() + s.slice(1))\n .join(\" \");\n addModel(id, name, \"google\", undefined, 2_000_000);\n }\n }\n } catch {\n logger.debug(\"Failed to read Gemini CLI models source\");\n }\n }\n\n // 2. Fallback: probe known recent Gemini models\n const knownGeminiModels = [\n { id: \"gemini-3.1-pro-preview\", name: \"Gemini 3.1 Pro Preview\", desc: \"Latest Gemini Pro preview\" },\n { id: \"gemini-3.1-flash-lite-preview\", name: \"Gemini 3.1 Flash Lite Preview\", desc: \"Latest Flash Lite preview\" },\n { id: \"gemini-3-flash-preview\", name: \"Gemini 3 Flash Preview\", desc: \"Gemini 3 Flash preview\" },\n ];\n for (const m of knownGeminiModels) {\n if (!SUPPORTED_MODELS[m.id] && !dynamicModels[m.id]) {\n addModel(m.id, m.name, \"google\", m.desc, 2_000_000);\n }\n }\n}\n\n/** Find the Gemini CLI's models.js file in node_modules. */\nasync function findGeminiModelsFile(): Promise<string | undefined> {\n // Try to find via which gemini → resolve symlink → find models.js\n try {\n const { stdout } = await execa(\"which\", [\"gemini\"], {\n stdin: \"ignore\",\n timeout: 5_000,\n env: { ...process.env, NO_COLOR: \"1\" },\n });\n const whichResult = stdout.trim();\n if (whichResult) {\n // gemini binary is at e.g. /Users/x/.nvm/versions/node/v22.18.0/bin/gemini\n // models.js is at .../lib/node_modules/@google/gemini-cli/node_modules/@google/gemini-cli-core/dist/src/config/models.js\n const binDir = dirname(whichResult);\n const modelsPath = join(\n binDir,\n \"..\",\n \"lib\",\n \"node_modules\",\n \"@google\",\n \"gemini-cli\",\n \"node_modules\",\n \"@google\",\n \"gemini-cli-core\",\n \"dist\",\n \"src\",\n \"config\",\n \"models.js\",\n );\n if (existsSync(modelsPath)) {\n return modelsPath;\n }\n }\n } catch {\n // which not available or gemini not installed\n }\n\n return undefined;\n}\n\n// ── Claude (Anthropic) discovery ────────────────────────────────────────\n\nasync function discoverClaudeModels(): Promise<void> {\n // Claude models are well-known and change infrequently.\n // The hardcoded list is accurate. Just verify claude CLI exists.\n try {\n await execa(\"claude\", [\"--version\"], {\n timeout: 5000,\n stdin: \"ignore\",\n env: { ...process.env, NO_COLOR: \"1\" },\n });\n } catch {\n logger.debug(\"Claude CLI not available\");\n }\n}\n\n// ── User-defined models from ~/.aemeathcli/models.json ─────────────────\n\ninterface IUserModelEntry {\n readonly id: string;\n readonly name: string;\n readonly provider: string;\n readonly description?: string;\n readonly contextWindow?: number;\n}\n\nasync function loadUserModels(): Promise<void> {\n const modelsPath = join(getAemeathHome(), \"models.json\");\n try {\n const raw = await readFile(modelsPath, \"utf-8\");\n const parsed = JSON.parse(raw) as unknown;\n if (!Array.isArray(parsed)) return;\n\n for (const entry of parsed) {\n if (\n typeof entry === \"object\" &&\n entry !== null &&\n typeof (entry as IUserModelEntry).id === \"string\" &&\n typeof (entry as IUserModelEntry).name === \"string\" &&\n typeof (entry as IUserModelEntry).provider === \"string\"\n ) {\n const e = entry as IUserModelEntry;\n addModel(\n e.id,\n e.name,\n e.provider as ProviderName,\n e.description,\n e.contextWindow,\n );\n }\n }\n } catch {\n // File doesn't exist or invalid\n }\n}\n\n// ── Internal helpers ────────────────────────────────────────────────────\n\nfunction addModel(\n id: string,\n name: string,\n provider: ProviderName,\n description?: string,\n contextWindow?: number,\n): void {\n dynamicModels[id] = makeModelInfo(id, name, provider, description, contextWindow);\n\n if (!dynamicDisplayOrder[provider]) {\n dynamicDisplayOrder[provider] = [];\n }\n if (!dynamicDisplayOrder[provider].some((e) => e.id === id)) {\n dynamicDisplayOrder[provider].push({\n id,\n label: name,\n description: description ?? \"\",\n });\n }\n}\n\n// ── Public API ──────────────────────────────────────────────────────────\n\nexport async function discoverModels(): Promise<void> {\n if (discoveryComplete) return;\n\n await Promise.allSettled([\n loadUserModels(),\n discoverClaudeModels(),\n discoverCodexModels(),\n discoverGeminiModels(),\n ]);\n\n discoveryComplete = true;\n const count = Object.keys(dynamicModels).length;\n if (count > 0) {\n logger.info({ count }, \"Discovered additional models at runtime\");\n }\n}\n\nexport function registerModel(model: IModelInfo): void {\n dynamicModels[model.id] = model;\n const provider = model.provider;\n if (!dynamicDisplayOrder[provider]) {\n dynamicDisplayOrder[provider] = [];\n }\n if (!dynamicDisplayOrder[provider].some((e) => e.id === model.id)) {\n dynamicDisplayOrder[provider].push({\n id: model.id,\n label: model.name,\n description: model.description ?? \"\",\n });\n }\n}\n\nexport function getModelInfo(modelId: string): IModelInfo | undefined {\n return dynamicModels[modelId] ?? SUPPORTED_MODELS[modelId];\n}\n\nexport function getAllModels(): Record<string, IModelInfo> {\n return { ...SUPPORTED_MODELS, ...dynamicModels };\n}\n\nexport function getDisplayOrder(): Record<string, readonly IModelDisplayEntry[]> {\n const result: Record<string, IModelDisplayEntry[]> = {};\n\n for (const [provider, entries] of Object.entries(PROVIDER_MODEL_ORDER)) {\n result[provider] = [...entries];\n }\n\n // Prepend dynamic models to their provider group (new models show at top)\n for (const [provider, entries] of Object.entries(dynamicDisplayOrder)) {\n if (!result[provider]) {\n result[provider] = [];\n }\n for (const entry of entries) {\n if (!result[provider].some((e) => e.id === entry.id)) {\n result[provider].unshift(entry);\n }\n }\n }\n\n return result;\n}\n\nexport function isKnownModel(modelId: string): boolean {\n return modelId in SUPPORTED_MODELS || modelId in dynamicModels;\n}\n"]}
@@ -1,6 +1,7 @@
1
- import { DEFAULT_CONFIG } from './chunk-CYQNBB25.js';
2
- import { getConfigPath, getProjectConfigPath, ensureDirectory } from './chunk-NBR3GHMT.js';
3
- import { logger } from './chunk-JAXXTYID.js';
1
+ import { CLI_PROVIDERS } from './chunk-M3FPQSRU.js';
2
+ import { DEFAULT_CONFIG } from './chunk-2Y7TR6BS.js';
3
+ import { logger } from './chunk-IR5HLBMH.js';
4
+ import { getConfigPath, getProjectConfigPath, ensureDirectory } from './chunk-D275MCIH.js';
4
5
  import { existsSync, readFileSync, writeFileSync, unwatchFile, watchFile } from 'fs';
5
6
  import { dirname } from 'path';
6
7
  import { z } from 'zod';
@@ -8,44 +9,51 @@ import { z } from 'zod';
8
9
  var ProviderConfigSchema = z.object({
9
10
  enabled: z.boolean(),
10
11
  baseUrl: z.string().optional()
11
- });
12
+ }).strict();
12
13
  var PermissionConfigSchema = z.object({
13
14
  mode: z.enum(["strict", "standard", "permissive"]),
14
15
  allowedPaths: z.array(z.string()),
15
16
  blockedCommands: z.array(z.string())
16
- });
17
+ }).strict();
17
18
  var SplitPanelConfigSchema = z.object({
18
19
  enabled: z.boolean(),
19
20
  backend: z.enum(["tmux", "iterm2"]),
20
- defaultLayout: z.enum(["auto", "horizontal", "vertical", "grid"]),
21
+ defaultLayout: z.enum(["auto", "horizontal", "vertical", "grid", "hub-spoke"]),
21
22
  maxPanes: z.number().int().min(1).max(16)
22
- });
23
+ }).strict();
24
+ var CLI_PROVIDER_ENUM_VALUES = [...CLI_PROVIDERS];
25
+ var SwarmConfigSchema = z.object({
26
+ onboardingComplete: z.boolean(),
27
+ detectedProviders: z.array(z.enum(CLI_PROVIDER_ENUM_VALUES)),
28
+ primaryMasterProvider: z.enum(CLI_PROVIDER_ENUM_VALUES).optional(),
29
+ fallbackMasterProviders: z.array(z.enum(CLI_PROVIDER_ENUM_VALUES))
30
+ }).strict();
23
31
  var CostConfigSchema = z.object({
24
32
  budgetWarning: z.number().nonnegative(),
25
33
  budgetHardStop: z.number().nonnegative(),
26
34
  currency: z.string()
27
- });
35
+ }).strict();
28
36
  var TelemetryConfigSchema = z.object({
29
37
  enabled: z.boolean(),
30
38
  anonymized: z.boolean()
31
- });
39
+ }).strict();
32
40
  var RoleConfigSchema = z.object({
33
41
  primary: z.string(),
34
42
  fallback: z.array(z.string())
35
- });
43
+ }).strict();
36
44
  var OAuthProviderConfigSchema = z.object({
37
45
  clientId: z.string(),
38
46
  clientSecret: z.string().optional(),
39
47
  authorizeUrl: z.string().optional(),
40
48
  tokenUrl: z.string().optional(),
41
49
  scope: z.string().optional()
42
- });
50
+ }).strict();
43
51
  var OAuthConfigSchema = z.object({
44
52
  anthropic: OAuthProviderConfigSchema.optional(),
45
53
  openai: OAuthProviderConfigSchema.optional(),
46
54
  google: OAuthProviderConfigSchema.optional(),
47
55
  kimi: OAuthProviderConfigSchema.optional()
48
- });
56
+ }).strict();
49
57
  var GlobalConfigSchema = z.object({
50
58
  version: z.string(),
51
59
  defaultModel: z.string(),
@@ -53,10 +61,14 @@ var GlobalConfigSchema = z.object({
53
61
  providers: z.record(z.string(), ProviderConfigSchema).optional(),
54
62
  permissions: PermissionConfigSchema.optional(),
55
63
  splitPanel: SplitPanelConfigSchema.optional(),
64
+ swarm: SwarmConfigSchema.optional(),
56
65
  cost: CostConfigSchema.optional(),
57
66
  telemetry: TelemetryConfigSchema.optional(),
58
67
  oauth: OAuthConfigSchema.optional()
59
- });
68
+ }).strict();
69
+ function formatValidationError(error) {
70
+ return error.issues.map((issue) => `${issue.path.join(".") || "<root>"}: ${issue.message}`).join("; ");
71
+ }
60
72
  var ConfigStore = class {
61
73
  globalConfig = DEFAULT_CONFIG;
62
74
  projectConfig;
@@ -77,8 +89,17 @@ var ConfigStore = class {
77
89
  this.rebuildMergedConfig();
78
90
  return this.mergedConfig;
79
91
  }
80
- const raw = readFileSync(resolvedPath, "utf-8");
81
- const parsed = JSON.parse(raw);
92
+ let parsed;
93
+ try {
94
+ const raw = readFileSync(resolvedPath, "utf-8");
95
+ parsed = JSON.parse(raw);
96
+ } catch (error) {
97
+ const message = error instanceof Error ? error.message : String(error);
98
+ logger.warn({ error: message, path: resolvedPath }, "Global config parse failed, using defaults");
99
+ this.globalConfig = DEFAULT_CONFIG;
100
+ this.rebuildMergedConfig();
101
+ return this.mergedConfig;
102
+ }
82
103
  const validated = GlobalConfigSchema.safeParse(parsed);
83
104
  if (!validated.success) {
84
105
  logger.warn(
@@ -105,8 +126,17 @@ var ConfigStore = class {
105
126
  this.rebuildMergedConfig();
106
127
  return this.mergedConfig;
107
128
  }
108
- const raw = readFileSync(resolvedPath, "utf-8");
109
- const parsed = JSON.parse(raw);
129
+ let parsed;
130
+ try {
131
+ const raw = readFileSync(resolvedPath, "utf-8");
132
+ parsed = JSON.parse(raw);
133
+ } catch (error) {
134
+ const message = error instanceof Error ? error.message : String(error);
135
+ logger.warn({ error: message, path: resolvedPath }, "Project config parse failed, ignoring");
136
+ this.projectConfig = void 0;
137
+ this.rebuildMergedConfig();
138
+ return this.mergedConfig;
139
+ }
110
140
  const validated = GlobalConfigSchema.partial().safeParse(parsed);
111
141
  if (!validated.success) {
112
142
  logger.warn(
@@ -125,21 +155,29 @@ var ConfigStore = class {
125
155
  saveGlobal(config, configPath) {
126
156
  const resolvedPath = configPath ?? getConfigPath();
127
157
  const configToSave = config ?? this.globalConfig;
158
+ const validated = GlobalConfigSchema.safeParse(configToSave);
159
+ if (!validated.success) {
160
+ throw new Error(`Invalid global config: ${formatValidationError(validated.error)}`);
161
+ }
128
162
  ensureDirectory(dirname(resolvedPath));
129
- const json = JSON.stringify(configToSave, null, 2);
163
+ const json = JSON.stringify(validated.data, null, 2);
130
164
  writeFileSync(resolvedPath, json, { encoding: "utf-8", mode: 384 });
131
165
  logger.info({ path: resolvedPath }, "Global config saved");
132
166
  if (config) {
133
- this.globalConfig = config;
167
+ this.globalConfig = this.applyDefaults(validated.data);
134
168
  this.rebuildMergedConfig();
135
169
  }
136
170
  }
137
171
  saveProject(projectRoot, config) {
138
172
  const resolvedPath = getProjectConfigPath(projectRoot);
173
+ const validated = GlobalConfigSchema.partial().safeParse(config);
174
+ if (!validated.success) {
175
+ throw new Error(`Invalid project config: ${formatValidationError(validated.error)}`);
176
+ }
139
177
  ensureDirectory(dirname(resolvedPath));
140
- const json = JSON.stringify(config, null, 2);
178
+ const json = JSON.stringify(validated.data, null, 2);
141
179
  writeFileSync(resolvedPath, json, { encoding: "utf-8", mode: 384 });
142
- this.projectConfig = config;
180
+ this.projectConfig = validated.data;
143
181
  this.rebuildMergedConfig();
144
182
  logger.info({ path: resolvedPath }, "Project config saved");
145
183
  }
@@ -209,6 +247,10 @@ var ConfigStore = class {
209
247
  ...this.globalConfig.splitPanel,
210
248
  ...this.projectConfig.splitPanel ?? {}
211
249
  },
250
+ swarm: {
251
+ ...this.globalConfig.swarm,
252
+ ...this.projectConfig.swarm ?? {}
253
+ },
212
254
  cost: {
213
255
  ...this.globalConfig.cost,
214
256
  ...this.projectConfig.cost ?? {}
@@ -243,6 +285,7 @@ var ConfigStore = class {
243
285
  },
244
286
  permissions: partial.permissions ? partial.permissions : DEFAULT_CONFIG.permissions,
245
287
  splitPanel: partial.splitPanel ? partial.splitPanel : DEFAULT_CONFIG.splitPanel,
288
+ swarm: partial.swarm ? partial.swarm : DEFAULT_CONFIG.swarm,
246
289
  cost: partial.cost ? partial.cost : DEFAULT_CONFIG.cost,
247
290
  telemetry: partial.telemetry ? partial.telemetry : DEFAULT_CONFIG.telemetry,
248
291
  oauth: partial.oauth ? partial.oauth : void 0
@@ -251,5 +294,5 @@ var ConfigStore = class {
251
294
  };
252
295
 
253
296
  export { ConfigStore };
254
- //# sourceMappingURL=chunk-IYW62KKR.js.map
255
- //# sourceMappingURL=chunk-IYW62KKR.js.map
297
+ //# sourceMappingURL=chunk-WXIN65UG.js.map
298
+ //# sourceMappingURL=chunk-WXIN65UG.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/storage/config-store.ts"],"names":[],"mappings":"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","file":"chunk-WXIN65UG.js","sourcesContent":["/**\n * Configuration store — PRD sections 17.2, 17.3\n * Loads/saves global and project config with Zod validation.\n * Merges project config over global config.\n * Watches for config file changes.\n */\n\nimport { readFileSync, writeFileSync, watchFile, unwatchFile } from \"node:fs\";\nimport { existsSync } from \"node:fs\";\nimport { dirname } from \"node:path\";\nimport { z } from \"zod\";\nimport { logger } from \"../utils/logger.js\";\nimport {\n getConfigPath,\n getProjectConfigPath,\n ensureDirectory,\n} from \"../utils/pathResolver.js\";\nimport { DEFAULT_CONFIG } from \"../types/config.js\";\nimport type { IGlobalConfig } from \"../types/config.js\";\nimport { CLI_PROVIDERS, type CliProviderType } from \"../orchestrator/constants.js\";\n\n// ── Zod Schemas ─────────────────────────────────────────────────────────\n\nconst ProviderConfigSchema = z.object({\n enabled: z.boolean(),\n baseUrl: z.string().optional(),\n}).strict();\n\nconst PermissionConfigSchema = z.object({\n mode: z.enum([\"strict\", \"standard\", \"permissive\"]),\n allowedPaths: z.array(z.string()),\n blockedCommands: z.array(z.string()),\n}).strict();\n\nconst SplitPanelConfigSchema = z.object({\n enabled: z.boolean(),\n backend: z.enum([\"tmux\", \"iterm2\"]),\n defaultLayout: z.enum([\"auto\", \"horizontal\", \"vertical\", \"grid\", \"hub-spoke\"]),\n maxPanes: z.number().int().min(1).max(16),\n}).strict();\n\nconst CLI_PROVIDER_ENUM_VALUES = [...CLI_PROVIDERS] as [\n CliProviderType,\n ...CliProviderType[],\n];\n\nconst SwarmConfigSchema = z.object({\n onboardingComplete: z.boolean(),\n detectedProviders: z.array(z.enum(CLI_PROVIDER_ENUM_VALUES)),\n primaryMasterProvider: z.enum(CLI_PROVIDER_ENUM_VALUES).optional(),\n fallbackMasterProviders: z.array(z.enum(CLI_PROVIDER_ENUM_VALUES)),\n}).strict();\n\nconst CostConfigSchema = z.object({\n budgetWarning: z.number().nonnegative(),\n budgetHardStop: z.number().nonnegative(),\n currency: z.string(),\n}).strict();\n\nconst TelemetryConfigSchema = z.object({\n enabled: z.boolean(),\n anonymized: z.boolean(),\n}).strict();\n\nconst RoleConfigSchema = z.object({\n primary: z.string(),\n fallback: z.array(z.string()),\n}).strict();\n\nconst OAuthProviderConfigSchema = z.object({\n clientId: z.string(),\n clientSecret: z.string().optional(),\n authorizeUrl: z.string().optional(),\n tokenUrl: z.string().optional(),\n scope: z.string().optional(),\n}).strict();\n\nconst OAuthConfigSchema = z.object({\n anthropic: OAuthProviderConfigSchema.optional(),\n openai: OAuthProviderConfigSchema.optional(),\n google: OAuthProviderConfigSchema.optional(),\n kimi: OAuthProviderConfigSchema.optional(),\n}).strict();\n\nconst GlobalConfigSchema = z.object({\n version: z.string(),\n defaultModel: z.string(),\n roles: z.record(z.string(), RoleConfigSchema).optional(),\n providers: z.record(z.string(), ProviderConfigSchema).optional(),\n permissions: PermissionConfigSchema.optional(),\n splitPanel: SplitPanelConfigSchema.optional(),\n swarm: SwarmConfigSchema.optional(),\n cost: CostConfigSchema.optional(),\n telemetry: TelemetryConfigSchema.optional(),\n oauth: OAuthConfigSchema.optional(),\n}).strict();\n\nfunction formatValidationError(error: z.ZodError): string {\n return error.issues\n .map((issue) => `${issue.path.join(\".\") || \"<root>\"}: ${issue.message}`)\n .join(\"; \");\n}\n\ntype ConfigChangeCallback = (config: IGlobalConfig) => void;\n\nexport class ConfigStore {\n private globalConfig: IGlobalConfig = DEFAULT_CONFIG;\n private projectConfig: Partial<IGlobalConfig> | undefined;\n private mergedConfig: IGlobalConfig = DEFAULT_CONFIG;\n private watchers: Array<{ path: string; active: boolean }> = [];\n private changeCallbacks: ConfigChangeCallback[] = [];\n\n get config(): IGlobalConfig {\n return this.mergedConfig;\n }\n\n loadGlobal(configPath?: string): IGlobalConfig {\n const resolvedPath = configPath ?? getConfigPath();\n\n if (!existsSync(resolvedPath)) {\n logger.info(\n { path: resolvedPath },\n \"Global config not found, using defaults\",\n );\n this.globalConfig = DEFAULT_CONFIG;\n this.rebuildMergedConfig();\n return this.mergedConfig;\n }\n\n let parsed: unknown;\n try {\n const raw = readFileSync(resolvedPath, \"utf-8\");\n parsed = JSON.parse(raw);\n } catch (error: unknown) {\n const message = error instanceof Error ? error.message : String(error);\n logger.warn({ error: message, path: resolvedPath }, \"Global config parse failed, using defaults\");\n this.globalConfig = DEFAULT_CONFIG;\n this.rebuildMergedConfig();\n return this.mergedConfig;\n }\n const validated = GlobalConfigSchema.safeParse(parsed);\n\n if (!validated.success) {\n logger.warn(\n { errors: validated.error.issues },\n \"Global config validation failed, using defaults\",\n );\n this.globalConfig = DEFAULT_CONFIG;\n this.rebuildMergedConfig();\n return this.mergedConfig;\n }\n\n this.globalConfig = this.applyDefaults(validated.data);\n this.rebuildMergedConfig();\n\n logger.info({ path: resolvedPath }, \"Global config loaded\");\n return this.mergedConfig;\n }\n\n loadProject(projectRoot: string): IGlobalConfig {\n const resolvedPath = getProjectConfigPath(projectRoot);\n\n if (!existsSync(resolvedPath)) {\n logger.debug(\n { path: resolvedPath },\n \"Project config not found, using global only\",\n );\n this.projectConfig = undefined;\n this.rebuildMergedConfig();\n return this.mergedConfig;\n }\n\n let parsed: unknown;\n try {\n const raw = readFileSync(resolvedPath, \"utf-8\");\n parsed = JSON.parse(raw);\n } catch (error: unknown) {\n const message = error instanceof Error ? error.message : String(error);\n logger.warn({ error: message, path: resolvedPath }, \"Project config parse failed, ignoring\");\n this.projectConfig = undefined;\n this.rebuildMergedConfig();\n return this.mergedConfig;\n }\n const validated = GlobalConfigSchema.partial().safeParse(parsed);\n\n if (!validated.success) {\n logger.warn(\n { errors: validated.error.issues },\n \"Project config validation failed, ignoring\",\n );\n this.projectConfig = undefined;\n this.rebuildMergedConfig();\n return this.mergedConfig;\n }\n\n this.projectConfig = validated.data as Partial<IGlobalConfig>;\n this.rebuildMergedConfig();\n\n logger.info({ path: resolvedPath }, \"Project config loaded\");\n return this.mergedConfig;\n }\n\n saveGlobal(\n config?: IGlobalConfig,\n configPath?: string,\n ): void {\n const resolvedPath = configPath ?? getConfigPath();\n const configToSave = config ?? this.globalConfig;\n const validated = GlobalConfigSchema.safeParse(configToSave);\n\n if (!validated.success) {\n throw new Error(`Invalid global config: ${formatValidationError(validated.error)}`);\n }\n\n ensureDirectory(dirname(resolvedPath));\n const json = JSON.stringify(validated.data, null, 2);\n writeFileSync(resolvedPath, json, { encoding: \"utf-8\", mode: 0o600 });\n\n logger.info({ path: resolvedPath }, \"Global config saved\");\n\n if (config) {\n this.globalConfig = this.applyDefaults(validated.data);\n this.rebuildMergedConfig();\n }\n }\n\n saveProject(\n projectRoot: string,\n config: Partial<IGlobalConfig>,\n ): void {\n const resolvedPath = getProjectConfigPath(projectRoot);\n const validated = GlobalConfigSchema.partial().safeParse(config);\n\n if (!validated.success) {\n throw new Error(`Invalid project config: ${formatValidationError(validated.error)}`);\n }\n\n ensureDirectory(dirname(resolvedPath));\n const json = JSON.stringify(validated.data, null, 2);\n writeFileSync(resolvedPath, json, { encoding: \"utf-8\", mode: 0o600 });\n\n this.projectConfig = validated.data as Partial<IGlobalConfig>;\n this.rebuildMergedConfig();\n\n logger.info({ path: resolvedPath }, \"Project config saved\");\n }\n\n watchGlobal(configPath?: string): void {\n const resolvedPath = configPath ?? getConfigPath();\n this.watchConfigFile(resolvedPath, () => {\n this.loadGlobal(resolvedPath);\n });\n }\n\n watchProject(projectRoot: string): void {\n const resolvedPath = getProjectConfigPath(projectRoot);\n this.watchConfigFile(resolvedPath, () => {\n this.loadProject(projectRoot);\n });\n }\n\n onChange(callback: ConfigChangeCallback): void {\n this.changeCallbacks.push(callback);\n }\n\n stopWatching(): void {\n for (const watcher of this.watchers) {\n if (watcher.active) {\n unwatchFile(watcher.path);\n watcher.active = false;\n }\n }\n this.watchers = [];\n }\n\n private watchConfigFile(filePath: string, onUpdate: () => void): void {\n if (!existsSync(filePath)) {\n return;\n }\n\n const entry = { path: filePath, active: true };\n this.watchers.push(entry);\n\n watchFile(filePath, { interval: 2000 }, () => {\n if (!entry.active) {\n return;\n }\n logger.info({ path: filePath }, \"Config file changed, reloading\");\n try {\n onUpdate();\n } catch (error: unknown) {\n const message =\n error instanceof Error ? error.message : String(error);\n logger.error({ error: message }, \"Failed to reload config\");\n }\n });\n }\n\n private rebuildMergedConfig(): void {\n if (!this.projectConfig) {\n this.mergedConfig = { ...this.globalConfig };\n } else {\n this.mergedConfig = {\n ...this.globalConfig,\n ...this.projectConfig,\n roles: {\n ...this.globalConfig.roles,\n ...(this.projectConfig.roles ?? {}),\n },\n providers: {\n ...this.globalConfig.providers,\n ...(this.projectConfig.providers ?? {}),\n },\n permissions: {\n ...this.globalConfig.permissions,\n ...(this.projectConfig.permissions ?? {}),\n },\n splitPanel: {\n ...this.globalConfig.splitPanel,\n ...(this.projectConfig.splitPanel ?? {}),\n },\n swarm: {\n ...this.globalConfig.swarm,\n ...(this.projectConfig.swarm ?? {}),\n },\n cost: {\n ...this.globalConfig.cost,\n ...(this.projectConfig.cost ?? {}),\n },\n telemetry: {\n ...this.globalConfig.telemetry,\n ...(this.projectConfig.telemetry ?? {}),\n },\n oauth: this.projectConfig.oauth ?? this.globalConfig.oauth,\n };\n }\n\n for (const cb of this.changeCallbacks) {\n try {\n cb(this.mergedConfig);\n } catch (error: unknown) {\n const message =\n error instanceof Error ? error.message : String(error);\n logger.error({ error: message }, \"Config change callback failed\");\n }\n }\n }\n\n private applyDefaults(\n partial: z.infer<typeof GlobalConfigSchema>,\n ): IGlobalConfig {\n return {\n version: partial.version,\n defaultModel: partial.defaultModel,\n roles: {\n ...DEFAULT_CONFIG.roles,\n ...(partial.roles as IGlobalConfig[\"roles\"] | undefined),\n },\n providers: {\n ...DEFAULT_CONFIG.providers,\n ...(partial.providers as IGlobalConfig[\"providers\"] | undefined),\n },\n permissions: partial.permissions\n ? (partial.permissions as IGlobalConfig[\"permissions\"])\n : DEFAULT_CONFIG.permissions,\n splitPanel: partial.splitPanel\n ? (partial.splitPanel as IGlobalConfig[\"splitPanel\"])\n : DEFAULT_CONFIG.splitPanel,\n swarm: partial.swarm\n ? (partial.swarm as IGlobalConfig[\"swarm\"])\n : DEFAULT_CONFIG.swarm,\n cost: partial.cost\n ? (partial.cost as IGlobalConfig[\"cost\"])\n : DEFAULT_CONFIG.cost,\n telemetry: partial.telemetry\n ? (partial.telemetry as IGlobalConfig[\"telemetry\"])\n : DEFAULT_CONFIG.telemetry,\n oauth: partial.oauth\n ? (partial.oauth as IGlobalConfig[\"oauth\"])\n : undefined,\n };\n }\n}\n"]}