@tonyclaw/agent-inspector 2.0.20 → 2.0.22
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 +10 -0
- package/.output/nitro.json +1 -1
- package/.output/public/assets/{CompareDrawer-CUqYtaH3.js → CompareDrawer-NEdpe1wl.js} +1 -1
- package/.output/public/assets/ProxyViewerContainer-Dwhi4Q1c.js +115 -0
- package/.output/public/assets/{ReplayDialog-CPXNEqVg.js → ReplayDialog-DijzJwaQ.js} +1 -1
- package/.output/public/assets/{RequestAnatomy-qkj8QgkY.js → RequestAnatomy-CYbosGYy.js} +1 -1
- package/.output/public/assets/{ResponseView-BPNLZpuw.js → ResponseView-B3dPM63X.js} +1 -1
- package/.output/public/assets/{StreamingChunkSequence-DGs-YFXI.js → StreamingChunkSequence-DYDx3xRY.js} +1 -1
- package/.output/public/assets/_sessionId-b1KDnByv.js +1 -0
- package/.output/public/assets/index-780zTVwp.css +1 -0
- package/.output/public/assets/index-CUyRKgII.js +1 -0
- package/.output/public/assets/{main-j3vS8rmP.js → main-N-sjHJUM.js} +2 -2
- package/.output/server/_libs/lucide-react.mjs +27 -27
- package/.output/server/{_sessionId-Bc5Nohhe.mjs → _sessionId-BR46y_bO.mjs} +2 -2
- package/.output/server/_ssr/{CompareDrawer-D0UewydM.mjs → CompareDrawer-DDxpmdPs.mjs} +3 -3
- package/.output/server/_ssr/{ProxyViewerContainer-BEUWt2eX.mjs → ProxyViewerContainer-B1zAefzz.mjs} +304 -55
- package/.output/server/_ssr/{ReplayDialog-zaN-xMOw.mjs → ReplayDialog-DleMFvMx.mjs} +4 -4
- package/.output/server/_ssr/{RequestAnatomy-BMomYged.mjs → RequestAnatomy-B-P9tC3D.mjs} +3 -3
- package/.output/server/_ssr/{ResponseView-DSoHCyAM.mjs → ResponseView-DWfGn0i3.mjs} +3 -3
- package/.output/server/_ssr/{StreamingChunkSequence-pt3pZOOL.mjs → StreamingChunkSequence-C8kFF6xJ.mjs} +3 -3
- package/.output/server/_ssr/{index-BCTKxcgV.mjs → index-DzENi2RO.mjs} +2 -2
- package/.output/server/_ssr/index.mjs +2 -2
- package/.output/server/_ssr/{router-DpaDa5q5.mjs → router-Dy1VEjxy.mjs} +434 -80
- package/.output/server/{_tanstack-start-manifest_v-EsubwO0A.mjs → _tanstack-start-manifest_v-CyzuAD8A.mjs} +1 -1
- package/.output/server/index.mjs +55 -55
- package/package.json +1 -1
- package/src/cli/templates/codex-skill-onboard.ts +5 -0
- package/src/cli/templates/skill-onboard.ts +5 -0
- package/src/components/OnboardingBanner.tsx +4 -0
- package/src/components/ProxyViewer.tsx +5 -0
- package/src/components/providers/ProviderCard.tsx +178 -38
- package/src/components/providers/ProviderForm.tsx +107 -16
- package/src/components/providers/ProvidersPanel.tsx +21 -3
- package/src/components/providers/SettingsDialog.tsx +76 -2
- package/src/lib/providerModelMetadata.ts +67 -3
- package/src/lib/providerTestContract.ts +13 -0
- package/src/lib/runtimeConfig.ts +8 -0
- package/src/lib/useOnboarding.ts +3 -0
- package/src/lib/useStripConfig.ts +22 -0
- package/src/proxy/config.ts +4 -0
- package/src/proxy/formats/index.ts +1 -0
- package/src/proxy/formats/openai/index.ts +1 -0
- package/src/proxy/formats/openai/zhipuProvider.ts +31 -0
- package/src/proxy/providerImporters.ts +47 -0
- package/src/proxy/providers.ts +55 -0
- package/src/proxy/upstream.ts +25 -0
- package/src/routes/api/config.ts +7 -0
- package/src/routes/api/providers.$providerId.test.log.ts +28 -12
- package/.output/public/assets/ProxyViewerContainer-CX0-R0nn.js +0 -114
- package/.output/public/assets/_sessionId-CXtbrFTj.js +0 -1
- package/.output/public/assets/index-DrppF281.js +0 -1
- package/.output/public/assets/index-DynnYt7S.css +0 -1
|
@@ -50,7 +50,7 @@ import "../_libs/mimic-function.mjs";
|
|
|
50
50
|
import "../_libs/semver.mjs";
|
|
51
51
|
import "../_libs/uint8array-extras.mjs";
|
|
52
52
|
const faviconSvg = "data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2064%2064'%20role='img'%20aria-label='Agent%20Inspector'%3e%3crect%20width='64'%20height='64'%20rx='14'%20fill='%23111827'%20/%3e%3cg%20fill='none'%20stroke='%23f59e0b'%20stroke-width='4.2'%20stroke-linecap='round'%20stroke-linejoin='round'%3e%3cpath%20fill='%23f59e0b'%20d='M15%2036c0-11%207-18%2017-18s17%207%2017%2018c0%208-7%2013-17%2013s-17-5-17-13z'%20/%3e%3cpath%20d='M16%2031c-6-5-12-3-12%204%200%205%206%206%2011%202'%20/%3e%3cpath%20d='M48%2031c6-5%2012-3%2012%204%200%205-6%206-11%202'%20/%3e%3cpath%20d='M27%2019l-3-7'%20/%3e%3cpath%20d='M37%2019l3-7'%20/%3e%3cpath%20d='M19%2045l-6%209'%20/%3e%3cpath%20d='M27%2048l-3%209'%20/%3e%3cpath%20d='M37%2048l3%209'%20/%3e%3cpath%20d='M45%2045l6%209'%20/%3e%3c/g%3e%3cpath%20d='M14%2047l9-8%208%209c-5%203.5-12%203-17-1z'%20fill='%232f6b3f'%20opacity='.95'%20/%3e%3cpath%20d='M18%2046l5-5%205%206c-3%201.6-7%201.4-10-1z'%20fill='%236fb36f'%20opacity='.95'%20/%3e%3cpath%20d='M23%2041v10'%20fill='none'%20stroke='%23d6b45f'%20stroke-width='1.6'%20stroke-linecap='round'%20/%3e%3ccircle%20cx='31'%20cy='48'%20r='1.8'%20fill='%23c2412d'%20/%3e%3cpath%20d='M24%2044l13-11%2014%2013c-8%205.8-18%205.3-27-2z'%20fill='%232f6b3f'%20opacity='.97'%20/%3e%3cpath%20d='M30%2043l7-7%209%209c-5%202.7-11%202.5-16-2z'%20fill='%236fb36f'%20opacity='.95'%20/%3e%3cpath%20d='M37%2036v14'%20fill='none'%20stroke='%23d6b45f'%20stroke-width='2'%20stroke-linecap='round'%20/%3e%3cpath%20d='M30%2043c5-2%2011-1.5%2016%202'%20fill='none'%20stroke='%239fca78'%20stroke-width='1.8'%20stroke-linecap='round'%20/%3e%3ccircle%20cx='51'%20cy='46'%20r='2'%20fill='%23c2412d'%20/%3e%3cpath%20d='M40%2050l8-8%207%208c-4.2%203.2-10%203-15%200z'%20fill='%232f6b3f'%20opacity='.95'%20/%3e%3cpath%20d='M43%2049l5-5%204.5%205.5c-3%201.5-6%201.2-9.5-.5z'%20fill='%236fb36f'%20opacity='.95'%20/%3e%3cpath%20d='M48%2044v9'%20fill='none'%20stroke='%23d6b45f'%20stroke-width='1.5'%20stroke-linecap='round'%20/%3e%3ccircle%20cx='55'%20cy='50'%20r='1.7'%20fill='%23c2412d'%20/%3e%3ccircle%20cx='24'%20cy='11'%20r='3.2'%20fill='%23f59e0b'%20/%3e%3ccircle%20cx='40'%20cy='11'%20r='3.2'%20fill='%23f59e0b'%20/%3e%3ccircle%20cx='25'%20cy='34'%20r='2.1'%20fill='%23111827'%20/%3e%3ccircle%20cx='39'%20cy='34'%20r='2.1'%20fill='%23111827'%20/%3e%3c/svg%3e";
|
|
53
|
-
const appCss = "/assets/index-
|
|
53
|
+
const appCss = "/assets/index-780zTVwp.css";
|
|
54
54
|
const Route$s = createRootRoute({
|
|
55
55
|
head: () => ({
|
|
56
56
|
meta: [
|
|
@@ -93,7 +93,7 @@ function RootDocument({ children }) {
|
|
|
93
93
|
] })
|
|
94
94
|
] });
|
|
95
95
|
}
|
|
96
|
-
const $$splitComponentImporter$1 = () => import("./index-
|
|
96
|
+
const $$splitComponentImporter$1 = () => import("./index-DzENi2RO.mjs");
|
|
97
97
|
const Route$r = createFileRoute("/")({
|
|
98
98
|
component: lazyRouteComponent($$splitComponentImporter$1, "component")
|
|
99
99
|
});
|
|
@@ -136,7 +136,7 @@ function decodeSessionIdFromPath(encoded) {
|
|
|
136
136
|
function getSessionPath(sessionId) {
|
|
137
137
|
return `/session/${encodeSessionIdForPath(sessionId)}`;
|
|
138
138
|
}
|
|
139
|
-
const $$splitComponentImporter = () => import("../_sessionId-
|
|
139
|
+
const $$splitComponentImporter = () => import("../_sessionId-BR46y_bO.mjs");
|
|
140
140
|
const Route$q = createFileRoute("/session/$sessionId")({
|
|
141
141
|
component: lazyRouteComponent($$splitComponentImporter, "component"),
|
|
142
142
|
parseParams: (params) => ({
|
|
@@ -2406,6 +2406,22 @@ const openaiProvider = {
|
|
|
2406
2406
|
}
|
|
2407
2407
|
};
|
|
2408
2408
|
registry.register(openaiProvider);
|
|
2409
|
+
const DEFAULT_ZHIPU_UPSTREAM = "https://open.bigmodel.cn/api/paas/v4";
|
|
2410
|
+
const ZHIPU_MODEL_PREFIXES$1 = ["glm-", "charglm-", "cogview-", "embedding-", "rerank-"];
|
|
2411
|
+
const zhipuProvider = {
|
|
2412
|
+
name: "zhipu",
|
|
2413
|
+
matches(model) {
|
|
2414
|
+
const normalized = model.toLowerCase().replace(/\s+/g, "-");
|
|
2415
|
+
return ZHIPU_MODEL_PREFIXES$1.some((prefix) => normalized.startsWith(prefix));
|
|
2416
|
+
},
|
|
2417
|
+
getUpstreamBase(_isChatCompletions, providerConfig) {
|
|
2418
|
+
return providerConfig?.baseUrl ?? DEFAULT_ZHIPU_UPSTREAM;
|
|
2419
|
+
},
|
|
2420
|
+
extractStream(raw, log, fallbackModel, collectChunks) {
|
|
2421
|
+
return extractOpenAIStream(raw, log, fallbackModel, collectChunks);
|
|
2422
|
+
}
|
|
2423
|
+
};
|
|
2424
|
+
registry.register(zhipuProvider);
|
|
2409
2425
|
const DEFAULT_ALIBABA_UPSTREAM = "https://dashscope.aliyuncs.com/compatible-mode/v1";
|
|
2410
2426
|
const alibabaProvider = {
|
|
2411
2427
|
name: "alibaba",
|
|
@@ -2483,6 +2499,10 @@ const HF_MINIMAX_M3_URL = "https://huggingface.co/MiniMaxAI/MiniMax-M3";
|
|
|
2483
2499
|
const HF_MINIMAX_M2_7_URL = "https://huggingface.co/MiniMaxAI/MiniMax-M2.7";
|
|
2484
2500
|
const HF_MINIMAX_M2_5_URL = "https://huggingface.co/MiniMaxAI/MiniMax-M2.5";
|
|
2485
2501
|
const HF_MINIMAX_M2_1_URL = "https://huggingface.co/MiniMaxAI/MiniMax-M2.1";
|
|
2502
|
+
const ZHIPU_GLM_4_5_URL = "https://docs.bigmodel.cn/cn/guide/models/text/glm-4.5";
|
|
2503
|
+
const ZHIPU_GLM_4_6_URL = "https://docs.bigmodel.cn/cn/guide/models/text/glm-4.6";
|
|
2504
|
+
const ZHIPU_GLM_4_7_URL = "https://docs.bigmodel.cn/cn/guide/models/text/glm-4.7";
|
|
2505
|
+
const ZHIPU_GLM_5_TURBO_URL = "https://docs.bigmodel.cn/cn/guide/models/text/glm-5-turbo";
|
|
2486
2506
|
const HF_GLM_5_URL = "https://huggingface.co/zai-org/GLM-5";
|
|
2487
2507
|
const HF_GLM_5_1_URL = "https://huggingface.co/zai-org/GLM-5.1";
|
|
2488
2508
|
const HF_GLM_5_2_URL = "https://huggingface.co/zai-org/GLM-5.2";
|
|
@@ -2557,10 +2577,63 @@ const BUILTIN_PROVIDER_MODEL_REGISTRY = {
|
|
|
2557
2577
|
]
|
|
2558
2578
|
},
|
|
2559
2579
|
{
|
|
2560
|
-
name: "
|
|
2561
|
-
aliases: ["glm", "zai", "zhipu", "bigmodel"],
|
|
2562
|
-
baseUrls: [
|
|
2580
|
+
name: "ZhipuAI",
|
|
2581
|
+
aliases: ["glm", "zai", "zhipu", "zhipuai", "bigmodel"],
|
|
2582
|
+
baseUrls: [
|
|
2583
|
+
"https://open.bigmodel.cn/api/paas/v4",
|
|
2584
|
+
"https://open.bigmodel.cn/api/coding/paas/v4",
|
|
2585
|
+
"https://open.bigmodel.cn/api/anthropic"
|
|
2586
|
+
],
|
|
2563
2587
|
models: [
|
|
2588
|
+
{
|
|
2589
|
+
id: "glm-4.5",
|
|
2590
|
+
aliases: ["GLM-4.5"],
|
|
2591
|
+
contextWindow: 131072,
|
|
2592
|
+
outputLimit: 98304,
|
|
2593
|
+
sourceUrl: ZHIPU_GLM_4_5_URL
|
|
2594
|
+
},
|
|
2595
|
+
{
|
|
2596
|
+
id: "glm-4.5-air",
|
|
2597
|
+
aliases: ["GLM-4.5-Air"],
|
|
2598
|
+
contextWindow: 131072,
|
|
2599
|
+
outputLimit: 98304,
|
|
2600
|
+
sourceUrl: ZHIPU_GLM_4_5_URL
|
|
2601
|
+
},
|
|
2602
|
+
{
|
|
2603
|
+
id: "glm-4.5-x",
|
|
2604
|
+
aliases: ["GLM-4.5-X"],
|
|
2605
|
+
contextWindow: 131072,
|
|
2606
|
+
outputLimit: 98304,
|
|
2607
|
+
sourceUrl: ZHIPU_GLM_4_5_URL
|
|
2608
|
+
},
|
|
2609
|
+
{
|
|
2610
|
+
id: "glm-4.5-airx",
|
|
2611
|
+
aliases: ["GLM-4.5-AirX"],
|
|
2612
|
+
contextWindow: 131072,
|
|
2613
|
+
outputLimit: 98304,
|
|
2614
|
+
sourceUrl: ZHIPU_GLM_4_5_URL
|
|
2615
|
+
},
|
|
2616
|
+
{
|
|
2617
|
+
id: "glm-4.5-flash",
|
|
2618
|
+
aliases: ["GLM-4.5-Flash"],
|
|
2619
|
+
contextWindow: 131072,
|
|
2620
|
+
outputLimit: 98304,
|
|
2621
|
+
sourceUrl: ZHIPU_GLM_4_5_URL
|
|
2622
|
+
},
|
|
2623
|
+
{
|
|
2624
|
+
id: "glm-4.6",
|
|
2625
|
+
aliases: ["GLM-4.6"],
|
|
2626
|
+
contextWindow: 202752,
|
|
2627
|
+
outputLimit: 65536,
|
|
2628
|
+
sourceUrl: ZHIPU_GLM_4_6_URL
|
|
2629
|
+
},
|
|
2630
|
+
{
|
|
2631
|
+
id: "glm-4.7",
|
|
2632
|
+
aliases: ["GLM-4.7"],
|
|
2633
|
+
contextWindow: 202752,
|
|
2634
|
+
outputLimit: 131072,
|
|
2635
|
+
sourceUrl: ZHIPU_GLM_4_7_URL
|
|
2636
|
+
},
|
|
2564
2637
|
{
|
|
2565
2638
|
id: "glm-5",
|
|
2566
2639
|
aliases: ["GLM-5"],
|
|
@@ -2578,6 +2651,13 @@ const BUILTIN_PROVIDER_MODEL_REGISTRY = {
|
|
|
2578
2651
|
aliases: ["GLM-5.2"],
|
|
2579
2652
|
contextWindow: 1048576,
|
|
2580
2653
|
sourceUrl: HF_GLM_5_2_URL
|
|
2654
|
+
},
|
|
2655
|
+
{
|
|
2656
|
+
id: "glm-5-turbo",
|
|
2657
|
+
aliases: ["GLM-5-Turbo"],
|
|
2658
|
+
contextWindow: 202752,
|
|
2659
|
+
outputLimit: 131072,
|
|
2660
|
+
sourceUrl: ZHIPU_GLM_5_TURBO_URL
|
|
2581
2661
|
}
|
|
2582
2662
|
]
|
|
2583
2663
|
}
|
|
@@ -3181,6 +3261,47 @@ function getModelUsageName(model, providerName) {
|
|
|
3181
3261
|
function normalizeModelName(name) {
|
|
3182
3262
|
return name.toLowerCase().replace(/\s+/g, "-");
|
|
3183
3263
|
}
|
|
3264
|
+
const ZHIPU_MODEL_PREFIXES = ["glm-", "charglm-", "cogview-", "embedding-", "rerank-"];
|
|
3265
|
+
const ZHIPU_PROVIDER_ALIASES = ["zhipu", "zhipuai", "bigmodel", "zai", "glm"];
|
|
3266
|
+
const ZHIPU_BASE_URL_MARKERS = [
|
|
3267
|
+
"open.bigmodel.cn/api/paas/v4",
|
|
3268
|
+
"open.bigmodel.cn/api/coding/paas/v4",
|
|
3269
|
+
"open.bigmodel.cn/api/anthropic"
|
|
3270
|
+
];
|
|
3271
|
+
function normalizeProviderAlias(name) {
|
|
3272
|
+
return name.toLowerCase().replace(/[^a-z0-9]/g, "");
|
|
3273
|
+
}
|
|
3274
|
+
function providerRoutingUrls(provider) {
|
|
3275
|
+
const urls = [];
|
|
3276
|
+
if (provider.anthropicBaseUrl !== void 0 && provider.anthropicBaseUrl.trim() !== "") {
|
|
3277
|
+
urls.push(provider.anthropicBaseUrl);
|
|
3278
|
+
}
|
|
3279
|
+
if (provider.openaiBaseUrl !== void 0 && provider.openaiBaseUrl.trim() !== "") {
|
|
3280
|
+
urls.push(provider.openaiBaseUrl);
|
|
3281
|
+
}
|
|
3282
|
+
if (provider.baseUrl !== void 0 && provider.baseUrl.trim() !== "") {
|
|
3283
|
+
urls.push(provider.baseUrl);
|
|
3284
|
+
}
|
|
3285
|
+
return urls;
|
|
3286
|
+
}
|
|
3287
|
+
function isZhipuProvider(provider) {
|
|
3288
|
+
const normalizedName = normalizeProviderAlias(provider.name);
|
|
3289
|
+
const nameMatches = ZHIPU_PROVIDER_ALIASES.some((alias) => {
|
|
3290
|
+
const normalizedAlias = normalizeProviderAlias(alias);
|
|
3291
|
+
return normalizedName.includes(normalizedAlias) || normalizedAlias.includes(normalizedName);
|
|
3292
|
+
});
|
|
3293
|
+
if (nameMatches) return true;
|
|
3294
|
+
return providerRoutingUrls(provider).some((url) => {
|
|
3295
|
+
const normalizedUrl = url.toLowerCase().replace(/\/+$/, "");
|
|
3296
|
+
return ZHIPU_BASE_URL_MARKERS.some((marker) => normalizedUrl.includes(marker));
|
|
3297
|
+
});
|
|
3298
|
+
}
|
|
3299
|
+
function modelMatchesKnownProviderPrefix(modelNormalized, provider) {
|
|
3300
|
+
if (isZhipuProvider(provider)) {
|
|
3301
|
+
return ZHIPU_MODEL_PREFIXES.some((prefix) => modelNormalized.startsWith(prefix));
|
|
3302
|
+
}
|
|
3303
|
+
return false;
|
|
3304
|
+
}
|
|
3184
3305
|
function findProviderByModel(model) {
|
|
3185
3306
|
const providers = getProviders();
|
|
3186
3307
|
const modelLower = model.toLowerCase();
|
|
@@ -3190,6 +3311,9 @@ function findProviderByModel(model) {
|
|
|
3190
3311
|
if (modelLower.startsWith(providerPrefix)) {
|
|
3191
3312
|
return provider;
|
|
3192
3313
|
}
|
|
3314
|
+
if (modelMatchesKnownProviderPrefix(modelNormalized, provider)) {
|
|
3315
|
+
return provider;
|
|
3316
|
+
}
|
|
3193
3317
|
const modelList = provider.models ?? (provider.model !== void 0 ? [provider.model] : []);
|
|
3194
3318
|
for (const m of modelList) {
|
|
3195
3319
|
if (m !== "" && modelNormalized === normalizeModelName(m)) {
|
|
@@ -3403,6 +3527,8 @@ async function getClientInfo(request) {
|
|
|
3403
3527
|
}
|
|
3404
3528
|
const DEFAULT_SLOW_RESPONSE_THRESHOLD_SECONDS = 10;
|
|
3405
3529
|
const MAX_SLOW_RESPONSE_THRESHOLD_SECONDS = 600;
|
|
3530
|
+
const DEFAULT_PROVIDER_TEST_TIMEOUT_SECONDS = 60;
|
|
3531
|
+
const MAX_PROVIDER_TEST_TIMEOUT_SECONDS = 600;
|
|
3406
3532
|
const DEFAULT_TIME_DISPLAY_FORMAT = "time";
|
|
3407
3533
|
const DEFAULT_CAPTURE_MODE = "simple";
|
|
3408
3534
|
const TimeDisplayFormatSchema = _enum(["time", "full"]);
|
|
@@ -3411,6 +3537,7 @@ const RuntimeConfigSchema = object({
|
|
|
3411
3537
|
stripClaudeCodeBillingHeader: boolean(),
|
|
3412
3538
|
hasSeenOnboarding: boolean().default(false),
|
|
3413
3539
|
slowResponseThresholdSeconds: number().int().min(0).max(MAX_SLOW_RESPONSE_THRESHOLD_SECONDS).default(DEFAULT_SLOW_RESPONSE_THRESHOLD_SECONDS),
|
|
3540
|
+
providerTestTimeoutSeconds: number().int().min(1).max(MAX_PROVIDER_TEST_TIMEOUT_SECONDS).default(DEFAULT_PROVIDER_TEST_TIMEOUT_SECONDS),
|
|
3414
3541
|
timeDisplayFormat: TimeDisplayFormatSchema.default(DEFAULT_TIME_DISPLAY_FORMAT),
|
|
3415
3542
|
captureMode: CaptureModeSchema.default(DEFAULT_CAPTURE_MODE)
|
|
3416
3543
|
});
|
|
@@ -3455,6 +3582,7 @@ function resolveInitialConfig() {
|
|
|
3455
3582
|
stripClaudeCodeBillingHeader: true,
|
|
3456
3583
|
hasSeenOnboarding: false,
|
|
3457
3584
|
slowResponseThresholdSeconds: DEFAULT_SLOW_RESPONSE_THRESHOLD_SECONDS,
|
|
3585
|
+
providerTestTimeoutSeconds: DEFAULT_PROVIDER_TEST_TIMEOUT_SECONDS,
|
|
3458
3586
|
timeDisplayFormat: DEFAULT_TIME_DISPLAY_FORMAT,
|
|
3459
3587
|
captureMode
|
|
3460
3588
|
};
|
|
@@ -3463,6 +3591,7 @@ function resolveInitialConfig() {
|
|
|
3463
3591
|
stripClaudeCodeBillingHeader: false,
|
|
3464
3592
|
hasSeenOnboarding: false,
|
|
3465
3593
|
slowResponseThresholdSeconds: DEFAULT_SLOW_RESPONSE_THRESHOLD_SECONDS,
|
|
3594
|
+
providerTestTimeoutSeconds: DEFAULT_PROVIDER_TEST_TIMEOUT_SECONDS,
|
|
3466
3595
|
timeDisplayFormat: DEFAULT_TIME_DISPLAY_FORMAT,
|
|
3467
3596
|
captureMode
|
|
3468
3597
|
};
|
|
@@ -3516,6 +3645,7 @@ function toPersistedConfig(value) {
|
|
|
3516
3645
|
stripClaudeCodeBillingHeader: value.stripClaudeCodeBillingHeader,
|
|
3517
3646
|
hasSeenOnboarding: value.hasSeenOnboarding,
|
|
3518
3647
|
slowResponseThresholdSeconds: value.slowResponseThresholdSeconds,
|
|
3648
|
+
providerTestTimeoutSeconds: value.providerTestTimeoutSeconds,
|
|
3519
3649
|
timeDisplayFormat: value.timeDisplayFormat
|
|
3520
3650
|
};
|
|
3521
3651
|
}
|
|
@@ -4052,11 +4182,26 @@ function selectUpstreamBase(route, provider) {
|
|
|
4052
4182
|
}
|
|
4053
4183
|
function buildUpstreamUrl(upstreamBase, normalizedPath) {
|
|
4054
4184
|
const base = upstreamBase.endsWith("/") ? upstreamBase.slice(0, -1) : upstreamBase;
|
|
4185
|
+
if (isZhipuVersionedOpenAIBase(base) && isVersionedChatCompletionsPath(normalizedPath)) {
|
|
4186
|
+
return base + normalizedPath.slice(3);
|
|
4187
|
+
}
|
|
4055
4188
|
if (base.endsWith("/v1") && normalizedPath.startsWith("/v1/")) {
|
|
4056
4189
|
return base + normalizedPath.slice(3);
|
|
4057
4190
|
}
|
|
4058
4191
|
return base + normalizedPath;
|
|
4059
4192
|
}
|
|
4193
|
+
function isVersionedChatCompletionsPath(normalizedPath) {
|
|
4194
|
+
return normalizedPath === PATH_V1_CHAT_COMPLETIONS || normalizedPath.startsWith(`${PATH_V1_CHAT_COMPLETIONS}?`) || normalizedPath.startsWith(`${PATH_V1_CHAT_COMPLETIONS}/`);
|
|
4195
|
+
}
|
|
4196
|
+
function isZhipuVersionedOpenAIBase(base) {
|
|
4197
|
+
try {
|
|
4198
|
+
const parsed = new URL(base);
|
|
4199
|
+
const path2 = parsed.pathname.replace(/\/+$/, "");
|
|
4200
|
+
return parsed.hostname === "open.bigmodel.cn" && (path2 === "/api/paas/v4" || path2 === "/api/coding/paas/v4");
|
|
4201
|
+
} catch {
|
|
4202
|
+
return false;
|
|
4203
|
+
}
|
|
4204
|
+
}
|
|
4060
4205
|
function setUpstreamHost(headers, upstreamBase) {
|
|
4061
4206
|
try {
|
|
4062
4207
|
headers.set(HEADER_HOST, new URL(upstreamBase).host);
|
|
@@ -5094,6 +5239,7 @@ const RuntimeConfigPatchSchema = object({
|
|
|
5094
5239
|
stripClaudeCodeBillingHeader: boolean().optional(),
|
|
5095
5240
|
hasSeenOnboarding: boolean().optional(),
|
|
5096
5241
|
slowResponseThresholdSeconds: number().int().min(0).max(MAX_SLOW_RESPONSE_THRESHOLD_SECONDS).optional(),
|
|
5242
|
+
providerTestTimeoutSeconds: number().int().min(1).max(MAX_PROVIDER_TEST_TIMEOUT_SECONDS).optional(),
|
|
5097
5243
|
timeDisplayFormat: TimeDisplayFormatSchema.optional()
|
|
5098
5244
|
}).strict().refine((v) => Object.keys(v).length > 0, {
|
|
5099
5245
|
message: "At least one field must be provided"
|
|
@@ -5127,6 +5273,9 @@ const Route$i = createFileRoute("/api/config")({
|
|
|
5127
5273
|
}
|
|
5128
5274
|
}
|
|
5129
5275
|
});
|
|
5276
|
+
const ZHIPU_OPENAI_BASE_URL = "https://open.bigmodel.cn/api/paas/v4";
|
|
5277
|
+
const ZHIPU_CODING_OPENAI_BASE_URL = "https://open.bigmodel.cn/api/coding/paas/v4";
|
|
5278
|
+
const ZHIPU_CODING_ANTHROPIC_BASE_URL = "https://open.bigmodel.cn/api/anthropic";
|
|
5130
5279
|
function readJsonSafe(filePath) {
|
|
5131
5280
|
try {
|
|
5132
5281
|
if (!existsSync(filePath)) return null;
|
|
@@ -5156,6 +5305,9 @@ const KNOWN_PROVIDER_NAMES = {
|
|
|
5156
5305
|
azure: "Azure",
|
|
5157
5306
|
moonshot: "Moonshot",
|
|
5158
5307
|
zhipu: "ZhipuAI",
|
|
5308
|
+
zhipuai: "ZhipuAI",
|
|
5309
|
+
bigmodel: "ZhipuAI",
|
|
5310
|
+
zai: "Z.AI",
|
|
5159
5311
|
qwen: "Qwen",
|
|
5160
5312
|
baichuan: "Baichuan",
|
|
5161
5313
|
iflytek: "iFlytek",
|
|
@@ -5435,6 +5587,46 @@ function detectMiMoCodeProviders() {
|
|
|
5435
5587
|
anthropicBaseUrl: "",
|
|
5436
5588
|
openaiBaseUrl: "https://api.together.xyz",
|
|
5437
5589
|
format: "openai"
|
|
5590
|
+
},
|
|
5591
|
+
zhipu: {
|
|
5592
|
+
anthropicBaseUrl: "",
|
|
5593
|
+
openaiBaseUrl: ZHIPU_OPENAI_BASE_URL,
|
|
5594
|
+
format: "openai"
|
|
5595
|
+
},
|
|
5596
|
+
zhipuai: {
|
|
5597
|
+
anthropicBaseUrl: "",
|
|
5598
|
+
openaiBaseUrl: ZHIPU_OPENAI_BASE_URL,
|
|
5599
|
+
format: "openai"
|
|
5600
|
+
},
|
|
5601
|
+
bigmodel: {
|
|
5602
|
+
anthropicBaseUrl: "",
|
|
5603
|
+
openaiBaseUrl: ZHIPU_OPENAI_BASE_URL,
|
|
5604
|
+
format: "openai"
|
|
5605
|
+
},
|
|
5606
|
+
zai: {
|
|
5607
|
+
anthropicBaseUrl: "",
|
|
5608
|
+
openaiBaseUrl: ZHIPU_OPENAI_BASE_URL,
|
|
5609
|
+
format: "openai"
|
|
5610
|
+
},
|
|
5611
|
+
glm: {
|
|
5612
|
+
anthropicBaseUrl: ZHIPU_CODING_ANTHROPIC_BASE_URL,
|
|
5613
|
+
openaiBaseUrl: ZHIPU_CODING_OPENAI_BASE_URL,
|
|
5614
|
+
format: "anthropic"
|
|
5615
|
+
},
|
|
5616
|
+
"glm-coding-plan": {
|
|
5617
|
+
anthropicBaseUrl: ZHIPU_CODING_ANTHROPIC_BASE_URL,
|
|
5618
|
+
openaiBaseUrl: ZHIPU_CODING_OPENAI_BASE_URL,
|
|
5619
|
+
format: "anthropic"
|
|
5620
|
+
},
|
|
5621
|
+
"zhipu-coding-plan": {
|
|
5622
|
+
anthropicBaseUrl: ZHIPU_CODING_ANTHROPIC_BASE_URL,
|
|
5623
|
+
openaiBaseUrl: ZHIPU_CODING_OPENAI_BASE_URL,
|
|
5624
|
+
format: "anthropic"
|
|
5625
|
+
},
|
|
5626
|
+
"zai-coding-plan": {
|
|
5627
|
+
anthropicBaseUrl: ZHIPU_CODING_ANTHROPIC_BASE_URL,
|
|
5628
|
+
openaiBaseUrl: ZHIPU_CODING_OPENAI_BASE_URL,
|
|
5629
|
+
format: "anthropic"
|
|
5438
5630
|
}
|
|
5439
5631
|
};
|
|
5440
5632
|
for (const [key, cred] of Object.entries(auth)) {
|
|
@@ -6414,10 +6606,11 @@ function buildProviderTestRequestBody(model, mode) {
|
|
|
6414
6606
|
return { ...base, stream: true };
|
|
6415
6607
|
}
|
|
6416
6608
|
}
|
|
6609
|
+
const CONTAINER_NETWORK_HINT = "If the tool, Agent Inspector, or provider runs in another container or host, replace localhost with an address reachable from the caller and verify the network/firewall path.";
|
|
6417
6610
|
const ERROR_HINTS = {
|
|
6418
|
-
timeout:
|
|
6419
|
-
network_unreachable:
|
|
6420
|
-
connection_refused:
|
|
6611
|
+
timeout: `The request took too long. Check your network connection or try again. ${CONTAINER_NETWORK_HINT}`,
|
|
6612
|
+
network_unreachable: `Cannot reach the server. Verify the base URL and check your firewall settings. ${CONTAINER_NETWORK_HINT}`,
|
|
6613
|
+
connection_refused: `Connection was refused. Make sure the provider server is running and the URL is correct. ${CONTAINER_NETWORK_HINT}`,
|
|
6421
6614
|
auth_failed: "Authentication failed. Check your API key is correct and has not expired.",
|
|
6422
6615
|
rate_limited: "Too many requests. Wait a moment and try again, or check your API quota.",
|
|
6423
6616
|
server_error: "The provider server encountered an error. Check their status page and try again later.",
|
|
@@ -6425,6 +6618,17 @@ const ERROR_HINTS = {
|
|
|
6425
6618
|
unknown: "An unexpected error occurred. Check the details and try again."
|
|
6426
6619
|
};
|
|
6427
6620
|
const MAX_ERROR_DETAILS_LENGTH = 200;
|
|
6621
|
+
const MAX_DEBUG_TEXT_LENGTH = 2e4;
|
|
6622
|
+
const REDACTED_HEADER_VALUE = "[redacted]";
|
|
6623
|
+
const SENSITIVE_HEADER_NAMES = /* @__PURE__ */ new Set([
|
|
6624
|
+
"authorization",
|
|
6625
|
+
"x-api-key",
|
|
6626
|
+
"api-key",
|
|
6627
|
+
"x-goog-api-key",
|
|
6628
|
+
"anthropic-api-key",
|
|
6629
|
+
"openai-api-key",
|
|
6630
|
+
"proxy-authorization"
|
|
6631
|
+
]);
|
|
6428
6632
|
function classifyError(error, responseStatus) {
|
|
6429
6633
|
const errorStr = String(error);
|
|
6430
6634
|
const errorLower = errorStr.toLowerCase();
|
|
@@ -6464,6 +6668,9 @@ function classifyError(error, responseStatus) {
|
|
|
6464
6668
|
if (errorLower.includes("bad gateway") || errorLower.includes("gateway timeout")) {
|
|
6465
6669
|
return { type: "server_error", details: extractErrorDetails(errorStr) };
|
|
6466
6670
|
}
|
|
6671
|
+
if (errorLower.includes("invalid response") || errorLower.includes("unexpected token") || errorLower.includes("failed to parse") || errorLower.includes("schema") || errorLower.includes("zod")) {
|
|
6672
|
+
return { type: "invalid_response", details: extractErrorDetails(errorStr) };
|
|
6673
|
+
}
|
|
6467
6674
|
if (responseStatus !== void 0) {
|
|
6468
6675
|
if (responseStatus === 401 || responseStatus === 403) {
|
|
6469
6676
|
return { type: "auth_failed", details: `Authentication failed (HTTP ${responseStatus})` };
|
|
@@ -6504,9 +6711,64 @@ function truncateErrorDetails(details) {
|
|
|
6504
6711
|
}
|
|
6505
6712
|
return details.slice(0, MAX_ERROR_DETAILS_LENGTH) + "...";
|
|
6506
6713
|
}
|
|
6507
|
-
function
|
|
6714
|
+
function truncateDebugText(text) {
|
|
6715
|
+
if (text.length <= MAX_DEBUG_TEXT_LENGTH) {
|
|
6716
|
+
return text;
|
|
6717
|
+
}
|
|
6718
|
+
return `${text.slice(0, MAX_DEBUG_TEXT_LENGTH)}
|
|
6719
|
+
... truncated`;
|
|
6720
|
+
}
|
|
6721
|
+
function headersToRecord(headers) {
|
|
6722
|
+
const result = {};
|
|
6723
|
+
headers.forEach((value, key) => {
|
|
6724
|
+
result[key] = value;
|
|
6725
|
+
});
|
|
6726
|
+
return result;
|
|
6727
|
+
}
|
|
6728
|
+
function redactHeaderValue(name, value) {
|
|
6729
|
+
const lowerName = name.toLowerCase();
|
|
6730
|
+
if (!SENSITIVE_HEADER_NAMES.has(lowerName)) {
|
|
6731
|
+
return value;
|
|
6732
|
+
}
|
|
6733
|
+
if (lowerName === "authorization" && value.startsWith("Bearer ")) {
|
|
6734
|
+
return `Bearer ${REDACTED_HEADER_VALUE}`;
|
|
6735
|
+
}
|
|
6736
|
+
return REDACTED_HEADER_VALUE;
|
|
6737
|
+
}
|
|
6738
|
+
function redactHeaders(headers) {
|
|
6739
|
+
const result = {};
|
|
6740
|
+
for (const [name, value] of Object.entries(headers)) {
|
|
6741
|
+
result[name] = redactHeaderValue(name, value);
|
|
6742
|
+
}
|
|
6743
|
+
return result;
|
|
6744
|
+
}
|
|
6745
|
+
function createTestDebug(input) {
|
|
6746
|
+
const debug = {
|
|
6747
|
+
requestUrl: input.requestUrl,
|
|
6748
|
+
requestMethod: "POST",
|
|
6749
|
+
requestHeaders: redactHeaders(input.requestHeaders),
|
|
6750
|
+
requestBody: truncateDebugText(input.requestBody)
|
|
6751
|
+
};
|
|
6752
|
+
if (input.response !== void 0) {
|
|
6753
|
+
debug.responseStatus = input.response.status;
|
|
6754
|
+
debug.responseStatusText = input.response.statusText;
|
|
6755
|
+
debug.responseHeaders = headersToRecord(input.response.headers);
|
|
6756
|
+
}
|
|
6757
|
+
if (input.responseBody !== void 0) {
|
|
6758
|
+
debug.responseBody = truncateDebugText(input.responseBody);
|
|
6759
|
+
}
|
|
6760
|
+
return debug;
|
|
6761
|
+
}
|
|
6762
|
+
async function readResponseText(response) {
|
|
6763
|
+
try {
|
|
6764
|
+
return await response.text();
|
|
6765
|
+
} catch (err) {
|
|
6766
|
+
return `Failed to read response body: ${String(err)}`;
|
|
6767
|
+
}
|
|
6768
|
+
}
|
|
6769
|
+
function createErrorResult(error, latencyMs, streaming, responseStatus, debug) {
|
|
6508
6770
|
const { type, details } = classifyError(error, responseStatus);
|
|
6509
|
-
|
|
6771
|
+
const result = {
|
|
6510
6772
|
success: false,
|
|
6511
6773
|
error: {
|
|
6512
6774
|
message: getErrorMessage(type),
|
|
@@ -6517,6 +6779,13 @@ function createErrorResult(error, latencyMs, streaming, responseStatus) {
|
|
|
6517
6779
|
latencyMs,
|
|
6518
6780
|
streaming
|
|
6519
6781
|
};
|
|
6782
|
+
if (debug !== void 0) {
|
|
6783
|
+
result.debug = debug;
|
|
6784
|
+
if (debug.requestHeaders !== void 0) {
|
|
6785
|
+
result.requestHeaders = debug.requestHeaders;
|
|
6786
|
+
}
|
|
6787
|
+
}
|
|
6788
|
+
return result;
|
|
6520
6789
|
}
|
|
6521
6790
|
function getErrorMessage(type) {
|
|
6522
6791
|
const messages = {
|
|
@@ -6566,7 +6835,9 @@ const OpenAIResponseSchema = object({
|
|
|
6566
6835
|
})
|
|
6567
6836
|
)
|
|
6568
6837
|
});
|
|
6569
|
-
|
|
6838
|
+
function getProviderTestTimeoutMs() {
|
|
6839
|
+
return getConfig().providerTestTimeoutSeconds * 1e3;
|
|
6840
|
+
}
|
|
6570
6841
|
function buildTestRequestHeaders(provider) {
|
|
6571
6842
|
const headers = new Headers();
|
|
6572
6843
|
headers.set("Content-Type", "application/json");
|
|
@@ -6581,27 +6852,36 @@ async function testEndpoint(baseUrl, provider, path2, model, isOpenAI) {
|
|
|
6581
6852
|
const startTime = Date.now();
|
|
6582
6853
|
const body = JSON.stringify(buildProviderTestRequestBody(model, "non-streaming"));
|
|
6583
6854
|
const requestHeaders = buildTestRequestHeaders(provider);
|
|
6855
|
+
let requestUrl = baseUrl;
|
|
6584
6856
|
const controller = new AbortController();
|
|
6585
|
-
const timeoutId = setTimeout(() => controller.abort(),
|
|
6857
|
+
const timeoutId = setTimeout(() => controller.abort(), getProviderTestTimeoutMs());
|
|
6586
6858
|
try {
|
|
6587
|
-
|
|
6588
|
-
const response = await fetch(
|
|
6859
|
+
requestUrl = buildUpstreamUrl(baseUrl, path2);
|
|
6860
|
+
const response = await fetch(requestUrl, {
|
|
6589
6861
|
method: "POST",
|
|
6590
6862
|
headers: requestHeaders,
|
|
6591
6863
|
body,
|
|
6592
6864
|
signal: controller.signal
|
|
6593
6865
|
});
|
|
6594
|
-
clearTimeout(timeoutId);
|
|
6595
6866
|
const latencyMs = Date.now() - startTime;
|
|
6596
6867
|
if (!response.ok) {
|
|
6868
|
+
const responseText2 = await readResponseText(response);
|
|
6597
6869
|
return createErrorResult(
|
|
6598
6870
|
`HTTP ${response.status}: ${response.statusText}`,
|
|
6599
6871
|
latencyMs,
|
|
6600
6872
|
false,
|
|
6601
|
-
response.status
|
|
6873
|
+
response.status,
|
|
6874
|
+
createTestDebug({
|
|
6875
|
+
requestUrl,
|
|
6876
|
+
requestHeaders,
|
|
6877
|
+
requestBody: body,
|
|
6878
|
+
response,
|
|
6879
|
+
responseBody: responseText2
|
|
6880
|
+
})
|
|
6602
6881
|
);
|
|
6603
6882
|
}
|
|
6604
6883
|
const responseText = await response.text();
|
|
6884
|
+
const safeRequestHeaders = redactHeaders(requestHeaders);
|
|
6605
6885
|
try {
|
|
6606
6886
|
if (isOpenAI) {
|
|
6607
6887
|
const json = OpenAIResponseSchema.parse(JSON.parse(responseText));
|
|
@@ -6617,7 +6897,7 @@ async function testEndpoint(baseUrl, provider, path2, model, isOpenAI) {
|
|
|
6617
6897
|
latencyMs,
|
|
6618
6898
|
content: content !== null && content !== "" ? [{ type: "text", text: content }] : void 0,
|
|
6619
6899
|
rawResponse: responseText,
|
|
6620
|
-
requestHeaders
|
|
6900
|
+
requestHeaders: safeRequestHeaders
|
|
6621
6901
|
};
|
|
6622
6902
|
} else {
|
|
6623
6903
|
const json = AnthropicResponseSchema.parse(JSON.parse(responseText));
|
|
@@ -6644,61 +6924,78 @@ async function testEndpoint(baseUrl, provider, path2, model, isOpenAI) {
|
|
|
6644
6924
|
latencyMs,
|
|
6645
6925
|
content: content.length > 0 ? content : void 0,
|
|
6646
6926
|
rawResponse: responseText,
|
|
6647
|
-
requestHeaders
|
|
6927
|
+
requestHeaders: safeRequestHeaders
|
|
6648
6928
|
};
|
|
6649
6929
|
}
|
|
6650
6930
|
} catch (parseErr) {
|
|
6651
|
-
return
|
|
6652
|
-
|
|
6653
|
-
model,
|
|
6931
|
+
return createErrorResult(
|
|
6932
|
+
`Invalid response: ${String(parseErr)}`,
|
|
6654
6933
|
latencyMs,
|
|
6655
|
-
|
|
6656
|
-
|
|
6657
|
-
|
|
6658
|
-
|
|
6934
|
+
false,
|
|
6935
|
+
response.status,
|
|
6936
|
+
createTestDebug({
|
|
6937
|
+
requestUrl,
|
|
6938
|
+
requestHeaders,
|
|
6939
|
+
requestBody: body,
|
|
6940
|
+
response,
|
|
6941
|
+
responseBody: responseText
|
|
6942
|
+
})
|
|
6943
|
+
);
|
|
6659
6944
|
}
|
|
6660
6945
|
} catch (err) {
|
|
6946
|
+
return createErrorResult(
|
|
6947
|
+
err,
|
|
6948
|
+
Date.now() - startTime,
|
|
6949
|
+
false,
|
|
6950
|
+
void 0,
|
|
6951
|
+
createTestDebug({ requestUrl, requestHeaders, requestBody: body })
|
|
6952
|
+
);
|
|
6953
|
+
} finally {
|
|
6661
6954
|
clearTimeout(timeoutId);
|
|
6662
|
-
return createErrorResult(err, Date.now() - startTime, false);
|
|
6663
6955
|
}
|
|
6664
6956
|
}
|
|
6665
6957
|
async function testStreamingEndpoint(baseUrl, provider, path2, model, isOpenAI) {
|
|
6666
6958
|
const startTime = Date.now();
|
|
6667
6959
|
const body = JSON.stringify(buildProviderTestRequestBody(model, "streaming"));
|
|
6668
6960
|
const requestHeaders = buildTestRequestHeaders(provider);
|
|
6961
|
+
let requestUrl = baseUrl;
|
|
6669
6962
|
const controller = new AbortController();
|
|
6670
|
-
const timeoutId = setTimeout(() => controller.abort(),
|
|
6963
|
+
const timeoutId = setTimeout(() => controller.abort(), getProviderTestTimeoutMs());
|
|
6671
6964
|
try {
|
|
6672
|
-
|
|
6673
|
-
const response = await fetch(
|
|
6965
|
+
requestUrl = buildUpstreamUrl(baseUrl, path2);
|
|
6966
|
+
const response = await fetch(requestUrl, {
|
|
6674
6967
|
method: "POST",
|
|
6675
6968
|
headers: requestHeaders,
|
|
6676
6969
|
body,
|
|
6677
6970
|
signal: controller.signal
|
|
6678
6971
|
});
|
|
6679
|
-
clearTimeout(timeoutId);
|
|
6680
6972
|
const latencyMs = Date.now() - startTime;
|
|
6681
6973
|
if (!response.ok) {
|
|
6974
|
+
const responseText = await readResponseText(response);
|
|
6682
6975
|
return createErrorResult(
|
|
6683
6976
|
`HTTP ${response.status}: ${response.statusText}`,
|
|
6684
6977
|
latencyMs,
|
|
6685
6978
|
true,
|
|
6686
|
-
response.status
|
|
6979
|
+
response.status,
|
|
6980
|
+
createTestDebug({
|
|
6981
|
+
requestUrl,
|
|
6982
|
+
requestHeaders,
|
|
6983
|
+
requestBody: body,
|
|
6984
|
+
response,
|
|
6985
|
+
responseBody: responseText
|
|
6986
|
+
})
|
|
6687
6987
|
);
|
|
6688
6988
|
}
|
|
6689
6989
|
const chunks = [];
|
|
6690
6990
|
const reader = response.body?.getReader();
|
|
6691
6991
|
if (!reader) {
|
|
6692
|
-
return
|
|
6693
|
-
|
|
6694
|
-
error: {
|
|
6695
|
-
message: "No response body",
|
|
6696
|
-
type: "invalid_response",
|
|
6697
|
-
hint: ERROR_HINTS.invalid_response
|
|
6698
|
-
},
|
|
6992
|
+
return createErrorResult(
|
|
6993
|
+
"Invalid response: no response body",
|
|
6699
6994
|
latencyMs,
|
|
6700
|
-
|
|
6701
|
-
|
|
6995
|
+
true,
|
|
6996
|
+
response.status,
|
|
6997
|
+
createTestDebug({ requestUrl, requestHeaders, requestBody: body, response })
|
|
6998
|
+
);
|
|
6702
6999
|
}
|
|
6703
7000
|
const decoder = new TextDecoder();
|
|
6704
7001
|
const MAX_CHUNKS_SIZE = 10 * 1024 * 1024;
|
|
@@ -6711,7 +7008,15 @@ async function testStreamingEndpoint(baseUrl, provider, path2, model, isOpenAI)
|
|
|
6711
7008
|
return createErrorResult(
|
|
6712
7009
|
"Response too large (exceeded 10MB limit)",
|
|
6713
7010
|
Date.now() - startTime,
|
|
6714
|
-
true
|
|
7011
|
+
true,
|
|
7012
|
+
response.status,
|
|
7013
|
+
createTestDebug({
|
|
7014
|
+
requestUrl,
|
|
7015
|
+
requestHeaders,
|
|
7016
|
+
requestBody: body,
|
|
7017
|
+
response,
|
|
7018
|
+
responseBody: chunks.join("")
|
|
7019
|
+
})
|
|
6715
7020
|
);
|
|
6716
7021
|
}
|
|
6717
7022
|
const decoded = decoder.decode(value, { stream: true });
|
|
@@ -6723,9 +7028,23 @@ async function testStreamingEndpoint(baseUrl, provider, path2, model, isOpenAI)
|
|
|
6723
7028
|
chunks.push(finalChunk);
|
|
6724
7029
|
}
|
|
6725
7030
|
} catch (readErr) {
|
|
6726
|
-
|
|
7031
|
+
const error = readErr instanceof Error && readErr.name === "AbortError" ? readErr : `Stream read error: ${String(readErr)}`;
|
|
7032
|
+
return createErrorResult(
|
|
7033
|
+
error,
|
|
7034
|
+
latencyMs,
|
|
7035
|
+
true,
|
|
7036
|
+
response.status,
|
|
7037
|
+
createTestDebug({
|
|
7038
|
+
requestUrl,
|
|
7039
|
+
requestHeaders,
|
|
7040
|
+
requestBody: body,
|
|
7041
|
+
response,
|
|
7042
|
+
responseBody: chunks.join("")
|
|
7043
|
+
})
|
|
7044
|
+
);
|
|
6727
7045
|
}
|
|
6728
7046
|
const fullResponse = chunks.join("");
|
|
7047
|
+
const safeRequestHeaders = redactHeaders(requestHeaders);
|
|
6729
7048
|
const mockLog = {
|
|
6730
7049
|
id: 0,
|
|
6731
7050
|
timestamp: "",
|
|
@@ -6797,23 +7116,33 @@ async function testStreamingEndpoint(baseUrl, provider, path2, model, isOpenAI)
|
|
|
6797
7116
|
rawResponse: reconstructedJson,
|
|
6798
7117
|
streaming: true,
|
|
6799
7118
|
streamingChunks,
|
|
6800
|
-
requestHeaders
|
|
7119
|
+
requestHeaders: safeRequestHeaders
|
|
6801
7120
|
};
|
|
6802
7121
|
} catch {
|
|
6803
|
-
return
|
|
6804
|
-
|
|
6805
|
-
model,
|
|
7122
|
+
return createErrorResult(
|
|
7123
|
+
"Invalid response: could not parse reconstructed stream response",
|
|
6806
7124
|
latencyMs,
|
|
6807
|
-
|
|
6808
|
-
|
|
6809
|
-
|
|
6810
|
-
|
|
6811
|
-
|
|
6812
|
-
|
|
7125
|
+
true,
|
|
7126
|
+
response.status,
|
|
7127
|
+
createTestDebug({
|
|
7128
|
+
requestUrl,
|
|
7129
|
+
requestHeaders,
|
|
7130
|
+
requestBody: body,
|
|
7131
|
+
response,
|
|
7132
|
+
responseBody: fullResponse
|
|
7133
|
+
})
|
|
7134
|
+
);
|
|
6813
7135
|
}
|
|
6814
7136
|
} catch (err) {
|
|
7137
|
+
return createErrorResult(
|
|
7138
|
+
err,
|
|
7139
|
+
Date.now() - startTime,
|
|
7140
|
+
true,
|
|
7141
|
+
void 0,
|
|
7142
|
+
createTestDebug({ requestUrl, requestHeaders, requestBody: body })
|
|
7143
|
+
);
|
|
7144
|
+
} finally {
|
|
6815
7145
|
clearTimeout(timeoutId);
|
|
6816
|
-
return createErrorResult(err, Date.now() - startTime, true);
|
|
6817
7146
|
}
|
|
6818
7147
|
}
|
|
6819
7148
|
const Route$7 = createFileRoute("/api/providers/$providerId/test")({
|
|
@@ -7266,6 +7595,16 @@ const ProviderTestContentSchema = object({
|
|
|
7266
7595
|
text: string().optional(),
|
|
7267
7596
|
thinking: string().optional()
|
|
7268
7597
|
});
|
|
7598
|
+
const ProviderTestDebugSchema = object({
|
|
7599
|
+
requestUrl: string().optional(),
|
|
7600
|
+
requestMethod: string().optional(),
|
|
7601
|
+
requestHeaders: record(string(), string()).optional(),
|
|
7602
|
+
requestBody: string().optional(),
|
|
7603
|
+
responseStatus: number().optional(),
|
|
7604
|
+
responseStatusText: string().optional(),
|
|
7605
|
+
responseHeaders: record(string(), string()).optional(),
|
|
7606
|
+
responseBody: string().optional()
|
|
7607
|
+
});
|
|
7269
7608
|
const ProviderTestResultSchema = object({
|
|
7270
7609
|
success: boolean(),
|
|
7271
7610
|
error: ProviderTestErrorSchema.optional(),
|
|
@@ -7282,7 +7621,8 @@ const ProviderTestResultSchema = object({
|
|
|
7282
7621
|
chunks: array(StreamingChunkSchema$1),
|
|
7283
7622
|
truncated: boolean().default(false)
|
|
7284
7623
|
}).optional(),
|
|
7285
|
-
requestHeaders: record(string(), string()).optional()
|
|
7624
|
+
requestHeaders: record(string(), string()).optional(),
|
|
7625
|
+
debug: ProviderTestDebugSchema.optional()
|
|
7286
7626
|
});
|
|
7287
7627
|
const ProviderTestStateSchema = union([
|
|
7288
7628
|
ProviderTestResultSchema,
|
|
@@ -7331,6 +7671,18 @@ function createFailedProviderTestResults(message, type) {
|
|
|
7331
7671
|
function hasSuccessField(result) {
|
|
7332
7672
|
return Object.prototype.hasOwnProperty.call(result, "success");
|
|
7333
7673
|
}
|
|
7674
|
+
function getResultResponseStatus(result) {
|
|
7675
|
+
if (result.debug?.responseStatus !== void 0) {
|
|
7676
|
+
return result.debug.responseStatus;
|
|
7677
|
+
}
|
|
7678
|
+
return result.success ? 200 : 500;
|
|
7679
|
+
}
|
|
7680
|
+
function getResultResponseText(result) {
|
|
7681
|
+
return result.rawResponse ?? result.debug?.responseBody ?? JSON.stringify(result);
|
|
7682
|
+
}
|
|
7683
|
+
function getResultHeaders(result) {
|
|
7684
|
+
return result.requestHeaders ?? result.debug?.requestHeaders ?? {};
|
|
7685
|
+
}
|
|
7334
7686
|
async function logModelResults(displayName, providerName, anthropicUrl, openaiUrl, modelResults, captureFullDetails) {
|
|
7335
7687
|
const usageModel = getModelUsageName(displayName, providerName);
|
|
7336
7688
|
if (anthropicUrl !== void 0) {
|
|
@@ -7347,8 +7699,8 @@ async function logModelResults(displayName, providerName, anthropicUrl, openaiUr
|
|
|
7347
7699
|
model: nonStreamingResult.model ?? displayName,
|
|
7348
7700
|
sessionId: null,
|
|
7349
7701
|
rawRequestBody: requestBody,
|
|
7350
|
-
responseStatus: nonStreamingResult
|
|
7351
|
-
responseText:
|
|
7702
|
+
responseStatus: getResultResponseStatus(nonStreamingResult),
|
|
7703
|
+
responseText: getResultResponseText(nonStreamingResult),
|
|
7352
7704
|
inputTokens: nonStreamingResult.inputTokens ?? null,
|
|
7353
7705
|
outputTokens: nonStreamingResult.outputTokens ?? null,
|
|
7354
7706
|
cacheCreationInputTokens: nonStreamingResult.cacheCreationInputTokens ?? null,
|
|
@@ -7360,7 +7712,7 @@ async function logModelResults(displayName, providerName, anthropicUrl, openaiUr
|
|
|
7360
7712
|
apiFormat: "anthropic",
|
|
7361
7713
|
isTest: true,
|
|
7362
7714
|
providerName,
|
|
7363
|
-
headers: captureFullDetails ? nonStreamingResult
|
|
7715
|
+
headers: captureFullDetails ? getResultHeaders(nonStreamingResult) : void 0
|
|
7364
7716
|
});
|
|
7365
7717
|
const streamingRequestBody = JSON.stringify(
|
|
7366
7718
|
buildProviderTestRequestBody(usageModel, "streaming")
|
|
@@ -7372,8 +7724,8 @@ async function logModelResults(displayName, providerName, anthropicUrl, openaiUr
|
|
|
7372
7724
|
model: streamingResult.model ?? displayName,
|
|
7373
7725
|
sessionId: null,
|
|
7374
7726
|
rawRequestBody: streamingRequestBody,
|
|
7375
|
-
responseStatus: streamingResult
|
|
7376
|
-
responseText:
|
|
7727
|
+
responseStatus: getResultResponseStatus(streamingResult),
|
|
7728
|
+
responseText: getResultResponseText(streamingResult),
|
|
7377
7729
|
inputTokens: streamingResult.inputTokens ?? null,
|
|
7378
7730
|
outputTokens: streamingResult.outputTokens ?? null,
|
|
7379
7731
|
cacheCreationInputTokens: streamingResult.cacheCreationInputTokens ?? null,
|
|
@@ -7386,7 +7738,7 @@ async function logModelResults(displayName, providerName, anthropicUrl, openaiUr
|
|
|
7386
7738
|
apiFormat: "anthropic",
|
|
7387
7739
|
isTest: true,
|
|
7388
7740
|
providerName,
|
|
7389
|
-
headers: captureFullDetails ? streamingResult
|
|
7741
|
+
headers: captureFullDetails ? getResultHeaders(streamingResult) : void 0
|
|
7390
7742
|
});
|
|
7391
7743
|
}
|
|
7392
7744
|
}
|
|
@@ -7404,8 +7756,8 @@ async function logModelResults(displayName, providerName, anthropicUrl, openaiUr
|
|
|
7404
7756
|
model: nonStreamingResult.model ?? displayName,
|
|
7405
7757
|
sessionId: null,
|
|
7406
7758
|
rawRequestBody: requestBody,
|
|
7407
|
-
responseStatus: nonStreamingResult
|
|
7408
|
-
responseText:
|
|
7759
|
+
responseStatus: getResultResponseStatus(nonStreamingResult),
|
|
7760
|
+
responseText: getResultResponseText(nonStreamingResult),
|
|
7409
7761
|
inputTokens: nonStreamingResult.inputTokens ?? null,
|
|
7410
7762
|
outputTokens: nonStreamingResult.outputTokens ?? null,
|
|
7411
7763
|
cacheCreationInputTokens: null,
|
|
@@ -7417,7 +7769,7 @@ async function logModelResults(displayName, providerName, anthropicUrl, openaiUr
|
|
|
7417
7769
|
apiFormat: "openai",
|
|
7418
7770
|
isTest: true,
|
|
7419
7771
|
providerName,
|
|
7420
|
-
headers: captureFullDetails ? nonStreamingResult
|
|
7772
|
+
headers: captureFullDetails ? getResultHeaders(nonStreamingResult) : void 0
|
|
7421
7773
|
});
|
|
7422
7774
|
const streamingRequestBody = JSON.stringify(
|
|
7423
7775
|
buildProviderTestRequestBody(usageModel, "streaming")
|
|
@@ -7429,8 +7781,8 @@ async function logModelResults(displayName, providerName, anthropicUrl, openaiUr
|
|
|
7429
7781
|
model: streamingResult.model ?? displayName,
|
|
7430
7782
|
sessionId: null,
|
|
7431
7783
|
rawRequestBody: streamingRequestBody,
|
|
7432
|
-
responseStatus: streamingResult
|
|
7433
|
-
responseText:
|
|
7784
|
+
responseStatus: getResultResponseStatus(streamingResult),
|
|
7785
|
+
responseText: getResultResponseText(streamingResult),
|
|
7434
7786
|
inputTokens: streamingResult.inputTokens ?? null,
|
|
7435
7787
|
outputTokens: streamingResult.outputTokens ?? null,
|
|
7436
7788
|
cacheCreationInputTokens: null,
|
|
@@ -7443,7 +7795,7 @@ async function logModelResults(displayName, providerName, anthropicUrl, openaiUr
|
|
|
7443
7795
|
apiFormat: "openai",
|
|
7444
7796
|
isTest: true,
|
|
7445
7797
|
providerName,
|
|
7446
|
-
headers: captureFullDetails ? streamingResult
|
|
7798
|
+
headers: captureFullDetails ? getResultHeaders(streamingResult) : void 0
|
|
7447
7799
|
});
|
|
7448
7800
|
}
|
|
7449
7801
|
}
|
|
@@ -7848,21 +8200,23 @@ export {
|
|
|
7848
8200
|
Route$q as R,
|
|
7849
8201
|
TimeDisplayFormatSchema as T,
|
|
7850
8202
|
DEFAULT_SLOW_RESPONSE_THRESHOLD_SECONDS as a,
|
|
7851
|
-
|
|
7852
|
-
|
|
7853
|
-
|
|
7854
|
-
|
|
7855
|
-
|
|
8203
|
+
DEFAULT_PROVIDER_TEST_TIMEOUT_SECONDS as b,
|
|
8204
|
+
DEFAULT_TIME_DISPLAY_FORMAT as c,
|
|
8205
|
+
RuntimeConfigSchema as d,
|
|
8206
|
+
AnthropicRequestSchema as e,
|
|
8207
|
+
stripClaudeCodeBillingHeader as f,
|
|
7856
8208
|
getSessionPath as g,
|
|
7857
|
-
|
|
7858
|
-
|
|
7859
|
-
|
|
7860
|
-
|
|
7861
|
-
|
|
8209
|
+
providerHasContextMetadata as h,
|
|
8210
|
+
findProviderModelMetadata as i,
|
|
8211
|
+
createPendingProviderTestResults as j,
|
|
8212
|
+
ProviderTestResultsSchema as k,
|
|
8213
|
+
createFailedProviderTestResults as l,
|
|
7862
8214
|
maskApiKey as m,
|
|
7863
|
-
|
|
7864
|
-
|
|
8215
|
+
MAX_PROVIDER_TEST_TIMEOUT_SECONDS as n,
|
|
8216
|
+
resolveProviderContextWindow as o,
|
|
7865
8217
|
parseOpenAIResponse as p,
|
|
8218
|
+
isPlainRecord as q,
|
|
7866
8219
|
requestFormatForPath as r,
|
|
7867
|
-
safeGetOwnProperty as s
|
|
8220
|
+
safeGetOwnProperty as s,
|
|
8221
|
+
router as t
|
|
7868
8222
|
};
|