@tonyclaw/agent-inspector 2.0.28 → 2.0.29
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/.output/nitro.json +1 -1
- package/.output/public/assets/{CompareDrawer-CicCP3Hb.js → CompareDrawer-DcqxlgSQ.js} +1 -1
- package/.output/public/assets/ProxyViewerContainer-D650kQlv.js +115 -0
- package/.output/public/assets/{ReplayDialog-Bc8q3ujm.js → ReplayDialog-CBcnPgx1.js} +1 -1
- package/.output/public/assets/{RequestAnatomy-Coyy3zcH.js → RequestAnatomy-DSgSqCYt.js} +1 -1
- package/.output/public/assets/{ResponseView-BWJzgh0c.js → ResponseView-CjqzBSoF.js} +1 -1
- package/.output/public/assets/{StreamingChunkSequence-BSC3uuE5.js → StreamingChunkSequence-DdBBKolI.js} +1 -1
- package/.output/public/assets/_sessionId-wctOoGh_.js +1 -0
- package/.output/public/assets/index-BhQGSdhG.js +1 -0
- package/.output/public/assets/{index-DsiKfWCp.css → index-CwlHPmgL.css} +1 -1
- package/.output/public/assets/{main-Brj0Gn91.js → main-B6OLZCp9.js} +2 -2
- package/.output/server/_libs/lucide-react.mjs +13 -13
- package/.output/server/{_sessionId-DDdyKVG-.mjs → _sessionId-CCfKJJ19.mjs} +2 -2
- package/.output/server/_ssr/{CompareDrawer-XSExe2ml.mjs → CompareDrawer-uaPI5R6e.mjs} +2 -2
- package/.output/server/_ssr/{ProxyViewerContainer-B5pIiBZN.mjs → ProxyViewerContainer-BV2nIxXy.mjs} +83 -20
- package/.output/server/_ssr/{ReplayDialog-BOAu0ric.mjs → ReplayDialog-eE2Hy2Nl.mjs} +4 -4
- package/.output/server/_ssr/{RequestAnatomy-C8Q5lozD.mjs → RequestAnatomy-B7vwWo57.mjs} +2 -2
- package/.output/server/_ssr/{ResponseView-a_iJfPUF.mjs → ResponseView-Bm6Qp8mo.mjs} +2 -2
- package/.output/server/_ssr/{StreamingChunkSequence-YMKC0j8U.mjs → StreamingChunkSequence-CbAJKJQx.mjs} +2 -2
- package/.output/server/_ssr/{index-CkDwBPzI.mjs → index-u14_Aj60.mjs} +2 -2
- package/.output/server/_ssr/index.mjs +2 -2
- package/.output/server/_ssr/{router-DXOXdFFM.mjs → router-qgeGUp1k.mjs} +161 -18
- package/.output/server/{_tanstack-start-manifest_v-DPf3uJys.mjs → _tanstack-start-manifest_v-BrfUXnre.mjs} +1 -1
- package/.output/server/index.mjs +66 -66
- package/package.json +1 -1
- package/src/components/ProxyViewer.tsx +3 -0
- package/src/components/providers/ProviderCard.tsx +32 -0
- package/src/components/proxy-viewer/LogEntryHeader.tsx +38 -1
- package/src/lib/providerTestContract.ts +3 -0
- package/src/lib/sessionInfoContract.ts +3 -0
- package/src/mcp/toolHandlers.ts +3 -0
- package/src/proxy/evidenceAnalysis.ts +5 -0
- package/src/proxy/evidenceExporter.ts +8 -3
- package/src/proxy/handler.ts +8 -1
- package/src/proxy/logFinalizer.ts +36 -0
- package/src/proxy/schemas.ts +3 -0
- package/src/proxy/sessionInfo.ts +3 -0
- package/src/proxy/store.ts +3 -0
- package/src/proxy/streamTiming.ts +31 -0
- package/src/routes/api/logs.$id.replay.ts +25 -2
- package/src/routes/api/providers.$providerId.test.log.ts +34 -2
- package/.output/public/assets/ProxyViewerContainer-BccuA6p5.js +0 -115
- package/.output/public/assets/_sessionId-9rEF0uSE.js +0 -1
- package/.output/public/assets/index-B9_VaAWl.js +0 -1
|
@@ -21,6 +21,7 @@ import {
|
|
|
21
21
|
selectUpstreamBase,
|
|
22
22
|
setUpstreamHost,
|
|
23
23
|
} from "../../proxy/upstream";
|
|
24
|
+
import { computeTokensPerSecond } from "../../proxy/streamTiming";
|
|
24
25
|
|
|
25
26
|
type ReplayRequest = {
|
|
26
27
|
modifiedBody: string;
|
|
@@ -38,6 +39,9 @@ type ReplayResponse = {
|
|
|
38
39
|
inputTokens?: number;
|
|
39
40
|
outputTokens?: number;
|
|
40
41
|
elapsedMs?: number;
|
|
42
|
+
firstChunkMs?: number | null;
|
|
43
|
+
totalStreamMs?: number | null;
|
|
44
|
+
tokensPerSecond?: number | null;
|
|
41
45
|
streaming?: boolean;
|
|
42
46
|
replayLogId?: number;
|
|
43
47
|
};
|
|
@@ -135,7 +139,6 @@ export const Route = createFileRoute("/api/logs/$id/replay")({
|
|
|
135
139
|
} satisfies ReplayResponse);
|
|
136
140
|
}
|
|
137
141
|
|
|
138
|
-
const elapsedMs = Date.now() - startTime;
|
|
139
142
|
const isStream =
|
|
140
143
|
upstreamRes.headers.get(HEADER_CONTENT_TYPE)?.includes(CONTENT_TYPE_EVENT_STREAM) ??
|
|
141
144
|
false;
|
|
@@ -145,11 +148,13 @@ export const Route = createFileRoute("/api/logs/$id/replay")({
|
|
|
145
148
|
const chunks: string[] = [];
|
|
146
149
|
const decoder = new TextDecoder();
|
|
147
150
|
const reader = upstreamRes.body?.getReader();
|
|
151
|
+
let firstChunkMs: number | null = null;
|
|
148
152
|
if (reader) {
|
|
149
153
|
try {
|
|
150
154
|
while (true) {
|
|
151
155
|
const { done, value } = await reader.read();
|
|
152
156
|
if (done) break;
|
|
157
|
+
if (firstChunkMs === null) firstChunkMs = Date.now() - startTime;
|
|
153
158
|
chunks.push(decoder.decode(value, { stream: true }));
|
|
154
159
|
}
|
|
155
160
|
} catch {
|
|
@@ -157,11 +162,19 @@ export const Route = createFileRoute("/api/logs/$id/replay")({
|
|
|
157
162
|
}
|
|
158
163
|
}
|
|
159
164
|
const fullResponse = chunks.join("");
|
|
165
|
+
const elapsedMs = Date.now() - startTime;
|
|
166
|
+
const totalStreamMs = elapsedMs;
|
|
160
167
|
|
|
161
168
|
// Create a mock log for streaming extraction
|
|
162
169
|
const mockLog: typeof log = { ...log };
|
|
163
170
|
const responseText = formatHandler.extractStream(fullResponse, mockLog, model, false);
|
|
164
171
|
const tokens = formatHandler.extractTokens(responseText);
|
|
172
|
+
const outputTokens = tokens.outputTokens ?? null;
|
|
173
|
+
const tokensPerSecond = computeTokensPerSecond({
|
|
174
|
+
outputTokens,
|
|
175
|
+
firstChunkMs,
|
|
176
|
+
totalStreamMs,
|
|
177
|
+
});
|
|
165
178
|
const savedReplayLog = await addTestLogEntry({
|
|
166
179
|
timestamp: new Date().toISOString(),
|
|
167
180
|
method: log.method,
|
|
@@ -172,10 +185,13 @@ export const Route = createFileRoute("/api/logs/$id/replay")({
|
|
|
172
185
|
responseStatus: upstreamRes.status,
|
|
173
186
|
responseText,
|
|
174
187
|
inputTokens: tokens.inputTokens ?? null,
|
|
175
|
-
outputTokens
|
|
188
|
+
outputTokens,
|
|
176
189
|
cacheCreationInputTokens: tokens.cacheCreationInputTokens ?? null,
|
|
177
190
|
cacheReadInputTokens: tokens.cacheReadInputTokens ?? null,
|
|
178
191
|
elapsedMs,
|
|
192
|
+
firstChunkMs,
|
|
193
|
+
totalStreamMs,
|
|
194
|
+
tokensPerSecond,
|
|
179
195
|
streaming: true,
|
|
180
196
|
userAgent: log.userAgent,
|
|
181
197
|
origin: log.origin,
|
|
@@ -201,11 +217,15 @@ export const Route = createFileRoute("/api/logs/$id/replay")({
|
|
|
201
217
|
inputTokens: tokens.inputTokens ?? undefined,
|
|
202
218
|
outputTokens: tokens.outputTokens ?? undefined,
|
|
203
219
|
elapsedMs,
|
|
220
|
+
firstChunkMs,
|
|
221
|
+
totalStreamMs,
|
|
222
|
+
tokensPerSecond,
|
|
204
223
|
streaming: true,
|
|
205
224
|
replayLogId: savedReplayLog.id,
|
|
206
225
|
} satisfies ReplayResponse);
|
|
207
226
|
} else {
|
|
208
227
|
const responseText = await upstreamRes.text();
|
|
228
|
+
const elapsedMs = Date.now() - startTime;
|
|
209
229
|
const tokens = formatHandler.extractTokens(responseText);
|
|
210
230
|
const savedReplayLog = await addTestLogEntry({
|
|
211
231
|
timestamp: new Date().toISOString(),
|
|
@@ -221,6 +241,9 @@ export const Route = createFileRoute("/api/logs/$id/replay")({
|
|
|
221
241
|
cacheCreationInputTokens: tokens.cacheCreationInputTokens ?? null,
|
|
222
242
|
cacheReadInputTokens: tokens.cacheReadInputTokens ?? null,
|
|
223
243
|
elapsedMs,
|
|
244
|
+
firstChunkMs: null,
|
|
245
|
+
totalStreamMs: null,
|
|
246
|
+
tokensPerSecond: null,
|
|
224
247
|
streaming: false,
|
|
225
248
|
userAgent: log.userAgent,
|
|
226
249
|
origin: log.origin,
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
type ProviderTestResult as TestResult,
|
|
9
9
|
type ProviderTestState,
|
|
10
10
|
} from "../../lib/providerTestContract";
|
|
11
|
+
import { computeTokensPerSecond, firstChunkMsFromChunks } from "../../proxy/streamTiming";
|
|
11
12
|
|
|
12
13
|
function hasSuccessField(result: ProviderTestState): result is TestResult {
|
|
13
14
|
return Object.prototype.hasOwnProperty.call(result, "success");
|
|
@@ -29,6 +30,25 @@ function getResultHeaders(result: TestResult): Record<string, string> {
|
|
|
29
30
|
return result.requestHeaders ?? result.debug?.requestHeaders ?? {};
|
|
30
31
|
}
|
|
31
32
|
|
|
33
|
+
function getResultTotalStreamMs(result: TestResult): number | null {
|
|
34
|
+
return result.totalStreamMs ?? (result.streaming === true ? (result.latencyMs ?? null) : null);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function getResultFirstChunkMs(result: TestResult): number | null {
|
|
38
|
+
return result.firstChunkMs ?? firstChunkMsFromChunks(result.streamingChunks?.chunks);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function getResultTokensPerSecond(result: TestResult): number | null {
|
|
42
|
+
return (
|
|
43
|
+
result.tokensPerSecond ??
|
|
44
|
+
computeTokensPerSecond({
|
|
45
|
+
outputTokens: result.outputTokens,
|
|
46
|
+
firstChunkMs: getResultFirstChunkMs(result),
|
|
47
|
+
totalStreamMs: getResultTotalStreamMs(result),
|
|
48
|
+
})
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
32
52
|
async function logModelResults(
|
|
33
53
|
displayName: string,
|
|
34
54
|
providerName: string,
|
|
@@ -65,6 +85,9 @@ async function logModelResults(
|
|
|
65
85
|
cacheCreationInputTokens: nonStreamingResult.cacheCreationInputTokens ?? null,
|
|
66
86
|
cacheReadInputTokens: nonStreamingResult.cacheReadInputTokens ?? null,
|
|
67
87
|
elapsedMs: nonStreamingResult.latencyMs ?? 0,
|
|
88
|
+
firstChunkMs: null,
|
|
89
|
+
totalStreamMs: null,
|
|
90
|
+
tokensPerSecond: null,
|
|
68
91
|
streaming: false,
|
|
69
92
|
userAgent: "provider-test",
|
|
70
93
|
origin: null,
|
|
@@ -91,7 +114,10 @@ async function logModelResults(
|
|
|
91
114
|
outputTokens: streamingResult.outputTokens ?? null,
|
|
92
115
|
cacheCreationInputTokens: streamingResult.cacheCreationInputTokens ?? null,
|
|
93
116
|
cacheReadInputTokens: streamingResult.cacheReadInputTokens ?? null,
|
|
94
|
-
elapsedMs: streamingResult
|
|
117
|
+
elapsedMs: getResultTotalStreamMs(streamingResult) ?? 0,
|
|
118
|
+
firstChunkMs: getResultFirstChunkMs(streamingResult),
|
|
119
|
+
totalStreamMs: getResultTotalStreamMs(streamingResult),
|
|
120
|
+
tokensPerSecond: getResultTokensPerSecond(streamingResult),
|
|
95
121
|
streaming: true,
|
|
96
122
|
streamingChunks: captureFullDetails ? streamingResult.streamingChunks : undefined,
|
|
97
123
|
userAgent: "provider-test",
|
|
@@ -127,6 +153,9 @@ async function logModelResults(
|
|
|
127
153
|
cacheCreationInputTokens: null,
|
|
128
154
|
cacheReadInputTokens: null,
|
|
129
155
|
elapsedMs: nonStreamingResult.latencyMs ?? 0,
|
|
156
|
+
firstChunkMs: null,
|
|
157
|
+
totalStreamMs: null,
|
|
158
|
+
tokensPerSecond: null,
|
|
130
159
|
streaming: false,
|
|
131
160
|
userAgent: "provider-test",
|
|
132
161
|
origin: null,
|
|
@@ -153,7 +182,10 @@ async function logModelResults(
|
|
|
153
182
|
outputTokens: streamingResult.outputTokens ?? null,
|
|
154
183
|
cacheCreationInputTokens: null,
|
|
155
184
|
cacheReadInputTokens: null,
|
|
156
|
-
elapsedMs: streamingResult
|
|
185
|
+
elapsedMs: getResultTotalStreamMs(streamingResult) ?? 0,
|
|
186
|
+
firstChunkMs: getResultFirstChunkMs(streamingResult),
|
|
187
|
+
totalStreamMs: getResultTotalStreamMs(streamingResult),
|
|
188
|
+
tokensPerSecond: getResultTokensPerSecond(streamingResult),
|
|
157
189
|
streaming: true,
|
|
158
190
|
streamingChunks: captureFullDetails ? streamingResult.streamingChunks : undefined,
|
|
159
191
|
userAgent: "provider-test",
|