@faithfulalabi/agent-lens 0.13.0 → 0.15.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/dist/src/cli/commands/doctor.js +8 -0
- package/dist/src/db/read.js +7 -2
- package/dist/src/db/schema.js +1 -0
- package/dist/src/project/pipeline.js +2 -1
- package/dist/src/project/tools.js +8 -0
- package/dist/src/transcript/drift.js +5 -0
- package/dist/src/transcript/line.js +17 -0
- package/dist/src/transcript/version.js +1 -1
- package/package.json +1 -1
- package/ui/dist/assets/index-CLP-ZNLR.js +254 -0
- package/ui/dist/index.html +1 -1
- package/ui/dist/assets/index-De9wOnVP.js +0 -254
|
@@ -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
|
}
|
|
@@ -136,7 +139,9 @@ const EVENT_COLUMNS = `id, turn_id, seq, kind, ts, request_id, block_index, name
|
|
|
136
139
|
text, text_bytes, output_storage, spill_path, spill_bytes,
|
|
137
140
|
model, tokens_in, tokens_out, tokens_cache_read, tokens_cache_write, est_cost,
|
|
138
141
|
child_session_id, agent_type, agent_status, raw_type, raw_subtype, image_count,
|
|
139
|
-
json_extract(attrs, '$.renderedRole') AS rendered_role
|
|
142
|
+
json_extract(attrs, '$.renderedRole') AS rendered_role,
|
|
143
|
+
json_extract(attrs, '$.permissionSource') AS permission_source,
|
|
144
|
+
json_extract(attrs, '$.permissionReasonType') AS permission_reason_type`;
|
|
140
145
|
export function buildEventPageSql(session_id, query) {
|
|
141
146
|
return {
|
|
142
147
|
sql: `SELECT ${EVENT_COLUMNS} FROM events WHERE session_id = ? AND seq >= ?` +
|
package/dist/src/db/schema.js
CHANGED
|
@@ -272,6 +272,7 @@ CREATE TABLE events (
|
|
|
272
272
|
attrs TEXT NOT NULL DEFAULT '{}' -- ALLOWLIST ONLY: attributionSkill,
|
|
273
273
|
-- attributionAgent, effort, permissionMode,
|
|
274
274
|
-- compactMetadata, toolDenialKind, renderedRole,
|
|
275
|
+
-- permissionSource, permissionReasonType,
|
|
275
276
|
-- unknown_fields[]
|
|
276
277
|
);
|
|
277
278
|
CREATE UNIQUE INDEX idx_events_session_seq ON events(session_id, seq);
|
|
@@ -2,7 +2,7 @@ import { asyncAgentLaunch, taskNotification } from '../transcript/agents.js';
|
|
|
2
2
|
import { attachmentRecord } from '../transcript/attachments.js';
|
|
3
3
|
import { contentBlocks, imageCount, resultText } from '../transcript/blocks.js';
|
|
4
4
|
import { isHumanPrompt, MACHINERY_TAGS } from '../transcript/human.js';
|
|
5
|
-
import { apiErrorText, foldControlLines, foldSessionEnvelope, permissionDecision, promptGroupId, toolDenialKind, turnDurationMs, } from '../transcript/line.js';
|
|
5
|
+
import { apiErrorText, foldControlLines, foldSessionEnvelope, permissionDecision, permissionGrounds, promptGroupId, toolDenialKind, turnDurationMs, } from '../transcript/line.js';
|
|
6
6
|
import { foldRequestGroup, groupByRequestId, modelOfRequestGroup, requestIdOf, } from '../transcript/usage.js';
|
|
7
7
|
import { joinToolCalls, NO_INPUT, NO_WIRE_INPUT, toolInput, wireInput, } from './tools.js';
|
|
8
8
|
import { wireInputOf } from '../transcript/wire.js';
|
|
@@ -138,6 +138,7 @@ export function runPipeline(lines, ctx) {
|
|
|
138
138
|
is_error: block.is_error,
|
|
139
139
|
denial: toolDenialKind(line),
|
|
140
140
|
decision: permissionDecision(line),
|
|
141
|
+
grounds: permissionGrounds(line),
|
|
141
142
|
launch: asyncAgentLaunch(line, output),
|
|
142
143
|
ts: line.timestamp ?? '',
|
|
143
144
|
result_offset: line.byte_offset,
|
|
@@ -113,6 +113,14 @@ export function joinToolCalls(events, results, notifications, drift) {
|
|
|
113
113
|
statedDenial(result.decision) !== (result.denial !== undefined)) {
|
|
114
114
|
drift.notePermissionDecisionMismatch();
|
|
115
115
|
}
|
|
116
|
+
const { source, reasonType } = result.grounds;
|
|
117
|
+
if (source !== undefined || reasonType !== undefined) {
|
|
118
|
+
event.attrs = JSON.stringify({
|
|
119
|
+
...JSON.parse(event.attrs),
|
|
120
|
+
permissionSource: source,
|
|
121
|
+
permissionReasonType: reasonType,
|
|
122
|
+
});
|
|
123
|
+
}
|
|
116
124
|
if (event.name === 'Agent' && result.launch !== undefined) {
|
|
117
125
|
backPatch(event, answers.get(event.id));
|
|
118
126
|
continue;
|
|
@@ -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),
|
|
@@ -243,6 +243,13 @@ function rawTypeKey(value) {
|
|
|
243
243
|
return value;
|
|
244
244
|
return value === null ? '<null>' : `<${typeof value}>`;
|
|
245
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
|
+
}
|
|
246
253
|
export function classifyLine(json, ctx) {
|
|
247
254
|
const raw = obj(json, EMPTY_RECORD);
|
|
248
255
|
const base = {
|
|
@@ -260,6 +267,9 @@ export function classifyLine(json, ctx) {
|
|
|
260
267
|
return { ...base, kind: 'unknown', raw_type, raw_subtype: str(raw.subtype, '') };
|
|
261
268
|
}
|
|
262
269
|
ctx.drift.noteLine(raw, entry.knownFields);
|
|
270
|
+
if (entry.kind === 'assistant' && servedOtherThanRequested(raw)) {
|
|
271
|
+
ctx.drift.noteRequestedModelMismatch();
|
|
272
|
+
}
|
|
263
273
|
if (entry.kind === 'system') {
|
|
264
274
|
const subtype = str(raw.subtype, '');
|
|
265
275
|
if (!isSystemSubtype(subtype)) {
|
|
@@ -298,6 +308,13 @@ export function permissionDecision(line) {
|
|
|
298
308
|
return undefined;
|
|
299
309
|
return str(obj(line.raw.permissionDecision, undefined)?.decision, '');
|
|
300
310
|
}
|
|
311
|
+
export function permissionGrounds(line) {
|
|
312
|
+
const stated = obj(line.raw.permissionDecision, undefined);
|
|
313
|
+
return {
|
|
314
|
+
source: str(stated?.source, '') || undefined,
|
|
315
|
+
reasonType: str(stated?.reasonType, '') || undefined,
|
|
316
|
+
};
|
|
317
|
+
}
|
|
301
318
|
export function turnDurationMs(line) {
|
|
302
319
|
return line.kind === 'system' && line.subtype === 'turn_duration'
|
|
303
320
|
? num(line.raw.durationMs, undefined)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export const PROJECTOR_VERSION =
|
|
1
|
+
export const PROJECTOR_VERSION = 20;
|