@tonyclaw/agent-inspector 2.0.13 → 2.0.15
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/cli.js +84 -0
- package/.output/nitro.json +1 -1
- package/.output/public/assets/{CompareDrawer-CrMyE23D.js → CompareDrawer-B6WCFRJq.js} +1 -1
- package/.output/public/assets/{ProxyViewerContainer-BZuo0px3.js → ProxyViewerContainer-CofGRJoO.js} +31 -31
- package/.output/public/assets/{ReplayDialog-TQGhDdTa.js → ReplayDialog-O_53zkX8.js} +1 -1
- package/.output/public/assets/{RequestAnatomy-D6kQYtfa.js → RequestAnatomy-CqBSMZv5.js} +1 -1
- package/.output/public/assets/{ResponseView-C6ybWuB8.js → ResponseView-BvbA6zot.js} +1 -1
- package/.output/public/assets/{StreamingChunkSequence-Bvs59_-I.js → StreamingChunkSequence-Bnf6djjc.js} +1 -1
- package/.output/public/assets/_sessionId-9ICCw6YA.js +1 -0
- package/.output/public/assets/index-DVkMYH8H.js +1 -0
- package/.output/public/assets/{main-DvFSJlOd.js → main-Biir9ZGe.js} +2 -2
- package/.output/server/{_sessionId-DHYJxPb7.mjs → _sessionId-B77Gh4IL.mjs} +2 -2
- package/.output/server/_ssr/{CompareDrawer-meimDBeA.mjs → CompareDrawer-D4-RHFqW.mjs} +2 -2
- package/.output/server/_ssr/{ProxyViewerContainer-Co-WKq6u.mjs → ProxyViewerContainer-YP28-_2H.mjs} +31 -10
- package/.output/server/_ssr/{ReplayDialog-cclcGyR9.mjs → ReplayDialog-D9rQlrcY.mjs} +3 -3
- package/.output/server/_ssr/{RequestAnatomy-to_rezzu.mjs → RequestAnatomy-BXCRWD9H.mjs} +2 -2
- package/.output/server/_ssr/{ResponseView-CZZI4IZd.mjs → ResponseView-DEwWMqSS.mjs} +2 -2
- package/.output/server/_ssr/{StreamingChunkSequence-BTF4xSYX.mjs → StreamingChunkSequence-CdrTPf5v.mjs} +2 -2
- package/.output/server/_ssr/{index-D2fpJFP5.mjs → index-Chf1DYqT.mjs} +2 -2
- package/.output/server/_ssr/index.mjs +2 -2
- package/.output/server/_ssr/{router-RDBAF-Iu.mjs → router-BHXU5jWm.mjs} +89 -46
- package/.output/server/{_tanstack-start-manifest_v-DB9sseoH.mjs → _tanstack-start-manifest_v-D1dtacWy.mjs} +1 -1
- package/.output/server/index.mjs +59 -59
- package/README.md +141 -1
- package/package.json +1 -1
- package/src/cli.ts +91 -0
- package/src/components/ProxyViewer.tsx +32 -24
- package/src/components/ProxyViewerContainer.tsx +2 -1
- package/src/components/providers/SettingsDialog.tsx +10 -0
- package/src/lib/runtimeConfig.ts +4 -0
- package/src/lib/useStripConfig.ts +10 -2
- package/src/proxy/config.ts +33 -3
- package/src/proxy/handler.ts +30 -13
- package/src/proxy/logFinalizer.ts +4 -2
- package/src/routes/api/providers.$providerId.test.log.ts +17 -7
- package/.output/public/assets/_sessionId-BNG_mnaH.js +0 -1
- package/.output/public/assets/index-BUxIwHhC.js +0 -1
package/src/proxy/handler.ts
CHANGED
|
@@ -36,16 +36,21 @@ import {
|
|
|
36
36
|
* Strips all custom/non-standard headers from the request and replaces with
|
|
37
37
|
* unified proxy identity. Only preserves standard HTTP headers needed for API calls.
|
|
38
38
|
*/
|
|
39
|
-
function buildProxyHeaders(
|
|
39
|
+
function buildProxyHeaders(
|
|
40
|
+
originalHeaders: Headers,
|
|
41
|
+
captureRawHeaders: boolean,
|
|
42
|
+
): {
|
|
40
43
|
headers: Headers;
|
|
41
|
-
rawHeaders: Record<string, string
|
|
44
|
+
rawHeaders: Record<string, string> | undefined;
|
|
42
45
|
} {
|
|
43
|
-
const rawHeaders: Record<string, string> = {};
|
|
46
|
+
const rawHeaders: Record<string, string> | undefined = captureRawHeaders ? {} : undefined;
|
|
44
47
|
const headers = new Headers();
|
|
45
48
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
+
if (rawHeaders !== undefined) {
|
|
50
|
+
originalHeaders.forEach((value, key) => {
|
|
51
|
+
rawHeaders[key.toLowerCase()] = value;
|
|
52
|
+
});
|
|
53
|
+
}
|
|
49
54
|
|
|
50
55
|
headers.set(HEADER_USER_AGENT, PROXY_IDENTITY);
|
|
51
56
|
headers.set(HEADER_X_PROXY_IDENTITY, PROXY_IDENTITY);
|
|
@@ -128,6 +133,7 @@ function handleStreamingResponse(
|
|
|
128
133
|
startTime: number,
|
|
129
134
|
upstreamUrl: string,
|
|
130
135
|
log: CapturedLog,
|
|
136
|
+
collectStreamingChunks: boolean,
|
|
131
137
|
): Response {
|
|
132
138
|
log.streaming = true;
|
|
133
139
|
log.responseStatus = upstreamRes.status;
|
|
@@ -151,6 +157,7 @@ function handleStreamingResponse(
|
|
|
151
157
|
elapsedMs,
|
|
152
158
|
responseStatus: upstreamRes.status,
|
|
153
159
|
rawStream: full,
|
|
160
|
+
collectStreamingChunks,
|
|
154
161
|
});
|
|
155
162
|
},
|
|
156
163
|
});
|
|
@@ -175,6 +182,7 @@ function handleStreamingResponse(
|
|
|
175
182
|
elapsedMs,
|
|
176
183
|
rawStream: full,
|
|
177
184
|
hasChunks,
|
|
185
|
+
collectStreamingChunks,
|
|
178
186
|
});
|
|
179
187
|
}
|
|
180
188
|
});
|
|
@@ -208,8 +216,9 @@ export async function handleProxy(req: Request): Promise<Response> {
|
|
|
208
216
|
// Important: the original `requestBody` must be preserved so the log stores
|
|
209
217
|
// the unmodified request (the "Raw Request" tab needs the true bytes the
|
|
210
218
|
// client sent). The rewritten body is only used for the upstream fetch.
|
|
219
|
+
const config = getConfig();
|
|
211
220
|
let bodyToForward = requestBody;
|
|
212
|
-
if (
|
|
221
|
+
if (config.stripClaudeCodeBillingHeader && requestBody !== null && parsed.isMessages) {
|
|
213
222
|
const stripped = stripClaudeCodeBillingHeader(requestBody);
|
|
214
223
|
if (stripped.removed > 0) {
|
|
215
224
|
logger.info(
|
|
@@ -248,7 +257,11 @@ export async function handleProxy(req: Request): Promise<Response> {
|
|
|
248
257
|
const upstreamUrl = buildUpstreamUrl(upstreamBase, parsed.normalizedPath);
|
|
249
258
|
const startTime = Date.now();
|
|
250
259
|
|
|
251
|
-
const
|
|
260
|
+
const captureFullDetails = config.captureMode === "full";
|
|
261
|
+
const { headers: upstreamHeaders, rawHeaders } = buildProxyHeaders(
|
|
262
|
+
req.headers,
|
|
263
|
+
captureFullDetails,
|
|
264
|
+
);
|
|
252
265
|
setUpstreamHost(upstreamHeaders, upstreamBase);
|
|
253
266
|
injectProviderAuth(upstreamHeaders, matchedProviderConfig);
|
|
254
267
|
|
|
@@ -277,10 +290,14 @@ export async function handleProxy(req: Request): Promise<Response> {
|
|
|
277
290
|
// full PowerShell round-trip on top of everything else before
|
|
278
291
|
// `fetch` is even issued.
|
|
279
292
|
const [clientInfo, preAcquiredId] = await Promise.all([getClientInfo(req), getNextLogId()]);
|
|
280
|
-
const upstreamHeadersObj: Record<string, string> =
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
293
|
+
const upstreamHeadersObj: Record<string, string> | undefined = captureFullDetails
|
|
294
|
+
? {}
|
|
295
|
+
: undefined;
|
|
296
|
+
if (upstreamHeadersObj !== undefined) {
|
|
297
|
+
upstreamHeaders.forEach((value, key) => {
|
|
298
|
+
upstreamHeadersObj[key.toLowerCase()] = value;
|
|
299
|
+
});
|
|
300
|
+
}
|
|
284
301
|
const log = await createLog(
|
|
285
302
|
req.method,
|
|
286
303
|
parsed.apiPath,
|
|
@@ -330,5 +347,5 @@ export async function handleProxy(req: Request): Promise<Response> {
|
|
|
330
347
|
return handleNonStreamingResponse(upstreamRes, responseBody, startTime, upstreamUrl, log);
|
|
331
348
|
}
|
|
332
349
|
|
|
333
|
-
return handleStreamingResponse(upstreamRes, req, startTime, upstreamUrl, log);
|
|
350
|
+
return handleStreamingResponse(upstreamRes, req, startTime, upstreamUrl, log, captureFullDetails);
|
|
334
351
|
}
|
|
@@ -22,12 +22,14 @@ export type FinalizeStreamingLogJob = BaseFinalizeLogJob & {
|
|
|
22
22
|
type: "streaming";
|
|
23
23
|
responseStatus: number;
|
|
24
24
|
rawStream: string;
|
|
25
|
+
collectStreamingChunks: boolean;
|
|
25
26
|
};
|
|
26
27
|
|
|
27
28
|
export type FinalizeStreamAbortLogJob = BaseFinalizeLogJob & {
|
|
28
29
|
type: "stream-abort";
|
|
29
30
|
rawStream: string;
|
|
30
31
|
hasChunks: boolean;
|
|
32
|
+
collectStreamingChunks: boolean;
|
|
31
33
|
};
|
|
32
34
|
|
|
33
35
|
export type FinalizeLogJob =
|
|
@@ -145,7 +147,7 @@ function finalizeStreaming(job: FinalizeStreamingLogJob, log: CapturedLog): Fina
|
|
|
145
147
|
job.rawStream,
|
|
146
148
|
log,
|
|
147
149
|
log.model ?? undefined,
|
|
148
|
-
|
|
150
|
+
job.collectStreamingChunks,
|
|
149
151
|
);
|
|
150
152
|
persistStreamingChunks(log);
|
|
151
153
|
|
|
@@ -168,7 +170,7 @@ function finalizeStreamAbort(job: FinalizeStreamAbortLogJob, log: CapturedLog):
|
|
|
168
170
|
job.rawStream,
|
|
169
171
|
log,
|
|
170
172
|
log.model ?? undefined,
|
|
171
|
-
|
|
173
|
+
job.collectStreamingChunks,
|
|
172
174
|
);
|
|
173
175
|
persistStreamingChunks(log);
|
|
174
176
|
} else {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { createFileRoute } from "@tanstack/react-router";
|
|
2
2
|
import { getProvider, getModelUsageName } from "../../proxy/providers";
|
|
3
3
|
import { addTestLogEntry } from "../../proxy/store";
|
|
4
|
+
import { getConfig } from "../../proxy/config";
|
|
4
5
|
import { buildProviderTestRequestBody } from "../../lib/providerTestPrompt";
|
|
5
6
|
import {
|
|
6
7
|
ProviderTestResultsSchema,
|
|
@@ -21,6 +22,7 @@ async function logModelResults(
|
|
|
21
22
|
anthropic: { nonStreaming: ProviderTestState; streaming: ProviderTestState };
|
|
22
23
|
openai: { nonStreaming: ProviderTestState; streaming: ProviderTestState };
|
|
23
24
|
},
|
|
25
|
+
captureFullDetails: boolean,
|
|
24
26
|
): Promise<void> {
|
|
25
27
|
const usageModel = getModelUsageName(displayName, providerName);
|
|
26
28
|
|
|
@@ -53,7 +55,7 @@ async function logModelResults(
|
|
|
53
55
|
apiFormat: "anthropic",
|
|
54
56
|
isTest: true,
|
|
55
57
|
providerName,
|
|
56
|
-
headers: nonStreamingResult.requestHeaders ?? {},
|
|
58
|
+
headers: captureFullDetails ? (nonStreamingResult.requestHeaders ?? {}) : undefined,
|
|
57
59
|
});
|
|
58
60
|
|
|
59
61
|
const streamingRequestBody = JSON.stringify(
|
|
@@ -75,13 +77,13 @@ async function logModelResults(
|
|
|
75
77
|
cacheReadInputTokens: streamingResult.cacheReadInputTokens ?? null,
|
|
76
78
|
elapsedMs: streamingResult.latencyMs ?? 0,
|
|
77
79
|
streaming: true,
|
|
78
|
-
streamingChunks: streamingResult.streamingChunks,
|
|
80
|
+
streamingChunks: captureFullDetails ? streamingResult.streamingChunks : undefined,
|
|
79
81
|
userAgent: "provider-test",
|
|
80
82
|
origin: null,
|
|
81
83
|
apiFormat: "anthropic",
|
|
82
84
|
isTest: true,
|
|
83
85
|
providerName,
|
|
84
|
-
headers: streamingResult.requestHeaders ?? {},
|
|
86
|
+
headers: captureFullDetails ? (streamingResult.requestHeaders ?? {}) : undefined,
|
|
85
87
|
});
|
|
86
88
|
}
|
|
87
89
|
}
|
|
@@ -115,7 +117,7 @@ async function logModelResults(
|
|
|
115
117
|
apiFormat: "openai",
|
|
116
118
|
isTest: true,
|
|
117
119
|
providerName,
|
|
118
|
-
headers: nonStreamingResult.requestHeaders ?? {},
|
|
120
|
+
headers: captureFullDetails ? (nonStreamingResult.requestHeaders ?? {}) : undefined,
|
|
119
121
|
});
|
|
120
122
|
|
|
121
123
|
const streamingRequestBody = JSON.stringify(
|
|
@@ -137,13 +139,13 @@ async function logModelResults(
|
|
|
137
139
|
cacheReadInputTokens: null,
|
|
138
140
|
elapsedMs: streamingResult.latencyMs ?? 0,
|
|
139
141
|
streaming: true,
|
|
140
|
-
streamingChunks: streamingResult.streamingChunks,
|
|
142
|
+
streamingChunks: captureFullDetails ? streamingResult.streamingChunks : undefined,
|
|
141
143
|
userAgent: "provider-test",
|
|
142
144
|
origin: null,
|
|
143
145
|
apiFormat: "openai",
|
|
144
146
|
isTest: true,
|
|
145
147
|
providerName,
|
|
146
|
-
headers: streamingResult.requestHeaders ?? {},
|
|
148
|
+
headers: captureFullDetails ? (streamingResult.requestHeaders ?? {}) : undefined,
|
|
147
149
|
});
|
|
148
150
|
}
|
|
149
151
|
}
|
|
@@ -174,6 +176,7 @@ export const Route = createFileRoute("/api/providers/$providerId/test/log")({
|
|
|
174
176
|
}
|
|
175
177
|
|
|
176
178
|
const results = parsed.data;
|
|
179
|
+
const captureFullDetails = getConfig().captureMode === "full";
|
|
177
180
|
const anthropicUrl =
|
|
178
181
|
provider.anthropicBaseUrl !== undefined && provider.anthropicBaseUrl.length > 0
|
|
179
182
|
? provider.anthropicBaseUrl
|
|
@@ -187,7 +190,14 @@ export const Route = createFileRoute("/api/providers/$providerId/test/log")({
|
|
|
187
190
|
if (results.models !== undefined) {
|
|
188
191
|
for (const [modelName, modelResult] of Object.entries(results.models)) {
|
|
189
192
|
entries.push(
|
|
190
|
-
logModelResults(
|
|
193
|
+
logModelResults(
|
|
194
|
+
modelName,
|
|
195
|
+
provider.name,
|
|
196
|
+
anthropicUrl,
|
|
197
|
+
openaiUrl,
|
|
198
|
+
modelResult,
|
|
199
|
+
captureFullDetails,
|
|
200
|
+
),
|
|
191
201
|
);
|
|
192
202
|
}
|
|
193
203
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{R as s,j as e}from"./main-DvFSJlOd.js";import{P as i}from"./ProxyViewerContainer-BZuo0px3.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-BZuo0px3.js";import"./main-DvFSJlOd.js";const r=o;export{r as component};
|