@tonyclaw/agent-inspector 2.0.27 → 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/cli.js +169 -13
- package/.output/nitro.json +1 -1
- package/.output/public/assets/{CompareDrawer-B_p6vmMQ.js → CompareDrawer-DcqxlgSQ.js} +1 -1
- package/.output/public/assets/ProxyViewerContainer-D650kQlv.js +115 -0
- package/.output/public/assets/{ReplayDialog-BmprJ6D3.js → ReplayDialog-CBcnPgx1.js} +1 -1
- package/.output/public/assets/{RequestAnatomy-DqO0_SVJ.js → RequestAnatomy-DSgSqCYt.js} +1 -1
- package/.output/public/assets/{ResponseView-FZbPNdHa.js → ResponseView-CjqzBSoF.js} +1 -1
- package/.output/public/assets/{StreamingChunkSequence-BZPzfJWj.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-CzItFZlM.js → main-B6OLZCp9.js} +2 -2
- package/.output/server/_libs/lucide-react.mjs +13 -13
- package/.output/server/{_sessionId-DZH8SrEZ.mjs → _sessionId-CCfKJJ19.mjs} +2 -2
- package/.output/server/_ssr/{CompareDrawer-L0aE1UV1.mjs → CompareDrawer-uaPI5R6e.mjs} +2 -2
- package/.output/server/_ssr/{ProxyViewerContainer-B62RB9ER.mjs → ProxyViewerContainer-BV2nIxXy.mjs} +83 -20
- package/.output/server/_ssr/{ReplayDialog-FVWnpx2C.mjs → ReplayDialog-eE2Hy2Nl.mjs} +4 -4
- package/.output/server/_ssr/{RequestAnatomy-DIyqW-Ny.mjs → RequestAnatomy-B7vwWo57.mjs} +2 -2
- package/.output/server/_ssr/{ResponseView-BX4mxEZ5.mjs → ResponseView-Bm6Qp8mo.mjs} +2 -2
- package/.output/server/_ssr/{StreamingChunkSequence-Cs3nzOor.mjs → StreamingChunkSequence-CbAJKJQx.mjs} +2 -2
- package/.output/server/_ssr/{index-Dik2Mc3h.mjs → index-u14_Aj60.mjs} +2 -2
- package/.output/server/_ssr/index.mjs +2 -2
- package/.output/server/_ssr/{router-DCPg8ykx.mjs → router-qgeGUp1k.mjs} +161 -18
- package/.output/server/{_tanstack-start-manifest_v-BaoL3JCh.mjs → _tanstack-start-manifest_v-BrfUXnre.mjs} +1 -1
- package/.output/server/index.mjs +59 -59
- package/package.json +1 -1
- package/src/cli/networkHints.ts +150 -0
- package/src/cli.ts +72 -13
- 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-DItqh1EO.js +0 -115
- package/.output/public/assets/_sessionId-y2ATIp51.js +0 -1
- package/.output/public/assets/index-CQT4higx.js +0 -1
|
@@ -50,7 +50,7 @@ import "../_libs/mimic-function.mjs";
|
|
|
50
50
|
import "../_libs/semver.mjs";
|
|
51
51
|
import "../_libs/uint8array-extras.mjs";
|
|
52
52
|
const faviconSvg = "data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2064%2064'%20role='img'%20aria-label='Agent%20Inspector'%3e%3crect%20width='64'%20height='64'%20rx='14'%20fill='%23111827'%20/%3e%3cg%20fill='none'%20stroke='%23f59e0b'%20stroke-width='4.2'%20stroke-linecap='round'%20stroke-linejoin='round'%3e%3cpath%20fill='%23f59e0b'%20d='M15%2036c0-11%207-18%2017-18s17%207%2017%2018c0%208-7%2013-17%2013s-17-5-17-13z'%20/%3e%3cpath%20d='M16%2031c-6-5-12-3-12%204%200%205%206%206%2011%202'%20/%3e%3cpath%20d='M48%2031c6-5%2012-3%2012%204%200%205-6%206-11%202'%20/%3e%3cpath%20d='M27%2019l-3-7'%20/%3e%3cpath%20d='M37%2019l3-7'%20/%3e%3cpath%20d='M19%2045l-6%209'%20/%3e%3cpath%20d='M27%2048l-3%209'%20/%3e%3cpath%20d='M37%2048l3%209'%20/%3e%3cpath%20d='M45%2045l6%209'%20/%3e%3c/g%3e%3cpath%20d='M14%2047l9-8%208%209c-5%203.5-12%203-17-1z'%20fill='%232f6b3f'%20opacity='.95'%20/%3e%3cpath%20d='M18%2046l5-5%205%206c-3%201.6-7%201.4-10-1z'%20fill='%236fb36f'%20opacity='.95'%20/%3e%3cpath%20d='M23%2041v10'%20fill='none'%20stroke='%23d6b45f'%20stroke-width='1.6'%20stroke-linecap='round'%20/%3e%3ccircle%20cx='31'%20cy='48'%20r='1.8'%20fill='%23c2412d'%20/%3e%3cpath%20d='M24%2044l13-11%2014%2013c-8%205.8-18%205.3-27-2z'%20fill='%232f6b3f'%20opacity='.97'%20/%3e%3cpath%20d='M30%2043l7-7%209%209c-5%202.7-11%202.5-16-2z'%20fill='%236fb36f'%20opacity='.95'%20/%3e%3cpath%20d='M37%2036v14'%20fill='none'%20stroke='%23d6b45f'%20stroke-width='2'%20stroke-linecap='round'%20/%3e%3cpath%20d='M30%2043c5-2%2011-1.5%2016%202'%20fill='none'%20stroke='%239fca78'%20stroke-width='1.8'%20stroke-linecap='round'%20/%3e%3ccircle%20cx='51'%20cy='46'%20r='2'%20fill='%23c2412d'%20/%3e%3cpath%20d='M40%2050l8-8%207%208c-4.2%203.2-10%203-15%200z'%20fill='%232f6b3f'%20opacity='.95'%20/%3e%3cpath%20d='M43%2049l5-5%204.5%205.5c-3%201.5-6%201.2-9.5-.5z'%20fill='%236fb36f'%20opacity='.95'%20/%3e%3cpath%20d='M48%2044v9'%20fill='none'%20stroke='%23d6b45f'%20stroke-width='1.5'%20stroke-linecap='round'%20/%3e%3ccircle%20cx='55'%20cy='50'%20r='1.7'%20fill='%23c2412d'%20/%3e%3ccircle%20cx='24'%20cy='11'%20r='3.2'%20fill='%23f59e0b'%20/%3e%3ccircle%20cx='40'%20cy='11'%20r='3.2'%20fill='%23f59e0b'%20/%3e%3ccircle%20cx='25'%20cy='34'%20r='2.1'%20fill='%23111827'%20/%3e%3ccircle%20cx='39'%20cy='34'%20r='2.1'%20fill='%23111827'%20/%3e%3c/svg%3e";
|
|
53
|
-
const appCss = "/assets/index-
|
|
53
|
+
const appCss = "/assets/index-CwlHPmgL.css";
|
|
54
54
|
const Route$v = createRootRoute({
|
|
55
55
|
head: () => ({
|
|
56
56
|
meta: [
|
|
@@ -93,7 +93,7 @@ function RootDocument({ children }) {
|
|
|
93
93
|
] })
|
|
94
94
|
] });
|
|
95
95
|
}
|
|
96
|
-
const $$splitComponentImporter$1 = () => import("./index-
|
|
96
|
+
const $$splitComponentImporter$1 = () => import("./index-u14_Aj60.mjs");
|
|
97
97
|
const Route$u = createFileRoute("/")({
|
|
98
98
|
component: lazyRouteComponent($$splitComponentImporter$1, "component")
|
|
99
99
|
});
|
|
@@ -136,7 +136,7 @@ function decodeSessionIdFromPath(encoded) {
|
|
|
136
136
|
function getSessionPath(sessionId) {
|
|
137
137
|
return `/session/${encodeSessionIdForPath(sessionId)}`;
|
|
138
138
|
}
|
|
139
|
-
const $$splitComponentImporter = () => import("../_sessionId-
|
|
139
|
+
const $$splitComponentImporter = () => import("../_sessionId-CCfKJJ19.mjs");
|
|
140
140
|
const Route$t = createFileRoute("/session/$sessionId")({
|
|
141
141
|
component: lazyRouteComponent($$splitComponentImporter, "component"),
|
|
142
142
|
parseParams: (params) => ({
|
|
@@ -713,6 +713,9 @@ const CapturedLogSchema = object({
|
|
|
713
713
|
cacheCreationInputTokens: number().nullable(),
|
|
714
714
|
cacheReadInputTokens: number().nullable(),
|
|
715
715
|
elapsedMs: number().nullable(),
|
|
716
|
+
firstChunkMs: number().nullable().optional(),
|
|
717
|
+
totalStreamMs: number().nullable().optional(),
|
|
718
|
+
tokensPerSecond: number().nullable().optional(),
|
|
716
719
|
streaming: boolean(),
|
|
717
720
|
userAgent: string().nullable(),
|
|
718
721
|
origin: string().nullable(),
|
|
@@ -1066,6 +1069,9 @@ function buildSessionLogSummary(log) {
|
|
|
1066
1069
|
hasError: hasLogError(log),
|
|
1067
1070
|
error: truncateError(log.error),
|
|
1068
1071
|
latencyMs: log.elapsedMs,
|
|
1072
|
+
firstChunkMs: log.firstChunkMs ?? null,
|
|
1073
|
+
totalStreamMs: log.totalStreamMs ?? null,
|
|
1074
|
+
tokensPerSecond: log.tokensPerSecond ?? null,
|
|
1069
1075
|
tokens: {
|
|
1070
1076
|
input: log.inputTokens,
|
|
1071
1077
|
output: log.outputTokens,
|
|
@@ -1602,6 +1608,9 @@ async function createLog(method, path2, requestBody, headers, clientInfo, rawHea
|
|
|
1602
1608
|
cacheCreationInputTokens: null,
|
|
1603
1609
|
cacheReadInputTokens: null,
|
|
1604
1610
|
elapsedMs: null,
|
|
1611
|
+
firstChunkMs: null,
|
|
1612
|
+
totalStreamMs: null,
|
|
1613
|
+
tokensPerSecond: null,
|
|
1605
1614
|
streaming: false,
|
|
1606
1615
|
userAgent,
|
|
1607
1616
|
origin,
|
|
@@ -4145,6 +4154,23 @@ function stripOpenAIOrphanToolMessages(rawBody) {
|
|
|
4145
4154
|
parsed.messages = kept;
|
|
4146
4155
|
return { body: JSON.stringify(parsed), removed: indices.length, orphanIds };
|
|
4147
4156
|
}
|
|
4157
|
+
function computeTokensPerSecond({
|
|
4158
|
+
outputTokens,
|
|
4159
|
+
firstChunkMs,
|
|
4160
|
+
totalStreamMs
|
|
4161
|
+
}) {
|
|
4162
|
+
if (outputTokens === null || outputTokens === void 0 || outputTokens <= 0) return null;
|
|
4163
|
+
if (totalStreamMs === null || totalStreamMs === void 0 || totalStreamMs <= 0) return null;
|
|
4164
|
+
const generationMs = firstChunkMs === null || firstChunkMs === void 0 ? totalStreamMs : totalStreamMs - firstChunkMs;
|
|
4165
|
+
if (!Number.isFinite(generationMs) || generationMs <= 0) return null;
|
|
4166
|
+
return Number((outputTokens / (generationMs / 1e3)).toFixed(2));
|
|
4167
|
+
}
|
|
4168
|
+
function firstChunkMsFromChunks(chunks) {
|
|
4169
|
+
const first = chunks?.[0];
|
|
4170
|
+
if (first === void 0) return null;
|
|
4171
|
+
if (!Number.isFinite(first.timestamp) || first.timestamp < 0) return null;
|
|
4172
|
+
return Math.floor(first.timestamp);
|
|
4173
|
+
}
|
|
4148
4174
|
const DEFAULT_MAX_FINALIZE_STREAM_BYTES = 20 * 1024 * 1024;
|
|
4149
4175
|
function resolveMaxFinalizeStreamBytes() {
|
|
4150
4176
|
const raw = process.env["AGENT_INSPECTOR_MAX_FINALIZE_STREAM_BYTES"];
|
|
@@ -4169,6 +4195,9 @@ function buildFileLogEntry(log, upstreamUrl) {
|
|
|
4169
4195
|
cacheCreationInputTokens: log.cacheCreationInputTokens,
|
|
4170
4196
|
cacheReadInputTokens: log.cacheReadInputTokens,
|
|
4171
4197
|
elapsedMs: log.elapsedMs,
|
|
4198
|
+
firstChunkMs: log.firstChunkMs,
|
|
4199
|
+
totalStreamMs: log.totalStreamMs,
|
|
4200
|
+
tokensPerSecond: log.tokensPerSecond,
|
|
4172
4201
|
streaming: log.streaming,
|
|
4173
4202
|
userAgent: log.userAgent,
|
|
4174
4203
|
origin: log.origin,
|
|
@@ -4204,9 +4233,29 @@ function finalizeWithError(job, log, fallbackStatus, fallbackResponseText, err,
|
|
|
4204
4233
|
log.responseStatus = log.responseStatus ?? fallbackStatus;
|
|
4205
4234
|
log.responseText = log.responseText ?? fallbackResponseText;
|
|
4206
4235
|
log.elapsedMs = job.elapsedMs;
|
|
4236
|
+
applyOptionalStreamingTiming(log, job);
|
|
4207
4237
|
log.error = message;
|
|
4208
4238
|
return { log, upstreamUrl: job.upstreamUrl, error: message, cleanupRawStreamPath };
|
|
4209
4239
|
}
|
|
4240
|
+
function applyOptionalStreamingTiming(log, job) {
|
|
4241
|
+
switch (job.type) {
|
|
4242
|
+
case "non-streaming":
|
|
4243
|
+
log.firstChunkMs = null;
|
|
4244
|
+
log.totalStreamMs = null;
|
|
4245
|
+
log.tokensPerSecond = null;
|
|
4246
|
+
return;
|
|
4247
|
+
case "streaming":
|
|
4248
|
+
case "stream-abort":
|
|
4249
|
+
log.firstChunkMs = job.firstChunkMs;
|
|
4250
|
+
log.totalStreamMs = job.totalStreamMs;
|
|
4251
|
+
log.tokensPerSecond = computeTokensPerSecond({
|
|
4252
|
+
outputTokens: log.outputTokens,
|
|
4253
|
+
firstChunkMs: job.firstChunkMs,
|
|
4254
|
+
totalStreamMs: job.totalStreamMs
|
|
4255
|
+
});
|
|
4256
|
+
return;
|
|
4257
|
+
}
|
|
4258
|
+
}
|
|
4210
4259
|
function finalizeNonStreaming(job, log) {
|
|
4211
4260
|
const formatHandler = formatForPath(log.path);
|
|
4212
4261
|
if (formatHandler === null) {
|
|
@@ -4215,6 +4264,9 @@ function finalizeNonStreaming(job, log) {
|
|
|
4215
4264
|
try {
|
|
4216
4265
|
const tokens = formatHandler.extractTokens(job.responseBody);
|
|
4217
4266
|
log.elapsedMs = job.elapsedMs;
|
|
4267
|
+
log.firstChunkMs = null;
|
|
4268
|
+
log.totalStreamMs = null;
|
|
4269
|
+
log.tokensPerSecond = null;
|
|
4218
4270
|
log.responseStatus = job.responseStatus;
|
|
4219
4271
|
log.responseText = job.responseBody;
|
|
4220
4272
|
log.inputTokens = tokens.inputTokens;
|
|
@@ -4295,6 +4347,7 @@ function finalizeStreaming(job, log) {
|
|
|
4295
4347
|
const oversized = getOversizedRawStream(job.rawStream);
|
|
4296
4348
|
if (oversized !== null) {
|
|
4297
4349
|
log.elapsedMs = job.elapsedMs;
|
|
4350
|
+
applyOptionalStreamingTiming(log, job);
|
|
4298
4351
|
log.responseStatus = job.responseStatus;
|
|
4299
4352
|
log.responseText = oversizedRawStreamText(oversized);
|
|
4300
4353
|
return {
|
|
@@ -4318,6 +4371,7 @@ function finalizeStreaming(job, log) {
|
|
|
4318
4371
|
log.model ?? void 0,
|
|
4319
4372
|
job.collectStreamingChunks
|
|
4320
4373
|
);
|
|
4374
|
+
applyOptionalStreamingTiming(log, job);
|
|
4321
4375
|
persistStreamingChunks(log);
|
|
4322
4376
|
return { log, upstreamUrl: job.upstreamUrl, error: null, cleanupRawStreamPath };
|
|
4323
4377
|
} catch (err) {
|
|
@@ -4347,6 +4401,7 @@ function finalizeStreamAbort(job, log) {
|
|
|
4347
4401
|
let cleanupRawStreamPath = null;
|
|
4348
4402
|
try {
|
|
4349
4403
|
log.elapsedMs = job.elapsedMs;
|
|
4404
|
+
applyOptionalStreamingTiming(log, job);
|
|
4350
4405
|
if (job.hasChunks && formatHandler !== null) {
|
|
4351
4406
|
const oversized = getOversizedRawStream(job.rawStream);
|
|
4352
4407
|
if (oversized !== null) {
|
|
@@ -4367,6 +4422,7 @@ function finalizeStreamAbort(job, log) {
|
|
|
4367
4422
|
log.model ?? void 0,
|
|
4368
4423
|
job.collectStreamingChunks
|
|
4369
4424
|
);
|
|
4425
|
+
applyOptionalStreamingTiming(log, job);
|
|
4370
4426
|
persistStreamingChunks(log);
|
|
4371
4427
|
} else {
|
|
4372
4428
|
log.responseText = "Client aborted";
|
|
@@ -4713,10 +4769,12 @@ function handleStreamingResponse(upstreamRes, req, startTime, upstreamUrl, log,
|
|
|
4713
4769
|
const capture = new RawStreamCapture();
|
|
4714
4770
|
const decoder = new TextDecoder();
|
|
4715
4771
|
let finalizationScheduled = false;
|
|
4772
|
+
let firstChunkMs = null;
|
|
4716
4773
|
const scheduleStreamingFinalization = (type) => {
|
|
4717
4774
|
if (finalizationScheduled) return;
|
|
4718
4775
|
finalizationScheduled = true;
|
|
4719
|
-
const
|
|
4776
|
+
const totalStreamMs = Date.now() - startTime;
|
|
4777
|
+
const elapsedMs = totalStreamMs;
|
|
4720
4778
|
const rawStream = capture.snapshot();
|
|
4721
4779
|
switch (type) {
|
|
4722
4780
|
case "streaming":
|
|
@@ -4727,7 +4785,9 @@ function handleStreamingResponse(upstreamRes, req, startTime, upstreamUrl, log,
|
|
|
4727
4785
|
elapsedMs,
|
|
4728
4786
|
responseStatus: upstreamRes.status,
|
|
4729
4787
|
rawStream,
|
|
4730
|
-
collectStreamingChunks
|
|
4788
|
+
collectStreamingChunks,
|
|
4789
|
+
firstChunkMs,
|
|
4790
|
+
totalStreamMs
|
|
4731
4791
|
});
|
|
4732
4792
|
return;
|
|
4733
4793
|
case "stream-abort":
|
|
@@ -4738,13 +4798,16 @@ function handleStreamingResponse(upstreamRes, req, startTime, upstreamUrl, log,
|
|
|
4738
4798
|
elapsedMs,
|
|
4739
4799
|
rawStream,
|
|
4740
4800
|
hasChunks: capture.hasChunks,
|
|
4741
|
-
collectStreamingChunks
|
|
4801
|
+
collectStreamingChunks,
|
|
4802
|
+
firstChunkMs,
|
|
4803
|
+
totalStreamMs
|
|
4742
4804
|
});
|
|
4743
4805
|
return;
|
|
4744
4806
|
}
|
|
4745
4807
|
};
|
|
4746
4808
|
const transform = new TransformStream({
|
|
4747
4809
|
async transform(chunk, controller) {
|
|
4810
|
+
if (firstChunkMs === null) firstChunkMs = Date.now() - startTime;
|
|
4748
4811
|
controller.enqueue(chunk);
|
|
4749
4812
|
await capture.append(decoder.decode(chunk, { stream: true }));
|
|
4750
4813
|
},
|
|
@@ -4942,6 +5005,9 @@ const SessionLogSummarySchema = object({
|
|
|
4942
5005
|
hasError: boolean(),
|
|
4943
5006
|
error: string().nullable(),
|
|
4944
5007
|
latencyMs: number().nullable(),
|
|
5008
|
+
firstChunkMs: number().nullable().optional(),
|
|
5009
|
+
totalStreamMs: number().nullable().optional(),
|
|
5010
|
+
tokensPerSecond: number().nullable().optional(),
|
|
4945
5011
|
tokens: object({
|
|
4946
5012
|
input: number().nullable(),
|
|
4947
5013
|
output: number().nullable(),
|
|
@@ -5616,6 +5682,9 @@ function buildLogSummary(log) {
|
|
|
5616
5682
|
isStreaming: log.streaming,
|
|
5617
5683
|
hasError,
|
|
5618
5684
|
latencyMs: log.elapsedMs,
|
|
5685
|
+
firstChunkMs: log.firstChunkMs ?? null,
|
|
5686
|
+
totalStreamMs: log.totalStreamMs ?? null,
|
|
5687
|
+
tokensPerSecond: log.tokensPerSecond ?? null,
|
|
5619
5688
|
tokens: {
|
|
5620
5689
|
input: log.inputTokens,
|
|
5621
5690
|
output: log.outputTokens,
|
|
@@ -8391,6 +8460,11 @@ function logDetails(log) {
|
|
|
8391
8460
|
`streaming=${log.isStreaming ? "yes" : "no"}`,
|
|
8392
8461
|
`latencyMs=${formatNullable(log.latencyMs)}`
|
|
8393
8462
|
];
|
|
8463
|
+
if (log.isStreaming) {
|
|
8464
|
+
parts.push(`firstChunkMs=${formatNullable(log.firstChunkMs ?? null)}`);
|
|
8465
|
+
parts.push(`totalStreamMs=${formatNullable(log.totalStreamMs ?? null)}`);
|
|
8466
|
+
parts.push(`tokensPerSecond=${formatNullable(log.tokensPerSecond ?? null)}`);
|
|
8467
|
+
}
|
|
8394
8468
|
if (log.error !== null) {
|
|
8395
8469
|
parts.push(`error=${log.error}`);
|
|
8396
8470
|
}
|
|
@@ -8643,12 +8717,13 @@ function buildMarkdown(document) {
|
|
|
8643
8717
|
lines.push("No compact logs were available.", "");
|
|
8644
8718
|
} else {
|
|
8645
8719
|
lines.push(
|
|
8646
|
-
"| ID | Status | Model | Latency | Path | Error |",
|
|
8647
|
-
"| --- | --- | --- | --- | --- | --- |"
|
|
8720
|
+
"| ID | Status | Model | Latency | Stream | Path | Error |",
|
|
8721
|
+
"| --- | --- | --- | --- | --- | --- | --- |"
|
|
8648
8722
|
);
|
|
8649
8723
|
for (const log of session.latestLogs) {
|
|
8724
|
+
const streamTiming = log.isStreaming ? `first=${log.firstChunkMs ?? "n/a"}ms total=${log.totalStreamMs ?? "n/a"}ms tps=${log.tokensPerSecond ?? "n/a"}` : "n/a";
|
|
8650
8725
|
lines.push(
|
|
8651
|
-
`| ${log.id} | ${log.status ?? "n/a"} | ${log.model ?? "n/a"} | ${log.latencyMs ?? "n/a"} | ${log.path} | ${log.hasError ? "yes" : "no"} |`
|
|
8726
|
+
`| ${log.id} | ${log.status ?? "n/a"} | ${log.model ?? "n/a"} | ${log.latencyMs ?? "n/a"} | ${streamTiming} | ${log.path} | ${log.hasError ? "yes" : "no"} |`
|
|
8652
8727
|
);
|
|
8653
8728
|
}
|
|
8654
8729
|
lines.push("");
|
|
@@ -8998,7 +9073,7 @@ async function readResponseText(response) {
|
|
|
8998
9073
|
return `Failed to read response body: ${String(err)}`;
|
|
8999
9074
|
}
|
|
9000
9075
|
}
|
|
9001
|
-
function createErrorResult(error, latencyMs, streaming, responseStatus, debug) {
|
|
9076
|
+
function createErrorResult(error, latencyMs, streaming, responseStatus, debug, streamTiming) {
|
|
9002
9077
|
const { type, details } = classifyError(error, responseStatus);
|
|
9003
9078
|
const result = {
|
|
9004
9079
|
success: false,
|
|
@@ -9011,6 +9086,11 @@ function createErrorResult(error, latencyMs, streaming, responseStatus, debug) {
|
|
|
9011
9086
|
latencyMs,
|
|
9012
9087
|
streaming
|
|
9013
9088
|
};
|
|
9089
|
+
if (streamTiming !== void 0) {
|
|
9090
|
+
result.firstChunkMs = streamTiming.firstChunkMs;
|
|
9091
|
+
result.totalStreamMs = streamTiming.totalStreamMs;
|
|
9092
|
+
result.tokensPerSecond = streamTiming.tokensPerSecond;
|
|
9093
|
+
}
|
|
9014
9094
|
if (debug !== void 0) {
|
|
9015
9095
|
result.debug = debug;
|
|
9016
9096
|
if (debug.requestHeaders !== void 0) {
|
|
@@ -9232,14 +9312,17 @@ async function testStreamingEndpoint(baseUrl, provider, path2, model, isOpenAI)
|
|
|
9232
9312
|
const decoder = new TextDecoder();
|
|
9233
9313
|
const MAX_CHUNKS_SIZE = 10 * 1024 * 1024;
|
|
9234
9314
|
let totalSize = 0;
|
|
9315
|
+
let firstChunkMs = null;
|
|
9235
9316
|
try {
|
|
9236
9317
|
while (true) {
|
|
9237
9318
|
const { done, value } = await reader.read();
|
|
9238
9319
|
if (done) break;
|
|
9320
|
+
if (firstChunkMs === null) firstChunkMs = Date.now() - startTime;
|
|
9239
9321
|
if (totalSize >= MAX_CHUNKS_SIZE) {
|
|
9322
|
+
const totalStreamMs2 = Date.now() - startTime;
|
|
9240
9323
|
return createErrorResult(
|
|
9241
9324
|
"Response too large (exceeded 10MB limit)",
|
|
9242
|
-
|
|
9325
|
+
totalStreamMs2,
|
|
9243
9326
|
true,
|
|
9244
9327
|
response.status,
|
|
9245
9328
|
createTestDebug({
|
|
@@ -9248,7 +9331,8 @@ async function testStreamingEndpoint(baseUrl, provider, path2, model, isOpenAI)
|
|
|
9248
9331
|
requestBody: body,
|
|
9249
9332
|
response,
|
|
9250
9333
|
responseBody: chunks.join("")
|
|
9251
|
-
})
|
|
9334
|
+
}),
|
|
9335
|
+
{ firstChunkMs, totalStreamMs: totalStreamMs2, tokensPerSecond: null }
|
|
9252
9336
|
);
|
|
9253
9337
|
}
|
|
9254
9338
|
const decoded = decoder.decode(value, { stream: true });
|
|
@@ -9260,6 +9344,7 @@ async function testStreamingEndpoint(baseUrl, provider, path2, model, isOpenAI)
|
|
|
9260
9344
|
chunks.push(finalChunk);
|
|
9261
9345
|
}
|
|
9262
9346
|
} catch (readErr) {
|
|
9347
|
+
const totalStreamMs2 = Date.now() - startTime;
|
|
9263
9348
|
const error = readErr instanceof Error && readErr.name === "AbortError" ? readErr : `Stream read error: ${String(readErr)}`;
|
|
9264
9349
|
return createErrorResult(
|
|
9265
9350
|
error,
|
|
@@ -9272,10 +9357,12 @@ async function testStreamingEndpoint(baseUrl, provider, path2, model, isOpenAI)
|
|
|
9272
9357
|
requestBody: body,
|
|
9273
9358
|
response,
|
|
9274
9359
|
responseBody: chunks.join("")
|
|
9275
|
-
})
|
|
9360
|
+
}),
|
|
9361
|
+
{ firstChunkMs, totalStreamMs: totalStreamMs2, tokensPerSecond: null }
|
|
9276
9362
|
);
|
|
9277
9363
|
}
|
|
9278
9364
|
const fullResponse = chunks.join("");
|
|
9365
|
+
const totalStreamMs = Date.now() - startTime;
|
|
9279
9366
|
const safeRequestHeaders = redactHeaders(requestHeaders);
|
|
9280
9367
|
const mockLog = {
|
|
9281
9368
|
id: 0,
|
|
@@ -9336,6 +9423,11 @@ async function testStreamingEndpoint(baseUrl, provider, path2, model, isOpenAI)
|
|
|
9336
9423
|
}
|
|
9337
9424
|
}
|
|
9338
9425
|
}
|
|
9426
|
+
const tokensPerSecond = computeTokensPerSecond({
|
|
9427
|
+
outputTokens,
|
|
9428
|
+
firstChunkMs,
|
|
9429
|
+
totalStreamMs
|
|
9430
|
+
});
|
|
9339
9431
|
return {
|
|
9340
9432
|
success: true,
|
|
9341
9433
|
model: responseModel ?? model,
|
|
@@ -9344,6 +9436,9 @@ async function testStreamingEndpoint(baseUrl, provider, path2, model, isOpenAI)
|
|
|
9344
9436
|
cacheCreationInputTokens,
|
|
9345
9437
|
cacheReadInputTokens,
|
|
9346
9438
|
latencyMs,
|
|
9439
|
+
firstChunkMs,
|
|
9440
|
+
totalStreamMs,
|
|
9441
|
+
tokensPerSecond,
|
|
9347
9442
|
content: content.length > 0 ? content : void 0,
|
|
9348
9443
|
rawResponse: reconstructedJson,
|
|
9349
9444
|
streaming: true,
|
|
@@ -9362,7 +9457,8 @@ async function testStreamingEndpoint(baseUrl, provider, path2, model, isOpenAI)
|
|
|
9362
9457
|
requestBody: body,
|
|
9363
9458
|
response,
|
|
9364
9459
|
responseBody: fullResponse
|
|
9365
|
-
})
|
|
9460
|
+
}),
|
|
9461
|
+
{ firstChunkMs, totalStreamMs, tokensPerSecond: null }
|
|
9366
9462
|
);
|
|
9367
9463
|
}
|
|
9368
9464
|
} catch (err) {
|
|
@@ -9633,26 +9729,35 @@ const Route$5 = createFileRoute("/api/logs/$id/replay")({
|
|
|
9633
9729
|
error: String(err)
|
|
9634
9730
|
});
|
|
9635
9731
|
}
|
|
9636
|
-
const elapsedMs = Date.now() - startTime;
|
|
9637
9732
|
const isStream = upstreamRes.headers.get(HEADER_CONTENT_TYPE)?.includes(CONTENT_TYPE_EVENT_STREAM) ?? false;
|
|
9638
9733
|
if (isStream) {
|
|
9639
9734
|
const chunks = [];
|
|
9640
9735
|
const decoder = new TextDecoder();
|
|
9641
9736
|
const reader = upstreamRes.body?.getReader();
|
|
9737
|
+
let firstChunkMs = null;
|
|
9642
9738
|
if (reader) {
|
|
9643
9739
|
try {
|
|
9644
9740
|
while (true) {
|
|
9645
9741
|
const { done, value } = await reader.read();
|
|
9646
9742
|
if (done) break;
|
|
9743
|
+
if (firstChunkMs === null) firstChunkMs = Date.now() - startTime;
|
|
9647
9744
|
chunks.push(decoder.decode(value, { stream: true }));
|
|
9648
9745
|
}
|
|
9649
9746
|
} catch {
|
|
9650
9747
|
}
|
|
9651
9748
|
}
|
|
9652
9749
|
const fullResponse = chunks.join("");
|
|
9750
|
+
const elapsedMs = Date.now() - startTime;
|
|
9751
|
+
const totalStreamMs = elapsedMs;
|
|
9653
9752
|
const mockLog = { ...log };
|
|
9654
9753
|
const responseText = formatHandler.extractStream(fullResponse, mockLog, model, false);
|
|
9655
9754
|
const tokens = formatHandler.extractTokens(responseText);
|
|
9755
|
+
const outputTokens = tokens.outputTokens ?? null;
|
|
9756
|
+
const tokensPerSecond = computeTokensPerSecond({
|
|
9757
|
+
outputTokens,
|
|
9758
|
+
firstChunkMs,
|
|
9759
|
+
totalStreamMs
|
|
9760
|
+
});
|
|
9656
9761
|
const savedReplayLog = await addTestLogEntry({
|
|
9657
9762
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
9658
9763
|
method: log.method,
|
|
@@ -9663,10 +9768,13 @@ const Route$5 = createFileRoute("/api/logs/$id/replay")({
|
|
|
9663
9768
|
responseStatus: upstreamRes.status,
|
|
9664
9769
|
responseText,
|
|
9665
9770
|
inputTokens: tokens.inputTokens ?? null,
|
|
9666
|
-
outputTokens
|
|
9771
|
+
outputTokens,
|
|
9667
9772
|
cacheCreationInputTokens: tokens.cacheCreationInputTokens ?? null,
|
|
9668
9773
|
cacheReadInputTokens: tokens.cacheReadInputTokens ?? null,
|
|
9669
9774
|
elapsedMs,
|
|
9775
|
+
firstChunkMs,
|
|
9776
|
+
totalStreamMs,
|
|
9777
|
+
tokensPerSecond,
|
|
9670
9778
|
streaming: true,
|
|
9671
9779
|
userAgent: log.userAgent,
|
|
9672
9780
|
origin: log.origin,
|
|
@@ -9691,11 +9799,15 @@ const Route$5 = createFileRoute("/api/logs/$id/replay")({
|
|
|
9691
9799
|
inputTokens: tokens.inputTokens ?? void 0,
|
|
9692
9800
|
outputTokens: tokens.outputTokens ?? void 0,
|
|
9693
9801
|
elapsedMs,
|
|
9802
|
+
firstChunkMs,
|
|
9803
|
+
totalStreamMs,
|
|
9804
|
+
tokensPerSecond,
|
|
9694
9805
|
streaming: true,
|
|
9695
9806
|
replayLogId: savedReplayLog.id
|
|
9696
9807
|
});
|
|
9697
9808
|
} else {
|
|
9698
9809
|
const responseText = await upstreamRes.text();
|
|
9810
|
+
const elapsedMs = Date.now() - startTime;
|
|
9699
9811
|
const tokens = formatHandler.extractTokens(responseText);
|
|
9700
9812
|
const savedReplayLog = await addTestLogEntry({
|
|
9701
9813
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -9711,6 +9823,9 @@ const Route$5 = createFileRoute("/api/logs/$id/replay")({
|
|
|
9711
9823
|
cacheCreationInputTokens: tokens.cacheCreationInputTokens ?? null,
|
|
9712
9824
|
cacheReadInputTokens: tokens.cacheReadInputTokens ?? null,
|
|
9713
9825
|
elapsedMs,
|
|
9826
|
+
firstChunkMs: null,
|
|
9827
|
+
totalStreamMs: null,
|
|
9828
|
+
tokensPerSecond: null,
|
|
9714
9829
|
streaming: false,
|
|
9715
9830
|
userAgent: log.userAgent,
|
|
9716
9831
|
origin: log.origin,
|
|
@@ -9846,6 +9961,9 @@ const ProviderTestResultSchema = object({
|
|
|
9846
9961
|
cacheCreationInputTokens: number().optional(),
|
|
9847
9962
|
cacheReadInputTokens: number().optional(),
|
|
9848
9963
|
latencyMs: number().optional(),
|
|
9964
|
+
firstChunkMs: number().nullable().optional(),
|
|
9965
|
+
totalStreamMs: number().nullable().optional(),
|
|
9966
|
+
tokensPerSecond: number().nullable().optional(),
|
|
9849
9967
|
content: array(ProviderTestContentSchema).optional(),
|
|
9850
9968
|
rawResponse: string().optional(),
|
|
9851
9969
|
streaming: boolean().optional(),
|
|
@@ -9915,6 +10033,19 @@ function getResultResponseText(result) {
|
|
|
9915
10033
|
function getResultHeaders(result) {
|
|
9916
10034
|
return result.requestHeaders ?? result.debug?.requestHeaders ?? {};
|
|
9917
10035
|
}
|
|
10036
|
+
function getResultTotalStreamMs(result) {
|
|
10037
|
+
return result.totalStreamMs ?? (result.streaming === true ? result.latencyMs ?? null : null);
|
|
10038
|
+
}
|
|
10039
|
+
function getResultFirstChunkMs(result) {
|
|
10040
|
+
return result.firstChunkMs ?? firstChunkMsFromChunks(result.streamingChunks?.chunks);
|
|
10041
|
+
}
|
|
10042
|
+
function getResultTokensPerSecond(result) {
|
|
10043
|
+
return result.tokensPerSecond ?? computeTokensPerSecond({
|
|
10044
|
+
outputTokens: result.outputTokens,
|
|
10045
|
+
firstChunkMs: getResultFirstChunkMs(result),
|
|
10046
|
+
totalStreamMs: getResultTotalStreamMs(result)
|
|
10047
|
+
});
|
|
10048
|
+
}
|
|
9918
10049
|
async function logModelResults(displayName, providerName, anthropicUrl, openaiUrl, modelResults, captureFullDetails) {
|
|
9919
10050
|
const usageModel = getModelUsageName(displayName, providerName);
|
|
9920
10051
|
if (anthropicUrl !== void 0) {
|
|
@@ -9938,6 +10069,9 @@ async function logModelResults(displayName, providerName, anthropicUrl, openaiUr
|
|
|
9938
10069
|
cacheCreationInputTokens: nonStreamingResult.cacheCreationInputTokens ?? null,
|
|
9939
10070
|
cacheReadInputTokens: nonStreamingResult.cacheReadInputTokens ?? null,
|
|
9940
10071
|
elapsedMs: nonStreamingResult.latencyMs ?? 0,
|
|
10072
|
+
firstChunkMs: null,
|
|
10073
|
+
totalStreamMs: null,
|
|
10074
|
+
tokensPerSecond: null,
|
|
9941
10075
|
streaming: false,
|
|
9942
10076
|
userAgent: "provider-test",
|
|
9943
10077
|
origin: null,
|
|
@@ -9962,7 +10096,10 @@ async function logModelResults(displayName, providerName, anthropicUrl, openaiUr
|
|
|
9962
10096
|
outputTokens: streamingResult.outputTokens ?? null,
|
|
9963
10097
|
cacheCreationInputTokens: streamingResult.cacheCreationInputTokens ?? null,
|
|
9964
10098
|
cacheReadInputTokens: streamingResult.cacheReadInputTokens ?? null,
|
|
9965
|
-
elapsedMs: streamingResult
|
|
10099
|
+
elapsedMs: getResultTotalStreamMs(streamingResult) ?? 0,
|
|
10100
|
+
firstChunkMs: getResultFirstChunkMs(streamingResult),
|
|
10101
|
+
totalStreamMs: getResultTotalStreamMs(streamingResult),
|
|
10102
|
+
tokensPerSecond: getResultTokensPerSecond(streamingResult),
|
|
9966
10103
|
streaming: true,
|
|
9967
10104
|
streamingChunks: captureFullDetails ? streamingResult.streamingChunks : void 0,
|
|
9968
10105
|
userAgent: "provider-test",
|
|
@@ -9995,6 +10132,9 @@ async function logModelResults(displayName, providerName, anthropicUrl, openaiUr
|
|
|
9995
10132
|
cacheCreationInputTokens: null,
|
|
9996
10133
|
cacheReadInputTokens: null,
|
|
9997
10134
|
elapsedMs: nonStreamingResult.latencyMs ?? 0,
|
|
10135
|
+
firstChunkMs: null,
|
|
10136
|
+
totalStreamMs: null,
|
|
10137
|
+
tokensPerSecond: null,
|
|
9998
10138
|
streaming: false,
|
|
9999
10139
|
userAgent: "provider-test",
|
|
10000
10140
|
origin: null,
|
|
@@ -10019,7 +10159,10 @@ async function logModelResults(displayName, providerName, anthropicUrl, openaiUr
|
|
|
10019
10159
|
outputTokens: streamingResult.outputTokens ?? null,
|
|
10020
10160
|
cacheCreationInputTokens: null,
|
|
10021
10161
|
cacheReadInputTokens: null,
|
|
10022
|
-
elapsedMs: streamingResult
|
|
10162
|
+
elapsedMs: getResultTotalStreamMs(streamingResult) ?? 0,
|
|
10163
|
+
firstChunkMs: getResultFirstChunkMs(streamingResult),
|
|
10164
|
+
totalStreamMs: getResultTotalStreamMs(streamingResult),
|
|
10165
|
+
tokensPerSecond: getResultTokensPerSecond(streamingResult),
|
|
10023
10166
|
streaming: true,
|
|
10024
10167
|
streamingChunks: captureFullDetails ? streamingResult.streamingChunks : void 0,
|
|
10025
10168
|
userAgent: "provider-test",
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const tsrStartManifest = () => ({ "routes": { "__root__": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/__root.tsx", "children": ["/", "/api/config", "/api/health", "/api/logs", "/api/mcp", "/api/models", "/api/providers", "/api/runs", "/api/sessions", "/proxy/$", "/session/$sessionId", "/api/knowledge/candidates", "/api/knowledge/project-context", "/api/knowledge/search", "/api/knowledge/sessions/$sessionId/candidates"], "preloads": ["/assets/main-
|
|
1
|
+
const tsrStartManifest = () => ({ "routes": { "__root__": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/__root.tsx", "children": ["/", "/api/config", "/api/health", "/api/logs", "/api/mcp", "/api/models", "/api/providers", "/api/runs", "/api/sessions", "/proxy/$", "/session/$sessionId", "/api/knowledge/candidates", "/api/knowledge/project-context", "/api/knowledge/search", "/api/knowledge/sessions/$sessionId/candidates"], "preloads": ["/assets/main-B6OLZCp9.js"], "assets": [] }, "/": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/index.tsx", "assets": [], "preloads": ["/assets/index-BhQGSdhG.js", "/assets/ProxyViewerContainer-D650kQlv.js"] }, "/api/config": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/config.ts", "children": ["/api/config/paths"] }, "/api/health": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/health.ts" }, "/api/logs": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/logs.ts", "children": ["/api/logs/$id", "/api/logs/stream"] }, "/api/mcp": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/mcp.ts" }, "/api/models": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/models.ts" }, "/api/providers": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/providers.ts", "children": ["/api/providers/$providerId", "/api/providers/export", "/api/providers/import", "/api/providers/scan"] }, "/api/runs": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/runs.ts", "children": ["/api/runs/$runId"] }, "/api/sessions": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/sessions.ts" }, "/proxy/$": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/proxy/$.ts" }, "/session/$sessionId": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/session/$sessionId.tsx", "assets": [], "preloads": ["/assets/_sessionId-wctOoGh_.js", "/assets/ProxyViewerContainer-D650kQlv.js"] }, "/api/config/paths": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/config.paths.ts" }, "/api/knowledge/candidates": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/knowledge.candidates.ts", "children": ["/api/knowledge/candidates/$candidateId"] }, "/api/knowledge/project-context": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/knowledge.project-context.ts" }, "/api/knowledge/search": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/knowledge.search.ts" }, "/api/logs/$id": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/logs.$id.ts", "children": ["/api/logs/$id/chunks", "/api/logs/$id/replay"] }, "/api/logs/stream": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/logs.stream.ts" }, "/api/providers/$providerId": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/providers.$providerId.ts", "children": ["/api/providers/$providerId/model-metadata", "/api/providers/$providerId/test"] }, "/api/providers/export": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/providers.export.ts" }, "/api/providers/import": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/providers.import.ts" }, "/api/providers/scan": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/providers.scan.ts" }, "/api/runs/$runId": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/runs.$runId.ts", "children": ["/api/runs/$runId/evidence"] }, "/api/knowledge/candidates/$candidateId": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/knowledge.candidates.$candidateId.ts", "children": ["/api/knowledge/candidates/$candidateId/promote"] }, "/api/logs/$id/chunks": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/logs.$id.chunks.ts" }, "/api/logs/$id/replay": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/logs.$id.replay.ts" }, "/api/providers/$providerId/model-metadata": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/providers.$providerId.model-metadata.ts" }, "/api/providers/$providerId/test": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/providers.$providerId.test.ts", "children": ["/api/providers/$providerId/test/log"] }, "/api/runs/$runId/evidence": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/runs.$runId.evidence.ts" }, "/api/knowledge/candidates/$candidateId/promote": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/knowledge.candidates.$candidateId.promote.ts" }, "/api/knowledge/sessions/$sessionId/candidates": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/knowledge.sessions.$sessionId.candidates.ts" }, "/api/providers/$providerId/test/log": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/providers.$providerId.test.log.ts" } }, "clientEntry": "/assets/main-B6OLZCp9.js" });
|
|
2
2
|
export {
|
|
3
3
|
tsrStartManifest
|
|
4
4
|
};
|