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.
Files changed (126) hide show
  1. package/README.md +124 -0
  2. package/dist/auth/credentials.d.ts +9 -0
  3. package/dist/auth/credentials.d.ts.map +1 -0
  4. package/dist/auth/credentials.js +32 -0
  5. package/dist/auth/credentials.js.map +1 -0
  6. package/dist/auth/detect.d.ts +7 -0
  7. package/dist/auth/detect.d.ts.map +1 -0
  8. package/dist/auth/detect.js +20 -0
  9. package/dist/auth/detect.js.map +1 -0
  10. package/dist/commands/config.d.ts +2 -0
  11. package/dist/commands/config.d.ts.map +1 -0
  12. package/dist/commands/config.js +26 -0
  13. package/dist/commands/config.js.map +1 -0
  14. package/dist/commands/history.d.ts +2 -0
  15. package/dist/commands/history.d.ts.map +1 -0
  16. package/dist/commands/history.js +19 -0
  17. package/dist/commands/history.js.map +1 -0
  18. package/dist/commands/init.d.ts +10 -0
  19. package/dist/commands/init.d.ts.map +1 -0
  20. package/dist/commands/init.js +58 -0
  21. package/dist/commands/init.js.map +1 -0
  22. package/dist/commands/report.d.ts +2 -0
  23. package/dist/commands/report.d.ts.map +1 -0
  24. package/dist/commands/report.js +37 -0
  25. package/dist/commands/report.js.map +1 -0
  26. package/dist/commands/status.d.ts +2 -0
  27. package/dist/commands/status.d.ts.map +1 -0
  28. package/dist/commands/status.js +20 -0
  29. package/dist/commands/status.js.map +1 -0
  30. package/dist/commands/uninstall.d.ts +2 -0
  31. package/dist/commands/uninstall.d.ts.map +1 -0
  32. package/dist/commands/uninstall.js +20 -0
  33. package/dist/commands/uninstall.js.map +1 -0
  34. package/dist/commands/wrap.d.ts +2 -0
  35. package/dist/commands/wrap.d.ts.map +1 -0
  36. package/dist/commands/wrap.js +189 -0
  37. package/dist/commands/wrap.js.map +1 -0
  38. package/dist/constants.d.ts +30 -0
  39. package/dist/constants.d.ts.map +1 -0
  40. package/dist/constants.js +48 -0
  41. package/dist/constants.js.map +1 -0
  42. package/dist/estimation/heuristics.d.ts +8 -0
  43. package/dist/estimation/heuristics.d.ts.map +1 -0
  44. package/dist/estimation/heuristics.js +28 -0
  45. package/dist/estimation/heuristics.js.map +1 -0
  46. package/dist/estimation/history-matcher.d.ts +4 -0
  47. package/dist/estimation/history-matcher.d.ts.map +1 -0
  48. package/dist/estimation/history-matcher.js +27 -0
  49. package/dist/estimation/history-matcher.js.map +1 -0
  50. package/dist/estimation/llm-precheck.d.ts +3 -0
  51. package/dist/estimation/llm-precheck.d.ts.map +1 -0
  52. package/dist/estimation/llm-precheck.js +21 -0
  53. package/dist/estimation/llm-precheck.js.map +1 -0
  54. package/dist/estimation/pipeline.d.ts +16 -0
  55. package/dist/estimation/pipeline.d.ts.map +1 -0
  56. package/dist/estimation/pipeline.js +48 -0
  57. package/dist/estimation/pipeline.js.map +1 -0
  58. package/dist/index.d.ts +3 -0
  59. package/dist/index.d.ts.map +1 -0
  60. package/dist/index.js +45 -0
  61. package/dist/index.js.map +1 -0
  62. package/dist/pty/resize.d.ts +7 -0
  63. package/dist/pty/resize.d.ts.map +1 -0
  64. package/dist/pty/resize.js +10 -0
  65. package/dist/pty/resize.js.map +1 -0
  66. package/dist/pty/screen.d.ts +6 -0
  67. package/dist/pty/screen.d.ts.map +1 -0
  68. package/dist/pty/screen.js +15 -0
  69. package/dist/pty/screen.js.map +1 -0
  70. package/dist/pty/wrapper.d.ts +15 -0
  71. package/dist/pty/wrapper.d.ts.map +1 -0
  72. package/dist/pty/wrapper.js +49 -0
  73. package/dist/pty/wrapper.js.map +1 -0
  74. package/dist/shell/binary-resolver.d.ts +2 -0
  75. package/dist/shell/binary-resolver.d.ts.map +1 -0
  76. package/dist/shell/binary-resolver.js +18 -0
  77. package/dist/shell/binary-resolver.js.map +1 -0
  78. package/dist/shell/detect.d.ts +5 -0
  79. package/dist/shell/detect.d.ts.map +1 -0
  80. package/dist/shell/detect.js +32 -0
  81. package/dist/shell/detect.js.map +1 -0
  82. package/dist/shell/path-inject.d.ts +5 -0
  83. package/dist/shell/path-inject.d.ts.map +1 -0
  84. package/dist/shell/path-inject.js +30 -0
  85. package/dist/shell/path-inject.js.map +1 -0
  86. package/dist/shell/shim-writer.d.ts +3 -0
  87. package/dist/shell/shim-writer.d.ts.map +1 -0
  88. package/dist/shell/shim-writer.js +22 -0
  89. package/dist/shell/shim-writer.js.map +1 -0
  90. package/dist/storage/config-store.d.ts +10 -0
  91. package/dist/storage/config-store.d.ts.map +1 -0
  92. package/dist/storage/config-store.js +42 -0
  93. package/dist/storage/config-store.js.map +1 -0
  94. package/dist/storage/db.d.ts +7 -0
  95. package/dist/storage/db.d.ts.map +1 -0
  96. package/dist/storage/db.js +53 -0
  97. package/dist/storage/db.js.map +1 -0
  98. package/dist/tracking/cost.d.ts +6 -0
  99. package/dist/tracking/cost.d.ts.map +1 -0
  100. package/dist/tracking/cost.js +6 -0
  101. package/dist/tracking/cost.js.map +1 -0
  102. package/dist/tracking/plan-usage.d.ts +6 -0
  103. package/dist/tracking/plan-usage.d.ts.map +1 -0
  104. package/dist/tracking/plan-usage.js +53 -0
  105. package/dist/tracking/plan-usage.js.map +1 -0
  106. package/dist/tracking/tokens.d.ts +7 -0
  107. package/dist/tracking/tokens.d.ts.map +1 -0
  108. package/dist/tracking/tokens.js +14 -0
  109. package/dist/tracking/tokens.js.map +1 -0
  110. package/dist/types.d.ts +70 -0
  111. package/dist/types.d.ts.map +1 -0
  112. package/dist/types.js +2 -0
  113. package/dist/types.js.map +1 -0
  114. package/dist/ui/keypress.d.ts +3 -0
  115. package/dist/ui/keypress.d.ts.map +1 -0
  116. package/dist/ui/keypress.js +20 -0
  117. package/dist/ui/keypress.js.map +1 -0
  118. package/dist/ui/notification.d.ts +11 -0
  119. package/dist/ui/notification.d.ts.map +1 -0
  120. package/dist/ui/notification.js +18 -0
  121. package/dist/ui/notification.js.map +1 -0
  122. package/dist/ui/statusbar.d.ts +15 -0
  123. package/dist/ui/statusbar.d.ts.map +1 -0
  124. package/dist/ui/statusbar.js +53 -0
  125. package/dist/ui/statusbar.js.map +1 -0
  126. 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,3 @@
1
+ import type { Complexity } from '../types.js';
2
+ export declare function llmClassify(prompt: string, repoFileCount: number, model: string): Promise<Complexity | null>;
3
+ //# sourceMappingURL=llm-precheck.d.ts.map
@@ -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"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -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,7 @@
1
+ export interface TerminalSize {
2
+ cols: number;
3
+ rows: number;
4
+ }
5
+ export declare function getTerminalSize(): TerminalSize;
6
+ export declare function calculateStatusBarLines(statusBarCharCount: number, cols: number): number;
7
+ //# sourceMappingURL=resize.d.ts.map
@@ -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,6 @@
1
+ export declare class AlternateScreenTracker {
2
+ private _isActive;
3
+ get isActive(): boolean;
4
+ process(chunk: string): void;
5
+ }
6
+ //# sourceMappingURL=screen.d.ts.map
@@ -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