@tonyclaw/agent-inspector 2.0.3 → 2.0.4

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 (53) hide show
  1. package/.output/nitro.json +1 -1
  2. package/.output/public/assets/{CompareDrawer-D5A4bTfV.js → CompareDrawer-BCH_fsLm.js} +1 -1
  3. package/.output/public/assets/ProxyViewerContainer-D85_UANk.js +101 -0
  4. package/.output/public/assets/{ReplayDialog-CxUk_TF0.js → ReplayDialog-DTeaHHit.js} +1 -1
  5. package/.output/public/assets/RequestAnatomy-DZ8grAih.js +1 -0
  6. package/.output/public/assets/ResponseView-Cldm6RCi.js +1 -0
  7. package/.output/public/assets/{StreamingChunkSequence-DHk4SGGL.js → StreamingChunkSequence-3x4p-yT7.js} +1 -1
  8. package/.output/public/assets/_sessionId-YqWFBu6d.js +1 -0
  9. package/.output/public/assets/index-BIw2H6jO.js +1 -0
  10. package/.output/public/assets/index-CobXD0yH.css +1 -0
  11. package/.output/public/assets/{json-viewer-BbU0n8eM.js → json-viewer-BrzjD7qI.js} +1 -1
  12. package/.output/public/assets/{main-CZT_F-gu.js → main-mgxeUdZQ.js} +2 -2
  13. package/.output/server/{_sessionId-B-s9P7fJ.mjs → _sessionId-C4xsxIWm.mjs} +2 -2
  14. package/.output/server/_ssr/{CompareDrawer-C08L3UOO.mjs → CompareDrawer-DuWEpqQ7.mjs} +3 -3
  15. package/.output/server/_ssr/{ProxyViewerContainer-CMWl3Ijy.mjs → ProxyViewerContainer-Cckz5qKu.mjs} +167 -87
  16. package/.output/server/_ssr/{ReplayDialog-CPDo9_G5.mjs → ReplayDialog-BDRcr8E5.mjs} +4 -4
  17. package/.output/server/_ssr/{RequestAnatomy-D9wt_K1E.mjs → RequestAnatomy-BoO2_Ij0.mjs} +4 -4
  18. package/.output/server/_ssr/{ResponseView-DXaL7nY3.mjs → ResponseView-DZiPBxvO.mjs} +20 -16
  19. package/.output/server/_ssr/{StreamingChunkSequence-B_hudZyb.mjs → StreamingChunkSequence-D-be7KEL.mjs} +3 -3
  20. package/.output/server/_ssr/{index-CuE_BN86.mjs → index-5RImHKfu.mjs} +2 -2
  21. package/.output/server/_ssr/index.mjs +2 -2
  22. package/.output/server/_ssr/{json-viewer-Ci6kkjde.mjs → json-viewer-aJhb93ZK.mjs} +2 -2
  23. package/.output/server/_ssr/{router-BemxgIg7.mjs → router-Dgkv5nKP.mjs} +22 -14
  24. package/.output/server/{_tanstack-start-manifest_v--L1_b4sd.mjs → _tanstack-start-manifest_v-B8rrWXjr.mjs} +1 -1
  25. package/.output/server/index.mjs +61 -61
  26. package/package.json +1 -1
  27. package/src/components/ProxyViewer.tsx +25 -15
  28. package/src/components/ProxyViewerContainer.tsx +2 -1
  29. package/src/components/providers/SettingsDialog.tsx +45 -1
  30. package/src/components/proxy-viewer/AgentTraceSummary.tsx +103 -45
  31. package/src/components/proxy-viewer/AnswerMarkdown.tsx +16 -0
  32. package/src/components/proxy-viewer/ConversationGroup.tsx +12 -0
  33. package/src/components/proxy-viewer/ConversationHeader.tsx +6 -6
  34. package/src/components/proxy-viewer/LogEntry.tsx +5 -5
  35. package/src/components/proxy-viewer/LogEntryHeader.tsx +9 -14
  36. package/src/components/proxy-viewer/ResponseView.tsx +2 -6
  37. package/src/components/proxy-viewer/ToolTraceEvents.tsx +3 -4
  38. package/src/components/proxy-viewer/TurnGroup.tsx +4 -0
  39. package/src/components/proxy-viewer/anatomy/SegmentBar.tsx +2 -2
  40. package/src/components/proxy-viewer/formats/anthropic/ContentBlocks.tsx +6 -12
  41. package/src/components/proxy-viewer/formats/openai/ResponseView.tsx +10 -14
  42. package/src/lib/runtimeConfig.ts +6 -0
  43. package/src/lib/timeDisplay.ts +22 -0
  44. package/src/lib/useOnboarding.ts +2 -0
  45. package/src/lib/useStripConfig.ts +16 -0
  46. package/src/proxy/config.ts +3 -0
  47. package/src/routes/api/config.ts +5 -1
  48. package/.output/public/assets/ProxyViewerContainer-Da0jpBkp.js +0 -101
  49. package/.output/public/assets/RequestAnatomy-DIlzjgjJ.js +0 -1
  50. package/.output/public/assets/ResponseView-DQCuKJ1G.js +0 -1
  51. package/.output/public/assets/_sessionId-dY1TTl7N.js +0 -1
  52. package/.output/public/assets/index-D7wwbwly.css +0 -1
  53. package/.output/public/assets/index-FqQZbfl2.js +0 -1
@@ -1,7 +1,7 @@
1
1
  import { Brain, ChevronDown, ChevronRight, Terminal } from "lucide-react";
2
2
  import { type JSX, memo, useState } from "react";
3
- import ReactMarkdown from "react-markdown";
4
3
  import type { ResponseContentBlockType } from "../../../../proxy/schemas";
4
+ import { AnswerMarkdown } from "../../AnswerMarkdown";
5
5
  import { Badge } from "../../../ui/badge";
6
6
  import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "../../../ui/collapsible";
7
7
  import { JsonViewer } from "../../../ui/json-viewer";
@@ -30,9 +30,7 @@ function SystemReminderBlock({ text }: { text: string }): JSX.Element {
30
30
  </CollapsibleTrigger>
31
31
  <CollapsibleContent>
32
32
  <div className="pl-4 pt-1">
33
- <div className="prose prose-sm dark:prose-invert max-w-none [&_pre]:bg-muted [&_pre]:text-foreground [&_code]:text-[0.8em] [&_p]:my-1 [&_ul]:my-1 [&_ol]:my-1">
34
- <ReactMarkdown>{text}</ReactMarkdown>
35
- </div>
33
+ <AnswerMarkdown text={text} />
36
34
  </div>
37
35
  </CollapsibleContent>
38
36
  </Collapsible>
@@ -50,11 +48,7 @@ export const TextBlock = memo(function TextBlock({ text }: { text: string }): JS
50
48
  return (
51
49
  <div className="space-y-2">
52
50
  {thinking !== null && <ThinkingBlock thinking={thinking} />}
53
- {remainingText.length > 0 && (
54
- <div className="prose prose-sm dark:prose-invert max-w-none [&_pre]:bg-muted [&_pre]:text-foreground [&_code]:text-[0.8em] [&_p]:my-1 [&_ul]:my-1 [&_ol]:my-1">
55
- <ReactMarkdown>{remainingText}</ReactMarkdown>
56
- </div>
57
- )}
51
+ {remainingText.length > 0 && <AnswerMarkdown text={remainingText} />}
58
52
  {thinking === null && remainingText.length === 0 && (
59
53
  <p className="text-xs text-muted-foreground italic">Empty text block</p>
60
54
  )}
@@ -113,9 +107,9 @@ export const ToolUseBlock = memo(function ToolUseBlock({
113
107
 
114
108
  return (
115
109
  <Collapsible open={open} onOpenChange={setOpen}>
116
- <div className="border-l-2 border-blue-500/40 my-1">
117
- <CollapsibleTrigger className="flex items-center gap-1.5 px-3 py-1 w-full text-left cursor-pointer hover:bg-blue-500/5 transition-colors rounded-r-sm group">
118
- <Terminal className="size-3.5 text-blue-400 shrink-0" />
110
+ <div className="border-l-2 border-sky-400/25 my-1">
111
+ <CollapsibleTrigger className="flex items-center gap-1.5 px-3 py-1 w-full text-left cursor-pointer hover:bg-sky-400/[0.04] transition-colors rounded-r-sm group">
112
+ <Terminal className="size-3.5 text-sky-400/70 shrink-0" />
119
113
  <Badge variant="outline" className="text-[10px] font-mono px-1.5 py-0 h-4">
120
114
  {name}
121
115
  </Badge>
@@ -1,8 +1,8 @@
1
1
  import { StopCircle, Terminal, Zap } from "lucide-react";
2
2
  import { memo, useState, type JSX } from "react";
3
- import ReactMarkdown from "react-markdown";
4
3
  import type { OpenAIResponse, OpenAIToolCall } from "../../../../proxy/schemas";
5
4
  import { formatTokens } from "../../../../lib/utils";
5
+ import { AnswerMarkdown } from "../../AnswerMarkdown";
6
6
  import { Badge } from "../../../ui/badge";
7
7
  import { JsonViewer } from "../../../ui/json-viewer";
8
8
  import { safeJsonValue } from "../../../ui/json-viewer-bulk";
@@ -29,8 +29,8 @@ function parseToolArguments(raw: string | undefined): unknown {
29
29
  }
30
30
 
31
31
  /** One collapsible tool_use row, mirroring the Anthropic ToolUseBlock visual
32
- * treatment (Terminal icon, blue accent, name as a Badge, JSON input in a
33
- * scrollable JsonViewer). */
32
+ * treatment (Terminal icon, soft tool accent, name as a Badge, JSON input in
33
+ * a scrollable JsonViewer). */
34
34
  function OpenAIToolCallBlock({ call }: { call: OpenAIToolCall }): JSX.Element {
35
35
  const [open, setOpen] = useState(false);
36
36
  const name = call.function.name ?? "(unnamed tool)";
@@ -38,9 +38,9 @@ function OpenAIToolCallBlock({ call }: { call: OpenAIToolCall }): JSX.Element {
38
38
 
39
39
  return (
40
40
  <Collapsible open={open} onOpenChange={setOpen}>
41
- <div className="border-l-2 border-blue-500/40 my-1">
42
- <CollapsibleTrigger className="flex items-center gap-1.5 px-3 py-1 w-full text-left cursor-pointer hover:bg-blue-500/5 transition-colors rounded-r-sm group">
43
- <Terminal className="size-3.5 text-blue-400 shrink-0" />
41
+ <div className="border-l-2 border-sky-400/25 my-1">
42
+ <CollapsibleTrigger className="flex items-center gap-1.5 px-3 py-1 w-full text-left cursor-pointer hover:bg-sky-400/[0.04] transition-colors rounded-r-sm group">
43
+ <Terminal className="size-3.5 text-sky-400/70 shrink-0" />
44
44
  <Badge variant="outline" className="text-[10px] font-mono px-1.5 py-0 h-4">
45
45
  {name}
46
46
  </Badge>
@@ -133,11 +133,7 @@ export const OpenAIResponseView = memo(function OpenAIResponseView({
133
133
  <div className="space-y-2">
134
134
  {/* Show thinking from tags only if no reasoning_content field */}
135
135
  {thinking !== null && !hasReasoningField && <ThinkingBlock thinking={thinking} />}
136
- {remainingText.length > 0 && (
137
- <div className="prose prose-sm dark:prose-invert max-w-none [&_pre]:bg-muted [&_pre]:text-foreground [&_code]:text-[0.8em] [&_p]:my-1 [&_ul]:my-1 [&_ol]:my-1">
138
- <ReactMarkdown>{remainingText}</ReactMarkdown>
139
- </div>
140
- )}
136
+ {remainingText.length > 0 && <AnswerMarkdown text={remainingText} />}
141
137
  </div>
142
138
  );
143
139
  })()}
@@ -146,10 +142,10 @@ export const OpenAIResponseView = memo(function OpenAIResponseView({
146
142
  <OpenAIToolCallBlock key={call.id ?? `tc-${i}`} call={call} />
147
143
  ))}
148
144
  {message?.function_call !== null && message?.function_call !== undefined && (
149
- <div className="border border-blue-500/30 rounded-md p-3 bg-blue-500/5">
150
- <div className="text-xs text-blue-400 font-mono mb-1">function_call</div>
145
+ <div className="border border-sky-400/20 rounded-md p-3 bg-muted/20">
146
+ <div className="text-xs text-sky-400/80 font-mono mb-1">function_call</div>
151
147
  <div className="font-mono text-xs">
152
- <span className="text-blue-300">{message.function_call.name}</span>
148
+ <span className="text-foreground/80">{message.function_call.name}</span>
153
149
  <span className="text-muted-foreground">({message.function_call.arguments})</span>
154
150
  </div>
155
151
  </div>
@@ -2,6 +2,11 @@ import { z } from "zod";
2
2
 
3
3
  export const DEFAULT_SLOW_RESPONSE_THRESHOLD_SECONDS = 10;
4
4
  export const MAX_SLOW_RESPONSE_THRESHOLD_SECONDS = 600;
5
+ export const DEFAULT_TIME_DISPLAY_FORMAT = "time";
6
+
7
+ export const TimeDisplayFormatSchema = z.enum(["time", "full"]);
8
+
9
+ export type TimeDisplayFormat = z.infer<typeof TimeDisplayFormatSchema>;
5
10
 
6
11
  /**
7
12
  * Schema for the runtime proxy config. Shared between server
@@ -20,6 +25,7 @@ export const RuntimeConfigSchema = z.object({
20
25
  .min(0)
21
26
  .max(MAX_SLOW_RESPONSE_THRESHOLD_SECONDS)
22
27
  .default(DEFAULT_SLOW_RESPONSE_THRESHOLD_SECONDS),
28
+ timeDisplayFormat: TimeDisplayFormatSchema.default(DEFAULT_TIME_DISPLAY_FORMAT),
23
29
  });
24
30
 
25
31
  export type RuntimeConfig = z.infer<typeof RuntimeConfigSchema>;
@@ -0,0 +1,22 @@
1
+ import type { TimeDisplayFormat } from "./runtimeConfig";
2
+
3
+ export function formatTimestamp(iso: string, format: TimeDisplayFormat): string {
4
+ switch (format) {
5
+ case "full":
6
+ return iso;
7
+ case "time":
8
+ return new Date(iso).toLocaleTimeString([], {
9
+ hour: "2-digit",
10
+ minute: "2-digit",
11
+ second: "2-digit",
12
+ });
13
+ }
14
+ }
15
+
16
+ export function formatTimestampRange(
17
+ startedAt: string,
18
+ endedAt: string,
19
+ format: TimeDisplayFormat,
20
+ ): string {
21
+ return `${formatTimestamp(startedAt, format)} - ${formatTimestamp(endedAt, format)}`;
22
+ }
@@ -2,6 +2,7 @@ import useSWR, { type SWRResponse, useSWRConfig } from "swr";
2
2
  import { fetchJson } from "./apiClient";
3
3
  import {
4
4
  DEFAULT_SLOW_RESPONSE_THRESHOLD_SECONDS,
5
+ DEFAULT_TIME_DISPLAY_FORMAT,
5
6
  RuntimeConfigSchema,
6
7
  type RuntimeConfig,
7
8
  } from "./runtimeConfig";
@@ -66,6 +67,7 @@ export function useOnboarding(): UseOnboarding {
66
67
  hasSeenOnboarding: true,
67
68
  slowResponseThresholdSeconds:
68
69
  response.data?.slowResponseThresholdSeconds ?? DEFAULT_SLOW_RESPONSE_THRESHOLD_SECONDS,
70
+ timeDisplayFormat: response.data?.timeDisplayFormat ?? DEFAULT_TIME_DISPLAY_FORMAT,
69
71
  },
70
72
  rollbackOnError: true,
71
73
  revalidate: false,
@@ -2,7 +2,9 @@ import useSWR, { type SWRResponse, useSWRConfig } from "swr";
2
2
  import { fetchJson } from "./apiClient";
3
3
  import {
4
4
  DEFAULT_SLOW_RESPONSE_THRESHOLD_SECONDS,
5
+ DEFAULT_TIME_DISPLAY_FORMAT,
5
6
  RuntimeConfigSchema,
7
+ type TimeDisplayFormat,
6
8
  type RuntimeConfig,
7
9
  } from "./runtimeConfig";
8
10
 
@@ -36,10 +38,12 @@ export async function setRuntimeConfig(patch: Partial<RuntimeConfig>): Promise<R
36
38
  export type UseStripConfig = {
37
39
  strip: boolean;
38
40
  slowResponseThresholdSeconds: number;
41
+ timeDisplayFormat: TimeDisplayFormat;
39
42
  isLoading: boolean;
40
43
  isError: boolean;
41
44
  setStrip: (next: boolean) => Promise<void>;
42
45
  setSlowResponseThresholdSeconds: (next: number) => Promise<void>;
46
+ setTimeDisplayFormat: (next: TimeDisplayFormat) => Promise<void>;
43
47
  };
44
48
 
45
49
  /**
@@ -64,12 +68,14 @@ export function useStripConfig(): UseStripConfig {
64
68
  const strip = response.data?.stripClaudeCodeBillingHeader ?? false;
65
69
  const slowResponseThresholdSeconds =
66
70
  response.data?.slowResponseThresholdSeconds ?? DEFAULT_SLOW_RESPONSE_THRESHOLD_SECONDS;
71
+ const timeDisplayFormat = response.data?.timeDisplayFormat ?? DEFAULT_TIME_DISPLAY_FORMAT;
67
72
 
68
73
  const optimisticConfig = (patch: Partial<RuntimeConfig>): RuntimeConfig => ({
69
74
  stripClaudeCodeBillingHeader: response.data?.stripClaudeCodeBillingHeader ?? false,
70
75
  hasSeenOnboarding: response.data?.hasSeenOnboarding ?? false,
71
76
  slowResponseThresholdSeconds:
72
77
  response.data?.slowResponseThresholdSeconds ?? DEFAULT_SLOW_RESPONSE_THRESHOLD_SECONDS,
78
+ timeDisplayFormat: response.data?.timeDisplayFormat ?? DEFAULT_TIME_DISPLAY_FORMAT,
73
79
  ...patch,
74
80
  });
75
81
 
@@ -97,12 +103,22 @@ export function useStripConfig(): UseStripConfig {
97
103
  );
98
104
  };
99
105
 
106
+ const setTimeDisplayFormat = async (next: TimeDisplayFormat): Promise<void> => {
107
+ await globalMutate(STRIP_CONFIG_SWR_KEY, setRuntimeConfig({ timeDisplayFormat: next }), {
108
+ optimisticData: optimisticConfig({ timeDisplayFormat: next }),
109
+ rollbackOnError: true,
110
+ revalidate: false,
111
+ });
112
+ };
113
+
100
114
  return {
101
115
  strip,
102
116
  slowResponseThresholdSeconds,
117
+ timeDisplayFormat,
103
118
  isLoading: response.isLoading,
104
119
  isError: response.error !== undefined,
105
120
  setStrip,
106
121
  setSlowResponseThresholdSeconds,
122
+ setTimeDisplayFormat,
107
123
  };
108
124
  }
@@ -12,6 +12,7 @@ import { logger } from "./logger";
12
12
  import { getDataDir } from "./dataDir";
13
13
  import {
14
14
  DEFAULT_SLOW_RESPONSE_THRESHOLD_SECONDS,
15
+ DEFAULT_TIME_DISPLAY_FORMAT,
15
16
  RuntimeConfigSchema,
16
17
  type RuntimeConfig,
17
18
  } from "../lib/runtimeConfig";
@@ -79,6 +80,7 @@ function resolveInitialConfig(): RuntimeConfig {
79
80
  stripClaudeCodeBillingHeader: true,
80
81
  hasSeenOnboarding: false,
81
82
  slowResponseThresholdSeconds: DEFAULT_SLOW_RESPONSE_THRESHOLD_SECONDS,
83
+ timeDisplayFormat: DEFAULT_TIME_DISPLAY_FORMAT,
82
84
  };
83
85
  }
84
86
 
@@ -87,6 +89,7 @@ function resolveInitialConfig(): RuntimeConfig {
87
89
  stripClaudeCodeBillingHeader: false,
88
90
  hasSeenOnboarding: false,
89
91
  slowResponseThresholdSeconds: DEFAULT_SLOW_RESPONSE_THRESHOLD_SECONDS,
92
+ timeDisplayFormat: DEFAULT_TIME_DISPLAY_FORMAT,
90
93
  };
91
94
  }
92
95
 
@@ -1,6 +1,9 @@
1
1
  import { createFileRoute } from "@tanstack/react-router";
2
2
  import { z } from "zod";
3
- import { MAX_SLOW_RESPONSE_THRESHOLD_SECONDS } from "../../lib/runtimeConfig";
3
+ import {
4
+ MAX_SLOW_RESPONSE_THRESHOLD_SECONDS,
5
+ TimeDisplayFormatSchema,
6
+ } from "../../lib/runtimeConfig";
4
7
  import { getConfig, setConfig, RuntimeConfigSchema } from "../../proxy/config";
5
8
 
6
9
  // Partial schema for PATCH: at least one known field must be present.
@@ -14,6 +17,7 @@ const RuntimeConfigPatchSchema = z
14
17
  .min(0)
15
18
  .max(MAX_SLOW_RESPONSE_THRESHOLD_SECONDS)
16
19
  .optional(),
20
+ timeDisplayFormat: TimeDisplayFormatSchema.optional(),
17
21
  })
18
22
  .strict()
19
23
  .refine((v) => Object.keys(v).length > 0, {