@tonyclaw/agent-inspector 2.0.3 → 2.0.5

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 (68) hide show
  1. package/.output/nitro.json +1 -1
  2. package/.output/public/assets/{CompareDrawer-D5A4bTfV.js → CompareDrawer-3nRwtk8J.js} +1 -1
  3. package/.output/public/assets/ProxyViewerContainer-CbW5VRER.js +101 -0
  4. package/.output/public/assets/ReplayDialog-Cl62N9PI.js +1 -0
  5. package/.output/public/assets/RequestAnatomy-DgQWGvjs.js +1 -0
  6. package/.output/public/assets/ResponseView-Cvc-ct4E.js +1 -0
  7. package/.output/public/assets/StreamingChunkSequence-BCQaCAIe.js +1 -0
  8. package/.output/public/assets/_sessionId-CcD_aLGq.js +1 -0
  9. package/.output/public/assets/index-B_dffD3u.js +1 -0
  10. package/.output/public/assets/index-CX796gvi.css +1 -0
  11. package/.output/public/assets/{json-viewer-BbU0n8eM.js → json-viewer-IXejqXB0.js} +1 -1
  12. package/.output/public/assets/{main-CZT_F-gu.js → main-2NlGzgOe.js} +2 -2
  13. package/.output/server/_libs/lucide-react.mjs +181 -114
  14. package/.output/server/{_sessionId-B-s9P7fJ.mjs → _sessionId-DWCTasJU.mjs} +3 -3
  15. package/.output/server/_ssr/{CompareDrawer-C08L3UOO.mjs → CompareDrawer-DhrN1uC2.mjs} +6 -6
  16. package/.output/server/_ssr/{ProxyViewerContainer-CMWl3Ijy.mjs → ProxyViewerContainer-DRl51s_n.mjs} +910 -186
  17. package/.output/server/_ssr/{ReplayDialog-CPDo9_G5.mjs → ReplayDialog-BQT_ygxC.mjs} +240 -14
  18. package/.output/server/_ssr/{RequestAnatomy-D9wt_K1E.mjs → RequestAnatomy-DS2tZOgq.mjs} +5 -5
  19. package/.output/server/_ssr/{ResponseView-DXaL7nY3.mjs → ResponseView-e0kL2C3x.mjs} +25 -21
  20. package/.output/server/_ssr/{StreamingChunkSequence-B_hudZyb.mjs → StreamingChunkSequence-BJG-m7xs.mjs} +3 -3
  21. package/.output/server/_ssr/{index-CuE_BN86.mjs → index-Dea3OeRw.mjs} +2 -2
  22. package/.output/server/_ssr/index.mjs +2 -2
  23. package/.output/server/_ssr/{json-viewer-Ci6kkjde.mjs → json-viewer-DDU55MLK.mjs} +3 -3
  24. package/.output/server/_ssr/{router-BemxgIg7.mjs → router-Dl7oh0zx.mjs} +164 -82
  25. package/.output/server/_tanstack-start-manifest_v-m-FJNBVf.mjs +4 -0
  26. package/.output/server/index.mjs +70 -70
  27. package/package.json +1 -1
  28. package/src/components/OnboardingBanner.tsx +11 -19
  29. package/src/components/ProxyViewer.tsx +26 -16
  30. package/src/components/ProxyViewerContainer.tsx +2 -1
  31. package/src/components/providers/ProviderCard.tsx +6 -20
  32. package/src/components/providers/SettingsDialog.tsx +140 -3
  33. package/src/components/proxy-viewer/AgentTraceSummary.tsx +731 -72
  34. package/src/components/proxy-viewer/AnswerMarkdown.tsx +16 -0
  35. package/src/components/proxy-viewer/CompareDrawer.tsx +4 -2
  36. package/src/components/proxy-viewer/ConversationGroup.tsx +12 -0
  37. package/src/components/proxy-viewer/ConversationHeader.tsx +6 -6
  38. package/src/components/proxy-viewer/LogEntry.tsx +5 -5
  39. package/src/components/proxy-viewer/LogEntryHeader.tsx +21 -36
  40. package/src/components/proxy-viewer/ReplayDialog.tsx +190 -8
  41. package/src/components/proxy-viewer/ResponseView.tsx +4 -8
  42. package/src/components/proxy-viewer/ToolTraceEvents.tsx +37 -17
  43. package/src/components/proxy-viewer/TurnGroup.tsx +18 -2
  44. package/src/components/proxy-viewer/anatomy/SegmentBar.tsx +2 -2
  45. package/src/components/proxy-viewer/formats/anthropic/ContentBlocks.tsx +6 -12
  46. package/src/components/proxy-viewer/formats/anthropic/ResponseView.tsx +2 -2
  47. package/src/components/proxy-viewer/formats/openai/ResponseView.tsx +10 -14
  48. package/src/components/proxy-viewer/replayComparison.ts +131 -0
  49. package/src/components/proxy-viewer/useKeyboardNavigation.ts +64 -22
  50. package/src/components/proxy-viewer/viewerState.ts +14 -2
  51. package/src/knowledge/candidateStore.ts +32 -1
  52. package/src/lib/runtimeConfig.ts +6 -0
  53. package/src/lib/timeDisplay.ts +22 -0
  54. package/src/lib/useOnboarding.ts +2 -0
  55. package/src/lib/useStripConfig.ts +16 -0
  56. package/src/proxy/config.ts +3 -0
  57. package/src/routes/api/config.ts +5 -1
  58. package/src/routes/api/knowledge.candidates.$candidateId.ts +50 -0
  59. package/src/routes/api/knowledge.sessions.$sessionId.candidates.ts +12 -2
  60. package/.output/public/assets/ProxyViewerContainer-Da0jpBkp.js +0 -101
  61. package/.output/public/assets/ReplayDialog-CxUk_TF0.js +0 -1
  62. package/.output/public/assets/RequestAnatomy-DIlzjgjJ.js +0 -1
  63. package/.output/public/assets/ResponseView-DQCuKJ1G.js +0 -1
  64. package/.output/public/assets/StreamingChunkSequence-DHk4SGGL.js +0 -1
  65. package/.output/public/assets/_sessionId-dY1TTl7N.js +0 -1
  66. package/.output/public/assets/index-D7wwbwly.css +0 -1
  67. package/.output/public/assets/index-FqQZbfl2.js +0 -1
  68. package/.output/server/_tanstack-start-manifest_v--L1_b4sd.mjs +0 -4
@@ -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, {
@@ -0,0 +1,50 @@
1
+ import { createFileRoute } from "@tanstack/react-router";
2
+ import { z } from "zod";
3
+ import { getCandidate, updateCandidateDraft } from "../../knowledge/candidateStore";
4
+ import { KnowledgeCandidateSchema, KnowledgeCandidateTypeSchema } from "../../knowledge/types";
5
+
6
+ const CandidateUpdateSchema = z
7
+ .object({
8
+ type: KnowledgeCandidateTypeSchema.optional(),
9
+ title: z.string().trim().min(1).max(160).optional(),
10
+ content: z.string().trim().min(1).max(12000).optional(),
11
+ tags: z.array(z.string().trim().min(1).max(64)).max(24).optional(),
12
+ })
13
+ .strict();
14
+
15
+ const CandidateUpdateResponseSchema = z.object({
16
+ candidate: KnowledgeCandidateSchema,
17
+ });
18
+
19
+ export type CandidateUpdateResponse = z.infer<typeof CandidateUpdateResponseSchema>;
20
+
21
+ export const Route = createFileRoute("/api/knowledge/candidates/$candidateId")({
22
+ server: {
23
+ handlers: {
24
+ PATCH: async ({ params, request }: { params: { candidateId: string }; request: Request }) => {
25
+ const existing = getCandidate(params.candidateId);
26
+ if (existing === null) {
27
+ return Response.json({ error: "Knowledge candidate not found" }, { status: 404 });
28
+ }
29
+ if (existing.status === "promoted") {
30
+ return Response.json(
31
+ { error: "Promoted knowledge candidates cannot be edited" },
32
+ { status: 409 },
33
+ );
34
+ }
35
+
36
+ const raw: unknown = await request.json().catch(() => null);
37
+ const parsed = CandidateUpdateSchema.safeParse(raw);
38
+ if (!parsed.success) {
39
+ return Response.json({ error: parsed.error.message }, { status: 400 });
40
+ }
41
+
42
+ const updated = updateCandidateDraft(existing.id, parsed.data);
43
+ if (updated === null) {
44
+ return Response.json({ error: "Knowledge candidate update failed" }, { status: 409 });
45
+ }
46
+ return Response.json({ candidate: updated } satisfies CandidateUpdateResponse);
47
+ },
48
+ },
49
+ },
50
+ });
@@ -1,13 +1,23 @@
1
1
  import { createFileRoute } from "@tanstack/react-router";
2
- import { getFilteredLogs } from "../../proxy/store";
2
+ import { getFilteredLogs, getLogSessionId } from "../../proxy/store";
3
3
  import { distillSessionCandidates } from "../../knowledge/distiller";
4
4
  import { saveCandidates } from "../../knowledge/candidateStore";
5
5
 
6
+ function getCandidateScopeId(log: ReturnType<typeof getFilteredLogs>[number]): string {
7
+ return getLogSessionId(log) ?? "default";
8
+ }
9
+
10
+ function getLogsForCandidateScope(scopeId: string): ReturnType<typeof getFilteredLogs> {
11
+ const direct = getFilteredLogs(scopeId);
12
+ if (direct.length > 0) return direct;
13
+ return getFilteredLogs().filter((log) => getCandidateScopeId(log) === scopeId);
14
+ }
15
+
6
16
  export const Route = createFileRoute("/api/knowledge/sessions/$sessionId/candidates")({
7
17
  server: {
8
18
  handlers: {
9
19
  POST: ({ params }: { params: { sessionId: string } }) => {
10
- const logs = getFilteredLogs(params.sessionId);
20
+ const logs = getLogsForCandidateScope(params.sessionId);
11
21
  const candidates = saveCandidates(distillSessionCandidates(params.sessionId, logs));
12
22
  return Response.json({ candidates });
13
23
  },