@tonyclaw/agent-inspector 3.0.45 → 3.0.47
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.
- package/.output/{nitro.json → backend/nitro.json} +3 -3
- package/.output/backend-public/assets/index-D4LX-sw-.js +11 -0
- package/.output/cli.js +8018 -5451
- package/.output/server/_libs/extend.mjs +4 -8
- package/.output/server/_libs/jszip.mjs +9 -35
- package/.output/server/_libs/react-dom.mjs +2 -3
- package/.output/server/_libs/react.mjs +1 -27
- package/.output/server/_libs/tanstack__react-router.mjs +1 -329
- package/.output/server/_libs/tanstack__router-core.mjs +42 -100
- package/.output/server/_libs/use-sync-external-store.mjs +1 -64
- package/.output/server/_libs/ws.mjs +1 -1
- package/.output/server/_ssr/index.mjs +4 -4
- package/.output/server/_ssr/{publicBasePathContext-5264L3rX.mjs → publicBasePathContext-IH2ilOfu.mjs} +52 -24
- package/.output/server/_ssr/{router-BJ_ltLim.mjs → router-BwZEsYfS.mjs} +19794 -19444
- package/.output/server/_ssr/{start-C6MjPjxp.mjs → start-COQu_AgD.mjs} +1 -1
- package/.output/server/_tanstack-start-manifest_v-DnbdNeun.mjs +4 -0
- package/.output/server/index.mjs +5 -145
- package/.output/{public/assets/CompareDrawer-B3_TLTJh.js → ui/assets/CompareDrawer-V-8lPASC.js} +1 -1
- package/.output/{public/assets/InspectorPet-Cpn6hv4P.js → ui/assets/InspectorPet-D4CVnfdf.js} +1 -1
- package/.output/ui/assets/ProxyViewerContainer-CO3ZVHLX.js +59 -0
- package/.output/{public/assets/ReplayDialog-B3EKVdJk.js → ui/assets/ReplayDialog-CpGyTLtt.js} +1 -1
- package/.output/{public/assets/RequestAnatomy-COOQjyUC.js → ui/assets/RequestAnatomy-BLuJL9dZ.js} +1 -1
- package/.output/ui/assets/ResponseView-BuSC-CH7.js +2 -0
- package/.output/ui/assets/StreamingChunkSequence-DeA-JJKa.js +1 -0
- package/.output/{public/assets/_sessionId-zbgYl7ZJ.js → ui/assets/_sessionId-8HuHFhjo.js} +1 -1
- package/.output/{public/assets/_sessionId-BJlM3nmt.js → ui/assets/_sessionId-Chp67th6.js} +1 -1
- package/.output/ui/assets/favicon-DYEkHSNl.svg +21 -0
- package/.output/ui/assets/index-BvXp42al.css +1 -0
- package/.output/{public/assets/index-xF_NY8Yb.js → ui/assets/index-DPmKK_5d.js} +5 -5
- package/.output/{public/assets/index-BIK4bPTv.js → ui/assets/index-atoQrlb8.js} +1 -1
- package/.output/ui/assets/index-nY3E1vxV.js +73 -0
- package/.output/{public/assets/index-D2Qw6Ri2.js → ui/assets/index-nl9-dpZn.js} +1 -1
- package/.output/ui/assets/json-viewer-B9kIzqeX.js +1 -0
- package/.output/{public/assets/jszip.min-B_rfAUCe.js → ui/assets/jszip.min-B7tfyE-I.js} +1 -1
- package/.output/ui/index.html +229 -0
- package/.output/ui/runtime-config.js +2 -0
- package/.output/workers/logFinalizer.worker.js +979 -414
- package/.output/workers/sessionWorkerEntry.js +979 -414
- package/README.md +182 -43
- package/docs/instance-control.openapi.yaml +59 -4
- package/package.json +40 -6
- package/scripts/generate-theme-scales.mjs +3 -3
- package/src/{router.tsx → backend/router.tsx} +3 -15
- package/src/backend/routes/$.ts +26 -0
- package/src/backend/routes/__root.ts +4 -0
- package/src/backend/routes/api/-instances.ts +7 -0
- package/src/{routes → backend/routes}/api/alerts.summary.ts +3 -3
- package/src/{routes → backend/routes}/api/alerts.ts +4 -4
- package/src/{routes → backend/routes}/api/config.paths.ts +1 -1
- package/src/{routes → backend/routes}/api/config.ts +11 -2
- package/src/{routes → backend/routes}/api/ecosystem.packages.$packageId.help.ts +1 -1
- package/src/{routes → backend/routes}/api/ecosystem.packages.$packageId.install.ts +1 -1
- package/src/{routes → backend/routes}/api/ecosystem.packages.$packageId.runner-presets.ts +1 -1
- package/src/{routes → backend/routes}/api/ecosystem.packages.$packageId.upgrade.ts +1 -1
- package/src/{routes → backend/routes}/api/ecosystem.packages.ts +5 -1
- package/src/{routes → backend/routes}/api/ecosystem.recipes.$recipeId.run.ts +1 -1
- package/src/{routes → backend/routes}/api/ecosystem.tasks.$taskId.ts +1 -1
- package/src/{routes → backend/routes}/api/ecosystem.tasks.ts +1 -1
- package/src/{routes → backend/routes}/api/groups.$groupId.evidence.ts +2 -2
- package/src/{routes → backend/routes}/api/groups.$groupId.sessions.ts +2 -2
- package/src/{routes → backend/routes}/api/groups.$groupId.ts +2 -2
- package/src/{routes → backend/routes}/api/groups.ts +2 -2
- package/src/{routes → backend/routes}/api/health.ts +3 -3
- package/src/{routes → backend/routes}/api/instances.$name.connection.ts +1 -1
- package/src/{routes → backend/routes}/api/instances.$name.restart.ts +2 -2
- package/src/{routes → backend/routes}/api/instances.$name.start.ts +2 -2
- package/src/{routes → backend/routes}/api/instances.$name.stop.ts +2 -2
- package/src/{routes → backend/routes}/api/instances.$name.ts +1 -1
- package/src/{routes → backend/routes}/api/instances.ts +1 -1
- package/src/{routes → backend/routes}/api/knowledge.candidates.$candidateId.promote.ts +2 -2
- package/src/{routes → backend/routes}/api/knowledge.candidates.$candidateId.ts +2 -2
- package/src/{routes → backend/routes}/api/knowledge.candidates.ts +1 -1
- package/src/{routes → backend/routes}/api/knowledge.project-context.ts +2 -2
- package/src/{routes → backend/routes}/api/knowledge.search.ts +2 -2
- package/src/{routes → backend/routes}/api/knowledge.sessions.$sessionId.candidates.ts +3 -3
- package/src/{routes → backend/routes}/api/logs.$id.body.ts +6 -6
- package/src/{routes → backend/routes}/api/logs.$id.chunks.ts +5 -4
- package/src/{routes → backend/routes}/api/logs.$id.replay.ts +12 -11
- package/src/{routes → backend/routes}/api/logs.$id.ts +4 -3
- package/src/{routes → backend/routes}/api/logs.import.ts +3 -3
- package/src/{routes → backend/routes}/api/logs.stream.ts +11 -7
- package/src/{routes → backend/routes}/api/logs.ts +17 -9
- package/src/{routes → backend/routes}/api/mcp.ts +1 -1
- package/src/{routes → backend/routes}/api/models.ts +1 -1
- package/src/{routes → backend/routes}/api/pi-agent.ts +2 -2
- package/src/{routes → backend/routes}/api/providers.$providerId.model-metadata.ts +5 -5
- package/src/{routes → backend/routes}/api/providers.$providerId.test.log.ts +7 -7
- package/src/{routes → backend/routes}/api/providers.$providerId.ts +4 -4
- package/src/{routes → backend/routes}/api/providers.export.ts +1 -1
- package/src/{routes → backend/routes}/api/providers.import.ts +3 -3
- package/src/{routes → backend/routes}/api/providers.scan.ts +2 -2
- package/src/{routes → backend/routes}/api/providers.ts +9 -4
- package/src/{routes → backend/routes}/api/runs.$runId.evidence.ts +2 -2
- package/src/{routes → backend/routes}/api/runs.$runId.ts +2 -2
- package/src/{routes → backend/routes}/api/runs.ts +4 -4
- package/src/backend/routes/api/runtime.ts +46 -0
- package/src/{routes → backend/routes}/api/sessions.ts +3 -3
- package/src/{routes → backend/routes}/proxy/$.ts +1 -1
- package/src/{routes → backend/routes}/readyz.ts +1 -1
- package/src/{start.ts → backend/start.ts} +1 -1
- package/src/cli/alias.ts +2 -11
- package/src/cli/doctor.ts +32 -9
- package/src/cli/instance.ts +36 -13
- package/src/cli/instanceApi.ts +213 -0
- package/src/cli/instanceArgs.ts +46 -11
- package/src/cli/instanceControl.ts +10 -2
- package/src/cli/instanceModel.ts +18 -17
- package/src/cli/instanceRegistry.ts +0 -9
- package/src/cli/networkHints.ts +27 -14
- package/src/cli/onboard.ts +69 -2
- package/src/cli/onboardTarget.ts +89 -40
- package/src/cli/rustBackendPackage.ts +450 -0
- package/src/cli/templates/codex-skill-onboard.ts +44 -14
- package/src/cli/templates/skill-onboard.ts +64 -28
- package/src/cli.ts +341 -75
- package/src/components/ProxyViewer.tsx +11 -9
- package/src/components/ProxyViewerContainer.tsx +12 -11
- package/src/components/pi-agent/PiAgentPanel.tsx +2 -2
- package/src/components/providers/ProviderCard.tsx +1 -1
- package/src/components/providers/ProviderTestResultsView.tsx +1 -1
- package/src/components/providers/SettingsDialog.tsx +159 -144
- package/src/components/proxy-viewer/ApplicationBar.tsx +2 -1
- package/src/components/proxy-viewer/LogEntry.tsx +1 -1
- package/src/components/proxy-viewer/log-formats/index.ts +1 -1
- package/src/contracts/index.ts +5 -0
- package/src/contracts/log.ts +33 -3
- package/src/knowledge/types.ts +3 -2
- package/src/lib/alertContract.ts +2 -2
- package/src/lib/apiClient.ts +30 -7
- package/src/lib/apiFormat.ts +29 -0
- package/src/lib/backendImplementation.ts +16 -0
- package/src/lib/basePath.ts +29 -11
- package/src/lib/browserRuntimeContract.ts +124 -0
- package/src/lib/browserRuntimeResolver.ts +244 -0
- package/src/{proxy → lib}/claudeCodeStrip.ts +6 -7
- package/src/lib/codingAgentEndpoints.ts +38 -0
- package/src/lib/instanceContract.ts +30 -11
- package/src/lib/managedInstance.ts +9 -1
- package/src/lib/piAgentContract.ts +3 -2
- package/src/lib/publicBasePathContext.ts +40 -10
- package/src/lib/resourceLimits.ts +2 -0
- package/src/lib/runContract.ts +3 -3
- package/src/lib/sessionInfoContract.ts +3 -2
- package/src/mcp/instanceHandlers.ts +2 -0
- package/src/mcp/server.ts +19 -24
- package/src/proxy/config.ts +25 -30
- package/src/proxy/dataDir.ts +43 -7
- package/src/proxy/ecosystemTasks.ts +161 -70
- package/src/proxy/formats/registry.ts +6 -21
- package/src/proxy/handler.ts +129 -29
- package/src/proxy/identityProxy.ts +567 -39
- package/src/proxy/jsonlRecovery.ts +554 -0
- package/src/proxy/logFinalizer.ts +25 -10
- package/src/proxy/logImporter.ts +2 -1
- package/src/proxy/logIndex.ts +191 -95
- package/src/proxy/logger.ts +77 -14
- package/src/proxy/platformCommands.ts +41 -0
- package/src/proxy/privateDataPath.ts +310 -88
- package/src/proxy/rawStreamCapture.ts +194 -13
- package/src/proxy/runtimeAdmission.ts +5 -2
- package/src/proxy/runtimeHealth.ts +14 -1
- package/src/proxy/runtimeShutdown.ts +11 -1
- package/src/proxy/schemas.ts +7 -1
- package/src/proxy/sessionArchive.ts +70 -14
- package/src/proxy/sqliteLogIndex.ts +65 -42
- package/src/proxy/store.ts +141 -34
- package/src/proxy/uiAssetServer.ts +106 -0
- package/src/proxy/upstream.ts +29 -2
- package/src/ui/bootstrap.ts +167 -0
- package/src/ui/index.html +38 -0
- package/src/ui/logsStreamClient.ts +20 -0
- package/src/ui/main.tsx +13 -0
- package/src/ui/public/runtime-config.js +2 -0
- package/src/ui/router.tsx +13 -0
- package/src/ui/routes/__root.tsx +69 -0
- package/src/{routes → ui/routes}/index.tsx +2 -3
- package/src/{routes → ui/routes}/session/$sessionId.tsx +5 -11
- package/src/ui/runtimeDiscovery.ts +50 -0
- package/styles/globals.css +1 -0
- package/.output/public/assets/ProxyViewerContainer-BEAhuGOJ.js +0 -126
- package/.output/public/assets/ResponseView-DBCjkwye.js +0 -2
- package/.output/public/assets/StreamingChunkSequence-CuXhDgMo.js +0 -1
- package/.output/public/assets/index-BZo_8koU.js +0 -70
- package/.output/public/assets/index-ZWschkCh.css +0 -1
- package/.output/public/assets/json-viewer-B-Ao6pwW.js +0 -1
- package/.output/server/_libs/@radix-ui/react-accessible-icon+[...].mjs +0 -1
- package/.output/server/_libs/@radix-ui/react-dismissable-layer+[...].mjs +0 -344
- package/.output/server/_libs/@radix-ui/react-navigation-menu+[...].mjs +0 -2
- package/.output/server/_libs/@radix-ui/react-one-time-password-field+[...].mjs +0 -2
- package/.output/server/_libs/@radix-ui/react-password-toggle-field+[...].mjs +0 -2
- package/.output/server/_libs/@radix-ui/react-use-callback-ref+[...].mjs +0 -11
- package/.output/server/_libs/@radix-ui/react-use-controllable-state+[...].mjs +0 -69
- package/.output/server/_libs/@radix-ui/react-use-effect-event+[...].mjs +0 -1
- package/.output/server/_libs/@radix-ui/react-use-is-hydrated+[...].mjs +0 -28
- package/.output/server/_libs/@radix-ui/react-use-layout-effect+[...].mjs +0 -6
- package/.output/server/_libs/@radix-ui/react-visually-hidden+[...].mjs +0 -34
- package/.output/server/_libs/aria-hidden.mjs +0 -122
- package/.output/server/_libs/bail.mjs +0 -8
- package/.output/server/_libs/character-entities.mjs +0 -2130
- package/.output/server/_libs/class-variance-authority.mjs +0 -44
- package/.output/server/_libs/clsx.mjs +0 -16
- package/.output/server/_libs/comma-separated-tokens.mjs +0 -10
- package/.output/server/_libs/decode-named-character-reference+[...].mjs +0 -8
- package/.output/server/_libs/dequal.mjs +0 -27
- package/.output/server/_libs/detect-node-es.mjs +0 -1
- package/.output/server/_libs/devlop.mjs +0 -8
- package/.output/server/_libs/diff.mjs +0 -320
- package/.output/server/_libs/estree-util-is-identifier-name.mjs +0 -11
- package/.output/server/_libs/floating-ui__core.mjs +0 -725
- package/.output/server/_libs/floating-ui__dom.mjs +0 -622
- package/.output/server/_libs/floating-ui__react-dom.mjs +0 -292
- package/.output/server/_libs/floating-ui__utils.mjs +0 -320
- package/.output/server/_libs/get-nonce.mjs +0 -9
- package/.output/server/_libs/hast-util-to-jsx-runtime.mjs +0 -388
- package/.output/server/_libs/hast-util-whitespace.mjs +0 -10
- package/.output/server/_libs/html-url-attributes.mjs +0 -26
- package/.output/server/_libs/inline-style-parser.mjs +0 -142
- package/.output/server/_libs/is-plain-obj.mjs +0 -10
- package/.output/server/_libs/lucide-react.mjs +0 -1027
- package/.output/server/_libs/mdast-util-from-markdown.mjs +0 -717
- package/.output/server/_libs/mdast-util-to-hast.mjs +0 -710
- package/.output/server/_libs/mdast-util-to-string.mjs +0 -38
- package/.output/server/_libs/micromark-core-commonmark.mjs +0 -2259
- package/.output/server/_libs/micromark-factory-destination.mjs +0 -94
- package/.output/server/_libs/micromark-factory-label.mjs +0 -63
- package/.output/server/_libs/micromark-factory-space.mjs +0 -24
- package/.output/server/_libs/micromark-factory-title.mjs +0 -65
- package/.output/server/_libs/micromark-factory-whitespace.mjs +0 -22
- package/.output/server/_libs/micromark-util-character.mjs +0 -44
- package/.output/server/_libs/micromark-util-chunked.mjs +0 -36
- package/.output/server/_libs/micromark-util-classify-character+[...].mjs +0 -12
- package/.output/server/_libs/micromark-util-combine-extensions+[...].mjs +0 -41
- package/.output/server/_libs/micromark-util-decode-numeric-character-reference+[...].mjs +0 -19
- package/.output/server/_libs/micromark-util-decode-string.mjs +0 -21
- package/.output/server/_libs/micromark-util-encode.mjs +0 -1
- package/.output/server/_libs/micromark-util-html-tag-name.mjs +0 -69
- package/.output/server/_libs/micromark-util-normalize-identifier+[...].mjs +0 -6
- package/.output/server/_libs/micromark-util-resolve-all.mjs +0 -15
- package/.output/server/_libs/micromark-util-sanitize-uri.mjs +0 -41
- package/.output/server/_libs/micromark-util-subtokenize.mjs +0 -346
- package/.output/server/_libs/micromark.mjs +0 -906
- package/.output/server/_libs/property-information.mjs +0 -1209
- package/.output/server/_libs/radix-ui.mjs +0 -1
- package/.output/server/_libs/radix-ui__number.mjs +0 -6
- package/.output/server/_libs/radix-ui__primitive.mjs +0 -11
- package/.output/server/_libs/radix-ui__react-accordion.mjs +0 -1
- package/.output/server/_libs/radix-ui__react-alert-dialog.mjs +0 -1
- package/.output/server/_libs/radix-ui__react-arrow.mjs +0 -23
- package/.output/server/_libs/radix-ui__react-aspect-ratio.mjs +0 -1
- package/.output/server/_libs/radix-ui__react-avatar.mjs +0 -1
- package/.output/server/_libs/radix-ui__react-checkbox.mjs +0 -1
- package/.output/server/_libs/radix-ui__react-collapsible.mjs +0 -144
- package/.output/server/_libs/radix-ui__react-collection.mjs +0 -69
- package/.output/server/_libs/radix-ui__react-compose-refs.mjs +0 -38
- package/.output/server/_libs/radix-ui__react-context-menu.mjs +0 -1
- package/.output/server/_libs/radix-ui__react-context.mjs +0 -64
- package/.output/server/_libs/radix-ui__react-dialog.mjs +0 -280
- package/.output/server/_libs/radix-ui__react-direction.mjs +0 -9
- package/.output/server/_libs/radix-ui__react-dropdown-menu.mjs +0 -1
- package/.output/server/_libs/radix-ui__react-focus-guards.mjs +0 -39
- package/.output/server/_libs/radix-ui__react-focus-scope.mjs +0 -210
- package/.output/server/_libs/radix-ui__react-form.mjs +0 -1
- package/.output/server/_libs/radix-ui__react-hover-card.mjs +0 -1
- package/.output/server/_libs/radix-ui__react-id.mjs +0 -14
- package/.output/server/_libs/radix-ui__react-label.mjs +0 -1
- package/.output/server/_libs/radix-ui__react-menu.mjs +0 -1
- package/.output/server/_libs/radix-ui__react-menubar.mjs +0 -1
- package/.output/server/_libs/radix-ui__react-popover.mjs +0 -1
- package/.output/server/_libs/radix-ui__react-popper.mjs +0 -340
- package/.output/server/_libs/radix-ui__react-portal.mjs +0 -16
- package/.output/server/_libs/radix-ui__react-presence.mjs +0 -173
- package/.output/server/_libs/radix-ui__react-primitive.mjs +0 -42
- package/.output/server/_libs/radix-ui__react-progress.mjs +0 -1
- package/.output/server/_libs/radix-ui__react-radio-group.mjs +0 -1
- package/.output/server/_libs/radix-ui__react-roving-focus.mjs +0 -235
- package/.output/server/_libs/radix-ui__react-scroll-area.mjs +0 -731
- package/.output/server/_libs/radix-ui__react-select.mjs +0 -1207
- package/.output/server/_libs/radix-ui__react-separator.mjs +0 -28
- package/.output/server/_libs/radix-ui__react-slider.mjs +0 -1
- package/.output/server/_libs/radix-ui__react-slot.mjs +0 -132
- package/.output/server/_libs/radix-ui__react-switch.mjs +0 -1
- package/.output/server/_libs/radix-ui__react-tabs.mjs +0 -194
- package/.output/server/_libs/radix-ui__react-toast.mjs +0 -2
- package/.output/server/_libs/radix-ui__react-toggle-group.mjs +0 -1
- package/.output/server/_libs/radix-ui__react-toggle.mjs +0 -1
- package/.output/server/_libs/radix-ui__react-toolbar.mjs +0 -1
- package/.output/server/_libs/radix-ui__react-tooltip.mjs +0 -498
- package/.output/server/_libs/radix-ui__react-use-previous.mjs +0 -14
- package/.output/server/_libs/radix-ui__react-use-size.mjs +0 -39
- package/.output/server/_libs/react-markdown.mjs +0 -235
- package/.output/server/_libs/react-remove-scroll-bar.mjs +0 -82
- package/.output/server/_libs/react-remove-scroll.mjs +0 -328
- package/.output/server/_libs/react-style-singleton.mjs +0 -69
- package/.output/server/_libs/remark-parse.mjs +0 -19
- package/.output/server/_libs/remark-rehype.mjs +0 -21
- package/.output/server/_libs/space-separated-tokens.mjs +0 -6
- package/.output/server/_libs/style-to-js.mjs +0 -72
- package/.output/server/_libs/style-to-object.mjs +0 -38
- package/.output/server/_libs/swr.mjs +0 -947
- package/.output/server/_libs/tailwind-merge.mjs +0 -3255
- package/.output/server/_libs/tanstack__react-virtual.mjs +0 -130
- package/.output/server/_libs/tanstack__virtual-core.mjs +0 -1319
- package/.output/server/_libs/three.mjs +0 -26016
- package/.output/server/_libs/trim-lines.mjs +0 -41
- package/.output/server/_libs/trough.mjs +0 -85
- package/.output/server/_libs/tslib.mjs +0 -1
- package/.output/server/_libs/ungap__structured-clone.mjs +0 -212
- package/.output/server/_libs/unified.mjs +0 -661
- package/.output/server/_libs/unist-util-is.mjs +0 -100
- package/.output/server/_libs/unist-util-position.mjs +0 -27
- package/.output/server/_libs/unist-util-stringify-position.mjs +0 -27
- package/.output/server/_libs/unist-util-visit-parents.mjs +0 -82
- package/.output/server/_libs/unist-util-visit.mjs +0 -24
- package/.output/server/_libs/use-callback-ref.mjs +0 -66
- package/.output/server/_libs/use-sidecar.mjs +0 -106
- package/.output/server/_libs/vfile-message.mjs +0 -138
- package/.output/server/_libs/vfile.mjs +0 -467
- package/.output/server/_sessionId-CJ99gZFV.mjs +0 -84
- package/.output/server/_sessionId-DEjScBpK.mjs +0 -146
- package/.output/server/_ssr/CompareDrawer-DtOIMeQB.mjs +0 -1060
- package/.output/server/_ssr/InspectorPet-CXc4oCBQ.mjs +0 -938
- package/.output/server/_ssr/ProxyViewerContainer-DVPlwfkt.mjs +0 -17632
- package/.output/server/_ssr/ReplayDialog-BQEA95qC.mjs +0 -725
- package/.output/server/_ssr/RequestAnatomy-BMyd8B7Q.mjs +0 -837
- package/.output/server/_ssr/ResponseView-qrTaEIM8.mjs +0 -757
- package/.output/server/_ssr/StreamingChunkSequence-BFTL8mIy.mjs +0 -274
- package/.output/server/_ssr/index-Bcj1Hcy4.mjs +0 -135
- package/.output/server/_ssr/index-DW-M7XUG.mjs +0 -84
- package/.output/server/_ssr/json-viewer-DiI0Yjsn.mjs +0 -483
- package/.output/server/_tanstack-start-manifest_v-C6pXXX9R.mjs +0 -4
- package/.output/server/node_modules/tslib/modules/index.js +0 -70
- package/.output/server/node_modules/tslib/modules/package.json +0 -3
- package/.output/server/node_modules/tslib/package.json +0 -47
- package/.output/server/node_modules/tslib/tslib.js +0 -484
- package/.output/server/package.json +0 -9
- package/src/routes/__root.tsx +0 -170
- package/src/routes/api/-instances.ts +0 -109
- /package/.output/{public → ui}/assets/agent-inspector-58K1_MsC.ico +0 -0
- /package/.output/{public → ui}/assets/alibaba-TTwafVwX.svg +0 -0
- /package/.output/{public → ui}/assets/minimax-BPMzvuL-.jpeg +0 -0
- /package/.output/{public → ui}/assets/qwen-mMn3f5ul.webp +0 -0
- /package/.output/{public → ui}/assets/zhipuai-BPNAnxo-.svg +0 -0
- /package/src/{routes → backend/routes}/livez.ts +0 -0
package/src/lib/apiClient.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/* eslint-disable functional/no-throw-statements */
|
|
2
2
|
import { z } from "zod";
|
|
3
|
-
import {
|
|
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
|
|
11
|
+
function withInspectorControlSurface(input: RequestInfo | URL): RequestInfo | URL {
|
|
12
12
|
if (typeof input !== "string") return input;
|
|
13
|
-
if (!input.startsWith("/")
|
|
14
|
-
|
|
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
|
|
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
|
|
111
|
-
...
|
|
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
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
export const AGENT_INSPECTOR_BACKEND_ENV = "AGENT_INSPECTOR_BACKEND";
|
|
4
|
+
export const AGENT_INSPECTOR_BACKEND_HEADER = "x-agent-inspector-backend";
|
|
5
|
+
|
|
6
|
+
export const BackendImplementationSchema = z.enum(["typescript", "rust"]);
|
|
7
|
+
|
|
8
|
+
export type BackendImplementation = z.infer<typeof BackendImplementationSchema>;
|
|
9
|
+
|
|
10
|
+
export function parseBackendImplementation(
|
|
11
|
+
value: string | undefined,
|
|
12
|
+
): BackendImplementation | null {
|
|
13
|
+
if (value === undefined) return "typescript";
|
|
14
|
+
const parsed = BackendImplementationSchema.safeParse(value.trim().toLowerCase());
|
|
15
|
+
return parsed.success ? parsed.data : null;
|
|
16
|
+
}
|
package/src/lib/basePath.ts
CHANGED
|
@@ -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
|
-
|
|
41
|
-
|
|
42
|
-
env[AGENT_INSPECTOR_BASE_PATH_ENV] ?? DEFAULT_AGENT_INSPECTOR_BASE_PATH
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
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
|
|
13
|
-
*
|
|
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
|
|
57
|
-
*
|
|
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
|
+
}
|