@narumitw/pi-subagents 2.0.2 → 2.0.4
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 +253 -160
- package/dist/chunks/auto-transport-SY2VHUFH.ts +8 -8
- package/dist/chunks/capability-grant-CGEWOEKE.ts +3 -3
- package/dist/chunks/{chunk-F5YWVHQX.ts → chunk-2OUVSORM.ts} +32 -32
- package/dist/chunks/chunk-434NII74.ts +4 -4
- package/dist/chunks/chunk-7QPPBBXZ.ts +3 -3
- package/dist/chunks/chunk-AEUYS7JC.ts +2 -2
- package/dist/chunks/chunk-BFK2Z4ZF.ts +1 -1
- package/dist/chunks/chunk-DQMN4OYM.ts +9 -9
- package/dist/chunks/chunk-DSOOH73Y.ts +1 -1
- package/dist/chunks/chunk-EFBPISNT.ts +5 -5
- package/dist/chunks/chunk-EWWXFU7N.ts +2 -2
- package/dist/chunks/chunk-F4L2UVSK.ts +3 -3
- package/dist/chunks/chunk-G3RSMSXJ.ts +3 -3
- package/dist/chunks/chunk-HA36LPCO.ts +1 -1
- package/dist/chunks/chunk-HKC4ES4B.ts +1 -1
- package/dist/chunks/chunk-I2FAK44T.ts +1 -1
- package/dist/chunks/chunk-NIF42QMF.ts +5 -5
- package/dist/chunks/chunk-O4VO6JUJ.ts +3 -3
- package/dist/chunks/chunk-ONDTY4EL.ts +1 -1
- package/dist/chunks/chunk-OVPHFGKO.ts +1 -1
- package/dist/chunks/chunk-PSK43Y6A.ts +2 -2
- package/dist/chunks/chunk-QBORTI4W.ts +3 -3
- package/dist/chunks/chunk-QDVGH2X7.ts +2 -2
- package/dist/chunks/chunk-RHRQMT7Q.ts +7 -7
- package/dist/chunks/chunk-RSUXZD6S.ts +1 -1
- package/dist/chunks/chunk-RTCVYIZA.ts +1 -1
- package/dist/chunks/chunk-SCZ33MYW.ts +4 -4
- package/dist/chunks/chunk-SWGQLFSD.ts +1 -1
- package/dist/chunks/chunk-UVFVHIOP.ts +12 -12
- package/dist/chunks/completion-delivery-YPOWSSV3.ts +6 -6
- package/dist/chunks/config-status-J4GPWP46.ts +8 -8
- package/dist/chunks/{config-ui-3IBMHTQB.ts → config-ui-7IMI3I4B.ts} +24 -24
- package/dist/chunks/consult-NYXVDN5G.ts +24 -24
- package/dist/chunks/context-QDKLVQXE.ts +1 -1
- package/dist/chunks/{create-stateful-transport-4WKZHRSI.ts → create-stateful-transport-F5OG2LEY.ts} +7 -7
- package/dist/chunks/cwd-policy-NB6XZ5GF.ts +3 -3
- package/dist/chunks/delegation-contract-WJPT4FVS.ts +2 -2
- package/dist/chunks/discovery-K25T3SH4.ts +4 -4
- package/dist/chunks/execution-DS2DEIQZ.ts +23 -23
- package/dist/chunks/in-process-transport-TEYAWSEC.ts +16 -16
- package/dist/chunks/inspect-UOQQ3KNL.ts +14 -14
- package/dist/chunks/peer-communication-KL36Z6CO.ts +2 -2
- package/dist/chunks/persistence-VSGXAW4P.ts +12 -12
- package/dist/chunks/registry-E6XPJB7L.ts +12 -12
- package/dist/chunks/retained-semantic-state-7WXSGRJU.ts +3 -3
- package/dist/chunks/{rpc-transport-Y6LA5BOP.ts → rpc-transport-ZNNBRUSY.ts} +118 -48
- package/dist/chunks/rpc-transport-ZNNBRUSY.ts.map +7 -0
- package/dist/chunks/runtime-policy-5YELCOVC.ts +1 -1
- package/dist/chunks/semantic-snapshot-WPJ3UAFW.ts +1 -1
- package/dist/chunks/spawn-idempotency-QGHO2WKC.ts +1 -1
- package/dist/chunks/stateful-lifecycle-JAR6K55H.ts +1 -1
- package/dist/chunks/subprocess-transport-C2XVR25R.ts +21 -21
- package/dist/chunks/workspace-WDKLN72J.ts +1 -1
- package/dist/index.ts +25 -25
- package/package.json +5 -5
- package/src/rpc-transport.ts +20 -6
- package/src/rpc-turn-capture.ts +98 -23
- package/dist/chunks/rpc-transport-Y6LA5BOP.ts.map +0 -7
- /package/dist/chunks/{chunk-F5YWVHQX.ts.map → chunk-2OUVSORM.ts.map} +0 -0
- /package/dist/chunks/{config-ui-3IBMHTQB.ts.map → config-ui-7IMI3I4B.ts.map} +0 -0
- /package/dist/chunks/{create-stateful-transport-4WKZHRSI.ts.map → create-stateful-transport-F5OG2LEY.ts.map} +0 -0
|
@@ -3,43 +3,43 @@
|
|
|
3
3
|
import {
|
|
4
4
|
buildStatefulTurnPrompt,
|
|
5
5
|
resolveStatefulTurnTimeout
|
|
6
|
-
} from "./chunk-SCZ33MYW.
|
|
6
|
+
} from "./chunk-SCZ33MYW.ts";
|
|
7
7
|
import {
|
|
8
8
|
runSingleAgent
|
|
9
|
-
} from "./chunk-DQMN4OYM.
|
|
10
|
-
import "./chunk-IGAMVWFN.
|
|
11
|
-
import "./chunk-47SK2QYC.
|
|
12
|
-
import "./chunk-HKC4ES4B.
|
|
13
|
-
import "./chunk-DSOOH73Y.
|
|
9
|
+
} from "./chunk-DQMN4OYM.ts";
|
|
10
|
+
import "./chunk-IGAMVWFN.ts";
|
|
11
|
+
import "./chunk-47SK2QYC.ts";
|
|
12
|
+
import "./chunk-HKC4ES4B.ts";
|
|
13
|
+
import "./chunk-DSOOH73Y.ts";
|
|
14
14
|
import {
|
|
15
15
|
CHILD_PEER_TOOL_NAMES,
|
|
16
16
|
childPeerBridgePath,
|
|
17
17
|
peerBridgeEnvironment
|
|
18
|
-
} from "./chunk-EWWXFU7N.
|
|
18
|
+
} from "./chunk-EWWXFU7N.ts";
|
|
19
19
|
import {
|
|
20
20
|
resolvePiPromptResources
|
|
21
|
-
} from "./chunk-G6VZTCFH.
|
|
22
|
-
import "./chunk-G3RSMSXJ.
|
|
21
|
+
} from "./chunk-G6VZTCFH.ts";
|
|
22
|
+
import "./chunk-G3RSMSXJ.ts";
|
|
23
23
|
import {
|
|
24
24
|
getResultFinalOutput
|
|
25
|
-
} from "./chunk-AEUYS7JC.
|
|
26
|
-
import "./chunk-RTCVYIZA.
|
|
27
|
-
import "./chunk-ONDTY4EL.
|
|
25
|
+
} from "./chunk-AEUYS7JC.ts";
|
|
26
|
+
import "./chunk-RTCVYIZA.ts";
|
|
27
|
+
import "./chunk-ONDTY4EL.ts";
|
|
28
28
|
import {
|
|
29
29
|
discoverAgents
|
|
30
|
-
} from "./chunk-PSK43Y6A.
|
|
31
|
-
import "./chunk-RSUXZD6S.
|
|
30
|
+
} from "./chunk-PSK43Y6A.ts";
|
|
31
|
+
import "./chunk-RSUXZD6S.ts";
|
|
32
32
|
import {
|
|
33
33
|
resolveSubagentThinkingLevel
|
|
34
|
-
} from "./chunk-7QPPBBXZ.
|
|
34
|
+
} from "./chunk-7QPPBBXZ.ts";
|
|
35
35
|
import {
|
|
36
36
|
readSubagentSettings
|
|
37
|
-
} from "./chunk-QBORTI4W.
|
|
38
|
-
import "./chunk-7OBINKFM.
|
|
39
|
-
import "./chunk-DPPVEQAM.
|
|
40
|
-
import "./chunk-I2FAK44T.
|
|
41
|
-
import "./chunk-H3FP6DLR.
|
|
42
|
-
import "./chunk-RRR66UWR.
|
|
37
|
+
} from "./chunk-QBORTI4W.ts";
|
|
38
|
+
import "./chunk-7OBINKFM.ts";
|
|
39
|
+
import "./chunk-DPPVEQAM.ts";
|
|
40
|
+
import "./chunk-I2FAK44T.ts";
|
|
41
|
+
import "./chunk-H3FP6DLR.ts";
|
|
42
|
+
import "./chunk-RRR66UWR.ts";
|
|
43
43
|
|
|
44
44
|
// src/subprocess-transport.ts
|
|
45
45
|
function resolveStatefulSubprocessThinkingLevel(agents, record) {
|
package/dist/index.ts
CHANGED
|
@@ -2,35 +2,35 @@
|
|
|
2
2
|
// @ts-nocheck -- generated JavaScript uses a .ts extension for Pi's Jiti loader.
|
|
3
3
|
import {
|
|
4
4
|
registerSubagentInspect
|
|
5
|
-
} from "./chunks/chunk-F4L2UVSK.
|
|
5
|
+
} from "./chunks/chunk-F4L2UVSK.ts";
|
|
6
6
|
import {
|
|
7
7
|
SubagentParams,
|
|
8
8
|
hasUsableAggregator
|
|
9
|
-
} from "./chunks/chunk-NIF42QMF.
|
|
9
|
+
} from "./chunks/chunk-NIF42QMF.ts";
|
|
10
10
|
import {
|
|
11
11
|
registerStatefulSubagents
|
|
12
|
-
} from "./chunks/chunk-
|
|
12
|
+
} from "./chunks/chunk-2OUVSORM.ts";
|
|
13
13
|
import {
|
|
14
14
|
discoverAgentCatalog,
|
|
15
15
|
formatAgentCatalog,
|
|
16
16
|
formatUsageStats,
|
|
17
17
|
registerSubagentConsult
|
|
18
|
-
} from "./chunks/chunk-RHRQMT7Q.
|
|
19
|
-
import "./chunks/chunk-P7OH4XMF.
|
|
20
|
-
import "./chunks/chunk-N7BLVXKK.
|
|
18
|
+
} from "./chunks/chunk-RHRQMT7Q.ts";
|
|
19
|
+
import "./chunks/chunk-P7OH4XMF.ts";
|
|
20
|
+
import "./chunks/chunk-N7BLVXKK.ts";
|
|
21
21
|
import {
|
|
22
22
|
getResultFinalOutput,
|
|
23
23
|
isResultError
|
|
24
|
-
} from "./chunks/chunk-AEUYS7JC.
|
|
25
|
-
import "./chunks/chunk-RTCVYIZA.
|
|
26
|
-
import "./chunks/chunk-ONDTY4EL.
|
|
27
|
-
import "./chunks/chunk-O4VO6JUJ.
|
|
24
|
+
} from "./chunks/chunk-AEUYS7JC.ts";
|
|
25
|
+
import "./chunks/chunk-RTCVYIZA.ts";
|
|
26
|
+
import "./chunks/chunk-ONDTY4EL.ts";
|
|
27
|
+
import "./chunks/chunk-O4VO6JUJ.ts";
|
|
28
28
|
import {
|
|
29
29
|
cachedModuleLoader,
|
|
30
30
|
throwIfAborted
|
|
31
|
-
} from "./chunks/chunk-HOP5FXDT.
|
|
32
|
-
import "./chunks/chunk-PSK43Y6A.
|
|
33
|
-
import "./chunks/chunk-RSUXZD6S.
|
|
31
|
+
} from "./chunks/chunk-HOP5FXDT.ts";
|
|
32
|
+
import "./chunks/chunk-PSK43Y6A.ts";
|
|
33
|
+
import "./chunks/chunk-RSUXZD6S.ts";
|
|
34
34
|
import {
|
|
35
35
|
DEFAULT_CONSULTATION_CWD_POLICY,
|
|
36
36
|
DEFAULT_CONSULT_RESOURCE_POLICY,
|
|
@@ -39,25 +39,25 @@ import {
|
|
|
39
39
|
inspectSubagentSettings,
|
|
40
40
|
readSubagentSettings,
|
|
41
41
|
resolveBlockingMaxParallelTasks
|
|
42
|
-
} from "./chunks/chunk-QBORTI4W.
|
|
43
|
-
import "./chunks/chunk-7OBINKFM.
|
|
44
|
-
import "./chunks/chunk-DPPVEQAM.
|
|
42
|
+
} from "./chunks/chunk-QBORTI4W.ts";
|
|
43
|
+
import "./chunks/chunk-7OBINKFM.ts";
|
|
44
|
+
import "./chunks/chunk-DPPVEQAM.ts";
|
|
45
45
|
import {
|
|
46
46
|
SUBAGENT_COMPLETION_MESSAGE_TYPE,
|
|
47
47
|
renderCompletionMessage
|
|
48
|
-
} from "./chunks/chunk-QDVGH2X7.
|
|
48
|
+
} from "./chunks/chunk-QDVGH2X7.ts";
|
|
49
49
|
import {
|
|
50
50
|
expansionHint,
|
|
51
51
|
formatToolActivity,
|
|
52
52
|
safeBlock,
|
|
53
53
|
safeLine
|
|
54
|
-
} from "./chunks/chunk-BFK2Z4ZF.
|
|
55
|
-
import "./chunks/chunk-SWGQLFSD.
|
|
56
|
-
import "./chunks/chunk-I2FAK44T.
|
|
54
|
+
} from "./chunks/chunk-BFK2Z4ZF.ts";
|
|
55
|
+
import "./chunks/chunk-SWGQLFSD.ts";
|
|
56
|
+
import "./chunks/chunk-I2FAK44T.ts";
|
|
57
57
|
import {
|
|
58
58
|
MAX_BLOCKING_PARALLEL_CONCURRENCY
|
|
59
|
-
} from "./chunks/chunk-H3FP6DLR.
|
|
60
|
-
import "./chunks/chunk-S2IWVK3J.
|
|
59
|
+
} from "./chunks/chunk-H3FP6DLR.ts";
|
|
60
|
+
import "./chunks/chunk-S2IWVK3J.ts";
|
|
61
61
|
|
|
62
62
|
// src/subagents-extension.ts
|
|
63
63
|
import {
|
|
@@ -85,10 +85,10 @@ function registerSubagentConfigLifecycle(pi) {
|
|
|
85
85
|
}
|
|
86
86
|
function registerSubagentConfigCommand(pi, runtime, owner = registerSubagentConfigLifecycle(pi), dependencies = {}) {
|
|
87
87
|
const loadConfigUi = cachedModuleLoader(
|
|
88
|
-
dependencies.loadConfigUi ?? (() => import("./chunks/config-ui-
|
|
88
|
+
dependencies.loadConfigUi ?? (() => import("./chunks/config-ui-7IMI3I4B.ts"))
|
|
89
89
|
);
|
|
90
90
|
const loadConfigStatus = cachedModuleLoader(
|
|
91
|
-
dependencies.loadConfigStatus ?? (() => import("./chunks/config-status-J4GPWP46.
|
|
91
|
+
dependencies.loadConfigStatus ?? (() => import("./chunks/config-status-J4GPWP46.ts"))
|
|
92
92
|
);
|
|
93
93
|
pi.registerCommand("subagents", {
|
|
94
94
|
description: "Manage current-session subagents and user settings",
|
|
@@ -832,7 +832,7 @@ ${expansionHint()}`;
|
|
|
832
832
|
function subagents_extension_default(pi, dependencies = {}) {
|
|
833
833
|
pi.registerMessageRenderer(SUBAGENT_COMPLETION_MESSAGE_TYPE, renderCompletionMessage);
|
|
834
834
|
const loadBlockingExecution = cachedModuleLoader(
|
|
835
|
-
dependencies.loadBlockingExecution ?? (() => import("./chunks/execution-DS2DEIQZ.
|
|
835
|
+
dependencies.loadBlockingExecution ?? (() => import("./chunks/execution-DS2DEIQZ.ts"))
|
|
836
836
|
);
|
|
837
837
|
const configOwner = registerSubagentConfigLifecycle(pi);
|
|
838
838
|
const settings = readSubagentSettings();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@narumitw/pi-subagents",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.4",
|
|
4
4
|
"description": "Pi extension for delegating work to specialized isolated subagents.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -42,17 +42,17 @@
|
|
|
42
42
|
"typebox": "*"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
|
-
"@biomejs/biome": "2.5.
|
|
45
|
+
"@biomejs/biome": "2.5.9",
|
|
46
46
|
"@earendil-works/pi-agent-core": "0.84.2",
|
|
47
47
|
"@earendil-works/pi-ai": "0.84.2",
|
|
48
48
|
"@earendil-works/pi-coding-agent": "0.84.2",
|
|
49
49
|
"@earendil-works/pi-tui": "0.84.2",
|
|
50
|
-
"esbuild": "0.28.
|
|
51
|
-
"typebox": "1.3.
|
|
50
|
+
"esbuild": "0.28.2",
|
|
51
|
+
"typebox": "1.3.16",
|
|
52
52
|
"typescript": "7.0.2"
|
|
53
53
|
},
|
|
54
54
|
"dependencies": {
|
|
55
|
-
"@narumitw/pi-tui-kit": "^0.56.
|
|
55
|
+
"@narumitw/pi-tui-kit": "^0.56.1",
|
|
56
56
|
"proper-lockfile": "^4.1.2"
|
|
57
57
|
},
|
|
58
58
|
"repository": {
|
package/src/rpc-transport.ts
CHANGED
|
@@ -37,8 +37,10 @@ import {
|
|
|
37
37
|
} from "./rpc-transport-metadata.js";
|
|
38
38
|
import {
|
|
39
39
|
captureRpcEvent,
|
|
40
|
+
commitRpcInFlightUsage,
|
|
40
41
|
createRpcTurnCapture,
|
|
41
42
|
observeRpcBudgetEvent,
|
|
43
|
+
snapshotRpcUsage,
|
|
42
44
|
} from "./rpc-turn-capture.js";
|
|
43
45
|
import { terminateProcess } from "./runner.js";
|
|
44
46
|
import { safeTerminalText } from "./safe-text.js";
|
|
@@ -501,11 +503,17 @@ export class RpcTransport implements SubagentTransport {
|
|
|
501
503
|
});
|
|
502
504
|
void settled.catch(() => undefined);
|
|
503
505
|
const unsubscribeEvent = child.client.onEvent((event) => {
|
|
504
|
-
captureRpcEvent(event, capture);
|
|
506
|
+
const usageChanged = captureRpcEvent(event, capture);
|
|
505
507
|
observeRpcBudgetEvent(event, budgetMonitor);
|
|
506
508
|
if (!capture.firstActivityAt && isActivityEvent(event)) {
|
|
507
509
|
capture.firstActivityAt = Date.now();
|
|
508
|
-
publish({
|
|
510
|
+
publish({
|
|
511
|
+
phase: "running",
|
|
512
|
+
timing: { firstActivityAt: capture.firstActivityAt },
|
|
513
|
+
...(usageChanged ? { usage: snapshotRpcUsage(capture) } : {}),
|
|
514
|
+
});
|
|
515
|
+
} else if (usageChanged) {
|
|
516
|
+
publish({ usage: snapshotRpcUsage(capture) });
|
|
509
517
|
}
|
|
510
518
|
const type = eventType(event);
|
|
511
519
|
if (type === "auto_retry_start") publish({ phase: "retrying" });
|
|
@@ -572,7 +580,7 @@ export class RpcTransport implements SubagentTransport {
|
|
|
572
580
|
phase: explicitAbort ? "interrupted" : "failed",
|
|
573
581
|
failurePhase: "running",
|
|
574
582
|
timing: { settledAt: Date.now() },
|
|
575
|
-
usage: capture
|
|
583
|
+
usage: snapshotRpcUsage(capture),
|
|
576
584
|
});
|
|
577
585
|
const checkpointOutput = termination
|
|
578
586
|
? formatTimeoutCheckpoint(termination.checkpoint)
|
|
@@ -591,7 +599,11 @@ export class RpcTransport implements SubagentTransport {
|
|
|
591
599
|
};
|
|
592
600
|
}
|
|
593
601
|
|
|
594
|
-
publish({
|
|
602
|
+
publish({
|
|
603
|
+
phase: "finalizing",
|
|
604
|
+
failurePhase: "running",
|
|
605
|
+
usage: snapshotRpcUsage(capture),
|
|
606
|
+
});
|
|
595
607
|
const finalizationStartedAt = Date.now();
|
|
596
608
|
const summary = await finalizeTimedOutRpcTurn({
|
|
597
609
|
client: child.client,
|
|
@@ -605,6 +617,7 @@ export class RpcTransport implements SubagentTransport {
|
|
|
605
617
|
finalizationTimeoutMs: this.options.timeoutFinalizationMs,
|
|
606
618
|
abortGraceMs: this.options.abortGraceMs ?? ABORT_GRACE_MS,
|
|
607
619
|
resetCapture() {
|
|
620
|
+
commitRpcInFlightUsage(capture);
|
|
608
621
|
capture.output = "";
|
|
609
622
|
capture.partial = "";
|
|
610
623
|
capture.stopReason = undefined;
|
|
@@ -625,7 +638,7 @@ export class RpcTransport implements SubagentTransport {
|
|
|
625
638
|
phase: "failed",
|
|
626
639
|
failurePhase: "running",
|
|
627
640
|
timing: { settledAt: Date.now() },
|
|
628
|
-
usage: capture
|
|
641
|
+
usage: snapshotRpcUsage(capture),
|
|
629
642
|
});
|
|
630
643
|
const checkpointOutput = termination ? formatTimeoutCheckpoint(termination.checkpoint) : "";
|
|
631
644
|
return {
|
|
@@ -651,7 +664,7 @@ export class RpcTransport implements SubagentTransport {
|
|
|
651
664
|
timing: { settledAt: Date.now() },
|
|
652
665
|
provider: capture.provider ?? telemetry.provider,
|
|
653
666
|
model: capture.model ?? telemetry.model,
|
|
654
|
-
usage: capture
|
|
667
|
+
usage: snapshotRpcUsage(capture),
|
|
655
668
|
});
|
|
656
669
|
return {
|
|
657
670
|
output: output.text,
|
|
@@ -686,6 +699,7 @@ export class RpcTransport implements SubagentTransport {
|
|
|
686
699
|
phase: signal.aborted ? "interrupted" : "failed",
|
|
687
700
|
failurePhase: accepted ? "running" : "ready",
|
|
688
701
|
timing: { settledAt: Date.now() },
|
|
702
|
+
usage: snapshotRpcUsage(capture),
|
|
689
703
|
});
|
|
690
704
|
return {
|
|
691
705
|
output:
|
package/src/rpc-turn-capture.ts
CHANGED
|
@@ -12,6 +12,7 @@ export interface RpcTurnCapture {
|
|
|
12
12
|
provider?: string;
|
|
13
13
|
model?: string;
|
|
14
14
|
usage: TransportUsage;
|
|
15
|
+
inFlightUsage?: TransportUsage;
|
|
15
16
|
firstActivityAt?: number;
|
|
16
17
|
journal: TimeoutProgressJournal;
|
|
17
18
|
}
|
|
@@ -25,8 +26,9 @@ export function createRpcTurnCapture(): RpcTurnCapture {
|
|
|
25
26
|
};
|
|
26
27
|
}
|
|
27
28
|
|
|
28
|
-
export function captureRpcEvent(event: unknown, capture: RpcTurnCapture):
|
|
29
|
-
if (!isRecord(event)) return;
|
|
29
|
+
export function captureRpcEvent(event: unknown, capture: RpcTurnCapture): boolean {
|
|
30
|
+
if (!isRecord(event)) return false;
|
|
31
|
+
const previousUsage = snapshotRpcUsage(capture);
|
|
30
32
|
if (event.type === "tool_execution_start") {
|
|
31
33
|
capture.journal.recordToolCall(
|
|
32
34
|
typeof event.toolCallId === "string" ? event.toolCallId : "",
|
|
@@ -42,7 +44,12 @@ export function captureRpcEvent(event: unknown, capture: RpcTurnCapture): void {
|
|
|
42
44
|
{ content: result.content, isError: event.isError },
|
|
43
45
|
);
|
|
44
46
|
}
|
|
47
|
+
if (event.type === "message_start" && isRecord(event.message)) {
|
|
48
|
+
if (event.message.role === "assistant") commitRpcInFlightUsage(capture);
|
|
49
|
+
}
|
|
45
50
|
if (event.type === "message_update") {
|
|
51
|
+
const usage = normalizeUsage(event.usage);
|
|
52
|
+
if (usage) capture.inFlightUsage = usage;
|
|
46
53
|
const delta = event.assistantMessageEvent;
|
|
47
54
|
if (isRecord(delta) && delta.type === "text_delta" && typeof delta.delta === "string") {
|
|
48
55
|
capture.partial = truncateUtf8(
|
|
@@ -51,10 +58,28 @@ export function captureRpcEvent(event: unknown, capture: RpcTurnCapture): void {
|
|
|
51
58
|
).text;
|
|
52
59
|
}
|
|
53
60
|
}
|
|
54
|
-
if (event.type
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
61
|
+
if (event.type === "message_end" && isRecord(event.message)) {
|
|
62
|
+
const candidate = event.message;
|
|
63
|
+
if (candidate.role !== "toolResult") journalMessages(capture.journal, [candidate]);
|
|
64
|
+
if (candidate.role === "assistant") captureAssistantEnd(candidate, capture);
|
|
65
|
+
}
|
|
66
|
+
return !sameUsage(previousUsage, snapshotRpcUsage(capture));
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export function snapshotRpcUsage(capture: RpcTurnCapture): TransportUsage {
|
|
70
|
+
const usage = { ...capture.usage };
|
|
71
|
+
if (capture.inFlightUsage) addUsage(usage, capture.inFlightUsage);
|
|
72
|
+
return usage;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export function commitRpcInFlightUsage(capture: RpcTurnCapture): boolean {
|
|
76
|
+
if (!capture.inFlightUsage) return false;
|
|
77
|
+
addUsage(capture.usage, capture.inFlightUsage);
|
|
78
|
+
capture.inFlightUsage = undefined;
|
|
79
|
+
return true;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function captureAssistantEnd(candidate: Record<string, unknown>, capture: RpcTurnCapture): void {
|
|
58
83
|
capture.output = truncateUtf8(
|
|
59
84
|
assistantText(candidate.content) || capture.partial,
|
|
60
85
|
DEFAULT_MAX_OUTPUT_BYTES,
|
|
@@ -76,8 +101,11 @@ export function captureRpcEvent(event: unknown, capture: RpcTurnCapture): void {
|
|
|
76
101
|
? candidate.model
|
|
77
102
|
: undefined;
|
|
78
103
|
capture.model = responseModel ? boundedPrivateText(responseModel, 256) : undefined;
|
|
79
|
-
|
|
80
|
-
|
|
104
|
+
const finalUsage = normalizeUsage(candidate.usage);
|
|
105
|
+
const completedUsage = finalUsage ?? capture.inFlightUsage;
|
|
106
|
+
if (completedUsage) addUsage(capture.usage, completedUsage);
|
|
107
|
+
capture.inFlightUsage = undefined;
|
|
108
|
+
capture.usage.turns = addUsageValue(capture.usage.turns, 1);
|
|
81
109
|
}
|
|
82
110
|
|
|
83
111
|
export function observeRpcBudgetEvent(event: unknown, monitor: TurnBudgetMonitor): void {
|
|
@@ -101,29 +129,76 @@ function assistantToolCallCount(content: unknown): number {
|
|
|
101
129
|
return content.filter((part) => isRecord(part) && part.type === "toolCall").length;
|
|
102
130
|
}
|
|
103
131
|
|
|
104
|
-
function
|
|
105
|
-
if (!isRecord(value)) return;
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
132
|
+
function normalizeUsage(value: unknown): TransportUsage | undefined {
|
|
133
|
+
if (!isRecord(value)) return undefined;
|
|
134
|
+
const input = safeNonNegative(value.input);
|
|
135
|
+
const output = safeNonNegative(value.output);
|
|
136
|
+
const cacheRead = safeNonNegative(value.cacheRead);
|
|
137
|
+
const cacheWrite = safeNonNegative(value.cacheWrite);
|
|
110
138
|
const reportedTotal = safeNonNegative(value.totalTokens);
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
139
|
+
const cost = isRecord(value.cost) ? safeNonNegative(value.cost.total) : undefined;
|
|
140
|
+
if (
|
|
141
|
+
input === undefined &&
|
|
142
|
+
output === undefined &&
|
|
143
|
+
cacheRead === undefined &&
|
|
144
|
+
cacheWrite === undefined &&
|
|
145
|
+
reportedTotal === undefined &&
|
|
146
|
+
cost === undefined
|
|
147
|
+
) {
|
|
148
|
+
return undefined;
|
|
149
|
+
}
|
|
150
|
+
const components = [input, output, cacheRead, cacheWrite].reduce<number>(
|
|
151
|
+
(total, current) => addUsageValue(total, current ?? 0),
|
|
152
|
+
0,
|
|
153
|
+
);
|
|
154
|
+
return {
|
|
155
|
+
input: input ?? 0,
|
|
156
|
+
output: output ?? 0,
|
|
157
|
+
cacheRead: cacheRead ?? 0,
|
|
158
|
+
cacheWrite: cacheWrite ?? 0,
|
|
159
|
+
totalTokens: reportedTotal ?? components,
|
|
160
|
+
cost: cost ?? 0,
|
|
161
|
+
turns: 0,
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
function addUsage(target: TransportUsage, value: TransportUsage): void {
|
|
166
|
+
for (const key of [
|
|
167
|
+
"input",
|
|
168
|
+
"output",
|
|
169
|
+
"cacheRead",
|
|
170
|
+
"cacheWrite",
|
|
171
|
+
"totalTokens",
|
|
172
|
+
"cost",
|
|
173
|
+
"turns",
|
|
174
|
+
] as const) {
|
|
175
|
+
target[key] = addUsageValue(target[key], value[key]);
|
|
176
|
+
}
|
|
118
177
|
}
|
|
119
178
|
|
|
120
|
-
function
|
|
179
|
+
function addUsageValue(current: number, addition: number): number {
|
|
180
|
+
return Math.min(Number.MAX_SAFE_INTEGER, current + addition);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
function safeNonNegative(value: unknown): number | undefined {
|
|
121
184
|
return typeof value === "number" &&
|
|
122
185
|
Number.isFinite(value) &&
|
|
123
186
|
value >= 0 &&
|
|
124
187
|
value <= Number.MAX_SAFE_INTEGER
|
|
125
188
|
? value
|
|
126
|
-
:
|
|
189
|
+
: undefined;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
function sameUsage(left: TransportUsage, right: TransportUsage): boolean {
|
|
193
|
+
return (
|
|
194
|
+
left.input === right.input &&
|
|
195
|
+
left.output === right.output &&
|
|
196
|
+
left.cacheRead === right.cacheRead &&
|
|
197
|
+
left.cacheWrite === right.cacheWrite &&
|
|
198
|
+
left.totalTokens === right.totalTokens &&
|
|
199
|
+
left.cost === right.cost &&
|
|
200
|
+
left.turns === right.turns
|
|
201
|
+
);
|
|
127
202
|
}
|
|
128
203
|
|
|
129
204
|
function assistantText(value: unknown): string {
|