@tonyclaw/agent-inspector 2.1.16 → 2.1.18

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 (55) hide show
  1. package/.output/cli.js +57 -13
  2. package/.output/nitro.json +1 -1
  3. package/.output/public/assets/{CompareDrawer-Ccrrcx1j.js → CompareDrawer-Fqqw5Lci.js} +1 -1
  4. package/.output/public/assets/ProxyViewerContainer-CP_RzwW9.js +106 -0
  5. package/.output/public/assets/{ReplayDialog-C7axhr-l.js → ReplayDialog-hYhz_i6W.js} +1 -1
  6. package/.output/public/assets/{RequestAnatomy-WOptg8j_.js → RequestAnatomy-CTuWbtwC.js} +1 -1
  7. package/.output/public/assets/{ResponseView-CSAcxh_M.js → ResponseView-CsZ7S5Gv.js} +2 -2
  8. package/.output/public/assets/{StreamingChunkSequence-DJS5KhPx.js → StreamingChunkSequence-PIbJMotU.js} +1 -1
  9. package/.output/public/assets/_sessionId-CUGA9qU3.js +1 -0
  10. package/.output/public/assets/{index-DMPNh46t.js → index-F7mynwuH.js} +1 -1
  11. package/.output/public/assets/index-G4dTUobw.js +1 -0
  12. package/.output/public/assets/index-gvYkgMPF.css +1 -0
  13. package/.output/public/assets/{json-viewer-inX5QSa3.js → json-viewer-DCXtNmmD.js} +1 -1
  14. package/.output/public/assets/{main-aCAKYGSD.js → main-BJZf7_Ib.js} +2 -2
  15. package/.output/server/_libs/lucide-react.mjs +220 -202
  16. package/.output/server/{_sessionId-C0fhvQnn.mjs → _sessionId-DjSHDNh8.mjs} +2 -2
  17. package/.output/server/_ssr/{CompareDrawer-CO-Ti5sg.mjs → CompareDrawer-Dal52IFo.mjs} +3 -3
  18. package/.output/server/_ssr/{ProxyViewerContainer-N4J7uBCX.mjs → ProxyViewerContainer-CVqFZGff.mjs} +1833 -1366
  19. package/.output/server/_ssr/{ReplayDialog-J1VxC0In.mjs → ReplayDialog-BOEgdMes.mjs} +4 -4
  20. package/.output/server/_ssr/{RequestAnatomy-DBH-F3rq.mjs → RequestAnatomy-gch7_vCV.mjs} +2 -2
  21. package/.output/server/_ssr/{ResponseView-DLFwV7Hd.mjs → ResponseView-lEWPy-H4.mjs} +3 -3
  22. package/.output/server/_ssr/{StreamingChunkSequence-BywmuND0.mjs → StreamingChunkSequence-DnudbJ1O.mjs} +2 -2
  23. package/.output/server/_ssr/{index-CStymIc0.mjs → index-Cza8zDrW.mjs} +2 -2
  24. package/.output/server/_ssr/index.mjs +2 -2
  25. package/.output/server/_ssr/{json-viewer-DlQu0N1x.mjs → json-viewer-C2lIVEX3.mjs} +3 -3
  26. package/.output/server/_ssr/{router-CQ4Zxhmr.mjs → router-bF9uzd1k.mjs} +939 -113
  27. package/.output/server/{_tanstack-start-manifest_v-BHeJBGfo.mjs → _tanstack-start-manifest_v-ErvW-mtr.mjs} +1 -1
  28. package/.output/server/index.mjs +74 -74
  29. package/README.md +57 -2
  30. package/package.json +1 -1
  31. package/src/cli/startupOutput.ts +16 -0
  32. package/src/cli.ts +61 -15
  33. package/src/components/ProxyViewer.tsx +395 -64
  34. package/src/components/providers/ProviderCard.tsx +132 -31
  35. package/src/components/providers/ProviderForm.tsx +43 -11
  36. package/src/components/providers/ProvidersPanel.tsx +1 -1
  37. package/src/components/proxy-viewer/ConversationHeader.tsx +133 -112
  38. package/src/components/proxy-viewer/LogEntry.tsx +109 -26
  39. package/src/components/proxy-viewer/LogEntryHeader.tsx +339 -329
  40. package/src/components/proxy-viewer/ThreadConnector.tsx +49 -46
  41. package/src/components/proxy-viewer/TurnGroup.tsx +22 -62
  42. package/src/components/proxy-viewer/bodyHydration.ts +56 -0
  43. package/src/lib/providerTestContract.ts +56 -10
  44. package/src/lib/providerTestPrompt.ts +23 -1
  45. package/src/lib/upstreamUrl.ts +105 -1
  46. package/src/mcp/server.ts +275 -0
  47. package/src/mcp/toolHandlers.ts +381 -4
  48. package/src/proxy/logSearch.ts +3 -0
  49. package/src/proxy/store.ts +40 -15
  50. package/src/routes/api/logs.ts +8 -2
  51. package/src/routes/api/providers.$providerId.test.log.ts +85 -10
  52. package/.output/public/assets/ProxyViewerContainer-DLqClc9A.js +0 -106
  53. package/.output/public/assets/_sessionId-DUSalzKH.js +0 -1
  54. package/.output/public/assets/index-BPpA21dY.css +0 -1
  55. package/.output/public/assets/index-Bt0Az2I2.js +0 -1
@@ -65,7 +65,7 @@ import "../_libs/immediate.mjs";
65
65
  import "../_libs/setimmediate.mjs";
66
66
  import "../_libs/pako.mjs";
67
67
  const faviconSvg = "data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20role='img'%20aria-label='Agent%20Inspector'%3e%3cg%20fill='none'%20stroke='%23f59e0b'%20stroke-width='1.5'%20stroke-linecap='round'%20stroke-linejoin='round'%20%3e%3cpath%20d='M5%2013%20C5%209%208%207%2012%207%20C16%207%2019%209%2019%2013%20C19%2016%2016%2018%2012%2018%20C8%2018%205%2016%205%2013%20Z'%20/%3e%3cpath%20d='M5%2011%20C3.5%209.5%201.5%2010%202%2012.5%20C2.5%2014%204%2013.5%205%2012.5'%20/%3e%3cpath%20d='M19%2011%20C20.5%209.5%2022.5%2010%2022%2012.5%20C21.5%2014%2020%2013.5%2019%2012.5'%20/%3e%3cline%20x1='10'%20y1='7'%20x2='9.5'%20y2='5'%20/%3e%3cline%20x1='14'%20y1='7'%20x2='14.5'%20y2='5'%20/%3e%3cline%20x1='6.5'%20y1='16'%20x2='4.5'%20y2='19.5'%20/%3e%3cline%20x1='9'%20y1='17.5'%20x2='8'%20y2='20.5'%20/%3e%3cline%20x1='15'%20y1='17.5'%20x2='16'%20y2='20.5'%20/%3e%3cline%20x1='17.5'%20y1='16'%20x2='19.5'%20y2='19.5'%20/%3e%3c/g%3e%3ccircle%20cx='9.5'%20cy='4.5'%20r='0.9'%20fill='%23f59e0b'%20/%3e%3ccircle%20cx='14.5'%20cy='4.5'%20r='0.9'%20fill='%23f59e0b'%20/%3e%3c/svg%3e";
68
- const appCss = "/assets/index-BPpA21dY.css";
68
+ const appCss = "/assets/index-gvYkgMPF.css";
69
69
  const Route$D = createRootRoute({
70
70
  head: () => ({
71
71
  meta: [
@@ -108,7 +108,7 @@ function RootDocument({ children }) {
108
108
  ] })
109
109
  ] });
110
110
  }
111
- const $$splitComponentImporter$1 = () => import("./index-CStymIc0.mjs");
111
+ const $$splitComponentImporter$1 = () => import("./index-Cza8zDrW.mjs");
112
112
  const Route$C = createFileRoute("/")({
113
113
  component: lazyRouteComponent($$splitComponentImporter$1, "component")
114
114
  });
@@ -151,7 +151,7 @@ function decodeSessionIdFromPath(encoded) {
151
151
  function getSessionPath(sessionId) {
152
152
  return `/session/${encodeSessionIdForPath(sessionId)}`;
153
153
  }
154
- const $$splitComponentImporter = () => import("../_sessionId-C0fhvQnn.mjs");
154
+ const $$splitComponentImporter = () => import("../_sessionId-DjSHDNh8.mjs");
155
155
  const Route$B = createFileRoute("/session/$sessionId")({
156
156
  component: lazyRouteComponent($$splitComponentImporter, "component"),
157
157
  parseParams: (params) => ({
@@ -1061,7 +1061,7 @@ function objectFromUnknown$1(value) {
1061
1061
  if (typeof value === "object" || typeof value === "function") return value;
1062
1062
  return null;
1063
1063
  }
1064
- function readProperty$3(value, name) {
1064
+ function readProperty$4(value, name) {
1065
1065
  let current = objectFromUnknown$1(value);
1066
1066
  while (current !== null) {
1067
1067
  const desc = Object.getOwnPropertyDescriptor(current, name);
@@ -1075,7 +1075,7 @@ function readProperty$3(value, name) {
1075
1075
  return void 0;
1076
1076
  }
1077
1077
  function readFunction$1(value, name) {
1078
- const property = readProperty$3(value, name);
1078
+ const property = readProperty$4(value, name);
1079
1079
  return typeof property === "function" ? property : null;
1080
1080
  }
1081
1081
  function callMethod$1(target, methodName, args) {
@@ -1117,7 +1117,7 @@ function execSql$1(db, sql) {
1117
1117
  return result !== void 0;
1118
1118
  }
1119
1119
  function sqliteConstructorFromModule$1(moduleValue, exportName) {
1120
- const exportedValue = readProperty$3(moduleValue, exportName);
1120
+ const exportedValue = readProperty$4(moduleValue, exportName);
1121
1121
  if (typeof exportedValue === "function") {
1122
1122
  return (path2) => Reflect.construct(exportedValue, [path2]);
1123
1123
  }
@@ -1260,11 +1260,11 @@ function entryParams(entry) {
1260
1260
  ];
1261
1261
  }
1262
1262
  function readNumber$1(row, name) {
1263
- const value = readProperty$3(row, name);
1263
+ const value = readProperty$4(row, name);
1264
1264
  return typeof value === "number" && Number.isFinite(value) ? value : null;
1265
1265
  }
1266
1266
  function readString$2(row, name) {
1267
- const value = readProperty$3(row, name);
1267
+ const value = readProperty$4(row, name);
1268
1268
  return typeof value === "string" ? value : null;
1269
1269
  }
1270
1270
  function readBoolean(row, name) {
@@ -2019,9 +2019,9 @@ const DEFAULT_OPENAI_UPSTREAM$1 = "https://api.openai.com/v1";
2019
2019
  const PROXY_IDENTITY = process.env["PROXY_IDENTITY"] ?? "inspector9527@Tony";
2020
2020
  const PATH_V1_CHAT_COMPLETIONS$1 = "/v1/chat/completions";
2021
2021
  const PATH_CHAT_COMPLETIONS = "/chat/completions";
2022
- const PATH_V1_RESPONSES = "/v1/responses";
2022
+ const PATH_V1_RESPONSES$1 = "/v1/responses";
2023
2023
  const PATH_RESPONSES = "/responses";
2024
- const PATH_V1_MESSAGES = "/v1/messages";
2024
+ const PATH_V1_MESSAGES$1 = "/v1/messages";
2025
2025
  const HEADER_CONTENT_TYPE = "content-type";
2026
2026
  const HEADER_USER_AGENT = "user-agent";
2027
2027
  const HEADER_X_PROXY_IDENTITY = "x-proxy-identity";
@@ -2075,10 +2075,10 @@ function formatForPath(path2) {
2075
2075
  function apiFormatForPath(path2) {
2076
2076
  return formatRegistry.getApiFormatByPath(path2) ?? "unknown";
2077
2077
  }
2078
- formatRegistry.registerPath(PATH_V1_MESSAGES, "anthropic");
2078
+ formatRegistry.registerPath(PATH_V1_MESSAGES$1, "anthropic");
2079
2079
  formatRegistry.registerPath(PATH_V1_CHAT_COMPLETIONS$1, "openai");
2080
2080
  formatRegistry.registerPath(PATH_CHAT_COMPLETIONS, "openai");
2081
- formatRegistry.registerPath(PATH_V1_RESPONSES, "openai");
2081
+ formatRegistry.registerPath(PATH_V1_RESPONSES$1, "openai");
2082
2082
  formatRegistry.registerPath(PATH_RESPONSES, "openai");
2083
2083
  const SESSION_ARCHIVE_DIR = "sessions";
2084
2084
  const SESSION_ARCHIVE_FILE = "session.sqlite";
@@ -2130,7 +2130,7 @@ function objectFromUnknown(value) {
2130
2130
  if (typeof value === "object" || typeof value === "function") return value;
2131
2131
  return null;
2132
2132
  }
2133
- function readProperty$2(value, name) {
2133
+ function readProperty$3(value, name) {
2134
2134
  let current = objectFromUnknown(value);
2135
2135
  while (current !== null) {
2136
2136
  const desc = Object.getOwnPropertyDescriptor(current, name);
@@ -2144,7 +2144,7 @@ function readProperty$2(value, name) {
2144
2144
  return void 0;
2145
2145
  }
2146
2146
  function readFunction(value, name) {
2147
- const property = readProperty$2(value, name);
2147
+ const property = readProperty$3(value, name);
2148
2148
  return typeof property === "function" ? property : null;
2149
2149
  }
2150
2150
  function callMethod(target, methodName, args) {
@@ -2182,7 +2182,7 @@ function closeDatabase(db) {
2182
2182
  callMethod(db, "close", []);
2183
2183
  }
2184
2184
  function sqliteConstructorFromModule(moduleValue, exportName) {
2185
- const exportedValue = readProperty$2(moduleValue, exportName);
2185
+ const exportedValue = readProperty$3(moduleValue, exportName);
2186
2186
  if (typeof exportedValue === "function") {
2187
2187
  return (path2) => Reflect.construct(exportedValue, [path2]);
2188
2188
  }
@@ -2273,11 +2273,11 @@ async function archiveSessionLog(log) {
2273
2273
  }
2274
2274
  }
2275
2275
  function readString$1(row, name) {
2276
- const value = readProperty$2(row, name);
2276
+ const value = readProperty$3(row, name);
2277
2277
  return typeof value === "string" ? value : null;
2278
2278
  }
2279
2279
  function readNumber(row, name) {
2280
- const value = readProperty$2(row, name);
2280
+ const value = readProperty$3(row, name);
2281
2281
  return typeof value === "number" && Number.isFinite(value) ? value : null;
2282
2282
  }
2283
2283
  function logFromJson(value) {
@@ -2734,12 +2734,14 @@ let sessionArchiveQueue = Promise.resolve();
2734
2734
  function cursorPageIndexKey(options) {
2735
2735
  return JSON.stringify({
2736
2736
  sessionId: options.sessionId ?? null,
2737
- model: options.model ?? null
2737
+ model: options.model ?? null,
2738
+ clientPid: options.clientPid ?? null
2738
2739
  });
2739
2740
  }
2740
2741
  function matchesCursorIndexFilters(log, index) {
2741
2742
  if (index.sessionId !== void 0 && getLogSessionId(log) !== index.sessionId) return false;
2742
2743
  if (index.model !== void 0 && log.model !== index.model) return false;
2744
+ if (index.clientPid !== void 0 && log.clientPid !== index.clientPid) return false;
2743
2745
  return true;
2744
2746
  }
2745
2747
  function insertSortedLogId(ids, id) {
@@ -3056,14 +3058,15 @@ async function scanLogFileForId(filePath, id) {
3056
3058
  }
3057
3059
  return lastMatch;
3058
3060
  }
3059
- function getFilteredLogs(sessionId, model) {
3061
+ function getFilteredLogs(sessionId, model, clientPid) {
3060
3062
  return [...memoryCache.values()].filter((l) => {
3061
- return matchesLogFilters(l, sessionId, model);
3063
+ return matchesLogFilters(l, sessionId, model, clientPid);
3062
3064
  });
3063
3065
  }
3064
- function matchesLogFilters(log, sessionId, model) {
3066
+ function matchesLogFilters(log, sessionId, model, clientPid) {
3065
3067
  if (sessionId !== void 0 && getLogSessionId(log) !== sessionId) return false;
3066
3068
  if (model !== void 0 && log.model !== model) return false;
3069
+ if (clientPid !== void 0 && log.clientPid !== clientPid) return false;
3067
3070
  return true;
3068
3071
  }
3069
3072
  async function visitPersistedLogs(visitor) {
@@ -3113,7 +3116,7 @@ async function visitArchivedSessionLogs(sessionId, visitor) {
3113
3116
  }
3114
3117
  }
3115
3118
  function canUseIndexedListPage(options) {
3116
- return options.sessionId === void 0 && options.model === void 0;
3119
+ return options.sessionId === void 0 && options.model === void 0 && options.clientPid === void 0;
3117
3120
  }
3118
3121
  function hasUsableIndexOffset(entry) {
3119
3122
  return entry.byteOffset >= 0 && entry.byteLength > 0;
@@ -3158,7 +3161,7 @@ async function listLogsPage(options) {
3158
3161
  const includeBodies = options.includeBodies !== false;
3159
3162
  let total = 0;
3160
3163
  const visitLog = (log) => {
3161
- if (!matchesLogFilters(log, options.sessionId, options.model)) return;
3164
+ if (!matchesLogFilters(log, options.sessionId, options.model, options.clientPid)) return;
3162
3165
  if (!seenIds.has(log.id)) {
3163
3166
  seenIds.add(log.id);
3164
3167
  const position = total;
@@ -3223,12 +3226,14 @@ function hasLogIndexFilterMetadata(entry) {
3223
3226
  function hasLogIndexSummary(entry) {
3224
3227
  return entry.summary !== void 0;
3225
3228
  }
3226
- function matchesLogIndexEntryFilters(entry, sessionId, model) {
3229
+ function matchesLogIndexEntryFilters(entry, sessionId, model, clientPid) {
3227
3230
  if (sessionId !== void 0 && entry.sessionId !== sessionId) return false;
3228
3231
  if (model !== void 0 && entry.model !== model) return false;
3232
+ if (clientPid !== void 0 && entry.summary?.clientPid !== clientPid) return false;
3229
3233
  return true;
3230
3234
  }
3231
3235
  async function buildLogCursorPageIndexFromLogIndex(options, allowRebuild) {
3236
+ if (options.clientPid !== void 0) return null;
3232
3237
  let entries = await listFilteredIndexEntries(options);
3233
3238
  if (entries.length === 0 && allowRebuild) {
3234
3239
  await rebuildIndex();
@@ -3240,7 +3245,7 @@ async function buildLogCursorPageIndexFromLogIndex(options, allowRebuild) {
3240
3245
  return await buildLogCursorPageIndexFromLogIndex(options, false);
3241
3246
  }
3242
3247
  const matchingEntries = entries.filter(
3243
- (entry) => matchesLogIndexEntryFilters(entry, options.sessionId, options.model)
3248
+ (entry) => matchesLogIndexEntryFilters(entry, options.sessionId, options.model, options.clientPid)
3244
3249
  );
3245
3250
  if (matchingEntries.some((entry) => !hasLogIndexSummary(entry))) {
3246
3251
  if (!allowRebuild) return null;
@@ -3260,7 +3265,7 @@ async function buildLogCursorPageIndexFromLogIndex(options, allowRebuild) {
3260
3265
  }
3261
3266
  const logsById = /* @__PURE__ */ new Map();
3262
3267
  for (const log of memoryCache.values()) {
3263
- if (!matchesLogFilters(log, options.sessionId, options.model)) continue;
3268
+ if (!matchesLogFilters(log, options.sessionId, options.model, options.clientPid)) continue;
3264
3269
  idsById.add(log.id);
3265
3270
  logsById.set(log.id, log);
3266
3271
  }
@@ -3269,7 +3274,7 @@ async function buildLogCursorPageIndexFromLogIndex(options, allowRebuild) {
3269
3274
  const archivedLogs = await listArchivedSessionLogs(options.sessionId);
3270
3275
  for (const archivedLog of archivedLogs) {
3271
3276
  const log = normalizeLog(archivedLog);
3272
- if (!matchesLogFilters(log, options.sessionId, options.model)) continue;
3277
+ if (!matchesLogFilters(log, options.sessionId, options.model, options.clientPid)) continue;
3273
3278
  observeSessionLog(log);
3274
3279
  idsById.add(log.id);
3275
3280
  logsById.set(log.id, log);
@@ -3279,6 +3284,7 @@ async function buildLogCursorPageIndexFromLogIndex(options, allowRebuild) {
3279
3284
  key: cursorPageIndexKey(options),
3280
3285
  sessionId: options.sessionId,
3281
3286
  model: options.model,
3287
+ clientPid: options.clientPid,
3282
3288
  ids: [...idsById].sort((left, right) => left - right),
3283
3289
  logsById,
3284
3290
  entriesById
@@ -3290,7 +3296,7 @@ async function buildLogCursorPageIndex(options) {
3290
3296
  const key = cursorPageIndexKey(options);
3291
3297
  const logsById = /* @__PURE__ */ new Map();
3292
3298
  const visitLog = (log) => {
3293
- if (!matchesLogFilters(log, options.sessionId, options.model)) return;
3299
+ if (!matchesLogFilters(log, options.sessionId, options.model, options.clientPid)) return;
3294
3300
  logsById.set(log.id, log);
3295
3301
  };
3296
3302
  await visitPersistedLogs((log) => {
@@ -3305,6 +3311,7 @@ async function buildLogCursorPageIndex(options) {
3305
3311
  key,
3306
3312
  sessionId: options.sessionId,
3307
3313
  model: options.model,
3314
+ clientPid: options.clientPid,
3308
3315
  ids: [...logsById.keys()].sort((left, right) => left - right),
3309
3316
  logsById,
3310
3317
  entriesById: /* @__PURE__ */ new Map()
@@ -3415,7 +3422,7 @@ async function collectIndexedSessionLogSummaries(sessionId) {
3415
3422
  if (entries.length === 0) return [];
3416
3423
  const needsMetadataRebuild = entries.some((entry) => !hasLogIndexFilterMetadata(entry));
3417
3424
  const needsSummaryRebuild = entries.some((entry) => {
3418
- if (!matchesLogIndexEntryFilters(entry, sessionId, void 0)) return false;
3425
+ if (!matchesLogIndexEntryFilters(entry, sessionId, void 0, void 0)) return false;
3419
3426
  return !hasLogIndexSummary(entry);
3420
3427
  });
3421
3428
  if (needsMetadataRebuild || needsSummaryRebuild) {
@@ -3424,7 +3431,7 @@ async function collectIndexedSessionLogSummaries(sessionId) {
3424
3431
  }
3425
3432
  const summaries = [];
3426
3433
  for (const entry of entries) {
3427
- if (!matchesLogIndexEntryFilters(entry, sessionId, void 0)) continue;
3434
+ if (!matchesLogIndexEntryFilters(entry, sessionId, void 0, void 0)) continue;
3428
3435
  if (entry.summary === void 0) continue;
3429
3436
  summaries.push(buildSessionLogSummary(compactLogFromIndexSummary(entry.summary)));
3430
3437
  }
@@ -4090,24 +4097,24 @@ const anthropicProvider = {
4090
4097
  };
4091
4098
  registry.register(anthropicProvider);
4092
4099
  const MAX_CHUNKS = 1e3;
4093
- function readProperty$1(value, key) {
4100
+ function readProperty$2(value, key) {
4094
4101
  if (value === null || typeof value !== "object" || Array.isArray(value)) return void 0;
4095
4102
  return Object.getOwnPropertyDescriptor(value, key)?.value;
4096
4103
  }
4097
- function readStringProperty$1(value, key) {
4098
- const property = readProperty$1(value, key);
4104
+ function readStringProperty$2(value, key) {
4105
+ const property = readProperty$2(value, key);
4099
4106
  return typeof property === "string" ? property : null;
4100
4107
  }
4101
4108
  function readNumberProperty(value, key) {
4102
- const property = readProperty$1(value, key);
4109
+ const property = readProperty$2(value, key);
4103
4110
  return typeof property === "number" && Number.isFinite(property) ? property : null;
4104
4111
  }
4105
4112
  function readObjectProperty(value, key) {
4106
- const property = readProperty$1(value, key);
4113
+ const property = readProperty$2(value, key);
4107
4114
  return property !== null && typeof property === "object" && !Array.isArray(property) ? property : null;
4108
4115
  }
4109
- function readArrayProperty(value, key) {
4110
- const property = readProperty$1(value, key);
4116
+ function readArrayProperty$1(value, key) {
4117
+ const property = readProperty$2(value, key);
4111
4118
  return Array.isArray(property) ? property : [];
4112
4119
  }
4113
4120
  function parseSseEvents(raw) {
@@ -4175,7 +4182,7 @@ function collectChunk(chunks, chunkIndex, streamStartMs, type, parsed) {
4175
4182
  }
4176
4183
  function setErrorFromPayload(log, payload) {
4177
4184
  const errorObject = readObjectProperty(payload, "error");
4178
- const message = readStringProperty$1(errorObject, "message") ?? readStringProperty$1(payload, "message") ?? readStringProperty$1(payload, "error");
4185
+ const message = readStringProperty$2(errorObject, "message") ?? readStringProperty$2(payload, "message") ?? readStringProperty$2(payload, "error");
4179
4186
  if (message !== null && message.length > 0) {
4180
4187
  log.error = message;
4181
4188
  }
@@ -4299,7 +4306,7 @@ function extractChatCompletionsStream(events, log, fallbackModel, collectChunks)
4299
4306
  }
4300
4307
  function parseResponsesResponse(value) {
4301
4308
  const fromResponseProperty = OpenAIResponsesResponseSchema.safeParse(
4302
- readProperty$1(value, "response")
4309
+ readProperty$2(value, "response")
4303
4310
  );
4304
4311
  if (fromResponseProperty.success) return fromResponseProperty.data;
4305
4312
  const direct = OpenAIResponsesResponseSchema.safeParse(value);
@@ -4311,10 +4318,10 @@ function responseTextFromOutput(response) {
4311
4318
  }
4312
4319
  const parts = [];
4313
4320
  for (const outputItem of response.output ?? []) {
4314
- const content = readArrayProperty(outputItem, "content");
4321
+ const content = readArrayProperty$1(outputItem, "content");
4315
4322
  for (const contentPart of content) {
4316
- const type = readStringProperty$1(contentPart, "type");
4317
- const text = readStringProperty$1(contentPart, "text");
4323
+ const type = readStringProperty$2(contentPart, "type");
4324
+ const text = readStringProperty$2(contentPart, "text");
4318
4325
  if ((type === "output_text" || type === "text") && text !== null && text.length > 0) {
4319
4326
  parts.push(text);
4320
4327
  }
@@ -4333,7 +4340,7 @@ function updateUsageFromResponse(response, log) {
4333
4340
  return { inputTokens, outputTokens };
4334
4341
  }
4335
4342
  function functionCallKey(payload, fallbackIndex) {
4336
- const itemId = readStringProperty$1(payload, "item_id");
4343
+ const itemId = readStringProperty$2(payload, "item_id");
4337
4344
  if (itemId !== null && itemId.length > 0) return itemId;
4338
4345
  const outputIndex = readNumberProperty(payload, "output_index");
4339
4346
  if (outputIndex !== null) return String(outputIndex);
@@ -4350,13 +4357,13 @@ function ensureFunctionCall(calls, key) {
4350
4357
  return created;
4351
4358
  }
4352
4359
  function updateFunctionCallFromItem(calls, key, item) {
4353
- if (readStringProperty$1(item, "type") !== "function_call") return;
4360
+ if (readStringProperty$2(item, "type") !== "function_call") return;
4354
4361
  const call = ensureFunctionCall(calls, key);
4355
- const id = readStringProperty$1(item, "id");
4356
- const callId = readStringProperty$1(item, "call_id");
4357
- const name = readStringProperty$1(item, "name");
4358
- const args = readStringProperty$1(item, "arguments");
4359
- const status = readStringProperty$1(item, "status");
4362
+ const id = readStringProperty$2(item, "id");
4363
+ const callId = readStringProperty$2(item, "call_id");
4364
+ const name = readStringProperty$2(item, "name");
4365
+ const args = readStringProperty$2(item, "arguments");
4366
+ const status = readStringProperty$2(item, "status");
4360
4367
  if (id !== null) call.id = id;
4361
4368
  if (callId !== null) call.call_id = callId;
4362
4369
  if (name !== null) call.name = name;
@@ -4444,13 +4451,13 @@ function extractResponsesStream(events, log, fallbackModel, collectChunks) {
4444
4451
  outputTokens = usage.outputTokens ?? outputTokens;
4445
4452
  setErrorFromPayload(log, response);
4446
4453
  }
4447
- const delta = readStringProperty$1(parsed, "delta");
4454
+ const delta = readStringProperty$2(parsed, "delta");
4448
4455
  switch (type) {
4449
4456
  case "response.output_text.delta":
4450
4457
  if (delta !== null) outputText += delta;
4451
4458
  break;
4452
4459
  case "response.output_text.done": {
4453
- const text = readStringProperty$1(parsed, "text");
4460
+ const text = readStringProperty$2(parsed, "text");
4454
4461
  if (outputText.length === 0 && text !== null) outputText = text;
4455
4462
  break;
4456
4463
  }
@@ -4462,7 +4469,7 @@ function extractResponsesStream(events, log, fallbackModel, collectChunks) {
4462
4469
  break;
4463
4470
  }
4464
4471
  case "response.function_call_arguments.done": {
4465
- const args = readStringProperty$1(parsed, "arguments");
4472
+ const args = readStringProperty$2(parsed, "arguments");
4466
4473
  if (args !== null) {
4467
4474
  const call = ensureFunctionCall(calls, functionCallKey(parsed, calls.size));
4468
4475
  call.arguments = args;
@@ -4511,7 +4518,7 @@ function extractResponsesStream(events, log, fallbackModel, collectChunks) {
4511
4518
  return JSON.stringify(normalizedResponse.data);
4512
4519
  }
4513
4520
  if (log.outputTokens === null) {
4514
- const finalText = readStringProperty$1(normalized, "output_text") ?? outputText;
4521
+ const finalText = readStringProperty$2(normalized, "output_text") ?? outputText;
4515
4522
  const estimatedOutputTokens = Math.ceil(finalText.length / 4);
4516
4523
  log.outputTokens = estimatedOutputTokens;
4517
4524
  }
@@ -6251,7 +6258,7 @@ function parseJson$1(raw) {
6251
6258
  function isRecord$1(value) {
6252
6259
  return typeof value === "object" && value !== null && !Array.isArray(value);
6253
6260
  }
6254
- function readProperty(value, key) {
6261
+ function readProperty$1(value, key) {
6255
6262
  if (!isRecord$1(value)) return void 0;
6256
6263
  return Object.getOwnPropertyDescriptor(value, key)?.value;
6257
6264
  }
@@ -6259,18 +6266,18 @@ function hasOwnProperty(value, key) {
6259
6266
  return Object.getOwnPropertyDescriptor(value, key) !== void 0;
6260
6267
  }
6261
6268
  function readString(value, key) {
6262
- const property = readProperty(value, key);
6269
+ const property = readProperty$1(value, key);
6263
6270
  return typeof property === "string" ? property : null;
6264
6271
  }
6265
6272
  function readArray(value, key) {
6266
- const property = readProperty(value, key);
6273
+ const property = readProperty$1(value, key);
6267
6274
  return Array.isArray(property) ? property : [];
6268
6275
  }
6269
6276
  function readStringArray(value, key) {
6270
6277
  return readArray(value, key).filter((item) => typeof item === "string");
6271
6278
  }
6272
6279
  function readObject(value, key) {
6273
- const property = readProperty(value, key);
6280
+ const property = readProperty$1(value, key);
6274
6281
  return isRecord$1(property) ? property : null;
6275
6282
  }
6276
6283
  function normalizeExpectedType(typeName) {
@@ -6288,7 +6295,7 @@ function normalizeExpectedType(typeName) {
6288
6295
  }
6289
6296
  }
6290
6297
  function schemaTypes(schema) {
6291
- const typeValue = readProperty(schema, "type");
6298
+ const typeValue = readProperty$1(schema, "type");
6292
6299
  const rawTypes = Array.isArray(typeValue) ? typeValue : [typeValue];
6293
6300
  const types = [];
6294
6301
  for (const rawType of rawTypes) {
@@ -6378,7 +6385,7 @@ function schemaAllowsObjectValidation(schema, expectedTypes) {
6378
6385
  return expectedTypes.includes("object");
6379
6386
  }
6380
6387
  function schemaAllowsArrayValidation(schema, expectedTypes) {
6381
- if (expectedTypes.length === 0) return readProperty(schema, "items") !== void 0;
6388
+ if (expectedTypes.length === 0) return readProperty$1(schema, "items") !== void 0;
6382
6389
  return expectedTypes.includes("array");
6383
6390
  }
6384
6391
  function addTypeWarning(warnings, toolName, path2, expectedTypes, value) {
@@ -6411,7 +6418,7 @@ function validateObjectSchema(schema, value, toolName, path2, warnings) {
6411
6418
  }
6412
6419
  }
6413
6420
  function validateArraySchema(schema, value, toolName, path2, warnings) {
6414
- const itemsSchema = readProperty(schema, "items");
6421
+ const itemsSchema = readProperty$1(schema, "items");
6415
6422
  if (itemsSchema === void 0) return;
6416
6423
  let index = 0;
6417
6424
  for (const item of value) {
@@ -6420,7 +6427,7 @@ function validateArraySchema(schema, value, toolName, path2, warnings) {
6420
6427
  }
6421
6428
  }
6422
6429
  function validateEnum(schema, value, toolName, path2, warnings) {
6423
- const enumValue = readProperty(schema, "enum");
6430
+ const enumValue = readProperty$1(schema, "enum");
6424
6431
  if (Array.isArray(enumValue) && enumValue.length > 0 && !enumMatches(value, enumValue)) {
6425
6432
  warnings.push(
6426
6433
  `Tool call "${toolName}" ${pathLabel(path2)} expected one of ${formatJsonValue(
@@ -6537,7 +6544,7 @@ function extractOpenAIToolCalls(response) {
6537
6544
  for (const call of readArray(message, "tool_calls")) {
6538
6545
  const functionCall = readObject(call, "function");
6539
6546
  const name = functionCall === null ? null : readString(functionCall, "name");
6540
- const parsedArguments = functionCall === null ? { value: {}, issue: "function block is missing" } : parseOpenAIArguments(readProperty(functionCall, "arguments"));
6547
+ const parsedArguments = functionCall === null ? { value: {}, issue: "function block is missing" } : parseOpenAIArguments(readProperty$1(functionCall, "arguments"));
6541
6548
  calls.push({
6542
6549
  name,
6543
6550
  arguments: parsedArguments.value,
@@ -6548,7 +6555,7 @@ function extractOpenAIToolCalls(response) {
6548
6555
  }
6549
6556
  const legacyFunctionCall = readObject(message, "function_call");
6550
6557
  if (legacyFunctionCall !== null) {
6551
- const parsedArguments = parseOpenAIArguments(readProperty(legacyFunctionCall, "arguments"));
6558
+ const parsedArguments = parseOpenAIArguments(readProperty$1(legacyFunctionCall, "arguments"));
6552
6559
  calls.push({
6553
6560
  name: readString(legacyFunctionCall, "name"),
6554
6561
  arguments: parsedArguments.value,
@@ -6564,7 +6571,7 @@ function extractOpenAIToolCalls(response) {
6564
6571
  outputIndex++;
6565
6572
  continue;
6566
6573
  }
6567
- const parsedArguments = parseOpenAIArguments(readProperty(item, "arguments"));
6574
+ const parsedArguments = parseOpenAIArguments(readProperty$1(item, "arguments"));
6568
6575
  calls.push({
6569
6576
  name: readString(item, "name"),
6570
6577
  arguments: parsedArguments.value,
@@ -6585,7 +6592,7 @@ function extractAnthropicToolCalls(response) {
6585
6592
  }
6586
6593
  calls.push({
6587
6594
  name: readString(block, "name"),
6588
- arguments: readProperty(block, "input") ?? {},
6595
+ arguments: readProperty$1(block, "input") ?? {},
6589
6596
  argumentIssue: null,
6590
6597
  location: `content[${contentIndex}]`
6591
6598
  });
@@ -7154,9 +7161,11 @@ class RawStreamCapture {
7154
7161
  }
7155
7162
  }
7156
7163
  const PATH_V1_CHAT_COMPLETIONS = "/v1/chat/completions";
7164
+ const PATH_V1_RESPONSES = "/v1/responses";
7165
+ const PATH_V1_MESSAGES = "/v1/messages";
7157
7166
  function buildUpstreamUrl(upstreamBase, normalizedPath) {
7158
7167
  const base = upstreamBase.endsWith("/") ? upstreamBase.slice(0, -1) : upstreamBase;
7159
- const endpointPath = normalizedPath.split("?")[0] ?? normalizedPath;
7168
+ const endpointPath = endpointPathFor(normalizedPath);
7160
7169
  const queryIndex = normalizedPath.indexOf("?");
7161
7170
  const search = queryIndex >= 0 ? normalizedPath.slice(queryIndex) : "";
7162
7171
  if (endpointPath !== "" && base.endsWith(endpointPath)) {
@@ -7170,9 +7179,78 @@ function buildUpstreamUrl(upstreamBase, normalizedPath) {
7170
7179
  }
7171
7180
  return base + normalizedPath;
7172
7181
  }
7182
+ function previewUpstreamUrl(upstreamBase, normalizedPath, options = {}) {
7183
+ const base = upstreamBase.trim().replace(/\/+$/, "");
7184
+ const endpointPath = endpointPathFor(normalizedPath);
7185
+ const finalUrl = buildUpstreamUrl(base, normalizedPath);
7186
+ const diagnostics = [];
7187
+ const exactEndpoint = endpointPath !== "" && base.endsWith(endpointPath);
7188
+ if (exactEndpoint) {
7189
+ diagnostics.push({
7190
+ severity: "info",
7191
+ message: "This already includes the exact endpoint; no duplicate suffix will be appended."
7192
+ });
7193
+ } else if (isZhipuVersionedOpenAIBase(base) && isVersionedChatCompletionsPath(normalizedPath)) {
7194
+ diagnostics.push({
7195
+ severity: "info",
7196
+ message: "Zhipu bases already include the API version; only /chat/completions is appended."
7197
+ });
7198
+ } else if (base.endsWith("/v1") && normalizedPath.startsWith("/v1/")) {
7199
+ diagnostics.push({
7200
+ severity: "info",
7201
+ message: "Base URL already ends with /v1; the suffix will not repeat /v1."
7202
+ });
7203
+ }
7204
+ if (isResponsesPath(endpointPath) && baseEndsWithChatEndpoint(base)) {
7205
+ diagnostics.push({
7206
+ severity: "warning",
7207
+ message: "This looks like a Chat Completions endpoint, so Responses would append after it."
7208
+ });
7209
+ }
7210
+ if (isChatCompletionsPath(endpointPath) && baseEndsWithResponsesEndpoint(base)) {
7211
+ diagnostics.push({
7212
+ severity: "warning",
7213
+ message: "This looks like a Responses endpoint, so Chat Completions would append after it."
7214
+ });
7215
+ }
7216
+ if (isResponsesPath(endpointPath) && isLikelyDeepSeekBase(base, options.providerName)) {
7217
+ diagnostics.push({
7218
+ severity: "warning",
7219
+ message: "DeepSeek's official API does not currently expose OpenAI Responses."
7220
+ });
7221
+ }
7222
+ return { finalUrl, diagnostics };
7223
+ }
7224
+ function endpointPathFor(normalizedPath) {
7225
+ return normalizedPath.split("?")[0] ?? normalizedPath;
7226
+ }
7173
7227
  function isVersionedChatCompletionsPath(normalizedPath) {
7174
7228
  return normalizedPath === PATH_V1_CHAT_COMPLETIONS || normalizedPath.startsWith(`${PATH_V1_CHAT_COMPLETIONS}?`) || normalizedPath.startsWith(`${PATH_V1_CHAT_COMPLETIONS}/`);
7175
7229
  }
7230
+ function isChatCompletionsPath(endpointPath) {
7231
+ return endpointPath === PATH_V1_CHAT_COMPLETIONS || endpointPath.startsWith(`${PATH_V1_CHAT_COMPLETIONS}/`);
7232
+ }
7233
+ function isResponsesPath(endpointPath) {
7234
+ return endpointPath === PATH_V1_RESPONSES || endpointPath.startsWith(`${PATH_V1_RESPONSES}/`);
7235
+ }
7236
+ function baseEndsWithChatEndpoint(base) {
7237
+ const normalized = base.toLowerCase();
7238
+ return normalized.endsWith("/chat/completions");
7239
+ }
7240
+ function baseEndsWithResponsesEndpoint(base) {
7241
+ const normalized = base.toLowerCase();
7242
+ return normalized.endsWith("/responses");
7243
+ }
7244
+ function isLikelyDeepSeekBase(base, providerName) {
7245
+ const provider = providerName?.toLowerCase();
7246
+ if (provider !== void 0 && provider.includes("deepseek")) return true;
7247
+ try {
7248
+ const parsed = new URL(base);
7249
+ return parsed.hostname.toLowerCase().includes("deepseek");
7250
+ } catch {
7251
+ return base.toLowerCase().includes("deepseek");
7252
+ }
7253
+ }
7176
7254
  function isZhipuVersionedOpenAIBase(base) {
7177
7255
  try {
7178
7256
  const parsed = new URL(base);
@@ -7185,7 +7263,7 @@ function isZhipuVersionedOpenAIBase(base) {
7185
7263
  function describeApiRoute(apiPath) {
7186
7264
  const endpointPath = apiPath.split("?")[0] ?? "";
7187
7265
  const isChatCompletions = endpointPath === PATH_CHAT_COMPLETIONS || endpointPath === PATH_V1_CHAT_COMPLETIONS$1;
7188
- const isResponses = endpointPath === PATH_RESPONSES || endpointPath === PATH_V1_RESPONSES;
7266
+ const isResponses = endpointPath === PATH_RESPONSES || endpointPath === PATH_V1_RESPONSES$1;
7189
7267
  const isOpenAI = isChatCompletions || isResponses;
7190
7268
  const normalizedPath = isOpenAI && !apiPath.startsWith("/v1/") ? `/v1${apiPath}` : apiPath;
7191
7269
  return { apiPath, endpointPath, isChatCompletions, isResponses, isOpenAI, normalizedPath };
@@ -7255,7 +7333,7 @@ function parseRequestPath(req, url) {
7255
7333
  const route = describeApiRoute(getProxyApiPath(url));
7256
7334
  const isPost = req.method === "POST";
7257
7335
  const isChatCompletions = isPost && route.isChatCompletions;
7258
- const isMessages = isPost && (route.endpointPath === PATH_V1_MESSAGES || route.isChatCompletions);
7336
+ const isMessages = isPost && (route.endpointPath === PATH_V1_MESSAGES$1 || route.isChatCompletions);
7259
7337
  return {
7260
7338
  apiPath: route.apiPath,
7261
7339
  isMessages,
@@ -9016,7 +9094,7 @@ const Route$w = createFileRoute("/api/models")({
9016
9094
  }
9017
9095
  }
9018
9096
  });
9019
- const version = "2.1.16";
9097
+ const version = "2.1.18";
9020
9098
  const packageJson = {
9021
9099
  version
9022
9100
  };
@@ -9650,11 +9728,18 @@ const SearchLogsResponseSchema = object({
9650
9728
  const PAGINATION_DEFAULTS = { offset: 0, limit: 3 };
9651
9729
  const LIMIT_HARD_CAP = 5;
9652
9730
  const LOG_DETAIL_TEXT_LIMIT = 2e5;
9731
+ const PROCESS_LOG_LIMIT_DEFAULT = 50;
9732
+ const PROCESS_LOG_LIMIT_MAX = 200;
9653
9733
  function clampLimit(input) {
9654
9734
  if (input === void 0) return PAGINATION_DEFAULTS.limit;
9655
9735
  if (!Number.isFinite(input) || input < 1) return 1;
9656
9736
  return Math.min(Math.floor(input), LIMIT_HARD_CAP);
9657
9737
  }
9738
+ function clampProcessLogLimit(input) {
9739
+ if (input === void 0) return PROCESS_LOG_LIMIT_DEFAULT;
9740
+ if (!Number.isFinite(input) || input < 1) return 1;
9741
+ return Math.min(Math.floor(input), PROCESS_LOG_LIMIT_MAX);
9742
+ }
9658
9743
  function textJson(data) {
9659
9744
  return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
9660
9745
  }
@@ -9700,8 +9785,11 @@ function buildBoundedLogDetail(log) {
9700
9785
  responseTextTruncated: boundedResponse.truncated
9701
9786
  };
9702
9787
  }
9788
+ function logHasError(log) {
9789
+ return log.error !== null && log.error !== void 0 && log.error.length > 0 || log.responseStatus !== null && log.responseStatus !== void 0 && log.responseStatus >= 400;
9790
+ }
9703
9791
  function buildLogSummary(log) {
9704
- const hasError = log.error !== null && log.error !== void 0 && log.error.length > 0 || log.responseStatus !== null && log.responseStatus !== void 0 && log.responseStatus >= 400;
9792
+ const hasError = logHasError(log);
9705
9793
  const rawRequestBodyBytes = log.rawRequestBodyBytes ?? textByteLength(log.rawRequestBody);
9706
9794
  const responseTextBytes = log.responseTextBytes ?? textByteLength(log.responseText);
9707
9795
  return {
@@ -9738,6 +9826,74 @@ function buildLogSummary(log) {
9738
9826
  responseTextBytes
9739
9827
  };
9740
9828
  }
9829
+ function sortedUniqueStrings(values) {
9830
+ return [
9831
+ ...new Set(
9832
+ values.filter(
9833
+ (value) => value !== null && value !== void 0 && value !== ""
9834
+ )
9835
+ )
9836
+ ].sort((left, right) => left.localeCompare(right));
9837
+ }
9838
+ function sortedUniqueNumbers(values) {
9839
+ return [
9840
+ ...new Set(
9841
+ values.filter(
9842
+ (value) => value !== null && value !== void 0 && Number.isFinite(value)
9843
+ )
9844
+ )
9845
+ ].sort((left, right) => left - right);
9846
+ }
9847
+ function inferAgentFromUserAgent(userAgent) {
9848
+ if (userAgent === null || userAgent === void 0) return null;
9849
+ const lower2 = userAgent.toLowerCase();
9850
+ if (lower2.includes("codex")) return "Codex";
9851
+ if (lower2.includes("opencode")) return "OpenCode";
9852
+ if (lower2.includes("claude")) return "Claude Code";
9853
+ if (lower2.includes("mimocode")) return "MiMoCode";
9854
+ if (lower2.includes("ai-sdk")) return "AI SDK";
9855
+ return null;
9856
+ }
9857
+ function processSummary(clientPid, logs, total, limit) {
9858
+ const sortedLogs = [...logs].sort((left, right) => left.id - right.id);
9859
+ const first = sortedLogs[0];
9860
+ const last = sortedLogs[sortedLogs.length - 1];
9861
+ const userAgents = sortedUniqueStrings(sortedLogs.map((log) => log.userAgent));
9862
+ const agents = sortedUniqueStrings(userAgents.map(inferAgentFromUserAgent));
9863
+ const sessions2 = sortedUniqueStrings(sortedLogs.map((log) => log.sessionId));
9864
+ return {
9865
+ clientPid,
9866
+ total,
9867
+ limit,
9868
+ logCount: sortedLogs.length,
9869
+ sessionCount: sessions2.length,
9870
+ sessions: sessions2,
9871
+ agents,
9872
+ userAgents,
9873
+ clientPorts: sortedUniqueNumbers(sortedLogs.map((log) => log.clientPort)),
9874
+ clientCwds: sortedUniqueStrings(sortedLogs.map((log) => log.clientCwd)),
9875
+ clientProjectFolders: sortedUniqueStrings(sortedLogs.map((log) => log.clientProjectFolder)),
9876
+ models: sortedUniqueStrings(sortedLogs.map((log) => log.model)),
9877
+ providers: sortedUniqueStrings(sortedLogs.map((log) => log.providerName)),
9878
+ errorCount: sortedLogs.filter(logHasError).length,
9879
+ startedAt: first?.timestamp ?? null,
9880
+ updatedAt: last?.timestamp ?? null,
9881
+ latestLogs: sortedLogs.slice(-Math.min(10, sortedLogs.length)).reverse().map(buildLogSummary)
9882
+ };
9883
+ }
9884
+ async function readCompactLogsPage(callApi2, params) {
9885
+ const path2 = `/api/logs?${params.toString()}`;
9886
+ const res = await callApi2(path2);
9887
+ if (!res.ok) return toolError(`GET ${path2} returned ${res.status}`);
9888
+ const rawBody = await res.json();
9889
+ const parsed = LogsListResponseSchema.safeParse(rawBody);
9890
+ if (!parsed.success) return toolError("GET /api/logs returned an unparseable logs shape");
9891
+ const logs = parsed.data.logs ?? [];
9892
+ return { logs, total: parsed.data.total ?? logs.length };
9893
+ }
9894
+ function isToolResult(value) {
9895
+ return typeof value === "object" && value !== null && Object.getOwnPropertyDescriptor(value, "content") !== void 0;
9896
+ }
9741
9897
  async function listLogsImpl(callApi2, args) {
9742
9898
  const offset = args.offset ?? PAGINATION_DEFAULTS.offset;
9743
9899
  const limit = clampLimit(args.limit);
@@ -9752,6 +9908,9 @@ async function listLogsImpl(callApi2, args) {
9752
9908
  if (args.model !== void 0 && args.model.length > 0) {
9753
9909
  params.set("model", args.model);
9754
9910
  }
9911
+ if (args.clientPid !== void 0) {
9912
+ params.set("clientPid", String(args.clientPid));
9913
+ }
9755
9914
  const res = await callApi2(`/api/logs?${params.toString()}`);
9756
9915
  if (!res.ok) return toolError(`GET /api/logs returned ${res.status}`);
9757
9916
  const rawBody = await res.json();
@@ -9777,6 +9936,9 @@ async function searchLogsImpl(callApi2, args) {
9777
9936
  if (args.model !== void 0 && args.model.length > 0) {
9778
9937
  params.set("model", args.model);
9779
9938
  }
9939
+ if (args.clientPid !== void 0) {
9940
+ params.set("clientPid", String(args.clientPid));
9941
+ }
9780
9942
  const res = await callApi2(`/api/logs?${params.toString()}`);
9781
9943
  if (!res.ok) return toolError(`GET /api/logs search returned ${res.status}`);
9782
9944
  const rawBody = await res.json();
@@ -9952,6 +10114,225 @@ async function getSessionTimelineImpl(callApi2, args) {
9952
10114
  buildSessionTimeline(args.sessionId, logs, parsed.data.total ?? logs.length, limit)
9953
10115
  );
9954
10116
  }
10117
+ async function listProcessesImpl(callApi2, args = {}) {
10118
+ const scanLimit = clampProcessLogLimit(args.scanLimit ?? args.limit);
10119
+ const params = new URLSearchParams({
10120
+ q: "",
10121
+ offset: "0",
10122
+ limit: String(Math.min(scanLimit, 50)),
10123
+ scanLimit: String(scanLimit)
10124
+ });
10125
+ const res = await callApi2(`/api/logs?${params.toString()}`);
10126
+ if (!res.ok) return toolError(`GET /api/logs process scan returned ${res.status}`);
10127
+ const rawBody = await res.json();
10128
+ const parsed = SearchLogsResponseSchema.safeParse(rawBody);
10129
+ if (!parsed.success) return toolError("GET /api/logs returned an unparseable process scan shape");
10130
+ const grouped = /* @__PURE__ */ new Map();
10131
+ for (const log of parsed.data.logs) {
10132
+ if (log.clientPid === null || log.clientPid === void 0) continue;
10133
+ const existing = grouped.get(log.clientPid) ?? [];
10134
+ existing.push(log);
10135
+ grouped.set(log.clientPid, existing);
10136
+ }
10137
+ const processes = [...grouped.entries()].map(([clientPid, logs]) => processSummary(clientPid, logs, logs.length, logs.length)).sort((left, right) => {
10138
+ const leftUpdated = typeof left["updatedAt"] === "string" ? left["updatedAt"] : "";
10139
+ const rightUpdated = typeof right["updatedAt"] === "string" ? right["updatedAt"] : "";
10140
+ return rightUpdated.localeCompare(leftUpdated);
10141
+ });
10142
+ return textJson({
10143
+ scanned: parsed.data.scanned ?? parsed.data.logs.length,
10144
+ processCount: processes.length,
10145
+ processes
10146
+ });
10147
+ }
10148
+ async function getProcessImpl(callApi2, args) {
10149
+ const limit = clampProcessLogLimit(args.limit);
10150
+ const offset = args.offset ?? 0;
10151
+ const params = new URLSearchParams({
10152
+ clientPid: String(args.clientPid),
10153
+ offset: String(offset),
10154
+ limit: String(limit),
10155
+ compact: "1"
10156
+ });
10157
+ const result = await readCompactLogsPage(callApi2, params);
10158
+ if (isToolResult(result)) return result;
10159
+ return textJson(processSummary(args.clientPid, result.logs, result.total, limit));
10160
+ }
10161
+ async function getProcessTimelineImpl(callApi2, args) {
10162
+ const limit = clampTimelineLimit(args.limit);
10163
+ const offset = args.offset ?? 0;
10164
+ const params = new URLSearchParams({
10165
+ clientPid: String(args.clientPid),
10166
+ offset: String(offset),
10167
+ limit: String(limit),
10168
+ compact: "1"
10169
+ });
10170
+ const result = await readCompactLogsPage(callApi2, params);
10171
+ if (isToolResult(result)) return result;
10172
+ const sortedLogs = [...result.logs].sort((left, right) => left.id - right.id);
10173
+ return textJson({
10174
+ clientPid: args.clientPid,
10175
+ logCoverage: "bounded",
10176
+ total: result.total,
10177
+ limit,
10178
+ eventCount: sortedLogs.length,
10179
+ requestCount: sortedLogs.length,
10180
+ errorCount: sortedLogs.filter(logHasError).length,
10181
+ startedAt: sortedLogs[0]?.timestamp ?? null,
10182
+ updatedAt: sortedLogs.at(-1)?.timestamp ?? null,
10183
+ sessions: sortedUniqueStrings(sortedLogs.map((log) => log.sessionId)),
10184
+ models: sortedUniqueStrings(sortedLogs.map((log) => log.model)),
10185
+ providers: sortedUniqueStrings(sortedLogs.map((log) => log.providerName)),
10186
+ events: sortedLogs.map((log, index) => ({
10187
+ sequence: index + 1,
10188
+ kind: "request",
10189
+ logId: log.id,
10190
+ ...buildLogSummary(log)
10191
+ }))
10192
+ });
10193
+ }
10194
+ async function getLogHeadersImpl(callApi2, id) {
10195
+ const res = await callApi2(`/api/logs/${id}`);
10196
+ if (!res.ok) return toolError(`GET /api/logs/${id} returned ${res.status}`);
10197
+ const rawBody = await res.json();
10198
+ const parsed = CapturedLogSchema.safeParse(rawBody);
10199
+ if (!parsed.success) {
10200
+ return toolError(`GET /api/logs/${id} returned an unparseable CapturedLog`);
10201
+ }
10202
+ const log = parsed.data;
10203
+ return textJson({
10204
+ id: log.id,
10205
+ sessionId: log.sessionId,
10206
+ userAgent: log.userAgent,
10207
+ origin: log.origin,
10208
+ clientPid: log.clientPid ?? null,
10209
+ clientPort: log.clientPort ?? null,
10210
+ clientCwd: log.clientCwd ?? null,
10211
+ clientProjectFolder: log.clientProjectFolder ?? null,
10212
+ apiFormat: log.apiFormat,
10213
+ method: log.method,
10214
+ path: log.path,
10215
+ model: log.model,
10216
+ rawHeaders: log.rawHeaders ?? null,
10217
+ headers: log.headers ?? null,
10218
+ hasRawHeaders: log.rawHeaders !== void 0 && Object.keys(log.rawHeaders).length > 0,
10219
+ hasHeaders: log.headers !== void 0 && Object.keys(log.headers).length > 0,
10220
+ bodyContentMode: log.bodyContentMode ?? null
10221
+ });
10222
+ }
10223
+ async function getRuntimeConfigImpl(callApi2) {
10224
+ const configRes = await callApi2("/api/config");
10225
+ if (!configRes.ok) return toolError(`GET /api/config returned ${configRes.status}`);
10226
+ const statsRes = await callApi2("/api/logs?stats=1");
10227
+ if (!statsRes.ok) return toolError(`GET /api/logs?stats=1 returned ${statsRes.status}`);
10228
+ const config = await configRes.json();
10229
+ const storage = await statsRes.json();
10230
+ return textJson({
10231
+ config,
10232
+ storage
10233
+ });
10234
+ }
10235
+ async function diagnoseCaptureImpl(callApi2, args = {}) {
10236
+ const runtime = await getRuntimeConfigImpl(callApi2);
10237
+ if (runtime.isError === true) return runtime;
10238
+ const runtimeText = runtime.content[0]?.text ?? "{}";
10239
+ const runtimePayload = JSON.parse(runtimeText);
10240
+ const runtimeRecord = isRecord(runtimePayload) ? runtimePayload : {};
10241
+ const configRecord = isRecord(runtimeRecord["config"]) ? runtimeRecord["config"] : {};
10242
+ const captureMode = stringField(configRecord, "captureMode");
10243
+ let log = null;
10244
+ if (args.id !== void 0) {
10245
+ const logRes = await callApi2(`/api/logs/${args.id}`);
10246
+ if (!logRes.ok) return toolError(`GET /api/logs/${args.id} returned ${logRes.status}`);
10247
+ const rawLog = await logRes.json();
10248
+ const parsed = CapturedLogSchema.safeParse(rawLog);
10249
+ if (!parsed.success) return toolError(`GET /api/logs/${args.id} returned an unparseable log`);
10250
+ log = parsed.data;
10251
+ }
10252
+ const findings = [];
10253
+ const recommendations = [];
10254
+ if (captureMode !== "full") {
10255
+ findings.push(
10256
+ "Runtime captureMode is not full, so request/response bodies and headers may be compacted."
10257
+ );
10258
+ recommendations.push(
10259
+ "Restart or launch Agent Inspector with full capture mode when header/body evidence is required."
10260
+ );
10261
+ }
10262
+ if (log !== null) {
10263
+ if (log.rawHeaders === void 0 || Object.keys(log.rawHeaders).length === 0) {
10264
+ findings.push(`Log ${String(log.id)} has no rawHeaders stored.`);
10265
+ }
10266
+ if (log.headers === void 0 || Object.keys(log.headers).length === 0) {
10267
+ findings.push(`Log ${String(log.id)} has no upstream headers stored.`);
10268
+ }
10269
+ if (log.rawRequestBody === null) {
10270
+ findings.push(`Log ${String(log.id)} does not include rawRequestBody in this response.`);
10271
+ }
10272
+ if (log.bodyContentMode === "compact") {
10273
+ findings.push(`Log ${String(log.id)} is in compact body mode.`);
10274
+ recommendations.push(
10275
+ "Use inspector_get_log_headers for header-only checks and enable full capture for future body inspection."
10276
+ );
10277
+ }
10278
+ }
10279
+ return textJson({
10280
+ captureMode,
10281
+ logId: log?.id ?? null,
10282
+ hasLog: log !== null,
10283
+ findings,
10284
+ recommendations,
10285
+ runtime: runtimeRecord
10286
+ });
10287
+ }
10288
+ async function addGroupProcessImpl(callApi2, args) {
10289
+ const params = new URLSearchParams({
10290
+ clientPid: String(args.clientPid),
10291
+ offset: "0",
10292
+ limit: String(PROCESS_LOG_LIMIT_MAX),
10293
+ compact: "1"
10294
+ });
10295
+ const result = await readCompactLogsPage(callApi2, params);
10296
+ if (isToolResult(result)) return result;
10297
+ const bySession = /* @__PURE__ */ new Map();
10298
+ for (const log of result.logs) {
10299
+ if (log.sessionId === null || log.sessionId === "") continue;
10300
+ const existing = bySession.get(log.sessionId) ?? [];
10301
+ existing.push(log);
10302
+ bySession.set(log.sessionId, existing);
10303
+ }
10304
+ if (bySession.size === 0) {
10305
+ return toolError(`No sessions found for clientPid ${String(args.clientPid)}`);
10306
+ }
10307
+ let groupResult = null;
10308
+ const attached = [];
10309
+ for (const [sessionId, logs] of bySession.entries()) {
10310
+ const first = logs[0];
10311
+ const last = logs.at(-1);
10312
+ const userAgent = last?.userAgent ?? first?.userAgent ?? null;
10313
+ const agent = inferAgentFromUserAgent(userAgent);
10314
+ groupResult = addInspectorGroupSession(args.groupId, {
10315
+ sessionId,
10316
+ label: `${args.labelPrefix ?? `PID ${String(args.clientPid)}`} - ${sessionId}`,
10317
+ agent,
10318
+ provider: last?.providerName ?? first?.providerName ?? null,
10319
+ model: last?.model ?? first?.model ?? null,
10320
+ metadata: {
10321
+ clientPid: args.clientPid,
10322
+ processLogCount: logs.length,
10323
+ userAgent: userAgent ?? ""
10324
+ }
10325
+ });
10326
+ if (!groupResult.ok) return toolError(groupResult.message);
10327
+ attached.push({ sessionId, logCount: logs.length, agent, userAgent });
10328
+ }
10329
+ if (groupResult === null || !groupResult.ok) return toolError("Group process attach failed");
10330
+ return textJson({
10331
+ group: groupResult.value,
10332
+ clientPid: args.clientPid,
10333
+ attached
10334
+ });
10335
+ }
9955
10336
  function fileBytes(path2) {
9956
10337
  if (!existsSync(path2)) return null;
9957
10338
  try {
@@ -10224,7 +10605,7 @@ function providerDiagnosticHints(result) {
10224
10605
  }
10225
10606
  if (text.includes("nonstream") || text.includes("non-stream")) {
10226
10607
  hints.push(
10227
- "The failure mentions non-streaming. Compare the OpenAI/Anthropic non-streaming path and payload with the streaming request."
10608
+ "The failure mentions non-streaming. Compare the Anthropic, OpenAI Chat, and OpenAI Responses non-streaming path and payload with the streaming request."
10228
10609
  );
10229
10610
  }
10230
10611
  return [...new Set(hints)];
@@ -10398,6 +10779,9 @@ const UpdateProviderInputSchema = object({
10398
10779
  const LogResourceListResponseSchema = object({
10399
10780
  logs: array(object({ id: number().int().positive() }))
10400
10781
  });
10782
+ const ProcessResourceListResponseSchema = object({
10783
+ logs: array(object({ clientPid: number().int().positive().nullable().optional() }))
10784
+ });
10401
10785
  function textResource(uri, mimeType, text) {
10402
10786
  return {
10403
10787
  contents: [{ uri: uri.href, mimeType, text }]
@@ -10438,6 +10822,7 @@ const WRITE_TOOL_NAMES = /* @__PURE__ */ new Set([
10438
10822
  "inspector_update_group",
10439
10823
  "inspector_delete_group",
10440
10824
  "inspector_add_group_session",
10825
+ "inspector_add_group_process",
10441
10826
  "inspector_export_group_evidence",
10442
10827
  "inspector_export_group_evidence_bundle",
10443
10828
  "inspector_set_current_context",
@@ -10616,6 +11001,40 @@ async function listLogResources() {
10616
11001
  return listResult([]);
10617
11002
  }
10618
11003
  }
11004
+ async function listProcessResources() {
11005
+ try {
11006
+ const response = await callApi("/api/logs?q=&offset=0&limit=50&scanLimit=200");
11007
+ if (!response.ok) return listResult([]);
11008
+ const parsed = ProcessResourceListResponseSchema.safeParse(await response.json());
11009
+ if (!parsed.success) return listResult([]);
11010
+ const pids = [
11011
+ ...new Set(
11012
+ parsed.data.logs.map((log) => log.clientPid ?? null).filter((pid) => pid !== null)
11013
+ )
11014
+ ].sort((left, right) => left - right);
11015
+ return listResult(
11016
+ pids.map((pid) => ({
11017
+ uri: `inspector://processes/${String(pid)}`,
11018
+ name: `process:${String(pid)}`,
11019
+ title: `Inspector process ${String(pid)}`,
11020
+ mimeType: "application/json"
11021
+ }))
11022
+ );
11023
+ } catch {
11024
+ return listResult([]);
11025
+ }
11026
+ }
11027
+ async function listProcessTimelineResources() {
11028
+ const processResources = await listProcessResources();
11029
+ return listResult(
11030
+ processResources.resources.map((resource) => ({
11031
+ uri: `${resource.uri}/timeline`,
11032
+ name: `${resource.name}:timeline`,
11033
+ title: `${resource.title ?? resource.name} timeline`,
11034
+ mimeType: "application/json"
11035
+ }))
11036
+ );
11037
+ }
10619
11038
  function listRunResources() {
10620
11039
  return listResult(
10621
11040
  listInspectorRuns().runs.map((run) => ({
@@ -10713,7 +11132,8 @@ function registerTools(server) {
10713
11132
  offset: number().int().nonnegative().optional().describe("Skip this many entries."),
10714
11133
  limit: number().int().positive().optional().describe("How many summaries to return. Hard-capped at 5."),
10715
11134
  sessionId: string().optional().describe("Filter by session/affinity id."),
10716
- model: string().optional().describe("Filter by model name.")
11135
+ model: string().optional().describe("Filter by model name."),
11136
+ clientPid: number().int().positive().optional().describe("Filter by originating client process PID.")
10717
11137
  })
10718
11138
  },
10719
11139
  (args) => safeCall(() => listLogsImpl(callApi, args))
@@ -10729,7 +11149,8 @@ function registerTools(server) {
10729
11149
  limit: number().int().positive().optional().describe("How many summaries to return. Hard-capped at 5 by the MCP handler."),
10730
11150
  scanLimit: number().int().positive().max(1e3).optional().describe("How many recent compact logs to scan before filtering. Default 200."),
10731
11151
  sessionId: string().optional().describe("Optional session/affinity id filter."),
10732
- model: string().optional().describe("Optional model name filter.")
11152
+ model: string().optional().describe("Optional model name filter."),
11153
+ clientPid: number().int().positive().optional().describe("Optional originating client process PID filter.")
10733
11154
  })
10734
11155
  },
10735
11156
  (args) => safeCall(() => searchLogsImpl(callApi, args))
@@ -10756,6 +11177,55 @@ function registerTools(server) {
10756
11177
  },
10757
11178
  ({ id }) => safeCall(() => getLogChunksImpl(callApi, id))
10758
11179
  );
11180
+ server.registerTool(
11181
+ "inspector_get_log_headers",
11182
+ {
11183
+ title: "Get captured log headers",
11184
+ description: "Returns header-focused evidence for one log without large request/response bodies: raw headers, upstream headers, user-agent, origin, client PID/port, session id, model, and API path.",
11185
+ inputSchema: object({
11186
+ id: number().int().positive().describe("The log id.")
11187
+ })
11188
+ },
11189
+ ({ id }) => safeCall(() => getLogHeadersImpl(callApi, id))
11190
+ );
11191
+ server.registerTool(
11192
+ "inspector_list_processes",
11193
+ {
11194
+ title: "List observed client processes",
11195
+ description: "Groups recent compact logs by originating client PID and returns sessions, agents, user-agents, models, providers, ports, error counts, and latest logs. Useful for IDE -> process -> session navigation.",
11196
+ inputSchema: object({
11197
+ scanLimit: number().int().positive().max(200).optional().describe("How many recent logs to scan. Default 50, max 200."),
11198
+ limit: number().int().positive().max(200).optional().describe("Alias for scanLimit for simpler MCP clients.")
11199
+ })
11200
+ },
11201
+ (args) => safeCall(() => listProcessesImpl(callApi, args))
11202
+ );
11203
+ server.registerTool(
11204
+ "inspector_get_process",
11205
+ {
11206
+ title: "Get process summary",
11207
+ description: "Returns a bounded summary for one originating client PID across sessions, including user-agents, ports, models, providers, errors, and latest compact logs.",
11208
+ inputSchema: object({
11209
+ clientPid: number().int().positive().describe("Originating client process PID."),
11210
+ offset: number().int().nonnegative().optional().describe("Skip this many matching logs."),
11211
+ limit: number().int().positive().max(200).optional().describe("Maximum logs to summarize. Default 50, max 200.")
11212
+ })
11213
+ },
11214
+ (args) => safeCall(() => getProcessImpl(callApi, args))
11215
+ );
11216
+ server.registerTool(
11217
+ "inspector_get_process_timeline",
11218
+ {
11219
+ title: "Get process timeline",
11220
+ description: "Returns a bounded chronological timeline for one originating client PID, spanning all sessions observed for that process.",
11221
+ inputSchema: object({
11222
+ clientPid: number().int().positive().describe("Originating client process PID."),
11223
+ offset: number().int().nonnegative().optional().describe("Skip this many matching logs."),
11224
+ limit: number().int().positive().max(50).optional().describe("Maximum timeline events to return. Default 20, max 50.")
11225
+ })
11226
+ },
11227
+ (args) => safeCall(() => getProcessTimelineImpl(callApi, args))
11228
+ );
10759
11229
  server.registerTool(
10760
11230
  "inspector_list_sessions",
10761
11231
  {
@@ -10819,6 +11289,26 @@ function registerTools(server) {
10819
11289
  },
10820
11290
  (args) => safeWriteCall("inspector_set_current_context", () => setCurrentContextImpl(args))
10821
11291
  );
11292
+ server.registerTool(
11293
+ "inspector_get_runtime_config",
11294
+ {
11295
+ title: "Get Inspector runtime config",
11296
+ description: "Read-only runtime diagnostics: current proxy config plus log storage stats, including captureMode and log/chunk directories. Does not expose provider secrets.",
11297
+ inputSchema: object({})
11298
+ },
11299
+ () => safeCall(() => getRuntimeConfigImpl(callApi))
11300
+ );
11301
+ server.registerTool(
11302
+ "inspector_diagnose_capture",
11303
+ {
11304
+ title: "Diagnose capture detail availability",
11305
+ description: "Explains why headers or bodies may be missing for the current runtime or a specific log, including captureMode, compact body mode, rawHeaders presence, and next-step recommendations.",
11306
+ inputSchema: object({
11307
+ id: number().int().positive().optional().describe("Optional log id to inspect.")
11308
+ })
11309
+ },
11310
+ (args) => safeCall(() => diagnoseCaptureImpl(callApi, args))
11311
+ );
10822
11312
  server.registerTool(
10823
11313
  "inspector_create_run",
10824
11314
  {
@@ -10980,6 +11470,19 @@ function registerTools(server) {
10980
11470
  },
10981
11471
  (args) => safeWriteCall("inspector_add_group_session", () => addGroupSessionImpl(args))
10982
11472
  );
11473
+ server.registerTool(
11474
+ "inspector_add_group_process",
11475
+ {
11476
+ title: "Attach a process to an Inspector group",
11477
+ description: "Finds sessions observed for one client PID and attaches each session to a group with inferred agent/model/provider metadata. Useful when a process has both process fallback and explicit sessions.",
11478
+ inputSchema: object({
11479
+ groupId: string().min(1).describe("The Inspector group id."),
11480
+ clientPid: number().int().positive().describe("Originating client process PID."),
11481
+ labelPrefix: string().min(1).optional().describe("Optional label prefix. Defaults to PID <clientPid>.")
11482
+ })
11483
+ },
11484
+ (args) => safeWriteCall("inspector_add_group_process", () => addGroupProcessImpl(callApi, args))
11485
+ );
10983
11486
  server.registerTool(
10984
11487
  "inspector_export_group_evidence",
10985
11488
  {
@@ -11208,6 +11711,21 @@ function registerResources(server) {
11208
11711
  },
11209
11712
  (uri) => jsonResource(uri, getCurrentContext())
11210
11713
  );
11714
+ server.registerResource(
11715
+ "inspector_runtime_config",
11716
+ "inspector://runtime/config",
11717
+ {
11718
+ title: "Inspector runtime config",
11719
+ description: "Read-only runtime config and log storage stats.",
11720
+ mimeType: "application/json"
11721
+ },
11722
+ async (uri) => {
11723
+ const result = await getRuntimeConfigImpl(callApi);
11724
+ const first = result.content[0];
11725
+ const text = first?.text ?? "";
11726
+ return textResource(uri, result.isError === true ? "text/plain" : "application/json", text);
11727
+ }
11728
+ );
11211
11729
  server.registerResource(
11212
11730
  "inspector_sessions",
11213
11731
  "inspector://sessions",
@@ -11272,6 +11790,63 @@ function registerResources(server) {
11272
11790
  return textResource(uri, result.isError === true ? "text/plain" : "application/json", text);
11273
11791
  }
11274
11792
  );
11793
+ server.registerResource(
11794
+ "inspector_processes",
11795
+ "inspector://processes",
11796
+ {
11797
+ title: "Inspector client processes",
11798
+ description: "Observed originating client process PIDs grouped from recent logs.",
11799
+ mimeType: "application/json"
11800
+ },
11801
+ async (uri) => {
11802
+ const result = await listProcessesImpl(callApi, { scanLimit: 200 });
11803
+ const first = result.content[0];
11804
+ const text = first?.text ?? "";
11805
+ return textResource(uri, result.isError === true ? "text/plain" : "application/json", text);
11806
+ }
11807
+ );
11808
+ server.registerResource(
11809
+ "inspector_process",
11810
+ new ResourceTemplate("inspector://processes/{clientPid}", { list: listProcessResources }),
11811
+ {
11812
+ title: "Inspector process",
11813
+ description: "One originating client process summary with sessions, agents, user-agents, ports, models, providers, errors, and latest logs.",
11814
+ mimeType: "application/json"
11815
+ },
11816
+ async (uri, variables) => {
11817
+ const clientPid = variableString(variables, "clientPid");
11818
+ const parsed = clientPid === null ? Number.NaN : Number(clientPid);
11819
+ if (!Number.isInteger(parsed) || parsed <= 0) {
11820
+ return textResource(uri, "text/plain", "Invalid clientPid");
11821
+ }
11822
+ const result = await getProcessImpl(callApi, { clientPid: parsed });
11823
+ const first = result.content[0];
11824
+ const text = first?.text ?? "";
11825
+ return textResource(uri, result.isError === true ? "text/plain" : "application/json", text);
11826
+ }
11827
+ );
11828
+ server.registerResource(
11829
+ "inspector_process_timeline",
11830
+ new ResourceTemplate("inspector://processes/{clientPid}/timeline", {
11831
+ list: listProcessTimelineResources
11832
+ }),
11833
+ {
11834
+ title: "Inspector process timeline",
11835
+ description: "Bounded chronological timeline for one originating client process PID.",
11836
+ mimeType: "application/json"
11837
+ },
11838
+ async (uri, variables) => {
11839
+ const clientPid = variableString(variables, "clientPid");
11840
+ const parsed = clientPid === null ? Number.NaN : Number(clientPid);
11841
+ if (!Number.isInteger(parsed) || parsed <= 0) {
11842
+ return textResource(uri, "text/plain", "Invalid clientPid");
11843
+ }
11844
+ const result = await getProcessTimelineImpl(callApi, { clientPid: parsed, limit: 50 });
11845
+ const first = result.content[0];
11846
+ const text = first?.text ?? "";
11847
+ return textResource(uri, result.isError === true ? "text/plain" : "application/json", text);
11848
+ }
11849
+ );
11275
11850
  server.registerResource(
11276
11851
  "inspector_runs",
11277
11852
  "inspector://runs",
@@ -11544,11 +12119,17 @@ const TOOL_NAMES = [
11544
12119
  "inspector_search_logs",
11545
12120
  "inspector_get_log",
11546
12121
  "inspector_get_log_chunks",
12122
+ "inspector_get_log_headers",
12123
+ "inspector_list_processes",
12124
+ "inspector_get_process",
12125
+ "inspector_get_process_timeline",
11547
12126
  "inspector_list_sessions",
11548
12127
  "inspector_get_session",
11549
12128
  "inspector_get_session_timeline",
11550
12129
  "inspector_get_current_context",
11551
12130
  "inspector_set_current_context",
12131
+ "inspector_get_runtime_config",
12132
+ "inspector_diagnose_capture",
11552
12133
  "inspector_create_run",
11553
12134
  "inspector_get_run",
11554
12135
  "inspector_update_run",
@@ -11562,6 +12143,7 @@ const TOOL_NAMES = [
11562
12143
  "inspector_update_group",
11563
12144
  "inspector_delete_group",
11564
12145
  "inspector_add_group_session",
12146
+ "inspector_add_group_process",
11565
12147
  "inspector_export_group_evidence",
11566
12148
  "inspector_get_group_evidence_files",
11567
12149
  "inspector_export_group_evidence_bundle",
@@ -11584,10 +12166,14 @@ const RESOURCE_NAMES = [
11584
12166
  "inspector_mcp_capabilities",
11585
12167
  "inspector_mcp_config",
11586
12168
  "inspector_current_context",
12169
+ "inspector_runtime_config",
11587
12170
  "inspector_sessions",
11588
12171
  "inspector_session",
11589
12172
  "inspector_session_timeline",
11590
12173
  "inspector_log",
12174
+ "inspector_processes",
12175
+ "inspector_process",
12176
+ "inspector_process_timeline",
11591
12177
  "inspector_runs",
11592
12178
  "inspector_recent_failures",
11593
12179
  "inspector_run",
@@ -11679,6 +12265,7 @@ async function searchLogsPage(options) {
11679
12265
  const firstPage = await listLogsPage({
11680
12266
  sessionId: options.sessionId,
11681
12267
  model: options.model,
12268
+ clientPid: options.clientPid,
11682
12269
  offset: 0,
11683
12270
  limit: 1,
11684
12271
  includeBodies: false
@@ -11687,6 +12274,7 @@ async function searchLogsPage(options) {
11687
12274
  const scanPage = await listLogsPage({
11688
12275
  sessionId: options.sessionId,
11689
12276
  model: options.model,
12277
+ clientPid: options.clientPid,
11690
12278
  offset: scanOffset,
11691
12279
  limit: scanLimit,
11692
12280
  includeBodies: false
@@ -11742,6 +12330,11 @@ const Route$u = createFileRoute("/api/logs")({
11742
12330
  }
11743
12331
  const sessionId = url.searchParams.get("sessionId") ?? void 0;
11744
12332
  const model = url.searchParams.get("model") ?? void 0;
12333
+ const clientPidResult = parseOptionalPositiveInt(url.searchParams.get("clientPid"));
12334
+ if (!clientPidResult.ok) {
12335
+ return Response.json({ error: "Invalid clientPid" }, { status: 400 });
12336
+ }
12337
+ const clientPid = clientPidResult.value ?? void 0;
11745
12338
  const query = url.searchParams.get("q") ?? url.searchParams.get("search");
11746
12339
  const offset = parseNonNegativeInt(url.searchParams.get("offset"), 0);
11747
12340
  if (query !== null) {
@@ -11751,7 +12344,7 @@ const Route$u = createFileRoute("/api/logs")({
11751
12344
  LOG_SEARCH_DEFAULT_SCAN_LIMIT
11752
12345
  );
11753
12346
  return Response.json(
11754
- await searchLogsPage({ query, sessionId, model, offset, limit: limit2, scanLimit })
12347
+ await searchLogsPage({ query, sessionId, model, clientPid, offset, limit: limit2, scanLimit })
11755
12348
  );
11756
12349
  }
11757
12350
  const limit = parsePositiveInt$2(url.searchParams.get("limit"), 50);
@@ -11773,6 +12366,7 @@ const Route$u = createFileRoute("/api/logs")({
11773
12366
  await listLogsCursorPage({
11774
12367
  sessionId,
11775
12368
  model,
12369
+ clientPid,
11776
12370
  limit,
11777
12371
  includeBodies,
11778
12372
  beforeLogId: beforeLogId.value ?? void 0,
@@ -11782,7 +12376,7 @@ const Route$u = createFileRoute("/api/logs")({
11782
12376
  );
11783
12377
  }
11784
12378
  return Response.json(
11785
- await listLogsPage({ sessionId, model, offset, limit, includeBodies })
12379
+ await listLogsPage({ sessionId, model, clientPid, offset, limit, includeBodies })
11786
12380
  );
11787
12381
  },
11788
12382
  DELETE: async ({ request }) => {
@@ -13229,7 +13823,7 @@ function parseJsonlLogs(text) {
13229
13823
  }
13230
13824
  return { logs, skipped };
13231
13825
  }
13232
- function readStringProperty(value, name) {
13826
+ function readStringProperty$1(value, name) {
13233
13827
  const property = readRecordProperty(value, name);
13234
13828
  return typeof property === "string" ? property : null;
13235
13829
  }
@@ -13238,7 +13832,7 @@ function hasProperty(value, name) {
13238
13832
  return Object.getOwnPropertyDescriptor(value, name) !== void 0;
13239
13833
  }
13240
13834
  function modelFromRequestText(requestText) {
13241
- return readStringProperty(parseJson(requestText), "model");
13835
+ return readStringProperty$1(parseJson(requestText), "model");
13242
13836
  }
13243
13837
  function inferApiFormatFromBody(path2, model, requestText) {
13244
13838
  const pathFormat = apiFormatForPath(path2);
@@ -14424,7 +15018,15 @@ function buildProviderTestUserPrompt(mode) {
14424
15018
  function buildProviderTestMessages(mode) {
14425
15019
  return [{ role: "user", content: buildProviderTestUserPrompt(mode) }];
14426
15020
  }
14427
- function buildProviderTestRequestBody(model, mode) {
15021
+ function buildProviderTestRequestBody(model, mode, apiShape = "chat") {
15022
+ if (apiShape === "responses") {
15023
+ return {
15024
+ model,
15025
+ input: buildProviderTestUserPrompt(mode),
15026
+ max_output_tokens: maxTokensForMode(mode),
15027
+ stream: mode === "streaming"
15028
+ };
15029
+ }
14428
15030
  const base = {
14429
15031
  model,
14430
15032
  messages: buildProviderTestMessages(mode),
@@ -14671,6 +15273,50 @@ const OpenAIResponseSchema = object({
14671
15273
  })
14672
15274
  )
14673
15275
  });
15276
+ function isOpenAIProtocol(protocol) {
15277
+ return protocol === "openaiChat" || protocol === "openaiResponses";
15278
+ }
15279
+ function providerTestApiShape(protocol) {
15280
+ switch (protocol) {
15281
+ case "anthropic":
15282
+ case "openaiChat":
15283
+ return "chat";
15284
+ case "openaiResponses":
15285
+ return "responses";
15286
+ }
15287
+ }
15288
+ function buildProviderTestBodyText(model, mode, protocol) {
15289
+ return JSON.stringify(buildProviderTestRequestBody(model, mode, providerTestApiShape(protocol)));
15290
+ }
15291
+ function readProperty(value, key) {
15292
+ if (value === null || typeof value !== "object" || Array.isArray(value)) return void 0;
15293
+ return Object.getOwnPropertyDescriptor(value, key)?.value;
15294
+ }
15295
+ function readStringProperty(value, key) {
15296
+ const property = readProperty(value, key);
15297
+ return typeof property === "string" ? property : null;
15298
+ }
15299
+ function readArrayProperty(value, key) {
15300
+ const property = readProperty(value, key);
15301
+ return Array.isArray(property) ? property : [];
15302
+ }
15303
+ function responseTextFromOpenAIResponses(response) {
15304
+ if (response.output_text !== void 0 && response.output_text.length > 0) {
15305
+ return response.output_text;
15306
+ }
15307
+ const parts = [];
15308
+ for (const outputItem of response.output ?? []) {
15309
+ const content = readArrayProperty(outputItem, "content");
15310
+ for (const contentPart of content) {
15311
+ const type = readStringProperty(contentPart, "type");
15312
+ const text = readStringProperty(contentPart, "text");
15313
+ if ((type === "output_text" || type === "text") && text !== null && text.length > 0) {
15314
+ parts.push(text);
15315
+ }
15316
+ }
15317
+ }
15318
+ return parts.length > 0 ? parts.join("\n") : null;
15319
+ }
14674
15320
  function getProviderTestTimeoutMs() {
14675
15321
  return getConfig().providerTestTimeoutSeconds * 1e3;
14676
15322
  }
@@ -14684,9 +15330,9 @@ function buildTestRequestHeaders(provider) {
14684
15330
  });
14685
15331
  return result;
14686
15332
  }
14687
- async function testEndpoint(baseUrl, provider, path2, model, isOpenAI) {
15333
+ async function testEndpoint(baseUrl, provider, path2, model, protocol) {
14688
15334
  const startTime = Date.now();
14689
- const body = JSON.stringify(buildProviderTestRequestBody(model, "non-streaming"));
15335
+ const body = buildProviderTestBodyText(model, "non-streaming", protocol);
14690
15336
  const requestHeaders = buildTestRequestHeaders(provider);
14691
15337
  let requestUrl = baseUrl;
14692
15338
  const controller = new AbortController();
@@ -14719,7 +15365,7 @@ async function testEndpoint(baseUrl, provider, path2, model, isOpenAI) {
14719
15365
  const responseText = await response.text();
14720
15366
  const safeRequestHeaders = redactHeaders(requestHeaders);
14721
15367
  try {
14722
- if (isOpenAI) {
15368
+ if (protocol === "openaiChat") {
14723
15369
  const json = OpenAIResponseSchema.parse(JSON.parse(responseText));
14724
15370
  const responseModel = json.model ?? model;
14725
15371
  const inputTokens = json.usage?.prompt_tokens;
@@ -14735,7 +15381,25 @@ async function testEndpoint(baseUrl, provider, path2, model, isOpenAI) {
14735
15381
  rawResponse: responseText,
14736
15382
  requestHeaders: safeRequestHeaders
14737
15383
  };
14738
- } else {
15384
+ }
15385
+ if (protocol === "openaiResponses") {
15386
+ const json = OpenAIResponsesResponseSchema.parse(JSON.parse(responseText));
15387
+ const responseModel = json.model ?? model;
15388
+ const inputTokens = json.usage?.input_tokens ?? void 0;
15389
+ const outputTokens = json.usage?.output_tokens ?? void 0;
15390
+ const content = responseTextFromOpenAIResponses(json);
15391
+ return {
15392
+ success: true,
15393
+ model: responseModel,
15394
+ inputTokens,
15395
+ outputTokens,
15396
+ latencyMs,
15397
+ content: content !== null && content !== "" ? [{ type: "text", text: content }] : void 0,
15398
+ rawResponse: responseText,
15399
+ requestHeaders: safeRequestHeaders
15400
+ };
15401
+ }
15402
+ {
14739
15403
  const json = AnthropicResponseSchema.parse(JSON.parse(responseText));
14740
15404
  const responseModel = json.model ?? model;
14741
15405
  const inputTokens = json.usage?.input_tokens;
@@ -14790,9 +15454,9 @@ async function testEndpoint(baseUrl, provider, path2, model, isOpenAI) {
14790
15454
  clearTimeout(timeoutId);
14791
15455
  }
14792
15456
  }
14793
- async function testStreamingEndpoint(baseUrl, provider, path2, model, isOpenAI) {
15457
+ async function testStreamingEndpoint(baseUrl, provider, path2, model, protocol) {
14794
15458
  const startTime = Date.now();
14795
- const body = JSON.stringify(buildProviderTestRequestBody(model, "streaming"));
15459
+ const body = buildProviderTestBodyText(model, "streaming", protocol);
14796
15460
  const requestHeaders = buildTestRequestHeaders(provider);
14797
15461
  let requestUrl = baseUrl;
14798
15462
  const controller = new AbortController();
@@ -14906,11 +15570,11 @@ async function testStreamingEndpoint(baseUrl, provider, path2, model, isOpenAI)
14906
15570
  streaming: true,
14907
15571
  userAgent: null,
14908
15572
  origin: null,
14909
- apiFormat: "anthropic",
15573
+ apiFormat: isOpenAIProtocol(protocol) ? "openai" : "anthropic",
14910
15574
  isTest: true
14911
15575
  };
14912
15576
  let reconstructedJson;
14913
- if (isOpenAI) {
15577
+ if (isOpenAIProtocol(protocol)) {
14914
15578
  reconstructedJson = extractOpenAIStream(fullResponse, mockLog, model, true);
14915
15579
  } else {
14916
15580
  reconstructedJson = extractAnthropicStream(fullResponse, mockLog, model, true);
@@ -14923,7 +15587,7 @@ async function testStreamingEndpoint(baseUrl, provider, path2, model, isOpenAI)
14923
15587
  let cacheCreationInputTokens;
14924
15588
  let cacheReadInputTokens;
14925
15589
  let responseModel;
14926
- if (isOpenAI) {
15590
+ if (protocol === "openaiChat") {
14927
15591
  const parsed = OpenAIResponseSchema.parse(JSON.parse(reconstructedJson));
14928
15592
  responseModel = typeof parsed.model === "string" && parsed.model !== "" ? parsed.model : void 0;
14929
15593
  inputTokens = parsed.usage?.prompt_tokens;
@@ -14932,6 +15596,15 @@ async function testStreamingEndpoint(baseUrl, provider, path2, model, isOpenAI)
14932
15596
  if (textContent !== null && textContent !== "") {
14933
15597
  content = [{ type: "text", text: textContent }];
14934
15598
  }
15599
+ } else if (protocol === "openaiResponses") {
15600
+ const parsed = OpenAIResponsesResponseSchema.parse(JSON.parse(reconstructedJson));
15601
+ responseModel = typeof parsed.model === "string" && parsed.model !== "" ? parsed.model : void 0;
15602
+ inputTokens = parsed.usage?.input_tokens ?? void 0;
15603
+ outputTokens = parsed.usage?.output_tokens ?? void 0;
15604
+ const textContent = responseTextFromOpenAIResponses(parsed);
15605
+ if (textContent !== null && textContent !== "") {
15606
+ content = [{ type: "text", text: textContent }];
15607
+ }
14935
15608
  } else {
14936
15609
  const parsed = AnthropicResponseSchema.parse(JSON.parse(reconstructedJson));
14937
15610
  responseModel = typeof parsed.model === "string" && parsed.model !== "" ? parsed.model : void 0;
@@ -15016,24 +15689,39 @@ const Route$a = createFileRoute("/api/providers/$providerId/test")({
15016
15689
  const results = {
15017
15690
  anthropic: { nonStreaming: { notConfigured: true }, streaming: { notConfigured: true } },
15018
15691
  openai: { nonStreaming: { notConfigured: true }, streaming: { notConfigured: true } },
15692
+ openaiChat: {
15693
+ nonStreaming: { notConfigured: true },
15694
+ streaming: { notConfigured: true }
15695
+ },
15696
+ openaiResponses: {
15697
+ nonStreaming: { notConfigured: true },
15698
+ streaming: { notConfigured: true }
15699
+ },
15019
15700
  models: {}
15020
15701
  };
15021
15702
  const anthropicUrl = provider.anthropicBaseUrl !== void 0 && provider.anthropicBaseUrl.length > 0 ? provider.anthropicBaseUrl : void 0;
15022
15703
  const openaiUrl = provider.openaiBaseUrl !== void 0 && provider.openaiBaseUrl.length > 0 ? provider.openaiBaseUrl : void 0;
15704
+ const openaiResponsesUrl = provider.openaiResponsesBaseUrl !== void 0 && provider.openaiResponsesBaseUrl.length > 0 ? provider.openaiResponsesBaseUrl : void 0;
15023
15705
  async function testOneModel(displayName) {
15024
15706
  const usageModel = getModelUsageName(displayName, p.name);
15025
15707
  const notConfigured = { notConfigured: true };
15708
+ const notConfiguredFormat = {
15709
+ nonStreaming: notConfigured,
15710
+ streaming: notConfigured
15711
+ };
15026
15712
  const modelResults = {
15027
15713
  anthropic: { nonStreaming: notConfigured, streaming: notConfigured },
15028
- openai: { nonStreaming: notConfigured, streaming: notConfigured }
15714
+ openai: notConfiguredFormat,
15715
+ openaiChat: { nonStreaming: notConfigured, streaming: notConfigured },
15716
+ openaiResponses: { nonStreaming: notConfigured, streaming: notConfigured }
15029
15717
  };
15030
15718
  const tasks = [];
15031
15719
  if (anthropicUrl !== void 0) {
15032
15720
  tasks.push(
15033
- testEndpoint(anthropicUrl, p, "/v1/messages", usageModel, false).then((r) => {
15721
+ testEndpoint(anthropicUrl, p, "/v1/messages", usageModel, "anthropic").then((r) => {
15034
15722
  modelResults.anthropic.nonStreaming = r;
15035
15723
  }),
15036
- testStreamingEndpoint(anthropicUrl, p, "/v1/messages", usageModel, false).then(
15724
+ testStreamingEndpoint(anthropicUrl, p, "/v1/messages", usageModel, "anthropic").then(
15037
15725
  (r) => {
15038
15726
  modelResults.anthropic.streaming = r;
15039
15727
  }
@@ -15042,14 +15730,44 @@ const Route$a = createFileRoute("/api/providers/$providerId/test")({
15042
15730
  }
15043
15731
  if (openaiUrl !== void 0) {
15044
15732
  tasks.push(
15045
- testEndpoint(openaiUrl, p, "/v1/chat/completions", usageModel, true).then((r) => {
15046
- modelResults.openai.nonStreaming = r;
15047
- }),
15048
- testStreamingEndpoint(openaiUrl, p, "/v1/chat/completions", usageModel, true).then(
15733
+ testEndpoint(openaiUrl, p, "/v1/chat/completions", usageModel, "openaiChat").then(
15049
15734
  (r) => {
15050
- modelResults.openai.streaming = r;
15735
+ modelResults.openai.nonStreaming = r;
15736
+ modelResults.openaiChat.nonStreaming = r;
15051
15737
  }
15052
- )
15738
+ ),
15739
+ testStreamingEndpoint(
15740
+ openaiUrl,
15741
+ p,
15742
+ "/v1/chat/completions",
15743
+ usageModel,
15744
+ "openaiChat"
15745
+ ).then((r) => {
15746
+ modelResults.openai.streaming = r;
15747
+ modelResults.openaiChat.streaming = r;
15748
+ })
15749
+ );
15750
+ }
15751
+ if (openaiResponsesUrl !== void 0) {
15752
+ tasks.push(
15753
+ testEndpoint(
15754
+ openaiResponsesUrl,
15755
+ p,
15756
+ "/v1/responses",
15757
+ usageModel,
15758
+ "openaiResponses"
15759
+ ).then((r) => {
15760
+ modelResults.openaiResponses.nonStreaming = r;
15761
+ }),
15762
+ testStreamingEndpoint(
15763
+ openaiResponsesUrl,
15764
+ p,
15765
+ "/v1/responses",
15766
+ usageModel,
15767
+ "openaiResponses"
15768
+ ).then((r) => {
15769
+ modelResults.openaiResponses.streaming = r;
15770
+ })
15053
15771
  );
15054
15772
  }
15055
15773
  await Promise.all(tasks);
@@ -15061,6 +15779,8 @@ const Route$a = createFileRoute("/api/providers/$providerId/test")({
15061
15779
  if (firstResults !== void 0) {
15062
15780
  results.anthropic = firstResults.anthropic;
15063
15781
  results.openai = firstResults.openai;
15782
+ results.openaiChat = firstResults.openaiChat;
15783
+ results.openaiResponses = firstResults.openaiResponses;
15064
15784
  }
15065
15785
  results.testedAt = (/* @__PURE__ */ new Date()).toISOString();
15066
15786
  return Response.json(results);
@@ -15701,15 +16421,41 @@ const ProviderFormatTestResultsSchema = object({
15701
16421
  nonStreaming: ProviderTestStateSchema,
15702
16422
  streaming: ProviderTestStateSchema
15703
16423
  });
16424
+ function createNotConfiguredProviderFormatTestResults() {
16425
+ return {
16426
+ nonStreaming: { notConfigured: true },
16427
+ streaming: { notConfigured: true }
16428
+ };
16429
+ }
15704
16430
  const ModelTestResultsSchema = object({
15705
16431
  anthropic: ProviderFormatTestResultsSchema,
15706
- openai: ProviderFormatTestResultsSchema
16432
+ openai: ProviderFormatTestResultsSchema.optional(),
16433
+ openaiChat: ProviderFormatTestResultsSchema.optional(),
16434
+ openaiResponses: ProviderFormatTestResultsSchema.optional()
16435
+ }).transform((value) => {
16436
+ const openaiChat = value.openaiChat ?? value.openai ?? createNotConfiguredProviderFormatTestResults();
16437
+ return {
16438
+ ...value,
16439
+ openai: value.openai ?? openaiChat,
16440
+ openaiChat,
16441
+ openaiResponses: value.openaiResponses ?? createNotConfiguredProviderFormatTestResults()
16442
+ };
15707
16443
  });
15708
16444
  const ProviderTestResultsSchema = object({
15709
16445
  anthropic: ProviderFormatTestResultsSchema,
15710
- openai: ProviderFormatTestResultsSchema,
16446
+ openai: ProviderFormatTestResultsSchema.optional(),
16447
+ openaiChat: ProviderFormatTestResultsSchema.optional(),
16448
+ openaiResponses: ProviderFormatTestResultsSchema.optional(),
15711
16449
  models: record(string(), ModelTestResultsSchema).optional(),
15712
16450
  testedAt: string().optional()
16451
+ }).transform((value) => {
16452
+ const openaiChat = value.openaiChat ?? value.openai ?? createNotConfiguredProviderFormatTestResults();
16453
+ return {
16454
+ ...value,
16455
+ openai: value.openai ?? openaiChat,
16456
+ openaiChat,
16457
+ openaiResponses: value.openaiResponses ?? createNotConfiguredProviderFormatTestResults()
16458
+ };
15713
16459
  });
15714
16460
  function createPendingProviderTestResults() {
15715
16461
  return {
@@ -15720,6 +16466,14 @@ function createPendingProviderTestResults() {
15720
16466
  openai: {
15721
16467
  nonStreaming: { testing: true },
15722
16468
  streaming: { testing: true }
16469
+ },
16470
+ openaiChat: {
16471
+ nonStreaming: { testing: true },
16472
+ streaming: { testing: true }
16473
+ },
16474
+ openaiResponses: {
16475
+ nonStreaming: { testing: true },
16476
+ streaming: { testing: true }
15723
16477
  }
15724
16478
  };
15725
16479
  }
@@ -15733,7 +16487,9 @@ function createFailedProviderTestResults(message, type) {
15733
16487
  });
15734
16488
  return {
15735
16489
  anthropic: createFormatResult(),
15736
- openai: createFormatResult()
16490
+ openai: createFormatResult(),
16491
+ openaiChat: createFormatResult(),
16492
+ openaiResponses: createFormatResult()
15737
16493
  };
15738
16494
  }
15739
16495
  function hasSuccessField(result) {
@@ -15764,7 +16520,7 @@ function getResultTokensPerSecond(result) {
15764
16520
  totalStreamMs: getResultTotalStreamMs(result)
15765
16521
  });
15766
16522
  }
15767
- async function logModelResults(displayName, providerName, providerSessionId, anthropicUrl, openaiUrl, modelResults, captureFullDetails) {
16523
+ async function logModelResults(displayName, providerName, providerSessionId, anthropicUrl, openaiChatUrl, openaiResponsesUrl, modelResults, captureFullDetails) {
15768
16524
  const usageModel = getModelUsageName(displayName, providerName);
15769
16525
  if (anthropicUrl !== void 0) {
15770
16526
  const nsResult = modelResults.anthropic.nonStreaming;
@@ -15829,9 +16585,9 @@ async function logModelResults(displayName, providerName, providerSessionId, ant
15829
16585
  });
15830
16586
  }
15831
16587
  }
15832
- if (openaiUrl !== void 0) {
15833
- const nsResult = modelResults.openai.nonStreaming;
15834
- const sResult = modelResults.openai.streaming;
16588
+ if (openaiChatUrl !== void 0) {
16589
+ const nsResult = modelResults.openaiChat.nonStreaming;
16590
+ const sResult = modelResults.openaiChat.streaming;
15835
16591
  if (hasSuccessField(nsResult) && hasSuccessField(sResult)) {
15836
16592
  const nonStreamingResult = nsResult;
15837
16593
  const streamingResult = sResult;
@@ -15892,6 +16648,71 @@ async function logModelResults(displayName, providerName, providerSessionId, ant
15892
16648
  });
15893
16649
  }
15894
16650
  }
16651
+ if (openaiResponsesUrl !== void 0) {
16652
+ const nsResult = modelResults.openaiResponses.nonStreaming;
16653
+ const sResult = modelResults.openaiResponses.streaming;
16654
+ if (hasSuccessField(nsResult) && hasSuccessField(sResult)) {
16655
+ const nonStreamingResult = nsResult;
16656
+ const streamingResult = sResult;
16657
+ const requestBody = JSON.stringify(
16658
+ buildProviderTestRequestBody(usageModel, "non-streaming", "responses")
16659
+ );
16660
+ await addTestLogEntry({
16661
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
16662
+ method: "POST",
16663
+ path: "/v1/responses",
16664
+ model: nonStreamingResult.model ?? displayName,
16665
+ sessionId: providerSessionId,
16666
+ rawRequestBody: requestBody,
16667
+ responseStatus: getResultResponseStatus(nonStreamingResult),
16668
+ responseText: getResultResponseText(nonStreamingResult),
16669
+ inputTokens: nonStreamingResult.inputTokens ?? null,
16670
+ outputTokens: nonStreamingResult.outputTokens ?? null,
16671
+ cacheCreationInputTokens: null,
16672
+ cacheReadInputTokens: nonStreamingResult.cacheReadInputTokens ?? null,
16673
+ elapsedMs: nonStreamingResult.latencyMs ?? 0,
16674
+ firstChunkMs: null,
16675
+ totalStreamMs: null,
16676
+ tokensPerSecond: null,
16677
+ streaming: false,
16678
+ userAgent: "provider-test",
16679
+ origin: null,
16680
+ apiFormat: "openai",
16681
+ isTest: true,
16682
+ providerName,
16683
+ headers: captureFullDetails ? getResultHeaders(nonStreamingResult) : void 0
16684
+ });
16685
+ const streamingRequestBody = JSON.stringify(
16686
+ buildProviderTestRequestBody(usageModel, "streaming", "responses")
16687
+ );
16688
+ await addTestLogEntry({
16689
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
16690
+ method: "POST",
16691
+ path: "/v1/responses",
16692
+ model: streamingResult.model ?? displayName,
16693
+ sessionId: providerSessionId,
16694
+ rawRequestBody: streamingRequestBody,
16695
+ responseStatus: getResultResponseStatus(streamingResult),
16696
+ responseText: getResultResponseText(streamingResult),
16697
+ inputTokens: streamingResult.inputTokens ?? null,
16698
+ outputTokens: streamingResult.outputTokens ?? null,
16699
+ cacheCreationInputTokens: null,
16700
+ cacheReadInputTokens: streamingResult.cacheReadInputTokens ?? null,
16701
+ elapsedMs: getResultTotalStreamMs(streamingResult) ?? 0,
16702
+ firstChunkMs: getResultFirstChunkMs(streamingResult),
16703
+ totalStreamMs: getResultTotalStreamMs(streamingResult),
16704
+ tokensPerSecond: getResultTokensPerSecond(streamingResult),
16705
+ streaming: true,
16706
+ streamingChunks: captureFullDetails ? streamingResult.streamingChunks : void 0,
16707
+ userAgent: "provider-test",
16708
+ origin: null,
16709
+ apiFormat: "openai",
16710
+ isTest: true,
16711
+ providerName,
16712
+ headers: captureFullDetails ? getResultHeaders(streamingResult) : void 0
16713
+ });
16714
+ }
16715
+ }
15895
16716
  }
15896
16717
  const Route$2 = createFileRoute("/api/providers/$providerId/test/log")({
15897
16718
  server: {
@@ -15918,7 +16739,8 @@ const Route$2 = createFileRoute("/api/providers/$providerId/test/log")({
15918
16739
  const providerSessionId = buildProviderTestSessionId(params.providerId);
15919
16740
  const captureFullDetails = getConfig().captureMode === "full";
15920
16741
  const anthropicUrl = provider.anthropicBaseUrl !== void 0 && provider.anthropicBaseUrl.length > 0 ? provider.anthropicBaseUrl : void 0;
15921
- const openaiUrl = provider.openaiBaseUrl !== void 0 && provider.openaiBaseUrl.length > 0 ? provider.openaiBaseUrl : void 0;
16742
+ const openaiChatUrl = provider.openaiBaseUrl !== void 0 && provider.openaiBaseUrl.length > 0 ? provider.openaiBaseUrl : void 0;
16743
+ const openaiResponsesUrl = provider.openaiResponsesBaseUrl !== void 0 && provider.openaiResponsesBaseUrl.length > 0 ? provider.openaiResponsesBaseUrl : void 0;
15922
16744
  const entries = [];
15923
16745
  if (results.models !== void 0) {
15924
16746
  for (const [modelName, modelResult] of Object.entries(results.models)) {
@@ -15928,7 +16750,8 @@ const Route$2 = createFileRoute("/api/providers/$providerId/test/log")({
15928
16750
  provider.name,
15929
16751
  providerSessionId,
15930
16752
  anthropicUrl,
15931
- openaiUrl,
16753
+ openaiChatUrl,
16754
+ openaiResponsesUrl,
15932
16755
  modelResult,
15933
16756
  captureFullDetails
15934
16757
  )
@@ -16386,12 +17209,15 @@ const router = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProper
16386
17209
  }, Symbol.toStringTag, { value: "Module" }));
16387
17210
  export {
16388
17211
  AnthropicResponseSchema$1 as A,
16389
- isPlainRecord as B,
17212
+ createFailedProviderTestResults as B,
16390
17213
  CapturedLogSchema as C,
16391
17214
  DEFAULT_CAPTURE_MODE as D,
16392
- router as E,
17215
+ MAX_PROVIDER_TEST_TIMEOUT_SECONDS as E,
17216
+ resolveProviderContextWindow as F,
16393
17217
  GroupEvidenceReadResponseSchema as G,
17218
+ isPlainRecord as H,
16394
17219
  InspectorGroupsListResponseSchema as I,
17220
+ router as J,
16395
17221
  KnowledgeCandidateSchema as K,
16396
17222
  LogBodyChunkSchema as L,
16397
17223
  MAX_SLOW_RESPONSE_THRESHOLD_SECONDS as M,
@@ -16419,10 +17245,10 @@ export {
16419
17245
  findProviderModelMetadata as r,
16420
17246
  safeGetOwnProperty as s,
16421
17247
  maskApiKey as t,
16422
- buildUpstreamUrl as u,
16423
- createPendingProviderTestResults as v,
16424
- ProviderTestResultsSchema as w,
16425
- createFailedProviderTestResults as x,
16426
- MAX_PROVIDER_TEST_TIMEOUT_SECONDS as y,
16427
- resolveProviderContextWindow as z
17248
+ PATH_V1_MESSAGES as u,
17249
+ PATH_V1_CHAT_COMPLETIONS as v,
17250
+ PATH_V1_RESPONSES as w,
17251
+ previewUpstreamUrl as x,
17252
+ createPendingProviderTestResults as y,
17253
+ ProviderTestResultsSchema as z
16428
17254
  };