@tonyclaw/agent-inspector 2.0.35 → 2.0.37
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-Cin0_f71.js → CompareDrawer-nEHCEVP4.js} +1 -1
- package/.output/public/assets/{ProxyViewerContainer-BVlcRirf.js → ProxyViewerContainer-BstBIX2B.js} +35 -35
- package/.output/public/assets/{ReplayDialog-C6nOMhjx.js → ReplayDialog-CUnBdt1Q.js} +1 -1
- package/.output/public/assets/{RequestAnatomy-DenWbdqV.js → RequestAnatomy-BU9VT2Sw.js} +1 -1
- package/.output/public/assets/{ResponseView-BsalZiZ5.js → ResponseView-amxuKPKY.js} +1 -1
- package/.output/public/assets/{StreamingChunkSequence-Cla2X13P.js → StreamingChunkSequence-DpscrQM2.js} +1 -1
- package/.output/public/assets/_sessionId-7c9bsOFT.js +1 -0
- package/.output/public/assets/index-B7a5OmIO.js +1 -0
- package/.output/public/assets/{main-eD8hEOHT.js → main-D56QvEyw.js} +4 -4
- package/.output/server/_libs/lucide-react.mjs +114 -94
- package/.output/server/{_sessionId-URSu2XsA.mjs → _sessionId-ChwEDyI4.mjs} +2 -2
- package/.output/server/_ssr/{CompareDrawer-BbBPKdVc.mjs → CompareDrawer-Ce2590rK.mjs} +3 -3
- package/.output/server/_ssr/{ProxyViewerContainer-DtQxtOpi.mjs → ProxyViewerContainer-D6xM8A0S.mjs} +797 -781
- package/.output/server/_ssr/{ReplayDialog-BU20cMGd.mjs → ReplayDialog-CB4KOlLe.mjs} +4 -4
- package/.output/server/_ssr/{RequestAnatomy-a5ySAAG1.mjs → RequestAnatomy-CsWV3W03.mjs} +3 -3
- package/.output/server/_ssr/{ResponseView-CA_QM1fM.mjs → ResponseView-BuCCV3LU.mjs} +3 -3
- package/.output/server/_ssr/{StreamingChunkSequence-DJjITqM7.mjs → StreamingChunkSequence-C5dE7V1d.mjs} +2 -2
- package/.output/server/_ssr/{index-DIFzLUAV.mjs → index-BeIi0CPv.mjs} +2 -2
- package/.output/server/_ssr/index.mjs +2 -2
- package/.output/server/_ssr/{router-aVeuM_1d.mjs → router-Ca2MCyUX.mjs} +91 -71
- package/.output/server/{_tanstack-start-manifest_v-BNlafGbl.mjs → _tanstack-start-manifest_v-CBAJfSAX.mjs} +1 -1
- package/.output/server/index.mjs +55 -55
- package/package.json +1 -1
- package/src/components/ProxyViewer.tsx +42 -8
- package/src/components/proxy-viewer/ConversationHeader.tsx +10 -6
- package/src/proxy/formats/registry.ts +7 -1
- package/src/proxy/store.ts +14 -11
- package/src/router.tsx +17 -0
- package/.output/public/assets/_sessionId-DkhHqlzB.js +0 -1
- package/.output/public/assets/index-AiQY20d7.js +0 -1
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
import { type JSX, useCallback, useEffect, useMemo, useRef, useState, Suspense } from "react";
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
ArrowDownRight,
|
|
4
|
+
ArrowLeft,
|
|
5
|
+
ArrowUpRight,
|
|
6
|
+
Check,
|
|
7
|
+
Copy,
|
|
8
|
+
Download,
|
|
9
|
+
FileJson,
|
|
10
|
+
Plus,
|
|
11
|
+
Trash2,
|
|
12
|
+
} from "lucide-react";
|
|
3
13
|
|
|
4
14
|
import type { CapturedLog } from "../proxy/schemas";
|
|
5
15
|
import { exportLogsAsZip, type ExportMode } from "../lib/export-logs";
|
|
@@ -43,6 +53,22 @@ export function shouldShowRawExport(captureMode: CaptureMode): boolean {
|
|
|
43
53
|
return captureMode === "full";
|
|
44
54
|
}
|
|
45
55
|
|
|
56
|
+
export type ExportActionVisibility = {
|
|
57
|
+
redacted: boolean;
|
|
58
|
+
raw: boolean;
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
export function getExportActionVisibility(
|
|
62
|
+
captureMode: CaptureMode,
|
|
63
|
+
logCount: number,
|
|
64
|
+
): ExportActionVisibility {
|
|
65
|
+
const hasLogs = logCount > 0;
|
|
66
|
+
return {
|
|
67
|
+
redacted: hasLogs,
|
|
68
|
+
raw: hasLogs && shouldShowRawExport(captureMode),
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
|
|
46
72
|
function computeTokenSummary(logs: CapturedLog[]): { totalIn: number; totalOut: number } {
|
|
47
73
|
let totalIn = 0;
|
|
48
74
|
let totalOut = 0;
|
|
@@ -714,7 +740,7 @@ export function ProxyViewer({
|
|
|
714
740
|
);
|
|
715
741
|
const cacheTrends = useMemo(() => computeCacheTrends(groups), [groups]);
|
|
716
742
|
const comparisonPredecessors = useMemo(() => buildValidPredecessors(groups), [groups]);
|
|
717
|
-
const
|
|
743
|
+
const exportActionVisibility = getExportActionVisibility(captureMode, logs.length);
|
|
718
744
|
const handleCompareWithPrevious = useCallback(
|
|
719
745
|
(log: CapturedLog) => {
|
|
720
746
|
const predecessor = comparisonPredecessors.get(log.id);
|
|
@@ -881,7 +907,7 @@ export function ProxyViewer({
|
|
|
881
907
|
: ""}
|
|
882
908
|
</span>
|
|
883
909
|
)}
|
|
884
|
-
{
|
|
910
|
+
{exportActionVisibility.redacted && (
|
|
885
911
|
<button
|
|
886
912
|
type="button"
|
|
887
913
|
onClick={() => {
|
|
@@ -901,26 +927,34 @@ export function ProxyViewer({
|
|
|
901
927
|
)}
|
|
902
928
|
</button>
|
|
903
929
|
)}
|
|
904
|
-
{
|
|
930
|
+
{exportActionVisibility.raw && (
|
|
905
931
|
<button
|
|
906
932
|
type="button"
|
|
907
933
|
onClick={() => {
|
|
908
934
|
void handleExport("raw");
|
|
909
935
|
}}
|
|
910
936
|
disabled={exporting !== null}
|
|
911
|
-
className="h-8 px-2 text-xs text-muted-foreground hover:text-foreground transition-colors cursor-pointer disabled:opacity-50 disabled:cursor-not-allowed rounded-md hover:bg-muted"
|
|
937
|
+
className="h-8 px-2.5 text-xs text-muted-foreground hover:text-foreground transition-colors cursor-pointer disabled:opacity-50 disabled:cursor-not-allowed inline-flex items-center gap-1.5 rounded-md hover:bg-muted"
|
|
912
938
|
title="Export raw logs without redaction"
|
|
913
939
|
>
|
|
914
|
-
{exporting === "raw" ?
|
|
940
|
+
{exporting === "raw" ? (
|
|
941
|
+
<span>Exporting...</span>
|
|
942
|
+
) : (
|
|
943
|
+
<>
|
|
944
|
+
<FileJson className="size-3.5" />
|
|
945
|
+
<span>Raw</span>
|
|
946
|
+
</>
|
|
947
|
+
)}
|
|
915
948
|
</button>
|
|
916
949
|
)}
|
|
917
950
|
<button
|
|
918
951
|
type="button"
|
|
919
952
|
onClick={onClearAll}
|
|
920
|
-
className="h-8 px-3 text-xs text-muted-foreground hover:text-foreground transition-colors cursor-pointer rounded-md hover:bg-muted"
|
|
953
|
+
className="h-8 px-3 text-xs text-muted-foreground hover:text-foreground transition-colors cursor-pointer inline-flex items-center gap-1.5 rounded-md hover:bg-muted"
|
|
921
954
|
title="Clear all logs"
|
|
922
955
|
>
|
|
923
|
-
|
|
956
|
+
<Trash2 className="size-3.5" />
|
|
957
|
+
<span>Clear</span>
|
|
924
958
|
</button>
|
|
925
959
|
</div>
|
|
926
960
|
{exportError !== null && (
|
|
@@ -18,6 +18,7 @@ import { cn, formatTokens } from "../../lib/utils";
|
|
|
18
18
|
import type { CapturedLog } from "../../proxy/schemas";
|
|
19
19
|
import { Badge } from "../ui/badge";
|
|
20
20
|
import { ConfirmDialog } from "../ui/confirm-dialog";
|
|
21
|
+
import { resolveLogFormat } from "./log-formats";
|
|
21
22
|
|
|
22
23
|
const API_FORMAT_LABELS: Record<"anthropic" | "openai" | "unknown", string> = {
|
|
23
24
|
anthropic: "Anthropic",
|
|
@@ -231,11 +232,13 @@ export type ConversationGroupData = {
|
|
|
231
232
|
};
|
|
232
233
|
|
|
233
234
|
export function getGroupApiFormat(logs: CapturedLog[]): "anthropic" | "openai" | "unknown" {
|
|
234
|
-
const
|
|
235
|
-
|
|
236
|
-
|
|
235
|
+
for (const log of logs) {
|
|
236
|
+
const apiFormat = resolveLogFormat(log);
|
|
237
|
+
if (apiFormat !== "unknown") {
|
|
238
|
+
return apiFormat;
|
|
239
|
+
}
|
|
237
240
|
}
|
|
238
|
-
return
|
|
241
|
+
return "unknown";
|
|
239
242
|
}
|
|
240
243
|
|
|
241
244
|
/**
|
|
@@ -248,8 +251,9 @@ export function hasMixedApiFormat(logs: CapturedLog[]): boolean {
|
|
|
248
251
|
let hasAnthropic = false;
|
|
249
252
|
let hasOpenai = false;
|
|
250
253
|
for (const log of logs) {
|
|
251
|
-
|
|
252
|
-
|
|
254
|
+
const apiFormat = resolveLogFormat(log);
|
|
255
|
+
if (apiFormat === "anthropic") hasAnthropic = true;
|
|
256
|
+
else if (apiFormat === "openai") hasOpenai = true;
|
|
253
257
|
if (hasAnthropic && hasOpenai) return true;
|
|
254
258
|
}
|
|
255
259
|
return false;
|
|
@@ -31,6 +31,12 @@ class FormatRegistryImpl {
|
|
|
31
31
|
return format === undefined ? undefined : this.handlers.get(format);
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
+
/** Get the wire format matching a request path without requiring handlers. */
|
|
35
|
+
getFormatByPath(path: string): RequestFormat | undefined {
|
|
36
|
+
const messagesPath = path.split("?")[0] ?? "";
|
|
37
|
+
return this.pathMap.get(messagesPath);
|
|
38
|
+
}
|
|
39
|
+
|
|
34
40
|
/** Detect format from request body content */
|
|
35
41
|
detectFormat(rawBody: string | null): RequestFormat {
|
|
36
42
|
if (rawBody === null) return "unknown";
|
|
@@ -57,7 +63,7 @@ export function formatForPath(path: string): FormatHandler | null {
|
|
|
57
63
|
* simple message-only calls.
|
|
58
64
|
*/
|
|
59
65
|
export function requestFormatForPath(path: string): RequestFormat {
|
|
60
|
-
return
|
|
66
|
+
return formatRegistry.getFormatByPath(path) ?? "unknown";
|
|
61
67
|
}
|
|
62
68
|
|
|
63
69
|
// Register known paths
|
package/src/proxy/store.ts
CHANGED
|
@@ -34,6 +34,7 @@ import type { SessionInfo, SessionLogSummary } from "../lib/sessionInfoContract"
|
|
|
34
34
|
import { buildSessionInfo, buildSessionLogSummary } from "./sessionInfo";
|
|
35
35
|
import type { CapturedLog } from "./schemas";
|
|
36
36
|
import { CapturedLogSchema } from "./schemas";
|
|
37
|
+
import { requestFormatForPath } from "./formats/registry";
|
|
37
38
|
import {
|
|
38
39
|
clearSessionRegistry,
|
|
39
40
|
getLogSessionId,
|
|
@@ -109,14 +110,16 @@ function evictOldestIfNeeded(): void {
|
|
|
109
110
|
}
|
|
110
111
|
}
|
|
111
112
|
|
|
112
|
-
function
|
|
113
|
+
function normalizeLog(log: CapturedLog): CapturedLog {
|
|
113
114
|
const sessionId = getLogSessionId(log);
|
|
114
|
-
|
|
115
|
-
|
|
115
|
+
const pathFormat = requestFormatForPath(log.path);
|
|
116
|
+
const apiFormat = pathFormat === "unknown" ? log.apiFormat : pathFormat;
|
|
117
|
+
if (sessionId === log.sessionId && apiFormat === log.apiFormat) return log;
|
|
118
|
+
return { ...log, sessionId, apiFormat };
|
|
116
119
|
}
|
|
117
120
|
|
|
118
121
|
function addToCache(log: CapturedLog): void {
|
|
119
|
-
const cachedLog =
|
|
122
|
+
const cachedLog = normalizeLog(log);
|
|
120
123
|
// If updating an existing entry, remove first to reset insertion order
|
|
121
124
|
if (memoryCache.has(cachedLog.id)) {
|
|
122
125
|
memoryCache.delete(cachedLog.id);
|
|
@@ -174,12 +177,12 @@ export async function addTestLogEntry(entry: Omit<CapturedLog, "id">): Promise<C
|
|
|
174
177
|
isTest: entry.isTest,
|
|
175
178
|
});
|
|
176
179
|
|
|
177
|
-
const log: CapturedLog = {
|
|
180
|
+
const log: CapturedLog = normalizeLog({
|
|
178
181
|
id,
|
|
179
182
|
...entry,
|
|
180
183
|
sessionId: session.id,
|
|
181
184
|
streamingChunksPath,
|
|
182
|
-
};
|
|
185
|
+
});
|
|
183
186
|
|
|
184
187
|
await runWithLogWriteLock(async () => {
|
|
185
188
|
const logFile = getCurrentLogFile();
|
|
@@ -218,7 +221,7 @@ export async function createLog(
|
|
|
218
221
|
clientInfo,
|
|
219
222
|
});
|
|
220
223
|
|
|
221
|
-
const log: CapturedLog = {
|
|
224
|
+
const log: CapturedLog = normalizeLog({
|
|
222
225
|
id,
|
|
223
226
|
timestamp: new Date().toISOString(),
|
|
224
227
|
method,
|
|
@@ -249,7 +252,7 @@ export async function createLog(
|
|
|
249
252
|
clientCwd: clientInfo?.cwd ?? null,
|
|
250
253
|
clientProjectFolder: clientInfo?.projectFolder ?? null,
|
|
251
254
|
streamingChunksPath: null,
|
|
252
|
-
};
|
|
255
|
+
});
|
|
253
256
|
|
|
254
257
|
// Write to disk and update index
|
|
255
258
|
await runWithLogWriteLock(async () => {
|
|
@@ -308,7 +311,7 @@ export async function getLogById(id: number): Promise<CapturedLog | null> {
|
|
|
308
311
|
const parsed: unknown = JSON.parse(line);
|
|
309
312
|
const result = CapturedLogSchema.safeParse(parsed);
|
|
310
313
|
if (result.success) {
|
|
311
|
-
const log =
|
|
314
|
+
const log = normalizeLog(result.data);
|
|
312
315
|
addToCache(log);
|
|
313
316
|
observeSessionLog(log);
|
|
314
317
|
return log;
|
|
@@ -348,7 +351,7 @@ async function scanLogFileForId(filePath: string, id: number): Promise<CapturedL
|
|
|
348
351
|
if (desc !== undefined && typeof desc.value === "number" && desc.value === id) {
|
|
349
352
|
const result = CapturedLogSchema.safeParse(parsed);
|
|
350
353
|
if (result.success) {
|
|
351
|
-
lastMatch =
|
|
354
|
+
lastMatch = normalizeLog(result.data);
|
|
352
355
|
if (result.data.responseStatus !== null) {
|
|
353
356
|
return lastMatch;
|
|
354
357
|
}
|
|
@@ -412,7 +415,7 @@ async function visitPersistedLogFile(
|
|
|
412
415
|
const parsed: unknown = JSON.parse(line);
|
|
413
416
|
const result = CapturedLogSchema.safeParse(parsed);
|
|
414
417
|
if (result.success) {
|
|
415
|
-
const log =
|
|
418
|
+
const log = normalizeLog(result.data);
|
|
416
419
|
visitor(log);
|
|
417
420
|
}
|
|
418
421
|
} catch {
|
package/src/router.tsx
CHANGED
|
@@ -6,9 +6,26 @@ export function getRouter() {
|
|
|
6
6
|
routeTree,
|
|
7
7
|
scrollRestoration: false,
|
|
8
8
|
});
|
|
9
|
+
attachServerSsrStoreCompatibility(router);
|
|
9
10
|
return router;
|
|
10
11
|
}
|
|
11
12
|
|
|
13
|
+
function attachServerSsrStoreCompatibility(
|
|
14
|
+
router: Readonly<{ state: Readonly<{ matches: unknown }> }>,
|
|
15
|
+
): void {
|
|
16
|
+
const existingStores = Object.getOwnPropertyDescriptor(router, "stores");
|
|
17
|
+
if (existingStores !== undefined) return;
|
|
18
|
+
|
|
19
|
+
Object.defineProperty(router, "stores", {
|
|
20
|
+
configurable: true,
|
|
21
|
+
value: {
|
|
22
|
+
matches: {
|
|
23
|
+
get: () => router.state.matches,
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
|
|
12
29
|
declare module "@tanstack/react-router" {
|
|
13
30
|
interface Register {
|
|
14
31
|
router: ReturnType<typeof getRouter>;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{R as s,j as e}from"./main-eD8hEOHT.js";import{P as i}from"./ProxyViewerContainer-BVlcRirf.js";function t(){const{sessionId:o}=s.useParams();return e.jsx(i,{initialSessionId:o},o)}export{t as component};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{P as o}from"./ProxyViewerContainer-BVlcRirf.js";import"./main-eD8hEOHT.js";const r=o;export{r as component};
|