@tonyclaw/agent-inspector 3.0.45 → 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 (338) 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 +2326 -516
  4. package/.output/server/_libs/extend.mjs +4 -8
  5. package/.output/server/_libs/jszip.mjs +9 -35
  6. package/.output/server/_libs/react-dom.mjs +2 -3
  7. package/.output/server/_libs/react.mjs +1 -27
  8. package/.output/server/_libs/tanstack__react-router.mjs +1 -329
  9. package/.output/server/_libs/tanstack__router-core.mjs +42 -100
  10. package/.output/server/_libs/use-sync-external-store.mjs +1 -64
  11. package/.output/server/_libs/ws.mjs +1 -1
  12. package/.output/server/_ssr/index.mjs +4 -4
  13. package/.output/server/_ssr/{publicBasePathContext-5264L3rX.mjs → publicBasePathContext-IH2ilOfu.mjs} +52 -24
  14. package/.output/server/_ssr/{router-BJ_ltLim.mjs → router-D18yUq36.mjs} +19770 -19447
  15. package/.output/server/_ssr/{start-C6MjPjxp.mjs → start-COQu_AgD.mjs} +1 -1
  16. package/.output/server/_tanstack-start-manifest_v-DnbdNeun.mjs +4 -0
  17. package/.output/server/index.mjs +5 -145
  18. package/.output/{public/assets/CompareDrawer-B3_TLTJh.js → ui/assets/CompareDrawer-DAUuIJ6G.js} +1 -1
  19. package/.output/{public/assets/InspectorPet-Cpn6hv4P.js → ui/assets/InspectorPet-BRBVjOWI.js} +1 -1
  20. package/.output/ui/assets/ProxyViewerContainer-D7Sq0ctc.js +59 -0
  21. package/.output/{public/assets/ReplayDialog-B3EKVdJk.js → ui/assets/ReplayDialog-nDLsjOhs.js} +1 -1
  22. package/.output/{public/assets/RequestAnatomy-COOQjyUC.js → ui/assets/RequestAnatomy-zd4BDgL0.js} +1 -1
  23. package/.output/ui/assets/ResponseView-AdIXGcSn.js +2 -0
  24. package/.output/ui/assets/StreamingChunkSequence-CesTz8He.js +1 -0
  25. package/.output/{public/assets/_sessionId-zbgYl7ZJ.js → ui/assets/_sessionId-BAfzrhSU.js} +1 -1
  26. package/.output/{public/assets/_sessionId-BJlM3nmt.js → ui/assets/_sessionId-QnBomgPD.js} +1 -1
  27. package/.output/ui/assets/favicon-DYEkHSNl.svg +21 -0
  28. package/.output/{public/assets/index-BIK4bPTv.js → ui/assets/index-BcsdxBAd.js} +1 -1
  29. package/.output/ui/assets/index-BvXp42al.css +1 -0
  30. package/.output/{public/assets/index-D2Qw6Ri2.js → ui/assets/index-D0rtCN9V.js} +1 -1
  31. package/.output/ui/assets/index-DHpwr08Z.js +73 -0
  32. package/.output/{public/assets/index-xF_NY8Yb.js → ui/assets/index-dNuk2dsU.js} +5 -5
  33. package/.output/ui/assets/json-viewer-BvFHglMb.js +1 -0
  34. package/.output/{public/assets/jszip.min-B_rfAUCe.js → ui/assets/jszip.min-B5Z7gNZB.js} +1 -1
  35. package/.output/ui/index.html +229 -0
  36. package/.output/ui/runtime-config.js +2 -0
  37. package/.output/workers/logFinalizer.worker.js +979 -414
  38. package/.output/workers/sessionWorkerEntry.js +979 -414
  39. package/README.md +175 -43
  40. package/docs/instance-control.openapi.yaml +59 -4
  41. package/package.json +25 -5
  42. package/scripts/generate-theme-scales.mjs +3 -3
  43. package/src/{router.tsx → backend/router.tsx} +3 -15
  44. package/src/backend/routes/$.ts +26 -0
  45. package/src/backend/routes/__root.ts +4 -0
  46. package/src/{routes → backend/routes}/api/-instances.ts +3 -3
  47. package/src/{routes → backend/routes}/api/alerts.summary.ts +3 -3
  48. package/src/{routes → backend/routes}/api/alerts.ts +4 -4
  49. package/src/{routes → backend/routes}/api/config.paths.ts +1 -1
  50. package/src/{routes → backend/routes}/api/config.ts +11 -2
  51. package/src/{routes → backend/routes}/api/ecosystem.packages.$packageId.help.ts +1 -1
  52. package/src/{routes → backend/routes}/api/ecosystem.packages.$packageId.install.ts +1 -1
  53. package/src/{routes → backend/routes}/api/ecosystem.packages.$packageId.runner-presets.ts +1 -1
  54. package/src/{routes → backend/routes}/api/ecosystem.packages.$packageId.upgrade.ts +1 -1
  55. package/src/{routes → backend/routes}/api/ecosystem.packages.ts +5 -1
  56. package/src/{routes → backend/routes}/api/ecosystem.recipes.$recipeId.run.ts +1 -1
  57. package/src/{routes → backend/routes}/api/ecosystem.tasks.$taskId.ts +1 -1
  58. package/src/{routes → backend/routes}/api/ecosystem.tasks.ts +1 -1
  59. package/src/{routes → backend/routes}/api/groups.$groupId.evidence.ts +2 -2
  60. package/src/{routes → backend/routes}/api/groups.$groupId.sessions.ts +2 -2
  61. package/src/{routes → backend/routes}/api/groups.$groupId.ts +2 -2
  62. package/src/{routes → backend/routes}/api/groups.ts +2 -2
  63. package/src/{routes → backend/routes}/api/health.ts +3 -3
  64. package/src/{routes → backend/routes}/api/instances.$name.connection.ts +1 -1
  65. package/src/{routes → backend/routes}/api/instances.$name.restart.ts +2 -2
  66. package/src/{routes → backend/routes}/api/instances.$name.start.ts +2 -2
  67. package/src/{routes → backend/routes}/api/instances.$name.stop.ts +2 -2
  68. package/src/{routes → backend/routes}/api/instances.$name.ts +1 -1
  69. package/src/{routes → backend/routes}/api/instances.ts +1 -1
  70. package/src/{routes → backend/routes}/api/knowledge.candidates.$candidateId.promote.ts +2 -2
  71. package/src/{routes → backend/routes}/api/knowledge.candidates.$candidateId.ts +2 -2
  72. package/src/{routes → backend/routes}/api/knowledge.candidates.ts +1 -1
  73. package/src/{routes → backend/routes}/api/knowledge.project-context.ts +2 -2
  74. package/src/{routes → backend/routes}/api/knowledge.search.ts +2 -2
  75. package/src/{routes → backend/routes}/api/knowledge.sessions.$sessionId.candidates.ts +3 -3
  76. package/src/{routes → backend/routes}/api/logs.$id.body.ts +6 -6
  77. package/src/{routes → backend/routes}/api/logs.$id.chunks.ts +5 -4
  78. package/src/{routes → backend/routes}/api/logs.$id.replay.ts +12 -11
  79. package/src/{routes → backend/routes}/api/logs.$id.ts +4 -3
  80. package/src/{routes → backend/routes}/api/logs.import.ts +3 -3
  81. package/src/{routes → backend/routes}/api/logs.stream.ts +11 -7
  82. package/src/{routes → backend/routes}/api/logs.ts +17 -9
  83. package/src/{routes → backend/routes}/api/mcp.ts +1 -1
  84. package/src/{routes → backend/routes}/api/models.ts +1 -1
  85. package/src/{routes → backend/routes}/api/pi-agent.ts +2 -2
  86. package/src/{routes → backend/routes}/api/providers.$providerId.model-metadata.ts +5 -5
  87. package/src/{routes → backend/routes}/api/providers.$providerId.test.log.ts +7 -7
  88. package/src/{routes → backend/routes}/api/providers.$providerId.ts +4 -4
  89. package/src/{routes → backend/routes}/api/providers.export.ts +1 -1
  90. package/src/{routes → backend/routes}/api/providers.import.ts +3 -3
  91. package/src/{routes → backend/routes}/api/providers.scan.ts +2 -2
  92. package/src/{routes → backend/routes}/api/providers.ts +9 -4
  93. package/src/{routes → backend/routes}/api/runs.$runId.evidence.ts +2 -2
  94. package/src/{routes → backend/routes}/api/runs.$runId.ts +2 -2
  95. package/src/{routes → backend/routes}/api/runs.ts +4 -4
  96. package/src/backend/routes/api/runtime.ts +46 -0
  97. package/src/{routes → backend/routes}/api/sessions.ts +3 -3
  98. package/src/{routes → backend/routes}/proxy/$.ts +1 -1
  99. package/src/{routes → backend/routes}/readyz.ts +1 -1
  100. package/src/{start.ts → backend/start.ts} +1 -1
  101. package/src/cli/alias.ts +2 -11
  102. package/src/cli/doctor.ts +32 -9
  103. package/src/cli/instance.ts +26 -13
  104. package/src/cli/instanceArgs.ts +30 -11
  105. package/src/cli/instanceControl.ts +0 -2
  106. package/src/cli/instanceModel.ts +9 -17
  107. package/src/cli/instanceRegistry.ts +0 -9
  108. package/src/cli/networkHints.ts +27 -14
  109. package/src/cli/onboard.ts +69 -2
  110. package/src/cli/onboardTarget.ts +89 -40
  111. package/src/cli/templates/codex-skill-onboard.ts +44 -14
  112. package/src/cli/templates/skill-onboard.ts +64 -28
  113. package/src/cli.ts +184 -61
  114. package/src/components/ProxyViewer.tsx +11 -9
  115. package/src/components/ProxyViewerContainer.tsx +12 -11
  116. package/src/components/pi-agent/PiAgentPanel.tsx +2 -2
  117. package/src/components/providers/ProviderCard.tsx +1 -1
  118. package/src/components/providers/ProviderTestResultsView.tsx +1 -1
  119. package/src/components/providers/SettingsDialog.tsx +159 -144
  120. package/src/components/proxy-viewer/ApplicationBar.tsx +2 -1
  121. package/src/components/proxy-viewer/LogEntry.tsx +1 -1
  122. package/src/components/proxy-viewer/log-formats/index.ts +1 -1
  123. package/src/contracts/index.ts +5 -0
  124. package/src/contracts/log.ts +33 -3
  125. package/src/knowledge/types.ts +3 -2
  126. package/src/lib/alertContract.ts +2 -2
  127. package/src/lib/apiClient.ts +30 -7
  128. package/src/lib/apiFormat.ts +29 -0
  129. package/src/lib/basePath.ts +29 -11
  130. package/src/lib/browserRuntimeContract.ts +124 -0
  131. package/src/lib/browserRuntimeResolver.ts +244 -0
  132. package/src/{proxy → lib}/claudeCodeStrip.ts +6 -7
  133. package/src/lib/codingAgentEndpoints.ts +38 -0
  134. package/src/lib/instanceContract.ts +27 -11
  135. package/src/lib/piAgentContract.ts +3 -2
  136. package/src/lib/publicBasePathContext.ts +40 -10
  137. package/src/lib/resourceLimits.ts +2 -0
  138. package/src/lib/runContract.ts +3 -3
  139. package/src/lib/sessionInfoContract.ts +3 -2
  140. package/src/mcp/instanceHandlers.ts +1 -0
  141. package/src/mcp/server.ts +19 -24
  142. package/src/proxy/config.ts +25 -30
  143. package/src/proxy/dataDir.ts +43 -7
  144. package/src/proxy/ecosystemTasks.ts +161 -70
  145. package/src/proxy/formats/registry.ts +6 -21
  146. package/src/proxy/handler.ts +129 -29
  147. package/src/proxy/identityProxy.ts +419 -39
  148. package/src/proxy/jsonlRecovery.ts +554 -0
  149. package/src/proxy/logFinalizer.ts +25 -10
  150. package/src/proxy/logImporter.ts +2 -1
  151. package/src/proxy/logIndex.ts +191 -95
  152. package/src/proxy/logger.ts +77 -14
  153. package/src/proxy/platformCommands.ts +41 -0
  154. package/src/proxy/privateDataPath.ts +310 -88
  155. package/src/proxy/rawStreamCapture.ts +194 -13
  156. package/src/proxy/runtimeAdmission.ts +5 -2
  157. package/src/proxy/runtimeHealth.ts +14 -1
  158. package/src/proxy/runtimeShutdown.ts +11 -1
  159. package/src/proxy/schemas.ts +7 -1
  160. package/src/proxy/sessionArchive.ts +78 -14
  161. package/src/proxy/sqliteLogIndex.ts +65 -2
  162. package/src/proxy/store.ts +141 -34
  163. package/src/proxy/uiAssetServer.ts +106 -0
  164. package/src/proxy/upstream.ts +29 -2
  165. package/src/ui/bootstrap.ts +167 -0
  166. package/src/ui/index.html +38 -0
  167. package/src/ui/logsStreamClient.ts +20 -0
  168. package/src/ui/main.tsx +13 -0
  169. package/src/ui/public/runtime-config.js +2 -0
  170. package/src/ui/router.tsx +13 -0
  171. package/src/ui/routes/__root.tsx +69 -0
  172. package/src/{routes → ui/routes}/index.tsx +2 -3
  173. package/src/{routes → ui/routes}/session/$sessionId.tsx +5 -11
  174. package/src/ui/runtimeDiscovery.ts +50 -0
  175. package/styles/globals.css +1 -0
  176. package/.output/public/assets/ProxyViewerContainer-BEAhuGOJ.js +0 -126
  177. package/.output/public/assets/ResponseView-DBCjkwye.js +0 -2
  178. package/.output/public/assets/StreamingChunkSequence-CuXhDgMo.js +0 -1
  179. package/.output/public/assets/index-BZo_8koU.js +0 -70
  180. package/.output/public/assets/index-ZWschkCh.css +0 -1
  181. package/.output/public/assets/json-viewer-B-Ao6pwW.js +0 -1
  182. package/.output/server/_libs/@radix-ui/react-accessible-icon+[...].mjs +0 -1
  183. package/.output/server/_libs/@radix-ui/react-dismissable-layer+[...].mjs +0 -344
  184. package/.output/server/_libs/@radix-ui/react-navigation-menu+[...].mjs +0 -2
  185. package/.output/server/_libs/@radix-ui/react-one-time-password-field+[...].mjs +0 -2
  186. package/.output/server/_libs/@radix-ui/react-password-toggle-field+[...].mjs +0 -2
  187. package/.output/server/_libs/@radix-ui/react-use-callback-ref+[...].mjs +0 -11
  188. package/.output/server/_libs/@radix-ui/react-use-controllable-state+[...].mjs +0 -69
  189. package/.output/server/_libs/@radix-ui/react-use-effect-event+[...].mjs +0 -1
  190. package/.output/server/_libs/@radix-ui/react-use-is-hydrated+[...].mjs +0 -28
  191. package/.output/server/_libs/@radix-ui/react-use-layout-effect+[...].mjs +0 -6
  192. package/.output/server/_libs/@radix-ui/react-visually-hidden+[...].mjs +0 -34
  193. package/.output/server/_libs/aria-hidden.mjs +0 -122
  194. package/.output/server/_libs/bail.mjs +0 -8
  195. package/.output/server/_libs/character-entities.mjs +0 -2130
  196. package/.output/server/_libs/class-variance-authority.mjs +0 -44
  197. package/.output/server/_libs/clsx.mjs +0 -16
  198. package/.output/server/_libs/comma-separated-tokens.mjs +0 -10
  199. package/.output/server/_libs/decode-named-character-reference+[...].mjs +0 -8
  200. package/.output/server/_libs/dequal.mjs +0 -27
  201. package/.output/server/_libs/detect-node-es.mjs +0 -1
  202. package/.output/server/_libs/devlop.mjs +0 -8
  203. package/.output/server/_libs/diff.mjs +0 -320
  204. package/.output/server/_libs/estree-util-is-identifier-name.mjs +0 -11
  205. package/.output/server/_libs/floating-ui__core.mjs +0 -725
  206. package/.output/server/_libs/floating-ui__dom.mjs +0 -622
  207. package/.output/server/_libs/floating-ui__react-dom.mjs +0 -292
  208. package/.output/server/_libs/floating-ui__utils.mjs +0 -320
  209. package/.output/server/_libs/get-nonce.mjs +0 -9
  210. package/.output/server/_libs/hast-util-to-jsx-runtime.mjs +0 -388
  211. package/.output/server/_libs/hast-util-whitespace.mjs +0 -10
  212. package/.output/server/_libs/html-url-attributes.mjs +0 -26
  213. package/.output/server/_libs/inline-style-parser.mjs +0 -142
  214. package/.output/server/_libs/is-plain-obj.mjs +0 -10
  215. package/.output/server/_libs/lucide-react.mjs +0 -1027
  216. package/.output/server/_libs/mdast-util-from-markdown.mjs +0 -717
  217. package/.output/server/_libs/mdast-util-to-hast.mjs +0 -710
  218. package/.output/server/_libs/mdast-util-to-string.mjs +0 -38
  219. package/.output/server/_libs/micromark-core-commonmark.mjs +0 -2259
  220. package/.output/server/_libs/micromark-factory-destination.mjs +0 -94
  221. package/.output/server/_libs/micromark-factory-label.mjs +0 -63
  222. package/.output/server/_libs/micromark-factory-space.mjs +0 -24
  223. package/.output/server/_libs/micromark-factory-title.mjs +0 -65
  224. package/.output/server/_libs/micromark-factory-whitespace.mjs +0 -22
  225. package/.output/server/_libs/micromark-util-character.mjs +0 -44
  226. package/.output/server/_libs/micromark-util-chunked.mjs +0 -36
  227. package/.output/server/_libs/micromark-util-classify-character+[...].mjs +0 -12
  228. package/.output/server/_libs/micromark-util-combine-extensions+[...].mjs +0 -41
  229. package/.output/server/_libs/micromark-util-decode-numeric-character-reference+[...].mjs +0 -19
  230. package/.output/server/_libs/micromark-util-decode-string.mjs +0 -21
  231. package/.output/server/_libs/micromark-util-encode.mjs +0 -1
  232. package/.output/server/_libs/micromark-util-html-tag-name.mjs +0 -69
  233. package/.output/server/_libs/micromark-util-normalize-identifier+[...].mjs +0 -6
  234. package/.output/server/_libs/micromark-util-resolve-all.mjs +0 -15
  235. package/.output/server/_libs/micromark-util-sanitize-uri.mjs +0 -41
  236. package/.output/server/_libs/micromark-util-subtokenize.mjs +0 -346
  237. package/.output/server/_libs/micromark.mjs +0 -906
  238. package/.output/server/_libs/property-information.mjs +0 -1209
  239. package/.output/server/_libs/radix-ui.mjs +0 -1
  240. package/.output/server/_libs/radix-ui__number.mjs +0 -6
  241. package/.output/server/_libs/radix-ui__primitive.mjs +0 -11
  242. package/.output/server/_libs/radix-ui__react-accordion.mjs +0 -1
  243. package/.output/server/_libs/radix-ui__react-alert-dialog.mjs +0 -1
  244. package/.output/server/_libs/radix-ui__react-arrow.mjs +0 -23
  245. package/.output/server/_libs/radix-ui__react-aspect-ratio.mjs +0 -1
  246. package/.output/server/_libs/radix-ui__react-avatar.mjs +0 -1
  247. package/.output/server/_libs/radix-ui__react-checkbox.mjs +0 -1
  248. package/.output/server/_libs/radix-ui__react-collapsible.mjs +0 -144
  249. package/.output/server/_libs/radix-ui__react-collection.mjs +0 -69
  250. package/.output/server/_libs/radix-ui__react-compose-refs.mjs +0 -38
  251. package/.output/server/_libs/radix-ui__react-context-menu.mjs +0 -1
  252. package/.output/server/_libs/radix-ui__react-context.mjs +0 -64
  253. package/.output/server/_libs/radix-ui__react-dialog.mjs +0 -280
  254. package/.output/server/_libs/radix-ui__react-direction.mjs +0 -9
  255. package/.output/server/_libs/radix-ui__react-dropdown-menu.mjs +0 -1
  256. package/.output/server/_libs/radix-ui__react-focus-guards.mjs +0 -39
  257. package/.output/server/_libs/radix-ui__react-focus-scope.mjs +0 -210
  258. package/.output/server/_libs/radix-ui__react-form.mjs +0 -1
  259. package/.output/server/_libs/radix-ui__react-hover-card.mjs +0 -1
  260. package/.output/server/_libs/radix-ui__react-id.mjs +0 -14
  261. package/.output/server/_libs/radix-ui__react-label.mjs +0 -1
  262. package/.output/server/_libs/radix-ui__react-menu.mjs +0 -1
  263. package/.output/server/_libs/radix-ui__react-menubar.mjs +0 -1
  264. package/.output/server/_libs/radix-ui__react-popover.mjs +0 -1
  265. package/.output/server/_libs/radix-ui__react-popper.mjs +0 -340
  266. package/.output/server/_libs/radix-ui__react-portal.mjs +0 -16
  267. package/.output/server/_libs/radix-ui__react-presence.mjs +0 -173
  268. package/.output/server/_libs/radix-ui__react-primitive.mjs +0 -42
  269. package/.output/server/_libs/radix-ui__react-progress.mjs +0 -1
  270. package/.output/server/_libs/radix-ui__react-radio-group.mjs +0 -1
  271. package/.output/server/_libs/radix-ui__react-roving-focus.mjs +0 -235
  272. package/.output/server/_libs/radix-ui__react-scroll-area.mjs +0 -731
  273. package/.output/server/_libs/radix-ui__react-select.mjs +0 -1207
  274. package/.output/server/_libs/radix-ui__react-separator.mjs +0 -28
  275. package/.output/server/_libs/radix-ui__react-slider.mjs +0 -1
  276. package/.output/server/_libs/radix-ui__react-slot.mjs +0 -132
  277. package/.output/server/_libs/radix-ui__react-switch.mjs +0 -1
  278. package/.output/server/_libs/radix-ui__react-tabs.mjs +0 -194
  279. package/.output/server/_libs/radix-ui__react-toast.mjs +0 -2
  280. package/.output/server/_libs/radix-ui__react-toggle-group.mjs +0 -1
  281. package/.output/server/_libs/radix-ui__react-toggle.mjs +0 -1
  282. package/.output/server/_libs/radix-ui__react-toolbar.mjs +0 -1
  283. package/.output/server/_libs/radix-ui__react-tooltip.mjs +0 -498
  284. package/.output/server/_libs/radix-ui__react-use-previous.mjs +0 -14
  285. package/.output/server/_libs/radix-ui__react-use-size.mjs +0 -39
  286. package/.output/server/_libs/react-markdown.mjs +0 -235
  287. package/.output/server/_libs/react-remove-scroll-bar.mjs +0 -82
  288. package/.output/server/_libs/react-remove-scroll.mjs +0 -328
  289. package/.output/server/_libs/react-style-singleton.mjs +0 -69
  290. package/.output/server/_libs/remark-parse.mjs +0 -19
  291. package/.output/server/_libs/remark-rehype.mjs +0 -21
  292. package/.output/server/_libs/space-separated-tokens.mjs +0 -6
  293. package/.output/server/_libs/style-to-js.mjs +0 -72
  294. package/.output/server/_libs/style-to-object.mjs +0 -38
  295. package/.output/server/_libs/swr.mjs +0 -947
  296. package/.output/server/_libs/tailwind-merge.mjs +0 -3255
  297. package/.output/server/_libs/tanstack__react-virtual.mjs +0 -130
  298. package/.output/server/_libs/tanstack__virtual-core.mjs +0 -1319
  299. package/.output/server/_libs/three.mjs +0 -26016
  300. package/.output/server/_libs/trim-lines.mjs +0 -41
  301. package/.output/server/_libs/trough.mjs +0 -85
  302. package/.output/server/_libs/tslib.mjs +0 -1
  303. package/.output/server/_libs/ungap__structured-clone.mjs +0 -212
  304. package/.output/server/_libs/unified.mjs +0 -661
  305. package/.output/server/_libs/unist-util-is.mjs +0 -100
  306. package/.output/server/_libs/unist-util-position.mjs +0 -27
  307. package/.output/server/_libs/unist-util-stringify-position.mjs +0 -27
  308. package/.output/server/_libs/unist-util-visit-parents.mjs +0 -82
  309. package/.output/server/_libs/unist-util-visit.mjs +0 -24
  310. package/.output/server/_libs/use-callback-ref.mjs +0 -66
  311. package/.output/server/_libs/use-sidecar.mjs +0 -106
  312. package/.output/server/_libs/vfile-message.mjs +0 -138
  313. package/.output/server/_libs/vfile.mjs +0 -467
  314. package/.output/server/_sessionId-CJ99gZFV.mjs +0 -84
  315. package/.output/server/_sessionId-DEjScBpK.mjs +0 -146
  316. package/.output/server/_ssr/CompareDrawer-DtOIMeQB.mjs +0 -1060
  317. package/.output/server/_ssr/InspectorPet-CXc4oCBQ.mjs +0 -938
  318. package/.output/server/_ssr/ProxyViewerContainer-DVPlwfkt.mjs +0 -17632
  319. package/.output/server/_ssr/ReplayDialog-BQEA95qC.mjs +0 -725
  320. package/.output/server/_ssr/RequestAnatomy-BMyd8B7Q.mjs +0 -837
  321. package/.output/server/_ssr/ResponseView-qrTaEIM8.mjs +0 -757
  322. package/.output/server/_ssr/StreamingChunkSequence-BFTL8mIy.mjs +0 -274
  323. package/.output/server/_ssr/index-Bcj1Hcy4.mjs +0 -135
  324. package/.output/server/_ssr/index-DW-M7XUG.mjs +0 -84
  325. package/.output/server/_ssr/json-viewer-DiI0Yjsn.mjs +0 -483
  326. package/.output/server/_tanstack-start-manifest_v-C6pXXX9R.mjs +0 -4
  327. package/.output/server/node_modules/tslib/modules/index.js +0 -70
  328. package/.output/server/node_modules/tslib/modules/package.json +0 -3
  329. package/.output/server/node_modules/tslib/package.json +0 -47
  330. package/.output/server/node_modules/tslib/tslib.js +0 -484
  331. package/.output/server/package.json +0 -9
  332. package/src/routes/__root.tsx +0 -170
  333. /package/.output/{public → ui}/assets/agent-inspector-58K1_MsC.ico +0 -0
  334. /package/.output/{public → ui}/assets/alibaba-TTwafVwX.svg +0 -0
  335. /package/.output/{public → ui}/assets/minimax-BPMzvuL-.jpeg +0 -0
  336. /package/.output/{public → ui}/assets/qwen-mMn3f5ul.webp +0 -0
  337. /package/.output/{public → ui}/assets/zhipuai-BPNAnxo-.svg +0 -0
  338. /package/src/{routes → backend/routes}/livez.ts +0 -0
@@ -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
+ }
@@ -6,6 +6,7 @@ export const AGENT_INSPECTOR_INTERNAL_STRIPPED_BASE_PATH_ENV =
6
6
  export const AGENT_INSPECTOR_BASE_PATH_META_NAME = "agent-inspector-base-path";
7
7
  export const AGENT_INSPECTOR_PUBLIC_BASE_PATH_HEADER = "x-agent-inspector-public-base-path";
8
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";
9
10
  export const DEFAULT_AGENT_INSPECTOR_BASE_PATH = "/inspector";
10
11
 
11
12
  type BasePathEnv = Readonly<Record<string, string | undefined>>;
@@ -14,6 +15,24 @@ function trimSlashes(value: string): string {
14
15
  return value.replace(/^\/+/u, "").replace(/\/+$/u, "");
15
16
  }
16
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
+
17
36
  export function normalizeBasePath(value: string | undefined): string {
18
37
  const trimmed = value?.trim();
19
38
  if (trimmed === undefined || trimmed.length === 0 || trimmed === "/") return "";
@@ -37,17 +56,16 @@ function readProcessBasePath(): string | undefined {
37
56
  }
38
57
 
39
58
  export function getConfiguredBasePath(env?: BasePathEnv): string {
40
- if (env !== undefined) {
41
- return normalizeBasePath(
42
- env[AGENT_INSPECTOR_BASE_PATH_ENV] ?? DEFAULT_AGENT_INSPECTOR_BASE_PATH,
43
- );
44
- }
45
- return normalizeBasePath(
46
- readProcessBasePath() ??
47
- readDocumentBasePath() ??
48
- import.meta.env?.BASE_URL ??
49
- DEFAULT_AGENT_INSPECTOR_BASE_PATH,
50
- );
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) ?? "";
51
69
  }
52
70
 
53
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;
@@ -1,4 +1,10 @@
1
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";
2
8
 
3
9
  export type CodingAgentEndpoints = {
4
10
  proxy: string;
@@ -14,3 +20,35 @@ export function deriveCodingAgentEndpoints(origin: string, basePath: string): Co
14
20
  mcp: appendBasePathToOrigin(origin, "/api/mcp", basePath),
15
21
  };
16
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
+ }