@tonyclaw/agent-inspector 2.0.21 → 2.0.23

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 (46) hide show
  1. package/.output/cli.js +10 -0
  2. package/.output/nitro.json +1 -1
  3. package/.output/public/assets/{CompareDrawer-ztKMd-FE.js → CompareDrawer-DnYQtd8R.js} +1 -1
  4. package/.output/public/assets/ProxyViewerContainer-BTYGkg36.js +115 -0
  5. package/.output/public/assets/{ReplayDialog-RNhfLSsW.js → ReplayDialog-B-3V95xT.js} +1 -1
  6. package/.output/public/assets/{RequestAnatomy-fsUI5HhH.js → RequestAnatomy-CT8hLGLa.js} +1 -1
  7. package/.output/public/assets/{ResponseView-B3YTDBBX.js → ResponseView-DK3CYom0.js} +1 -1
  8. package/.output/public/assets/{StreamingChunkSequence-CbGqQ0mO.js → StreamingChunkSequence-D3jJutjp.js} +1 -1
  9. package/.output/public/assets/_sessionId-DpdfAzbo.js +1 -0
  10. package/.output/public/assets/index-780zTVwp.css +1 -0
  11. package/.output/public/assets/index-BpJNbm9G.js +1 -0
  12. package/.output/public/assets/{main-lTQKpxiU.js → main-hF_572U6.js} +2 -2
  13. package/.output/server/_libs/lucide-react.mjs +27 -27
  14. package/.output/server/{_sessionId-DsF6LFJG.mjs → _sessionId-BqhNE2M8.mjs} +2 -2
  15. package/.output/server/_ssr/{CompareDrawer-DgdZcMpg.mjs → CompareDrawer-C4LQW4S1.mjs} +3 -3
  16. package/.output/server/_ssr/{ProxyViewerContainer-DaFW1IVu.mjs → ProxyViewerContainer-BKInvawk.mjs} +214 -41
  17. package/.output/server/_ssr/{ReplayDialog-BOaTX1ir.mjs → ReplayDialog-C3ZiRihL.mjs} +4 -4
  18. package/.output/server/_ssr/{RequestAnatomy-C-2_dejd.mjs → RequestAnatomy-DlVAPIQZ.mjs} +3 -3
  19. package/.output/server/_ssr/{ResponseView-BtRVhgzy.mjs → ResponseView-nMS0rkxu.mjs} +3 -3
  20. package/.output/server/_ssr/{StreamingChunkSequence-DZaerowX.mjs → StreamingChunkSequence-PDWqrNiO.mjs} +3 -3
  21. package/.output/server/_ssr/{index-B3_fgwFy.mjs → index-Cd1zD-lo.mjs} +2 -2
  22. package/.output/server/_ssr/index.mjs +2 -2
  23. package/.output/server/_ssr/{router-CDOnHAWy.mjs → router-R9gm7_sh.mjs} +394 -151
  24. package/.output/server/{_tanstack-start-manifest_v-Brrx1NEa.mjs → _tanstack-start-manifest_v-BnLVH_EX.mjs} +1 -1
  25. package/.output/server/index.mjs +60 -60
  26. package/package.json +1 -1
  27. package/src/cli/templates/codex-skill-onboard.ts +5 -0
  28. package/src/cli/templates/skill-onboard.ts +5 -0
  29. package/src/components/OnboardingBanner.tsx +4 -0
  30. package/src/components/ProxyViewer.tsx +5 -0
  31. package/src/components/providers/ProviderCard.tsx +178 -38
  32. package/src/components/providers/ProvidersPanel.tsx +21 -3
  33. package/src/components/providers/SettingsDialog.tsx +76 -2
  34. package/src/lib/providerTestContract.ts +13 -0
  35. package/src/lib/runtimeConfig.ts +8 -0
  36. package/src/lib/useOnboarding.ts +3 -0
  37. package/src/lib/useStripConfig.ts +22 -0
  38. package/src/proxy/config.ts +4 -0
  39. package/src/proxy/store.ts +198 -135
  40. package/src/routes/api/config.ts +7 -0
  41. package/src/routes/api/logs.stream.ts +1 -1
  42. package/src/routes/api/providers.$providerId.test.log.ts +28 -12
  43. package/.output/public/assets/ProxyViewerContainer-BT8Ilsbs.js +0 -114
  44. package/.output/public/assets/_sessionId-C9cpyfLX.js +0 -1
  45. package/.output/public/assets/index-0mTTpvA2.js +0 -1
  46. package/.output/public/assets/index-DynnYt7S.css +0 -1
@@ -1,8 +1,8 @@
1
1
  import { c as createRouter, a as createRootRoute, b as createFileRoute, l as lazyRouteComponent, O as Outlet, H as HeadContent, S as Scripts } from "../_libs/tanstack__react-router.mjs";
2
2
  import { j as jsxRuntimeExports } from "../_libs/react.mjs";
3
3
  import { S as SWRConfig } from "../_libs/swr.mjs";
4
- import { existsSync, readFileSync, mkdirSync, writeFileSync, renameSync, copyFileSync, unlinkSync, readdirSync, statSync, createReadStream, cpSync, rmSync } from "node:fs";
5
- import fs, { mkdir, appendFile, readFile, writeFile, readdir, open, stat, unlink } from "node:fs/promises";
4
+ import { existsSync, readFileSync, mkdirSync, writeFileSync, renameSync, copyFileSync, unlinkSync, readdirSync, statSync, createReadStream, cpSync, rmSync, createWriteStream } from "node:fs";
5
+ import fs, { mkdir, appendFile, readFile, writeFile, readdir, open, stat, unlink, rename } from "node:fs/promises";
6
6
  import { createInterface } from "node:readline";
7
7
  import { Buffer } from "node:buffer";
8
8
  import path, { join, isAbsolute, dirname } from "node:path";
@@ -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-DynnYt7S.css";
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-B3_fgwFy.mjs");
96
+ const $$splitComponentImporter$1 = () => import("./index-Cd1zD-lo.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-DsF6LFJG.mjs");
139
+ const $$splitComponentImporter = () => import("../_sessionId-BqhNE2M8.mjs");
140
140
  const Route$q = createFileRoute("/session/$sessionId")({
141
141
  component: lazyRouteComponent($$splitComponentImporter, "component"),
142
142
  parseParams: (params) => ({
@@ -1458,30 +1458,7 @@ async function getLogById(id) {
1458
1458
  }
1459
1459
  return null;
1460
1460
  }
1461
- const content = readFileSync(filePath, "utf-8");
1462
- const lines = content.split("\n");
1463
- let lastMatch = null;
1464
- for (const line of lines) {
1465
- if (line.trim() === "") continue;
1466
- try {
1467
- const parsed = JSON.parse(line);
1468
- if (typeof parsed === "object" && parsed !== null) {
1469
- const desc = Object.getOwnPropertyDescriptor(parsed, "id");
1470
- if (desc !== void 0 && typeof desc.value === "number" && desc.value === id) {
1471
- const result = CapturedLogSchema.safeParse(parsed);
1472
- if (result.success) {
1473
- lastMatch = normalizeLogSession(result.data);
1474
- if (result.data.responseStatus !== null) {
1475
- addToCache(lastMatch);
1476
- observeSessionLog(lastMatch);
1477
- return lastMatch;
1478
- }
1479
- }
1480
- }
1481
- }
1482
- } catch {
1483
- }
1484
- }
1461
+ const lastMatch = await scanLogFileForId(filePath, id);
1485
1462
  if (lastMatch !== null) {
1486
1463
  addToCache(lastMatch);
1487
1464
  observeSessionLog(lastMatch);
@@ -1492,6 +1469,33 @@ async function getLogById(id) {
1492
1469
  }
1493
1470
  return null;
1494
1471
  }
1472
+ async function scanLogFileForId(filePath, id) {
1473
+ let lastMatch = null;
1474
+ const fileStream = createInterface({
1475
+ input: createReadStream(filePath),
1476
+ crlfDelay: Infinity
1477
+ });
1478
+ for await (const line of fileStream) {
1479
+ if (line.trim() === "") continue;
1480
+ try {
1481
+ const parsed = JSON.parse(line);
1482
+ if (typeof parsed === "object" && parsed !== null) {
1483
+ const desc = Object.getOwnPropertyDescriptor(parsed, "id");
1484
+ if (desc !== void 0 && typeof desc.value === "number" && desc.value === id) {
1485
+ const result = CapturedLogSchema.safeParse(parsed);
1486
+ if (result.success) {
1487
+ lastMatch = normalizeLogSession(result.data);
1488
+ if (result.data.responseStatus !== null) {
1489
+ return lastMatch;
1490
+ }
1491
+ }
1492
+ }
1493
+ }
1494
+ } catch {
1495
+ }
1496
+ }
1497
+ return lastMatch;
1498
+ }
1495
1499
  function getFilteredLogs(sessionId, model) {
1496
1500
  return [...memoryCache.values()].filter((l) => {
1497
1501
  return matchesLogFilters(l, sessionId, model);
@@ -1502,31 +1506,20 @@ function matchesLogFilters(log, sessionId, model) {
1502
1506
  if (model !== void 0 && log.model !== model) return false;
1503
1507
  return true;
1504
1508
  }
1505
- function requestedWindowFitsMemory(filteredMemoryCount, offset, limit) {
1506
- return offset + limit <= filteredMemoryCount;
1507
- }
1508
- function paginateLogs(logs, offset, limit) {
1509
- return logs.slice(offset, offset + limit);
1510
- }
1511
- async function readPersistedLogsById() {
1512
- const byId = /* @__PURE__ */ new Map();
1509
+ async function visitPersistedLogs(visitor) {
1513
1510
  const logDir = resolveLogDir();
1514
- if (!existsSync(logDir)) return byId;
1511
+ if (!existsSync(logDir)) return;
1515
1512
  try {
1516
1513
  const entries = await readdir(logDir);
1517
1514
  const files = entries.filter((file) => file.endsWith(".jsonl")).sort();
1518
1515
  for (const file of files) {
1519
- await readPersistedLogFile(join(logDir, file), byId);
1516
+ await visitPersistedLogFile(join(logDir, file), visitor);
1520
1517
  }
1521
1518
  } catch (err) {
1522
1519
  logger.error("[store] Failed to list persisted logs:", String(err));
1523
1520
  }
1524
- for (const log of memoryCache.values()) {
1525
- byId.set(log.id, log);
1526
- }
1527
- return byId;
1528
1521
  }
1529
- async function readPersistedLogFile(filePath, byId) {
1522
+ async function visitPersistedLogFile(filePath, visitor) {
1530
1523
  if (!existsSync(filePath)) return;
1531
1524
  try {
1532
1525
  const fileStream = createInterface({
@@ -1540,8 +1533,7 @@ async function readPersistedLogFile(filePath, byId) {
1540
1533
  const result = CapturedLogSchema.safeParse(parsed);
1541
1534
  if (result.success) {
1542
1535
  const log = normalizeLogSession(result.data);
1543
- byId.set(log.id, log);
1544
- observeSessionLog(log);
1536
+ visitor(log);
1545
1537
  }
1546
1538
  } catch {
1547
1539
  }
@@ -1551,20 +1543,37 @@ async function readPersistedLogFile(filePath, byId) {
1551
1543
  }
1552
1544
  }
1553
1545
  async function listLogsPage(options) {
1554
- const memoryLogs = getFilteredLogs(options.sessionId, options.model);
1555
- if (requestedWindowFitsMemory(memoryLogs.length, options.offset, options.limit)) {
1556
- return {
1557
- logs: paginateLogs(memoryLogs, options.offset, options.limit),
1558
- total: memoryLogs.length,
1559
- offset: options.offset,
1560
- limit: options.limit
1561
- };
1546
+ const seenIds = /* @__PURE__ */ new Set();
1547
+ const pageById = /* @__PURE__ */ new Map();
1548
+ const pageStart = options.offset;
1549
+ const pageEnd = options.offset + options.limit;
1550
+ let total = 0;
1551
+ const visitLog = (log) => {
1552
+ if (!matchesLogFilters(log, options.sessionId, options.model)) return;
1553
+ if (!seenIds.has(log.id)) {
1554
+ seenIds.add(log.id);
1555
+ const position = total;
1556
+ total += 1;
1557
+ if (position >= pageStart && position < pageEnd) {
1558
+ pageById.set(log.id, log);
1559
+ }
1560
+ return;
1561
+ }
1562
+ if (pageById.has(log.id)) {
1563
+ pageById.set(log.id, log);
1564
+ }
1565
+ };
1566
+ await visitPersistedLogs((log) => {
1567
+ observeSessionLog(log);
1568
+ visitLog(log);
1569
+ });
1570
+ for (const log of memoryCache.values()) {
1571
+ visitLog(log);
1562
1572
  }
1563
- const persistedById = await readPersistedLogsById();
1564
- const persistedLogs = [...persistedById.values()].filter((log) => matchesLogFilters(log, options.sessionId, options.model)).sort((left, right) => left.id - right.id);
1573
+ const logs = [...pageById.values()].sort((left, right) => left.id - right.id);
1565
1574
  return {
1566
- logs: paginateLogs(persistedLogs, options.offset, options.limit),
1567
- total: persistedLogs.length,
1575
+ logs,
1576
+ total,
1568
1577
  offset: options.offset,
1569
1578
  limit: options.limit
1570
1579
  };
@@ -1687,35 +1696,100 @@ function readLogIdFromLine(line) {
1687
1696
  return null;
1688
1697
  }
1689
1698
  }
1699
+ function tempRewritePath(filePath) {
1700
+ return `${filePath}.rewrite-${String(process.pid)}-${String(Date.now())}.tmp`;
1701
+ }
1702
+ async function removeTempFile(filePath) {
1703
+ try {
1704
+ await unlink(filePath);
1705
+ } catch {
1706
+ }
1707
+ }
1708
+ function waitForWriterDrain(writer) {
1709
+ return new Promise((resolve) => {
1710
+ const cleanup = () => {
1711
+ writer.off("drain", onDrain);
1712
+ writer.off("error", onError);
1713
+ };
1714
+ const onDrain = () => {
1715
+ cleanup();
1716
+ resolve(true);
1717
+ };
1718
+ const onError = () => {
1719
+ cleanup();
1720
+ resolve(false);
1721
+ };
1722
+ writer.once("drain", onDrain);
1723
+ writer.once("error", onError);
1724
+ });
1725
+ }
1726
+ async function writeKeptLogLine(writer, line) {
1727
+ if (writer.write(`${line}
1728
+ `, "utf-8")) return true;
1729
+ return await waitForWriterDrain(writer);
1730
+ }
1731
+ function finishWriter(writer) {
1732
+ return new Promise((resolve) => {
1733
+ const cleanup = () => {
1734
+ writer.off("finish", onFinish);
1735
+ writer.off("error", onError);
1736
+ };
1737
+ const onFinish = () => {
1738
+ cleanup();
1739
+ resolve(true);
1740
+ };
1741
+ const onError = () => {
1742
+ cleanup();
1743
+ resolve(false);
1744
+ };
1745
+ writer.once("finish", onFinish);
1746
+ writer.once("error", onError);
1747
+ writer.end();
1748
+ });
1749
+ }
1690
1750
  async function rewriteLogFileWithoutIds(filePath, ids) {
1691
- let content;
1751
+ const tempPath = tempRewritePath(filePath);
1752
+ const writer = createWriteStream(tempPath, { encoding: "utf-8" });
1753
+ const removedIds = /* @__PURE__ */ new Set();
1754
+ let keptLineCount = 0;
1755
+ let writeOk = true;
1692
1756
  try {
1693
- content = await readFile(filePath, "utf-8");
1757
+ const fileStream = createInterface({
1758
+ input: createReadStream(filePath),
1759
+ crlfDelay: Infinity
1760
+ });
1761
+ for await (const line of fileStream) {
1762
+ if (line === "") continue;
1763
+ const id = readLogIdFromLine(line);
1764
+ if (id !== null && ids.has(id)) {
1765
+ removedIds.add(id);
1766
+ } else {
1767
+ keptLineCount += 1;
1768
+ writeOk = await writeKeptLogLine(writer, line);
1769
+ if (!writeOk) break;
1770
+ }
1771
+ }
1694
1772
  } catch (err) {
1695
- logger.warn("[store] Failed to read log file for deletion:", filePath, String(err));
1773
+ logger.warn("[store] Failed to stream log file for deletion:", filePath, String(err));
1774
+ writeOk = false;
1775
+ }
1776
+ if (!await finishWriter(writer) || !writeOk) {
1777
+ await removeTempFile(tempPath);
1696
1778
  return { rewritten: false, removedIds: /* @__PURE__ */ new Set() };
1697
1779
  }
1698
- const lines = content.split("\n");
1699
- const keptLines = [];
1700
- const removedIds = /* @__PURE__ */ new Set();
1701
- for (const line of lines) {
1702
- if (line === "") continue;
1703
- const id = readLogIdFromLine(line);
1704
- if (id !== null && ids.has(id)) {
1705
- removedIds.add(id);
1706
- } else {
1707
- keptLines.push(line);
1708
- }
1780
+ if (removedIds.size === 0) {
1781
+ await removeTempFile(tempPath);
1782
+ return { rewritten: false, removedIds };
1709
1783
  }
1710
- if (removedIds.size === 0) return { rewritten: false, removedIds };
1711
1784
  try {
1712
- if (keptLines.length === 0) {
1785
+ if (keptLineCount === 0) {
1786
+ await removeTempFile(tempPath);
1713
1787
  await unlink(filePath);
1714
1788
  } else {
1715
- await writeFile(filePath, `${keptLines.join("\n")}
1716
- `, "utf-8");
1789
+ await rename(tempPath, filePath);
1717
1790
  }
1718
1791
  } catch (err) {
1792
+ await removeTempFile(tempPath);
1719
1793
  logger.warn("[store] Failed to rewrite log file after deletion:", filePath, String(err));
1720
1794
  return { rewritten: false, removedIds: /* @__PURE__ */ new Set() };
1721
1795
  }
@@ -3527,6 +3601,8 @@ async function getClientInfo(request) {
3527
3601
  }
3528
3602
  const DEFAULT_SLOW_RESPONSE_THRESHOLD_SECONDS = 10;
3529
3603
  const MAX_SLOW_RESPONSE_THRESHOLD_SECONDS = 600;
3604
+ const DEFAULT_PROVIDER_TEST_TIMEOUT_SECONDS = 60;
3605
+ const MAX_PROVIDER_TEST_TIMEOUT_SECONDS = 600;
3530
3606
  const DEFAULT_TIME_DISPLAY_FORMAT = "time";
3531
3607
  const DEFAULT_CAPTURE_MODE = "simple";
3532
3608
  const TimeDisplayFormatSchema = _enum(["time", "full"]);
@@ -3535,6 +3611,7 @@ const RuntimeConfigSchema = object({
3535
3611
  stripClaudeCodeBillingHeader: boolean(),
3536
3612
  hasSeenOnboarding: boolean().default(false),
3537
3613
  slowResponseThresholdSeconds: number().int().min(0).max(MAX_SLOW_RESPONSE_THRESHOLD_SECONDS).default(DEFAULT_SLOW_RESPONSE_THRESHOLD_SECONDS),
3614
+ providerTestTimeoutSeconds: number().int().min(1).max(MAX_PROVIDER_TEST_TIMEOUT_SECONDS).default(DEFAULT_PROVIDER_TEST_TIMEOUT_SECONDS),
3538
3615
  timeDisplayFormat: TimeDisplayFormatSchema.default(DEFAULT_TIME_DISPLAY_FORMAT),
3539
3616
  captureMode: CaptureModeSchema.default(DEFAULT_CAPTURE_MODE)
3540
3617
  });
@@ -3579,6 +3656,7 @@ function resolveInitialConfig() {
3579
3656
  stripClaudeCodeBillingHeader: true,
3580
3657
  hasSeenOnboarding: false,
3581
3658
  slowResponseThresholdSeconds: DEFAULT_SLOW_RESPONSE_THRESHOLD_SECONDS,
3659
+ providerTestTimeoutSeconds: DEFAULT_PROVIDER_TEST_TIMEOUT_SECONDS,
3582
3660
  timeDisplayFormat: DEFAULT_TIME_DISPLAY_FORMAT,
3583
3661
  captureMode
3584
3662
  };
@@ -3587,6 +3665,7 @@ function resolveInitialConfig() {
3587
3665
  stripClaudeCodeBillingHeader: false,
3588
3666
  hasSeenOnboarding: false,
3589
3667
  slowResponseThresholdSeconds: DEFAULT_SLOW_RESPONSE_THRESHOLD_SECONDS,
3668
+ providerTestTimeoutSeconds: DEFAULT_PROVIDER_TEST_TIMEOUT_SECONDS,
3590
3669
  timeDisplayFormat: DEFAULT_TIME_DISPLAY_FORMAT,
3591
3670
  captureMode
3592
3671
  };
@@ -3640,6 +3719,7 @@ function toPersistedConfig(value) {
3640
3719
  stripClaudeCodeBillingHeader: value.stripClaudeCodeBillingHeader,
3641
3720
  hasSeenOnboarding: value.hasSeenOnboarding,
3642
3721
  slowResponseThresholdSeconds: value.slowResponseThresholdSeconds,
3722
+ providerTestTimeoutSeconds: value.providerTestTimeoutSeconds,
3643
3723
  timeDisplayFormat: value.timeDisplayFormat
3644
3724
  };
3645
3725
  }
@@ -5233,6 +5313,7 @@ const RuntimeConfigPatchSchema = object({
5233
5313
  stripClaudeCodeBillingHeader: boolean().optional(),
5234
5314
  hasSeenOnboarding: boolean().optional(),
5235
5315
  slowResponseThresholdSeconds: number().int().min(0).max(MAX_SLOW_RESPONSE_THRESHOLD_SECONDS).optional(),
5316
+ providerTestTimeoutSeconds: number().int().min(1).max(MAX_PROVIDER_TEST_TIMEOUT_SECONDS).optional(),
5236
5317
  timeDisplayFormat: TimeDisplayFormatSchema.optional()
5237
5318
  }).strict().refine((v) => Object.keys(v).length > 0, {
5238
5319
  message: "At least one field must be provided"
@@ -5813,7 +5894,7 @@ const Route$e = createFileRoute("/api/providers/$providerId")({
5813
5894
  }
5814
5895
  }
5815
5896
  });
5816
- const INITIAL_STREAM_LOG_LIMIT = 500;
5897
+ const INITIAL_STREAM_LOG_LIMIT = 100;
5817
5898
  const Route$d = createFileRoute("/api/logs/stream")({
5818
5899
  server: {
5819
5900
  handlers: {
@@ -6599,10 +6680,11 @@ function buildProviderTestRequestBody(model, mode) {
6599
6680
  return { ...base, stream: true };
6600
6681
  }
6601
6682
  }
6683
+ 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.";
6602
6684
  const ERROR_HINTS = {
6603
- timeout: "The request took too long. Check your network connection or try again.",
6604
- network_unreachable: "Cannot reach the server. Verify the base URL and check your firewall settings.",
6605
- connection_refused: "Connection was refused. Make sure the provider server is running and the URL is correct.",
6685
+ timeout: `The request took too long. Check your network connection or try again. ${CONTAINER_NETWORK_HINT}`,
6686
+ network_unreachable: `Cannot reach the server. Verify the base URL and check your firewall settings. ${CONTAINER_NETWORK_HINT}`,
6687
+ connection_refused: `Connection was refused. Make sure the provider server is running and the URL is correct. ${CONTAINER_NETWORK_HINT}`,
6606
6688
  auth_failed: "Authentication failed. Check your API key is correct and has not expired.",
6607
6689
  rate_limited: "Too many requests. Wait a moment and try again, or check your API quota.",
6608
6690
  server_error: "The provider server encountered an error. Check their status page and try again later.",
@@ -6610,6 +6692,17 @@ const ERROR_HINTS = {
6610
6692
  unknown: "An unexpected error occurred. Check the details and try again."
6611
6693
  };
6612
6694
  const MAX_ERROR_DETAILS_LENGTH = 200;
6695
+ const MAX_DEBUG_TEXT_LENGTH = 2e4;
6696
+ const REDACTED_HEADER_VALUE = "[redacted]";
6697
+ const SENSITIVE_HEADER_NAMES = /* @__PURE__ */ new Set([
6698
+ "authorization",
6699
+ "x-api-key",
6700
+ "api-key",
6701
+ "x-goog-api-key",
6702
+ "anthropic-api-key",
6703
+ "openai-api-key",
6704
+ "proxy-authorization"
6705
+ ]);
6613
6706
  function classifyError(error, responseStatus) {
6614
6707
  const errorStr = String(error);
6615
6708
  const errorLower = errorStr.toLowerCase();
@@ -6649,6 +6742,9 @@ function classifyError(error, responseStatus) {
6649
6742
  if (errorLower.includes("bad gateway") || errorLower.includes("gateway timeout")) {
6650
6743
  return { type: "server_error", details: extractErrorDetails(errorStr) };
6651
6744
  }
6745
+ if (errorLower.includes("invalid response") || errorLower.includes("unexpected token") || errorLower.includes("failed to parse") || errorLower.includes("schema") || errorLower.includes("zod")) {
6746
+ return { type: "invalid_response", details: extractErrorDetails(errorStr) };
6747
+ }
6652
6748
  if (responseStatus !== void 0) {
6653
6749
  if (responseStatus === 401 || responseStatus === 403) {
6654
6750
  return { type: "auth_failed", details: `Authentication failed (HTTP ${responseStatus})` };
@@ -6689,9 +6785,64 @@ function truncateErrorDetails(details) {
6689
6785
  }
6690
6786
  return details.slice(0, MAX_ERROR_DETAILS_LENGTH) + "...";
6691
6787
  }
6692
- function createErrorResult(error, latencyMs, streaming, responseStatus) {
6788
+ function truncateDebugText(text) {
6789
+ if (text.length <= MAX_DEBUG_TEXT_LENGTH) {
6790
+ return text;
6791
+ }
6792
+ return `${text.slice(0, MAX_DEBUG_TEXT_LENGTH)}
6793
+ ... truncated`;
6794
+ }
6795
+ function headersToRecord(headers) {
6796
+ const result = {};
6797
+ headers.forEach((value, key) => {
6798
+ result[key] = value;
6799
+ });
6800
+ return result;
6801
+ }
6802
+ function redactHeaderValue(name, value) {
6803
+ const lowerName = name.toLowerCase();
6804
+ if (!SENSITIVE_HEADER_NAMES.has(lowerName)) {
6805
+ return value;
6806
+ }
6807
+ if (lowerName === "authorization" && value.startsWith("Bearer ")) {
6808
+ return `Bearer ${REDACTED_HEADER_VALUE}`;
6809
+ }
6810
+ return REDACTED_HEADER_VALUE;
6811
+ }
6812
+ function redactHeaders(headers) {
6813
+ const result = {};
6814
+ for (const [name, value] of Object.entries(headers)) {
6815
+ result[name] = redactHeaderValue(name, value);
6816
+ }
6817
+ return result;
6818
+ }
6819
+ function createTestDebug(input) {
6820
+ const debug = {
6821
+ requestUrl: input.requestUrl,
6822
+ requestMethod: "POST",
6823
+ requestHeaders: redactHeaders(input.requestHeaders),
6824
+ requestBody: truncateDebugText(input.requestBody)
6825
+ };
6826
+ if (input.response !== void 0) {
6827
+ debug.responseStatus = input.response.status;
6828
+ debug.responseStatusText = input.response.statusText;
6829
+ debug.responseHeaders = headersToRecord(input.response.headers);
6830
+ }
6831
+ if (input.responseBody !== void 0) {
6832
+ debug.responseBody = truncateDebugText(input.responseBody);
6833
+ }
6834
+ return debug;
6835
+ }
6836
+ async function readResponseText(response) {
6837
+ try {
6838
+ return await response.text();
6839
+ } catch (err) {
6840
+ return `Failed to read response body: ${String(err)}`;
6841
+ }
6842
+ }
6843
+ function createErrorResult(error, latencyMs, streaming, responseStatus, debug) {
6693
6844
  const { type, details } = classifyError(error, responseStatus);
6694
- return {
6845
+ const result = {
6695
6846
  success: false,
6696
6847
  error: {
6697
6848
  message: getErrorMessage(type),
@@ -6702,6 +6853,13 @@ function createErrorResult(error, latencyMs, streaming, responseStatus) {
6702
6853
  latencyMs,
6703
6854
  streaming
6704
6855
  };
6856
+ if (debug !== void 0) {
6857
+ result.debug = debug;
6858
+ if (debug.requestHeaders !== void 0) {
6859
+ result.requestHeaders = debug.requestHeaders;
6860
+ }
6861
+ }
6862
+ return result;
6705
6863
  }
6706
6864
  function getErrorMessage(type) {
6707
6865
  const messages = {
@@ -6751,7 +6909,9 @@ const OpenAIResponseSchema = object({
6751
6909
  })
6752
6910
  )
6753
6911
  });
6754
- const TEST_TIMEOUT_MS = 3e4;
6912
+ function getProviderTestTimeoutMs() {
6913
+ return getConfig().providerTestTimeoutSeconds * 1e3;
6914
+ }
6755
6915
  function buildTestRequestHeaders(provider) {
6756
6916
  const headers = new Headers();
6757
6917
  headers.set("Content-Type", "application/json");
@@ -6766,27 +6926,36 @@ async function testEndpoint(baseUrl, provider, path2, model, isOpenAI) {
6766
6926
  const startTime = Date.now();
6767
6927
  const body = JSON.stringify(buildProviderTestRequestBody(model, "non-streaming"));
6768
6928
  const requestHeaders = buildTestRequestHeaders(provider);
6929
+ let requestUrl = baseUrl;
6769
6930
  const controller = new AbortController();
6770
- const timeoutId = setTimeout(() => controller.abort(), TEST_TIMEOUT_MS);
6931
+ const timeoutId = setTimeout(() => controller.abort(), getProviderTestTimeoutMs());
6771
6932
  try {
6772
- const url = buildUpstreamUrl(baseUrl, path2);
6773
- const response = await fetch(url, {
6933
+ requestUrl = buildUpstreamUrl(baseUrl, path2);
6934
+ const response = await fetch(requestUrl, {
6774
6935
  method: "POST",
6775
6936
  headers: requestHeaders,
6776
6937
  body,
6777
6938
  signal: controller.signal
6778
6939
  });
6779
- clearTimeout(timeoutId);
6780
6940
  const latencyMs = Date.now() - startTime;
6781
6941
  if (!response.ok) {
6942
+ const responseText2 = await readResponseText(response);
6782
6943
  return createErrorResult(
6783
6944
  `HTTP ${response.status}: ${response.statusText}`,
6784
6945
  latencyMs,
6785
6946
  false,
6786
- response.status
6947
+ response.status,
6948
+ createTestDebug({
6949
+ requestUrl,
6950
+ requestHeaders,
6951
+ requestBody: body,
6952
+ response,
6953
+ responseBody: responseText2
6954
+ })
6787
6955
  );
6788
6956
  }
6789
6957
  const responseText = await response.text();
6958
+ const safeRequestHeaders = redactHeaders(requestHeaders);
6790
6959
  try {
6791
6960
  if (isOpenAI) {
6792
6961
  const json = OpenAIResponseSchema.parse(JSON.parse(responseText));
@@ -6802,7 +6971,7 @@ async function testEndpoint(baseUrl, provider, path2, model, isOpenAI) {
6802
6971
  latencyMs,
6803
6972
  content: content !== null && content !== "" ? [{ type: "text", text: content }] : void 0,
6804
6973
  rawResponse: responseText,
6805
- requestHeaders
6974
+ requestHeaders: safeRequestHeaders
6806
6975
  };
6807
6976
  } else {
6808
6977
  const json = AnthropicResponseSchema.parse(JSON.parse(responseText));
@@ -6829,61 +6998,78 @@ async function testEndpoint(baseUrl, provider, path2, model, isOpenAI) {
6829
6998
  latencyMs,
6830
6999
  content: content.length > 0 ? content : void 0,
6831
7000
  rawResponse: responseText,
6832
- requestHeaders
7001
+ requestHeaders: safeRequestHeaders
6833
7002
  };
6834
7003
  }
6835
7004
  } catch (parseErr) {
6836
- return {
6837
- success: true,
6838
- model,
7005
+ return createErrorResult(
7006
+ `Invalid response: ${String(parseErr)}`,
6839
7007
  latencyMs,
6840
- content: [{ type: "text", text: responseText.slice(0, 2e3) }],
6841
- rawResponse: responseText,
6842
- requestHeaders
6843
- };
7008
+ false,
7009
+ response.status,
7010
+ createTestDebug({
7011
+ requestUrl,
7012
+ requestHeaders,
7013
+ requestBody: body,
7014
+ response,
7015
+ responseBody: responseText
7016
+ })
7017
+ );
6844
7018
  }
6845
7019
  } catch (err) {
7020
+ return createErrorResult(
7021
+ err,
7022
+ Date.now() - startTime,
7023
+ false,
7024
+ void 0,
7025
+ createTestDebug({ requestUrl, requestHeaders, requestBody: body })
7026
+ );
7027
+ } finally {
6846
7028
  clearTimeout(timeoutId);
6847
- return createErrorResult(err, Date.now() - startTime, false);
6848
7029
  }
6849
7030
  }
6850
7031
  async function testStreamingEndpoint(baseUrl, provider, path2, model, isOpenAI) {
6851
7032
  const startTime = Date.now();
6852
7033
  const body = JSON.stringify(buildProviderTestRequestBody(model, "streaming"));
6853
7034
  const requestHeaders = buildTestRequestHeaders(provider);
7035
+ let requestUrl = baseUrl;
6854
7036
  const controller = new AbortController();
6855
- const timeoutId = setTimeout(() => controller.abort(), TEST_TIMEOUT_MS);
7037
+ const timeoutId = setTimeout(() => controller.abort(), getProviderTestTimeoutMs());
6856
7038
  try {
6857
- const url = buildUpstreamUrl(baseUrl, path2);
6858
- const response = await fetch(url, {
7039
+ requestUrl = buildUpstreamUrl(baseUrl, path2);
7040
+ const response = await fetch(requestUrl, {
6859
7041
  method: "POST",
6860
7042
  headers: requestHeaders,
6861
7043
  body,
6862
7044
  signal: controller.signal
6863
7045
  });
6864
- clearTimeout(timeoutId);
6865
7046
  const latencyMs = Date.now() - startTime;
6866
7047
  if (!response.ok) {
7048
+ const responseText = await readResponseText(response);
6867
7049
  return createErrorResult(
6868
7050
  `HTTP ${response.status}: ${response.statusText}`,
6869
7051
  latencyMs,
6870
7052
  true,
6871
- response.status
7053
+ response.status,
7054
+ createTestDebug({
7055
+ requestUrl,
7056
+ requestHeaders,
7057
+ requestBody: body,
7058
+ response,
7059
+ responseBody: responseText
7060
+ })
6872
7061
  );
6873
7062
  }
6874
7063
  const chunks = [];
6875
7064
  const reader = response.body?.getReader();
6876
7065
  if (!reader) {
6877
- return {
6878
- success: false,
6879
- error: {
6880
- message: "No response body",
6881
- type: "invalid_response",
6882
- hint: ERROR_HINTS.invalid_response
6883
- },
7066
+ return createErrorResult(
7067
+ "Invalid response: no response body",
6884
7068
  latencyMs,
6885
- streaming: true
6886
- };
7069
+ true,
7070
+ response.status,
7071
+ createTestDebug({ requestUrl, requestHeaders, requestBody: body, response })
7072
+ );
6887
7073
  }
6888
7074
  const decoder = new TextDecoder();
6889
7075
  const MAX_CHUNKS_SIZE = 10 * 1024 * 1024;
@@ -6896,7 +7082,15 @@ async function testStreamingEndpoint(baseUrl, provider, path2, model, isOpenAI)
6896
7082
  return createErrorResult(
6897
7083
  "Response too large (exceeded 10MB limit)",
6898
7084
  Date.now() - startTime,
6899
- true
7085
+ true,
7086
+ response.status,
7087
+ createTestDebug({
7088
+ requestUrl,
7089
+ requestHeaders,
7090
+ requestBody: body,
7091
+ response,
7092
+ responseBody: chunks.join("")
7093
+ })
6900
7094
  );
6901
7095
  }
6902
7096
  const decoded = decoder.decode(value, { stream: true });
@@ -6908,9 +7102,23 @@ async function testStreamingEndpoint(baseUrl, provider, path2, model, isOpenAI)
6908
7102
  chunks.push(finalChunk);
6909
7103
  }
6910
7104
  } catch (readErr) {
6911
- return createErrorResult(`Stream read error: ${readErr}`, latencyMs, true);
7105
+ const error = readErr instanceof Error && readErr.name === "AbortError" ? readErr : `Stream read error: ${String(readErr)}`;
7106
+ return createErrorResult(
7107
+ error,
7108
+ latencyMs,
7109
+ true,
7110
+ response.status,
7111
+ createTestDebug({
7112
+ requestUrl,
7113
+ requestHeaders,
7114
+ requestBody: body,
7115
+ response,
7116
+ responseBody: chunks.join("")
7117
+ })
7118
+ );
6912
7119
  }
6913
7120
  const fullResponse = chunks.join("");
7121
+ const safeRequestHeaders = redactHeaders(requestHeaders);
6914
7122
  const mockLog = {
6915
7123
  id: 0,
6916
7124
  timestamp: "",
@@ -6982,23 +7190,33 @@ async function testStreamingEndpoint(baseUrl, provider, path2, model, isOpenAI)
6982
7190
  rawResponse: reconstructedJson,
6983
7191
  streaming: true,
6984
7192
  streamingChunks,
6985
- requestHeaders
7193
+ requestHeaders: safeRequestHeaders
6986
7194
  };
6987
7195
  } catch {
6988
- return {
6989
- success: true,
6990
- model,
7196
+ return createErrorResult(
7197
+ "Invalid response: could not parse reconstructed stream response",
6991
7198
  latencyMs,
6992
- content: [{ type: "text", text: reconstructedJson.slice(0, 2e3) }],
6993
- rawResponse: reconstructedJson,
6994
- streaming: true,
6995
- streamingChunks,
6996
- requestHeaders
6997
- };
7199
+ true,
7200
+ response.status,
7201
+ createTestDebug({
7202
+ requestUrl,
7203
+ requestHeaders,
7204
+ requestBody: body,
7205
+ response,
7206
+ responseBody: fullResponse
7207
+ })
7208
+ );
6998
7209
  }
6999
7210
  } catch (err) {
7211
+ return createErrorResult(
7212
+ err,
7213
+ Date.now() - startTime,
7214
+ true,
7215
+ void 0,
7216
+ createTestDebug({ requestUrl, requestHeaders, requestBody: body })
7217
+ );
7218
+ } finally {
7000
7219
  clearTimeout(timeoutId);
7001
- return createErrorResult(err, Date.now() - startTime, true);
7002
7220
  }
7003
7221
  }
7004
7222
  const Route$7 = createFileRoute("/api/providers/$providerId/test")({
@@ -7451,6 +7669,16 @@ const ProviderTestContentSchema = object({
7451
7669
  text: string().optional(),
7452
7670
  thinking: string().optional()
7453
7671
  });
7672
+ const ProviderTestDebugSchema = object({
7673
+ requestUrl: string().optional(),
7674
+ requestMethod: string().optional(),
7675
+ requestHeaders: record(string(), string()).optional(),
7676
+ requestBody: string().optional(),
7677
+ responseStatus: number().optional(),
7678
+ responseStatusText: string().optional(),
7679
+ responseHeaders: record(string(), string()).optional(),
7680
+ responseBody: string().optional()
7681
+ });
7454
7682
  const ProviderTestResultSchema = object({
7455
7683
  success: boolean(),
7456
7684
  error: ProviderTestErrorSchema.optional(),
@@ -7467,7 +7695,8 @@ const ProviderTestResultSchema = object({
7467
7695
  chunks: array(StreamingChunkSchema$1),
7468
7696
  truncated: boolean().default(false)
7469
7697
  }).optional(),
7470
- requestHeaders: record(string(), string()).optional()
7698
+ requestHeaders: record(string(), string()).optional(),
7699
+ debug: ProviderTestDebugSchema.optional()
7471
7700
  });
7472
7701
  const ProviderTestStateSchema = union([
7473
7702
  ProviderTestResultSchema,
@@ -7516,6 +7745,18 @@ function createFailedProviderTestResults(message, type) {
7516
7745
  function hasSuccessField(result) {
7517
7746
  return Object.prototype.hasOwnProperty.call(result, "success");
7518
7747
  }
7748
+ function getResultResponseStatus(result) {
7749
+ if (result.debug?.responseStatus !== void 0) {
7750
+ return result.debug.responseStatus;
7751
+ }
7752
+ return result.success ? 200 : 500;
7753
+ }
7754
+ function getResultResponseText(result) {
7755
+ return result.rawResponse ?? result.debug?.responseBody ?? JSON.stringify(result);
7756
+ }
7757
+ function getResultHeaders(result) {
7758
+ return result.requestHeaders ?? result.debug?.requestHeaders ?? {};
7759
+ }
7519
7760
  async function logModelResults(displayName, providerName, anthropicUrl, openaiUrl, modelResults, captureFullDetails) {
7520
7761
  const usageModel = getModelUsageName(displayName, providerName);
7521
7762
  if (anthropicUrl !== void 0) {
@@ -7532,8 +7773,8 @@ async function logModelResults(displayName, providerName, anthropicUrl, openaiUr
7532
7773
  model: nonStreamingResult.model ?? displayName,
7533
7774
  sessionId: null,
7534
7775
  rawRequestBody: requestBody,
7535
- responseStatus: nonStreamingResult.success ? 200 : 500,
7536
- responseText: nonStreamingResult.rawResponse ?? JSON.stringify(nonStreamingResult),
7776
+ responseStatus: getResultResponseStatus(nonStreamingResult),
7777
+ responseText: getResultResponseText(nonStreamingResult),
7537
7778
  inputTokens: nonStreamingResult.inputTokens ?? null,
7538
7779
  outputTokens: nonStreamingResult.outputTokens ?? null,
7539
7780
  cacheCreationInputTokens: nonStreamingResult.cacheCreationInputTokens ?? null,
@@ -7545,7 +7786,7 @@ async function logModelResults(displayName, providerName, anthropicUrl, openaiUr
7545
7786
  apiFormat: "anthropic",
7546
7787
  isTest: true,
7547
7788
  providerName,
7548
- headers: captureFullDetails ? nonStreamingResult.requestHeaders ?? {} : void 0
7789
+ headers: captureFullDetails ? getResultHeaders(nonStreamingResult) : void 0
7549
7790
  });
7550
7791
  const streamingRequestBody = JSON.stringify(
7551
7792
  buildProviderTestRequestBody(usageModel, "streaming")
@@ -7557,8 +7798,8 @@ async function logModelResults(displayName, providerName, anthropicUrl, openaiUr
7557
7798
  model: streamingResult.model ?? displayName,
7558
7799
  sessionId: null,
7559
7800
  rawRequestBody: streamingRequestBody,
7560
- responseStatus: streamingResult.success ? 200 : 500,
7561
- responseText: streamingResult.rawResponse ?? JSON.stringify(streamingResult),
7801
+ responseStatus: getResultResponseStatus(streamingResult),
7802
+ responseText: getResultResponseText(streamingResult),
7562
7803
  inputTokens: streamingResult.inputTokens ?? null,
7563
7804
  outputTokens: streamingResult.outputTokens ?? null,
7564
7805
  cacheCreationInputTokens: streamingResult.cacheCreationInputTokens ?? null,
@@ -7571,7 +7812,7 @@ async function logModelResults(displayName, providerName, anthropicUrl, openaiUr
7571
7812
  apiFormat: "anthropic",
7572
7813
  isTest: true,
7573
7814
  providerName,
7574
- headers: captureFullDetails ? streamingResult.requestHeaders ?? {} : void 0
7815
+ headers: captureFullDetails ? getResultHeaders(streamingResult) : void 0
7575
7816
  });
7576
7817
  }
7577
7818
  }
@@ -7589,8 +7830,8 @@ async function logModelResults(displayName, providerName, anthropicUrl, openaiUr
7589
7830
  model: nonStreamingResult.model ?? displayName,
7590
7831
  sessionId: null,
7591
7832
  rawRequestBody: requestBody,
7592
- responseStatus: nonStreamingResult.success ? 200 : 500,
7593
- responseText: nonStreamingResult.rawResponse ?? JSON.stringify(nonStreamingResult),
7833
+ responseStatus: getResultResponseStatus(nonStreamingResult),
7834
+ responseText: getResultResponseText(nonStreamingResult),
7594
7835
  inputTokens: nonStreamingResult.inputTokens ?? null,
7595
7836
  outputTokens: nonStreamingResult.outputTokens ?? null,
7596
7837
  cacheCreationInputTokens: null,
@@ -7602,7 +7843,7 @@ async function logModelResults(displayName, providerName, anthropicUrl, openaiUr
7602
7843
  apiFormat: "openai",
7603
7844
  isTest: true,
7604
7845
  providerName,
7605
- headers: captureFullDetails ? nonStreamingResult.requestHeaders ?? {} : void 0
7846
+ headers: captureFullDetails ? getResultHeaders(nonStreamingResult) : void 0
7606
7847
  });
7607
7848
  const streamingRequestBody = JSON.stringify(
7608
7849
  buildProviderTestRequestBody(usageModel, "streaming")
@@ -7614,8 +7855,8 @@ async function logModelResults(displayName, providerName, anthropicUrl, openaiUr
7614
7855
  model: streamingResult.model ?? displayName,
7615
7856
  sessionId: null,
7616
7857
  rawRequestBody: streamingRequestBody,
7617
- responseStatus: streamingResult.success ? 200 : 500,
7618
- responseText: streamingResult.rawResponse ?? JSON.stringify(streamingResult),
7858
+ responseStatus: getResultResponseStatus(streamingResult),
7859
+ responseText: getResultResponseText(streamingResult),
7619
7860
  inputTokens: streamingResult.inputTokens ?? null,
7620
7861
  outputTokens: streamingResult.outputTokens ?? null,
7621
7862
  cacheCreationInputTokens: null,
@@ -7628,7 +7869,7 @@ async function logModelResults(displayName, providerName, anthropicUrl, openaiUr
7628
7869
  apiFormat: "openai",
7629
7870
  isTest: true,
7630
7871
  providerName,
7631
- headers: captureFullDetails ? streamingResult.requestHeaders ?? {} : void 0
7872
+ headers: captureFullDetails ? getResultHeaders(streamingResult) : void 0
7632
7873
  });
7633
7874
  }
7634
7875
  }
@@ -8033,21 +8274,23 @@ export {
8033
8274
  Route$q as R,
8034
8275
  TimeDisplayFormatSchema as T,
8035
8276
  DEFAULT_SLOW_RESPONSE_THRESHOLD_SECONDS as a,
8036
- DEFAULT_TIME_DISPLAY_FORMAT as b,
8037
- RuntimeConfigSchema as c,
8038
- AnthropicRequestSchema as d,
8039
- stripClaudeCodeBillingHeader as e,
8040
- providerHasContextMetadata as f,
8277
+ DEFAULT_PROVIDER_TEST_TIMEOUT_SECONDS as b,
8278
+ DEFAULT_TIME_DISPLAY_FORMAT as c,
8279
+ RuntimeConfigSchema as d,
8280
+ AnthropicRequestSchema as e,
8281
+ stripClaudeCodeBillingHeader as f,
8041
8282
  getSessionPath as g,
8042
- findProviderModelMetadata as h,
8043
- createPendingProviderTestResults as i,
8044
- ProviderTestResultsSchema as j,
8045
- createFailedProviderTestResults as k,
8046
- resolveProviderContextWindow as l,
8283
+ providerHasContextMetadata as h,
8284
+ findProviderModelMetadata as i,
8285
+ createPendingProviderTestResults as j,
8286
+ ProviderTestResultsSchema as k,
8287
+ createFailedProviderTestResults as l,
8047
8288
  maskApiKey as m,
8048
- isPlainRecord as n,
8049
- router as o,
8289
+ MAX_PROVIDER_TEST_TIMEOUT_SECONDS as n,
8290
+ resolveProviderContextWindow as o,
8050
8291
  parseOpenAIResponse as p,
8292
+ isPlainRecord as q,
8051
8293
  requestFormatForPath as r,
8052
- safeGetOwnProperty as s
8294
+ safeGetOwnProperty as s,
8295
+ router as t
8053
8296
  };