@rasensio/aidlc 1.2.1 → 1.4.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 (120) hide show
  1. package/dist/cli.js +4 -0
  2. package/dist/cli.js.map +1 -1
  3. package/dist/commands/claim.d.ts +15 -0
  4. package/dist/commands/claim.d.ts.map +1 -0
  5. package/dist/commands/claim.js +122 -0
  6. package/dist/commands/claim.js.map +1 -0
  7. package/dist/commands/cost.d.ts +12 -0
  8. package/dist/commands/cost.d.ts.map +1 -0
  9. package/dist/commands/cost.js +409 -0
  10. package/dist/commands/cost.js.map +1 -0
  11. package/dist/commands/gate.d.ts.map +1 -1
  12. package/dist/commands/gate.js +17 -0
  13. package/dist/commands/gate.js.map +1 -1
  14. package/dist/commands/init.d.ts.map +1 -1
  15. package/dist/commands/init.js +38 -2
  16. package/dist/commands/init.js.map +1 -1
  17. package/dist/commands/status.d.ts.map +1 -1
  18. package/dist/commands/status.js +59 -2
  19. package/dist/commands/status.js.map +1 -1
  20. package/dist/commands/transition.d.ts.map +1 -1
  21. package/dist/commands/transition.js +30 -0
  22. package/dist/commands/transition.js.map +1 -1
  23. package/dist/core/gate.d.ts +7 -0
  24. package/dist/core/gate.d.ts.map +1 -1
  25. package/dist/core/gate.js.map +1 -1
  26. package/dist/core/types.d.ts +18 -1
  27. package/dist/core/types.d.ts.map +1 -1
  28. package/dist/cost/config.d.ts +8 -0
  29. package/dist/cost/config.d.ts.map +1 -0
  30. package/dist/cost/config.js +37 -0
  31. package/dist/cost/config.js.map +1 -0
  32. package/dist/cost/hooks/claude-code.d.ts +29 -0
  33. package/dist/cost/hooks/claude-code.d.ts.map +1 -0
  34. package/dist/cost/hooks/claude-code.js +101 -0
  35. package/dist/cost/hooks/claude-code.js.map +1 -0
  36. package/dist/cost/hooks/kiro.d.ts +17 -0
  37. package/dist/cost/hooks/kiro.d.ts.map +1 -0
  38. package/dist/cost/hooks/kiro.js +66 -0
  39. package/dist/cost/hooks/kiro.js.map +1 -0
  40. package/dist/cost/ledger.d.ts +70 -0
  41. package/dist/cost/ledger.d.ts.map +1 -0
  42. package/dist/cost/ledger.js +314 -0
  43. package/dist/cost/ledger.js.map +1 -0
  44. package/dist/cost/providers/claude-code.d.ts +20 -0
  45. package/dist/cost/providers/claude-code.d.ts.map +1 -0
  46. package/dist/cost/providers/claude-code.js +116 -0
  47. package/dist/cost/providers/claude-code.js.map +1 -0
  48. package/dist/cost/providers/kiro.d.ts +19 -0
  49. package/dist/cost/providers/kiro.d.ts.map +1 -0
  50. package/dist/cost/providers/kiro.js +147 -0
  51. package/dist/cost/providers/kiro.js.map +1 -0
  52. package/dist/cost/providers/provider.d.ts +36 -0
  53. package/dist/cost/providers/provider.d.ts.map +1 -0
  54. package/dist/cost/providers/provider.js +21 -0
  55. package/dist/cost/providers/provider.js.map +1 -0
  56. package/dist/cost/rates-bundled.d.ts +11 -0
  57. package/dist/cost/rates-bundled.d.ts.map +1 -0
  58. package/dist/cost/rates-bundled.js +23 -0
  59. package/dist/cost/rates-bundled.js.map +1 -0
  60. package/dist/cost/rates.d.ts +42 -0
  61. package/dist/cost/rates.d.ts.map +1 -0
  62. package/dist/cost/rates.js +190 -0
  63. package/dist/cost/rates.js.map +1 -0
  64. package/dist/cost/recorder.d.ts +57 -0
  65. package/dist/cost/recorder.d.ts.map +1 -0
  66. package/dist/cost/recorder.js +339 -0
  67. package/dist/cost/recorder.js.map +1 -0
  68. package/dist/cost/report.d.ts +44 -0
  69. package/dist/cost/report.d.ts.map +1 -0
  70. package/dist/cost/report.js +164 -0
  71. package/dist/cost/report.js.map +1 -0
  72. package/dist/cost/sessions.d.ts +40 -0
  73. package/dist/cost/sessions.d.ts.map +1 -0
  74. package/dist/cost/sessions.js +200 -0
  75. package/dist/cost/sessions.js.map +1 -0
  76. package/dist/cost/sync.d.ts +24 -0
  77. package/dist/cost/sync.d.ts.map +1 -0
  78. package/dist/cost/sync.js +191 -0
  79. package/dist/cost/sync.js.map +1 -0
  80. package/dist/cost/types.d.ts +116 -0
  81. package/dist/cost/types.d.ts.map +1 -0
  82. package/dist/cost/types.js +13 -0
  83. package/dist/cost/types.js.map +1 -0
  84. package/dist/setup/setup-compute.d.ts +6 -0
  85. package/dist/setup/setup-compute.d.ts.map +1 -1
  86. package/dist/setup/setup-compute.js +3 -0
  87. package/dist/setup/setup-compute.js.map +1 -1
  88. package/dist/traceability/cache.d.ts +21 -0
  89. package/dist/traceability/cache.d.ts.map +1 -0
  90. package/dist/traceability/cache.js +106 -0
  91. package/dist/traceability/cache.js.map +1 -0
  92. package/dist/traceability/coverage-block.d.ts +21 -0
  93. package/dist/traceability/coverage-block.d.ts.map +1 -0
  94. package/dist/traceability/coverage-block.js +41 -0
  95. package/dist/traceability/coverage-block.js.map +1 -0
  96. package/dist/traceability/gate-criterion.d.ts +34 -0
  97. package/dist/traceability/gate-criterion.d.ts.map +1 -0
  98. package/dist/traceability/gate-criterion.js +128 -0
  99. package/dist/traceability/gate-criterion.js.map +1 -0
  100. package/dist/traceability/matrix.d.ts +35 -0
  101. package/dist/traceability/matrix.d.ts.map +1 -0
  102. package/dist/traceability/matrix.js +93 -0
  103. package/dist/traceability/matrix.js.map +1 -0
  104. package/dist/traceability/parser.d.ts +27 -0
  105. package/dist/traceability/parser.d.ts.map +1 -0
  106. package/dist/traceability/parser.js +101 -0
  107. package/dist/traceability/parser.js.map +1 -0
  108. package/dist/traceability/scanner.d.ts +62 -0
  109. package/dist/traceability/scanner.d.ts.map +1 -0
  110. package/dist/traceability/scanner.js +198 -0
  111. package/dist/traceability/scanner.js.map +1 -0
  112. package/dist/traceability/types.d.ts +77 -0
  113. package/dist/traceability/types.d.ts.map +1 -0
  114. package/dist/traceability/types.js +8 -0
  115. package/dist/traceability/types.js.map +1 -0
  116. package/package.json +3 -5
  117. package/dist/commands/setup.d.ts +0 -24
  118. package/dist/commands/setup.d.ts.map +0 -1
  119. package/dist/commands/setup.js +0 -262
  120. package/dist/commands/setup.js.map +0 -1
@@ -0,0 +1,190 @@
1
+ /**
2
+ * Rate table: bundled defaults, on-demand cached updates, config overrides.
3
+ *
4
+ * Resolution precedence: config override > cached update > bundled (FR6.5).
5
+ * Model ids are normalized with a closed table-driven rule before lookup —
6
+ * additions are code changes with tests, never "etc.".
7
+ *
8
+ * Dollar math uses integer micro-dollars to avoid float drift (DD6).
9
+ *
10
+ * Design: design.md §4.5, D3
11
+ */
12
+ import { readFileSync, writeFileSync, renameSync, mkdirSync, existsSync } from 'node:fs';
13
+ import { dirname, join } from 'node:path';
14
+ import { BUNDLED_RATES } from './rates-bundled.js';
15
+ const DEFAULT_RATES_URL = 'https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json';
16
+ const FETCH_SIZE_CAP = 5 * 1024 * 1024;
17
+ /** Normalization rule: applied in order; printed by `rates show --normalization`. */
18
+ export const NORMALIZATION_RULES = [
19
+ { kind: 'prefix', pattern: /^(us|eu|apac|global)\./, describe: 'strip region prefix (us./eu./apac./global.)' },
20
+ { kind: 'prefix', pattern: /^anthropic\./, describe: 'strip anthropic. prefix' },
21
+ { kind: 'prefix', pattern: /^aws\//, describe: 'strip aws/ prefix' },
22
+ { kind: 'prefix', pattern: /^bedrock\//, describe: 'strip bedrock/ prefix' },
23
+ { kind: 'prefix', pattern: /^vertex_ai\//, describe: 'strip vertex_ai/ prefix' },
24
+ { kind: 'suffix', pattern: /-v\d+(:\d+)?$/, describe: 'strip -vN / -vN:M version suffix' },
25
+ { kind: 'suffix', pattern: /@\d{8}$/, describe: 'strip @YYYYMMDD suffix' },
26
+ ];
27
+ /** Normalize a raw model id for rate lookup (FR6.5). */
28
+ export function normalizeModelId(model) {
29
+ let m = model.toLowerCase();
30
+ let changed = true;
31
+ while (changed) {
32
+ changed = false;
33
+ for (const rule of NORMALIZATION_RULES) {
34
+ const next = m.replace(rule.pattern, '');
35
+ if (next !== m) {
36
+ m = next;
37
+ changed = true;
38
+ }
39
+ }
40
+ }
41
+ return m;
42
+ }
43
+ export function cachedRatesPath(projectRoot) {
44
+ return join(projectRoot, '.aidlc', 'cost', 'rates.json');
45
+ }
46
+ function isRateEntry(v) {
47
+ if (typeof v !== 'object' || v === null)
48
+ return false;
49
+ const allowed = new Set([
50
+ 'input_per_mtok', 'output_per_mtok', 'cache_read_per_mtok', 'cache_write_per_mtok', 'per_unit',
51
+ ]);
52
+ return Object.entries(v).every(([k, val]) => allowed.has(k) && typeof val === 'number' && Number.isFinite(val) && val >= 0);
53
+ }
54
+ function validateSnapshot(data) {
55
+ if (typeof data !== 'object' || data === null)
56
+ return false;
57
+ const s = data;
58
+ return (typeof s.snapshot_version === 'string' &&
59
+ typeof s.effective_date === 'string' &&
60
+ typeof s.rates === 'object' &&
61
+ s.rates !== null &&
62
+ Object.values(s.rates).every(isRateEntry));
63
+ }
64
+ export function loadBundled() {
65
+ return BUNDLED_RATES;
66
+ }
67
+ function loadCached(projectRoot) {
68
+ const p = cachedRatesPath(projectRoot);
69
+ if (!existsSync(p))
70
+ return null;
71
+ try {
72
+ const parsed = JSON.parse(readFileSync(p, 'utf8'));
73
+ return validateSnapshot(parsed) ? parsed : null;
74
+ }
75
+ catch {
76
+ return null;
77
+ }
78
+ }
79
+ /** Merge bundled < cached < overrides into the effective table. */
80
+ export function effectiveRates(projectRoot, config) {
81
+ const bundled = loadBundled();
82
+ const cached = loadCached(projectRoot);
83
+ const entries = new Map();
84
+ for (const [model, rate] of Object.entries(bundled.rates)) {
85
+ entries.set(model, { rate, origin: 'bundled' });
86
+ }
87
+ if (cached) {
88
+ for (const [model, rate] of Object.entries(cached.rates)) {
89
+ entries.set(model, { rate, origin: 'cached' });
90
+ }
91
+ }
92
+ for (const [model, rate] of Object.entries(config?.rates ?? {})) {
93
+ if (isRateEntry(rate))
94
+ entries.set(normalizeModelId(model), { rate, origin: 'override' });
95
+ }
96
+ const snapshot = cached ? cached.snapshot_version : bundled.snapshot_version;
97
+ return { snapshot: config?.rates ? `${snapshot}+overrides` : snapshot, entries };
98
+ }
99
+ /** Cost of usage units in integer micro-dollars; null = unpriced. */
100
+ export function priceUnits(units, rates) {
101
+ if (units.kind === 'tokens') {
102
+ const entry = rates.entries.get(normalizeModelId(units.model));
103
+ if (!entry)
104
+ return null;
105
+ const r = entry.rate;
106
+ if (r.input_per_mtok === undefined || r.output_per_mtok === undefined)
107
+ return null;
108
+ const micro = (units.input_tokens * r.input_per_mtok) +
109
+ (units.output_tokens * r.output_per_mtok) +
110
+ (units.cache_read_tokens * (r.cache_read_per_mtok ?? 0)) +
111
+ (units.cache_write_tokens * (r.cache_write_per_mtok ?? 0));
112
+ // rate is $/MTok → micro-dollars = tokens * rate ($/MTok) * 1e6 / 1e6.
113
+ return Math.round(micro);
114
+ }
115
+ const entry = rates.entries.get('kiro-credit');
116
+ if (!entry || entry.rate.per_unit === undefined)
117
+ return null;
118
+ return Math.round(units.credits * entry.rate.per_unit * 1_000_000);
119
+ }
120
+ export function microToUsd(micro) {
121
+ return `$${(micro / 1_000_000).toFixed(2)}`;
122
+ }
123
+ /**
124
+ * Fetch the LiteLLM pricing JSON and cache the models we know how to price.
125
+ * HTTPS only, redirects refused, 5MB cap, schema-validated, temp-then-rename.
126
+ * Throws with a user-safe message on any failure — callers keep the old table.
127
+ */
128
+ export async function updateRates(projectRoot, config) {
129
+ const url = config?.rates_url ?? DEFAULT_RATES_URL;
130
+ if (!url.startsWith('https://'))
131
+ throw new Error('rates_url must be https://');
132
+ const res = await fetch(url, { redirect: 'error' });
133
+ if (!res.ok)
134
+ throw new Error(`rate source returned ${res.status}`);
135
+ const text = await res.text();
136
+ if (text.length > FETCH_SIZE_CAP)
137
+ throw new Error('rate source exceeds size cap');
138
+ let raw;
139
+ try {
140
+ raw = JSON.parse(text);
141
+ }
142
+ catch {
143
+ throw new Error('rate source is not valid JSON');
144
+ }
145
+ const bundled = loadBundled();
146
+ const rates = {};
147
+ // Extract only models present in the bundled table (extract-known-only, DD7):
148
+ // upstream keys are matched post-normalization.
149
+ const wanted = new Set(Object.keys(bundled.rates));
150
+ for (const [key, value] of Object.entries(raw)) {
151
+ const norm = normalizeModelId(key);
152
+ if (!wanted.has(norm))
153
+ continue;
154
+ const e = value;
155
+ if (typeof e.input_cost_per_token !== 'number' || typeof e.output_cost_per_token !== 'number')
156
+ continue;
157
+ const entry = {
158
+ input_per_mtok: e.input_cost_per_token * 1_000_000,
159
+ output_per_mtok: e.output_cost_per_token * 1_000_000,
160
+ };
161
+ if (typeof e.cache_read_input_token_cost === 'number') {
162
+ entry.cache_read_per_mtok = e.cache_read_input_token_cost * 1_000_000;
163
+ }
164
+ if (typeof e.cache_creation_input_token_cost === 'number') {
165
+ entry.cache_write_per_mtok = e.cache_creation_input_token_cost * 1_000_000;
166
+ }
167
+ if (isRateEntry(entry))
168
+ rates[norm] = entry;
169
+ }
170
+ if (Object.keys(rates).length === 0) {
171
+ throw new Error('rate source contained no known models');
172
+ }
173
+ // Unit-priced entries (kiro-credit) have no public feed — carry from bundled.
174
+ for (const [model, rate] of Object.entries(bundled.rates)) {
175
+ if (rate.per_unit !== undefined && !(model in rates))
176
+ rates[model] = rate;
177
+ }
178
+ const snapshot = {
179
+ snapshot_version: `litellm-${new Date().toISOString().slice(0, 10)}`,
180
+ effective_date: new Date().toISOString().slice(0, 10),
181
+ rates,
182
+ };
183
+ const target = cachedRatesPath(projectRoot);
184
+ mkdirSync(dirname(target), { recursive: true });
185
+ const tmp = target + '.tmp';
186
+ writeFileSync(tmp, JSON.stringify(snapshot, null, 2) + '\n');
187
+ renameSync(tmp, target);
188
+ return snapshot;
189
+ }
190
+ //# sourceMappingURL=rates.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rates.js","sourceRoot":"","sources":["../../src/cost/rates.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Cost recorder: orchestrates capture from provider extraction to ledger
3
+ * appends. Owns all attribution — providers stay platform-pure (DD3).
4
+ *
5
+ * Flow (design §4.1): validate input → acquire per-session lock → read
6
+ * newest cursor (instance ledgers + unattributed) → provider.extract →
7
+ * split segments by claim intervals × phase transitions → merge per
8
+ * (instance, phase, model) → validate + append. The ledger append is the
9
+ * atomic commit point (DD1); re-runs after a crash re-extract from the
10
+ * last committed cursor.
11
+ *
12
+ * Failures append structured lines to .aidlc/cost/capture.log — never raw
13
+ * transcript or ledger content (SR1).
14
+ */
15
+ import { type ProviderEnv } from './providers/provider.js';
16
+ import type { RecordInput } from './types.js';
17
+ export declare function captureLogPath(projectRoot: string): string;
18
+ export declare function logCapture(projectRoot: string, stage: string, errorCode: string, counts?: Record<string, number>): void;
19
+ /** Most recent capture-log line, for surfacing in `aidlc cost` (FR3.10). */
20
+ export declare function lastCaptureError(projectRoot: string): {
21
+ timestamp: string;
22
+ stage: string;
23
+ error_code: string;
24
+ } | null;
25
+ /** Try to take the per-session lock. Returns a release fn, or null if held. */
26
+ export declare function acquireLock(projectRoot: string, sessionId: string): (() => void) | null;
27
+ interface PhaseWindow {
28
+ phase: string;
29
+ from: number;
30
+ /** Exclusive upper bound; Infinity for the current phase. */
31
+ to: number;
32
+ }
33
+ /** Build phase windows for an instance from its transitions.log. */
34
+ export declare function phaseWindows(projectRoot: string, instance: string, initialPhase: string): PhaseWindow[];
35
+ /** All instances that have session events mentioning this session. */
36
+ export declare function instancesForSession(projectRoot: string, sessionId: string): string[];
37
+ export interface RecordResult {
38
+ appended: number;
39
+ unattributed: number;
40
+ instances: string[];
41
+ }
42
+ export interface RecordOptions {
43
+ projectRoot: string;
44
+ provider: string;
45
+ input: RecordInput;
46
+ claimTimeoutMinutes: number;
47
+ env?: ProviderEnv;
48
+ now?: Date;
49
+ }
50
+ /**
51
+ * Run one capture pass for a session. Returns counts, or null when the
52
+ * lock is held elsewhere (the holder re-checks before releasing, so a
53
+ * firing lost to the lock is still captured — design §4.2).
54
+ */
55
+ export declare function recordUsage(opts: RecordOptions): Promise<RecordResult | null>;
56
+ export {};
57
+ //# sourceMappingURL=recorder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recorder.d.ts","sourceRoot":"","sources":["../../src/cost/recorder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAoBH,OAAO,EAAe,KAAK,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACxE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAS9C,wBAAgB,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAE1D;AAED,wBAAgB,UAAU,CACxB,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,MAAM,EACjB,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,GAClC,IAAI,CA+BN;AAED,4EAA4E;AAC5E,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAarH;AAUD,+EAA+E;AAC/E,wBAAgB,WAAW,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,CAAC,MAAM,IAAI,CAAC,GAAG,IAAI,CAqCvF;AAMD,UAAU,WAAW;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,6DAA6D;IAC7D,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,oEAAoE;AACpE,wBAAgB,YAAY,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,WAAW,EAAE,CAiBvG;AASD,sEAAsE;AACtE,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE,CASpF;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,WAAW,CAAC;IACnB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,GAAG,CAAC,EAAE,WAAW,CAAC;IAClB,GAAG,CAAC,EAAE,IAAI,CAAC;CACZ;AAED;;;;GAIG;AACH,wBAAsB,WAAW,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAkCnF"}
@@ -0,0 +1,339 @@
1
+ /**
2
+ * Cost recorder: orchestrates capture from provider extraction to ledger
3
+ * appends. Owns all attribution — providers stay platform-pure (DD3).
4
+ *
5
+ * Flow (design §4.1): validate input → acquire per-session lock → read
6
+ * newest cursor (instance ledgers + unattributed) → provider.extract →
7
+ * split segments by claim intervals × phase transitions → merge per
8
+ * (instance, phase, model) → validate + append. The ledger append is the
9
+ * atomic commit point (DD1); re-runs after a crash re-extract from the
10
+ * last committed cursor.
11
+ *
12
+ * Failures append structured lines to .aidlc/cost/capture.log — never raw
13
+ * transcript or ledger content (SR1).
14
+ */
15
+ import { readdirSync, existsSync, openSync, writeSync, closeSync, unlinkSync, readFileSync, statSync, renameSync, constants, mkdirSync, } from 'node:fs';
16
+ import { join, dirname } from 'node:path';
17
+ import { appendEntry, ledgerPath, unattributedPath, newestCursor } from './ledger.js';
18
+ import { sessionsPath, readSessionEvents, resolveIntervals, appendSessionEvent } from './sessions.js';
19
+ import { readTransitions } from '../state/transition-log.js';
20
+ import { getProvider } from './providers/provider.js';
21
+ const LOCK_STALE_MS = 10 * 60 * 1000;
22
+ const CAPTURE_LOG_MAX_BYTES = 256 * 1024;
23
+ // ---------------------------------------------------------------------------
24
+ // Capture log (FR3.10 / SR1: structured lines only)
25
+ // ---------------------------------------------------------------------------
26
+ export function captureLogPath(projectRoot) {
27
+ return join(projectRoot, '.aidlc', 'cost', 'capture.log');
28
+ }
29
+ export function logCapture(projectRoot, stage, errorCode, counts = {}) {
30
+ const path = captureLogPath(projectRoot);
31
+ mkdirSync(dirname(path), { recursive: true });
32
+ const line = JSON.stringify({
33
+ timestamp: new Date().toISOString(),
34
+ stage,
35
+ error_code: errorCode,
36
+ counts,
37
+ }) + '\n';
38
+ try {
39
+ if (existsSync(path) && statSync(path).size + line.length > CAPTURE_LOG_MAX_BYTES) {
40
+ // Keep the newest half on rotation.
41
+ const kept = readFileSync(path, 'utf8').split('\n');
42
+ const tmp = path + '.tmp';
43
+ const fd = openSync(tmp, 'w');
44
+ try {
45
+ writeSync(fd, kept.slice(Math.floor(kept.length / 2)).join('\n'));
46
+ }
47
+ finally {
48
+ closeSync(fd);
49
+ }
50
+ renameSync(tmp, path);
51
+ }
52
+ const fd = openSync(path, constants.O_WRONLY | constants.O_APPEND | constants.O_CREAT);
53
+ try {
54
+ writeSync(fd, line);
55
+ }
56
+ finally {
57
+ closeSync(fd);
58
+ }
59
+ }
60
+ catch {
61
+ // Diagnostics must never crash capture.
62
+ }
63
+ }
64
+ /** Most recent capture-log line, for surfacing in `aidlc cost` (FR3.10). */
65
+ export function lastCaptureError(projectRoot) {
66
+ const path = captureLogPath(projectRoot);
67
+ if (!existsSync(path))
68
+ return null;
69
+ const lines = readFileSync(path, 'utf8').trim().split('\n');
70
+ for (let i = lines.length - 1; i >= 0; i--) {
71
+ try {
72
+ const parsed = JSON.parse(lines[i]);
73
+ if (parsed.error_code && parsed.error_code !== 'ok')
74
+ return parsed;
75
+ }
76
+ catch {
77
+ continue;
78
+ }
79
+ }
80
+ return null;
81
+ }
82
+ // ---------------------------------------------------------------------------
83
+ // Lock (design §4.1 step 3)
84
+ // ---------------------------------------------------------------------------
85
+ function lockPath(projectRoot, sessionId) {
86
+ return join(projectRoot, '.aidlc', 'cost', 'locks', `${sessionId}.lock`);
87
+ }
88
+ /** Try to take the per-session lock. Returns a release fn, or null if held. */
89
+ export function acquireLock(projectRoot, sessionId) {
90
+ const path = lockPath(projectRoot, sessionId);
91
+ mkdirSync(dirname(path), { recursive: true });
92
+ const tryOnce = () => {
93
+ try {
94
+ const fd = openSync(path, constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL);
95
+ writeSync(fd, JSON.stringify({ pid: process.pid, at: new Date().toISOString() }));
96
+ closeSync(fd);
97
+ return () => {
98
+ try {
99
+ unlinkSync(path);
100
+ }
101
+ catch {
102
+ // Already gone — fine.
103
+ }
104
+ };
105
+ }
106
+ catch {
107
+ return null;
108
+ }
109
+ };
110
+ const release = tryOnce();
111
+ if (release)
112
+ return release;
113
+ // Steal stale locks (>10min old).
114
+ try {
115
+ const held = JSON.parse(readFileSync(path, 'utf8'));
116
+ if (Date.now() - Date.parse(held.at) > LOCK_STALE_MS) {
117
+ unlinkSync(path);
118
+ return tryOnce();
119
+ }
120
+ }
121
+ catch {
122
+ try {
123
+ unlinkSync(path);
124
+ }
125
+ catch {
126
+ // Lost the race; treat as held.
127
+ }
128
+ return tryOnce();
129
+ }
130
+ return null;
131
+ }
132
+ /** Build phase windows for an instance from its transitions.log. */
133
+ export function phaseWindows(projectRoot, instance, initialPhase) {
134
+ const logFile = join(projectRoot, '.aidlc', 'state', instance, 'transitions.log');
135
+ const transitions = readTransitions(logFile);
136
+ const windows = [];
137
+ let phase = initialPhase;
138
+ let from = 0;
139
+ for (const t of transitions) {
140
+ const rec = t;
141
+ if (!rec.timestamp || !rec.to)
142
+ continue;
143
+ const at = Date.parse(rec.timestamp);
144
+ if (Number.isNaN(at))
145
+ continue;
146
+ windows.push({ phase: rec.from ?? phase, from, to: at });
147
+ phase = rec.to;
148
+ from = at;
149
+ }
150
+ windows.push({ phase, from, to: Infinity });
151
+ return windows;
152
+ }
153
+ function phaseAt(windows, at) {
154
+ for (const w of windows) {
155
+ if (at >= w.from && at < w.to)
156
+ return w.phase;
157
+ }
158
+ return windows[windows.length - 1].phase;
159
+ }
160
+ /** All instances that have session events mentioning this session. */
161
+ export function instancesForSession(projectRoot, sessionId) {
162
+ const stateDir = join(projectRoot, '.aidlc', 'state');
163
+ if (!existsSync(stateDir))
164
+ return [];
165
+ const out = [];
166
+ for (const name of readdirSync(stateDir)) {
167
+ const events = readSessionEvents(sessionsPath(projectRoot, name));
168
+ if (events.some((e) => e.session_id === sessionId))
169
+ out.push(name);
170
+ }
171
+ return out;
172
+ }
173
+ /**
174
+ * Run one capture pass for a session. Returns counts, or null when the
175
+ * lock is held elsewhere (the holder re-checks before releasing, so a
176
+ * firing lost to the lock is still captured — design §4.2).
177
+ */
178
+ export async function recordUsage(opts) {
179
+ const { projectRoot, input } = opts;
180
+ const env = opts.env ?? { projectRoot };
181
+ const now = opts.now ?? new Date();
182
+ const provider = getProvider(opts.provider);
183
+ if (!provider) {
184
+ logCapture(projectRoot, 'resolve-provider', 'unknown-provider');
185
+ return { appended: 0, unattributed: 0, instances: [] };
186
+ }
187
+ const source = provider.resolveSource(input, env);
188
+ if (!source) {
189
+ logCapture(projectRoot, 'resolve-source', 'invalid-input');
190
+ return { appended: 0, unattributed: 0, instances: [] };
191
+ }
192
+ const release = acquireLock(projectRoot, input.session_id);
193
+ if (!release)
194
+ return null;
195
+ try {
196
+ let result = await capturePass(opts, source.path, env, now);
197
+ // Re-check once before releasing: a firing that lost the lock while we
198
+ // ran may have carried new usage (design §4.2).
199
+ const second = await capturePass(opts, source.path, env, now);
200
+ result = {
201
+ appended: result.appended + second.appended,
202
+ unattributed: result.unattributed + second.unattributed,
203
+ instances: [...new Set([...result.instances, ...second.instances])],
204
+ };
205
+ return result;
206
+ }
207
+ finally {
208
+ release();
209
+ }
210
+ }
211
+ async function capturePass(opts, sourcePath, env, now) {
212
+ const { projectRoot, input } = opts;
213
+ const provider = getProvider(opts.provider);
214
+ const instances = instancesForSession(projectRoot, input.session_id);
215
+ const ledgers = instances.map((i) => ledgerPath(projectRoot, i));
216
+ ledgers.push(unattributedPath(projectRoot));
217
+ const cursor = newestCursor(input.session_id, ledgers);
218
+ let segments;
219
+ try {
220
+ segments = await provider.extract({ provider: opts.provider, path: sourcePath }, cursor, env);
221
+ }
222
+ catch {
223
+ logCapture(projectRoot, 'extract', 'extract-failed');
224
+ return { appended: 0, unattributed: 0, instances: [] };
225
+ }
226
+ if (segments.length === 0)
227
+ return { appended: 0, unattributed: 0, instances: [] };
228
+ // Resolve claim intervals per instance, and renew open claims (design §2.2).
229
+ const intervalsByInstance = new Map();
230
+ for (const instance of instances) {
231
+ const events = readSessionEvents(sessionsPath(projectRoot, instance));
232
+ const intervals = resolveIntervals(events, opts.claimTimeoutMinutes, now).filter((iv) => iv.session_id === input.session_id);
233
+ intervalsByInstance.set(instance, intervals);
234
+ const hasOpen = intervals.some((iv) => iv.open);
235
+ if (hasOpen) {
236
+ let claimEvent;
237
+ for (const e of events) {
238
+ if (e.session_id === input.session_id && e.event === 'claim')
239
+ claimEvent = e;
240
+ }
241
+ if (claimEvent) {
242
+ appendSessionEvent(sessionsPath(projectRoot, instance), {
243
+ event: 'renew',
244
+ session_id: input.session_id,
245
+ id_source: claimEvent.id_source,
246
+ agent: claimEvent.agent,
247
+ timestamp: now.toISOString(),
248
+ });
249
+ }
250
+ }
251
+ }
252
+ const buckets = new Map();
253
+ const windowsCache = new Map();
254
+ for (const seg of segments) {
255
+ const at = Date.parse(seg.at);
256
+ let instance = null;
257
+ for (const [name, intervals] of intervalsByInstance) {
258
+ if (intervals.some((iv) => at >= Date.parse(iv.from) && at <= Date.parse(iv.to))) {
259
+ instance = name;
260
+ break;
261
+ }
262
+ }
263
+ let phase = null;
264
+ if (instance !== null) {
265
+ let windows = windowsCache.get(instance);
266
+ if (!windows) {
267
+ windows = phaseWindows(projectRoot, instance, 'implementation');
268
+ windowsCache.set(instance, windows);
269
+ }
270
+ phase = phaseAt(windows, at);
271
+ }
272
+ const modelKey = seg.units.kind === 'tokens' ? seg.units.model : `credits:${seg.units.model ?? ''}`;
273
+ const key = `${instance ?? '∅'}|${phase ?? '∅'}|${modelKey}`;
274
+ const existing = buckets.get(key);
275
+ if (existing) {
276
+ mergeUnits(existing.units, seg.units);
277
+ existing.from = Math.min(existing.from, at);
278
+ existing.to = Math.max(existing.to, at);
279
+ existing.cursor = seg.cursor;
280
+ }
281
+ else {
282
+ buckets.set(key, {
283
+ instance,
284
+ phase,
285
+ units: structuredClone(seg.units),
286
+ from: at,
287
+ to: at,
288
+ cursor: seg.cursor,
289
+ });
290
+ }
291
+ }
292
+ // Append entries; the final segment's cursor rides on every bucket from
293
+ // the same pass so any single entry can resume the stream.
294
+ const finalCursor = segments[segments.length - 1].cursor;
295
+ let appended = 0;
296
+ let unattributed = 0;
297
+ const touched = new Set();
298
+ for (const b of buckets.values()) {
299
+ const entry = {
300
+ timestamp: now.toISOString(),
301
+ session_id: input.session_id,
302
+ phase: b.phase,
303
+ provider: opts.provider,
304
+ fidelity: 'metered',
305
+ coverage: { from: new Date(b.from).toISOString(), to: new Date(b.to).toISOString() },
306
+ cursor: finalCursor,
307
+ units: b.units,
308
+ };
309
+ const target = b.instance !== null
310
+ ? ledgerPath(projectRoot, b.instance)
311
+ : unattributedPath(projectRoot);
312
+ try {
313
+ appendEntry(target, entry);
314
+ if (b.instance !== null) {
315
+ appended++;
316
+ touched.add(b.instance);
317
+ }
318
+ else {
319
+ unattributed++;
320
+ }
321
+ }
322
+ catch {
323
+ logCapture(projectRoot, 'append', 'validation-rejected');
324
+ }
325
+ }
326
+ return { appended, unattributed, instances: [...touched] };
327
+ }
328
+ function mergeUnits(target, add) {
329
+ if (target.kind === 'tokens' && add.kind === 'tokens') {
330
+ target.input_tokens += add.input_tokens;
331
+ target.output_tokens += add.output_tokens;
332
+ target.cache_read_tokens += add.cache_read_tokens;
333
+ target.cache_write_tokens += add.cache_write_tokens;
334
+ }
335
+ else if (target.kind === 'credits' && add.kind === 'credits') {
336
+ target.credits += add.credits;
337
+ }
338
+ }
339
+ //# sourceMappingURL=recorder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recorder.js","sourceRoot":"","sources":["../../src/cost/recorder.ts"],"names":[],"mappings":"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"}