@ai-dossier/core 1.4.2 → 1.5.1
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/README.md +32 -0
- package/dist/agent-usage.d.ts +103 -0
- package/dist/agent-usage.d.ts.map +1 -0
- package/dist/agent-usage.js +493 -0
- package/dist/agent-usage.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -2
- package/dist/index.js.map +1 -1
- package/dist/run-log-entry.d.ts +97 -0
- package/dist/run-log-entry.d.ts.map +1 -0
- package/dist/run-log-entry.js +50 -0
- package/dist/run-log-entry.js.map +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -205,6 +205,38 @@ const verifier = registry.get('ed25519');
|
|
|
205
205
|
const result = await verifier.verify(content, signature);
|
|
206
206
|
```
|
|
207
207
|
|
|
208
|
+
### Agent Usage & Run Log
|
|
209
|
+
|
|
210
|
+
Shared with `packages/sched` so both the `ai-dossier run` headless path and the
|
|
211
|
+
scheduler's detached dispatch path agree on which block of an agent's result is the
|
|
212
|
+
source of record.
|
|
213
|
+
|
|
214
|
+
```typescript
|
|
215
|
+
import {
|
|
216
|
+
parseAgentUsage, // claude: one --output-format json object, OR a stream-json event stream
|
|
217
|
+
parseOpenCodeUsage, // opencode: a `run --format json` JSONL event stream
|
|
218
|
+
usageParserFor, // pick the parser from the spawned binary's basename
|
|
219
|
+
runsLogPath, // ~/.dossier/runs.jsonl
|
|
220
|
+
SCHED_DISPATCH_EVENT, // the sched dispatch-log preamble `type`, skipped by both parsers
|
|
221
|
+
type AgentRunUsage,
|
|
222
|
+
type RunLogEntry,
|
|
223
|
+
} from '@ai-dossier/core';
|
|
224
|
+
|
|
225
|
+
const usage = parseAgentUsage(stdout);
|
|
226
|
+
// → { model, input_tokens, output_tokens, cache_creation_tokens,
|
|
227
|
+
// cache_read_tokens, total_cost_usd, result_text } — every field null
|
|
228
|
+
// when the agent did not report it; values are never fabricated.
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
`parseAgentUsage` treats the agent's per-model **`modelUsage` map as the source of
|
|
232
|
+
record** whenever it carries at least one object-shaped entry, summed across models. The
|
|
233
|
+
top-level `usage` block is used only when `modelUsage` has no such entry — the two are
|
|
234
|
+
never blended field-by-field, because they have been observed to disagree enough to
|
|
235
|
+
fabricate a ~43% "saving" when mixed (ai-dossier#524). Cost is read from `costUSD` (the
|
|
236
|
+
key claude writes), falling back to the top-level total when `modelUsage` reports no cost
|
|
237
|
+
at all. For a `stream-json` log the final `type:"result"` event wins; with no such event
|
|
238
|
+
(an agent killed mid-run) per-turn `assistant` usage is summed instead.
|
|
239
|
+
|
|
208
240
|
## Types
|
|
209
241
|
|
|
210
242
|
All TypeScript types are exported from the package root:
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parsers for headless-agent JSON result output — the token/cost/model data
|
|
3
|
+
* an `ai-dossier run` or `packages/sched` dispatch needs to record in
|
|
4
|
+
* `runs.jsonl` (#458, #524).
|
|
5
|
+
*
|
|
6
|
+
* Shared between `cli` (the `ai-dossier run` headless path) and `sched` (the
|
|
7
|
+
* scheduler's detached-agent dispatch path) so both consumers agree on which
|
|
8
|
+
* block of a claude/opencode result is the source of record — the divergence
|
|
9
|
+
* between them (one reading `usage`, the other `modelUsage`, and disagreeing
|
|
10
|
+
* enough to fabricate a ~43% "saving" when mixed, ai-dossier#524) is exactly
|
|
11
|
+
* the bug this module exists to close off. Lives in `core`, not `cli`,
|
|
12
|
+
* because `sched` cannot depend on `cli` (the dependency runs the other way:
|
|
13
|
+
* `cli` already depends on both `core` and `sched`).
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* Usage data extracted from an agent CLI's JSON result output.
|
|
17
|
+
* Every field is null when the CLI did not report it — values are never
|
|
18
|
+
* fabricated or estimated.
|
|
19
|
+
*/
|
|
20
|
+
export interface AgentRunUsage {
|
|
21
|
+
/** Model id the agent reported; comma-joined when several models ran (token/cost fields are totals across all). */
|
|
22
|
+
model: string | null;
|
|
23
|
+
input_tokens: number | null;
|
|
24
|
+
output_tokens: number | null;
|
|
25
|
+
/** Cache-creation (write) input tokens, summed across models when several ran. */
|
|
26
|
+
cache_creation_tokens: number | null;
|
|
27
|
+
/** Cache-read input tokens, summed across models when several ran. */
|
|
28
|
+
cache_read_tokens: number | null;
|
|
29
|
+
total_cost_usd: number | null;
|
|
30
|
+
/** The final result text (claude's `result` field), for re-emitting to stdout. */
|
|
31
|
+
result_text: string | null;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* `type` of the preamble line `packages/sched` writes to a dispatch log at
|
|
35
|
+
* spawn time (ai-dossier#524). It exists so a log is never 0 bytes for a unit
|
|
36
|
+
* that ran; every parser here skips it rather than counting it as agent
|
|
37
|
+
* output. Shared from `core` so the writer (`sched`'s `createSpawnDeps`) and
|
|
38
|
+
* the readers (below) can never drift apart on the sentinel's spelling.
|
|
39
|
+
*/
|
|
40
|
+
export declare const SCHED_DISPATCH_EVENT = "sched-dispatch";
|
|
41
|
+
/**
|
|
42
|
+
* Parse a claude headless result into usage data — both output formats.
|
|
43
|
+
*
|
|
44
|
+
* Accepts either shape, because the two consumers spawn claude differently:
|
|
45
|
+
*
|
|
46
|
+
* - **A single JSON object** (`--output-format json`, what `ai-dossier run`
|
|
47
|
+
* uses): parsed whole.
|
|
48
|
+
* - **A JSONL event stream** (`--output-format stream-json`, what the
|
|
49
|
+
* scheduler dispatches with since ai-dossier#524): the LAST `type:"result"`
|
|
50
|
+
* event wins — a per-unit log is append-mode, so a prior dispatch's result
|
|
51
|
+
* may precede this one in the same slice. With no `result` event at all (an
|
|
52
|
+
* agent killed mid-run), per-turn `assistant` usage is summed instead, so an
|
|
53
|
+
* interrupted dispatch still reports the tokens it really spent.
|
|
54
|
+
*
|
|
55
|
+
* Lines that do not parse as JSON objects are skipped rather than
|
|
56
|
+
* disqualifying the stream: the sched dispatch preamble
|
|
57
|
+
* ({@link SCHED_DISPATCH_EVENT}) sits at the head of every dispatch slice, and
|
|
58
|
+
* an agent killed mid-write leaves a truncated final line.
|
|
59
|
+
*
|
|
60
|
+
* Returns null when the output parses as neither shape (and for a stream
|
|
61
|
+
* holding no usage-bearing event). A result object that simply reported no
|
|
62
|
+
* usage yields an entry whose fields are all null, not `null` itself —
|
|
63
|
+
* "the agent reported nothing" and "there was no agent output" stay distinct.
|
|
64
|
+
*/
|
|
65
|
+
export declare function parseAgentUsage(stdout: string | null | undefined): AgentRunUsage | null;
|
|
66
|
+
/**
|
|
67
|
+
* Parse an `opencode run --format json` result stream into usage data (#459).
|
|
68
|
+
*
|
|
69
|
+
* opencode emits one JSON event per line: the assistant's text arrives in
|
|
70
|
+
* `type:"text"` parts, and per-step token/cost totals in `type:"step_finish"`
|
|
71
|
+
* parts (a multi-step run emits several — tokens and cost are summed), with
|
|
72
|
+
* cache counts nested as `tokens.cache: { write, read }`. The model id is not
|
|
73
|
+
* present in the events, so `model` is null and callers fall back to the
|
|
74
|
+
* requested --model alias — that field, and only that field, is genuinely
|
|
75
|
+
* unavailable here rather than merely absent. Returns null when the output
|
|
76
|
+
* holds no opencode event at all; individual non-JSON lines (stderr warnings
|
|
77
|
+
* interleaved by the scheduler's merged stdout/stderr fd) are skipped, not
|
|
78
|
+
* treated as disqualifying.
|
|
79
|
+
*
|
|
80
|
+
* **Cross-agent caveat.** opencode reports `tokens.reasoning` SEPARATELY from
|
|
81
|
+
* `tokens.output` (a step's `total` is input + output + reasoning +
|
|
82
|
+
* cache.read), whereas claude folds thinking tokens into `output_tokens`.
|
|
83
|
+
* Reasoning is 45-75% of generated tokens in real logs, so an opencode
|
|
84
|
+
* `output_tokens` is NOT directly comparable to a claude one — do not put the
|
|
85
|
+
* two in the same column of a cost comparison without saying so. It is left
|
|
86
|
+
* out rather than summed in because this module never derives a value the
|
|
87
|
+
* agent did not report; capturing it needs a field of its own on
|
|
88
|
+
* {@link AgentRunUsage} and `RunLogEntry`, which is a schema change beyond
|
|
89
|
+
* ai-dossier#524's scope.
|
|
90
|
+
*/
|
|
91
|
+
export declare function parseOpenCodeUsage(stdout: string | null | undefined): AgentRunUsage | null;
|
|
92
|
+
/**
|
|
93
|
+
* Pick the usage parser for a dispatched agent, keyed off the spawned
|
|
94
|
+
* binary's basename — `opencode` (any path) routes to
|
|
95
|
+
* {@link parseOpenCodeUsage}; everything else, including an
|
|
96
|
+
* operator-configured command this build doesn't specifically recognize,
|
|
97
|
+
* falls back to {@link parseAgentUsage} (the claude shape). A command this
|
|
98
|
+
* build doesn't recognize is not guessed at further than that fallback —
|
|
99
|
+
* its output either parses as a claude-shaped JSON result or the parser
|
|
100
|
+
* returns null, never a fabricated guess.
|
|
101
|
+
*/
|
|
102
|
+
export declare function usageParserFor(cmd0: string): (stdout: string | null | undefined) => AgentRunUsage | null;
|
|
103
|
+
//# sourceMappingURL=agent-usage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-usage.d.ts","sourceRoot":"","sources":["../src/agent-usage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAIH;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC5B,mHAAmH;IACnH,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,kFAAkF;IAClF,qBAAqB,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,sEAAsE;IACtE,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,kFAAkF;IAClF,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAsFD;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,mBAAmB,CAAC;AAoLrD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,aAAa,GAAG,IAAI,CA6BvF;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,aAAa,GAAG,IAAI,CA6F1F;AAED;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,GACX,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,KAAK,aAAa,GAAG,IAAI,CAE7D"}
|
|
@@ -0,0 +1,493 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Parsers for headless-agent JSON result output — the token/cost/model data
|
|
4
|
+
* an `ai-dossier run` or `packages/sched` dispatch needs to record in
|
|
5
|
+
* `runs.jsonl` (#458, #524).
|
|
6
|
+
*
|
|
7
|
+
* Shared between `cli` (the `ai-dossier run` headless path) and `sched` (the
|
|
8
|
+
* scheduler's detached-agent dispatch path) so both consumers agree on which
|
|
9
|
+
* block of a claude/opencode result is the source of record — the divergence
|
|
10
|
+
* between them (one reading `usage`, the other `modelUsage`, and disagreeing
|
|
11
|
+
* enough to fabricate a ~43% "saving" when mixed, ai-dossier#524) is exactly
|
|
12
|
+
* the bug this module exists to close off. Lives in `core`, not `cli`,
|
|
13
|
+
* because `sched` cannot depend on `cli` (the dependency runs the other way:
|
|
14
|
+
* `cli` already depends on both `core` and `sched`).
|
|
15
|
+
*/
|
|
16
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
17
|
+
if (k2 === undefined) k2 = k;
|
|
18
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
19
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
20
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
21
|
+
}
|
|
22
|
+
Object.defineProperty(o, k2, desc);
|
|
23
|
+
}) : (function(o, m, k, k2) {
|
|
24
|
+
if (k2 === undefined) k2 = k;
|
|
25
|
+
o[k2] = m[k];
|
|
26
|
+
}));
|
|
27
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
28
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
29
|
+
}) : function(o, v) {
|
|
30
|
+
o["default"] = v;
|
|
31
|
+
});
|
|
32
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
33
|
+
var ownKeys = function(o) {
|
|
34
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
35
|
+
var ar = [];
|
|
36
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
37
|
+
return ar;
|
|
38
|
+
};
|
|
39
|
+
return ownKeys(o);
|
|
40
|
+
};
|
|
41
|
+
return function (mod) {
|
|
42
|
+
if (mod && mod.__esModule) return mod;
|
|
43
|
+
var result = {};
|
|
44
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
45
|
+
__setModuleDefault(result, mod);
|
|
46
|
+
return result;
|
|
47
|
+
};
|
|
48
|
+
})();
|
|
49
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
50
|
+
exports.SCHED_DISPATCH_EVENT = void 0;
|
|
51
|
+
exports.parseAgentUsage = parseAgentUsage;
|
|
52
|
+
exports.parseOpenCodeUsage = parseOpenCodeUsage;
|
|
53
|
+
exports.usageParserFor = usageParserFor;
|
|
54
|
+
const path = __importStar(require("node:path"));
|
|
55
|
+
/**
|
|
56
|
+
* Largest token count accepted from an agent (#524). Well above any real run
|
|
57
|
+
* (a 1M-token context ×1000 turns), and low enough that summing a cohort of
|
|
58
|
+
* them in `sched stats` cannot reach Infinity.
|
|
59
|
+
*/
|
|
60
|
+
const MAX_REPORTED_TOKENS = 1e15;
|
|
61
|
+
/** Largest cost in USD accepted from an agent (#524) — no real dispatch approaches it. */
|
|
62
|
+
const MAX_REPORTED_COST_USD = 1e6;
|
|
63
|
+
/**
|
|
64
|
+
* Narrow untrusted agent output to a finite, non-negative number within a
|
|
65
|
+
* sane ceiling (#524). Used for token counts AND for costs — hence the
|
|
66
|
+
* explicit `max`, since the two have very different plausible ranges.
|
|
67
|
+
*
|
|
68
|
+
* The ceiling is not paranoia: `sched stats` sums these across a cohort, and
|
|
69
|
+
* a single `1e308` entry would carry the whole TOTAL row to Infinity, which
|
|
70
|
+
* the formatter renders as `-` — silently blanking every legitimate run
|
|
71
|
+
* alongside it. Out-of-range values are rejected (null = "not reported")
|
|
72
|
+
* rather than clamped, so a bogus number is never presented as a real one.
|
|
73
|
+
*/
|
|
74
|
+
function toBounded(value, max) {
|
|
75
|
+
return typeof value === 'number' && Number.isFinite(value) && value >= 0 && value <= max
|
|
76
|
+
? value
|
|
77
|
+
: null;
|
|
78
|
+
}
|
|
79
|
+
/** Token-count flavour of {@link toBounded}. */
|
|
80
|
+
function toCount(value) {
|
|
81
|
+
return toBounded(value, MAX_REPORTED_TOKENS);
|
|
82
|
+
}
|
|
83
|
+
/** Cost flavour of {@link toBounded} — a USD amount, not a count. */
|
|
84
|
+
function toCost(value) {
|
|
85
|
+
return toBounded(value, MAX_REPORTED_COST_USD);
|
|
86
|
+
}
|
|
87
|
+
/** Longest `model` value written to `runs.jsonl` before truncation (#524). */
|
|
88
|
+
const MAX_MODEL_LENGTH = 200;
|
|
89
|
+
/**
|
|
90
|
+
* Most model names joined into one `model` value (#524). The map/stream those
|
|
91
|
+
* names come from is agent-controlled and unbounded, so the join is capped
|
|
92
|
+
* before {@link sanitizeModel} ever sees it — 16 distinct models in one run
|
|
93
|
+
* is already far beyond anything real.
|
|
94
|
+
*/
|
|
95
|
+
const MAX_MODELS_JOINED = 16;
|
|
96
|
+
/** Join model names for the `model` field, bounded by {@link MAX_MODELS_JOINED}. */
|
|
97
|
+
function joinModels(names) {
|
|
98
|
+
if (names.length === 0)
|
|
99
|
+
return null;
|
|
100
|
+
if (names.length === 1)
|
|
101
|
+
return names[0];
|
|
102
|
+
return names.slice(0, MAX_MODELS_JOINED).join(',');
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* `model` is copied verbatim from untrusted agent JSON into a `runs.jsonl`
|
|
106
|
+
* entry a later command (`ai-dossier history`, `sched stats`) may render.
|
|
107
|
+
* Strip control characters (the terminal-escape/log-injection risk) and cap
|
|
108
|
+
* the length, rather than trusting an agent-controlled string unbounded.
|
|
109
|
+
*/
|
|
110
|
+
function sanitizeModel(value) {
|
|
111
|
+
if (value === null)
|
|
112
|
+
return null;
|
|
113
|
+
let clean = '';
|
|
114
|
+
// Bound the WORK, not just the result: `value` is agent-controlled and can
|
|
115
|
+
// be arbitrarily long, so stop as soon as the cap is reached rather than
|
|
116
|
+
// materializing a sanitized copy of the whole string first.
|
|
117
|
+
for (const char of value) {
|
|
118
|
+
if (clean.length >= MAX_MODEL_LENGTH)
|
|
119
|
+
break;
|
|
120
|
+
const code = char.codePointAt(0) ?? 0;
|
|
121
|
+
// C0 (< 0x20), DEL (0x7f) and C1 (0x80-0x9f) alike: U+009B is the 8-bit
|
|
122
|
+
// CSI, which a terminal in a non-UTF-8 locale acts on exactly like ESC[.
|
|
123
|
+
if (code >= 0x20 && code !== 0x7f && !(code >= 0x80 && code <= 0x9f))
|
|
124
|
+
clean += char;
|
|
125
|
+
}
|
|
126
|
+
return clean;
|
|
127
|
+
}
|
|
128
|
+
/** Narrow an unknown value to a plain-object record; null for anything else. */
|
|
129
|
+
function asRecord(value) {
|
|
130
|
+
return value !== null && typeof value === 'object' && !Array.isArray(value)
|
|
131
|
+
? value
|
|
132
|
+
: null;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* `type` of the preamble line `packages/sched` writes to a dispatch log at
|
|
136
|
+
* spawn time (ai-dossier#524). It exists so a log is never 0 bytes for a unit
|
|
137
|
+
* that ran; every parser here skips it rather than counting it as agent
|
|
138
|
+
* output. Shared from `core` so the writer (`sched`'s `createSpawnDeps`) and
|
|
139
|
+
* the readers (below) can never drift apart on the sentinel's spelling.
|
|
140
|
+
*/
|
|
141
|
+
exports.SCHED_DISPATCH_EVENT = 'sched-dispatch';
|
|
142
|
+
/**
|
|
143
|
+
* Event `type`s that only ever appear INSIDE a stream, never as a whole
|
|
144
|
+
* `--output-format json` payload. A single such line must be parsed as a
|
|
145
|
+
* one-line stream, not mistaken for a result object (#524 review).
|
|
146
|
+
*/
|
|
147
|
+
const STREAM_EVENT_TYPES = new Set([
|
|
148
|
+
'assistant',
|
|
149
|
+
'user',
|
|
150
|
+
'system',
|
|
151
|
+
exports.SCHED_DISPATCH_EVENT,
|
|
152
|
+
]);
|
|
153
|
+
/** Parse one string as a JSON object; null for anything else (array, scalar, malformed). */
|
|
154
|
+
function parseJsonObject(text) {
|
|
155
|
+
try {
|
|
156
|
+
return asRecord(JSON.parse(text));
|
|
157
|
+
}
|
|
158
|
+
catch {
|
|
159
|
+
return null;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Extract usage from a claude `result`-shaped object — the payload of
|
|
164
|
+
* `--output-format json`, and of the final `type:"result"` event of
|
|
165
|
+
* `--output-format stream-json`. Both carry the same fields.
|
|
166
|
+
*
|
|
167
|
+
* `modelUsage` (summed across every model entry) is the source of record for
|
|
168
|
+
* token counts and cost — it is the only block that reflects a multi-model
|
|
169
|
+
* run accurately. The top-level `usage` / `total_cost_usd` (older: `cost_usd`)
|
|
170
|
+
* fields are used ONLY when `modelUsage` has no object-shaped entry at all:
|
|
171
|
+
* they are never blended field-by-field with it, because the two blocks have been
|
|
172
|
+
* observed to disagree (ai-dossier#524) — picking one field from each would
|
|
173
|
+
* silently produce a number neither block actually reported.
|
|
174
|
+
*/
|
|
175
|
+
function extractResultUsage(parsed) {
|
|
176
|
+
const usage = asRecord(parsed.usage) ?? {};
|
|
177
|
+
const modelUsage = asRecord(parsed.modelUsage);
|
|
178
|
+
// Keep only object-shaped entries; a scalar entry is malformed, not a model.
|
|
179
|
+
const modelEntries = modelUsage
|
|
180
|
+
? Object.entries(modelUsage).filter((entry) => !!asRecord(entry[1]))
|
|
181
|
+
: [];
|
|
182
|
+
const hasModelUsage = modelEntries.length > 0;
|
|
183
|
+
/** Sum one field across every model entry, trying each spelling in turn. */
|
|
184
|
+
const sumFromModelUsage = (keys, narrow = toCount) => {
|
|
185
|
+
let sum = 0;
|
|
186
|
+
let seen = false;
|
|
187
|
+
for (const [, entry] of modelEntries) {
|
|
188
|
+
let value = null;
|
|
189
|
+
for (const key of keys) {
|
|
190
|
+
value = narrow(entry[key]);
|
|
191
|
+
if (value !== null)
|
|
192
|
+
break;
|
|
193
|
+
}
|
|
194
|
+
if (value !== null) {
|
|
195
|
+
sum += value;
|
|
196
|
+
seen = true;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
return seen ? sum : null;
|
|
200
|
+
};
|
|
201
|
+
// modelUsage wins whenever it carries at least one object-shaped entry —
|
|
202
|
+
// even if that entry only answers some of the fields — so a run's numbers
|
|
203
|
+
// always come from a single, consistent block rather than a per-field blend
|
|
204
|
+
// with `usage`. (`modelUsage: {}`, or a map whose every entry is a scalar,
|
|
205
|
+
// is malformed rather than present: `usage` is used in that case.)
|
|
206
|
+
const input_tokens = hasModelUsage
|
|
207
|
+
? sumFromModelUsage(['inputTokens', 'input_tokens'])
|
|
208
|
+
: toCount(usage.input_tokens);
|
|
209
|
+
const output_tokens = hasModelUsage
|
|
210
|
+
? sumFromModelUsage(['outputTokens', 'output_tokens'])
|
|
211
|
+
: toCount(usage.output_tokens);
|
|
212
|
+
const cache_creation_tokens = hasModelUsage
|
|
213
|
+
? sumFromModelUsage(['cacheCreationInputTokens', 'cache_creation_input_tokens'])
|
|
214
|
+
: toCount(usage.cache_creation_input_tokens);
|
|
215
|
+
const cache_read_tokens = hasModelUsage
|
|
216
|
+
? sumFromModelUsage(['cacheReadInputTokens', 'cache_read_input_tokens'])
|
|
217
|
+
: toCount(usage.cache_read_input_tokens);
|
|
218
|
+
// `costUSD` FIRST: that is the key claude actually writes inside a
|
|
219
|
+
// `modelUsage` entry (verified against a live claude stats artifact, #524
|
|
220
|
+
// review). `totalCostUsd`/`total_cost_usd` are kept as tolerated spellings.
|
|
221
|
+
// When modelUsage reports no cost key at all, fall back to the top-level
|
|
222
|
+
// total rather than reporting null — the whole-run cost is not a per-field
|
|
223
|
+
// blend of two token blocks, it is the one number both shapes agree on, and
|
|
224
|
+
// dropping it silently regressed `ai-dossier run`'s existing cost recording.
|
|
225
|
+
const costFromModelUsage = hasModelUsage
|
|
226
|
+
? sumFromModelUsage(['costUSD', 'totalCostUsd', 'total_cost_usd'], toCost)
|
|
227
|
+
: null;
|
|
228
|
+
const total_cost_usd = costFromModelUsage ?? toCost(parsed.total_cost_usd) ?? toCost(parsed.cost_usd);
|
|
229
|
+
const modelFromUsage = joinModels(modelEntries.map(([key]) => key));
|
|
230
|
+
const rawModel = typeof parsed.model === 'string' && parsed.model ? parsed.model : modelFromUsage;
|
|
231
|
+
const model = sanitizeModel(rawModel);
|
|
232
|
+
const result_text = typeof parsed.result === 'string' ? parsed.result : null;
|
|
233
|
+
return {
|
|
234
|
+
model,
|
|
235
|
+
input_tokens,
|
|
236
|
+
output_tokens,
|
|
237
|
+
cache_creation_tokens,
|
|
238
|
+
cache_read_tokens,
|
|
239
|
+
total_cost_usd,
|
|
240
|
+
result_text,
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Sum per-turn usage from `type:"assistant"` stream events — the fallback for
|
|
245
|
+
* a run that produced NO final `result` event (ai-dossier#524).
|
|
246
|
+
*
|
|
247
|
+
* The scheduler kills an agent that is still alive when ground truth says its
|
|
248
|
+
* unit is already done (`reconcileRunning`'s external-advance branch), and a
|
|
249
|
+
* killed agent never emits its `result` event. Before stream-json that meant
|
|
250
|
+
* zero recoverable tokens for those dispatches — six of the eleven pilot units.
|
|
251
|
+
* Each `assistant` event carries the usage of the request that produced it, so
|
|
252
|
+
* summing them recovers what the run actually spent up to the kill.
|
|
253
|
+
*
|
|
254
|
+
* `total_cost_usd` stays null: per-turn events do not report cost, and this
|
|
255
|
+
* path must not fabricate one from token counts.
|
|
256
|
+
*/
|
|
257
|
+
function sumAssistantUsage(events) {
|
|
258
|
+
let input = 0;
|
|
259
|
+
let output = 0;
|
|
260
|
+
let cacheCreation = 0;
|
|
261
|
+
let cacheRead = 0;
|
|
262
|
+
let sawInput = false;
|
|
263
|
+
let sawOutput = false;
|
|
264
|
+
let sawCacheCreation = false;
|
|
265
|
+
let sawCacheRead = false;
|
|
266
|
+
const models = new Set();
|
|
267
|
+
for (const event of events) {
|
|
268
|
+
const message = asRecord(event.message);
|
|
269
|
+
if (!message)
|
|
270
|
+
continue;
|
|
271
|
+
if (typeof message.model === 'string' && message.model)
|
|
272
|
+
models.add(message.model);
|
|
273
|
+
const usage = asRecord(message.usage);
|
|
274
|
+
if (!usage)
|
|
275
|
+
continue;
|
|
276
|
+
const inputTokens = toCount(usage.input_tokens);
|
|
277
|
+
if (inputTokens !== null) {
|
|
278
|
+
input += inputTokens;
|
|
279
|
+
sawInput = true;
|
|
280
|
+
}
|
|
281
|
+
const outputTokens = toCount(usage.output_tokens);
|
|
282
|
+
if (outputTokens !== null) {
|
|
283
|
+
output += outputTokens;
|
|
284
|
+
sawOutput = true;
|
|
285
|
+
}
|
|
286
|
+
const cacheCreationTokens = toCount(usage.cache_creation_input_tokens);
|
|
287
|
+
if (cacheCreationTokens !== null) {
|
|
288
|
+
cacheCreation += cacheCreationTokens;
|
|
289
|
+
sawCacheCreation = true;
|
|
290
|
+
}
|
|
291
|
+
const cacheReadTokens = toCount(usage.cache_read_input_tokens);
|
|
292
|
+
if (cacheReadTokens !== null) {
|
|
293
|
+
cacheRead += cacheReadTokens;
|
|
294
|
+
sawCacheRead = true;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
return {
|
|
298
|
+
model: sanitizeModel(joinModels([...models])),
|
|
299
|
+
input_tokens: sawInput ? input : null,
|
|
300
|
+
output_tokens: sawOutput ? output : null,
|
|
301
|
+
cache_creation_tokens: sawCacheCreation ? cacheCreation : null,
|
|
302
|
+
cache_read_tokens: sawCacheRead ? cacheRead : null,
|
|
303
|
+
total_cost_usd: null,
|
|
304
|
+
result_text: null,
|
|
305
|
+
};
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* Parse a claude headless result into usage data — both output formats.
|
|
309
|
+
*
|
|
310
|
+
* Accepts either shape, because the two consumers spawn claude differently:
|
|
311
|
+
*
|
|
312
|
+
* - **A single JSON object** (`--output-format json`, what `ai-dossier run`
|
|
313
|
+
* uses): parsed whole.
|
|
314
|
+
* - **A JSONL event stream** (`--output-format stream-json`, what the
|
|
315
|
+
* scheduler dispatches with since ai-dossier#524): the LAST `type:"result"`
|
|
316
|
+
* event wins — a per-unit log is append-mode, so a prior dispatch's result
|
|
317
|
+
* may precede this one in the same slice. With no `result` event at all (an
|
|
318
|
+
* agent killed mid-run), per-turn `assistant` usage is summed instead, so an
|
|
319
|
+
* interrupted dispatch still reports the tokens it really spent.
|
|
320
|
+
*
|
|
321
|
+
* Lines that do not parse as JSON objects are skipped rather than
|
|
322
|
+
* disqualifying the stream: the sched dispatch preamble
|
|
323
|
+
* ({@link SCHED_DISPATCH_EVENT}) sits at the head of every dispatch slice, and
|
|
324
|
+
* an agent killed mid-write leaves a truncated final line.
|
|
325
|
+
*
|
|
326
|
+
* Returns null when the output parses as neither shape (and for a stream
|
|
327
|
+
* holding no usage-bearing event). A result object that simply reported no
|
|
328
|
+
* usage yields an entry whose fields are all null, not `null` itself —
|
|
329
|
+
* "the agent reported nothing" and "there was no agent output" stay distinct.
|
|
330
|
+
*/
|
|
331
|
+
function parseAgentUsage(stdout) {
|
|
332
|
+
if (typeof stdout !== 'string' || stdout.trim() === '')
|
|
333
|
+
return null;
|
|
334
|
+
// `--output-format json`: the whole payload is one object. Checked first so
|
|
335
|
+
// a pretty-printed (multi-line) result is not mistaken for an event stream.
|
|
336
|
+
// Stream event types are excluded, or a stream that happens to hold exactly
|
|
337
|
+
// ONE line (an agent killed after a single turn, or whose preamble write
|
|
338
|
+
// failed) would take this path and report all-null instead of falling
|
|
339
|
+
// through to the per-turn sum below.
|
|
340
|
+
const single = parseJsonObject(stdout);
|
|
341
|
+
if (single && !STREAM_EVENT_TYPES.has(single.type))
|
|
342
|
+
return extractResultUsage(single);
|
|
343
|
+
let lastResult = null;
|
|
344
|
+
const assistants = [];
|
|
345
|
+
for (const line of stdout.split('\n')) {
|
|
346
|
+
const trimmed = line.trim();
|
|
347
|
+
if (!trimmed)
|
|
348
|
+
continue;
|
|
349
|
+
const event = parseJsonObject(trimmed);
|
|
350
|
+
if (!event || event.type === exports.SCHED_DISPATCH_EVENT)
|
|
351
|
+
continue;
|
|
352
|
+
if (event.type === 'result')
|
|
353
|
+
lastResult = event;
|
|
354
|
+
else if (event.type === 'assistant')
|
|
355
|
+
assistants.push(event);
|
|
356
|
+
}
|
|
357
|
+
if (lastResult)
|
|
358
|
+
return extractResultUsage(lastResult);
|
|
359
|
+
if (assistants.length > 0)
|
|
360
|
+
return sumAssistantUsage(assistants);
|
|
361
|
+
return null;
|
|
362
|
+
}
|
|
363
|
+
/**
|
|
364
|
+
* Parse an `opencode run --format json` result stream into usage data (#459).
|
|
365
|
+
*
|
|
366
|
+
* opencode emits one JSON event per line: the assistant's text arrives in
|
|
367
|
+
* `type:"text"` parts, and per-step token/cost totals in `type:"step_finish"`
|
|
368
|
+
* parts (a multi-step run emits several — tokens and cost are summed), with
|
|
369
|
+
* cache counts nested as `tokens.cache: { write, read }`. The model id is not
|
|
370
|
+
* present in the events, so `model` is null and callers fall back to the
|
|
371
|
+
* requested --model alias — that field, and only that field, is genuinely
|
|
372
|
+
* unavailable here rather than merely absent. Returns null when the output
|
|
373
|
+
* holds no opencode event at all; individual non-JSON lines (stderr warnings
|
|
374
|
+
* interleaved by the scheduler's merged stdout/stderr fd) are skipped, not
|
|
375
|
+
* treated as disqualifying.
|
|
376
|
+
*
|
|
377
|
+
* **Cross-agent caveat.** opencode reports `tokens.reasoning` SEPARATELY from
|
|
378
|
+
* `tokens.output` (a step's `total` is input + output + reasoning +
|
|
379
|
+
* cache.read), whereas claude folds thinking tokens into `output_tokens`.
|
|
380
|
+
* Reasoning is 45-75% of generated tokens in real logs, so an opencode
|
|
381
|
+
* `output_tokens` is NOT directly comparable to a claude one — do not put the
|
|
382
|
+
* two in the same column of a cost comparison without saying so. It is left
|
|
383
|
+
* out rather than summed in because this module never derives a value the
|
|
384
|
+
* agent did not report; capturing it needs a field of its own on
|
|
385
|
+
* {@link AgentRunUsage} and `RunLogEntry`, which is a schema change beyond
|
|
386
|
+
* ai-dossier#524's scope.
|
|
387
|
+
*/
|
|
388
|
+
function parseOpenCodeUsage(stdout) {
|
|
389
|
+
if (typeof stdout !== 'string' || stdout.trim() === '')
|
|
390
|
+
return null;
|
|
391
|
+
let sawEvent = false;
|
|
392
|
+
const texts = [];
|
|
393
|
+
let inputTokens = 0;
|
|
394
|
+
let outputTokens = 0;
|
|
395
|
+
let cacheCreationTokens = 0;
|
|
396
|
+
let cacheReadTokens = 0;
|
|
397
|
+
let costUsd = 0;
|
|
398
|
+
let sawUsage = false;
|
|
399
|
+
let sawCacheCreation = false;
|
|
400
|
+
let sawCacheRead = false;
|
|
401
|
+
for (const line of stdout.split('\n')) {
|
|
402
|
+
const trimmed = line.trim();
|
|
403
|
+
if (!trimmed)
|
|
404
|
+
continue;
|
|
405
|
+
const event = parseJsonObject(trimmed);
|
|
406
|
+
// Skip an unparseable line rather than discarding the whole stream
|
|
407
|
+
// (#524 review). `createSpawnDeps` merges stderr into the SAME fd as
|
|
408
|
+
// stdout, and opencode writes ANSI-coloured warnings there ("permission
|
|
409
|
+
// requested: ... auto-rejecting"), so ONE such line in a 1,600-line log
|
|
410
|
+
// used to null out the entire run — ~$28 and ~97M cache-read tokens
|
|
411
|
+
// across two real logs on a six-run cohort, recorded as indistinguishable
|
|
412
|
+
// nulls. Format-mismatch detection is preserved by `sawEvent` below: a
|
|
413
|
+
// stream with no valid opencode event at all still returns null.
|
|
414
|
+
if (!event)
|
|
415
|
+
continue;
|
|
416
|
+
// The sched dispatch preamble (#524) is written by the scheduler, not by
|
|
417
|
+
// opencode: skip it WITHOUT setting `sawEvent`, so a log holding only a
|
|
418
|
+
// preamble still reads as "the agent wrote nothing" (null) rather than an
|
|
419
|
+
// all-null usage object implying opencode reported no tokens.
|
|
420
|
+
if (event.type === exports.SCHED_DISPATCH_EVENT)
|
|
421
|
+
continue;
|
|
422
|
+
sawEvent = true;
|
|
423
|
+
const part = asRecord(event.part);
|
|
424
|
+
if (event.type === 'text' && part && typeof part.text === 'string') {
|
|
425
|
+
texts.push(part.text);
|
|
426
|
+
}
|
|
427
|
+
if (event.type === 'step_finish' && part) {
|
|
428
|
+
const tokens = asRecord(part.tokens);
|
|
429
|
+
if (tokens) {
|
|
430
|
+
const input = toCount(tokens.input);
|
|
431
|
+
if (input !== null) {
|
|
432
|
+
inputTokens += input;
|
|
433
|
+
sawUsage = true;
|
|
434
|
+
}
|
|
435
|
+
const output = toCount(tokens.output);
|
|
436
|
+
if (output !== null) {
|
|
437
|
+
outputTokens += output;
|
|
438
|
+
sawUsage = true;
|
|
439
|
+
}
|
|
440
|
+
// opencode nests cache counts one level down, as
|
|
441
|
+
// `tokens.cache: { write, read }` — verified against a real 310-event
|
|
442
|
+
// dispatch log (#524 review). They were previously hardcoded null on
|
|
443
|
+
// the mistaken belief opencode did not report them, silently dropping
|
|
444
|
+
// tens of millions of cache-read tokens per run.
|
|
445
|
+
const cache = asRecord(tokens.cache);
|
|
446
|
+
if (cache) {
|
|
447
|
+
const write = toCount(cache.write);
|
|
448
|
+
if (write !== null) {
|
|
449
|
+
cacheCreationTokens += write;
|
|
450
|
+
sawCacheCreation = true;
|
|
451
|
+
sawUsage = true;
|
|
452
|
+
}
|
|
453
|
+
const read = toCount(cache.read);
|
|
454
|
+
if (read !== null) {
|
|
455
|
+
cacheReadTokens += read;
|
|
456
|
+
sawCacheRead = true;
|
|
457
|
+
sawUsage = true;
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
const cost = toCost(part.cost);
|
|
462
|
+
if (cost !== null) {
|
|
463
|
+
costUsd += cost;
|
|
464
|
+
sawUsage = true;
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
if (!sawEvent)
|
|
469
|
+
return null;
|
|
470
|
+
return {
|
|
471
|
+
model: null,
|
|
472
|
+
input_tokens: sawUsage ? inputTokens : null,
|
|
473
|
+
output_tokens: sawUsage ? outputTokens : null,
|
|
474
|
+
cache_creation_tokens: sawCacheCreation ? cacheCreationTokens : null,
|
|
475
|
+
cache_read_tokens: sawCacheRead ? cacheReadTokens : null,
|
|
476
|
+
total_cost_usd: sawUsage ? costUsd : null,
|
|
477
|
+
result_text: texts.length > 0 ? texts.join('') : null,
|
|
478
|
+
};
|
|
479
|
+
}
|
|
480
|
+
/**
|
|
481
|
+
* Pick the usage parser for a dispatched agent, keyed off the spawned
|
|
482
|
+
* binary's basename — `opencode` (any path) routes to
|
|
483
|
+
* {@link parseOpenCodeUsage}; everything else, including an
|
|
484
|
+
* operator-configured command this build doesn't specifically recognize,
|
|
485
|
+
* falls back to {@link parseAgentUsage} (the claude shape). A command this
|
|
486
|
+
* build doesn't recognize is not guessed at further than that fallback —
|
|
487
|
+
* its output either parses as a claude-shaped JSON result or the parser
|
|
488
|
+
* returns null, never a fabricated guess.
|
|
489
|
+
*/
|
|
490
|
+
function usageParserFor(cmd0) {
|
|
491
|
+
return path.basename(cmd0) === 'opencode' ? parseOpenCodeUsage : parseAgentUsage;
|
|
492
|
+
}
|
|
493
|
+
//# sourceMappingURL=agent-usage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-usage.js","sourceRoot":"","sources":["../src/agent-usage.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -6,8 +6,12 @@
|
|
|
6
6
|
* - Checksum verification (SHA256 integrity checks)
|
|
7
7
|
* - Signature verification (Minisign and AWS KMS)
|
|
8
8
|
* - Output coherence validation
|
|
9
|
+
* - Headless-agent usage parsing (token/cost from claude/opencode JSON results)
|
|
10
|
+
* - runs.jsonl entry schema and path (shared by cli + sched)
|
|
9
11
|
* - TypeScript type definitions
|
|
10
12
|
*/
|
|
13
|
+
export type { AgentRunUsage } from './agent-usage';
|
|
14
|
+
export { parseAgentUsage, parseOpenCodeUsage, SCHED_DISPATCH_EVENT, usageParserFor, } from './agent-usage';
|
|
11
15
|
export { calculateChecksum, verifyIntegrity } from './checksum';
|
|
12
16
|
export type { CoherenceContext, CoherenceDiagnostic, CoherenceResult, CoherenceSeverity, DeclaredOutputSchema, StepOutput, } from './coherence';
|
|
13
17
|
export { validateCoherence, validateStepCoherence } from './coherence';
|
|
@@ -18,6 +22,8 @@ export { defaultRules, LintRuleRegistry, lintDossier, lintDossierFile, loadLintC
|
|
|
18
22
|
export { parseDossierContent, parseDossierFile, RECOMMENDED_FIELDS, REQUIRED_FIELDS, VALID_RISK_LEVELS, VALID_STATUSES, validateFrontmatter, } from './parser';
|
|
19
23
|
export type { ChecksumStatus, ContentRiskResult, SignatureStatus, VerificationRiskLevel, VerificationRiskResult, } from './risk-assessment';
|
|
20
24
|
export { assessContentRisk, assessVerificationRisk } from './risk-assessment';
|
|
25
|
+
export type { RunLogEntry } from './run-log-entry';
|
|
26
|
+
export { runsLogPath } from './run-log-entry';
|
|
21
27
|
export type { SecurityCategory, SecurityFinding, SecurityReport, SecurityRule, SecurityRuleContext, SecurityRuleSeverityOverride, SecurityScanConfig, SecuritySeverity, } from './security-scanner';
|
|
22
28
|
export { buildReport, defaultSecurityRules, SecurityRuleRegistry, scanDossier, scanDossierFile, scanMarkdown, } from './security-scanner';
|
|
23
29
|
export type { TrustedKeyEntry, TrustedKeyProblem } from './signature';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -7,6 +7,8 @@
|
|
|
7
7
|
* - Checksum verification (SHA256 integrity checks)
|
|
8
8
|
* - Signature verification (Minisign and AWS KMS)
|
|
9
9
|
* - Output coherence validation
|
|
10
|
+
* - Headless-agent usage parsing (token/cost from claude/opencode JSON results)
|
|
11
|
+
* - runs.jsonl entry schema and path (shared by cli + sched)
|
|
10
12
|
* - TypeScript type definitions
|
|
11
13
|
*/
|
|
12
14
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
@@ -24,8 +26,13 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
24
26
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
25
27
|
};
|
|
26
28
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
27
|
-
exports.
|
|
28
|
-
exports.createDefaultVerificationResult = exports.scanBodyForUrls = exports.isUrlCoveredByDeclared = exports.isPlaceholderUrl = exports.findUndeclaredUrls = exports.findStaleReferences = exports.collectDeclaredUrls = exports.readFileIfExists = exports.getErrorStack = exports.getErrorMessage = exports.sha256Hex = exports.sha256Hash = exports.VALID_TRACE_STATUSES = void 0;
|
|
29
|
+
exports.normalizePublicKey = exports.isSupportedPublicKey = exports.canonicalizeFrontmatter = exports.buildSignedPayload = exports.VerifierRegistry = exports.KmsVerifier = exports.KmsSigner = exports.getVerifierRegistry = exports.Ed25519Verifier = exports.Ed25519Signer = exports.verifyWithKms = exports.verifyWithEd25519 = exports.verifySignature = exports.trustedKeysFromContent = exports.reportTrustedKeyProblems = exports.parseTrustedKeys = exports.loadTrustedKeys = exports.isKmsKeyIdentifier = exports.findTrustedIdentifier = exports.scanMarkdown = exports.scanDossierFile = exports.scanDossier = exports.SecurityRuleRegistry = exports.defaultSecurityRules = exports.buildReport = exports.runsLogPath = exports.assessVerificationRisk = exports.assessContentRisk = exports.validateFrontmatter = exports.VALID_STATUSES = exports.VALID_RISK_LEVELS = exports.REQUIRED_FIELDS = exports.RECOMMENDED_FIELDS = exports.parseDossierFile = exports.parseDossierContent = exports.loadLintConfig = exports.lintDossierFile = exports.lintDossier = exports.LintRuleRegistry = exports.defaultRules = exports.formatDossierFile = exports.formatDossierContent = exports.validateStepCoherence = exports.validateCoherence = exports.verifyIntegrity = exports.calculateChecksum = exports.usageParserFor = exports.SCHED_DISPATCH_EVENT = exports.parseOpenCodeUsage = exports.parseAgentUsage = void 0;
|
|
30
|
+
exports.createDefaultVerificationResult = exports.scanBodyForUrls = exports.isUrlCoveredByDeclared = exports.isPlaceholderUrl = exports.findUndeclaredUrls = exports.findStaleReferences = exports.collectDeclaredUrls = exports.readFileIfExists = exports.getErrorStack = exports.getErrorMessage = exports.sha256Hex = exports.sha256Hash = exports.VALID_TRACE_STATUSES = exports.createTraceRecorder = exports.resolveTraceConfig = exports.toSpkiPem = exports.signatureCoverage = exports.publicKeysMatch = void 0;
|
|
31
|
+
var agent_usage_1 = require("./agent-usage");
|
|
32
|
+
Object.defineProperty(exports, "parseAgentUsage", { enumerable: true, get: function () { return agent_usage_1.parseAgentUsage; } });
|
|
33
|
+
Object.defineProperty(exports, "parseOpenCodeUsage", { enumerable: true, get: function () { return agent_usage_1.parseOpenCodeUsage; } });
|
|
34
|
+
Object.defineProperty(exports, "SCHED_DISPATCH_EVENT", { enumerable: true, get: function () { return agent_usage_1.SCHED_DISPATCH_EVENT; } });
|
|
35
|
+
Object.defineProperty(exports, "usageParserFor", { enumerable: true, get: function () { return agent_usage_1.usageParserFor; } });
|
|
29
36
|
// Checksum exports
|
|
30
37
|
var checksum_1 = require("./checksum");
|
|
31
38
|
Object.defineProperty(exports, "calculateChecksum", { enumerable: true, get: function () { return checksum_1.calculateChecksum; } });
|
|
@@ -57,6 +64,8 @@ Object.defineProperty(exports, "validateFrontmatter", { enumerable: true, get: f
|
|
|
57
64
|
var risk_assessment_1 = require("./risk-assessment");
|
|
58
65
|
Object.defineProperty(exports, "assessContentRisk", { enumerable: true, get: function () { return risk_assessment_1.assessContentRisk; } });
|
|
59
66
|
Object.defineProperty(exports, "assessVerificationRisk", { enumerable: true, get: function () { return risk_assessment_1.assessVerificationRisk; } });
|
|
67
|
+
var run_log_entry_1 = require("./run-log-entry");
|
|
68
|
+
Object.defineProperty(exports, "runsLogPath", { enumerable: true, get: function () { return run_log_entry_1.runsLogPath; } });
|
|
60
69
|
var security_scanner_1 = require("./security-scanner");
|
|
61
70
|
Object.defineProperty(exports, "buildReport", { enumerable: true, get: function () { return security_scanner_1.buildReport; } });
|
|
62
71
|
Object.defineProperty(exports, "defaultSecurityRules", { enumerable: true, get: function () { return security_scanner_1.defaultSecurityRules; } });
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;GAWG;;;;;;;;;;;;;;;;;;AAIH,6CAKuB;AAJrB,8GAAA,eAAe,OAAA;AACf,iHAAA,kBAAkB,OAAA;AAClB,mHAAA,oBAAoB,OAAA;AACpB,6GAAA,cAAc,OAAA;AAEhB,mBAAmB;AACnB,uCAAgE;AAAvD,6GAAA,iBAAiB,OAAA;AAAE,2GAAA,eAAe,OAAA;AAU3C,yCAAuE;AAA9D,8GAAA,iBAAiB,OAAA;AAAE,kHAAA,qBAAqB,OAAA;AAEjD,oBAAoB;AACpB,yCAAsE;AAA7D,iHAAA,oBAAoB,OAAA;AAAE,8GAAA,iBAAiB,OAAA;AAUhD,iBAAiB;AACjB,mCAMkB;AALhB,sGAAA,YAAY,OAAA;AACZ,0GAAA,gBAAgB,OAAA;AAChB,qGAAA,WAAW,OAAA;AACX,yGAAA,eAAe,OAAA;AACf,wGAAA,cAAc,OAAA;AAEhB,iBAAiB;AACjB,mCAQkB;AAPhB,6GAAA,mBAAmB,OAAA;AACnB,0GAAA,gBAAgB,OAAA;AAChB,4GAAA,kBAAkB,OAAA;AAClB,yGAAA,eAAe,OAAA;AACf,2GAAA,iBAAiB,OAAA;AACjB,wGAAA,cAAc,OAAA;AACd,6GAAA,mBAAmB,OAAA;AASrB,0BAA0B;AAC1B,qDAA8E;AAArE,oHAAA,iBAAiB,OAAA;AAAE,yHAAA,sBAAsB,OAAA;AAGlD,iDAA8C;AAArC,4GAAA,WAAW,OAAA;AAYpB,uDAO4B;AAN1B,+GAAA,WAAW,OAAA;AACX,wHAAA,oBAAoB,OAAA;AACpB,wHAAA,oBAAoB,OAAA;AACpB,+GAAA,WAAW,OAAA;AACX,mHAAA,eAAe,OAAA;AACf,gHAAA,YAAY,OAAA;AAId,yCAUqB;AATnB,kHAAA,qBAAqB,OAAA;AACrB,+GAAA,kBAAkB,OAAA;AAClB,4GAAA,eAAe,OAAA;AACf,6GAAA,gBAAgB,OAAA;AAChB,qHAAA,wBAAwB,OAAA;AACxB,mHAAA,sBAAsB,OAAA;AACtB,4GAAA,eAAe,OAAA;AACf,8GAAA,iBAAiB,OAAA;AACjB,0GAAA,aAAa,OAAA;AAEf,iDAAiD;AACjD,qCAWmB;AAVjB,wGAAA,aAAa,OAAA;AACb,0GAAA,eAAe,OAAA;AACf,8GAAA,mBAAmB,OAAA;AACnB,oGAAA,SAAS,OAAA;AACT,sGAAA,WAAW,OAAA;AAIX,2GAAA,gBAAgB,OAAA;AAKlB,qDAQ2B;AAPzB,qHAAA,kBAAkB,OAAA;AAClB,0HAAA,uBAAuB,OAAA;AACvB,uHAAA,oBAAoB,OAAA;AACpB,qHAAA,kBAAkB,OAAA;AAClB,kHAAA,eAAe,OAAA;AACf,oHAAA,iBAAiB,OAAA;AACjB,4GAAA,SAAS,OAAA;AASX,+CAAoD;AAA3C,kHAAA,kBAAkB,OAAA;AAW3B,mDAA6E;AAApE,qHAAA,mBAAmB,OAAA;AAAE,sHAAA,oBAAoB,OAAA;AAClD,eAAe;AACf,0CAAwB;AACxB,mBAAmB;AACnB,yCAAuD;AAA9C,oGAAA,UAAU,OAAA;AAAE,mGAAA,SAAS,OAAA;AAC9B,kBAAkB;AAClB,yCAAgE;AAAvD,yGAAA,eAAe,OAAA;AAAE,uGAAA,aAAa,OAAA;AACvC,wBAAwB;AACxB,iCAA8C;AAArC,sGAAA,gBAAgB,OAAA;AACzB,yBAAyB;AACzB,mDAO6B;AAN3B,kHAAA,mBAAmB,OAAA;AACnB,kHAAA,mBAAmB,OAAA;AACnB,iHAAA,kBAAkB,OAAA;AAClB,+GAAA,gBAAgB,OAAA;AAChB,qHAAA,sBAAsB,OAAA;AACtB,8GAAA,eAAe,OAAA;AAEjB,yBAAyB;AACzB,qDAAuE;AAA9D,+HAAA,+BAA+B,OAAA"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `~/.dossier/runs.jsonl` entry schema (#458, #524).
|
|
3
|
+
*
|
|
4
|
+
* Lives in `core`, not `cli`, so `packages/sched`'s dispatch path can write
|
|
5
|
+
* entries in the same shape `cli`'s `ai-dossier run` and `ai-dossier history`
|
|
6
|
+
* already read — one schema, two writers — without `sched` depending on
|
|
7
|
+
* `cli` (the dependency runs the other way). `cli/src/run-log.ts` re-exports
|
|
8
|
+
* this type and owns the actual file I/O (respecting the `auditLog` config
|
|
9
|
+
* flag); `sched` writes its own entries independently — see
|
|
10
|
+
* `packages/sched/src/run-log.ts`.
|
|
11
|
+
*/
|
|
12
|
+
export interface RunLogEntry {
|
|
13
|
+
timestamp: string;
|
|
14
|
+
dossier: string;
|
|
15
|
+
resolved_version: string;
|
|
16
|
+
source: 'cache' | 'registry' | 'local' | 'url';
|
|
17
|
+
registry?: string;
|
|
18
|
+
/**
|
|
19
|
+
* How the version was resolved (only meaningful for registry sources):
|
|
20
|
+
* - 'pinned' — caller passed name@version explicitly
|
|
21
|
+
* - 'registry' — resolver called the registry and got a fresh version
|
|
22
|
+
* - 'cache' — resolver served from TTL'd resolution cache (no registry call)
|
|
23
|
+
* - 'stale-cache' — registry was unreachable; fell back to highest cached semver
|
|
24
|
+
* Useful for postmortems answering "did this run hit a stale resolution that
|
|
25
|
+
* masked a registry outage?". Absent for local files and URLs.
|
|
26
|
+
*/
|
|
27
|
+
resolution_source?: 'pinned' | 'registry' | 'cache' | 'stale-cache';
|
|
28
|
+
verification: 'passed' | 'failed' | 'skipped' | 'nested-skip';
|
|
29
|
+
llm: string;
|
|
30
|
+
user: string;
|
|
31
|
+
cwd: string;
|
|
32
|
+
nested: boolean;
|
|
33
|
+
/**
|
|
34
|
+
* Deprecated: written by the pre-#401 update-check machinery. Retained on the
|
|
35
|
+
* interface so `dossier history` can still display this field when reading
|
|
36
|
+
* older runs.jsonl entries. Not written by new runs.
|
|
37
|
+
*/
|
|
38
|
+
update_available?: string;
|
|
39
|
+
/**
|
|
40
|
+
* Cost/observability fields (#458). All optional and nullable so old-schema
|
|
41
|
+
* entries still parse; written by new runs with explicit nulls when a value
|
|
42
|
+
* is unavailable — never fabricated.
|
|
43
|
+
*/
|
|
44
|
+
/** Wall-clock duration of the run in milliseconds (action start → entry write). */
|
|
45
|
+
duration_ms?: number | null;
|
|
46
|
+
/**
|
|
47
|
+
* The exact agent command spawned (binary + args). Prompt content is excluded
|
|
48
|
+
* (headless prompts travel over stdin). Null when nothing was spawned
|
|
49
|
+
* (nested-skip, failed verification, dry-run, no LLM detected, unknown LLM).
|
|
50
|
+
*/
|
|
51
|
+
spawned_command?: string | null;
|
|
52
|
+
/** Model id as reported by the agent CLI, else the requested --model alias. Null when unknown. */
|
|
53
|
+
model?: string | null;
|
|
54
|
+
/** Exit code of the spawned agent process, or of the CLI action for early exits. Null when killed by a signal or failed to spawn. */
|
|
55
|
+
exit_code?: number | null;
|
|
56
|
+
/** Why the spawned process produced no exit code: spawn error (e.g. ENOENT) or signal. Null when the process exited normally. */
|
|
57
|
+
spawn_error?: string | null;
|
|
58
|
+
/** Input tokens reported by the agent CLI. Null when unavailable. */
|
|
59
|
+
input_tokens?: number | null;
|
|
60
|
+
/** Output tokens reported by the agent CLI. Null when unavailable. */
|
|
61
|
+
output_tokens?: number | null;
|
|
62
|
+
/**
|
|
63
|
+
* Cache-creation (write) and cache-read input tokens reported by the agent
|
|
64
|
+
* CLI (#524). Sourced from `modelUsage`, the same as `input_tokens`/
|
|
65
|
+
* `output_tokens` — see `parseAgentUsage` in `./agent-usage`. Null when
|
|
66
|
+
* unavailable.
|
|
67
|
+
*/
|
|
68
|
+
cache_creation_tokens?: number | null;
|
|
69
|
+
cache_read_tokens?: number | null;
|
|
70
|
+
/** Total cost in USD reported by the agent CLI. Null when unavailable. */
|
|
71
|
+
total_cost_usd?: number | null;
|
|
72
|
+
/**
|
|
73
|
+
* The scheduler unit this run belongs to (#524), e.g. `issue:524` or
|
|
74
|
+
* `batch:b1` — set by `packages/sched` dispatch entries, null/absent for
|
|
75
|
+
* an ordinary `ai-dossier run` invocation (which has no unit).
|
|
76
|
+
*/
|
|
77
|
+
unit?: string | null;
|
|
78
|
+
/**
|
|
79
|
+
* The escalation-ladder model tier this dispatch ran at (#564), e.g.
|
|
80
|
+
* `mechanical` | `mid` | `strong` — set by `packages/sched` dispatch
|
|
81
|
+
* entries (the queue entry's resolved tier at spawn time); null/absent for
|
|
82
|
+
* an ordinary `ai-dossier run` invocation and for reconstructed entries
|
|
83
|
+
* (`sched stats --batch`'s raw-log recovery) where the tier that spawned a
|
|
84
|
+
* historical dispatch is no longer recorded anywhere.
|
|
85
|
+
*/
|
|
86
|
+
tier?: string | null;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* `~/.dossier/runs.jsonl` — the single location both writers (`cli`'s
|
|
90
|
+
* `ai-dossier run` and `packages/sched`'s dispatch path) append to, and both
|
|
91
|
+
* readers (`ai-dossier history`, `ai-dossier sched stats`) read from (#524).
|
|
92
|
+
* Hoisted here so the path is computed in exactly one place; before this,
|
|
93
|
+
* `cli/src/run-log.ts` and `packages/sched/src/run-log.ts` each built it
|
|
94
|
+
* independently and agreed only by coincidence. Testable via `home`.
|
|
95
|
+
*/
|
|
96
|
+
export declare function runsLogPath(home?: string): string;
|
|
97
|
+
//# sourceMappingURL=run-log-entry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-log-entry.d.ts","sourceRoot":"","sources":["../src/run-log-entry.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;GAUG;AACH,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,gBAAgB,EAAE,MAAM,CAAC;IACzB,MAAM,EAAE,OAAO,GAAG,UAAU,GAAG,OAAO,GAAG,KAAK,CAAC;IAC/C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;;;;;OAQG;IACH,iBAAiB,CAAC,EAAE,QAAQ,GAAG,UAAU,GAAG,OAAO,GAAG,aAAa,CAAC;IACpE,YAAY,EAAE,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,aAAa,CAAC;IAC9D,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,OAAO,CAAC;IAChB;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;;OAIG;IACH,mFAAmF;IACnF,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,kGAAkG;IAClG,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,qIAAqI;IACrI,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,iIAAiI;IACjI,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,qEAAqE;IACrE,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,sEAAsE;IACtE,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B;;;;;OAKG;IACH,qBAAqB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,0EAA0E;IAC1E,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB;;;;;;;OAOG;IACH,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,IAAI,GAAE,MAAqB,GAAG,MAAM,CAE/D"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.runsLogPath = runsLogPath;
|
|
37
|
+
const os = __importStar(require("node:os"));
|
|
38
|
+
const path = __importStar(require("node:path"));
|
|
39
|
+
/**
|
|
40
|
+
* `~/.dossier/runs.jsonl` — the single location both writers (`cli`'s
|
|
41
|
+
* `ai-dossier run` and `packages/sched`'s dispatch path) append to, and both
|
|
42
|
+
* readers (`ai-dossier history`, `ai-dossier sched stats`) read from (#524).
|
|
43
|
+
* Hoisted here so the path is computed in exactly one place; before this,
|
|
44
|
+
* `cli/src/run-log.ts` and `packages/sched/src/run-log.ts` each built it
|
|
45
|
+
* independently and agreed only by coincidence. Testable via `home`.
|
|
46
|
+
*/
|
|
47
|
+
function runsLogPath(home = os.homedir()) {
|
|
48
|
+
return path.join(home, '.dossier', 'runs.jsonl');
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=run-log-entry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-log-entry.js","sourceRoot":"","sources":["../src/run-log-entry.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmGA,kCAEC;AArGD,4CAA8B;AAC9B,gDAAkC;AA0FlC;;;;;;;GAOG;AACH,SAAgB,WAAW,CAAC,OAAe,EAAE,CAAC,OAAO,EAAE;IACrD,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,EAAE,YAAY,CAAC,CAAC;AACnD,CAAC"}
|
package/package.json
CHANGED