erosolar-cli 2.1.203 → 2.1.205

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 (52) hide show
  1. package/dist/core/agentOrchestrator.d.ts +16 -4
  2. package/dist/core/agentOrchestrator.d.ts.map +1 -1
  3. package/dist/core/agentOrchestrator.js +181 -61
  4. package/dist/core/agentOrchestrator.js.map +1 -1
  5. package/dist/core/errors/errorTypes.d.ts +0 -6
  6. package/dist/core/errors/errorTypes.d.ts.map +1 -1
  7. package/dist/core/errors/errorTypes.js +0 -26
  8. package/dist/core/errors/errorTypes.js.map +1 -1
  9. package/dist/shell/interactiveShell.d.ts +0 -5
  10. package/dist/shell/interactiveShell.d.ts.map +1 -1
  11. package/dist/shell/interactiveShell.js +45 -205
  12. package/dist/shell/interactiveShell.js.map +1 -1
  13. package/dist/ui/UnifiedUIRenderer.d.ts.map +1 -1
  14. package/dist/ui/UnifiedUIRenderer.js +6 -3
  15. package/dist/ui/UnifiedUIRenderer.js.map +1 -1
  16. package/package.json +1 -1
  17. package/dist/core/LazyLoader.d.ts +0 -129
  18. package/dist/core/LazyLoader.d.ts.map +0 -1
  19. package/dist/core/LazyLoader.js +0 -240
  20. package/dist/core/LazyLoader.js.map +0 -1
  21. package/dist/core/alphaZeroOrchestrator.d.ts +0 -140
  22. package/dist/core/alphaZeroOrchestrator.d.ts.map +0 -1
  23. package/dist/core/alphaZeroOrchestrator.js +0 -418
  24. package/dist/core/alphaZeroOrchestrator.js.map +0 -1
  25. package/dist/core/checkpoint.d.ts +0 -76
  26. package/dist/core/checkpoint.d.ts.map +0 -1
  27. package/dist/core/checkpoint.js +0 -278
  28. package/dist/core/checkpoint.js.map +0 -1
  29. package/dist/core/costTracker.d.ts +0 -87
  30. package/dist/core/costTracker.d.ts.map +0 -1
  31. package/dist/core/costTracker.js +0 -285
  32. package/dist/core/costTracker.js.map +0 -1
  33. package/dist/core/isolatedVerifier.d.ts +0 -40
  34. package/dist/core/isolatedVerifier.d.ts.map +0 -1
  35. package/dist/core/isolatedVerifier.js +0 -129
  36. package/dist/core/isolatedVerifier.js.map +0 -1
  37. package/dist/core/responseVerifier.d.ts +0 -98
  38. package/dist/core/responseVerifier.d.ts.map +0 -1
  39. package/dist/core/responseVerifier.js +0 -509
  40. package/dist/core/responseVerifier.js.map +0 -1
  41. package/dist/core/securityAssessment.d.ts +0 -91
  42. package/dist/core/securityAssessment.d.ts.map +0 -1
  43. package/dist/core/securityAssessment.js +0 -580
  44. package/dist/core/securityAssessment.js.map +0 -1
  45. package/dist/core/verification.d.ts +0 -137
  46. package/dist/core/verification.d.ts.map +0 -1
  47. package/dist/core/verification.js +0 -323
  48. package/dist/core/verification.js.map +0 -1
  49. package/dist/tools/softwareEngineeringTools.d.ts +0 -7
  50. package/dist/tools/softwareEngineeringTools.d.ts.map +0 -1
  51. package/dist/tools/softwareEngineeringTools.js +0 -338
  52. package/dist/tools/softwareEngineeringTools.js.map +0 -1
@@ -1,278 +0,0 @@
1
- /**
2
- * Checkpoint System - Erosolar-CLI Style
3
- *
4
- * Automatic checkpointing before code changes with instant rewind capability.
5
- * Saves both code state and conversation state for full restoration.
6
- *
7
- * Features:
8
- * - Automatic checkpoint creation before file modifications
9
- * - Rewind to any previous checkpoint (code only, conversation only, or both)
10
- * - Efficient diff-based storage to minimize disk usage
11
- * - Integration with session management
12
- */
13
- import { existsSync, mkdirSync, readFileSync, writeFileSync, readdirSync, unlinkSync, statSync } from 'node:fs';
14
- import { homedir } from 'node:os';
15
- import { join, dirname, relative } from 'node:path';
16
- import { createHash } from 'node:crypto';
17
- const CHECKPOINT_DIR = join(homedir(), '.erosolar', 'checkpoints');
18
- const MAX_CHECKPOINTS = 50; // Keep last 50 checkpoints per session
19
- const MAX_CHECKPOINT_AGE_DAYS = 7;
20
- /**
21
- * Create a hash for file content
22
- */
23
- function hashContent(content) {
24
- return createHash('sha256').update(content).digest('hex').slice(0, 16);
25
- }
26
- /**
27
- * Generate a unique checkpoint ID
28
- */
29
- function generateCheckpointId() {
30
- const timestamp = Date.now().toString(36);
31
- const random = Math.random().toString(36).slice(2, 8);
32
- return `cp_${timestamp}_${random}`;
33
- }
34
- /**
35
- * Get session checkpoint directory
36
- */
37
- function getSessionCheckpointDir(sessionId) {
38
- const sanitized = sessionId.replace(/[^a-zA-Z0-9_-]/g, '_');
39
- return join(CHECKPOINT_DIR, sanitized);
40
- }
41
- /**
42
- * Read file content safely
43
- */
44
- function readFileSafe(filePath) {
45
- try {
46
- if (!existsSync(filePath)) {
47
- return null;
48
- }
49
- const stats = statSync(filePath);
50
- const content = readFileSync(filePath, 'utf8');
51
- return { content, mtime: stats.mtimeMs };
52
- }
53
- catch {
54
- return null;
55
- }
56
- }
57
- /**
58
- * Write file content safely with directory creation
59
- */
60
- function writeFileSafe(filePath, content) {
61
- try {
62
- const dir = dirname(filePath);
63
- mkdirSync(dir, { recursive: true });
64
- writeFileSync(filePath, content, 'utf8');
65
- return true;
66
- }
67
- catch {
68
- return false;
69
- }
70
- }
71
- /**
72
- * Create a checkpoint manager for a working directory
73
- */
74
- export function createCheckpointManager(workingDir) {
75
- // Ensure checkpoint directory exists
76
- mkdirSync(CHECKPOINT_DIR, { recursive: true });
77
- return {
78
- async createCheckpoint(options) {
79
- const checkpointId = generateCheckpointId();
80
- const timestamp = Date.now();
81
- // Snapshot specified files (or use metadata.filePath)
82
- const filesToSnapshot = options.files ??
83
- (options.metadata?.filePath ? [options.metadata.filePath] : []);
84
- const fileSnapshots = [];
85
- for (const filePath of filesToSnapshot) {
86
- const fullPath = filePath.startsWith('/') ? filePath : join(workingDir, filePath);
87
- const fileData = readFileSafe(fullPath);
88
- if (fileData) {
89
- fileSnapshots.push({
90
- path: relative(workingDir, fullPath) || fullPath,
91
- content: fileData.content,
92
- hash: hashContent(fileData.content),
93
- mtime: fileData.mtime,
94
- });
95
- }
96
- }
97
- const checkpoint = {
98
- id: checkpointId,
99
- timestamp,
100
- sessionId: options.sessionId,
101
- description: options.description,
102
- trigger: options.trigger,
103
- files: fileSnapshots,
104
- conversation: options.conversation,
105
- metadata: options.metadata ?? {},
106
- };
107
- // Save checkpoint
108
- const sessionDir = getSessionCheckpointDir(options.sessionId);
109
- mkdirSync(sessionDir, { recursive: true });
110
- const checkpointPath = join(sessionDir, `${checkpointId}.json`);
111
- writeFileSafe(checkpointPath, JSON.stringify(checkpoint, null, 2));
112
- // Cleanup old checkpoints
113
- this.cleanupOldCheckpoints();
114
- return checkpoint;
115
- },
116
- getCheckpoints(sessionId) {
117
- const sessionDir = getSessionCheckpointDir(sessionId);
118
- if (!existsSync(sessionDir)) {
119
- return [];
120
- }
121
- const checkpoints = [];
122
- try {
123
- const files = readdirSync(sessionDir).filter(f => f.endsWith('.json'));
124
- for (const file of files) {
125
- try {
126
- const content = readFileSync(join(sessionDir, file), 'utf8');
127
- const checkpoint = JSON.parse(content);
128
- checkpoints.push(checkpoint);
129
- }
130
- catch {
131
- // Skip invalid checkpoint files
132
- }
133
- }
134
- }
135
- catch {
136
- return [];
137
- }
138
- // Sort by timestamp descending (newest first)
139
- return checkpoints.sort((a, b) => b.timestamp - a.timestamp);
140
- },
141
- getCheckpoint(id) {
142
- // Search all session directories for the checkpoint
143
- if (!existsSync(CHECKPOINT_DIR)) {
144
- return null;
145
- }
146
- try {
147
- const sessions = readdirSync(CHECKPOINT_DIR);
148
- for (const session of sessions) {
149
- const checkpointPath = join(CHECKPOINT_DIR, session, `${id}.json`);
150
- if (existsSync(checkpointPath)) {
151
- const content = readFileSync(checkpointPath, 'utf8');
152
- return JSON.parse(content);
153
- }
154
- }
155
- }
156
- catch {
157
- return null;
158
- }
159
- return null;
160
- },
161
- async rewind(options) {
162
- const checkpoint = this.getCheckpoint(options.checkpointId);
163
- if (!checkpoint) {
164
- return {
165
- success: false,
166
- checkpoint: {},
167
- restoredFiles: [],
168
- restoredConversation: false,
169
- errors: [`Checkpoint not found: ${options.checkpointId}`],
170
- };
171
- }
172
- const errors = [];
173
- const restoredFiles = [];
174
- let restoredConversation = false;
175
- // Restore files if requested
176
- if (options.mode === 'code-only' || options.mode === 'both') {
177
- for (const fileSnapshot of checkpoint.files) {
178
- const fullPath = fileSnapshot.path.startsWith('/')
179
- ? fileSnapshot.path
180
- : join(workingDir, fileSnapshot.path);
181
- if (writeFileSafe(fullPath, fileSnapshot.content)) {
182
- restoredFiles.push(fileSnapshot.path);
183
- }
184
- else {
185
- errors.push(`Failed to restore: ${fileSnapshot.path}`);
186
- }
187
- }
188
- }
189
- // Conversation restoration is handled by the caller (session manager)
190
- if (options.mode === 'conversation-only' || options.mode === 'both') {
191
- if (checkpoint.conversation) {
192
- restoredConversation = true;
193
- }
194
- }
195
- return {
196
- success: errors.length === 0,
197
- checkpoint,
198
- restoredFiles,
199
- restoredConversation,
200
- errors,
201
- };
202
- },
203
- cleanupOldCheckpoints() {
204
- if (!existsSync(CHECKPOINT_DIR)) {
205
- return;
206
- }
207
- const now = Date.now();
208
- const maxAge = MAX_CHECKPOINT_AGE_DAYS * 24 * 60 * 60 * 1000;
209
- try {
210
- const sessions = readdirSync(CHECKPOINT_DIR);
211
- for (const session of sessions) {
212
- const sessionDir = join(CHECKPOINT_DIR, session);
213
- const files = readdirSync(sessionDir)
214
- .filter(f => f.endsWith('.json'))
215
- .map(f => ({
216
- name: f,
217
- path: join(sessionDir, f),
218
- mtime: statSync(join(sessionDir, f)).mtimeMs,
219
- }))
220
- .sort((a, b) => b.mtime - a.mtime);
221
- // Remove old checkpoints beyond max count
222
- for (let i = MAX_CHECKPOINTS; i < files.length; i++) {
223
- try {
224
- unlinkSync(files[i].path);
225
- }
226
- catch {
227
- // Ignore deletion errors
228
- }
229
- }
230
- // Remove checkpoints older than max age
231
- for (const file of files) {
232
- if (now - file.mtime > maxAge) {
233
- try {
234
- unlinkSync(file.path);
235
- }
236
- catch {
237
- // Ignore deletion errors
238
- }
239
- }
240
- }
241
- }
242
- }
243
- catch {
244
- // Ignore cleanup errors
245
- }
246
- },
247
- };
248
- }
249
- /**
250
- * Format checkpoint for display
251
- */
252
- export function formatCheckpointForDisplay(checkpoint) {
253
- const date = new Date(checkpoint.timestamp);
254
- const timeStr = date.toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit' });
255
- const dateStr = date.toLocaleDateString('en-US', { month: 'short', day: 'numeric' });
256
- const filesStr = checkpoint.files.length > 0
257
- ? `${checkpoint.files.length} file${checkpoint.files.length > 1 ? 's' : ''}`
258
- : 'no files';
259
- const triggerIcon = {
260
- 'auto': '⚙',
261
- 'manual': '📌',
262
- 'pre-edit': '✏️',
263
- 'pre-write': '📝',
264
- 'pre-delete': '🗑️',
265
- }[checkpoint.trigger] || '•';
266
- return `${triggerIcon} ${dateStr} ${timeStr} - ${checkpoint.description} (${filesStr})`;
267
- }
268
- /**
269
- * Global checkpoint manager instance
270
- */
271
- let globalCheckpointManager = null;
272
- export function getCheckpointManager(workingDir) {
273
- if (!globalCheckpointManager || workingDir) {
274
- globalCheckpointManager = createCheckpointManager(workingDir ?? process.cwd());
275
- }
276
- return globalCheckpointManager;
277
- }
278
- //# sourceMappingURL=checkpoint.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"checkpoint.js","sourceRoot":"","sources":["../../src/core/checkpoint.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAChH,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAY,QAAQ,EAAE,MAAM,WAAW,CAAC;AAC9D,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,MAAM,cAAc,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,WAAW,EAAE,aAAa,CAAC,CAAC;AACnE,MAAM,eAAe,GAAG,EAAE,CAAC,CAAC,uCAAuC;AACnE,MAAM,uBAAuB,GAAG,CAAC,CAAC;AA+DlC;;GAEG;AACH,SAAS,WAAW,CAAC,OAAe;IAClC,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AACzE,CAAC;AAED;;GAEG;AACH,SAAS,oBAAoB;IAC3B,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;IAC1C,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACtD,OAAO,MAAM,SAAS,IAAI,MAAM,EAAE,CAAC;AACrC,CAAC;AAED;;GAEG;AACH,SAAS,uBAAuB,CAAC,SAAiB;IAChD,MAAM,SAAS,GAAG,SAAS,CAAC,OAAO,CAAC,iBAAiB,EAAE,GAAG,CAAC,CAAC;IAC5D,OAAO,IAAI,CAAC,cAAc,EAAE,SAAS,CAAC,CAAC;AACzC,CAAC;AAED;;GAEG;AACH,SAAS,YAAY,CAAC,QAAgB;IACpC,IAAI,CAAC;QACH,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC1B,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,KAAK,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC;QACjC,MAAM,OAAO,GAAG,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QAC/C,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC;IAC3C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;GAEG;AACH,SAAS,aAAa,CAAC,QAAgB,EAAE,OAAe;IACtD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;QAC9B,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACpC,aAAa,CAAC,QAAQ,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;QACzC,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,uBAAuB,CAAC,UAAkB;IACxD,qCAAqC;IACrC,SAAS,CAAC,cAAc,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAE/C,OAAO;QACL,KAAK,CAAC,gBAAgB,CAAC,OAAgC;YACrD,MAAM,YAAY,GAAG,oBAAoB,EAAE,CAAC;YAC5C,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YAE7B,sDAAsD;YACtD,MAAM,eAAe,GAAG,OAAO,CAAC,KAAK;gBACnC,CAAC,OAAO,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YAElE,MAAM,aAAa,GAAmB,EAAE,CAAC;YACzC,KAAK,MAAM,QAAQ,IAAI,eAAe,EAAE,CAAC;gBACvC,MAAM,QAAQ,GAAG,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;gBAClF,MAAM,QAAQ,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;gBACxC,IAAI,QAAQ,EAAE,CAAC;oBACb,aAAa,CAAC,IAAI,CAAC;wBACjB,IAAI,EAAE,QAAQ,CAAC,UAAU,EAAE,QAAQ,CAAC,IAAI,QAAQ;wBAChD,OAAO,EAAE,QAAQ,CAAC,OAAO;wBACzB,IAAI,EAAE,WAAW,CAAC,QAAQ,CAAC,OAAO,CAAC;wBACnC,KAAK,EAAE,QAAQ,CAAC,KAAK;qBACtB,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;YAED,MAAM,UAAU,GAAe;gBAC7B,EAAE,EAAE,YAAY;gBAChB,SAAS;gBACT,SAAS,EAAE,OAAO,CAAC,SAAS;gBAC5B,WAAW,EAAE,OAAO,CAAC,WAAW;gBAChC,OAAO,EAAE,OAAO,CAAC,OAAO;gBACxB,KAAK,EAAE,aAAa;gBACpB,YAAY,EAAE,OAAO,CAAC,YAAY;gBAClC,QAAQ,EAAE,OAAO,CAAC,QAAQ,IAAI,EAAE;aACjC,CAAC;YAEF,kBAAkB;YAClB,MAAM,UAAU,GAAG,uBAAuB,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;YAC9D,SAAS,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YAC3C,MAAM,cAAc,GAAG,IAAI,CAAC,UAAU,EAAE,GAAG,YAAY,OAAO,CAAC,CAAC;YAChE,aAAa,CAAC,cAAc,EAAE,IAAI,CAAC,SAAS,CAAC,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;YAEnE,0BAA0B;YAC1B,IAAI,CAAC,qBAAqB,EAAE,CAAC;YAE7B,OAAO,UAAU,CAAC;QACpB,CAAC;QAED,cAAc,CAAC,SAAiB;YAC9B,MAAM,UAAU,GAAG,uBAAuB,CAAC,SAAS,CAAC,CAAC;YACtD,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;gBAC5B,OAAO,EAAE,CAAC;YACZ,CAAC;YAED,MAAM,WAAW,GAAiB,EAAE,CAAC;YACrC,IAAI,CAAC;gBACH,MAAM,KAAK,GAAG,WAAW,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;gBACvE,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;oBACzB,IAAI,CAAC;wBACH,MAAM,OAAO,GAAG,YAAY,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,CAAC;wBAC7D,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAe,CAAC;wBACrD,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;oBAC/B,CAAC;oBAAC,MAAM,CAAC;wBACP,gCAAgC;oBAClC,CAAC;gBACH,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,EAAE,CAAC;YACZ,CAAC;YAED,8CAA8C;YAC9C,OAAO,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC;QAC/D,CAAC;QAED,aAAa,CAAC,EAAU;YACtB,oDAAoD;YACpD,IAAI,CAAC,UAAU,CAAC,cAAc,CAAC,EAAE,CAAC;gBAChC,OAAO,IAAI,CAAC;YACd,CAAC;YAED,IAAI,CAAC;gBACH,MAAM,QAAQ,GAAG,WAAW,CAAC,cAAc,CAAC,CAAC;gBAC7C,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;oBAC/B,MAAM,cAAc,GAAG,IAAI,CAAC,cAAc,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC;oBACnE,IAAI,UAAU,CAAC,cAAc,CAAC,EAAE,CAAC;wBAC/B,MAAM,OAAO,GAAG,YAAY,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC;wBACrD,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAe,CAAC;oBAC3C,CAAC;gBACH,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,IAAI,CAAC;YACd,CAAC;YAED,OAAO,IAAI,CAAC;QACd,CAAC;QAED,KAAK,CAAC,MAAM,CAAC,OAAsB;YACjC,MAAM,UAAU,GAAG,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;YAC5D,IAAI,CAAC,UAAU,EAAE,CAAC;gBAChB,OAAO;oBACL,OAAO,EAAE,KAAK;oBACd,UAAU,EAAE,EAAgB;oBAC5B,aAAa,EAAE,EAAE;oBACjB,oBAAoB,EAAE,KAAK;oBAC3B,MAAM,EAAE,CAAC,yBAAyB,OAAO,CAAC,YAAY,EAAE,CAAC;iBAC1D,CAAC;YACJ,CAAC;YAED,MAAM,MAAM,GAAa,EAAE,CAAC;YAC5B,MAAM,aAAa,GAAa,EAAE,CAAC;YACnC,IAAI,oBAAoB,GAAG,KAAK,CAAC;YAEjC,6BAA6B;YAC7B,IAAI,OAAO,CAAC,IAAI,KAAK,WAAW,IAAI,OAAO,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;gBAC5D,KAAK,MAAM,YAAY,IAAI,UAAU,CAAC,KAAK,EAAE,CAAC;oBAC5C,MAAM,QAAQ,GAAG,YAAY,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;wBAChD,CAAC,CAAC,YAAY,CAAC,IAAI;wBACnB,CAAC,CAAC,IAAI,CAAC,UAAU,EAAE,YAAY,CAAC,IAAI,CAAC,CAAC;oBAExC,IAAI,aAAa,CAAC,QAAQ,EAAE,YAAY,CAAC,OAAO,CAAC,EAAE,CAAC;wBAClD,aAAa,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;oBACxC,CAAC;yBAAM,CAAC;wBACN,MAAM,CAAC,IAAI,CAAC,sBAAsB,YAAY,CAAC,IAAI,EAAE,CAAC,CAAC;oBACzD,CAAC;gBACH,CAAC;YACH,CAAC;YAED,sEAAsE;YACtE,IAAI,OAAO,CAAC,IAAI,KAAK,mBAAmB,IAAI,OAAO,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;gBACpE,IAAI,UAAU,CAAC,YAAY,EAAE,CAAC;oBAC5B,oBAAoB,GAAG,IAAI,CAAC;gBAC9B,CAAC;YACH,CAAC;YAED,OAAO;gBACL,OAAO,EAAE,MAAM,CAAC,MAAM,KAAK,CAAC;gBAC5B,UAAU;gBACV,aAAa;gBACb,oBAAoB;gBACpB,MAAM;aACP,CAAC;QACJ,CAAC;QAED,qBAAqB;YACnB,IAAI,CAAC,UAAU,CAAC,cAAc,CAAC,EAAE,CAAC;gBAChC,OAAO;YACT,CAAC;YAED,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YACvB,MAAM,MAAM,GAAG,uBAAuB,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;YAE7D,IAAI,CAAC;gBACH,MAAM,QAAQ,GAAG,WAAW,CAAC,cAAc,CAAC,CAAC;gBAC7C,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;oBAC/B,MAAM,UAAU,GAAG,IAAI,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC;oBACjD,MAAM,KAAK,GAAG,WAAW,CAAC,UAAU,CAAC;yBAClC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;yBAChC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;wBACT,IAAI,EAAE,CAAC;wBACP,IAAI,EAAE,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC;wBACzB,KAAK,EAAE,QAAQ,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO;qBAC7C,CAAC,CAAC;yBACF,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;oBAErC,0CAA0C;oBAC1C,KAAK,IAAI,CAAC,GAAG,eAAe,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;wBACpD,IAAI,CAAC;4BACH,UAAU,CAAC,KAAK,CAAC,CAAC,CAAE,CAAC,IAAI,CAAC,CAAC;wBAC7B,CAAC;wBAAC,MAAM,CAAC;4BACP,yBAAyB;wBAC3B,CAAC;oBACH,CAAC;oBAED,wCAAwC;oBACxC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;wBACzB,IAAI,GAAG,GAAG,IAAI,CAAC,KAAK,GAAG,MAAM,EAAE,CAAC;4BAC9B,IAAI,CAAC;gCACH,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;4BACxB,CAAC;4BAAC,MAAM,CAAC;gCACP,yBAAyB;4BAC3B,CAAC;wBACH,CAAC;oBACH,CAAC;gBACH,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,wBAAwB;YAC1B,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,0BAA0B,CAAC,UAAsB;IAC/D,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;IAC5C,MAAM,OAAO,GAAG,IAAI,CAAC,kBAAkB,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC;IACzF,MAAM,OAAO,GAAG,IAAI,CAAC,kBAAkB,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC,CAAC;IAErF,MAAM,QAAQ,GAAG,UAAU,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC;QAC1C,CAAC,CAAC,GAAG,UAAU,CAAC,KAAK,CAAC,MAAM,QAAQ,UAAU,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QAC5E,CAAC,CAAC,UAAU,CAAC;IAEf,MAAM,WAAW,GAAG;QAClB,MAAM,EAAE,GAAG;QACX,QAAQ,EAAE,IAAI;QACd,UAAU,EAAE,IAAI;QAChB,WAAW,EAAE,IAAI;QACjB,YAAY,EAAE,KAAK;KACpB,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,GAAG,CAAC;IAE7B,OAAO,GAAG,WAAW,IAAI,OAAO,IAAI,OAAO,MAAM,UAAU,CAAC,WAAW,KAAK,QAAQ,GAAG,CAAC;AAC1F,CAAC;AAED;;GAEG;AACH,IAAI,uBAAuB,GAA6B,IAAI,CAAC;AAE7D,MAAM,UAAU,oBAAoB,CAAC,UAAmB;IACtD,IAAI,CAAC,uBAAuB,IAAI,UAAU,EAAE,CAAC;QAC3C,uBAAuB,GAAG,uBAAuB,CAAC,UAAU,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IACjF,CAAC;IACD,OAAO,uBAAuB,CAAC;AACjC,CAAC"}
@@ -1,87 +0,0 @@
1
- /**
2
- * Cost Tracker - Erosolar-CLI Style
3
- *
4
- * Tracks token usage and API costs across the session.
5
- * Provides real-time cost display and detailed breakdowns.
6
- *
7
- * Features:
8
- * - Real-time token counting (input/output)
9
- * - Cost estimation based on model pricing
10
- * - Session and lifetime cost tracking
11
- * - Detailed breakdown by model and request
12
- */
13
- export interface TokenUsage {
14
- inputTokens: number;
15
- outputTokens: number;
16
- totalTokens: number;
17
- }
18
- export interface RequestCost {
19
- timestamp: number;
20
- model: string;
21
- inputTokens: number;
22
- outputTokens: number;
23
- inputCost: number;
24
- outputCost: number;
25
- totalCost: number;
26
- requestType: 'chat' | 'tool' | 'embedding';
27
- }
28
- export interface SessionUsage {
29
- sessionId: string;
30
- startTime: number;
31
- requests: RequestCost[];
32
- totalInputTokens: number;
33
- totalOutputTokens: number;
34
- totalCost: number;
35
- }
36
- export interface LifetimeUsage {
37
- totalInputTokens: number;
38
- totalOutputTokens: number;
39
- totalCost: number;
40
- sessions: number;
41
- firstUse: number;
42
- lastUse: number;
43
- }
44
- /**
45
- * Cost Tracker class
46
- */
47
- export declare class CostTracker {
48
- private sessionId;
49
- private startTime;
50
- private requests;
51
- constructor(sessionId?: string);
52
- /**
53
- * Record a request's token usage
54
- */
55
- recordUsage(model: string, inputTokens: number, outputTokens: number, requestType?: 'chat' | 'tool' | 'embedding'): RequestCost;
56
- /**
57
- * Get session usage summary
58
- */
59
- getSessionUsage(): SessionUsage;
60
- /**
61
- * Get lifetime usage
62
- */
63
- getLifetimeUsage(): LifetimeUsage;
64
- /**
65
- * Save request to lifetime usage
66
- */
67
- private saveToLifetime;
68
- /**
69
- * Format session usage for display
70
- */
71
- formatSessionUsage(): string;
72
- /**
73
- * Format cost breakdown for display
74
- */
75
- formatCostBreakdown(): string;
76
- /**
77
- * Format compact cost display for status bar
78
- */
79
- formatCompactCost(): string;
80
- /**
81
- * Reset session tracking
82
- */
83
- reset(): void;
84
- }
85
- export declare function getCostTracker(sessionId?: string): CostTracker;
86
- export declare function resetCostTracker(): void;
87
- //# sourceMappingURL=costTracker.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"costTracker.d.ts","sourceRoot":"","sources":["../../src/core/costTracker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AA2CH,MAAM,WAAW,UAAU;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,WAAW,CAAC;CAC5C;AAED,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,gBAAgB,EAAE,MAAM,CAAC;IACzB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,aAAa;IAC5B,gBAAgB,EAAE,MAAM,CAAC;IACzB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CACjB;AAuCD;;GAEG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,QAAQ,CAAqB;gBAEzB,SAAS,CAAC,EAAE,MAAM;IAK9B;;OAEG;IACH,WAAW,CACT,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,MAAM,EACpB,WAAW,GAAE,MAAM,GAAG,MAAM,GAAG,WAAoB,GAClD,WAAW;IAoBd;;OAEG;IACH,eAAe,IAAI,YAAY;IAqB/B;;OAEG;IACH,gBAAgB,IAAI,aAAa;IA2BjC;;OAEG;IACH,OAAO,CAAC,cAAc;IAgBtB;;OAEG;IACH,kBAAkB,IAAI,MAAM;IA0B5B;;OAEG;IACH,mBAAmB,IAAI,MAAM;IA2C7B;;OAEG;IACH,iBAAiB,IAAI,MAAM;IAM3B;;OAEG;IACH,KAAK,IAAI,IAAI;CAId;AA2BD,wBAAgB,cAAc,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,WAAW,CAK9D;AAED,wBAAgB,gBAAgB,IAAI,IAAI,CAEvC"}
@@ -1,285 +0,0 @@
1
- /**
2
- * Cost Tracker - Erosolar-CLI Style
3
- *
4
- * Tracks token usage and API costs across the session.
5
- * Provides real-time cost display and detailed breakdowns.
6
- *
7
- * Features:
8
- * - Real-time token counting (input/output)
9
- * - Cost estimation based on model pricing
10
- * - Session and lifetime cost tracking
11
- * - Detailed breakdown by model and request
12
- */
13
- import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'node:fs';
14
- import { homedir } from 'node:os';
15
- import { join } from 'node:path';
16
- const USAGE_FILE = join(homedir(), '.erosolar', 'usage.json');
17
- /**
18
- * Model pricing (per 1M tokens)
19
- */
20
- const MODEL_PRICING = {
21
- // Anthropic
22
- 'claude-sonnet-4-5-20250929': { input: 3.0, output: 15.0 },
23
- 'claude-opus-4-20250514': { input: 15.0, output: 75.0 },
24
- 'claude-haiku-4-5-20251001': { input: 0.25, output: 1.25 },
25
- // OpenAI
26
- 'gpt-5.1-codex-mini': { input: 0.15, output: 0.60 },
27
- 'gpt-5.1-codex': { input: 2.5, output: 10.0 },
28
- 'gpt-5.1': { input: 5.0, output: 15.0 },
29
- 'gpt-5-pro': { input: 15.0, output: 60.0 },
30
- 'gpt-5-mini': { input: 0.3, output: 1.2 },
31
- 'gpt-5-nano': { input: 0.075, output: 0.30 },
32
- // Google
33
- 'gemini-2.5-pro': { input: 1.25, output: 5.0 },
34
- 'gemini-2.5-flash': { input: 0.075, output: 0.30 },
35
- // xAI
36
- 'grok-4': { input: 5.0, output: 15.0 },
37
- 'grok-4-1-fast-reasoning': { input: 2.0, output: 10.0 },
38
- 'grok-4-1-fast-non-reasoning': { input: 0.5, output: 2.0 },
39
- 'grok-code-fast-1': { input: 0.5, output: 2.0 },
40
- // DeepSeek
41
- 'deepseek-reasoner': { input: 0.55, output: 2.19 },
42
- 'deepseek-chat': { input: 0.27, output: 1.10 },
43
- // Default for unknown models
44
- 'default': { input: 1.0, output: 3.0 },
45
- };
46
- /**
47
- * Get pricing for a model
48
- */
49
- function getModelPricing(model) {
50
- // Try exact match first
51
- if (MODEL_PRICING[model]) {
52
- return MODEL_PRICING[model];
53
- }
54
- // Try prefix match (for versioned models)
55
- for (const [key, pricing] of Object.entries(MODEL_PRICING)) {
56
- if (model.startsWith(key) || key.startsWith(model)) {
57
- return pricing;
58
- }
59
- }
60
- return MODEL_PRICING['default'];
61
- }
62
- /**
63
- * Calculate cost for tokens
64
- */
65
- function calculateCost(model, inputTokens, outputTokens) {
66
- const pricing = getModelPricing(model);
67
- const inputCost = (inputTokens / 1_000_000) * pricing.input;
68
- const outputCost = (outputTokens / 1_000_000) * pricing.output;
69
- return {
70
- inputCost,
71
- outputCost,
72
- totalCost: inputCost + outputCost,
73
- };
74
- }
75
- /**
76
- * Cost Tracker class
77
- */
78
- export class CostTracker {
79
- sessionId;
80
- startTime;
81
- requests = [];
82
- constructor(sessionId) {
83
- this.sessionId = sessionId ?? `session_${Date.now().toString(36)}`;
84
- this.startTime = Date.now();
85
- }
86
- /**
87
- * Record a request's token usage
88
- */
89
- recordUsage(model, inputTokens, outputTokens, requestType = 'chat') {
90
- const costs = calculateCost(model, inputTokens, outputTokens);
91
- const request = {
92
- timestamp: Date.now(),
93
- model,
94
- inputTokens,
95
- outputTokens,
96
- inputCost: costs.inputCost,
97
- outputCost: costs.outputCost,
98
- totalCost: costs.totalCost,
99
- requestType,
100
- };
101
- this.requests.push(request);
102
- this.saveToLifetime(request);
103
- return request;
104
- }
105
- /**
106
- * Get session usage summary
107
- */
108
- getSessionUsage() {
109
- let totalInputTokens = 0;
110
- let totalOutputTokens = 0;
111
- let totalCost = 0;
112
- for (const req of this.requests) {
113
- totalInputTokens += req.inputTokens;
114
- totalOutputTokens += req.outputTokens;
115
- totalCost += req.totalCost;
116
- }
117
- return {
118
- sessionId: this.sessionId,
119
- startTime: this.startTime,
120
- requests: [...this.requests],
121
- totalInputTokens,
122
- totalOutputTokens,
123
- totalCost,
124
- };
125
- }
126
- /**
127
- * Get lifetime usage
128
- */
129
- getLifetimeUsage() {
130
- try {
131
- if (!existsSync(USAGE_FILE)) {
132
- return {
133
- totalInputTokens: 0,
134
- totalOutputTokens: 0,
135
- totalCost: 0,
136
- sessions: 0,
137
- firstUse: Date.now(),
138
- lastUse: Date.now(),
139
- };
140
- }
141
- const data = JSON.parse(readFileSync(USAGE_FILE, 'utf8'));
142
- return data;
143
- }
144
- catch {
145
- return {
146
- totalInputTokens: 0,
147
- totalOutputTokens: 0,
148
- totalCost: 0,
149
- sessions: 0,
150
- firstUse: Date.now(),
151
- lastUse: Date.now(),
152
- };
153
- }
154
- }
155
- /**
156
- * Save request to lifetime usage
157
- */
158
- saveToLifetime(request) {
159
- try {
160
- const usage = this.getLifetimeUsage();
161
- usage.totalInputTokens += request.inputTokens;
162
- usage.totalOutputTokens += request.outputTokens;
163
- usage.totalCost += request.totalCost;
164
- usage.lastUse = Date.now();
165
- mkdirSync(join(homedir(), '.erosolar'), { recursive: true });
166
- writeFileSync(USAGE_FILE, JSON.stringify(usage, null, 2));
167
- }
168
- catch {
169
- // Ignore save errors
170
- }
171
- }
172
- /**
173
- * Format session usage for display
174
- */
175
- formatSessionUsage() {
176
- const usage = this.getSessionUsage();
177
- const duration = Math.floor((Date.now() - this.startTime) / 1000);
178
- const mins = Math.floor(duration / 60);
179
- const secs = duration % 60;
180
- const lines = [
181
- 'Session Usage:',
182
- '',
183
- ` Duration: ${mins}m ${secs}s`,
184
- ` Requests: ${usage.requests.length}`,
185
- '',
186
- ' Tokens:',
187
- ` Input: ${formatNumber(usage.totalInputTokens)}`,
188
- ` Output: ${formatNumber(usage.totalOutputTokens)}`,
189
- ` Total: ${formatNumber(usage.totalInputTokens + usage.totalOutputTokens)}`,
190
- '',
191
- ' Cost:',
192
- ` Input: $${usage.requests.reduce((sum, r) => sum + r.inputCost, 0).toFixed(4)}`,
193
- ` Output: $${usage.requests.reduce((sum, r) => sum + r.outputCost, 0).toFixed(4)}`,
194
- ` Total: $${usage.totalCost.toFixed(4)}`,
195
- ];
196
- return lines.join('\n');
197
- }
198
- /**
199
- * Format cost breakdown for display
200
- */
201
- formatCostBreakdown() {
202
- const usage = this.getSessionUsage();
203
- const lifetime = this.getLifetimeUsage();
204
- // Group by model
205
- const byModel = new Map();
206
- for (const req of usage.requests) {
207
- const existing = byModel.get(req.model) ?? { input: 0, output: 0, cost: 0, count: 0 };
208
- existing.input += req.inputTokens;
209
- existing.output += req.outputTokens;
210
- existing.cost += req.totalCost;
211
- existing.count += 1;
212
- byModel.set(req.model, existing);
213
- }
214
- const lines = [
215
- 'Cost Breakdown:',
216
- '',
217
- '┌─ Session ─────────────────────────────────────┐',
218
- `│ Total Cost: $${usage.totalCost.toFixed(4)}`,
219
- `│ Tokens: ${formatNumber(usage.totalInputTokens + usage.totalOutputTokens)} (${formatNumber(usage.totalInputTokens)} in / ${formatNumber(usage.totalOutputTokens)} out)`,
220
- '│',
221
- ];
222
- if (byModel.size > 0) {
223
- lines.push('│ By Model:');
224
- for (const [model, data] of byModel) {
225
- const shortModel = model.length > 25 ? `${model.slice(0, 22)}...` : model;
226
- lines.push(`│ ${shortModel}: $${data.cost.toFixed(4)} (${data.count} req)`);
227
- }
228
- }
229
- lines.push('└───────────────────────────────────────────────┘');
230
- lines.push('');
231
- lines.push('┌─ Lifetime ────────────────────────────────────┐');
232
- lines.push(`│ Total Cost: $${lifetime.totalCost.toFixed(4)}`);
233
- lines.push(`│ Total Tokens: ${formatNumber(lifetime.totalInputTokens + lifetime.totalOutputTokens)}`);
234
- lines.push(`│ Sessions: ${lifetime.sessions}`);
235
- lines.push('└───────────────────────────────────────────────┘');
236
- return lines.join('\n');
237
- }
238
- /**
239
- * Format compact cost display for status bar
240
- */
241
- formatCompactCost() {
242
- const usage = this.getSessionUsage();
243
- const totalTokens = usage.totalInputTokens + usage.totalOutputTokens;
244
- return `$${usage.totalCost.toFixed(3)} · ${formatCompactNumber(totalTokens)} tok`;
245
- }
246
- /**
247
- * Reset session tracking
248
- */
249
- reset() {
250
- this.requests = [];
251
- this.startTime = Date.now();
252
- }
253
- }
254
- /**
255
- * Format number with commas
256
- */
257
- function formatNumber(n) {
258
- return n.toLocaleString('en-US');
259
- }
260
- /**
261
- * Format number compactly (1.2k, 3.5M)
262
- */
263
- function formatCompactNumber(n) {
264
- if (n >= 1_000_000) {
265
- return `${(n / 1_000_000).toFixed(1)}M`;
266
- }
267
- if (n >= 1_000) {
268
- return `${(n / 1_000).toFixed(1)}k`;
269
- }
270
- return n.toString();
271
- }
272
- /**
273
- * Global cost tracker instance
274
- */
275
- let globalCostTracker = null;
276
- export function getCostTracker(sessionId) {
277
- if (!globalCostTracker) {
278
- globalCostTracker = new CostTracker(sessionId);
279
- }
280
- return globalCostTracker;
281
- }
282
- export function resetCostTracker() {
283
- globalCostTracker = null;
284
- }
285
- //# sourceMappingURL=costTracker.js.map