meter-ai 0.1.0
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 +124 -0
- package/dist/auth/credentials.d.ts +9 -0
- package/dist/auth/credentials.d.ts.map +1 -0
- package/dist/auth/credentials.js +32 -0
- package/dist/auth/credentials.js.map +1 -0
- package/dist/auth/detect.d.ts +7 -0
- package/dist/auth/detect.d.ts.map +1 -0
- package/dist/auth/detect.js +20 -0
- package/dist/auth/detect.js.map +1 -0
- package/dist/commands/config.d.ts +2 -0
- package/dist/commands/config.d.ts.map +1 -0
- package/dist/commands/config.js +26 -0
- package/dist/commands/config.js.map +1 -0
- package/dist/commands/history.d.ts +2 -0
- package/dist/commands/history.d.ts.map +1 -0
- package/dist/commands/history.js +19 -0
- package/dist/commands/history.js.map +1 -0
- package/dist/commands/init.d.ts +10 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +58 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/report.d.ts +2 -0
- package/dist/commands/report.d.ts.map +1 -0
- package/dist/commands/report.js +37 -0
- package/dist/commands/report.js.map +1 -0
- package/dist/commands/status.d.ts +2 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +20 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/uninstall.d.ts +2 -0
- package/dist/commands/uninstall.d.ts.map +1 -0
- package/dist/commands/uninstall.js +20 -0
- package/dist/commands/uninstall.js.map +1 -0
- package/dist/commands/wrap.d.ts +2 -0
- package/dist/commands/wrap.d.ts.map +1 -0
- package/dist/commands/wrap.js +189 -0
- package/dist/commands/wrap.js.map +1 -0
- package/dist/constants.d.ts +30 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +48 -0
- package/dist/constants.js.map +1 -0
- package/dist/estimation/heuristics.d.ts +8 -0
- package/dist/estimation/heuristics.d.ts.map +1 -0
- package/dist/estimation/heuristics.js +28 -0
- package/dist/estimation/heuristics.js.map +1 -0
- package/dist/estimation/history-matcher.d.ts +4 -0
- package/dist/estimation/history-matcher.d.ts.map +1 -0
- package/dist/estimation/history-matcher.js +27 -0
- package/dist/estimation/history-matcher.js.map +1 -0
- package/dist/estimation/llm-precheck.d.ts +3 -0
- package/dist/estimation/llm-precheck.d.ts.map +1 -0
- package/dist/estimation/llm-precheck.js +21 -0
- package/dist/estimation/llm-precheck.js.map +1 -0
- package/dist/estimation/pipeline.d.ts +16 -0
- package/dist/estimation/pipeline.d.ts.map +1 -0
- package/dist/estimation/pipeline.js +48 -0
- package/dist/estimation/pipeline.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +45 -0
- package/dist/index.js.map +1 -0
- package/dist/pty/resize.d.ts +7 -0
- package/dist/pty/resize.d.ts.map +1 -0
- package/dist/pty/resize.js +10 -0
- package/dist/pty/resize.js.map +1 -0
- package/dist/pty/screen.d.ts +6 -0
- package/dist/pty/screen.d.ts.map +1 -0
- package/dist/pty/screen.js +15 -0
- package/dist/pty/screen.js.map +1 -0
- package/dist/pty/wrapper.d.ts +15 -0
- package/dist/pty/wrapper.d.ts.map +1 -0
- package/dist/pty/wrapper.js +49 -0
- package/dist/pty/wrapper.js.map +1 -0
- package/dist/shell/binary-resolver.d.ts +2 -0
- package/dist/shell/binary-resolver.d.ts.map +1 -0
- package/dist/shell/binary-resolver.js +18 -0
- package/dist/shell/binary-resolver.js.map +1 -0
- package/dist/shell/detect.d.ts +5 -0
- package/dist/shell/detect.d.ts.map +1 -0
- package/dist/shell/detect.js +32 -0
- package/dist/shell/detect.js.map +1 -0
- package/dist/shell/path-inject.d.ts +5 -0
- package/dist/shell/path-inject.d.ts.map +1 -0
- package/dist/shell/path-inject.js +30 -0
- package/dist/shell/path-inject.js.map +1 -0
- package/dist/shell/shim-writer.d.ts +3 -0
- package/dist/shell/shim-writer.d.ts.map +1 -0
- package/dist/shell/shim-writer.js +22 -0
- package/dist/shell/shim-writer.js.map +1 -0
- package/dist/storage/config-store.d.ts +10 -0
- package/dist/storage/config-store.d.ts.map +1 -0
- package/dist/storage/config-store.js +42 -0
- package/dist/storage/config-store.js.map +1 -0
- package/dist/storage/db.d.ts +7 -0
- package/dist/storage/db.d.ts.map +1 -0
- package/dist/storage/db.js +53 -0
- package/dist/storage/db.js.map +1 -0
- package/dist/tracking/cost.d.ts +6 -0
- package/dist/tracking/cost.d.ts.map +1 -0
- package/dist/tracking/cost.js +6 -0
- package/dist/tracking/cost.js.map +1 -0
- package/dist/tracking/plan-usage.d.ts +6 -0
- package/dist/tracking/plan-usage.d.ts.map +1 -0
- package/dist/tracking/plan-usage.js +53 -0
- package/dist/tracking/plan-usage.js.map +1 -0
- package/dist/tracking/tokens.d.ts +7 -0
- package/dist/tracking/tokens.d.ts.map +1 -0
- package/dist/tracking/tokens.js +14 -0
- package/dist/tracking/tokens.js.map +1 -0
- package/dist/types.d.ts +70 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/ui/keypress.d.ts +3 -0
- package/dist/ui/keypress.d.ts.map +1 -0
- package/dist/ui/keypress.js +20 -0
- package/dist/ui/keypress.js.map +1 -0
- package/dist/ui/notification.d.ts +11 -0
- package/dist/ui/notification.d.ts.map +1 -0
- package/dist/ui/notification.js +18 -0
- package/dist/ui/notification.js.map +1 -0
- package/dist/ui/statusbar.d.ts +15 -0
- package/dist/ui/statusbar.d.ts.map +1 -0
- package/dist/ui/statusbar.js +53 -0
- package/dist/ui/statusbar.js.map +1 -0
- package/package.json +34 -0
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import { PtyWrapper } from '../pty/wrapper.js';
|
|
2
|
+
import { readConfig } from '../storage/config-store.js';
|
|
3
|
+
import { openDb, insertTask } from '../storage/db.js';
|
|
4
|
+
import { runEstimationPipeline } from '../estimation/pipeline.js';
|
|
5
|
+
import { injectStatusBar, renderStatusBar } from '../ui/statusbar.js';
|
|
6
|
+
import { renderNotification } from '../ui/notification.js';
|
|
7
|
+
import { waitForKeypress } from '../ui/keypress.js';
|
|
8
|
+
import { parseTokensFromOutput, estimateInputTokens } from '../tracking/tokens.js';
|
|
9
|
+
import { fetchPlanUsage, formatResetCountdown } from '../tracking/plan-usage.js';
|
|
10
|
+
import { readCredentials, watchCredentials } from '../auth/credentials.js';
|
|
11
|
+
import { calculateStatusBarLines } from '../pty/resize.js';
|
|
12
|
+
import { CONFIG_PATH, HISTORY_DB_PATH, CLAUDE_CREDENTIALS_PATH } from '../constants.js';
|
|
13
|
+
import { execSync } from 'child_process';
|
|
14
|
+
import { createHash } from 'crypto';
|
|
15
|
+
export async function runWrap(args) {
|
|
16
|
+
const trueBinary = args[0];
|
|
17
|
+
const agentArgs = args.slice(1);
|
|
18
|
+
const prompt = agentArgs.join(' ');
|
|
19
|
+
if (!trueBinary) {
|
|
20
|
+
console.error('[meter] wrap: missing binary argument');
|
|
21
|
+
process.exit(1);
|
|
22
|
+
}
|
|
23
|
+
const config = await readConfig(CONFIG_PATH);
|
|
24
|
+
if (!config) {
|
|
25
|
+
// No config — run agent directly without wrapping
|
|
26
|
+
const w = new PtyWrapper();
|
|
27
|
+
w.spawn(trueBinary, agentArgs, process.env);
|
|
28
|
+
await new Promise(resolve => w.on('exit', () => resolve()));
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
const db = await openDb(HISTORY_DB_PATH);
|
|
32
|
+
// Get repo identifier
|
|
33
|
+
let repo = null;
|
|
34
|
+
try {
|
|
35
|
+
repo = execSync('git remote get-url origin 2>/dev/null').toString().trim();
|
|
36
|
+
}
|
|
37
|
+
catch { }
|
|
38
|
+
if (!repo) {
|
|
39
|
+
try {
|
|
40
|
+
repo = process.cwd();
|
|
41
|
+
}
|
|
42
|
+
catch { }
|
|
43
|
+
}
|
|
44
|
+
// Get repo file count for estimation
|
|
45
|
+
let repoFileCount = 100;
|
|
46
|
+
try {
|
|
47
|
+
repoFileCount = parseInt(execSync('git ls-files 2>/dev/null | wc -l').toString().trim(), 10) || 100;
|
|
48
|
+
}
|
|
49
|
+
catch { }
|
|
50
|
+
// Run estimation (non-blocking display)
|
|
51
|
+
const estimation = await runEstimationPipeline({
|
|
52
|
+
prompt,
|
|
53
|
+
repoFileCount,
|
|
54
|
+
db,
|
|
55
|
+
repo,
|
|
56
|
+
config: config.estimation,
|
|
57
|
+
});
|
|
58
|
+
// Fetch initial plan usage if Plan Mode
|
|
59
|
+
let planUsage = null;
|
|
60
|
+
let creds = null;
|
|
61
|
+
if (config.mode === 'plan' && config.org_id) {
|
|
62
|
+
creds = await readCredentials(CLAUDE_CREDENTIALS_PATH);
|
|
63
|
+
if (creds)
|
|
64
|
+
planUsage = await fetchPlanUsage(config.org_id, creds);
|
|
65
|
+
}
|
|
66
|
+
// State for status bar
|
|
67
|
+
const state = {
|
|
68
|
+
model: config.models.claude_chain[0],
|
|
69
|
+
estimatedCost: estimation.estimated_cost,
|
|
70
|
+
complexity: estimation.complexity,
|
|
71
|
+
mode: config.mode,
|
|
72
|
+
elapsedCost: 0,
|
|
73
|
+
budgetUsd: config.budget.per_task_usd,
|
|
74
|
+
windowPct: planUsage?.five_hour_pct ?? null,
|
|
75
|
+
windowResetIn: planUsage ? formatResetCountdown(planUsage.five_hour_reset_at) : null,
|
|
76
|
+
};
|
|
77
|
+
// Spawn agent in PTY — declare BEFORE updateBar so closure can reference it safely
|
|
78
|
+
const wrapper = new PtyWrapper();
|
|
79
|
+
let outputBuffer = '';
|
|
80
|
+
let thresholdNotified = false;
|
|
81
|
+
let modelSwitched = 0;
|
|
82
|
+
// Status bar update function
|
|
83
|
+
const updateBar = () => {
|
|
84
|
+
if (wrapper.isInAlternateScreen)
|
|
85
|
+
return;
|
|
86
|
+
const content = renderStatusBar(state);
|
|
87
|
+
const N = calculateStatusBarLines(content.replace(/\x1b\[[^m]*m/g, '').length, process.stdout.columns ?? 80);
|
|
88
|
+
injectStatusBar(content, N);
|
|
89
|
+
};
|
|
90
|
+
// Watch for credential refresh
|
|
91
|
+
if (config.mode === 'plan') {
|
|
92
|
+
watchCredentials(CLAUDE_CREDENTIALS_PATH, async (newCreds) => {
|
|
93
|
+
if (newCreds)
|
|
94
|
+
creds = newCreds;
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
// Plan usage polling (15s during active task)
|
|
98
|
+
let pollInterval = null;
|
|
99
|
+
if (config.mode === 'plan' && config.org_id && creds) {
|
|
100
|
+
pollInterval = setInterval(async () => {
|
|
101
|
+
if (!creds || !config.org_id)
|
|
102
|
+
return;
|
|
103
|
+
const usage = await fetchPlanUsage(config.org_id, creds);
|
|
104
|
+
if (usage) {
|
|
105
|
+
state.windowPct = usage.five_hour_pct;
|
|
106
|
+
state.windowResetIn = formatResetCountdown(usage.five_hour_reset_at);
|
|
107
|
+
updateBar();
|
|
108
|
+
}
|
|
109
|
+
}, 15_000);
|
|
110
|
+
}
|
|
111
|
+
wrapper.on('data', (chunk) => {
|
|
112
|
+
outputBuffer += chunk;
|
|
113
|
+
// Rough running cost estimate from output volume
|
|
114
|
+
state.elapsedCost = (state.elapsedCost ?? 0) + (chunk.length / 4 / 1_000_000) * 15;
|
|
115
|
+
updateBar();
|
|
116
|
+
// Check threshold
|
|
117
|
+
if (!thresholdNotified) {
|
|
118
|
+
const exceeded = config.mode === 'api'
|
|
119
|
+
? ((state.elapsedCost ?? 0) / config.budget.per_task_usd) * 100 >= config.budget.threshold_pct
|
|
120
|
+
: (state.windowPct ?? 0) >= config.plan.window_threshold_pct;
|
|
121
|
+
if (exceeded) {
|
|
122
|
+
thresholdNotified = true;
|
|
123
|
+
handleThreshold();
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
async function handleThreshold() {
|
|
128
|
+
// config is guaranteed non-null here (we returned early above if null)
|
|
129
|
+
const cfg = config;
|
|
130
|
+
const nextModel = cfg.models.claude_chain[1] ?? null;
|
|
131
|
+
const notification = renderNotification({
|
|
132
|
+
mode: cfg.mode,
|
|
133
|
+
thresholdPct: cfg.mode === 'api' ? cfg.budget.threshold_pct : cfg.plan.window_threshold_pct,
|
|
134
|
+
elapsedCost: state.elapsedCost,
|
|
135
|
+
budgetUsd: cfg.budget.per_task_usd,
|
|
136
|
+
windowPct: state.windowPct,
|
|
137
|
+
nextModel,
|
|
138
|
+
});
|
|
139
|
+
process.stdout.write('\n' + notification + '\n');
|
|
140
|
+
const action = await waitForKeypress(['s', 'd', 'c'], 0);
|
|
141
|
+
if (action === 'c') {
|
|
142
|
+
wrapper.kill();
|
|
143
|
+
}
|
|
144
|
+
else if (action === 's' && nextModel) {
|
|
145
|
+
process.stdout.write(`\n↻ restarting with ${nextModel} (context will reset — press c within 5s to cancel)\n`);
|
|
146
|
+
const cancel = await waitForKeypress(['c'], 5_000);
|
|
147
|
+
if (cancel !== 'c') {
|
|
148
|
+
wrapper.kill();
|
|
149
|
+
state.model = nextModel;
|
|
150
|
+
modelSwitched = 1;
|
|
151
|
+
wrapper.spawn(trueBinary, [`--model`, nextModel, ...agentArgs.slice(1)], process.env);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
// 'd' = dismiss, do nothing
|
|
155
|
+
}
|
|
156
|
+
const taskStart = Date.now();
|
|
157
|
+
// Reserve status bar line and spawn
|
|
158
|
+
process.stdout.write('\n');
|
|
159
|
+
updateBar();
|
|
160
|
+
wrapper.spawn(trueBinary, agentArgs, process.env);
|
|
161
|
+
const exitCode = await new Promise(resolve => {
|
|
162
|
+
wrapper.on('exit', (code) => resolve(code));
|
|
163
|
+
});
|
|
164
|
+
if (pollInterval)
|
|
165
|
+
clearInterval(pollInterval);
|
|
166
|
+
// Parse final token counts
|
|
167
|
+
const tokens = parseTokensFromOutput(outputBuffer);
|
|
168
|
+
const promptHash = createHash('sha256').update(prompt.toLowerCase().trim()).digest('hex').slice(0, 16);
|
|
169
|
+
insertTask(db, {
|
|
170
|
+
created_at: taskStart,
|
|
171
|
+
repo,
|
|
172
|
+
prompt_hash: promptHash,
|
|
173
|
+
prompt_text: prompt,
|
|
174
|
+
model: state.model,
|
|
175
|
+
complexity: estimation.complexity,
|
|
176
|
+
est_layer: estimation.layer_used,
|
|
177
|
+
est_cost: estimation.estimated_cost,
|
|
178
|
+
actual_tokens_in: tokens?.input ?? estimateInputTokens(prompt.length),
|
|
179
|
+
actual_tokens_out: tokens?.output ?? null,
|
|
180
|
+
actual_cost: config.mode === 'api' ? (state.elapsedCost ?? null) : null,
|
|
181
|
+
window_pct_start: planUsage?.five_hour_pct ?? null,
|
|
182
|
+
window_pct_end: state.windowPct,
|
|
183
|
+
model_switched: modelSwitched,
|
|
184
|
+
exit_code: exitCode,
|
|
185
|
+
});
|
|
186
|
+
db.close();
|
|
187
|
+
process.exit(exitCode);
|
|
188
|
+
}
|
|
189
|
+
//# sourceMappingURL=wrap.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wrap.js","sourceRoot":"","sources":["../../src/commands/wrap.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export declare const METER_DIR: string;
|
|
2
|
+
export declare const METER_BIN_DIR: string;
|
|
3
|
+
export declare const CONFIG_PATH: string;
|
|
4
|
+
export declare const HISTORY_DB_PATH: string;
|
|
5
|
+
export declare const PRICING_PATH: string;
|
|
6
|
+
export declare const USAGE_CACHE_PATH: string;
|
|
7
|
+
export declare const SESSION_CACHE_PATH: string;
|
|
8
|
+
export declare const ERRORS_LOG_PATH: string;
|
|
9
|
+
export declare const REPORTS_DIR: string;
|
|
10
|
+
export declare const DEFAULT_CONFIG_VALUES: {
|
|
11
|
+
budget_per_task_usd: number;
|
|
12
|
+
threshold_pct: number;
|
|
13
|
+
window_threshold_pct: number;
|
|
14
|
+
poll_interval_seconds: number;
|
|
15
|
+
min_confidence_to_skip_llm: number;
|
|
16
|
+
claude_chain: string[];
|
|
17
|
+
llm_precheck_model: string;
|
|
18
|
+
};
|
|
19
|
+
export declare const CLAUDE_USAGE_API = "https://claude.ai/api/organizations";
|
|
20
|
+
export declare const CLAUDE_BOOTSTRAP_API = "https://claude.ai/api/bootstrap";
|
|
21
|
+
export declare const CLAUDE_CREDENTIALS_PATH: string;
|
|
22
|
+
export declare const CLAUDE_SETTINGS_PATH: string;
|
|
23
|
+
export declare const KEYWORD_WEIGHTS: Record<string, number>;
|
|
24
|
+
export declare const COMPLEXITY_THRESHOLDS: {
|
|
25
|
+
low: number;
|
|
26
|
+
medium: number;
|
|
27
|
+
heavy: number;
|
|
28
|
+
critical: number;
|
|
29
|
+
};
|
|
30
|
+
//# sourceMappingURL=constants.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,SAAS,QAA4B,CAAA;AAClD,eAAO,MAAM,aAAa,QAAyB,CAAA;AACnD,eAAO,MAAM,WAAW,QAAiC,CAAA;AACzD,eAAO,MAAM,eAAe,QAAgC,CAAA;AAC5D,eAAO,MAAM,YAAY,QAAkC,CAAA;AAC3D,eAAO,MAAM,gBAAgB,QAAyC,CAAA;AACtE,eAAO,MAAM,kBAAkB,QAA2C,CAAA;AAC1E,eAAO,MAAM,eAAe,QAAyC,CAAA;AACrE,eAAO,MAAM,WAAW,QAA6B,CAAA;AAErD,eAAO,MAAM,qBAAqB;;;;;;;;CAQjC,CAAA;AAED,eAAO,MAAM,gBAAgB,wCAAwC,CAAA;AACrE,eAAO,MAAM,oBAAoB,oCAAoC,CAAA;AACrE,eAAO,MAAM,uBAAuB,QAAkD,CAAA;AACtF,eAAO,MAAM,oBAAoB,QAA8C,CAAA;AAE/E,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAgBlD,CAAA;AAED,eAAO,MAAM,qBAAqB;;;;;CAKjC,CAAA"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { homedir } from 'os';
|
|
2
|
+
import { join } from 'path';
|
|
3
|
+
export const METER_DIR = join(homedir(), '.meter');
|
|
4
|
+
export const METER_BIN_DIR = join(METER_DIR, 'bin');
|
|
5
|
+
export const CONFIG_PATH = join(METER_DIR, 'config.json');
|
|
6
|
+
export const HISTORY_DB_PATH = join(METER_DIR, 'history.db');
|
|
7
|
+
export const PRICING_PATH = join(METER_DIR, 'pricing.json');
|
|
8
|
+
export const USAGE_CACHE_PATH = join(METER_DIR, 'cache', 'usage.json');
|
|
9
|
+
export const SESSION_CACHE_PATH = join(METER_DIR, 'cache', 'session.json');
|
|
10
|
+
export const ERRORS_LOG_PATH = join(METER_DIR, 'cache', 'errors.log');
|
|
11
|
+
export const REPORTS_DIR = join(METER_DIR, 'reports');
|
|
12
|
+
export const DEFAULT_CONFIG_VALUES = {
|
|
13
|
+
budget_per_task_usd: 0.50,
|
|
14
|
+
threshold_pct: 80,
|
|
15
|
+
window_threshold_pct: 80,
|
|
16
|
+
poll_interval_seconds: 60,
|
|
17
|
+
min_confidence_to_skip_llm: 0.85,
|
|
18
|
+
claude_chain: ['claude-opus-4-20250514', 'claude-sonnet-4-20250514', 'claude-haiku-4-20250307'],
|
|
19
|
+
llm_precheck_model: 'claude-haiku-4-20250307',
|
|
20
|
+
};
|
|
21
|
+
export const CLAUDE_USAGE_API = 'https://claude.ai/api/organizations';
|
|
22
|
+
export const CLAUDE_BOOTSTRAP_API = 'https://claude.ai/api/bootstrap';
|
|
23
|
+
export const CLAUDE_CREDENTIALS_PATH = join(homedir(), '.claude', '.credentials.json');
|
|
24
|
+
export const CLAUDE_SETTINGS_PATH = join(homedir(), '.claude', 'settings.json');
|
|
25
|
+
export const KEYWORD_WEIGHTS = {
|
|
26
|
+
'refactor entire': 0.9,
|
|
27
|
+
'rewrite': 0.85,
|
|
28
|
+
'migrate': 0.8,
|
|
29
|
+
'refactor': 0.7,
|
|
30
|
+
'implement': 0.6,
|
|
31
|
+
'add feature': 0.55,
|
|
32
|
+
'add tests': 0.5,
|
|
33
|
+
'add': 0.4,
|
|
34
|
+
'update': 0.35,
|
|
35
|
+
'fix': 0.3,
|
|
36
|
+
'debug': 0.3,
|
|
37
|
+
'change': 0.25,
|
|
38
|
+
'rename': 0.2,
|
|
39
|
+
'fix typo': 0.05,
|
|
40
|
+
'typo': 0.05,
|
|
41
|
+
};
|
|
42
|
+
export const COMPLEXITY_THRESHOLDS = {
|
|
43
|
+
low: 0.3,
|
|
44
|
+
medium: 0.55,
|
|
45
|
+
heavy: 0.75,
|
|
46
|
+
critical: 1.0,
|
|
47
|
+
};
|
|
48
|
+
//# sourceMappingURL=constants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAA;AAC5B,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAE3B,MAAM,CAAC,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,QAAQ,CAAC,CAAA;AAClD,MAAM,CAAC,MAAM,aAAa,GAAG,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,CAAA;AACnD,MAAM,CAAC,MAAM,WAAW,GAAG,IAAI,CAAC,SAAS,EAAE,aAAa,CAAC,CAAA;AACzD,MAAM,CAAC,MAAM,eAAe,GAAG,IAAI,CAAC,SAAS,EAAE,YAAY,CAAC,CAAA;AAC5D,MAAM,CAAC,MAAM,YAAY,GAAG,IAAI,CAAC,SAAS,EAAE,cAAc,CAAC,CAAA;AAC3D,MAAM,CAAC,MAAM,gBAAgB,GAAG,IAAI,CAAC,SAAS,EAAE,OAAO,EAAE,YAAY,CAAC,CAAA;AACtE,MAAM,CAAC,MAAM,kBAAkB,GAAG,IAAI,CAAC,SAAS,EAAE,OAAO,EAAE,cAAc,CAAC,CAAA;AAC1E,MAAM,CAAC,MAAM,eAAe,GAAG,IAAI,CAAC,SAAS,EAAE,OAAO,EAAE,YAAY,CAAC,CAAA;AACrE,MAAM,CAAC,MAAM,WAAW,GAAG,IAAI,CAAC,SAAS,EAAE,SAAS,CAAC,CAAA;AAErD,MAAM,CAAC,MAAM,qBAAqB,GAAG;IACnC,mBAAmB,EAAE,IAAI;IACzB,aAAa,EAAE,EAAE;IACjB,oBAAoB,EAAE,EAAE;IACxB,qBAAqB,EAAE,EAAE;IACzB,0BAA0B,EAAE,IAAI;IAChC,YAAY,EAAE,CAAC,wBAAwB,EAAE,0BAA0B,EAAE,yBAAyB,CAAC;IAC/F,kBAAkB,EAAE,yBAAyB;CAC9C,CAAA;AAED,MAAM,CAAC,MAAM,gBAAgB,GAAG,qCAAqC,CAAA;AACrE,MAAM,CAAC,MAAM,oBAAoB,GAAG,iCAAiC,CAAA;AACrE,MAAM,CAAC,MAAM,uBAAuB,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,mBAAmB,CAAC,CAAA;AACtF,MAAM,CAAC,MAAM,oBAAoB,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,eAAe,CAAC,CAAA;AAE/E,MAAM,CAAC,MAAM,eAAe,GAA2B;IACrD,iBAAiB,EAAE,GAAG;IACtB,SAAS,EAAE,IAAI;IACf,SAAS,EAAE,GAAG;IACd,UAAU,EAAE,GAAG;IACf,WAAW,EAAE,GAAG;IAChB,aAAa,EAAE,IAAI;IACnB,WAAW,EAAE,GAAG;IAChB,KAAK,EAAE,GAAG;IACV,QAAQ,EAAE,IAAI;IACd,KAAK,EAAE,GAAG;IACV,OAAO,EAAE,GAAG;IACZ,QAAQ,EAAE,IAAI;IACd,QAAQ,EAAE,GAAG;IACb,UAAU,EAAE,IAAI;IAChB,MAAM,EAAE,IAAI;CACb,CAAA;AAED,MAAM,CAAC,MAAM,qBAAqB,GAAG;IACnC,GAAG,EAAE,GAAG;IACR,MAAM,EAAE,IAAI;IACZ,KAAK,EAAE,IAAI;IACX,QAAQ,EAAE,GAAG;CACd,CAAA"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { EstimationResult } from '../types.js';
|
|
2
|
+
interface HeuristicInput {
|
|
3
|
+
prompt: string;
|
|
4
|
+
repoFileCount: number;
|
|
5
|
+
}
|
|
6
|
+
export declare function scoreHeuristics(input: HeuristicInput): Pick<EstimationResult, 'complexity' | 'confidence'>;
|
|
7
|
+
export {};
|
|
8
|
+
//# sourceMappingURL=heuristics.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"heuristics.d.ts","sourceRoot":"","sources":["../../src/estimation/heuristics.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAc,gBAAgB,EAAE,MAAM,aAAa,CAAA;AAE/D,UAAU,cAAc;IACtB,MAAM,EAAE,MAAM,CAAA;IACd,aAAa,EAAE,MAAM,CAAA;CACtB;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,cAAc,GAAG,IAAI,CAAC,gBAAgB,EAAE,YAAY,GAAG,YAAY,CAAC,CA2B1G"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { KEYWORD_WEIGHTS, COMPLEXITY_THRESHOLDS } from '../constants.js';
|
|
2
|
+
export function scoreHeuristics(input) {
|
|
3
|
+
const lower = input.prompt.toLowerCase();
|
|
4
|
+
// Use the most-specific (longest) matching keyword to avoid over-counting
|
|
5
|
+
let keywordScore = 0.35;
|
|
6
|
+
let bestMatchLen = 0;
|
|
7
|
+
for (const [keyword, weight] of Object.entries(KEYWORD_WEIGHTS)) {
|
|
8
|
+
if (lower.includes(keyword) && keyword.length > bestMatchLen) {
|
|
9
|
+
bestMatchLen = keyword.length;
|
|
10
|
+
keywordScore = weight;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
const sizeModifier = Math.min(input.repoFileCount / 500, 0.2);
|
|
14
|
+
const lengthModifier = lower.length > 60 ? 0.05 : 0;
|
|
15
|
+
const rawScore = Math.min(keywordScore + sizeModifier + lengthModifier, 1.0);
|
|
16
|
+
// critical uses strict > so it is unreachable via capped rawScore;
|
|
17
|
+
// heavy is the practical maximum from heuristics alone
|
|
18
|
+
let complexity = 'low';
|
|
19
|
+
if (rawScore > COMPLEXITY_THRESHOLDS.critical)
|
|
20
|
+
complexity = 'critical';
|
|
21
|
+
else if (rawScore >= COMPLEXITY_THRESHOLDS.heavy)
|
|
22
|
+
complexity = 'heavy';
|
|
23
|
+
else if (rawScore >= COMPLEXITY_THRESHOLDS.medium)
|
|
24
|
+
complexity = 'medium';
|
|
25
|
+
const confidence = keywordScore >= 0.8 || keywordScore <= 0.1 ? 0.9 : 0.65;
|
|
26
|
+
return { complexity, confidence };
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=heuristics.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"heuristics.js","sourceRoot":"","sources":["../../src/estimation/heuristics.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAA;AAQxE,MAAM,UAAU,eAAe,CAAC,KAAqB;IACnD,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,WAAW,EAAE,CAAA;IAExC,0EAA0E;IAC1E,IAAI,YAAY,GAAG,IAAI,CAAA;IACvB,IAAI,YAAY,GAAG,CAAC,CAAA;IACpB,KAAK,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,eAAe,CAAC,EAAE,CAAC;QAChE,IAAI,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC,MAAM,GAAG,YAAY,EAAE,CAAC;YAC7D,YAAY,GAAG,OAAO,CAAC,MAAM,CAAA;YAC7B,YAAY,GAAG,MAAM,CAAA;QACvB,CAAC;IACH,CAAC;IAED,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,aAAa,GAAG,GAAG,EAAE,GAAG,CAAC,CAAA;IAC7D,MAAM,cAAc,GAAG,KAAK,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAA;IACnD,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,YAAY,GAAG,YAAY,GAAG,cAAc,EAAE,GAAG,CAAC,CAAA;IAE5E,mEAAmE;IACnE,uDAAuD;IACvD,IAAI,UAAU,GAAe,KAAK,CAAA;IAClC,IAAI,QAAQ,GAAG,qBAAqB,CAAC,QAAQ;QAAE,UAAU,GAAG,UAAU,CAAA;SACjE,IAAI,QAAQ,IAAI,qBAAqB,CAAC,KAAK;QAAE,UAAU,GAAG,OAAO,CAAA;SACjE,IAAI,QAAQ,IAAI,qBAAqB,CAAC,MAAM;QAAE,UAAU,GAAG,QAAQ,CAAA;IAExE,MAAM,UAAU,GAAG,YAAY,IAAI,GAAG,IAAI,YAAY,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAA;IAE1E,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,CAAA;AACnC,CAAC"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { DB } from '../storage/db.js';
|
|
2
|
+
import type { EstimationResult } from '../types.js';
|
|
3
|
+
export declare function matchHistory(db: DB, prompt: string, repo: string | null): Pick<EstimationResult, 'estimated_cost' | 'layer_used'> | null;
|
|
4
|
+
//# sourceMappingURL=history-matcher.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"history-matcher.d.ts","sourceRoot":"","sources":["../../src/estimation/history-matcher.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAA;AAC1C,OAAO,KAAK,EAAE,gBAAgB,EAAc,MAAM,aAAa,CAAA;AAsB/D,wBAAgB,YAAY,CAC1B,EAAE,EAAE,EAAE,EACN,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,GAAG,IAAI,GAClB,IAAI,CAAC,gBAAgB,EAAE,gBAAgB,GAAG,YAAY,CAAC,GAAG,IAAI,CAehE"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
function trigramSimilarity(a, b) {
|
|
2
|
+
const trigrams = (s) => {
|
|
3
|
+
const set = new Set();
|
|
4
|
+
const padded = ` ${s.toLowerCase()} `;
|
|
5
|
+
for (let i = 0; i < padded.length - 2; i++) {
|
|
6
|
+
set.add(padded.slice(i, i + 3));
|
|
7
|
+
}
|
|
8
|
+
return set;
|
|
9
|
+
};
|
|
10
|
+
const ta = trigrams(a);
|
|
11
|
+
const tb = trigrams(b);
|
|
12
|
+
const intersection = [...ta].filter(t => tb.has(t)).length;
|
|
13
|
+
const union = new Set([...ta, ...tb]).size;
|
|
14
|
+
return union === 0 ? 0 : intersection / union;
|
|
15
|
+
}
|
|
16
|
+
const MIN_SIMILARITY = 0.25;
|
|
17
|
+
const MIN_RUNS = 3;
|
|
18
|
+
export function matchHistory(db, prompt, repo) {
|
|
19
|
+
const candidates = db.prepare('SELECT * FROM tasks WHERE repo = ? AND actual_cost IS NOT NULL ORDER BY created_at DESC LIMIT 100').all(repo);
|
|
20
|
+
const matches = candidates.filter(t => trigramSimilarity(t.prompt_text, prompt) >= MIN_SIMILARITY);
|
|
21
|
+
if (matches.length < MIN_RUNS)
|
|
22
|
+
return null;
|
|
23
|
+
const costs = matches.map(t => t.actual_cost).sort((a, b) => a - b);
|
|
24
|
+
const median = costs[Math.floor(costs.length / 2)];
|
|
25
|
+
return { estimated_cost: median, layer_used: 2 };
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=history-matcher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"history-matcher.js","sourceRoot":"","sources":["../../src/estimation/history-matcher.ts"],"names":[],"mappings":"AAGA,SAAS,iBAAiB,CAAC,CAAS,EAAE,CAAS;IAC7C,MAAM,QAAQ,GAAG,CAAC,CAAS,EAAe,EAAE;QAC1C,MAAM,GAAG,GAAG,IAAI,GAAG,EAAU,CAAA;QAC7B,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,WAAW,EAAE,IAAI,CAAA;QACvC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YAC3C,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;QACjC,CAAC;QACD,OAAO,GAAG,CAAA;IACZ,CAAC,CAAA;IAED,MAAM,EAAE,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAA;IACtB,MAAM,EAAE,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAA;IACtB,MAAM,YAAY,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAA;IAC1D,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,CAAA;IAC1C,OAAO,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,YAAY,GAAG,KAAK,CAAA;AAC/C,CAAC;AAED,MAAM,cAAc,GAAG,IAAI,CAAA;AAC3B,MAAM,QAAQ,GAAG,CAAC,CAAA;AAElB,MAAM,UAAU,YAAY,CAC1B,EAAM,EACN,MAAc,EACd,IAAmB;IAEnB,MAAM,UAAU,GAAG,EAAE,CAAC,OAAO,CAC3B,mGAAmG,CACpG,CAAC,GAAG,CAAC,IAAI,CAAiB,CAAA;IAE3B,MAAM,OAAO,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CACpC,iBAAiB,CAAC,CAAC,CAAC,WAAW,EAAE,MAAM,CAAC,IAAI,cAAc,CAC3D,CAAA;IAED,IAAI,OAAO,CAAC,MAAM,GAAG,QAAQ;QAAE,OAAO,IAAI,CAAA;IAE1C,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,WAAY,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA;IACpE,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAA;IAElD,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC,EAAE,CAAA;AAClD,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"llm-precheck.d.ts","sourceRoot":"","sources":["../../src/estimation/llm-precheck.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAI7C,wBAAsB,WAAW,CAC/B,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,MAAM,EACrB,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAiB5B"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import Anthropic from '@anthropic-ai/sdk';
|
|
2
|
+
const VALID_COMPLEXITIES = new Set(['low', 'medium', 'heavy', 'critical']);
|
|
3
|
+
export async function llmClassify(prompt, repoFileCount, model) {
|
|
4
|
+
try {
|
|
5
|
+
const client = new Anthropic();
|
|
6
|
+
const message = await client.messages.create({
|
|
7
|
+
model,
|
|
8
|
+
max_tokens: 10,
|
|
9
|
+
messages: [{
|
|
10
|
+
role: 'user',
|
|
11
|
+
content: `Classify this coding task complexity: low | medium | heavy | critical\nTask: "${prompt}"\nRepo: ${repoFileCount} files\nReply with exactly one word.`
|
|
12
|
+
}]
|
|
13
|
+
});
|
|
14
|
+
const text = message.content[0].text.trim().toLowerCase();
|
|
15
|
+
return VALID_COMPLEXITIES.has(text) ? text : null;
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=llm-precheck.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"llm-precheck.js","sourceRoot":"","sources":["../../src/estimation/llm-precheck.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,mBAAmB,CAAA;AAGzC,MAAM,kBAAkB,GAAG,IAAI,GAAG,CAAa,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC,CAAA;AAEtF,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,MAAc,EACd,aAAqB,EACrB,KAAa;IAEb,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,SAAS,EAAE,CAAA;QAC9B,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC;YAC3C,KAAK;YACL,UAAU,EAAE,EAAE;YACd,QAAQ,EAAE,CAAC;oBACT,IAAI,EAAE,MAAM;oBACZ,OAAO,EAAE,iFAAiF,MAAM,YAAY,aAAa,sCAAsC;iBAChK,CAAC;SACH,CAAC,CAAA;QAEF,MAAM,IAAI,GAAI,OAAO,CAAC,OAAO,CAAC,CAAC,CAAoC,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,WAAW,EAAgB,CAAA;QAC3G,OAAO,kBAAkB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAA;IACnD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAA;IACb,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { DB } from '../storage/db.js';
|
|
2
|
+
import type { EstimationResult } from '../types.js';
|
|
3
|
+
interface PipelineInput {
|
|
4
|
+
prompt: string;
|
|
5
|
+
repoFileCount: number;
|
|
6
|
+
db: DB | null;
|
|
7
|
+
repo: string | null;
|
|
8
|
+
config: {
|
|
9
|
+
use_llm_precheck: boolean;
|
|
10
|
+
llm_precheck_model: string;
|
|
11
|
+
min_confidence_to_skip_llm: number;
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
export declare function runEstimationPipeline(input: PipelineInput): Promise<EstimationResult>;
|
|
15
|
+
export {};
|
|
16
|
+
//# sourceMappingURL=pipeline.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pipeline.d.ts","sourceRoot":"","sources":["../../src/estimation/pipeline.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAA;AAC1C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AAInD,UAAU,aAAa;IACrB,MAAM,EAAE,MAAM,CAAA;IACd,aAAa,EAAE,MAAM,CAAA;IACrB,EAAE,EAAE,EAAE,GAAG,IAAI,CAAA;IACb,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IACnB,MAAM,EAAE;QACN,gBAAgB,EAAE,OAAO,CAAA;QACzB,kBAAkB,EAAE,MAAM,CAAA;QAC1B,0BAA0B,EAAE,MAAM,CAAA;KACnC,CAAA;CACF;AAED,wBAAsB,qBAAqB,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,gBAAgB,CAAC,CA8C3F"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { scoreHeuristics } from './heuristics.js';
|
|
2
|
+
import { matchHistory } from './history-matcher.js';
|
|
3
|
+
import { llmClassify } from './llm-precheck.js';
|
|
4
|
+
const COST_BY_COMPLEXITY = { low: 0.02, medium: 0.09, heavy: 0.38, critical: 0.80 };
|
|
5
|
+
export async function runEstimationPipeline(input) {
|
|
6
|
+
// Layer 1: heuristics
|
|
7
|
+
const heuristic = scoreHeuristics({ prompt: input.prompt, repoFileCount: input.repoFileCount });
|
|
8
|
+
if (heuristic.confidence >= input.config.min_confidence_to_skip_llm) {
|
|
9
|
+
return {
|
|
10
|
+
complexity: heuristic.complexity,
|
|
11
|
+
confidence: heuristic.confidence,
|
|
12
|
+
estimated_cost: COST_BY_COMPLEXITY[heuristic.complexity],
|
|
13
|
+
layer_used: 1
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
// Layer 2: historical baseline
|
|
17
|
+
if (input.db && input.repo) {
|
|
18
|
+
const historical = matchHistory(input.db, input.prompt, input.repo);
|
|
19
|
+
if (historical?.estimated_cost !== undefined) {
|
|
20
|
+
return {
|
|
21
|
+
complexity: heuristic.complexity,
|
|
22
|
+
confidence: 0.8,
|
|
23
|
+
estimated_cost: historical.estimated_cost,
|
|
24
|
+
layer_used: 2
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
// Layer 3: LLM pre-call
|
|
29
|
+
if (input.config.use_llm_precheck) {
|
|
30
|
+
const llmResult = await llmClassify(input.prompt, input.repoFileCount, input.config.llm_precheck_model);
|
|
31
|
+
if (llmResult) {
|
|
32
|
+
return {
|
|
33
|
+
complexity: llmResult,
|
|
34
|
+
confidence: 0.87,
|
|
35
|
+
estimated_cost: COST_BY_COMPLEXITY[llmResult],
|
|
36
|
+
layer_used: 3
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
// Fallback: use heuristic
|
|
41
|
+
return {
|
|
42
|
+
complexity: heuristic.complexity,
|
|
43
|
+
confidence: heuristic.confidence,
|
|
44
|
+
estimated_cost: COST_BY_COMPLEXITY[heuristic.complexity],
|
|
45
|
+
layer_used: 1
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=pipeline.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pipeline.js","sourceRoot":"","sources":["../../src/estimation/pipeline.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AACnD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAI/C,MAAM,kBAAkB,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAA;AAcnF,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,KAAoB;IAC9D,sBAAsB;IACtB,MAAM,SAAS,GAAG,eAAe,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,aAAa,EAAE,KAAK,CAAC,aAAa,EAAE,CAAC,CAAA;IAE/F,IAAI,SAAS,CAAC,UAAU,IAAI,KAAK,CAAC,MAAM,CAAC,0BAA0B,EAAE,CAAC;QACpE,OAAO;YACL,UAAU,EAAE,SAAS,CAAC,UAAU;YAChC,UAAU,EAAE,SAAS,CAAC,UAAU;YAChC,cAAc,EAAE,kBAAkB,CAAC,SAAS,CAAC,UAAU,CAAC;YACxD,UAAU,EAAE,CAAC;SACd,CAAA;IACH,CAAC;IAED,+BAA+B;IAC/B,IAAI,KAAK,CAAC,EAAE,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC;QAC3B,MAAM,UAAU,GAAG,YAAY,CAAC,KAAK,CAAC,EAAE,EAAE,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,CAAA;QACnE,IAAI,UAAU,EAAE,cAAc,KAAK,SAAS,EAAE,CAAC;YAC7C,OAAO;gBACL,UAAU,EAAE,SAAS,CAAC,UAAU;gBAChC,UAAU,EAAE,GAAG;gBACf,cAAc,EAAE,UAAU,CAAC,cAAc;gBACzC,UAAU,EAAE,CAAC;aACd,CAAA;QACH,CAAC;IACH,CAAC;IAED,wBAAwB;IACxB,IAAI,KAAK,CAAC,MAAM,CAAC,gBAAgB,EAAE,CAAC;QAClC,MAAM,SAAS,GAAG,MAAM,WAAW,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,aAAa,EAAE,KAAK,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAA;QACvG,IAAI,SAAS,EAAE,CAAC;YACd,OAAO;gBACL,UAAU,EAAE,SAAS;gBACrB,UAAU,EAAE,IAAI;gBAChB,cAAc,EAAE,kBAAkB,CAAC,SAAS,CAAC;gBAC7C,UAAU,EAAE,CAAC;aACd,CAAA;QACH,CAAC;IACH,CAAC;IAED,0BAA0B;IAC1B,OAAO;QACL,UAAU,EAAE,SAAS,CAAC,UAAU;QAChC,UAAU,EAAE,SAAS,CAAC,UAAU;QAChC,cAAc,EAAE,kBAAkB,CAAC,SAAS,CAAC,UAAU,CAAC;QACxD,UAAU,EAAE,CAAC;KACd,CAAA;AACH,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { runInit } from './commands/init.js';
|
|
3
|
+
import { runStatus } from './commands/status.js';
|
|
4
|
+
import { runReport } from './commands/report.js';
|
|
5
|
+
import { runHistory } from './commands/history.js';
|
|
6
|
+
import { runConfig } from './commands/config.js';
|
|
7
|
+
import { runUninstall } from './commands/uninstall.js';
|
|
8
|
+
import { runWrap } from './commands/wrap.js';
|
|
9
|
+
import { METER_DIR } from './constants.js';
|
|
10
|
+
const [, , command, ...args] = process.argv;
|
|
11
|
+
const commands = {
|
|
12
|
+
init: () => runInit({ meterDir: METER_DIR }),
|
|
13
|
+
status: runStatus,
|
|
14
|
+
report: runReport,
|
|
15
|
+
history: () => runHistory(args),
|
|
16
|
+
config: () => runConfig(args),
|
|
17
|
+
uninstall: runUninstall,
|
|
18
|
+
wrap: () => runWrap(args),
|
|
19
|
+
};
|
|
20
|
+
async function main() {
|
|
21
|
+
if (!command || command === '--help' || command === '-h') {
|
|
22
|
+
console.log(`
|
|
23
|
+
◆ meter — intelligent wrapper for Claude Code
|
|
24
|
+
|
|
25
|
+
meter init Set up PATH shim and config
|
|
26
|
+
meter status Show current mode, usage, and config
|
|
27
|
+
meter report Weekly digest of usage and costs
|
|
28
|
+
meter history Browse past task records
|
|
29
|
+
meter config View and set configuration values
|
|
30
|
+
meter uninstall Remove meter completely
|
|
31
|
+
`);
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
const handler = commands[command];
|
|
35
|
+
if (!handler) {
|
|
36
|
+
console.error(`Unknown command: ${command}`);
|
|
37
|
+
process.exit(1);
|
|
38
|
+
}
|
|
39
|
+
await handler();
|
|
40
|
+
}
|
|
41
|
+
main().catch(err => {
|
|
42
|
+
console.error('[meter error]', err.message);
|
|
43
|
+
process.exit(1);
|
|
44
|
+
});
|
|
45
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAA;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAA;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAA;AAChD,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAA;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAA;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAA;AACtD,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAA;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAE1C,MAAM,CAAC,EAAC,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,CAAA;AAE1C,MAAM,QAAQ,GAAwC;IACpD,IAAI,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC;IAC5C,MAAM,EAAE,SAAS;IACjB,MAAM,EAAE,SAAS;IACjB,OAAO,EAAE,GAAG,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC;IAC/B,MAAM,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC;IAC7B,SAAS,EAAE,YAAY;IACvB,IAAI,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;CAC1B,CAAA;AAED,KAAK,UAAU,IAAI;IACjB,IAAI,CAAC,OAAO,IAAI,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;QACzD,OAAO,CAAC,GAAG,CAAC;;;;;;;;;CASf,CAAC,CAAA;QACE,OAAM;IACR,CAAC;IAED,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAA;IACjC,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,oBAAoB,OAAO,EAAE,CAAC,CAAA;QAC5C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC;IAED,MAAM,OAAO,EAAE,CAAA;AACjB,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE;IACjB,OAAO,CAAC,KAAK,CAAC,eAAe,EAAE,GAAG,CAAC,OAAO,CAAC,CAAA;IAC3C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;AACjB,CAAC,CAAC,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resize.d.ts","sourceRoot":"","sources":["../../src/pty/resize.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;CACb;AAED,wBAAgB,eAAe,IAAI,YAAY,CAK9C;AAED,wBAAgB,uBAAuB,CAAC,kBAAkB,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAExF"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export function getTerminalSize() {
|
|
2
|
+
return {
|
|
3
|
+
cols: process.stdout.columns ?? 80,
|
|
4
|
+
rows: process.stdout.rows ?? 24,
|
|
5
|
+
};
|
|
6
|
+
}
|
|
7
|
+
export function calculateStatusBarLines(statusBarCharCount, cols) {
|
|
8
|
+
return Math.ceil(statusBarCharCount / cols);
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=resize.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resize.js","sourceRoot":"","sources":["../../src/pty/resize.ts"],"names":[],"mappings":"AAKA,MAAM,UAAU,eAAe;IAC7B,OAAO;QACL,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,OAAO,IAAI,EAAE;QAClC,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,IAAI,IAAI,EAAE;KAChC,CAAA;AACH,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,kBAA0B,EAAE,IAAY;IAC9E,OAAO,IAAI,CAAC,IAAI,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAAA;AAC7C,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"screen.d.ts","sourceRoot":"","sources":["../../src/pty/screen.ts"],"names":[],"mappings":"AAGA,qBAAa,sBAAsB;IACjC,OAAO,CAAC,SAAS,CAAQ;IAEzB,IAAI,QAAQ,IAAI,OAAO,CAEtB;IAED,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;CAI7B"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
const ENTER_ALT_SCREEN = '\x1b[?1049h';
|
|
2
|
+
const EXIT_ALT_SCREEN = '\x1b[?1049l';
|
|
3
|
+
export class AlternateScreenTracker {
|
|
4
|
+
_isActive = false;
|
|
5
|
+
get isActive() {
|
|
6
|
+
return this._isActive;
|
|
7
|
+
}
|
|
8
|
+
process(chunk) {
|
|
9
|
+
if (chunk.includes(ENTER_ALT_SCREEN))
|
|
10
|
+
this._isActive = true;
|
|
11
|
+
if (chunk.includes(EXIT_ALT_SCREEN))
|
|
12
|
+
this._isActive = false;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=screen.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"screen.js","sourceRoot":"","sources":["../../src/pty/screen.ts"],"names":[],"mappings":"AAAA,MAAM,gBAAgB,GAAG,aAAa,CAAA;AACtC,MAAM,eAAe,GAAG,aAAa,CAAA;AAErC,MAAM,OAAO,sBAAsB;IACzB,SAAS,GAAG,KAAK,CAAA;IAEzB,IAAI,QAAQ;QACV,OAAO,IAAI,CAAC,SAAS,CAAA;IACvB,CAAC;IAED,OAAO,CAAC,KAAa;QACnB,IAAI,KAAK,CAAC,QAAQ,CAAC,gBAAgB,CAAC;YAAE,IAAI,CAAC,SAAS,GAAG,IAAI,CAAA;QAC3D,IAAI,KAAK,CAAC,QAAQ,CAAC,eAAe,CAAC;YAAE,IAAI,CAAC,SAAS,GAAG,KAAK,CAAA;IAC7D,CAAC;CACF"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { EventEmitter } from 'events';
|
|
2
|
+
export interface WrapperEvents {
|
|
3
|
+
data: (chunk: string) => void;
|
|
4
|
+
exit: (code: number, signal: number) => void;
|
|
5
|
+
}
|
|
6
|
+
export declare class PtyWrapper extends EventEmitter {
|
|
7
|
+
private ptyProcess;
|
|
8
|
+
private screenTracker;
|
|
9
|
+
get isInAlternateScreen(): boolean;
|
|
10
|
+
spawn(binary: string, args: string[], env: NodeJS.ProcessEnv): void;
|
|
11
|
+
write(data: string): void;
|
|
12
|
+
kill(signal?: string): void;
|
|
13
|
+
resize(cols: number, rows: number): void;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=wrapper.d.ts.map
|