@faithfulalabi/agent-lens 0.12.0 → 0.14.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.
|
@@ -44,6 +44,10 @@ export function readCacheStats(dataDir) {
|
|
|
44
44
|
row.drifting += 1;
|
|
45
45
|
mergeNamed(row, 'unknown_line_types', session.counts.unknown_line_types);
|
|
46
46
|
mergeNamed(row, 'unknown_top_level_fields', session.counts.unknown_top_level_fields);
|
|
47
|
+
const mismatches = session.counts.requested_model_mismatch;
|
|
48
|
+
if (mismatches !== undefined) {
|
|
49
|
+
row.requested_model_mismatch = (row.requested_model_mismatch ?? 0) + mismatches;
|
|
50
|
+
}
|
|
47
51
|
}
|
|
48
52
|
return {
|
|
49
53
|
state: 'ready',
|
|
@@ -105,6 +109,10 @@ export function formatCacheSection(cache) {
|
|
|
105
109
|
lines.push(` ${row.version}: ${row.projected} projected, ${row.drifting} drifting`);
|
|
106
110
|
lines.push(...namedDrift('unknown record types', row.unknown_line_types));
|
|
107
111
|
lines.push(...namedDrift('unknown top-level fields', row.unknown_top_level_fields));
|
|
112
|
+
const mismatches = row.requested_model_mismatch;
|
|
113
|
+
if (mismatches !== undefined) {
|
|
114
|
+
lines.push(` requested model differed from served model: ${mismatches} line${mismatches === 1 ? '' : 's'}`);
|
|
115
|
+
}
|
|
108
116
|
}
|
|
109
117
|
return lines;
|
|
110
118
|
}
|
package/dist/src/db/read.js
CHANGED
|
@@ -25,7 +25,10 @@ const SESSION_LIST_COLUMNS = `id, title, preview, project_path, git_branch, mode
|
|
|
25
25
|
sub_tokens_cache_read, sub_tokens_cache_write, sub_est_cost, sub_models, rollup_state, drift_json`;
|
|
26
26
|
const TOP_LEVEL_ONLY = 'parent_session_id IS NULL';
|
|
27
27
|
const NO_DRIFT = '{}';
|
|
28
|
-
export const FIELD_TIER_BUCKETS = new Set([
|
|
28
|
+
export const FIELD_TIER_BUCKETS = new Set([
|
|
29
|
+
'requested_model_mismatch',
|
|
30
|
+
'unknown_top_level_fields',
|
|
31
|
+
]);
|
|
29
32
|
export function hasStructuralDrift(counts) {
|
|
30
33
|
return Object.keys(counts).some((bucket) => !FIELD_TIER_BUCKETS.has(bucket));
|
|
31
34
|
}
|
|
@@ -236,8 +236,14 @@ export function runPipeline(lines, ctx) {
|
|
|
236
236
|
continue;
|
|
237
237
|
}
|
|
238
238
|
for (const [blockIndex, block] of blocks.entries()) {
|
|
239
|
-
if (block.kind !== 'tool_result')
|
|
239
|
+
if (block.kind !== 'tool_result') {
|
|
240
240
|
emit(block, blockIndex);
|
|
241
|
+
continue;
|
|
242
|
+
}
|
|
243
|
+
for (const child of block.children) {
|
|
244
|
+
if (child.kind === 'unknown_block')
|
|
245
|
+
ctx.drift.noteUnknownBlock(child.raw_type);
|
|
246
|
+
}
|
|
241
247
|
}
|
|
242
248
|
}
|
|
243
249
|
const eventsOf = new Map();
|
|
@@ -13,6 +13,7 @@ export class DriftCounter {
|
|
|
13
13
|
unjoinedToolUses = 0;
|
|
14
14
|
sidecarAgentIdMismatches = 0;
|
|
15
15
|
permissionDecisionMismatches = 0;
|
|
16
|
+
requestedModelMismatches = 0;
|
|
16
17
|
noteLine(line, knownFields) {
|
|
17
18
|
for (const name of Object.keys(line)) {
|
|
18
19
|
if (!knownFields.has(name))
|
|
@@ -34,9 +35,13 @@ export class DriftCounter {
|
|
|
34
35
|
notePermissionDecisionMismatch() {
|
|
35
36
|
this.permissionDecisionMismatches += 1;
|
|
36
37
|
}
|
|
38
|
+
noteRequestedModelMismatch() {
|
|
39
|
+
this.requestedModelMismatches += 1;
|
|
40
|
+
}
|
|
37
41
|
serialize() {
|
|
38
42
|
return JSON.stringify({
|
|
39
43
|
permission_decision_mismatch: this.permissionDecisionMismatches === 0 ? undefined : this.permissionDecisionMismatches,
|
|
44
|
+
requested_model_mismatch: this.requestedModelMismatches === 0 ? undefined : this.requestedModelMismatches,
|
|
40
45
|
sidecar_agent_id_mismatch: this.sidecarAgentIdMismatches === 0 ? undefined : this.sidecarAgentIdMismatches,
|
|
41
46
|
unjoined_tool_uses: this.unjoinedToolUses === 0 ? undefined : this.unjoinedToolUses,
|
|
42
47
|
unknown_block_types: bucket(this.blockTypes),
|
|
@@ -54,6 +54,9 @@ const LINE_TYPES = new Map([
|
|
|
54
54
|
'wireIngestContext',
|
|
55
55
|
'apiErrorStatus',
|
|
56
56
|
'quotaLimits',
|
|
57
|
+
'requestedModel',
|
|
58
|
+
'thinkingDisplay',
|
|
59
|
+
'thinkingDurationMs',
|
|
57
60
|
]),
|
|
58
61
|
},
|
|
59
62
|
],
|
|
@@ -82,6 +85,8 @@ const LINE_TYPES = new Map([
|
|
|
82
85
|
'queueSkipAttachments',
|
|
83
86
|
'turnPosition',
|
|
84
87
|
'turnCompanion',
|
|
88
|
+
'interruptedMessageId',
|
|
89
|
+
'classifierBoundary',
|
|
85
90
|
]),
|
|
86
91
|
},
|
|
87
92
|
],
|
|
@@ -169,7 +174,16 @@ const LINE_TYPES = new Map([
|
|
|
169
174
|
'queue-operation',
|
|
170
175
|
{
|
|
171
176
|
kind: 'queue-operation',
|
|
172
|
-
knownFields: fields([
|
|
177
|
+
knownFields: fields([
|
|
178
|
+
'type',
|
|
179
|
+
'operation',
|
|
180
|
+
'content',
|
|
181
|
+
'timestamp',
|
|
182
|
+
'sessionId',
|
|
183
|
+
'reason',
|
|
184
|
+
'commandUuid',
|
|
185
|
+
'deliveryId',
|
|
186
|
+
]),
|
|
173
187
|
},
|
|
174
188
|
],
|
|
175
189
|
[
|
|
@@ -215,6 +229,13 @@ const LINE_TYPES = new Map([
|
|
|
215
229
|
]),
|
|
216
230
|
},
|
|
217
231
|
],
|
|
232
|
+
[
|
|
233
|
+
'bridge-session',
|
|
234
|
+
{
|
|
235
|
+
kind: 'bridge-session',
|
|
236
|
+
knownFields: fields(['type', 'bridgeSessionId', 'lastSequenceNum', 'sessionId']),
|
|
237
|
+
},
|
|
238
|
+
],
|
|
218
239
|
]);
|
|
219
240
|
const EMPTY_RECORD = Object.freeze({});
|
|
220
241
|
function rawTypeKey(value) {
|
|
@@ -222,6 +243,13 @@ function rawTypeKey(value) {
|
|
|
222
243
|
return value;
|
|
223
244
|
return value === null ? '<null>' : `<${typeof value}>`;
|
|
224
245
|
}
|
|
246
|
+
function servedOtherThanRequested(raw) {
|
|
247
|
+
const served = str(obj(raw.message, undefined)?.model, undefined);
|
|
248
|
+
return (raw.requestedModel !== undefined &&
|
|
249
|
+
served !== undefined &&
|
|
250
|
+
served !== SYNTHETIC_MODEL &&
|
|
251
|
+
raw.requestedModel !== served);
|
|
252
|
+
}
|
|
225
253
|
export function classifyLine(json, ctx) {
|
|
226
254
|
const raw = obj(json, EMPTY_RECORD);
|
|
227
255
|
const base = {
|
|
@@ -239,6 +267,9 @@ export function classifyLine(json, ctx) {
|
|
|
239
267
|
return { ...base, kind: 'unknown', raw_type, raw_subtype: str(raw.subtype, '') };
|
|
240
268
|
}
|
|
241
269
|
ctx.drift.noteLine(raw, entry.knownFields);
|
|
270
|
+
if (entry.kind === 'assistant' && servedOtherThanRequested(raw)) {
|
|
271
|
+
ctx.drift.noteRequestedModelMismatch();
|
|
272
|
+
}
|
|
242
273
|
if (entry.kind === 'system') {
|
|
243
274
|
const subtype = str(raw.subtype, '');
|
|
244
275
|
if (!isSystemSubtype(subtype)) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export const PROJECTOR_VERSION =
|
|
1
|
+
export const PROJECTOR_VERSION = 19;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@faithfulalabi/agent-lens",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.0",
|
|
4
4
|
"description": "Local-first agentic tracing platform: inspect everything your agent did in a session.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -38,6 +38,8 @@
|
|
|
38
38
|
"dev": "tsx src/dev/server.ts",
|
|
39
39
|
"dev:ui": "npm --prefix ui run dev",
|
|
40
40
|
"render-gate": "tsx src/render-gate/index.ts",
|
|
41
|
+
"shapes:census": "node scripts/shapes-census.mjs",
|
|
42
|
+
"shapes:diff": "node --import tsx scripts/shapes-diff.ts",
|
|
41
43
|
"demo:capture": "node --import tsx scripts/capture-screenshots.mjs",
|
|
42
44
|
"test": "vitest run",
|
|
43
45
|
"typecheck": "tsc -p tsconfig.node.json --noEmit && npm --prefix ui run typecheck",
|