@tonyclaw/agent-inspector 3.0.23 → 3.0.24

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.
Files changed (47) hide show
  1. package/.output/nitro.json +1 -1
  2. package/.output/public/assets/{CompareDrawer-CFedvZHU.js → CompareDrawer-BC52FYwn.js} +1 -1
  3. package/.output/public/assets/ProxyViewerContainer-WuChOrSS.js +127 -0
  4. package/.output/public/assets/{ReplayDialog-X-fRSKAu.js → ReplayDialog-BcKsarKt.js} +1 -1
  5. package/.output/public/assets/{RequestAnatomy-S8qB5nVg.js → RequestAnatomy-DR0uGpCj.js} +1 -1
  6. package/.output/public/assets/{ResponseView-_rcOWSwJ.js → ResponseView-kxAAPfmn.js} +2 -2
  7. package/.output/public/assets/{StreamingChunkSequence-Bc15AVpN.js → StreamingChunkSequence-YQR0PjQj.js} +1 -1
  8. package/.output/public/assets/{_sessionId-Cz-HW2Wf.js → _sessionId-DRl-Y9om.js} +1 -1
  9. package/.output/public/assets/{index-CEgwWY3E.js → index-CQbrc-hi.js} +71 -7
  10. package/.output/public/assets/{index-CXYBU0j8.js → index-CcSIBI4L.js} +1 -1
  11. package/.output/public/assets/index-DQeXi4Rv.css +1 -0
  12. package/.output/public/assets/{index-ClKXooQd.js → index-ZrMgyEZV.js} +1 -1
  13. package/.output/public/assets/{json-viewer-QfU4qGdd.js → json-viewer-CS5pwnEA.js} +1 -1
  14. package/.output/server/_libs/lucide-react.mjs +266 -234
  15. package/.output/server/{_sessionId-9FAmYZVf.mjs → _sessionId-BLk2xPkR.mjs} +2 -2
  16. package/.output/server/_ssr/{CompareDrawer-BLKjOzwD.mjs → CompareDrawer-Cw7Dseo3.mjs} +3 -3
  17. package/.output/server/_ssr/{ProxyViewerContainer-Dcs2Mq8l.mjs → ProxyViewerContainer-D8SB0zyQ.mjs} +1124 -877
  18. package/.output/server/_ssr/{ReplayDialog-oyiF4LIo.mjs → ReplayDialog-B-YMhZkE.mjs} +4 -4
  19. package/.output/server/_ssr/{RequestAnatomy-DkyQXSuj.mjs → RequestAnatomy-a9d8UTYZ.mjs} +2 -2
  20. package/.output/server/_ssr/{ResponseView-3NTDEiDh.mjs → ResponseView-PzaZS4CN.mjs} +3 -3
  21. package/.output/server/_ssr/{StreamingChunkSequence-DRq-5Bgn.mjs → StreamingChunkSequence-C21_TCXk.mjs} +2 -2
  22. package/.output/server/_ssr/{index-dtMiNUa1.mjs → index-CrCeNP7H.mjs} +2 -2
  23. package/.output/server/_ssr/index.mjs +2 -2
  24. package/.output/server/_ssr/{json-viewer-BhUwicvp.mjs → json-viewer-Di2gxs9H.mjs} +3 -3
  25. package/.output/server/_ssr/{router-DO0OntUK.mjs → router-BJzdUbcH.mjs} +296 -91
  26. package/.output/server/{_tanstack-start-manifest_v-DO5v3BHY.mjs → _tanstack-start-manifest_v-CGBTdAYC.mjs} +1 -1
  27. package/.output/server/index.mjs +76 -76
  28. package/package.json +3 -2
  29. package/src/components/ProxyViewer.tsx +136 -460
  30. package/src/components/ProxyViewerContainer.tsx +5 -47
  31. package/src/components/alerts/AlertsDialog.tsx +6 -2
  32. package/src/components/providers/ProviderCard.tsx +20 -579
  33. package/src/components/providers/ProviderTestResultsView.tsx +732 -0
  34. package/src/components/proxy-viewer/LogEntry.tsx +5 -0
  35. package/src/components/proxy-viewer/LogEntryHeader.tsx +7 -0
  36. package/src/components/proxy-viewer/ToolTraceEvents.tsx +33 -36
  37. package/src/components/proxy-viewer/TurnGroup.tsx +1 -5
  38. package/src/components/proxy-viewer/proxyViewerContainerLogic.ts +46 -0
  39. package/src/components/proxy-viewer/proxyViewerLogic.ts +469 -0
  40. package/src/lib/themeMode.ts +45 -0
  41. package/src/lib/uiScale.ts +112 -0
  42. package/src/lib/useThemeMode.ts +40 -0
  43. package/src/lib/useUiScale.ts +52 -0
  44. package/src/routes/__root.tsx +78 -1
  45. package/styles/globals.css +305 -23
  46. package/.output/public/assets/ProxyViewerContainer-BlCrBvdm.js +0 -127
  47. package/.output/public/assets/index-B_SIQ47i.css +0 -1
@@ -39,6 +39,7 @@ import { RequestTools } from "./RequestToolsPanel";
39
39
  import type { CacheTrendEntry } from "./cacheTrend";
40
40
  import { getLogFormatAdapter, resolveLogFormat } from "./log-formats";
41
41
  import { LOG_FOCUS_REQUEST_EVENT, readLogFocusRequest, type LogFocusTab } from "./logFocus";
42
+ import type { ToolTraceEvent } from "./viewerState";
42
43
  import {
43
44
  shouldShowHeadersDiffButton,
44
45
  shouldShowHeadersTab,
@@ -353,6 +354,8 @@ export type LogEntryProps = {
353
354
  onCompareWithPrevious?: (log: CapturedLog) => void;
354
355
  /** Show client PID/project metadata on the log header row. */
355
356
  showClientMetadata?: boolean;
357
+ /** Tools called by the response, rendered in the compact log header. */
358
+ toolEvents?: ToolTraceEvent[];
356
359
  };
357
360
 
358
361
  function DiffToggleButton({
@@ -427,6 +430,7 @@ export const LogEntry = memo(function ({
427
430
  cacheTrend = null,
428
431
  onCompareWithPrevious,
429
432
  showClientMetadata = true,
433
+ toolEvents = [],
430
434
  }: LogEntryProps): JSX.Element {
431
435
  const [expanded, setExpanded] = useState<boolean>(false);
432
436
  const [replayOpen, setReplayOpen] = useState<boolean>(false);
@@ -831,6 +835,7 @@ export const LogEntry = memo(function ({
831
835
  displayNumber={displayNumber}
832
836
  messageCount={requestAnalysis.messageCount}
833
837
  toolCount={requestAnalysis.toolCount}
838
+ toolEvents={toolEvents}
834
839
  expanded={expanded}
835
840
  onToggle={handleToggleExpanded}
836
841
  cacheTrend={cacheTrend}
@@ -32,6 +32,8 @@ import { Badge } from "../ui/badge";
32
32
  import { Button } from "../ui/button";
33
33
  import { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider } from "../ui/tooltip";
34
34
  import type { CacheTrend } from "./cacheTrend";
35
+ import { ToolTraceEvents } from "./ToolTraceEvents";
36
+ import type { ToolTraceEvent } from "./viewerState";
35
37
 
36
38
  const STATUS_BADGE_CLASSES: Record<StatusCategory, string> = {
37
39
  success: "bg-slate-300/[0.08] text-slate-100 border-transparent",
@@ -150,6 +152,8 @@ export type LogEntryHeaderProps = {
150
152
  messageCount?: number | null;
151
153
  /** Number of tools defined in the request (supports both Anthropic and OpenAI formats). */
152
154
  toolCount?: number | null;
155
+ /** Tools actually called by this response, shown inline with the log telemetry. */
156
+ toolEvents?: ToolTraceEvent[];
153
157
  expanded: boolean;
154
158
  onToggle: () => void;
155
159
  /** Per-log cache token trend (creation + read) relative to the previous log
@@ -180,6 +184,7 @@ export const LogEntryHeader = memo(function ({
180
184
  displayNumber,
181
185
  messageCount = null,
182
186
  toolCount = null,
187
+ toolEvents = [],
183
188
  expanded,
184
189
  onToggle,
185
190
  cacheTrend = null,
@@ -406,6 +411,8 @@ export const LogEntryHeader = memo(function ({
406
411
  </span>
407
412
  )}
408
413
 
414
+ <ToolTraceEvents events={toolEvents} />
415
+
409
416
  {/* Origin */}
410
417
  {log.origin !== null && (
411
418
  <span
@@ -1,67 +1,64 @@
1
- import { type JSX } from "react";
2
- import { AlertTriangle, Wrench } from "lucide-react";
1
+ import { type JSX, type MouseEvent } from "react";
2
+ import { Wrench } from "lucide-react";
3
3
  import type { ToolTraceEvent } from "./viewerState";
4
4
  import { dispatchLogFocusRequest } from "./logFocus";
5
5
 
6
6
  type ToolTraceEventsProps = {
7
7
  events: ToolTraceEvent[];
8
- warnings?: readonly string[];
9
8
  };
10
9
 
11
- const VISIBLE_TOOL_LIMIT = 4;
10
+ const VISIBLE_TOOL_LIMIT = 3;
12
11
 
13
12
  function ToolTraceEventChip({ event }: { event: ToolTraceEvent }): JSX.Element {
13
+ const handleClick = (clickEvent: MouseEvent<HTMLButtonElement>): void => {
14
+ clickEvent.stopPropagation();
15
+ dispatchLogFocusRequest({
16
+ logId: event.logId,
17
+ tab: "response",
18
+ toolCallIndex: event.index,
19
+ });
20
+ };
21
+
14
22
  return (
15
23
  <button
16
24
  type="button"
17
- key={event.id}
18
- className="inline-flex h-6 max-w-[11rem] min-w-0 items-center gap-1 rounded-md bg-white/[0.028] px-1.5 text-[11px] text-muted-foreground transition-colors hover:bg-sky-400/[0.08] hover:text-sky-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
19
- onClick={() =>
20
- dispatchLogFocusRequest({
21
- logId: event.logId,
22
- tab: "response",
23
- toolCallIndex: event.index,
24
- })
25
- }
25
+ className="inline-flex h-5 min-w-0 max-w-[8.5rem] items-center rounded px-1.5 text-[10px] text-muted-foreground transition-colors hover:bg-background/65 hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
26
+ onClick={handleClick}
27
+ onKeyDown={(keyEvent) => keyEvent.stopPropagation()}
26
28
  aria-label={`Open response tool call ${event.name}`}
29
+ title={event.name}
27
30
  >
28
- <Wrench className="size-3 shrink-0 text-sky-400/65" />
29
31
  <span className="min-w-0 truncate font-mono font-semibold">{event.name}</span>
30
32
  </button>
31
33
  );
32
34
  }
33
35
 
34
- export function ToolTraceEvents({
35
- events,
36
- warnings = [],
37
- }: ToolTraceEventsProps): JSX.Element | null {
38
- if (events.length === 0 && warnings.length === 0) return null;
36
+ export function ToolTraceEvents({ events }: ToolTraceEventsProps): JSX.Element | null {
37
+ if (events.length === 0) return null;
39
38
  const visibleEvents = events.slice(0, VISIBLE_TOOL_LIMIT);
40
39
  const hiddenCount = Math.max(0, events.length - visibleEvents.length);
41
40
  return (
42
- <div className="mx-3 mb-2 flex min-w-0 items-center gap-1.5 overflow-hidden rounded-md bg-black/[0.10] px-2 py-1 shadow-[inset_0_1px_0_rgba(255,255,255,0.025)]">
43
- {events.length > 0 && (
44
- <span className="inline-flex h-6 shrink-0 items-center gap-1 rounded-md px-1.5 font-mono text-[10px] font-semibold uppercase tracking-[0.12em] text-sky-300/70">
45
- <Wrench className="size-3" />
46
- {events.length}
47
- </span>
48
- )}
49
- {warnings.length > 0 && (
50
- <span className="inline-flex h-6 shrink-0 items-center gap-1 rounded-md border border-amber-300/20 bg-amber-300/[0.08] px-1.5 font-mono text-[10px] font-semibold text-amber-100">
51
- <AlertTriangle className="size-3" />
52
- {warnings.length}
53
- </span>
54
- )}
55
- <div className="flex min-w-0 flex-1 items-center gap-1 overflow-hidden">
41
+ <span
42
+ className="inline-flex h-7 min-w-0 max-w-full items-center gap-1 overflow-hidden rounded-md border border-cyan-300/10 bg-cyan-300/[0.055] px-1 sm:max-w-[26rem]"
43
+ role="group"
44
+ aria-label={`${events.length} response tool ${events.length === 1 ? "call" : "calls"}`}
45
+ onClick={(clickEvent) => clickEvent.stopPropagation()}
46
+ onKeyDown={(keyEvent) => keyEvent.stopPropagation()}
47
+ >
48
+ <span className="inline-flex h-5 shrink-0 items-center gap-1 px-1 font-mono text-[9px] font-semibold uppercase text-cyan-300">
49
+ <Wrench className="size-3" />
50
+ Call {events.length}
51
+ </span>
52
+ <span className="flex min-w-0 flex-1 items-center gap-0.5 overflow-hidden">
56
53
  {visibleEvents.map((event) => (
57
54
  <ToolTraceEventChip key={event.id} event={event} />
58
55
  ))}
59
56
  {hiddenCount > 0 && (
60
- <span className="inline-flex h-6 shrink-0 items-center rounded-md bg-white/[0.025] px-1.5 font-mono text-[11px] font-semibold text-muted-foreground">
57
+ <span className="inline-flex h-5 shrink-0 items-center rounded px-1 font-mono text-[10px] font-semibold text-muted-foreground">
61
58
  +{hiddenCount}
62
59
  </span>
63
60
  )}
64
- </div>
65
- </div>
61
+ </span>
62
+ </span>
66
63
  );
67
64
  }
@@ -24,7 +24,6 @@ import {
24
24
  type LogFocusRequest,
25
25
  } from "./logFocus";
26
26
  import { ThreadConnector } from "./ThreadConnector";
27
- import { ToolTraceEvents } from "./ToolTraceEvents";
28
27
  import { extractToolTraceEvents, isTurnCollapsible, type TurnEntry } from "./viewerState";
29
28
 
30
29
  function formatElapsed(ms: number): string {
@@ -358,14 +357,11 @@ export const TurnGroup = memo(function TurnGroup({
358
357
  timeDisplayFormat={timeDisplayFormat}
359
358
  cacheTrend={cacheTrends?.get(log.id) ?? null}
360
359
  showClientMetadata={showLogClientMetadata}
360
+ toolEvents={toolEventsByLogId.get(log.id)}
361
361
  onCompareWithPrevious={
362
362
  comparisonPredecessors.has(log.id) ? onCompareWithPrevious : undefined
363
363
  }
364
364
  />
365
- <ToolTraceEvents
366
- events={toolEventsByLogId.get(log.id) ?? []}
367
- warnings={log.warnings ?? []}
368
- />
369
365
  </div>
370
366
  </div>
371
367
  );
@@ -0,0 +1,46 @@
1
+ import type { CapturedLog } from "../../contracts";
2
+
3
+ /**
4
+ * Filter logs by selected session/model. Both `__all__` and missing values
5
+ * pass through. Returns the input array reference when no log matches the
6
+ * filter, so referential equality is preserved for empty results.
7
+ */
8
+ export function filterLogs(
9
+ logs: CapturedLog[],
10
+ selectedSession: string,
11
+ selectedModel: string,
12
+ ): CapturedLog[] {
13
+ if (selectedSession === "__all__" && selectedModel === "__all__") return logs;
14
+ return logs.filter((l) => {
15
+ if (selectedSession !== "__all__" && l.sessionId !== selectedSession) return false;
16
+ if (selectedModel !== "__all__" && l.model !== selectedModel) return false;
17
+ return true;
18
+ });
19
+ }
20
+
21
+ export function mergeLogsById(
22
+ previousLogs: readonly CapturedLog[],
23
+ incomingLogs: readonly CapturedLog[],
24
+ ): CapturedLog[] {
25
+ if (previousLogs.length === 0) return [...incomingLogs];
26
+ if (incomingLogs.length === 0) return [...previousLogs];
27
+
28
+ const byId = new Map<number, CapturedLog>();
29
+ for (const log of previousLogs) byId.set(log.id, log);
30
+ for (const log of incomingLogs) byId.set(log.id, log);
31
+ return [...byId.values()].toSorted((left, right) => left.id - right.id);
32
+ }
33
+
34
+ export function mergeSessionIds(
35
+ previousSessions: readonly string[],
36
+ incomingSessions: readonly string[],
37
+ ): string[] {
38
+ const merged = new Set<string>();
39
+ for (const session of previousSessions) {
40
+ if (session !== "") merged.add(session);
41
+ }
42
+ for (const session of incomingSessions) {
43
+ if (session !== "") merged.add(session);
44
+ }
45
+ return [...merged].sort();
46
+ }