@rasensio/aidlc 1.2.0 → 1.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/LICENSE +21 -0
- package/dist/cli.js +4 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/claim.d.ts +15 -0
- package/dist/commands/claim.d.ts.map +1 -0
- package/dist/commands/claim.js +122 -0
- package/dist/commands/claim.js.map +1 -0
- package/dist/commands/cost.d.ts +12 -0
- package/dist/commands/cost.d.ts.map +1 -0
- package/dist/commands/cost.js +409 -0
- package/dist/commands/cost.js.map +1 -0
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +38 -2
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/status.d.ts.map +1 -1
- package/dist/commands/status.js +30 -1
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/transition.js +9 -0
- package/dist/commands/transition.js.map +1 -1
- package/dist/core/types.d.ts +8 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/cost/config.d.ts +8 -0
- package/dist/cost/config.d.ts.map +1 -0
- package/dist/cost/config.js +37 -0
- package/dist/cost/config.js.map +1 -0
- package/dist/cost/hooks/claude-code.d.ts +29 -0
- package/dist/cost/hooks/claude-code.d.ts.map +1 -0
- package/dist/cost/hooks/claude-code.js +101 -0
- package/dist/cost/hooks/claude-code.js.map +1 -0
- package/dist/cost/hooks/kiro.d.ts +17 -0
- package/dist/cost/hooks/kiro.d.ts.map +1 -0
- package/dist/cost/hooks/kiro.js +66 -0
- package/dist/cost/hooks/kiro.js.map +1 -0
- package/dist/cost/ledger.d.ts +70 -0
- package/dist/cost/ledger.d.ts.map +1 -0
- package/dist/cost/ledger.js +314 -0
- package/dist/cost/ledger.js.map +1 -0
- package/dist/cost/providers/claude-code.d.ts +20 -0
- package/dist/cost/providers/claude-code.d.ts.map +1 -0
- package/dist/cost/providers/claude-code.js +116 -0
- package/dist/cost/providers/claude-code.js.map +1 -0
- package/dist/cost/providers/kiro.d.ts +19 -0
- package/dist/cost/providers/kiro.d.ts.map +1 -0
- package/dist/cost/providers/kiro.js +147 -0
- package/dist/cost/providers/kiro.js.map +1 -0
- package/dist/cost/providers/provider.d.ts +36 -0
- package/dist/cost/providers/provider.d.ts.map +1 -0
- package/dist/cost/providers/provider.js +21 -0
- package/dist/cost/providers/provider.js.map +1 -0
- package/dist/cost/rates-bundled.d.ts +11 -0
- package/dist/cost/rates-bundled.d.ts.map +1 -0
- package/dist/cost/rates-bundled.js +23 -0
- package/dist/cost/rates-bundled.js.map +1 -0
- package/dist/cost/rates.d.ts +42 -0
- package/dist/cost/rates.d.ts.map +1 -0
- package/dist/cost/rates.js +190 -0
- package/dist/cost/rates.js.map +1 -0
- package/dist/cost/recorder.d.ts +57 -0
- package/dist/cost/recorder.d.ts.map +1 -0
- package/dist/cost/recorder.js +339 -0
- package/dist/cost/recorder.js.map +1 -0
- package/dist/cost/report.d.ts +44 -0
- package/dist/cost/report.d.ts.map +1 -0
- package/dist/cost/report.js +164 -0
- package/dist/cost/report.js.map +1 -0
- package/dist/cost/sessions.d.ts +40 -0
- package/dist/cost/sessions.d.ts.map +1 -0
- package/dist/cost/sessions.js +200 -0
- package/dist/cost/sessions.js.map +1 -0
- package/dist/cost/sync.d.ts +24 -0
- package/dist/cost/sync.d.ts.map +1 -0
- package/dist/cost/sync.js +191 -0
- package/dist/cost/sync.js.map +1 -0
- package/dist/cost/types.d.ts +116 -0
- package/dist/cost/types.d.ts.map +1 -0
- package/dist/cost/types.js +13 -0
- package/dist/cost/types.js.map +1 -0
- package/dist/setup/setup-compute.d.ts +6 -0
- package/dist/setup/setup-compute.d.ts.map +1 -1
- package/dist/setup/setup-compute.js +3 -0
- package/dist/setup/setup-compute.js.map +1 -1
- package/package.json +11 -14
|
@@ -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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"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cost reports: per-instance, all-instances, by-template, unattributed.
|
|
3
|
+
*
|
|
4
|
+
* Reads ledgers only — never re-parses platform records (FR7.4). Applies
|
|
5
|
+
* read-time fidelity precedence, then prices weighted usage against the
|
|
6
|
+
* effective rate table. Every dollar-bearing report names its snapshot.
|
|
7
|
+
*
|
|
8
|
+
* Design: design.md §4.5
|
|
9
|
+
*/
|
|
10
|
+
import type { CostConfig, CostFidelity, CostEntry } from './types.js';
|
|
11
|
+
export interface PhaseCost {
|
|
12
|
+
phase: string;
|
|
13
|
+
microUsd: number | null;
|
|
14
|
+
unpricedModels: string[];
|
|
15
|
+
tokens: number;
|
|
16
|
+
credits: number;
|
|
17
|
+
elapsedSeconds: number;
|
|
18
|
+
}
|
|
19
|
+
export interface InstanceCost {
|
|
20
|
+
instance: string;
|
|
21
|
+
template: string | null;
|
|
22
|
+
microUsd: number | null;
|
|
23
|
+
unpricedModels: string[];
|
|
24
|
+
tokens: number;
|
|
25
|
+
credits: number;
|
|
26
|
+
elapsedSeconds: number;
|
|
27
|
+
fidelityMix: Record<CostFidelity, number>;
|
|
28
|
+
phases: PhaseCost[];
|
|
29
|
+
snapshot: string;
|
|
30
|
+
}
|
|
31
|
+
/** Compute the full cost view of one instance. */
|
|
32
|
+
export declare function instanceCost(projectRoot: string, instance: string, config: CostConfig | null): InstanceCost;
|
|
33
|
+
/** All instances with state directories. */
|
|
34
|
+
export declare function listInstances(projectRoot: string): string[];
|
|
35
|
+
export interface TemplateRollup {
|
|
36
|
+
template: string;
|
|
37
|
+
count: number;
|
|
38
|
+
avgMicroUsd: number;
|
|
39
|
+
avgElapsedSeconds: number;
|
|
40
|
+
}
|
|
41
|
+
export declare function byTemplate(projectRoot: string, config: CostConfig | null): TemplateRollup[];
|
|
42
|
+
/** Unattributed ledger entries (FR7.2 --unattributed). */
|
|
43
|
+
export declare function unattributedEntries(projectRoot: string): CostEntry[];
|
|
44
|
+
//# sourceMappingURL=report.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../../src/cost/report.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAOH,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEtE,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;IAC1C,MAAM,EAAE,SAAS,EAAE,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;CAClB;AA6DD,kDAAkD;AAClD,wBAAgB,YAAY,CAC1B,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,UAAU,GAAG,IAAI,GACxB,YAAY,CA8Dd;AAED,4CAA4C;AAC5C,wBAAgB,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,EAAE,CAO3D;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED,wBAAgB,UAAU,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,GAAG,IAAI,GAAG,cAAc,EAAE,CAoB3F;AAED,0DAA0D;AAC1D,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,EAAE,CAEpE"}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cost reports: per-instance, all-instances, by-template, unattributed.
|
|
3
|
+
*
|
|
4
|
+
* Reads ledgers only — never re-parses platform records (FR7.4). Applies
|
|
5
|
+
* read-time fidelity precedence, then prices weighted usage against the
|
|
6
|
+
* effective rate table. Every dollar-bearing report names its snapshot.
|
|
7
|
+
*
|
|
8
|
+
* Design: design.md §4.5
|
|
9
|
+
*/
|
|
10
|
+
import { existsSync, readdirSync } from 'node:fs';
|
|
11
|
+
import { join } from 'node:path';
|
|
12
|
+
import { loadYaml } from '../state/yaml-helpers.js';
|
|
13
|
+
import { readEntries, applyPrecedence, ledgerPath, unattributedPath } from './ledger.js';
|
|
14
|
+
import { priceUnits, effectiveRates } from './rates.js';
|
|
15
|
+
function sumWeighted(weighted, rates) {
|
|
16
|
+
let micro = 0;
|
|
17
|
+
let anyPriced = false;
|
|
18
|
+
const unpriced = new Set();
|
|
19
|
+
let tokens = 0;
|
|
20
|
+
let credits = 0;
|
|
21
|
+
for (const { entry, weight } of weighted) {
|
|
22
|
+
if (weight === 0 || entry.units === null)
|
|
23
|
+
continue;
|
|
24
|
+
const price = priceUnits(entry.units, rates);
|
|
25
|
+
if (price === null) {
|
|
26
|
+
unpriced.add(entry.units.kind === 'tokens' ? entry.units.model : 'kiro-credit');
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
micro += price * weight;
|
|
30
|
+
anyPriced = true;
|
|
31
|
+
}
|
|
32
|
+
if (entry.units.kind === 'tokens') {
|
|
33
|
+
tokens += (entry.units.input_tokens + entry.units.output_tokens) * weight;
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
credits += entry.units.credits * weight;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return { microUsd: anyPriced || unpriced.size === 0 ? Math.round(micro) : null, unpriced, tokens, credits };
|
|
40
|
+
}
|
|
41
|
+
function phaseElapsed(projectRoot, instance) {
|
|
42
|
+
const dir = join(projectRoot, '.aidlc', 'state', instance);
|
|
43
|
+
const out = new Map();
|
|
44
|
+
if (!existsSync(dir))
|
|
45
|
+
return out;
|
|
46
|
+
for (const f of readdirSync(dir)) {
|
|
47
|
+
if (!f.startsWith('phase-') || !f.endsWith('.yaml'))
|
|
48
|
+
continue;
|
|
49
|
+
try {
|
|
50
|
+
const state = loadYaml(join(dir, f));
|
|
51
|
+
out.set(state.phase, state.metrics?.elapsed_seconds ?? 0);
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return out;
|
|
58
|
+
}
|
|
59
|
+
function instanceTemplate(projectRoot, instance) {
|
|
60
|
+
try {
|
|
61
|
+
const meta = loadYaml(join(projectRoot, '.aidlc', 'state', instance, 'instance.yaml'));
|
|
62
|
+
return meta.template ?? null;
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/** Compute the full cost view of one instance. */
|
|
69
|
+
export function instanceCost(projectRoot, instance, config) {
|
|
70
|
+
const rates = effectiveRates(projectRoot, config);
|
|
71
|
+
const entries = readEntries(ledgerPath(projectRoot, instance));
|
|
72
|
+
const weighted = applyPrecedence(entries);
|
|
73
|
+
const elapsed = phaseElapsed(projectRoot, instance);
|
|
74
|
+
const byPhase = new Map();
|
|
75
|
+
for (const w of weighted) {
|
|
76
|
+
const phase = w.entry.phase ?? 'unknown';
|
|
77
|
+
const list = byPhase.get(phase) ?? [];
|
|
78
|
+
list.push(w);
|
|
79
|
+
byPhase.set(phase, list);
|
|
80
|
+
}
|
|
81
|
+
const phases = [];
|
|
82
|
+
for (const [phase, list] of byPhase) {
|
|
83
|
+
const s = sumWeighted(list, rates);
|
|
84
|
+
phases.push({
|
|
85
|
+
phase,
|
|
86
|
+
microUsd: s.microUsd,
|
|
87
|
+
unpricedModels: [...s.unpriced],
|
|
88
|
+
tokens: Math.round(s.tokens),
|
|
89
|
+
credits: s.credits,
|
|
90
|
+
elapsedSeconds: elapsed.get(phase) ?? 0,
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
// Phases with time but no cost still appear.
|
|
94
|
+
for (const [phase, secs] of elapsed) {
|
|
95
|
+
if (secs > 0 && !byPhase.has(phase)) {
|
|
96
|
+
phases.push({ phase, microUsd: 0, unpricedModels: [], tokens: 0, credits: 0, elapsedSeconds: secs });
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
const total = sumWeighted(weighted, rates);
|
|
100
|
+
const fidelityMix = { metered: 0, reconciled: 0, estimated: 0, unknown: 0 };
|
|
101
|
+
let mixTotal = 0;
|
|
102
|
+
for (const { entry, weight } of weighted) {
|
|
103
|
+
if (entry.units === null)
|
|
104
|
+
continue;
|
|
105
|
+
fidelityMix[entry.fidelity] += weight;
|
|
106
|
+
mixTotal += weight;
|
|
107
|
+
}
|
|
108
|
+
if (mixTotal > 0) {
|
|
109
|
+
for (const k of Object.keys(fidelityMix)) {
|
|
110
|
+
fidelityMix[k] = fidelityMix[k] / mixTotal;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
let totalElapsed = 0;
|
|
114
|
+
for (const secs of elapsed.values())
|
|
115
|
+
totalElapsed += secs;
|
|
116
|
+
return {
|
|
117
|
+
instance,
|
|
118
|
+
template: instanceTemplate(projectRoot, instance),
|
|
119
|
+
microUsd: total.microUsd,
|
|
120
|
+
unpricedModels: [...total.unpriced],
|
|
121
|
+
tokens: Math.round(total.tokens),
|
|
122
|
+
credits: total.credits,
|
|
123
|
+
elapsedSeconds: totalElapsed,
|
|
124
|
+
fidelityMix,
|
|
125
|
+
phases,
|
|
126
|
+
snapshot: rates.snapshot,
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
/** All instances with state directories. */
|
|
130
|
+
export function listInstances(projectRoot) {
|
|
131
|
+
const dir = join(projectRoot, '.aidlc', 'state');
|
|
132
|
+
if (!existsSync(dir))
|
|
133
|
+
return [];
|
|
134
|
+
return readdirSync(dir, { withFileTypes: true })
|
|
135
|
+
.filter((d) => d.isDirectory())
|
|
136
|
+
.map((d) => d.name)
|
|
137
|
+
.sort();
|
|
138
|
+
}
|
|
139
|
+
export function byTemplate(projectRoot, config) {
|
|
140
|
+
const groups = new Map();
|
|
141
|
+
for (const name of listInstances(projectRoot)) {
|
|
142
|
+
const cost = instanceCost(projectRoot, name, config);
|
|
143
|
+
const template = cost.template ?? '(unknown)';
|
|
144
|
+
const g = groups.get(template) ?? { micro: [], secs: [] };
|
|
145
|
+
g.micro.push(cost.microUsd ?? 0);
|
|
146
|
+
g.secs.push(cost.elapsedSeconds);
|
|
147
|
+
groups.set(template, g);
|
|
148
|
+
}
|
|
149
|
+
const out = [];
|
|
150
|
+
for (const [template, g] of groups) {
|
|
151
|
+
out.push({
|
|
152
|
+
template,
|
|
153
|
+
count: g.micro.length,
|
|
154
|
+
avgMicroUsd: Math.round(g.micro.reduce((a, b) => a + b, 0) / g.micro.length),
|
|
155
|
+
avgElapsedSeconds: Math.round(g.secs.reduce((a, b) => a + b, 0) / g.secs.length),
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
return out.sort((a, b) => a.template.localeCompare(b.template));
|
|
159
|
+
}
|
|
160
|
+
/** Unattributed ledger entries (FR7.2 --unattributed). */
|
|
161
|
+
export function unattributedEntries(projectRoot) {
|
|
162
|
+
return readEntries(unattributedPath(projectRoot));
|
|
163
|
+
}
|
|
164
|
+
//# sourceMappingURL=report.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"report.js","sourceRoot":"","sources":["../../src/cost/report.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session ledger: durable session↔instance mapping (FR1).
|
|
3
|
+
*
|
|
4
|
+
* sessions.ndjson is append-only; the instance.yaml claim field remains
|
|
5
|
+
* concurrency control only. Attribution intervals are derived here.
|
|
6
|
+
*
|
|
7
|
+
* The active-session stash (design §2.3) joins platform session ids to
|
|
8
|
+
* claims: SessionStart hooks write stash entries; `aidlc claim` resolves
|
|
9
|
+
* the current session with a strict single-candidate rule.
|
|
10
|
+
*
|
|
11
|
+
* Design: design.md §2.2, §2.3, §4.3
|
|
12
|
+
*/
|
|
13
|
+
import type { SessionEvent, ClaimInterval, ActiveSession } from './types.js';
|
|
14
|
+
export declare function sessionsPath(projectRoot: string, instance: string): string;
|
|
15
|
+
export declare function stashDir(projectRoot: string): string;
|
|
16
|
+
/** Append a session event (O_APPEND whole-line write). */
|
|
17
|
+
export declare function appendSessionEvent(path: string, event: SessionEvent): void;
|
|
18
|
+
/** Read valid session events; missing file → empty; bad lines skipped. */
|
|
19
|
+
export declare function readSessionEvents(path: string): SessionEvent[];
|
|
20
|
+
/**
|
|
21
|
+
* Resolve attribution intervals from session events (FR1.3).
|
|
22
|
+
*
|
|
23
|
+
* claim → release pairs per session; an unreleased claim is bounded by
|
|
24
|
+
* min(now, lastEventForSession + claimTimeoutMinutes) and marked open.
|
|
25
|
+
* Renew events extend the liveness bound of an open claim.
|
|
26
|
+
*/
|
|
27
|
+
export declare function resolveIntervals(events: SessionEvent[], claimTimeoutMinutes: number, now?: Date): ClaimInterval[];
|
|
28
|
+
/** Write a stash entry for a just-started platform session. */
|
|
29
|
+
export declare function stashSession(projectRoot: string, session: ActiveSession): void;
|
|
30
|
+
/** Remove stash entries older than the TTL. Called opportunistically. */
|
|
31
|
+
export declare function pruneStash(projectRoot: string, now?: Date): void;
|
|
32
|
+
/** Resolve a directory to its repo identity (git common dir), or null. */
|
|
33
|
+
export declare function repoIdentity(cwd: string): string | null;
|
|
34
|
+
/**
|
|
35
|
+
* Find the current platform session with the strict single-candidate rule:
|
|
36
|
+
* exactly one live stash entry whose repo identity matches → that session;
|
|
37
|
+
* zero or multiple → null (caller degrades to id_source: agent).
|
|
38
|
+
*/
|
|
39
|
+
export declare function resolveCurrentSession(projectRoot: string, now?: Date): ActiveSession | null;
|
|
40
|
+
//# sourceMappingURL=sessions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sessions.d.ts","sourceRoot":"","sources":["../../src/cost/sessions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAgBH,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAM7E,wBAAgB,YAAY,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAE1E;AAED,wBAAgB,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAEpD;AAgBD,0DAA0D;AAC1D,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,GAAG,IAAI,CAS1E;AAED,0EAA0E;AAC1E,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,EAAE,CAuB9D;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,YAAY,EAAE,EACtB,mBAAmB,EAAE,MAAM,EAC3B,GAAG,GAAE,IAAiB,GACrB,aAAa,EAAE,CA6BjB;AAiBD,+DAA+D;AAC/D,wBAAgB,YAAY,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,GAAG,IAAI,CAK9E;AAED,yEAAyE;AACzE,wBAAgB,UAAU,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,GAAE,IAAiB,GAAG,IAAI,CAc5E;AAED,0EAA0E;AAC1E,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAWvD;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CACnC,WAAW,EAAE,MAAM,EACnB,GAAG,GAAE,IAAiB,GACrB,aAAa,GAAG,IAAI,CAqBtB"}
|