@tonyclaw/agent-inspector 3.0.44 → 3.0.46
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.output/{nitro.json → backend/nitro.json} +3 -3
- package/.output/backend-public/assets/index-D4LX-sw-.js +11 -0
- package/.output/cli.js +22707 -17099
- package/.output/server/_libs/extend.mjs +4 -8
- package/.output/server/_libs/jszip.mjs +9 -35
- package/.output/server/_libs/modelcontextprotocol__core.mjs +25 -25
- package/.output/server/_libs/modelcontextprotocol__server.mjs +2 -2
- 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/_libs/zod.mjs +6 -6
- package/.output/server/_ssr/index.mjs +5 -4
- package/.output/server/_ssr/publicBasePathContext-IH2ilOfu.mjs +176 -0
- package/.output/server/_ssr/{router-DWcUFPR3.mjs → router-D18yUq36.mjs} +7877 -5597
- package/.output/server/_ssr/start-COQu_AgD.mjs +57 -0
- package/.output/server/_tanstack-start-manifest_v-DnbdNeun.mjs +4 -0
- package/.output/server/index.mjs +5 -145
- package/.output/{public/assets/CompareDrawer-DQHjxFO6.js → ui/assets/CompareDrawer-DAUuIJ6G.js} +1 -1
- package/.output/{public/assets/InspectorPet-D1A4505B.js → ui/assets/InspectorPet-BRBVjOWI.js} +1 -1
- package/.output/ui/assets/ProxyViewerContainer-D7Sq0ctc.js +59 -0
- package/.output/{public/assets/ReplayDialog-C5vmbecv.js → ui/assets/ReplayDialog-nDLsjOhs.js} +1 -1
- package/.output/{public/assets/RequestAnatomy-CPGNB8lk.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-CDhRgzf6.js → ui/assets/_sessionId-BAfzrhSU.js} +1 -1
- package/.output/{public/assets/_sessionId-mw3aA8Bp.js → ui/assets/_sessionId-QnBomgPD.js} +1 -1
- package/.output/ui/assets/favicon-DYEkHSNl.svg +21 -0
- package/.output/{public/assets/index-B2eoeT-Z.js → ui/assets/index-BcsdxBAd.js} +1 -1
- package/.output/ui/assets/index-BvXp42al.css +1 -0
- package/.output/{public/assets/index-CX7_rf7o.js → ui/assets/index-D0rtCN9V.js} +1 -1
- package/.output/ui/assets/index-DHpwr08Z.js +73 -0
- package/.output/{public/assets/index-BfRhTvOd.js → ui/assets/index-dNuk2dsU.js} +1 -1
- package/.output/ui/assets/json-viewer-BvFHglMb.js +1 -0
- package/.output/{public/assets/jszip.min-C9rCFoU3.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 +983 -414
- package/.output/workers/sessionWorkerEntry.js +983 -414
- package/README.md +363 -35
- package/docs/instance-control.openapi.yaml +361 -0
- package/package.json +28 -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/backend/routes/api/-instances.ts +109 -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/backend/routes/api/instances.$name.connection.ts +12 -0
- package/src/backend/routes/api/instances.$name.restart.ts +23 -0
- package/src/backend/routes/api/instances.$name.start.ts +18 -0
- package/src/backend/routes/api/instances.$name.stop.ts +23 -0
- package/src/backend/routes/api/instances.$name.ts +12 -0
- package/src/backend/routes/api/instances.ts +16 -0
- 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/backend/start.ts +10 -0
- package/src/cli/alias.ts +431 -0
- package/src/cli/doctor.ts +32 -9
- package/src/cli/instance.ts +1050 -0
- package/src/cli/instanceArgs.ts +285 -0
- package/src/cli/instanceControl.ts +181 -0
- package/src/cli/instanceModel.ts +267 -0
- package/src/cli/instanceRegistry.ts +731 -0
- package/src/cli/networkHints.ts +27 -14
- package/src/cli/onboard.ts +190 -35
- package/src/cli/onboardTarget.ts +228 -0
- package/src/cli/templates/codex-skill-onboard.ts +109 -31
- package/src/cli/templates/skill-onboard.ts +140 -70
- package/src/cli.ts +338 -77
- package/src/components/ProxyViewer.tsx +20 -10
- 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 +160 -140
- 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 +31 -7
- 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 +54 -0
- package/src/lib/instanceContract.ts +236 -0
- package/src/lib/managedInstance.ts +104 -0
- package/src/lib/piAgentContract.ts +3 -2
- package/src/lib/publicBasePathContext.ts +137 -0
- 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 +150 -0
- package/src/mcp/loopback.ts +16 -5
- package/src/mcp/mode.ts +25 -0
- package/src/mcp/server.ts +274 -39
- package/src/mcp/toolHandlers.ts +2 -2
- 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 +1049 -50
- 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 +84 -2
- package/src/proxy/schemas.ts +7 -1
- package/src/proxy/sessionArchive.ts +78 -14
- package/src/proxy/sessionInfo.ts +5 -4
- 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-BhpIgfBi.js +0 -126
- package/.output/public/assets/ResponseView-DUfrajCm.js +0 -2
- package/.output/public/assets/StreamingChunkSequence-nbeCQqOz.js +0 -1
- package/.output/public/assets/index-BWjeqxbk.css +0 -1
- package/.output/public/assets/index-C6qZwYlR.js +0 -70
- package/.output/public/assets/json-viewer-BLmF1sOZ.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-E_Dmopc-.mjs +0 -144
- package/.output/server/_sessionId-U54BAqdp.mjs +0 -82
- package/.output/server/_ssr/CompareDrawer-CksatPed.mjs +0 -1058
- package/.output/server/_ssr/InspectorPet-DNc4GQ7z.mjs +0 -936
- package/.output/server/_ssr/ProxyViewerContainer-B02Ey0p_.mjs +0 -17607
- package/.output/server/_ssr/ReplayDialog-DdMvHJF1.mjs +0 -723
- package/.output/server/_ssr/RequestAnatomy--vh2Z8__.mjs +0 -835
- package/.output/server/_ssr/ResponseView-Dhxc-cKC.mjs +0 -755
- package/.output/server/_ssr/StreamingChunkSequence-BG0EQmaD.mjs +0 -272
- package/.output/server/_ssr/index-D0At9nfd.mjs +0 -82
- package/.output/server/_ssr/index-lcfulIXa.mjs +0 -133
- package/.output/server/_ssr/json-viewer-My1J1_5R.mjs +0 -481
- package/.output/server/_ssr/start-HYkvq4Ni.mjs +0 -4
- package/.output/server/_tanstack-start-manifest_v-B2chR8ef.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
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import {
|
|
3
|
+
InstanceConnectionOutputSchema,
|
|
4
|
+
InstanceEmptyRequestSchema,
|
|
5
|
+
InstanceErrorOutputSchema,
|
|
6
|
+
InstanceListOutputSchema,
|
|
7
|
+
InstanceOperationOutputSchema,
|
|
8
|
+
InstanceStartRequestSchema,
|
|
9
|
+
InstanceStatusOutputSchema,
|
|
10
|
+
type InstanceStartRequest,
|
|
11
|
+
} from "../lib/instanceContract";
|
|
12
|
+
import type { CallApiOptions } from "./loopback";
|
|
13
|
+
import type { ToolResult } from "./toolHandlers";
|
|
14
|
+
|
|
15
|
+
export const INSTANCE_LIFECYCLE_TIMEOUT_MS = 60_000;
|
|
16
|
+
|
|
17
|
+
export const InstanceToolNameSchema = z.string().trim().min(1).max(64);
|
|
18
|
+
|
|
19
|
+
export const InstanceLifecycleToolInputSchema = InstanceStartRequestSchema.extend({
|
|
20
|
+
name: InstanceToolNameSchema,
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
export const InstanceNameToolInputSchema = z
|
|
24
|
+
.object({
|
|
25
|
+
name: InstanceToolNameSchema,
|
|
26
|
+
})
|
|
27
|
+
.strict();
|
|
28
|
+
|
|
29
|
+
export type InstanceCallApiFn = (path: string, options?: CallApiOptions) => Promise<Response>;
|
|
30
|
+
|
|
31
|
+
export type InstanceLifecycleToolInput = InstanceStartRequest & { name: string };
|
|
32
|
+
|
|
33
|
+
function textJson(data: unknown): ToolResult {
|
|
34
|
+
return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function toolError(message: string): ToolResult {
|
|
38
|
+
return { content: [{ type: "text", text: message }], isError: true };
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
async function responseJson(response: Response): Promise<unknown | null> {
|
|
42
|
+
try {
|
|
43
|
+
const value: unknown = await response.json();
|
|
44
|
+
return value;
|
|
45
|
+
} catch {
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
async function validatedInstanceResponse(
|
|
51
|
+
response: Response,
|
|
52
|
+
schema: z.ZodType,
|
|
53
|
+
operation: string,
|
|
54
|
+
): Promise<ToolResult> {
|
|
55
|
+
const value = await responseJson(response);
|
|
56
|
+
if (!response.ok) {
|
|
57
|
+
const error = InstanceErrorOutputSchema.safeParse(value);
|
|
58
|
+
return error.success
|
|
59
|
+
? { ...textJson(error.data), isError: true }
|
|
60
|
+
: toolError(
|
|
61
|
+
`${operation} returned HTTP ${String(response.status)} with an invalid error body`,
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const parsed = schema.safeParse(value);
|
|
66
|
+
return parsed.success
|
|
67
|
+
? textJson(parsed.data)
|
|
68
|
+
: toolError(`${operation} returned an invalid public instance document`);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function instancePath(name: string, suffix = ""): string {
|
|
72
|
+
return `/api/instances/${encodeURIComponent(name)}${suffix}`;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function jsonPost(body: unknown): CallApiOptions {
|
|
76
|
+
return {
|
|
77
|
+
method: "POST",
|
|
78
|
+
headers: {
|
|
79
|
+
accept: "application/json",
|
|
80
|
+
"content-type": "application/json",
|
|
81
|
+
},
|
|
82
|
+
body: JSON.stringify(body),
|
|
83
|
+
timeoutMs: INSTANCE_LIFECYCLE_TIMEOUT_MS,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function lifecycleRequest(input: InstanceLifecycleToolInput): InstanceStartRequest {
|
|
88
|
+
return {
|
|
89
|
+
port: input.port,
|
|
90
|
+
basePath: input.basePath,
|
|
91
|
+
host: input.host,
|
|
92
|
+
captureMode: input.captureMode,
|
|
93
|
+
uiEnabled: input.uiEnabled,
|
|
94
|
+
dataDir: input.dataDir,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export async function listInstancesImpl(callApi: InstanceCallApiFn): Promise<ToolResult> {
|
|
99
|
+
const response = await callApi("/api/instances", {
|
|
100
|
+
headers: { accept: "application/json" },
|
|
101
|
+
});
|
|
102
|
+
return validatedInstanceResponse(response, InstanceListOutputSchema, "GET /api/instances");
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export async function getInstanceImpl(
|
|
106
|
+
callApi: InstanceCallApiFn,
|
|
107
|
+
name: string,
|
|
108
|
+
): Promise<ToolResult> {
|
|
109
|
+
const path = instancePath(name);
|
|
110
|
+
const response = await callApi(path, { headers: { accept: "application/json" } });
|
|
111
|
+
return validatedInstanceResponse(response, InstanceStatusOutputSchema, `GET ${path}`);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export async function getInstanceConnectionImpl(
|
|
115
|
+
callApi: InstanceCallApiFn,
|
|
116
|
+
name: string,
|
|
117
|
+
): Promise<ToolResult> {
|
|
118
|
+
const path = instancePath(name, "/connection");
|
|
119
|
+
const response = await callApi(path, { headers: { accept: "application/json" } });
|
|
120
|
+
return validatedInstanceResponse(response, InstanceConnectionOutputSchema, `GET ${path}`);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export async function startInstanceImpl(
|
|
124
|
+
callApi: InstanceCallApiFn,
|
|
125
|
+
input: InstanceLifecycleToolInput,
|
|
126
|
+
): Promise<ToolResult> {
|
|
127
|
+
const path = instancePath(input.name, "/start");
|
|
128
|
+
const request = lifecycleRequest(input);
|
|
129
|
+
const response = await callApi(path, jsonPost(InstanceStartRequestSchema.parse(request)));
|
|
130
|
+
return validatedInstanceResponse(response, InstanceOperationOutputSchema, `POST ${path}`);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export async function stopInstanceImpl(
|
|
134
|
+
callApi: InstanceCallApiFn,
|
|
135
|
+
name: string,
|
|
136
|
+
): Promise<ToolResult> {
|
|
137
|
+
const path = instancePath(name, "/stop");
|
|
138
|
+
const response = await callApi(path, jsonPost(InstanceEmptyRequestSchema.parse({})));
|
|
139
|
+
return validatedInstanceResponse(response, InstanceOperationOutputSchema, `POST ${path}`);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
export async function restartInstanceImpl(
|
|
143
|
+
callApi: InstanceCallApiFn,
|
|
144
|
+
input: InstanceLifecycleToolInput,
|
|
145
|
+
): Promise<ToolResult> {
|
|
146
|
+
const path = instancePath(input.name, "/restart");
|
|
147
|
+
const request = lifecycleRequest(input);
|
|
148
|
+
const response = await callApi(path, jsonPost(InstanceStartRequestSchema.parse(request)));
|
|
149
|
+
return validatedInstanceResponse(response, InstanceOperationOutputSchema, `POST ${path}`);
|
|
150
|
+
}
|
package/src/mcp/loopback.ts
CHANGED
|
@@ -16,8 +16,12 @@
|
|
|
16
16
|
* — should stay identical so callers don't change.
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
|
-
import {
|
|
20
|
-
|
|
19
|
+
import {
|
|
20
|
+
AGENT_INSPECTOR_PUBLIC_BASE_PATH_HEADER,
|
|
21
|
+
AGENT_INSPECTOR_PUBLIC_PORT_HEADER,
|
|
22
|
+
withBasePath,
|
|
23
|
+
} from "../lib/basePath";
|
|
24
|
+
import { getPublicBasePath, getPublicPort } from "../lib/publicBasePathContext";
|
|
21
25
|
|
|
22
26
|
const DEFAULT_TIMEOUT_MS = 30_000;
|
|
23
27
|
|
|
@@ -47,10 +51,17 @@ export async function callApi(path: string, options: CallApiOptions = {}): Promi
|
|
|
47
51
|
if (!path.startsWith("/")) {
|
|
48
52
|
throw new Error(`callApi: path must start with '/', got: ${path}`);
|
|
49
53
|
}
|
|
50
|
-
const port =
|
|
51
|
-
const
|
|
54
|
+
const port = getPublicPort();
|
|
55
|
+
const publicBasePath = getPublicBasePath();
|
|
56
|
+
const url = `http://127.0.0.1:${port}${withBasePath(path, publicBasePath)}`;
|
|
52
57
|
|
|
53
58
|
const { timeoutMs = DEFAULT_TIMEOUT_MS, signal: userSignal, ...rest } = options;
|
|
59
|
+
const headers = new Headers(rest.headers);
|
|
60
|
+
headers.set(
|
|
61
|
+
AGENT_INSPECTOR_PUBLIC_BASE_PATH_HEADER,
|
|
62
|
+
publicBasePath.length === 0 ? "/" : publicBasePath,
|
|
63
|
+
);
|
|
64
|
+
headers.set(AGENT_INSPECTOR_PUBLIC_PORT_HEADER, String(port));
|
|
54
65
|
|
|
55
66
|
const controller = new AbortController();
|
|
56
67
|
const timeoutHandle = setTimeout(() => controller.abort(), timeoutMs);
|
|
@@ -65,7 +76,7 @@ export async function callApi(path: string, options: CallApiOptions = {}): Promi
|
|
|
65
76
|
}
|
|
66
77
|
|
|
67
78
|
try {
|
|
68
|
-
return await fetch(url, { ...rest, signal: controller.signal });
|
|
79
|
+
return await fetch(url, { ...rest, headers, signal: controller.signal });
|
|
69
80
|
} catch (err) {
|
|
70
81
|
if (err instanceof Error && err.name === "AbortError") {
|
|
71
82
|
throw new LoopbackTimeoutError(path, timeoutMs);
|
package/src/mcp/mode.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
export type McpWriteMode = "enabled" | "readonly";
|
|
2
2
|
|
|
3
|
+
export const MCP_INSTANCE_WRITES_ENV = "AGENT_INSPECTOR_MCP_INSTANCE_WRITES";
|
|
4
|
+
|
|
3
5
|
function parseFlag(value: string | undefined): boolean | null {
|
|
4
6
|
if (value === undefined) return null;
|
|
5
7
|
switch (value.trim().toLowerCase()) {
|
|
@@ -26,6 +28,29 @@ export function isMcpWriteEnabled(): boolean {
|
|
|
26
28
|
return writesFlag === true;
|
|
27
29
|
}
|
|
28
30
|
|
|
31
|
+
export function isMcpInstanceWriteEnabled(): boolean {
|
|
32
|
+
return process.env[MCP_INSTANCE_WRITES_ENV] === "1";
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function getMcpInstanceModeInfo(): {
|
|
36
|
+
writeMode: McpWriteMode;
|
|
37
|
+
writesEnabled: boolean;
|
|
38
|
+
env: { AGENT_INSPECTOR_MCP_INSTANCE_WRITES: string | null };
|
|
39
|
+
note: string;
|
|
40
|
+
} {
|
|
41
|
+
const writesEnabled = isMcpInstanceWriteEnabled();
|
|
42
|
+
return {
|
|
43
|
+
writeMode: writesEnabled ? "enabled" : "readonly",
|
|
44
|
+
writesEnabled,
|
|
45
|
+
env: {
|
|
46
|
+
AGENT_INSPECTOR_MCP_INSTANCE_WRITES: process.env[MCP_INSTANCE_WRITES_ENV] ?? null,
|
|
47
|
+
},
|
|
48
|
+
note: writesEnabled
|
|
49
|
+
? "Named-instance lifecycle tools passed the instance-specific opt-in. General MCP writes must also be enabled."
|
|
50
|
+
: "Named-instance lifecycle tools require AGENT_INSPECTOR_MCP_INSTANCE_WRITES=1 in addition to general MCP writes.",
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
|
|
29
54
|
export function getMcpModeInfo(): {
|
|
30
55
|
writeMode: McpWriteMode;
|
|
31
56
|
writesEnabled: boolean;
|
package/src/mcp/server.ts
CHANGED
|
@@ -33,9 +33,14 @@ import {
|
|
|
33
33
|
UpdateInspectorGroupInputSchema,
|
|
34
34
|
} from "../lib/groupContract";
|
|
35
35
|
import { InspectorRunStatusSchema, UpdateInspectorRunInputSchema } from "../lib/runContract";
|
|
36
|
-
import {
|
|
37
|
-
import {
|
|
38
|
-
|
|
36
|
+
import { withBasePath } from "../lib/basePath";
|
|
37
|
+
import {
|
|
38
|
+
getPublicBasePath,
|
|
39
|
+
getPublicOrigin,
|
|
40
|
+
runWithRequestPublicBasePath,
|
|
41
|
+
} from "../lib/publicBasePathContext";
|
|
42
|
+
import { JsonValueSchema, LogIdSchema, parseLogId } from "../contracts";
|
|
43
|
+
import { InstanceListOutputSchema } from "../lib/instanceContract";
|
|
39
44
|
import {
|
|
40
45
|
MAX_PROVIDER_MODEL_NAME_CHARS,
|
|
41
46
|
MAX_PROVIDER_MODELS,
|
|
@@ -43,7 +48,22 @@ import {
|
|
|
43
48
|
MAX_SEARCH_QUERY_CHARS,
|
|
44
49
|
} from "../lib/resourceLimits";
|
|
45
50
|
import { getCurrentContext } from "./currentContext";
|
|
46
|
-
import {
|
|
51
|
+
import {
|
|
52
|
+
getMcpInstanceModeInfo,
|
|
53
|
+
getMcpModeInfo,
|
|
54
|
+
isMcpInstanceWriteEnabled,
|
|
55
|
+
isMcpWriteEnabled,
|
|
56
|
+
} from "./mode";
|
|
57
|
+
import {
|
|
58
|
+
getInstanceConnectionImpl,
|
|
59
|
+
getInstanceImpl,
|
|
60
|
+
InstanceLifecycleToolInputSchema,
|
|
61
|
+
InstanceNameToolInputSchema,
|
|
62
|
+
listInstancesImpl,
|
|
63
|
+
restartInstanceImpl,
|
|
64
|
+
startInstanceImpl,
|
|
65
|
+
stopInstanceImpl,
|
|
66
|
+
} from "./instanceHandlers";
|
|
47
67
|
import {
|
|
48
68
|
getInspectorGroup,
|
|
49
69
|
listInspectorGroups,
|
|
@@ -178,17 +198,10 @@ export async function _resetForTests(): Promise<void> {
|
|
|
178
198
|
* handler — accepts a Web `Request`, returns a `Promise<Response>`.
|
|
179
199
|
*/
|
|
180
200
|
export async function handleMcpRequest(request: Request): Promise<Response> {
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
const port = Number(url.port);
|
|
186
|
-
if (port > 0) setCurrentPort(port);
|
|
187
|
-
} catch {
|
|
188
|
-
// URL parse failure → fall through to PORT env var in getCurrentPort()
|
|
189
|
-
}
|
|
190
|
-
const { transport } = await getServer();
|
|
191
|
-
return transport.handleRequest(request);
|
|
201
|
+
return runWithRequestPublicBasePath(request, async () => {
|
|
202
|
+
const { transport } = await getServer();
|
|
203
|
+
return transport.handleRequest(request);
|
|
204
|
+
});
|
|
192
205
|
}
|
|
193
206
|
|
|
194
207
|
// ---------------------------------------------------------------------------
|
|
@@ -219,6 +232,27 @@ Either preview field is null when the body is unknown format, unparseable, or th
|
|
|
219
232
|
const PROVIDER_WRITE_WARNING =
|
|
220
233
|
"⚠ This tool mutates provider configuration. Confirm with the user before invoking.";
|
|
221
234
|
|
|
235
|
+
const INSTANCE_LIFECYCLE_WRITE_WARNING =
|
|
236
|
+
"This tool changes a local Agent Inspector process. Obtain explicit user approval before invoking it.";
|
|
237
|
+
|
|
238
|
+
const INSTANCE_READ_TOOL_NAMES = [
|
|
239
|
+
"inspector_list_instances",
|
|
240
|
+
"inspector_get_instance",
|
|
241
|
+
"inspector_get_instance_connection",
|
|
242
|
+
] as const;
|
|
243
|
+
|
|
244
|
+
const INSTANCE_WRITE_TOOL_NAMES = [
|
|
245
|
+
"inspector_start_instance",
|
|
246
|
+
"inspector_stop_instance",
|
|
247
|
+
"inspector_restart_instance",
|
|
248
|
+
] as const;
|
|
249
|
+
|
|
250
|
+
const INSTANCE_RESOURCE_URIS = [
|
|
251
|
+
"inspector://instances",
|
|
252
|
+
"inspector://instances/{name}",
|
|
253
|
+
"inspector://instances/{name}/connection",
|
|
254
|
+
] as const;
|
|
255
|
+
|
|
222
256
|
const AddProviderInputSchema = z
|
|
223
257
|
.object({
|
|
224
258
|
name: z.string().min(1).describe("Provider display name."),
|
|
@@ -301,7 +335,15 @@ const UpdateProviderInputSchema = z.object({
|
|
|
301
335
|
});
|
|
302
336
|
|
|
303
337
|
const LogResourceListResponseSchema = z.object({
|
|
304
|
-
logs: z.array(z.object({ id:
|
|
338
|
+
logs: z.array(z.object({ id: LogIdSchema })),
|
|
339
|
+
});
|
|
340
|
+
|
|
341
|
+
export const McpLogIdInputSchema = z.object({
|
|
342
|
+
id: LogIdSchema.describe("The log id."),
|
|
343
|
+
});
|
|
344
|
+
|
|
345
|
+
export const McpOptionalLogIdInputSchema = z.object({
|
|
346
|
+
id: LogIdSchema.optional().describe("Optional log id to inspect."),
|
|
305
347
|
});
|
|
306
348
|
|
|
307
349
|
const ProcessResourceListResponseSchema = z.object({
|
|
@@ -327,10 +369,7 @@ function jsonResource(uri: URL, data: unknown): ReadResourceResult {
|
|
|
327
369
|
}
|
|
328
370
|
|
|
329
371
|
function mcpEndpointUrl(): string {
|
|
330
|
-
return
|
|
331
|
-
"/api/mcp",
|
|
332
|
-
getConfiguredBasePath(process.env),
|
|
333
|
-
)}`;
|
|
372
|
+
return `${getPublicOrigin()}${withBasePath("/api/mcp", getPublicBasePath())}`;
|
|
334
373
|
}
|
|
335
374
|
|
|
336
375
|
function mcpHealth(): Record<string, unknown> {
|
|
@@ -342,7 +381,7 @@ function mcpHealth(): Record<string, unknown> {
|
|
|
342
381
|
},
|
|
343
382
|
transport: {
|
|
344
383
|
primary: "streamable-http",
|
|
345
|
-
endpoint:
|
|
384
|
+
endpoint: mcpEndpointUrl(),
|
|
346
385
|
stateless: true,
|
|
347
386
|
},
|
|
348
387
|
mode: getMcpModeInfo(),
|
|
@@ -355,6 +394,7 @@ function mcpHealth(): Record<string, unknown> {
|
|
|
355
394
|
}
|
|
356
395
|
|
|
357
396
|
const WRITE_TOOL_NAMES = new Set<string>([
|
|
397
|
+
...INSTANCE_WRITE_TOOL_NAMES,
|
|
358
398
|
"inspector_create_run",
|
|
359
399
|
"inspector_update_run",
|
|
360
400
|
"inspector_export_evidence",
|
|
@@ -379,18 +419,36 @@ const WRITE_TOOL_NAMES = new Set<string>([
|
|
|
379
419
|
function mcpCapabilities(): Record<string, unknown> {
|
|
380
420
|
const readTools = TOOL_NAMES.filter((name) => !WRITE_TOOL_NAMES.has(name));
|
|
381
421
|
const writeTools = TOOL_NAMES.filter((name) => WRITE_TOOL_NAMES.has(name));
|
|
422
|
+
const generalWriteMode = getMcpModeInfo();
|
|
423
|
+
const instanceWriteMode = getMcpInstanceModeInfo();
|
|
382
424
|
return {
|
|
383
425
|
serverInfo: {
|
|
384
426
|
name: "agent-inspector",
|
|
385
427
|
version: MCP_SERVER_VERSION,
|
|
386
428
|
},
|
|
387
|
-
mode:
|
|
429
|
+
mode: generalWriteMode,
|
|
388
430
|
tools: {
|
|
389
431
|
read: readTools,
|
|
390
432
|
writeOrAction: writeTools,
|
|
391
433
|
},
|
|
392
434
|
resources: RESOURCE_NAMES,
|
|
393
435
|
prompts: PROMPT_NAMES,
|
|
436
|
+
instanceControl: {
|
|
437
|
+
tools: {
|
|
438
|
+
read: INSTANCE_READ_TOOL_NAMES,
|
|
439
|
+
writeOrAction: INSTANCE_WRITE_TOOL_NAMES,
|
|
440
|
+
},
|
|
441
|
+
resources: INSTANCE_RESOURCE_URIS,
|
|
442
|
+
writeGates: {
|
|
443
|
+
general: generalWriteMode,
|
|
444
|
+
instance: instanceWriteMode,
|
|
445
|
+
lifecycleWritesEnabled: generalWriteMode.writesEnabled && instanceWriteMode.writesEnabled,
|
|
446
|
+
},
|
|
447
|
+
limitations: {
|
|
448
|
+
selfStopOrRestart:
|
|
449
|
+
"The serving managed instance cannot stop or restart itself over REST or MCP. Use the CLI or a sibling controller instance.",
|
|
450
|
+
},
|
|
451
|
+
},
|
|
394
452
|
};
|
|
395
453
|
}
|
|
396
454
|
|
|
@@ -473,6 +531,36 @@ function safeWriteCall(
|
|
|
473
531
|
});
|
|
474
532
|
}
|
|
475
533
|
|
|
534
|
+
function disabledInstanceWriteTool(toolName: string): ToolResult {
|
|
535
|
+
return {
|
|
536
|
+
content: [
|
|
537
|
+
{
|
|
538
|
+
type: "text",
|
|
539
|
+
text: JSON.stringify(
|
|
540
|
+
{
|
|
541
|
+
error: "mcp-instance-write-disabled",
|
|
542
|
+
tool: toolName,
|
|
543
|
+
generalMode: getMcpModeInfo(),
|
|
544
|
+
instanceMode: getMcpInstanceModeInfo(),
|
|
545
|
+
},
|
|
546
|
+
null,
|
|
547
|
+
2,
|
|
548
|
+
),
|
|
549
|
+
},
|
|
550
|
+
],
|
|
551
|
+
isError: true,
|
|
552
|
+
};
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
function safeInstanceWriteCall(
|
|
556
|
+
toolName: string,
|
|
557
|
+
fn: () => ToolResult | Promise<ToolResult>,
|
|
558
|
+
): Promise<ToolResult> {
|
|
559
|
+
return safeWriteCall(toolName, () =>
|
|
560
|
+
isMcpInstanceWriteEnabled() ? fn() : disabledInstanceWriteTool(toolName),
|
|
561
|
+
);
|
|
562
|
+
}
|
|
563
|
+
|
|
476
564
|
function variableString(variables: Variables, name: string): string | null {
|
|
477
565
|
const value = variables[name];
|
|
478
566
|
if (Array.isArray(value)) return value[0] ?? null;
|
|
@@ -504,6 +592,41 @@ function readServiceJsonResource<T>(
|
|
|
504
592
|
return jsonResource(uri, result.value);
|
|
505
593
|
}
|
|
506
594
|
|
|
595
|
+
async function readInstanceToolResource(
|
|
596
|
+
uri: URL,
|
|
597
|
+
resultPromise: Promise<ToolResult>,
|
|
598
|
+
): Promise<ReadResourceResult> {
|
|
599
|
+
const result = await resultPromise;
|
|
600
|
+
const text = result.content[0]?.text ?? "";
|
|
601
|
+
return textResource(uri, result.isError === true ? "text/plain" : "application/json", text);
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
async function listInstanceTemplateResources(connection: boolean): Promise<ListResourcesResult> {
|
|
605
|
+
try {
|
|
606
|
+
const response = await callApi("/api/instances", {
|
|
607
|
+
headers: { accept: "application/json" },
|
|
608
|
+
});
|
|
609
|
+
if (!response.ok) return listResult([]);
|
|
610
|
+
const parsed = InstanceListOutputSchema.safeParse(await response.json());
|
|
611
|
+
if (!parsed.success) return listResult([]);
|
|
612
|
+
return listResult(
|
|
613
|
+
parsed.data.instances.map((instance) => ({
|
|
614
|
+
uri: connection
|
|
615
|
+
? `inspector://instances/${encodeURIComponent(instance.name)}/connection`
|
|
616
|
+
: `inspector://instances/${encodeURIComponent(instance.name)}`,
|
|
617
|
+
name: connection ? `instance-connection:${instance.name}` : `instance:${instance.name}`,
|
|
618
|
+
title: connection
|
|
619
|
+
? `Agent Inspector connection for ${instance.name}`
|
|
620
|
+
: `Agent Inspector instance ${instance.name}`,
|
|
621
|
+
mimeType: "application/json",
|
|
622
|
+
description: `${instance.state} at ${instance.urls.ui}`,
|
|
623
|
+
})),
|
|
624
|
+
);
|
|
625
|
+
} catch {
|
|
626
|
+
return listResult([]);
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
|
|
507
630
|
async function listSessionResources(): Promise<ListResourcesResult> {
|
|
508
631
|
try {
|
|
509
632
|
const response = await callApi("/api/sessions");
|
|
@@ -707,6 +830,74 @@ function userPrompt(text: string): GetPromptResult {
|
|
|
707
830
|
// ---------------------------------------------------------------------------
|
|
708
831
|
|
|
709
832
|
function registerTools(server: McpServer): void {
|
|
833
|
+
// ----- Named instance discovery and lifecycle -----
|
|
834
|
+
|
|
835
|
+
server.registerTool(
|
|
836
|
+
"inspector_list_instances",
|
|
837
|
+
{
|
|
838
|
+
title: "List named Agent Inspector instances",
|
|
839
|
+
description:
|
|
840
|
+
"Returns the versioned, token-free REST instance list with live state, saved configuration, and public URLs. Available in readonly mode.",
|
|
841
|
+
inputSchema: z.object({}).strict(),
|
|
842
|
+
},
|
|
843
|
+
() => safeCall(() => listInstancesImpl(callApi)),
|
|
844
|
+
);
|
|
845
|
+
|
|
846
|
+
server.registerTool(
|
|
847
|
+
"inspector_get_instance",
|
|
848
|
+
{
|
|
849
|
+
title: "Get a named Agent Inspector instance",
|
|
850
|
+
description:
|
|
851
|
+
"Returns one versioned, token-free named-instance status document from the REST control plane. Available in readonly mode.",
|
|
852
|
+
inputSchema: InstanceNameToolInputSchema,
|
|
853
|
+
},
|
|
854
|
+
({ name }) => safeCall(() => getInstanceImpl(callApi, name)),
|
|
855
|
+
);
|
|
856
|
+
|
|
857
|
+
server.registerTool(
|
|
858
|
+
"inspector_get_instance_connection",
|
|
859
|
+
{
|
|
860
|
+
title: "Get coding-agent connection settings for an instance",
|
|
861
|
+
description:
|
|
862
|
+
"Returns the REST connection descriptor for one named instance, including protocol-correct proxy, OpenAI /v1, MCP, health, environment, and Codex values. It never includes credentials.",
|
|
863
|
+
inputSchema: InstanceNameToolInputSchema,
|
|
864
|
+
},
|
|
865
|
+
({ name }) => safeCall(() => getInstanceConnectionImpl(callApi, name)),
|
|
866
|
+
);
|
|
867
|
+
|
|
868
|
+
server.registerTool(
|
|
869
|
+
"inspector_start_instance",
|
|
870
|
+
{
|
|
871
|
+
title: "Start or create a named Agent Inspector instance",
|
|
872
|
+
description: `${INSTANCE_LIFECYCLE_WRITE_WARNING} Starts, creates, or idempotently reuses a named sibling instance through the REST lifecycle API. Requires both AGENT_INSPECTOR_MCP_WRITES=1 and AGENT_INSPECTOR_MCP_INSTANCE_WRITES=1.`,
|
|
873
|
+
inputSchema: InstanceLifecycleToolInputSchema,
|
|
874
|
+
},
|
|
875
|
+
(args) =>
|
|
876
|
+
safeInstanceWriteCall("inspector_start_instance", () => startInstanceImpl(callApi, args)),
|
|
877
|
+
);
|
|
878
|
+
|
|
879
|
+
server.registerTool(
|
|
880
|
+
"inspector_stop_instance",
|
|
881
|
+
{
|
|
882
|
+
title: "Stop a named Agent Inspector instance",
|
|
883
|
+
description: `${INSTANCE_LIFECYCLE_WRITE_WARNING} Gracefully stops a sibling instance after authenticated ownership checks. The instance serving this MCP connection cannot stop itself. Requires both MCP write gates.`,
|
|
884
|
+
inputSchema: InstanceNameToolInputSchema,
|
|
885
|
+
},
|
|
886
|
+
({ name }) =>
|
|
887
|
+
safeInstanceWriteCall("inspector_stop_instance", () => stopInstanceImpl(callApi, name)),
|
|
888
|
+
);
|
|
889
|
+
|
|
890
|
+
server.registerTool(
|
|
891
|
+
"inspector_restart_instance",
|
|
892
|
+
{
|
|
893
|
+
title: "Restart a named Agent Inspector instance",
|
|
894
|
+
description: `${INSTANCE_LIFECYCLE_WRITE_WARNING} Validates and restarts a sibling instance through the bounded REST lifecycle path. The instance serving this MCP connection cannot restart itself. Requires both MCP write gates.`,
|
|
895
|
+
inputSchema: InstanceLifecycleToolInputSchema,
|
|
896
|
+
},
|
|
897
|
+
(args) =>
|
|
898
|
+
safeInstanceWriteCall("inspector_restart_instance", () => restartInstanceImpl(callApi, args)),
|
|
899
|
+
);
|
|
900
|
+
|
|
710
901
|
// ----- Read tools -----
|
|
711
902
|
|
|
712
903
|
server.registerTool(
|
|
@@ -782,9 +973,7 @@ function registerTools(server: McpServer): void {
|
|
|
782
973
|
title: "Get a single captured log by id",
|
|
783
974
|
description:
|
|
784
975
|
"Returns the full CapturedLog for the given id, including rawRequestBody and responseText with no truncation. SSE streaming chunks are NOT included — use inspector_get_log_chunks for those. Returns an error if the id does not exist.",
|
|
785
|
-
inputSchema:
|
|
786
|
-
id: z.number().int().positive().describe("The log id."),
|
|
787
|
-
}),
|
|
976
|
+
inputSchema: McpLogIdInputSchema,
|
|
788
977
|
},
|
|
789
978
|
({ id }) => safeCall(() => getLogImpl(callApi, id)),
|
|
790
979
|
);
|
|
@@ -795,9 +984,7 @@ function registerTools(server: McpServer): void {
|
|
|
795
984
|
title: "Get SSE streaming chunks for a captured log",
|
|
796
985
|
description:
|
|
797
986
|
"Returns the SSE chunks array for a streaming log, in the order they were received. Returns an error if the log has no chunks (i.e. was non-streaming or the log id is unknown).",
|
|
798
|
-
inputSchema:
|
|
799
|
-
id: z.number().int().positive().describe("The log id."),
|
|
800
|
-
}),
|
|
987
|
+
inputSchema: McpLogIdInputSchema,
|
|
801
988
|
},
|
|
802
989
|
({ id }) => safeCall(() => getLogChunksImpl(callApi, id)),
|
|
803
990
|
);
|
|
@@ -808,9 +995,7 @@ function registerTools(server: McpServer): void {
|
|
|
808
995
|
title: "Get captured log headers",
|
|
809
996
|
description:
|
|
810
997
|
"Returns header-focused evidence for one log without large request/response bodies: raw headers, upstream headers, user-agent, origin, client PID/port, session id, model, and API path.",
|
|
811
|
-
inputSchema:
|
|
812
|
-
id: z.number().int().positive().describe("The log id."),
|
|
813
|
-
}),
|
|
998
|
+
inputSchema: McpLogIdInputSchema,
|
|
814
999
|
},
|
|
815
1000
|
({ id }) => safeCall(() => getLogHeadersImpl(callApi, id)),
|
|
816
1001
|
);
|
|
@@ -988,9 +1173,7 @@ function registerTools(server: McpServer): void {
|
|
|
988
1173
|
title: "Diagnose capture detail availability",
|
|
989
1174
|
description:
|
|
990
1175
|
"Explains why headers or bodies may be missing for the current runtime or a specific log, including captureMode, compact body mode, rawHeaders presence, and next-step recommendations.",
|
|
991
|
-
inputSchema:
|
|
992
|
-
id: z.number().int().positive().optional().describe("Optional log id to inspect."),
|
|
993
|
-
}),
|
|
1176
|
+
inputSchema: McpOptionalLogIdInputSchema,
|
|
994
1177
|
},
|
|
995
1178
|
(args) => safeCall(() => diagnoseCaptureImpl(callApi, args)),
|
|
996
1179
|
);
|
|
@@ -1318,9 +1501,7 @@ function registerTools(server: McpServer): void {
|
|
|
1318
1501
|
title: "Replay a captured log against its provider",
|
|
1319
1502
|
description:
|
|
1320
1503
|
"Re-sends the captured request body to the upstream LLM and returns the response summary: success flag, status, responseText, input/output token counts, elapsedMs, and whether the response was streaming. Useful for re-running a request after a fix or a transient failure. Returns an error if the log id is unknown or the upstream call fails.",
|
|
1321
|
-
inputSchema:
|
|
1322
|
-
id: z.number().int().positive().describe("The log id to replay."),
|
|
1323
|
-
}),
|
|
1504
|
+
inputSchema: McpLogIdInputSchema,
|
|
1324
1505
|
},
|
|
1325
1506
|
(args) => safeWriteCall("inspector_replay_log", () => replayLogImpl(callApi, args)),
|
|
1326
1507
|
);
|
|
@@ -1460,6 +1641,55 @@ PATCH-style update: only the fields you supply are changed. Use models to update
|
|
|
1460
1641
|
}
|
|
1461
1642
|
|
|
1462
1643
|
function registerResources(server: McpServer): void {
|
|
1644
|
+
server.registerResource(
|
|
1645
|
+
"inspector_instances",
|
|
1646
|
+
"inspector://instances",
|
|
1647
|
+
{
|
|
1648
|
+
title: "Named Agent Inspector instances",
|
|
1649
|
+
description: "Versioned, token-free named-instance list backed by GET /api/instances.",
|
|
1650
|
+
mimeType: "application/json",
|
|
1651
|
+
},
|
|
1652
|
+
(uri) => readInstanceToolResource(uri, listInstancesImpl(callApi)),
|
|
1653
|
+
);
|
|
1654
|
+
|
|
1655
|
+
server.registerResource(
|
|
1656
|
+
"inspector_instance",
|
|
1657
|
+
new ResourceTemplate("inspector://instances/{name}", {
|
|
1658
|
+
list: async () => await listInstanceTemplateResources(false),
|
|
1659
|
+
}),
|
|
1660
|
+
{
|
|
1661
|
+
title: "Named Agent Inspector instance",
|
|
1662
|
+
description:
|
|
1663
|
+
"Versioned, token-free status for one named instance backed by GET /api/instances/{name}.",
|
|
1664
|
+
mimeType: "application/json",
|
|
1665
|
+
},
|
|
1666
|
+
(uri, variables) => {
|
|
1667
|
+
const name = variableString(variables, "name");
|
|
1668
|
+
return name === null
|
|
1669
|
+
? textResource(uri, "text/plain", "Missing instance name")
|
|
1670
|
+
: readInstanceToolResource(uri, getInstanceImpl(callApi, name));
|
|
1671
|
+
},
|
|
1672
|
+
);
|
|
1673
|
+
|
|
1674
|
+
server.registerResource(
|
|
1675
|
+
"inspector_instance_connection",
|
|
1676
|
+
new ResourceTemplate("inspector://instances/{name}/connection", {
|
|
1677
|
+
list: async () => await listInstanceTemplateResources(true),
|
|
1678
|
+
}),
|
|
1679
|
+
{
|
|
1680
|
+
title: "Named instance coding-agent connection",
|
|
1681
|
+
description:
|
|
1682
|
+
"Token-free connection descriptor backed by GET /api/instances/{name}/connection.",
|
|
1683
|
+
mimeType: "application/json",
|
|
1684
|
+
},
|
|
1685
|
+
(uri, variables) => {
|
|
1686
|
+
const name = variableString(variables, "name");
|
|
1687
|
+
return name === null
|
|
1688
|
+
? textResource(uri, "text/plain", "Missing instance name")
|
|
1689
|
+
: readInstanceToolResource(uri, getInstanceConnectionImpl(callApi, name));
|
|
1690
|
+
},
|
|
1691
|
+
);
|
|
1692
|
+
|
|
1463
1693
|
server.registerResource(
|
|
1464
1694
|
"inspector_mcp_health",
|
|
1465
1695
|
"inspector://mcp/health",
|
|
@@ -1580,8 +1810,8 @@ function registerResources(server: McpServer): void {
|
|
|
1580
1810
|
},
|
|
1581
1811
|
async (uri, variables) => {
|
|
1582
1812
|
const id = variableString(variables, "id");
|
|
1583
|
-
const parsed = id === null ?
|
|
1584
|
-
if (
|
|
1813
|
+
const parsed = id === null ? null : parseLogId(id);
|
|
1814
|
+
if (parsed === null) {
|
|
1585
1815
|
return textResource(uri, "text/plain", "Invalid log id");
|
|
1586
1816
|
}
|
|
1587
1817
|
const result = await getLogImpl(callApi, parsed);
|
|
@@ -1958,6 +2188,8 @@ Return:
|
|
|
1958
2188
|
|
|
1959
2189
|
// Surface the tool catalog for tests that assert on the tool name set.
|
|
1960
2190
|
export const TOOL_NAMES = [
|
|
2191
|
+
...INSTANCE_READ_TOOL_NAMES,
|
|
2192
|
+
...INSTANCE_WRITE_TOOL_NAMES,
|
|
1961
2193
|
"inspector_list_logs",
|
|
1962
2194
|
"inspector_search_logs",
|
|
1963
2195
|
"inspector_get_log",
|
|
@@ -2006,6 +2238,9 @@ export const TOOL_NAMES = [
|
|
|
2006
2238
|
] as const;
|
|
2007
2239
|
|
|
2008
2240
|
export const RESOURCE_NAMES = [
|
|
2241
|
+
"inspector_instances",
|
|
2242
|
+
"inspector_instance",
|
|
2243
|
+
"inspector_instance_connection",
|
|
2009
2244
|
"inspector_mcp_health",
|
|
2010
2245
|
"inspector_mcp_capabilities",
|
|
2011
2246
|
"inspector_mcp_config",
|