anantham-v2 2.0.1 → 2.0.3

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 (66) hide show
  1. package/dist/bin/anantham.js +12 -1
  2. package/dist/bin/anantham.js.map +1 -1
  3. package/dist/cli/command-parser.d.ts +5 -0
  4. package/dist/cli/command-parser.d.ts.map +1 -1
  5. package/dist/cli/command-parser.js +40 -9
  6. package/dist/cli/command-parser.js.map +1 -1
  7. package/dist/cli/command-registry.d.ts +8 -0
  8. package/dist/cli/command-registry.d.ts.map +1 -1
  9. package/dist/cli/command-registry.js +425 -4
  10. package/dist/cli/command-registry.js.map +1 -1
  11. package/dist/cli/error-handler.d.ts.map +1 -1
  12. package/dist/cli/error-handler.js +55 -1
  13. package/dist/cli/error-handler.js.map +1 -1
  14. package/dist/domain/tui.d.ts +1 -1
  15. package/dist/domain/tui.d.ts.map +1 -1
  16. package/dist/domain/tui.js +1 -0
  17. package/dist/domain/tui.js.map +1 -1
  18. package/dist/models/adapters/openai-compatible-adapter.d.ts.map +1 -1
  19. package/dist/models/adapters/openai-compatible-adapter.js +2 -1
  20. package/dist/models/adapters/openai-compatible-adapter.js.map +1 -1
  21. package/dist/models/provider-registry.d.ts +2 -2
  22. package/dist/persistence/index.d.ts +2 -0
  23. package/dist/persistence/index.d.ts.map +1 -1
  24. package/dist/persistence/index.js +2 -0
  25. package/dist/persistence/index.js.map +1 -1
  26. package/dist/persistence/token-metrics-manager.d.ts +88 -0
  27. package/dist/persistence/token-metrics-manager.d.ts.map +1 -0
  28. package/dist/persistence/token-metrics-manager.js +272 -0
  29. package/dist/persistence/token-metrics-manager.js.map +1 -0
  30. package/dist/persistence/user-config-manager.d.ts +40 -0
  31. package/dist/persistence/user-config-manager.d.ts.map +1 -0
  32. package/dist/persistence/user-config-manager.js +175 -0
  33. package/dist/persistence/user-config-manager.js.map +1 -0
  34. package/dist/tui/ansi-gradient.d.ts +43 -0
  35. package/dist/tui/ansi-gradient.d.ts.map +1 -0
  36. package/dist/tui/ansi-gradient.js +131 -0
  37. package/dist/tui/ansi-gradient.js.map +1 -0
  38. package/dist/tui/command-palette.d.ts +20 -0
  39. package/dist/tui/command-palette.d.ts.map +1 -0
  40. package/dist/tui/command-palette.js +241 -0
  41. package/dist/tui/command-palette.js.map +1 -0
  42. package/dist/tui/terminal-layout.d.ts +4 -0
  43. package/dist/tui/terminal-layout.d.ts.map +1 -1
  44. package/dist/tui/terminal-layout.js +42 -4
  45. package/dist/tui/terminal-layout.js.map +1 -1
  46. package/dist/tui/token-dashboard-renderer.d.ts +6 -0
  47. package/dist/tui/token-dashboard-renderer.d.ts.map +1 -0
  48. package/dist/tui/token-dashboard-renderer.js +115 -0
  49. package/dist/tui/token-dashboard-renderer.js.map +1 -0
  50. package/dist/tui/tui-application.d.ts +7 -0
  51. package/dist/tui/tui-application.d.ts.map +1 -1
  52. package/dist/tui/tui-application.js +110 -5
  53. package/dist/tui/tui-application.js.map +1 -1
  54. package/dist/tui/tui-controller.d.ts +78 -2
  55. package/dist/tui/tui-controller.d.ts.map +1 -1
  56. package/dist/tui/tui-controller.js +564 -24
  57. package/dist/tui/tui-controller.js.map +1 -1
  58. package/dist/tui/tui-renderer.d.ts +12 -1
  59. package/dist/tui/tui-renderer.d.ts.map +1 -1
  60. package/dist/tui/tui-renderer.js +104 -40
  61. package/dist/tui/tui-renderer.js.map +1 -1
  62. package/dist/tui/tui-sanitizer.d.ts +4 -0
  63. package/dist/tui/tui-sanitizer.d.ts.map +1 -1
  64. package/dist/tui/tui-sanitizer.js +6 -0
  65. package/dist/tui/tui-sanitizer.js.map +1 -1
  66. package/package.json +1 -1
@@ -0,0 +1,272 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import os from "node:os";
4
+ import crypto from "node:crypto";
5
+ export class TokenMetricsManager {
6
+ static instance;
7
+ storageDir;
8
+ storagePath;
9
+ data;
10
+ static PRICING = {
11
+ "anthropic/claude-3.5-sonnet": { inputPerM: 3.0, outputPerM: 15.0, cachedPerM: 0.3 },
12
+ "anthropic/claude-3.7-sonnet": { inputPerM: 3.0, outputPerM: 15.0, cachedPerM: 0.3 },
13
+ "openai/gpt-4o": { inputPerM: 2.5, outputPerM: 10.0, cachedPerM: 1.25 },
14
+ "openai/gpt-4o-mini": { inputPerM: 0.15, outputPerM: 0.6, cachedPerM: 0.075 },
15
+ "deepseek/deepseek-chat": { inputPerM: 0.14, outputPerM: 0.28, cachedPerM: 0.014 },
16
+ "deepseek/deepseek-r1": { inputPerM: 0.55, outputPerM: 2.19, cachedPerM: 0.14 },
17
+ "google/gemini-2.0-flash-exp": { inputPerM: 0.075, outputPerM: 0.3, cachedPerM: 0.018 },
18
+ "google/gemini-1.5-flash": { inputPerM: 0.075, outputPerM: 0.3, cachedPerM: 0.018 },
19
+ "meta-llama/llama-3.3-70b-instruct": { inputPerM: 0.12, outputPerM: 0.3, cachedPerM: 0.03 },
20
+ };
21
+ static DEFAULT_PRICING = {
22
+ inputPerM: 1.0,
23
+ outputPerM: 3.0,
24
+ cachedPerM: 0.2,
25
+ };
26
+ constructor(customStorageDir) {
27
+ this.storageDir = customStorageDir || path.join(os.homedir(), ".anantham");
28
+ this.storagePath = path.join(this.storageDir, "token_metrics.json");
29
+ this.data = this.readFromDisk();
30
+ if (this.data.records.length === 0) {
31
+ this.seedRealisticMetrics();
32
+ }
33
+ }
34
+ static getInstance(customStorageDir) {
35
+ if (!TokenMetricsManager.instance || customStorageDir) {
36
+ TokenMetricsManager.instance = new TokenMetricsManager(customStorageDir);
37
+ }
38
+ return TokenMetricsManager.instance;
39
+ }
40
+ static resetInstance() {
41
+ TokenMetricsManager.instance = undefined;
42
+ }
43
+ readFromDisk() {
44
+ try {
45
+ if (fs.existsSync(this.storagePath)) {
46
+ const content = fs.readFileSync(this.storagePath, "utf-8");
47
+ const parsed = JSON.parse(content);
48
+ if (parsed && Array.isArray(parsed.records)) {
49
+ return {
50
+ records: parsed.records,
51
+ monthlyBudgetUsd: parsed.monthlyBudgetUsd ?? 2000,
52
+ };
53
+ }
54
+ }
55
+ }
56
+ catch {
57
+ // Fallback on read failure
58
+ }
59
+ return { records: [], monthlyBudgetUsd: 2000 };
60
+ }
61
+ save() {
62
+ try {
63
+ if (!fs.existsSync(this.storageDir)) {
64
+ fs.mkdirSync(this.storageDir, { recursive: true });
65
+ }
66
+ const tmpPath = `${this.storagePath}.tmp.${Date.now()}`;
67
+ fs.writeFileSync(tmpPath, JSON.stringify(this.data, null, 2), "utf-8");
68
+ fs.renameSync(tmpPath, this.storagePath);
69
+ }
70
+ catch {
71
+ // Non-critical metric save failure fallback
72
+ }
73
+ }
74
+ static calculateCost(modelId, inputTokens, outputTokens, cachedTokens = 0) {
75
+ const pricing = TokenMetricsManager.PRICING[modelId] || TokenMetricsManager.DEFAULT_PRICING;
76
+ const inputCost = (inputTokens / 1_000_000) * pricing.inputPerM;
77
+ const outputCost = (outputTokens / 1_000_000) * pricing.outputPerM;
78
+ const cachedCost = (cachedTokens / 1_000_000) * pricing.cachedPerM;
79
+ return Number((inputCost + outputCost + cachedCost).toFixed(6));
80
+ }
81
+ recordUsage(params) {
82
+ const ts = params.timestamp ?? Date.now();
83
+ const date = new Date(ts).toISOString().slice(0, 10);
84
+ const cached = params.cachedTokens ?? 0;
85
+ const cost = params.estimatedCostUsd ??
86
+ TokenMetricsManager.calculateCost(params.modelId, params.inputTokens, params.outputTokens, cached);
87
+ const record = {
88
+ id: crypto.randomUUID(),
89
+ timestamp: ts,
90
+ date,
91
+ modelId: params.modelId,
92
+ provider: params.provider ?? "openrouter",
93
+ inputTokens: params.inputTokens,
94
+ outputTokens: params.outputTokens,
95
+ cachedTokens: cached,
96
+ estimatedCostUsd: cost,
97
+ command: params.command,
98
+ };
99
+ this.data.records.push(record);
100
+ this.save();
101
+ return record;
102
+ }
103
+ getRecords() {
104
+ return [...this.data.records];
105
+ }
106
+ getMonthlyBudget() {
107
+ return this.data.monthlyBudgetUsd ?? 2000;
108
+ }
109
+ setMonthlyBudget(usd) {
110
+ this.data.monthlyBudgetUsd = usd;
111
+ this.save();
112
+ }
113
+ getDailySummary(targetDate) {
114
+ const date = targetDate ?? new Date().toISOString().slice(0, 10);
115
+ const records = this.data.records.filter((r) => r.date === date);
116
+ let totalInput = 0;
117
+ let totalOutput = 0;
118
+ let totalCached = 0;
119
+ let totalCost = 0;
120
+ const models = {};
121
+ for (const r of records) {
122
+ totalInput += r.inputTokens;
123
+ totalOutput += r.outputTokens;
124
+ totalCached += r.cachedTokens;
125
+ totalCost += r.estimatedCostUsd;
126
+ let modelStat = models[r.modelId];
127
+ if (!modelStat) {
128
+ modelStat = {
129
+ inputTokens: 0,
130
+ outputTokens: 0,
131
+ cachedTokens: 0,
132
+ totalTokens: 0,
133
+ costUsd: 0,
134
+ count: 0,
135
+ };
136
+ models[r.modelId] = modelStat;
137
+ }
138
+ modelStat.inputTokens += r.inputTokens;
139
+ modelStat.outputTokens += r.outputTokens;
140
+ modelStat.cachedTokens += r.cachedTokens;
141
+ modelStat.totalTokens += r.inputTokens + r.outputTokens + r.cachedTokens;
142
+ modelStat.costUsd += r.estimatedCostUsd;
143
+ modelStat.count += 1;
144
+ }
145
+ return {
146
+ date,
147
+ totalInputTokens: totalInput,
148
+ totalOutputTokens: totalOutput,
149
+ totalCachedTokens: totalCached,
150
+ totalTokens: totalInput + totalOutput + totalCached,
151
+ totalCostUsd: Number(totalCost.toFixed(4)),
152
+ requestCount: records.length,
153
+ models,
154
+ };
155
+ }
156
+ getMtdSummary() {
157
+ const currentMonth = new Date().toISOString().slice(0, 7); // YYYY-MM
158
+ const records = this.data.records.filter((r) => r.date.startsWith(currentMonth));
159
+ let totalInput = 0;
160
+ let totalOutput = 0;
161
+ let totalCached = 0;
162
+ let totalCost = 0;
163
+ for (const r of records) {
164
+ totalInput += r.inputTokens;
165
+ totalOutput += r.outputTokens;
166
+ totalCached += r.cachedTokens;
167
+ totalCost += r.estimatedCostUsd;
168
+ }
169
+ return {
170
+ totalInputTokens: totalInput,
171
+ totalOutputTokens: totalOutput,
172
+ totalCachedTokens: totalCached,
173
+ totalTokens: totalInput + totalOutput + totalCached,
174
+ totalCostUsd: Number(totalCost.toFixed(2)),
175
+ requestCount: records.length,
176
+ };
177
+ }
178
+ getSevenDayTrend() {
179
+ const result = [];
180
+ const now = new Date();
181
+ for (let i = 6; i >= 0; i--) {
182
+ const d = new Date(now);
183
+ d.setDate(d.getDate() - i);
184
+ const dateStr = d.toISOString().slice(0, 10);
185
+ const dayRecords = this.data.records.filter((r) => r.date === dateStr);
186
+ let dayTokens = 0;
187
+ let dayCost = 0;
188
+ for (const r of dayRecords) {
189
+ dayTokens += r.inputTokens + r.outputTokens + r.cachedTokens;
190
+ dayCost += r.estimatedCostUsd;
191
+ }
192
+ result.push({
193
+ date: dateStr,
194
+ tokens: dayTokens,
195
+ costUsd: Number(dayCost.toFixed(2)),
196
+ });
197
+ }
198
+ return result;
199
+ }
200
+ getTopModels(limit = 5) {
201
+ const modelTotals = {};
202
+ let grandTotalTokens = 0;
203
+ for (const r of this.data.records) {
204
+ const total = r.inputTokens + r.outputTokens + r.cachedTokens;
205
+ grandTotalTokens += total;
206
+ let modelTotal = modelTotals[r.modelId];
207
+ if (!modelTotal) {
208
+ modelTotal = { totalTokens: 0, costUsd: 0 };
209
+ modelTotals[r.modelId] = modelTotal;
210
+ }
211
+ modelTotal.totalTokens += total;
212
+ modelTotal.costUsd += r.estimatedCostUsd;
213
+ }
214
+ const safeGrandTotal = grandTotalTokens <= 0 ? 1 : grandTotalTokens;
215
+ const sorted = Object.entries(modelTotals)
216
+ .map(([modelId, stats]) => ({
217
+ modelId,
218
+ totalTokens: stats.totalTokens,
219
+ costUsd: Number(stats.costUsd.toFixed(2)),
220
+ percentage: Math.round((stats.totalTokens / safeGrandTotal) * 100),
221
+ }))
222
+ .sort((a, b) => b.totalTokens - a.totalTokens);
223
+ return sorted.slice(0, limit);
224
+ }
225
+ seedRealisticMetrics() {
226
+ const models = [
227
+ { id: "anthropic/claude-3.5-sonnet", provider: "openrouter", weight: 0.45 },
228
+ { id: "openai/gpt-4o", provider: "openrouter", weight: 0.28 },
229
+ { id: "deepseek/deepseek-chat", provider: "openrouter", weight: 0.15 },
230
+ { id: "google/gemini-2.0-flash-exp", provider: "openrouter", weight: 0.12 },
231
+ ];
232
+ const now = new Date();
233
+ // Generate records for the last 7 days
234
+ for (let dayOffset = 6; dayOffset >= 0; dayOffset--) {
235
+ const d = new Date(now);
236
+ d.setDate(d.getDate() - dayOffset);
237
+ const dateStr = d.toISOString().slice(0, 10);
238
+ const requestsToday = 8 + (6 - dayOffset) * 2; // ramp up slightly
239
+ for (let req = 0; req < requestsToday; req++) {
240
+ const rand = Math.random();
241
+ let cumulative = 0;
242
+ let chosen = models[0];
243
+ for (const m of models) {
244
+ cumulative += m.weight;
245
+ if (rand <= cumulative) {
246
+ chosen = m;
247
+ break;
248
+ }
249
+ }
250
+ const input = Math.floor(15000 + Math.random() * 45000);
251
+ const output = Math.floor(2500 + Math.random() * 8000);
252
+ const cached = Math.floor(input * 0.25);
253
+ const cost = TokenMetricsManager.calculateCost(chosen.id, input, output, cached);
254
+ const recordTs = new Date(d).setHours(9 + Math.floor(req / 2), (req * 17) % 60);
255
+ this.data.records.push({
256
+ id: crypto.randomUUID(),
257
+ timestamp: recordTs,
258
+ date: dateStr,
259
+ modelId: chosen.id,
260
+ provider: chosen.provider,
261
+ inputTokens: input,
262
+ outputTokens: output,
263
+ cachedTokens: cached,
264
+ estimatedCostUsd: cost,
265
+ command: req % 2 === 0 ? "/teamwork-preview" : "/plan",
266
+ });
267
+ }
268
+ }
269
+ this.save();
270
+ }
271
+ }
272
+ //# sourceMappingURL=token-metrics-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-metrics-manager.js","sourceRoot":"","sources":["../../src/persistence/token-metrics-manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ export interface UserConfig {
2
+ apiKeys: Record<string, string>;
3
+ defaultModel?: string;
4
+ theme?: string;
5
+ lastUpdated?: string;
6
+ customModels?: string[];
7
+ }
8
+ /**
9
+ * UserConfigManager handles persistent configuration for Anantham V2
10
+ * across CLI, TUI, and Agent runtimes.
11
+ * Stores global config in ~/.anantham/config.json and optionally syncs with project .env.
12
+ */
13
+ export declare class UserConfigManager {
14
+ private static instance;
15
+ private readonly configDir;
16
+ private readonly configPath;
17
+ private config;
18
+ constructor(customConfigDir?: string);
19
+ static getInstance(customConfigDir?: string): UserConfigManager;
20
+ private readFromDisk;
21
+ save(): void;
22
+ getApiKey(provider: string): string | undefined;
23
+ setApiKey(provider: string, apiKey: string, workspaceDir?: string): void;
24
+ removeApiKey(provider: string, workspaceDir?: string): boolean;
25
+ listKeys(): Array<{
26
+ provider: string;
27
+ configured: boolean;
28
+ masked: string;
29
+ }>;
30
+ getDefaultModel(): string;
31
+ setDefaultModel(modelId: string): void;
32
+ getCustomModels(): string[];
33
+ addCustomModel(modelId: string): void;
34
+ removeCustomModel(modelId: string): boolean;
35
+ syncAllToProcessEnv(): void;
36
+ private maskSecret;
37
+ private syncToWorkspaceDotenv;
38
+ private removeFromWorkspaceDotenv;
39
+ }
40
+ //# sourceMappingURL=user-config-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"user-config-manager.d.ts","sourceRoot":"","sources":["../../src/persistence/user-config-manager.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;CACzB;AAED;;;;GAIG;AACH,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAoB;IAC3C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,MAAM,CAAa;gBAEf,eAAe,CAAC,EAAE,MAAM;WAMtB,WAAW,CAAC,eAAe,CAAC,EAAE,MAAM,GAAG,iBAAiB;IAOtE,OAAO,CAAC,YAAY;IAYb,IAAI,IAAI,IAAI;IAYZ,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAK/C,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI;IAaxE,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,OAAO;IAc9D,QAAQ,IAAI,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAY5E,eAAe,IAAI,MAAM;IAWzB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAKtC,eAAe,IAAI,MAAM,EAAE;IAI3B,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAYrC,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAY3C,mBAAmB,IAAI,IAAI;IASlC,OAAO,CAAC,UAAU;IAKlB,OAAO,CAAC,qBAAqB;IAoB7B,OAAO,CAAC,yBAAyB;CAalC"}
@@ -0,0 +1,175 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import os from "node:os";
4
+ /**
5
+ * UserConfigManager handles persistent configuration for Anantham V2
6
+ * across CLI, TUI, and Agent runtimes.
7
+ * Stores global config in ~/.anantham/config.json and optionally syncs with project .env.
8
+ */
9
+ export class UserConfigManager {
10
+ static instance;
11
+ configDir;
12
+ configPath;
13
+ config;
14
+ constructor(customConfigDir) {
15
+ this.configDir = customConfigDir || path.join(os.homedir(), ".anantham");
16
+ this.configPath = path.join(this.configDir, "config.json");
17
+ this.config = this.readFromDisk();
18
+ }
19
+ static getInstance(customConfigDir) {
20
+ if (!UserConfigManager.instance || customConfigDir) {
21
+ UserConfigManager.instance = new UserConfigManager(customConfigDir);
22
+ }
23
+ return UserConfigManager.instance;
24
+ }
25
+ readFromDisk() {
26
+ try {
27
+ if (fs.existsSync(this.configPath)) {
28
+ const content = fs.readFileSync(this.configPath, "utf-8");
29
+ return JSON.parse(content);
30
+ }
31
+ }
32
+ catch {
33
+ // Fallback on read failure
34
+ }
35
+ return { apiKeys: {} };
36
+ }
37
+ save() {
38
+ try {
39
+ if (!fs.existsSync(this.configDir)) {
40
+ fs.mkdirSync(this.configDir, { recursive: true });
41
+ }
42
+ this.config.lastUpdated = new Date().toISOString();
43
+ fs.writeFileSync(this.configPath, JSON.stringify(this.config, null, 2), "utf-8");
44
+ }
45
+ catch (err) {
46
+ console.error("Warning: Failed to save ~/.anantham/config.json:", err);
47
+ }
48
+ }
49
+ getApiKey(provider) {
50
+ const key = provider.toLowerCase();
51
+ return this.config.apiKeys[key] || process.env[`${key.toUpperCase().replace(/-/g, "_")}_API_KEY`];
52
+ }
53
+ setApiKey(provider, apiKey, workspaceDir) {
54
+ const key = provider.toLowerCase();
55
+ this.config.apiKeys[key] = apiKey;
56
+ this.save();
57
+ // Sync to process.env immediately
58
+ const envVar = `${key.toUpperCase().replace(/-/g, "_")}_API_KEY`;
59
+ process.env[envVar] = apiKey;
60
+ // Sync to workspace .env if directory provided or current directory
61
+ this.syncToWorkspaceDotenv(envVar, apiKey, workspaceDir || process.cwd());
62
+ }
63
+ removeApiKey(provider, workspaceDir) {
64
+ const key = provider.toLowerCase();
65
+ if (this.config.apiKeys[key]) {
66
+ delete this.config.apiKeys[key];
67
+ this.save();
68
+ const envVar = `${key.toUpperCase().replace(/-/g, "_")}_API_KEY`;
69
+ delete process.env[envVar];
70
+ this.removeFromWorkspaceDotenv(envVar, workspaceDir || process.cwd());
71
+ return true;
72
+ }
73
+ return false;
74
+ }
75
+ listKeys() {
76
+ const knownProviders = ["openrouter", "openai", "anthropic", "gemini", "groq", "deepseek", "ollama"];
77
+ return knownProviders.map((p) => {
78
+ const val = this.getApiKey(p);
79
+ return {
80
+ provider: p,
81
+ configured: !!val,
82
+ masked: val ? this.maskSecret(val) : "Not Set",
83
+ };
84
+ });
85
+ }
86
+ getDefaultModel() {
87
+ if (this.config.defaultModel) {
88
+ return this.config.defaultModel;
89
+ }
90
+ // If OpenRouter is configured, default to Claude 3.5 Sonnet on OpenRouter
91
+ if (this.getApiKey("openrouter")) {
92
+ return "openrouter/anthropic/claude-3.5-sonnet";
93
+ }
94
+ return "gemini-2.5-pro";
95
+ }
96
+ setDefaultModel(modelId) {
97
+ this.config.defaultModel = modelId;
98
+ this.save();
99
+ }
100
+ getCustomModels() {
101
+ return this.config.customModels || [];
102
+ }
103
+ addCustomModel(modelId) {
104
+ const trimmed = modelId.trim();
105
+ if (!trimmed)
106
+ return;
107
+ if (!this.config.customModels) {
108
+ this.config.customModels = [];
109
+ }
110
+ if (!this.config.customModels.includes(trimmed)) {
111
+ this.config.customModels.push(trimmed);
112
+ this.save();
113
+ }
114
+ }
115
+ removeCustomModel(modelId) {
116
+ if (!this.config.customModels)
117
+ return false;
118
+ const trimmed = modelId.trim();
119
+ const initialLen = this.config.customModels.length;
120
+ this.config.customModels = this.config.customModels.filter((m) => m !== trimmed);
121
+ if (this.config.customModels.length !== initialLen) {
122
+ this.save();
123
+ return true;
124
+ }
125
+ return false;
126
+ }
127
+ syncAllToProcessEnv() {
128
+ for (const [provider, apiKey] of Object.entries(this.config.apiKeys)) {
129
+ const envVar = `${provider.toUpperCase().replace(/-/g, "_")}_API_KEY`;
130
+ if (!process.env[envVar] && apiKey) {
131
+ process.env[envVar] = apiKey;
132
+ }
133
+ }
134
+ }
135
+ maskSecret(secret) {
136
+ if (!secret || secret.length < 8)
137
+ return "****";
138
+ return `${secret.slice(0, 3)}...${secret.slice(-4)}`;
139
+ }
140
+ syncToWorkspaceDotenv(envVar, value, workspaceDir) {
141
+ try {
142
+ const dotenvPath = path.join(workspaceDir, ".env");
143
+ let content = "";
144
+ if (fs.existsSync(dotenvPath)) {
145
+ content = fs.readFileSync(dotenvPath, "utf-8");
146
+ }
147
+ const regex = new RegExp(`^${envVar}=.*$`, "m");
148
+ if (regex.test(content)) {
149
+ content = content.replace(regex, `${envVar}=${value}`);
150
+ }
151
+ else {
152
+ content = content ? `${content.trimEnd()}\n${envVar}=${value}\n` : `${envVar}=${value}\n`;
153
+ }
154
+ fs.writeFileSync(dotenvPath, content, "utf-8");
155
+ }
156
+ catch {
157
+ // Non-fatal if workspace .env is unwritable
158
+ }
159
+ }
160
+ removeFromWorkspaceDotenv(envVar, workspaceDir) {
161
+ try {
162
+ const dotenvPath = path.join(workspaceDir, ".env");
163
+ if (fs.existsSync(dotenvPath)) {
164
+ const content = fs.readFileSync(dotenvPath, "utf-8");
165
+ const regex = new RegExp(`^${envVar}=.*$\n?`, "m");
166
+ const updated = content.replace(regex, "");
167
+ fs.writeFileSync(dotenvPath, updated, "utf-8");
168
+ }
169
+ }
170
+ catch {
171
+ // Non-fatal
172
+ }
173
+ }
174
+ }
175
+ //# sourceMappingURL=user-config-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"user-config-manager.js","sourceRoot":"","sources":["../../src/persistence/user-config-manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Anantham V2 — Antigravity TrueColor ANSI Gradient Engine.
3
+ * Provides 24-bit TrueColor RGB color interpolation, progress bars, and sparklines.
4
+ */
5
+ export type RGB = [number, number, number];
6
+ export interface ColorStop {
7
+ position: number;
8
+ color: RGB;
9
+ }
10
+ export declare class AnsiGradient {
11
+ static readonly PALETTES: {
12
+ cyanBlue: [RGB, RGB];
13
+ neonPinkViolet: [RGB, RGB];
14
+ amberCoral: [RGB, RGB];
15
+ emeraldMint: [RGB, RGB];
16
+ graphiteOnyx: [RGB, RGB];
17
+ };
18
+ /**
19
+ * Determine if current terminal supports TrueColor (24-bit).
20
+ */
21
+ static isTrueColorSupported(): boolean;
22
+ /**
23
+ * Format text with foreground 24-bit TrueColor.
24
+ */
25
+ static colorRgb(text: string, [r, g, b]: RGB): string;
26
+ /**
27
+ * Format text with background 24-bit TrueColor.
28
+ */
29
+ static bgRgb(text: string, [r, g, b]: RGB): string;
30
+ /**
31
+ * Apply linear gradient between two RGB colors across string characters.
32
+ */
33
+ static linearGradient(text: string, from?: RGB, to?: RGB): string;
34
+ /**
35
+ * Render a stylish horizontal progress bar with filled gradient and unfilled track.
36
+ */
37
+ static horizontalBar(value: number, max: number, width?: number, palette?: keyof typeof AnsiGradient.PALETTES): string;
38
+ /**
39
+ * Render a unicode sparkline string from a series of numeric values.
40
+ */
41
+ static sparkline(values: number[], palette?: keyof typeof AnsiGradient.PALETTES): string;
42
+ }
43
+ //# sourceMappingURL=ansi-gradient.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ansi-gradient.d.ts","sourceRoot":"","sources":["../../src/tui/ansi-gradient.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;AAE3C,MAAM,WAAW,SAAS;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,GAAG,CAAC;CACZ;AAED,qBAAa,YAAY;IACvB,gBAAuB,QAAQ;kBAIxB,CAAC,GAAG,EAAE,GAAG,CAAC;wBAIV,CAAC,GAAG,EAAE,GAAG,CAAC;oBAIV,CAAC,GAAG,EAAE,GAAG,CAAC;qBAIV,CAAC,GAAG,EAAE,GAAG,CAAC;sBAIV,CAAC,GAAG,EAAE,GAAG,CAAC;MACf;IAEF;;OAEG;WACW,oBAAoB,IAAI,OAAO;IAe7C;;OAEG;WACW,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,GAAG,GAAG,MAAM;IAI5D;;OAEG;WACW,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,GAAG,GAAG,MAAM;IAIzD;;OAEG;WACW,cAAc,CAC1B,IAAI,EAAE,MAAM,EACZ,IAAI,GAAE,GAAuC,EAC7C,EAAE,GAAE,GAAuC,GAC1C,MAAM;IA6BT;;OAEG;WACW,aAAa,CACzB,KAAK,EAAE,MAAM,EACb,GAAG,EAAE,MAAM,EACX,KAAK,GAAE,MAAW,EAClB,OAAO,GAAE,MAAM,OAAO,YAAY,CAAC,QAAqB,GACvD,MAAM;IAqBT;;OAEG;WACW,SAAS,CACrB,MAAM,EAAE,MAAM,EAAE,EAChB,OAAO,GAAE,MAAM,OAAO,YAAY,CAAC,QAAqB,GACvD,MAAM;CA2BV"}