@koda-sl/baker-bridge 0.154.0-dev.db7cf2f5d → 0.154.0-dev.eb1bb1bf7
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 +35 -3
- package/dist/hono/agent-session.d.ts +0 -1
- package/dist/hono/agent-session.d.ts.map +1 -1
- package/dist/hono/agent-session.js +0 -7
- package/dist/hono/agent-session.js.map +1 -1
- package/dist/hono/agent-session.test.js +1 -7
- package/dist/hono/agent-session.test.js.map +1 -1
- package/dist/hono/agent.d.ts.map +1 -1
- package/dist/hono/agent.js +10 -10
- package/dist/hono/agent.js.map +1 -1
- package/dist/hono/agent.test.js +24 -0
- package/dist/hono/agent.test.js.map +1 -1
- package/dist/hono/bridge-job.d.ts +20 -1
- package/dist/hono/bridge-job.d.ts.map +1 -1
- package/dist/hono/bridge-job.js +71 -6
- package/dist/hono/bridge-job.js.map +1 -1
- package/dist/hono/bridge-job.test.js +102 -0
- package/dist/hono/bridge-job.test.js.map +1 -1
- package/dist/hono/convex.d.ts +2 -1
- package/dist/hono/convex.d.ts.map +1 -1
- package/dist/hono/convex.js +4 -0
- package/dist/hono/convex.js.map +1 -1
- package/dist/hono/main-sync.d.ts +7 -0
- package/dist/hono/main-sync.d.ts.map +1 -1
- package/dist/hono/main-sync.js +39 -0
- package/dist/hono/main-sync.js.map +1 -1
- package/dist/hono/main-sync.test.js +29 -1
- package/dist/hono/main-sync.test.js.map +1 -1
- package/dist/hono/publish-handoff.d.ts +12 -1
- package/dist/hono/publish-handoff.d.ts.map +1 -1
- package/dist/hono/publish-handoff.js +86 -0
- package/dist/hono/publish-handoff.js.map +1 -1
- package/dist/hono/publish-handoff.test.js +76 -1
- package/dist/hono/publish-handoff.test.js.map +1 -1
- package/dist/hono/relay.d.ts +10 -1
- package/dist/hono/relay.d.ts.map +1 -1
- package/dist/hono/relay.js +4 -0
- package/dist/hono/relay.js.map +1 -1
- package/dist/hono/relay.test.js +11 -0
- package/dist/hono/relay.test.js.map +1 -1
- package/dist/hono/served-model.d.ts +23 -0
- package/dist/hono/served-model.d.ts.map +1 -0
- package/dist/hono/served-model.js +82 -0
- package/dist/hono/served-model.js.map +1 -0
- package/dist/hono/served-model.test.d.ts +2 -0
- package/dist/hono/served-model.test.d.ts.map +1 -0
- package/dist/hono/served-model.test.js +29 -0
- package/dist/hono/served-model.test.js.map +1 -0
- package/dist/hono/session-continuity.d.ts +24 -0
- package/dist/hono/session-continuity.d.ts.map +1 -1
- package/dist/hono/session-continuity.integration.test.js +201 -5
- package/dist/hono/session-continuity.integration.test.js.map +1 -1
- package/dist/hono/session-continuity.js +94 -7
- package/dist/hono/session-continuity.js.map +1 -1
- package/dist/hono/session-store.d.ts +2 -0
- package/dist/hono/session-store.d.ts.map +1 -1
- package/dist/hono/session-store.js +6 -0
- package/dist/hono/session-store.js.map +1 -1
- package/dist/hono/session-usage-baseline.d.ts +1 -0
- package/dist/hono/session-usage-baseline.d.ts.map +1 -1
- package/dist/hono/session-usage-baseline.js +17 -4
- package/dist/hono/session-usage-baseline.js.map +1 -1
- package/dist/hono/turn-events.d.ts +1 -1
- package/dist/hono/turn-events.d.ts.map +1 -1
- package/dist/hono/turn-events.js.map +1 -1
- package/dist/hono/types.d.ts +26 -0
- package/dist/hono/types.d.ts.map +1 -1
- package/dist/review/digest.d.ts +35 -0
- package/dist/review/digest.d.ts.map +1 -1
- package/dist/review/digest.js +171 -27
- package/dist/review/digest.js.map +1 -1
- package/dist/review/digest.test.js +130 -1
- package/dist/review/digest.test.js.map +1 -1
- package/package.json +1 -1
package/dist/review/digest.js
CHANGED
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
* it could NOT find, so missing evidence is a fact before the model starts
|
|
16
16
|
* rather than a silence it fills in.
|
|
17
17
|
*/
|
|
18
|
+
import { createHash } from "node:crypto";
|
|
18
19
|
import { imageSize } from "image-size";
|
|
19
20
|
import { languageMismatch, marketerWords, messageLanguage } from "./reply-language.js";
|
|
20
21
|
/** Parse a `.jsonl` body, dropping lines that are not JSON rather than failing. */
|
|
@@ -289,6 +290,49 @@ function clip(text, max = TRUNCATE) {
|
|
|
289
290
|
function currentTurn(acc) {
|
|
290
291
|
return acc.turns[acc.turns.length - 1];
|
|
291
292
|
}
|
|
293
|
+
/** One conversation inside a thread: the main agent, or one subagent. */
|
|
294
|
+
function conversationKey(threadId, agentId) {
|
|
295
|
+
return `${threadId ?? ""}\u0000${agentId ?? ""}`;
|
|
296
|
+
}
|
|
297
|
+
function isSubagentLine(line) {
|
|
298
|
+
return line.isSidechain === true || line.isSubagent === true;
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* The turn a line belongs to.
|
|
302
|
+
*
|
|
303
|
+
* A subagent's own file is read after the whole session file it was spawned
|
|
304
|
+
* in, so the turn open by then is that session's last one. Charged to it, a
|
|
305
|
+
* fan-out in turn 1 was listed under the re-render turn 2 — its refusals, its
|
|
306
|
+
* denials and its parent's closing recap as their intent. A subagent belongs to
|
|
307
|
+
* the last turn of its thread that began before the prompt that started it, or
|
|
308
|
+
* before the later prompt that continued it.
|
|
309
|
+
*/
|
|
310
|
+
function turnIndexOf(acc, line) {
|
|
311
|
+
const current = currentTurn(acc)?.index;
|
|
312
|
+
if (!isSubagentLine(line)) {
|
|
313
|
+
return current;
|
|
314
|
+
}
|
|
315
|
+
const key = line.agentId === undefined ? undefined : conversationKey(line.threadId, line.agentId);
|
|
316
|
+
const known = key === undefined ? undefined : acc.subagentTurns.get(key);
|
|
317
|
+
if (known !== undefined) {
|
|
318
|
+
return known;
|
|
319
|
+
}
|
|
320
|
+
const at = stampOf(line.timestamp);
|
|
321
|
+
if (at === undefined) {
|
|
322
|
+
return current;
|
|
323
|
+
}
|
|
324
|
+
let spawned;
|
|
325
|
+
for (const turn of acc.turns) {
|
|
326
|
+
const began = stampOf(turn.timestamp);
|
|
327
|
+
if (turn.threadId === line.threadId && began !== undefined && began <= at) {
|
|
328
|
+
spawned = turn.index;
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
if (key !== undefined && spawned !== undefined) {
|
|
332
|
+
acc.subagentTurns.set(key, spawned);
|
|
333
|
+
}
|
|
334
|
+
return spawned ?? current;
|
|
335
|
+
}
|
|
292
336
|
/**
|
|
293
337
|
* Close the open turn at the latest line that still belongs to it.
|
|
294
338
|
*
|
|
@@ -302,7 +346,8 @@ function currentTurn(acc) {
|
|
|
302
346
|
*/
|
|
303
347
|
function noteTurnEnd(acc, line) {
|
|
304
348
|
const at = stampOf(line.timestamp);
|
|
305
|
-
const
|
|
349
|
+
const index = turnIndexOf(acc, line);
|
|
350
|
+
const turn = index === undefined ? undefined : acc.turns[index];
|
|
306
351
|
if (at === undefined || turn === undefined) {
|
|
307
352
|
return;
|
|
308
353
|
}
|
|
@@ -430,16 +475,22 @@ function absorbFailure(acc, call, block) {
|
|
|
430
475
|
}
|
|
431
476
|
acc.failureMessages.set(call.toolUseId, clip(message, 400));
|
|
432
477
|
const guard = namedGuard(message);
|
|
478
|
+
// A subagent's words, never the turn's: the turn's are its parent's.
|
|
479
|
+
const intent = call.isSidechain
|
|
480
|
+
? acc.subagentWords.get(conversationKey(call.threadId, call.agentId))
|
|
481
|
+
: turn?.assistantText || undefined;
|
|
433
482
|
acc.guards.push({
|
|
434
483
|
turn: call.turn,
|
|
435
484
|
...(call.threadId === undefined ? {} : { threadId: call.threadId }),
|
|
436
485
|
toolUseId: call.toolUseId,
|
|
437
486
|
tool: call.tool,
|
|
438
487
|
attempted: call.summary,
|
|
488
|
+
inputKey: call.inputKey,
|
|
439
489
|
message: clip(message, 400),
|
|
440
490
|
refusal: call.failureClass === "refused",
|
|
441
491
|
...(guard === undefined ? {} : { guard }),
|
|
442
|
-
...(
|
|
492
|
+
...(intent ? { intent: clip(intent, 300) } : {}),
|
|
493
|
+
...(call.isSidechain && call.agentId !== undefined ? { agentId: call.agentId } : {}),
|
|
443
494
|
repeats: 1,
|
|
444
495
|
});
|
|
445
496
|
}
|
|
@@ -490,6 +541,11 @@ function absorbUserLine(acc, line) {
|
|
|
490
541
|
absorbToolResults(acc, line);
|
|
491
542
|
const spoken = raw.replace(SYSTEM_REMINDER, "").trim();
|
|
492
543
|
const isToolResult = blocks(line).some((block) => block.type === "tool_result");
|
|
544
|
+
if (isSubagentLine(line) && !isToolResult && spoken.length > 0) {
|
|
545
|
+
// A prompt to a subagent: its spawn, or a later turn continuing it (`SendMessage`
|
|
546
|
+
// keeps the id), so the turn it belongs to is read again from this line.
|
|
547
|
+
acc.subagentTurns.delete(conversationKey(line.threadId, line.agentId));
|
|
548
|
+
}
|
|
493
549
|
if (line.isSidechain || line.isSubagent || isToolResult || spoken.length === 0) {
|
|
494
550
|
return;
|
|
495
551
|
}
|
|
@@ -509,6 +565,7 @@ function absorbUserLine(acc, line) {
|
|
|
509
565
|
outputTokens: 0,
|
|
510
566
|
cacheReadTokens: 0,
|
|
511
567
|
cacheWriteTokens: 0,
|
|
568
|
+
subagent: { inputTokens: 0, outputTokens: 0, cacheReadTokens: 0, cacheWriteTokens: 0 },
|
|
512
569
|
denials: 0,
|
|
513
570
|
compacted: false,
|
|
514
571
|
});
|
|
@@ -535,21 +592,25 @@ function absorbRequestUsage(acc, line, turnAt) {
|
|
|
535
592
|
acc.countedRequests.add(requestId);
|
|
536
593
|
}
|
|
537
594
|
const usage = line.message?.usage ?? {};
|
|
595
|
+
const subagent = isSubagentLine(line);
|
|
538
596
|
const request = {
|
|
539
597
|
turn: turnAt,
|
|
540
598
|
...(line.message?.model === undefined ? {} : { model: line.message.model }),
|
|
599
|
+
subagent,
|
|
600
|
+
...(subagent && line.agentId !== undefined ? { agentId: line.agentId } : {}),
|
|
541
601
|
inputTokens: usage.input_tokens ?? 0,
|
|
542
602
|
outputTokens: usage.output_tokens ?? 0,
|
|
543
603
|
cacheReadTokens: usage.cache_read_input_tokens ?? 0,
|
|
544
604
|
cacheWriteTokens: usage.cache_creation_input_tokens ?? 0,
|
|
545
605
|
};
|
|
546
606
|
acc.requests.push(request);
|
|
547
|
-
const turn =
|
|
607
|
+
const turn = acc.turns[turnAt];
|
|
548
608
|
if (turn) {
|
|
549
|
-
turn.
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
609
|
+
const usage = subagent ? turn.subagent : turn;
|
|
610
|
+
usage.inputTokens += request.inputTokens;
|
|
611
|
+
usage.outputTokens += request.outputTokens;
|
|
612
|
+
usage.cacheReadTokens += request.cacheReadTokens;
|
|
613
|
+
usage.cacheWriteTokens += request.cacheWriteTokens;
|
|
553
614
|
}
|
|
554
615
|
}
|
|
555
616
|
function buildToolCall(input) {
|
|
@@ -561,6 +622,10 @@ function buildToolCall(input) {
|
|
|
561
622
|
toolUseId: input.block.id ?? `${input.turnAt}:${input.index}`,
|
|
562
623
|
tool,
|
|
563
624
|
summary: clip(summarizeInput(tool, input.block.input), 400),
|
|
625
|
+
inputKey: createHash("sha256")
|
|
626
|
+
.update(JSON.stringify(input.block.input ?? {}))
|
|
627
|
+
.digest("hex")
|
|
628
|
+
.slice(0, 16),
|
|
564
629
|
...(bakerVerb ? { bakerVerb } : {}),
|
|
565
630
|
resultBytes: 0,
|
|
566
631
|
resultTokens: 0,
|
|
@@ -608,12 +673,16 @@ function absorbToolUses(acc, line, turnAt, isSidechain) {
|
|
|
608
673
|
return uses.length;
|
|
609
674
|
}
|
|
610
675
|
function absorbAssistantLine(acc, line) {
|
|
611
|
-
const turnAt =
|
|
676
|
+
const turnAt = turnIndexOf(acc, line) ?? 0;
|
|
612
677
|
absorbRequestUsage(acc, line, turnAt);
|
|
613
|
-
const isSidechain = line
|
|
678
|
+
const isSidechain = isSubagentLine(line);
|
|
614
679
|
const uses = absorbToolUses(acc, line, turnAt, isSidechain);
|
|
615
680
|
const text = textOf(line);
|
|
616
|
-
if (text.trim().length === 0
|
|
681
|
+
if (text.trim().length === 0) {
|
|
682
|
+
return;
|
|
683
|
+
}
|
|
684
|
+
if (isSidechain) {
|
|
685
|
+
acc.subagentWords.set(conversationKey(line.threadId, line.agentId), text);
|
|
617
686
|
return;
|
|
618
687
|
}
|
|
619
688
|
const turn = currentTurn(acc);
|
|
@@ -698,7 +767,7 @@ function attributeGuardFollowUps(guards, calls) {
|
|
|
698
767
|
.find((call) => call.threadId === refused.threadId &&
|
|
699
768
|
call.isSidechain === refused.isSidechain &&
|
|
700
769
|
call.agentId === refused.agentId &&
|
|
701
|
-
call.
|
|
770
|
+
call.inputKey !== refused.inputKey);
|
|
702
771
|
if (after) {
|
|
703
772
|
guard.nextAction = `${after.tool}: ${clip(after.summary, 160)}`;
|
|
704
773
|
}
|
|
@@ -715,11 +784,11 @@ function attributeGuardFollowUps(guards, calls) {
|
|
|
715
784
|
function countGuardRepeats(guards) {
|
|
716
785
|
const counts = new Map();
|
|
717
786
|
for (const guard of guards) {
|
|
718
|
-
const key = `${guard.tool}\u0000${guard.
|
|
787
|
+
const key = `${guard.tool}\u0000${guard.inputKey}\u0000${guard.guard ?? guard.message}`;
|
|
719
788
|
counts.set(key, (counts.get(key) ?? 0) + 1);
|
|
720
789
|
}
|
|
721
790
|
for (const guard of guards) {
|
|
722
|
-
const key = `${guard.tool}\u0000${guard.
|
|
791
|
+
const key = `${guard.tool}\u0000${guard.inputKey}\u0000${guard.guard ?? guard.message}`;
|
|
723
792
|
guard.repeats = counts.get(key) ?? 1;
|
|
724
793
|
}
|
|
725
794
|
}
|
|
@@ -739,6 +808,8 @@ export function buildTranscriptDigest(lines) {
|
|
|
739
808
|
marketerLanguage: new Map(),
|
|
740
809
|
batches: new Map(),
|
|
741
810
|
answeredAt: new Map(),
|
|
811
|
+
subagentTurns: new Map(),
|
|
812
|
+
subagentWords: new Map(),
|
|
742
813
|
};
|
|
743
814
|
for (const line of lines) {
|
|
744
815
|
const openTurns = acc.turns.length;
|
|
@@ -847,7 +918,7 @@ function aggregateFailures(calls, messages) {
|
|
|
847
918
|
function findFlakyCalls(calls) {
|
|
848
919
|
const groups = new Map();
|
|
849
920
|
for (const call of calls) {
|
|
850
|
-
const key = `${call.tool}\u0000${call.
|
|
921
|
+
const key = `${call.tool}\u0000${call.inputKey}`;
|
|
851
922
|
groups.set(key, [...(groups.get(key) ?? []), call]);
|
|
852
923
|
}
|
|
853
924
|
const out = [];
|
|
@@ -877,7 +948,18 @@ function findFlakyCalls(calls) {
|
|
|
877
948
|
* and this is what says where in the Session to look.
|
|
878
949
|
*/
|
|
879
950
|
function emptyThread(threadId) {
|
|
880
|
-
return {
|
|
951
|
+
return {
|
|
952
|
+
threadId,
|
|
953
|
+
turns: 0,
|
|
954
|
+
toolCalls: 0,
|
|
955
|
+
resultBytes: 0,
|
|
956
|
+
resultTokens: 0,
|
|
957
|
+
subagentToolCalls: 0,
|
|
958
|
+
subagentResultTokens: 0,
|
|
959
|
+
errors: 0,
|
|
960
|
+
denials: 0,
|
|
961
|
+
workingMs: 0,
|
|
962
|
+
};
|
|
881
963
|
}
|
|
882
964
|
/** Milliseconds parsed off an ISO timestamp, or nothing. */
|
|
883
965
|
function stampOf(value) {
|
|
@@ -914,6 +996,8 @@ function aggregateByThread(turns, calls, stamps) {
|
|
|
914
996
|
entry.toolCalls += 1;
|
|
915
997
|
entry.resultBytes += call.resultBytes;
|
|
916
998
|
entry.resultTokens += call.resultTokens;
|
|
999
|
+
entry.subagentToolCalls += call.isSidechain ? 1 : 0;
|
|
1000
|
+
entry.subagentResultTokens += call.isSidechain ? call.resultTokens : 0;
|
|
917
1001
|
entry.errors += call.isError ? 1 : 0;
|
|
918
1002
|
}
|
|
919
1003
|
for (const [threadId, values] of stamps) {
|
|
@@ -930,14 +1014,18 @@ function aggregateByTool(calls) {
|
|
|
930
1014
|
const entry = map.get(call.tool) ?? {
|
|
931
1015
|
tool: call.tool,
|
|
932
1016
|
calls: 0,
|
|
1017
|
+
subagentCalls: 0,
|
|
933
1018
|
totalBytes: 0,
|
|
934
1019
|
totalTokens: 0,
|
|
1020
|
+
subagentTokens: 0,
|
|
935
1021
|
maxBytes: 0,
|
|
936
1022
|
errors: 0,
|
|
937
1023
|
};
|
|
938
1024
|
entry.calls += 1;
|
|
1025
|
+
entry.subagentCalls += call.isSidechain ? 1 : 0;
|
|
939
1026
|
entry.totalBytes += call.resultBytes;
|
|
940
1027
|
entry.totalTokens += call.resultTokens;
|
|
1028
|
+
entry.subagentTokens += call.isSidechain ? call.resultTokens : 0;
|
|
941
1029
|
entry.maxBytes = Math.max(entry.maxBytes, call.resultBytes);
|
|
942
1030
|
entry.errors += call.isError ? 1 : 0;
|
|
943
1031
|
map.set(call.tool, entry);
|
|
@@ -974,7 +1062,7 @@ function aggregateByVerb(calls) {
|
|
|
974
1062
|
function findRepeats(calls) {
|
|
975
1063
|
const seen = new Map();
|
|
976
1064
|
for (const call of calls) {
|
|
977
|
-
const key = `${call.tool}\u0000${call.
|
|
1065
|
+
const key = `${call.tool}\u0000${call.inputKey}`;
|
|
978
1066
|
const entry = seen.get(key);
|
|
979
1067
|
if (entry) {
|
|
980
1068
|
entry.extra += 1;
|
|
@@ -1141,12 +1229,25 @@ export function renderTurns(digest) {
|
|
|
1141
1229
|
"",
|
|
1142
1230
|
digest.threads.length === 0
|
|
1143
1231
|
? "No thread could be attributed — the transcripts carried no thread id."
|
|
1144
|
-
: table([
|
|
1232
|
+
: table([
|
|
1233
|
+
"thread",
|
|
1234
|
+
"turns",
|
|
1235
|
+
"tool calls",
|
|
1236
|
+
"subagent calls",
|
|
1237
|
+
"result bytes",
|
|
1238
|
+
"~main result tokens",
|
|
1239
|
+
"~subagent result tokens",
|
|
1240
|
+
"errors",
|
|
1241
|
+
"denials",
|
|
1242
|
+
"running",
|
|
1243
|
+
], digest.threads.map((thread) => [
|
|
1145
1244
|
thread.threadId,
|
|
1146
1245
|
thread.turns,
|
|
1147
1246
|
thread.toolCalls,
|
|
1247
|
+
thread.subagentToolCalls,
|
|
1148
1248
|
thread.resultBytes,
|
|
1149
|
-
thread.resultTokens,
|
|
1249
|
+
thread.resultTokens - thread.subagentResultTokens,
|
|
1250
|
+
thread.subagentResultTokens,
|
|
1150
1251
|
thread.errors,
|
|
1151
1252
|
thread.denials,
|
|
1152
1253
|
`${Math.round(thread.workingMs / 1000)}s`,
|
|
@@ -1154,7 +1255,25 @@ export function renderTurns(digest) {
|
|
|
1154
1255
|
"",
|
|
1155
1256
|
"## Every turn",
|
|
1156
1257
|
"",
|
|
1157
|
-
|
|
1258
|
+
"`in`, `out` and `cache read` are the main agent's context; `subagent` columns",
|
|
1259
|
+
"are what that turn's subagents spent, which never reached it.",
|
|
1260
|
+
"",
|
|
1261
|
+
table([
|
|
1262
|
+
"#",
|
|
1263
|
+
"thread",
|
|
1264
|
+
"at",
|
|
1265
|
+
"user",
|
|
1266
|
+
"assistant",
|
|
1267
|
+
"tools",
|
|
1268
|
+
"in",
|
|
1269
|
+
"out",
|
|
1270
|
+
"cache read",
|
|
1271
|
+
"subagent in",
|
|
1272
|
+
"subagent out",
|
|
1273
|
+
"subagent cache read",
|
|
1274
|
+
"denials",
|
|
1275
|
+
"compacted",
|
|
1276
|
+
], digest.turns.map((turn) => [
|
|
1158
1277
|
turn.index,
|
|
1159
1278
|
turn.threadId ?? "",
|
|
1160
1279
|
turn.timestamp ?? "",
|
|
@@ -1164,23 +1283,36 @@ export function renderTurns(digest) {
|
|
|
1164
1283
|
turn.inputTokens,
|
|
1165
1284
|
turn.outputTokens,
|
|
1166
1285
|
turn.cacheReadTokens,
|
|
1286
|
+
turn.subagent.inputTokens,
|
|
1287
|
+
turn.subagent.outputTokens,
|
|
1288
|
+
turn.subagent.cacheReadTokens,
|
|
1167
1289
|
turn.denials,
|
|
1168
1290
|
turn.compacted ? "yes" : "",
|
|
1169
1291
|
])),
|
|
1170
1292
|
"",
|
|
1171
1293
|
].join("\n");
|
|
1172
1294
|
}
|
|
1295
|
+
/** Who made a call: the main agent, or the subagent by its id. */
|
|
1296
|
+
function agentOf(call) {
|
|
1297
|
+
return call.isSidechain ? `subagent ${call.agentId ?? "(unnamed)"}` : "main";
|
|
1298
|
+
}
|
|
1173
1299
|
export function renderTools(digest) {
|
|
1174
1300
|
const sections = [
|
|
1175
1301
|
"# Tool calls",
|
|
1176
1302
|
"",
|
|
1177
1303
|
"## Per tool",
|
|
1178
1304
|
"",
|
|
1179
|
-
|
|
1305
|
+
"`main` is what the agent the marketer talks to called; `subagent` ran in a",
|
|
1306
|
+
"subagent, and its results never reached the main agent's context.",
|
|
1307
|
+
"",
|
|
1308
|
+
table(["tool", "calls", "main", "subagent", "total bytes", "~main tokens", "~subagent tokens", "max bytes", "errors"], digest.byTool.map((entry) => [
|
|
1180
1309
|
entry.tool,
|
|
1181
1310
|
entry.calls,
|
|
1311
|
+
entry.calls - entry.subagentCalls,
|
|
1312
|
+
entry.subagentCalls,
|
|
1182
1313
|
entry.totalBytes,
|
|
1183
|
-
entry.totalTokens,
|
|
1314
|
+
entry.totalTokens - entry.subagentTokens,
|
|
1315
|
+
entry.subagentTokens,
|
|
1184
1316
|
entry.maxBytes,
|
|
1185
1317
|
entry.errors,
|
|
1186
1318
|
])),
|
|
@@ -1208,7 +1340,14 @@ export function renderTools(digest) {
|
|
|
1208
1340
|
"",
|
|
1209
1341
|
"## Ten largest single results (by what the model received)",
|
|
1210
1342
|
"",
|
|
1211
|
-
table(["turn", "tool", "input", "bytes", "~tokens"], digest.largestResults.map((call) => [
|
|
1343
|
+
table(["turn", "agent", "tool", "input", "bytes", "~tokens"], digest.largestResults.map((call) => [
|
|
1344
|
+
call.turn,
|
|
1345
|
+
agentOf(call),
|
|
1346
|
+
call.tool,
|
|
1347
|
+
call.summary,
|
|
1348
|
+
call.resultBytes,
|
|
1349
|
+
call.resultTokens,
|
|
1350
|
+
])),
|
|
1212
1351
|
"",
|
|
1213
1352
|
"## Introspection calls (`baker schema`, `--help`)",
|
|
1214
1353
|
"",
|
|
@@ -1279,8 +1418,9 @@ export function renderFailures(digest) {
|
|
|
1279
1418
|
"",
|
|
1280
1419
|
digest.slowest.length === 0
|
|
1281
1420
|
? "No call carried both a request and a result timestamp, so nothing here can be timed."
|
|
1282
|
-
: table(["turn", "tool", "took", "failed", "input"], digest.slowest.map((call) => [
|
|
1421
|
+
: table(["turn", "agent", "tool", "took", "failed", "input"], digest.slowest.map((call) => [
|
|
1283
1422
|
call.turn,
|
|
1423
|
+
agentOf(call),
|
|
1284
1424
|
call.tool,
|
|
1285
1425
|
secs(call.durationMs ?? 0),
|
|
1286
1426
|
call.isError ? (call.failureClass ?? "yes") : "",
|
|
@@ -1304,6 +1444,9 @@ export function renderHooks(digest) {
|
|
|
1304
1444
|
"",
|
|
1305
1445
|
].join("\n");
|
|
1306
1446
|
}
|
|
1447
|
+
function guardAgent(guard) {
|
|
1448
|
+
return guard.agentId === undefined ? "" : ` · subagent ${guard.agentId}`;
|
|
1449
|
+
}
|
|
1307
1450
|
export function renderGuards(digest) {
|
|
1308
1451
|
const refusals = digest.guards.filter((guard) => guard.refusal);
|
|
1309
1452
|
const errors = digest.guards.filter((guard) => !guard.refusal);
|
|
@@ -1323,13 +1466,14 @@ export function renderGuards(digest) {
|
|
|
1323
1466
|
: [
|
|
1324
1467
|
`${refusals.length} refusals.`,
|
|
1325
1468
|
"",
|
|
1326
|
-
"`Intent` is the agent's own words
|
|
1327
|
-
"
|
|
1469
|
+
"`Intent` is the refused agent's own words — the main agent's in that",
|
|
1470
|
+
"turn, or the subagent's own when a subagent was refused: what it thought",
|
|
1471
|
+
"it was doing. It is the transcript's only answer to why it went there;",
|
|
1328
1472
|
"the rest of the answer is in whatever doc, skill, hint or example",
|
|
1329
1473
|
"pointed it that way, which is yours to go and open.",
|
|
1330
1474
|
"",
|
|
1331
1475
|
...refusals.map((guard) => [
|
|
1332
|
-
`### Turn ${guard.turn} · ${guard.tool}${guard.guard ? ` · ${guard.guard}` : ""}${guard.repeats > 1 ? ` · refused ${guard.repeats}× this Session` : ""}`,
|
|
1476
|
+
`### Turn ${guard.turn}${guardAgent(guard)} · ${guard.tool}${guard.guard ? ` · ${guard.guard}` : ""}${guard.repeats > 1 ? ` · refused ${guard.repeats}× this Session` : ""}`,
|
|
1333
1477
|
"",
|
|
1334
1478
|
`Attempted: \`${guard.attempted}\``,
|
|
1335
1479
|
"",
|
|
@@ -1348,7 +1492,7 @@ export function renderGuards(digest) {
|
|
|
1348
1492
|
? "No tool returned an error."
|
|
1349
1493
|
: errors
|
|
1350
1494
|
.map((guard) => [
|
|
1351
|
-
`### Turn ${guard.turn} · ${guard.tool}${guard.repeats > 1 ? ` · ${guard.repeats}×` : ""}`,
|
|
1495
|
+
`### Turn ${guard.turn}${guardAgent(guard)} · ${guard.tool}${guard.repeats > 1 ? ` · ${guard.repeats}×` : ""}`,
|
|
1352
1496
|
"",
|
|
1353
1497
|
`Attempted: \`${guard.attempted}\``,
|
|
1354
1498
|
"",
|