@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
@@ -1,123 +0,0 @@
1
- import {
2
- writeFileSync,
3
- readFileSync,
4
- unlinkSync,
5
- existsSync,
6
- renameSync,
7
- copyFileSync,
8
- } from "node:fs";
9
- import { join, isAbsolute } from "node:path";
10
- import { logger } from "./logger";
11
- import { z } from "zod";
12
- import { JsonValueSchema, type StreamingChunk } from "./schemas";
13
- import { getDataDir } from "./dataDir";
14
- import {
15
- ensurePrivateDirectorySync,
16
- PRIVATE_FILE_MODE,
17
- securePrivateFileSync,
18
- } from "./privateDataPath";
19
-
20
- export type StreamingChunksData = {
21
- chunks: StreamingChunk[];
22
- truncated?: boolean;
23
- };
24
-
25
- const StreamingChunkSchema: z.ZodType<StreamingChunk> = z.object({
26
- index: z.number(),
27
- timestamp: z.number(),
28
- type: z.string(),
29
- data: JsonValueSchema,
30
- });
31
-
32
- const StreamingChunksDataSchema = z.object({
33
- chunks: z.array(StreamingChunkSchema),
34
- truncated: z.boolean().optional(),
35
- });
36
-
37
- export function getChunksDir(): string {
38
- const chunksDirEnv = process.env["CHUNKS_DIR"];
39
- if (chunksDirEnv !== undefined && chunksDirEnv !== "") {
40
- return isAbsolute(chunksDirEnv) ? chunksDirEnv : join(getDataDir(), chunksDirEnv);
41
- }
42
- return join(getDataDir(), "chunks");
43
- }
44
-
45
- function getChunkFilePath(logId: number): string {
46
- return join(getChunksDir(), `${logId}.json`);
47
- }
48
-
49
- function getTempFilePath(logId: number): string {
50
- return join(getChunksDir(), `.${logId}.tmp`);
51
- }
52
-
53
- /**
54
- * Write chunks to disk atomically: write to temp file first, then rename.
55
- * Returns the absolute path to the written chunk file.
56
- */
57
- export function writeChunks(logId: number, chunks: StreamingChunk[], truncated?: boolean): string {
58
- const dir = getChunksDir();
59
- const targetPath = getChunkFilePath(logId);
60
- const tempPath = getTempFilePath(logId);
61
-
62
- // Ensure directory exists
63
- if (!ensurePrivateDirectorySync(dir)) {
64
- logger.error("[chunkStorage] Failed to secure chunks directory:", dir);
65
- return targetPath;
66
- }
67
-
68
- const data: StreamingChunksData = { chunks, truncated };
69
-
70
- // Write to temp file first
71
- try {
72
- writeFileSync(tempPath, JSON.stringify(data), {
73
- encoding: "utf-8",
74
- mode: PRIVATE_FILE_MODE,
75
- });
76
- if (!securePrivateFileSync(tempPath)) {
77
- unlinkSync(tempPath);
78
- logger.error("[chunkStorage] Failed to secure chunks temp file:", tempPath);
79
- return targetPath;
80
- }
81
- } catch (err) {
82
- logger.error("[chunkStorage] Failed to write chunks temp file:", String(err));
83
- return targetPath;
84
- }
85
-
86
- // Rename to target (atomic on most filesystems)
87
- try {
88
- renameSync(tempPath, targetPath);
89
- } catch (err) {
90
- logger.warn("[chunkStorage] Rename failed, falling back to copy+delete:", String(err));
91
- // If rename fails, try copy + delete
92
- try {
93
- copyFileSync(tempPath, targetPath);
94
- if (!securePrivateFileSync(targetPath)) {
95
- logger.error("[chunkStorage] Failed to secure chunks file:", targetPath);
96
- }
97
- unlinkSync(tempPath);
98
- } catch (copyErr) {
99
- logger.error("[chunkStorage] Failed to copy chunks file:", String(copyErr));
100
- }
101
- }
102
-
103
- return targetPath;
104
- }
105
-
106
- /**
107
- * Read chunks from a chunk file path.
108
- * Returns null if the file does not exist or cannot be read.
109
- */
110
- export function readChunks(path: string): StreamingChunksData | null {
111
- if (!existsSync(path)) {
112
- return null;
113
- }
114
- try {
115
- const content = readFileSync(path, "utf-8");
116
- const parsed: unknown = JSON.parse(content);
117
- const result = StreamingChunksDataSchema.safeParse(parsed);
118
- if (!result.success) return null;
119
- return result.data;
120
- } catch {
121
- return null;
122
- }
123
- }
@@ -1,218 +0,0 @@
1
- import { writeFileSync, readFileSync, unlinkSync, existsSync, renameSync } from "node:fs";
2
- import { join } from "node:path";
3
- import { logger } from "./logger";
4
- import { getDataDir } from "./dataDir";
5
- import {
6
- ensurePrivateDirectorySync,
7
- PRIVATE_FILE_MODE,
8
- securePrivateFileSync,
9
- } from "./privateDataPath";
10
- import {
11
- CaptureModeSchema,
12
- DEFAULT_CAPTURE_MODE,
13
- DEFAULT_PROVIDER_TEST_TIMEOUT_SECONDS,
14
- DEFAULT_SLOW_RESPONSE_THRESHOLD_SECONDS,
15
- DEFAULT_TIME_DISPLAY_FORMAT,
16
- RuntimeConfigSchema,
17
- type CaptureMode,
18
- type RuntimeConfig,
19
- } from "../lib/runtimeConfig";
20
-
21
- // Re-export so server-side callers (api/config.ts, tests) keep the
22
- // existing import path `from "../../proxy/config"`.
23
- export { RuntimeConfigSchema };
24
- export type { RuntimeConfig };
25
-
26
- /**
27
- * Runtime-mutable server config. Includes proxy behavior flags and UI tuning
28
- * settings that should take effect without restarting the dev server. The API
29
- * layer reads and writes the same object via `getConfig` / `setConfig`.
30
- *
31
- * Boot-time precedence (first match wins):
32
- * 1. `data/config.json` on disk (persisted state)
33
- * 2. `AGENT_INSPECTOR_STRIP_CLAUDE_CODE_BILLING_HEADER` env var
34
- * 3. `false` (off by default, to keep the proxy transparent)
35
- *
36
- * The env var is read once at module init; changing it requires a restart.
37
- * Once the user has saved a value via the API, the persisted file takes
38
- * precedence over the env var for the lifetime of the process.
39
- */
40
-
41
- // --- Persistence ---
42
-
43
- function getConfigFilePath(): string {
44
- return join(getDataDir(), "config.json");
45
- }
46
-
47
- function getConfigTempPath(): string {
48
- return join(getDataDir(), "config.json.tmp");
49
- }
50
-
51
- // --- Module state ---
52
-
53
- // Internal: writeable singleton. Read via getConfig(), mutate via setConfig().
54
- let currentConfig: RuntimeConfig = resolveInitialConfig();
55
-
56
- type MutableRuntimeConfig = Omit<RuntimeConfig, "captureMode">;
57
-
58
- function resolveInitialCaptureMode(): CaptureMode {
59
- const value = process.env["AGENT_INSPECTOR_CAPTURE_MODE"] ?? process.env["AGENT_INSPECTOR_MODE"];
60
- if (value === undefined || value === "") return DEFAULT_CAPTURE_MODE;
61
-
62
- const result = CaptureModeSchema.safeParse(value);
63
- if (result.success) return result.data;
64
-
65
- logger.warn(`[config] Invalid capture mode ${value}; falling back to ${DEFAULT_CAPTURE_MODE}`);
66
- return DEFAULT_CAPTURE_MODE;
67
- }
68
-
69
- function resolveInitialConfig(): RuntimeConfig {
70
- const captureMode = resolveInitialCaptureMode();
71
-
72
- // 1. Persisted file
73
- const filePath = getConfigFilePath();
74
- if (existsSync(filePath)) {
75
- try {
76
- const content = readFileSync(filePath, "utf-8");
77
- const parsed: unknown = JSON.parse(content);
78
- const result = RuntimeConfigSchema.safeParse(parsed);
79
- if (result.success) {
80
- logger.info(`[config] Loaded persisted config from ${filePath}`);
81
- return { ...result.data, captureMode };
82
- }
83
- logger.warn(
84
- `[config] Persisted config at ${filePath} is invalid; falling back to env/default`,
85
- );
86
- } catch (err) {
87
- logger.warn(
88
- `[config] Failed to read persisted config at ${filePath}: ${String(err)}; falling back to env/default`,
89
- );
90
- }
91
- }
92
-
93
- // 2. Env var
94
- if (process.env["AGENT_INSPECTOR_STRIP_CLAUDE_CODE_BILLING_HEADER"] === "1") {
95
- return {
96
- stripClaudeCodeBillingHeader: true,
97
- hasSeenOnboarding: false,
98
- slowResponseThresholdSeconds: DEFAULT_SLOW_RESPONSE_THRESHOLD_SECONDS,
99
- providerTestTimeoutSeconds: DEFAULT_PROVIDER_TEST_TIMEOUT_SECONDS,
100
- timeDisplayFormat: DEFAULT_TIME_DISPLAY_FORMAT,
101
- captureMode,
102
- };
103
- }
104
-
105
- // 3. Default off
106
- return {
107
- stripClaudeCodeBillingHeader: false,
108
- hasSeenOnboarding: false,
109
- slowResponseThresholdSeconds: DEFAULT_SLOW_RESPONSE_THRESHOLD_SECONDS,
110
- providerTestTimeoutSeconds: DEFAULT_PROVIDER_TEST_TIMEOUT_SECONDS,
111
- timeDisplayFormat: DEFAULT_TIME_DISPLAY_FORMAT,
112
- captureMode,
113
- };
114
- }
115
-
116
- /**
117
- * Returns the current config. Synchronous; safe to call on the hot path.
118
- */
119
- export function getConfig(): RuntimeConfig {
120
- return currentConfig;
121
- }
122
-
123
- /**
124
- * Applies a partial update after atomically persisting it to disk.
125
- * Returns the updated full config on success or null when persistence
126
- * fails. A failed write leaves both the in-memory value and the existing
127
- * on-disk value unchanged.
128
- */
129
- export function setConfig(patch: Partial<MutableRuntimeConfig>): RuntimeConfig | null {
130
- const next: RuntimeConfig = {
131
- ...currentConfig,
132
- ...patch,
133
- captureMode: currentConfig.captureMode,
134
- };
135
- if (!persistConfig(next)) return null;
136
- currentConfig = next;
137
- return next;
138
- }
139
-
140
- /**
141
- * For tests: reset the in-memory config to a known value without
142
- * touching disk. Use `setConfig` in production code.
143
- */
144
- export function _resetConfigForTests(value: RuntimeConfig): void {
145
- currentConfig = value;
146
- }
147
-
148
- /**
149
- * For tests: re-run the boot-time resolution against the current env vars
150
- * and the on-disk config file, and update the in-memory value. Use this to
151
- * test env-var precedence without having to reload the module.
152
- */
153
- export function _rebootForTests(): void {
154
- currentConfig = resolveInitialConfig();
155
- }
156
-
157
- // --- Atomic write ---
158
-
159
- /**
160
- * Atomic write: secure temp file + rename in the same directory.
161
- * Returns true on success, false on failure (logged but not thrown). There is
162
- * deliberately no copy fallback because replacing the target through a copy
163
- * could expose a partially written config after a crash.
164
- */
165
- function persistConfig(value: RuntimeConfig): boolean {
166
- const dir = getDataDir();
167
- const targetPath = getConfigFilePath();
168
- const tempPath = getConfigTempPath();
169
-
170
- if (!ensurePrivateDirectorySync(dir)) {
171
- logger.error(`[config] Failed to secure data directory ${dir}`);
172
- return false;
173
- }
174
-
175
- try {
176
- writeFileSync(tempPath, JSON.stringify(toPersistedConfig(value)), {
177
- encoding: "utf-8",
178
- mode: PRIVATE_FILE_MODE,
179
- flush: true,
180
- });
181
- if (!securePrivateFileSync(tempPath)) {
182
- removeConfigTempFile(tempPath);
183
- logger.error(`[config] Failed to secure config temp file ${tempPath}`);
184
- return false;
185
- }
186
- } catch (err) {
187
- removeConfigTempFile(tempPath);
188
- logger.error(`[config] Failed to write config temp file: ${String(err)}`);
189
- return false;
190
- }
191
-
192
- try {
193
- renameSync(tempPath, targetPath);
194
- return true;
195
- } catch (err) {
196
- removeConfigTempFile(tempPath);
197
- logger.error(`[config] Failed to atomically replace config file: ${String(err)}`);
198
- return false;
199
- }
200
- }
201
-
202
- function removeConfigTempFile(tempPath: string): void {
203
- try {
204
- unlinkSync(tempPath);
205
- } catch {
206
- // Best effort. A stale temp path is never read as runtime configuration.
207
- }
208
- }
209
-
210
- function toPersistedConfig(value: RuntimeConfig): Record<string, unknown> {
211
- return {
212
- stripClaudeCodeBillingHeader: value.stripClaudeCodeBillingHeader,
213
- hasSeenOnboarding: value.hasSeenOnboarding,
214
- slowResponseThresholdSeconds: value.slowResponseThresholdSeconds,
215
- providerTestTimeoutSeconds: value.providerTestTimeoutSeconds,
216
- timeDisplayFormat: value.timeDisplayFormat,
217
- };
218
- }
@@ -1,66 +0,0 @@
1
- // Proxy module constants
2
-
3
- export const DEFAULT_UPSTREAM = "https://api.anthropic.com";
4
- export const DEFAULT_OPENAI_UPSTREAM = "https://api.openai.com/v1";
5
-
6
- // Unified proxy identity - used as user-agent and x-proxy-identity header value
7
- export const PROXY_IDENTITY = process.env["PROXY_IDENTITY"] ?? "inspector9527@Tony";
8
-
9
- // API paths
10
- export const PATH_V1_CHAT_COMPLETIONS = "/v1/chat/completions";
11
- export const PATH_CHAT_COMPLETIONS = "/chat/completions";
12
- export const PATH_V1_RESPONSES = "/v1/responses";
13
- export const PATH_RESPONSES = "/responses";
14
- export const PATH_V1_MESSAGES = "/v1/messages";
15
-
16
- // Header names
17
- export const HEADER_CONTENT_TYPE = "content-type";
18
- export const HEADER_USER_AGENT = "user-agent";
19
- export const HEADER_X_PROXY_IDENTITY = "x-proxy-identity";
20
- export const HEADER_AUTHORIZATION = "authorization";
21
- export const HEADER_X_API_KEY = "x-api-key";
22
- export const HEADER_CONTENT_ENCODING = "content-encoding";
23
- export const HEADER_CONTENT_LENGTH = "content-length";
24
- export const HEADER_HOST = "host";
25
-
26
- // Auth header types
27
- export const AUTH_HEADER_X_API_KEY = "x-api-key";
28
-
29
- // Headers whose values contain secrets (API keys, bearer tokens).
30
- // These are redacted before being written to logs when captureMode is "full".
31
- export const SENSITIVE_HEADERS = new Set([
32
- HEADER_AUTHORIZATION,
33
- HEADER_X_API_KEY,
34
- "cookie",
35
- "set-cookie",
36
- "proxy-authorization",
37
- ]);
38
-
39
- // Content types
40
- export const CONTENT_TYPE_EVENT_STREAM = "text/event-stream";
41
-
42
- // Response status
43
- export const STATUS_FORBIDDEN = 403;
44
- export const STATUS_BAD_GATEWAY = 502;
45
- export const STATUS_PAYLOAD_TOO_LARGE = 413;
46
-
47
- // Maximum request body size accepted by the proxy (50 MB).
48
- // Legitimate LLM API requests (system prompts, conversation history, tool
49
- // definitions) are well under this limit; larger payloads are almost certainly
50
- // malicious or malformed.
51
- export const MAX_REQUEST_BODY_BYTES = 50 * 1024 * 1024;
52
-
53
- // Standard/safe headers to preserve when forwarding to upstream.
54
- // NOTE: Authorization is intentionally excluded to prevent client auth tokens from leaking.
55
- export const PRESERVE_HEADERS = new Set([HEADER_CONTENT_TYPE]);
56
-
57
- // Opt-in rewrite: the *initial* value for the strip-Claude-Code-billing-header
58
- // flag. The runtime, mutable source of truth is `src/proxy/config.ts`, which
59
- // reads this constant at module-load time as its precedence-2 fallback (after
60
- // the persisted `data/config.json`, before the `false` default). After boot,
61
- // the handler reads `getConfig().stripClaudeCodeBillingHeader` on every
62
- // request, so a PATCH to `/api/config` (or the Settings → Proxy tab in the UI)
63
- // takes effect without a restart. The env var itself is read once at boot.
64
- //
65
- // What it does: when enabled, the proxy strips the
66
- // `x-anthropic-billing-header:` text block that Claude Code prepends to the
@@ -1,147 +0,0 @@
1
- import { cpSync, existsSync, readdirSync, renameSync, rmSync } from "node:fs";
2
- import { isAbsolute, join } from "node:path";
3
- import {
4
- ensurePrivateDirectorySync,
5
- isPathTreeFreeOfIndirectionSync,
6
- securePrivateTreeSync,
7
- } from "./privateDataPath";
8
-
9
- const CURRENT_DATA_DIR_NAME = ".agent-inspector";
10
- const LEGACY_DATA_DIR_NAMES = [".llm-inspector", ".llm-agent"];
11
-
12
- /**
13
- * Compute the directory where agent-inspector stores its on-disk state
14
- * (runtime config, providers config, log chunks, etc.). Centralised here
15
- * so every store agrees on the same path.
16
- *
17
- * Resolution order (first match wins):
18
- * 1. `AGENT_INSPECTOR_DATA_DIR` env var - absolute path used as-is,
19
- * relative path joined to the OS-specific base below.
20
- * 2. `AGENT_INSPECTOR_CONFIG_DIR` env var - kept for backward compat
21
- * with the runtime config; treated as a directory *name* (relative
22
- * to the OS-specific base) when not absolute.
23
- * 3. OS-specific base + `.agent-inspector`.
24
- *
25
- * Windows base is `%USERPROFILE%` (falling back to `%APPDATA%`, then `C:\`).
26
- * macOS / Linux base is `$HOME` (falling back to `/tmp`).
27
- *
28
- * The env var is re-read on every call so tests and the CLI can swap the
29
- * directory after this module has been imported.
30
- */
31
- export function getDataDir(): string {
32
- migrateLegacyDataDirs();
33
- return resolveDataDir(existsSync);
34
- }
35
-
36
- type PathExists = (path: string) => boolean;
37
- type DataDirEnv = Readonly<Record<string, string | undefined>>;
38
-
39
- function hasDataDirState(pathExists: PathExists, dir: string): boolean {
40
- return (
41
- pathExists(join(dir, "providers.json")) ||
42
- pathExists(join(dir, "config.json")) ||
43
- pathExists(join(dir, "logs")) ||
44
- pathExists(join(dir, "chunks"))
45
- );
46
- }
47
-
48
- function defaultBaseDir(
49
- env: DataDirEnv = process.env,
50
- platform: typeof process.platform = process.platform,
51
- ): string {
52
- return platform === "win32"
53
- ? (env["USERPROFILE"] ?? env["APPDATA"] ?? "C:\\")
54
- : (env["HOME"] ?? "/tmp");
55
- }
56
-
57
- export function resolveDataDir(
58
- _pathExists: PathExists,
59
- env: DataDirEnv = process.env,
60
- platform: typeof process.platform = process.platform,
61
- ): string {
62
- const base = defaultBaseDir(env, platform);
63
-
64
- const dirEnv = env["AGENT_INSPECTOR_DATA_DIR"];
65
- if (dirEnv !== undefined && dirEnv !== "") {
66
- return isAbsolute(dirEnv) ? dirEnv : join(base, dirEnv);
67
- }
68
-
69
- // Backward-compat: the runtime config historically read
70
- // `AGENT_INSPECTOR_CONFIG_DIR` as a directory *name* (relative to base).
71
- // Honour it so existing CLI scripts keep working.
72
- const legacyDirEnv = env["AGENT_INSPECTOR_CONFIG_DIR"];
73
- if (legacyDirEnv !== undefined && legacyDirEnv !== "") {
74
- return isAbsolute(legacyDirEnv) ? legacyDirEnv : join(base, legacyDirEnv);
75
- }
76
-
77
- return join(base, CURRENT_DATA_DIR_NAME);
78
- }
79
-
80
- /**
81
- * `true` when the user has explicitly asked for a non-default data
82
- * directory. Used to skip the one-time legacy migration so we don't
83
- * write to a path the user didn't choose.
84
- */
85
- export function hasExplicitDataDir(): boolean {
86
- return (
87
- (process.env["AGENT_INSPECTOR_DATA_DIR"] !== undefined &&
88
- process.env["AGENT_INSPECTOR_DATA_DIR"] !== "") ||
89
- (process.env["AGENT_INSPECTOR_CONFIG_DIR"] !== undefined &&
90
- process.env["AGENT_INSPECTOR_CONFIG_DIR"] !== "")
91
- );
92
- }
93
-
94
- export function migrateLegacyDataDirs(): void {
95
- if (hasExplicitDataDir()) return;
96
-
97
- const base = defaultBaseDir();
98
- const currentDir = join(base, CURRENT_DATA_DIR_NAME);
99
- if (hasDataDirState(existsSync, currentDir)) return;
100
-
101
- for (const legacyName of LEGACY_DATA_DIR_NAMES) {
102
- const legacyDir = join(base, legacyName);
103
- if (!existsSync(legacyDir)) continue;
104
-
105
- const stagingDir = join(
106
- base,
107
- `${CURRENT_DATA_DIR_NAME}.migration-${String(process.pid)}-${String(Date.now())}`,
108
- );
109
-
110
- try {
111
- // cpSync may dereference junctions on some Windows runtimes. Reject the source tree before
112
- // copying and recheck it afterwards so migration never imports through an indirection.
113
- if (!isPathTreeFreeOfIndirectionSync(legacyDir)) return;
114
- if (existsSync(currentDir)) {
115
- // Never merge legacy state into an unknown or partially initialized destination. A caller
116
- // can inspect it and retry after resolving the conflict; the authoritative legacy source
117
- // remains untouched.
118
- if (readdirSync(currentDir).length > 0) return;
119
- rmSync(currentDir, { recursive: true, force: false });
120
- }
121
- if (!ensurePrivateDirectorySync(stagingDir)) return;
122
- for (const entry of readdirSync(legacyDir)) {
123
- cpSync(join(legacyDir, entry), join(stagingDir, entry), {
124
- recursive: true,
125
- force: false,
126
- errorOnExist: true,
127
- });
128
- }
129
- if (!isPathTreeFreeOfIndirectionSync(legacyDir)) {
130
- rmSync(stagingDir, { recursive: true, force: true });
131
- return;
132
- }
133
- if (!securePrivateTreeSync(stagingDir)) {
134
- rmSync(stagingDir, { recursive: true, force: true });
135
- return;
136
- }
137
- renameSync(stagingDir, currentDir);
138
- rmSync(legacyDir, { recursive: true, force: true });
139
- return;
140
- } catch {
141
- // A failed staged migration never deletes the legacy source. Remove only this attempt's
142
- // private sibling and retry on a later startup.
143
- if (existsSync(stagingDir)) rmSync(stagingDir, { recursive: true, force: true });
144
- return;
145
- }
146
- }
147
- }
@@ -1,114 +0,0 @@
1
- import { randomUUID } from "node:crypto";
2
- import {
3
- ECOSYSTEM_EXECUTION_CONFIRMATION_PHRASE,
4
- type EcosystemExecutionConfirmation,
5
- type EcosystemExecutionPlan,
6
- type EcosystemTaskAction,
7
- } from "../lib/ecosystemContract";
8
- import { logger } from "./logger";
9
-
10
- const CONFIRMATION_TTL_MS = 2 * 60 * 1000;
11
- const MAX_PENDING_CONFIRMATIONS = 100;
12
-
13
- type ConfirmationRecord = {
14
- confirmation: EcosystemExecutionConfirmation;
15
- expiresAtMs: number;
16
- };
17
-
18
- type ConfirmationFailureReason =
19
- | "missing_or_invalid_confirmation"
20
- | "expired_confirmation"
21
- | "mismatched_confirmation";
22
-
23
- type ConsumeEcosystemConfirmationResult =
24
- | { ok: true; plan: EcosystemExecutionPlan }
25
- | { ok: false; reason: ConfirmationFailureReason };
26
-
27
- type EcosystemAuditEvent = "confirmation_issued" | "confirmation_rejected" | "execution_started";
28
- type EcosystemAuditReason =
29
- | "none"
30
- | "invalid_request"
31
- | "unknown_target"
32
- | "missing_or_invalid_confirmation"
33
- | "expired_confirmation"
34
- | "mismatched_confirmation"
35
- | "task_unavailable";
36
-
37
- const confirmations = new Map<string, ConfirmationRecord>();
38
-
39
- function pruneConfirmations(nowMs: number): void {
40
- for (const [nonce, record] of confirmations) {
41
- if (record.expiresAtMs <= nowMs) confirmations.delete(nonce);
42
- }
43
- while (confirmations.size >= MAX_PENDING_CONFIRMATIONS) {
44
- const oldestNonce = confirmations.keys().next().value;
45
- if (typeof oldestNonce !== "string") return;
46
- confirmations.delete(oldestNonce);
47
- }
48
- }
49
-
50
- function safeAuditTarget(targetId: string | null): string {
51
- if (targetId === null || !/^[a-z0-9-]{1,64}$/.test(targetId)) return "unrecognized";
52
- return targetId;
53
- }
54
-
55
- export function auditEcosystemExecution(
56
- event: EcosystemAuditEvent,
57
- action: EcosystemTaskAction,
58
- targetId: string | null,
59
- reason: EcosystemAuditReason,
60
- ): void {
61
- logger.info(
62
- `[security-audit] event=${event} action=${action} target=${safeAuditTarget(targetId)} reason=${reason}`,
63
- );
64
- }
65
-
66
- export function createEcosystemExecutionConfirmation(
67
- plan: EcosystemExecutionPlan,
68
- nowMs = Date.now(),
69
- ): EcosystemExecutionConfirmation {
70
- pruneConfirmations(nowMs);
71
- const expiresAtMs = nowMs + CONFIRMATION_TTL_MS;
72
- const confirmation: EcosystemExecutionConfirmation = {
73
- nonce: randomUUID(),
74
- phrase: ECOSYSTEM_EXECUTION_CONFIRMATION_PHRASE,
75
- expiresAt: new Date(expiresAtMs).toISOString(),
76
- plan,
77
- };
78
- confirmations.set(confirmation.nonce, { confirmation, expiresAtMs });
79
- return confirmation;
80
- }
81
-
82
- export function consumeEcosystemExecutionConfirmation(
83
- nonce: string,
84
- phrase: string,
85
- expectedPlan: EcosystemExecutionPlan,
86
- nowMs = Date.now(),
87
- ): ConsumeEcosystemConfirmationResult {
88
- const record = confirmations.get(nonce);
89
- if (record === undefined) {
90
- return { ok: false, reason: "missing_or_invalid_confirmation" };
91
- }
92
-
93
- confirmations.delete(nonce);
94
- if (record.expiresAtMs <= nowMs) return { ok: false, reason: "expired_confirmation" };
95
- const reviewedPlan = record.confirmation.plan;
96
- if (
97
- phrase !== ECOSYSTEM_EXECUTION_CONFIRMATION_PHRASE ||
98
- reviewedPlan.action !== expectedPlan.action ||
99
- reviewedPlan.targetId !== expectedPlan.targetId ||
100
- reviewedPlan.targetName !== expectedPlan.targetName ||
101
- reviewedPlan.command !== expectedPlan.command ||
102
- reviewedPlan.source !== expectedPlan.source ||
103
- reviewedPlan.timeoutMs !== expectedPlan.timeoutMs ||
104
- reviewedPlan.scope !== expectedPlan.scope
105
- ) {
106
- return { ok: false, reason: "mismatched_confirmation" };
107
- }
108
-
109
- return { ok: true, plan: reviewedPlan };
110
- }
111
-
112
- export function resetEcosystemExecutionConfirmationsForTests(): void {
113
- confirmations.clear();
114
- }