@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/alias.ts
DELETED
|
@@ -1,431 +0,0 @@
|
|
|
1
|
-
import { normalizeBasePath, normalizePublicBasePath } from "../lib/basePath";
|
|
2
|
-
|
|
3
|
-
const DEFAULT_ALIAS_HOST = "localhost";
|
|
4
|
-
const DEFAULT_ALIAS_PORT = 9527;
|
|
5
|
-
const ALIAS_CONTROL_PATH = "/.agent-inspector/base-path-aliases";
|
|
6
|
-
const REQUEST_TIMEOUT_MS = 5_000;
|
|
7
|
-
|
|
8
|
-
export type AliasFetch = (input: string, init?: RequestInit) => Promise<Response>;
|
|
9
|
-
|
|
10
|
-
export type AliasIo = {
|
|
11
|
-
stdout: (text: string) => void;
|
|
12
|
-
stderr: (text: string) => void;
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
type AliasAction =
|
|
16
|
-
| { kind: "add"; basePath: string }
|
|
17
|
-
| { kind: "list" }
|
|
18
|
-
| { kind: "remove"; basePath: string };
|
|
19
|
-
|
|
20
|
-
type AliasOptions = {
|
|
21
|
-
action: AliasAction;
|
|
22
|
-
host: string;
|
|
23
|
-
port: number;
|
|
24
|
-
json: boolean;
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
type AliasParseResult =
|
|
28
|
-
| { kind: "help" }
|
|
29
|
-
| { kind: "ok"; options: AliasOptions }
|
|
30
|
-
| { kind: "error"; message: string };
|
|
31
|
-
|
|
32
|
-
type AliasSnapshot = {
|
|
33
|
-
canonicalBasePath: string;
|
|
34
|
-
aliases: readonly string[];
|
|
35
|
-
runtimeScoped: true;
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
type AliasRequestResult =
|
|
39
|
-
| { kind: "success"; snapshot: AliasSnapshot }
|
|
40
|
-
| { kind: "http-error"; status: number; detail: string | null }
|
|
41
|
-
| { kind: "network-error"; timedOut: boolean }
|
|
42
|
-
| { kind: "invalid-response" };
|
|
43
|
-
|
|
44
|
-
type AliasOutput = {
|
|
45
|
-
action: AliasAction["kind"];
|
|
46
|
-
canonicalBasePath: string;
|
|
47
|
-
canonicalUrl: string;
|
|
48
|
-
aliases: readonly string[];
|
|
49
|
-
aliasUrls: readonly string[];
|
|
50
|
-
runtimeScoped: true;
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
const processIo: AliasIo = {
|
|
54
|
-
stdout: (text) => {
|
|
55
|
-
process.stdout.write(text);
|
|
56
|
-
},
|
|
57
|
-
stderr: (text) => {
|
|
58
|
-
process.stderr.write(text);
|
|
59
|
-
},
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
function parsePort(raw: string | undefined): number | null {
|
|
63
|
-
if (raw === undefined || raw.trim() === "") return null;
|
|
64
|
-
const port = Number(raw);
|
|
65
|
-
if (!Number.isInteger(port) || port < 1 || port > 65_535) return null;
|
|
66
|
-
return port;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
function normalizeAliasPath(raw: string): string | null {
|
|
70
|
-
return normalizePublicBasePath(raw);
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
function isValidHost(host: string): boolean {
|
|
74
|
-
const trimmed = host.trim();
|
|
75
|
-
return (
|
|
76
|
-
trimmed.length > 0 &&
|
|
77
|
-
!trimmed.includes("://") &&
|
|
78
|
-
!trimmed.includes("/") &&
|
|
79
|
-
!trimmed.includes("?") &&
|
|
80
|
-
!trimmed.includes("#") &&
|
|
81
|
-
!/\s/u.test(trimmed)
|
|
82
|
-
);
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
function formatHostForUrl(host: string): string {
|
|
86
|
-
if (host.startsWith("[") && host.endsWith("]")) return host;
|
|
87
|
-
return host.includes(":") ? `[${host}]` : host;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
export function parseAliasArgs(argv: readonly string[]): AliasParseResult {
|
|
91
|
-
let host = DEFAULT_ALIAS_HOST;
|
|
92
|
-
let port = DEFAULT_ALIAS_PORT;
|
|
93
|
-
let json = false;
|
|
94
|
-
let help = false;
|
|
95
|
-
const positional: string[] = [];
|
|
96
|
-
|
|
97
|
-
for (let index = 0; index < argv.length; index++) {
|
|
98
|
-
const arg = argv[index];
|
|
99
|
-
switch (arg) {
|
|
100
|
-
case undefined:
|
|
101
|
-
continue;
|
|
102
|
-
case "--help":
|
|
103
|
-
case "-h":
|
|
104
|
-
help = true;
|
|
105
|
-
break;
|
|
106
|
-
case "--host": {
|
|
107
|
-
const value = argv[index + 1];
|
|
108
|
-
if (value === undefined || !isValidHost(value)) {
|
|
109
|
-
return {
|
|
110
|
-
kind: "error",
|
|
111
|
-
message: "alias: --host requires a hostname or IP address without a protocol or path",
|
|
112
|
-
};
|
|
113
|
-
}
|
|
114
|
-
host = value.trim();
|
|
115
|
-
index++;
|
|
116
|
-
break;
|
|
117
|
-
}
|
|
118
|
-
case "--port":
|
|
119
|
-
case "-p": {
|
|
120
|
-
const value = parsePort(argv[index + 1]);
|
|
121
|
-
if (value === null) {
|
|
122
|
-
return {
|
|
123
|
-
kind: "error",
|
|
124
|
-
message: "alias: --port must be an integer from 1 to 65535",
|
|
125
|
-
};
|
|
126
|
-
}
|
|
127
|
-
port = value;
|
|
128
|
-
index++;
|
|
129
|
-
break;
|
|
130
|
-
}
|
|
131
|
-
case "--json":
|
|
132
|
-
json = true;
|
|
133
|
-
break;
|
|
134
|
-
default:
|
|
135
|
-
if (arg.startsWith("-")) {
|
|
136
|
-
return { kind: "error", message: `alias: unknown option ${arg}` };
|
|
137
|
-
}
|
|
138
|
-
positional.push(arg);
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
if (help) return { kind: "help" };
|
|
143
|
-
|
|
144
|
-
const command = positional[0];
|
|
145
|
-
switch (command) {
|
|
146
|
-
case "list":
|
|
147
|
-
if (positional.length !== 1) {
|
|
148
|
-
return { kind: "error", message: "alias: list does not accept a base path" };
|
|
149
|
-
}
|
|
150
|
-
return { kind: "ok", options: { action: { kind: "list" }, host, port, json } };
|
|
151
|
-
case "add":
|
|
152
|
-
case "remove": {
|
|
153
|
-
const rawBasePath = positional[1];
|
|
154
|
-
if (rawBasePath === undefined || positional.length !== 2) {
|
|
155
|
-
return { kind: "error", message: `alias: ${command} requires exactly one base path` };
|
|
156
|
-
}
|
|
157
|
-
const basePath = normalizeAliasPath(rawBasePath);
|
|
158
|
-
if (basePath === null) {
|
|
159
|
-
return {
|
|
160
|
-
kind: "error",
|
|
161
|
-
message: `alias: ${command} base path must be an absolute URL path without a query or hash`,
|
|
162
|
-
};
|
|
163
|
-
}
|
|
164
|
-
const action: AliasAction = { kind: command, basePath };
|
|
165
|
-
return { kind: "ok", options: { action, host, port, json } };
|
|
166
|
-
}
|
|
167
|
-
case undefined:
|
|
168
|
-
return { kind: "error", message: "alias: expected add <path>, list, or remove <path>" };
|
|
169
|
-
default:
|
|
170
|
-
return { kind: "error", message: `alias: unknown command ${command}` };
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
function aliasHelp(): string {
|
|
175
|
-
return `agent-inspector alias - mount additional base paths on a running runtime
|
|
176
|
-
|
|
177
|
-
Usage:
|
|
178
|
-
agent-inspector alias add <path> [--host <host>] [--port <port>] [--json]
|
|
179
|
-
agent-inspector alias list [--host <host>] [--port <port>] [--json]
|
|
180
|
-
agent-inspector alias remove <path> [--host <host>] [--port <port>] [--json]
|
|
181
|
-
|
|
182
|
-
Options:
|
|
183
|
-
--host <host> Running instance host (default: localhost)
|
|
184
|
-
--port <port> Running instance port (default: 9527)
|
|
185
|
-
--json Emit machine-readable output
|
|
186
|
-
--help, -h Show this help
|
|
187
|
-
|
|
188
|
-
Aliases are runtime-scoped. This command never starts another Agent Inspector runtime.
|
|
189
|
-
`;
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
function isObject(value: unknown): value is Record<string, unknown> {
|
|
193
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
function parseAliasSnapshot(value: unknown): AliasSnapshot | null {
|
|
197
|
-
if (!isObject(value)) return null;
|
|
198
|
-
const canonicalBasePath = value["canonicalBasePath"];
|
|
199
|
-
const aliases = value["aliases"];
|
|
200
|
-
const runtimeScoped = value["runtimeScoped"];
|
|
201
|
-
if (
|
|
202
|
-
typeof canonicalBasePath !== "string" ||
|
|
203
|
-
!Array.isArray(aliases) ||
|
|
204
|
-
!aliases.every((alias) => typeof alias === "string") ||
|
|
205
|
-
runtimeScoped !== true
|
|
206
|
-
) {
|
|
207
|
-
return null;
|
|
208
|
-
}
|
|
209
|
-
return {
|
|
210
|
-
canonicalBasePath: normalizeBasePath(canonicalBasePath),
|
|
211
|
-
aliases: aliases.map((alias) => normalizeBasePath(alias)),
|
|
212
|
-
runtimeScoped: true,
|
|
213
|
-
};
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
function readErrorDetail(value: unknown): string | null {
|
|
217
|
-
if (!isObject(value)) return null;
|
|
218
|
-
const error = value["error"];
|
|
219
|
-
if (typeof error === "string" && error.trim() !== "") return error;
|
|
220
|
-
const message = value["message"];
|
|
221
|
-
return typeof message === "string" && message.trim() !== "" ? message : null;
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
async function readJson(response: Response): Promise<unknown | null> {
|
|
225
|
-
try {
|
|
226
|
-
const value: unknown = await response.json();
|
|
227
|
-
return value;
|
|
228
|
-
} catch {
|
|
229
|
-
return null;
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
async function requestAliases(
|
|
234
|
-
endpoint: string,
|
|
235
|
-
action: AliasAction,
|
|
236
|
-
fetchImpl: AliasFetch,
|
|
237
|
-
): Promise<AliasRequestResult> {
|
|
238
|
-
const controller = new AbortController();
|
|
239
|
-
const timeout = setTimeout(() => {
|
|
240
|
-
controller.abort();
|
|
241
|
-
}, REQUEST_TIMEOUT_MS);
|
|
242
|
-
const method = action.kind === "list" ? "GET" : action.kind === "add" ? "POST" : "DELETE";
|
|
243
|
-
const basePath = action.kind === "list" ? null : action.basePath;
|
|
244
|
-
const init: RequestInit = {
|
|
245
|
-
method,
|
|
246
|
-
headers:
|
|
247
|
-
action.kind === "list"
|
|
248
|
-
? { accept: "application/json" }
|
|
249
|
-
: {
|
|
250
|
-
accept: "application/json",
|
|
251
|
-
"content-type": "application/json",
|
|
252
|
-
"x-agent-inspector-csrf": "1",
|
|
253
|
-
},
|
|
254
|
-
signal: controller.signal,
|
|
255
|
-
};
|
|
256
|
-
if (basePath !== null) init.body = JSON.stringify({ basePath });
|
|
257
|
-
|
|
258
|
-
try {
|
|
259
|
-
const response = await fetchImpl(endpoint, init);
|
|
260
|
-
const value = await readJson(response);
|
|
261
|
-
if (!response.ok) {
|
|
262
|
-
return { kind: "http-error", status: response.status, detail: readErrorDetail(value) };
|
|
263
|
-
}
|
|
264
|
-
const snapshot = parseAliasSnapshot(value);
|
|
265
|
-
return snapshot === null ? { kind: "invalid-response" } : { kind: "success", snapshot };
|
|
266
|
-
} catch (error) {
|
|
267
|
-
const timedOut =
|
|
268
|
-
controller.signal.aborted || (error instanceof Error && error.name === "AbortError");
|
|
269
|
-
return { kind: "network-error", timedOut };
|
|
270
|
-
} finally {
|
|
271
|
-
clearTimeout(timeout);
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
function displayBasePath(basePath: string): string {
|
|
276
|
-
const normalized = normalizeBasePath(basePath);
|
|
277
|
-
return normalized === "" ? "/" : normalized;
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
function fullUrl(origin: string, basePath: string): string {
|
|
281
|
-
return `${origin}${normalizeBasePath(basePath)}`;
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
function buildOutput(origin: string, action: AliasAction, snapshot: AliasSnapshot): AliasOutput {
|
|
285
|
-
return {
|
|
286
|
-
action: action.kind,
|
|
287
|
-
canonicalBasePath: displayBasePath(snapshot.canonicalBasePath),
|
|
288
|
-
canonicalUrl: fullUrl(origin, snapshot.canonicalBasePath),
|
|
289
|
-
aliases: snapshot.aliases.map(displayBasePath),
|
|
290
|
-
aliasUrls: snapshot.aliases.map((alias) => fullUrl(origin, alias)),
|
|
291
|
-
runtimeScoped: true,
|
|
292
|
-
};
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
function formatHumanOutput(output: AliasOutput): string {
|
|
296
|
-
const heading =
|
|
297
|
-
output.action === "add"
|
|
298
|
-
? "Base-path alias added."
|
|
299
|
-
: output.action === "remove"
|
|
300
|
-
? "Base-path alias removed."
|
|
301
|
-
: "Base-path aliases for the running runtime:";
|
|
302
|
-
const aliasPaths = output.aliases.length === 0 ? "(none)" : output.aliases.join(", ");
|
|
303
|
-
const aliasUrls =
|
|
304
|
-
output.aliasUrls.length === 0
|
|
305
|
-
? " (none)"
|
|
306
|
-
: output.aliasUrls.map((url) => ` - ${url}`).join("\n");
|
|
307
|
-
return `${heading}
|
|
308
|
-
Canonical base path: ${output.canonicalBasePath}
|
|
309
|
-
Canonical URL: ${output.canonicalUrl}
|
|
310
|
-
Alias base paths: ${aliasPaths}
|
|
311
|
-
Alias URLs:
|
|
312
|
-
${aliasUrls}
|
|
313
|
-
Scope: current runtime only; no second runtime was started and aliases are not persisted.
|
|
314
|
-
`;
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
function writeError(io: AliasIo, json: boolean, code: string, message: string): void {
|
|
318
|
-
if (json) {
|
|
319
|
-
io.stderr(`${JSON.stringify({ error: code, message, runtimeStarted: false })}\n`);
|
|
320
|
-
return;
|
|
321
|
-
}
|
|
322
|
-
io.stderr(`agent-inspector alias: ${message}\n`);
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
function oldRuntimeMessage(origin: string): string {
|
|
326
|
-
return `the runtime at ${origin} does not support base-path aliases. Upgrade Agent Inspector and restart that instance, then retry; this command did not start a runtime.`;
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
async function handleHttpError(
|
|
330
|
-
options: AliasOptions,
|
|
331
|
-
endpoint: string,
|
|
332
|
-
origin: string,
|
|
333
|
-
result: Extract<AliasRequestResult, { kind: "http-error" }>,
|
|
334
|
-
fetchImpl: AliasFetch,
|
|
335
|
-
io: AliasIo,
|
|
336
|
-
): Promise<number> {
|
|
337
|
-
if (result.status === 404 && options.action.kind === "remove") {
|
|
338
|
-
const probe = await requestAliases(endpoint, { kind: "list" }, fetchImpl);
|
|
339
|
-
if (probe.kind === "success") {
|
|
340
|
-
writeError(
|
|
341
|
-
io,
|
|
342
|
-
options.json,
|
|
343
|
-
"alias_not_found",
|
|
344
|
-
`base path ${displayBasePath(options.action.basePath)} is not mounted. Run "agent-inspector alias list --host ${options.host} --port ${options.port}" to inspect the current runtime.`,
|
|
345
|
-
);
|
|
346
|
-
return 1;
|
|
347
|
-
}
|
|
348
|
-
if (probe.kind === "network-error") {
|
|
349
|
-
writeError(
|
|
350
|
-
io,
|
|
351
|
-
options.json,
|
|
352
|
-
probe.timedOut ? "request_timeout" : "runtime_unreachable",
|
|
353
|
-
`${probe.timedOut ? "timed out contacting" : "cannot reach"} ${origin}. Confirm the existing runtime is running and the --host/--port values are correct; no runtime was started.`,
|
|
354
|
-
);
|
|
355
|
-
return 1;
|
|
356
|
-
}
|
|
357
|
-
if (probe.kind === "http-error" && (probe.status === 404 || probe.status === 405)) {
|
|
358
|
-
writeError(io, options.json, "unsupported_runtime", oldRuntimeMessage(origin));
|
|
359
|
-
return 1;
|
|
360
|
-
}
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
if (result.status === 404 || result.status === 405) {
|
|
364
|
-
writeError(io, options.json, "unsupported_runtime", oldRuntimeMessage(origin));
|
|
365
|
-
return 1;
|
|
366
|
-
}
|
|
367
|
-
if (result.status === 409) {
|
|
368
|
-
writeError(
|
|
369
|
-
io,
|
|
370
|
-
options.json,
|
|
371
|
-
"alias_conflict",
|
|
372
|
-
`${result.detail ?? "the base path is already mounted or conflicts with another mount"}. Run "agent-inspector alias list --host ${options.host} --port ${options.port}" to inspect the current runtime.`,
|
|
373
|
-
);
|
|
374
|
-
return 1;
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
const detail = result.detail === null ? "the runtime rejected the request" : result.detail;
|
|
378
|
-
writeError(
|
|
379
|
-
io,
|
|
380
|
-
options.json,
|
|
381
|
-
"runtime_rejected_request",
|
|
382
|
-
`${detail} (HTTP ${result.status}). Check the running instance and retry; no runtime was started.`,
|
|
383
|
-
);
|
|
384
|
-
return 1;
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
export async function runAlias(
|
|
388
|
-
argv: readonly string[],
|
|
389
|
-
fetchImpl: AliasFetch = fetch,
|
|
390
|
-
io: AliasIo = processIo,
|
|
391
|
-
): Promise<number> {
|
|
392
|
-
const parsed = parseAliasArgs(argv);
|
|
393
|
-
if (parsed.kind === "help") {
|
|
394
|
-
io.stdout(aliasHelp());
|
|
395
|
-
return 0;
|
|
396
|
-
}
|
|
397
|
-
if (parsed.kind === "error") {
|
|
398
|
-
io.stderr(`${parsed.message}\n\n${aliasHelp()}`);
|
|
399
|
-
return 2;
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
const { options } = parsed;
|
|
403
|
-
const origin = `http://${formatHostForUrl(options.host)}:${options.port}`;
|
|
404
|
-
const endpoint = `${origin}${ALIAS_CONTROL_PATH}`;
|
|
405
|
-
const result = await requestAliases(endpoint, options.action, fetchImpl);
|
|
406
|
-
switch (result.kind) {
|
|
407
|
-
case "success": {
|
|
408
|
-
const output = buildOutput(origin, options.action, result.snapshot);
|
|
409
|
-
io.stdout(options.json ? `${JSON.stringify(output, null, 2)}\n` : formatHumanOutput(output));
|
|
410
|
-
return 0;
|
|
411
|
-
}
|
|
412
|
-
case "network-error":
|
|
413
|
-
writeError(
|
|
414
|
-
io,
|
|
415
|
-
options.json,
|
|
416
|
-
result.timedOut ? "request_timeout" : "runtime_unreachable",
|
|
417
|
-
`${result.timedOut ? "timed out contacting" : "cannot reach"} ${origin}. Confirm the existing runtime is running and the --host/--port values are correct; no runtime was started.`,
|
|
418
|
-
);
|
|
419
|
-
return 1;
|
|
420
|
-
case "invalid-response":
|
|
421
|
-
writeError(
|
|
422
|
-
io,
|
|
423
|
-
options.json,
|
|
424
|
-
"invalid_runtime_response",
|
|
425
|
-
`the runtime at ${origin} returned an invalid alias response. Upgrade and restart that instance, then retry; no runtime was started.`,
|
|
426
|
-
);
|
|
427
|
-
return 1;
|
|
428
|
-
case "http-error":
|
|
429
|
-
return handleHttpError(options, endpoint, origin, result, fetchImpl, io);
|
|
430
|
-
}
|
|
431
|
-
}
|
package/src/cli/detect-tools.ts
DELETED
|
@@ -1,123 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tool detection for the onboard subcommand (and the SKILL.md instructions
|
|
3
|
-
* that read this code path). Pure functions only — no side effects, no fs
|
|
4
|
-
* watchers. Each detector returns a discriminated union so callers can tell
|
|
5
|
-
* a "found" from a "not found" without throwing.
|
|
6
|
-
*
|
|
7
|
-
* Detection is heuristic and best-effort. A miss is never an error — the
|
|
8
|
-
* user might have a tool installed in a non-standard location, or might be
|
|
9
|
-
* using a tool we don't enumerate. The skill falls through to a generic
|
|
10
|
-
* `curl` example in that case.
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
import { existsSync } from "node:fs";
|
|
14
|
-
import { join } from "node:path";
|
|
15
|
-
import { homedir } from "node:os";
|
|
16
|
-
import { resolveExecutableOnPath } from "../proxy/platformCommands.js";
|
|
17
|
-
|
|
18
|
-
export type DetectedTool = {
|
|
19
|
-
readonly found: true;
|
|
20
|
-
/** Absolute path to the most distinctive artifact (config dir or binary). */
|
|
21
|
-
readonly path: string;
|
|
22
|
-
/** Best-effort version string, if we can cheaply read one. */
|
|
23
|
-
readonly versionHint?: string;
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
export type MissingTool = { readonly found: false };
|
|
27
|
-
|
|
28
|
-
export type ToolDetectionResult = DetectedTool | MissingTool;
|
|
29
|
-
|
|
30
|
-
export type SupportedToolId = "claude-code" | "opencode" | "mimo" | "cursor" | "cody";
|
|
31
|
-
|
|
32
|
-
export type DetectedToolEntry = {
|
|
33
|
-
readonly id: SupportedToolId;
|
|
34
|
-
readonly displayName: string;
|
|
35
|
-
readonly result: ToolDetectionResult;
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
function which(bin: string): string | null {
|
|
39
|
-
return resolveExecutableOnPath(bin);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
function tryDir(path: string): string | null {
|
|
43
|
-
return existsSync(path) ? path : null;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
function detectClaudeCode(): ToolDetectionResult {
|
|
47
|
-
// Claude Code stores its config under ~/.claude/. The binary is `claude`.
|
|
48
|
-
const configDir = tryDir(join(homedir(), ".claude"));
|
|
49
|
-
const bin = which("claude");
|
|
50
|
-
if (configDir === null && bin === null) return { found: false };
|
|
51
|
-
return { found: true, path: configDir ?? bin ?? "" };
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
function detectOpenCode(): ToolDetectionResult {
|
|
55
|
-
const configDir = tryDir(join(homedir(), ".config", "opencode"));
|
|
56
|
-
const bin = which("opencode");
|
|
57
|
-
if (configDir === null && bin === null) return { found: false };
|
|
58
|
-
return { found: true, path: configDir ?? bin ?? "" };
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
function detectMiMo(): ToolDetectionResult {
|
|
62
|
-
const configDir =
|
|
63
|
-
tryDir(join(homedir(), ".config", "mimocode")) ?? tryDir(join(homedir(), ".mimocode"));
|
|
64
|
-
const bin = which("mimo");
|
|
65
|
-
if (configDir === null && bin === null) return { found: false };
|
|
66
|
-
return { found: true, path: configDir ?? bin ?? "" };
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
function detectCursor(): ToolDetectionResult {
|
|
70
|
-
const configDir = tryDir(join(homedir(), ".cursor"));
|
|
71
|
-
const bin = which("cursor");
|
|
72
|
-
if (configDir === null && bin === null) return { found: false };
|
|
73
|
-
return { found: true, path: configDir ?? bin ?? "" };
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
function detectCody(): ToolDetectionResult {
|
|
77
|
-
// Sourcegraph's Cody uses `~/.config/cody/` (Linux/macOS) and stores
|
|
78
|
-
// its binary on PATH as `cody`. Note: `~/.codex/` is OpenAI Codex CLI's
|
|
79
|
-
// config dir, *not* Cody's — keep these distinct.
|
|
80
|
-
const configDir = tryDir(join(homedir(), ".config", "cody"));
|
|
81
|
-
const bin = which("cody");
|
|
82
|
-
if (configDir === null && bin === null) return { found: false };
|
|
83
|
-
return { found: true, path: configDir ?? bin ?? "" };
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
const DETECTORS: ReadonlyArray<{
|
|
87
|
-
id: SupportedToolId;
|
|
88
|
-
displayName: string;
|
|
89
|
-
detect: () => ToolDetectionResult;
|
|
90
|
-
}> = [
|
|
91
|
-
{ id: "claude-code", displayName: "Claude Code", detect: detectClaudeCode },
|
|
92
|
-
{ id: "opencode", displayName: "OpenCode", detect: detectOpenCode },
|
|
93
|
-
{ id: "mimo", displayName: "MiMo Code", detect: detectMiMo },
|
|
94
|
-
{ id: "cursor", displayName: "Cursor", detect: detectCursor },
|
|
95
|
-
{ id: "cody", displayName: "Cody", detect: detectCody },
|
|
96
|
-
];
|
|
97
|
-
|
|
98
|
-
/**
|
|
99
|
-
* Run every detector and return the full list, including misses. Useful for
|
|
100
|
-
* the SKILL.md instructions that want to give the user a summary of what's
|
|
101
|
-
* available ("detected: Claude Code, OpenCode; not detected: Cursor, Cody").
|
|
102
|
-
*/
|
|
103
|
-
export function detectAll(): ReadonlyArray<DetectedToolEntry> {
|
|
104
|
-
return DETECTORS.map(({ id, displayName, detect }) => ({
|
|
105
|
-
id,
|
|
106
|
-
displayName,
|
|
107
|
-
result: detect(),
|
|
108
|
-
}));
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
/**
|
|
112
|
-
* Return the first tool that the detector finds. Used by the onboard
|
|
113
|
-
* subcommand when it needs to pick a single "wiring example" to print.
|
|
114
|
-
* Order in `DETECTORS` is the priority order — Claude Code first because
|
|
115
|
-
* it's the namesake of the project.
|
|
116
|
-
*/
|
|
117
|
-
export function detectFirst(): DetectedToolEntry | null {
|
|
118
|
-
for (const entry of DETECTORS) {
|
|
119
|
-
const result = entry.detect();
|
|
120
|
-
if (result.found) return { id: entry.id, displayName: entry.displayName, result };
|
|
121
|
-
}
|
|
122
|
-
return null;
|
|
123
|
-
}
|