@tonyclaw/agent-inspector 4.0.1 → 4.0.3

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 +193 -110
  3. package/.output/server/_ssr/index.mjs +1 -1
  4. package/.output/server/_ssr/{router-CTHqmroT.mjs → router-ChILzhmz.mjs} +92 -4
  5. package/.output/server/index.mjs +1 -1
  6. package/.output/ui/assets/{CompareDrawer-L3n4J-Or.js → CompareDrawer-Co3cUF_I.js} +1 -1
  7. package/.output/ui/assets/{InspectorPet-D5o_3OZS.js → InspectorPet-jFcrL37X.js} +1 -1
  8. package/.output/ui/assets/{ProxyViewerContainer-Ocagx75S.js → ProxyViewerContainer-BPzt_VpM.js} +4 -4
  9. package/.output/ui/assets/{ReplayDialog-Bk7x1h-y.js → ReplayDialog-C6O_zuwI.js} +1 -1
  10. package/.output/ui/assets/{RequestAnatomy-U4lzL7Sc.js → RequestAnatomy-Ca6NvB7L.js} +1 -1
  11. package/.output/ui/assets/{ResponseView-LOWfvBLK.js → ResponseView-BzqKcveJ.js} +1 -1
  12. package/.output/ui/assets/{StreamingChunkSequence-DPfsrrXQ.js → StreamingChunkSequence-9pCZIsS_.js} +1 -1
  13. package/.output/ui/assets/{_sessionId-0MlWS-CO.js → _sessionId-BMP3KVGR.js} +1 -1
  14. package/.output/ui/assets/{_sessionId-OdX2Jvt1.js → _sessionId-y4eRoT1H.js} +1 -1
  15. package/.output/ui/assets/{index-Ea-c8hPg.js → index-CH5w-haG.js} +1 -1
  16. package/.output/ui/assets/{index-zVVS53Hd.js → index-CmocEhyU.js} +1 -1
  17. package/.output/ui/assets/{index-Du4qNOOt.js → index-DT8sMJ_n.js} +2 -2
  18. package/.output/ui/assets/{index-gvFj_9K6.js → index-bfsbIRZa.js} +1 -1
  19. package/.output/ui/assets/{json-viewer-C1WAMzg3.js → json-viewer-BfFOSDG5.js} +1 -1
  20. package/.output/ui/assets/{jszip.min-B8AKu2zm.js → jszip.min-BkbVkOsp.js} +1 -1
  21. package/.output/ui/index.html +1 -1
  22. package/package.json +5 -10
  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 -1433
  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 -258
  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
@@ -1,1668 +0,0 @@
1
- /**
2
- * `agent-inspector onboard` subcommand.
3
- *
4
- * Generates Agent Inspector onboarding skills into the user's home dir.
5
- * Claude Code gets a skill + slash command. Codex gets a skill under
6
- * ~/.codex/skills that guides the user through connecting /api/mcp.
7
- *
8
- * Idempotent by default: re-runs without `--force` write missing files and
9
- * refresh older generated files. `--force` overwrites, `--dry-run` writes
10
- * nothing. Designed as an explicit setup step that can fail softly without
11
- * blocking normal CLI use.
12
- */
13
-
14
- import {
15
- mkdirSync,
16
- writeFileSync,
17
- existsSync,
18
- readFileSync,
19
- unlinkSync,
20
- readdirSync,
21
- rmdirSync,
22
- } from "node:fs";
23
- import { homedir } from "node:os";
24
- import { dirname, join } from "node:path";
25
- import { fileURLToPath } from "node:url";
26
-
27
- import { appendBasePathToOrigin, getConfiguredBasePath } from "../lib/basePath.js";
28
- import { detectAll, detectFirst } from "./detect-tools.js";
29
- import { type OnboardTarget, resolveOnboardTarget } from "./onboardTarget.js";
30
- import { renderCommandOnboard } from "./templates/command-onboard.js";
31
- import {
32
- renderCodexSkillOnboard,
33
- REQUIRED_CODEX_PHASE_HEADINGS,
34
- } from "./templates/codex-skill-onboard.js";
35
- import { renderSkillOnboard, REQUIRED_PHASE_HEADINGS } from "./templates/skill-onboard.js";
36
-
37
- const __filename = fileURLToPath(import.meta.url);
38
- const __dirname = dirname(__filename);
39
-
40
- const DEFAULT_PORT = 9527;
41
- const DEFAULT_ORIGIN = `http://localhost:${DEFAULT_PORT}`;
42
- const DEFAULT_MCP_URL = appendBasePathToOrigin(
43
- DEFAULT_ORIGIN,
44
- "/api/mcp",
45
- getConfiguredBasePath({}),
46
- );
47
- const LEGACY_MCP_URL = "http://localhost:9527/api/mcp";
48
- const SKILL_DIR_NAME = "agent-inspector-onboard";
49
- const SKILL_FILE_NAME = "SKILL.md";
50
- // Windows reserves `:` for NTFS alternate data streams, so a file named
51
- // `agent-inspector:onboard.md` becomes an empty `agent-inspector` on disk.
52
- // Use `-` on Windows and `:` on Unix to match the slash-command convention
53
- // (`/agent-inspector:onboard` vs `/agent-inspector-onboard`) within the
54
- // constraints of each platform.
55
- const COMMAND_FILE_NAME =
56
- process.platform === "win32" ? "agent-inspector-onboard.md" : "agent-inspector:onboard.md";
57
-
58
- const GENERATED_VERSION_PATTERN = /^\s*version:\s*([0-9]+\.[0-9]+\.[0-9]+(?:[-+][^\s]+)?)\s*$/m;
59
- const FRONTMATTER_PATTERN = /^---\r?\n([\s\S]*?)\r?\n---/;
60
- const SEMVER_PATTERN = /^(\d+)\.(\d+)\.(\d+)(?:[-+].*)?$/;
61
-
62
- export type OnboardFlags = {
63
- force: boolean;
64
- dryRun: boolean;
65
- skipProvider: boolean;
66
- skipToolWire: boolean;
67
- codexOnly: boolean;
68
- skipCodexSkill: boolean;
69
- opencode: boolean;
70
- opencodeOnly: boolean;
71
- opencodeConfig: string | null;
72
- opencodeTransport: AgentMcpTransport;
73
- opencodeMcpUrl: string | null;
74
- mimo: boolean;
75
- mimoOnly: boolean;
76
- mimoConfig: string | null;
77
- mimoTransport: AgentMcpTransport;
78
- mimoMcpUrl: string | null;
79
- instanceName: string | null;
80
- baseUrl: string | null;
81
- controlBaseUrl: string | null;
82
- agentBaseUrl: string | null;
83
- uiUrl: string | null | undefined;
84
- mcpName: string | null;
85
- uninstall: boolean;
86
- status: boolean;
87
- json: boolean;
88
- skillDir: string | null;
89
- codexSkillDir: string | null;
90
- };
91
-
92
- type AgentMcpTransport = "local" | "remote";
93
- type AgentMcpStatusTransport = AgentMcpTransport | "unknown";
94
- type AgentMcpConfigState = "missing" | "configured" | "custom" | "disabled" | "invalid";
95
-
96
- type AgentMcpConfigTarget = {
97
- label: "OpenCode" | "MiMo Code";
98
- configLabel: "OpenCode MCP config" | "MiMo Code MCP config";
99
- configPath: string;
100
- transport: AgentMcpTransport;
101
- endpoint: string;
102
- mcpName: string;
103
- setupAction: string;
104
- forceAction: string;
105
- verifyCommand: string;
106
- invalidAction: string;
107
- configObjectName: string;
108
- defaultSchema: string;
109
- };
110
-
111
- type AgentMcpConfigStatus = {
112
- label: "OpenCode MCP config" | "MiMo Code MCP config";
113
- path: string;
114
- state: AgentMcpConfigState;
115
- transport: AgentMcpStatusTransport;
116
- endpoint: string;
117
- mcpName: string;
118
- action: string;
119
- forceAction: string;
120
- verifyCommand: string;
121
- detail: string;
122
- };
123
-
124
- type AgentMcpConfigPlan = {
125
- status: AgentMcpConfigStatus;
126
- body: string | null;
127
- shouldWrite: boolean;
128
- shouldRemove: boolean;
129
- blockedMessage: string | null;
130
- };
131
-
132
- type AgentConfigReadResult =
133
- | {
134
- ok: true;
135
- exists: boolean;
136
- config: Record<string, unknown>;
137
- }
138
- | {
139
- ok: false;
140
- exists: boolean;
141
- message: string;
142
- };
143
-
144
- type OnboardTargets = {
145
- claudeSkillFile: string;
146
- claudeCommandFile: string;
147
- codexSkillFile: string;
148
- };
149
-
150
- type PlannedFile = {
151
- label: string;
152
- path: string;
153
- body: string;
154
- enabled: boolean;
155
- };
156
-
157
- type ParsedVersion = {
158
- major: number;
159
- minor: number;
160
- patch: number;
161
- };
162
-
163
- type GeneratedFileState = "missing" | "current" | "outdated" | "newer" | "custom";
164
-
165
- type GeneratedFileStatus = {
166
- label: string;
167
- path: string;
168
- state: GeneratedFileState;
169
- version: string | null;
170
- action: string;
171
- };
172
-
173
- function actionForStatus(label: string, state: GeneratedFileState): string {
174
- switch (state) {
175
- case "missing":
176
- switch (label) {
177
- case "Codex skill":
178
- return "agent-inspector onboard --codex-only";
179
- case "Claude skill":
180
- case "Claude command":
181
- return "agent-inspector onboard --skip-codex-skill";
182
- default:
183
- return "agent-inspector onboard";
184
- }
185
- case "outdated":
186
- return "agent-inspector onboard --force";
187
- case "custom":
188
- return "preserved; use agent-inspector onboard --force to replace";
189
- case "newer":
190
- return "no action; installed file is newer than this package";
191
- case "current":
192
- return "no action";
193
- default:
194
- return "agent-inspector onboard";
195
- }
196
- }
197
-
198
- function parseFlags(argv: readonly string[]): OnboardFlags {
199
- const flags: OnboardFlags = {
200
- force: false,
201
- dryRun: false,
202
- skipProvider: false,
203
- skipToolWire: false,
204
- codexOnly: false,
205
- skipCodexSkill: false,
206
- opencode: false,
207
- opencodeOnly: false,
208
- opencodeConfig: null,
209
- opencodeTransport: "local",
210
- opencodeMcpUrl: null,
211
- mimo: false,
212
- mimoOnly: false,
213
- mimoConfig: null,
214
- mimoTransport: "local",
215
- mimoMcpUrl: null,
216
- instanceName: null,
217
- baseUrl: null,
218
- controlBaseUrl: null,
219
- agentBaseUrl: null,
220
- uiUrl: undefined,
221
- mcpName: null,
222
- uninstall: false,
223
- status: false,
224
- json: false,
225
- skillDir: null,
226
- codexSkillDir: null,
227
- };
228
- for (let i = 0; i < argv.length; i++) {
229
- const arg = argv[i];
230
- switch (arg) {
231
- case undefined:
232
- continue;
233
- case "--force":
234
- flags.force = true;
235
- break;
236
- case "--dry-run":
237
- flags.dryRun = true;
238
- break;
239
- case "--skip-provider":
240
- flags.skipProvider = true;
241
- break;
242
- case "--skip-tool-wire":
243
- flags.skipToolWire = true;
244
- break;
245
- case "--codex-only":
246
- flags.codexOnly = true;
247
- break;
248
- case "--skip-codex-skill":
249
- flags.skipCodexSkill = true;
250
- break;
251
- case "--opencode":
252
- flags.opencode = true;
253
- break;
254
- case "--opencode-only":
255
- flags.opencode = true;
256
- flags.opencodeOnly = true;
257
- break;
258
- case "--opencode-config": {
259
- const next = argv[i + 1];
260
- if (next === undefined) {
261
- process.stderr.write(
262
- "agent-inspector onboard: --opencode-config requires a path argument\n",
263
- );
264
- process.exit(2);
265
- }
266
- flags.opencodeConfig = next;
267
- i++;
268
- break;
269
- }
270
- case "--opencode-transport": {
271
- const next = argv[i + 1];
272
- if (next === undefined) {
273
- process.stderr.write(
274
- "agent-inspector onboard: --opencode-transport requires local or remote\n",
275
- );
276
- process.exit(2);
277
- }
278
- switch (next) {
279
- case "local":
280
- case "remote":
281
- flags.opencodeTransport = next;
282
- break;
283
- default:
284
- process.stderr.write(
285
- `agent-inspector onboard: invalid --opencode-transport: ${next}\n`,
286
- );
287
- process.exit(2);
288
- }
289
- i++;
290
- break;
291
- }
292
- case "--opencode-mcp-url": {
293
- const next = argv[i + 1];
294
- if (next === undefined) {
295
- process.stderr.write("agent-inspector onboard: --opencode-mcp-url requires a URL\n");
296
- process.exit(2);
297
- }
298
- flags.opencodeMcpUrl = next;
299
- i++;
300
- break;
301
- }
302
- case "--mimo":
303
- flags.mimo = true;
304
- break;
305
- case "--mimo-only":
306
- flags.mimo = true;
307
- flags.mimoOnly = true;
308
- break;
309
- case "--mimo-config": {
310
- const next = argv[i + 1];
311
- if (next === undefined) {
312
- process.stderr.write("agent-inspector onboard: --mimo-config requires a path argument\n");
313
- process.exit(2);
314
- }
315
- flags.mimoConfig = next;
316
- i++;
317
- break;
318
- }
319
- case "--mimo-transport": {
320
- const next = argv[i + 1];
321
- if (next === undefined) {
322
- process.stderr.write(
323
- "agent-inspector onboard: --mimo-transport requires local or remote\n",
324
- );
325
- process.exit(2);
326
- }
327
- switch (next) {
328
- case "local":
329
- case "remote":
330
- flags.mimoTransport = next;
331
- break;
332
- default:
333
- process.stderr.write(`agent-inspector onboard: invalid --mimo-transport: ${next}\n`);
334
- process.exit(2);
335
- }
336
- i++;
337
- break;
338
- }
339
- case "--mimo-mcp-url": {
340
- const next = argv[i + 1];
341
- if (next === undefined) {
342
- process.stderr.write("agent-inspector onboard: --mimo-mcp-url requires a URL\n");
343
- process.exit(2);
344
- }
345
- flags.mimoMcpUrl = next;
346
- i++;
347
- break;
348
- }
349
- case "--instance": {
350
- const next = argv[i + 1];
351
- if (next === undefined || next.trim().length === 0) {
352
- process.stderr.write("agent-inspector onboard: --instance requires a name\n");
353
- process.exit(2);
354
- }
355
- flags.instanceName = next;
356
- i++;
357
- break;
358
- }
359
- case "--base-url": {
360
- const next = argv[i + 1];
361
- if (next === undefined || next.trim().length === 0) {
362
- process.stderr.write("agent-inspector onboard: --base-url requires a URL\n");
363
- process.exit(2);
364
- }
365
- flags.baseUrl = next;
366
- i++;
367
- break;
368
- }
369
- case "--control-base-url": {
370
- const next = argv[i + 1];
371
- if (next === undefined || next.trim().length === 0) {
372
- process.stderr.write("agent-inspector onboard: --control-base-url requires a URL\n");
373
- process.exit(2);
374
- }
375
- flags.controlBaseUrl = next;
376
- i++;
377
- break;
378
- }
379
- case "--agent-base-url": {
380
- const next = argv[i + 1];
381
- if (next === undefined || next.trim().length === 0) {
382
- process.stderr.write("agent-inspector onboard: --agent-base-url requires a URL\n");
383
- process.exit(2);
384
- }
385
- flags.agentBaseUrl = next;
386
- i++;
387
- break;
388
- }
389
- case "--ui-url": {
390
- const next = argv[i + 1];
391
- if (next === undefined || next.trim().length === 0) {
392
- process.stderr.write("agent-inspector onboard: --ui-url requires a URL\n");
393
- process.exit(2);
394
- }
395
- flags.uiUrl = next;
396
- i++;
397
- break;
398
- }
399
- case "--no-ui":
400
- flags.uiUrl = null;
401
- break;
402
- case "--mcp-name": {
403
- const next = argv[i + 1];
404
- if (next === undefined || next.trim().length === 0) {
405
- process.stderr.write("agent-inspector onboard: --mcp-name requires a name\n");
406
- process.exit(2);
407
- }
408
- flags.mcpName = next;
409
- i++;
410
- break;
411
- }
412
- case "--uninstall":
413
- flags.uninstall = true;
414
- break;
415
- case "--status":
416
- flags.status = true;
417
- break;
418
- case "--json":
419
- flags.json = true;
420
- break;
421
- case "--skill-dir": {
422
- const next = argv[i + 1];
423
- if (next === undefined) {
424
- process.stderr.write("agent-inspector onboard: --skill-dir requires a path argument\n");
425
- process.exit(2);
426
- }
427
- flags.skillDir = next;
428
- i++;
429
- break;
430
- }
431
- case "--codex-skill-dir": {
432
- const next = argv[i + 1];
433
- if (next === undefined) {
434
- process.stderr.write(
435
- "agent-inspector onboard: --codex-skill-dir requires a path argument\n",
436
- );
437
- process.exit(2);
438
- }
439
- flags.codexSkillDir = next;
440
- i++;
441
- break;
442
- }
443
- case "--help":
444
- case "-h":
445
- printHelp();
446
- process.exit(0);
447
- break;
448
- default:
449
- process.stderr.write(`agent-inspector onboard: unknown flag: ${arg}\n`);
450
- process.exit(2);
451
- }
452
- }
453
- return flags;
454
- }
455
-
456
- function printHelp(): void {
457
- process.stdout.write(`agent-inspector onboard - install Agent Inspector onboarding skills
458
-
459
- Usage:
460
- agent-inspector onboard [options]
461
-
462
- Options:
463
- --force Overwrite existing generated skills and slash command
464
- --dry-run Print target paths and template previews, write nothing
465
- --skip-provider Skip the provider-setup phase in the Claude skill body
466
- --skip-tool-wire Skip the wire-tool phase in the Claude skill body
467
- --skip-codex-skill Install only the Claude Code skill and slash command
468
- --codex-only Install only the Codex skill
469
- --opencode Also configure OpenCode MCP in opencode.json/jsonc
470
- --opencode-only Configure only OpenCode MCP
471
- --opencode-config <path> Override OpenCode config path (default: ~/.config/opencode/opencode.json)
472
- --opencode-transport <local|remote>
473
- OpenCode MCP transport to write (default: local)
474
- --opencode-mcp-url <url> Agent Inspector MCP endpoint for OpenCode
475
- --mimo Also configure MiMo Code MCP in mimocode.json/jsonc
476
- --mimo-only Configure only MiMo Code MCP
477
- --mimo-config <path> Override MiMo config path (default: ~/.config/mimocode/mimocode.jsonc)
478
- --mimo-transport <local|remote>
479
- MiMo Code MCP transport to write (default: local)
480
- --mimo-mcp-url <url> Agent Inspector MCP endpoint for MiMo Code
481
- --instance <name> Target a registered named Inspector instance
482
- --base-url <url> Target an explicit credential-free backend control/agent Base URL
483
- --control-base-url <url> Control API Base URL for a separated deployment
484
- --agent-base-url <url> Proxy and MCP Base URL for Coding Agents
485
- --ui-url <url> Browser UI URL for a separated deployment
486
- --no-ui Declare that the explicit target has no browser UI
487
- --mcp-name <name> MCP config key (named default: agent-inspector-<instance>)
488
- --uninstall Remove generated files whose version matches this package
489
- --status Show installed onboarding file versions and suggested action
490
- --json Emit machine-readable JSON with --status
491
- --skill-dir <path> Override the target Claude root directory (default: ~/.claude)
492
- --codex-skill-dir <path> Override the target Codex skills directory (default: ~/.codex/skills)
493
- -h, --help Show this help
494
-
495
- Exit codes:
496
- 0 success (or already installed)
497
- 2 invalid arguments
498
- 1 write failed
499
- `);
500
- }
501
-
502
- function resolveTargets(flags: OnboardFlags): OnboardTargets {
503
- const claudeRoot = flags.skillDir ?? join(homedir(), ".claude");
504
- const claudeSkillDir = join(claudeRoot, "skills", SKILL_DIR_NAME);
505
- const claudeCommandsDir = join(claudeRoot, "commands");
506
- const codexRoot = process.env["CODEX_HOME"] ?? join(homedir(), ".codex");
507
- const codexSkillsDir = flags.codexSkillDir ?? join(codexRoot, "skills");
508
- return {
509
- claudeSkillFile: join(claudeSkillDir, SKILL_FILE_NAME),
510
- claudeCommandFile: join(claudeCommandsDir, COMMAND_FILE_NAME),
511
- codexSkillFile: join(codexSkillsDir, SKILL_DIR_NAME, SKILL_FILE_NAME),
512
- };
513
- }
514
-
515
- function isObject(value: unknown): value is Record<string, unknown> {
516
- return typeof value === "object" && value !== null;
517
- }
518
-
519
- function isOpenCodeEnabled(flags: OnboardFlags): boolean {
520
- return flags.opencode || flags.opencodeOnly;
521
- }
522
-
523
- function isMiMoEnabled(flags: OnboardFlags): boolean {
524
- return flags.mimo || flags.mimoOnly;
525
- }
526
-
527
- function hasOnlyAgentMcpTarget(flags: OnboardFlags): boolean {
528
- return flags.opencodeOnly || flags.mimoOnly;
529
- }
530
-
531
- function resolveOpenCodeConfigPath(flags: OnboardFlags): string {
532
- if (flags.opencodeConfig !== null) {
533
- return flags.opencodeConfig;
534
- }
535
-
536
- const configDir = join(homedir(), ".config", "opencode");
537
- const jsoncPath = join(configDir, "opencode.jsonc");
538
- if (existsSync(jsoncPath)) {
539
- return jsoncPath;
540
- }
541
- return join(configDir, "opencode.json");
542
- }
543
-
544
- function resolveMiMoConfigPath(flags: OnboardFlags): string {
545
- if (flags.mimoConfig !== null) {
546
- return flags.mimoConfig;
547
- }
548
-
549
- const configDir = join(homedir(), ".config", "mimocode");
550
- const jsoncPath = join(configDir, "mimocode.jsonc");
551
- if (existsSync(jsoncPath)) {
552
- return jsoncPath;
553
- }
554
-
555
- const jsonPath = join(configDir, "mimocode.json");
556
- if (existsSync(jsonPath)) {
557
- return jsonPath;
558
- }
559
-
560
- const legacyDir = join(homedir(), ".mimocode");
561
- const legacyJsoncPath = join(legacyDir, "config.jsonc");
562
- if (existsSync(legacyJsoncPath)) {
563
- return legacyJsoncPath;
564
- }
565
-
566
- const legacyJsonPath = join(legacyDir, "config.json");
567
- if (existsSync(legacyJsonPath)) {
568
- return legacyJsonPath;
569
- }
570
-
571
- return jsoncPath;
572
- }
573
-
574
- function onboardSelectionArguments(flags: OnboardFlags, target: OnboardTarget): string {
575
- const args: string[] = [];
576
- if (target.kind === "instance" && target.instanceName !== null) {
577
- args.push("--instance", target.instanceName);
578
- } else if (target.kind === "base-url") {
579
- const usedSharedBaseUrl =
580
- flags.baseUrl !== null &&
581
- flags.controlBaseUrl === null &&
582
- flags.agentBaseUrl === null &&
583
- flags.uiUrl === undefined;
584
- if (usedSharedBaseUrl) {
585
- args.push("--base-url", target.baseUrl);
586
- } else {
587
- args.push("--control-base-url", target.controlBaseUrl);
588
- args.push("--agent-base-url", target.agentBaseUrl);
589
- if (target.uiUrl === null) {
590
- args.push("--no-ui");
591
- } else {
592
- args.push("--ui-url", target.uiUrl);
593
- }
594
- }
595
- }
596
- if (flags.mcpName !== null) args.push("--mcp-name", target.mcpName);
597
- return args.length === 0 ? "" : ` ${args.join(" ")}`;
598
- }
599
-
600
- function openCodeTarget(flags: OnboardFlags, onboardTarget: OnboardTarget): AgentMcpConfigTarget {
601
- const setupAction = `agent-inspector onboard --opencode-only${onboardSelectionArguments(flags, onboardTarget)}`;
602
- return {
603
- label: "OpenCode",
604
- configLabel: "OpenCode MCP config",
605
- configPath: resolveOpenCodeConfigPath(flags),
606
- transport: flags.opencodeTransport,
607
- endpoint: flags.opencodeMcpUrl ?? onboardTarget.mcpUrl,
608
- mcpName: onboardTarget.mcpName,
609
- setupAction,
610
- forceAction: `${setupAction} --force`,
611
- verifyCommand: "opencode mcp list",
612
- invalidAction: `fix OpenCode JSON/JSONC, then rerun ${setupAction}`,
613
- configObjectName: `mcp.${onboardTarget.mcpName}`,
614
- defaultSchema: "https://opencode.ai/config.json",
615
- };
616
- }
617
-
618
- function miMoTarget(flags: OnboardFlags, onboardTarget: OnboardTarget): AgentMcpConfigTarget {
619
- const setupAction = `agent-inspector onboard --mimo-only${onboardSelectionArguments(flags, onboardTarget)}`;
620
- return {
621
- label: "MiMo Code",
622
- configLabel: "MiMo Code MCP config",
623
- configPath: resolveMiMoConfigPath(flags),
624
- transport: flags.mimoTransport,
625
- endpoint: flags.mimoMcpUrl ?? onboardTarget.mcpUrl,
626
- mcpName: onboardTarget.mcpName,
627
- setupAction,
628
- forceAction: `${setupAction} --force`,
629
- verifyCommand: "mimo mcp list",
630
- invalidAction: `fix MiMo Code JSON/JSONC, then rerun ${setupAction}`,
631
- configObjectName: `mcp.${onboardTarget.mcpName}`,
632
- defaultSchema: "https://mimo.xiaomi.com/mimocode/config.json",
633
- };
634
- }
635
-
636
- function stripJsoncComments(raw: string): string {
637
- let result = "";
638
- let index = 0;
639
- let inString = false;
640
- let stringChar = "";
641
-
642
- while (index < raw.length) {
643
- const ch = raw[index];
644
- const next = raw[index + 1];
645
-
646
- if (inString) {
647
- if (ch === "\\" && next !== undefined) {
648
- result += ch + next;
649
- index += 2;
650
- continue;
651
- }
652
- if (ch === stringChar) {
653
- inString = false;
654
- stringChar = "";
655
- }
656
- result += ch;
657
- index += 1;
658
- continue;
659
- }
660
-
661
- if (ch === '"' || ch === "'") {
662
- inString = true;
663
- stringChar = ch;
664
- result += ch;
665
- index += 1;
666
- continue;
667
- }
668
-
669
- if (ch === "/" && next === "/") {
670
- while (index < raw.length && raw[index] !== "\n") {
671
- index += 1;
672
- }
673
- continue;
674
- }
675
-
676
- if (ch === "/" && next === "*") {
677
- index += 2;
678
- while (index < raw.length - 1 && !(raw[index] === "*" && raw[index + 1] === "/")) {
679
- index += 1;
680
- }
681
- index += 2;
682
- continue;
683
- }
684
-
685
- result += ch;
686
- index += 1;
687
- }
688
-
689
- return result;
690
- }
691
-
692
- function readAgentConfig(path: string, target: AgentMcpConfigTarget): AgentConfigReadResult {
693
- if (!existsSync(path)) {
694
- return { ok: true, exists: false, config: {} };
695
- }
696
-
697
- try {
698
- const raw = readFileSync(path, "utf8");
699
- if (raw.trim().length === 0) {
700
- return { ok: true, exists: true, config: {} };
701
- }
702
- const parsed: unknown = JSON.parse(stripJsoncComments(raw));
703
- if (isObject(parsed)) {
704
- return { ok: true, exists: true, config: parsed };
705
- }
706
- return {
707
- ok: false,
708
- exists: true,
709
- message: `${target.label} config root must be a JSON object`,
710
- };
711
- } catch (err) {
712
- const message = err instanceof Error ? err.message : String(err);
713
- return {
714
- ok: false,
715
- exists: true,
716
- message,
717
- };
718
- }
719
- }
720
-
721
- function buildAgentMcpEntry(
722
- transport: AgentMcpTransport,
723
- endpoint: string,
724
- ): Record<string, unknown> {
725
- switch (transport) {
726
- case "local":
727
- return {
728
- type: "local",
729
- command: ["agent-inspector-mcp", "stdio", "--url", endpoint],
730
- enabled: true,
731
- };
732
- case "remote":
733
- return {
734
- type: "remote",
735
- url: endpoint,
736
- enabled: true,
737
- };
738
- default:
739
- return {
740
- type: "local",
741
- command: ["agent-inspector-mcp", "stdio", "--url", endpoint],
742
- enabled: true,
743
- };
744
- }
745
- }
746
-
747
- function stringArrayEquals(value: unknown, expected: readonly string[]): boolean {
748
- if (!Array.isArray(value) || value.length !== expected.length) {
749
- return false;
750
- }
751
-
752
- return value.every((item, index) => item === expected[index]);
753
- }
754
-
755
- function knownMcpEndpoints(endpoint: string): readonly string[] {
756
- return endpoint === DEFAULT_MCP_URL ? [DEFAULT_MCP_URL, LEGACY_MCP_URL] : [endpoint];
757
- }
758
-
759
- function isAgentLocalEntry(value: unknown, endpoint: string, ignoreEnabled: boolean): boolean {
760
- if (!isObject(value)) {
761
- return false;
762
- }
763
-
764
- const enabled = value["enabled"];
765
- if (!ignoreEnabled && enabled === false) {
766
- return false;
767
- }
768
-
769
- const env = value["environment"];
770
- const endpoints = knownMcpEndpoints(endpoint);
771
- const usesUrlArg = endpoints.some((candidate) =>
772
- stringArrayEquals(value["command"], ["agent-inspector-mcp", "stdio", "--url", candidate]),
773
- );
774
- const usesEnv =
775
- stringArrayEquals(value["command"], ["agent-inspector-mcp", "stdio"]) &&
776
- isObject(env) &&
777
- endpoints.some((candidate) => env["AGENT_INSPECTOR_MCP_URL"] === candidate);
778
-
779
- return value["type"] === "local" && (usesUrlArg || usesEnv);
780
- }
781
-
782
- function isAgentRemoteEntry(value: unknown, endpoint: string, ignoreEnabled: boolean): boolean {
783
- if (!isObject(value)) {
784
- return false;
785
- }
786
-
787
- const enabled = value["enabled"];
788
- if (!ignoreEnabled && enabled === false) {
789
- return false;
790
- }
791
-
792
- return (
793
- value["type"] === "remote" &&
794
- knownMcpEndpoints(endpoint).some((candidate) => value["url"] === candidate)
795
- );
796
- }
797
-
798
- function isKnownAgentEntry(value: unknown, endpoint: string, ignoreEnabled: boolean): boolean {
799
- return (
800
- isAgentLocalEntry(value, endpoint, ignoreEnabled) ||
801
- isAgentRemoteEntry(value, endpoint, ignoreEnabled)
802
- );
803
- }
804
-
805
- function detectAgentTransport(value: unknown): AgentMcpStatusTransport {
806
- if (!isObject(value)) {
807
- return "unknown";
808
- }
809
-
810
- switch (value["type"]) {
811
- case "local":
812
- return "local";
813
- case "remote":
814
- return "remote";
815
- default:
816
- return "unknown";
817
- }
818
- }
819
-
820
- function agentActionForStatus(target: AgentMcpConfigTarget, status: AgentMcpConfigStatus): string {
821
- switch (status.state) {
822
- case "missing":
823
- return target.setupAction;
824
- case "configured":
825
- return target.verifyCommand;
826
- case "disabled":
827
- case "custom":
828
- return target.forceAction;
829
- case "invalid":
830
- return target.invalidAction;
831
- default:
832
- return target.setupAction;
833
- }
834
- }
835
-
836
- function makeAgentStatus(
837
- target: AgentMcpConfigTarget,
838
- state: AgentMcpConfigState,
839
- transport: AgentMcpStatusTransport,
840
- detail: string,
841
- ): AgentMcpConfigStatus {
842
- const status: AgentMcpConfigStatus = {
843
- label: target.configLabel,
844
- path: target.configPath,
845
- state,
846
- transport,
847
- endpoint: target.endpoint,
848
- mcpName: target.mcpName,
849
- action: target.setupAction,
850
- forceAction: target.forceAction,
851
- verifyCommand: target.verifyCommand,
852
- detail,
853
- };
854
-
855
- return {
856
- ...status,
857
- action: agentActionForStatus(target, status),
858
- };
859
- }
860
-
861
- function getAgentEntry(config: Record<string, unknown>, mcpName: string): unknown {
862
- const mcp = config["mcp"];
863
- if (!isObject(mcp)) {
864
- return undefined;
865
- }
866
- return mcp[mcpName];
867
- }
868
-
869
- function buildAgentConfig(
870
- config: Record<string, unknown>,
871
- target: AgentMcpConfigTarget,
872
- ): Record<string, unknown> {
873
- const schema = typeof config["$schema"] === "string" ? config["$schema"] : target.defaultSchema;
874
- const nextConfig: Record<string, unknown> = {
875
- $schema: schema,
876
- };
877
-
878
- for (const [key, value] of Object.entries(config)) {
879
- if (key !== "$schema" && key !== "mcp") {
880
- nextConfig[key] = value;
881
- }
882
- }
883
-
884
- const currentMcp = config["mcp"];
885
- const nextMcp: Record<string, unknown> = isObject(currentMcp) ? { ...currentMcp } : {};
886
- nextMcp[target.mcpName] = buildAgentMcpEntry(target.transport, target.endpoint);
887
- nextConfig["mcp"] = nextMcp;
888
- return nextConfig;
889
- }
890
-
891
- function formatAgentConfig(config: Record<string, unknown>): string {
892
- return `${JSON.stringify(config, null, 2)}\n`;
893
- }
894
-
895
- function removeAgentEntry(
896
- config: Record<string, unknown>,
897
- mcpName: string,
898
- ): Record<string, unknown> {
899
- const nextConfig: Record<string, unknown> = {};
900
- for (const [key, value] of Object.entries(config)) {
901
- if (key !== "mcp") {
902
- nextConfig[key] = value;
903
- }
904
- }
905
-
906
- const currentMcp = config["mcp"];
907
- if (!isObject(currentMcp)) {
908
- return nextConfig;
909
- }
910
-
911
- const nextMcp: Record<string, unknown> = {};
912
- for (const [key, value] of Object.entries(currentMcp)) {
913
- if (key !== mcpName) {
914
- nextMcp[key] = value;
915
- }
916
- }
917
-
918
- if (Object.keys(nextMcp).length > 0) {
919
- nextConfig["mcp"] = nextMcp;
920
- }
921
- return nextConfig;
922
- }
923
-
924
- function readAgentStatus(target: AgentMcpConfigTarget): AgentMcpConfigStatus {
925
- const read = readAgentConfig(target.configPath, target);
926
- if (!read.ok) {
927
- return makeAgentStatus(target, "invalid", "unknown", read.message);
928
- }
929
-
930
- const entry = getAgentEntry(read.config, target.mcpName);
931
- if (entry === undefined) {
932
- const detail = read.exists
933
- ? `${target.label} config has no ${target.configObjectName}`
934
- : "Missing file";
935
- return makeAgentStatus(target, "missing", "unknown", detail);
936
- }
937
-
938
- const transport = detectAgentTransport(entry);
939
- if (isObject(entry) && entry["enabled"] === false) {
940
- return makeAgentStatus(
941
- target,
942
- "disabled",
943
- transport,
944
- `${target.configObjectName} is present but disabled`,
945
- );
946
- }
947
-
948
- if (isKnownAgentEntry(entry, target.endpoint, false)) {
949
- return makeAgentStatus(
950
- target,
951
- "configured",
952
- transport,
953
- `${target.configObjectName} points at Agent Inspector MCP`,
954
- );
955
- }
956
-
957
- return makeAgentStatus(
958
- target,
959
- "custom",
960
- transport,
961
- `${target.configObjectName} exists but does not match Agent Inspector defaults`,
962
- );
963
- }
964
-
965
- function buildAgentPlan(
966
- target: AgentMcpConfigTarget,
967
- uninstall: boolean,
968
- force: boolean,
969
- ): AgentMcpConfigPlan {
970
- const read = readAgentConfig(target.configPath, target);
971
- if (!read.ok) {
972
- return {
973
- status: makeAgentStatus(target, "invalid", "unknown", read.message),
974
- body: null,
975
- shouldWrite: false,
976
- shouldRemove: false,
977
- blockedMessage: `${target.label} config is invalid: ${read.message}`,
978
- };
979
- }
980
-
981
- const status = readAgentStatus(target);
982
- const entry = getAgentEntry(read.config, target.mcpName);
983
- const nextBody = formatAgentConfig(buildAgentConfig(read.config, target));
984
-
985
- if (uninstall) {
986
- const shouldRemove = entry !== undefined && isKnownAgentEntry(entry, target.endpoint, true);
987
- const removeBody = shouldRemove
988
- ? formatAgentConfig(removeAgentEntry(read.config, target.mcpName))
989
- : null;
990
- return {
991
- status,
992
- body: removeBody,
993
- shouldWrite: false,
994
- shouldRemove,
995
- blockedMessage: shouldRemove
996
- ? null
997
- : `${target.label} ${target.configObjectName} is missing or custom; preserved`,
998
- };
999
- }
1000
-
1001
- switch (status.state) {
1002
- case "configured":
1003
- return {
1004
- status,
1005
- body: nextBody,
1006
- shouldWrite: force,
1007
- shouldRemove: false,
1008
- blockedMessage: null,
1009
- };
1010
- case "missing":
1011
- return {
1012
- status,
1013
- body: nextBody,
1014
- shouldWrite: true,
1015
- shouldRemove: false,
1016
- blockedMessage: null,
1017
- };
1018
- case "custom":
1019
- case "disabled":
1020
- return {
1021
- status,
1022
- body: nextBody,
1023
- shouldWrite: force,
1024
- shouldRemove: false,
1025
- blockedMessage: force
1026
- ? null
1027
- : `${target.label} ${target.configObjectName} is custom or disabled; use --force to replace`,
1028
- };
1029
- case "invalid":
1030
- return {
1031
- status,
1032
- body: null,
1033
- shouldWrite: false,
1034
- shouldRemove: false,
1035
- blockedMessage: `${target.label} config is invalid`,
1036
- };
1037
- default:
1038
- return {
1039
- status,
1040
- body: null,
1041
- shouldWrite: false,
1042
- shouldRemove: false,
1043
- blockedMessage: `${target.label} config state is unknown`,
1044
- };
1045
- }
1046
- }
1047
-
1048
- function buildDetectedSummary(): string {
1049
- const entries = detectAll();
1050
- const present = entries.filter((e) => e.result.found);
1051
- const absent = entries.filter((e) => !e.result.found);
1052
- const presentList = present.map((e) => e.displayName).join(", ") || "(none)";
1053
- const absentList = absent.map((e) => e.displayName).join(", ") || "(none)";
1054
- return ` - Detected: ${presentList}\n - Not detected: ${absentList}`;
1055
- }
1056
-
1057
- function readPackageVersion(): string {
1058
- const packageJsonPaths = [
1059
- join(__dirname, "..", "package.json"),
1060
- join(__dirname, "..", "..", "package.json"),
1061
- ];
1062
-
1063
- try {
1064
- for (const packageJsonPath of packageJsonPaths) {
1065
- if (existsSync(packageJsonPath)) {
1066
- const raw: unknown = JSON.parse(readFileSync(packageJsonPath, "utf8"));
1067
- if (isObject(raw) && typeof raw["version"] === "string") {
1068
- return raw["version"];
1069
- }
1070
- }
1071
- }
1072
- } catch {
1073
- // best-effort: leave version as the fallback
1074
- }
1075
- return "0.0.0";
1076
- }
1077
-
1078
- function parseVersion(version: string): ParsedVersion | null {
1079
- const match = SEMVER_PATTERN.exec(version);
1080
- if (match === null) {
1081
- return null;
1082
- }
1083
-
1084
- const majorText = match[1];
1085
- const minorText = match[2];
1086
- const patchText = match[3];
1087
- if (majorText === undefined || minorText === undefined || patchText === undefined) {
1088
- return null;
1089
- }
1090
-
1091
- const major = Number(majorText);
1092
- const minor = Number(minorText);
1093
- const patch = Number(patchText);
1094
- if (!Number.isInteger(major) || !Number.isInteger(minor) || !Number.isInteger(patch)) {
1095
- return null;
1096
- }
1097
-
1098
- return { major, minor, patch };
1099
- }
1100
-
1101
- function compareVersions(left: string, right: string): number | null {
1102
- const leftVersion = parseVersion(left);
1103
- const rightVersion = parseVersion(right);
1104
- if (leftVersion === null || rightVersion === null) {
1105
- return null;
1106
- }
1107
-
1108
- const leftParts = [leftVersion.major, leftVersion.minor, leftVersion.patch];
1109
- const rightParts = [rightVersion.major, rightVersion.minor, rightVersion.patch];
1110
- for (let index = 0; index < leftParts.length; index++) {
1111
- const leftPart = leftParts[index];
1112
- const rightPart = rightParts[index];
1113
- if (leftPart === undefined || rightPart === undefined) {
1114
- return null;
1115
- }
1116
- if (leftPart > rightPart) {
1117
- return 1;
1118
- }
1119
- if (leftPart < rightPart) {
1120
- return -1;
1121
- }
1122
- }
1123
-
1124
- return 0;
1125
- }
1126
-
1127
- function extractGeneratedVersion(body: string): string | null {
1128
- const frontmatterMatch = FRONTMATTER_PATTERN.exec(body);
1129
- if (frontmatterMatch === null) {
1130
- return null;
1131
- }
1132
-
1133
- const frontmatter = frontmatterMatch[1];
1134
- if (frontmatter === undefined) {
1135
- return null;
1136
- }
1137
-
1138
- const versionMatch = GENERATED_VERSION_PATTERN.exec(frontmatter);
1139
- if (versionMatch === null) {
1140
- return null;
1141
- }
1142
-
1143
- return versionMatch[1] ?? null;
1144
- }
1145
-
1146
- function hasAgentInspectorAuthor(body: string): boolean {
1147
- const frontmatterMatch = FRONTMATTER_PATTERN.exec(body);
1148
- if (frontmatterMatch === null) {
1149
- return false;
1150
- }
1151
-
1152
- const frontmatter = frontmatterMatch[1];
1153
- if (frontmatter === undefined) {
1154
- return false;
1155
- }
1156
-
1157
- return /^\s*author:\s*agent-inspector\s*$/m.test(frontmatter);
1158
- }
1159
-
1160
- function readGeneratedVersion(path: string): string | null {
1161
- try {
1162
- return extractGeneratedVersion(readFileSync(path, "utf8"));
1163
- } catch {
1164
- return null;
1165
- }
1166
- }
1167
-
1168
- function isMatchingGeneratedFile(path: string, currentVersion: string): boolean {
1169
- try {
1170
- const body = readFileSync(path, "utf8");
1171
- return hasAgentInspectorAuthor(body) && extractGeneratedVersion(body) === currentVersion;
1172
- } catch {
1173
- return false;
1174
- }
1175
- }
1176
-
1177
- function readGeneratedFileStatus(file: PlannedFile, currentVersion: string): GeneratedFileStatus {
1178
- if (!existsSync(file.path)) {
1179
- return {
1180
- label: file.label,
1181
- path: file.path,
1182
- state: "missing",
1183
- version: null,
1184
- action: actionForStatus(file.label, "missing"),
1185
- };
1186
- }
1187
-
1188
- try {
1189
- const body = readFileSync(file.path, "utf8");
1190
- const version = extractGeneratedVersion(body);
1191
- if (!hasAgentInspectorAuthor(body) || version === null) {
1192
- return {
1193
- label: file.label,
1194
- path: file.path,
1195
- state: "custom",
1196
- version,
1197
- action: actionForStatus(file.label, "custom"),
1198
- };
1199
- }
1200
-
1201
- const comparison = compareVersions(version, currentVersion);
1202
- if (comparison === null) {
1203
- return {
1204
- label: file.label,
1205
- path: file.path,
1206
- state: "custom",
1207
- version,
1208
- action: actionForStatus(file.label, "custom"),
1209
- };
1210
- }
1211
- if (comparison < 0) {
1212
- return {
1213
- label: file.label,
1214
- path: file.path,
1215
- state: "outdated",
1216
- version,
1217
- action: actionForStatus(file.label, "outdated"),
1218
- };
1219
- }
1220
- if (comparison > 0) {
1221
- return {
1222
- label: file.label,
1223
- path: file.path,
1224
- state: "newer",
1225
- version,
1226
- action: actionForStatus(file.label, "newer"),
1227
- };
1228
- }
1229
-
1230
- return {
1231
- label: file.label,
1232
- path: file.path,
1233
- state: "current",
1234
- version,
1235
- action: actionForStatus(file.label, "current"),
1236
- };
1237
- } catch {
1238
- return {
1239
- label: file.label,
1240
- path: file.path,
1241
- state: "custom",
1242
- version: null,
1243
- action: actionForStatus(file.label, "custom"),
1244
- };
1245
- }
1246
- }
1247
-
1248
- function buildPlannedFiles(
1249
- flags: OnboardFlags,
1250
- targets: OnboardTargets,
1251
- version: string,
1252
- onboardTarget: OnboardTarget,
1253
- ): PlannedFile[] {
1254
- const installClaude = !flags.codexOnly && !hasOnlyAgentMcpTarget(flags);
1255
- const installCodex = !flags.skipCodexSkill && !hasOnlyAgentMcpTarget(flags);
1256
- const detectedSummary = installClaude ? buildDetectedSummary() : "";
1257
- const targetArguments = onboardSelectionArguments(flags, onboardTarget);
1258
- const claudeSkillBody = installClaude
1259
- ? renderSkillOnboard({
1260
- version,
1261
- port: onboardTarget.port,
1262
- baseUrl: onboardTarget.baseUrl,
1263
- controlBaseUrl: onboardTarget.controlBaseUrl,
1264
- agentBaseUrl: onboardTarget.agentBaseUrl,
1265
- uiUrl: onboardTarget.uiUrl,
1266
- mcpName: onboardTarget.mcpName,
1267
- targetKind: onboardTarget.kind,
1268
- instanceName: onboardTarget.instanceName,
1269
- onboardTargetArguments: targetArguments,
1270
- detectedSummary,
1271
- })
1272
- : "";
1273
- const commandBody = installClaude ? renderCommandOnboard({ version }) : "";
1274
- const codexSkillBody = installCodex
1275
- ? renderCodexSkillOnboard({
1276
- version,
1277
- port: onboardTarget.port,
1278
- baseUrl: onboardTarget.baseUrl,
1279
- controlBaseUrl: onboardTarget.controlBaseUrl,
1280
- agentBaseUrl: onboardTarget.agentBaseUrl,
1281
- uiUrl: onboardTarget.uiUrl,
1282
- mcpName: onboardTarget.mcpName,
1283
- targetKind: onboardTarget.kind,
1284
- instanceName: onboardTarget.instanceName,
1285
- onboardTargetArguments: targetArguments,
1286
- })
1287
- : "";
1288
-
1289
- return [
1290
- {
1291
- label: "Claude skill",
1292
- path: targets.claudeSkillFile,
1293
- body: claudeSkillBody,
1294
- enabled: installClaude,
1295
- },
1296
- {
1297
- label: "Claude command",
1298
- path: targets.claudeCommandFile,
1299
- body: commandBody,
1300
- enabled: installClaude,
1301
- },
1302
- {
1303
- label: "Codex skill",
1304
- path: targets.codexSkillFile,
1305
- body: codexSkillBody,
1306
- enabled: installCodex,
1307
- },
1308
- ];
1309
- }
1310
-
1311
- function shouldWrite(file: PlannedFile, force: boolean, currentVersion: string): boolean {
1312
- if (!file.enabled) {
1313
- return false;
1314
- }
1315
- if (force || !existsSync(file.path)) {
1316
- return true;
1317
- }
1318
-
1319
- const existingVersion = readGeneratedVersion(file.path);
1320
- if (existingVersion === null) {
1321
- return false;
1322
- }
1323
-
1324
- const comparison = compareVersions(existingVersion, currentVersion);
1325
- return comparison !== null && comparison < 0;
1326
- }
1327
-
1328
- function shouldUninstall(file: PlannedFile, currentVersion: string): boolean {
1329
- return (
1330
- file.enabled && existsSync(file.path) && isMatchingGeneratedFile(file.path, currentVersion)
1331
- );
1332
- }
1333
-
1334
- function removeEmptyDirectory(path: string): void {
1335
- try {
1336
- if (readdirSync(path).length === 0) {
1337
- rmdirSync(path);
1338
- }
1339
- } catch {
1340
- // best-effort cleanup only
1341
- }
1342
- }
1343
-
1344
- function runUninstall(
1345
- plannedFiles: readonly PlannedFile[],
1346
- currentVersion: string,
1347
- dryRun: boolean,
1348
- agentPlans: readonly AgentMcpConfigPlan[],
1349
- ): number {
1350
- const enabledFiles = plannedFiles.filter((file) => file.enabled);
1351
- const filesToRemove = enabledFiles.filter((file) => shouldUninstall(file, currentVersion));
1352
-
1353
- if (dryRun) {
1354
- process.stdout.write(`agent-inspector onboard --uninstall --dry-run\n\n`);
1355
- for (const file of enabledFiles) {
1356
- const status = shouldUninstall(file, currentVersion) ? "matching" : "skipped";
1357
- process.stdout.write(`${file.label}: ${file.path} (${status})\n`);
1358
- }
1359
- for (const plan of agentPlans) {
1360
- const status = plan.shouldRemove ? "matching" : "skipped";
1361
- process.stdout.write(`${plan.status.label}: ${plan.status.path} (${status})\n`);
1362
- if (plan.blockedMessage !== null) {
1363
- process.stdout.write(` ${plan.blockedMessage}\n`);
1364
- }
1365
- }
1366
- process.stdout.write(`\nNo files were removed.\n`);
1367
- return 0;
1368
- }
1369
-
1370
- const hasAgentConfigToRemove = agentPlans.some((plan) => plan.shouldRemove);
1371
- if (filesToRemove.length === 0 && !hasAgentConfigToRemove) {
1372
- process.stdout.write(
1373
- "agent-inspector onboard: no generated onboarding files match this package version\n",
1374
- );
1375
- for (const plan of agentPlans) {
1376
- if (plan.blockedMessage !== null) {
1377
- process.stdout.write(`${plan.blockedMessage}\n`);
1378
- }
1379
- }
1380
- return 0;
1381
- }
1382
-
1383
- try {
1384
- for (const file of filesToRemove) {
1385
- unlinkSync(file.path);
1386
- removeEmptyDirectory(dirname(file.path));
1387
- process.stdout.write(`Removed ${file.label}: ${file.path}\n`);
1388
- }
1389
- for (const plan of agentPlans) {
1390
- if (plan.shouldRemove && plan.body !== null) {
1391
- mkdirSync(dirname(plan.status.path), { recursive: true });
1392
- writeFileSync(plan.status.path, plan.body, "utf8");
1393
- process.stdout.write(`Removed ${plan.status.label} entry from: ${plan.status.path}\n`);
1394
- }
1395
- }
1396
- } catch (err) {
1397
- const msg = err instanceof Error ? err.message : String(err);
1398
- process.stderr.write(`agent-inspector onboard: failed to remove files: ${msg}\n`);
1399
- return 1;
1400
- }
1401
-
1402
- return 0;
1403
- }
1404
-
1405
- function formatStatusVersion(status: GeneratedFileStatus): string {
1406
- return status.version ?? "-";
1407
- }
1408
-
1409
- function summarizeStatusAction(
1410
- statuses: readonly GeneratedFileStatus[],
1411
- agentStatuses: readonly AgentMcpConfigStatus[],
1412
- ): string {
1413
- const actionable = statuses.filter(
1414
- (status) => status.state === "missing" || status.state === "outdated",
1415
- );
1416
- const actions = actionable.map((status) => status.action);
1417
- for (const agentStatus of agentStatuses) {
1418
- if (agentStatus.state === "missing") {
1419
- actions.push(agentStatus.action);
1420
- }
1421
- }
1422
- if (actions.length > 0) {
1423
- const uniqueActions = Array.from(new Set(actions));
1424
- return `Run: ${uniqueActions.join(" && ")}`;
1425
- }
1426
- for (const agentStatus of agentStatuses) {
1427
- if (
1428
- agentStatus.state === "custom" ||
1429
- agentStatus.state === "disabled" ||
1430
- agentStatus.state === "invalid"
1431
- ) {
1432
- return `${agentStatus.label} needs review: ${agentStatus.action}`;
1433
- }
1434
- }
1435
- if (statuses.some((status) => status.state === "custom")) {
1436
- return "Custom files are preserved. Use --force only if you want to replace them.";
1437
- }
1438
- if (statuses.some((status) => status.state === "newer")) {
1439
- return "Installed files are newer than this package. No action needed.";
1440
- }
1441
- return "All selected onboarding files are current.";
1442
- }
1443
-
1444
- function runStatus(
1445
- plannedFiles: readonly PlannedFile[],
1446
- currentVersion: string,
1447
- json: boolean,
1448
- agentStatuses: readonly AgentMcpConfigStatus[],
1449
- ): number {
1450
- const enabledFiles = plannedFiles.filter((file) => file.enabled);
1451
- const statuses = enabledFiles.map((file) => readGeneratedFileStatus(file, currentVersion));
1452
- const summary = summarizeStatusAction(statuses, agentStatuses);
1453
- const opencodeConfig =
1454
- agentStatuses.find((status) => status.label === "OpenCode MCP config") ?? null;
1455
- const mimoConfig =
1456
- agentStatuses.find((status) => status.label === "MiMo Code MCP config") ?? null;
1457
-
1458
- if (json) {
1459
- process.stdout.write(
1460
- `${JSON.stringify(
1461
- {
1462
- packageVersion: currentVersion,
1463
- files: statuses,
1464
- opencodeConfig,
1465
- mimoConfig,
1466
- suggestedAction: summary,
1467
- },
1468
- null,
1469
- 2,
1470
- )}\n`,
1471
- );
1472
- return 0;
1473
- }
1474
-
1475
- process.stdout.write(`agent-inspector onboard status\n`);
1476
- process.stdout.write(`Package version: ${currentVersion}\n\n`);
1477
-
1478
- for (const status of statuses) {
1479
- process.stdout.write(`${status.label}: ${status.state}`);
1480
- process.stdout.write(`, version ${formatStatusVersion(status)}\n`);
1481
- process.stdout.write(` ${status.path}\n`);
1482
- process.stdout.write(` Action: ${status.action}\n`);
1483
- }
1484
-
1485
- for (const agentStatus of agentStatuses) {
1486
- process.stdout.write(`${agentStatus.label}: ${agentStatus.state}`);
1487
- process.stdout.write(`, transport ${agentStatus.transport}\n`);
1488
- process.stdout.write(` ${agentStatus.path}\n`);
1489
- process.stdout.write(` MCP key: ${agentStatus.mcpName}\n`);
1490
- process.stdout.write(` Endpoint: ${agentStatus.endpoint}\n`);
1491
- process.stdout.write(` Detail: ${agentStatus.detail}\n`);
1492
- process.stdout.write(` Action: ${agentStatus.action}\n`);
1493
- }
1494
-
1495
- process.stdout.write(`\nSuggested action: ${summary}\n`);
1496
- return 0;
1497
- }
1498
-
1499
- export function runOnboard(argv: readonly string[]): Promise<number> {
1500
- try {
1501
- return Promise.resolve(runOnboardSync(argv));
1502
- } catch (err) {
1503
- // Last-resort safety net: report setup failures without blocking normal CLI use.
1504
- const msg = err instanceof Error ? err.message : String(err);
1505
- process.stderr.write(`agent-inspector onboard: ${msg}\n`);
1506
- process.stderr.write("(run `agent-inspector onboard` again after fixing the issue)\n");
1507
- return Promise.resolve(0);
1508
- }
1509
- }
1510
-
1511
- function runOnboardSync(argv: readonly string[]): number {
1512
- const flags = parseFlags(argv);
1513
- const resolvedTarget = resolveOnboardTarget({
1514
- instanceName: flags.instanceName,
1515
- baseUrl: flags.baseUrl,
1516
- controlBaseUrl: flags.controlBaseUrl,
1517
- agentBaseUrl: flags.agentBaseUrl,
1518
- uiUrl: flags.uiUrl,
1519
- mcpName: flags.mcpName,
1520
- });
1521
- if (!resolvedTarget.ok) {
1522
- process.stderr.write(`agent-inspector onboard: ${resolvedTarget.message}\n`);
1523
- return 2;
1524
- }
1525
- const onboardTarget = resolvedTarget.target;
1526
- const targets = resolveTargets(flags);
1527
- const version = readPackageVersion();
1528
- const plannedFiles = buildPlannedFiles(flags, targets, version, onboardTarget);
1529
- const enabledFiles = plannedFiles.filter((file) => file.enabled);
1530
- const agentPlans: AgentMcpConfigPlan[] = [];
1531
- if (isOpenCodeEnabled(flags)) {
1532
- agentPlans.push(
1533
- buildAgentPlan(openCodeTarget(flags, onboardTarget), flags.uninstall, flags.force),
1534
- );
1535
- }
1536
- if (isMiMoEnabled(flags)) {
1537
- agentPlans.push(buildAgentPlan(miMoTarget(flags, onboardTarget), flags.uninstall, flags.force));
1538
- }
1539
- const agentStatuses = agentPlans.map((plan) => plan.status);
1540
-
1541
- if (flags.json && !flags.status) {
1542
- process.stderr.write("agent-inspector onboard: --json is only supported with --status\n");
1543
- return 2;
1544
- }
1545
-
1546
- if (enabledFiles.length === 0 && agentPlans.length === 0) {
1547
- process.stderr.write("agent-inspector onboard: no onboarding target selected\n");
1548
- return 2;
1549
- }
1550
-
1551
- if (flags.status) {
1552
- return runStatus(plannedFiles, version, flags.json, agentStatuses);
1553
- }
1554
-
1555
- if (flags.uninstall) {
1556
- return runUninstall(plannedFiles, version, flags.dryRun, agentPlans);
1557
- }
1558
-
1559
- if (flags.dryRun) {
1560
- process.stdout.write(`agent-inspector onboard --dry-run\n\n`);
1561
- for (const file of enabledFiles) {
1562
- const status = existsSync(file.path) ? "exists" : "missing";
1563
- process.stdout.write(`${file.label}: ${file.path} (${status})\n`);
1564
- }
1565
- for (const plan of agentPlans) {
1566
- process.stdout.write(`${plan.status.label}: ${plan.status.path} (${plan.status.state})\n`);
1567
- process.stdout.write(` Transport: ${plan.status.transport}\n`);
1568
- process.stdout.write(` MCP key: ${plan.status.mcpName}\n`);
1569
- process.stdout.write(` Endpoint: ${plan.status.endpoint}\n`);
1570
- process.stdout.write(` Action: ${plan.status.action}\n`);
1571
- if (plan.blockedMessage !== null) {
1572
- process.stdout.write(` ${plan.blockedMessage}\n`);
1573
- }
1574
- }
1575
- process.stdout.write(`\nClaude skill headings:\n`);
1576
- if (!flags.codexOnly && !hasOnlyAgentMcpTarget(flags)) {
1577
- for (const heading of REQUIRED_PHASE_HEADINGS) {
1578
- process.stdout.write(` - ${heading}\n`);
1579
- }
1580
- } else {
1581
- process.stdout.write(` (disabled by selected targets)\n`);
1582
- }
1583
- process.stdout.write(`\nCodex skill headings:\n`);
1584
- if (!flags.skipCodexSkill && !hasOnlyAgentMcpTarget(flags)) {
1585
- for (const heading of REQUIRED_CODEX_PHASE_HEADINGS) {
1586
- process.stdout.write(` - ${heading}\n`);
1587
- }
1588
- } else {
1589
- process.stdout.write(` (disabled by selected targets)\n`);
1590
- }
1591
- if (!flags.codexOnly && !hasOnlyAgentMcpTarget(flags)) {
1592
- process.stdout.write(`\nDetected tools:\n${buildDetectedSummary()}\n`);
1593
- }
1594
- process.stdout.write(`\nNo files were written.\n`);
1595
- return 0;
1596
- }
1597
-
1598
- const filesToWrite = plannedFiles.filter((file) => shouldWrite(file, flags.force, version));
1599
- const agentPlansToWrite = agentPlans.filter((plan) => plan.shouldWrite && plan.body !== null);
1600
- for (const plan of agentPlans) {
1601
- if (plan.status.state === "invalid") {
1602
- process.stderr.write(`agent-inspector onboard: ${plan.blockedMessage ?? "invalid"}\n`);
1603
- return 1;
1604
- }
1605
- }
1606
- if (filesToWrite.length === 0 && agentPlansToWrite.length === 0) {
1607
- process.stdout.write(
1608
- "agent-inspector onboard: all selected onboarding files are already up to date\n",
1609
- );
1610
- for (const plan of agentPlans) {
1611
- if (plan.blockedMessage !== null) {
1612
- process.stdout.write(`${plan.blockedMessage}\n`);
1613
- }
1614
- }
1615
- process.stdout.write("Re-run with --force to refresh.\n");
1616
- return 0;
1617
- }
1618
-
1619
- try {
1620
- for (const file of filesToWrite) {
1621
- mkdirSync(dirname(file.path), { recursive: true });
1622
- writeFileSync(file.path, file.body, "utf8");
1623
- }
1624
- for (const plan of agentPlansToWrite) {
1625
- if (plan.body !== null) {
1626
- mkdirSync(dirname(plan.status.path), { recursive: true });
1627
- writeFileSync(plan.status.path, plan.body, "utf8");
1628
- }
1629
- }
1630
- } catch (err) {
1631
- const msg = err instanceof Error ? err.message : String(err);
1632
- process.stderr.write(`agent-inspector onboard: failed to write files: ${msg}\n`);
1633
- return 1;
1634
- }
1635
-
1636
- const firstTool = detectFirst();
1637
- const toolHint = firstTool !== null ? firstTool.displayName : "no known tool detected";
1638
-
1639
- for (const file of filesToWrite) {
1640
- process.stdout.write(`Installed/updated ${file.label} to: ${file.path}\n`);
1641
- }
1642
- for (const plan of agentPlansToWrite) {
1643
- process.stdout.write(`Installed/updated ${plan.status.label}: ${plan.status.path}\n`);
1644
- }
1645
- process.stdout.write(`\nNext steps:\n`);
1646
- if (!flags.codexOnly && !hasOnlyAgentMcpTarget(flags)) {
1647
- process.stdout.write(` - Open Claude Code and run: /agent-inspector:onboard\n`);
1648
- }
1649
- if (!flags.skipCodexSkill && !hasOnlyAgentMcpTarget(flags)) {
1650
- process.stdout.write(` - Open Codex and ask to use the agent-inspector-onboard skill\n`);
1651
- }
1652
- for (const plan of agentPlans) {
1653
- process.stdout.write(` - Verify ${plan.status.label}: ${plan.status.verifyCommand}\n`);
1654
- }
1655
- if (hasOnlyAgentMcpTarget(flags)) {
1656
- const refreshActions = agentPlans.map((plan) => plan.status.forceAction);
1657
- const uniqueRefreshActions = Array.from(new Set(refreshActions));
1658
- const refresh =
1659
- uniqueRefreshActions.length > 0
1660
- ? uniqueRefreshActions.join(" && ")
1661
- : "agent-inspector onboard --force";
1662
- process.stdout.write(` - Refresh selected MCP config later: ${refresh}\n`);
1663
- } else {
1664
- process.stdout.write(` - Refresh later: agent-inspector onboard --force\n`);
1665
- process.stdout.write(` - Detected primary tool: ${toolHint}\n`);
1666
- }
1667
- return 0;
1668
- }