codehere 0.2.1 → 0.3.0-rc.1
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/README.md +88 -68
- package/dist/domain/entities/task.js +4 -4
- package/dist/error-handler.js +4 -9
- package/dist/index.js +253 -1219
- package/dist/infrastructure/config/product-context.js +7 -6
- package/dist/infrastructure/hooks/claude-sdk-hook.js +335 -63
- package/dist/infrastructure/observability/execution-tracer.js +11 -6
- package/dist/infrastructure/orchestration/agent-adapter.js +13 -0
- package/dist/infrastructure/orchestration/agent-installer.js +101 -0
- package/dist/infrastructure/orchestration/agents-config-seed.js +56 -0
- package/dist/infrastructure/orchestration/aider-adapter.js +319 -0
- package/dist/infrastructure/orchestration/artifacts-extractor.js +175 -0
- package/dist/infrastructure/orchestration/claude-code-adapter.js +352 -0
- package/dist/infrastructure/orchestration/codex-adapter.js +310 -0
- package/dist/infrastructure/orchestration/generic-cli-adapter.js +553 -0
- package/dist/infrastructure/orchestration/opencode-adapter.js +275 -0
- package/dist/infrastructure/orchestration/progress-aggregator.js +189 -0
- package/dist/infrastructure/orchestration/readiness.js +106 -0
- package/dist/infrastructure/orchestration/session-manager.js +272 -0
- package/dist/infrastructure/orchestration/session-persistence.js +109 -0
- package/dist/infrastructure/protocols/mcp-helpers.js +10 -30
- package/dist/infrastructure/protocols/mcp-server-impl.js +359 -21
- package/dist/infrastructure/protocols/ui-page.js +1827 -0
- package/dist/infrastructure/security/file-collection.js +115 -0
- package/dist/infrastructure/security/trust-scorer.js +301 -56
- package/dist/infrastructure/storage/task-repository.js +8 -7
- package/dist/monitoring.js +10 -49
- package/dist/presentation/cli/commands/help-command.js +96 -139
- package/dist/presentation/cli/commands/hook-command.js +17 -24
- package/dist/presentation/cli/commands/report-command.js +59 -72
- package/dist/presentation/cli/commands/setup-command.js +4 -4
- package/dist/presentation/cli/commands/status-command.js +334 -43
- package/dist/presentation/cli/commands/trust-command.js +115 -99
- package/dist/presentation/cli/error-display.js +17 -21
- package/dist/ui.js +17 -12
- package/package.json +35 -67
- package/dist/agents/base.js +0 -101
- package/dist/agents/orchestrator-model-driven.js +0 -141
- package/dist/agents/react-orchestrator-agent.js +0 -54
- package/dist/application/agents/execution-agent.js +0 -508
- package/dist/application/agents/multi-agent-orchestrator.js +0 -295
- package/dist/application/agents/planning-agent.js +0 -433
- package/dist/application/agents/validation-agent.js +0 -317
- package/dist/application/architectures/plan-and-act.js +0 -242
- package/dist/application/index.js +0 -12
- package/dist/application/services/agent-factory.js +0 -28
- package/dist/application/services/dependency-container.js +0 -596
- package/dist/application/services/git-context-service.js +0 -83
- package/dist/application/services/intelligent-router.js +0 -934
- package/dist/application/services/tool-executor-service.js +0 -94
- package/dist/application/use-cases/ask-question-use-case.js +0 -338
- package/dist/application/use-cases/edit-file-use-case.js +0 -830
- package/dist/application/use-cases/explain-file-use-case.js +0 -50
- package/dist/application/use-cases/index-codebase-use-case.js +0 -113
- package/dist/application/use-cases/planning-use-case.js +0 -276
- package/dist/application/use-cases/react-orchestration-use-case.js +0 -329
- package/dist/application/use-cases/reflexion-use-case.js +0 -30
- package/dist/application/workflows/deterministic-workflows.js +0 -189
- package/dist/ast-parser.js +0 -331
- package/dist/cache.js +0 -180
- package/dist/chat.js +0 -251
- package/dist/code-analysis.js +0 -327
- package/dist/context.js +0 -187
- package/dist/docs.js +0 -146
- package/dist/domain/entities/code-chunk.js +0 -6
- package/dist/domain/entities/decision.js +0 -9
- package/dist/domain/entities/edit.js +0 -6
- package/dist/domain/entities/knowledge-node.js +0 -9
- package/dist/domain/entities/knowledge-preservation.js +0 -10
- package/dist/domain/entities/memory.js +0 -6
- package/dist/domain/entities/pattern.js +0 -7
- package/dist/domain/entities/plan.js +0 -6
- package/dist/domain/entities/query.js +0 -6
- package/dist/domain/errors/embeddings-not-found-error.js +0 -13
- package/dist/domain/index.js +0 -19
- package/dist/domain/interfaces/ai-service.interface.js +0 -6
- package/dist/domain/interfaces/code-analyzer.interface.js +0 -6
- package/dist/domain/interfaces/decision-repository.interface.js +0 -9
- package/dist/domain/interfaces/embedding-repository.interface.js +0 -6
- package/dist/domain/interfaces/knowledge-graph-repository.interface.js +0 -9
- package/dist/domain/interfaces/knowledge-preservation-repository.interface.js +0 -8
- package/dist/domain/interfaces/memory-repository.interface.js +0 -6
- package/dist/domain/interfaces/pattern-repository.interface.js +0 -6
- package/dist/domain/interfaces/verification-service.interface.js +0 -6
- package/dist/domain/services/cross-team-pattern-sharing.js +0 -125
- package/dist/domain/services/decision-recorder.js +0 -223
- package/dist/domain/services/decision-retriever.js +0 -133
- package/dist/domain/services/environment-mode-manager.js +0 -22
- package/dist/domain/services/graded-memory-activation.js +0 -69
- package/dist/domain/services/knowledge-access.js +0 -132
- package/dist/domain/services/knowledge-extractor.js +0 -247
- package/dist/domain/services/knowledge-graph-builder.js +0 -268
- package/dist/domain/services/knowledge-graph-query.js +0 -187
- package/dist/domain/services/memory-retriever.js +0 -82
- package/dist/domain/services/memory-synthesizer.js +0 -91
- package/dist/domain/services/pattern-extractor.js +0 -442
- package/dist/domain/services/query-intent-classifier.js +0 -140
- package/dist/domain/services/react-loop.js +0 -186
- package/dist/domain/services/risk-tier-detector.js +0 -78
- package/dist/edit.js +0 -319
- package/dist/embed.js +0 -459
- package/dist/formatter.js +0 -168
- package/dist/git.js +0 -198
- package/dist/infrastructure/ai/cohere-ai-service.js +0 -607
- package/dist/infrastructure/ai/command-r-evaluation.js +0 -206
- package/dist/infrastructure/ai/model-config.js +0 -84
- package/dist/infrastructure/ai/provider-ai-service.js +0 -477
- package/dist/infrastructure/cache/embedding-cache.js +0 -175
- package/dist/infrastructure/cache/query-result-cache.js +0 -66
- package/dist/infrastructure/cache/response-cache.js +0 -48
- package/dist/infrastructure/cache/security-scan-cache.js +0 -47
- package/dist/infrastructure/chunking/ast-code-chunker.js +0 -19
- package/dist/infrastructure/chunking/code-aware-chunker.js +0 -397
- package/dist/infrastructure/context/context-compressor.js +0 -329
- package/dist/infrastructure/context/conversation-context.js +0 -128
- package/dist/infrastructure/context/session-manager.js +0 -94
- package/dist/infrastructure/cost/cost-tracker.js +0 -360
- package/dist/infrastructure/file-scanner/file-scanner.js +0 -106
- package/dist/infrastructure/governance/nist-ai-rmf.js +0 -292
- package/dist/infrastructure/governance/policy-as-code.js +0 -258
- package/dist/infrastructure/governance/prompt-to-code-lineage.js +0 -239
- package/dist/infrastructure/index.js +0 -7
- package/dist/infrastructure/observability/prompt-versioner.js +0 -145
- package/dist/infrastructure/protocols/a2a-metadata.js +0 -137
- package/dist/infrastructure/protocols/a2a-protocol.js +0 -314
- package/dist/infrastructure/protocols/mcp-oauth.js +0 -184
- package/dist/infrastructure/protocols/mcp-server.js +0 -333
- package/dist/infrastructure/protocols/streaming-handler.js +0 -103
- package/dist/infrastructure/providers/cohere-provider.js +0 -444
- package/dist/infrastructure/providers/fake-provider.js +0 -130
- package/dist/infrastructure/providers/local-llm-provider.js +0 -330
- package/dist/infrastructure/providers/model-config.types.js +0 -9
- package/dist/infrastructure/providers/model-provider.interface.js +0 -8
- package/dist/infrastructure/providers/openai-provider.js +0 -413
- package/dist/infrastructure/providers/openrouter-provider.js +0 -399
- package/dist/infrastructure/providers/operation-provider-resolver.js +0 -105
- package/dist/infrastructure/providers/provider-config-loader.js +0 -120
- package/dist/infrastructure/providers/provider-registry.js +0 -88
- package/dist/infrastructure/safety/pattern-detector.js +0 -133
- package/dist/infrastructure/security/ai-sast-scanner.js +0 -290
- package/dist/infrastructure/security/docker-sandbox.js +0 -178
- package/dist/infrastructure/security/enhanced-security-gate.js +0 -151
- package/dist/infrastructure/security/license-scanner.js +0 -167
- package/dist/infrastructure/security/provider-bias-detector.js +0 -164
- package/dist/infrastructure/security/sandbox-executor.js +0 -64
- package/dist/infrastructure/serialization/toon-serializer.js +0 -119
- package/dist/infrastructure/storage/memory-stream-service.js +0 -204
- package/dist/infrastructure/storage/plan-repository.js +0 -96
- package/dist/infrastructure/storage/sqlite-decision-repository.js +0 -232
- package/dist/infrastructure/storage/sqlite-embedding-repository.js +0 -311
- package/dist/infrastructure/storage/sqlite-knowledge-graph-repository.js +0 -417
- package/dist/infrastructure/storage/sqlite-knowledge-preservation-repository.js +0 -230
- package/dist/infrastructure/storage/sqlite-memory-repository.js +0 -229
- package/dist/infrastructure/storage/sqlite-pattern-repository.js +0 -249
- package/dist/infrastructure/storage/task-helpers.js +0 -197
- package/dist/infrastructure/telemetry/telemetry-service.js +0 -167
- package/dist/infrastructure/ux/appropriate-friction.js +0 -213
- package/dist/infrastructure/ux/bi-directional-learning.js +0 -337
- package/dist/infrastructure/ux/capability-boundaries.js +0 -42
- package/dist/infrastructure/ux/comprehensive-formatter.js +0 -117
- package/dist/infrastructure/ux/contextual-feature-discovery.js +0 -10
- package/dist/infrastructure/ux/expectation-management.js +0 -327
- package/dist/infrastructure/ux/feature-discovery.js +0 -14
- package/dist/infrastructure/ux/feedback-prompt.js +0 -45
- package/dist/infrastructure/ux/hitl-validation.js +0 -297
- package/dist/infrastructure/ux/progress-indicator.js +0 -116
- package/dist/infrastructure/ux/progressive-disclosure.js +0 -236
- package/dist/infrastructure/ux/review-checkpoint.js +0 -72
- package/dist/infrastructure/ux/staged-feature-intro.js +0 -24
- package/dist/infrastructure/ux/stream-markdown.js +0 -151
- package/dist/infrastructure/ux/syntax-highlighter.js +0 -91
- package/dist/infrastructure/ux/team-standards.js +0 -196
- package/dist/infrastructure/ux/transparency.js +0 -71
- package/dist/infrastructure/validation/agent-feedback.js +0 -55
- package/dist/infrastructure/validation/agent-validation-helper.js +0 -137
- package/dist/infrastructure/validation/review-handler.js +0 -40
- package/dist/infrastructure/validation/summary-aggregator.js +0 -70
- package/dist/infrastructure/validation/summary-extractor.js +0 -45
- package/dist/infrastructure/validation/trace-summary.js +0 -52
- package/dist/infrastructure/verification/verification-service.js +0 -47
- package/dist/infrastructure/xai/attention-visualizer.js +0 -172
- package/dist/infrastructure/xai/cot-visualizer.js +0 -283
- package/dist/infrastructure/xai/decision-tree-log.js +0 -212
- package/dist/infrastructure/xai/interactive-xai.js +0 -260
- package/dist/infrastructure/xai/uncertainty-quantifier.js +0 -198
- package/dist/intelligent-retrieval.js +0 -272
- package/dist/intent/classifier.js +0 -2
- package/dist/intent/context.js +0 -2
- package/dist/iterative-refinement.js +0 -189
- package/dist/learning.js +0 -232
- package/dist/log.js +0 -31
- package/dist/migrate.js +0 -133
- package/dist/parallel-processor.js +0 -530
- package/dist/planner.js +0 -198
- package/dist/policy.js +0 -26
- package/dist/presentation/cli/commands/ask-command.js +0 -314
- package/dist/presentation/cli/commands/cost-command.js +0 -191
- package/dist/presentation/cli/commands/decision-command.js +0 -207
- package/dist/presentation/cli/commands/docs-command.js +0 -25
- package/dist/presentation/cli/commands/fix-command.js +0 -53
- package/dist/presentation/cli/commands/knowledge-command.js +0 -129
- package/dist/presentation/cli/commands/learning-dashboard-command.js +0 -183
- package/dist/presentation/cli/commands/models-command.js +0 -194
- package/dist/presentation/cli/commands/orchestrate-command.js +0 -207
- package/dist/presentation/cli/commands/plan-command.js +0 -246
- package/dist/presentation/cli/commands/product-command.js +0 -199
- package/dist/presentation/cli/commands/react-command.js +0 -181
- package/dist/presentation/cli/commands/review-command.js +0 -154
- package/dist/presentation/cli/commands/run-command.js +0 -188
- package/dist/presentation/cli/commands/smart-command.js +0 -395
- package/dist/presentation/cli/commands/suggest-command.js +0 -138
- package/dist/presentation/cli/commands/trace-command.js +0 -129
- package/dist/presentation/cli/commands/undo-command.js +0 -150
- package/dist/query-optimizer.js +0 -205
- package/dist/refactor.js +0 -116
- package/dist/review.js +0 -206
- package/dist/search.js +0 -163
- package/dist/session.js +0 -652
- package/dist/task-verification.js +0 -336
- package/dist/testgen.js +0 -166
- package/dist/token-optimizer.js +0 -277
- package/dist/tools/bash.js +0 -213
- package/dist/tools/edit.js +0 -235
- package/dist/tools/executor.js +0 -153
- package/dist/tools/git-tool.js +0 -292
- package/dist/tools/parser.js +0 -158
- package/dist/tools/registry.js +0 -302
- package/dist/tools/search.js +0 -100
- package/dist/types.js +0 -2
- package/dist/utils/check-api-status.js +0 -100
- package/dist/utils/diff-parser.js +0 -162
- package/dist/verification/backup.js +0 -259
- package/dist/verification/compiler.js +0 -264
- package/dist/verification/index.js +0 -273
- package/dist/verification/test-runner.js +0 -379
|
@@ -1,360 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Infrastructure: Cost Tracker
|
|
3
|
-
* Tracks API costs per operation and provides budget alerts
|
|
4
|
-
*
|
|
5
|
-
* IMPORTANT: This is a LOCAL ESTIMATE based on token counts and pricing.
|
|
6
|
-
* It does NOT sync with actual Cohere billing dashboard.
|
|
7
|
-
* Use `codehere cost reset` to reset for new billing period.
|
|
8
|
-
*
|
|
9
|
-
* Clean Architecture: Infrastructure Layer
|
|
10
|
-
* Strategic: Provides cost visibility and budget alerts (local estimate only)
|
|
11
|
-
*/
|
|
12
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';
|
|
13
|
-
import { join, dirname } from 'path';
|
|
14
|
-
import { fileURLToPath } from 'url';
|
|
15
|
-
import initSqlJs from 'sql.js';
|
|
16
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
17
|
-
const __dirname = dirname(__filename);
|
|
18
|
-
// Cohere pricing (as of 2024, update as needed)
|
|
19
|
-
// These are approximate - check Cohere pricing page for exact rates
|
|
20
|
-
const PRICING = {
|
|
21
|
-
'command-r-plus': {
|
|
22
|
-
input: 0.000003, // $3 per 1M input tokens
|
|
23
|
-
output: 0.000015, // $15 per 1M output tokens
|
|
24
|
-
},
|
|
25
|
-
'command-r': {
|
|
26
|
-
input: 0.0000005, // $0.5 per 1M input tokens
|
|
27
|
-
output: 0.0000015, // $1.5 per 1M output tokens
|
|
28
|
-
},
|
|
29
|
-
'embed-english-v3.0': {
|
|
30
|
-
input: 0.0000001, // $0.1 per 1M tokens
|
|
31
|
-
output: 0,
|
|
32
|
-
},
|
|
33
|
-
'rerank-english-v3': {
|
|
34
|
-
input: 0.000001, // $1 per 1M tokens
|
|
35
|
-
output: 0,
|
|
36
|
-
},
|
|
37
|
-
'default': {
|
|
38
|
-
input: 0.000003, // Conservative default
|
|
39
|
-
output: 0.000015,
|
|
40
|
-
},
|
|
41
|
-
};
|
|
42
|
-
export class CostTracker {
|
|
43
|
-
db = null;
|
|
44
|
-
dbPath;
|
|
45
|
-
budgetLimit; // null = no budget limit
|
|
46
|
-
alertThreshold; // Alert at 80% of budget
|
|
47
|
-
// Default budget limit when no override is provided
|
|
48
|
-
static DEFAULT_BUDGET_LIMIT = 2.0;
|
|
49
|
-
constructor(budgetLimit, alertThreshold = 0.8) {
|
|
50
|
-
const agentDir = join(__dirname, '../../..');
|
|
51
|
-
const dataDir = join(agentDir, 'data');
|
|
52
|
-
if (!existsSync(dataDir)) {
|
|
53
|
-
mkdirSync(dataDir, { recursive: true });
|
|
54
|
-
}
|
|
55
|
-
this.dbPath = join(dataDir, 'costs.sqlite');
|
|
56
|
-
// Budget limit priority: explicit parameter > env var > default (2.0)
|
|
57
|
-
if (budgetLimit !== undefined) {
|
|
58
|
-
// Explicit parameter: null means no budget, otherwise use provided value if > 0
|
|
59
|
-
this.budgetLimit = (budgetLimit !== null && budgetLimit > 0) ? budgetLimit : null;
|
|
60
|
-
}
|
|
61
|
-
else {
|
|
62
|
-
// Check env var first
|
|
63
|
-
const envBudget = process.env.COHERE_BUDGET_LIMIT;
|
|
64
|
-
if (envBudget) {
|
|
65
|
-
const parsed = parseFloat(envBudget);
|
|
66
|
-
this.budgetLimit = (parsed > 0) ? parsed : null;
|
|
67
|
-
}
|
|
68
|
-
else {
|
|
69
|
-
// Default to 2.0 when no parameter and no env var
|
|
70
|
-
this.budgetLimit = CostTracker.DEFAULT_BUDGET_LIMIT;
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
this.alertThreshold = alertThreshold;
|
|
74
|
-
}
|
|
75
|
-
async getDb() {
|
|
76
|
-
if (this.db)
|
|
77
|
-
return this.db;
|
|
78
|
-
const SQL = await initSqlJs();
|
|
79
|
-
const dbDir = dirname(this.dbPath);
|
|
80
|
-
if (!existsSync(dbDir)) {
|
|
81
|
-
mkdirSync(dbDir, { recursive: true });
|
|
82
|
-
}
|
|
83
|
-
if (existsSync(this.dbPath)) {
|
|
84
|
-
const buffer = readFileSync(this.dbPath);
|
|
85
|
-
this.db = new SQL.Database(buffer);
|
|
86
|
-
}
|
|
87
|
-
else {
|
|
88
|
-
this.db = new SQL.Database();
|
|
89
|
-
}
|
|
90
|
-
// Initialize schema
|
|
91
|
-
this.db.run(`
|
|
92
|
-
CREATE TABLE IF NOT EXISTS costs (
|
|
93
|
-
id TEXT PRIMARY KEY,
|
|
94
|
-
timestamp INTEGER NOT NULL,
|
|
95
|
-
operation TEXT NOT NULL,
|
|
96
|
-
operation_type TEXT NOT NULL,
|
|
97
|
-
model TEXT,
|
|
98
|
-
input_tokens INTEGER,
|
|
99
|
-
output_tokens INTEGER,
|
|
100
|
-
cost REAL NOT NULL,
|
|
101
|
-
run_id TEXT,
|
|
102
|
-
metadata TEXT
|
|
103
|
-
);
|
|
104
|
-
`);
|
|
105
|
-
// Create indices (sql.js doesn't support CREATE INDEX IF NOT EXISTS, so we'll handle errors)
|
|
106
|
-
try {
|
|
107
|
-
this.db.run('CREATE INDEX idx_timestamp ON costs(timestamp);');
|
|
108
|
-
}
|
|
109
|
-
catch { }
|
|
110
|
-
try {
|
|
111
|
-
this.db.run('CREATE INDEX idx_operation ON costs(operation);');
|
|
112
|
-
}
|
|
113
|
-
catch { }
|
|
114
|
-
try {
|
|
115
|
-
this.db.run('CREATE INDEX idx_run_id ON costs(run_id);');
|
|
116
|
-
}
|
|
117
|
-
catch { }
|
|
118
|
-
return this.db;
|
|
119
|
-
}
|
|
120
|
-
async saveDb() {
|
|
121
|
-
if (!this.db)
|
|
122
|
-
return;
|
|
123
|
-
const buffer = this.db.export();
|
|
124
|
-
writeFileSync(this.dbPath, buffer);
|
|
125
|
-
}
|
|
126
|
-
/**
|
|
127
|
-
* Calculate cost for an operation
|
|
128
|
-
*/
|
|
129
|
-
calculateCost(operationType, model = 'default', inputTokens, outputTokens) {
|
|
130
|
-
const pricing = PRICING[model] || PRICING.default;
|
|
131
|
-
let cost = 0;
|
|
132
|
-
if (operationType === 'chat') {
|
|
133
|
-
const inputCost = (inputTokens || 0) * pricing.input;
|
|
134
|
-
const outputCost = (outputTokens || 0) * pricing.output;
|
|
135
|
-
cost = inputCost + outputCost;
|
|
136
|
-
}
|
|
137
|
-
else if (operationType === 'embed') {
|
|
138
|
-
cost = (inputTokens || 0) * pricing.input;
|
|
139
|
-
}
|
|
140
|
-
else if (operationType === 'rerank') {
|
|
141
|
-
cost = (inputTokens || 0) * pricing.input;
|
|
142
|
-
}
|
|
143
|
-
return cost;
|
|
144
|
-
}
|
|
145
|
-
/**
|
|
146
|
-
* Record a cost
|
|
147
|
-
*/
|
|
148
|
-
async recordCost(record) {
|
|
149
|
-
const db = await this.getDb();
|
|
150
|
-
const id = `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
151
|
-
const timestamp = Date.now();
|
|
152
|
-
db.run(`
|
|
153
|
-
INSERT INTO costs (id, timestamp, operation, operation_type, model, input_tokens, output_tokens, cost, run_id, metadata)
|
|
154
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
155
|
-
`, [
|
|
156
|
-
id,
|
|
157
|
-
timestamp,
|
|
158
|
-
record.operation,
|
|
159
|
-
record.operationType,
|
|
160
|
-
record.model || null,
|
|
161
|
-
record.inputTokens || null,
|
|
162
|
-
record.outputTokens || null,
|
|
163
|
-
record.cost,
|
|
164
|
-
record.runId || null,
|
|
165
|
-
record.metadata ? JSON.stringify(record.metadata) : null
|
|
166
|
-
]);
|
|
167
|
-
await this.saveDb();
|
|
168
|
-
// Check budget and alert if needed
|
|
169
|
-
await this.checkBudget();
|
|
170
|
-
}
|
|
171
|
-
/**
|
|
172
|
-
* Get cost summary
|
|
173
|
-
*/
|
|
174
|
-
async getSummary(timeRange) {
|
|
175
|
-
const db = await this.getDb();
|
|
176
|
-
let query = `
|
|
177
|
-
SELECT
|
|
178
|
-
operation,
|
|
179
|
-
operation_type,
|
|
180
|
-
model,
|
|
181
|
-
COUNT(*) as count,
|
|
182
|
-
SUM(cost) as total_cost
|
|
183
|
-
FROM costs
|
|
184
|
-
`;
|
|
185
|
-
const params = [];
|
|
186
|
-
if (timeRange) {
|
|
187
|
-
query += ' WHERE timestamp >= ? AND timestamp <= ?';
|
|
188
|
-
params.push(timeRange.start, timeRange.end);
|
|
189
|
-
}
|
|
190
|
-
query += ' GROUP BY operation, operation_type, model';
|
|
191
|
-
const stmt = db.prepare(query);
|
|
192
|
-
if (params.length > 0) {
|
|
193
|
-
stmt.bind(params);
|
|
194
|
-
}
|
|
195
|
-
const rows = [];
|
|
196
|
-
while (stmt.step()) {
|
|
197
|
-
const row = stmt.getAsObject();
|
|
198
|
-
rows.push({
|
|
199
|
-
operation: row.operation,
|
|
200
|
-
operation_type: row.operation_type,
|
|
201
|
-
model: row.model,
|
|
202
|
-
count: row.count,
|
|
203
|
-
total_cost: row.total_cost,
|
|
204
|
-
});
|
|
205
|
-
}
|
|
206
|
-
stmt.free();
|
|
207
|
-
const byOperation = {};
|
|
208
|
-
const byModel = {};
|
|
209
|
-
let totalCost = 0;
|
|
210
|
-
let operationCount = 0;
|
|
211
|
-
rows.forEach(row => {
|
|
212
|
-
totalCost += row.total_cost;
|
|
213
|
-
operationCount += row.count;
|
|
214
|
-
if (!byOperation[row.operation]) {
|
|
215
|
-
byOperation[row.operation] = { count: 0, cost: 0 };
|
|
216
|
-
}
|
|
217
|
-
byOperation[row.operation].count += row.count;
|
|
218
|
-
byOperation[row.operation].cost += row.total_cost;
|
|
219
|
-
const modelKey = row.model || 'default';
|
|
220
|
-
if (!byModel[modelKey]) {
|
|
221
|
-
byModel[modelKey] = { count: 0, cost: 0 };
|
|
222
|
-
}
|
|
223
|
-
byModel[modelKey].count += row.count;
|
|
224
|
-
byModel[modelKey].cost += row.total_cost;
|
|
225
|
-
});
|
|
226
|
-
// Calculate daily and monthly costs
|
|
227
|
-
const now = Date.now();
|
|
228
|
-
const oneDayAgo = now - (24 * 60 * 60 * 1000);
|
|
229
|
-
const oneMonthAgo = now - (30 * 24 * 60 * 60 * 1000);
|
|
230
|
-
const dailyStmt = db.prepare('SELECT SUM(cost) as total FROM costs WHERE timestamp >= ?');
|
|
231
|
-
dailyStmt.bind([oneDayAgo]);
|
|
232
|
-
dailyStmt.step();
|
|
233
|
-
const dailyRow = dailyStmt.getAsObject();
|
|
234
|
-
dailyStmt.free();
|
|
235
|
-
const monthlyStmt = db.prepare('SELECT SUM(cost) as total FROM costs WHERE timestamp >= ?');
|
|
236
|
-
monthlyStmt.bind([oneMonthAgo]);
|
|
237
|
-
monthlyStmt.step();
|
|
238
|
-
const monthlyRow = monthlyStmt.getAsObject();
|
|
239
|
-
monthlyStmt.free();
|
|
240
|
-
return {
|
|
241
|
-
totalCost,
|
|
242
|
-
operationCount,
|
|
243
|
-
byOperation,
|
|
244
|
-
byModel,
|
|
245
|
-
dailyCost: dailyRow.total || 0,
|
|
246
|
-
monthlyCost: monthlyRow.total || 0,
|
|
247
|
-
};
|
|
248
|
-
}
|
|
249
|
-
/**
|
|
250
|
-
* Get costs for a specific run
|
|
251
|
-
*/
|
|
252
|
-
async getRunCosts(runId) {
|
|
253
|
-
const db = await this.getDb();
|
|
254
|
-
const stmt = db.prepare('SELECT * FROM costs WHERE run_id = ? ORDER BY timestamp');
|
|
255
|
-
stmt.bind([runId]);
|
|
256
|
-
const rows = [];
|
|
257
|
-
while (stmt.step()) {
|
|
258
|
-
const row = stmt.getAsObject();
|
|
259
|
-
rows.push({
|
|
260
|
-
id: row.id,
|
|
261
|
-
timestamp: row.timestamp,
|
|
262
|
-
operation: row.operation,
|
|
263
|
-
operation_type: row.operation_type,
|
|
264
|
-
model: row.model,
|
|
265
|
-
input_tokens: row.input_tokens,
|
|
266
|
-
output_tokens: row.output_tokens,
|
|
267
|
-
cost: row.cost,
|
|
268
|
-
run_id: row.run_id,
|
|
269
|
-
metadata: row.metadata,
|
|
270
|
-
});
|
|
271
|
-
}
|
|
272
|
-
stmt.free();
|
|
273
|
-
return rows.map(row => ({
|
|
274
|
-
id: row.id,
|
|
275
|
-
timestamp: row.timestamp,
|
|
276
|
-
operation: row.operation,
|
|
277
|
-
operationType: row.operation_type,
|
|
278
|
-
model: row.model || undefined,
|
|
279
|
-
inputTokens: row.input_tokens || undefined,
|
|
280
|
-
outputTokens: row.output_tokens || undefined,
|
|
281
|
-
cost: row.cost,
|
|
282
|
-
runId: row.run_id || undefined,
|
|
283
|
-
metadata: row.metadata ? JSON.parse(row.metadata) : undefined,
|
|
284
|
-
}));
|
|
285
|
-
}
|
|
286
|
-
/**
|
|
287
|
-
* Check budget and alert if threshold exceeded
|
|
288
|
-
* NOTE: This does NOT block API calls - it only warns
|
|
289
|
-
*/
|
|
290
|
-
async checkBudget() {
|
|
291
|
-
// Only check budget if limit is set
|
|
292
|
-
if (this.budgetLimit === null || this.budgetLimit <= 0) {
|
|
293
|
-
return;
|
|
294
|
-
}
|
|
295
|
-
const summary = await this.getSummary();
|
|
296
|
-
const percentage = (summary.totalCost / this.budgetLimit) * 100;
|
|
297
|
-
const threshold = this.budgetLimit * this.alertThreshold;
|
|
298
|
-
if (summary.totalCost >= threshold && summary.totalCost < this.budgetLimit) {
|
|
299
|
-
console.warn(`⚠️ Budget Alert (LOCAL ESTIMATE ONLY): $${summary.totalCost.toFixed(4)} / $${this.budgetLimit} (${percentage.toFixed(1)}%)`);
|
|
300
|
-
console.warn(` This is a LOCAL ESTIMATE - check https://dashboard.cohere.com for actual usage`);
|
|
301
|
-
console.warn(` API calls will continue. Run 'codehere cost reset' to reset local tracking.`);
|
|
302
|
-
}
|
|
303
|
-
else if (summary.totalCost >= this.budgetLimit) {
|
|
304
|
-
console.warn(`⚠️ Budget Exceeded (LOCAL ESTIMATE ONLY): $${summary.totalCost.toFixed(4)} / $${this.budgetLimit}`);
|
|
305
|
-
console.warn(` This is a LOCAL ESTIMATE - check https://dashboard.cohere.com for actual usage`);
|
|
306
|
-
console.warn(` API calls will continue. Run 'codehere cost reset' to reset local tracking.`);
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
/**
|
|
310
|
-
* Get current budget status
|
|
311
|
-
*/
|
|
312
|
-
async getBudgetStatus() {
|
|
313
|
-
const summary = await this.getSummary();
|
|
314
|
-
if (this.budgetLimit === null || this.budgetLimit <= 0) {
|
|
315
|
-
return {
|
|
316
|
-
spent: summary.totalCost,
|
|
317
|
-
limit: null,
|
|
318
|
-
remaining: null,
|
|
319
|
-
percentage: null,
|
|
320
|
-
alert: false,
|
|
321
|
-
};
|
|
322
|
-
}
|
|
323
|
-
const remaining = Math.max(0, this.budgetLimit - summary.totalCost);
|
|
324
|
-
const percentage = (summary.totalCost / this.budgetLimit) * 100;
|
|
325
|
-
const alert = summary.totalCost >= (this.budgetLimit * this.alertThreshold);
|
|
326
|
-
return {
|
|
327
|
-
spent: summary.totalCost,
|
|
328
|
-
limit: this.budgetLimit,
|
|
329
|
-
remaining,
|
|
330
|
-
percentage,
|
|
331
|
-
alert,
|
|
332
|
-
};
|
|
333
|
-
}
|
|
334
|
-
/**
|
|
335
|
-
* Get budget limit
|
|
336
|
-
*/
|
|
337
|
-
getBudgetLimit() {
|
|
338
|
-
return this.budgetLimit;
|
|
339
|
-
}
|
|
340
|
-
/**
|
|
341
|
-
* Reset costs (for testing or new billing period)
|
|
342
|
-
*/
|
|
343
|
-
async resetCosts() {
|
|
344
|
-
const db = await this.getDb();
|
|
345
|
-
db.run('DELETE FROM costs');
|
|
346
|
-
await this.saveDb();
|
|
347
|
-
}
|
|
348
|
-
}
|
|
349
|
-
// Singleton instance
|
|
350
|
-
let costTrackerInstance = null;
|
|
351
|
-
export function getCostTracker(budgetLimit) {
|
|
352
|
-
if (!costTrackerInstance) {
|
|
353
|
-
// Only set budget if explicitly provided via env var or parameter
|
|
354
|
-
// null = no budget tracking (default behavior)
|
|
355
|
-
const budget = budgetLimit ?? (process.env.COHERE_BUDGET_LIMIT ? parseFloat(process.env.COHERE_BUDGET_LIMIT) : null);
|
|
356
|
-
costTrackerInstance = new CostTracker(budget);
|
|
357
|
-
}
|
|
358
|
-
return costTrackerInstance;
|
|
359
|
-
}
|
|
360
|
-
//# sourceMappingURL=cost-tracker.js.map
|
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Infrastructure: File Scanner
|
|
3
|
-
* Scans repository for code files to index
|
|
4
|
-
*/
|
|
5
|
-
import { readdirSync, statSync, existsSync } from 'fs';
|
|
6
|
-
import { join, extname } from 'path';
|
|
7
|
-
export class FileScanner {
|
|
8
|
-
CODE_EXTENSIONS = new Set([
|
|
9
|
-
'.ts', '.tsx', '.js', '.jsx', '.py', '.java', '.go', '.rs',
|
|
10
|
-
'.cpp', '.c', '.h', '.hpp', '.cs', '.rb', '.php', '.swift',
|
|
11
|
-
'.kt', '.scala', '.clj', '.sh', '.bash', '.zsh',
|
|
12
|
-
]);
|
|
13
|
-
DOC_EXTENSIONS = new Set([
|
|
14
|
-
'.md', '.txt', '.rst', '.adoc',
|
|
15
|
-
]);
|
|
16
|
-
IGNORE_PATTERNS = [
|
|
17
|
-
/^node_modules$/,
|
|
18
|
-
/^\.git$/,
|
|
19
|
-
/^\.next$/,
|
|
20
|
-
/^\.nuxt$/,
|
|
21
|
-
/^dist$/,
|
|
22
|
-
/^build$/,
|
|
23
|
-
/^\.build$/,
|
|
24
|
-
/^coverage$/,
|
|
25
|
-
/^\.coverage$/,
|
|
26
|
-
/^\.venv$/,
|
|
27
|
-
/^venv$/,
|
|
28
|
-
/^\.env$/,
|
|
29
|
-
/^\.DS_Store$/,
|
|
30
|
-
/^\.vscode$/,
|
|
31
|
-
/^\.idea$/,
|
|
32
|
-
];
|
|
33
|
-
/**
|
|
34
|
-
* Scan repository for code files
|
|
35
|
-
*/
|
|
36
|
-
async scan(repoPath) {
|
|
37
|
-
if (!existsSync(repoPath)) {
|
|
38
|
-
throw new Error(`Repository path does not exist: ${repoPath}`);
|
|
39
|
-
}
|
|
40
|
-
const files = [];
|
|
41
|
-
this.scanDirectory(repoPath, repoPath, files);
|
|
42
|
-
return files;
|
|
43
|
-
}
|
|
44
|
-
/**
|
|
45
|
-
* Recursively scan directory
|
|
46
|
-
*/
|
|
47
|
-
scanDirectory(dirPath, basePath, files) {
|
|
48
|
-
try {
|
|
49
|
-
const entries = readdirSync(dirPath);
|
|
50
|
-
for (const entry of entries) {
|
|
51
|
-
const fullPath = join(dirPath, entry);
|
|
52
|
-
const relativePath = fullPath.replace(basePath + '/', '').replace(basePath, '');
|
|
53
|
-
// Skip ignored patterns
|
|
54
|
-
if (this.shouldIgnore(entry, relativePath)) {
|
|
55
|
-
continue;
|
|
56
|
-
}
|
|
57
|
-
const stat = statSync(fullPath);
|
|
58
|
-
if (stat.isDirectory()) {
|
|
59
|
-
// Recursively scan subdirectories
|
|
60
|
-
this.scanDirectory(fullPath, basePath, files);
|
|
61
|
-
}
|
|
62
|
-
else if (stat.isFile()) {
|
|
63
|
-
// Check if file is code or documentation
|
|
64
|
-
if (this.isCodeFile(entry) || this.isDocFile(entry)) {
|
|
65
|
-
files.push(fullPath);
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
catch (error) {
|
|
71
|
-
// Skip directories we can't read (permissions, etc.)
|
|
72
|
-
console.warn(`Warning: Could not scan directory ${dirPath}:`, error instanceof Error ? error.message : String(error));
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
/**
|
|
76
|
-
* Check if file should be ignored
|
|
77
|
-
*/
|
|
78
|
-
shouldIgnore(filename, relativePath) {
|
|
79
|
-
// Check ignore patterns
|
|
80
|
-
for (const pattern of this.IGNORE_PATTERNS) {
|
|
81
|
-
if (pattern.test(filename) || pattern.test(relativePath)) {
|
|
82
|
-
return true;
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
// Ignore hidden files (except .env.example, .gitignore, etc.)
|
|
86
|
-
if (filename.startsWith('.') && !['.env.example', '.gitignore', '.eslintrc', '.prettierrc'].includes(filename)) {
|
|
87
|
-
return true;
|
|
88
|
-
}
|
|
89
|
-
return false;
|
|
90
|
-
}
|
|
91
|
-
/**
|
|
92
|
-
* Check if file is a code file
|
|
93
|
-
*/
|
|
94
|
-
isCodeFile(filename) {
|
|
95
|
-
const ext = extname(filename).toLowerCase();
|
|
96
|
-
return this.CODE_EXTENSIONS.has(ext);
|
|
97
|
-
}
|
|
98
|
-
/**
|
|
99
|
-
* Check if file is a documentation file
|
|
100
|
-
*/
|
|
101
|
-
isDocFile(filename) {
|
|
102
|
-
const ext = extname(filename).toLowerCase();
|
|
103
|
-
return this.DOC_EXTENSIONS.has(ext);
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
//# sourceMappingURL=file-scanner.js.map
|