@tonyclaw/agent-inspector 3.0.8 → 3.0.9

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 (40) hide show
  1. package/.output/nitro.json +1 -1
  2. package/.output/public/assets/{CompareDrawer-Bth_Ywyt.js → CompareDrawer-CJKL4LMm.js} +1 -1
  3. package/.output/public/assets/ProxyViewerContainer-DBUy29O-.js +106 -0
  4. package/.output/public/assets/{ReplayDialog-C2YYAuTe.js → ReplayDialog-BYanl-a_.js} +1 -1
  5. package/.output/public/assets/{RequestAnatomy-8k9dAX2j.js → RequestAnatomy-DvPz1jqE.js} +1 -1
  6. package/.output/public/assets/{ResponseView-DEL6JcXm.js → ResponseView-sZnxp9GN.js} +2 -2
  7. package/.output/public/assets/{StreamingChunkSequence-DngmoR9j.js → StreamingChunkSequence-G-tiYiBd.js} +1 -1
  8. package/.output/public/assets/{_sessionId-4vk9RMZ5.js → _sessionId-_hDcsmXq.js} +1 -1
  9. package/.output/public/assets/agent-inspector-58K1_MsC.ico +0 -0
  10. package/.output/public/assets/index-DAPAWsAd.js +1 -0
  11. package/.output/public/assets/index-DspnLqUW.css +1 -0
  12. package/.output/public/assets/{index-DINLvnm9.js → index-SuOSQb2_.js} +1 -1
  13. package/.output/public/assets/{json-viewer-CH5dvS2Y.js → json-viewer-yQdhgjaw.js} +1 -1
  14. package/.output/public/assets/{main-GWkZn4xy.js → main-CgjcDxjR.js} +2 -2
  15. package/.output/server/_libs/radix-ui__react-dialog.mjs +2 -2
  16. package/.output/server/{_sessionId-EgsjdkN7.mjs → _sessionId-BGISf2En.mjs} +2 -2
  17. package/.output/server/_ssr/{CompareDrawer-CaM8FYuD.mjs → CompareDrawer-s-UF9gW3.mjs} +2 -2
  18. package/.output/server/_ssr/{ProxyViewerContainer-EJIogcGd.mjs → ProxyViewerContainer-C0Sbz9ED.mjs} +496 -229
  19. package/.output/server/_ssr/{ReplayDialog-BPpJ2-q8.mjs → ReplayDialog-DvS8gvJr.mjs} +3 -3
  20. package/.output/server/_ssr/{RequestAnatomy-DeQAWnZx.mjs → RequestAnatomy-BwhWglJL.mjs} +2 -2
  21. package/.output/server/_ssr/{ResponseView-Dshm8iQ7.mjs → ResponseView-wBVreqQf.mjs} +2 -2
  22. package/.output/server/_ssr/{StreamingChunkSequence-32yIU2hn.mjs → StreamingChunkSequence-Dr6eg-MJ.mjs} +2 -2
  23. package/.output/server/_ssr/{index-XRcx9blU.mjs → index-B98Wia1X.mjs} +2 -2
  24. package/.output/server/_ssr/index.mjs +2 -2
  25. package/.output/server/_ssr/{json-viewer-C0aX5rqC.mjs → json-viewer-D7L8y0FH.mjs} +2 -2
  26. package/.output/server/_ssr/{router-BI-Mvxz9.mjs → router-g9mo0nWT.mjs} +22 -28
  27. package/.output/server/{_tanstack-start-manifest_v-jKScklL_.mjs → _tanstack-start-manifest_v-CbGc-o50.mjs} +1 -1
  28. package/.output/server/index.mjs +74 -67
  29. package/package.json +1 -1
  30. package/src/components/ProxyViewer.tsx +194 -29
  31. package/src/components/ProxyViewerContainer.tsx +137 -3
  32. package/src/components/clients/ClientLogo.tsx +16 -1
  33. package/src/components/proxy-viewer/TurnGroup.tsx +0 -16
  34. package/src/components/proxy-viewer/log-formats/anthropic.ts +5 -5
  35. package/src/components/proxy-viewer/log-formats/openai.ts +7 -10
  36. package/src/components/proxy-viewer/requestTools.ts +5 -2
  37. package/src/routes/api/providers.$providerId.test.log.ts +28 -24
  38. package/.output/public/assets/ProxyViewerContainer-C73EU9Jq.js +0 -106
  39. package/.output/public/assets/index-DBEB1rHe.css +0 -1
  40. package/.output/public/assets/index-LPIGiUMP.js +0 -1
@@ -4,8 +4,15 @@ import ClaudeCodeLogoSvg from "../../assets/IDE/claudecode-color.svg";
4
4
  import CodexLogoSvg from "../../assets/IDE/codex-color.svg";
5
5
  import OpenCodeLogoSvg from "../../assets/IDE/opencode.svg";
6
6
  import MiMoCodeLogoSvg from "../../assets/IDE/xiaomimimo.svg";
7
+ import AgentInspectorLogo from "../../assets/agent-inspector.ico";
7
8
 
8
- export type ClientApp = "codex" | "opencode" | "mimo-code" | "claude-code" | "unknown";
9
+ export type ClientApp =
10
+ | "agent-inspector"
11
+ | "codex"
12
+ | "opencode"
13
+ | "mimo-code"
14
+ | "claude-code"
15
+ | "unknown";
9
16
 
10
17
  export type ClientAppDetectionInput = {
11
18
  userAgent?: string | null;
@@ -14,6 +21,7 @@ export type ClientAppDetectionInput = {
14
21
  };
15
22
 
16
23
  const CLIENT_LABELS: Record<Exclude<ClientApp, "unknown">, string> = {
24
+ "agent-inspector": "Inspector",
17
25
  codex: "Codex",
18
26
  opencode: "OpenCode",
19
27
  "mimo-code": "MiMo Code",
@@ -38,6 +46,9 @@ export function detectClientApp(input: ClientAppDetectionInput): ClientApp {
38
46
  normalize(input.clientProjectFolder),
39
47
  ].join(" ");
40
48
 
49
+ if (matchesAny(haystack, ["agent-inspector", "agent inspector", "provider-test"])) {
50
+ return "agent-inspector";
51
+ }
41
52
  if (matchesAny(haystack, ["mimocode", "mimo-code", "mimo code"])) return "mimo-code";
42
53
  if (matchesAny(haystack, ["opencode", "open-code", "open code"])) return "opencode";
43
54
  if (matchesAny(haystack, ["claude-code", "claude code", "claudecode"])) return "claude-code";
@@ -50,6 +61,7 @@ export function detectClientApp(input: ClientAppDetectionInput): ClientApp {
50
61
 
51
62
  export function clientAppLabel(client: ClientApp): string | null {
52
63
  switch (client) {
64
+ case "agent-inspector":
53
65
  case "codex":
54
66
  case "opencode":
55
67
  case "mimo-code":
@@ -61,6 +73,7 @@ export function clientAppLabel(client: ClientApp): string | null {
61
73
  }
62
74
 
63
75
  const CLIENT_LOGOS: Record<Exclude<ClientApp, "unknown">, string> = {
76
+ "agent-inspector": AgentInspectorLogo,
64
77
  codex: CodexLogoSvg,
65
78
  opencode: OpenCodeLogoSvg,
66
79
  "mimo-code": MiMoCodeLogoSvg,
@@ -68,6 +81,7 @@ const CLIENT_LOGOS: Record<Exclude<ClientApp, "unknown">, string> = {
68
81
  };
69
82
 
70
83
  const CLIENT_LOGO_FRAMES: Record<Exclude<ClientApp, "unknown">, string> = {
84
+ "agent-inspector": "border-orange-200/25 bg-orange-300/[0.12]",
71
85
  codex: "border-cyan-200/20 bg-cyan-300/[0.08]",
72
86
  opencode: "border-sky-200/25 bg-sky-300/[0.12]",
73
87
  "mimo-code": "border-orange-200/25 bg-orange-400/[0.12]",
@@ -75,6 +89,7 @@ const CLIENT_LOGO_FRAMES: Record<Exclude<ClientApp, "unknown">, string> = {
75
89
  };
76
90
 
77
91
  const CLIENT_LOGO_IMAGES: Record<Exclude<ClientApp, "unknown">, string> = {
92
+ "agent-inspector": "p-0.5 drop-shadow-[0_0_8px_rgba(251,146,60,0.35)]",
78
93
  codex: "p-0.5",
79
94
  opencode: "p-1 drop-shadow-[0_0_8px_rgba(125,211,252,0.35)]",
80
95
  "mimo-code": "p-0.5 drop-shadow-[0_0_8px_rgba(255,105,0,0.35)]",
@@ -217,13 +217,6 @@ export const TurnGroup = memo(function TurnGroup({
217
217
  }
218
218
  }}
219
219
  >
220
- {/* Turn number */}
221
- <div className="w-5 shrink-0 flex items-start pt-1.5">
222
- <span className="text-[10px] text-muted-foreground/50 font-mono tabular-nums leading-none select-none">
223
- {turnIndex + 1}
224
- </span>
225
- </div>
226
-
227
220
  <div className="w-6 shrink-0 flex flex-col items-center pt-1.5 pb-1.5">
228
221
  <div className="flex justify-center h-[calc(0.75rem-8px)]" />
229
222
  <CollapsedCrab
@@ -344,15 +337,6 @@ export const TurnGroup = memo(function TurnGroup({
344
337
 
345
338
  return (
346
339
  <div key={log.id} className="flex items-stretch">
347
- {isTurnStart ? (
348
- <div className="w-5 shrink-0 flex items-start pt-1.5">
349
- <span className="text-[10px] text-muted-foreground/50 font-mono tabular-nums leading-none select-none">
350
- {turnIndex + 1}
351
- </span>
352
- </div>
353
- ) : (
354
- <div className="w-5 shrink-0" />
355
- )}
356
340
  <ThreadConnector
357
341
  stopReason={reason}
358
342
  isPending={log.responseStatus === null}
@@ -1,6 +1,7 @@
1
1
  import { AnthropicRequestSchema, AnthropicResponseSchema } from "../../../contracts/anthropic";
2
2
  import type { AnatomySegment } from "../anatomy/types";
3
3
  import { countCharacters, estimateTokens } from "../anatomy/tokenEstimate";
4
+ import { parseRequestTools } from "../requestTools";
4
5
  import type { LogFormatAdapter } from "./types";
5
6
  import { emptyRequestAnalysis, EMPTY_RESPONSE_ANALYSIS } from "./types";
6
7
 
@@ -113,16 +114,15 @@ export const anthropicLogFormatAdapter: LogFormatAdapter = {
113
114
  analyzeRequest(rawBody) {
114
115
  if (rawBody === null) return emptyRequestAnalysis(rawBody);
115
116
  try {
116
- const result = AnthropicRequestSchema.safeParse(JSON.parse(rawBody));
117
+ const parsedBody: unknown = JSON.parse(rawBody);
118
+ const toolCount = parseRequestTools(parsedBody)?.tools.length ?? null;
119
+ const result = AnthropicRequestSchema.safeParse(parsedBody);
117
120
  if (!result.success) return emptyRequestAnalysis(rawBody);
118
121
  return {
119
122
  parsed: result.data,
120
123
  comparisonValue: result.data,
121
124
  messageCount: result.data.messages.length,
122
- toolCount:
123
- result.data.tools !== undefined && result.data.tools.length > 0
124
- ? result.data.tools.length
125
- : null,
125
+ toolCount,
126
126
  };
127
127
  } catch {
128
128
  return emptyRequestAnalysis(rawBody);
@@ -7,6 +7,7 @@ import {
7
7
  import { safeGetOwnProperty } from "../../../lib/objectUtils";
8
8
  import type { AnatomySegment } from "../anatomy/types";
9
9
  import { countCharacters, estimateTokens } from "../anatomy/tokenEstimate";
10
+ import { parseRequestTools } from "../requestTools";
10
11
  import type { LogFormatAdapter } from "./types";
11
12
  import { emptyRequestAnalysis, EMPTY_RESPONSE_ANALYSIS } from "./types";
12
13
 
@@ -146,28 +147,24 @@ export const openAILogFormatAdapter: LogFormatAdapter = {
146
147
  analyzeRequest(rawBody) {
147
148
  if (rawBody === null) return emptyRequestAnalysis(rawBody);
148
149
  try {
149
- const result = OpenAIRequestSchema.safeParse(JSON.parse(rawBody));
150
+ const parsedBody: unknown = JSON.parse(rawBody);
151
+ const toolCount = parseRequestTools(parsedBody)?.tools.length ?? null;
152
+ const result = OpenAIRequestSchema.safeParse(parsedBody);
150
153
  if (!result.success) {
151
- const responsesResult = OpenAIResponsesRequestSchema.safeParse(JSON.parse(rawBody));
154
+ const responsesResult = OpenAIResponsesRequestSchema.safeParse(parsedBody);
152
155
  if (!responsesResult.success) return emptyRequestAnalysis(rawBody);
153
156
  return {
154
157
  parsed: responsesResult.data,
155
158
  comparisonValue: responsesResult.data,
156
159
  messageCount: countResponsesInput(responsesResult.data.input),
157
- toolCount:
158
- responsesResult.data.tools !== undefined && responsesResult.data.tools.length > 0
159
- ? responsesResult.data.tools.length
160
- : null,
160
+ toolCount,
161
161
  };
162
162
  }
163
163
  return {
164
164
  parsed: result.data,
165
165
  comparisonValue: result.data,
166
166
  messageCount: result.data.messages.length,
167
- toolCount:
168
- result.data.tools !== undefined && result.data.tools.length > 0
169
- ? result.data.tools.length
170
- : null,
167
+ toolCount,
171
168
  };
172
169
  } catch {
173
170
  return emptyRequestAnalysis(rawBody);
@@ -145,8 +145,11 @@ function parseAnthropicTool(tool: unknown): RequestToolDefinition | null {
145
145
  function parseOpenAITool(tool: unknown): RequestToolDefinition | null {
146
146
  const fn = safeGetOwnProperty(tool, "function");
147
147
  const toolType = safeGetOwnProperty(tool, "type");
148
- if (fn === undefined && toolType !== "function") return null;
149
- const name = safeGetOwnProperty(fn, "name") ?? safeGetOwnProperty(tool, "name");
148
+ if (fn === undefined && typeof toolType !== "string") return null;
149
+ const name =
150
+ safeGetOwnProperty(fn, "name") ??
151
+ safeGetOwnProperty(tool, "name") ??
152
+ (typeof toolType === "string" ? toolType : undefined);
150
153
  if (typeof name !== "string" || name.length === 0) return null;
151
154
  const description =
152
155
  safeGetOwnProperty(fn, "description") ?? safeGetOwnProperty(tool, "description");
@@ -1,4 +1,5 @@
1
1
  import { createFileRoute } from "@tanstack/react-router";
2
+ import { basename } from "node:path";
2
3
  import { getProvider, getModelUsageName } from "../../proxy/providers";
3
4
  import { addTestLogEntry } from "../../proxy/store";
4
5
  import { getConfig } from "../../proxy/config";
@@ -51,6 +52,27 @@ function getResultTokensPerSecond(result: TestResult): number | null {
51
52
  );
52
53
  }
53
54
 
55
+ function providerTestClientFields(providerName: string): {
56
+ userAgent: string;
57
+ origin: null;
58
+ isTest: true;
59
+ providerName: string;
60
+ clientPid: number;
61
+ clientCwd: string;
62
+ clientProjectFolder: string;
63
+ } {
64
+ const cwd = process.cwd();
65
+ return {
66
+ userAgent: "Agent Inspector Provider Test",
67
+ origin: null,
68
+ isTest: true,
69
+ providerName,
70
+ clientPid: process.pid,
71
+ clientCwd: cwd,
72
+ clientProjectFolder: basename(cwd),
73
+ };
74
+ }
75
+
54
76
  async function logModelResults(
55
77
  displayName: string,
56
78
  providerName: string,
@@ -90,11 +112,8 @@ async function logModelResults(
90
112
  totalStreamMs: null,
91
113
  tokensPerSecond: null,
92
114
  streaming: false,
93
- userAgent: "provider-test",
94
- origin: null,
95
115
  apiFormat: "anthropic",
96
- isTest: true,
97
- providerName,
116
+ ...providerTestClientFields(providerName),
98
117
  headers: captureFullDetails ? getResultHeaders(nonStreamingResult) : undefined,
99
118
  });
100
119
 
@@ -121,11 +140,8 @@ async function logModelResults(
121
140
  tokensPerSecond: getResultTokensPerSecond(streamingResult),
122
141
  streaming: true,
123
142
  streamingChunks: captureFullDetails ? streamingResult.streamingChunks : undefined,
124
- userAgent: "provider-test",
125
- origin: null,
126
143
  apiFormat: "anthropic",
127
- isTest: true,
128
- providerName,
144
+ ...providerTestClientFields(providerName),
129
145
  headers: captureFullDetails ? getResultHeaders(streamingResult) : undefined,
130
146
  });
131
147
  }
@@ -158,11 +174,8 @@ async function logModelResults(
158
174
  totalStreamMs: null,
159
175
  tokensPerSecond: null,
160
176
  streaming: false,
161
- userAgent: "provider-test",
162
- origin: null,
163
177
  apiFormat: "openai",
164
- isTest: true,
165
- providerName,
178
+ ...providerTestClientFields(providerName),
166
179
  headers: captureFullDetails ? getResultHeaders(nonStreamingResult) : undefined,
167
180
  });
168
181
 
@@ -189,11 +202,8 @@ async function logModelResults(
189
202
  tokensPerSecond: getResultTokensPerSecond(streamingResult),
190
203
  streaming: true,
191
204
  streamingChunks: captureFullDetails ? streamingResult.streamingChunks : undefined,
192
- userAgent: "provider-test",
193
- origin: null,
194
205
  apiFormat: "openai",
195
- isTest: true,
196
- providerName,
206
+ ...providerTestClientFields(providerName),
197
207
  headers: captureFullDetails ? getResultHeaders(streamingResult) : undefined,
198
208
  });
199
209
  }
@@ -228,11 +238,8 @@ async function logModelResults(
228
238
  totalStreamMs: null,
229
239
  tokensPerSecond: null,
230
240
  streaming: false,
231
- userAgent: "provider-test",
232
- origin: null,
233
241
  apiFormat: "openai",
234
- isTest: true,
235
- providerName,
242
+ ...providerTestClientFields(providerName),
236
243
  headers: captureFullDetails ? getResultHeaders(nonStreamingResult) : undefined,
237
244
  });
238
245
 
@@ -259,11 +266,8 @@ async function logModelResults(
259
266
  tokensPerSecond: getResultTokensPerSecond(streamingResult),
260
267
  streaming: true,
261
268
  streamingChunks: captureFullDetails ? streamingResult.streamingChunks : undefined,
262
- userAgent: "provider-test",
263
- origin: null,
264
269
  apiFormat: "openai",
265
- isTest: true,
266
- providerName,
270
+ ...providerTestClientFields(providerName),
267
271
  headers: captureFullDetails ? getResultHeaders(streamingResult) : undefined,
268
272
  });
269
273
  }