@tonyclaw/agent-inspector 3.0.44 → 3.0.46

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 (347) hide show
  1. package/.output/{nitro.json → backend/nitro.json} +3 -3
  2. package/.output/backend-public/assets/index-D4LX-sw-.js +11 -0
  3. package/.output/cli.js +22707 -17099
  4. package/.output/server/_libs/extend.mjs +4 -8
  5. package/.output/server/_libs/jszip.mjs +9 -35
  6. package/.output/server/_libs/modelcontextprotocol__core.mjs +25 -25
  7. package/.output/server/_libs/modelcontextprotocol__server.mjs +2 -2
  8. package/.output/server/_libs/react-dom.mjs +2 -3
  9. package/.output/server/_libs/react.mjs +1 -27
  10. package/.output/server/_libs/tanstack__react-router.mjs +1 -329
  11. package/.output/server/_libs/tanstack__router-core.mjs +42 -100
  12. package/.output/server/_libs/use-sync-external-store.mjs +1 -64
  13. package/.output/server/_libs/ws.mjs +1 -1
  14. package/.output/server/_libs/zod.mjs +6 -6
  15. package/.output/server/_ssr/index.mjs +5 -4
  16. package/.output/server/_ssr/publicBasePathContext-IH2ilOfu.mjs +176 -0
  17. package/.output/server/_ssr/{router-DWcUFPR3.mjs → router-D18yUq36.mjs} +7877 -5597
  18. package/.output/server/_ssr/start-COQu_AgD.mjs +57 -0
  19. package/.output/server/_tanstack-start-manifest_v-DnbdNeun.mjs +4 -0
  20. package/.output/server/index.mjs +5 -145
  21. package/.output/{public/assets/CompareDrawer-DQHjxFO6.js → ui/assets/CompareDrawer-DAUuIJ6G.js} +1 -1
  22. package/.output/{public/assets/InspectorPet-D1A4505B.js → ui/assets/InspectorPet-BRBVjOWI.js} +1 -1
  23. package/.output/ui/assets/ProxyViewerContainer-D7Sq0ctc.js +59 -0
  24. package/.output/{public/assets/ReplayDialog-C5vmbecv.js → ui/assets/ReplayDialog-nDLsjOhs.js} +1 -1
  25. package/.output/{public/assets/RequestAnatomy-CPGNB8lk.js → ui/assets/RequestAnatomy-zd4BDgL0.js} +1 -1
  26. package/.output/ui/assets/ResponseView-AdIXGcSn.js +2 -0
  27. package/.output/ui/assets/StreamingChunkSequence-CesTz8He.js +1 -0
  28. package/.output/{public/assets/_sessionId-CDhRgzf6.js → ui/assets/_sessionId-BAfzrhSU.js} +1 -1
  29. package/.output/{public/assets/_sessionId-mw3aA8Bp.js → ui/assets/_sessionId-QnBomgPD.js} +1 -1
  30. package/.output/ui/assets/favicon-DYEkHSNl.svg +21 -0
  31. package/.output/{public/assets/index-B2eoeT-Z.js → ui/assets/index-BcsdxBAd.js} +1 -1
  32. package/.output/ui/assets/index-BvXp42al.css +1 -0
  33. package/.output/{public/assets/index-CX7_rf7o.js → ui/assets/index-D0rtCN9V.js} +1 -1
  34. package/.output/ui/assets/index-DHpwr08Z.js +73 -0
  35. package/.output/{public/assets/index-BfRhTvOd.js → ui/assets/index-dNuk2dsU.js} +1 -1
  36. package/.output/ui/assets/json-viewer-BvFHglMb.js +1 -0
  37. package/.output/{public/assets/jszip.min-C9rCFoU3.js → ui/assets/jszip.min-B5Z7gNZB.js} +1 -1
  38. package/.output/ui/index.html +229 -0
  39. package/.output/ui/runtime-config.js +2 -0
  40. package/.output/workers/logFinalizer.worker.js +983 -414
  41. package/.output/workers/sessionWorkerEntry.js +983 -414
  42. package/README.md +363 -35
  43. package/docs/instance-control.openapi.yaml +361 -0
  44. package/package.json +28 -5
  45. package/scripts/generate-theme-scales.mjs +3 -3
  46. package/src/{router.tsx → backend/router.tsx} +3 -15
  47. package/src/backend/routes/$.ts +26 -0
  48. package/src/backend/routes/__root.ts +4 -0
  49. package/src/backend/routes/api/-instances.ts +109 -0
  50. package/src/{routes → backend/routes}/api/alerts.summary.ts +3 -3
  51. package/src/{routes → backend/routes}/api/alerts.ts +4 -4
  52. package/src/{routes → backend/routes}/api/config.paths.ts +1 -1
  53. package/src/{routes → backend/routes}/api/config.ts +11 -2
  54. package/src/{routes → backend/routes}/api/ecosystem.packages.$packageId.help.ts +1 -1
  55. package/src/{routes → backend/routes}/api/ecosystem.packages.$packageId.install.ts +1 -1
  56. package/src/{routes → backend/routes}/api/ecosystem.packages.$packageId.runner-presets.ts +1 -1
  57. package/src/{routes → backend/routes}/api/ecosystem.packages.$packageId.upgrade.ts +1 -1
  58. package/src/{routes → backend/routes}/api/ecosystem.packages.ts +5 -1
  59. package/src/{routes → backend/routes}/api/ecosystem.recipes.$recipeId.run.ts +1 -1
  60. package/src/{routes → backend/routes}/api/ecosystem.tasks.$taskId.ts +1 -1
  61. package/src/{routes → backend/routes}/api/ecosystem.tasks.ts +1 -1
  62. package/src/{routes → backend/routes}/api/groups.$groupId.evidence.ts +2 -2
  63. package/src/{routes → backend/routes}/api/groups.$groupId.sessions.ts +2 -2
  64. package/src/{routes → backend/routes}/api/groups.$groupId.ts +2 -2
  65. package/src/{routes → backend/routes}/api/groups.ts +2 -2
  66. package/src/{routes → backend/routes}/api/health.ts +3 -3
  67. package/src/backend/routes/api/instances.$name.connection.ts +12 -0
  68. package/src/backend/routes/api/instances.$name.restart.ts +23 -0
  69. package/src/backend/routes/api/instances.$name.start.ts +18 -0
  70. package/src/backend/routes/api/instances.$name.stop.ts +23 -0
  71. package/src/backend/routes/api/instances.$name.ts +12 -0
  72. package/src/backend/routes/api/instances.ts +16 -0
  73. package/src/{routes → backend/routes}/api/knowledge.candidates.$candidateId.promote.ts +2 -2
  74. package/src/{routes → backend/routes}/api/knowledge.candidates.$candidateId.ts +2 -2
  75. package/src/{routes → backend/routes}/api/knowledge.candidates.ts +1 -1
  76. package/src/{routes → backend/routes}/api/knowledge.project-context.ts +2 -2
  77. package/src/{routes → backend/routes}/api/knowledge.search.ts +2 -2
  78. package/src/{routes → backend/routes}/api/knowledge.sessions.$sessionId.candidates.ts +3 -3
  79. package/src/{routes → backend/routes}/api/logs.$id.body.ts +6 -6
  80. package/src/{routes → backend/routes}/api/logs.$id.chunks.ts +5 -4
  81. package/src/{routes → backend/routes}/api/logs.$id.replay.ts +12 -11
  82. package/src/{routes → backend/routes}/api/logs.$id.ts +4 -3
  83. package/src/{routes → backend/routes}/api/logs.import.ts +3 -3
  84. package/src/{routes → backend/routes}/api/logs.stream.ts +11 -7
  85. package/src/{routes → backend/routes}/api/logs.ts +17 -9
  86. package/src/{routes → backend/routes}/api/mcp.ts +1 -1
  87. package/src/{routes → backend/routes}/api/models.ts +1 -1
  88. package/src/{routes → backend/routes}/api/pi-agent.ts +2 -2
  89. package/src/{routes → backend/routes}/api/providers.$providerId.model-metadata.ts +5 -5
  90. package/src/{routes → backend/routes}/api/providers.$providerId.test.log.ts +7 -7
  91. package/src/{routes → backend/routes}/api/providers.$providerId.ts +4 -4
  92. package/src/{routes → backend/routes}/api/providers.export.ts +1 -1
  93. package/src/{routes → backend/routes}/api/providers.import.ts +3 -3
  94. package/src/{routes → backend/routes}/api/providers.scan.ts +2 -2
  95. package/src/{routes → backend/routes}/api/providers.ts +9 -4
  96. package/src/{routes → backend/routes}/api/runs.$runId.evidence.ts +2 -2
  97. package/src/{routes → backend/routes}/api/runs.$runId.ts +2 -2
  98. package/src/{routes → backend/routes}/api/runs.ts +4 -4
  99. package/src/backend/routes/api/runtime.ts +46 -0
  100. package/src/{routes → backend/routes}/api/sessions.ts +3 -3
  101. package/src/{routes → backend/routes}/proxy/$.ts +1 -1
  102. package/src/{routes → backend/routes}/readyz.ts +1 -1
  103. package/src/backend/start.ts +10 -0
  104. package/src/cli/alias.ts +431 -0
  105. package/src/cli/doctor.ts +32 -9
  106. package/src/cli/instance.ts +1050 -0
  107. package/src/cli/instanceArgs.ts +285 -0
  108. package/src/cli/instanceControl.ts +181 -0
  109. package/src/cli/instanceModel.ts +267 -0
  110. package/src/cli/instanceRegistry.ts +731 -0
  111. package/src/cli/networkHints.ts +27 -14
  112. package/src/cli/onboard.ts +190 -35
  113. package/src/cli/onboardTarget.ts +228 -0
  114. package/src/cli/templates/codex-skill-onboard.ts +109 -31
  115. package/src/cli/templates/skill-onboard.ts +140 -70
  116. package/src/cli.ts +338 -77
  117. package/src/components/ProxyViewer.tsx +20 -10
  118. package/src/components/ProxyViewerContainer.tsx +12 -11
  119. package/src/components/pi-agent/PiAgentPanel.tsx +2 -2
  120. package/src/components/providers/ProviderCard.tsx +1 -1
  121. package/src/components/providers/ProviderTestResultsView.tsx +1 -1
  122. package/src/components/providers/SettingsDialog.tsx +160 -140
  123. package/src/components/proxy-viewer/ApplicationBar.tsx +2 -1
  124. package/src/components/proxy-viewer/LogEntry.tsx +1 -1
  125. package/src/components/proxy-viewer/log-formats/index.ts +1 -1
  126. package/src/contracts/index.ts +5 -0
  127. package/src/contracts/log.ts +33 -3
  128. package/src/knowledge/types.ts +3 -2
  129. package/src/lib/alertContract.ts +2 -2
  130. package/src/lib/apiClient.ts +30 -7
  131. package/src/lib/apiFormat.ts +29 -0
  132. package/src/lib/basePath.ts +31 -7
  133. package/src/lib/browserRuntimeContract.ts +124 -0
  134. package/src/lib/browserRuntimeResolver.ts +244 -0
  135. package/src/{proxy → lib}/claudeCodeStrip.ts +6 -7
  136. package/src/lib/codingAgentEndpoints.ts +54 -0
  137. package/src/lib/instanceContract.ts +236 -0
  138. package/src/lib/managedInstance.ts +104 -0
  139. package/src/lib/piAgentContract.ts +3 -2
  140. package/src/lib/publicBasePathContext.ts +137 -0
  141. package/src/lib/resourceLimits.ts +2 -0
  142. package/src/lib/runContract.ts +3 -3
  143. package/src/lib/sessionInfoContract.ts +3 -2
  144. package/src/mcp/instanceHandlers.ts +150 -0
  145. package/src/mcp/loopback.ts +16 -5
  146. package/src/mcp/mode.ts +25 -0
  147. package/src/mcp/server.ts +274 -39
  148. package/src/mcp/toolHandlers.ts +2 -2
  149. package/src/proxy/config.ts +25 -30
  150. package/src/proxy/dataDir.ts +43 -7
  151. package/src/proxy/ecosystemTasks.ts +161 -70
  152. package/src/proxy/formats/registry.ts +6 -21
  153. package/src/proxy/handler.ts +129 -29
  154. package/src/proxy/identityProxy.ts +1049 -50
  155. package/src/proxy/jsonlRecovery.ts +554 -0
  156. package/src/proxy/logFinalizer.ts +25 -10
  157. package/src/proxy/logImporter.ts +2 -1
  158. package/src/proxy/logIndex.ts +191 -95
  159. package/src/proxy/logger.ts +77 -14
  160. package/src/proxy/platformCommands.ts +41 -0
  161. package/src/proxy/privateDataPath.ts +310 -88
  162. package/src/proxy/rawStreamCapture.ts +194 -13
  163. package/src/proxy/runtimeAdmission.ts +5 -2
  164. package/src/proxy/runtimeHealth.ts +14 -1
  165. package/src/proxy/runtimeShutdown.ts +84 -2
  166. package/src/proxy/schemas.ts +7 -1
  167. package/src/proxy/sessionArchive.ts +78 -14
  168. package/src/proxy/sessionInfo.ts +5 -4
  169. package/src/proxy/sqliteLogIndex.ts +65 -2
  170. package/src/proxy/store.ts +141 -34
  171. package/src/proxy/uiAssetServer.ts +106 -0
  172. package/src/proxy/upstream.ts +29 -2
  173. package/src/ui/bootstrap.ts +167 -0
  174. package/src/ui/index.html +38 -0
  175. package/src/ui/logsStreamClient.ts +20 -0
  176. package/src/ui/main.tsx +13 -0
  177. package/src/ui/public/runtime-config.js +2 -0
  178. package/src/ui/router.tsx +13 -0
  179. package/src/ui/routes/__root.tsx +69 -0
  180. package/src/{routes → ui/routes}/index.tsx +2 -3
  181. package/src/{routes → ui/routes}/session/$sessionId.tsx +5 -11
  182. package/src/ui/runtimeDiscovery.ts +50 -0
  183. package/styles/globals.css +1 -0
  184. package/.output/public/assets/ProxyViewerContainer-BhpIgfBi.js +0 -126
  185. package/.output/public/assets/ResponseView-DUfrajCm.js +0 -2
  186. package/.output/public/assets/StreamingChunkSequence-nbeCQqOz.js +0 -1
  187. package/.output/public/assets/index-BWjeqxbk.css +0 -1
  188. package/.output/public/assets/index-C6qZwYlR.js +0 -70
  189. package/.output/public/assets/json-viewer-BLmF1sOZ.js +0 -1
  190. package/.output/server/_libs/@radix-ui/react-accessible-icon+[...].mjs +0 -1
  191. package/.output/server/_libs/@radix-ui/react-dismissable-layer+[...].mjs +0 -344
  192. package/.output/server/_libs/@radix-ui/react-navigation-menu+[...].mjs +0 -2
  193. package/.output/server/_libs/@radix-ui/react-one-time-password-field+[...].mjs +0 -2
  194. package/.output/server/_libs/@radix-ui/react-password-toggle-field+[...].mjs +0 -2
  195. package/.output/server/_libs/@radix-ui/react-use-callback-ref+[...].mjs +0 -11
  196. package/.output/server/_libs/@radix-ui/react-use-controllable-state+[...].mjs +0 -69
  197. package/.output/server/_libs/@radix-ui/react-use-effect-event+[...].mjs +0 -1
  198. package/.output/server/_libs/@radix-ui/react-use-is-hydrated+[...].mjs +0 -28
  199. package/.output/server/_libs/@radix-ui/react-use-layout-effect+[...].mjs +0 -6
  200. package/.output/server/_libs/@radix-ui/react-visually-hidden+[...].mjs +0 -34
  201. package/.output/server/_libs/aria-hidden.mjs +0 -122
  202. package/.output/server/_libs/bail.mjs +0 -8
  203. package/.output/server/_libs/character-entities.mjs +0 -2130
  204. package/.output/server/_libs/class-variance-authority.mjs +0 -44
  205. package/.output/server/_libs/clsx.mjs +0 -16
  206. package/.output/server/_libs/comma-separated-tokens.mjs +0 -10
  207. package/.output/server/_libs/decode-named-character-reference+[...].mjs +0 -8
  208. package/.output/server/_libs/dequal.mjs +0 -27
  209. package/.output/server/_libs/detect-node-es.mjs +0 -1
  210. package/.output/server/_libs/devlop.mjs +0 -8
  211. package/.output/server/_libs/diff.mjs +0 -320
  212. package/.output/server/_libs/estree-util-is-identifier-name.mjs +0 -11
  213. package/.output/server/_libs/floating-ui__core.mjs +0 -725
  214. package/.output/server/_libs/floating-ui__dom.mjs +0 -622
  215. package/.output/server/_libs/floating-ui__react-dom.mjs +0 -292
  216. package/.output/server/_libs/floating-ui__utils.mjs +0 -320
  217. package/.output/server/_libs/get-nonce.mjs +0 -9
  218. package/.output/server/_libs/hast-util-to-jsx-runtime.mjs +0 -388
  219. package/.output/server/_libs/hast-util-whitespace.mjs +0 -10
  220. package/.output/server/_libs/html-url-attributes.mjs +0 -26
  221. package/.output/server/_libs/inline-style-parser.mjs +0 -142
  222. package/.output/server/_libs/is-plain-obj.mjs +0 -10
  223. package/.output/server/_libs/lucide-react.mjs +0 -1027
  224. package/.output/server/_libs/mdast-util-from-markdown.mjs +0 -717
  225. package/.output/server/_libs/mdast-util-to-hast.mjs +0 -710
  226. package/.output/server/_libs/mdast-util-to-string.mjs +0 -38
  227. package/.output/server/_libs/micromark-core-commonmark.mjs +0 -2259
  228. package/.output/server/_libs/micromark-factory-destination.mjs +0 -94
  229. package/.output/server/_libs/micromark-factory-label.mjs +0 -63
  230. package/.output/server/_libs/micromark-factory-space.mjs +0 -24
  231. package/.output/server/_libs/micromark-factory-title.mjs +0 -65
  232. package/.output/server/_libs/micromark-factory-whitespace.mjs +0 -22
  233. package/.output/server/_libs/micromark-util-character.mjs +0 -44
  234. package/.output/server/_libs/micromark-util-chunked.mjs +0 -36
  235. package/.output/server/_libs/micromark-util-classify-character+[...].mjs +0 -12
  236. package/.output/server/_libs/micromark-util-combine-extensions+[...].mjs +0 -41
  237. package/.output/server/_libs/micromark-util-decode-numeric-character-reference+[...].mjs +0 -19
  238. package/.output/server/_libs/micromark-util-decode-string.mjs +0 -21
  239. package/.output/server/_libs/micromark-util-encode.mjs +0 -1
  240. package/.output/server/_libs/micromark-util-html-tag-name.mjs +0 -69
  241. package/.output/server/_libs/micromark-util-normalize-identifier+[...].mjs +0 -6
  242. package/.output/server/_libs/micromark-util-resolve-all.mjs +0 -15
  243. package/.output/server/_libs/micromark-util-sanitize-uri.mjs +0 -41
  244. package/.output/server/_libs/micromark-util-subtokenize.mjs +0 -346
  245. package/.output/server/_libs/micromark.mjs +0 -906
  246. package/.output/server/_libs/property-information.mjs +0 -1209
  247. package/.output/server/_libs/radix-ui.mjs +0 -1
  248. package/.output/server/_libs/radix-ui__number.mjs +0 -6
  249. package/.output/server/_libs/radix-ui__primitive.mjs +0 -11
  250. package/.output/server/_libs/radix-ui__react-accordion.mjs +0 -1
  251. package/.output/server/_libs/radix-ui__react-alert-dialog.mjs +0 -1
  252. package/.output/server/_libs/radix-ui__react-arrow.mjs +0 -23
  253. package/.output/server/_libs/radix-ui__react-aspect-ratio.mjs +0 -1
  254. package/.output/server/_libs/radix-ui__react-avatar.mjs +0 -1
  255. package/.output/server/_libs/radix-ui__react-checkbox.mjs +0 -1
  256. package/.output/server/_libs/radix-ui__react-collapsible.mjs +0 -144
  257. package/.output/server/_libs/radix-ui__react-collection.mjs +0 -69
  258. package/.output/server/_libs/radix-ui__react-compose-refs.mjs +0 -38
  259. package/.output/server/_libs/radix-ui__react-context-menu.mjs +0 -1
  260. package/.output/server/_libs/radix-ui__react-context.mjs +0 -64
  261. package/.output/server/_libs/radix-ui__react-dialog.mjs +0 -280
  262. package/.output/server/_libs/radix-ui__react-direction.mjs +0 -9
  263. package/.output/server/_libs/radix-ui__react-dropdown-menu.mjs +0 -1
  264. package/.output/server/_libs/radix-ui__react-focus-guards.mjs +0 -39
  265. package/.output/server/_libs/radix-ui__react-focus-scope.mjs +0 -210
  266. package/.output/server/_libs/radix-ui__react-form.mjs +0 -1
  267. package/.output/server/_libs/radix-ui__react-hover-card.mjs +0 -1
  268. package/.output/server/_libs/radix-ui__react-id.mjs +0 -14
  269. package/.output/server/_libs/radix-ui__react-label.mjs +0 -1
  270. package/.output/server/_libs/radix-ui__react-menu.mjs +0 -1
  271. package/.output/server/_libs/radix-ui__react-menubar.mjs +0 -1
  272. package/.output/server/_libs/radix-ui__react-popover.mjs +0 -1
  273. package/.output/server/_libs/radix-ui__react-popper.mjs +0 -340
  274. package/.output/server/_libs/radix-ui__react-portal.mjs +0 -16
  275. package/.output/server/_libs/radix-ui__react-presence.mjs +0 -173
  276. package/.output/server/_libs/radix-ui__react-primitive.mjs +0 -42
  277. package/.output/server/_libs/radix-ui__react-progress.mjs +0 -1
  278. package/.output/server/_libs/radix-ui__react-radio-group.mjs +0 -1
  279. package/.output/server/_libs/radix-ui__react-roving-focus.mjs +0 -235
  280. package/.output/server/_libs/radix-ui__react-scroll-area.mjs +0 -731
  281. package/.output/server/_libs/radix-ui__react-select.mjs +0 -1207
  282. package/.output/server/_libs/radix-ui__react-separator.mjs +0 -28
  283. package/.output/server/_libs/radix-ui__react-slider.mjs +0 -1
  284. package/.output/server/_libs/radix-ui__react-slot.mjs +0 -132
  285. package/.output/server/_libs/radix-ui__react-switch.mjs +0 -1
  286. package/.output/server/_libs/radix-ui__react-tabs.mjs +0 -194
  287. package/.output/server/_libs/radix-ui__react-toast.mjs +0 -2
  288. package/.output/server/_libs/radix-ui__react-toggle-group.mjs +0 -1
  289. package/.output/server/_libs/radix-ui__react-toggle.mjs +0 -1
  290. package/.output/server/_libs/radix-ui__react-toolbar.mjs +0 -1
  291. package/.output/server/_libs/radix-ui__react-tooltip.mjs +0 -498
  292. package/.output/server/_libs/radix-ui__react-use-previous.mjs +0 -14
  293. package/.output/server/_libs/radix-ui__react-use-size.mjs +0 -39
  294. package/.output/server/_libs/react-markdown.mjs +0 -235
  295. package/.output/server/_libs/react-remove-scroll-bar.mjs +0 -82
  296. package/.output/server/_libs/react-remove-scroll.mjs +0 -328
  297. package/.output/server/_libs/react-style-singleton.mjs +0 -69
  298. package/.output/server/_libs/remark-parse.mjs +0 -19
  299. package/.output/server/_libs/remark-rehype.mjs +0 -21
  300. package/.output/server/_libs/space-separated-tokens.mjs +0 -6
  301. package/.output/server/_libs/style-to-js.mjs +0 -72
  302. package/.output/server/_libs/style-to-object.mjs +0 -38
  303. package/.output/server/_libs/swr.mjs +0 -947
  304. package/.output/server/_libs/tailwind-merge.mjs +0 -3255
  305. package/.output/server/_libs/tanstack__react-virtual.mjs +0 -130
  306. package/.output/server/_libs/tanstack__virtual-core.mjs +0 -1319
  307. package/.output/server/_libs/three.mjs +0 -26016
  308. package/.output/server/_libs/trim-lines.mjs +0 -41
  309. package/.output/server/_libs/trough.mjs +0 -85
  310. package/.output/server/_libs/tslib.mjs +0 -1
  311. package/.output/server/_libs/ungap__structured-clone.mjs +0 -212
  312. package/.output/server/_libs/unified.mjs +0 -661
  313. package/.output/server/_libs/unist-util-is.mjs +0 -100
  314. package/.output/server/_libs/unist-util-position.mjs +0 -27
  315. package/.output/server/_libs/unist-util-stringify-position.mjs +0 -27
  316. package/.output/server/_libs/unist-util-visit-parents.mjs +0 -82
  317. package/.output/server/_libs/unist-util-visit.mjs +0 -24
  318. package/.output/server/_libs/use-callback-ref.mjs +0 -66
  319. package/.output/server/_libs/use-sidecar.mjs +0 -106
  320. package/.output/server/_libs/vfile-message.mjs +0 -138
  321. package/.output/server/_libs/vfile.mjs +0 -467
  322. package/.output/server/_sessionId-E_Dmopc-.mjs +0 -144
  323. package/.output/server/_sessionId-U54BAqdp.mjs +0 -82
  324. package/.output/server/_ssr/CompareDrawer-CksatPed.mjs +0 -1058
  325. package/.output/server/_ssr/InspectorPet-DNc4GQ7z.mjs +0 -936
  326. package/.output/server/_ssr/ProxyViewerContainer-B02Ey0p_.mjs +0 -17607
  327. package/.output/server/_ssr/ReplayDialog-DdMvHJF1.mjs +0 -723
  328. package/.output/server/_ssr/RequestAnatomy--vh2Z8__.mjs +0 -835
  329. package/.output/server/_ssr/ResponseView-Dhxc-cKC.mjs +0 -755
  330. package/.output/server/_ssr/StreamingChunkSequence-BG0EQmaD.mjs +0 -272
  331. package/.output/server/_ssr/index-D0At9nfd.mjs +0 -82
  332. package/.output/server/_ssr/index-lcfulIXa.mjs +0 -133
  333. package/.output/server/_ssr/json-viewer-My1J1_5R.mjs +0 -481
  334. package/.output/server/_ssr/start-HYkvq4Ni.mjs +0 -4
  335. package/.output/server/_tanstack-start-manifest_v-B2chR8ef.mjs +0 -4
  336. package/.output/server/node_modules/tslib/modules/index.js +0 -70
  337. package/.output/server/node_modules/tslib/modules/package.json +0 -3
  338. package/.output/server/node_modules/tslib/package.json +0 -47
  339. package/.output/server/node_modules/tslib/tslib.js +0 -484
  340. package/.output/server/package.json +0 -9
  341. package/src/routes/__root.tsx +0 -170
  342. /package/.output/{public → ui}/assets/agent-inspector-58K1_MsC.ico +0 -0
  343. /package/.output/{public → ui}/assets/alibaba-TTwafVwX.svg +0 -0
  344. /package/.output/{public → ui}/assets/minimax-BPMzvuL-.jpeg +0 -0
  345. /package/.output/{public → ui}/assets/qwen-mMn3f5ul.webp +0 -0
  346. /package/.output/{public → ui}/assets/zhipuai-BPNAnxo-.svg +0 -0
  347. /package/src/{routes → backend/routes}/livez.ts +0 -0
@@ -1,5 +1,5 @@
1
1
  import { z } from "zod";
2
- import { JsonValueSchema } from "../contracts";
2
+ import { JsonValueSchema, LogIdSchema } from "../contracts";
3
3
 
4
4
  export const AlertSeveritySchema = z.enum(["critical", "warning", "notice"]);
5
5
  export const AlertStatusSchema = z.enum(["open"]);
@@ -35,7 +35,7 @@ export const AlertSchema = z.object({
35
35
  count: z.number().int().positive(),
36
36
  firstSeenAt: z.string(),
37
37
  lastSeenAt: z.string(),
38
- logIds: z.array(z.number().int().positive()),
38
+ logIds: z.array(LogIdSchema),
39
39
  sessionIds: z.array(z.string()),
40
40
  runIds: z.array(z.string()),
41
41
  groupIds: z.array(z.string()),
@@ -1,6 +1,6 @@
1
1
  /* eslint-disable functional/no-throw-statements */
2
2
  import { z } from "zod";
3
- import { withBasePath } from "./basePath";
3
+ import { buildControlRuntimeUrl, resolveBrowserRuntimeForDocument } from "./browserRuntimeResolver";
4
4
 
5
5
  const ApiErrorSchema = z.object({
6
6
  error: z.string(),
@@ -8,10 +8,22 @@ const ApiErrorSchema = z.object({
8
8
 
9
9
  const MUTATION_METHODS = new Set(["POST", "PUT", "PATCH", "DELETE"]);
10
10
 
11
- function withInspectorBasePath(input: RequestInfo | URL): RequestInfo | URL {
11
+ function withInspectorControlSurface(input: RequestInfo | URL): RequestInfo | URL {
12
12
  if (typeof input !== "string") return input;
13
- if (!input.startsWith("/") || input.startsWith("//")) return input;
14
- return withBasePath(input);
13
+ if (!input.startsWith("/")) return input;
14
+ if (input.startsWith("//")) {
15
+ throw new TypeError("Protocol-relative API URLs are not allowed.");
16
+ }
17
+
18
+ const runtime = resolveBrowserRuntimeForDocument();
19
+ if (!runtime.ok) {
20
+ throw new Error(`Browser runtime is unavailable: ${runtime.issues.join("; ")}`);
21
+ }
22
+ const url = buildControlRuntimeUrl(runtime.runtime, input);
23
+ if (url === null) {
24
+ throw new TypeError(`Invalid logical control path: ${input}`);
25
+ }
26
+ return url;
15
27
  }
16
28
 
17
29
  export function withBrowserMutationProof(init?: RequestInit): RequestInit | undefined {
@@ -50,6 +62,17 @@ export async function readApiError(response: Response, fallback: string): Promis
50
62
  }
51
63
  }
52
64
 
65
+ /**
66
+ * Fetch through the browser runtime's control surface while retaining the
67
+ * mutation proof required by the protected ingress.
68
+ */
69
+ export async function fetchControl(
70
+ input: RequestInfo | URL,
71
+ init?: RequestInit,
72
+ ): Promise<Response> {
73
+ return await fetch(withInspectorControlSurface(input), withBrowserMutationProof(init));
74
+ }
75
+
53
76
  /**
54
77
  * Fetch a JSON resource and validate its successful response.
55
78
  */
@@ -59,7 +82,7 @@ export async function fetchJson<T>(
59
82
  init?: RequestInit,
60
83
  errorFallback?: (response: Response) => string,
61
84
  ): Promise<T> {
62
- const response = await fetch(withInspectorBasePath(input), withBrowserMutationProof(init));
85
+ const response = await fetchControl(input, init);
63
86
  if (!response.ok) {
64
87
  const fallback = errorFallback?.(response) ?? `Request failed with status ${response.status}`;
65
88
  throw new Error(await readApiError(response, fallback));
@@ -107,8 +130,8 @@ export async function fetchWithTimeout(
107
130
  }
108
131
 
109
132
  try {
110
- return await fetch(withInspectorBasePath(input), {
111
- ...withBrowserMutationProof(init),
133
+ return await fetchControl(input, {
134
+ ...init,
112
135
  signal: controller.signal,
113
136
  });
114
137
  } catch (error) {
@@ -0,0 +1,29 @@
1
+ import type { ApiFormat } from "../contracts/log";
2
+
3
+ type KnownApiFormat = Exclude<ApiFormat, "unknown">;
4
+
5
+ /**
6
+ * Request paths whose protocol is part of the public Agent Inspector contract.
7
+ *
8
+ * Keep this module browser-safe: both the proxy registry and the UI's log
9
+ * presentation use the same path classifier without importing proxy startup
10
+ * registrations or provider implementations.
11
+ */
12
+ export const API_FORMAT_PATH_ENTRIES: ReadonlyArray<
13
+ readonly [path: string, format: KnownApiFormat]
14
+ > = [
15
+ ["/v1/messages", "anthropic"],
16
+ ["/v1/chat/completions", "openai"],
17
+ ["/chat/completions", "openai"],
18
+ ["/v1/responses", "openai"],
19
+ ["/responses", "openai"],
20
+ ];
21
+
22
+ /** Resolve an API format from its authoritative request path. */
23
+ export function apiFormatForPath(path: string): ApiFormat {
24
+ const requestPath = path.split("?")[0] ?? "";
25
+ for (const [knownPath, format] of API_FORMAT_PATH_ENTRIES) {
26
+ if (requestPath === knownPath) return format;
27
+ }
28
+ return "unknown";
29
+ }
@@ -4,6 +4,9 @@ export const AGENT_INSPECTOR_BASE_PATH_ENV = "AGENT_INSPECTOR_BASE_PATH";
4
4
  export const AGENT_INSPECTOR_INTERNAL_STRIPPED_BASE_PATH_ENV =
5
5
  "AGENT_INSPECTOR_INTERNAL_STRIPPED_BASE_PATH";
6
6
  export const AGENT_INSPECTOR_BASE_PATH_META_NAME = "agent-inspector-base-path";
7
+ export const AGENT_INSPECTOR_PUBLIC_BASE_PATH_HEADER = "x-agent-inspector-public-base-path";
8
+ export const AGENT_INSPECTOR_PUBLIC_PORT_HEADER = "x-agent-inspector-public-port";
9
+ export const AGENT_INSPECTOR_PUBLIC_ORIGIN_HEADER = "x-agent-inspector-public-origin";
7
10
  export const DEFAULT_AGENT_INSPECTOR_BASE_PATH = "/inspector";
8
11
 
9
12
  type BasePathEnv = Readonly<Record<string, string | undefined>>;
@@ -12,6 +15,24 @@ function trimSlashes(value: string): string {
12
15
  return value.replace(/^\/+/u, "").replace(/\/+$/u, "");
13
16
  }
14
17
 
18
+ const SAFE_PUBLIC_BASE_PATH_PATTERN = /^\/[A-Za-z0-9._~-]+(?:\/[A-Za-z0-9._~-]+)*$/u;
19
+
20
+ /**
21
+ * Normalize a public mount path only when every segment is safe to reuse in
22
+ * URLs, HTML attributes, JavaScript bootstrap data, and ingress routing.
23
+ * Root is represented internally as the empty string.
24
+ */
25
+ export function normalizePublicBasePath(value: string | undefined): string | null {
26
+ const trimmed = value?.trim() ?? "";
27
+ if (trimmed.length === 0 || trimmed === "/") return "";
28
+ if (!trimmed.startsWith("/") || trimmed.startsWith("//")) return null;
29
+
30
+ const normalized = normalizeBasePath(trimmed);
31
+ if (!SAFE_PUBLIC_BASE_PATH_PATTERN.test(normalized)) return null;
32
+ if (normalized.split("/").some((segment) => segment === "." || segment === "..")) return null;
33
+ return normalized;
34
+ }
35
+
15
36
  export function normalizeBasePath(value: string | undefined): string {
16
37
  const trimmed = value?.trim();
17
38
  if (trimmed === undefined || trimmed.length === 0 || trimmed === "/") return "";
@@ -35,13 +56,16 @@ function readProcessBasePath(): string | undefined {
35
56
  }
36
57
 
37
58
  export function getConfiguredBasePath(env?: BasePathEnv): string {
38
- return normalizeBasePath(
39
- env?.[AGENT_INSPECTOR_BASE_PATH_ENV] ??
40
- readProcessBasePath() ??
41
- readDocumentBasePath() ??
42
- import.meta.env?.BASE_URL ??
43
- DEFAULT_AGENT_INSPECTOR_BASE_PATH,
44
- );
59
+ const configured =
60
+ env !== undefined
61
+ ? (env[AGENT_INSPECTOR_BASE_PATH_ENV] ?? DEFAULT_AGENT_INSPECTOR_BASE_PATH)
62
+ : (readProcessBasePath() ??
63
+ readDocumentBasePath() ??
64
+ import.meta.env?.BASE_URL ??
65
+ DEFAULT_AGENT_INSPECTOR_BASE_PATH);
66
+ const normalized = normalizePublicBasePath(configured);
67
+ if (normalized !== null) return normalized;
68
+ return normalizePublicBasePath(DEFAULT_AGENT_INSPECTOR_BASE_PATH) ?? "";
45
69
  }
46
70
 
47
71
  export function getRouterBasePath(env?: BasePathEnv): string {
@@ -0,0 +1,124 @@
1
+ import { z } from "zod";
2
+ import { normalizePublicBasePath } from "./basePath";
3
+
4
+ export const BROWSER_RUNTIME_SCHEMA_VERSION = 1;
5
+ export const BROWSER_RUNTIME_JSON_PLACEHOLDER = "__AGENT_INSPECTOR_RUNTIME_JSON__";
6
+
7
+ function parseAbsoluteUrl(value: string): URL | null {
8
+ try {
9
+ return new URL(value);
10
+ } catch {
11
+ return null;
12
+ }
13
+ }
14
+
15
+ function hasUnsafePathSegment(pathname: string): boolean {
16
+ return pathname
17
+ .split("/")
18
+ .some((segment) => segment === "." || segment === ".." || /%(?:2e|2f|5c)/iu.test(segment));
19
+ }
20
+
21
+ function hasControlCharacter(value: string): boolean {
22
+ return [...value].some((character) => {
23
+ const code = character.charCodeAt(0);
24
+ return code < 32 || code === 127;
25
+ });
26
+ }
27
+
28
+ export function normalizeBrowserRuntimeBasePath(value: string): string | null {
29
+ const trimmed = value.trim();
30
+ if (trimmed.length === 0) return null;
31
+ const normalized = normalizePublicBasePath(trimmed);
32
+ if (normalized === null) return null;
33
+ return normalized.length === 0 ? "/" : normalized;
34
+ }
35
+
36
+ export function normalizeBrowserRuntimeBaseUrl(value: string): string | null {
37
+ if (
38
+ value.trim() !== value ||
39
+ value.includes("\\") ||
40
+ hasControlCharacter(value) ||
41
+ hasUnsafePathSegment(value)
42
+ ) {
43
+ return null;
44
+ }
45
+
46
+ const parsed = parseAbsoluteUrl(value);
47
+ if (parsed === null) return null;
48
+
49
+ switch (parsed.protocol) {
50
+ case "http:":
51
+ case "https:":
52
+ break;
53
+ default:
54
+ return null;
55
+ }
56
+
57
+ if (
58
+ parsed.username.length > 0 ||
59
+ parsed.password.length > 0 ||
60
+ parsed.search.length > 0 ||
61
+ parsed.hash.length > 0 ||
62
+ hasUnsafePathSegment(parsed.pathname)
63
+ ) {
64
+ return null;
65
+ }
66
+
67
+ const basePath = normalizeBrowserRuntimeBasePath(parsed.pathname);
68
+ if (basePath === null) return null;
69
+ return basePath === "/" ? parsed.origin : `${parsed.origin}${basePath}`;
70
+ }
71
+
72
+ export const BrowserRuntimeBasePathSchema = z
73
+ .string()
74
+ .min(1)
75
+ .max(2_048)
76
+ .refine(
77
+ (value) => normalizeBrowserRuntimeBasePath(value) !== null,
78
+ "UI Base Path must be an absolute path without query, hash, backslash, or traversal",
79
+ )
80
+ .transform((value) => normalizeBrowserRuntimeBasePath(value) ?? value);
81
+
82
+ export const BrowserRuntimeBaseUrlSchema = z
83
+ .string()
84
+ .min(1)
85
+ .max(2_048)
86
+ .refine(
87
+ (value) => normalizeBrowserRuntimeBaseUrl(value) !== null,
88
+ "Runtime Base URL must be an HTTP(S) URL without credentials, query, hash, or traversal",
89
+ )
90
+ .transform((value) => normalizeBrowserRuntimeBaseUrl(value) ?? value);
91
+
92
+ export const BrowserRuntimeCapabilitiesSchema = z
93
+ .object({
94
+ rest: z.boolean(),
95
+ sse: z.boolean(),
96
+ proxy: z.boolean(),
97
+ mcp: z.boolean(),
98
+ })
99
+ .strict();
100
+
101
+ export const BrowserRuntimeDeploymentSchema = z
102
+ .object({
103
+ schemaVersion: z.literal(BROWSER_RUNTIME_SCHEMA_VERSION),
104
+ deploymentMode: z.enum(["composed", "backend-only", "separated"]),
105
+ ui: z
106
+ .object({
107
+ basePath: BrowserRuntimeBasePathSchema,
108
+ })
109
+ .strict(),
110
+ control: z
111
+ .object({
112
+ baseUrl: BrowserRuntimeBaseUrlSchema,
113
+ })
114
+ .strict(),
115
+ agent: z
116
+ .object({
117
+ baseUrl: BrowserRuntimeBaseUrlSchema,
118
+ })
119
+ .strict(),
120
+ capabilities: BrowserRuntimeCapabilitiesSchema,
121
+ })
122
+ .strict();
123
+
124
+ export type BrowserRuntimeDeployment = z.infer<typeof BrowserRuntimeDeploymentSchema>;
@@ -0,0 +1,244 @@
1
+ import { getConfiguredBasePath } from "./basePath";
2
+ import {
3
+ BROWSER_RUNTIME_SCHEMA_VERSION,
4
+ BrowserRuntimeDeploymentSchema,
5
+ normalizeBrowserRuntimeBasePath,
6
+ normalizeBrowserRuntimeBaseUrl,
7
+ type BrowserRuntimeDeployment,
8
+ } from "./browserRuntimeContract";
9
+
10
+ export const AGENT_INSPECTOR_INJECTED_RUNTIME_GLOBAL = "__AGENT_INSPECTOR_RUNTIME__";
11
+ export const AGENT_INSPECTOR_OPERATOR_RUNTIME_GLOBAL = "__AGENT_INSPECTOR_RUNTIME_CONFIG__";
12
+ export const AGENT_INSPECTOR_RUNTIME_DISCOVERED_EVENT = "agent-inspector:runtime-discovered";
13
+
14
+ export type BrowserRuntimeSource = "injected" | "operator" | "discovered" | "composed-fallback";
15
+
16
+ export type BrowserRuntimeComposedFallback = {
17
+ origin: string;
18
+ uiBasePath: string;
19
+ };
20
+
21
+ export type BrowserRuntimeSources = {
22
+ injected?: unknown;
23
+ operator?: unknown;
24
+ composedFallback?: BrowserRuntimeComposedFallback;
25
+ };
26
+
27
+ export type BrowserRuntimeResolution =
28
+ | {
29
+ ok: true;
30
+ source: BrowserRuntimeSource;
31
+ runtime: BrowserRuntimeDeployment;
32
+ }
33
+ | {
34
+ ok: false;
35
+ source: BrowserRuntimeSource | "none";
36
+ code: "invalid" | "missing";
37
+ issues: readonly string[];
38
+ };
39
+
40
+ let discoveredRuntimeForDocument: BrowserRuntimeDeployment | null = null;
41
+
42
+ function readGlobalValue(name: string): unknown {
43
+ const descriptor = Object.getOwnPropertyDescriptor(globalThis, name);
44
+ const value: unknown = descriptor?.value;
45
+ if (
46
+ typeof value === "object" &&
47
+ value !== null &&
48
+ !Array.isArray(value) &&
49
+ Object.keys(value).length === 0
50
+ ) {
51
+ return undefined;
52
+ }
53
+ return value;
54
+ }
55
+
56
+ export function readBrowserRuntimeSources(): Pick<BrowserRuntimeSources, "injected" | "operator"> {
57
+ return {
58
+ injected: readGlobalValue(AGENT_INSPECTOR_INJECTED_RUNTIME_GLOBAL),
59
+ operator: readGlobalValue(AGENT_INSPECTOR_OPERATOR_RUNTIME_GLOBAL),
60
+ };
61
+ }
62
+
63
+ function formatIssues(error: {
64
+ issues: readonly { path: PropertyKey[]; message: string }[];
65
+ }): string[] {
66
+ return error.issues.map((issue) => {
67
+ const path = issue.path.map(String).join(".");
68
+ return path.length === 0 ? issue.message : `${path}: ${issue.message}`;
69
+ });
70
+ }
71
+
72
+ function validateRuntime(source: BrowserRuntimeSource, value: unknown): BrowserRuntimeResolution {
73
+ const parsed = BrowserRuntimeDeploymentSchema.safeParse(value);
74
+ if (parsed.success) {
75
+ return { ok: true, source, runtime: parsed.data };
76
+ }
77
+ return {
78
+ ok: false,
79
+ source,
80
+ code: "invalid",
81
+ issues: formatIssues(parsed.error),
82
+ };
83
+ }
84
+
85
+ function fallbackRuntime(fallback: BrowserRuntimeComposedFallback): unknown {
86
+ const normalizedOrigin = normalizeBrowserRuntimeBaseUrl(fallback.origin);
87
+ const normalizedBasePath = normalizeBrowserRuntimeBasePath(
88
+ fallback.uiBasePath.length === 0 ? "/" : fallback.uiBasePath,
89
+ );
90
+ if (
91
+ normalizedOrigin === null ||
92
+ normalizedBasePath === null ||
93
+ normalizedOrigin !== new URL(normalizedOrigin).origin
94
+ ) {
95
+ return null;
96
+ }
97
+
98
+ const baseUrl =
99
+ normalizedBasePath === "/" ? normalizedOrigin : `${normalizedOrigin}${normalizedBasePath}`;
100
+ return {
101
+ schemaVersion: BROWSER_RUNTIME_SCHEMA_VERSION,
102
+ deploymentMode: "composed",
103
+ ui: { basePath: normalizedBasePath },
104
+ control: { baseUrl },
105
+ agent: { baseUrl },
106
+ capabilities: {
107
+ rest: true,
108
+ sse: true,
109
+ proxy: true,
110
+ mcp: true,
111
+ },
112
+ };
113
+ }
114
+
115
+ export function resolveBrowserRuntime(sources: BrowserRuntimeSources): BrowserRuntimeResolution {
116
+ if (sources.injected !== undefined) {
117
+ return validateRuntime("injected", sources.injected);
118
+ }
119
+ if (sources.operator !== undefined) {
120
+ return validateRuntime("operator", sources.operator);
121
+ }
122
+ if (sources.composedFallback !== undefined) {
123
+ return validateRuntime("composed-fallback", fallbackRuntime(sources.composedFallback));
124
+ }
125
+ return {
126
+ ok: false,
127
+ source: "none",
128
+ code: "missing",
129
+ issues: ["No injected, operator, or explicit composed runtime configuration is available."],
130
+ };
131
+ }
132
+
133
+ function configuredBrowserRuntimeForDocument(): BrowserRuntimeResolution | null {
134
+ const sources = readBrowserRuntimeSources();
135
+ if (sources.injected !== undefined || sources.operator !== undefined) {
136
+ return resolveBrowserRuntime(sources);
137
+ }
138
+ return null;
139
+ }
140
+
141
+ export function acceptBrowserRuntimeDiscovery(
142
+ expectedFallback: BrowserRuntimeDeployment,
143
+ value: unknown,
144
+ ): BrowserRuntimeResolution {
145
+ const discovered = validateRuntime("discovered", value);
146
+ if (!discovered.ok) return discovered;
147
+ if (
148
+ discovered.runtime.control.baseUrl !== expectedFallback.control.baseUrl ||
149
+ discovered.runtime.ui.basePath !== expectedFallback.ui.basePath
150
+ ) {
151
+ return {
152
+ ok: false,
153
+ source: "discovered",
154
+ code: "invalid",
155
+ issues: ["Backend discovery does not match the same-origin fallback control surface."],
156
+ };
157
+ }
158
+ discoveredRuntimeForDocument = discovered.runtime;
159
+ if (typeof globalThis.dispatchEvent === "function" && typeof globalThis.Event === "function") {
160
+ globalThis.dispatchEvent(new Event(AGENT_INSPECTOR_RUNTIME_DISCOVERED_EVENT));
161
+ }
162
+ return discovered;
163
+ }
164
+
165
+ export function resolveVerifiedBrowserRuntimeForDocument(): BrowserRuntimeResolution {
166
+ const configured = configuredBrowserRuntimeForDocument();
167
+ if (configured !== null) return configured;
168
+ if (discoveredRuntimeForDocument !== null) {
169
+ return validateRuntime("discovered", discoveredRuntimeForDocument);
170
+ }
171
+ return {
172
+ ok: false,
173
+ source: "none",
174
+ code: "missing",
175
+ issues: ["The same-origin backend discovery response has not been validated."],
176
+ };
177
+ }
178
+
179
+ export function resolveBrowserRuntimeForDocument(): BrowserRuntimeResolution {
180
+ const configured = configuredBrowserRuntimeForDocument();
181
+ if (configured !== null) return configured;
182
+ if (discoveredRuntimeForDocument !== null) {
183
+ return validateRuntime("discovered", discoveredRuntimeForDocument);
184
+ }
185
+ if (typeof globalThis.location === "undefined") return resolveBrowserRuntime({});
186
+ return resolveBrowserRuntime({
187
+ composedFallback: {
188
+ origin: globalThis.location.origin,
189
+ uiBasePath: getConfiguredBasePath(),
190
+ },
191
+ });
192
+ }
193
+
194
+ function hasControlCharacter(value: string): boolean {
195
+ return [...value].some((character) => {
196
+ const code = character.charCodeAt(0);
197
+ return code < 32 || code === 127;
198
+ });
199
+ }
200
+
201
+ function normalizeLogicalRuntimePath(value: string): string | null {
202
+ if (
203
+ value.trim() !== value ||
204
+ !value.startsWith("/") ||
205
+ value.startsWith("//") ||
206
+ value.includes("#") ||
207
+ value.includes("\\") ||
208
+ hasControlCharacter(value)
209
+ ) {
210
+ return null;
211
+ }
212
+
213
+ const queryIndex = value.indexOf("?");
214
+ const pathname = queryIndex < 0 ? value : value.slice(0, queryIndex);
215
+ const segments = pathname.split("/");
216
+ if (
217
+ segments.some(
218
+ (segment) => segment === "." || segment === ".." || /%(?:2e|2f|5c)/iu.test(segment),
219
+ )
220
+ ) {
221
+ return null;
222
+ }
223
+ return value === "/" ? "" : value;
224
+ }
225
+
226
+ function buildRuntimeUrl(baseUrl: string, logicalPath: string): string | null {
227
+ const path = normalizeLogicalRuntimePath(logicalPath);
228
+ if (path === null) return null;
229
+ return `${baseUrl}${path}`;
230
+ }
231
+
232
+ export function buildControlRuntimeUrl(
233
+ runtime: BrowserRuntimeDeployment,
234
+ logicalPath: string,
235
+ ): string | null {
236
+ return buildRuntimeUrl(runtime.control.baseUrl, logicalPath);
237
+ }
238
+
239
+ export function buildAgentRuntimeUrl(
240
+ runtime: BrowserRuntimeDeployment,
241
+ logicalPath: string,
242
+ ): string | null {
243
+ return buildRuntimeUrl(runtime.agent.baseUrl, logicalPath);
244
+ }
@@ -1,3 +1,5 @@
1
+ import { isPlainRecord, safeGetOwnProperty } from "./objectUtils";
2
+
1
3
  /**
2
4
  * Claude Code (and similar Anthropic SDK-based clients) prepend a synthetic
3
5
  * text block to the `system` array that looks like an HTTP header:
@@ -9,9 +11,8 @@
9
11
  * changes on every request, which kills prefix-cache hit rates and wastes
10
12
  * input tokens.
11
13
  *
12
- * This module detects the marker and returns a rewritten body with the
13
- * block removed. It is opt-in (see constants.ts) so the proxy remains a
14
- * transparent pass-through by default.
14
+ * This browser-safe module contains only the pure request transformation so
15
+ * the proxy and UI preview can share it without coupling the UI to the proxy.
15
16
  */
16
17
 
17
18
  const BILLING_HEADER_PREFIX = "x-anthropic-billing-header:";
@@ -33,8 +34,6 @@ export function isClaudeCodeBillingHeaderBlock(text: string): boolean {
33
34
  return trimmed.toLowerCase().startsWith(BILLING_HEADER_PREFIX);
34
35
  }
35
36
 
36
- import { safeGetOwnProperty, isPlainRecord } from "../lib/objectUtils";
37
-
38
37
  function isObjectWithSystem(value: unknown): value is { system?: unknown[] } {
39
38
  if (!isPlainRecord(value)) return false;
40
39
  return Object.prototype.hasOwnProperty.call(value, "system");
@@ -53,8 +52,8 @@ function isBillingHeaderTextBlock(block: unknown): boolean {
53
52
  * Inspects the request body and, if it is an Anthropic-format request whose
54
53
  * `system` array contains one or more Claude Code billing-header text blocks,
55
54
  * returns a new body with those blocks removed. The original string is
56
- * returned unchanged (by reference equality on the result) when no edit is
57
- * needed so callers can avoid re-serializing.
55
+ * returned unchanged when no edit is needed so callers can avoid
56
+ * re-serializing.
58
57
  */
59
58
  export function stripClaudeCodeBillingHeader(rawBody: string): StripResult {
60
59
  let parsed: unknown;
@@ -0,0 +1,54 @@
1
+ import { appendBasePathToOrigin } from "./basePath";
2
+ import type { BrowserRuntimeDeployment } from "./browserRuntimeContract";
3
+ import {
4
+ AGENT_INSPECTOR_RUNTIME_DISCOVERED_EVENT,
5
+ buildAgentRuntimeUrl,
6
+ resolveVerifiedBrowserRuntimeForDocument,
7
+ } from "./browserRuntimeResolver";
8
+
9
+ export type CodingAgentEndpoints = {
10
+ proxy: string;
11
+ openAiV1: string;
12
+ mcp: string;
13
+ };
14
+
15
+ /** Derive the public protocol endpoints shown to coding agents from one Inspector origin. */
16
+ export function deriveCodingAgentEndpoints(origin: string, basePath: string): CodingAgentEndpoints {
17
+ return {
18
+ proxy: appendBasePathToOrigin(origin, "/proxy", basePath),
19
+ openAiV1: appendBasePathToOrigin(origin, "/proxy/v1", basePath),
20
+ mcp: appendBasePathToOrigin(origin, "/api/mcp", basePath),
21
+ };
22
+ }
23
+
24
+ /** Derive copyable Coding Agent endpoints exclusively from the agent-facing runtime surface. */
25
+ export function deriveCodingAgentEndpointsFromRuntime(
26
+ runtime: BrowserRuntimeDeployment,
27
+ ): CodingAgentEndpoints | null {
28
+ const proxy = buildAgentRuntimeUrl(runtime, "/proxy");
29
+ const openAiV1 = buildAgentRuntimeUrl(runtime, "/proxy/v1");
30
+ const mcp = buildAgentRuntimeUrl(runtime, "/api/mcp");
31
+ if (proxy === null || openAiV1 === null || mcp === null) return null;
32
+ return { proxy, openAiV1, mcp };
33
+ }
34
+
35
+ export function resolveCodingAgentEndpointsForDocument(): CodingAgentEndpoints | null {
36
+ const runtime = resolveVerifiedBrowserRuntimeForDocument();
37
+ if (!runtime.ok) return null;
38
+ return deriveCodingAgentEndpointsFromRuntime(runtime.runtime);
39
+ }
40
+
41
+ export function subscribeCodingAgentEndpoints(
42
+ listener: (endpoints: CodingAgentEndpoints | null) => void,
43
+ ): () => void {
44
+ const update = (): void => listener(resolveCodingAgentEndpointsForDocument());
45
+ update();
46
+ if (
47
+ typeof globalThis.addEventListener !== "function" ||
48
+ typeof globalThis.removeEventListener !== "function"
49
+ ) {
50
+ return () => undefined;
51
+ }
52
+ globalThis.addEventListener(AGENT_INSPECTOR_RUNTIME_DISCOVERED_EVENT, update);
53
+ return () => globalThis.removeEventListener(AGENT_INSPECTOR_RUNTIME_DISCOVERED_EVENT, update);
54
+ }