erosolar-cli 2.1.202 → 2.1.204
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.
- package/agents/erosolar-code.rules.json +8 -13
- package/agents/general.rules.json +20 -33
- package/dist/core/agentOrchestrator.d.ts +19 -5
- package/dist/core/agentOrchestrator.d.ts.map +1 -1
- package/dist/core/agentOrchestrator.js +221 -245
- package/dist/core/agentOrchestrator.js.map +1 -1
- package/dist/core/errors/errorTypes.d.ts +0 -6
- package/dist/core/errors/errorTypes.d.ts.map +1 -1
- package/dist/core/errors/errorTypes.js +0 -26
- package/dist/core/errors/errorTypes.js.map +1 -1
- package/dist/core/errors/safetyValidator.d.ts +1 -40
- package/dist/core/errors/safetyValidator.d.ts.map +1 -1
- package/dist/core/errors/safetyValidator.js +1 -145
- package/dist/core/errors/safetyValidator.js.map +1 -1
- package/dist/core/reliabilityPrompt.d.ts.map +1 -1
- package/dist/core/reliabilityPrompt.js +10 -11
- package/dist/core/reliabilityPrompt.js.map +1 -1
- package/dist/providers/openaiResponsesProvider.d.ts +0 -5
- package/dist/providers/openaiResponsesProvider.d.ts.map +1 -1
- package/dist/providers/openaiResponsesProvider.js +1 -38
- package/dist/providers/openaiResponsesProvider.js.map +1 -1
- package/dist/shell/interactiveShell.d.ts +0 -3
- package/dist/shell/interactiveShell.d.ts.map +1 -1
- package/dist/shell/interactiveShell.js +47 -73
- package/dist/shell/interactiveShell.js.map +1 -1
- package/dist/ui/PromptController.d.ts +1 -0
- package/dist/ui/PromptController.d.ts.map +1 -1
- package/dist/ui/PromptController.js +3 -0
- package/dist/ui/PromptController.js.map +1 -1
- package/dist/ui/UnifiedUIRenderer.d.ts +2 -0
- package/dist/ui/UnifiedUIRenderer.d.ts.map +1 -1
- package/dist/ui/UnifiedUIRenderer.js +8 -1
- package/dist/ui/UnifiedUIRenderer.js.map +1 -1
- package/package.json +1 -1
- package/dist/core/LazyLoader.d.ts +0 -129
- package/dist/core/LazyLoader.d.ts.map +0 -1
- package/dist/core/LazyLoader.js +0 -240
- package/dist/core/LazyLoader.js.map +0 -1
- package/dist/core/alphaZeroOrchestrator.d.ts +0 -140
- package/dist/core/alphaZeroOrchestrator.d.ts.map +0 -1
- package/dist/core/alphaZeroOrchestrator.js +0 -418
- package/dist/core/alphaZeroOrchestrator.js.map +0 -1
- package/dist/core/checkpoint.d.ts +0 -76
- package/dist/core/checkpoint.d.ts.map +0 -1
- package/dist/core/checkpoint.js +0 -278
- package/dist/core/checkpoint.js.map +0 -1
- package/dist/core/costTracker.d.ts +0 -87
- package/dist/core/costTracker.d.ts.map +0 -1
- package/dist/core/costTracker.js +0 -285
- package/dist/core/costTracker.js.map +0 -1
- package/dist/core/errors/errorUtils.d.ts +0 -87
- package/dist/core/errors/errorUtils.d.ts.map +0 -1
- package/dist/core/errors/errorUtils.js +0 -158
- package/dist/core/errors/errorUtils.js.map +0 -1
- package/dist/core/errors/promptBlockErrors.d.ts +0 -9
- package/dist/core/errors/promptBlockErrors.d.ts.map +0 -1
- package/dist/core/errors/promptBlockErrors.js +0 -54
- package/dist/core/errors/promptBlockErrors.js.map +0 -1
- package/dist/core/isolatedVerifier.d.ts +0 -40
- package/dist/core/isolatedVerifier.d.ts.map +0 -1
- package/dist/core/isolatedVerifier.js +0 -129
- package/dist/core/isolatedVerifier.js.map +0 -1
- package/dist/core/responseVerifier.d.ts +0 -98
- package/dist/core/responseVerifier.d.ts.map +0 -1
- package/dist/core/responseVerifier.js +0 -509
- package/dist/core/responseVerifier.js.map +0 -1
- package/dist/core/securityAssessment.d.ts +0 -91
- package/dist/core/securityAssessment.d.ts.map +0 -1
- package/dist/core/securityAssessment.js +0 -580
- package/dist/core/securityAssessment.js.map +0 -1
- package/dist/core/verification.d.ts +0 -137
- package/dist/core/verification.d.ts.map +0 -1
- package/dist/core/verification.js +0 -323
- package/dist/core/verification.js.map +0 -1
package/dist/core/checkpoint.js
DELETED
|
@@ -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":"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"}
|
|
@@ -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"}
|
package/dist/core/costTracker.js
DELETED
|
@@ -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
|