@tonyclaw/agent-inspector 4.0.1 → 4.0.3
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 +193 -110
- package/.output/server/_ssr/index.mjs +1 -1
- package/.output/server/_ssr/{router-CTHqmroT.mjs → router-ChILzhmz.mjs} +92 -4
- package/.output/server/index.mjs +1 -1
- package/.output/ui/assets/{CompareDrawer-L3n4J-Or.js → CompareDrawer-Co3cUF_I.js} +1 -1
- package/.output/ui/assets/{InspectorPet-D5o_3OZS.js → InspectorPet-jFcrL37X.js} +1 -1
- package/.output/ui/assets/{ProxyViewerContainer-Ocagx75S.js → ProxyViewerContainer-BPzt_VpM.js} +4 -4
- package/.output/ui/assets/{ReplayDialog-Bk7x1h-y.js → ReplayDialog-C6O_zuwI.js} +1 -1
- package/.output/ui/assets/{RequestAnatomy-U4lzL7Sc.js → RequestAnatomy-Ca6NvB7L.js} +1 -1
- package/.output/ui/assets/{ResponseView-LOWfvBLK.js → ResponseView-BzqKcveJ.js} +1 -1
- package/.output/ui/assets/{StreamingChunkSequence-DPfsrrXQ.js → StreamingChunkSequence-9pCZIsS_.js} +1 -1
- package/.output/ui/assets/{_sessionId-0MlWS-CO.js → _sessionId-BMP3KVGR.js} +1 -1
- package/.output/ui/assets/{_sessionId-OdX2Jvt1.js → _sessionId-y4eRoT1H.js} +1 -1
- package/.output/ui/assets/{index-Ea-c8hPg.js → index-CH5w-haG.js} +1 -1
- package/.output/ui/assets/{index-zVVS53Hd.js → index-CmocEhyU.js} +1 -1
- package/.output/ui/assets/{index-Du4qNOOt.js → index-DT8sMJ_n.js} +2 -2
- package/.output/ui/assets/{index-gvFj_9K6.js → index-bfsbIRZa.js} +1 -1
- package/.output/ui/assets/{json-viewer-C1WAMzg3.js → json-viewer-BfFOSDG5.js} +1 -1
- package/.output/ui/assets/{jszip.min-B8AKu2zm.js → jszip.min-BkbVkOsp.js} +1 -1
- package/.output/ui/index.html +1 -1
- package/package.json +5 -10
- 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 -1433
- 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 -258
- 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
|
@@ -1,419 +0,0 @@
|
|
|
1
|
-
import { spawnSync } from "node:child_process";
|
|
2
|
-
import {
|
|
3
|
-
closeSync,
|
|
4
|
-
constants,
|
|
5
|
-
fchmodSync,
|
|
6
|
-
fstatSync,
|
|
7
|
-
lstatSync,
|
|
8
|
-
mkdirSync,
|
|
9
|
-
openSync,
|
|
10
|
-
readdirSync,
|
|
11
|
-
realpathSync,
|
|
12
|
-
} from "node:fs";
|
|
13
|
-
import { join, parse, resolve, sep } from "node:path";
|
|
14
|
-
|
|
15
|
-
export const PRIVATE_DIRECTORY_MODE = 0o700;
|
|
16
|
-
export const PRIVATE_FILE_MODE = 0o600;
|
|
17
|
-
|
|
18
|
-
export type PrivateDataPathKind = "directory" | "file";
|
|
19
|
-
|
|
20
|
-
type WindowsCommandResult = {
|
|
21
|
-
status: number | null;
|
|
22
|
-
stdout: string;
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
export type WindowsCommandRunner = (
|
|
26
|
-
executable: string,
|
|
27
|
-
args: readonly string[],
|
|
28
|
-
) => WindowsCommandResult;
|
|
29
|
-
|
|
30
|
-
type PathEntry = {
|
|
31
|
-
path: string;
|
|
32
|
-
kind: PrivateDataPathKind;
|
|
33
|
-
identity: string;
|
|
34
|
-
mode: number;
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
type PathChainSnapshot = {
|
|
38
|
-
absolutePath: string;
|
|
39
|
-
complete: boolean;
|
|
40
|
-
entries: readonly PathEntry[];
|
|
41
|
-
missingParts: readonly string[];
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
type TreeEntry = {
|
|
45
|
-
path: string;
|
|
46
|
-
kind: PrivateDataPathKind;
|
|
47
|
-
fingerprint: string;
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
type PathEntryRead =
|
|
51
|
-
| { status: "ok"; entry: PathEntry }
|
|
52
|
-
| { status: "missing" }
|
|
53
|
-
| { status: "unsafe" };
|
|
54
|
-
|
|
55
|
-
const securedPathFingerprints = new Map<string, string>();
|
|
56
|
-
let cachedWindowsSid: string | null = null;
|
|
57
|
-
|
|
58
|
-
// Always invoke the system copies of Windows security utilities regardless of PATH ordering.
|
|
59
|
-
function windowsSystemPath(executable: string): string {
|
|
60
|
-
const systemRoot = process.env["SystemRoot"] ?? "C:\\Windows";
|
|
61
|
-
return `${systemRoot}\\System32\\${executable}`;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
function runWindowsCommand(executable: string, args: readonly string[]): WindowsCommandResult {
|
|
65
|
-
const resolved =
|
|
66
|
-
process.platform === "win32" && /^(whoami|icacls)\.exe$/iu.test(executable)
|
|
67
|
-
? windowsSystemPath(executable)
|
|
68
|
-
: executable;
|
|
69
|
-
const result = spawnSync(resolved, [...args], {
|
|
70
|
-
encoding: "utf8",
|
|
71
|
-
shell: false,
|
|
72
|
-
windowsHide: true,
|
|
73
|
-
});
|
|
74
|
-
return { status: result.status, stdout: result.stdout };
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
function windowsUserSid(output: string): string | null {
|
|
78
|
-
const match = /S-\d+(?:-\d+)+/.exec(output);
|
|
79
|
-
return match?.[0] ?? null;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
function resolveWindowsUserSid(run: WindowsCommandRunner): string | null {
|
|
83
|
-
if (run === runWindowsCommand && cachedWindowsSid !== null) return cachedWindowsSid;
|
|
84
|
-
const identity = run("whoami.exe", ["/user", "/fo", "csv", "/nh"]);
|
|
85
|
-
if (identity.status !== 0) return null;
|
|
86
|
-
const sid = windowsUserSid(identity.stdout);
|
|
87
|
-
if (run === runWindowsCommand) cachedWindowsSid = sid;
|
|
88
|
-
return sid;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
function windowsBroadGroupRemovalArgs(): readonly string[] {
|
|
92
|
-
return ["/remove:g", "*S-1-1-0", "*S-1-5-11", "*S-1-5-32-545", "CodexSandboxUsers"];
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
function applyWindowsAclWithSid(
|
|
96
|
-
path: string,
|
|
97
|
-
kind: PrivateDataPathKind,
|
|
98
|
-
sid: string,
|
|
99
|
-
run: WindowsCommandRunner,
|
|
100
|
-
): boolean {
|
|
101
|
-
const access = kind === "directory" ? `(OI)(CI)F` : "F";
|
|
102
|
-
const result = run("icacls.exe", [
|
|
103
|
-
path,
|
|
104
|
-
"/inheritance:r",
|
|
105
|
-
"/grant:r",
|
|
106
|
-
`*${sid}:${access}`,
|
|
107
|
-
...windowsBroadGroupRemovalArgs(),
|
|
108
|
-
"/q",
|
|
109
|
-
]);
|
|
110
|
-
return result.status === 0;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
/** Remove inherited Windows permissions and grant access only to the current process user. */
|
|
114
|
-
export function applyWindowsUserOnlyAcl(
|
|
115
|
-
path: string,
|
|
116
|
-
kind: PrivateDataPathKind,
|
|
117
|
-
run: WindowsCommandRunner = runWindowsCommand,
|
|
118
|
-
): boolean {
|
|
119
|
-
const sid = resolveWindowsUserSid(run);
|
|
120
|
-
return sid !== null && applyWindowsAclWithSid(path, kind, sid, run);
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
function comparablePath(path: string): string {
|
|
124
|
-
let normalized = path;
|
|
125
|
-
if (process.platform === "win32") {
|
|
126
|
-
if (normalized.startsWith("\\\\?\\UNC\\")) {
|
|
127
|
-
normalized = `\\\\${normalized.slice(8)}`;
|
|
128
|
-
} else if (normalized.startsWith("\\\\?\\")) {
|
|
129
|
-
normalized = normalized.slice(4);
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
const absolute = resolve(normalized);
|
|
133
|
-
return process.platform === "win32" ? absolute.toLowerCase() : absolute;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
type PathStats = NonNullable<ReturnType<typeof lstatSync>>;
|
|
137
|
-
|
|
138
|
-
function pathIdentity(stats: PathStats): string {
|
|
139
|
-
return `${String(stats.dev)}:${String(stats.ino)}:${String(stats.birthtimeMs)}`;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
function readPathEntry(path: string): PathEntryRead {
|
|
143
|
-
let stats: PathStats;
|
|
144
|
-
try {
|
|
145
|
-
const observed = lstatSync(path);
|
|
146
|
-
if (observed === undefined) return { status: "missing" };
|
|
147
|
-
stats = observed;
|
|
148
|
-
} catch {
|
|
149
|
-
return { status: "missing" };
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
// On Windows, junctions and the supported reparse indirections are surfaced as symbolic links.
|
|
153
|
-
// The realpath equality check also rejects path aliases whose target differs from the lexical path.
|
|
154
|
-
if (stats.isSymbolicLink()) return { status: "unsafe" };
|
|
155
|
-
const kind: PrivateDataPathKind | null = stats.isDirectory()
|
|
156
|
-
? "directory"
|
|
157
|
-
: stats.isFile()
|
|
158
|
-
? "file"
|
|
159
|
-
: null;
|
|
160
|
-
if (kind === null) return { status: "unsafe" };
|
|
161
|
-
|
|
162
|
-
let canonical: string;
|
|
163
|
-
try {
|
|
164
|
-
canonical = realpathSync.native(path);
|
|
165
|
-
} catch {
|
|
166
|
-
return { status: "unsafe" };
|
|
167
|
-
}
|
|
168
|
-
if (comparablePath(canonical) !== comparablePath(path)) return { status: "unsafe" };
|
|
169
|
-
|
|
170
|
-
return {
|
|
171
|
-
status: "ok",
|
|
172
|
-
entry: {
|
|
173
|
-
path,
|
|
174
|
-
kind,
|
|
175
|
-
identity: pathIdentity(stats),
|
|
176
|
-
mode: stats.mode & 0o777,
|
|
177
|
-
},
|
|
178
|
-
};
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
function snapshotPathChain(path: string): PathChainSnapshot | null {
|
|
182
|
-
const absolutePath = resolve(path);
|
|
183
|
-
const root = parse(absolutePath).root;
|
|
184
|
-
const suffix = absolutePath.slice(root.length);
|
|
185
|
-
const parts = suffix === "" ? [] : suffix.split(sep).filter((part) => part !== "");
|
|
186
|
-
const entries: PathEntry[] = [];
|
|
187
|
-
let current = root;
|
|
188
|
-
|
|
189
|
-
const rootRead = readPathEntry(root);
|
|
190
|
-
if (rootRead.status !== "ok" || rootRead.entry.kind !== "directory") return null;
|
|
191
|
-
entries.push(rootRead.entry);
|
|
192
|
-
|
|
193
|
-
for (let index = 0; index < parts.length; index += 1) {
|
|
194
|
-
const part = parts[index];
|
|
195
|
-
if (part === undefined) return null;
|
|
196
|
-
current = join(current, part);
|
|
197
|
-
const read = readPathEntry(current);
|
|
198
|
-
if (read.status === "unsafe") return null;
|
|
199
|
-
if (read.status === "missing") {
|
|
200
|
-
return {
|
|
201
|
-
absolutePath,
|
|
202
|
-
complete: false,
|
|
203
|
-
entries,
|
|
204
|
-
missingParts: parts.slice(index),
|
|
205
|
-
};
|
|
206
|
-
}
|
|
207
|
-
if (index < parts.length - 1 && read.entry.kind !== "directory") return null;
|
|
208
|
-
entries.push(read.entry);
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
return { absolutePath, complete: true, entries, missingParts: [] };
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
function chainFingerprint(snapshot: PathChainSnapshot): string {
|
|
215
|
-
return snapshot.entries.map((entry) => `${entry.path}:${entry.identity}`).join("|");
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
function snapshotsRetainPrefix(before: PathChainSnapshot, after: PathChainSnapshot): boolean {
|
|
219
|
-
if (after.entries.length < before.entries.length) return false;
|
|
220
|
-
return before.entries.every((entry, index) => {
|
|
221
|
-
const next = after.entries[index];
|
|
222
|
-
return next !== undefined && next.path === entry.path && next.identity === entry.identity;
|
|
223
|
-
});
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
function completeSnapshotForKind(
|
|
227
|
-
path: string,
|
|
228
|
-
kind: PrivateDataPathKind,
|
|
229
|
-
): PathChainSnapshot | null {
|
|
230
|
-
const snapshot = snapshotPathChain(path);
|
|
231
|
-
if (snapshot === null || !snapshot.complete) return null;
|
|
232
|
-
const leaf = snapshot.entries.at(-1);
|
|
233
|
-
return leaf !== undefined && leaf.kind === kind ? snapshot : null;
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
function applyPosixPermissions(
|
|
237
|
-
path: string,
|
|
238
|
-
kind: PrivateDataPathKind,
|
|
239
|
-
expectedIdentity: string,
|
|
240
|
-
): boolean {
|
|
241
|
-
let descriptor: number | null = null;
|
|
242
|
-
try {
|
|
243
|
-
const directoryFlag = kind === "directory" ? constants.O_DIRECTORY : 0;
|
|
244
|
-
descriptor = openSync(path, constants.O_RDONLY | constants.O_NOFOLLOW | directoryFlag);
|
|
245
|
-
const before = fstatSync(descriptor);
|
|
246
|
-
if (pathIdentity(before) !== expectedIdentity) return false;
|
|
247
|
-
fchmodSync(descriptor, kind === "directory" ? PRIVATE_DIRECTORY_MODE : PRIVATE_FILE_MODE);
|
|
248
|
-
const after = fstatSync(descriptor);
|
|
249
|
-
return (
|
|
250
|
-
pathIdentity(after) === expectedIdentity &&
|
|
251
|
-
(after.mode & 0o777) === (kind === "directory" ? PRIVATE_DIRECTORY_MODE : PRIVATE_FILE_MODE)
|
|
252
|
-
);
|
|
253
|
-
} catch {
|
|
254
|
-
return false;
|
|
255
|
-
} finally {
|
|
256
|
-
if (descriptor !== null) {
|
|
257
|
-
try {
|
|
258
|
-
closeSync(descriptor);
|
|
259
|
-
} catch {
|
|
260
|
-
// The permission result already fails closed; descriptor cleanup is best effort here.
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
function permissionsArePrivate(entry: PathEntry): boolean {
|
|
267
|
-
if (process.platform === "win32") return true;
|
|
268
|
-
return entry.mode === (entry.kind === "directory" ? PRIVATE_DIRECTORY_MODE : PRIVATE_FILE_MODE);
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
function secureExistingPath(
|
|
272
|
-
path: string,
|
|
273
|
-
kind: PrivateDataPathKind,
|
|
274
|
-
forcePermissions = false,
|
|
275
|
-
): boolean {
|
|
276
|
-
const before = completeSnapshotForKind(path, kind);
|
|
277
|
-
if (before === null) return false;
|
|
278
|
-
const leaf = before.entries.at(-1);
|
|
279
|
-
if (leaf === undefined) return false;
|
|
280
|
-
const cacheKey = `${kind}:${before.absolutePath}`;
|
|
281
|
-
const beforeFingerprint = chainFingerprint(before);
|
|
282
|
-
if (
|
|
283
|
-
!forcePermissions &&
|
|
284
|
-
securedPathFingerprints.get(cacheKey) === beforeFingerprint &&
|
|
285
|
-
permissionsArePrivate(leaf)
|
|
286
|
-
) {
|
|
287
|
-
const cachedCheck = completeSnapshotForKind(path, kind);
|
|
288
|
-
return cachedCheck !== null && chainFingerprint(cachedCheck) === beforeFingerprint;
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
const applied =
|
|
292
|
-
process.platform === "win32"
|
|
293
|
-
? applyWindowsUserOnlyAcl(path, kind)
|
|
294
|
-
: applyPosixPermissions(path, kind, leaf.identity);
|
|
295
|
-
if (!applied) return false;
|
|
296
|
-
|
|
297
|
-
const after = completeSnapshotForKind(path, kind);
|
|
298
|
-
if (after === null || !snapshotsRetainPrefix(before, after)) return false;
|
|
299
|
-
const afterLeaf = after.entries.at(-1);
|
|
300
|
-
if (afterLeaf === undefined || afterLeaf.identity !== leaf.identity) return false;
|
|
301
|
-
if (!permissionsArePrivate(afterLeaf)) return false;
|
|
302
|
-
securedPathFingerprints.set(cacheKey, chainFingerprint(after));
|
|
303
|
-
return true;
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
export function ensurePrivateDirectorySync(path: string): boolean {
|
|
307
|
-
const before = snapshotPathChain(path);
|
|
308
|
-
if (before === null) return false;
|
|
309
|
-
|
|
310
|
-
let current = before.entries.at(-1)?.path;
|
|
311
|
-
if (current === undefined) return false;
|
|
312
|
-
for (const part of before.missingParts) {
|
|
313
|
-
const next = join(current, part);
|
|
314
|
-
try {
|
|
315
|
-
mkdirSync(next, { mode: PRIVATE_DIRECTORY_MODE });
|
|
316
|
-
} catch {
|
|
317
|
-
const raced = readPathEntry(next);
|
|
318
|
-
if (raced.status !== "ok" || raced.entry.kind !== "directory") return false;
|
|
319
|
-
}
|
|
320
|
-
if (!secureExistingPath(next, "directory", true)) return false;
|
|
321
|
-
current = next;
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
const complete = completeSnapshotForKind(path, "directory");
|
|
325
|
-
if (complete === null || !snapshotsRetainPrefix(before, complete)) return false;
|
|
326
|
-
return secureExistingPath(path, "directory");
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
export function securePrivateFileSync(path: string, forceAcl = false): boolean {
|
|
330
|
-
return secureExistingPath(path, "file", forceAcl);
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
function collectSafeTree(root: string): TreeEntry[] | null {
|
|
334
|
-
const collected: TreeEntry[] = [];
|
|
335
|
-
|
|
336
|
-
const visit = (path: string): boolean => {
|
|
337
|
-
const snapshot = snapshotPathChain(path);
|
|
338
|
-
if (snapshot === null || !snapshot.complete) return false;
|
|
339
|
-
const leaf = snapshot.entries.at(-1);
|
|
340
|
-
if (leaf === undefined) return false;
|
|
341
|
-
const fingerprint = chainFingerprint(snapshot);
|
|
342
|
-
collected.push({ path: snapshot.absolutePath, kind: leaf.kind, fingerprint });
|
|
343
|
-
if (leaf.kind === "file") return true;
|
|
344
|
-
|
|
345
|
-
let entries: string[];
|
|
346
|
-
try {
|
|
347
|
-
entries = readdirSync(path);
|
|
348
|
-
} catch {
|
|
349
|
-
return false;
|
|
350
|
-
}
|
|
351
|
-
const afterRead = completeSnapshotForKind(path, "directory");
|
|
352
|
-
if (afterRead === null || chainFingerprint(afterRead) !== fingerprint) return false;
|
|
353
|
-
for (const entry of entries) {
|
|
354
|
-
if (!visit(join(path, entry))) return false;
|
|
355
|
-
}
|
|
356
|
-
return true;
|
|
357
|
-
};
|
|
358
|
-
|
|
359
|
-
return visit(root) ? collected : null;
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
function treeFingerprintsMatch(
|
|
363
|
-
expected: readonly TreeEntry[],
|
|
364
|
-
observed: readonly TreeEntry[] | null,
|
|
365
|
-
): boolean {
|
|
366
|
-
if (observed === null || observed.length !== expected.length) return false;
|
|
367
|
-
return expected.every((entry, index) => {
|
|
368
|
-
const next = observed[index];
|
|
369
|
-
return (
|
|
370
|
-
next !== undefined &&
|
|
371
|
-
next.path === entry.path &&
|
|
372
|
-
next.kind === entry.kind &&
|
|
373
|
-
next.fingerprint === entry.fingerprint
|
|
374
|
-
);
|
|
375
|
-
});
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
/** Read-only preflight used before copy/import operations that must not follow indirection. */
|
|
379
|
-
export function isPathTreeFreeOfIndirectionSync(root: string): boolean {
|
|
380
|
-
return collectSafeTree(root) !== null;
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
/** Apply ACLs item by item after a no-follow scan; never use icacls /T across a reparse point. */
|
|
384
|
-
export function applyWindowsUserOnlyTreeAcl(
|
|
385
|
-
root: string,
|
|
386
|
-
run: WindowsCommandRunner = runWindowsCommand,
|
|
387
|
-
): boolean {
|
|
388
|
-
const entries = collectSafeTree(root);
|
|
389
|
-
if (entries === null) return false;
|
|
390
|
-
const sid = resolveWindowsUserSid(run);
|
|
391
|
-
if (sid === null) return false;
|
|
392
|
-
|
|
393
|
-
for (const entry of entries) {
|
|
394
|
-
const before = completeSnapshotForKind(entry.path, entry.kind);
|
|
395
|
-
if (before === null || chainFingerprint(before) !== entry.fingerprint) return false;
|
|
396
|
-
if (!applyWindowsAclWithSid(entry.path, entry.kind, sid, run)) return false;
|
|
397
|
-
const after = completeSnapshotForKind(entry.path, entry.kind);
|
|
398
|
-
if (after === null || chainFingerprint(after) !== entry.fingerprint) return false;
|
|
399
|
-
securedPathFingerprints.set(`${entry.kind}:${entry.path}`, entry.fingerprint);
|
|
400
|
-
}
|
|
401
|
-
return treeFingerprintsMatch(entries, collectSafeTree(root));
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
/** Secure an existing tree while refusing every symlink, junction, or reparse indirection. */
|
|
405
|
-
export function securePrivateTreeSync(root: string): boolean {
|
|
406
|
-
const entries = collectSafeTree(root);
|
|
407
|
-
if (entries === null) return false;
|
|
408
|
-
if (process.platform === "win32") return applyWindowsUserOnlyTreeAcl(root);
|
|
409
|
-
|
|
410
|
-
for (const entry of entries) {
|
|
411
|
-
if (!secureExistingPath(entry.path, entry.kind, true)) return false;
|
|
412
|
-
}
|
|
413
|
-
return treeFingerprintsMatch(entries, collectSafeTree(root));
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
export function _resetPrivateDataPathCacheForTests(): void {
|
|
417
|
-
securedPathFingerprints.clear();
|
|
418
|
-
cachedWindowsSid = null;
|
|
419
|
-
}
|