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 @@
1
+ {"version":3,"file":"wrapper.d.ts","sourceRoot":"","sources":["../../src/pty/wrapper.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAA;AAIrC,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;AAED,qBAAa,UAAW,SAAQ,YAAY;IAC1C,OAAO,CAAC,UAAU,CAAwB;IAC1C,OAAO,CAAC,aAAa,CAA+B;IAEpD,IAAI,mBAAmB,IAAI,OAAO,CAEjC;IAED,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,CAAC,UAAU,GAAG,IAAI;IAkCnE,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAIzB,IAAI,CAAC,MAAM,SAAY,GAAG,IAAI;IAI9B,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;CAGzC"}
@@ -0,0 +1,49 @@
1
+ import * as pty from 'node-pty';
2
+ import { EventEmitter } from 'events';
3
+ import { AlternateScreenTracker } from './screen.js';
4
+ import { getTerminalSize } from './resize.js';
5
+ export class PtyWrapper extends EventEmitter {
6
+ ptyProcess = null;
7
+ screenTracker = new AlternateScreenTracker();
8
+ get isInAlternateScreen() {
9
+ return this.screenTracker.isActive;
10
+ }
11
+ spawn(binary, args, env) {
12
+ const size = getTerminalSize();
13
+ this.ptyProcess = pty.spawn(binary, args, {
14
+ name: process.env.TERM ?? 'xterm-256color',
15
+ cols: size.cols,
16
+ rows: size.rows,
17
+ env: { ...env },
18
+ cwd: process.cwd(),
19
+ });
20
+ this.ptyProcess.onData((data) => {
21
+ this.screenTracker.process(data);
22
+ this.emit('data', data);
23
+ process.stdout.write(data);
24
+ });
25
+ this.ptyProcess.onExit(({ exitCode, signal }) => {
26
+ this.emit('exit', exitCode, signal ?? 0);
27
+ });
28
+ // Forward stdin to PTY
29
+ process.stdin.setRawMode(true);
30
+ process.stdin.on('data', (data) => {
31
+ this.ptyProcess?.write(data.toString());
32
+ });
33
+ // Handle terminal resize
34
+ process.on('SIGWINCH', () => {
35
+ const newSize = getTerminalSize();
36
+ this.ptyProcess?.resize(newSize.cols, newSize.rows);
37
+ });
38
+ }
39
+ write(data) {
40
+ this.ptyProcess?.write(data);
41
+ }
42
+ kill(signal = 'SIGTERM') {
43
+ this.ptyProcess?.kill(signal);
44
+ }
45
+ resize(cols, rows) {
46
+ this.ptyProcess?.resize(cols, rows);
47
+ }
48
+ }
49
+ //# sourceMappingURL=wrapper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wrapper.js","sourceRoot":"","sources":["../../src/pty/wrapper.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,GAAG,MAAM,UAAU,CAAA;AAC/B,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAA;AACrC,OAAO,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAA;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAO7C,MAAM,OAAO,UAAW,SAAQ,YAAY;IAClC,UAAU,GAAoB,IAAI,CAAA;IAClC,aAAa,GAAG,IAAI,sBAAsB,EAAE,CAAA;IAEpD,IAAI,mBAAmB;QACrB,OAAO,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAA;IACpC,CAAC;IAED,KAAK,CAAC,MAAc,EAAE,IAAc,EAAE,GAAsB;QAC1D,MAAM,IAAI,GAAG,eAAe,EAAE,CAAA;QAE9B,IAAI,CAAC,UAAU,GAAG,GAAG,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,EAAE;YACxC,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,gBAAgB;YAC1C,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,GAAG,EAAE,EAAE,GAAG,GAAG,EAAE;YACf,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE;SACnB,CAAC,CAAA;QAEF,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,IAAY,EAAE,EAAE;YACtC,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;YAChC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,CAAA;YACvB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;QAC5B,CAAC,CAAC,CAAA;QAEF,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAyC,EAAE,EAAE;YACrF,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,EAAE,MAAM,IAAI,CAAC,CAAC,CAAA;QAC1C,CAAC,CAAC,CAAA;QAEF,uBAAuB;QACvB,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,CAAA;QAC9B,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAY,EAAE,EAAE;YACxC,IAAI,CAAC,UAAU,EAAE,KAAK,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAA;QACzC,CAAC,CAAC,CAAA;QAEF,yBAAyB;QACzB,OAAO,CAAC,EAAE,CAAC,UAAU,EAAE,GAAG,EAAE;YAC1B,MAAM,OAAO,GAAG,eAAe,EAAE,CAAA;YACjC,IAAI,CAAC,UAAU,EAAE,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,CAAA;QACrD,CAAC,CAAC,CAAA;IACJ,CAAC;IAED,KAAK,CAAC,IAAY;QAChB,IAAI,CAAC,UAAU,EAAE,KAAK,CAAC,IAAI,CAAC,CAAA;IAC9B,CAAC;IAED,IAAI,CAAC,MAAM,GAAG,SAAS;QACrB,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,MAAM,CAAC,CAAA;IAC/B,CAAC;IAED,MAAM,CAAC,IAAY,EAAE,IAAY;QAC/B,IAAI,CAAC,UAAU,EAAE,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,CAAA;IACrC,CAAC;CACF"}
@@ -0,0 +1,2 @@
1
+ export declare function resolveTrueBinary(name: string, skipDir: string): Promise<string | null>;
2
+ //# sourceMappingURL=binary-resolver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"binary-resolver.d.ts","sourceRoot":"","sources":["../../src/shell/binary-resolver.ts"],"names":[],"mappings":"AAGA,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAcxB"}
@@ -0,0 +1,18 @@
1
+ import { access, constants } from 'fs/promises';
2
+ import { join } from 'path';
3
+ export async function resolveTrueBinary(name, skipDir) {
4
+ const pathEnv = process.env.PATH ?? '';
5
+ const dirs = pathEnv.split(':').filter(d => d !== skipDir && d !== '');
6
+ for (const dir of dirs) {
7
+ const fullPath = join(dir, name);
8
+ try {
9
+ await access(fullPath, constants.X_OK);
10
+ return fullPath;
11
+ }
12
+ catch {
13
+ // not found or not executable, continue
14
+ }
15
+ }
16
+ return null;
17
+ }
18
+ //# sourceMappingURL=binary-resolver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"binary-resolver.js","sourceRoot":"","sources":["../../src/shell/binary-resolver.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAC/C,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAE3B,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,IAAY,EACZ,OAAe;IAEf,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAAA;IACtC,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,OAAO,IAAI,CAAC,KAAK,EAAE,CAAC,CAAA;IAEtE,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAA;QAChC,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,QAAQ,EAAE,SAAS,CAAC,IAAI,CAAC,CAAA;YACtC,OAAO,QAAQ,CAAA;QACjB,CAAC;QAAC,MAAM,CAAC;YACP,wCAAwC;QAC1C,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAA;AACb,CAAC"}
@@ -0,0 +1,5 @@
1
+ export type ShellType = 'zsh' | 'bash' | 'fish' | 'nushell';
2
+ export declare function detectShell(): ShellType;
3
+ export declare function getShellConfigPath(shell: ShellType): string;
4
+ export declare function getPathInjectLine(shell: ShellType): string;
5
+ //# sourceMappingURL=detect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detect.d.ts","sourceRoot":"","sources":["../../src/shell/detect.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,SAAS,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,CAAA;AAE3D,wBAAgB,WAAW,IAAI,SAAS,CAMvC;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,CAS3D;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,CAQ1D"}
@@ -0,0 +1,32 @@
1
+ import { homedir } from 'os';
2
+ import { join } from 'path';
3
+ export function detectShell() {
4
+ const shell = process.env.SHELL ?? '';
5
+ if (shell.includes('zsh'))
6
+ return 'zsh';
7
+ if (shell.includes('fish'))
8
+ return 'fish';
9
+ if (shell.includes('nu'))
10
+ return 'nushell';
11
+ return 'bash';
12
+ }
13
+ export function getShellConfigPath(shell) {
14
+ const home = homedir();
15
+ const paths = {
16
+ zsh: join(home, '.zshrc'),
17
+ bash: join(home, '.bashrc'),
18
+ fish: join(home, '.config', 'fish', 'config.fish'),
19
+ nushell: join(home, '.config', 'nushell', 'env.nu'),
20
+ };
21
+ return paths[shell];
22
+ }
23
+ export function getPathInjectLine(shell) {
24
+ const lines = {
25
+ zsh: `export PATH="$HOME/.meter/bin:$PATH" # added by meter`,
26
+ bash: `export PATH="$HOME/.meter/bin:$PATH" # added by meter`,
27
+ fish: `fish_add_path ~/.meter/bin # added by meter`,
28
+ nushell: `$env.PATH = ($env.PATH | prepend ($env.HOME + "/.meter/bin")) # added by meter`,
29
+ };
30
+ return lines[shell];
31
+ }
32
+ //# sourceMappingURL=detect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detect.js","sourceRoot":"","sources":["../../src/shell/detect.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAA;AAC5B,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAI3B,MAAM,UAAU,WAAW;IACzB,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,EAAE,CAAA;IACrC,IAAI,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAA;IACvC,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC;QAAE,OAAO,MAAM,CAAA;IACzC,IAAI,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,OAAO,SAAS,CAAA;IAC1C,OAAO,MAAM,CAAA;AACf,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,KAAgB;IACjD,MAAM,IAAI,GAAG,OAAO,EAAE,CAAA;IACtB,MAAM,KAAK,GAA8B;QACvC,GAAG,EAAE,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC;QACzB,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC;QAC3B,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,aAAa,CAAC;QAClD,OAAO,EAAE,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ,CAAC;KACpD,CAAA;IACD,OAAO,KAAK,CAAC,KAAK,CAAC,CAAA;AACrB,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,KAAgB;IAChD,MAAM,KAAK,GAA8B;QACvC,GAAG,EAAE,uDAAuD;QAC5D,IAAI,EAAE,uDAAuD;QAC7D,IAAI,EAAE,6CAA6C;QACnD,OAAO,EAAE,gFAAgF;KAC1F,CAAA;IACD,OAAO,KAAK,CAAC,KAAK,CAAC,CAAA;AACrB,CAAC"}
@@ -0,0 +1,5 @@
1
+ import type { ShellType } from './detect.js';
2
+ export declare function isPathAlreadyInjected(configPath: string): Promise<boolean>;
3
+ export declare function injectPath(shell: ShellType, configPath: string): Promise<void>;
4
+ export declare function removePath(configPath: string): Promise<void>;
5
+ //# sourceMappingURL=path-inject.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path-inject.d.ts","sourceRoot":"","sources":["../../src/shell/path-inject.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAK5C,wBAAsB,qBAAqB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAOhF;AAED,wBAAsB,UAAU,CAAC,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAKpF;AAED,wBAAsB,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAQlE"}
@@ -0,0 +1,30 @@
1
+ import { readFile, writeFile, appendFile } from 'fs/promises';
2
+ import { getPathInjectLine } from './detect.js';
3
+ const METER_MARKER = '# added by meter';
4
+ export async function isPathAlreadyInjected(configPath) {
5
+ try {
6
+ const content = await readFile(configPath, 'utf-8');
7
+ return content.includes(METER_MARKER);
8
+ }
9
+ catch {
10
+ return false;
11
+ }
12
+ }
13
+ export async function injectPath(shell, configPath) {
14
+ const already = await isPathAlreadyInjected(configPath);
15
+ if (already)
16
+ return;
17
+ const line = getPathInjectLine(shell);
18
+ await appendFile(configPath, `\n${line}\n`, 'utf-8');
19
+ }
20
+ export async function removePath(configPath) {
21
+ try {
22
+ const content = await readFile(configPath, 'utf-8');
23
+ const cleaned = content.split('\n').filter(line => !line.includes(METER_MARKER)).join('\n');
24
+ await writeFile(configPath, cleaned, 'utf-8');
25
+ }
26
+ catch {
27
+ // file may not exist, that's fine
28
+ }
29
+ }
30
+ //# sourceMappingURL=path-inject.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path-inject.js","sourceRoot":"","sources":["../../src/shell/path-inject.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAE7D,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAE/C,MAAM,YAAY,GAAG,kBAAkB,CAAA;AAEvC,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,UAAkB;IAC5D,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC,CAAA;QACnD,OAAO,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAA;IACvC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAA;IACd,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,KAAgB,EAAE,UAAkB;IACnE,MAAM,OAAO,GAAG,MAAM,qBAAqB,CAAC,UAAU,CAAC,CAAA;IACvD,IAAI,OAAO;QAAE,OAAM;IACnB,MAAM,IAAI,GAAG,iBAAiB,CAAC,KAAK,CAAC,CAAA;IACrC,MAAM,UAAU,CAAC,UAAU,EAAE,KAAK,IAAI,IAAI,EAAE,OAAO,CAAC,CAAA;AACtD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,UAAkB;IACjD,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC,CAAA;QACnD,MAAM,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAC3F,MAAM,SAAS,CAAC,UAAU,EAAE,OAAO,EAAE,OAAO,CAAC,CAAA;IAC/C,CAAC;IAAC,MAAM,CAAC;QACP,kCAAkC;IACpC,CAAC;AACH,CAAC"}
@@ -0,0 +1,3 @@
1
+ export declare function writeShim(shimPath: string, trueBinary: string, meterEntrypoint?: string): Promise<void>;
2
+ export declare function shimExists(shimPath: string): Promise<boolean>;
3
+ //# sourceMappingURL=shim-writer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shim-writer.d.ts","sourceRoot":"","sources":["../../src/shell/shim-writer.ts"],"names":[],"mappings":"AASA,wBAAsB,SAAS,CAC7B,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,eAAe,CAAC,EAAE,MAAM,GACvB,OAAO,CAAC,IAAI,CAAC,CAKf;AAED,wBAAsB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAOnE"}
@@ -0,0 +1,22 @@
1
+ import { writeFile, mkdir, chmod, access } from 'fs/promises';
2
+ import { dirname } from 'path';
3
+ const SHIM_EXEC_TEMPLATE = (trueBinary, meterBin) => `#!/bin/sh
4
+ # meter shim — do not edit manually
5
+ exec "${meterBin}" wrap "${trueBinary}" "$@"
6
+ `;
7
+ export async function writeShim(shimPath, trueBinary, meterEntrypoint) {
8
+ await mkdir(dirname(shimPath), { recursive: true });
9
+ const content = SHIM_EXEC_TEMPLATE(trueBinary, meterEntrypoint ?? 'meter');
10
+ await writeFile(shimPath, content, 'utf-8');
11
+ await chmod(shimPath, 0o755);
12
+ }
13
+ export async function shimExists(shimPath) {
14
+ try {
15
+ await access(shimPath);
16
+ return true;
17
+ }
18
+ catch {
19
+ return false;
20
+ }
21
+ }
22
+ //# sourceMappingURL=shim-writer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shim-writer.js","sourceRoot":"","sources":["../../src/shell/shim-writer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAC7D,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;AAE9B,MAAM,kBAAkB,GAAG,CAAC,UAAkB,EAAE,QAAgB,EAAE,EAAE,CACpE;;QAEQ,QAAQ,WAAW,UAAU;CACpC,CAAA;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,QAAgB,EAChB,UAAkB,EAClB,eAAwB;IAExB,MAAM,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IACnD,MAAM,OAAO,GAAG,kBAAkB,CAAC,UAAU,EAAE,eAAe,IAAI,OAAO,CAAC,CAAA;IAC1E,MAAM,SAAS,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,CAAA;IAC3C,MAAM,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAA;AAC9B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,QAAgB;IAC/C,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,QAAQ,CAAC,CAAA;QACtB,OAAO,IAAI,CAAA;IACb,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAA;IACd,CAAC;AACH,CAAC"}
@@ -0,0 +1,10 @@
1
+ import type { MeterConfig, UserMode } from '../types.js';
2
+ export declare function readConfig(path: string): Promise<MeterConfig | null>;
3
+ export declare function writeConfig(path: string, config: MeterConfig): Promise<void>;
4
+ export declare function ensureConfigDefaults(partial: Partial<MeterConfig> & {
5
+ mode: UserMode;
6
+ resolved_binaries: {
7
+ claude: string;
8
+ };
9
+ }): MeterConfig;
10
+ //# sourceMappingURL=config-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-store.d.ts","sourceRoot":"","sources":["../../src/storage/config-store.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AAExD,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAO1E;AAED,wBAAsB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAGlF;AAED,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,OAAO,CAAC,WAAW,CAAC,GAAG;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,iBAAiB,EAAE;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,GACxF,WAAW,CAwBb"}
@@ -0,0 +1,42 @@
1
+ import { readFile, writeFile, mkdir } from 'fs/promises';
2
+ import { dirname } from 'path';
3
+ import { DEFAULT_CONFIG_VALUES } from '../constants.js';
4
+ export async function readConfig(path) {
5
+ try {
6
+ const raw = await readFile(path, 'utf-8');
7
+ return JSON.parse(raw);
8
+ }
9
+ catch {
10
+ return null;
11
+ }
12
+ }
13
+ export async function writeConfig(path, config) {
14
+ await mkdir(dirname(path), { recursive: true });
15
+ await writeFile(path, JSON.stringify(config, null, 2), 'utf-8');
16
+ }
17
+ export function ensureConfigDefaults(partial) {
18
+ return {
19
+ version: 1,
20
+ org_id: partial.org_id,
21
+ budget: {
22
+ per_task_usd: DEFAULT_CONFIG_VALUES.budget_per_task_usd,
23
+ threshold_pct: DEFAULT_CONFIG_VALUES.threshold_pct,
24
+ action: 'notify',
25
+ },
26
+ plan: {
27
+ window_threshold_pct: DEFAULT_CONFIG_VALUES.window_threshold_pct,
28
+ action: 'notify',
29
+ },
30
+ models: {
31
+ claude_chain: DEFAULT_CONFIG_VALUES.claude_chain,
32
+ },
33
+ estimation: {
34
+ use_llm_precheck: true,
35
+ llm_precheck_model: DEFAULT_CONFIG_VALUES.llm_precheck_model,
36
+ min_confidence_to_skip_llm: DEFAULT_CONFIG_VALUES.min_confidence_to_skip_llm,
37
+ },
38
+ poll_interval_seconds: DEFAULT_CONFIG_VALUES.poll_interval_seconds,
39
+ ...partial,
40
+ };
41
+ }
42
+ //# sourceMappingURL=config-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-store.js","sourceRoot":"","sources":["../../src/storage/config-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AACxD,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;AAC9B,OAAO,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAA;AAGvD,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,IAAY;IAC3C,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;QACzC,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAgB,CAAA;IACvC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAA;IACb,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,IAAY,EAAE,MAAmB;IACjE,MAAM,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IAC/C,MAAM,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAA;AACjE,CAAC;AAED,MAAM,UAAU,oBAAoB,CAClC,OAAyF;IAEzF,OAAO;QACL,OAAO,EAAE,CAAC;QACV,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,MAAM,EAAE;YACN,YAAY,EAAE,qBAAqB,CAAC,mBAAmB;YACvD,aAAa,EAAE,qBAAqB,CAAC,aAAa;YAClD,MAAM,EAAE,QAAQ;SACjB;QACD,IAAI,EAAE;YACJ,oBAAoB,EAAE,qBAAqB,CAAC,oBAAoB;YAChE,MAAM,EAAE,QAAQ;SACjB;QACD,MAAM,EAAE;YACN,YAAY,EAAE,qBAAqB,CAAC,YAAY;SACjD;QACD,UAAU,EAAE;YACV,gBAAgB,EAAE,IAAI;YACtB,kBAAkB,EAAE,qBAAqB,CAAC,kBAAkB;YAC5D,0BAA0B,EAAE,qBAAqB,CAAC,0BAA0B;SAC7E;QACD,qBAAqB,EAAE,qBAAqB,CAAC,qBAAqB;QAClE,GAAG,OAAO;KACX,CAAA;AACH,CAAC"}
@@ -0,0 +1,7 @@
1
+ import type { TaskRecord } from '../types.js';
2
+ export type DB = import('better-sqlite3').Database;
3
+ export declare function initDb(path: string): DB;
4
+ export declare function insertTask(db: DB, task: Omit<TaskRecord, 'id'>): number;
5
+ export declare function getRecentTasks(db: DB, limit: number): TaskRecord[];
6
+ export declare function openDb(path: string): Promise<DB>;
7
+ //# sourceMappingURL=db.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../../src/storage/db.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAG7C,MAAM,MAAM,EAAE,GAAG,OAAO,gBAAgB,EAAE,QAAQ,CAAA;AAElD,wBAAgB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,EAAE,CA6BvC;AAED,wBAAgB,UAAU,CAAC,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,GAAG,MAAM,CAcvE;AAED,wBAAgB,cAAc,CAAC,EAAE,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,UAAU,EAAE,CAIlE;AAED,wBAAsB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,EAAE,CAAC,CAEtD"}
@@ -0,0 +1,53 @@
1
+ import { mkdirSync } from 'fs';
2
+ import { dirname } from 'path';
3
+ import Database from 'better-sqlite3';
4
+ export function initDb(path) {
5
+ mkdirSync(dirname(path), { recursive: true });
6
+ const db = new Database(path);
7
+ db.exec(`
8
+ CREATE TABLE IF NOT EXISTS tasks (
9
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
10
+ created_at INTEGER NOT NULL,
11
+ repo TEXT,
12
+ prompt_hash TEXT NOT NULL,
13
+ prompt_text TEXT NOT NULL,
14
+ model TEXT NOT NULL,
15
+ complexity TEXT NOT NULL,
16
+ est_layer INTEGER NOT NULL,
17
+ est_cost REAL,
18
+ actual_tokens_in INTEGER,
19
+ actual_tokens_out INTEGER,
20
+ actual_cost REAL,
21
+ window_pct_start REAL,
22
+ window_pct_end REAL,
23
+ model_switched INTEGER DEFAULT 0,
24
+ exit_code INTEGER
25
+ );
26
+ CREATE INDEX IF NOT EXISTS idx_tasks_created_at ON tasks(created_at DESC);
27
+ CREATE INDEX IF NOT EXISTS idx_tasks_repo ON tasks(repo);
28
+ CREATE INDEX IF NOT EXISTS idx_tasks_prompt_hash ON tasks(prompt_hash);
29
+ `);
30
+ return db;
31
+ }
32
+ export function insertTask(db, task) {
33
+ const stmt = db.prepare(`
34
+ INSERT INTO tasks (
35
+ created_at, repo, prompt_hash, prompt_text, model, complexity,
36
+ est_layer, est_cost, actual_tokens_in, actual_tokens_out, actual_cost,
37
+ window_pct_start, window_pct_end, model_switched, exit_code
38
+ ) VALUES (
39
+ @created_at, @repo, @prompt_hash, @prompt_text, @model, @complexity,
40
+ @est_layer, @est_cost, @actual_tokens_in, @actual_tokens_out, @actual_cost,
41
+ @window_pct_start, @window_pct_end, @model_switched, @exit_code
42
+ )
43
+ `);
44
+ const result = stmt.run(task);
45
+ return result.lastInsertRowid;
46
+ }
47
+ export function getRecentTasks(db, limit) {
48
+ return db.prepare('SELECT * FROM tasks ORDER BY created_at DESC LIMIT ?').all(limit);
49
+ }
50
+ export async function openDb(path) {
51
+ return initDb(path);
52
+ }
53
+ //# sourceMappingURL=db.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"db.js","sourceRoot":"","sources":["../../src/storage/db.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,IAAI,CAAA;AAC9B,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;AAE9B,OAAO,QAAQ,MAAM,gBAAgB,CAAA;AAIrC,MAAM,UAAU,MAAM,CAAC,IAAY;IACjC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IAC7C,MAAM,EAAE,GAAG,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAA;IAE7B,EAAE,CAAC,IAAI,CAAC;;;;;;;;;;;;;;;;;;;;;;GAsBP,CAAC,CAAA;IAEF,OAAO,EAAE,CAAA;AACX,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,EAAM,EAAE,IAA4B;IAC7D,MAAM,IAAI,GAAG,EAAE,CAAC,OAAO,CAAC;;;;;;;;;;GAUvB,CAAC,CAAA;IACF,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;IAC7B,OAAO,MAAM,CAAC,eAAyB,CAAA;AACzC,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,EAAM,EAAE,KAAa;IAClD,OAAO,EAAE,CAAC,OAAO,CACf,sDAAsD,CACvD,CAAC,GAAG,CAAC,KAAK,CAAiB,CAAA;AAC9B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,IAAY;IACvC,OAAO,MAAM,CAAC,IAAI,CAAC,CAAA;AACrB,CAAC"}
@@ -0,0 +1,6 @@
1
+ import type { ModelPricing } from '../types.js';
2
+ export declare function calculateCost(tokens: {
3
+ input: number;
4
+ output: number;
5
+ }, pricing: ModelPricing): number;
6
+ //# sourceMappingURL=cost.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cost.d.ts","sourceRoot":"","sources":["../../src/tracking/cost.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAE/C,wBAAgB,aAAa,CAAC,MAAM,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,EAAE,OAAO,EAAE,YAAY,GAAG,MAAM,CAItG"}
@@ -0,0 +1,6 @@
1
+ export function calculateCost(tokens, pricing) {
2
+ const inputCost = (tokens.input / 1_000_000) * pricing.input_per_million;
3
+ const outputCost = (tokens.output / 1_000_000) * pricing.output_per_million;
4
+ return inputCost + outputCost;
5
+ }
6
+ //# sourceMappingURL=cost.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cost.js","sourceRoot":"","sources":["../../src/tracking/cost.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,aAAa,CAAC,MAAyC,EAAE,OAAqB;IAC5F,MAAM,SAAS,GAAG,CAAC,MAAM,CAAC,KAAK,GAAG,SAAS,CAAC,GAAG,OAAO,CAAC,iBAAiB,CAAA;IACxE,MAAM,UAAU,GAAG,CAAC,MAAM,CAAC,MAAM,GAAG,SAAS,CAAC,GAAG,OAAO,CAAC,kBAAkB,CAAA;IAC3E,OAAO,SAAS,GAAG,UAAU,CAAA;AAC/B,CAAC"}
@@ -0,0 +1,6 @@
1
+ import type { PlanUsage } from '../types.js';
2
+ import type { ClaudeCredentials } from '../auth/credentials.js';
3
+ export declare function resolveOrgId(creds: ClaudeCredentials): Promise<string | null>;
4
+ export declare function fetchPlanUsage(orgId: string, creds: ClaudeCredentials): Promise<PlanUsage | null>;
5
+ export declare function formatResetCountdown(resetAt: string): string;
6
+ //# sourceMappingURL=plan-usage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plan-usage.d.ts","sourceRoot":"","sources":["../../src/tracking/plan-usage.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAC5C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAA;AAO/D,wBAAsB,YAAY,CAAC,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAYnF;AAED,wBAAsB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CAuBvG;AAED,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAM5D"}
@@ -0,0 +1,53 @@
1
+ import { appendFile, mkdir } from 'fs/promises';
2
+ import { dirname } from 'path';
3
+ import { ERRORS_LOG_PATH, CLAUDE_BOOTSTRAP_API, CLAUDE_USAGE_API } from '../constants.js';
4
+ async function logError(message) {
5
+ await mkdir(dirname(ERRORS_LOG_PATH), { recursive: true });
6
+ await appendFile(ERRORS_LOG_PATH, `[${new Date().toISOString()}] ${message}\n`);
7
+ }
8
+ export async function resolveOrgId(creds) {
9
+ try {
10
+ const res = await fetch(CLAUDE_BOOTSTRAP_API, {
11
+ headers: { Authorization: `Bearer ${creds.accessToken}` }
12
+ });
13
+ if (!res.ok)
14
+ throw new Error(`HTTP ${res.status}`);
15
+ const data = await res.json();
16
+ return data?.account?.memberships?.[0]?.organization?.id ?? null;
17
+ }
18
+ catch (err) {
19
+ await logError(`bootstrap failed: ${err}`);
20
+ return null;
21
+ }
22
+ }
23
+ export async function fetchPlanUsage(orgId, creds) {
24
+ try {
25
+ const res = await fetch(`${CLAUDE_USAGE_API}/${orgId}/usage`, {
26
+ headers: { Authorization: `Bearer ${creds.accessToken}` }
27
+ });
28
+ if (!res.ok) {
29
+ await logError(`usage API returned ${res.status}`);
30
+ return null;
31
+ }
32
+ const data = await res.json();
33
+ return {
34
+ five_hour_pct: data.five_hour?.utilization_pct ?? 0,
35
+ five_hour_reset_at: data.five_hour?.reset_at ?? '',
36
+ seven_day_pct: data.seven_day?.utilization_pct ?? 0,
37
+ fetched_at: Date.now(),
38
+ };
39
+ }
40
+ catch (err) {
41
+ await logError(`fetchPlanUsage failed: ${err}`);
42
+ return null;
43
+ }
44
+ }
45
+ export function formatResetCountdown(resetAt) {
46
+ const ms = new Date(resetAt).getTime() - Date.now();
47
+ if (ms <= 0)
48
+ return 'resetting...';
49
+ const h = Math.floor(ms / 3_600_000);
50
+ const m = Math.floor((ms % 3_600_000) / 60_000);
51
+ return h > 0 ? `${h}h ${m}m` : `${m}m`;
52
+ }
53
+ //# sourceMappingURL=plan-usage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plan-usage.js","sourceRoot":"","sources":["../../src/tracking/plan-usage.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ export interface TokenCounts {
2
+ input: number;
3
+ output: number;
4
+ }
5
+ export declare function parseTokensFromOutput(output: string): TokenCounts | null;
6
+ export declare function estimateInputTokens(charCount: number): number;
7
+ //# sourceMappingURL=tokens.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tokens.d.ts","sourceRoot":"","sources":["../../src/tracking/tokens.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,WAAW;IAAG,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE;AAI9D,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAOxE;AAED,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAE7D"}
@@ -0,0 +1,14 @@
1
+ const TOKEN_PATTERN = /tokens?:\s*([\d,]+)\s*input,\s*([\d,]+)\s*output/i;
2
+ export function parseTokensFromOutput(output) {
3
+ const match = TOKEN_PATTERN.exec(output);
4
+ if (!match)
5
+ return null;
6
+ return {
7
+ input: parseInt(match[1].replace(/,/g, ''), 10),
8
+ output: parseInt(match[2].replace(/,/g, ''), 10),
9
+ };
10
+ }
11
+ export function estimateInputTokens(charCount) {
12
+ return Math.ceil(charCount / 4);
13
+ }
14
+ //# sourceMappingURL=tokens.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tokens.js","sourceRoot":"","sources":["../../src/tracking/tokens.ts"],"names":[],"mappings":"AAEA,MAAM,aAAa,GAAG,mDAAmD,CAAA;AAEzE,MAAM,UAAU,qBAAqB,CAAC,MAAc;IAClD,MAAM,KAAK,GAAG,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;IACxC,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAA;IACvB,OAAO;QACL,KAAK,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC;QAC/C,MAAM,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC;KACjD,CAAA;AACH,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,SAAiB;IACnD,OAAO,IAAI,CAAC,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC,CAAA;AACjC,CAAC"}
@@ -0,0 +1,70 @@
1
+ export type UserMode = 'api' | 'plan';
2
+ export type Complexity = 'low' | 'medium' | 'heavy' | 'critical';
3
+ export type EstimationLayer = 1 | 2 | 3;
4
+ export interface MeterConfig {
5
+ version: number;
6
+ mode: UserMode;
7
+ resolved_binaries: {
8
+ claude: string;
9
+ };
10
+ org_id?: string;
11
+ budget: {
12
+ per_task_usd: number;
13
+ threshold_pct: number;
14
+ action: 'notify';
15
+ };
16
+ plan: {
17
+ window_threshold_pct: number;
18
+ action: 'notify';
19
+ };
20
+ models: {
21
+ claude_chain: string[];
22
+ };
23
+ estimation: {
24
+ use_llm_precheck: boolean;
25
+ llm_precheck_model: string;
26
+ min_confidence_to_skip_llm: number;
27
+ };
28
+ poll_interval_seconds: number;
29
+ }
30
+ export interface TaskRecord {
31
+ id?: number;
32
+ created_at: number;
33
+ repo: string | null;
34
+ prompt_hash: string;
35
+ prompt_text: string;
36
+ model: string;
37
+ complexity: Complexity;
38
+ est_layer: EstimationLayer;
39
+ est_cost: number | null;
40
+ actual_tokens_in: number | null;
41
+ actual_tokens_out: number | null;
42
+ actual_cost: number | null;
43
+ window_pct_start: number | null;
44
+ window_pct_end: number | null;
45
+ model_switched: number;
46
+ exit_code: number | null;
47
+ }
48
+ export interface EstimationResult {
49
+ complexity: Complexity;
50
+ confidence: number;
51
+ estimated_cost: number | null;
52
+ layer_used: EstimationLayer;
53
+ }
54
+ export interface PlanUsage {
55
+ five_hour_pct: number;
56
+ five_hour_reset_at: string;
57
+ seven_day_pct: number;
58
+ fetched_at: number;
59
+ }
60
+ export interface ModelPricing {
61
+ model: string;
62
+ input_per_million: number;
63
+ output_per_million: number;
64
+ updated_at: number;
65
+ }
66
+ export interface TokenCounts {
67
+ input: number;
68
+ output: number;
69
+ }
70
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,QAAQ,GAAG,KAAK,GAAG,MAAM,CAAA;AACrC,MAAM,MAAM,UAAU,GAAG,KAAK,GAAG,QAAQ,GAAG,OAAO,GAAG,UAAU,CAAA;AAChE,MAAM,MAAM,eAAe,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;AAEvC,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,QAAQ,CAAA;IACd,iBAAiB,EAAE;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAA;IACrC,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,MAAM,EAAE;QACN,YAAY,EAAE,MAAM,CAAA;QACpB,aAAa,EAAE,MAAM,CAAA;QACrB,MAAM,EAAE,QAAQ,CAAA;KACjB,CAAA;IACD,IAAI,EAAE;QACJ,oBAAoB,EAAE,MAAM,CAAA;QAC5B,MAAM,EAAE,QAAQ,CAAA;KACjB,CAAA;IACD,MAAM,EAAE;QACN,YAAY,EAAE,MAAM,EAAE,CAAA;KACvB,CAAA;IACD,UAAU,EAAE;QACV,gBAAgB,EAAE,OAAO,CAAA;QACzB,kBAAkB,EAAE,MAAM,CAAA;QAC1B,0BAA0B,EAAE,MAAM,CAAA;KACnC,CAAA;IACD,qBAAqB,EAAE,MAAM,CAAA;CAC9B;AAED,MAAM,WAAW,UAAU;IACzB,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,UAAU,EAAE,MAAM,CAAA;IAClB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IACnB,WAAW,EAAE,MAAM,CAAA;IACnB,WAAW,EAAE,MAAM,CAAA;IACnB,KAAK,EAAE,MAAM,CAAA;IACb,UAAU,EAAE,UAAU,CAAA;IACtB,SAAS,EAAE,eAAe,CAAA;IAC1B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAA;IAC/B,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAA;IAChC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAA;IAC/B,cAAc,EAAE,MAAM,GAAG,IAAI,CAAA;IAC7B,cAAc,EAAE,MAAM,CAAA;IACtB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;CACzB;AAED,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,UAAU,CAAA;IACtB,UAAU,EAAE,MAAM,CAAA;IAClB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAA;IAC7B,UAAU,EAAE,eAAe,CAAA;CAC5B;AAED,MAAM,WAAW,SAAS;IACxB,aAAa,EAAE,MAAM,CAAA;IACrB,kBAAkB,EAAE,MAAM,CAAA;IAC1B,aAAa,EAAE,MAAM,CAAA;IACrB,UAAU,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAA;IACb,iBAAiB,EAAE,MAAM,CAAA;IACzB,kBAAkB,EAAE,MAAM,CAAA;IAC1B,UAAU,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;CACf"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,3 @@
1
+ export type KeypressAction = 's' | 'd' | 'c';
2
+ export declare function waitForKeypress(validKeys: KeypressAction[], timeoutMs: number): Promise<KeypressAction | 'timeout'>;
3
+ //# sourceMappingURL=keypress.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keypress.d.ts","sourceRoot":"","sources":["../../src/ui/keypress.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,cAAc,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAA;AAE5C,wBAAgB,eAAe,CAC7B,SAAS,EAAE,cAAc,EAAE,EAC3B,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,cAAc,GAAG,SAAS,CAAC,CAqBrC"}
@@ -0,0 +1,20 @@
1
+ export function waitForKeypress(validKeys, timeoutMs) {
2
+ return new Promise(resolve => {
3
+ const cleanup = () => {
4
+ process.stdin.removeListener('data', onData);
5
+ clearTimeout(timer);
6
+ };
7
+ const timer = timeoutMs > 0
8
+ ? setTimeout(() => { cleanup(); resolve('timeout'); }, timeoutMs)
9
+ : undefined;
10
+ const onData = (data) => {
11
+ const key = data.toString().toLowerCase().trim();
12
+ if (validKeys.includes(key)) {
13
+ cleanup();
14
+ resolve(key);
15
+ }
16
+ };
17
+ process.stdin.on('data', onData);
18
+ });
19
+ }
20
+ //# sourceMappingURL=keypress.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keypress.js","sourceRoot":"","sources":["../../src/ui/keypress.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,eAAe,CAC7B,SAA2B,EAC3B,SAAiB;IAEjB,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE;QAC3B,MAAM,OAAO,GAAG,GAAG,EAAE;YACnB,OAAO,CAAC,KAAK,CAAC,cAAc,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;YAC5C,YAAY,CAAC,KAAK,CAAC,CAAA;QACrB,CAAC,CAAA;QAED,MAAM,KAAK,GAAG,SAAS,GAAG,CAAC;YACzB,CAAC,CAAC,UAAU,CAAC,GAAG,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,CAAA,CAAC,CAAC,EAAE,SAAS,CAAC;YAChE,CAAC,CAAC,SAAS,CAAA;QAEb,MAAM,MAAM,GAAG,CAAC,IAAY,EAAE,EAAE;YAC9B,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC,WAAW,EAAE,CAAC,IAAI,EAAoB,CAAA;YAClE,IAAI,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC5B,OAAO,EAAE,CAAA;gBACT,OAAO,CAAC,GAAG,CAAC,CAAA;YACd,CAAC;QACH,CAAC,CAAA;QAED,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAClC,CAAC,CAAC,CAAA;AACJ,CAAC"}
@@ -0,0 +1,11 @@
1
+ import type { UserMode } from '../types.js';
2
+ export interface NotificationState {
3
+ mode: UserMode;
4
+ thresholdPct: number;
5
+ elapsedCost: number | null;
6
+ budgetUsd: number | null;
7
+ windowPct: number | null;
8
+ nextModel: string | null;
9
+ }
10
+ export declare function renderNotification(state: NotificationState): string;
11
+ //# sourceMappingURL=notification.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"notification.d.ts","sourceRoot":"","sources":["../../src/ui/notification.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AAE3C,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,QAAQ,CAAA;IACd,YAAY,EAAE,MAAM,CAAA;IACpB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;CACzB;AAOD,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,iBAAiB,GAAG,MAAM,CAcnE"}