@tonyclaw/agent-inspector 2.1.17 → 2.1.19

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 (44) hide show
  1. package/.output/nitro.json +1 -1
  2. package/.output/public/assets/{CompareDrawer-B9sLBHw5.js → CompareDrawer-CHXN5HYU.js} +1 -1
  3. package/.output/public/assets/ProxyViewerContainer-TZJV7HhE.js +106 -0
  4. package/.output/public/assets/{ReplayDialog-D9I9W9n3.js → ReplayDialog-DQ7nS5Rr.js} +1 -1
  5. package/.output/public/assets/{RequestAnatomy-DGXK_Rii.js → RequestAnatomy-DXWweH_2.js} +1 -1
  6. package/.output/public/assets/{ResponseView-df_JzwsS.js → ResponseView-3PimPfiD.js} +2 -2
  7. package/.output/public/assets/{StreamingChunkSequence-i3DM5IKL.js → StreamingChunkSequence-4v52v-7a.js} +1 -1
  8. package/.output/public/assets/_sessionId-DfkBPvCC.js +1 -0
  9. package/.output/public/assets/{index-Dqc2r1ea.js → index-BuhFRImh.js} +1 -1
  10. package/.output/public/assets/index-ChgjUix0.css +1 -0
  11. package/.output/public/assets/index-Uf87L52J.js +1 -0
  12. package/.output/public/assets/{json-viewer-D3QWQlSB.js → json-viewer-d2gWBDLO.js} +1 -1
  13. package/.output/public/assets/{main-ZhxhOCmF.js → main-Do-E-46G.js} +2 -2
  14. package/.output/server/{_sessionId-YFrP0lZP.mjs → _sessionId-B82aMW2A.mjs} +2 -2
  15. package/.output/server/_ssr/{CompareDrawer-qC3adEeq.mjs → CompareDrawer-Bud_yIrM.mjs} +2 -2
  16. package/.output/server/_ssr/{ProxyViewerContainer-DCZIJC2b.mjs → ProxyViewerContainer-DqgVb0So.mjs} +1976 -1988
  17. package/.output/server/_ssr/{ReplayDialog-CvX4XYCi.mjs → ReplayDialog-DKbV5fnW.mjs} +3 -3
  18. package/.output/server/_ssr/{RequestAnatomy-HQfrxjO1.mjs → RequestAnatomy-MStxp1Wp.mjs} +2 -2
  19. package/.output/server/_ssr/{ResponseView-QSlSD11e.mjs → ResponseView-HLTCpJcF.mjs} +2 -2
  20. package/.output/server/_ssr/{StreamingChunkSequence-DTAiwlnI.mjs → StreamingChunkSequence-DEiyiUs_.mjs} +2 -2
  21. package/.output/server/_ssr/{index-D_EzfXaN.mjs → index-DamOPFDI.mjs} +2 -2
  22. package/.output/server/_ssr/index.mjs +2 -2
  23. package/.output/server/_ssr/{json-viewer-CrIX0e0Q.mjs → json-viewer-MmTWKxqh.mjs} +2 -2
  24. package/.output/server/_ssr/{router-__o2wrfO.mjs → router-50BIB6ED.mjs} +545 -22
  25. package/.output/server/{_tanstack-start-manifest_v-DbqyLpsI.mjs → _tanstack-start-manifest_v-TSwb1vFc.mjs} +1 -1
  26. package/.output/server/index.mjs +66 -66
  27. package/package.json +1 -1
  28. package/src/components/proxy-viewer/ConversationGroupList.tsx +11 -11
  29. package/src/components/proxy-viewer/ConversationHeader.tsx +7 -7
  30. package/src/components/proxy-viewer/LogEntry.tsx +15 -26
  31. package/src/components/proxy-viewer/LogEntryHeader.tsx +11 -14
  32. package/src/components/proxy-viewer/RequestToolsPanel.tsx +15 -15
  33. package/src/components/proxy-viewer/ThreadConnector.tsx +75 -91
  34. package/src/components/proxy-viewer/ToolTraceEvents.tsx +1 -1
  35. package/src/components/proxy-viewer/TurnGroup.tsx +11 -14
  36. package/src/mcp/server.ts +275 -0
  37. package/src/mcp/toolHandlers.ts +380 -3
  38. package/src/proxy/logSearch.ts +3 -0
  39. package/src/proxy/store.ts +40 -15
  40. package/src/routes/api/logs.ts +8 -2
  41. package/.output/public/assets/ProxyViewerContainer-DbWjc_BE.js +0 -106
  42. package/.output/public/assets/_sessionId-CTpCHdFh.js +0 -1
  43. package/.output/public/assets/index-Blqvndcn.js +0 -1
  44. package/.output/public/assets/index-Cs79WRQj.css +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-Cs79WRQj.css";
68
+ const appCss = "/assets/index-ChgjUix0.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-D_EzfXaN.mjs");
111
+ const $$splitComponentImporter$1 = () => import("./index-DamOPFDI.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-YFrP0lZP.mjs");
154
+ const $$splitComponentImporter = () => import("../_sessionId-B82aMW2A.mjs");
155
155
  const Route$B = createFileRoute("/session/$sessionId")({
156
156
  component: lazyRouteComponent($$splitComponentImporter, "component"),
157
157
  parseParams: (params) => ({
@@ -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
  }
@@ -9087,7 +9094,7 @@ const Route$w = createFileRoute("/api/models")({
9087
9094
  }
9088
9095
  }
9089
9096
  });
9090
- const version = "2.1.17";
9097
+ const version = "2.1.19";
9091
9098
  const packageJson = {
9092
9099
  version
9093
9100
  };
@@ -9721,11 +9728,18 @@ const SearchLogsResponseSchema = object({
9721
9728
  const PAGINATION_DEFAULTS = { offset: 0, limit: 3 };
9722
9729
  const LIMIT_HARD_CAP = 5;
9723
9730
  const LOG_DETAIL_TEXT_LIMIT = 2e5;
9731
+ const PROCESS_LOG_LIMIT_DEFAULT = 50;
9732
+ const PROCESS_LOG_LIMIT_MAX = 200;
9724
9733
  function clampLimit(input) {
9725
9734
  if (input === void 0) return PAGINATION_DEFAULTS.limit;
9726
9735
  if (!Number.isFinite(input) || input < 1) return 1;
9727
9736
  return Math.min(Math.floor(input), LIMIT_HARD_CAP);
9728
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
+ }
9729
9743
  function textJson(data) {
9730
9744
  return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
9731
9745
  }
@@ -9771,8 +9785,11 @@ function buildBoundedLogDetail(log) {
9771
9785
  responseTextTruncated: boundedResponse.truncated
9772
9786
  };
9773
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
+ }
9774
9791
  function buildLogSummary(log) {
9775
- 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);
9776
9793
  const rawRequestBodyBytes = log.rawRequestBodyBytes ?? textByteLength(log.rawRequestBody);
9777
9794
  const responseTextBytes = log.responseTextBytes ?? textByteLength(log.responseText);
9778
9795
  return {
@@ -9809,6 +9826,74 @@ function buildLogSummary(log) {
9809
9826
  responseTextBytes
9810
9827
  };
9811
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
+ }
9812
9897
  async function listLogsImpl(callApi2, args) {
9813
9898
  const offset = args.offset ?? PAGINATION_DEFAULTS.offset;
9814
9899
  const limit = clampLimit(args.limit);
@@ -9823,6 +9908,9 @@ async function listLogsImpl(callApi2, args) {
9823
9908
  if (args.model !== void 0 && args.model.length > 0) {
9824
9909
  params.set("model", args.model);
9825
9910
  }
9911
+ if (args.clientPid !== void 0) {
9912
+ params.set("clientPid", String(args.clientPid));
9913
+ }
9826
9914
  const res = await callApi2(`/api/logs?${params.toString()}`);
9827
9915
  if (!res.ok) return toolError(`GET /api/logs returned ${res.status}`);
9828
9916
  const rawBody = await res.json();
@@ -9848,6 +9936,9 @@ async function searchLogsImpl(callApi2, args) {
9848
9936
  if (args.model !== void 0 && args.model.length > 0) {
9849
9937
  params.set("model", args.model);
9850
9938
  }
9939
+ if (args.clientPid !== void 0) {
9940
+ params.set("clientPid", String(args.clientPid));
9941
+ }
9851
9942
  const res = await callApi2(`/api/logs?${params.toString()}`);
9852
9943
  if (!res.ok) return toolError(`GET /api/logs search returned ${res.status}`);
9853
9944
  const rawBody = await res.json();
@@ -10023,6 +10114,225 @@ async function getSessionTimelineImpl(callApi2, args) {
10023
10114
  buildSessionTimeline(args.sessionId, logs, parsed.data.total ?? logs.length, limit)
10024
10115
  );
10025
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
+ }
10026
10336
  function fileBytes(path2) {
10027
10337
  if (!existsSync(path2)) return null;
10028
10338
  try {
@@ -10469,6 +10779,9 @@ const UpdateProviderInputSchema = object({
10469
10779
  const LogResourceListResponseSchema = object({
10470
10780
  logs: array(object({ id: number().int().positive() }))
10471
10781
  });
10782
+ const ProcessResourceListResponseSchema = object({
10783
+ logs: array(object({ clientPid: number().int().positive().nullable().optional() }))
10784
+ });
10472
10785
  function textResource(uri, mimeType, text) {
10473
10786
  return {
10474
10787
  contents: [{ uri: uri.href, mimeType, text }]
@@ -10509,6 +10822,7 @@ const WRITE_TOOL_NAMES = /* @__PURE__ */ new Set([
10509
10822
  "inspector_update_group",
10510
10823
  "inspector_delete_group",
10511
10824
  "inspector_add_group_session",
10825
+ "inspector_add_group_process",
10512
10826
  "inspector_export_group_evidence",
10513
10827
  "inspector_export_group_evidence_bundle",
10514
10828
  "inspector_set_current_context",
@@ -10687,6 +11001,40 @@ async function listLogResources() {
10687
11001
  return listResult([]);
10688
11002
  }
10689
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
+ }
10690
11038
  function listRunResources() {
10691
11039
  return listResult(
10692
11040
  listInspectorRuns().runs.map((run) => ({
@@ -10784,7 +11132,8 @@ function registerTools(server) {
10784
11132
  offset: number().int().nonnegative().optional().describe("Skip this many entries."),
10785
11133
  limit: number().int().positive().optional().describe("How many summaries to return. Hard-capped at 5."),
10786
11134
  sessionId: string().optional().describe("Filter by session/affinity id."),
10787
- 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.")
10788
11137
  })
10789
11138
  },
10790
11139
  (args) => safeCall(() => listLogsImpl(callApi, args))
@@ -10800,7 +11149,8 @@ function registerTools(server) {
10800
11149
  limit: number().int().positive().optional().describe("How many summaries to return. Hard-capped at 5 by the MCP handler."),
10801
11150
  scanLimit: number().int().positive().max(1e3).optional().describe("How many recent compact logs to scan before filtering. Default 200."),
10802
11151
  sessionId: string().optional().describe("Optional session/affinity id filter."),
10803
- 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.")
10804
11154
  })
10805
11155
  },
10806
11156
  (args) => safeCall(() => searchLogsImpl(callApi, args))
@@ -10827,6 +11177,55 @@ function registerTools(server) {
10827
11177
  },
10828
11178
  ({ id }) => safeCall(() => getLogChunksImpl(callApi, id))
10829
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
+ );
10830
11229
  server.registerTool(
10831
11230
  "inspector_list_sessions",
10832
11231
  {
@@ -10890,6 +11289,26 @@ function registerTools(server) {
10890
11289
  },
10891
11290
  (args) => safeWriteCall("inspector_set_current_context", () => setCurrentContextImpl(args))
10892
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
+ );
10893
11312
  server.registerTool(
10894
11313
  "inspector_create_run",
10895
11314
  {
@@ -11051,6 +11470,19 @@ function registerTools(server) {
11051
11470
  },
11052
11471
  (args) => safeWriteCall("inspector_add_group_session", () => addGroupSessionImpl(args))
11053
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
+ );
11054
11486
  server.registerTool(
11055
11487
  "inspector_export_group_evidence",
11056
11488
  {
@@ -11279,6 +11711,21 @@ function registerResources(server) {
11279
11711
  },
11280
11712
  (uri) => jsonResource(uri, getCurrentContext())
11281
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
+ );
11282
11729
  server.registerResource(
11283
11730
  "inspector_sessions",
11284
11731
  "inspector://sessions",
@@ -11343,6 +11790,63 @@ function registerResources(server) {
11343
11790
  return textResource(uri, result.isError === true ? "text/plain" : "application/json", text);
11344
11791
  }
11345
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
+ );
11346
11850
  server.registerResource(
11347
11851
  "inspector_runs",
11348
11852
  "inspector://runs",
@@ -11615,11 +12119,17 @@ const TOOL_NAMES = [
11615
12119
  "inspector_search_logs",
11616
12120
  "inspector_get_log",
11617
12121
  "inspector_get_log_chunks",
12122
+ "inspector_get_log_headers",
12123
+ "inspector_list_processes",
12124
+ "inspector_get_process",
12125
+ "inspector_get_process_timeline",
11618
12126
  "inspector_list_sessions",
11619
12127
  "inspector_get_session",
11620
12128
  "inspector_get_session_timeline",
11621
12129
  "inspector_get_current_context",
11622
12130
  "inspector_set_current_context",
12131
+ "inspector_get_runtime_config",
12132
+ "inspector_diagnose_capture",
11623
12133
  "inspector_create_run",
11624
12134
  "inspector_get_run",
11625
12135
  "inspector_update_run",
@@ -11633,6 +12143,7 @@ const TOOL_NAMES = [
11633
12143
  "inspector_update_group",
11634
12144
  "inspector_delete_group",
11635
12145
  "inspector_add_group_session",
12146
+ "inspector_add_group_process",
11636
12147
  "inspector_export_group_evidence",
11637
12148
  "inspector_get_group_evidence_files",
11638
12149
  "inspector_export_group_evidence_bundle",
@@ -11655,10 +12166,14 @@ const RESOURCE_NAMES = [
11655
12166
  "inspector_mcp_capabilities",
11656
12167
  "inspector_mcp_config",
11657
12168
  "inspector_current_context",
12169
+ "inspector_runtime_config",
11658
12170
  "inspector_sessions",
11659
12171
  "inspector_session",
11660
12172
  "inspector_session_timeline",
11661
12173
  "inspector_log",
12174
+ "inspector_processes",
12175
+ "inspector_process",
12176
+ "inspector_process_timeline",
11662
12177
  "inspector_runs",
11663
12178
  "inspector_recent_failures",
11664
12179
  "inspector_run",
@@ -11750,6 +12265,7 @@ async function searchLogsPage(options) {
11750
12265
  const firstPage = await listLogsPage({
11751
12266
  sessionId: options.sessionId,
11752
12267
  model: options.model,
12268
+ clientPid: options.clientPid,
11753
12269
  offset: 0,
11754
12270
  limit: 1,
11755
12271
  includeBodies: false
@@ -11758,6 +12274,7 @@ async function searchLogsPage(options) {
11758
12274
  const scanPage = await listLogsPage({
11759
12275
  sessionId: options.sessionId,
11760
12276
  model: options.model,
12277
+ clientPid: options.clientPid,
11761
12278
  offset: scanOffset,
11762
12279
  limit: scanLimit,
11763
12280
  includeBodies: false
@@ -11813,6 +12330,11 @@ const Route$u = createFileRoute("/api/logs")({
11813
12330
  }
11814
12331
  const sessionId = url.searchParams.get("sessionId") ?? void 0;
11815
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;
11816
12338
  const query = url.searchParams.get("q") ?? url.searchParams.get("search");
11817
12339
  const offset = parseNonNegativeInt(url.searchParams.get("offset"), 0);
11818
12340
  if (query !== null) {
@@ -11822,7 +12344,7 @@ const Route$u = createFileRoute("/api/logs")({
11822
12344
  LOG_SEARCH_DEFAULT_SCAN_LIMIT
11823
12345
  );
11824
12346
  return Response.json(
11825
- await searchLogsPage({ query, sessionId, model, offset, limit: limit2, scanLimit })
12347
+ await searchLogsPage({ query, sessionId, model, clientPid, offset, limit: limit2, scanLimit })
11826
12348
  );
11827
12349
  }
11828
12350
  const limit = parsePositiveInt$2(url.searchParams.get("limit"), 50);
@@ -11844,6 +12366,7 @@ const Route$u = createFileRoute("/api/logs")({
11844
12366
  await listLogsCursorPage({
11845
12367
  sessionId,
11846
12368
  model,
12369
+ clientPid,
11847
12370
  limit,
11848
12371
  includeBodies,
11849
12372
  beforeLogId: beforeLogId.value ?? void 0,
@@ -11853,7 +12376,7 @@ const Route$u = createFileRoute("/api/logs")({
11853
12376
  );
11854
12377
  }
11855
12378
  return Response.json(
11856
- await listLogsPage({ sessionId, model, offset, limit, includeBodies })
12379
+ await listLogsPage({ sessionId, model, clientPid, offset, limit, includeBodies })
11857
12380
  );
11858
12381
  },
11859
12382
  DELETE: async ({ request }) => {