@tonyclaw/agent-inspector 3.1.19 → 3.1.21

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 (61) hide show
  1. package/.output/backend/nitro.json +1 -1
  2. package/.output/cli.js +140 -20
  3. package/.output/server/_ssr/index.mjs +2 -2
  4. package/.output/server/_ssr/{router-0qlvqhVh.mjs → router-Be6BLuut.mjs} +2454 -1135
  5. package/.output/server/_tanstack-start-manifest_v-ClTaMkEj.mjs +4 -0
  6. package/.output/server/index.mjs +1 -1
  7. package/.output/ui/assets/{CompareDrawer-BOk9hd-Z.js → CompareDrawer-CGk2HFI1.js} +1 -1
  8. package/.output/ui/assets/{InspectorPet-DhHDBpk7.js → InspectorPet-CDM7SdOT.js} +1 -1
  9. package/.output/ui/assets/ProxyViewerContainer-CaWD78tw.js +60 -0
  10. package/.output/ui/assets/{ReplayDialog-DJhKtuNB.js → ReplayDialog-DqaeV1He.js} +1 -1
  11. package/.output/ui/assets/{RequestAnatomy-hP0tsqDC.js → RequestAnatomy-BtHl9P0k.js} +1 -1
  12. package/.output/ui/assets/{ResponseView-BSiUkwCb.js → ResponseView-C6t1vpxs.js} +1 -1
  13. package/.output/ui/assets/{StreamingChunkSequence-CzQqwv4X.js → StreamingChunkSequence-R4mgd3GQ.js} +1 -1
  14. package/.output/ui/assets/{_sessionId-BU-i6h0V.js → _sessionId-CL3hdLlQ.js} +1 -1
  15. package/.output/ui/assets/{_sessionId-C2Pq4Jb0.js → _sessionId-HS666S72.js} +1 -1
  16. package/.output/ui/assets/index-B-Qod-aA.css +1 -0
  17. package/.output/ui/assets/{index-D8C-t-2U.js → index-Bd9jPL4n.js} +1 -1
  18. package/.output/ui/assets/{index-zHpVF0jk.js → index-C4NHrclw.js} +1 -1
  19. package/.output/ui/assets/{index-UUnRwbOJ.js → index-UF1PJEcq.js} +1 -1
  20. package/.output/ui/assets/{index-B7NeIBDf.js → index-tX38BNV2.js} +2 -2
  21. package/.output/ui/assets/{json-viewer-DOzS5rUT.js → json-viewer-KSgzN_Ov.js} +1 -1
  22. package/.output/ui/assets/{jszip.min-CCCY7qNk.js → jszip.min-BiMDxghN.js} +1 -1
  23. package/.output/ui/index.html +2 -2
  24. package/.output/workers/logFinalizer.worker.js +261 -0
  25. package/.output/workers/sessionWorkerEntry.js +261 -0
  26. package/package.json +13 -6
  27. package/src/backend/routes/api/logs.$id.replay.ts +6 -1
  28. package/src/backend/routes/api/logs.stream.ts +7 -0
  29. package/src/backend/routes/api/providers.$providerId.model-metadata.ts +15 -4
  30. package/src/backend/routes/api/storage.ts +56 -0
  31. package/src/backend/routes/metrics.ts +14 -0
  32. package/src/cli/doctor.ts +135 -2
  33. package/src/cli.ts +7 -4
  34. package/src/components/ProxyViewerContainer.tsx +41 -24
  35. package/src/components/providers/SettingsDialog.tsx +261 -70
  36. package/src/components/proxy-viewer/LogEntry.tsx +19 -5
  37. package/src/components/proxy-viewer/bodyHydration.ts +67 -0
  38. package/src/components/proxy-viewer/proxyViewerContainerLogic.ts +78 -0
  39. package/src/contracts/index.ts +2 -0
  40. package/src/contracts/log.ts +5 -0
  41. package/src/knowledge/openclawClient.ts +11 -2
  42. package/src/knowledge/openclawGatewayClient.ts +6 -1
  43. package/src/lib/resourceLimits.ts +191 -0
  44. package/src/lib/safeFetch.ts +428 -20
  45. package/src/lib/stopReason.ts +66 -39
  46. package/src/proxy/ecosystemTasks.ts +20 -0
  47. package/src/proxy/handler.ts +17 -4
  48. package/src/proxy/identityProxy.ts +36 -16
  49. package/src/proxy/logIndex.ts +57 -6
  50. package/src/proxy/logger.ts +4 -0
  51. package/src/proxy/rawStreamCapture.ts +16 -1
  52. package/src/proxy/runtimeHealth.ts +4 -2
  53. package/src/proxy/runtimeMetrics.ts +149 -0
  54. package/src/proxy/schemas.ts +2 -0
  55. package/src/proxy/sessionRuntime.ts +38 -0
  56. package/src/proxy/sqliteLogIndex.ts +78 -2
  57. package/src/proxy/storageLifecycle.ts +432 -0
  58. package/src/proxy/store.ts +69 -13
  59. package/.output/server/_tanstack-start-manifest_v-DnbdNeun.mjs +0 -4
  60. package/.output/ui/assets/ProxyViewerContainer-BRYf987G.js +0 -59
  61. package/.output/ui/assets/index-IBEDJoV_.css +0 -1
@@ -34,9 +34,10 @@ import {
34
34
  type LogIndexSummary,
35
35
  } from "./logIndex";
36
36
  import { writeChunks } from "./chunkStorage";
37
- import { closeSqliteLogIndex } from "./sqliteLogIndex";
37
+ import { closeSqliteLogIndex, listSqliteLogCursorEntries } from "./sqliteLogIndex";
38
38
  import type { SessionInfo, SessionLogSummary } from "../lib/sessionInfoContract";
39
39
  import { extractToolTraceEvents } from "../lib/toolTrace";
40
+ import { extractStopReason } from "../lib/stopReason";
40
41
  import { textByteLength } from "../lib/unknown";
41
42
  import { buildSessionInfo, buildSessionLogSummary } from "./sessionInfo";
42
43
  import type { CapturedLog } from "./schemas";
@@ -71,6 +72,7 @@ import {
71
72
  type SessionClientInfo,
72
73
  type SessionSnapshot,
73
74
  } from "./sessionSupervisor";
75
+ import { installStorageLifecycleMaintenance, runStorageLifecycleGc } from "./storageLifecycle";
74
76
 
75
77
  export type { CapturedLog };
76
78
  export { getNextLogId };
@@ -277,13 +279,15 @@ function normalizeLog(log: CapturedLog): CapturedLog {
277
279
  const droppedChunks = log.droppedChunks ?? 0;
278
280
  const droppedBytes = log.droppedBytes ?? 0;
279
281
  const captureIncompleteReason = log.captureIncompleteReason ?? null;
282
+ const stopReason = log.stopReason ?? extractStopReason(log);
280
283
  if (
281
284
  sessionId === log.sessionId &&
282
285
  apiFormat === log.apiFormat &&
283
286
  log.captureIncomplete !== undefined &&
284
287
  log.droppedChunks !== undefined &&
285
288
  log.droppedBytes !== undefined &&
286
- log.captureIncompleteReason !== undefined
289
+ log.captureIncompleteReason !== undefined &&
290
+ log.stopReason !== undefined
287
291
  ) {
288
292
  return log;
289
293
  }
@@ -295,6 +299,7 @@ function normalizeLog(log: CapturedLog): CapturedLog {
295
299
  droppedChunks,
296
300
  droppedBytes,
297
301
  captureIncompleteReason,
302
+ stopReason,
298
303
  };
299
304
  }
300
305
 
@@ -339,6 +344,7 @@ export function compactLogForList(log: CapturedLog): CapturedLog {
339
344
  rawHeaders: undefined,
340
345
  headers: undefined,
341
346
  streamingChunks: undefined,
347
+ stopReason: log.stopReason ?? extractStopReason(log),
342
348
  toolTraceEvents: log.toolTraceEvents ?? extractToolTraceEvents(log),
343
349
  rawRequestBodyBytes: log.rawRequestBodyBytes ?? textByteLength(log.rawRequestBody),
344
350
  responseTextBytes: log.responseTextBytes ?? textByteLength(log.responseText),
@@ -385,6 +391,7 @@ function compactLogFromIndexSummary(summary: LogIndexSummary): CapturedLog {
385
391
  droppedBytes: summary.droppedBytes,
386
392
  captureIncompleteReason: summary.captureIncompleteReason,
387
393
  warnings: summary.warnings,
394
+ stopReason: summary.stopReason,
388
395
  toolTraceEvents: summary.toolTraceEvents,
389
396
  error: summary.error,
390
397
  });
@@ -863,21 +870,50 @@ export async function listLogsPage(options: ListLogsPageOptions): Promise<ListLo
863
870
  };
864
871
  }
865
872
 
866
- function matchesCursorWindow(id: number, options: ListLogsCursorPageOptions): boolean {
867
- if (options.beforeLogId !== undefined && id >= options.beforeLogId) return false;
868
- if (options.afterLogId !== undefined && id <= options.afterLogId) return false;
869
- return true;
873
+ function lowerBoundLogId(ids: readonly number[], target: number): number {
874
+ let low = 0;
875
+ let high = ids.length;
876
+ while (low < high) {
877
+ const middle = Math.floor((low + high) / 2);
878
+ const id = ids[middle];
879
+ if (id === undefined || id >= target) {
880
+ high = middle;
881
+ continue;
882
+ }
883
+ low = middle + 1;
884
+ }
885
+ return low;
886
+ }
887
+
888
+ function upperBoundLogId(ids: readonly number[], target: number): number {
889
+ let low = 0;
890
+ let high = ids.length;
891
+ while (low < high) {
892
+ const middle = Math.floor((low + high) / 2);
893
+ const id = ids[middle];
894
+ if (id === undefined || id > target) {
895
+ high = middle;
896
+ continue;
897
+ }
898
+ low = middle + 1;
899
+ }
900
+ return low;
870
901
  }
871
902
 
872
903
  function selectCursorPageLogs(
873
904
  ids: readonly number[],
874
905
  options: ListLogsCursorPageOptions,
875
906
  ): number[] {
876
- const matchingWindow = ids.filter((id) => matchesCursorWindow(id, options));
907
+ const windowStart =
908
+ options.afterLogId === undefined ? 0 : upperBoundLogId(ids, options.afterLogId);
909
+ const windowEnd =
910
+ options.beforeLogId === undefined ? ids.length : lowerBoundLogId(ids, options.beforeLogId);
911
+ if (windowStart >= windowEnd) return [];
912
+
877
913
  if (options.afterLogId !== undefined || options.anchor === "oldest") {
878
- return matchingWindow.slice(0, options.limit);
914
+ return ids.slice(windowStart, Math.min(windowEnd, windowStart + options.limit));
879
915
  }
880
- return matchingWindow.slice(Math.max(0, matchingWindow.length - options.limit));
916
+ return ids.slice(Math.max(windowStart, windowEnd - options.limit), windowEnd);
881
917
  }
882
918
 
883
919
  function rememberLogCursorPageIndex(index: LogCursorPageIndex): LogCursorPageIndex {
@@ -923,12 +959,18 @@ async function buildLogCursorPageIndexFromLogIndex(
923
959
  options: Pick<ListLogsCursorPageOptions, "sessionId" | "model" | "clientPid">,
924
960
  allowRebuild: boolean,
925
961
  ): Promise<LogCursorPageIndex | null> {
926
- if (options.clientPid !== undefined) return null;
927
-
928
- let entries = await listFilteredIndexEntries(options);
962
+ let entries = await listSqliteLogCursorEntries(options);
963
+ if (entries === null) {
964
+ if (options.clientPid !== undefined) return null;
965
+ entries = await listFilteredIndexEntries(options);
966
+ }
929
967
  if (entries.length === 0 && allowRebuild) {
930
968
  await rebuildIndex();
931
- entries = await listFilteredIndexEntries(options);
969
+ entries = await listSqliteLogCursorEntries(options);
970
+ if (entries === null) {
971
+ if (options.clientPid !== undefined) return null;
972
+ entries = await listFilteredIndexEntries(options);
973
+ }
932
974
  }
933
975
 
934
976
  if (entries.some((entry) => !hasLogIndexFilterMetadata(entry))) {
@@ -1308,6 +1350,20 @@ export function getLogStorageStats(): LogStorageStats {
1308
1350
  * then only retain the newest MAX_MEMORY_CACHE entries in cache.
1309
1351
  */
1310
1352
  export async function loadLogsIntoMemory(): Promise<void> {
1353
+ try {
1354
+ const gcResult = runStorageLifecycleGc();
1355
+ if (gcResult.filesDeleted > 0 || gcResult.errors.length > 0) {
1356
+ logger.info(
1357
+ "[store] Storage lifecycle GC completed:",
1358
+ `${gcResult.filesDeleted} files deleted, ${gcResult.bytesDeleted} bytes reclaimed,`,
1359
+ `${gcResult.errors.length} errors`,
1360
+ );
1361
+ }
1362
+ } catch (err) {
1363
+ logger.warn("[store] Storage lifecycle GC failed:", String(err));
1364
+ }
1365
+ installStorageLifecycleMaintenance();
1366
+
1311
1367
  const logDir = resolveLogDir();
1312
1368
  if (!existsSync(logDir)) return;
1313
1369
 
@@ -1,4 +0,0 @@
1
- const tsrStartManifest = () => ({ routes: { __root__: { filePath: "C:/Users/claw/workspace/agent-inspector/src/backend/routes/__root.ts", children: ["/$", "/livez", "/readyz", "/api/alerts", "/api/config", "/api/groups", "/api/health", "/api/instances", "/api/logs", "/api/mcp", "/api/models", "/api/pi-agent", "/api/providers", "/api/runs", "/api/runtime", "/api/sessions", "/proxy/$", "/api/ecosystem/packages", "/api/ecosystem/tasks", "/api/knowledge/candidates", "/api/knowledge/project-context", "/api/knowledge/search", "/api/ecosystem/recipes/$recipeId/run", "/api/knowledge/sessions/$sessionId/candidates"], preloads: ["/assets/index-D4LX-sw-.js"], scripts: [{ attrs: { type: "module", async: true, src: "/assets/index-D4LX-sw-.js" } }] } } });
2
- export {
3
- tsrStartManifest
4
- };