meter-ai 0.1.2 → 0.3.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/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +74 -3
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/wrap.d.ts.map +1 -1
- package/dist/commands/wrap.js +23 -2
- package/dist/commands/wrap.js.map +1 -1
- package/dist/pty/wrapper.d.ts +9 -8
- package/dist/pty/wrapper.d.ts.map +1 -1
- package/dist/pty/wrapper.js +39 -14
- package/dist/pty/wrapper.js.map +1 -1
- package/package.json +1 -1
- package/src/auth/credentials.ts +44 -0
- package/src/auth/detect.ts +24 -0
- package/src/commands/config.ts +19 -0
- package/src/commands/history.ts +16 -0
- package/src/commands/init.ts +149 -0
- package/src/commands/report.ts +27 -0
- package/src/commands/status.ts +16 -0
- package/src/commands/uninstall.ts +20 -0
- package/src/commands/wrap.ts +235 -0
- package/src/constants.ts +52 -0
- package/src/estimation/heuristics.ts +36 -0
- package/src/estimation/history-matcher.ts +43 -0
- package/src/estimation/llm-precheck.ts +27 -0
- package/src/estimation/pipeline.ts +67 -0
- package/src/hooks/on-prompt.js +92 -0
- package/src/hooks/statusline.js +36 -0
- package/src/index.ts +50 -0
- package/src/pty/resize.ts +15 -0
- package/src/pty/screen.ts +15 -0
- package/src/pty/wrapper.ts +143 -0
- package/src/shell/binary-resolver.ts +21 -0
- package/src/shell/detect.ts +33 -0
- package/src/shell/path-inject.ts +31 -0
- package/src/shell/shim-writer.ts +28 -0
- package/src/storage/config-store.ts +46 -0
- package/src/storage/db.ts +63 -0
- package/src/tracking/cost.ts +7 -0
- package/src/tracking/plan-usage.ts +57 -0
- package/src/tracking/tokens.ts +16 -0
- package/src/types.ts +73 -0
- package/src/ui/keypress.ts +27 -0
- package/src/ui/notification.ts +31 -0
- package/src/ui/statusbar.ts +74 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AAE3C,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,IAAI,CAAC,EAAE,QAAQ,CAAA;IACf,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAC3B,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CACtB;AAED,wBAAsB,OAAO,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAwD9D"}
|
package/dist/commands/init.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { mkdir } from 'fs/promises';
|
|
2
|
-
import { join } from 'path';
|
|
1
|
+
import { mkdir, readFile, writeFile, copyFile, chmod } from 'fs/promises';
|
|
2
|
+
import { join, dirname } from 'path';
|
|
3
|
+
import { fileURLToPath } from 'url';
|
|
3
4
|
import { detectShell, getShellConfigPath } from '../shell/detect.js';
|
|
4
5
|
import { resolveTrueBinary } from '../shell/binary-resolver.js';
|
|
5
6
|
import { writeShim } from '../shell/shim-writer.js';
|
|
@@ -8,7 +9,7 @@ import { writeConfig, ensureConfigDefaults } from '../storage/config-store.js';
|
|
|
8
9
|
import { detectMode } from '../auth/detect.js';
|
|
9
10
|
import { readCredentials } from '../auth/credentials.js';
|
|
10
11
|
import { resolveOrgId } from '../tracking/plan-usage.js';
|
|
11
|
-
import { CLAUDE_CREDENTIALS_PATH } from '../constants.js';
|
|
12
|
+
import { CLAUDE_CREDENTIALS_PATH, CLAUDE_SETTINGS_PATH } from '../constants.js';
|
|
12
13
|
export async function runInit(opts) {
|
|
13
14
|
const meterDir = opts.meterDir;
|
|
14
15
|
const binDir = join(meterDir, 'bin');
|
|
@@ -52,7 +53,77 @@ export async function runInit(opts) {
|
|
|
52
53
|
...(orgId ? { org_id: orgId } : {}),
|
|
53
54
|
});
|
|
54
55
|
await writeConfig(join(meterDir, 'config.json'), config);
|
|
56
|
+
// Install Claude Code hooks (skip in tests)
|
|
57
|
+
if (!opts.skipPathInjection) {
|
|
58
|
+
await installClaudeHooks(meterDir);
|
|
59
|
+
}
|
|
55
60
|
console.log(`✓ meter initialised (${mode} mode)`);
|
|
56
61
|
console.log(` Restart your terminal or run: source ~/.zshrc`);
|
|
57
62
|
}
|
|
63
|
+
async function installClaudeHooks(meterDir) {
|
|
64
|
+
const hooksDir = join(meterDir, 'hooks');
|
|
65
|
+
await mkdir(hooksDir, { recursive: true });
|
|
66
|
+
// Copy hook scripts to ~/.meter/hooks/
|
|
67
|
+
const srcDir = join(dirname(fileURLToPath(import.meta.url)), '..', 'hooks');
|
|
68
|
+
for (const file of ['on-prompt.js', 'statusline.js']) {
|
|
69
|
+
try {
|
|
70
|
+
await copyFile(join(srcDir, file), join(hooksDir, file));
|
|
71
|
+
await chmod(join(hooksDir, file), 0o755);
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
// If source doesn't exist (running from dist), try the dist/hooks path
|
|
75
|
+
const distDir = join(dirname(fileURLToPath(import.meta.url)), '..', '..', 'src', 'hooks');
|
|
76
|
+
try {
|
|
77
|
+
await copyFile(join(distDir, file), join(hooksDir, file));
|
|
78
|
+
await chmod(join(hooksDir, file), 0o755);
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
console.warn(` ⚠ Could not copy ${file} — skipping hook installation`);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
// Update Claude Code settings.json to add meter hooks
|
|
86
|
+
try {
|
|
87
|
+
let settings = {};
|
|
88
|
+
try {
|
|
89
|
+
settings = JSON.parse(await readFile(CLAUDE_SETTINGS_PATH, 'utf-8'));
|
|
90
|
+
}
|
|
91
|
+
catch {
|
|
92
|
+
// settings file doesn't exist yet — we'll create it
|
|
93
|
+
}
|
|
94
|
+
// Add UserPromptSubmit hook if not already present
|
|
95
|
+
const meterHookCommand = `node "${join(hooksDir, 'on-prompt.js')}"`;
|
|
96
|
+
if (!settings.hooks)
|
|
97
|
+
settings.hooks = {};
|
|
98
|
+
if (!settings.hooks.UserPromptSubmit)
|
|
99
|
+
settings.hooks.UserPromptSubmit = [];
|
|
100
|
+
const alreadyHasHook = settings.hooks.UserPromptSubmit.some((h) => h.hooks?.some((hh) => hh.command?.includes('meter')));
|
|
101
|
+
if (!alreadyHasHook) {
|
|
102
|
+
settings.hooks.UserPromptSubmit.push({
|
|
103
|
+
hooks: [{ type: 'command', command: meterHookCommand }]
|
|
104
|
+
});
|
|
105
|
+
console.log('✓ Added meter estimation hook to Claude Code');
|
|
106
|
+
}
|
|
107
|
+
// Add/update statusline command
|
|
108
|
+
const meterStatuslineCommand = `node "${join(hooksDir, 'statusline.js')}"`;
|
|
109
|
+
const existingStatusLine = settings.statusLine;
|
|
110
|
+
if (!existingStatusLine || existingStatusLine.command?.includes('meter')) {
|
|
111
|
+
// No existing statusline or it's ours — set it
|
|
112
|
+
settings.statusLine = { type: 'command', command: meterStatuslineCommand };
|
|
113
|
+
console.log('✓ Added meter statusline to Claude Code');
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
// There's an existing statusline from another tool — chain them
|
|
117
|
+
// Create a wrapper that runs both
|
|
118
|
+
const chainCommand = `${existingStatusLine.command} && echo " │ " && ${meterStatuslineCommand}`;
|
|
119
|
+
settings.statusLine = { type: 'command', command: chainCommand };
|
|
120
|
+
console.log('✓ Chained meter statusline with existing statusline');
|
|
121
|
+
}
|
|
122
|
+
await mkdir(dirname(CLAUDE_SETTINGS_PATH), { recursive: true });
|
|
123
|
+
await writeFile(CLAUDE_SETTINGS_PATH, JSON.stringify(settings, null, 2), 'utf-8');
|
|
124
|
+
}
|
|
125
|
+
catch (err) {
|
|
126
|
+
console.warn(` ⚠ Could not update Claude Code settings: ${err}`);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
58
129
|
//# sourceMappingURL=init.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wrap.d.ts","sourceRoot":"","sources":["../../src/commands/wrap.ts"],"names":[],"mappings":"AAmBA,wBAAsB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"wrap.d.ts","sourceRoot":"","sources":["../../src/commands/wrap.ts"],"names":[],"mappings":"AAmBA,wBAAsB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAuN3D"}
|
package/dist/commands/wrap.js
CHANGED
|
@@ -119,6 +119,26 @@ export async function runWrap(args) {
|
|
|
119
119
|
}
|
|
120
120
|
}, 15_000);
|
|
121
121
|
}
|
|
122
|
+
// Per-prompt estimation: when user submits a new prompt inside the interactive
|
|
123
|
+
// session, re-run the estimation pipeline and update the status bar
|
|
124
|
+
let lastPrompt = prompt; // initial prompt from CLI args
|
|
125
|
+
wrapper.on('input', async (newPrompt) => {
|
|
126
|
+
lastPrompt = newPrompt;
|
|
127
|
+
const newEstimation = await runEstimationPipeline({
|
|
128
|
+
prompt: newPrompt,
|
|
129
|
+
repoFileCount,
|
|
130
|
+
db,
|
|
131
|
+
repo,
|
|
132
|
+
config: config.estimation,
|
|
133
|
+
});
|
|
134
|
+
state.estimatedCost = newEstimation.estimated_cost;
|
|
135
|
+
state.complexity = newEstimation.complexity;
|
|
136
|
+
// Reset elapsed cost for the new prompt
|
|
137
|
+
state.elapsedCost = 0;
|
|
138
|
+
thresholdNotified = false;
|
|
139
|
+
statusBarShown = false; // allow fallback mode to re-print
|
|
140
|
+
updateBar();
|
|
141
|
+
});
|
|
122
142
|
wrapper.on('data', (chunk) => {
|
|
123
143
|
outputBuffer += chunk;
|
|
124
144
|
// Rough running cost estimate from output volume
|
|
@@ -176,12 +196,13 @@ export async function runWrap(args) {
|
|
|
176
196
|
clearInterval(pollInterval);
|
|
177
197
|
// Parse final token counts
|
|
178
198
|
const tokens = parseTokensFromOutput(outputBuffer);
|
|
179
|
-
const
|
|
199
|
+
const finalPrompt = lastPrompt || prompt;
|
|
200
|
+
const promptHash = createHash('sha256').update(finalPrompt.toLowerCase().trim()).digest('hex').slice(0, 16);
|
|
180
201
|
insertTask(db, {
|
|
181
202
|
created_at: taskStart,
|
|
182
203
|
repo,
|
|
183
204
|
prompt_hash: promptHash,
|
|
184
|
-
prompt_text:
|
|
205
|
+
prompt_text: finalPrompt,
|
|
185
206
|
model: state.model,
|
|
186
207
|
complexity: estimation.complexity,
|
|
187
208
|
est_layer: estimation.layer_used,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wrap.js","sourceRoot":"","sources":["../../src/commands/wrap.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"wrap.js","sourceRoot":"","sources":["../../src/commands/wrap.ts"],"names":[],"mappings":"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"}
|
package/dist/pty/wrapper.d.ts
CHANGED
|
@@ -1,25 +1,26 @@
|
|
|
1
1
|
import { EventEmitter } from 'events';
|
|
2
2
|
export interface WrapperEvents {
|
|
3
3
|
data: (chunk: string) => void;
|
|
4
|
+
input: (prompt: string) => void;
|
|
4
5
|
exit: (code: number, signal: number) => void;
|
|
5
6
|
}
|
|
6
7
|
/**
|
|
7
|
-
* PtyWrapper with automatic fallback.
|
|
8
|
+
* PtyWrapper with automatic fallback and input capture.
|
|
8
9
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
10
|
+
* In PTY mode:
|
|
11
|
+
* - Captures all user input keystroke by keystroke
|
|
12
|
+
* - Buffers input and emits 'input' event on Enter (prompt submission)
|
|
13
|
+
* - This enables per-prompt estimation during interactive sessions
|
|
13
14
|
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
* at a fixed terminal position.
|
|
15
|
+
* In fallback mode:
|
|
16
|
+
* - stdio is inherited, no input capture possible
|
|
17
17
|
*/
|
|
18
18
|
export declare class PtyWrapper extends EventEmitter {
|
|
19
19
|
private ptyProcess;
|
|
20
20
|
private childProcess;
|
|
21
21
|
private screenTracker;
|
|
22
22
|
private _usingFallback;
|
|
23
|
+
private inputBuffer;
|
|
23
24
|
get isInAlternateScreen(): boolean;
|
|
24
25
|
get usingFallback(): boolean;
|
|
25
26
|
spawn(binary: string, args: string[], env: NodeJS.ProcessEnv): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wrapper.d.ts","sourceRoot":"","sources":["../../src/pty/wrapper.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAA;AAKrC,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IAC7B,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAA;CAC7C;AAID
|
|
1
|
+
{"version":3,"file":"wrapper.d.ts","sourceRoot":"","sources":["../../src/pty/wrapper.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAA;AAKrC,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IAC7B,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAA;IAC/B,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAA;CAC7C;AAID;;;;;;;;;;GAUG;AACH,qBAAa,UAAW,SAAQ,YAAY;IAC1C,OAAO,CAAC,UAAU,CAAuC;IACzD,OAAO,CAAC,YAAY,CAA4B;IAChD,OAAO,CAAC,aAAa,CAA+B;IACpD,OAAO,CAAC,cAAc,CAAQ;IAC9B,OAAO,CAAC,WAAW,CAAK;IAExB,IAAI,mBAAmB,IAAI,OAAO,CAEjC;IAED,IAAI,aAAa,IAAI,OAAO,CAE3B;IAED,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,CAAC,UAAU,GAAG,IAAI;IAUnE,OAAO,CAAC,aAAa;IA8DrB,OAAO,CAAC,sBAAsB;IAY9B,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAQzB,IAAI,CAAC,MAAM,GAAE,MAAM,CAAC,OAAmB,GAAG,IAAI;IAQ9C,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;CAGzC"}
|
package/dist/pty/wrapper.js
CHANGED
|
@@ -3,22 +3,22 @@ import { spawn as cpSpawn } from 'child_process';
|
|
|
3
3
|
import { AlternateScreenTracker } from './screen.js';
|
|
4
4
|
import { getTerminalSize } from './resize.js';
|
|
5
5
|
/**
|
|
6
|
-
* PtyWrapper with automatic fallback.
|
|
6
|
+
* PtyWrapper with automatic fallback and input capture.
|
|
7
7
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
8
|
+
* In PTY mode:
|
|
9
|
+
* - Captures all user input keystroke by keystroke
|
|
10
|
+
* - Buffers input and emits 'input' event on Enter (prompt submission)
|
|
11
|
+
* - This enables per-prompt estimation during interactive sessions
|
|
12
12
|
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* at a fixed terminal position.
|
|
13
|
+
* In fallback mode:
|
|
14
|
+
* - stdio is inherited, no input capture possible
|
|
16
15
|
*/
|
|
17
16
|
export class PtyWrapper extends EventEmitter {
|
|
18
17
|
ptyProcess = null;
|
|
19
18
|
childProcess = null;
|
|
20
19
|
screenTracker = new AlternateScreenTracker();
|
|
21
20
|
_usingFallback = false;
|
|
21
|
+
inputBuffer = '';
|
|
22
22
|
get isInAlternateScreen() {
|
|
23
23
|
return this.screenTracker.isActive;
|
|
24
24
|
}
|
|
@@ -26,13 +26,11 @@ export class PtyWrapper extends EventEmitter {
|
|
|
26
26
|
return this._usingFallback;
|
|
27
27
|
}
|
|
28
28
|
spawn(binary, args, env) {
|
|
29
|
-
// Try node-pty first
|
|
30
29
|
try {
|
|
31
30
|
const pty = require('node-pty');
|
|
32
31
|
this._spawnWithPty(pty, binary, args, env);
|
|
33
32
|
}
|
|
34
33
|
catch {
|
|
35
|
-
// node-pty failed — fall back to child_process
|
|
36
34
|
this._usingFallback = true;
|
|
37
35
|
this._spawnWithChildProcess(binary, args, env);
|
|
38
36
|
}
|
|
@@ -54,12 +52,41 @@ export class PtyWrapper extends EventEmitter {
|
|
|
54
52
|
this.ptyProcess.onExit(({ exitCode, signal }) => {
|
|
55
53
|
this.emit('exit', exitCode, signal ?? 0);
|
|
56
54
|
});
|
|
57
|
-
// Forward stdin to PTY
|
|
55
|
+
// Forward stdin to PTY and capture input for per-prompt estimation
|
|
58
56
|
if (process.stdin.isTTY) {
|
|
59
57
|
process.stdin.setRawMode(true);
|
|
60
58
|
}
|
|
61
59
|
process.stdin.on('data', (data) => {
|
|
62
|
-
|
|
60
|
+
const str = data.toString();
|
|
61
|
+
this.ptyProcess?.write(str);
|
|
62
|
+
// Track user input for prompt detection
|
|
63
|
+
for (const char of str) {
|
|
64
|
+
if (char === '\r' || char === '\n') {
|
|
65
|
+
// Enter pressed — emit the buffered input as a prompt
|
|
66
|
+
const prompt = this.inputBuffer.trim();
|
|
67
|
+
if (prompt.length > 0) {
|
|
68
|
+
this.emit('input', prompt);
|
|
69
|
+
}
|
|
70
|
+
this.inputBuffer = '';
|
|
71
|
+
}
|
|
72
|
+
else if (char === '\x7f' || char === '\b') {
|
|
73
|
+
// Backspace — remove last char from buffer
|
|
74
|
+
this.inputBuffer = this.inputBuffer.slice(0, -1);
|
|
75
|
+
}
|
|
76
|
+
else if (char === '\x03') {
|
|
77
|
+
// Ctrl+C — clear buffer
|
|
78
|
+
this.inputBuffer = '';
|
|
79
|
+
}
|
|
80
|
+
else if (char === '\x15') {
|
|
81
|
+
// Ctrl+U — clear line
|
|
82
|
+
this.inputBuffer = '';
|
|
83
|
+
}
|
|
84
|
+
else if (char.charCodeAt(0) >= 32) {
|
|
85
|
+
// Printable character — append to buffer
|
|
86
|
+
this.inputBuffer += char;
|
|
87
|
+
}
|
|
88
|
+
// Ignore other control characters (arrows, escape sequences, etc.)
|
|
89
|
+
}
|
|
63
90
|
});
|
|
64
91
|
// Handle terminal resize
|
|
65
92
|
process.on('SIGWINCH', () => {
|
|
@@ -68,8 +95,6 @@ export class PtyWrapper extends EventEmitter {
|
|
|
68
95
|
});
|
|
69
96
|
}
|
|
70
97
|
_spawnWithChildProcess(binary, args, env) {
|
|
71
|
-
// Use fully inherited stdio so Claude Code's interactive TUI works.
|
|
72
|
-
// We lose per-chunk output capture, but the agent runs correctly.
|
|
73
98
|
this.childProcess = cpSpawn(binary, args, {
|
|
74
99
|
env: { ...env },
|
|
75
100
|
cwd: process.cwd(),
|
package/dist/pty/wrapper.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wrapper.js","sourceRoot":"","sources":["../../src/pty/wrapper.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAA;AACrC,OAAO,EAAE,KAAK,IAAI,OAAO,EAAqB,MAAM,eAAe,CAAA;AACnE,OAAO,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAA;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"wrapper.js","sourceRoot":"","sources":["../../src/pty/wrapper.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { watch } from 'fs'
|
|
2
|
+
import { readFile as readFileAsync } from 'fs/promises'
|
|
3
|
+
|
|
4
|
+
export interface ClaudeCredentials {
|
|
5
|
+
accessToken: string
|
|
6
|
+
refreshToken?: string
|
|
7
|
+
expiresAt?: number
|
|
8
|
+
[key: string]: unknown
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export async function readCredentials(path: string): Promise<ClaudeCredentials | null> {
|
|
12
|
+
async function tryRead(): Promise<ClaudeCredentials | null> {
|
|
13
|
+
try {
|
|
14
|
+
const raw = await readFileAsync(path, 'utf-8')
|
|
15
|
+
return JSON.parse(raw) as ClaudeCredentials
|
|
16
|
+
} catch {
|
|
17
|
+
return null
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const first = await tryRead()
|
|
22
|
+
if (first) return first
|
|
23
|
+
|
|
24
|
+
// retry once after 200ms (handles partial writes on macOS kqueue)
|
|
25
|
+
await new Promise(r => setTimeout(r, 200))
|
|
26
|
+
return tryRead()
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function watchCredentials(
|
|
30
|
+
path: string,
|
|
31
|
+
onChange: (creds: ClaudeCredentials | null) => void
|
|
32
|
+
): () => void {
|
|
33
|
+
let debounceTimer: NodeJS.Timeout | null = null
|
|
34
|
+
|
|
35
|
+
const watcher = watch(path, () => {
|
|
36
|
+
if (debounceTimer) clearTimeout(debounceTimer)
|
|
37
|
+
debounceTimer = setTimeout(async () => {
|
|
38
|
+
const creds = await readCredentials(path)
|
|
39
|
+
onChange(creds)
|
|
40
|
+
}, 100) // 100ms debounce to avoid partial-write reads
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
return () => watcher.close()
|
|
44
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { access } from 'fs/promises'
|
|
2
|
+
import type { UserMode } from '../types.js'
|
|
3
|
+
|
|
4
|
+
interface DetectOptions {
|
|
5
|
+
credentialsPath: string
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
async function fileExists(path: string): Promise<boolean> {
|
|
9
|
+
try {
|
|
10
|
+
await access(path)
|
|
11
|
+
return true
|
|
12
|
+
} catch {
|
|
13
|
+
return false
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export async function detectMode(opts: DetectOptions): Promise<UserMode | null> {
|
|
18
|
+
const hasApiKey = Boolean(process.env.ANTHROPIC_API_KEY)
|
|
19
|
+
const hasCredentials = await fileExists(opts.credentialsPath)
|
|
20
|
+
|
|
21
|
+
if (hasCredentials) return 'plan'
|
|
22
|
+
if (hasApiKey) return 'api'
|
|
23
|
+
return null
|
|
24
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { readConfig, writeConfig } from '../storage/config-store.js'
|
|
2
|
+
import { CONFIG_PATH } from '../constants.js'
|
|
3
|
+
|
|
4
|
+
export async function runConfig(args: string[]): Promise<void> {
|
|
5
|
+
const config = await readConfig(CONFIG_PATH)
|
|
6
|
+
if (!config) { console.log('Run meter init first.'); return }
|
|
7
|
+
if (args.length === 0) { console.log(JSON.stringify(config, null, 2)); return }
|
|
8
|
+
if (args[0] === 'set' && args[1] && args[2]) {
|
|
9
|
+
const field = args[1]
|
|
10
|
+
const val = args[2]
|
|
11
|
+
if (field === 'budget') config.budget.per_task_usd = parseFloat(val)
|
|
12
|
+
else if (field === 'threshold') {
|
|
13
|
+
config.budget.threshold_pct = parseInt(val, 10)
|
|
14
|
+
config.plan.window_threshold_pct = parseInt(val, 10)
|
|
15
|
+
}
|
|
16
|
+
await writeConfig(CONFIG_PATH, config)
|
|
17
|
+
console.log(`✓ ${field} set to ${val}`)
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { openDb, getRecentTasks } from '../storage/db.js'
|
|
2
|
+
import { HISTORY_DB_PATH } from '../constants.js'
|
|
3
|
+
|
|
4
|
+
export async function runHistory(args: string[]): Promise<void> {
|
|
5
|
+
const limit = parseInt(args[0] ?? '30', 10)
|
|
6
|
+
const db = await openDb(HISTORY_DB_PATH)
|
|
7
|
+
const tasks = getRecentTasks(db, limit)
|
|
8
|
+
db.close()
|
|
9
|
+
if (tasks.length === 0) { console.log('No tasks recorded yet.'); return }
|
|
10
|
+
console.log(`\n◆ meter history (last ${limit})\n`)
|
|
11
|
+
for (const t of tasks) {
|
|
12
|
+
const date = new Date(t.created_at).toLocaleString()
|
|
13
|
+
const cost = t.actual_cost != null ? `$${t.actual_cost.toFixed(3)}` : t.window_pct_end != null ? `${t.window_pct_end.toFixed(0)}% window` : '—'
|
|
14
|
+
console.log(` ${date} ${t.complexity.padEnd(8)} ${cost.padStart(10)} ${t.prompt_text.slice(0, 50)}`)
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import { mkdir, readFile, writeFile, copyFile, chmod } from 'fs/promises'
|
|
2
|
+
import { join, dirname } from 'path'
|
|
3
|
+
import { fileURLToPath } from 'url'
|
|
4
|
+
import { detectShell, getShellConfigPath } from '../shell/detect.js'
|
|
5
|
+
import { resolveTrueBinary } from '../shell/binary-resolver.js'
|
|
6
|
+
import { writeShim } from '../shell/shim-writer.js'
|
|
7
|
+
import { injectPath, isPathAlreadyInjected } from '../shell/path-inject.js'
|
|
8
|
+
import { writeConfig, ensureConfigDefaults } from '../storage/config-store.js'
|
|
9
|
+
import { detectMode } from '../auth/detect.js'
|
|
10
|
+
import { readCredentials } from '../auth/credentials.js'
|
|
11
|
+
import { resolveOrgId } from '../tracking/plan-usage.js'
|
|
12
|
+
import { METER_BIN_DIR, CLAUDE_CREDENTIALS_PATH, CLAUDE_SETTINGS_PATH } from '../constants.js'
|
|
13
|
+
import type { UserMode } from '../types.js'
|
|
14
|
+
|
|
15
|
+
export interface InitOptions {
|
|
16
|
+
meterDir: string
|
|
17
|
+
trueBinary?: string
|
|
18
|
+
mode?: UserMode
|
|
19
|
+
skipPathInjection?: boolean
|
|
20
|
+
orgId?: string | null
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export async function runInit(opts: InitOptions): Promise<void> {
|
|
24
|
+
const meterDir = opts.meterDir
|
|
25
|
+
const binDir = join(meterDir, 'bin')
|
|
26
|
+
await mkdir(binDir, { recursive: true })
|
|
27
|
+
await mkdir(join(meterDir, 'cache'), { recursive: true })
|
|
28
|
+
await mkdir(join(meterDir, 'reports'), { recursive: true })
|
|
29
|
+
|
|
30
|
+
// Resolve true claude binary
|
|
31
|
+
const trueBinary = opts.trueBinary ?? await resolveTrueBinary('claude', binDir)
|
|
32
|
+
if (!trueBinary) {
|
|
33
|
+
throw new Error('claude not found in PATH. Install Claude Code first.')
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Detect mode
|
|
37
|
+
const mode = opts.mode ?? await detectMode({ credentialsPath: CLAUDE_CREDENTIALS_PATH })
|
|
38
|
+
if (!mode) {
|
|
39
|
+
throw new Error('No Claude credentials found. Run `claude` first to authenticate.')
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Resolve org_id for Plan Mode
|
|
43
|
+
let orgId = opts.orgId ?? null
|
|
44
|
+
if (mode === 'plan' && orgId === null) {
|
|
45
|
+
const creds = await readCredentials(CLAUDE_CREDENTIALS_PATH)
|
|
46
|
+
if (creds) orgId = await resolveOrgId(creds)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Write shim
|
|
50
|
+
const shimPath = join(binDir, 'claude')
|
|
51
|
+
await writeShim(shimPath, trueBinary)
|
|
52
|
+
|
|
53
|
+
// Inject PATH (skip in tests)
|
|
54
|
+
if (!opts.skipPathInjection) {
|
|
55
|
+
const shell = detectShell()
|
|
56
|
+
const configPath = getShellConfigPath(shell)
|
|
57
|
+
const already = await isPathAlreadyInjected(configPath)
|
|
58
|
+
await injectPath(shell, configPath)
|
|
59
|
+
if (!already) {
|
|
60
|
+
console.log(`✓ Added ~/.meter/bin to PATH in ${configPath}`)
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Write config
|
|
65
|
+
const config = ensureConfigDefaults({
|
|
66
|
+
mode,
|
|
67
|
+
resolved_binaries: { claude: trueBinary },
|
|
68
|
+
...(orgId ? { org_id: orgId } : {}),
|
|
69
|
+
})
|
|
70
|
+
await writeConfig(join(meterDir, 'config.json'), config)
|
|
71
|
+
|
|
72
|
+
// Install Claude Code hooks (skip in tests)
|
|
73
|
+
if (!opts.skipPathInjection) {
|
|
74
|
+
await installClaudeHooks(meterDir)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
console.log(`✓ meter initialised (${mode} mode)`)
|
|
78
|
+
console.log(` Restart your terminal or run: source ~/.zshrc`)
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
async function installClaudeHooks(meterDir: string): Promise<void> {
|
|
82
|
+
const hooksDir = join(meterDir, 'hooks')
|
|
83
|
+
await mkdir(hooksDir, { recursive: true })
|
|
84
|
+
|
|
85
|
+
// Copy hook scripts to ~/.meter/hooks/
|
|
86
|
+
const srcDir = join(dirname(fileURLToPath(import.meta.url)), '..', 'hooks')
|
|
87
|
+
for (const file of ['on-prompt.js', 'statusline.js']) {
|
|
88
|
+
try {
|
|
89
|
+
await copyFile(join(srcDir, file), join(hooksDir, file))
|
|
90
|
+
await chmod(join(hooksDir, file), 0o755)
|
|
91
|
+
} catch {
|
|
92
|
+
// If source doesn't exist (running from dist), try the dist/hooks path
|
|
93
|
+
const distDir = join(dirname(fileURLToPath(import.meta.url)), '..', '..', 'src', 'hooks')
|
|
94
|
+
try {
|
|
95
|
+
await copyFile(join(distDir, file), join(hooksDir, file))
|
|
96
|
+
await chmod(join(hooksDir, file), 0o755)
|
|
97
|
+
} catch {
|
|
98
|
+
console.warn(` ⚠ Could not copy ${file} — skipping hook installation`)
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Update Claude Code settings.json to add meter hooks
|
|
104
|
+
try {
|
|
105
|
+
let settings: Record<string, any> = {}
|
|
106
|
+
try {
|
|
107
|
+
settings = JSON.parse(await readFile(CLAUDE_SETTINGS_PATH, 'utf-8'))
|
|
108
|
+
} catch {
|
|
109
|
+
// settings file doesn't exist yet — we'll create it
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Add UserPromptSubmit hook if not already present
|
|
113
|
+
const meterHookCommand = `node "${join(hooksDir, 'on-prompt.js')}"`
|
|
114
|
+
if (!settings.hooks) settings.hooks = {}
|
|
115
|
+
if (!settings.hooks.UserPromptSubmit) settings.hooks.UserPromptSubmit = []
|
|
116
|
+
|
|
117
|
+
const alreadyHasHook = settings.hooks.UserPromptSubmit.some((h: any) =>
|
|
118
|
+
h.hooks?.some((hh: any) => hh.command?.includes('meter'))
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
if (!alreadyHasHook) {
|
|
122
|
+
settings.hooks.UserPromptSubmit.push({
|
|
123
|
+
hooks: [{ type: 'command', command: meterHookCommand }]
|
|
124
|
+
})
|
|
125
|
+
console.log('✓ Added meter estimation hook to Claude Code')
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Add/update statusline command
|
|
129
|
+
const meterStatuslineCommand = `node "${join(hooksDir, 'statusline.js')}"`
|
|
130
|
+
const existingStatusLine = settings.statusLine
|
|
131
|
+
|
|
132
|
+
if (!existingStatusLine || existingStatusLine.command?.includes('meter')) {
|
|
133
|
+
// No existing statusline or it's ours — set it
|
|
134
|
+
settings.statusLine = { type: 'command', command: meterStatuslineCommand }
|
|
135
|
+
console.log('✓ Added meter statusline to Claude Code')
|
|
136
|
+
} else {
|
|
137
|
+
// There's an existing statusline from another tool — chain them
|
|
138
|
+
// Create a wrapper that runs both
|
|
139
|
+
const chainCommand = `${existingStatusLine.command} && echo " │ " && ${meterStatuslineCommand}`
|
|
140
|
+
settings.statusLine = { type: 'command', command: chainCommand }
|
|
141
|
+
console.log('✓ Chained meter statusline with existing statusline')
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
await mkdir(dirname(CLAUDE_SETTINGS_PATH), { recursive: true })
|
|
145
|
+
await writeFile(CLAUDE_SETTINGS_PATH, JSON.stringify(settings, null, 2), 'utf-8')
|
|
146
|
+
} catch (err) {
|
|
147
|
+
console.warn(` ⚠ Could not update Claude Code settings: ${err}`)
|
|
148
|
+
}
|
|
149
|
+
}
|