@tonyclaw/agent-inspector 3.0.29 → 3.0.31

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 (156) hide show
  1. package/.output/cli.js +791 -191
  2. package/.output/nitro.json +1 -1
  3. package/.output/public/assets/CompareDrawer-DB2KggLE.js +1 -0
  4. package/.output/public/assets/InspectorPet-CfwDw6kD.js +4108 -0
  5. package/.output/public/assets/ProxyViewerContainer-PcrO96_F.js +126 -0
  6. package/.output/public/assets/{ReplayDialog-CctnITbt.js → ReplayDialog-3Pl7EKjp.js} +1 -1
  7. package/.output/public/assets/{RequestAnatomy-BrN0RBbL.js → RequestAnatomy-BcPjcHLX.js} +1 -1
  8. package/.output/public/assets/ResponseView-DOx51wV3.js +2 -0
  9. package/.output/public/assets/StreamingChunkSequence-LkYJWM1A.js +1 -0
  10. package/.output/public/assets/_sessionId-BSg32vC6.js +1 -0
  11. package/.output/public/assets/{_sessionId-DKM91udC.js → _sessionId-C0CA68QV.js} +1 -1
  12. package/.output/public/assets/{index-Bq-nqolG.js → index-BpBUqdAB.js} +1 -1
  13. package/.output/public/assets/index-D93dCgAQ.js +1 -0
  14. package/.output/public/assets/{index-DPiESBo2.js → index-FV5sxqx3.js} +6 -6
  15. package/.output/public/assets/index-VUsF4nhf.js +76 -0
  16. package/.output/public/assets/index-hyQHZeQI.css +1 -0
  17. package/.output/public/assets/{json-viewer-CfaDJwx8.js → json-viewer-WctIbAh_.js} +1 -1
  18. package/.output/public/assets/jszip.min-DnSIoTix.js +2 -0
  19. package/.output/public/assets/qwen-mMn3f5ul.webp +0 -0
  20. package/.output/server/_libs/jszip.mjs +35 -9
  21. package/.output/server/_libs/lucide-react.mjs +80 -80
  22. package/.output/server/_libs/radix-ui__react-dialog.mjs +3 -3
  23. package/.output/server/_libs/tanstack__react-router.mjs +1 -1
  24. package/.output/server/{_sessionId-CwGXPD4C.mjs → _sessionId-BHBK3VbF.mjs} +15 -15
  25. package/.output/server/_sessionId-CyuJ6Kfl.mjs +81 -0
  26. package/.output/server/_ssr/{CompareDrawer-R_P1-VNr.mjs → CompareDrawer-27amlv_a.mjs} +138 -103
  27. package/.output/server/_ssr/InspectorPet-CQnGXfLs.mjs +925 -0
  28. package/.output/server/_ssr/{ProxyViewerContainer-DUgxRNbj.mjs → ProxyViewerContainer-DlAl0uF-.mjs} +1569 -1646
  29. package/.output/server/_ssr/{ReplayDialog-De9wKKzS.mjs → ReplayDialog-5m2jtlLa.mjs} +18 -18
  30. package/.output/server/_ssr/{RequestAnatomy-Db4MxUYo.mjs → RequestAnatomy--1WtQNY9.mjs} +58 -58
  31. package/.output/server/_ssr/{ResponseView-8rDXOiNB.mjs → ResponseView-CgbqS8sr.mjs} +60 -71
  32. package/.output/server/_ssr/{StreamingChunkSequence-N9teZHkA.mjs → StreamingChunkSequence-BwpnopWx.mjs} +16 -16
  33. package/.output/server/_ssr/{index-D4DvByuW.mjs → index-CNVi1TzT.mjs} +15 -15
  34. package/.output/server/_ssr/index-DMCjH_4V.mjs +81 -0
  35. package/.output/server/_ssr/index.mjs +2 -2
  36. package/.output/server/_ssr/{json-viewer-BjoHRbjS.mjs → json-viewer-DNGN2uoe.mjs} +58 -58
  37. package/.output/server/_ssr/{router-BYlePDj8.mjs → router-CgsqLnk5.mjs} +16007 -12632
  38. package/.output/server/_tanstack-start-manifest_v-BH5f_kWV.mjs +4 -0
  39. package/.output/server/index.mjs +99 -71
  40. package/.output/workers/logFinalizer.worker.js +16908 -0
  41. package/.output/workers/sessionWorkerEntry.js +16904 -0
  42. package/README.md +21 -5
  43. package/package.json +6 -2
  44. package/src/assets/logos/qwen.webp +0 -0
  45. package/src/cli.ts +85 -10
  46. package/src/components/OnboardingBanner.tsx +41 -21
  47. package/src/components/ProxyViewer.tsx +198 -269
  48. package/src/components/ProxyViewerContainer.tsx +128 -17
  49. package/src/components/ecosystem/AgentLabDialog.tsx +166 -19
  50. package/src/components/errors/SafeErrorBoundary.tsx +201 -0
  51. package/src/components/pi-agent/PiAgentPanel.tsx +209 -35
  52. package/src/components/pi-agent/piAgentChatLogic.ts +263 -0
  53. package/src/components/providers/ImportWizardDialog.tsx +18 -42
  54. package/src/components/providers/ProviderLogo.tsx +1 -1
  55. package/src/components/providers/ProvidersPanel.tsx +8 -5
  56. package/src/components/providers/SettingsDialog.tsx +34 -11
  57. package/src/components/proxy-viewer/ApplicationBar.tsx +63 -0
  58. package/src/components/proxy-viewer/CompareDrawer.tsx +92 -49
  59. package/src/components/proxy-viewer/LiveConnectionStatus.tsx +186 -0
  60. package/src/components/proxy-viewer/LogEntry.tsx +283 -275
  61. package/src/components/proxy-viewer/RawExportWarning.tsx +77 -0
  62. package/src/components/proxy-viewer/SessionLoadProgressBar.tsx +61 -0
  63. package/src/components/proxy-viewer/ThreadConnector.tsx +16 -1
  64. package/src/components/proxy-viewer/TurnGroup.tsx +13 -2
  65. package/src/components/proxy-viewer/accessibility.ts +8 -0
  66. package/src/components/proxy-viewer/lazy.ts +4 -0
  67. package/src/components/proxy-viewer/liveConnectionState.ts +158 -0
  68. package/src/components/proxy-viewer/proxyViewerLogic.ts +10 -0
  69. package/src/components/proxy-viewer/viewerState.ts +2 -6
  70. package/src/components/ui/select.tsx +1 -1
  71. package/src/components/ui/tabs.tsx +3 -3
  72. package/src/components/ui/transient-toast.tsx +7 -6
  73. package/src/lib/apiClient.ts +17 -2
  74. package/src/lib/ecosystemContract.ts +34 -0
  75. package/src/lib/export-logs.ts +1 -1
  76. package/src/lib/piAgentContract.ts +80 -0
  77. package/src/lib/providerContract.ts +70 -4
  78. package/src/lib/providerImportContract.ts +27 -0
  79. package/src/lib/providerModelMetadata.ts +16 -7
  80. package/src/lib/resourceLimits.ts +152 -0
  81. package/src/lib/safeDiagnostic.ts +38 -0
  82. package/src/lib/useProviders.ts +4 -4
  83. package/src/mcp/server.ts +39 -6
  84. package/src/mcp/toolHandlers.ts +131 -4
  85. package/src/proxy/chunkStorage.ts +20 -6
  86. package/src/proxy/config.ts +20 -6
  87. package/src/proxy/dataDir.ts +3 -0
  88. package/src/proxy/ecosystemExecutionConfirmation.ts +114 -0
  89. package/src/proxy/ecosystemExecutionRoute.ts +116 -0
  90. package/src/proxy/ecosystemTasks.ts +48 -0
  91. package/src/proxy/evidenceExporter.ts +23 -9
  92. package/src/proxy/groupEvidenceExporter.ts +26 -5
  93. package/src/proxy/groupStore.ts +13 -3
  94. package/src/proxy/handler.ts +103 -20
  95. package/src/proxy/identityProxy.ts +333 -14
  96. package/src/proxy/logFinalizer.ts +73 -6
  97. package/src/proxy/logImportUpload.ts +128 -0
  98. package/src/proxy/logImporter.ts +321 -70
  99. package/src/proxy/logIndex.ts +16 -6
  100. package/src/proxy/logger.ts +294 -41
  101. package/src/proxy/privateDataPath.ts +183 -0
  102. package/src/proxy/providerScanStore.ts +87 -0
  103. package/src/proxy/providerSecretStore.ts +58 -19
  104. package/src/proxy/providers.ts +175 -58
  105. package/src/proxy/rawStreamCapture.ts +66 -5
  106. package/src/proxy/runStore.ts +13 -3
  107. package/src/proxy/runtimeAdmission.ts +52 -0
  108. package/src/proxy/runtimeHealth.ts +206 -0
  109. package/src/proxy/runtimeShutdown.ts +75 -0
  110. package/src/proxy/sessionArchive.ts +15 -2
  111. package/src/proxy/sessionProcess.ts +19 -0
  112. package/src/proxy/sessionRuntime.ts +7 -0
  113. package/src/proxy/shutdownCoordinator.ts +90 -0
  114. package/src/proxy/sqliteLogIndex.ts +18 -2
  115. package/src/proxy/store.ts +18 -2
  116. package/src/routes/__root.tsx +18 -1
  117. package/src/routes/api/alerts.summary.ts +12 -8
  118. package/src/routes/api/alerts.ts +27 -9
  119. package/src/routes/api/ecosystem.packages.$packageId.help.ts +3 -8
  120. package/src/routes/api/ecosystem.packages.$packageId.install.ts +3 -8
  121. package/src/routes/api/ecosystem.packages.$packageId.runner-presets.ts +3 -11
  122. package/src/routes/api/ecosystem.packages.$packageId.upgrade.ts +3 -8
  123. package/src/routes/api/ecosystem.recipes.$recipeId.run.ts +3 -8
  124. package/src/routes/api/health.ts +9 -2
  125. package/src/routes/api/knowledge.project-context.ts +11 -0
  126. package/src/routes/api/knowledge.search.ts +33 -2
  127. package/src/routes/api/logs.$id.body.ts +16 -2
  128. package/src/routes/api/logs.import.ts +7 -18
  129. package/src/routes/api/logs.stream.ts +147 -69
  130. package/src/routes/api/logs.ts +55 -14
  131. package/src/routes/api/providers.$providerId.model-metadata.ts +22 -4
  132. package/src/routes/api/providers.$providerId.ts +37 -6
  133. package/src/routes/api/providers.export.ts +34 -16
  134. package/src/routes/api/providers.import.ts +42 -8
  135. package/src/routes/api/providers.scan.ts +13 -8
  136. package/src/routes/api/providers.ts +36 -5
  137. package/src/routes/api/runs.ts +12 -12
  138. package/src/routes/api/sessions.ts +15 -8
  139. package/src/routes/index.tsx +6 -0
  140. package/src/routes/livez.ts +13 -0
  141. package/src/routes/readyz.ts +18 -0
  142. package/src/routes/session/$sessionId.tsx +6 -0
  143. package/src/services/piAgent.ts +131 -102
  144. package/src/services/piAgentRetrieval.ts +1180 -0
  145. package/styles/globals.css +19 -3
  146. package/.output/public/assets/CompareDrawer-Cb5ccPeX.js +0 -1
  147. package/.output/public/assets/ProxyViewerContainer-COBe5GTT.js +0 -4234
  148. package/.output/public/assets/ResponseView-Cqq87lX_.js +0 -3
  149. package/.output/public/assets/StreamingChunkSequence-CnTa9mCr.js +0 -1
  150. package/.output/public/assets/index-DTLNVcgc.js +0 -76
  151. package/.output/public/assets/index-DliqmwUw.css +0 -1
  152. package/.output/public/assets/qwen-CONDcHqt.png +0 -0
  153. package/.output/server/_tanstack-start-manifest_v-DMCA8KK3.mjs +0 -4
  154. package/src/assets/logos/mcp.png +0 -0
  155. package/src/assets/logos/qwen.png +0 -0
  156. package/src/components/ui/mcp-logo.tsx +0 -20
@@ -1,4 +1,5 @@
1
- import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
1
+ import assert from "node:assert/strict";
2
+ import { existsSync, readFileSync, writeFileSync } from "node:fs";
2
3
  import { join } from "node:path";
3
4
  import {
4
5
  type EvidenceExportOptions,
@@ -10,6 +11,11 @@ import { getDataDir } from "./dataDir";
10
11
  import { analyzeEvidence } from "./evidenceAnalysis";
11
12
  import { getSessionInfo } from "./store";
12
13
  import { updateRunEvidence } from "./runStore";
14
+ import {
15
+ ensurePrivateDirectorySync,
16
+ PRIVATE_FILE_MODE,
17
+ securePrivateFileSync,
18
+ } from "./privateDataPath";
13
19
 
14
20
  type EvidenceDocument = EvidenceExportResult;
15
21
 
@@ -197,14 +203,22 @@ export async function exportRunEvidence(
197
203
  };
198
204
  const markdown = buildMarkdown(document);
199
205
 
200
- mkdirSync(evidenceDir(run.id), { recursive: true });
201
- writeFileSync(
202
- evidence.jsonPath,
203
- `${JSON.stringify({ ...document, evidence }, null, 2)}\n`,
204
- "utf8",
205
- );
206
- writeFileSync(evidence.markdownPath, markdown, "utf8");
207
- writeFileSync(evidence.htmlPath, buildHtml(markdown, run.title), "utf8");
206
+ assert(ensurePrivateDirectorySync(evidenceDir(run.id)), "Could not secure evidence directory");
207
+ writeFileSync(evidence.jsonPath, `${JSON.stringify({ ...document, evidence }, null, 2)}\n`, {
208
+ encoding: "utf8",
209
+ mode: PRIVATE_FILE_MODE,
210
+ });
211
+ writeFileSync(evidence.markdownPath, markdown, {
212
+ encoding: "utf8",
213
+ mode: PRIVATE_FILE_MODE,
214
+ });
215
+ writeFileSync(evidence.htmlPath, buildHtml(markdown, run.title), {
216
+ encoding: "utf8",
217
+ mode: PRIVATE_FILE_MODE,
218
+ });
219
+ for (const path of [evidence.jsonPath, evidence.markdownPath, evidence.htmlPath]) {
220
+ assert(securePrivateFileSync(path), `Could not secure evidence file ${path}`);
221
+ }
208
222
 
209
223
  const updatedRun = updateRunEvidence(run.id, evidence) ?? documentRun;
210
224
  return { ...document, run: updatedRun };
@@ -1,4 +1,5 @@
1
- import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
1
+ import assert from "node:assert/strict";
2
+ import { existsSync, readFileSync, writeFileSync } from "node:fs";
2
3
  import { join } from "node:path";
3
4
  import {
4
5
  GroupEvidenceExportResultSchema,
@@ -16,6 +17,11 @@ import { getRun } from "./runStore";
16
17
  import { getSessionInfo } from "./store";
17
18
  import { updateGroupEvidence } from "./groupStore";
18
19
  import { readJsonFile } from "../lib/jsonFile";
20
+ import {
21
+ ensurePrivateDirectorySync,
22
+ PRIVATE_FILE_MODE,
23
+ securePrivateFileSync,
24
+ } from "./privateDataPath";
19
25
 
20
26
  type GroupEvidenceDocument = GroupEvidenceExportResult;
21
27
 
@@ -323,10 +329,25 @@ export async function exportGroupEvidence(
323
329
  };
324
330
  const markdown = buildMarkdown(document);
325
331
 
326
- mkdirSync(groupEvidenceDir(group.id), { recursive: true });
327
- writeFileSync(evidence.jsonPath, `${JSON.stringify(document, null, 2)}\n`, "utf8");
328
- writeFileSync(evidence.markdownPath, markdown, "utf8");
329
- writeFileSync(evidence.htmlPath, buildHtml(markdown, group.title), "utf8");
332
+ assert(
333
+ ensurePrivateDirectorySync(groupEvidenceDir(group.id)),
334
+ "Could not secure group evidence directory",
335
+ );
336
+ writeFileSync(evidence.jsonPath, `${JSON.stringify(document, null, 2)}\n`, {
337
+ encoding: "utf8",
338
+ mode: PRIVATE_FILE_MODE,
339
+ });
340
+ writeFileSync(evidence.markdownPath, markdown, {
341
+ encoding: "utf8",
342
+ mode: PRIVATE_FILE_MODE,
343
+ });
344
+ writeFileSync(evidence.htmlPath, buildHtml(markdown, group.title), {
345
+ encoding: "utf8",
346
+ mode: PRIVATE_FILE_MODE,
347
+ });
348
+ for (const path of [evidence.jsonPath, evidence.markdownPath, evidence.htmlPath]) {
349
+ assert(securePrivateFileSync(path), `Could not secure group evidence file ${path}`);
350
+ }
330
351
 
331
352
  const updatedGroup = updateGroupEvidence(group.id, evidence) ?? documentGroup;
332
353
  return { ...document, group: updatedGroup };
@@ -1,5 +1,6 @@
1
+ import assert from "node:assert/strict";
1
2
  import { randomUUID } from "node:crypto";
2
- import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
3
+ import { existsSync, readFileSync, rmSync, writeFileSync } from "node:fs";
3
4
  import { dirname, isAbsolute, join, relative, resolve } from "node:path";
4
5
  import { z } from "zod";
5
6
  import {
@@ -20,6 +21,11 @@ import {
20
21
  } from "../lib/groupContract";
21
22
  import { getDataDir } from "./dataDir";
22
23
  import { readJsonFile } from "../lib/jsonFile";
24
+ import {
25
+ ensurePrivateDirectorySync,
26
+ PRIVATE_FILE_MODE,
27
+ securePrivateFileSync,
28
+ } from "./privateDataPath";
23
29
 
24
30
  const GroupsFileSchema = z.object({
25
31
  groups: z.array(InspectorGroupSchema),
@@ -77,8 +83,12 @@ function readGroups(): InspectorGroup[] {
77
83
 
78
84
  function writeGroups(groups: readonly InspectorGroup[]): void {
79
85
  const filePath = groupsFilePath();
80
- mkdirSync(dirname(filePath), { recursive: true });
81
- writeFileSync(filePath, `${JSON.stringify({ groups }, null, 2)}\n`, "utf8");
86
+ assert(ensurePrivateDirectorySync(dirname(filePath)), "Could not secure groups directory");
87
+ writeFileSync(filePath, `${JSON.stringify({ groups }, null, 2)}\n`, {
88
+ encoding: "utf8",
89
+ mode: PRIVATE_FILE_MODE,
90
+ });
91
+ assert(securePrivateFileSync(filePath), "Could not secure groups file");
82
92
  }
83
93
 
84
94
  function sortedGroups(groups: readonly InspectorGroup[]): InspectorGroup[] {
@@ -31,6 +31,7 @@ import { maskApiKey } from "../lib/mask";
31
31
  import { buildFileLogEntry, type FinalizeLogJob } from "./logFinalizer";
32
32
  import { enqueueFinalizeLogJob } from "./sessionRuntime";
33
33
  import { RawStreamCapture } from "./rawStreamCapture";
34
+ import { acquireRuntimeRequest, type RuntimeRequestLease } from "./runtimeAdmission";
34
35
  import {
35
36
  buildUpstreamUrl,
36
37
  describeApiRoute,
@@ -202,35 +203,56 @@ function handleStreamingResponse(
202
203
 
203
204
  const totalStreamMs = Date.now() - startTime;
204
205
  const elapsedMs = totalStreamMs;
205
- const rawStream = capture.snapshot();
206
- switch (type) {
207
- case "streaming":
208
- scheduleLogFinalization({
209
- type: "streaming",
210
- log,
211
- upstreamUrl,
212
- elapsedMs,
213
- responseStatus: upstreamRes.status,
214
- rawStream,
215
- collectStreamingChunks,
216
- firstChunkMs,
217
- totalStreamMs,
218
- });
219
- return;
220
- case "stream-abort":
206
+ void capture
207
+ .finalize()
208
+ .then((rawStream) => {
209
+ switch (type) {
210
+ case "streaming":
211
+ scheduleLogFinalization({
212
+ type: "streaming",
213
+ log,
214
+ upstreamUrl,
215
+ elapsedMs,
216
+ responseStatus: upstreamRes.status,
217
+ rawStream,
218
+ collectStreamingChunks,
219
+ firstChunkMs,
220
+ totalStreamMs,
221
+ });
222
+ return;
223
+ case "stream-abort":
224
+ scheduleLogFinalization({
225
+ type: "stream-abort",
226
+ log,
227
+ upstreamUrl,
228
+ elapsedMs,
229
+ rawStream,
230
+ hasChunks: capture.hasChunks,
231
+ collectStreamingChunks,
232
+ firstChunkMs,
233
+ totalStreamMs,
234
+ });
235
+ return;
236
+ }
237
+ })
238
+ .catch((error: unknown) => {
239
+ const message = error instanceof Error ? error.message : String(error);
240
+ logger.error(
241
+ `[handler] Raw stream finalization failed for log #${String(log.id)}:`,
242
+ message,
243
+ );
221
244
  scheduleLogFinalization({
222
245
  type: "stream-abort",
223
246
  log,
224
247
  upstreamUrl,
225
248
  elapsedMs,
226
- rawStream,
249
+ rawStream: { type: "memory", rawStream: "" },
227
250
  hasChunks: capture.hasChunks,
228
251
  collectStreamingChunks,
229
252
  firstChunkMs,
230
253
  totalStreamMs,
231
254
  });
232
- return;
233
- }
255
+ });
234
256
  };
235
257
 
236
258
  const transform = new TransformStream<Uint8Array, Uint8Array>({
@@ -278,7 +300,7 @@ function handleStreamingResponse(
278
300
  });
279
301
  }
280
302
 
281
- export async function handleProxy(req: Request): Promise<Response> {
303
+ async function handleAdmittedProxy(req: Request): Promise<Response> {
282
304
  const url = new URL(req.url);
283
305
  const parsed = parseRequestPath(req, url);
284
306
 
@@ -457,3 +479,64 @@ export async function handleProxy(req: Request): Promise<Response> {
457
479
 
458
480
  return handleStreamingResponse(upstreamRes, req, startTime, upstreamUrl, log, captureFullDetails);
459
481
  }
482
+
483
+ function responseWithRuntimeLease(response: Response, lease: RuntimeRequestLease): Response {
484
+ if (response.body === null) {
485
+ lease.release();
486
+ return response;
487
+ }
488
+
489
+ const reader = response.body.getReader();
490
+ let released = false;
491
+ const release = (): void => {
492
+ if (released) return;
493
+ released = true;
494
+ lease.release();
495
+ };
496
+ const trackedBody = new ReadableStream<Uint8Array>({
497
+ async pull(controller) {
498
+ try {
499
+ const chunk = await reader.read();
500
+ if (chunk.done) {
501
+ controller.close();
502
+ release();
503
+ return;
504
+ }
505
+ controller.enqueue(chunk.value);
506
+ } catch (error) {
507
+ controller.error(error);
508
+ release();
509
+ }
510
+ },
511
+ async cancel(reason) {
512
+ try {
513
+ await reader.cancel(reason);
514
+ } finally {
515
+ release();
516
+ }
517
+ },
518
+ });
519
+
520
+ return new Response(trackedBody, {
521
+ status: response.status,
522
+ statusText: response.statusText,
523
+ headers: response.headers,
524
+ });
525
+ }
526
+
527
+ export async function handleProxy(req: Request): Promise<Response> {
528
+ const lease = acquireRuntimeRequest();
529
+ if (lease === null) {
530
+ return Response.json(
531
+ { error: "Agent Inspector is shutting down" },
532
+ { status: 503, headers: { "cache-control": "no-store", "retry-after": "5" } },
533
+ );
534
+ }
535
+
536
+ try {
537
+ return responseWithRuntimeLease(await handleAdmittedProxy(req), lease);
538
+ } catch (error) {
539
+ lease.release();
540
+ return await Promise.reject(error);
541
+ }
542
+ }