@tonyclaw/agent-inspector 3.1.32 → 4.0.2
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/backend/nitro.json +1 -1
- package/.output/cli.js +241 -120
- package/.output/server/_ssr/index.mjs +1 -1
- package/.output/server/_ssr/{router-oXUk3MBR.mjs → router-BBY_zWRK.mjs} +91 -3
- package/.output/server/index.mjs +1 -1
- package/.output/ui/assets/{CompareDrawer-BtfPSpkV.js → CompareDrawer-rtNElN-B.js} +1 -1
- package/.output/ui/assets/{InspectorPet-D9DPPQ3n.js → InspectorPet-QaAiuF3d.js} +1 -1
- package/.output/ui/assets/{ProxyViewerContainer-Buu8vkCK.js → ProxyViewerContainer-6twNZHwl.js} +4 -4
- package/.output/ui/assets/{ReplayDialog-BER-QzpD.js → ReplayDialog-B7KlziO2.js} +1 -1
- package/.output/ui/assets/{RequestAnatomy-C8Zwxrr7.js → RequestAnatomy-2XVFBrW4.js} +1 -1
- package/.output/ui/assets/{ResponseView-DDpKdYk6.js → ResponseView-BULgzLVB.js} +1 -1
- package/.output/ui/assets/{StreamingChunkSequence-sMPGG7Sw.js → StreamingChunkSequence-DSkvkbns.js} +1 -1
- package/.output/ui/assets/{_sessionId-e4IheHnP.js → _sessionId-D2dmJi3G.js} +1 -1
- package/.output/ui/assets/{_sessionId-C5Uv72Fx.js → _sessionId-DcS0s1Mr.js} +1 -1
- package/.output/ui/assets/{index-B__qT0Yd.js → index-B0TN1KKO.js} +2 -2
- package/.output/ui/assets/{index-Be3bTCzi.js → index-Bva1zHEs.js} +1 -1
- package/.output/ui/assets/{index-C9q__p8J.js → index-BzBExOxu.js} +1 -1
- package/.output/ui/assets/{index-CtB0deSZ.js → index-k6sRQz55.js} +1 -1
- package/.output/ui/assets/{json-viewer-Db0AFp-7.js → json-viewer-CWM4tY-j.js} +1 -1
- package/.output/ui/assets/{jszip.min-DkY0Ym_q.js → jszip.min-BkWvRFlo.js} +1 -1
- package/.output/ui/index.html +1 -1
- package/package.json +8 -13
- package/src/assets/IDE/claudecode-color.svg +0 -1
- package/src/assets/IDE/codex-color.svg +0 -1
- package/src/assets/IDE/opencode.svg +0 -1
- package/src/assets/IDE/xiaomimimo.svg +0 -1
- package/src/assets/favicon.svg +0 -21
- package/src/assets/logos/alibaba.svg +0 -1
- package/src/assets/logos/anthropic.svg +0 -1
- package/src/assets/logos/claude-code.svg +0 -4
- package/src/assets/logos/deepseek.svg +0 -1
- package/src/assets/logos/minimax.jpeg +0 -0
- package/src/assets/logos/openai.svg +0 -1
- package/src/assets/logos/opencode.svg +0 -4
- package/src/assets/logos/qwen.webp +0 -0
- package/src/assets/logos/zhipuai.svg +0 -219
- package/src/backend/router.tsx +0 -36
- package/src/backend/routes/$.ts +0 -26
- package/src/backend/routes/__root.ts +0 -4
- package/src/backend/routes/api/-instances.ts +0 -7
- package/src/backend/routes/api/alerts.summary.ts +0 -28
- package/src/backend/routes/api/alerts.ts +0 -70
- package/src/backend/routes/api/config.paths.ts +0 -14
- package/src/backend/routes/api/config.ts +0 -73
- package/src/backend/routes/api/ecosystem.packages.$packageId.help.ts +0 -11
- package/src/backend/routes/api/ecosystem.packages.$packageId.install.ts +0 -11
- package/src/backend/routes/api/ecosystem.packages.$packageId.runner-presets.ts +0 -11
- package/src/backend/routes/api/ecosystem.packages.$packageId.upgrade.ts +0 -11
- package/src/backend/routes/api/ecosystem.packages.ts +0 -21
- package/src/backend/routes/api/ecosystem.recipes.$recipeId.run.ts +0 -11
- package/src/backend/routes/api/ecosystem.tasks.$taskId.ts +0 -16
- package/src/backend/routes/api/ecosystem.tasks.ts +0 -12
- package/src/backend/routes/api/groups.$groupId.evidence.ts +0 -55
- package/src/backend/routes/api/groups.$groupId.sessions.ts +0 -50
- package/src/backend/routes/api/groups.$groupId.ts +0 -93
- package/src/backend/routes/api/groups.ts +0 -79
- package/src/backend/routes/api/health.ts +0 -22
- package/src/backend/routes/api/instances.$name.connection.ts +0 -12
- package/src/backend/routes/api/instances.$name.restart.ts +0 -23
- package/src/backend/routes/api/instances.$name.start.ts +0 -18
- package/src/backend/routes/api/instances.$name.stop.ts +0 -23
- package/src/backend/routes/api/instances.$name.ts +0 -12
- package/src/backend/routes/api/instances.ts +0 -16
- package/src/backend/routes/api/knowledge.candidates.$candidateId.promote.ts +0 -32
- package/src/backend/routes/api/knowledge.candidates.$candidateId.ts +0 -50
- package/src/backend/routes/api/knowledge.candidates.ts +0 -10
- package/src/backend/routes/api/knowledge.project-context.ts +0 -29
- package/src/backend/routes/api/knowledge.search.ts +0 -62
- package/src/backend/routes/api/knowledge.sessions.$sessionId.candidates.ts +0 -26
- package/src/backend/routes/api/logs.$id.body.ts +0 -58
- package/src/backend/routes/api/logs.$id.chunks.ts +0 -37
- package/src/backend/routes/api/logs.$id.replay.ts +0 -297
- package/src/backend/routes/api/logs.$id.ts +0 -23
- package/src/backend/routes/api/logs.import.ts +0 -39
- package/src/backend/routes/api/logs.stream.ts +0 -174
- package/src/backend/routes/api/logs.ts +0 -214
- package/src/backend/routes/api/mcp.ts +0 -25
- package/src/backend/routes/api/models.ts +0 -10
- package/src/backend/routes/api/pi-agent.ts +0 -29
- package/src/backend/routes/api/providers.$providerId.model-metadata.ts +0 -173
- package/src/backend/routes/api/providers.$providerId.test.log.ts +0 -342
- package/src/backend/routes/api/providers.$providerId.ts +0 -111
- package/src/backend/routes/api/providers.export.ts +0 -44
- package/src/backend/routes/api/providers.import.ts +0 -81
- package/src/backend/routes/api/providers.scan.ts +0 -28
- package/src/backend/routes/api/providers.ts +0 -102
- package/src/backend/routes/api/runs.$runId.evidence.ts +0 -55
- package/src/backend/routes/api/runs.$runId.ts +0 -50
- package/src/backend/routes/api/runs.ts +0 -62
- package/src/backend/routes/api/runtime.ts +0 -46
- package/src/backend/routes/api/sessions.ts +0 -51
- package/src/backend/routes/api/storage.ts +0 -56
- package/src/backend/routes/livez.ts +0 -13
- package/src/backend/routes/metrics.ts +0 -14
- package/src/backend/routes/proxy/$.ts +0 -15
- package/src/backend/routes/readyz.ts +0 -18
- package/src/backend/start.ts +0 -10
- package/src/cli/alias.ts +0 -431
- package/src/cli/detect-tools.ts +0 -123
- package/src/cli/doctor.ts +0 -836
- package/src/cli/instance.ts +0 -1071
- package/src/cli/instanceApi.ts +0 -213
- package/src/cli/instanceArgs.ts +0 -301
- package/src/cli/instanceControl.ts +0 -191
- package/src/cli/instanceModel.ts +0 -276
- package/src/cli/instanceRegistry.ts +0 -731
- package/src/cli/networkHints.ts +0 -170
- package/src/cli/onboard.ts +0 -1668
- package/src/cli/onboardTarget.ts +0 -228
- package/src/cli/rustBackendPackage.ts +0 -458
- package/src/cli/startupOutput.ts +0 -16
- package/src/cli/templates/codex-skill-onboard.ts +0 -320
- package/src/cli/templates/command-onboard.ts +0 -25
- package/src/cli/templates/skill-onboard.ts +0 -625
- package/src/cli.ts +0 -1397
- package/src/components/OnboardingBanner.tsx +0 -115
- package/src/components/ProxyViewer.tsx +0 -2259
- package/src/components/ProxyViewerContainer.tsx +0 -1076
- package/src/components/alerts/AlertsDialog.tsx +0 -615
- package/src/components/clients/ClientLogo.tsx +0 -175
- package/src/components/ecosystem/AgentLabDialog.tsx +0 -947
- package/src/components/errors/SafeErrorBoundary.tsx +0 -201
- package/src/components/groups/GroupsDialog.tsx +0 -1304
- package/src/components/inspector-pet/InspectorPet.tsx +0 -398
- package/src/components/inspector-pet/InspectorPetCrab3D.tsx +0 -455
- package/src/components/inspector-pet/inspectorPetLogic.ts +0 -272
- package/src/components/pi-agent/PiAgentPanel.tsx +0 -446
- package/src/components/pi-agent/piAgentChatLogic.ts +0 -273
- package/src/components/providers/ImportWizardDialog.tsx +0 -281
- package/src/components/providers/ProviderCard.tsx +0 -347
- package/src/components/providers/ProviderForm.tsx +0 -1183
- package/src/components/providers/ProviderLogo.tsx +0 -122
- package/src/components/providers/ProviderTestResultsView.tsx +0 -734
- package/src/components/providers/ProvidersPanel.tsx +0 -714
- package/src/components/providers/SettingsDialog.tsx +0 -1042
- package/src/components/providers/providerFormCapabilities.ts +0 -36
- package/src/components/proxy-viewer/AgentTraceSummary.tsx +0 -902
- package/src/components/proxy-viewer/AnswerMarkdown.tsx +0 -51
- package/src/components/proxy-viewer/ApplicationBar.tsx +0 -123
- package/src/components/proxy-viewer/CompareDrawer.tsx +0 -984
- package/src/components/proxy-viewer/ConversationGroup.tsx +0 -208
- package/src/components/proxy-viewer/ConversationGroupList.tsx +0 -652
- package/src/components/proxy-viewer/ConversationHeader.tsx +0 -429
- package/src/components/proxy-viewer/LiveConnectionStatus.tsx +0 -186
- package/src/components/proxy-viewer/LogEntry.tsx +0 -1419
- package/src/components/proxy-viewer/LogEntryHeader.tsx +0 -596
- package/src/components/proxy-viewer/ProviderLogoStack.tsx +0 -57
- package/src/components/proxy-viewer/RawExportWarning.tsx +0 -77
- package/src/components/proxy-viewer/ReplayDialog.tsx +0 -636
- package/src/components/proxy-viewer/RequestToolsPanel.tsx +0 -299
- package/src/components/proxy-viewer/ResponseView.tsx +0 -202
- package/src/components/proxy-viewer/SessionLoadProgressBar.tsx +0 -61
- package/src/components/proxy-viewer/StreamingChunkSequence.tsx +0 -265
- package/src/components/proxy-viewer/ThreadConnector.tsx +0 -165
- package/src/components/proxy-viewer/ToolTraceEvents.tsx +0 -64
- package/src/components/proxy-viewer/TurnGroup.tsx +0 -383
- package/src/components/proxy-viewer/TurnGroupList.tsx +0 -156
- package/src/components/proxy-viewer/accessibility.ts +0 -8
- package/src/components/proxy-viewer/anatomy/RequestAnatomy.tsx +0 -887
- package/src/components/proxy-viewer/anatomy/SegmentBar.tsx +0 -222
- package/src/components/proxy-viewer/anatomy/contextIntelligence.ts +0 -737
- package/src/components/proxy-viewer/anatomy/sessionContextSummary.ts +0 -268
- package/src/components/proxy-viewer/anatomy/tokenEstimate.ts +0 -53
- package/src/components/proxy-viewer/anatomy/types.ts +0 -41
- package/src/components/proxy-viewer/anatomy/useAnatomyJump.ts +0 -114
- package/src/components/proxy-viewer/bodyHydration.ts +0 -123
- package/src/components/proxy-viewer/cacheTrend.ts +0 -50
- package/src/components/proxy-viewer/diff/DiffView.tsx +0 -321
- package/src/components/proxy-viewer/diff/computeDiff.ts +0 -178
- package/src/components/proxy-viewer/diff/index.ts +0 -3
- package/src/components/proxy-viewer/formats/anthropic/ContentBlocks.tsx +0 -194
- package/src/components/proxy-viewer/formats/anthropic/ResponseView.tsx +0 -81
- package/src/components/proxy-viewer/formats/anthropic/thinkingExtract.ts +0 -21
- package/src/components/proxy-viewer/formats/index.tsx +0 -47
- package/src/components/proxy-viewer/formats/openai/ResponseView.tsx +0 -442
- package/src/components/proxy-viewer/index.ts +0 -9
- package/src/components/proxy-viewer/lazy.ts +0 -41
- package/src/components/proxy-viewer/liveConnectionState.ts +0 -158
- package/src/components/proxy-viewer/log-formats/anthropic.ts +0 -191
- package/src/components/proxy-viewer/log-formats/index.ts +0 -23
- package/src/components/proxy-viewer/log-formats/openai.ts +0 -256
- package/src/components/proxy-viewer/log-formats/types.ts +0 -40
- package/src/components/proxy-viewer/log-formats/unknown.ts +0 -18
- package/src/components/proxy-viewer/logEntryVisibility.ts +0 -73
- package/src/components/proxy-viewer/logFocus.ts +0 -54
- package/src/components/proxy-viewer/proxyViewerContainerLogic.ts +0 -124
- package/src/components/proxy-viewer/proxyViewerLogic.ts +0 -488
- package/src/components/proxy-viewer/replayComparison.ts +0 -131
- package/src/components/proxy-viewer/requestDiff.ts +0 -277
- package/src/components/proxy-viewer/requestTools.ts +0 -220
- package/src/components/proxy-viewer/useCopyFeedback.ts +0 -38
- package/src/components/proxy-viewer/useKeyboardNavigation.ts +0 -232
- package/src/components/proxy-viewer/viewerState.ts +0 -176
- package/src/components/ui/badge.tsx +0 -47
- package/src/components/ui/button.tsx +0 -47
- package/src/components/ui/collapsible.tsx +0 -21
- package/src/components/ui/confirm-dialog.tsx +0 -51
- package/src/components/ui/crab-logo.tsx +0 -45
- package/src/components/ui/crab-variants.tsx +0 -467
- package/src/components/ui/dialog.tsx +0 -130
- package/src/components/ui/icon-trigger.ts +0 -2
- package/src/components/ui/json-viewer-bulk.ts +0 -132
- package/src/components/ui/json-viewer.tsx +0 -508
- package/src/components/ui/scroll-area.tsx +0 -54
- package/src/components/ui/select.tsx +0 -178
- package/src/components/ui/separator.tsx +0 -28
- package/src/components/ui/tabs.tsx +0 -88
- package/src/components/ui/tooltip.tsx +0 -51
- package/src/components/ui/transient-toast.tsx +0 -105
- package/src/contracts/anthropic.ts +0 -230
- package/src/contracts/index.ts +0 -59
- package/src/contracts/json.ts +0 -37
- package/src/contracts/log.ts +0 -139
- package/src/contracts/openai.ts +0 -267
- package/src/index.css +0 -11
- package/src/knowledge/candidateStore.ts +0 -94
- package/src/knowledge/distiller.ts +0 -98
- package/src/knowledge/openclawClient.ts +0 -161
- package/src/knowledge/openclawGatewayClient.ts +0 -249
- package/src/knowledge/openclawMarkdown.ts +0 -146
- package/src/knowledge/redactor.ts +0 -80
- package/src/knowledge/types.ts +0 -83
- package/src/lib/alertContract.ts +0 -76
- package/src/lib/apiClient.ts +0 -166
- package/src/lib/apiFormat.ts +0 -29
- package/src/lib/backendImplementation.ts +0 -16
- package/src/lib/basePath.ts +0 -107
- package/src/lib/browserRuntimeContract.ts +0 -124
- package/src/lib/browserRuntimeResolver.ts +0 -333
- package/src/lib/chunkLoadRecovery.ts +0 -83
- package/src/lib/claudeCodeStrip.ts +0 -98
- package/src/lib/clipboard.ts +0 -67
- package/src/lib/codingAgentEndpoints.ts +0 -54
- package/src/lib/ecosystemContract.ts +0 -130
- package/src/lib/export-logs.ts +0 -287
- package/src/lib/groupContract.ts +0 -166
- package/src/lib/instanceContract.ts +0 -239
- package/src/lib/jsonFile.ts +0 -46
- package/src/lib/logImportContract.ts +0 -12
- package/src/lib/managedInstance.ts +0 -112
- package/src/lib/mask.ts +0 -4
- package/src/lib/objectUtils.ts +0 -22
- package/src/lib/piAgentContract.ts +0 -102
- package/src/lib/providerContract.ts +0 -125
- package/src/lib/providerImportContract.ts +0 -27
- package/src/lib/providerModelMetadata.ts +0 -458
- package/src/lib/providerTestContract.ts +0 -170
- package/src/lib/providerTestPrompt.ts +0 -100
- package/src/lib/publicBasePathContext.ts +0 -137
- package/src/lib/resourceLimits.ts +0 -345
- package/src/lib/runContract.ts +0 -164
- package/src/lib/runtimeConfig.ts +0 -43
- package/src/lib/safeDiagnostic.ts +0 -38
- package/src/lib/safeFetch.ts +0 -508
- package/src/lib/serverPort.ts +0 -47
- package/src/lib/sessionInfoContract.ts +0 -78
- package/src/lib/sessionUrl.ts +0 -46
- package/src/lib/ssrfGuard.ts +0 -133
- package/src/lib/stopReason.ts +0 -130
- package/src/lib/themeMode.ts +0 -41
- package/src/lib/timeDisplay.ts +0 -22
- package/src/lib/toolTrace.ts +0 -290
- package/src/lib/uiScale.ts +0 -117
- package/src/lib/unknown.ts +0 -27
- package/src/lib/upstreamUrl.ts +0 -150
- package/src/lib/useAlerts.ts +0 -82
- package/src/lib/useGroupEvidence.ts +0 -37
- package/src/lib/useGroups.ts +0 -32
- package/src/lib/useOnboarding.ts +0 -93
- package/src/lib/useProviders.ts +0 -30
- package/src/lib/useStripConfig.ts +0 -154
- package/src/lib/useThemeMode.ts +0 -40
- package/src/lib/useUiScale.ts +0 -52
- package/src/lib/utils.ts +0 -78
- package/src/mcp/currentContext.ts +0 -65
- package/src/mcp/instanceHandlers.ts +0 -151
- package/src/mcp/loopback.ts +0 -88
- package/src/mcp/mode.ts +0 -75
- package/src/mcp/previewExtractor.ts +0 -233
- package/src/mcp/server.ts +0 -2274
- package/src/mcp/toolHandlers.ts +0 -1533
- package/src/proxy/alerts.ts +0 -664
- package/src/proxy/chunkStorage.ts +0 -123
- package/src/proxy/config.ts +0 -218
- package/src/proxy/constants.ts +0 -66
- package/src/proxy/dataDir.ts +0 -147
- package/src/proxy/ecosystemExecutionConfirmation.ts +0 -114
- package/src/proxy/ecosystemExecutionRoute.ts +0 -116
- package/src/proxy/ecosystemRegistry.ts +0 -296
- package/src/proxy/ecosystemTasks.ts +0 -415
- package/src/proxy/evidenceAnalysis.ts +0 -526
- package/src/proxy/evidenceExporter.ts +0 -235
- package/src/proxy/formats/anthropic/anthropicProvider.ts +0 -75
- package/src/proxy/formats/anthropic/handler.ts +0 -75
- package/src/proxy/formats/anthropic/index.ts +0 -13
- package/src/proxy/formats/anthropic/register.ts +0 -4
- package/src/proxy/formats/anthropic/schemas.ts +0 -6
- package/src/proxy/formats/anthropic/stream.ts +0 -205
- package/src/proxy/formats/handler.ts +0 -46
- package/src/proxy/formats/index.ts +0 -13
- package/src/proxy/formats/jsonSchema.ts +0 -2
- package/src/proxy/formats/openai/alibabaProvider.ts +0 -34
- package/src/proxy/formats/openai/codexMetadata.ts +0 -61
- package/src/proxy/formats/openai/handler.ts +0 -133
- package/src/proxy/formats/openai/index.ts +0 -33
- package/src/proxy/formats/openai/provider.ts +0 -50
- package/src/proxy/formats/openai/register.ts +0 -4
- package/src/proxy/formats/openai/schemas.ts +0 -25
- package/src/proxy/formats/openai/stream.ts +0 -600
- package/src/proxy/formats/openai/zhipuProvider.ts +0 -31
- package/src/proxy/formats/providerAdapter.ts +0 -50
- package/src/proxy/formats/providerRegistry.ts +0 -51
- package/src/proxy/formats/providers/index.ts +0 -3
- package/src/proxy/formats/registry.ts +0 -65
- package/src/proxy/groupEvidenceExporter.ts +0 -371
- package/src/proxy/groupStore.ts +0 -336
- package/src/proxy/handler.ts +0 -729
- package/src/proxy/identityProxy.ts +0 -1842
- package/src/proxy/jsonlRecovery.ts +0 -554
- package/src/proxy/logBodyChunks.ts +0 -91
- package/src/proxy/logFinalizer.ts +0 -777
- package/src/proxy/logFinalizer.worker.ts +0 -24
- package/src/proxy/logImportUpload.ts +0 -128
- package/src/proxy/logImporter.ts +0 -813
- package/src/proxy/logIndex.ts +0 -663
- package/src/proxy/logSearch.ts +0 -122
- package/src/proxy/logger.ts +0 -537
- package/src/proxy/openaiOrphanToolStrip.ts +0 -142
- package/src/proxy/platformCommands.ts +0 -253
- package/src/proxy/privateDataPath.ts +0 -419
- package/src/proxy/providerImporters.ts +0 -578
- package/src/proxy/providerScanStore.ts +0 -87
- package/src/proxy/providerSecretStore.ts +0 -216
- package/src/proxy/providers.ts +0 -998
- package/src/proxy/rawStreamCapture.ts +0 -342
- package/src/proxy/runFailures.ts +0 -94
- package/src/proxy/runStore.ts +0 -214
- package/src/proxy/runtimeAdmission.ts +0 -55
- package/src/proxy/runtimeHealth.ts +0 -221
- package/src/proxy/runtimeMetrics.ts +0 -149
- package/src/proxy/runtimeShutdown.ts +0 -157
- package/src/proxy/schemas.ts +0 -112
- package/src/proxy/sessionArchive.ts +0 -479
- package/src/proxy/sessionInfo.ts +0 -266
- package/src/proxy/sessionProcess.ts +0 -194
- package/src/proxy/sessionRuntime.ts +0 -121
- package/src/proxy/sessionSupervisor.ts +0 -305
- package/src/proxy/sessionWorkerEntry.ts +0 -26
- package/src/proxy/shutdownCoordinator.ts +0 -90
- package/src/proxy/socketTracker.ts +0 -639
- package/src/proxy/sqliteLogIndex.ts +0 -733
- package/src/proxy/storageLifecycle.ts +0 -432
- package/src/proxy/store.ts +0 -1773
- package/src/proxy/streamTiming.ts +0 -31
- package/src/proxy/toolSchemaWarnings.ts +0 -529
- package/src/proxy/uiAssetServer.ts +0 -106
- package/src/proxy/upstream.ts +0 -127
- package/src/services/alerts.ts +0 -12
- package/src/services/groups.ts +0 -119
- package/src/services/piAgent.ts +0 -421
- package/src/services/piAgentRetrieval.ts +0 -1180
- package/src/services/result.ts +0 -17
- package/src/services/runs.ts +0 -76
- package/src/ui/bootstrap.ts +0 -167
- package/src/ui/index.html +0 -38
- package/src/ui/logsStreamClient.ts +0 -20
- package/src/ui/main.tsx +0 -13
- package/src/ui/public/runtime-config.js +0 -2
- package/src/ui/router.tsx +0 -13
- package/src/ui/routes/__root.tsx +0 -69
- package/src/ui/routes/index.tsx +0 -35
- package/src/ui/routes/session/$sessionId.tsx +0 -50
- package/src/ui/runtimeDiscovery.ts +0 -50
package/src/cli/onboardTarget.ts
DELETED
|
@@ -1,228 +0,0 @@
|
|
|
1
|
-
import { appendBasePathToOrigin, getConfiguredBasePath } from "../lib/basePath.js";
|
|
2
|
-
import { normalizeBrowserRuntimeBaseUrl } from "../lib/browserRuntimeContract.js";
|
|
3
|
-
import { getInstancesRoot, readInstanceRecord, validateInstanceName } from "./instanceRegistry.js";
|
|
4
|
-
import { urlForHost } from "./networkHints.js";
|
|
5
|
-
|
|
6
|
-
const DEFAULT_PORT = 9527;
|
|
7
|
-
const DEFAULT_ORIGIN = `http://localhost:${String(DEFAULT_PORT)}`;
|
|
8
|
-
const AGENT_INSPECTOR_PUBLIC_ORIGIN_ENV = "AGENT_INSPECTOR_PUBLIC_ORIGIN";
|
|
9
|
-
const MCP_NAME_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/u;
|
|
10
|
-
|
|
11
|
-
type OnboardTargetEnv = Readonly<Record<string, string | undefined>>;
|
|
12
|
-
|
|
13
|
-
export type OnboardTargetKind = "default" | "instance" | "base-url";
|
|
14
|
-
|
|
15
|
-
export type OnboardTarget = {
|
|
16
|
-
kind: OnboardTargetKind;
|
|
17
|
-
instanceName: string | null;
|
|
18
|
-
mcpName: string;
|
|
19
|
-
port: number;
|
|
20
|
-
uiUrl: string | null;
|
|
21
|
-
controlBaseUrl: string;
|
|
22
|
-
agentBaseUrl: string;
|
|
23
|
-
/** @deprecated Compatibility alias for controlBaseUrl. */
|
|
24
|
-
baseUrl: string;
|
|
25
|
-
apiUrl: string;
|
|
26
|
-
healthUrl: string;
|
|
27
|
-
anthropicProxyUrl: string;
|
|
28
|
-
openAiProxyUrl: string;
|
|
29
|
-
mcpUrl: string;
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
export type OnboardTargetOptions = {
|
|
33
|
-
instanceName: string | null;
|
|
34
|
-
baseUrl: string | null;
|
|
35
|
-
controlBaseUrl?: string | null;
|
|
36
|
-
agentBaseUrl?: string | null;
|
|
37
|
-
uiUrl?: string | null;
|
|
38
|
-
mcpName: string | null;
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
export type OnboardTargetResult =
|
|
42
|
-
| { ok: true; target: OnboardTarget }
|
|
43
|
-
| { ok: false; message: string };
|
|
44
|
-
|
|
45
|
-
function targetFromSurfaces(
|
|
46
|
-
kind: OnboardTargetKind,
|
|
47
|
-
instanceName: string | null,
|
|
48
|
-
mcpName: string,
|
|
49
|
-
port: number,
|
|
50
|
-
controlBaseUrl: string,
|
|
51
|
-
agentBaseUrl: string,
|
|
52
|
-
uiUrl: string | null,
|
|
53
|
-
): OnboardTarget {
|
|
54
|
-
return {
|
|
55
|
-
kind,
|
|
56
|
-
instanceName,
|
|
57
|
-
mcpName,
|
|
58
|
-
port,
|
|
59
|
-
uiUrl,
|
|
60
|
-
controlBaseUrl,
|
|
61
|
-
agentBaseUrl,
|
|
62
|
-
baseUrl: controlBaseUrl,
|
|
63
|
-
apiUrl: `${controlBaseUrl}/api`,
|
|
64
|
-
healthUrl: `${controlBaseUrl}/api/health`,
|
|
65
|
-
anthropicProxyUrl: `${agentBaseUrl}/proxy`,
|
|
66
|
-
openAiProxyUrl: `${agentBaseUrl}/proxy/v1`,
|
|
67
|
-
mcpUrl: `${agentBaseUrl}/api/mcp`,
|
|
68
|
-
};
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
function validateMcpName(rawName: string): string | null {
|
|
72
|
-
const name = rawName.trim();
|
|
73
|
-
return name === rawName && MCP_NAME_PATTERN.test(name) ? name : null;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
function normalizeExplicitBaseUrl(rawBaseUrl: string): { baseUrl: string; port: number } | null {
|
|
77
|
-
const baseUrl = normalizeBrowserRuntimeBaseUrl(rawBaseUrl);
|
|
78
|
-
if (baseUrl === null) return null;
|
|
79
|
-
try {
|
|
80
|
-
const parsed = new URL(baseUrl);
|
|
81
|
-
const defaultPort = parsed.protocol === "https:" ? 443 : 80;
|
|
82
|
-
const port = parsed.port === "" ? defaultPort : Number(parsed.port);
|
|
83
|
-
return Number.isInteger(port) && port >= 1 && port <= 65_535 ? { baseUrl, port } : null;
|
|
84
|
-
} catch {
|
|
85
|
-
return null;
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
function normalizePublicOrigin(rawOrigin: string): string | null {
|
|
90
|
-
if (rawOrigin.trim() !== rawOrigin) return null;
|
|
91
|
-
try {
|
|
92
|
-
const parsed = new URL(rawOrigin);
|
|
93
|
-
if (
|
|
94
|
-
(parsed.protocol !== "http:" && parsed.protocol !== "https:") ||
|
|
95
|
-
parsed.username.length > 0 ||
|
|
96
|
-
parsed.password.length > 0 ||
|
|
97
|
-
parsed.pathname !== "/" ||
|
|
98
|
-
parsed.search.length > 0 ||
|
|
99
|
-
parsed.hash.length > 0
|
|
100
|
-
) {
|
|
101
|
-
return null;
|
|
102
|
-
}
|
|
103
|
-
return parsed.origin;
|
|
104
|
-
} catch {
|
|
105
|
-
return null;
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
export function resolveOnboardTarget(
|
|
110
|
-
options: OnboardTargetOptions,
|
|
111
|
-
env: OnboardTargetEnv = process.env,
|
|
112
|
-
): OnboardTargetResult {
|
|
113
|
-
const hasExplicitSurface =
|
|
114
|
-
options.baseUrl !== null ||
|
|
115
|
-
(options.controlBaseUrl !== null && options.controlBaseUrl !== undefined) ||
|
|
116
|
-
(options.agentBaseUrl !== null && options.agentBaseUrl !== undefined) ||
|
|
117
|
-
options.uiUrl !== undefined;
|
|
118
|
-
if (options.instanceName !== null && hasExplicitSurface) {
|
|
119
|
-
return {
|
|
120
|
-
ok: false,
|
|
121
|
-
message:
|
|
122
|
-
"--instance and explicit --base-url/--control-base-url/--agent-base-url/--ui-url options are mutually exclusive",
|
|
123
|
-
};
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
const explicitMcpName = options.mcpName === null ? null : validateMcpName(options.mcpName);
|
|
127
|
-
if (options.mcpName !== null && explicitMcpName === null) {
|
|
128
|
-
return {
|
|
129
|
-
ok: false,
|
|
130
|
-
message:
|
|
131
|
-
"--mcp-name must be 1-128 letters, digits, dots, hyphens, or underscores and start with a letter or digit",
|
|
132
|
-
};
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
if (hasExplicitSurface) {
|
|
136
|
-
const sharedRaw = options.baseUrl;
|
|
137
|
-
const controlRaw = options.controlBaseUrl ?? sharedRaw ?? options.agentBaseUrl;
|
|
138
|
-
const agentRaw = options.agentBaseUrl ?? sharedRaw ?? options.controlBaseUrl;
|
|
139
|
-
const control =
|
|
140
|
-
controlRaw === null || controlRaw === undefined ? null : normalizeExplicitBaseUrl(controlRaw);
|
|
141
|
-
const agent =
|
|
142
|
-
agentRaw === null || agentRaw === undefined ? null : normalizeExplicitBaseUrl(agentRaw);
|
|
143
|
-
const ui =
|
|
144
|
-
options.uiUrl === undefined || options.uiUrl === null
|
|
145
|
-
? null
|
|
146
|
-
: normalizeExplicitBaseUrl(options.uiUrl);
|
|
147
|
-
if (
|
|
148
|
-
control === null ||
|
|
149
|
-
agent === null ||
|
|
150
|
-
(options.uiUrl !== undefined && options.uiUrl !== null && ui === null)
|
|
151
|
-
) {
|
|
152
|
-
return {
|
|
153
|
-
ok: false,
|
|
154
|
-
message:
|
|
155
|
-
"Explicit UI, control, and agent Base URLs must be credential-free HTTP(S) URLs without a query or fragment",
|
|
156
|
-
};
|
|
157
|
-
}
|
|
158
|
-
return {
|
|
159
|
-
ok: true,
|
|
160
|
-
target: targetFromSurfaces(
|
|
161
|
-
"base-url",
|
|
162
|
-
null,
|
|
163
|
-
explicitMcpName ?? "agent-inspector",
|
|
164
|
-
control.port,
|
|
165
|
-
control.baseUrl,
|
|
166
|
-
agent.baseUrl,
|
|
167
|
-
ui?.baseUrl ?? null,
|
|
168
|
-
),
|
|
169
|
-
};
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
if (options.instanceName !== null) {
|
|
173
|
-
const validatedName = validateInstanceName(options.instanceName);
|
|
174
|
-
if (validatedName.kind === "error") {
|
|
175
|
-
return { ok: false, message: validatedName.error.message };
|
|
176
|
-
}
|
|
177
|
-
const record = readInstanceRecord(getInstancesRoot(env), validatedName.value);
|
|
178
|
-
if (record.kind === "error") {
|
|
179
|
-
return { ok: false, message: record.error.message };
|
|
180
|
-
}
|
|
181
|
-
if (record.value === null) {
|
|
182
|
-
return {
|
|
183
|
-
ok: false,
|
|
184
|
-
message: `Named instance ${validatedName.value} does not exist`,
|
|
185
|
-
};
|
|
186
|
-
}
|
|
187
|
-
const origin = urlForHost(record.value.publicPort, record.value.host);
|
|
188
|
-
const baseUrl = appendBasePathToOrigin(origin, "/", record.value.basePath);
|
|
189
|
-
return {
|
|
190
|
-
ok: true,
|
|
191
|
-
target: targetFromSurfaces(
|
|
192
|
-
"instance",
|
|
193
|
-
record.value.name,
|
|
194
|
-
explicitMcpName ?? `agent-inspector-${record.value.name}`,
|
|
195
|
-
record.value.publicPort,
|
|
196
|
-
baseUrl,
|
|
197
|
-
baseUrl,
|
|
198
|
-
record.value.uiEnabled ? baseUrl : null,
|
|
199
|
-
),
|
|
200
|
-
};
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
const configuredPublicOrigin = env[AGENT_INSPECTOR_PUBLIC_ORIGIN_ENV];
|
|
204
|
-
const publicOrigin =
|
|
205
|
-
configuredPublicOrigin === undefined
|
|
206
|
-
? DEFAULT_ORIGIN
|
|
207
|
-
: normalizePublicOrigin(configuredPublicOrigin);
|
|
208
|
-
if (publicOrigin === null) {
|
|
209
|
-
return {
|
|
210
|
-
ok: false,
|
|
211
|
-
message:
|
|
212
|
-
"AGENT_INSPECTOR_PUBLIC_ORIGIN must be an exact credential-free HTTP(S) origin without a path, query, or fragment",
|
|
213
|
-
};
|
|
214
|
-
}
|
|
215
|
-
const baseUrl = appendBasePathToOrigin(publicOrigin, "/", getConfiguredBasePath(env));
|
|
216
|
-
return {
|
|
217
|
-
ok: true,
|
|
218
|
-
target: targetFromSurfaces(
|
|
219
|
-
"default",
|
|
220
|
-
null,
|
|
221
|
-
explicitMcpName ?? "agent-inspector",
|
|
222
|
-
DEFAULT_PORT,
|
|
223
|
-
baseUrl,
|
|
224
|
-
baseUrl,
|
|
225
|
-
env["AGENT_INSPECTOR_BACKEND_ONLY"] === "1" ? null : baseUrl,
|
|
226
|
-
),
|
|
227
|
-
};
|
|
228
|
-
}
|
|
@@ -1,458 +0,0 @@
|
|
|
1
|
-
import { spawnSync } from "node:child_process";
|
|
2
|
-
import { Buffer } from "node:buffer";
|
|
3
|
-
import { createHash } from "node:crypto";
|
|
4
|
-
import { existsSync, readFileSync, statSync } from "node:fs";
|
|
5
|
-
import { createRequire } from "node:module";
|
|
6
|
-
import { dirname, isAbsolute, relative, resolve } from "node:path";
|
|
7
|
-
import { fileURLToPath } from "node:url";
|
|
8
|
-
import { z } from "zod";
|
|
9
|
-
|
|
10
|
-
export const RUST_BACKEND_IDENTITY_FLAG = "--agent-inspector-package-identity";
|
|
11
|
-
export const RUST_BACKEND_CLI_PROTOCOL = "agent-inspector-cli-backend-v1";
|
|
12
|
-
export const RUST_BACKEND_IDENTITY_TIMEOUT_MS = 2_000;
|
|
13
|
-
|
|
14
|
-
export type RustBackendLibc = "glibc" | "musl" | "unknown" | "not-applicable";
|
|
15
|
-
|
|
16
|
-
export type RustBackendTarget = {
|
|
17
|
-
packageName: string;
|
|
18
|
-
target: string;
|
|
19
|
-
binary: string;
|
|
20
|
-
os: "win32" | "linux" | "darwin";
|
|
21
|
-
cpu: "x64" | "arm64";
|
|
22
|
-
libc: "glibc" | null;
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
export type RustBackendPackageErrorCode =
|
|
26
|
-
| "binary_invalid"
|
|
27
|
-
| "binary_missing"
|
|
28
|
-
| "hash_mismatch"
|
|
29
|
-
| "identity_failed"
|
|
30
|
-
| "identity_mismatch"
|
|
31
|
-
| "manifest_invalid"
|
|
32
|
-
| "package_invalid"
|
|
33
|
-
| "package_missing"
|
|
34
|
-
| "target_mismatch"
|
|
35
|
-
| "unsupported_platform"
|
|
36
|
-
| "version_mismatch";
|
|
37
|
-
|
|
38
|
-
export type RustBackendPackageError = {
|
|
39
|
-
code: RustBackendPackageErrorCode;
|
|
40
|
-
message: string;
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
export type RustBackendPackageResolution =
|
|
44
|
-
| {
|
|
45
|
-
kind: "success";
|
|
46
|
-
value: {
|
|
47
|
-
command: string;
|
|
48
|
-
args: readonly string[];
|
|
49
|
-
packageName: string;
|
|
50
|
-
packageVersion: string;
|
|
51
|
-
target: string;
|
|
52
|
-
sha256: string;
|
|
53
|
-
};
|
|
54
|
-
}
|
|
55
|
-
| { kind: "error"; error: RustBackendPackageError };
|
|
56
|
-
|
|
57
|
-
export type RustBackendTargetResolution =
|
|
58
|
-
| { kind: "success"; value: RustBackendTarget }
|
|
59
|
-
| { kind: "error"; error: RustBackendPackageError };
|
|
60
|
-
|
|
61
|
-
export type PreferredBackendImplementation = "typescript" | "rust";
|
|
62
|
-
|
|
63
|
-
const RustBackendIdentitySchema = z
|
|
64
|
-
.object({
|
|
65
|
-
schemaVersion: z.literal(1),
|
|
66
|
-
name: z.literal("agent-inspector-backend"),
|
|
67
|
-
packageVersion: z.string().min(1),
|
|
68
|
-
target: z.string().min(1),
|
|
69
|
-
binary: z.string().min(1),
|
|
70
|
-
cliProtocol: z.literal(RUST_BACKEND_CLI_PROTOCOL),
|
|
71
|
-
productionReady: z.literal(true),
|
|
72
|
-
capabilities: z
|
|
73
|
-
.object({
|
|
74
|
-
nodeProtectedIngress: z.literal(true),
|
|
75
|
-
basePath: z.literal(true),
|
|
76
|
-
namedInstances: z.literal(true),
|
|
77
|
-
gracefulShutdown: z.literal(true),
|
|
78
|
-
})
|
|
79
|
-
.strict(),
|
|
80
|
-
})
|
|
81
|
-
.strict();
|
|
82
|
-
|
|
83
|
-
export type RustBackendIdentity = z.infer<typeof RustBackendIdentitySchema>;
|
|
84
|
-
|
|
85
|
-
const RustBackendPackageJsonSchema = z
|
|
86
|
-
.object({
|
|
87
|
-
name: z.string().min(1),
|
|
88
|
-
version: z.string().min(1),
|
|
89
|
-
os: z.array(z.string()).min(1),
|
|
90
|
-
cpu: z.array(z.string()).min(1),
|
|
91
|
-
libc: z.array(z.string()).optional(),
|
|
92
|
-
agentInspectorRustBackend: z
|
|
93
|
-
.object({
|
|
94
|
-
schemaVersion: z.literal(1),
|
|
95
|
-
target: z.string().min(1),
|
|
96
|
-
binary: z.string().min(1),
|
|
97
|
-
manifest: z.string().min(1),
|
|
98
|
-
identityFlag: z.literal(RUST_BACKEND_IDENTITY_FLAG),
|
|
99
|
-
cliProtocol: z.literal(RUST_BACKEND_CLI_PROTOCOL),
|
|
100
|
-
})
|
|
101
|
-
.strict(),
|
|
102
|
-
})
|
|
103
|
-
.passthrough();
|
|
104
|
-
|
|
105
|
-
const RustBackendBinaryManifestSchema = z
|
|
106
|
-
.object({
|
|
107
|
-
schemaVersion: z.literal(1),
|
|
108
|
-
packageName: z.string().min(1),
|
|
109
|
-
packageVersion: z.string().min(1),
|
|
110
|
-
target: z.string().min(1),
|
|
111
|
-
binary: z.string().min(1),
|
|
112
|
-
sha256: z.string().regex(/^[a-f0-9]{64}$/u),
|
|
113
|
-
identity: RustBackendIdentitySchema,
|
|
114
|
-
})
|
|
115
|
-
.strict();
|
|
116
|
-
|
|
117
|
-
type IdentityProbeResult =
|
|
118
|
-
| { kind: "success"; value: RustBackendIdentity }
|
|
119
|
-
| { kind: "error"; message: string };
|
|
120
|
-
|
|
121
|
-
export type ResolveRustBackendPackageOptions = {
|
|
122
|
-
rootVersion: string;
|
|
123
|
-
platform?: string;
|
|
124
|
-
arch?: string;
|
|
125
|
-
libc?: RustBackendLibc;
|
|
126
|
-
resolvePackageJson?: (specifier: string) => string;
|
|
127
|
-
identityProbe?: (binaryPath: string, identityFlag: string) => IdentityProbeResult;
|
|
128
|
-
};
|
|
129
|
-
|
|
130
|
-
function packageFailure(
|
|
131
|
-
code: RustBackendPackageErrorCode,
|
|
132
|
-
message: string,
|
|
133
|
-
): RustBackendPackageResolution {
|
|
134
|
-
return { kind: "error", error: { code, message } };
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
function targetFailure(message: string): RustBackendTargetResolution {
|
|
138
|
-
return { kind: "error", error: { code: "unsupported_platform", message } };
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
function detectLinuxLibc(): RustBackendLibc {
|
|
142
|
-
if (process.platform !== "linux") return "not-applicable";
|
|
143
|
-
const report = process.report.getReport();
|
|
144
|
-
const header = objectProperty(report, "header");
|
|
145
|
-
const glibcVersion = objectProperty(header, "glibcVersionRuntime");
|
|
146
|
-
if (typeof glibcVersion === "string" && glibcVersion.length > 0) {
|
|
147
|
-
return "glibc";
|
|
148
|
-
}
|
|
149
|
-
const sharedObjects = objectProperty(report, "sharedObjects");
|
|
150
|
-
return Array.isArray(sharedObjects) &&
|
|
151
|
-
sharedObjects.some((path) => typeof path === "string" && path.toLowerCase().includes("musl"))
|
|
152
|
-
? "musl"
|
|
153
|
-
: "unknown";
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
function objectProperty(value: unknown, name: string): unknown {
|
|
157
|
-
if (typeof value !== "object" || value === null || Array.isArray(value)) return undefined;
|
|
158
|
-
return Object.getOwnPropertyDescriptor(value, name)?.value;
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
export function resolveRustBackendTarget(
|
|
162
|
-
platform: string = process.platform,
|
|
163
|
-
arch: string = process.arch,
|
|
164
|
-
libc: RustBackendLibc = platform === "linux" ? detectLinuxLibc() : "not-applicable",
|
|
165
|
-
): RustBackendTargetResolution {
|
|
166
|
-
switch (platform) {
|
|
167
|
-
case "win32":
|
|
168
|
-
return arch === "x64"
|
|
169
|
-
? {
|
|
170
|
-
kind: "success",
|
|
171
|
-
value: {
|
|
172
|
-
packageName: "@tonyclaw/agent-inspector-backend-win32-x64-msvc",
|
|
173
|
-
target: "x86_64-pc-windows-msvc",
|
|
174
|
-
binary: "bin/agent-inspector-backend.exe",
|
|
175
|
-
os: "win32",
|
|
176
|
-
cpu: "x64",
|
|
177
|
-
libc: null,
|
|
178
|
-
},
|
|
179
|
-
}
|
|
180
|
-
: targetFailure(`Rust backend packages do not support Windows ${arch}.`);
|
|
181
|
-
case "linux":
|
|
182
|
-
if (arch !== "x64")
|
|
183
|
-
return targetFailure(`Rust backend packages do not support Linux ${arch}.`);
|
|
184
|
-
if (libc !== "glibc") {
|
|
185
|
-
return targetFailure(
|
|
186
|
-
`The Linux Rust backend package requires glibc; detected ${libc}. No binary was started.`,
|
|
187
|
-
);
|
|
188
|
-
}
|
|
189
|
-
return {
|
|
190
|
-
kind: "success",
|
|
191
|
-
value: {
|
|
192
|
-
packageName: "@tonyclaw/agent-inspector-backend-linux-x64-gnu",
|
|
193
|
-
target: "x86_64-unknown-linux-gnu",
|
|
194
|
-
binary: "bin/agent-inspector-backend",
|
|
195
|
-
os: "linux",
|
|
196
|
-
cpu: "x64",
|
|
197
|
-
libc: "glibc",
|
|
198
|
-
},
|
|
199
|
-
};
|
|
200
|
-
case "darwin":
|
|
201
|
-
return arch === "arm64"
|
|
202
|
-
? {
|
|
203
|
-
kind: "success",
|
|
204
|
-
value: {
|
|
205
|
-
packageName: "@tonyclaw/agent-inspector-backend-darwin-arm64",
|
|
206
|
-
target: "aarch64-apple-darwin",
|
|
207
|
-
binary: "bin/agent-inspector-backend",
|
|
208
|
-
os: "darwin",
|
|
209
|
-
cpu: "arm64",
|
|
210
|
-
libc: null,
|
|
211
|
-
},
|
|
212
|
-
}
|
|
213
|
-
: targetFailure(`Rust backend packages do not support macOS ${arch}.`);
|
|
214
|
-
default:
|
|
215
|
-
return targetFailure(`Rust backend packages do not support ${platform} ${arch}.`);
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
function readJson(path: string): { kind: "success"; value: unknown } | { kind: "error" } {
|
|
220
|
-
try {
|
|
221
|
-
const value: unknown = JSON.parse(readFileSync(path, "utf8"));
|
|
222
|
-
return { kind: "success", value };
|
|
223
|
-
} catch {
|
|
224
|
-
return { kind: "error" };
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
function isConfinedPath(root: string, candidate: string): boolean {
|
|
229
|
-
const child = relative(root, candidate);
|
|
230
|
-
return child.length > 0 && !child.startsWith("..") && !isAbsolute(child);
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
function identitiesMatch(left: RustBackendIdentity, right: RustBackendIdentity): boolean {
|
|
234
|
-
return (
|
|
235
|
-
left.schemaVersion === right.schemaVersion &&
|
|
236
|
-
left.name === right.name &&
|
|
237
|
-
left.packageVersion === right.packageVersion &&
|
|
238
|
-
left.target === right.target &&
|
|
239
|
-
left.binary === right.binary &&
|
|
240
|
-
left.cliProtocol === right.cliProtocol &&
|
|
241
|
-
left.productionReady === right.productionReady &&
|
|
242
|
-
left.capabilities.nodeProtectedIngress === right.capabilities.nodeProtectedIngress &&
|
|
243
|
-
left.capabilities.basePath === right.capabilities.basePath &&
|
|
244
|
-
left.capabilities.namedInstances === right.capabilities.namedInstances &&
|
|
245
|
-
left.capabilities.gracefulShutdown === right.capabilities.gracefulShutdown
|
|
246
|
-
);
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
function probeBinaryIdentity(binaryPath: string, identityFlag: string): IdentityProbeResult {
|
|
250
|
-
const result = spawnSync(binaryPath, [identityFlag], {
|
|
251
|
-
encoding: "utf8",
|
|
252
|
-
windowsHide: true,
|
|
253
|
-
timeout: RUST_BACKEND_IDENTITY_TIMEOUT_MS,
|
|
254
|
-
maxBuffer: 64 * 1024,
|
|
255
|
-
});
|
|
256
|
-
if (result.error !== undefined) {
|
|
257
|
-
return { kind: "error", message: result.error.message };
|
|
258
|
-
}
|
|
259
|
-
if (result.status !== 0) {
|
|
260
|
-
return {
|
|
261
|
-
kind: "error",
|
|
262
|
-
message: `identity command exited with status ${String(result.status)}`,
|
|
263
|
-
};
|
|
264
|
-
}
|
|
265
|
-
let raw: unknown;
|
|
266
|
-
try {
|
|
267
|
-
raw = JSON.parse(result.stdout);
|
|
268
|
-
} catch {
|
|
269
|
-
return { kind: "error", message: "identity command did not return JSON" };
|
|
270
|
-
}
|
|
271
|
-
const parsed = RustBackendIdentitySchema.safeParse(raw);
|
|
272
|
-
return parsed.success
|
|
273
|
-
? { kind: "success", value: parsed.data }
|
|
274
|
-
: { kind: "error", message: "identity command returned an unsupported contract" };
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
const packageRequire = createRequire(import.meta.url);
|
|
278
|
-
|
|
279
|
-
function defaultResolvePackageJson(specifier: string): string {
|
|
280
|
-
try {
|
|
281
|
-
return packageRequire.resolve(specifier);
|
|
282
|
-
} catch {
|
|
283
|
-
const suffix = "/package.json";
|
|
284
|
-
const packageName = specifier.endsWith(suffix) ? specifier.slice(0, -suffix.length) : "";
|
|
285
|
-
const directoryName = packageName.split("/").at(-1);
|
|
286
|
-
if (directoryName !== undefined && directoryName.length > 0) {
|
|
287
|
-
const localPackageJson = resolve(
|
|
288
|
-
dirname(fileURLToPath(import.meta.url)),
|
|
289
|
-
"../packages",
|
|
290
|
-
directoryName,
|
|
291
|
-
"package.json",
|
|
292
|
-
);
|
|
293
|
-
if (existsSync(localPackageJson)) return localPackageJson;
|
|
294
|
-
}
|
|
295
|
-
return packageRequire.resolve(specifier);
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
export function resolveRustBackendPackage(
|
|
300
|
-
options: ResolveRustBackendPackageOptions,
|
|
301
|
-
): RustBackendPackageResolution {
|
|
302
|
-
const target = resolveRustBackendTarget(options.platform, options.arch, options.libc);
|
|
303
|
-
if (target.kind === "error") return { kind: "error", error: target.error };
|
|
304
|
-
|
|
305
|
-
const packageJsonSpecifier = `${target.value.packageName}/package.json`;
|
|
306
|
-
let packageJsonPath: string;
|
|
307
|
-
try {
|
|
308
|
-
packageJsonPath = (options.resolvePackageJson ?? defaultResolvePackageJson)(
|
|
309
|
-
packageJsonSpecifier,
|
|
310
|
-
);
|
|
311
|
-
} catch {
|
|
312
|
-
return packageFailure(
|
|
313
|
-
"package_missing",
|
|
314
|
-
`Rust backend ${target.value.target} was requested, but optional package ${target.value.packageName}@${options.rootVersion} is not installed. Reinstall without omitting optional dependencies; no TypeScript fallback was used.`,
|
|
315
|
-
);
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
const rawPackage = readJson(packageJsonPath);
|
|
319
|
-
if (rawPackage.kind === "error") {
|
|
320
|
-
return packageFailure("package_invalid", `Cannot read ${packageJsonSpecifier}.`);
|
|
321
|
-
}
|
|
322
|
-
const packageJson = RustBackendPackageJsonSchema.safeParse(rawPackage.value);
|
|
323
|
-
if (!packageJson.success) {
|
|
324
|
-
return packageFailure(
|
|
325
|
-
"package_invalid",
|
|
326
|
-
`Package ${target.value.packageName} does not contain the Rust backend package contract.`,
|
|
327
|
-
);
|
|
328
|
-
}
|
|
329
|
-
if (
|
|
330
|
-
packageJson.data.name !== target.value.packageName ||
|
|
331
|
-
packageJson.data.version !== options.rootVersion
|
|
332
|
-
) {
|
|
333
|
-
return packageFailure(
|
|
334
|
-
"version_mismatch",
|
|
335
|
-
`Rust backend package must exactly match @tonyclaw/agent-inspector@${options.rootVersion}; found ${packageJson.data.name}@${packageJson.data.version}.`,
|
|
336
|
-
);
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
const metadata = packageJson.data.agentInspectorRustBackend;
|
|
340
|
-
const expectedLibc = target.value.libc === null ? undefined : [target.value.libc];
|
|
341
|
-
if (
|
|
342
|
-
metadata.target !== target.value.target ||
|
|
343
|
-
metadata.binary !== target.value.binary ||
|
|
344
|
-
metadata.manifest !== "binary-manifest.json" ||
|
|
345
|
-
packageJson.data.os.length !== 1 ||
|
|
346
|
-
packageJson.data.os[0] !== target.value.os ||
|
|
347
|
-
packageJson.data.cpu.length !== 1 ||
|
|
348
|
-
packageJson.data.cpu[0] !== target.value.cpu ||
|
|
349
|
-
JSON.stringify(packageJson.data.libc) !== JSON.stringify(expectedLibc)
|
|
350
|
-
) {
|
|
351
|
-
return packageFailure(
|
|
352
|
-
"target_mismatch",
|
|
353
|
-
`Package ${target.value.packageName} does not match target ${target.value.target}.`,
|
|
354
|
-
);
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
const packageRoot = dirname(packageJsonPath);
|
|
358
|
-
const manifestPath = resolve(packageRoot, metadata.manifest);
|
|
359
|
-
const binaryPath = resolve(packageRoot, metadata.binary);
|
|
360
|
-
if (!isConfinedPath(packageRoot, manifestPath) || !isConfinedPath(packageRoot, binaryPath)) {
|
|
361
|
-
return packageFailure(
|
|
362
|
-
"package_invalid",
|
|
363
|
-
`Package ${target.value.packageName} contains an unsafe artifact path.`,
|
|
364
|
-
);
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
const rawManifest = readJson(manifestPath);
|
|
368
|
-
if (rawManifest.kind === "error") {
|
|
369
|
-
return packageFailure(
|
|
370
|
-
"manifest_invalid",
|
|
371
|
-
`Rust backend package ${target.value.packageName} is incomplete: binary-manifest.json is missing or invalid.`,
|
|
372
|
-
);
|
|
373
|
-
}
|
|
374
|
-
const manifest = RustBackendBinaryManifestSchema.safeParse(rawManifest.value);
|
|
375
|
-
if (!manifest.success) {
|
|
376
|
-
return packageFailure(
|
|
377
|
-
"manifest_invalid",
|
|
378
|
-
`Rust backend package ${target.value.packageName} has an invalid target manifest.`,
|
|
379
|
-
);
|
|
380
|
-
}
|
|
381
|
-
if (
|
|
382
|
-
manifest.data.packageName !== target.value.packageName ||
|
|
383
|
-
manifest.data.packageVersion !== options.rootVersion ||
|
|
384
|
-
manifest.data.identity.packageVersion !== options.rootVersion
|
|
385
|
-
) {
|
|
386
|
-
return packageFailure(
|
|
387
|
-
"version_mismatch",
|
|
388
|
-
`Rust backend manifest must exactly match @tonyclaw/agent-inspector@${options.rootVersion}.`,
|
|
389
|
-
);
|
|
390
|
-
}
|
|
391
|
-
if (
|
|
392
|
-
manifest.data.target !== target.value.target ||
|
|
393
|
-
manifest.data.binary !== target.value.binary ||
|
|
394
|
-
manifest.data.identity.target !== target.value.target ||
|
|
395
|
-
manifest.data.identity.binary !== target.value.binary
|
|
396
|
-
) {
|
|
397
|
-
return packageFailure(
|
|
398
|
-
"target_mismatch",
|
|
399
|
-
`Rust backend manifest identity does not match target ${target.value.target}.`,
|
|
400
|
-
);
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
let binaryBytes: Buffer;
|
|
404
|
-
try {
|
|
405
|
-
const stats = statSync(binaryPath);
|
|
406
|
-
if (!stats.isFile()) {
|
|
407
|
-
return packageFailure("binary_invalid", `Rust backend artifact is not a regular file.`);
|
|
408
|
-
}
|
|
409
|
-
if (target.value.os !== "win32" && (stats.mode & 0o111) === 0) {
|
|
410
|
-
return packageFailure("binary_invalid", `Rust backend artifact is not executable.`);
|
|
411
|
-
}
|
|
412
|
-
binaryBytes = readFileSync(binaryPath);
|
|
413
|
-
} catch {
|
|
414
|
-
return packageFailure(
|
|
415
|
-
"binary_missing",
|
|
416
|
-
`Rust backend binary ${target.value.binary} is missing from ${target.value.packageName}.`,
|
|
417
|
-
);
|
|
418
|
-
}
|
|
419
|
-
const sha256 = createHash("sha256").update(binaryBytes).digest("hex");
|
|
420
|
-
if (sha256 !== manifest.data.sha256) {
|
|
421
|
-
return packageFailure(
|
|
422
|
-
"hash_mismatch",
|
|
423
|
-
`Rust backend binary integrity check failed for ${target.value.packageName}; no binary was started.`,
|
|
424
|
-
);
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
const probed = (options.identityProbe ?? probeBinaryIdentity)(binaryPath, metadata.identityFlag);
|
|
428
|
-
if (probed.kind === "error") {
|
|
429
|
-
return packageFailure(
|
|
430
|
-
"identity_failed",
|
|
431
|
-
`Rust backend binary did not pass the production identity gate: ${probed.message}. No TypeScript fallback was used.`,
|
|
432
|
-
);
|
|
433
|
-
}
|
|
434
|
-
if (!identitiesMatch(probed.value, manifest.data.identity)) {
|
|
435
|
-
return packageFailure(
|
|
436
|
-
"identity_mismatch",
|
|
437
|
-
`Rust backend binary identity differs from its signed package manifest; no binary was started.`,
|
|
438
|
-
);
|
|
439
|
-
}
|
|
440
|
-
|
|
441
|
-
return {
|
|
442
|
-
kind: "success",
|
|
443
|
-
value: {
|
|
444
|
-
command: binaryPath,
|
|
445
|
-
args: [],
|
|
446
|
-
packageName: target.value.packageName,
|
|
447
|
-
packageVersion: options.rootVersion,
|
|
448
|
-
target: target.value.target,
|
|
449
|
-
sha256,
|
|
450
|
-
},
|
|
451
|
-
};
|
|
452
|
-
}
|
|
453
|
-
|
|
454
|
-
export function resolvePreferredBackendImplementation(
|
|
455
|
-
options: ResolveRustBackendPackageOptions,
|
|
456
|
-
): PreferredBackendImplementation {
|
|
457
|
-
return resolveRustBackendPackage(options).kind === "success" ? "rust" : "typescript";
|
|
458
|
-
}
|
package/src/cli/startupOutput.ts
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
export type ServerOutputFilterContext = {
|
|
2
|
-
enableIdentityProxy: boolean;
|
|
3
|
-
publicPort: number;
|
|
4
|
-
upstreamPort: number;
|
|
5
|
-
};
|
|
6
|
-
|
|
7
|
-
export function shouldSuppressServerOutputLine(
|
|
8
|
-
line: string,
|
|
9
|
-
context: ServerOutputFilterContext,
|
|
10
|
-
): boolean {
|
|
11
|
-
if (!context.enableIdentityProxy) return false;
|
|
12
|
-
if (context.publicPort === context.upstreamPort) return false;
|
|
13
|
-
|
|
14
|
-
const lowerLine = line.toLowerCase();
|
|
15
|
-
return lowerLine.includes("listening on") && lowerLine.includes(`:${context.upstreamPort}`);
|
|
16
|
-
}
|