@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.
- package/.output/{nitro.json → backend/nitro.json} +3 -3
- package/.output/backend-public/assets/index-D4LX-sw-.js +11 -0
- package/.output/cli.js +2326 -516
- 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-D18yUq36.mjs} +19770 -19447
- 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-DAUuIJ6G.js} +1 -1
- package/.output/{public/assets/InspectorPet-Cpn6hv4P.js → ui/assets/InspectorPet-BRBVjOWI.js} +1 -1
- package/.output/ui/assets/ProxyViewerContainer-D7Sq0ctc.js +59 -0
- package/.output/{public/assets/ReplayDialog-B3EKVdJk.js → ui/assets/ReplayDialog-nDLsjOhs.js} +1 -1
- package/.output/{public/assets/RequestAnatomy-COOQjyUC.js → ui/assets/RequestAnatomy-zd4BDgL0.js} +1 -1
- package/.output/ui/assets/ResponseView-AdIXGcSn.js +2 -0
- package/.output/ui/assets/StreamingChunkSequence-CesTz8He.js +1 -0
- package/.output/{public/assets/_sessionId-zbgYl7ZJ.js → ui/assets/_sessionId-BAfzrhSU.js} +1 -1
- package/.output/{public/assets/_sessionId-BJlM3nmt.js → ui/assets/_sessionId-QnBomgPD.js} +1 -1
- package/.output/ui/assets/favicon-DYEkHSNl.svg +21 -0
- package/.output/{public/assets/index-BIK4bPTv.js → ui/assets/index-BcsdxBAd.js} +1 -1
- package/.output/ui/assets/index-BvXp42al.css +1 -0
- package/.output/{public/assets/index-D2Qw6Ri2.js → ui/assets/index-D0rtCN9V.js} +1 -1
- package/.output/ui/assets/index-DHpwr08Z.js +73 -0
- package/.output/{public/assets/index-xF_NY8Yb.js → ui/assets/index-dNuk2dsU.js} +5 -5
- package/.output/ui/assets/json-viewer-BvFHglMb.js +1 -0
- package/.output/{public/assets/jszip.min-B_rfAUCe.js → ui/assets/jszip.min-B5Z7gNZB.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 +175 -43
- package/docs/instance-control.openapi.yaml +59 -4
- package/package.json +25 -5
- 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/{routes → backend/routes}/api/-instances.ts +3 -3
- 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 +26 -13
- package/src/cli/instanceArgs.ts +30 -11
- package/src/cli/instanceControl.ts +0 -2
- package/src/cli/instanceModel.ts +9 -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/templates/codex-skill-onboard.ts +44 -14
- package/src/cli/templates/skill-onboard.ts +64 -28
- package/src/cli.ts +184 -61
- 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/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 +27 -11
- 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 +1 -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 +419 -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 +78 -14
- package/src/proxy/sqliteLogIndex.ts +65 -2
- 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/.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
|
@@ -24,8 +24,14 @@ export type SkillOnboardContext = {
|
|
|
24
24
|
readonly version: string;
|
|
25
25
|
/** The default proxy port (mirrors `DEFAULT_PORT` in `src/cli.ts`). */
|
|
26
26
|
readonly port: number;
|
|
27
|
-
/** Public
|
|
27
|
+
/** Public backend control/agent Base URL, including the configured Base Path. */
|
|
28
28
|
readonly baseUrl: string;
|
|
29
|
+
/** Optional composed or standalone UI URL. Undefined preserves the legacy composed default. */
|
|
30
|
+
readonly uiUrl?: string | null;
|
|
31
|
+
/** REST/SSE Base URL. Falls back to baseUrl for compatibility. */
|
|
32
|
+
readonly controlBaseUrl?: string;
|
|
33
|
+
/** Proxy/MCP Base URL. Falls back to baseUrl for compatibility. */
|
|
34
|
+
readonly agentBaseUrl?: string;
|
|
29
35
|
/** MCP config key selected by onboarding. */
|
|
30
36
|
readonly mcpName?: string;
|
|
31
37
|
/** Selected onboarding target type. */
|
|
@@ -56,24 +62,29 @@ export const REQUIRED_PHASE_HEADINGS = [
|
|
|
56
62
|
] as const;
|
|
57
63
|
|
|
58
64
|
export function renderSkillOnboard(ctx: SkillOnboardContext): string {
|
|
59
|
-
const { version, port,
|
|
65
|
+
const { version, port, detectedSummary } = ctx;
|
|
66
|
+
const controlBaseUrl = ctx.controlBaseUrl ?? ctx.baseUrl;
|
|
67
|
+
const agentBaseUrl = ctx.agentBaseUrl ?? ctx.baseUrl;
|
|
68
|
+
const uiUrl = ctx.uiUrl === undefined ? ctx.baseUrl : ctx.uiUrl;
|
|
60
69
|
const mcpName = ctx.mcpName ?? "agent-inspector";
|
|
61
70
|
const targetKind = ctx.targetKind ?? "default";
|
|
62
71
|
const targetArguments = ctx.onboardTargetArguments ?? "";
|
|
63
72
|
const instanceName = ctx.instanceName ?? null;
|
|
64
|
-
const healthUrl = `${
|
|
65
|
-
const
|
|
66
|
-
const
|
|
67
|
-
const
|
|
68
|
-
const
|
|
69
|
-
const
|
|
73
|
+
const healthUrl = `${controlBaseUrl}/api/health`;
|
|
74
|
+
const runtimeUrl = `${controlBaseUrl}/api/runtime`;
|
|
75
|
+
const configUrl = `${controlBaseUrl}/api/config`;
|
|
76
|
+
const anthropicProxyUrl = `${agentBaseUrl}/proxy`;
|
|
77
|
+
const openAiProxyUrl = `${agentBaseUrl}/proxy/v1`;
|
|
78
|
+
const mcpUrl = `${agentBaseUrl}/api/mcp`;
|
|
79
|
+
const logsUrl = `${controlBaseUrl}/api/logs`;
|
|
80
|
+
const providersUrl = `${controlBaseUrl}/api/providers`;
|
|
70
81
|
const statusCommand = `agent-inspector onboard --status${targetArguments}`;
|
|
71
82
|
const refreshCommand = `agent-inspector onboard --force${targetArguments}`;
|
|
72
83
|
const startCommand =
|
|
73
84
|
targetKind === "instance" && instanceName !== null
|
|
74
85
|
? `agent-inspector instance start ${instanceName}`
|
|
75
86
|
: targetKind === "base-url"
|
|
76
|
-
? `# Explicit target ${
|
|
87
|
+
? `# Explicit control target ${controlBaseUrl}: do not start a replacement local runtime.`
|
|
77
88
|
: "agent-inspector --mode simple --background --no-open";
|
|
78
89
|
const fullModeCommand =
|
|
79
90
|
targetKind === "instance" && instanceName !== null
|
|
@@ -95,17 +106,27 @@ if (-not $found) { throw 'agent-inspector is not on PATH' }
|
|
|
95
106
|
& $found.Source ${windowsStartArguments}`;
|
|
96
107
|
const startExplanation =
|
|
97
108
|
targetKind === "base-url"
|
|
98
|
-
? `The selected Inspector target
|
|
99
|
-
: `Start or reuse the selected Inspector
|
|
109
|
+
? `The selected Inspector target uses control Base URL \`${controlBaseUrl}\` and agent Base URL \`${agentBaseUrl}\`. Do not launch a default local runtime as a substitute; verify the selected target and ask its operator for help if it is unavailable.`
|
|
110
|
+
: `Start or reuse the selected Inspector backend. Its public control and agent endpoints preserve the selected Base Path; a Web UI may be composed at the same URL, hosted separately, or intentionally absent in backend-only mode. Use \`${fullModeCommand}\` only when the user needs raw headers, raw response, or SSE chunks.`;
|
|
100
111
|
const stopSnippet =
|
|
101
112
|
targetKind === "instance" && instanceName !== null
|
|
102
113
|
? `agent-inspector instance stop ${instanceName}`
|
|
103
114
|
: targetKind === "base-url"
|
|
104
|
-
? `# Ask the operator of ${
|
|
115
|
+
? `# Ask the operator of ${controlBaseUrl} to stop the selected runtime.`
|
|
105
116
|
: `# Unix / macOS\n lsof -ti:${String(port)} | xargs -r kill -9\n\n # Windows PowerShell\n Get-NetTCPConnection -LocalPort ${String(port)} | ForEach-Object { Stop-Process -Id $_.OwningProcess -Force }`;
|
|
117
|
+
const providerScopeGuidance =
|
|
118
|
+
targetKind === "default"
|
|
119
|
+
? "The unmanaged default target owns the local Agent Inspector data directory used by the file checks below."
|
|
120
|
+
: `The selected target is not the unmanaged default data directory. Do not inspect or edit local ~/.agent-inspector Provider files as a substitute. Query \`${providersUrl}\`, use the selected target's MCP Provider tools with explicit approval, or ask its operator to configure Providers. Skip local-file commands below.`;
|
|
121
|
+
const selectedUi =
|
|
122
|
+
uiUrl === null ? "not supplied (do not infer one from a backend URL)" : `\`${uiUrl}\``;
|
|
123
|
+
const uiTour =
|
|
124
|
+
uiUrl === null
|
|
125
|
+
? "not supplied; continue with MCP/REST, and ask the operator for a standalone UI URL only if the user needs one"
|
|
126
|
+
: `\`${uiUrl}\` — use this explicit composed or standalone browser URL; do not replace it with the control or agent Base URL`;
|
|
106
127
|
return `---
|
|
107
128
|
name: agent-inspector-onboard
|
|
108
|
-
description: Guided setup for Agent Inspector v${version}: start the
|
|
129
|
+
description: Guided setup for Agent Inspector v${version}: start or select the backend, wire your AI coding tool, and capture your first request with or without a Web UI.
|
|
109
130
|
metadata:
|
|
110
131
|
author: agent-inspector
|
|
111
132
|
version: ${version}
|
|
@@ -113,12 +134,16 @@ metadata:
|
|
|
113
134
|
|
|
114
135
|
# Agent Inspector onboard
|
|
115
136
|
|
|
116
|
-
Guide the user from "I just installed Agent Inspector" to "
|
|
137
|
+
Guide the user from "I just installed Agent Inspector" to "my coding agent can use the proxy, REST API, and MCP surface". The backend works in composed and headless deployments; treat the Web UI as an optional presentation surface.
|
|
117
138
|
|
|
118
139
|
Environment detected by the installer:
|
|
119
140
|
${detectedSummary || " (no known AI tool detected — the user can still use the generic curl example in Phase 4)"}
|
|
120
141
|
|
|
121
|
-
Selected Inspector
|
|
142
|
+
Selected Inspector surfaces:
|
|
143
|
+
- UI URL: ${selectedUi}
|
|
144
|
+
- Control Base URL: \`${controlBaseUrl}\`
|
|
145
|
+
- Agent Base URL: \`${agentBaseUrl}\`
|
|
146
|
+
- MCP key: \`${mcpName}\`
|
|
122
147
|
|
|
123
148
|
> **PAUSE protocol.** Every \`**PAUSE**\` marker in this skill is a real stop.
|
|
124
149
|
> Use the \`AskUserQuestion\` tool to actually wait for the user before
|
|
@@ -146,9 +171,11 @@ ${statusCommand}
|
|
|
146
171
|
|
|
147
172
|
**DO:** Then probe the three pieces of state this skill touches. Use targeted checks — do **not** read large JSON files into the conversation.
|
|
148
173
|
|
|
174
|
+
**DO:** ${providerScopeGuidance}
|
|
175
|
+
|
|
149
176
|
\`\`\`bash
|
|
150
|
-
# 1. Is the
|
|
151
|
-
curl -fsS "${healthUrl}" 2>/dev/null && echo "
|
|
177
|
+
# 1. Is the backend already up?
|
|
178
|
+
curl -fsS "${healthUrl}" 2>/dev/null && echo "BACKEND: up" || echo "BACKEND: down"
|
|
152
179
|
|
|
153
180
|
# 2. Does the provider config have a real provider key?
|
|
154
181
|
agent_inspector_data_dir() {
|
|
@@ -209,12 +236,12 @@ $dataDir = Resolve-AgentInspectorDataDir
|
|
|
209
236
|
$providers = Join-Path $dataDir 'providers.json'
|
|
210
237
|
$legacyConfig = Join-Path $dataDir 'config.json'
|
|
211
238
|
|
|
212
|
-
# 1. Is the
|
|
239
|
+
# 1. Is the backend already up?
|
|
213
240
|
try {
|
|
214
241
|
$null = Invoke-RestMethod -Uri "${healthUrl}" -TimeoutSec 2 -ErrorAction Stop
|
|
215
|
-
Write-Host '
|
|
242
|
+
Write-Host 'BACKEND: up'
|
|
216
243
|
} catch {
|
|
217
|
-
Write-Host '
|
|
244
|
+
Write-Host 'BACKEND: down'
|
|
218
245
|
}
|
|
219
246
|
|
|
220
247
|
# 2. Does the config have a real provider key?
|
|
@@ -284,7 +311,7 @@ node -e "const fs=require('node:fs'),p=require('node:path');const names=process.
|
|
|
284
311
|
\`\`\`
|
|
285
312
|
## Welcome to Agent Inspector!
|
|
286
313
|
|
|
287
|
-
Agent Inspector is an agent observability and knowledge-capture platform for AI coding tools.
|
|
314
|
+
Agent Inspector is an agent observability and knowledge-capture platform for AI coding tools. Its backend owns the transparent model proxy, REST/SSE APIs, capture storage, and MCP server. The default CLI composes a Web UI at the same public Base URL, while \`--backend-only\` keeps every Coding Agent surface available without serving UI files.
|
|
288
315
|
|
|
289
316
|
Agent Inspector starts in **Simple mode** by default. Simple mode is the right habit for everyday use: it keeps requests, responses, tools, timing, and token usage while avoiding heavier raw headers, raw response, and detailed SSE chunk artifacts. Use **Full mode** only when the user is debugging provider headers, raw response payloads, or SSE stream details.
|
|
290
317
|
|
|
@@ -304,6 +331,8 @@ Ready? Let's start with the provider.
|
|
|
304
331
|
|
|
305
332
|
## Phase 2: Provider setup
|
|
306
333
|
|
|
334
|
+
**DO:** ${providerScopeGuidance}
|
|
335
|
+
|
|
307
336
|
**EXPLAIN:** "A 'provider' is an upstream LLM endpoint — Anthropic, OpenAI, MiniMax, etc. agent-inspector routes each request to the right upstream based on the model name. You need at least one provider configured for the proxy to forward traffic."
|
|
308
337
|
|
|
309
338
|
**DO:** First, re-check whether \`<dataDir>/providers.json\` already has a real key (Phase 0 may have raced with a manual edit). Use the same data-dir resolution and \`grep -qE '"apiKey":"sk-'\` (bash) or \`Select-String\` (PowerShell) check from Phase 0. If a real key is present, skip the rest of this phase.
|
|
@@ -399,7 +428,7 @@ $json | Set-Content -Path $file -Encoding UTF8
|
|
|
399
428
|
|
|
400
429
|
**EXPLAIN:** "${startExplanation}"
|
|
401
430
|
|
|
402
|
-
**DO:** Skip this phase entirely if the Phase 0 health check already reported \`
|
|
431
|
+
**DO:** Skip this phase entirely if the Phase 0 health check already reported \`BACKEND: up\` and the user opted to skip done phases.
|
|
403
432
|
|
|
404
433
|
**DO:** Otherwise, use the selected target command below. An explicit wrapper Base URL is connection-only and must not cause a replacement local runtime to start.
|
|
405
434
|
|
|
@@ -412,7 +441,7 @@ ${bashStartSnippet}
|
|
|
412
441
|
${powershellStartSnippet}
|
|
413
442
|
\`\`\`
|
|
414
443
|
|
|
415
|
-
Then wait for the
|
|
444
|
+
Then wait for the selected backend health URL to be ready:
|
|
416
445
|
|
|
417
446
|
\`\`\`bash
|
|
418
447
|
for i in $(seq 1 20); do
|
|
@@ -421,12 +450,18 @@ for i in $(seq 1 20); do
|
|
|
421
450
|
done
|
|
422
451
|
\`\`\`
|
|
423
452
|
|
|
424
|
-
**DO:** Hit the health endpoint to confirm the
|
|
453
|
+
**DO:** Hit the health endpoint to confirm the backend is alive:
|
|
425
454
|
|
|
426
455
|
\`\`\`bash
|
|
427
456
|
curl -sS "${healthUrl}"
|
|
428
457
|
\`\`\`
|
|
429
458
|
|
|
459
|
+
**DO:** Read the token-free runtime discovery document. Report \`deploymentMode\` and capabilities; do not treat \`backend-only\` as a failure or infer that a UI is present.
|
|
460
|
+
|
|
461
|
+
\`\`\`bash
|
|
462
|
+
curl -sS "${runtimeUrl}"
|
|
463
|
+
\`\`\`
|
|
464
|
+
|
|
430
465
|
**DO:** Read \`/api/config\` and tell the user which capture mode is active. If deeper capture is required, offer \`${fullModeCommand}\`.
|
|
431
466
|
|
|
432
467
|
\`\`\`bash
|
|
@@ -566,10 +601,11 @@ done
|
|
|
566
601
|
|
|
567
602
|
## Phase 6: Tour & wrap
|
|
568
603
|
|
|
569
|
-
**EXPLAIN:** "Everything's working. Here's the cheat sheet for the
|
|
604
|
+
**EXPLAIN:** "Everything's working. Here's the cheat sheet for the backend surfaces and the optional Web UI:"
|
|
570
605
|
|
|
571
|
-
- **
|
|
572
|
-
- **
|
|
606
|
+
- **Runtime discovery**: \`${runtimeUrl}\` — token-free deployment mode, UI Base Path, control/agent Base URLs, and capabilities.
|
|
607
|
+
- **Web UI**: ${uiTour}.
|
|
608
|
+
- **MCP server**: \`${mcpUrl}\` — connect from the coding agent to query logs, replay, and test providers; it does not require a Web UI process.
|
|
573
609
|
- **REST API**: \`/api/logs\`, \`/api/sessions\`, \`/api/providers\` — for scripting and shell-based inspection.
|
|
574
610
|
- **Stop the proxy**:
|
|
575
611
|
|
|
@@ -580,7 +616,7 @@ ${stopSnippet}
|
|
|
580
616
|
- **Re-run onboard**: \`${refreshCommand}\` refreshes this skill.
|
|
581
617
|
- **Check onboard files**: \`${statusCommand}\` shows whether generated skills are
|
|
582
618
|
current, outdated, missing, newer, or custom.
|
|
583
|
-
- **Full docs**: see the project README
|
|
619
|
+
- **Full docs**: see the project README; do not depend on a UI footer being available.
|
|
584
620
|
|
|
585
621
|
> **PAUSE** — use \`AskUserQuestion\` with header \`All set?\` and options \`["All set, I'm done", "Wait, I want to revisit a phase"]\`. Wait for the answer.
|
|
586
622
|
|
package/src/cli.ts
CHANGED
|
@@ -8,9 +8,11 @@ import { existsSync } from "node:fs";
|
|
|
8
8
|
import type { Readable, Writable } from "node:stream";
|
|
9
9
|
import packageJson from "../package.json";
|
|
10
10
|
import {
|
|
11
|
+
AGENT_INSPECTOR_BASE_PATH_ENV,
|
|
11
12
|
AGENT_INSPECTOR_INTERNAL_STRIPPED_BASE_PATH_ENV,
|
|
12
13
|
appendBasePathToOrigin,
|
|
13
14
|
getConfiguredBasePath,
|
|
15
|
+
normalizePublicBasePath,
|
|
14
16
|
} from "./lib/basePath.js";
|
|
15
17
|
import {
|
|
16
18
|
AGENT_INSPECTOR_CLI_ENTRY_ENV,
|
|
@@ -34,6 +36,7 @@ import {
|
|
|
34
36
|
import {
|
|
35
37
|
closeIdentityProxyGracefully,
|
|
36
38
|
forceCloseIdentityProxy,
|
|
39
|
+
parseUiOriginAllowlist,
|
|
37
40
|
startIdentityProxy,
|
|
38
41
|
stopIdentityProxyAdmission,
|
|
39
42
|
type ManagedInstanceControlOptions,
|
|
@@ -83,6 +86,14 @@ Global options:
|
|
|
83
86
|
-h, --help Show this help without starting a runtime
|
|
84
87
|
-v, --version Print the package version
|
|
85
88
|
|
|
89
|
+
Start options:
|
|
90
|
+
--backend-only, --headless Start the API, proxy, and MCP runtime without serving the UI
|
|
91
|
+
--with-ui Serve the independently built UI through the protected ingress
|
|
92
|
+
--port, -p <port> Public ingress port (default: 9527)
|
|
93
|
+
--host, -H <host> Bind host (default: 127.0.0.1)
|
|
94
|
+
--background Start a hidden supervisor and return after readiness
|
|
95
|
+
--no-open Do not open the UI after startup
|
|
96
|
+
|
|
86
97
|
Run \`agent-inspector instance --help\`, \`agent-inspector onboard --help\`, or
|
|
87
98
|
\`agent-inspector doctor --help\` for command-specific options.`);
|
|
88
99
|
}
|
|
@@ -309,11 +320,26 @@ function readCaptureMode(raw: unknown): CaptureMode | null {
|
|
|
309
320
|
return typeof value === "string" ? parseCaptureMode(value) : null;
|
|
310
321
|
}
|
|
311
322
|
|
|
312
|
-
function printAccessHints(
|
|
323
|
+
function printAccessHints(
|
|
324
|
+
port: number,
|
|
325
|
+
host: string | undefined,
|
|
326
|
+
basePath: string,
|
|
327
|
+
serveUi: boolean,
|
|
328
|
+
publicOrigin: string | undefined,
|
|
329
|
+
): void {
|
|
313
330
|
const networkUrls = networkUrlsForBindHost(port, host);
|
|
314
|
-
for (const line of formatAccessHintLines(port, networkUrls, host, basePath)) {
|
|
331
|
+
for (const line of formatAccessHintLines(port, networkUrls, host, basePath, serveUi)) {
|
|
315
332
|
console.log(line);
|
|
316
333
|
}
|
|
334
|
+
if (publicOrigin !== undefined) {
|
|
335
|
+
const publicBaseUrl = appendBasePathToOrigin(publicOrigin, "/", basePath);
|
|
336
|
+
if (serveUi) console.log(` Public UI: ${publicBaseUrl}`);
|
|
337
|
+
console.log(` Public control Base: ${publicBaseUrl}`);
|
|
338
|
+
console.log(` Public agent Base: ${publicBaseUrl}`);
|
|
339
|
+
console.log(` Public REST API: ${appendBasePathToOrigin(publicOrigin, "/api", basePath)}`);
|
|
340
|
+
console.log(` Public proxy: ${appendBasePathToOrigin(publicOrigin, "/proxy", basePath)}`);
|
|
341
|
+
console.log(` Public MCP: ${appendBasePathToOrigin(publicOrigin, "/api/mcp", basePath)}`);
|
|
342
|
+
}
|
|
317
343
|
if (!isLoopbackHost(host)) {
|
|
318
344
|
const proxyTokenConfigured = (process.env["AGENT_INSPECTOR_PROXY_TOKEN"] ?? "") !== "";
|
|
319
345
|
const legacyProxyEnabled =
|
|
@@ -345,6 +371,19 @@ function readPositiveIntegerEnv(name: string): number | undefined {
|
|
|
345
371
|
return undefined;
|
|
346
372
|
}
|
|
347
373
|
|
|
374
|
+
function normalizeExplicitPublicOrigin(value: string | undefined): string | null | undefined {
|
|
375
|
+
if (value === undefined || value.trim().length === 0) return undefined;
|
|
376
|
+
try {
|
|
377
|
+
const parsed = new URL(value.trim());
|
|
378
|
+
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") return null;
|
|
379
|
+
if (parsed.username.length > 0 || parsed.password.length > 0) return null;
|
|
380
|
+
if (parsed.pathname !== "/" || parsed.search.length > 0 || parsed.hash.length > 0) return null;
|
|
381
|
+
return parsed.origin;
|
|
382
|
+
} catch {
|
|
383
|
+
return null;
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
|
|
348
387
|
type BackgroundSupervisorOptions = {
|
|
349
388
|
port: number;
|
|
350
389
|
host: string | undefined;
|
|
@@ -353,6 +392,7 @@ type BackgroundSupervisorOptions = {
|
|
|
353
392
|
captureMode: CaptureMode;
|
|
354
393
|
enableIdentityProxy: boolean;
|
|
355
394
|
legacyAliasEnabled: boolean;
|
|
395
|
+
serveUi: boolean;
|
|
356
396
|
};
|
|
357
397
|
|
|
358
398
|
function buildBackgroundSupervisorArgs(options: BackgroundSupervisorOptions): string[] {
|
|
@@ -372,6 +412,9 @@ function buildBackgroundSupervisorArgs(options: BackgroundSupervisorOptions): st
|
|
|
372
412
|
if (options.legacyAliasEnabled) {
|
|
373
413
|
args.push("--legacy-port");
|
|
374
414
|
}
|
|
415
|
+
if (!options.serveUi) {
|
|
416
|
+
args.push("--backend-only");
|
|
417
|
+
}
|
|
375
418
|
return args;
|
|
376
419
|
}
|
|
377
420
|
|
|
@@ -395,17 +438,17 @@ function pickUpstreamPort(publicPort: number, legacyAliasPort: number | null): n
|
|
|
395
438
|
return DEFAULT_UPSTREAM_PORT;
|
|
396
439
|
}
|
|
397
440
|
|
|
398
|
-
/** Try to start
|
|
399
|
-
*
|
|
400
|
-
* restarting a previous instance that didn't shut down cleanly. The
|
|
401
|
-
* TanStack Start server keeps running either way; clients just lose the
|
|
402
|
-
* per-PID attribution until they fall back to direct port `port` access. */
|
|
441
|
+
/** Try to start an identity-proxy ingress. The primary caller treats a
|
|
442
|
+
* `null` result as fatal; only an optional compatibility alias may degrade. */
|
|
403
443
|
async function tryStartIdentityProxy(
|
|
404
444
|
identityPort: number,
|
|
405
445
|
upstreamPort: number,
|
|
406
446
|
listenHost: string,
|
|
407
447
|
upstreamHost: string,
|
|
408
448
|
managedInstance: ManagedInstanceControlOptions | undefined,
|
|
449
|
+
allowedUiOrigins: readonly string[],
|
|
450
|
+
uiDirectory: string | undefined,
|
|
451
|
+
publicOrigin: string | undefined,
|
|
409
452
|
): Promise<import("node:http").Server | null> {
|
|
410
453
|
try {
|
|
411
454
|
const server = await startIdentityProxy({
|
|
@@ -423,6 +466,9 @@ async function tryStartIdentityProxy(
|
|
|
423
466
|
.split(",")
|
|
424
467
|
.map((host) => host.trim())
|
|
425
468
|
.filter((host) => host.length > 0),
|
|
469
|
+
allowedUiOrigins,
|
|
470
|
+
uiDirectory,
|
|
471
|
+
publicOrigin,
|
|
426
472
|
maxRequestBytes: readPositiveIntegerEnv("AGENT_INSPECTOR_MAX_REQUEST_BYTES"),
|
|
427
473
|
requestTimeoutMs: readPositiveIntegerEnv("AGENT_INSPECTOR_REQUEST_TIMEOUT_MS"),
|
|
428
474
|
managedInstance,
|
|
@@ -430,11 +476,7 @@ async function tryStartIdentityProxy(
|
|
|
430
476
|
return server;
|
|
431
477
|
} catch (err) {
|
|
432
478
|
const message = err instanceof Error ? err.message : String(err);
|
|
433
|
-
console.warn(
|
|
434
|
-
`[identity-proxy] Could not listen on port ${identityPort}: ${message}. ` +
|
|
435
|
-
`Falling back to OS-scan heuristic on port ${upstreamPort}. ` +
|
|
436
|
-
`Pass --identity-proxy-port <n> to choose another port, or --no-identity-proxy to disable.`,
|
|
437
|
-
);
|
|
479
|
+
console.warn(`[identity-proxy] Could not listen on port ${identityPort}: ${message}.`);
|
|
438
480
|
return null;
|
|
439
481
|
}
|
|
440
482
|
}
|
|
@@ -467,6 +509,7 @@ async function runStart(args: string[]): Promise<void> {
|
|
|
467
509
|
let captureModeWasSpecified = false;
|
|
468
510
|
let enableIdentityProxy = true;
|
|
469
511
|
let legacyAliasEnabled = false;
|
|
512
|
+
let serveUi = process.env["AGENT_INSPECTOR_BACKEND_ONLY"] !== "1";
|
|
470
513
|
|
|
471
514
|
if (envMode !== undefined && envMode !== "") {
|
|
472
515
|
const parsedMode = parseCaptureMode(envMode);
|
|
@@ -546,6 +589,14 @@ async function runStart(args: string[]): Promise<void> {
|
|
|
546
589
|
case "--background":
|
|
547
590
|
background = true;
|
|
548
591
|
break;
|
|
592
|
+
case "--backend-only":
|
|
593
|
+
case "--headless":
|
|
594
|
+
serveUi = false;
|
|
595
|
+
open = false;
|
|
596
|
+
break;
|
|
597
|
+
case "--with-ui":
|
|
598
|
+
serveUi = true;
|
|
599
|
+
break;
|
|
549
600
|
case "--config-dir":
|
|
550
601
|
configDir = args[i + 1];
|
|
551
602
|
i++;
|
|
@@ -618,6 +669,40 @@ async function runStart(args: string[]): Promise<void> {
|
|
|
618
669
|
process.exitCode = 1;
|
|
619
670
|
return;
|
|
620
671
|
}
|
|
672
|
+
if (!serveUi) open = false;
|
|
673
|
+
if (!enableIdentityProxy && serveUi) {
|
|
674
|
+
console.error(
|
|
675
|
+
"The decoupled UI is composed only by the protected ingress. Use --backend-only with --no-identity-proxy, or keep the identity proxy enabled.",
|
|
676
|
+
);
|
|
677
|
+
process.exitCode = 1;
|
|
678
|
+
return;
|
|
679
|
+
}
|
|
680
|
+
const uiOriginAllowlist = parseUiOriginAllowlist(process.env["AGENT_INSPECTOR_UI_ORIGINS"]);
|
|
681
|
+
if (uiOriginAllowlist.rejected.length > 0) {
|
|
682
|
+
console.error(
|
|
683
|
+
`Invalid AGENT_INSPECTOR_UI_ORIGINS entries: ${uiOriginAllowlist.rejected.join(", ")}. Only exact loopback http(s) origins are accepted; use a same-origin authenticated gateway for remote UI hosting.`,
|
|
684
|
+
);
|
|
685
|
+
process.exitCode = 1;
|
|
686
|
+
return;
|
|
687
|
+
}
|
|
688
|
+
const publicOrigin = normalizeExplicitPublicOrigin(process.env["AGENT_INSPECTOR_PUBLIC_ORIGIN"]);
|
|
689
|
+
if (publicOrigin === null) {
|
|
690
|
+
console.error(
|
|
691
|
+
"Invalid AGENT_INSPECTOR_PUBLIC_ORIGIN. Use an exact http(s) origin without credentials, path, query, or fragment.",
|
|
692
|
+
);
|
|
693
|
+
process.exitCode = 1;
|
|
694
|
+
return;
|
|
695
|
+
}
|
|
696
|
+
const uiDirectoryCandidate = join(__dirname, "../.output/ui");
|
|
697
|
+
const uiIndexPath = join(uiDirectoryCandidate, "index.html");
|
|
698
|
+
const uiDirectory = serveUi && existsSync(uiIndexPath) ? uiDirectoryCandidate : undefined;
|
|
699
|
+
if (serveUi && uiDirectory === undefined) {
|
|
700
|
+
console.error(
|
|
701
|
+
`Agent Inspector UI artifact is missing at ${uiIndexPath}. Run the composed build or use --backend-only.`,
|
|
702
|
+
);
|
|
703
|
+
process.exitCode = 1;
|
|
704
|
+
return;
|
|
705
|
+
}
|
|
621
706
|
|
|
622
707
|
/**
|
|
623
708
|
* Check if a port is in use and kill the process using it
|
|
@@ -655,11 +740,22 @@ async function runStart(args: string[]): Promise<void> {
|
|
|
655
740
|
const upstreamHost = enableIdentityProxy ? DEFAULT_BIND_HOST : host;
|
|
656
741
|
process.env["PORT"] = String(upstreamPort);
|
|
657
742
|
|
|
743
|
+
const configuredBasePath = process.env[AGENT_INSPECTOR_BASE_PATH_ENV];
|
|
744
|
+
if (configuredBasePath !== undefined && normalizePublicBasePath(configuredBasePath) === null) {
|
|
745
|
+
console.error(
|
|
746
|
+
`Invalid ${AGENT_INSPECTOR_BASE_PATH_ENV}. Use / for root or URL-safe path segments such as /inspector or /foo-bar/v1.`,
|
|
747
|
+
);
|
|
748
|
+
process.exitCode = 1;
|
|
749
|
+
return;
|
|
750
|
+
}
|
|
658
751
|
const basePath = getConfiguredBasePath(process.env);
|
|
659
|
-
const
|
|
660
|
-
const
|
|
661
|
-
const
|
|
662
|
-
const
|
|
752
|
+
const bindOrigin = urlForHost(port, host);
|
|
753
|
+
const outwardOrigin = publicOrigin ?? bindOrigin;
|
|
754
|
+
const surfaceBaseUrl = appendBasePathToOrigin(outwardOrigin, "/", basePath);
|
|
755
|
+
const uiUrl = serveUi ? surfaceBaseUrl : null;
|
|
756
|
+
const proxyUrl = appendBasePathToOrigin(outwardOrigin, "/proxy", basePath);
|
|
757
|
+
const openAiProxyUrl = appendBasePathToOrigin(outwardOrigin, "/proxy/v1", basePath);
|
|
758
|
+
const proxyMessagesUrl = appendBasePathToOrigin(outwardOrigin, "/proxy/v1/messages", basePath);
|
|
663
759
|
const legacyUrl =
|
|
664
760
|
legacyAliasPort === null
|
|
665
761
|
? null
|
|
@@ -674,8 +770,10 @@ async function runStart(args: string[]): Promise<void> {
|
|
|
674
770
|
: appendBasePathToOrigin(localUrlForPort(legacyAliasPort), "/api/mcp", basePath);
|
|
675
771
|
|
|
676
772
|
if (!forceRestart && (await isInspectorHealthy(port, host, basePath))) {
|
|
677
|
-
console.log(
|
|
678
|
-
|
|
773
|
+
console.log(
|
|
774
|
+
`agent-inspector ${serveUi ? "is already running" : "backend is already running"} at ${surfaceBaseUrl}`,
|
|
775
|
+
);
|
|
776
|
+
printAccessHints(port, host, basePath, serveUi, publicOrigin);
|
|
679
777
|
if (captureModeWasSpecified) {
|
|
680
778
|
const runningMode = await getRunningCaptureMode(port, host, basePath);
|
|
681
779
|
if (runningMode !== null && runningMode !== captureMode) {
|
|
@@ -684,7 +782,7 @@ async function runStart(args: string[]): Promise<void> {
|
|
|
684
782
|
}
|
|
685
783
|
}
|
|
686
784
|
console.log(`Use --force-restart to restart the existing instance.`);
|
|
687
|
-
if (open && openWasSpecified) {
|
|
785
|
+
if (open && openWasSpecified && uiUrl !== null) {
|
|
688
786
|
openBrowser(uiUrl);
|
|
689
787
|
}
|
|
690
788
|
return;
|
|
@@ -725,6 +823,7 @@ async function runStart(args: string[]): Promise<void> {
|
|
|
725
823
|
captureMode,
|
|
726
824
|
enableIdentityProxy,
|
|
727
825
|
legacyAliasEnabled,
|
|
826
|
+
serveUi,
|
|
728
827
|
});
|
|
729
828
|
const supervisorProcess = spawn(process.execPath, [cliEntry, ...supervisorArgs], {
|
|
730
829
|
stdio: "ignore",
|
|
@@ -738,8 +837,10 @@ async function runStart(args: string[]): Promise<void> {
|
|
|
738
837
|
supervisorProcess.unref();
|
|
739
838
|
|
|
740
839
|
if (await waitForInspectorHealthy(port, 10000, host, basePath)) {
|
|
741
|
-
console.log(
|
|
742
|
-
|
|
840
|
+
console.log(
|
|
841
|
+
`agent-inspector background ${serveUi ? "server" : "backend"} is ready at ${surfaceBaseUrl}`,
|
|
842
|
+
);
|
|
843
|
+
printAccessHints(port, host, basePath, serveUi, publicOrigin);
|
|
743
844
|
if (legacyProxyUrl !== null && legacyMcpUrl !== null) {
|
|
744
845
|
console.log(` Legacy proxy: ${legacyProxyUrl}`);
|
|
745
846
|
console.log(` Legacy MCP: ${legacyMcpUrl}`);
|
|
@@ -748,48 +849,18 @@ async function runStart(args: string[]): Promise<void> {
|
|
|
748
849
|
console.log(`Route AI coding tools through the identity proxy for accurate PID attribution:`);
|
|
749
850
|
console.log(` Claude Code: ANTHROPIC_BASE_URL=${proxyUrl} claude`);
|
|
750
851
|
console.log(` OpenCode: LLM_BASE_URL=${proxyUrl} opencode`);
|
|
751
|
-
console.log(` MiMo Code: OPENAI_BASE_URL=${
|
|
752
|
-
if (open && openWasSpecified) {
|
|
852
|
+
console.log(` MiMo Code: OPENAI_BASE_URL=${openAiProxyUrl} mimo`);
|
|
853
|
+
if (open && openWasSpecified && uiUrl !== null) {
|
|
753
854
|
openBrowser(uiUrl);
|
|
754
855
|
}
|
|
755
856
|
return;
|
|
756
857
|
}
|
|
757
858
|
|
|
758
|
-
console.error(`agent-inspector background server did not become ready at ${
|
|
859
|
+
console.error(`agent-inspector background server did not become ready at ${surfaceBaseUrl}.`);
|
|
759
860
|
process.exitCode = 1;
|
|
760
861
|
return;
|
|
761
862
|
}
|
|
762
863
|
|
|
763
|
-
console.log(`Server running at ${uiUrl}`);
|
|
764
|
-
console.log(` Capture mode: ${captureMode}`);
|
|
765
|
-
console.log(` Proxy: ${proxyUrl}`);
|
|
766
|
-
printAccessHints(port, host, basePath);
|
|
767
|
-
if (legacyUrl !== null && legacyProxyUrl !== null && legacyMcpUrl !== null) {
|
|
768
|
-
console.log(` Legacy UI: ${legacyUrl}`);
|
|
769
|
-
console.log(` Legacy proxy: ${legacyProxyUrl}`);
|
|
770
|
-
console.log(` Legacy MCP: ${legacyMcpUrl}`);
|
|
771
|
-
}
|
|
772
|
-
console.log(``);
|
|
773
|
-
console.log(`Route AI coding tools through the proxy:`);
|
|
774
|
-
console.log(` Claude Code: ANTHROPIC_BASE_URL=${proxyUrl} claude`);
|
|
775
|
-
console.log(` OpenCode: LLM_BASE_URL=${proxyUrl} opencode`);
|
|
776
|
-
console.log(` MiMo Code: OPENAI_BASE_URL=${proxyUrl} mimo`);
|
|
777
|
-
console.log(` Direct HTTP: curl ${proxyMessagesUrl} -d '{"model":"...","messages":[...]}'`);
|
|
778
|
-
console.log(
|
|
779
|
-
` Remote/container tools: use the Network proxy URL above when shown; otherwise restart with --host 0.0.0.0 or a reachable IP.`,
|
|
780
|
-
);
|
|
781
|
-
console.log(``);
|
|
782
|
-
console.log(`Routing environment variables:`);
|
|
783
|
-
console.log(` ROUTES JSON map of model prefix -> upstream URL`);
|
|
784
|
-
console.log(` DEFAULT_UPSTREAM Fallback upstream for unmatched models`);
|
|
785
|
-
console.log(
|
|
786
|
-
` Example: ROUTES='{"claude-":"https://api.anthropic.com","MiniMax":"https://api.minimaxi.com/anthropic"}'`,
|
|
787
|
-
);
|
|
788
|
-
|
|
789
|
-
if (open) {
|
|
790
|
-
openBrowser(uiUrl);
|
|
791
|
-
}
|
|
792
|
-
|
|
793
864
|
// Compute server path
|
|
794
865
|
const outputDir = __dirname;
|
|
795
866
|
const serverPath = join(outputDir, "../.output/server/index.mjs");
|
|
@@ -831,6 +902,7 @@ async function runStart(args: string[]): Promise<void> {
|
|
|
831
902
|
serverEnv["AGENT_INSPECTOR_PUBLIC_PORT"] = String(port);
|
|
832
903
|
serverEnv["PROXY_PORT"] = String(port);
|
|
833
904
|
serverEnv["AGENT_INSPECTOR_CAPTURE_MODE"] = captureMode;
|
|
905
|
+
serverEnv["AGENT_INSPECTOR_BACKEND_ONLY"] = serveUi ? "0" : "1";
|
|
834
906
|
const workerDir = join(__dirname, "workers");
|
|
835
907
|
if (existsSync(workerDir)) {
|
|
836
908
|
serverEnv["AGENT_INSPECTOR_WORKER_DIR"] = workerDir;
|
|
@@ -933,10 +1005,23 @@ async function runStart(args: string[]): Promise<void> {
|
|
|
933
1005
|
host,
|
|
934
1006
|
upstreamHost,
|
|
935
1007
|
managedInstanceControl,
|
|
1008
|
+
uiOriginAllowlist.origins,
|
|
1009
|
+
uiDirectory,
|
|
1010
|
+
publicOrigin,
|
|
936
1011
|
);
|
|
937
|
-
if (primaryProxy
|
|
938
|
-
|
|
1012
|
+
if (primaryProxy === null) {
|
|
1013
|
+
console.error(
|
|
1014
|
+
`Agent Inspector could not bind its protected public ingress at ${bindOrigin}; stopping the private backend.`,
|
|
1015
|
+
);
|
|
1016
|
+
requestSupervisorShutdown("SIGTERM");
|
|
1017
|
+
const failedStartupShutdown = currentSupervisorShutdown();
|
|
1018
|
+
if (failedStartupShutdown !== null) await failedStartupShutdown;
|
|
1019
|
+
process.off("SIGINT", handleSigint);
|
|
1020
|
+
process.off("SIGTERM", handleSigterm);
|
|
1021
|
+
process.exitCode = 1;
|
|
1022
|
+
return;
|
|
939
1023
|
}
|
|
1024
|
+
identityProxies.push({ label: "primary", port, server: primaryProxy });
|
|
940
1025
|
if (legacyAliasPort !== null) {
|
|
941
1026
|
const legacyProxy = await tryStartIdentityProxy(
|
|
942
1027
|
legacyAliasPort,
|
|
@@ -944,6 +1029,9 @@ async function runStart(args: string[]): Promise<void> {
|
|
|
944
1029
|
host,
|
|
945
1030
|
upstreamHost,
|
|
946
1031
|
managedInstanceControl,
|
|
1032
|
+
uiOriginAllowlist.origins,
|
|
1033
|
+
uiDirectory,
|
|
1034
|
+
publicOrigin,
|
|
947
1035
|
);
|
|
948
1036
|
if (legacyProxy !== null) {
|
|
949
1037
|
identityProxies.push({ label: "legacy", port: legacyAliasPort, server: legacyProxy });
|
|
@@ -957,11 +1045,13 @@ async function runStart(args: string[]): Promise<void> {
|
|
|
957
1045
|
// not started yet so the public port is not yet accepting traffic.
|
|
958
1046
|
const upstreamProbeBasePath = enableIdentityProxy ? "" : basePath;
|
|
959
1047
|
if (await waitForInspectorHealthy(upstreamPort, 5000, host, upstreamProbeBasePath)) {
|
|
960
|
-
console.log(
|
|
1048
|
+
console.log(
|
|
1049
|
+
`agent-inspector background ${serveUi ? "server" : "backend"} is ready at ${surfaceBaseUrl}`,
|
|
1050
|
+
);
|
|
961
1051
|
if (identityProxies.length > 0) {
|
|
962
1052
|
console.log(`Identity proxy ready on port ${port} (PID-attributing proxy).`);
|
|
963
1053
|
}
|
|
964
|
-
printAccessHints(port, host, basePath);
|
|
1054
|
+
printAccessHints(port, host, basePath, serveUi, publicOrigin);
|
|
965
1055
|
if (legacyProxyUrl !== null && legacyMcpUrl !== null) {
|
|
966
1056
|
console.log(` Legacy proxy: ${legacyProxyUrl}`);
|
|
967
1057
|
console.log(` Legacy MCP: ${legacyMcpUrl}`);
|
|
@@ -972,7 +1062,7 @@ async function runStart(args: string[]): Promise<void> {
|
|
|
972
1062
|
`Route AI coding tools through the identity proxy for accurate PID attribution:`,
|
|
973
1063
|
` Claude Code: ANTHROPIC_BASE_URL=${proxyUrl} claude`,
|
|
974
1064
|
` OpenCode: LLM_BASE_URL=${proxyUrl} opencode`,
|
|
975
|
-
` MiMo Code: OPENAI_BASE_URL=${
|
|
1065
|
+
` MiMo Code: OPENAI_BASE_URL=${openAiProxyUrl} mimo`,
|
|
976
1066
|
legacyProxyUrl === null
|
|
977
1067
|
? ` Override the port with --port <n> when needed.`
|
|
978
1068
|
: ` Legacy configs using ${legacyProxyUrl} still work.`,
|
|
@@ -980,14 +1070,25 @@ async function runStart(args: string[]): Promise<void> {
|
|
|
980
1070
|
}
|
|
981
1071
|
return;
|
|
982
1072
|
}
|
|
983
|
-
console.error(`agent-inspector background server did not become ready at ${
|
|
1073
|
+
console.error(`agent-inspector background server did not become ready at ${surfaceBaseUrl}.`);
|
|
1074
|
+
process.exitCode = 1;
|
|
1075
|
+
return;
|
|
1076
|
+
}
|
|
1077
|
+
|
|
1078
|
+
if (!(await waitForInspectorHealthy(port, 10_000, host, basePath))) {
|
|
1079
|
+
console.error(`Agent Inspector did not become ready at ${surfaceBaseUrl}; stopping startup.`);
|
|
1080
|
+
requestSupervisorShutdown("SIGTERM");
|
|
1081
|
+
const failedStartupShutdown = currentSupervisorShutdown();
|
|
1082
|
+
if (failedStartupShutdown !== null) await failedStartupShutdown;
|
|
1083
|
+
process.off("SIGINT", handleSigint);
|
|
1084
|
+
process.off("SIGTERM", handleSigterm);
|
|
984
1085
|
process.exitCode = 1;
|
|
985
1086
|
return;
|
|
986
1087
|
}
|
|
987
1088
|
|
|
988
1089
|
if (identityProxies.length > 0) {
|
|
989
1090
|
console.log(``);
|
|
990
|
-
console.log(`Identity proxy ready at ${
|
|
1091
|
+
console.log(`Identity proxy ready at ${bindOrigin} (PID-attributing ingress).`);
|
|
991
1092
|
if (legacyAliasPort !== null) {
|
|
992
1093
|
const legacyReady = identityProxies.some((proxy) => proxy.label === "legacy");
|
|
993
1094
|
if (legacyReady) {
|
|
@@ -999,6 +1100,28 @@ async function runStart(args: string[]): Promise<void> {
|
|
|
999
1100
|
}
|
|
1000
1101
|
}
|
|
1001
1102
|
|
|
1103
|
+
console.log(
|
|
1104
|
+
`${serveUi ? "UI and backend" : "Backend control and agent runtime"} running at ${surfaceBaseUrl}`,
|
|
1105
|
+
);
|
|
1106
|
+
console.log(` Capture mode: ${captureMode}`);
|
|
1107
|
+
console.log(` Proxy: ${proxyUrl}`);
|
|
1108
|
+
printAccessHints(port, host, basePath, serveUi, publicOrigin);
|
|
1109
|
+
if (legacyUrl !== null && legacyProxyUrl !== null && legacyMcpUrl !== null) {
|
|
1110
|
+
console.log(` Legacy UI: ${legacyUrl}`);
|
|
1111
|
+
console.log(` Legacy proxy: ${legacyProxyUrl}`);
|
|
1112
|
+
console.log(` Legacy MCP: ${legacyMcpUrl}`);
|
|
1113
|
+
}
|
|
1114
|
+
console.log(``);
|
|
1115
|
+
console.log(`Route AI coding tools through the proxy:`);
|
|
1116
|
+
console.log(` Claude Code: ANTHROPIC_BASE_URL=${proxyUrl} claude`);
|
|
1117
|
+
console.log(` OpenCode: LLM_BASE_URL=${proxyUrl} opencode`);
|
|
1118
|
+
console.log(` MiMo Code: OPENAI_BASE_URL=${openAiProxyUrl} mimo`);
|
|
1119
|
+
console.log(` Direct HTTP: curl ${proxyMessagesUrl} -d '{"model":"...","messages":[...]}'`);
|
|
1120
|
+
console.log(
|
|
1121
|
+
` Remote/container tools: use the Network proxy URL above when shown; otherwise restart with --host 0.0.0.0 or a reachable IP.`,
|
|
1122
|
+
);
|
|
1123
|
+
if (open && uiUrl !== null) openBrowser(uiUrl);
|
|
1124
|
+
|
|
1002
1125
|
process.exitCode = await serverExit;
|
|
1003
1126
|
|
|
1004
1127
|
const activeSupervisorShutdown = currentSupervisorShutdown();
|