@tonyclaw/agent-inspector 3.1.32 → 4.0.2

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 (373) hide show
  1. package/.output/backend/nitro.json +1 -1
  2. package/.output/cli.js +241 -120
  3. package/.output/server/_ssr/index.mjs +1 -1
  4. package/.output/server/_ssr/{router-oXUk3MBR.mjs → router-BBY_zWRK.mjs} +91 -3
  5. package/.output/server/index.mjs +1 -1
  6. package/.output/ui/assets/{CompareDrawer-BtfPSpkV.js → CompareDrawer-rtNElN-B.js} +1 -1
  7. package/.output/ui/assets/{InspectorPet-D9DPPQ3n.js → InspectorPet-QaAiuF3d.js} +1 -1
  8. package/.output/ui/assets/{ProxyViewerContainer-Buu8vkCK.js → ProxyViewerContainer-6twNZHwl.js} +4 -4
  9. package/.output/ui/assets/{ReplayDialog-BER-QzpD.js → ReplayDialog-B7KlziO2.js} +1 -1
  10. package/.output/ui/assets/{RequestAnatomy-C8Zwxrr7.js → RequestAnatomy-2XVFBrW4.js} +1 -1
  11. package/.output/ui/assets/{ResponseView-DDpKdYk6.js → ResponseView-BULgzLVB.js} +1 -1
  12. package/.output/ui/assets/{StreamingChunkSequence-sMPGG7Sw.js → StreamingChunkSequence-DSkvkbns.js} +1 -1
  13. package/.output/ui/assets/{_sessionId-e4IheHnP.js → _sessionId-D2dmJi3G.js} +1 -1
  14. package/.output/ui/assets/{_sessionId-C5Uv72Fx.js → _sessionId-DcS0s1Mr.js} +1 -1
  15. package/.output/ui/assets/{index-B__qT0Yd.js → index-B0TN1KKO.js} +2 -2
  16. package/.output/ui/assets/{index-Be3bTCzi.js → index-Bva1zHEs.js} +1 -1
  17. package/.output/ui/assets/{index-C9q__p8J.js → index-BzBExOxu.js} +1 -1
  18. package/.output/ui/assets/{index-CtB0deSZ.js → index-k6sRQz55.js} +1 -1
  19. package/.output/ui/assets/{json-viewer-Db0AFp-7.js → json-viewer-CWM4tY-j.js} +1 -1
  20. package/.output/ui/assets/{jszip.min-DkY0Ym_q.js → jszip.min-BkWvRFlo.js} +1 -1
  21. package/.output/ui/index.html +1 -1
  22. package/package.json +8 -13
  23. package/src/assets/IDE/claudecode-color.svg +0 -1
  24. package/src/assets/IDE/codex-color.svg +0 -1
  25. package/src/assets/IDE/opencode.svg +0 -1
  26. package/src/assets/IDE/xiaomimimo.svg +0 -1
  27. package/src/assets/favicon.svg +0 -21
  28. package/src/assets/logos/alibaba.svg +0 -1
  29. package/src/assets/logos/anthropic.svg +0 -1
  30. package/src/assets/logos/claude-code.svg +0 -4
  31. package/src/assets/logos/deepseek.svg +0 -1
  32. package/src/assets/logos/minimax.jpeg +0 -0
  33. package/src/assets/logos/openai.svg +0 -1
  34. package/src/assets/logos/opencode.svg +0 -4
  35. package/src/assets/logos/qwen.webp +0 -0
  36. package/src/assets/logos/zhipuai.svg +0 -219
  37. package/src/backend/router.tsx +0 -36
  38. package/src/backend/routes/$.ts +0 -26
  39. package/src/backend/routes/__root.ts +0 -4
  40. package/src/backend/routes/api/-instances.ts +0 -7
  41. package/src/backend/routes/api/alerts.summary.ts +0 -28
  42. package/src/backend/routes/api/alerts.ts +0 -70
  43. package/src/backend/routes/api/config.paths.ts +0 -14
  44. package/src/backend/routes/api/config.ts +0 -73
  45. package/src/backend/routes/api/ecosystem.packages.$packageId.help.ts +0 -11
  46. package/src/backend/routes/api/ecosystem.packages.$packageId.install.ts +0 -11
  47. package/src/backend/routes/api/ecosystem.packages.$packageId.runner-presets.ts +0 -11
  48. package/src/backend/routes/api/ecosystem.packages.$packageId.upgrade.ts +0 -11
  49. package/src/backend/routes/api/ecosystem.packages.ts +0 -21
  50. package/src/backend/routes/api/ecosystem.recipes.$recipeId.run.ts +0 -11
  51. package/src/backend/routes/api/ecosystem.tasks.$taskId.ts +0 -16
  52. package/src/backend/routes/api/ecosystem.tasks.ts +0 -12
  53. package/src/backend/routes/api/groups.$groupId.evidence.ts +0 -55
  54. package/src/backend/routes/api/groups.$groupId.sessions.ts +0 -50
  55. package/src/backend/routes/api/groups.$groupId.ts +0 -93
  56. package/src/backend/routes/api/groups.ts +0 -79
  57. package/src/backend/routes/api/health.ts +0 -22
  58. package/src/backend/routes/api/instances.$name.connection.ts +0 -12
  59. package/src/backend/routes/api/instances.$name.restart.ts +0 -23
  60. package/src/backend/routes/api/instances.$name.start.ts +0 -18
  61. package/src/backend/routes/api/instances.$name.stop.ts +0 -23
  62. package/src/backend/routes/api/instances.$name.ts +0 -12
  63. package/src/backend/routes/api/instances.ts +0 -16
  64. package/src/backend/routes/api/knowledge.candidates.$candidateId.promote.ts +0 -32
  65. package/src/backend/routes/api/knowledge.candidates.$candidateId.ts +0 -50
  66. package/src/backend/routes/api/knowledge.candidates.ts +0 -10
  67. package/src/backend/routes/api/knowledge.project-context.ts +0 -29
  68. package/src/backend/routes/api/knowledge.search.ts +0 -62
  69. package/src/backend/routes/api/knowledge.sessions.$sessionId.candidates.ts +0 -26
  70. package/src/backend/routes/api/logs.$id.body.ts +0 -58
  71. package/src/backend/routes/api/logs.$id.chunks.ts +0 -37
  72. package/src/backend/routes/api/logs.$id.replay.ts +0 -297
  73. package/src/backend/routes/api/logs.$id.ts +0 -23
  74. package/src/backend/routes/api/logs.import.ts +0 -39
  75. package/src/backend/routes/api/logs.stream.ts +0 -174
  76. package/src/backend/routes/api/logs.ts +0 -214
  77. package/src/backend/routes/api/mcp.ts +0 -25
  78. package/src/backend/routes/api/models.ts +0 -10
  79. package/src/backend/routes/api/pi-agent.ts +0 -29
  80. package/src/backend/routes/api/providers.$providerId.model-metadata.ts +0 -173
  81. package/src/backend/routes/api/providers.$providerId.test.log.ts +0 -342
  82. package/src/backend/routes/api/providers.$providerId.ts +0 -111
  83. package/src/backend/routes/api/providers.export.ts +0 -44
  84. package/src/backend/routes/api/providers.import.ts +0 -81
  85. package/src/backend/routes/api/providers.scan.ts +0 -28
  86. package/src/backend/routes/api/providers.ts +0 -102
  87. package/src/backend/routes/api/runs.$runId.evidence.ts +0 -55
  88. package/src/backend/routes/api/runs.$runId.ts +0 -50
  89. package/src/backend/routes/api/runs.ts +0 -62
  90. package/src/backend/routes/api/runtime.ts +0 -46
  91. package/src/backend/routes/api/sessions.ts +0 -51
  92. package/src/backend/routes/api/storage.ts +0 -56
  93. package/src/backend/routes/livez.ts +0 -13
  94. package/src/backend/routes/metrics.ts +0 -14
  95. package/src/backend/routes/proxy/$.ts +0 -15
  96. package/src/backend/routes/readyz.ts +0 -18
  97. package/src/backend/start.ts +0 -10
  98. package/src/cli/alias.ts +0 -431
  99. package/src/cli/detect-tools.ts +0 -123
  100. package/src/cli/doctor.ts +0 -836
  101. package/src/cli/instance.ts +0 -1071
  102. package/src/cli/instanceApi.ts +0 -213
  103. package/src/cli/instanceArgs.ts +0 -301
  104. package/src/cli/instanceControl.ts +0 -191
  105. package/src/cli/instanceModel.ts +0 -276
  106. package/src/cli/instanceRegistry.ts +0 -731
  107. package/src/cli/networkHints.ts +0 -170
  108. package/src/cli/onboard.ts +0 -1668
  109. package/src/cli/onboardTarget.ts +0 -228
  110. package/src/cli/rustBackendPackage.ts +0 -458
  111. package/src/cli/startupOutput.ts +0 -16
  112. package/src/cli/templates/codex-skill-onboard.ts +0 -320
  113. package/src/cli/templates/command-onboard.ts +0 -25
  114. package/src/cli/templates/skill-onboard.ts +0 -625
  115. package/src/cli.ts +0 -1397
  116. package/src/components/OnboardingBanner.tsx +0 -115
  117. package/src/components/ProxyViewer.tsx +0 -2259
  118. package/src/components/ProxyViewerContainer.tsx +0 -1076
  119. package/src/components/alerts/AlertsDialog.tsx +0 -615
  120. package/src/components/clients/ClientLogo.tsx +0 -175
  121. package/src/components/ecosystem/AgentLabDialog.tsx +0 -947
  122. package/src/components/errors/SafeErrorBoundary.tsx +0 -201
  123. package/src/components/groups/GroupsDialog.tsx +0 -1304
  124. package/src/components/inspector-pet/InspectorPet.tsx +0 -398
  125. package/src/components/inspector-pet/InspectorPetCrab3D.tsx +0 -455
  126. package/src/components/inspector-pet/inspectorPetLogic.ts +0 -272
  127. package/src/components/pi-agent/PiAgentPanel.tsx +0 -446
  128. package/src/components/pi-agent/piAgentChatLogic.ts +0 -273
  129. package/src/components/providers/ImportWizardDialog.tsx +0 -281
  130. package/src/components/providers/ProviderCard.tsx +0 -347
  131. package/src/components/providers/ProviderForm.tsx +0 -1183
  132. package/src/components/providers/ProviderLogo.tsx +0 -122
  133. package/src/components/providers/ProviderTestResultsView.tsx +0 -734
  134. package/src/components/providers/ProvidersPanel.tsx +0 -714
  135. package/src/components/providers/SettingsDialog.tsx +0 -1042
  136. package/src/components/providers/providerFormCapabilities.ts +0 -36
  137. package/src/components/proxy-viewer/AgentTraceSummary.tsx +0 -902
  138. package/src/components/proxy-viewer/AnswerMarkdown.tsx +0 -51
  139. package/src/components/proxy-viewer/ApplicationBar.tsx +0 -123
  140. package/src/components/proxy-viewer/CompareDrawer.tsx +0 -984
  141. package/src/components/proxy-viewer/ConversationGroup.tsx +0 -208
  142. package/src/components/proxy-viewer/ConversationGroupList.tsx +0 -652
  143. package/src/components/proxy-viewer/ConversationHeader.tsx +0 -429
  144. package/src/components/proxy-viewer/LiveConnectionStatus.tsx +0 -186
  145. package/src/components/proxy-viewer/LogEntry.tsx +0 -1419
  146. package/src/components/proxy-viewer/LogEntryHeader.tsx +0 -596
  147. package/src/components/proxy-viewer/ProviderLogoStack.tsx +0 -57
  148. package/src/components/proxy-viewer/RawExportWarning.tsx +0 -77
  149. package/src/components/proxy-viewer/ReplayDialog.tsx +0 -636
  150. package/src/components/proxy-viewer/RequestToolsPanel.tsx +0 -299
  151. package/src/components/proxy-viewer/ResponseView.tsx +0 -202
  152. package/src/components/proxy-viewer/SessionLoadProgressBar.tsx +0 -61
  153. package/src/components/proxy-viewer/StreamingChunkSequence.tsx +0 -265
  154. package/src/components/proxy-viewer/ThreadConnector.tsx +0 -165
  155. package/src/components/proxy-viewer/ToolTraceEvents.tsx +0 -64
  156. package/src/components/proxy-viewer/TurnGroup.tsx +0 -383
  157. package/src/components/proxy-viewer/TurnGroupList.tsx +0 -156
  158. package/src/components/proxy-viewer/accessibility.ts +0 -8
  159. package/src/components/proxy-viewer/anatomy/RequestAnatomy.tsx +0 -887
  160. package/src/components/proxy-viewer/anatomy/SegmentBar.tsx +0 -222
  161. package/src/components/proxy-viewer/anatomy/contextIntelligence.ts +0 -737
  162. package/src/components/proxy-viewer/anatomy/sessionContextSummary.ts +0 -268
  163. package/src/components/proxy-viewer/anatomy/tokenEstimate.ts +0 -53
  164. package/src/components/proxy-viewer/anatomy/types.ts +0 -41
  165. package/src/components/proxy-viewer/anatomy/useAnatomyJump.ts +0 -114
  166. package/src/components/proxy-viewer/bodyHydration.ts +0 -123
  167. package/src/components/proxy-viewer/cacheTrend.ts +0 -50
  168. package/src/components/proxy-viewer/diff/DiffView.tsx +0 -321
  169. package/src/components/proxy-viewer/diff/computeDiff.ts +0 -178
  170. package/src/components/proxy-viewer/diff/index.ts +0 -3
  171. package/src/components/proxy-viewer/formats/anthropic/ContentBlocks.tsx +0 -194
  172. package/src/components/proxy-viewer/formats/anthropic/ResponseView.tsx +0 -81
  173. package/src/components/proxy-viewer/formats/anthropic/thinkingExtract.ts +0 -21
  174. package/src/components/proxy-viewer/formats/index.tsx +0 -47
  175. package/src/components/proxy-viewer/formats/openai/ResponseView.tsx +0 -442
  176. package/src/components/proxy-viewer/index.ts +0 -9
  177. package/src/components/proxy-viewer/lazy.ts +0 -41
  178. package/src/components/proxy-viewer/liveConnectionState.ts +0 -158
  179. package/src/components/proxy-viewer/log-formats/anthropic.ts +0 -191
  180. package/src/components/proxy-viewer/log-formats/index.ts +0 -23
  181. package/src/components/proxy-viewer/log-formats/openai.ts +0 -256
  182. package/src/components/proxy-viewer/log-formats/types.ts +0 -40
  183. package/src/components/proxy-viewer/log-formats/unknown.ts +0 -18
  184. package/src/components/proxy-viewer/logEntryVisibility.ts +0 -73
  185. package/src/components/proxy-viewer/logFocus.ts +0 -54
  186. package/src/components/proxy-viewer/proxyViewerContainerLogic.ts +0 -124
  187. package/src/components/proxy-viewer/proxyViewerLogic.ts +0 -488
  188. package/src/components/proxy-viewer/replayComparison.ts +0 -131
  189. package/src/components/proxy-viewer/requestDiff.ts +0 -277
  190. package/src/components/proxy-viewer/requestTools.ts +0 -220
  191. package/src/components/proxy-viewer/useCopyFeedback.ts +0 -38
  192. package/src/components/proxy-viewer/useKeyboardNavigation.ts +0 -232
  193. package/src/components/proxy-viewer/viewerState.ts +0 -176
  194. package/src/components/ui/badge.tsx +0 -47
  195. package/src/components/ui/button.tsx +0 -47
  196. package/src/components/ui/collapsible.tsx +0 -21
  197. package/src/components/ui/confirm-dialog.tsx +0 -51
  198. package/src/components/ui/crab-logo.tsx +0 -45
  199. package/src/components/ui/crab-variants.tsx +0 -467
  200. package/src/components/ui/dialog.tsx +0 -130
  201. package/src/components/ui/icon-trigger.ts +0 -2
  202. package/src/components/ui/json-viewer-bulk.ts +0 -132
  203. package/src/components/ui/json-viewer.tsx +0 -508
  204. package/src/components/ui/scroll-area.tsx +0 -54
  205. package/src/components/ui/select.tsx +0 -178
  206. package/src/components/ui/separator.tsx +0 -28
  207. package/src/components/ui/tabs.tsx +0 -88
  208. package/src/components/ui/tooltip.tsx +0 -51
  209. package/src/components/ui/transient-toast.tsx +0 -105
  210. package/src/contracts/anthropic.ts +0 -230
  211. package/src/contracts/index.ts +0 -59
  212. package/src/contracts/json.ts +0 -37
  213. package/src/contracts/log.ts +0 -139
  214. package/src/contracts/openai.ts +0 -267
  215. package/src/index.css +0 -11
  216. package/src/knowledge/candidateStore.ts +0 -94
  217. package/src/knowledge/distiller.ts +0 -98
  218. package/src/knowledge/openclawClient.ts +0 -161
  219. package/src/knowledge/openclawGatewayClient.ts +0 -249
  220. package/src/knowledge/openclawMarkdown.ts +0 -146
  221. package/src/knowledge/redactor.ts +0 -80
  222. package/src/knowledge/types.ts +0 -83
  223. package/src/lib/alertContract.ts +0 -76
  224. package/src/lib/apiClient.ts +0 -166
  225. package/src/lib/apiFormat.ts +0 -29
  226. package/src/lib/backendImplementation.ts +0 -16
  227. package/src/lib/basePath.ts +0 -107
  228. package/src/lib/browserRuntimeContract.ts +0 -124
  229. package/src/lib/browserRuntimeResolver.ts +0 -333
  230. package/src/lib/chunkLoadRecovery.ts +0 -83
  231. package/src/lib/claudeCodeStrip.ts +0 -98
  232. package/src/lib/clipboard.ts +0 -67
  233. package/src/lib/codingAgentEndpoints.ts +0 -54
  234. package/src/lib/ecosystemContract.ts +0 -130
  235. package/src/lib/export-logs.ts +0 -287
  236. package/src/lib/groupContract.ts +0 -166
  237. package/src/lib/instanceContract.ts +0 -239
  238. package/src/lib/jsonFile.ts +0 -46
  239. package/src/lib/logImportContract.ts +0 -12
  240. package/src/lib/managedInstance.ts +0 -112
  241. package/src/lib/mask.ts +0 -4
  242. package/src/lib/objectUtils.ts +0 -22
  243. package/src/lib/piAgentContract.ts +0 -102
  244. package/src/lib/providerContract.ts +0 -125
  245. package/src/lib/providerImportContract.ts +0 -27
  246. package/src/lib/providerModelMetadata.ts +0 -458
  247. package/src/lib/providerTestContract.ts +0 -170
  248. package/src/lib/providerTestPrompt.ts +0 -100
  249. package/src/lib/publicBasePathContext.ts +0 -137
  250. package/src/lib/resourceLimits.ts +0 -345
  251. package/src/lib/runContract.ts +0 -164
  252. package/src/lib/runtimeConfig.ts +0 -43
  253. package/src/lib/safeDiagnostic.ts +0 -38
  254. package/src/lib/safeFetch.ts +0 -508
  255. package/src/lib/serverPort.ts +0 -47
  256. package/src/lib/sessionInfoContract.ts +0 -78
  257. package/src/lib/sessionUrl.ts +0 -46
  258. package/src/lib/ssrfGuard.ts +0 -133
  259. package/src/lib/stopReason.ts +0 -130
  260. package/src/lib/themeMode.ts +0 -41
  261. package/src/lib/timeDisplay.ts +0 -22
  262. package/src/lib/toolTrace.ts +0 -290
  263. package/src/lib/uiScale.ts +0 -117
  264. package/src/lib/unknown.ts +0 -27
  265. package/src/lib/upstreamUrl.ts +0 -150
  266. package/src/lib/useAlerts.ts +0 -82
  267. package/src/lib/useGroupEvidence.ts +0 -37
  268. package/src/lib/useGroups.ts +0 -32
  269. package/src/lib/useOnboarding.ts +0 -93
  270. package/src/lib/useProviders.ts +0 -30
  271. package/src/lib/useStripConfig.ts +0 -154
  272. package/src/lib/useThemeMode.ts +0 -40
  273. package/src/lib/useUiScale.ts +0 -52
  274. package/src/lib/utils.ts +0 -78
  275. package/src/mcp/currentContext.ts +0 -65
  276. package/src/mcp/instanceHandlers.ts +0 -151
  277. package/src/mcp/loopback.ts +0 -88
  278. package/src/mcp/mode.ts +0 -75
  279. package/src/mcp/previewExtractor.ts +0 -233
  280. package/src/mcp/server.ts +0 -2274
  281. package/src/mcp/toolHandlers.ts +0 -1533
  282. package/src/proxy/alerts.ts +0 -664
  283. package/src/proxy/chunkStorage.ts +0 -123
  284. package/src/proxy/config.ts +0 -218
  285. package/src/proxy/constants.ts +0 -66
  286. package/src/proxy/dataDir.ts +0 -147
  287. package/src/proxy/ecosystemExecutionConfirmation.ts +0 -114
  288. package/src/proxy/ecosystemExecutionRoute.ts +0 -116
  289. package/src/proxy/ecosystemRegistry.ts +0 -296
  290. package/src/proxy/ecosystemTasks.ts +0 -415
  291. package/src/proxy/evidenceAnalysis.ts +0 -526
  292. package/src/proxy/evidenceExporter.ts +0 -235
  293. package/src/proxy/formats/anthropic/anthropicProvider.ts +0 -75
  294. package/src/proxy/formats/anthropic/handler.ts +0 -75
  295. package/src/proxy/formats/anthropic/index.ts +0 -13
  296. package/src/proxy/formats/anthropic/register.ts +0 -4
  297. package/src/proxy/formats/anthropic/schemas.ts +0 -6
  298. package/src/proxy/formats/anthropic/stream.ts +0 -205
  299. package/src/proxy/formats/handler.ts +0 -46
  300. package/src/proxy/formats/index.ts +0 -13
  301. package/src/proxy/formats/jsonSchema.ts +0 -2
  302. package/src/proxy/formats/openai/alibabaProvider.ts +0 -34
  303. package/src/proxy/formats/openai/codexMetadata.ts +0 -61
  304. package/src/proxy/formats/openai/handler.ts +0 -133
  305. package/src/proxy/formats/openai/index.ts +0 -33
  306. package/src/proxy/formats/openai/provider.ts +0 -50
  307. package/src/proxy/formats/openai/register.ts +0 -4
  308. package/src/proxy/formats/openai/schemas.ts +0 -25
  309. package/src/proxy/formats/openai/stream.ts +0 -600
  310. package/src/proxy/formats/openai/zhipuProvider.ts +0 -31
  311. package/src/proxy/formats/providerAdapter.ts +0 -50
  312. package/src/proxy/formats/providerRegistry.ts +0 -51
  313. package/src/proxy/formats/providers/index.ts +0 -3
  314. package/src/proxy/formats/registry.ts +0 -65
  315. package/src/proxy/groupEvidenceExporter.ts +0 -371
  316. package/src/proxy/groupStore.ts +0 -336
  317. package/src/proxy/handler.ts +0 -729
  318. package/src/proxy/identityProxy.ts +0 -1842
  319. package/src/proxy/jsonlRecovery.ts +0 -554
  320. package/src/proxy/logBodyChunks.ts +0 -91
  321. package/src/proxy/logFinalizer.ts +0 -777
  322. package/src/proxy/logFinalizer.worker.ts +0 -24
  323. package/src/proxy/logImportUpload.ts +0 -128
  324. package/src/proxy/logImporter.ts +0 -813
  325. package/src/proxy/logIndex.ts +0 -663
  326. package/src/proxy/logSearch.ts +0 -122
  327. package/src/proxy/logger.ts +0 -537
  328. package/src/proxy/openaiOrphanToolStrip.ts +0 -142
  329. package/src/proxy/platformCommands.ts +0 -253
  330. package/src/proxy/privateDataPath.ts +0 -419
  331. package/src/proxy/providerImporters.ts +0 -578
  332. package/src/proxy/providerScanStore.ts +0 -87
  333. package/src/proxy/providerSecretStore.ts +0 -216
  334. package/src/proxy/providers.ts +0 -998
  335. package/src/proxy/rawStreamCapture.ts +0 -342
  336. package/src/proxy/runFailures.ts +0 -94
  337. package/src/proxy/runStore.ts +0 -214
  338. package/src/proxy/runtimeAdmission.ts +0 -55
  339. package/src/proxy/runtimeHealth.ts +0 -221
  340. package/src/proxy/runtimeMetrics.ts +0 -149
  341. package/src/proxy/runtimeShutdown.ts +0 -157
  342. package/src/proxy/schemas.ts +0 -112
  343. package/src/proxy/sessionArchive.ts +0 -479
  344. package/src/proxy/sessionInfo.ts +0 -266
  345. package/src/proxy/sessionProcess.ts +0 -194
  346. package/src/proxy/sessionRuntime.ts +0 -121
  347. package/src/proxy/sessionSupervisor.ts +0 -305
  348. package/src/proxy/sessionWorkerEntry.ts +0 -26
  349. package/src/proxy/shutdownCoordinator.ts +0 -90
  350. package/src/proxy/socketTracker.ts +0 -639
  351. package/src/proxy/sqliteLogIndex.ts +0 -733
  352. package/src/proxy/storageLifecycle.ts +0 -432
  353. package/src/proxy/store.ts +0 -1773
  354. package/src/proxy/streamTiming.ts +0 -31
  355. package/src/proxy/toolSchemaWarnings.ts +0 -529
  356. package/src/proxy/uiAssetServer.ts +0 -106
  357. package/src/proxy/upstream.ts +0 -127
  358. package/src/services/alerts.ts +0 -12
  359. package/src/services/groups.ts +0 -119
  360. package/src/services/piAgent.ts +0 -421
  361. package/src/services/piAgentRetrieval.ts +0 -1180
  362. package/src/services/result.ts +0 -17
  363. package/src/services/runs.ts +0 -76
  364. package/src/ui/bootstrap.ts +0 -167
  365. package/src/ui/index.html +0 -38
  366. package/src/ui/logsStreamClient.ts +0 -20
  367. package/src/ui/main.tsx +0 -13
  368. package/src/ui/public/runtime-config.js +0 -2
  369. package/src/ui/router.tsx +0 -13
  370. package/src/ui/routes/__root.tsx +0 -69
  371. package/src/ui/routes/index.tsx +0 -35
  372. package/src/ui/routes/session/$sessionId.tsx +0 -50
  373. package/src/ui/runtimeDiscovery.ts +0 -50
package/src/cli/doctor.ts DELETED
@@ -1,836 +0,0 @@
1
- import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
2
- import { isAbsolute, join, resolve } from "node:path";
3
- import { createConnection } from "node:net";
4
- import { appendBasePathToOrigin, getConfiguredBasePath } from "../lib/basePath";
5
- import { migrateLegacyDataDirs, resolveDataDir } from "../proxy/dataDir";
6
-
7
- const DEFAULT_PORT = 9527;
8
- const PROBE_TIMEOUT_MS = 2000;
9
- const EXTENSION_REQUIRED_FILES = [
10
- "manifest.json",
11
- "sidepanel.html",
12
- "sidepanel.js",
13
- "sidepanel.css",
14
- "service-worker.js",
15
- "icons/icon.svg",
16
- "icons/icon-16.png",
17
- "icons/icon-32.png",
18
- "icons/icon-48.png",
19
- "icons/icon-128.png",
20
- ];
21
-
22
- export type DoctorSeverity = "pass" | "warn" | "fail";
23
-
24
- export type DoctorCheck = {
25
- name: string;
26
- severity: DoctorSeverity;
27
- message: string;
28
- hint: string | null;
29
- };
30
-
31
- export type DoctorOptions = {
32
- port: number;
33
- configDir: string | null;
34
- providersJson: string | null;
35
- chromeExtension: boolean;
36
- fix: boolean;
37
- json: boolean;
38
- supportBundle: boolean;
39
- verbose: boolean;
40
- help: boolean;
41
- };
42
-
43
- export type DoctorParseResult =
44
- | { kind: "ok"; options: DoctorOptions }
45
- | { kind: "error"; message: string };
46
-
47
- export type HealthProbe = {
48
- ok: boolean;
49
- status: number | null;
50
- };
51
-
52
- export type ReadinessProbe = {
53
- ok: boolean;
54
- status: number | null;
55
- body: unknown;
56
- };
57
-
58
- export type DoctorDeps = {
59
- env: Readonly<Record<string, string | undefined>>;
60
- platform: typeof process.platform;
61
- cwd: string;
62
- readText: (path: string) => string | null;
63
- exists: (path: string) => boolean;
64
- listDir: (path: string) => readonly string[] | null;
65
- stat: (path: string) => { isDirectory: boolean; size: number } | null;
66
- fetchHealth: (port: number, basePath: string) => Promise<HealthProbe>;
67
- fetchReadiness: (port: number, basePath: string) => Promise<ReadinessProbe>;
68
- isPortOpen: (port: number) => Promise<boolean>;
69
- };
70
-
71
- export type DoctorReport = {
72
- checks: readonly DoctorCheck[];
73
- readiness: ReadinessProbe | null;
74
- passCount: number;
75
- warnCount: number;
76
- failCount: number;
77
- exitCode: number;
78
- };
79
-
80
- export type DoctorSupportBundle = {
81
- schema: "agent-inspector.support-bundle/v1";
82
- createdAt: string;
83
- report: DoctorReport;
84
- environment: {
85
- platform: typeof process.platform;
86
- cwd: string;
87
- basePath: string;
88
- port: number;
89
- hasControlToken: boolean;
90
- hasProxyToken: boolean;
91
- hasProviderJsonOverride: boolean;
92
- };
93
- storage: readonly DoctorCheck[];
94
- };
95
-
96
- function check(name: string, severity: DoctorSeverity, message: string, hint = ""): DoctorCheck {
97
- return {
98
- name,
99
- severity,
100
- message,
101
- hint: hint === "" ? null : hint,
102
- };
103
- }
104
-
105
- function parsePort(raw: string | undefined): number | null {
106
- if (raw === undefined || raw.trim() === "") return null;
107
- const port = Number(raw);
108
- if (!Number.isInteger(port) || port <= 0 || port > 65535) return null;
109
- return port;
110
- }
111
-
112
- export function parseDoctorArgs(
113
- argv: readonly string[],
114
- env: Readonly<Record<string, string | undefined>> = process.env,
115
- ): DoctorParseResult {
116
- const envPort = parsePort(env["PORT"]);
117
- const options: DoctorOptions = {
118
- port: envPort ?? DEFAULT_PORT,
119
- configDir: null,
120
- providersJson: null,
121
- chromeExtension: false,
122
- fix: false,
123
- json: false,
124
- supportBundle: false,
125
- verbose: false,
126
- help: false,
127
- };
128
-
129
- for (let i = 0; i < argv.length; i++) {
130
- const arg = argv[i];
131
- switch (arg) {
132
- case undefined:
133
- continue;
134
- case "--help":
135
- case "-h":
136
- options.help = true;
137
- break;
138
- case "--port":
139
- case "-p": {
140
- const parsed = parsePort(argv[i + 1]);
141
- if (parsed === null) {
142
- return { kind: "error", message: "doctor: --port must be an integer from 1 to 65535" };
143
- }
144
- options.port = parsed;
145
- i++;
146
- break;
147
- }
148
- case "--config-dir": {
149
- const next = argv[i + 1];
150
- if (next === undefined || next.trim() === "") {
151
- return { kind: "error", message: "doctor: --config-dir requires a path argument" };
152
- }
153
- options.configDir = next;
154
- i++;
155
- break;
156
- }
157
- case "--providers": {
158
- const next = argv[i + 1];
159
- if (next === undefined || next.trim() === "") {
160
- return { kind: "error", message: "doctor: --providers requires a JSON argument" };
161
- }
162
- options.providersJson = next;
163
- i++;
164
- break;
165
- }
166
- case "--chrome-extension":
167
- options.chromeExtension = true;
168
- break;
169
- case "--fix":
170
- options.fix = true;
171
- break;
172
- case "--json":
173
- options.json = true;
174
- break;
175
- case "--support-bundle":
176
- options.supportBundle = true;
177
- options.json = true;
178
- break;
179
- case "--verbose":
180
- options.verbose = true;
181
- break;
182
- default:
183
- return { kind: "error", message: `doctor: unknown option ${arg}` };
184
- }
185
- }
186
-
187
- return { kind: "ok", options };
188
- }
189
-
190
- function isObject(value: unknown): value is Record<string, unknown> {
191
- return typeof value === "object" && value !== null && !Array.isArray(value);
192
- }
193
-
194
- function providerCountFromParsed(value: unknown): number | null {
195
- if (Array.isArray(value)) return value.length;
196
- if (isObject(value)) {
197
- const providers = value["providers"];
198
- if (Array.isArray(providers)) return providers.length;
199
- }
200
- return null;
201
- }
202
-
203
- function providerCountFromJson(raw: string): "invalid" | number | null {
204
- try {
205
- const parsed: unknown = JSON.parse(raw);
206
- return providerCountFromParsed(parsed);
207
- } catch {
208
- return "invalid";
209
- }
210
- }
211
-
212
- function resolveMaybeRelative(base: string, value: string): string {
213
- return isAbsolute(value) ? value : resolve(base, value);
214
- }
215
-
216
- function resolveDefaultDataDir(
217
- env: Readonly<Record<string, string | undefined>>,
218
- platform: typeof process.platform,
219
- exists: (path: string) => boolean,
220
- ): string {
221
- return resolveDataDir(exists, env, platform);
222
- }
223
-
224
- function providerConfigCandidates(options: DoctorOptions, deps: DoctorDeps): readonly string[] {
225
- const explicitPath = deps.env["AGENT_INSPECTOR_CONFIG_PATH"];
226
- if (explicitPath !== undefined && explicitPath !== "") {
227
- return [resolveMaybeRelative(deps.cwd, explicitPath)];
228
- }
229
- if (options.configDir !== null) {
230
- const dir = resolveMaybeRelative(deps.cwd, options.configDir);
231
- return [join(dir, "providers.json"), join(dir, "config.json")];
232
- }
233
- const dataDir = resolveDefaultDataDir(deps.env, deps.platform, deps.exists);
234
- return [join(dataDir, "providers.json"), join(dataDir, "config.json")];
235
- }
236
-
237
- function checkProviderConfig(options: DoctorOptions, deps: DoctorDeps): DoctorCheck {
238
- const providersJson = options.providersJson ?? deps.env["AGENT_INSPECTOR_PROVIDERS_JSON"] ?? null;
239
- if (providersJson !== null) {
240
- const count = providerCountFromJson(providersJson);
241
- if (count === "invalid") {
242
- return check(
243
- "Provider config",
244
- "fail",
245
- "Provider JSON override is not valid JSON.",
246
- "Fix --providers or AGENT_INSPECTOR_PROVIDERS_JSON; doctor never prints the raw value.",
247
- );
248
- }
249
- if (count !== null) {
250
- return check("Provider config", "pass", `${count} provider(s) found in JSON override.`);
251
- }
252
- return check(
253
- "Provider config",
254
- "fail",
255
- "Provider JSON override does not look like a provider array or { providers } object.",
256
- "Use an exported providers JSON payload or configure providers in the UI.",
257
- );
258
- }
259
-
260
- const candidates = providerConfigCandidates(options, deps);
261
- for (const candidate of candidates) {
262
- if (!deps.exists(candidate)) continue;
263
- const text = deps.readText(candidate);
264
- if (text === null) {
265
- return check(
266
- "Provider config",
267
- "fail",
268
- `Provider config exists but could not be read: ${candidate}`,
269
- );
270
- }
271
- const count = providerCountFromJson(text);
272
- if (count === "invalid") {
273
- return check("Provider config", "fail", `Provider config is invalid JSON: ${candidate}`);
274
- }
275
- if (count !== null && count > 0) {
276
- return check("Provider config", "pass", `${count} provider(s) configured.`);
277
- }
278
- return check(
279
- "Provider config",
280
- "warn",
281
- `Provider config exists but no providers were found: ${candidate}`,
282
- "Add a provider through the control API/MCP, or use Settings when a UI is available.",
283
- );
284
- }
285
-
286
- return check(
287
- "Provider config",
288
- "warn",
289
- "No provider config was found.",
290
- "Add a provider through the control API/MCP, use Settings when a UI is available, or pass --providers for this check.",
291
- );
292
- }
293
-
294
- function publicOriginForDoctor(port: number, env: DoctorDeps["env"]): string {
295
- const configured = env["AGENT_INSPECTOR_PUBLIC_ORIGIN"];
296
- if (configured !== undefined && configured.trim() === configured) {
297
- try {
298
- const parsed = new URL(configured);
299
- if (
300
- (parsed.protocol === "http:" || parsed.protocol === "https:") &&
301
- parsed.username.length === 0 &&
302
- parsed.password.length === 0 &&
303
- parsed.pathname === "/" &&
304
- parsed.search.length === 0 &&
305
- parsed.hash.length === 0
306
- ) {
307
- return parsed.origin;
308
- }
309
- } catch {
310
- // Startup reports invalid public-origin configuration; doctor keeps a safe local hint.
311
- }
312
- }
313
- return `http://localhost:${String(port)}`;
314
- }
315
-
316
- async function checkProxyHealth(port: number, deps: DoctorDeps): Promise<DoctorCheck> {
317
- const basePath = getConfiguredBasePath(deps.env);
318
- const health = await deps.fetchHealth(port, basePath);
319
- const url = publicOriginForDoctor(port, deps.env);
320
- const proxyUrl = appendBasePathToOrigin(url, "/proxy", basePath);
321
- const healthPath = appendBasePathToOrigin("", "/api/health", basePath);
322
- if (health.ok) {
323
- return check(
324
- "Backend health",
325
- "pass",
326
- `Agent Inspector backend is healthy at ${appendBasePathToOrigin(url, "/", basePath)}.`,
327
- `Agent proxy URL: ${proxyUrl}. UI availability is not part of this backend check.`,
328
- );
329
- }
330
-
331
- if (await deps.isPortOpen(port)) {
332
- const suffix = health.status === null ? "" : ` (HTTP ${health.status})`;
333
- return check(
334
- "Backend health",
335
- "fail",
336
- `Port ${port} is accepting connections, but ${healthPath} is not healthy${suffix}.`,
337
- "Stop that process, choose --port <n>, or start agent-inspector with --force-restart.",
338
- );
339
- }
340
-
341
- return check(
342
- "Backend health",
343
- "warn",
344
- `No process is listening on port ${port}.`,
345
- "Start with `agent-inspector`, `agent-inspector --background`, or `bun run dev`.",
346
- );
347
- }
348
-
349
- function readinessChecks(readiness: ReadinessProbe): readonly DoctorCheck[] {
350
- if (!readiness.ok) {
351
- const suffix = readiness.status === null ? "" : ` (HTTP ${readiness.status})`;
352
- return [
353
- check(
354
- "Readiness",
355
- "warn",
356
- `Readiness probe is unavailable${suffix}.`,
357
- "Use /readyz locally or run with --verbose for storage and worker hints.",
358
- ),
359
- ];
360
- }
361
- if (!isObject(readiness.body)) {
362
- return [check("Readiness", "warn", "Readiness response was not an object.")];
363
- }
364
- const status = readiness.body["status"];
365
- const checks = readiness.body["checks"];
366
- if (typeof status !== "string" || !isObject(checks)) {
367
- return [check("Readiness", "warn", "Readiness response did not include status/checks.")];
368
- }
369
- const degraded = Object.entries(checks)
370
- .filter(([, value]) => value !== "ok")
371
- .map(([name, value]) => `${name}=${String(value)}`);
372
- if (degraded.length === 0) {
373
- return [check("Readiness", "pass", `Runtime readiness is ${status}.`)];
374
- }
375
- return [
376
- check(
377
- "Readiness",
378
- status === "unavailable" ? "fail" : "warn",
379
- `Runtime readiness is ${status}: ${degraded.join(", ")}.`,
380
- "Inspect /readyz and /metrics for safe aggregate runtime details.",
381
- ),
382
- ];
383
- }
384
-
385
- function findProjectRoot(startDir: string, deps: Pick<DoctorDeps, "exists">): string {
386
- let current = resolve(startDir);
387
- for (let i = 0; i < 6; i++) {
388
- if (deps.exists(join(current, "package.json"))) return current;
389
- const next = resolve(current, "..");
390
- if (next === current) return startDir;
391
- current = next;
392
- }
393
- return startDir;
394
- }
395
-
396
- function checkPackage(rootDir: string, deps: DoctorDeps): DoctorCheck {
397
- const packagePath = join(rootDir, "package.json");
398
- const text = deps.readText(packagePath);
399
- if (text === null) {
400
- return check("Package metadata", "warn", "package.json was not found near the CLI bundle.");
401
- }
402
- try {
403
- const parsed: unknown = JSON.parse(text);
404
- if (!isObject(parsed)) {
405
- return check("Package metadata", "warn", "package.json is not an object.");
406
- }
407
- const name = parsed["name"];
408
- const version = parsed["version"];
409
- if (typeof name === "string" && typeof version === "string") {
410
- return check("Package metadata", "pass", `${name}@${version}`);
411
- }
412
- return check("Package metadata", "warn", "package.json is missing name or version.");
413
- } catch {
414
- return check("Package metadata", "warn", "package.json is not valid JSON.");
415
- }
416
- }
417
-
418
- function countFilesInDir(dir: string, deps: Pick<DoctorDeps, "listDir" | "stat">): number | null {
419
- const files = deps.listDir(dir);
420
- if (files === null) return null;
421
- let count = 0;
422
- for (const file of files) {
423
- const fileStat = deps.stat(join(dir, file));
424
- if (fileStat !== null && !fileStat.isDirectory) count += 1;
425
- }
426
- return count;
427
- }
428
-
429
- function formatBytes(bytes: number): string {
430
- if (bytes < 1024) return `${bytes} B`;
431
- if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KiB`;
432
- if (bytes < 1024 * 1024 * 1024) return `${(bytes / 1024 / 1024).toFixed(1)} MiB`;
433
- return `${(bytes / 1024 / 1024 / 1024).toFixed(1)} GiB`;
434
- }
435
-
436
- function dirSize(
437
- dir: string,
438
- deps: Pick<DoctorDeps, "listDir" | "stat">,
439
- depth = 0,
440
- ): number | null {
441
- const dirStat = deps.stat(dir);
442
- if (dirStat === null) return null;
443
- if (!dirStat.isDirectory) return dirStat.size;
444
- if (depth > 4) return 0;
445
-
446
- const files = deps.listDir(dir);
447
- if (files === null) return null;
448
- let total = 0;
449
- for (const file of files) {
450
- const childSize = dirSize(join(dir, file), deps, depth + 1);
451
- if (childSize !== null) total += childSize;
452
- }
453
- return total;
454
- }
455
-
456
- function verboseChecks(options: DoctorOptions, deps: DoctorDeps): readonly DoctorCheck[] {
457
- const dataDir = resolveDefaultDataDir(deps.env, deps.platform, deps.exists);
458
- const logsDir = join(dataDir, "logs");
459
- const chunksDir = join(dataDir, "chunks");
460
- const providerCandidates = providerConfigCandidates(options, deps);
461
- const captureMode =
462
- deps.env["AGENT_INSPECTOR_MODE"] ?? deps.env["AGENT_INSPECTOR_CAPTURE_MODE"] ?? "simple";
463
- const logCount = countFilesInDir(logsDir, deps);
464
- const logSize = dirSize(logsDir, deps);
465
- const chunkSize = dirSize(chunksDir, deps);
466
- const homeDir =
467
- deps.platform === "win32"
468
- ? (deps.env["USERPROFILE"] ?? deps.env["APPDATA"] ?? null)
469
- : (deps.env["HOME"] ?? null);
470
- const claudeSkill =
471
- homeDir === null
472
- ? null
473
- : join(homeDir, ".claude", "skills", "agent-inspector-onboard", "SKILL.md");
474
- const claudeCommand =
475
- homeDir === null ? null : join(homeDir, ".claude", "commands", "agent-inspector-onboard.md");
476
- const codexSkill =
477
- homeDir === null
478
- ? null
479
- : join(homeDir, ".codex", "skills", "agent-inspector-onboard", "SKILL.md");
480
- const hasClaudeOnboarding =
481
- claudeSkill !== null &&
482
- claudeCommand !== null &&
483
- deps.exists(claudeSkill) &&
484
- deps.exists(claudeCommand);
485
- const hasCodexOnboarding = codexSkill !== null && deps.exists(codexSkill);
486
-
487
- return [
488
- check("Data directory", "pass", dataDir),
489
- check("Provider config search", "pass", providerCandidates.join(", ")),
490
- check("Capture mode env", "pass", captureMode),
491
- check(
492
- "Log storage",
493
- logCount === null ? "warn" : "pass",
494
- logCount === null
495
- ? `Log directory was not found or could not be read: ${logsDir}`
496
- : `${logCount} file(s), ${formatBytes(logSize ?? 0)} under ${logsDir}`,
497
- ),
498
- check(
499
- "Chunk storage",
500
- chunkSize === null ? "warn" : "pass",
501
- chunkSize === null
502
- ? `Chunk directory was not found or could not be read: ${chunksDir}`
503
- : `${formatBytes(chunkSize)} under ${chunksDir}`,
504
- ),
505
- check(
506
- "Claude onboarding",
507
- hasClaudeOnboarding ? "pass" : "warn",
508
- hasClaudeOnboarding
509
- ? "Claude Code skill and slash command are installed."
510
- : "Claude Code onboarding files were not found.",
511
- "Run `agent-inspector onboard --force` after installing or upgrading.",
512
- ),
513
- check(
514
- "Codex onboarding",
515
- hasCodexOnboarding ? "pass" : "warn",
516
- hasCodexOnboarding
517
- ? "Codex onboarding skill is installed."
518
- : "Codex onboarding skill was not found.",
519
- "Run `agent-inspector onboard --force` after installing or upgrading.",
520
- ),
521
- ];
522
- }
523
-
524
- function checkExtensionSource(rootDir: string, deps: DoctorDeps): DoctorCheck {
525
- const extensionDir = join(rootDir, "extensions", "chrome");
526
- const missing = EXTENSION_REQUIRED_FILES.filter((file) => !deps.exists(join(extensionDir, file)));
527
- if (missing.length === 0) {
528
- return check(
529
- "Chrome extension source",
530
- "pass",
531
- "Manifest, side panel, service worker, and icons are present.",
532
- );
533
- }
534
- return check(
535
- "Chrome extension source",
536
- "fail",
537
- `Missing ${missing.length} Chrome extension file(s): ${missing.join(", ")}`,
538
- "Restore the extension files before packaging or loading unpacked.",
539
- );
540
- }
541
-
542
- function extensionManifestVersion(rootDir: string, deps: DoctorDeps): string | null {
543
- const manifestText = deps.readText(join(rootDir, "extensions", "chrome", "manifest.json"));
544
- if (manifestText === null) return null;
545
- try {
546
- const manifest: unknown = JSON.parse(manifestText);
547
- if (!isObject(manifest)) return null;
548
- const version = manifest["version"];
549
- return typeof version === "string" && version !== "" ? version : null;
550
- } catch {
551
- return null;
552
- }
553
- }
554
-
555
- function checkExtensionPackage(rootDir: string, deps: DoctorDeps): DoctorCheck {
556
- const distDir = join(rootDir, "dist", "chrome-extension");
557
- const files = deps.listDir(distDir);
558
- if (files === null) {
559
- return check(
560
- "Chrome extension package",
561
- "warn",
562
- "No packaged Chrome extension artifact was found.",
563
- "Run `npm run extension:zip` before Chrome Web Store upload.",
564
- );
565
- }
566
-
567
- const manifestVersion = extensionManifestVersion(rootDir, deps);
568
- if (manifestVersion !== null) {
569
- const zipName = `agent-inspector-companion-v${manifestVersion}.zip`;
570
- const checksumName = `${zipName}.sha256`;
571
- const hasZip = files.includes(zipName);
572
- const hasChecksum = files.includes(checksumName);
573
- if (hasZip && hasChecksum) {
574
- return check("Chrome extension package", "pass", `${zipName} with checksum is present.`);
575
- }
576
- if (hasZip) {
577
- return check(
578
- "Chrome extension package",
579
- "warn",
580
- `${zipName} exists but no .sha256 checksum was found.`,
581
- "Run `npm run extension:zip` to regenerate the zip and checksum.",
582
- );
583
- }
584
- return check(
585
- "Chrome extension package",
586
- "warn",
587
- `Current Chrome extension package was not found: ${zipName}`,
588
- "Run `npm run extension:zip` before Chrome Web Store upload.",
589
- );
590
- }
591
-
592
- const zip = files.find((file) => file.endsWith(".zip"));
593
- const checksum = files.find((file) => file.endsWith(".zip.sha256"));
594
- if (zip !== undefined && checksum !== undefined) {
595
- return check("Chrome extension package", "pass", `${zip} with checksum is present.`);
596
- }
597
- if (zip !== undefined) {
598
- return check(
599
- "Chrome extension package",
600
- "warn",
601
- `${zip} exists but no .sha256 checksum was found.`,
602
- "Run `npm run extension:zip` to regenerate the zip and checksum.",
603
- );
604
- }
605
- return check(
606
- "Chrome extension package",
607
- "warn",
608
- "No Chrome extension zip artifact was found.",
609
- "Run `npm run extension:zip` before Chrome Web Store upload.",
610
- );
611
- }
612
-
613
- export async function buildDoctorReport(
614
- options: DoctorOptions,
615
- deps: DoctorDeps = createDoctorDeps(),
616
- ): Promise<DoctorReport> {
617
- const rootDir = findProjectRoot(deps.cwd, deps);
618
- const basePath = getConfiguredBasePath(deps.env);
619
- const readiness = await deps.fetchReadiness(options.port, basePath);
620
- const coreChecks = [
621
- await checkProxyHealth(options.port, deps),
622
- ...readinessChecks(readiness),
623
- checkProviderConfig(options, deps),
624
- checkPackage(rootDir, deps),
625
- ];
626
- const checksWithExtension = options.chromeExtension
627
- ? [...coreChecks, checkExtensionSource(rootDir, deps), checkExtensionPackage(rootDir, deps)]
628
- : coreChecks;
629
- const checks = options.verbose
630
- ? [...checksWithExtension, ...verboseChecks(options, deps)]
631
- : checksWithExtension;
632
-
633
- const passCount = checks.filter((item) => item.severity === "pass").length;
634
- const warnCount = checks.filter((item) => item.severity === "warn").length;
635
- const failCount = checks.filter((item) => item.severity === "fail").length;
636
-
637
- return {
638
- checks,
639
- readiness,
640
- passCount,
641
- warnCount,
642
- failCount,
643
- exitCode: failCount > 0 ? 1 : 0,
644
- };
645
- }
646
-
647
- export function buildDoctorSupportBundle(
648
- options: DoctorOptions,
649
- deps: DoctorDeps,
650
- report: DoctorReport,
651
- ): DoctorSupportBundle {
652
- return {
653
- schema: "agent-inspector.support-bundle/v1",
654
- createdAt: new Date().toISOString(),
655
- report,
656
- environment: {
657
- platform: deps.platform,
658
- cwd: deps.cwd,
659
- basePath: getConfiguredBasePath(deps.env),
660
- port: options.port,
661
- hasControlToken:
662
- deps.env["AGENT_INSPECTOR_CONTROL_TOKEN"] !== undefined ||
663
- deps.env["AGENT_INSPECTOR_API_TOKEN"] !== undefined,
664
- hasProxyToken: deps.env["AGENT_INSPECTOR_PROXY_TOKEN"] !== undefined,
665
- hasProviderJsonOverride:
666
- options.providersJson !== null || deps.env["AGENT_INSPECTOR_PROVIDERS_JSON"] !== undefined,
667
- },
668
- storage: verboseChecks(options, deps).filter((item) => item.name.includes("storage")),
669
- };
670
- }
671
-
672
- export function formatDoctorReport(report: DoctorReport): string {
673
- const lines = ["agent-inspector doctor", ""];
674
- for (const item of report.checks) {
675
- lines.push(`${item.severity.toUpperCase().padEnd(4)} ${item.name}: ${item.message}`);
676
- if (item.hint !== null) {
677
- lines.push(` ${item.hint}`);
678
- }
679
- }
680
- lines.push("");
681
- lines.push(
682
- `Summary: ${report.passCount} pass, ${report.warnCount} warn, ${report.failCount} fail`,
683
- );
684
- return `${lines.join("\n")}\n`;
685
- }
686
-
687
- export function formatDoctorJson(report: DoctorReport): string {
688
- return `${JSON.stringify(report, null, 2)}\n`;
689
- }
690
-
691
- export function formatDoctorSupportBundle(bundle: DoctorSupportBundle): string {
692
- return `${JSON.stringify(bundle, null, 2)}\n`;
693
- }
694
-
695
- export function doctorHelp(): string {
696
- return [
697
- "agent-inspector doctor",
698
- "",
699
- "Usage:",
700
- " agent-inspector doctor [--port <port>] [--config-dir <dir>] [--providers <json>] [--fix] [--json] [--support-bundle] [--verbose] [--chrome-extension]",
701
- "",
702
- "Checks local backend health, provider config presence, and package metadata.",
703
- "The backend check probes the local health endpoint and does not require a composed Web UI.",
704
- "Pass --fix to run safe local repairs before checks, including legacy data-dir migration.",
705
- "Pass --json to emit a machine-readable report for CI, scripts, and Jenkins.",
706
- "Pass --support-bundle to emit a redacted JSON bundle with readiness causes and storage summary.",
707
- "Pass --verbose to include local paths, capture mode, and log storage checks.",
708
- "Pass --chrome-extension to also check Chrome companion source and packaged artifacts.",
709
- "",
710
- ].join("\n");
711
- }
712
-
713
- async function fetchHealth(port: number, basePath: string): Promise<HealthProbe> {
714
- const controller = new AbortController();
715
- const timeout = setTimeout(() => controller.abort(), PROBE_TIMEOUT_MS);
716
- try {
717
- const response = await fetch(
718
- appendBasePathToOrigin(`http://127.0.0.1:${port}`, "/api/health", basePath),
719
- {
720
- cache: "no-store",
721
- signal: controller.signal,
722
- },
723
- );
724
- return { ok: response.ok, status: response.status };
725
- } catch {
726
- return { ok: false, status: null };
727
- } finally {
728
- clearTimeout(timeout);
729
- }
730
- }
731
-
732
- async function fetchReadiness(port: number, basePath: string): Promise<ReadinessProbe> {
733
- const controller = new AbortController();
734
- const timeout = setTimeout(() => controller.abort(), PROBE_TIMEOUT_MS);
735
- try {
736
- const response = await fetch(
737
- appendBasePathToOrigin(`http://127.0.0.1:${port}`, "/readyz", basePath),
738
- {
739
- cache: "no-store",
740
- signal: controller.signal,
741
- },
742
- );
743
- let body: unknown = null;
744
- try {
745
- body = await response.json();
746
- } catch {
747
- body = null;
748
- }
749
- return { ok: response.ok, status: response.status, body };
750
- } catch {
751
- return { ok: false, status: null, body: null };
752
- } finally {
753
- clearTimeout(timeout);
754
- }
755
- }
756
-
757
- function isPortOpen(port: number): Promise<boolean> {
758
- return new Promise((resolveOpen) => {
759
- const socket = createConnection({ host: "127.0.0.1", port });
760
- const finish = (value: boolean): void => {
761
- socket.removeAllListeners();
762
- socket.destroy();
763
- resolveOpen(value);
764
- };
765
-
766
- socket.setTimeout(PROBE_TIMEOUT_MS);
767
- socket.once("connect", () => finish(true));
768
- socket.once("timeout", () => finish(false));
769
- socket.once("error", () => finish(false));
770
- });
771
- }
772
-
773
- function readText(path: string): string | null {
774
- try {
775
- return readFileSync(path, "utf8");
776
- } catch {
777
- return null;
778
- }
779
- }
780
-
781
- function listDir(path: string): readonly string[] | null {
782
- try {
783
- return readdirSync(path);
784
- } catch {
785
- return null;
786
- }
787
- }
788
-
789
- function stat(path: string): { isDirectory: boolean; size: number } | null {
790
- try {
791
- const fileStat = statSync(path);
792
- return { isDirectory: fileStat.isDirectory(), size: fileStat.size };
793
- } catch {
794
- return null;
795
- }
796
- }
797
-
798
- export function createDoctorDeps(): DoctorDeps {
799
- return {
800
- env: process.env,
801
- platform: process.platform,
802
- cwd: process.cwd(),
803
- exists: existsSync,
804
- readText,
805
- listDir,
806
- stat,
807
- fetchHealth,
808
- fetchReadiness,
809
- isPortOpen,
810
- };
811
- }
812
-
813
- export async function runDoctor(argv: readonly string[]): Promise<number> {
814
- const parsed = parseDoctorArgs(argv);
815
- if (parsed.kind === "error") {
816
- process.stderr.write(`${parsed.message}\n`);
817
- return 2;
818
- }
819
- if (parsed.options.help) {
820
- process.stdout.write(doctorHelp());
821
- return 0;
822
- }
823
- if (parsed.options.fix) {
824
- migrateLegacyDataDirs();
825
- }
826
- const report = await buildDoctorReport(parsed.options);
827
- if (parsed.options.supportBundle) {
828
- const bundle = buildDoctorSupportBundle(parsed.options, createDoctorDeps(), report);
829
- process.stdout.write(formatDoctorSupportBundle(bundle));
830
- } else {
831
- process.stdout.write(
832
- parsed.options.json ? formatDoctorJson(report) : formatDoctorReport(report),
833
- );
834
- }
835
- return report.exitCode;
836
- }