@stigmer/react 0.0.56 → 0.0.58
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/execution/ApprovalCard.d.ts.map +1 -1
- package/execution/ApprovalCard.js +1 -1
- package/execution/ApprovalCard.js.map +1 -1
- package/execution/ArtifactsWidget.d.ts +1 -1
- package/execution/ArtifactsWidget.js +1 -1
- package/execution/ExecutionProgress.d.ts.map +1 -1
- package/execution/ExecutionProgress.js +2 -59
- package/execution/ExecutionProgress.js.map +1 -1
- package/execution/MessageThread.d.ts.map +1 -1
- package/execution/MessageThread.js +31 -6
- package/execution/MessageThread.js.map +1 -1
- package/execution/SubAgentSection.d.ts +25 -4
- package/execution/SubAgentSection.d.ts.map +1 -1
- package/execution/SubAgentSection.js +70 -11
- package/execution/SubAgentSection.js.map +1 -1
- package/execution/TodoList.d.ts +42 -0
- package/execution/TodoList.d.ts.map +1 -0
- package/execution/TodoList.js +108 -0
- package/execution/TodoList.js.map +1 -0
- package/execution/ToolCallItem.js +1 -1
- package/execution/ToolCallItem.js.map +1 -1
- package/execution/UsageWidget.d.ts +57 -0
- package/execution/UsageWidget.d.ts.map +1 -0
- package/execution/UsageWidget.js +72 -0
- package/execution/UsageWidget.js.map +1 -0
- package/execution/index.d.ts +4 -4
- package/execution/index.d.ts.map +1 -1
- package/execution/index.js +2 -2
- package/execution/index.js.map +1 -1
- package/execution/useExecutionArtifacts.d.ts +1 -1
- package/execution/useExecutionArtifacts.js +1 -1
- package/index.d.ts +4 -4
- package/index.d.ts.map +1 -1
- package/index.js +2 -2
- package/index.js.map +1 -1
- package/package.json +4 -4
- package/session/index.d.ts +2 -0
- package/session/index.d.ts.map +1 -1
- package/session/index.js +1 -0
- package/session/index.js.map +1 -1
- package/session/useSessionUsage.d.ts +65 -0
- package/session/useSessionUsage.d.ts.map +1 -0
- package/session/useSessionUsage.js +107 -0
- package/session/useSessionUsage.js.map +1 -0
- package/src/execution/ApprovalCard.tsx +7 -13
- package/src/execution/ArtifactsWidget.tsx +1 -1
- package/src/execution/ExecutionProgress.tsx +2 -134
- package/src/execution/MessageThread.tsx +39 -6
- package/src/execution/SubAgentSection.tsx +323 -16
- package/src/execution/TodoList.tsx +202 -0
- package/src/execution/ToolCallItem.tsx +1 -1
- package/src/execution/{ExecutionCostSummary.tsx → UsageWidget.tsx} +43 -50
- package/src/execution/index.ts +10 -4
- package/src/execution/useExecutionArtifacts.ts +1 -1
- package/src/index.ts +12 -5
- package/src/session/index.ts +6 -0
- package/src/session/useSessionUsage.ts +159 -0
- package/styles.css +1 -1
- package/execution/ExecutionCostSummary.d.ts +0 -47
- package/execution/ExecutionCostSummary.d.ts.map +0 -1
- package/execution/ExecutionCostSummary.js +0 -77
- package/execution/ExecutionCostSummary.js.map +0 -1
- package/execution/__tests__/ExecutionCostSummary.test.d.ts +0 -2
- package/execution/__tests__/ExecutionCostSummary.test.d.ts.map +0 -1
- package/execution/__tests__/ExecutionCostSummary.test.js +0 -255
- package/execution/__tests__/ExecutionCostSummary.test.js.map +0 -1
- package/execution/__tests__/useExecutionUsage.test.d.ts +0 -2
- package/execution/__tests__/useExecutionUsage.test.d.ts.map +0 -1
- package/execution/__tests__/useExecutionUsage.test.js +0 -303
- package/execution/__tests__/useExecutionUsage.test.js.map +0 -1
- package/execution/useExecutionUsage.d.ts +0 -45
- package/execution/useExecutionUsage.d.ts.map +0 -1
- package/execution/useExecutionUsage.js +0 -157
- package/execution/useExecutionUsage.js.map +0 -1
- package/src/execution/__tests__/ExecutionCostSummary.test.tsx +0 -416
- package/src/execution/__tests__/useExecutionUsage.test.tsx +0 -408
- package/src/execution/useExecutionUsage.ts +0 -213
|
@@ -1,51 +1,59 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
3
|
import type { AgentExecution } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/api_pb";
|
|
4
|
-
import type { ModelUsage } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/usage_pb";
|
|
5
4
|
import { cn } from "@stigmer/theme";
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
5
|
+
import {
|
|
6
|
+
useSessionUsage,
|
|
7
|
+
type ModelCostEntry,
|
|
8
|
+
} from "../session/useSessionUsage";
|
|
9
|
+
|
|
10
|
+
export interface UsageWidgetProps {
|
|
11
|
+
/**
|
|
12
|
+
* All executions for the current session — both completed and
|
|
13
|
+
* actively streaming. The widget aggregates cost data across
|
|
14
|
+
* every execution's per-message `llm_metrics`, presenting a
|
|
15
|
+
* session-level total that never resets.
|
|
16
|
+
*
|
|
17
|
+
* Renders nothing when the list is empty or no execution has
|
|
18
|
+
* usage data.
|
|
19
|
+
*/
|
|
20
|
+
readonly executions: readonly AgentExecution[];
|
|
21
|
+
/** Additional CSS classes for the root element. */
|
|
11
22
|
readonly className?: string;
|
|
12
23
|
}
|
|
13
24
|
|
|
14
25
|
/**
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* The headline shows estimated USD cost. Below it: model identification,
|
|
19
|
-
* total token and LLM call counts, a prompt/completion breakdown, and
|
|
20
|
-
* conditional annotations for cache usage and sub-agent contributions.
|
|
26
|
+
* Right-sidebar widget that displays session-level cost and token
|
|
27
|
+
* usage aggregated from per-message {@link LlmCallMetrics}.
|
|
21
28
|
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
* widths so the layout does not shift as numbers grow.
|
|
29
|
+
* Usage data is computed purely from messages the frontend already
|
|
30
|
+
* has — no server RPC is required for the real-time widget.
|
|
25
31
|
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
32
|
+
* Returns `null` when no execution has usage data, matching the
|
|
33
|
+
* conditional-render pattern of {@link ArtifactsWidget} and
|
|
34
|
+
* {@link WriteBacksWidget}.
|
|
28
35
|
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
36
|
+
* All visual properties flow through `--stgm-*` tokens. Zero
|
|
37
|
+
* Console dependencies.
|
|
31
38
|
*
|
|
32
39
|
* @example
|
|
33
40
|
* ```tsx
|
|
34
|
-
* const
|
|
41
|
+
* const conv = useSessionConversation(sessionId, org);
|
|
35
42
|
*
|
|
36
|
-
* <
|
|
37
|
-
*
|
|
38
|
-
*
|
|
43
|
+
* <UsageWidget
|
|
44
|
+
* executions={[
|
|
45
|
+
* ...conv.completedExecutions,
|
|
46
|
+
* ...(conv.activeStreamExecution ? [conv.activeStreamExecution] : []),
|
|
47
|
+
* ]}
|
|
48
|
+
* />
|
|
39
49
|
* ```
|
|
50
|
+
*
|
|
51
|
+
* @see {@link useSessionUsage} — headless session-level usage aggregation hook
|
|
40
52
|
*/
|
|
41
|
-
export function
|
|
42
|
-
|
|
43
|
-
className,
|
|
44
|
-
}: ExecutionCostSummaryProps) {
|
|
45
|
-
const { usage, hasSubAgentUsage, subAgentUsageCount } =
|
|
46
|
-
useExecutionUsage(execution);
|
|
53
|
+
export function UsageWidget({ executions, className }: UsageWidgetProps) {
|
|
54
|
+
const usage = useSessionUsage(executions);
|
|
47
55
|
|
|
48
|
-
if (!usage) return null;
|
|
56
|
+
if (!usage.hasUsage) return null;
|
|
49
57
|
|
|
50
58
|
const multiModel = usage.modelBreakdown.length > 1;
|
|
51
59
|
|
|
@@ -53,10 +61,10 @@ export function ExecutionCostSummary({
|
|
|
53
61
|
<div
|
|
54
62
|
className={cn("flex flex-col gap-1.5", className)}
|
|
55
63
|
role="region"
|
|
56
|
-
aria-label="
|
|
64
|
+
aria-label="Session cost summary"
|
|
57
65
|
>
|
|
58
66
|
<div className="text-sm font-medium tabular-nums text-foreground">
|
|
59
|
-
{formatCost(usage.
|
|
67
|
+
{formatCost(usage.totalCostUsd)}
|
|
60
68
|
</div>
|
|
61
69
|
|
|
62
70
|
{multiModel ? (
|
|
@@ -74,8 +82,8 @@ export function ExecutionCostSummary({
|
|
|
74
82
|
</div>
|
|
75
83
|
|
|
76
84
|
<div className="pl-2 text-xs tabular-nums text-muted-foreground">
|
|
77
|
-
prompt {formatTokenCount(usage.
|
|
78
|
-
{formatTokenCount(usage.
|
|
85
|
+
prompt {formatTokenCount(usage.inputTokens)} · completion{" "}
|
|
86
|
+
{formatTokenCount(usage.outputTokens)}
|
|
79
87
|
</div>
|
|
80
88
|
|
|
81
89
|
{(usage.cacheReadTokens > 0 || usage.cacheCreationTokens > 0) && (
|
|
@@ -84,25 +92,14 @@ export function ExecutionCostSummary({
|
|
|
84
92
|
creationTokens={usage.cacheCreationTokens}
|
|
85
93
|
/>
|
|
86
94
|
)}
|
|
87
|
-
|
|
88
|
-
{hasSubAgentUsage && (
|
|
89
|
-
<div className="text-xs text-muted-foreground">
|
|
90
|
-
Includes {subAgentUsageCount} sub-agent
|
|
91
|
-
{subAgentUsageCount > 1 ? "s" : ""}
|
|
92
|
-
</div>
|
|
93
|
-
)}
|
|
94
95
|
</div>
|
|
95
96
|
);
|
|
96
97
|
}
|
|
97
98
|
|
|
98
|
-
// ---------------------------------------------------------------------------
|
|
99
|
-
// Internal sub-components
|
|
100
|
-
// ---------------------------------------------------------------------------
|
|
101
|
-
|
|
102
99
|
function ModelBreakdown({
|
|
103
100
|
models,
|
|
104
101
|
}: {
|
|
105
|
-
readonly models: readonly
|
|
102
|
+
readonly models: readonly ModelCostEntry[];
|
|
106
103
|
}) {
|
|
107
104
|
return (
|
|
108
105
|
<div
|
|
@@ -145,10 +142,6 @@ function CacheLine({
|
|
|
145
142
|
);
|
|
146
143
|
}
|
|
147
144
|
|
|
148
|
-
// ---------------------------------------------------------------------------
|
|
149
|
-
// Formatting utilities
|
|
150
|
-
// ---------------------------------------------------------------------------
|
|
151
|
-
|
|
152
145
|
/**
|
|
153
146
|
* Formats a USD cost value for display.
|
|
154
147
|
* - Zero: "$0.00"
|
package/src/execution/index.ts
CHANGED
|
@@ -10,8 +10,8 @@ export { isTerminalPhase } from "./execution-phases";
|
|
|
10
10
|
export { useExecutionStream } from "./useExecutionStream";
|
|
11
11
|
export type { UseExecutionStreamReturn } from "./useExecutionStream";
|
|
12
12
|
|
|
13
|
-
export {
|
|
14
|
-
export type {
|
|
13
|
+
export { UsageWidget, formatCost, formatTokenCount } from "./UsageWidget";
|
|
14
|
+
export type { UsageWidgetProps } from "./UsageWidget";
|
|
15
15
|
|
|
16
16
|
export { useExecutionArtifacts } from "./useExecutionArtifacts";
|
|
17
17
|
export type { UseExecutionArtifactsReturn } from "./useExecutionArtifacts";
|
|
@@ -89,8 +89,14 @@ export type { FollowUpInputProps } from "./FollowUpInput";
|
|
|
89
89
|
export { ExecutionProgress } from "./ExecutionProgress";
|
|
90
90
|
export type { ExecutionProgressProps } from "./ExecutionProgress";
|
|
91
91
|
|
|
92
|
-
export {
|
|
93
|
-
|
|
92
|
+
export {
|
|
93
|
+
TodoList,
|
|
94
|
+
TodoInProgressIcon,
|
|
95
|
+
findActiveTodo,
|
|
96
|
+
todoCompletionSummary,
|
|
97
|
+
} from "./TodoList";
|
|
98
|
+
export type { TodoListProps } from "./TodoList";
|
|
99
|
+
|
|
94
100
|
|
|
95
101
|
export { useSubmitApproval } from "./useSubmitApproval";
|
|
96
102
|
export type { UseSubmitApprovalReturn } from "./useSubmitApproval";
|
|
@@ -17,7 +17,7 @@ export interface UseExecutionArtifactsReturn {
|
|
|
17
17
|
* Pure derivation hook that extracts artifact metadata from an
|
|
18
18
|
* {@link AgentExecution} snapshot.
|
|
19
19
|
*
|
|
20
|
-
* Follows the same pattern as {@link
|
|
20
|
+
* Follows the same pattern as {@link useSessionUsage}: a `useMemo`-based
|
|
21
21
|
* derivation with no side effects and no data fetching. The execution
|
|
22
22
|
* object (typically from {@link useExecutionStream}) is the single input.
|
|
23
23
|
*
|
package/src/index.ts
CHANGED
|
@@ -54,6 +54,7 @@ export {
|
|
|
54
54
|
useSessionConversation,
|
|
55
55
|
useSessionArtifacts,
|
|
56
56
|
useSessionWriteBacks,
|
|
57
|
+
useSessionUsage,
|
|
57
58
|
useAgentRefFromSession,
|
|
58
59
|
groupSessionsByTime,
|
|
59
60
|
PENDING_SUBJECT,
|
|
@@ -74,6 +75,8 @@ export type {
|
|
|
74
75
|
UseSessionArtifactsReturn,
|
|
75
76
|
SessionWriteBackEntry,
|
|
76
77
|
UseSessionWriteBacksReturn,
|
|
78
|
+
ModelCostEntry,
|
|
79
|
+
UseSessionUsageReturn,
|
|
77
80
|
UseAgentRefFromSessionReturn,
|
|
78
81
|
SessionGroup,
|
|
79
82
|
} from "./session";
|
|
@@ -83,13 +86,17 @@ export {
|
|
|
83
86
|
isTerminalPhase,
|
|
84
87
|
useCreateAgentExecution,
|
|
85
88
|
useExecutionStream,
|
|
86
|
-
useExecutionUsage,
|
|
87
|
-
aggregateUsage,
|
|
88
89
|
useSubmitApproval,
|
|
89
90
|
ExecutionPhaseBadge,
|
|
90
91
|
SetupProgress,
|
|
91
92
|
ExecutionProgress,
|
|
92
|
-
|
|
93
|
+
TodoList,
|
|
94
|
+
TodoInProgressIcon,
|
|
95
|
+
findActiveTodo,
|
|
96
|
+
todoCompletionSummary,
|
|
97
|
+
UsageWidget,
|
|
98
|
+
formatCost,
|
|
99
|
+
formatTokenCount,
|
|
93
100
|
ToolCallGroup,
|
|
94
101
|
ToolCallDetail,
|
|
95
102
|
McpToolDetail,
|
|
@@ -133,12 +140,12 @@ export type {
|
|
|
133
140
|
CreateAgentExecutionResult,
|
|
134
141
|
UseCreateAgentExecutionReturn,
|
|
135
142
|
UseExecutionStreamReturn,
|
|
136
|
-
UseExecutionUsageReturn,
|
|
137
143
|
UseSubmitApprovalReturn,
|
|
138
144
|
ExecutionPhaseBadgeProps,
|
|
139
145
|
SetupProgressProps,
|
|
140
146
|
ExecutionProgressProps,
|
|
141
|
-
|
|
147
|
+
TodoListProps,
|
|
148
|
+
UsageWidgetProps,
|
|
142
149
|
ToolCallGroupProps,
|
|
143
150
|
ToolCallDetailProps,
|
|
144
151
|
McpToolDetailProps,
|
package/src/session/index.ts
CHANGED
|
@@ -38,6 +38,12 @@ export type {
|
|
|
38
38
|
UseSessionWriteBacksReturn,
|
|
39
39
|
} from "./useSessionWriteBacks";
|
|
40
40
|
|
|
41
|
+
export { useSessionUsage } from "./useSessionUsage";
|
|
42
|
+
export type {
|
|
43
|
+
ModelCostEntry,
|
|
44
|
+
UseSessionUsageReturn,
|
|
45
|
+
} from "./useSessionUsage";
|
|
46
|
+
|
|
41
47
|
export { useAgentRefFromSession } from "./useAgentRefFromSession";
|
|
42
48
|
export type { UseAgentRefFromSessionReturn } from "./useAgentRefFromSession";
|
|
43
49
|
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useMemo } from "react";
|
|
4
|
+
import type { AgentExecution } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/api_pb";
|
|
5
|
+
import { MessageType } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
|
|
6
|
+
import type { LlmCallMetrics } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/usage_pb";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Per-model cost breakdown computed from per-message {@link LlmCallMetrics}.
|
|
10
|
+
*/
|
|
11
|
+
export interface ModelCostEntry {
|
|
12
|
+
readonly model: string;
|
|
13
|
+
readonly provider: string;
|
|
14
|
+
readonly estimatedCostUsd: number;
|
|
15
|
+
readonly inputTokens: number;
|
|
16
|
+
readonly outputTokens: number;
|
|
17
|
+
readonly cacheCreationTokens: number;
|
|
18
|
+
readonly cacheReadTokens: number;
|
|
19
|
+
readonly callCount: number;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface UseSessionUsageReturn {
|
|
23
|
+
/** Total estimated cost across all executions in the session. */
|
|
24
|
+
readonly totalCostUsd: number;
|
|
25
|
+
/** Total tokens (all types) across all executions. */
|
|
26
|
+
readonly totalTokens: number;
|
|
27
|
+
/** Total input tokens (non-cached) across all executions. */
|
|
28
|
+
readonly inputTokens: number;
|
|
29
|
+
/** Total output tokens across all executions. */
|
|
30
|
+
readonly outputTokens: number;
|
|
31
|
+
/** Total cache read tokens across all executions. */
|
|
32
|
+
readonly cacheReadTokens: number;
|
|
33
|
+
/** Total cache creation tokens across all executions. */
|
|
34
|
+
readonly cacheCreationTokens: number;
|
|
35
|
+
/** Total number of LLM calls across all executions. */
|
|
36
|
+
readonly llmCallCount: number;
|
|
37
|
+
/** Per-model breakdown, sorted by cost descending. */
|
|
38
|
+
readonly modelBreakdown: readonly ModelCostEntry[];
|
|
39
|
+
/** Primary model (first model encountered). */
|
|
40
|
+
readonly primaryModel: string;
|
|
41
|
+
/** Primary provider (first provider encountered). */
|
|
42
|
+
readonly primaryProvider: string;
|
|
43
|
+
/** `true` when at least one execution has cost data. */
|
|
44
|
+
readonly hasUsage: boolean;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Pure derivation hook that aggregates usage data across all executions
|
|
49
|
+
* in a session from per-message {@link LlmCallMetrics}.
|
|
50
|
+
*
|
|
51
|
+
* Follows the same pattern as {@link useSessionArtifacts} and
|
|
52
|
+
* {@link useSessionWriteBacks}: `useMemo`-based derivation, no side
|
|
53
|
+
* effects, no data fetching. Takes the same `executions` array input.
|
|
54
|
+
*
|
|
55
|
+
* Per-message `llm_metrics` on `AgentMessage` (type == MESSAGE_AI) is
|
|
56
|
+
* the single source of truth for cost data. This hook walks all messages
|
|
57
|
+
* (main agent + sub-agents) across all executions and sums the fields.
|
|
58
|
+
*
|
|
59
|
+
* @param executions - All executions for a session, in chronological
|
|
60
|
+
* order. Pass both completed and active-stream executions.
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* ```tsx
|
|
64
|
+
* const conv = useSessionConversation(sessionId, org);
|
|
65
|
+
* const allExecutions = [
|
|
66
|
+
* ...conv.completedExecutions,
|
|
67
|
+
* ...(conv.activeStreamExecution ? [conv.activeStreamExecution] : []),
|
|
68
|
+
* ];
|
|
69
|
+
* const { totalCostUsd, totalTokens, hasUsage } = useSessionUsage(allExecutions);
|
|
70
|
+
* ```
|
|
71
|
+
*/
|
|
72
|
+
export function useSessionUsage(
|
|
73
|
+
executions: readonly AgentExecution[],
|
|
74
|
+
): UseSessionUsageReturn {
|
|
75
|
+
return useMemo(() => {
|
|
76
|
+
let totalCostUsd = 0;
|
|
77
|
+
let totalTokens = 0;
|
|
78
|
+
let inputTokens = 0;
|
|
79
|
+
let outputTokens = 0;
|
|
80
|
+
let cacheReadTokens = 0;
|
|
81
|
+
let cacheCreationTokens = 0;
|
|
82
|
+
let llmCallCount = 0;
|
|
83
|
+
let primaryModel = "";
|
|
84
|
+
let primaryProvider = "";
|
|
85
|
+
const modelMap = new Map<string, ModelCostEntry>();
|
|
86
|
+
|
|
87
|
+
const processMessage = (msg: { type: MessageType; llmMetrics?: LlmCallMetrics }) => {
|
|
88
|
+
const m = msg.llmMetrics;
|
|
89
|
+
if (!m) return;
|
|
90
|
+
|
|
91
|
+
totalCostUsd += m.estimatedCostUsd;
|
|
92
|
+
totalTokens += m.totalTokens;
|
|
93
|
+
inputTokens += m.inputTokens;
|
|
94
|
+
outputTokens += m.outputTokens;
|
|
95
|
+
cacheReadTokens += m.cacheReadTokens;
|
|
96
|
+
cacheCreationTokens += m.cacheCreationTokens;
|
|
97
|
+
llmCallCount++;
|
|
98
|
+
|
|
99
|
+
if (!primaryModel && m.model) {
|
|
100
|
+
primaryModel = m.model;
|
|
101
|
+
primaryProvider = m.provider;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const key = `${m.model}\0${m.provider}`;
|
|
105
|
+
const existing = modelMap.get(key);
|
|
106
|
+
if (existing) {
|
|
107
|
+
modelMap.set(key, {
|
|
108
|
+
...existing,
|
|
109
|
+
estimatedCostUsd: existing.estimatedCostUsd + m.estimatedCostUsd,
|
|
110
|
+
inputTokens: existing.inputTokens + m.inputTokens,
|
|
111
|
+
outputTokens: existing.outputTokens + m.outputTokens,
|
|
112
|
+
cacheCreationTokens: existing.cacheCreationTokens + m.cacheCreationTokens,
|
|
113
|
+
cacheReadTokens: existing.cacheReadTokens + m.cacheReadTokens,
|
|
114
|
+
callCount: existing.callCount + 1,
|
|
115
|
+
});
|
|
116
|
+
} else {
|
|
117
|
+
modelMap.set(key, {
|
|
118
|
+
model: m.model,
|
|
119
|
+
provider: m.provider,
|
|
120
|
+
estimatedCostUsd: m.estimatedCostUsd,
|
|
121
|
+
inputTokens: m.inputTokens,
|
|
122
|
+
outputTokens: m.outputTokens,
|
|
123
|
+
cacheCreationTokens: m.cacheCreationTokens,
|
|
124
|
+
cacheReadTokens: m.cacheReadTokens,
|
|
125
|
+
callCount: 1,
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
for (const execution of executions) {
|
|
131
|
+
for (const msg of execution.status?.messages ?? []) {
|
|
132
|
+
processMessage(msg);
|
|
133
|
+
}
|
|
134
|
+
for (const sub of execution.status?.subAgentExecutions ?? []) {
|
|
135
|
+
for (const msg of sub.messages) {
|
|
136
|
+
processMessage(msg);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const modelBreakdown = Array.from(modelMap.values()).sort(
|
|
142
|
+
(a, b) => b.estimatedCostUsd - a.estimatedCostUsd,
|
|
143
|
+
);
|
|
144
|
+
|
|
145
|
+
return {
|
|
146
|
+
totalCostUsd,
|
|
147
|
+
totalTokens,
|
|
148
|
+
inputTokens,
|
|
149
|
+
outputTokens,
|
|
150
|
+
cacheReadTokens,
|
|
151
|
+
cacheCreationTokens,
|
|
152
|
+
llmCallCount,
|
|
153
|
+
modelBreakdown,
|
|
154
|
+
primaryModel,
|
|
155
|
+
primaryProvider,
|
|
156
|
+
hasUsage: llmCallCount > 0,
|
|
157
|
+
};
|
|
158
|
+
}, [executions]);
|
|
159
|
+
}
|