rivet-design 0.17.4 → 0.18.0
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/bin/rivet.js +0 -16
- package/dist/agent-variants/SessionStore.d.ts +5 -240
- package/dist/agent-variants/SessionStore.d.ts.map +1 -1
- package/dist/agent-variants/SessionStore.js +42 -371
- package/dist/agent-variants/SessionStore.js.map +1 -1
- package/dist/agent-variants/VariantWorkspaceManager.d.ts +0 -10
- package/dist/agent-variants/VariantWorkspaceManager.d.ts.map +1 -1
- package/dist/agent-variants/VariantWorkspaceManager.js +0 -17
- package/dist/agent-variants/VariantWorkspaceManager.js.map +1 -1
- package/dist/agent-variants/WorkerExecutorService.d.ts +1 -105
- package/dist/agent-variants/WorkerExecutorService.d.ts.map +1 -1
- package/dist/agent-variants/WorkerExecutorService.js +11 -182
- package/dist/agent-variants/WorkerExecutorService.js.map +1 -1
- package/dist/agent-variants/WorktreeOrchestrator.d.ts +6 -598
- package/dist/agent-variants/WorktreeOrchestrator.d.ts.map +1 -1
- package/dist/agent-variants/WorktreeOrchestrator.js +55 -1288
- package/dist/agent-variants/WorktreeOrchestrator.js.map +1 -1
- package/dist/agent-variants/WorktreeOrchestrator.testHelpers.d.ts +0 -6
- package/dist/agent-variants/WorktreeOrchestrator.testHelpers.d.ts.map +1 -1
- package/dist/agent-variants/WorktreeOrchestrator.testHelpers.js +0 -23
- package/dist/agent-variants/WorktreeOrchestrator.testHelpers.js.map +1 -1
- package/dist/agent-variants/briefContent.d.ts +0 -11
- package/dist/agent-variants/briefContent.d.ts.map +1 -1
- package/dist/agent-variants/briefContent.js +0 -12
- package/dist/agent-variants/briefContent.js.map +1 -1
- package/dist/agent-variants/contextAssets.d.ts +0 -3
- package/dist/agent-variants/contextAssets.d.ts.map +1 -1
- package/dist/agent-variants/contextAssets.js +0 -3
- package/dist/agent-variants/contextAssets.js.map +1 -1
- package/dist/agent-variants/contracts.d.ts +2016 -600
- package/dist/agent-variants/contracts.d.ts.map +1 -1
- package/dist/agent-variants/contracts.js +10 -174
- package/dist/agent-variants/contracts.js.map +1 -1
- package/dist/agent-variants/createProjectArtifacts.d.ts +0 -17
- package/dist/agent-variants/createProjectArtifacts.d.ts.map +1 -1
- package/dist/agent-variants/createProjectArtifacts.js +0 -10
- package/dist/agent-variants/createProjectArtifacts.js.map +1 -1
- package/dist/agent-variants/diffQa.d.ts +0 -1
- package/dist/agent-variants/diffQa.d.ts.map +1 -1
- package/dist/agent-variants/diffQa.js +0 -1
- package/dist/agent-variants/diffQa.js.map +1 -1
- package/dist/agent-variants/directionAuthoring.d.ts +0 -13
- package/dist/agent-variants/directionAuthoring.d.ts.map +1 -1
- package/dist/agent-variants/directionAuthoring.js +12 -46
- package/dist/agent-variants/directionAuthoring.js.map +1 -1
- package/dist/agent-variants/elementRefToTarget.d.ts +0 -17
- package/dist/agent-variants/elementRefToTarget.d.ts.map +1 -1
- package/dist/agent-variants/elementRefToTarget.js +0 -17
- package/dist/agent-variants/elementRefToTarget.js.map +1 -1
- package/dist/agent-variants/generatedDestination.d.ts +0 -3
- package/dist/agent-variants/generatedDestination.d.ts.map +1 -1
- package/dist/agent-variants/generatedDestination.js +0 -3
- package/dist/agent-variants/generatedDestination.js.map +1 -1
- package/dist/agent-variants/previewQa.d.ts +0 -6
- package/dist/agent-variants/previewQa.d.ts.map +1 -1
- package/dist/agent-variants/previewQa.js +0 -5
- package/dist/agent-variants/previewQa.js.map +1 -1
- package/dist/agent-variants/runLabel.d.ts +0 -15
- package/dist/agent-variants/runLabel.d.ts.map +1 -1
- package/dist/agent-variants/runLabel.js +0 -19
- package/dist/agent-variants/runLabel.js.map +1 -1
- package/dist/agent-variants/runPlan.d.ts +3 -84
- package/dist/agent-variants/runPlan.d.ts.map +1 -1
- package/dist/agent-variants/runPlan.js +0 -51
- package/dist/agent-variants/runPlan.js.map +1 -1
- package/dist/agent-variants/sourceContext.d.ts +0 -10
- package/dist/agent-variants/sourceContext.d.ts.map +1 -1
- package/dist/agent-variants/sourceContext.js +0 -36
- package/dist/agent-variants/sourceContext.js.map +1 -1
- package/dist/agent-variants/variantContext.d.ts +6 -7
- package/dist/agent-variants/variantContext.d.ts.map +1 -1
- package/dist/agent-variants/variantContext.js +69 -10
- package/dist/agent-variants/variantContext.js.map +1 -1
- package/dist/agent-variants/videoKeyframes.d.ts +0 -7
- package/dist/agent-variants/videoKeyframes.d.ts.map +1 -1
- package/dist/agent-variants/videoKeyframes.js +0 -7
- package/dist/agent-variants/videoKeyframes.js.map +1 -1
- package/dist/agent-variants/workItemBriefing.d.ts +0 -21
- package/dist/agent-variants/workItemBriefing.d.ts.map +1 -1
- package/dist/agent-variants/workItemBriefing.js +0 -49
- package/dist/agent-variants/workItemBriefing.js.map +1 -1
- package/dist/agent-variants/workerRuntime.d.ts +1 -137
- package/dist/agent-variants/workerRuntime.d.ts.map +1 -1
- package/dist/agent-variants/workerRuntime.js +8 -147
- package/dist/agent-variants/workerRuntime.js.map +1 -1
- package/dist/cli/browser.d.ts +0 -1
- package/dist/cli/browser.d.ts.map +1 -1
- package/dist/cli/browser.js +0 -1
- package/dist/cli/browser.js.map +1 -1
- package/dist/cli/callerRunnerPaths.d.ts +0 -50
- package/dist/cli/callerRunnerPaths.d.ts.map +1 -1
- package/dist/cli/callerRunnerPaths.js +0 -59
- package/dist/cli/callerRunnerPaths.js.map +1 -1
- package/dist/cli/client.d.ts +0 -18
- package/dist/cli/client.d.ts.map +1 -1
- package/dist/cli/client.js +0 -28
- package/dist/cli/client.js.map +1 -1
- package/dist/cli/commandNames.d.ts +0 -7
- package/dist/cli/commandNames.d.ts.map +1 -1
- package/dist/cli/commandNames.js +1 -7
- package/dist/cli/commandNames.js.map +1 -1
- package/dist/cli/commands/auth.d.ts +0 -6
- package/dist/cli/commands/auth.d.ts.map +1 -1
- package/dist/cli/commands/auth.js +0 -6
- package/dist/cli/commands/auth.js.map +1 -1
- package/dist/cli/commands/elementSelector.d.ts +0 -6
- package/dist/cli/commands/elementSelector.d.ts.map +1 -1
- package/dist/cli/commands/elementSelector.js +0 -7
- package/dist/cli/commands/elementSelector.js.map +1 -1
- package/dist/cli/commands/evidence.d.ts +0 -6
- package/dist/cli/commands/evidence.d.ts.map +1 -1
- package/dist/cli/commands/evidence.js +0 -6
- package/dist/cli/commands/evidence.js.map +1 -1
- package/dist/cli/commands/libraryOpen.d.ts +0 -1
- package/dist/cli/commands/libraryOpen.d.ts.map +1 -1
- package/dist/cli/commands/libraryOpen.js +0 -4
- package/dist/cli/commands/libraryOpen.js.map +1 -1
- package/dist/cli/commands/mcpServe.d.ts +0 -24
- package/dist/cli/commands/mcpServe.d.ts.map +1 -1
- package/dist/cli/commands/mcpServe.js +126 -106
- package/dist/cli/commands/mcpServe.js.map +1 -1
- package/dist/cli/commands/open.d.ts +0 -8
- package/dist/cli/commands/open.d.ts.map +1 -1
- package/dist/cli/commands/open.js +0 -57
- package/dist/cli/commands/open.js.map +1 -1
- package/dist/cli/commands/profile.d.ts +3 -0
- package/dist/cli/commands/profile.d.ts.map +1 -0
- package/dist/cli/commands/profile.js +192 -0
- package/dist/cli/commands/profile.js.map +1 -0
- package/dist/cli/commands/reference.d.ts +0 -5
- package/dist/cli/commands/reference.d.ts.map +1 -1
- package/dist/cli/commands/reference.js +4 -27
- package/dist/cli/commands/reference.js.map +1 -1
- package/dist/cli/commands/serve.d.ts +0 -5
- package/dist/cli/commands/serve.d.ts.map +1 -1
- package/dist/cli/commands/serve.js +0 -34
- package/dist/cli/commands/serve.js.map +1 -1
- package/dist/cli/commands/shared.d.ts +0 -16
- package/dist/cli/commands/shared.d.ts.map +1 -1
- package/dist/cli/commands/shared.js +0 -19
- package/dist/cli/commands/shared.js.map +1 -1
- package/dist/cli/commands/status.d.ts +0 -6
- package/dist/cli/commands/status.d.ts.map +1 -1
- package/dist/cli/commands/status.js +0 -11
- package/dist/cli/commands/status.js.map +1 -1
- package/dist/cli/commands/stop.d.ts +0 -5
- package/dist/cli/commands/stop.d.ts.map +1 -1
- package/dist/cli/commands/stop.js +0 -6
- package/dist/cli/commands/stop.js.map +1 -1
- package/dist/cli/commands/update.d.ts +0 -1
- package/dist/cli/commands/update.d.ts.map +1 -1
- package/dist/cli/commands/update.js +0 -1
- package/dist/cli/commands/update.js.map +1 -1
- package/dist/cli/commands/variants.d.ts +0 -1
- package/dist/cli/commands/variants.d.ts.map +1 -1
- package/dist/cli/commands/variants.js +13 -32
- package/dist/cli/commands/variants.js.map +1 -1
- package/dist/cli/commands/wait.d.ts +0 -21
- package/dist/cli/commands/wait.d.ts.map +1 -1
- package/dist/cli/commands/wait.js +0 -23
- package/dist/cli/commands/wait.js.map +1 -1
- package/dist/cli/entry.d.ts +0 -10
- package/dist/cli/entry.d.ts.map +1 -1
- package/dist/cli/entry.js +0 -13
- package/dist/cli/entry.js.map +1 -1
- package/dist/cli/envelope.d.ts +1 -25
- package/dist/cli/envelope.d.ts.map +1 -1
- package/dist/cli/envelope.js +0 -19
- package/dist/cli/envelope.js.map +1 -1
- package/dist/cli/flags.d.ts +0 -7
- package/dist/cli/flags.d.ts.map +1 -1
- package/dist/cli/flags.js +0 -7
- package/dist/cli/flags.js.map +1 -1
- package/dist/cli/handoff.d.ts +0 -33
- package/dist/cli/handoff.d.ts.map +1 -1
- package/dist/cli/handoff.js +0 -42
- package/dist/cli/handoff.js.map +1 -1
- package/dist/cli/handoffStore.d.ts +0 -11
- package/dist/cli/handoffStore.d.ts.map +1 -1
- package/dist/cli/handoffStore.js +0 -10
- package/dist/cli/handoffStore.js.map +1 -1
- package/dist/cli/hostWorkNextAction.d.ts +0 -11
- package/dist/cli/hostWorkNextAction.d.ts.map +1 -1
- package/dist/cli/hostWorkNextAction.js +0 -4
- package/dist/cli/hostWorkNextAction.js.map +1 -1
- package/dist/cli/io.d.ts +0 -9
- package/dist/cli/io.d.ts.map +1 -1
- package/dist/cli/io.js +0 -1
- package/dist/cli/io.js.map +1 -1
- package/dist/cli/resolveDefaultNodeEnv.d.ts +0 -5
- package/dist/cli/resolveDefaultNodeEnv.d.ts.map +1 -1
- package/dist/cli/resolveDefaultNodeEnv.js +0 -5
- package/dist/cli/resolveDefaultNodeEnv.js.map +1 -1
- package/dist/cli/router.d.ts +0 -21
- package/dist/cli/router.d.ts.map +1 -1
- package/dist/cli/router.js +8 -46
- package/dist/cli/router.js.map +1 -1
- package/dist/cli/runnerSelection.d.ts +0 -58
- package/dist/cli/runnerSelection.d.ts.map +1 -1
- package/dist/cli/runnerSelection.js +0 -16
- package/dist/cli/runnerSelection.js.map +1 -1
- package/dist/cli/serverHandshake.d.ts +0 -36
- package/dist/cli/serverHandshake.d.ts.map +1 -1
- package/dist/cli/serverHandshake.js +0 -29
- package/dist/cli/serverHandshake.js.map +1 -1
- package/dist/cli/serverUnavailable.d.ts +0 -1
- package/dist/cli/serverUnavailable.d.ts.map +1 -1
- package/dist/cli/serverUnavailable.js +0 -1
- package/dist/cli/serverUnavailable.js.map +1 -1
- package/dist/cli/serverVersion.d.ts +0 -22
- package/dist/cli/serverVersion.d.ts.map +1 -1
- package/dist/cli/serverVersion.js +0 -12
- package/dist/cli/serverVersion.js.map +1 -1
- package/dist/cli/telemetry.d.ts +0 -4
- package/dist/cli/telemetry.d.ts.map +1 -1
- package/dist/cli/telemetry.js +0 -4
- package/dist/cli/telemetry.js.map +1 -1
- package/dist/config/evaluateFlags.d.ts +0 -4
- package/dist/config/evaluateFlags.d.ts.map +1 -1
- package/dist/config/evaluateFlags.js +0 -11
- package/dist/config/evaluateFlags.js.map +1 -1
- package/dist/config/featureFlagUserKey.d.ts +0 -3
- package/dist/config/featureFlagUserKey.d.ts.map +1 -1
- package/dist/config/featureFlagUserKey.js +0 -3
- package/dist/config/featureFlagUserKey.js.map +1 -1
- package/dist/config/flags.d.ts +0 -14
- package/dist/config/flags.d.ts.map +1 -1
- package/dist/config/flags.js +0 -27
- package/dist/config/flags.js.map +1 -1
- package/dist/config/proxy.d.ts +0 -3
- package/dist/config/proxy.d.ts.map +1 -1
- package/dist/config/proxy.js +0 -11
- package/dist/config/proxy.js.map +1 -1
- package/dist/config/telemetry.d.ts +0 -13
- package/dist/config/telemetry.d.ts.map +1 -1
- package/dist/config/telemetry.js +0 -13
- package/dist/config/telemetry.js.map +1 -1
- package/dist/config/telemetryContract.d.ts +0 -1
- package/dist/config/telemetryContract.d.ts.map +1 -1
- package/dist/config/telemetryContract.js +0 -1
- package/dist/config/telemetryContract.js.map +1 -1
- package/dist/hosts/workerDefaults.d.ts +0 -69
- package/dist/hosts/workerDefaults.d.ts.map +1 -1
- package/dist/hosts/workerDefaults.js +0 -68
- package/dist/hosts/workerDefaults.js.map +1 -1
- package/dist/index-core.d.ts.map +1 -1
- package/dist/index-core.js +0 -2
- package/dist/index-core.js.map +1 -1
- package/dist/index.d.ts +0 -20
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -105
- package/dist/index.js.map +1 -1
- package/dist/install/allowlists.d.ts +0 -32
- package/dist/install/allowlists.d.ts.map +1 -1
- package/dist/install/allowlists.js +0 -44
- package/dist/install/allowlists.js.map +1 -1
- package/dist/install/automaticCliUpdate.d.ts +0 -6
- package/dist/install/automaticCliUpdate.d.ts.map +1 -1
- package/dist/install/automaticCliUpdate.js +0 -13
- package/dist/install/automaticCliUpdate.js.map +1 -1
- package/dist/install/channelCli.d.ts +0 -1
- package/dist/install/channelCli.d.ts.map +1 -1
- package/dist/install/channelCli.js +0 -3
- package/dist/install/channelCli.js.map +1 -1
- package/dist/install/channelManager.d.ts +0 -14
- package/dist/install/channelManager.d.ts.map +1 -1
- package/dist/install/channelManager.js +0 -22
- package/dist/install/channelManager.js.map +1 -1
- package/dist/install/codexGuidance.d.ts +0 -1
- package/dist/install/codexGuidance.d.ts.map +1 -1
- package/dist/install/codexGuidance.js +0 -7
- package/dist/install/codexGuidance.js.map +1 -1
- package/dist/install/globalBootstrap.d.ts +0 -25
- package/dist/install/globalBootstrap.d.ts.map +1 -1
- package/dist/install/globalBootstrap.js +0 -10
- package/dist/install/globalBootstrap.js.map +1 -1
- package/dist/install/harnesses.d.ts +0 -66
- package/dist/install/harnesses.d.ts.map +1 -1
- package/dist/install/harnesses.js +0 -60
- package/dist/install/harnesses.js.map +1 -1
- package/dist/install/installationChannel.d.ts +0 -1
- package/dist/install/installationChannel.d.ts.map +1 -1
- package/dist/install/installationChannel.js +0 -1
- package/dist/install/installationChannel.js.map +1 -1
- package/dist/install/legacyMcp.d.ts +0 -23
- package/dist/install/legacyMcp.d.ts.map +1 -1
- package/dist/install/legacyMcp.js +3 -46
- package/dist/install/legacyMcp.js.map +1 -1
- package/dist/install/mcpRegistration.d.ts +0 -41
- package/dist/install/mcpRegistration.d.ts.map +1 -1
- package/dist/install/mcpRegistration.js +2 -70
- package/dist/install/mcpRegistration.js.map +1 -1
- package/dist/library/HubClient.d.ts +1 -2
- package/dist/library/HubClient.d.ts.map +1 -1
- package/dist/library/HubClient.js +11 -5
- package/dist/library/HubClient.js.map +1 -1
- package/dist/library/HubServer.d.ts +0 -1
- package/dist/library/HubServer.d.ts.map +1 -1
- package/dist/library/HubServer.js +19 -1
- package/dist/library/HubServer.js.map +1 -1
- package/dist/library/StaticPreviewServer.d.ts +0 -1
- package/dist/library/StaticPreviewServer.d.ts.map +1 -1
- package/dist/library/StaticPreviewServer.js +0 -1
- package/dist/library/StaticPreviewServer.js.map +1 -1
- package/dist/library/http.d.ts +0 -2
- package/dist/library/http.d.ts.map +1 -1
- package/dist/library/http.js +0 -2
- package/dist/library/http.js.map +1 -1
- package/dist/library/importFiles.d.ts +0 -6
- package/dist/library/importFiles.d.ts.map +1 -1
- package/dist/library/importFiles.js +45 -11
- package/dist/library/importFiles.js.map +1 -1
- package/dist/mcp/changeBatchClassification.d.ts +0 -40
- package/dist/mcp/changeBatchClassification.d.ts.map +1 -1
- package/dist/mcp/changeBatchClassification.js +0 -34
- package/dist/mcp/changeBatchClassification.js.map +1 -1
- package/dist/prompts/commentVariationPrompts.d.ts +0 -5
- package/dist/prompts/commentVariationPrompts.d.ts.map +1 -1
- package/dist/prompts/commentVariationPrompts.js +0 -5
- package/dist/prompts/commentVariationPrompts.js.map +1 -1
- package/dist/prototype-host.js +0 -15
- package/dist/prototype-host.js.map +1 -1
- package/dist/proxy-middleware/preview-bridge.d.ts +0 -2
- package/dist/proxy-middleware/preview-bridge.d.ts.map +1 -1
- package/dist/proxy-middleware/preview-bridge.js +0 -2
- package/dist/proxy-middleware/preview-bridge.js.map +1 -1
- package/dist/proxy-middleware/preview-connections.d.ts +0 -1
- package/dist/proxy-middleware/preview-connections.d.ts.map +1 -1
- package/dist/proxy-middleware/preview-connections.js +0 -1
- package/dist/proxy-middleware/preview-connections.js.map +1 -1
- package/dist/proxy-middleware/proxy-config.d.ts +0 -12
- package/dist/proxy-middleware/proxy-config.d.ts.map +1 -1
- package/dist/proxy-middleware/proxy-config.js +2 -49
- package/dist/proxy-middleware/proxy-config.js.map +1 -1
- package/dist/routes/account.d.ts +0 -1
- package/dist/routes/account.d.ts.map +1 -1
- package/dist/routes/account.js +0 -2
- package/dist/routes/account.js.map +1 -1
- package/dist/routes/agentVariants.d.ts +0 -15
- package/dist/routes/agentVariants.d.ts.map +1 -1
- package/dist/routes/agentVariants.js +132 -329
- package/dist/routes/agentVariants.js.map +1 -1
- package/dist/routes/cli.d.ts +0 -17
- package/dist/routes/cli.d.ts.map +1 -1
- package/dist/routes/cli.js +0 -13
- package/dist/routes/cli.js.map +1 -1
- package/dist/routes/emptyStatePage.d.ts +0 -12
- package/dist/routes/emptyStatePage.d.ts.map +1 -1
- package/dist/routes/emptyStatePage.js +0 -12
- package/dist/routes/emptyStatePage.js.map +1 -1
- package/dist/routes/git.d.ts.map +1 -1
- package/dist/routes/git.js +0 -13
- package/dist/routes/git.js.map +1 -1
- package/dist/routes/inlineStartTracker.d.ts +0 -16
- package/dist/routes/inlineStartTracker.d.ts.map +1 -1
- package/dist/routes/inlineStartTracker.js.map +1 -1
- package/dist/routes/integrations.d.ts +0 -6
- package/dist/routes/integrations.d.ts.map +1 -1
- package/dist/routes/integrations.js +0 -6
- package/dist/routes/integrations.js.map +1 -1
- package/dist/routes/library/app.d.ts +0 -1
- package/dist/routes/library/app.d.ts.map +1 -1
- package/dist/routes/library/app.js +1 -3
- package/dist/routes/library/app.js.map +1 -1
- package/dist/routes/library/index.d.ts +0 -1
- package/dist/routes/library/index.d.ts.map +1 -1
- package/dist/routes/library/index.js +3 -1
- package/dist/routes/library/index.js.map +1 -1
- package/dist/routes/library/middleware.d.ts +0 -3
- package/dist/routes/library/middleware.d.ts.map +1 -1
- package/dist/routes/library/middleware.js +0 -4
- package/dist/routes/library/middleware.js.map +1 -1
- package/dist/routes/library/navigation.d.ts +0 -1
- package/dist/routes/library/navigation.d.ts.map +1 -1
- package/dist/routes/library/navigation.js +0 -1
- package/dist/routes/library/navigation.js.map +1 -1
- package/dist/routes/library/profiles.d.ts +5 -0
- package/dist/routes/library/profiles.d.ts.map +1 -0
- package/dist/routes/library/profiles.js +182 -0
- package/dist/routes/library/profiles.js.map +1 -0
- package/dist/routes/library/projects.d.ts +0 -1
- package/dist/routes/library/projects.d.ts.map +1 -1
- package/dist/routes/library/projects.js +0 -1
- package/dist/routes/library/projects.js.map +1 -1
- package/dist/routes/library/schemas.d.ts +2 -2
- package/dist/routes/library/staticPreview.d.ts +0 -1
- package/dist/routes/library/staticPreview.d.ts.map +1 -1
- package/dist/routes/library/staticPreview.js +0 -1
- package/dist/routes/library/staticPreview.js.map +1 -1
- package/dist/routes/library/types.d.ts +2 -0
- package/dist/routes/library/types.d.ts.map +1 -1
- package/dist/routes/library/variants.d.ts +0 -1
- package/dist/routes/library/variants.d.ts.map +1 -1
- package/dist/routes/library/variants.js +0 -1
- package/dist/routes/library/variants.js.map +1 -1
- package/dist/routes/mcp.d.ts +0 -3
- package/dist/routes/mcp.d.ts.map +1 -1
- package/dist/routes/mcp.js +0 -5
- package/dist/routes/mcp.js.map +1 -1
- package/dist/routes/prototypeHost.d.ts +0 -2
- package/dist/routes/prototypeHost.d.ts.map +1 -1
- package/dist/routes/prototypeHost.js +6 -32
- package/dist/routes/prototypeHost.js.map +1 -1
- package/dist/routes/static.d.ts +0 -3
- package/dist/routes/static.d.ts.map +1 -1
- package/dist/routes/static.js +0 -6
- package/dist/routes/static.js.map +1 -1
- package/dist/routes/support.d.ts +0 -3
- package/dist/routes/support.d.ts.map +1 -1
- package/dist/routes/support.js +0 -3
- package/dist/routes/support.js.map +1 -1
- package/dist/server.d.ts +0 -42
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +1 -129
- package/dist/server.js.map +1 -1
- package/dist/services/AuthService.d.ts +0 -76
- package/dist/services/AuthService.d.ts.map +1 -1
- package/dist/services/AuthService.js +0 -112
- package/dist/services/AuthService.js.map +1 -1
- package/dist/services/BrowserAgentClient.d.ts +1 -21
- package/dist/services/BrowserAgentClient.d.ts.map +1 -1
- package/dist/services/BrowserAgentClient.js +0 -10
- package/dist/services/BrowserAgentClient.js.map +1 -1
- package/dist/services/BundleStore.d.ts +0 -18
- package/dist/services/BundleStore.d.ts.map +1 -1
- package/dist/services/BundleStore.js +0 -10
- package/dist/services/BundleStore.js.map +1 -1
- package/dist/services/CliLogForwarder.d.ts +0 -26
- package/dist/services/CliLogForwarder.d.ts.map +1 -1
- package/dist/services/CliLogForwarder.js +1 -33
- package/dist/services/CliLogForwarder.js.map +1 -1
- package/dist/services/CommitMessageGenerator.d.ts +0 -6
- package/dist/services/CommitMessageGenerator.d.ts.map +1 -1
- package/dist/services/CommitMessageGenerator.js +0 -3
- package/dist/services/CommitMessageGenerator.js.map +1 -1
- package/dist/services/ComponentSearchService.d.ts +2 -16
- package/dist/services/ComponentSearchService.d.ts.map +1 -1
- package/dist/services/ComponentSearchService.js +2 -56
- package/dist/services/ComponentSearchService.js.map +1 -1
- package/dist/services/ConfigManager.d.ts +0 -113
- package/dist/services/ConfigManager.d.ts.map +1 -1
- package/dist/services/ConfigManager.js +0 -101
- package/dist/services/ConfigManager.js.map +1 -1
- package/dist/services/DependencyPreparationService.d.ts +0 -6
- package/dist/services/DependencyPreparationService.d.ts.map +1 -1
- package/dist/services/DependencyPreparationService.js +0 -22
- package/dist/services/DependencyPreparationService.js.map +1 -1
- package/dist/services/DevServerRuntimeService.d.ts +0 -20
- package/dist/services/DevServerRuntimeService.d.ts.map +1 -1
- package/dist/services/DevServerRuntimeService.js +0 -46
- package/dist/services/DevServerRuntimeService.js.map +1 -1
- package/dist/services/FeatureFlagService.d.ts +0 -15
- package/dist/services/FeatureFlagService.d.ts.map +1 -1
- package/dist/services/FeatureFlagService.js +0 -23
- package/dist/services/FeatureFlagService.js.map +1 -1
- package/dist/services/GatewayClient.d.ts +0 -27
- package/dist/services/GatewayClient.d.ts.map +1 -1
- package/dist/services/GatewayClient.js +0 -25
- package/dist/services/GatewayClient.js.map +1 -1
- package/dist/services/HistoryReplayService.d.ts +0 -31
- package/dist/services/HistoryReplayService.d.ts.map +1 -1
- package/dist/services/HistoryReplayService.js +2 -55
- package/dist/services/HistoryReplayService.js.map +1 -1
- package/dist/services/HubDiscovery.d.ts +0 -8
- package/dist/services/HubDiscovery.d.ts.map +1 -1
- package/dist/services/HubDiscovery.js +0 -8
- package/dist/services/HubDiscovery.js.map +1 -1
- package/dist/services/HubNavigation.d.ts +0 -6
- package/dist/services/HubNavigation.d.ts.map +1 -1
- package/dist/services/HubNavigation.js +5 -8
- package/dist/services/HubNavigation.js.map +1 -1
- package/dist/services/IntegrationsClient.d.ts +20 -38
- package/dist/services/IntegrationsClient.d.ts.map +1 -1
- package/dist/services/IntegrationsClient.js +71 -31
- package/dist/services/IntegrationsClient.js.map +1 -1
- package/dist/services/LocalGitService.d.ts +0 -57
- package/dist/services/LocalGitService.d.ts.map +1 -1
- package/dist/services/LocalGitService.js +4 -85
- package/dist/services/LocalGitService.js.map +1 -1
- package/dist/services/MCPOnboardingTelemetry.d.ts +0 -9
- package/dist/services/MCPOnboardingTelemetry.d.ts.map +1 -1
- package/dist/services/MCPOnboardingTelemetry.js +0 -9
- package/dist/services/MCPOnboardingTelemetry.js.map +1 -1
- package/dist/services/MCPVariantsTelemetry.d.ts +0 -2
- package/dist/services/MCPVariantsTelemetry.d.ts.map +1 -1
- package/dist/services/MCPVariantsTelemetry.js +0 -2
- package/dist/services/MCPVariantsTelemetry.js.map +1 -1
- package/dist/services/OperatingSystemServices.d.ts +0 -12
- package/dist/services/OperatingSystemServices.d.ts.map +1 -1
- package/dist/services/OperatingSystemServices.js +0 -7
- package/dist/services/OperatingSystemServices.js.map +1 -1
- package/dist/services/PRTitleGenerator.d.ts +0 -7
- package/dist/services/PRTitleGenerator.d.ts.map +1 -1
- package/dist/services/PRTitleGenerator.js +0 -3
- package/dist/services/PRTitleGenerator.js.map +1 -1
- package/dist/services/ProjectCardPreviews.d.ts +0 -5
- package/dist/services/ProjectCardPreviews.d.ts.map +1 -1
- package/dist/services/ProjectCardPreviews.js +0 -5
- package/dist/services/ProjectCardPreviews.js.map +1 -1
- package/dist/services/ProjectDetectionService.d.ts +0 -4
- package/dist/services/ProjectDetectionService.d.ts.map +1 -1
- package/dist/services/ProjectDetectionService.js +2 -44
- package/dist/services/ProjectDetectionService.js.map +1 -1
- package/dist/services/ProjectFolderPicker.d.ts +0 -3
- package/dist/services/ProjectFolderPicker.d.ts.map +1 -1
- package/dist/services/ProjectFolderPicker.js +0 -4
- package/dist/services/ProjectFolderPicker.js.map +1 -1
- package/dist/services/ProjectImport.d.ts +0 -1
- package/dist/services/ProjectImport.d.ts.map +1 -1
- package/dist/services/ProjectImport.js +0 -3
- package/dist/services/ProjectImport.js.map +1 -1
- package/dist/services/ProjectLibrary.d.ts +0 -18
- package/dist/services/ProjectLibrary.d.ts.map +1 -1
- package/dist/services/ProjectLibrary.js +0 -20
- package/dist/services/ProjectLibrary.js.map +1 -1
- package/dist/services/ProjectMetadataStore.d.ts +0 -73
- package/dist/services/ProjectMetadataStore.d.ts.map +1 -1
- package/dist/services/ProjectMetadataStore.js +0 -90
- package/dist/services/ProjectMetadataStore.js.map +1 -1
- package/dist/services/ProjectPackageManager.d.ts +0 -12
- package/dist/services/ProjectPackageManager.d.ts.map +1 -1
- package/dist/services/ProjectPackageManager.js +0 -16
- package/dist/services/ProjectPackageManager.js.map +1 -1
- package/dist/services/ProjectRegistry.d.ts +2 -18
- package/dist/services/ProjectRegistry.d.ts.map +1 -1
- package/dist/services/ProjectRegistry.js +0 -18
- package/dist/services/ProjectRegistry.js.map +1 -1
- package/dist/services/ProjectRuntimeService.d.ts +0 -4
- package/dist/services/ProjectRuntimeService.d.ts.map +1 -1
- package/dist/services/ProjectRuntimeService.js +0 -5
- package/dist/services/ProjectRuntimeService.js.map +1 -1
- package/dist/services/ProjectScreenshotService.d.ts +0 -5
- package/dist/services/ProjectScreenshotService.d.ts.map +1 -1
- package/dist/services/ProjectScreenshotService.js +0 -6
- package/dist/services/ProjectScreenshotService.js.map +1 -1
- package/dist/services/ProjectStorage.d.ts +0 -4
- package/dist/services/ProjectStorage.d.ts.map +1 -1
- package/dist/services/ProjectStorage.js +0 -4
- package/dist/services/ProjectStorage.js.map +1 -1
- package/dist/services/PrototypeBuildService.d.ts +1 -23
- package/dist/services/PrototypeBuildService.d.ts.map +1 -1
- package/dist/services/PrototypeBuildService.js +6 -31
- package/dist/services/PrototypeBuildService.js.map +1 -1
- package/dist/services/PrototypeDeployService.d.ts +0 -20
- package/dist/services/PrototypeDeployService.d.ts.map +1 -1
- package/dist/services/PrototypeDeployService.js +1 -24
- package/dist/services/PrototypeDeployService.js.map +1 -1
- package/dist/services/RequestAuthContext.d.ts +0 -5
- package/dist/services/RequestAuthContext.d.ts.map +1 -1
- package/dist/services/RequestAuthContext.js +0 -5
- package/dist/services/RequestAuthContext.js.map +1 -1
- package/dist/services/SessionBridgeService.d.ts.map +1 -1
- package/dist/services/SessionBridgeService.js +0 -2
- package/dist/services/SessionBridgeService.js.map +1 -1
- package/dist/services/SessionService.d.ts +0 -4
- package/dist/services/SessionService.d.ts.map +1 -1
- package/dist/services/SessionService.js +1 -22
- package/dist/services/SessionService.js.map +1 -1
- package/dist/services/StaticFileService.d.ts +0 -9
- package/dist/services/StaticFileService.d.ts.map +1 -1
- package/dist/services/StaticFileService.js +0 -11
- package/dist/services/StaticFileService.js.map +1 -1
- package/dist/services/StaticLibraryPreviews.d.ts +0 -3
- package/dist/services/StaticLibraryPreviews.d.ts.map +1 -1
- package/dist/services/StaticLibraryPreviews.js +0 -3
- package/dist/services/StaticLibraryPreviews.js.map +1 -1
- package/dist/services/StaticPreviewServer.d.ts +0 -16
- package/dist/services/StaticPreviewServer.d.ts.map +1 -1
- package/dist/services/StaticPreviewServer.js +2 -28
- package/dist/services/StaticPreviewServer.js.map +1 -1
- package/dist/services/SupabaseAuthService.d.ts +0 -11
- package/dist/services/SupabaseAuthService.d.ts.map +1 -1
- package/dist/services/SupabaseAuthService.js +0 -11
- package/dist/services/SupabaseAuthService.js.map +1 -1
- package/dist/services/SupportTicketService.d.ts +0 -4
- package/dist/services/SupportTicketService.d.ts.map +1 -1
- package/dist/services/SupportTicketService.js +0 -4
- package/dist/services/SupportTicketService.js.map +1 -1
- package/dist/services/TelemetryService.d.ts +9 -182
- package/dist/services/TelemetryService.d.ts.map +1 -1
- package/dist/services/TelemetryService.js +11 -195
- package/dist/services/TelemetryService.js.map +1 -1
- package/dist/services/TreeStore.d.ts +0 -72
- package/dist/services/TreeStore.d.ts.map +1 -1
- package/dist/services/TreeStore.js +0 -93
- package/dist/services/TreeStore.js.map +1 -1
- package/dist/services/VariantGenerationService.d.ts +1 -32
- package/dist/services/VariantGenerationService.d.ts.map +1 -1
- package/dist/services/VariantGenerationService.js +36 -66
- package/dist/services/VariantGenerationService.js.map +1 -1
- package/dist/services/VariantHistoryService.d.ts +12 -114
- package/dist/services/VariantHistoryService.d.ts.map +1 -1
- package/dist/services/VariantHistoryService.js +56 -144
- package/dist/services/VariantHistoryService.js.map +1 -1
- package/dist/services/VariantRunService.d.ts +6 -31
- package/dist/services/VariantRunService.d.ts.map +1 -1
- package/dist/services/VariantRunService.js +86 -37
- package/dist/services/VariantRunService.js.map +1 -1
- package/dist/services/VariantsRuntime.d.ts +0 -3
- package/dist/services/VariantsRuntime.d.ts.map +1 -1
- package/dist/services/VariantsRuntime.js +2 -5
- package/dist/services/VariantsRuntime.js.map +1 -1
- package/dist/services/WorktreeManager.d.ts +0 -217
- package/dist/services/WorktreeManager.d.ts.map +1 -1
- package/dist/services/WorktreeManager.js +3 -321
- package/dist/services/WorktreeManager.js.map +1 -1
- package/dist/services/accessTokenRefresh.d.ts +0 -25
- package/dist/services/accessTokenRefresh.d.ts.map +1 -1
- package/dist/services/accessTokenRefresh.js +0 -25
- package/dist/services/accessTokenRefresh.js.map +1 -1
- package/dist/services/adapters/TailwindTokenAdapter.d.ts +0 -29
- package/dist/services/adapters/TailwindTokenAdapter.d.ts.map +1 -1
- package/dist/services/adapters/TailwindTokenAdapter.js +1 -46
- package/dist/services/adapters/TailwindTokenAdapter.js.map +1 -1
- package/dist/services/createAgentVariantsOrchestrator.d.ts +0 -18
- package/dist/services/createAgentVariantsOrchestrator.d.ts.map +1 -1
- package/dist/services/createAgentVariantsOrchestrator.js +0 -22
- package/dist/services/createAgentVariantsOrchestrator.js.map +1 -1
- package/dist/services/extractors/CSSVariableExtractor.d.ts +0 -25
- package/dist/services/extractors/CSSVariableExtractor.d.ts.map +1 -1
- package/dist/services/extractors/CSSVariableExtractor.js +1 -42
- package/dist/services/extractors/CSSVariableExtractor.js.map +1 -1
- package/dist/services/historyRoots.d.ts +0 -12
- package/dist/services/historyRoots.d.ts.map +1 -1
- package/dist/services/historyRoots.js +0 -13
- package/dist/services/historyRoots.js.map +1 -1
- package/dist/services/libraryErrors.d.ts +0 -1
- package/dist/services/libraryErrors.d.ts.map +1 -1
- package/dist/services/libraryErrors.js +0 -1
- package/dist/services/libraryErrors.js.map +1 -1
- package/dist/services/pendingLogin.d.ts +0 -13
- package/dist/services/pendingLogin.d.ts.map +1 -1
- package/dist/services/pendingLogin.js +0 -3
- package/dist/services/pendingLogin.js.map +1 -1
- package/dist/services/profiles/DesignProfiles.d.ts +446 -0
- package/dist/services/profiles/DesignProfiles.d.ts.map +1 -0
- package/dist/services/profiles/DesignProfiles.js +552 -0
- package/dist/services/profiles/DesignProfiles.js.map +1 -0
- package/dist/services/profiles/MemoryModelService.d.ts +14 -0
- package/dist/services/profiles/MemoryModelService.d.ts.map +1 -0
- package/dist/services/profiles/MemoryModelService.js +113 -0
- package/dist/services/profiles/MemoryModelService.js.map +1 -0
- package/dist/services/profiles/MemoryRuntime.d.ts +26 -0
- package/dist/services/profiles/MemoryRuntime.d.ts.map +1 -0
- package/dist/services/profiles/MemoryRuntime.js +192 -0
- package/dist/services/profiles/MemoryRuntime.js.map +1 -0
- package/dist/services/profiles/ProfileAgent.d.ts +20 -0
- package/dist/services/profiles/ProfileAgent.d.ts.map +1 -0
- package/dist/services/profiles/ProfileAgent.js +196 -0
- package/dist/services/profiles/ProfileAgent.js.map +1 -0
- package/dist/services/profiles/ProfileAnalysis.d.ts +23 -0
- package/dist/services/profiles/ProfileAnalysis.d.ts.map +1 -0
- package/dist/services/profiles/ProfileAnalysis.js +114 -0
- package/dist/services/profiles/ProfileAnalysis.js.map +1 -0
- package/dist/services/profiles/ProfileImportSchedule.d.ts +15 -0
- package/dist/services/profiles/ProfileImportSchedule.d.ts.map +1 -0
- package/dist/services/profiles/ProfileImportSchedule.js +40 -0
- package/dist/services/profiles/ProfileImportSchedule.js.map +1 -0
- package/dist/services/profiles/ProfileImports.d.ts +47 -0
- package/dist/services/profiles/ProfileImports.d.ts.map +1 -0
- package/dist/services/profiles/ProfileImports.js +248 -0
- package/dist/services/profiles/ProfileImports.js.map +1 -0
- package/dist/services/profiles/ProfileIndex.d.ts +18 -0
- package/dist/services/profiles/ProfileIndex.d.ts.map +1 -0
- package/dist/services/profiles/ProfileIndex.js +119 -0
- package/dist/services/profiles/ProfileIndex.js.map +1 -0
- package/dist/services/profiles/ProfileMedia.d.ts +10 -0
- package/dist/services/profiles/ProfileMedia.d.ts.map +1 -0
- package/dist/services/profiles/ProfileMedia.js +76 -0
- package/dist/services/profiles/ProfileMedia.js.map +1 -0
- package/dist/services/profiles/ProfilePreparation.d.ts +17 -0
- package/dist/services/profiles/ProfilePreparation.d.ts.map +1 -0
- package/dist/services/profiles/ProfilePreparation.js +214 -0
- package/dist/services/profiles/ProfilePreparation.js.map +1 -0
- package/dist/services/profiles/ProfileVariants.d.ts +33 -0
- package/dist/services/profiles/ProfileVariants.d.ts.map +1 -0
- package/dist/services/profiles/ProfileVariants.js +129 -0
- package/dist/services/profiles/ProfileVariants.js.map +1 -0
- package/dist/services/profiles/analysisBatch.d.ts +53 -0
- package/dist/services/profiles/analysisBatch.d.ts.map +1 -0
- package/dist/services/profiles/analysisBatch.js +86 -0
- package/dist/services/profiles/analysisBatch.js.map +1 -0
- package/dist/services/profiles/boardPage.d.ts +12 -0
- package/dist/services/profiles/boardPage.d.ts.map +1 -0
- package/dist/services/profiles/boardPage.js +156 -0
- package/dist/services/profiles/boardPage.js.map +1 -0
- package/dist/services/profiles/engineAccess.d.ts +2 -0
- package/dist/services/profiles/engineAccess.d.ts.map +1 -0
- package/dist/services/profiles/engineAccess.js +55 -0
- package/dist/services/profiles/engineAccess.js.map +1 -0
- package/dist/services/profiles/memoryComponents.d.ts +7 -0
- package/dist/services/profiles/memoryComponents.d.ts.map +1 -0
- package/dist/services/profiles/memoryComponents.js +105 -0
- package/dist/services/profiles/memoryComponents.js.map +1 -0
- package/dist/services/profiles/modelContract.d.ts +14 -0
- package/dist/services/profiles/modelContract.d.ts.map +1 -0
- package/dist/services/profiles/modelContract.js +124 -0
- package/dist/services/profiles/modelContract.js.map +1 -0
- package/dist/services/profiles/nativeImages.d.ts +3 -0
- package/dist/services/profiles/nativeImages.d.ts.map +1 -0
- package/dist/services/profiles/nativeImages.js +72 -0
- package/dist/services/profiles/nativeImages.js.map +1 -0
- package/dist/services/profiles/profileAccount.d.ts +4 -0
- package/dist/services/profiles/profileAccount.d.ts.map +1 -0
- package/dist/services/profiles/profileAccount.js +21 -0
- package/dist/services/profiles/profileAccount.js.map +1 -0
- package/dist/services/profiles/profileContext.d.ts +18 -0
- package/dist/services/profiles/profileContext.d.ts.map +1 -0
- package/dist/services/profiles/profileContext.js +189 -0
- package/dist/services/profiles/profileContext.js.map +1 -0
- package/dist/services/profiles/profileEvidence.d.ts +3 -0
- package/dist/services/profiles/profileEvidence.d.ts.map +1 -0
- package/dist/services/profiles/profileEvidence.js +15 -0
- package/dist/services/profiles/profileEvidence.js.map +1 -0
- package/dist/services/profiles/profileQueries.d.ts +2 -0
- package/dist/services/profiles/profileQueries.d.ts.map +1 -0
- package/dist/services/profiles/profileQueries.js +23 -0
- package/dist/services/profiles/profileQueries.js.map +1 -0
- package/dist/services/profiles/profileSelection.d.ts +29 -0
- package/dist/services/profiles/profileSelection.d.ts.map +1 -0
- package/dist/services/profiles/profileSelection.js +43 -0
- package/dist/services/profiles/profileSelection.js.map +1 -0
- package/dist/services/profiles/xPage.d.ts +4 -0
- package/dist/services/profiles/xPage.d.ts.map +1 -0
- package/dist/services/profiles/xPage.js +58 -0
- package/dist/services/profiles/xPage.js.map +1 -0
- package/dist/services/referenceImages.d.ts +17 -0
- package/dist/services/referenceImages.d.ts.map +1 -0
- package/dist/services/referenceImages.js +138 -0
- package/dist/services/referenceImages.js.map +1 -0
- package/dist/services/staticProjectTarget.d.ts +0 -4
- package/dist/services/staticProjectTarget.d.ts.map +1 -1
- package/dist/services/staticProjectTarget.js +0 -4
- package/dist/services/staticProjectTarget.js.map +1 -1
- package/dist/services/staticStarter.d.ts +0 -20
- package/dist/services/staticStarter.d.ts.map +1 -1
- package/dist/services/staticStarter.js +0 -20
- package/dist/services/staticStarter.js.map +1 -1
- package/dist/services/templates/designCatalog.d.ts +0 -11
- package/dist/services/templates/designCatalog.d.ts.map +1 -1
- package/dist/services/templates/designCatalog.js +0 -26
- package/dist/services/templates/designCatalog.js.map +1 -1
- package/dist/services/templates/viteReactTs.d.ts +0 -26
- package/dist/services/templates/viteReactTs.d.ts.map +1 -1
- package/dist/services/templates/viteReactTs.js +0 -20
- package/dist/services/templates/viteReactTs.js.map +1 -1
- package/dist/storage/library/BundleMetadataStore.d.ts +0 -16
- package/dist/storage/library/BundleMetadataStore.d.ts.map +1 -1
- package/dist/storage/library/BundleMetadataStore.js +0 -17
- package/dist/storage/library/BundleMetadataStore.js.map +1 -1
- package/dist/storage/library/CoordinatorRecords.d.ts +0 -9
- package/dist/storage/library/CoordinatorRecords.d.ts.map +1 -1
- package/dist/storage/library/CoordinatorRecords.js +0 -9
- package/dist/storage/library/CoordinatorRecords.js.map +1 -1
- package/dist/storage/library/ProjectPreviewCache.d.ts +0 -4
- package/dist/storage/library/ProjectPreviewCache.d.ts.map +1 -1
- package/dist/storage/library/ProjectPreviewCache.js +0 -4
- package/dist/storage/library/ProjectPreviewCache.js.map +1 -1
- package/dist/storage/library/ProjectRecords.d.ts +0 -17
- package/dist/storage/library/ProjectRecords.d.ts.map +1 -1
- package/dist/storage/library/ProjectRecords.js +0 -17
- package/dist/storage/library/ProjectRecords.js.map +1 -1
- package/dist/storage/library/database.d.ts +0 -3
- package/dist/storage/library/database.d.ts.map +1 -1
- package/dist/storage/library/database.js +0 -3
- package/dist/storage/library/database.js.map +1 -1
- package/dist/storage/library/migrations.d.ts +0 -2
- package/dist/storage/library/migrations.d.ts.map +1 -1
- package/dist/storage/library/migrations.js +0 -2
- package/dist/storage/library/migrations.js.map +1 -1
- package/dist/storage/library/sourcePresentation.d.ts +0 -1
- package/dist/storage/library/sourcePresentation.d.ts.map +1 -1
- package/dist/storage/library/sourcePresentation.js +0 -1
- package/dist/storage/library/sourcePresentation.js.map +1 -1
- package/dist/storage/profiles/ProfileRecords.d.ts +199 -0
- package/dist/storage/profiles/ProfileRecords.d.ts.map +1 -0
- package/dist/storage/profiles/ProfileRecords.js +659 -0
- package/dist/storage/profiles/ProfileRecords.js.map +1 -0
- package/dist/storage/profiles/contextReceipts.d.ts +14 -0
- package/dist/storage/profiles/contextReceipts.d.ts.map +1 -0
- package/dist/storage/profiles/contextReceipts.js +52 -0
- package/dist/storage/profiles/contextReceipts.js.map +1 -0
- package/dist/storage/profiles/migrations.d.ts +4 -0
- package/dist/storage/profiles/migrations.d.ts.map +1 -0
- package/dist/storage/profiles/migrations.js +41 -0
- package/dist/storage/profiles/migrations.js.map +1 -0
- package/dist/storage/profiles/schema.d.ts +961 -0
- package/dist/storage/profiles/schema.d.ts.map +1 -0
- package/dist/storage/profiles/schema.js +102 -0
- package/dist/storage/profiles/schema.js.map +1 -0
- package/dist/storage/project-metadata/ProjectMetadataRecords.d.ts +0 -11
- package/dist/storage/project-metadata/ProjectMetadataRecords.d.ts.map +1 -1
- package/dist/storage/project-metadata/ProjectMetadataRecords.js +0 -13
- package/dist/storage/project-metadata/ProjectMetadataRecords.js.map +1 -1
- package/dist/storage/project-metadata/database.d.ts +0 -1
- package/dist/storage/project-metadata/database.d.ts.map +1 -1
- package/dist/storage/project-metadata/database.js +0 -7
- package/dist/storage/project-metadata/database.js.map +1 -1
- package/dist/storage/project-metadata/migrations.d.ts +0 -42
- package/dist/storage/project-metadata/migrations.d.ts.map +1 -1
- package/dist/storage/project-metadata/migrations.js +0 -41
- package/dist/storage/project-metadata/migrations.js.map +1 -1
- package/dist/types/account.d.ts +0 -1
- package/dist/types/account.d.ts.map +1 -1
- package/dist/types/change-request-types.d.ts +5 -167
- package/dist/types/change-request-types.d.ts.map +1 -1
- package/dist/types/change-types.d.ts +0 -1
- package/dist/types/change-types.d.ts.map +1 -1
- package/dist/types/change-types.js +0 -1
- package/dist/types/change-types.js.map +1 -1
- package/dist/types/design-profile.d.ts +570 -0
- package/dist/types/design-profile.d.ts.map +1 -0
- package/dist/types/design-profile.js +127 -0
- package/dist/types/design-profile.js.map +1 -0
- package/dist/types/project-library.d.ts +0 -1
- package/dist/types/project-library.d.ts.map +1 -1
- package/dist/types/style-manipulation-types.d.ts +0 -69
- package/dist/types/style-manipulation-types.d.ts.map +1 -1
- package/dist/types/style-manipulation-types.js +0 -26
- package/dist/types/style-manipulation-types.js.map +1 -1
- package/dist/types/token-types.d.ts +0 -30
- package/dist/types/token-types.d.ts.map +1 -1
- package/dist/types/token-types.js +0 -1
- package/dist/types/token-types.js.map +1 -1
- package/dist/types/variant-history.d.ts +3 -39
- package/dist/types/variant-history.d.ts.map +1 -1
- package/dist/types/variant-reference.d.ts +46 -0
- package/dist/types/variant-reference.d.ts.map +1 -0
- package/dist/types/variant-reference.js +58 -0
- package/dist/types/variant-reference.js.map +1 -0
- package/dist/types/x-bookmarks.d.ts +352 -0
- package/dist/types/x-bookmarks.d.ts.map +1 -0
- package/dist/types/x-bookmarks.js +56 -0
- package/dist/types/x-bookmarks.js.map +1 -0
- package/dist/utils/ProviderRateLimit.d.ts +7 -0
- package/dist/utils/ProviderRateLimit.d.ts.map +1 -0
- package/dist/utils/ProviderRateLimit.js +36 -0
- package/dist/utils/ProviderRateLimit.js.map +1 -0
- package/dist/utils/branchNames.d.ts +0 -1
- package/dist/utils/branchNames.d.ts.map +1 -1
- package/dist/utils/branchNames.js +0 -2
- package/dist/utils/branchNames.js.map +1 -1
- package/dist/utils/cloneOrCopyDirSync.d.ts +0 -12
- package/dist/utils/cloneOrCopyDirSync.d.ts.map +1 -1
- package/dist/utils/cloneOrCopyDirSync.js +0 -16
- package/dist/utils/cloneOrCopyDirSync.js.map +1 -1
- package/dist/utils/devServerCommand.d.ts +0 -23
- package/dist/utils/devServerCommand.d.ts.map +1 -1
- package/dist/utils/devServerCommand.js +0 -24
- package/dist/utils/devServerCommand.js.map +1 -1
- package/dist/utils/devServerError.d.ts +0 -16
- package/dist/utils/devServerError.d.ts.map +1 -1
- package/dist/utils/devServerError.js +0 -17
- package/dist/utils/devServerError.js.map +1 -1
- package/dist/utils/displayLocale.d.ts +0 -2
- package/dist/utils/displayLocale.d.ts.map +1 -1
- package/dist/utils/displayLocale.js +0 -2
- package/dist/utils/displayLocale.js.map +1 -1
- package/dist/utils/elementFileHintSignals.d.ts +0 -5
- package/dist/utils/elementFileHintSignals.d.ts.map +1 -1
- package/dist/utils/elementFileHintSignals.js +0 -5
- package/dist/utils/elementFileHintSignals.js.map +1 -1
- package/dist/utils/formatElementTargetingContext.d.ts +0 -6
- package/dist/utils/formatElementTargetingContext.d.ts.map +1 -1
- package/dist/utils/formatElementTargetingContext.js +3 -9
- package/dist/utils/formatElementTargetingContext.js.map +1 -1
- package/dist/utils/hostAgentEnv.d.ts +0 -17
- package/dist/utils/hostAgentEnv.d.ts.map +1 -1
- package/dist/utils/hostAgentEnv.js +0 -17
- package/dist/utils/hostAgentEnv.js.map +1 -1
- package/dist/utils/htmlDocument.d.ts +0 -5
- package/dist/utils/htmlDocument.d.ts.map +1 -1
- package/dist/utils/htmlDocument.js +2 -7
- package/dist/utils/htmlDocument.js.map +1 -1
- package/dist/utils/internalGitIdentity.d.ts +0 -5
- package/dist/utils/internalGitIdentity.d.ts.map +1 -1
- package/dist/utils/internalGitIdentity.js +0 -5
- package/dist/utils/internalGitIdentity.js.map +1 -1
- package/dist/utils/logger.d.ts +0 -5
- package/dist/utils/logger.d.ts.map +1 -1
- package/dist/utils/logger.js +2 -19
- package/dist/utils/logger.js.map +1 -1
- package/dist/utils/loginShellPath.d.ts +0 -9
- package/dist/utils/loginShellPath.d.ts.map +1 -1
- package/dist/utils/loginShellPath.js +0 -69
- package/dist/utils/loginShellPath.js.map +1 -1
- package/dist/utils/loopback.d.ts +0 -1
- package/dist/utils/loopback.d.ts.map +1 -1
- package/dist/utils/loopback.js +0 -1
- package/dist/utils/loopback.js.map +1 -1
- package/dist/utils/pid.d.ts +0 -1
- package/dist/utils/pid.d.ts.map +1 -1
- package/dist/utils/pid.js +0 -1
- package/dist/utils/pid.js.map +1 -1
- package/dist/utils/portUtils.d.ts +0 -15
- package/dist/utils/portUtils.d.ts.map +1 -1
- package/dist/utils/portUtils.js +0 -21
- package/dist/utils/portUtils.js.map +1 -1
- package/dist/utils/queueAccess.d.ts +0 -9
- package/dist/utils/queueAccess.d.ts.map +1 -1
- package/dist/utils/queueAccess.js +0 -9
- package/dist/utils/queueAccess.js.map +1 -1
- package/dist/utils/skillWriter.d.ts +0 -17
- package/dist/utils/skillWriter.d.ts.map +1 -1
- package/dist/utils/skillWriter.js +0 -20
- package/dist/utils/skillWriter.js.map +1 -1
- package/dist/utils/skills/claude-skill.d.ts +0 -5
- package/dist/utils/skills/claude-skill.d.ts.map +1 -1
- package/dist/utils/skills/claude-skill.js +0 -5
- package/dist/utils/skills/claude-skill.js.map +1 -1
- package/dist/utils/skills/cli-guidance.d.ts +1 -9
- package/dist/utils/skills/cli-guidance.d.ts.map +1 -1
- package/dist/utils/skills/cli-guidance.js +6 -10
- package/dist/utils/skills/cli-guidance.js.map +1 -1
- package/dist/utils/skills/cursor-rules.d.ts +0 -6
- package/dist/utils/skills/cursor-rules.d.ts.map +1 -1
- package/dist/utils/skills/cursor-rules.js +0 -6
- package/dist/utils/skills/cursor-rules.js.map +1 -1
- package/dist/utils/variantPreviewPort.d.ts +0 -3
- package/dist/utils/variantPreviewPort.d.ts.map +1 -1
- package/dist/utils/variantPreviewPort.js +0 -3
- package/dist/utils/variantPreviewPort.js.map +1 -1
- package/dist/utils/windowPlacement.d.ts +0 -4
- package/dist/utils/windowPlacement.d.ts.map +1 -1
- package/dist/utils/windowPlacement.js +0 -4
- package/dist/utils/windowPlacement.js.map +1 -1
- package/package.json +13 -13
- package/scripts/verify-node-version.cjs +0 -3
- package/src/ui/dist/assets/{LibraryApp-qbLqcNxM.js → LibraryApp-Bu7hVbt_.js} +1 -1
- package/src/ui/dist/assets/main-CHyx_rEa.css +1 -0
- package/src/ui/dist/assets/main-CuiPb_rl.js +438 -0
- package/src/ui/dist/index.html +2 -2
- package/dist/utils/skills/describe-motion-protocol.d.ts +0 -10
- package/dist/utils/skills/describe-motion-protocol.d.ts.map +0 -1
- package/dist/utils/skills/describe-motion-protocol.js +0 -231
- package/dist/utils/skills/describe-motion-protocol.js.map +0 -1
- package/src/ui/dist/assets/main-BUZjlAHd.css +0 -1
- package/src/ui/dist/assets/main-touv07Dk.js +0 -438
|
@@ -75,44 +75,14 @@ const FALLBACK_DIRECTION_FOCI = [
|
|
|
75
75
|
'Explore tactile depth, layering, and purposeful interaction cues.',
|
|
76
76
|
'Reduce the concept to its most essential typography and geometry.',
|
|
77
77
|
];
|
|
78
|
-
// Upper bound on waiting for in-flight history persists during session
|
|
79
|
-
// teardown. Generous enough for a full-repo snapshot on a large project;
|
|
80
|
-
// small enough that a wedged git subprocess (which has its own 120s block
|
|
81
|
-
// timeout) can't make commit/cancel appear hung.
|
|
82
78
|
const SETTLE_PERSISTS_TEARDOWN_TIMEOUT_MS = 20_000;
|
|
83
|
-
// Sentinel port for deriving a persist-time serve recipe when the dev server
|
|
84
|
-
// hasn't booted yet: resolved into the command, then reverse-substituted to
|
|
85
|
-
// the ${PORT} placeholder. Digit-boundary-guarded substitution means only an
|
|
86
|
-
// exact standalone occurrence is replaced, and 65535 never appears in any
|
|
87
|
-
// framework's default invocation.
|
|
88
79
|
const RECIPE_PORT_SENTINEL = 65535;
|
|
89
|
-
// Fresh worktrees run the Vite React template, whose dev server defaults to
|
|
90
|
-
// 5173. Used as the scan start when allocating a fresh variant's preview port.
|
|
91
80
|
const FRESH_DEV_SERVER_DEFAULT_PORT = 5173;
|
|
92
|
-
// Startup attempts for a variant's dev server. Attempt 2 covers a transient
|
|
93
|
-
// early exit (with a dependency install first when the output shows
|
|
94
|
-
// module-resolution errors); attempt 3 leaves room for one more port step
|
|
95
|
-
// when a collision persists. Early exits fail fast, so extra attempts cost
|
|
96
|
-
// little wall clock.
|
|
97
81
|
const DEV_SERVER_START_MAX_ATTEMPTS = 3;
|
|
98
|
-
// Auto-restarts allowed after a READY dev server crashes (see the exit
|
|
99
|
-
// handler in startVariantDevServer). Two rescues cover transient crashes;
|
|
100
|
-
// a third crash means the build is genuinely broken, so stop looping.
|
|
101
82
|
const DEV_SERVER_MAX_AUTO_RESTARTS = 2;
|
|
102
|
-
// Grace before an auto-restart so a crashing process's port and file locks
|
|
103
|
-
// are actually released first.
|
|
104
83
|
const DEV_SERVER_RESTART_DELAY_MS = 1_000;
|
|
105
84
|
const DESIGN_CONTEXT_ROUTE_SEGMENT = 'design-md';
|
|
106
85
|
const DESIGN_CONTEXT_VIEW_SEGMENT = 'view';
|
|
107
|
-
// Hard ceiling on worktree provisioning so a slow/large host project can never
|
|
108
|
-
// stall the `start_variants` / `approve_variant_briefs` tool call indefinitely.
|
|
109
|
-
// Existing-project provisioning clones the host working tree once per variant
|
|
110
|
-
// (`git worktree add` + untracked-file copy), so its cost scales with repo
|
|
111
|
-
// size — a big monorepo (or a React Native tree with native build dirs) used to
|
|
112
|
-
// hang the call for 15+ minutes with no signal. With this bound the call fails
|
|
113
|
-
// fast and legibly instead. Per-git-op hangs are already caught by simple-git's
|
|
114
|
-
// block timeout in WorktreeManager; this is the cross-op backstop. Override via
|
|
115
|
-
// env for unusually large repos.
|
|
116
86
|
const DEFAULT_PROVISION_TIMEOUT_MS = 540_000;
|
|
117
87
|
const PROVISION_TIMEOUT_MS = (() => {
|
|
118
88
|
const raw = process.env.RIVET_VARIANTS_PROVISION_TIMEOUT_MS;
|
|
@@ -121,10 +91,6 @@ const PROVISION_TIMEOUT_MS = (() => {
|
|
|
121
91
|
? parsed
|
|
122
92
|
: DEFAULT_PROVISION_TIMEOUT_MS;
|
|
123
93
|
})();
|
|
124
|
-
// Active variant dev servers are useful only while the Rivet app is being used.
|
|
125
|
-
// Reclaim them after app/API silence so abandoned sessions do not pin one child
|
|
126
|
-
// process per succeeded variant forever. The session state and worktrees stay
|
|
127
|
-
// intact; only live preview ports are cleared.
|
|
128
94
|
const DEFAULT_ACTIVE_VARIANT_SERVER_IDLE_TTL_MS = 30 * 60 * 1000;
|
|
129
95
|
const ACTIVE_VARIANT_SERVER_IDLE_TTL_MS = (() => {
|
|
130
96
|
const raw = process.env.RIVET_ACTIVE_VARIANT_SERVER_IDLE_TTL_MS;
|
|
@@ -133,7 +99,6 @@ const ACTIVE_VARIANT_SERVER_IDLE_TTL_MS = (() => {
|
|
|
133
99
|
? parsed
|
|
134
100
|
: DEFAULT_ACTIVE_VARIANT_SERVER_IDLE_TTL_MS;
|
|
135
101
|
})();
|
|
136
|
-
/** Sentinel so callers can distinguish a provisioning timeout from other errors. */
|
|
137
102
|
class ProvisionTimeoutError extends Error {
|
|
138
103
|
timeoutMs;
|
|
139
104
|
constructor(timeoutMs) {
|
|
@@ -142,12 +107,6 @@ class ProvisionTimeoutError extends Error {
|
|
|
142
107
|
this.name = 'ProvisionTimeoutError';
|
|
143
108
|
}
|
|
144
109
|
}
|
|
145
|
-
/**
|
|
146
|
-
* Reject with `ProvisionTimeoutError` if `work` hasn't settled within
|
|
147
|
-
* `timeoutMs`. The underlying work is NOT cancellable (git/fs I/O), so it may
|
|
148
|
-
* keep running after we reject — callers should best-effort clean up partial
|
|
149
|
-
* state. The timer is unref'd so it never keeps the process alive on its own.
|
|
150
|
-
*/
|
|
151
110
|
function withProvisionTimeout(work, timeoutMs) {
|
|
152
111
|
let timer;
|
|
153
112
|
const timeout = new Promise((_, reject) => {
|
|
@@ -157,11 +116,6 @@ function withProvisionTimeout(work, timeoutMs) {
|
|
|
157
116
|
});
|
|
158
117
|
return Promise.race([work, timeout]).finally(() => clearTimeout(timer));
|
|
159
118
|
}
|
|
160
|
-
/**
|
|
161
|
-
* File types an agent-authored asset plan may copy into a generated preview.
|
|
162
|
-
* This allowlist protects an agent-controlled path; caller-selected context
|
|
163
|
-
* assets use the separate, type-neutral delivery path.
|
|
164
|
-
*/
|
|
165
119
|
const ALLOWED_INERT_ASSET_EXTENSIONS = new Set([
|
|
166
120
|
'.glb',
|
|
167
121
|
'.gltf',
|
|
@@ -191,13 +145,6 @@ const ALLOWED_INERT_ASSET_EXTENSIONS = new Set([
|
|
|
191
145
|
'.eot',
|
|
192
146
|
'.pdf',
|
|
193
147
|
]);
|
|
194
|
-
/**
|
|
195
|
-
* Reject paths that traverse through a "sensitive" directory anywhere
|
|
196
|
-
* in their ancestry — `.ssh`, `.aws`, `.config`, `.gnupg`, etc. Even if
|
|
197
|
-
* a copy passes the extension allowlist, an agent-controlled source
|
|
198
|
-
* resolving inside `~/.ssh/` is almost certainly an exfiltration
|
|
199
|
-
* attempt rather than a legitimate asset reference.
|
|
200
|
-
*/
|
|
201
148
|
const SENSITIVE_PATH_SEGMENTS = new Set([
|
|
202
149
|
'.ssh',
|
|
203
150
|
'.aws',
|
|
@@ -214,14 +161,9 @@ const SENSITIVE_PATH_SEGMENTS = new Set([
|
|
|
214
161
|
'credentials',
|
|
215
162
|
]);
|
|
216
163
|
function hasSensitivePathSegment(absolutePath) {
|
|
217
|
-
// Split on any path separator; check each segment case-insensitively.
|
|
218
164
|
const segments = absolutePath.split(/[/\\]/).filter(Boolean);
|
|
219
165
|
return segments.some((segment) => SENSITIVE_PATH_SEGMENTS.has(segment.toLowerCase()));
|
|
220
166
|
}
|
|
221
|
-
/**
|
|
222
|
-
* Returns true when `absolutePath` is the root itself or one of its
|
|
223
|
-
* descendants after both paths have been resolved.
|
|
224
|
-
*/
|
|
225
167
|
function isPathWithinRoot(absolutePath, root) {
|
|
226
168
|
const relative = path_1.default.relative(root, absolutePath);
|
|
227
169
|
return (relative === '' ||
|
|
@@ -229,25 +171,6 @@ function isPathWithinRoot(absolutePath, root) {
|
|
|
229
171
|
!relative.startsWith('..') &&
|
|
230
172
|
!path_1.default.isAbsolute(relative)));
|
|
231
173
|
}
|
|
232
|
-
/**
|
|
233
|
-
* Copy one agent-planned asset file into a variant worktree at the
|
|
234
|
-
* project-relative `destination`. The agent decides routing
|
|
235
|
-
* (`destination` like `public/assets/avatar.glb`) so all variants share
|
|
236
|
-
* a consistent layout. Fails loudly when the source is missing or the
|
|
237
|
-
* destination tries to escape the worktree — silent fallbacks here
|
|
238
|
-
* would re-introduce the broken-asset failure mode this routing is
|
|
239
|
-
* supposed to prevent.
|
|
240
|
-
*
|
|
241
|
-
* Security: `entry.source` comes from `report_source_plan` and is
|
|
242
|
-
* agent-controlled. To prevent a prompt-injected source plan from
|
|
243
|
-
* exfiltrating arbitrary readable host files (SSH keys, dotfiles,
|
|
244
|
-
* cloud credentials, project secrets) into the generated app, the
|
|
245
|
-
* source must (1) be an absolute path that resolves via realpath
|
|
246
|
-
* (no traversal, no symlinks pointing outside the resolved location),
|
|
247
|
-
* (2) be a regular file (not a device, socket, fifo, or directory),
|
|
248
|
-
* (3) live under the approved asset root, (4) have an extension on the
|
|
249
|
-
* asset allowlist.
|
|
250
|
-
*/
|
|
251
174
|
function copyAssetIntoWorktree(worktreePath, entry, assetSourceRoot) {
|
|
252
175
|
if (!assetSourceRoot) {
|
|
253
176
|
throw new errors_1.AgentVariantsError('RUNTIME_VALIDATION_FAILED', `assetPlan.source requires an approved asset root before copying '${entry.source}'`);
|
|
@@ -255,14 +178,6 @@ function copyAssetIntoWorktree(worktreePath, entry, assetSourceRoot) {
|
|
|
255
178
|
if (!path_1.default.isAbsolute(assetSourceRoot)) {
|
|
256
179
|
throw new errors_1.AgentVariantsError('RUNTIME_VALIDATION_FAILED', `assetSourceRoot must be an absolute path, got '${assetSourceRoot}'`);
|
|
257
180
|
}
|
|
258
|
-
// A relative source is resolved against the approved asset root. The
|
|
259
|
-
// agent-facing protocol requires the source to live under that root but not
|
|
260
|
-
// to be absolute, and the root path is internal to Rivet (a staged context
|
|
261
|
-
// bundle) — so a relative name such as 'avatar.glb' is the natural, safe
|
|
262
|
-
// form. Every downstream guard (symlink, extension, within-root, sensitive
|
|
263
|
-
// segments) runs against this resolved absolute path, so the resolution
|
|
264
|
-
// cannot widen what is copyable: a relative `..` escape still fails the
|
|
265
|
-
// within-root check below.
|
|
266
181
|
const absoluteSource = path_1.default.isAbsolute(entry.source)
|
|
267
182
|
? entry.source
|
|
268
183
|
: path_1.default.resolve(assetSourceRoot, entry.source);
|
|
@@ -270,10 +185,6 @@ function copyAssetIntoWorktree(worktreePath, entry, assetSourceRoot) {
|
|
|
270
185
|
if (!ALLOWED_INERT_ASSET_EXTENSIONS.has(ext)) {
|
|
271
186
|
throw new errors_1.AgentVariantsError('RUNTIME_VALIDATION_FAILED', `assetPlan.source extension '${ext || '(none)'}' is not on the allowlist (got '${entry.source}'). Only inert media/font/document assets may be copied.`);
|
|
272
187
|
}
|
|
273
|
-
// lstat first: a symlink whose target lies outside the source path
|
|
274
|
-
// could otherwise smuggle in arbitrary files. Reject symlinks outright;
|
|
275
|
-
// realpath would resolve them but the user-visible intent of an
|
|
276
|
-
// assetPlan entry is to name a concrete file.
|
|
277
188
|
let lstat;
|
|
278
189
|
try {
|
|
279
190
|
lstat = fs_1.default.lstatSync(absoluteSource);
|
|
@@ -287,9 +198,6 @@ function copyAssetIntoWorktree(worktreePath, entry, assetSourceRoot) {
|
|
|
287
198
|
if (!lstat.isFile()) {
|
|
288
199
|
throw new errors_1.AgentVariantsError('RUNTIME_VALIDATION_FAILED', `assetPlan.source must be a regular file: ${entry.source}`);
|
|
289
200
|
}
|
|
290
|
-
// Resolve realpath as additional defense: even with no symlinks at the
|
|
291
|
-
// leaf, an intermediate directory could be a symlink. Cross-check the
|
|
292
|
-
// file kind on the resolved path.
|
|
293
201
|
let resolvedSource;
|
|
294
202
|
try {
|
|
295
203
|
resolvedSource = fs_1.default.realpathSync(absoluteSource);
|
|
@@ -308,24 +216,9 @@ function copyAssetIntoWorktree(worktreePath, entry, assetSourceRoot) {
|
|
|
308
216
|
if (!resolvedStat.isFile()) {
|
|
309
217
|
throw new errors_1.AgentVariantsError('RUNTIME_VALIDATION_FAILED', `assetPlan.source resolved target must be a regular file: ${entry.source}`);
|
|
310
218
|
}
|
|
311
|
-
// Containment is the security boundary and must be checked before any
|
|
312
|
-
// sensitive-segment scan. The approved asset root is system-chosen and
|
|
313
|
-
// trusted (a staged context bundle), and its realpath can legitimately
|
|
314
|
-
// pass through a "sensitive" segment that is NOT agent-controlled — on
|
|
315
|
-
// macOS `fs.realpathSync(os.tmpdir())` resolves to `/private/var/folders/...`,
|
|
316
|
-
// so the temp-staged root contains `private`. A symlinked intermediate dir
|
|
317
|
-
// that forwards into a sensitive ancestor (e.g. `<asset-root>/avatar -> ~/.ssh`)
|
|
318
|
-
// pushes the realpath OUTSIDE the root and is rejected here.
|
|
319
219
|
if (!isPathWithinRoot(resolvedSource, resolvedAssetSourceRoot)) {
|
|
320
220
|
throw new errors_1.AgentVariantsError('RUNTIME_VALIDATION_FAILED', `assetPlan.source must stay inside the approved asset root: ${entry.source}`);
|
|
321
221
|
}
|
|
322
|
-
// Sensitive-segment defense, scoped to the agent-controlled portion BELOW
|
|
323
|
-
// the trusted root. Only this relative remainder is chosen by the agent's
|
|
324
|
-
// source plan, so a sensitive segment it introduces under the root (a real
|
|
325
|
-
// `<asset-root>/.ssh/key.glb`, or a within-root symlink that realpaths into
|
|
326
|
-
// one) is still refused, while the trusted root prefix is never scanned.
|
|
327
|
-
// `resolvedSource` is the fully symlink-resolved real path, so the scan
|
|
328
|
-
// covers what the file actually resolves to, not just its literal name.
|
|
329
222
|
const relativeResolvedSource = path_1.default.relative(resolvedAssetSourceRoot, resolvedSource);
|
|
330
223
|
if (hasSensitivePathSegment(relativeResolvedSource)) {
|
|
331
224
|
throw new errors_1.AgentVariantsError('RUNTIME_VALIDATION_FAILED', `assetPlan.source traverses a sensitive directory and is refused: ${entry.source}`);
|
|
@@ -343,7 +236,6 @@ function copyAssetIntoWorktree(worktreePath, entry, assetSourceRoot) {
|
|
|
343
236
|
fs_1.default.copyFileSync(resolvedSource, absDest);
|
|
344
237
|
}
|
|
345
238
|
const defaultPreviewQaRunner = ({ html }) => (0, previewQa_1.runPreviewQa)({ html });
|
|
346
|
-
/** Disabled-reason copy for a variant whose preview cannot be opened. */
|
|
347
239
|
const buildViewDisabledReason = (args) => {
|
|
348
240
|
if (args.status === 'failed') {
|
|
349
241
|
return args.qa?.summary ?? 'Generation failed';
|
|
@@ -367,11 +259,9 @@ const DESIGN_CREATION_ACTION_RE = /\b(create|build|design|make|redesign|refresh|
|
|
|
367
259
|
const DESIGN_CREATION_SURFACE_RE = /\b(home\s?page|landing page|dashboard|screen|site|website|app|page|ui|interface|component|hero)\b/i;
|
|
368
260
|
const NON_VISUAL_CHANGE_RE = /\b(api|backend|database|event|lint|query|server|test|tracking|typecheck)\b/i;
|
|
369
261
|
const DIFF_CAPTURE_FAILURE_SUMMARY = 'Unable to verify the generated design diff; regenerate this variant so Rivet can confirm source changes.';
|
|
370
|
-
/** Separates invalid worker output from a Rivet check that could not run. */
|
|
371
262
|
const qaFailureErrorCode = (qa) => qa.issues.some((issue) => issue.kind === 'verification_unavailable')
|
|
372
263
|
? 'VARIANT_VERIFICATION_UNAVAILABLE'
|
|
373
264
|
: 'VARIANT_QA_FAILED';
|
|
374
|
-
/** Identifies a repair-triggering completion across transport retries. */
|
|
375
265
|
const repairCompletionKey = (args) => JSON.stringify([args.workItemId, args.leaseId, args.attempt, 'succeeded']);
|
|
376
266
|
const briefLabelKey = (value) => value.trim().toLowerCase().replace(/\s+/g, ' ');
|
|
377
267
|
const truncateBriefLabel = (value) => {
|
|
@@ -452,17 +342,6 @@ const isDesignCreationCodeGenInput = (input, prompt) => {
|
|
|
452
342
|
return (DESIGN_CREATION_ACTION_RE.test(text) &&
|
|
453
343
|
DESIGN_CREATION_SURFACE_RE.test(text));
|
|
454
344
|
};
|
|
455
|
-
/**
|
|
456
|
-
* Wraps SessionStore for the operations that have side effects: approve
|
|
457
|
-
* (provision worktrees), reportComplete (capture diff), commit (apply picked
|
|
458
|
-
* output), cancel (teardown). Pure read paths bypass and call SessionStore
|
|
459
|
-
* directly.
|
|
460
|
-
*
|
|
461
|
-
* This is the terminal-native variant of the orchestrator: the user picks
|
|
462
|
-
* a single brief upfront, so there's only ever one code-gen item per
|
|
463
|
-
* session and no live preview / proxy retarget. Once the agent reports
|
|
464
|
-
* the variant succeeded, the CLI can commit the chosen output directly.
|
|
465
|
-
*/
|
|
466
345
|
class AgentVariantsOrchestrator {
|
|
467
346
|
store;
|
|
468
347
|
worktrees;
|
|
@@ -479,31 +358,9 @@ class AgentVariantsOrchestrator {
|
|
|
479
358
|
activeVariantServerIdleTtlMs;
|
|
480
359
|
devServerRestartDelayMs;
|
|
481
360
|
resources = new Map();
|
|
482
|
-
/**
|
|
483
|
-
* Committed dev servers from prior sessions that survived teardown. The
|
|
484
|
-
* orchestrator outlives any single session — once a new session starts, the
|
|
485
|
-
* prior committed dev server is no longer needed (the next session opens
|
|
486
|
-
* its own preview chip), so stop it before the new session's first preview
|
|
487
|
-
* goes live. Keyed by sessionId for diagnostics; values are kept alive
|
|
488
|
-
* intentionally between commit and next `propose` / `shutdown`.
|
|
489
|
-
*/
|
|
490
361
|
lingeringCommittedDevServers = new Map();
|
|
491
|
-
/**
|
|
492
|
-
* Per-session in-flight commit chain. Two overlapping commitVariant calls
|
|
493
|
-
* would otherwise both pass the `getVariantPick` idempotency check (the
|
|
494
|
-
* pick isn't recorded until after `applyDiffToProject`) and double-invoke
|
|
495
|
-
* `git apply` — which corrupts the working tree on the second run. The
|
|
496
|
-
* chain serializes commits per session so the second caller waits for the
|
|
497
|
-
* first to finish and then hits the idempotency check (returning
|
|
498
|
-
* `duplicate: true` for the same variantId, or `PENDING_CHANGE_CONFLICT`
|
|
499
|
-
* for a different one).
|
|
500
|
-
*/
|
|
501
362
|
inflightCommits = new Map();
|
|
502
|
-
/** Most recent agent-variants sessionId — read by the iframe chip via
|
|
503
|
-
* GET /api/variants/active. Cleared on cancel or commit. */
|
|
504
363
|
activeSessionId = null;
|
|
505
|
-
/** Push channel for the iframe chip's SSE subscription. Emits an
|
|
506
|
-
* ActiveSnapshot on every state change so the chip never has to poll. */
|
|
507
364
|
events = new events_1.EventEmitter();
|
|
508
365
|
constructor(deps) {
|
|
509
366
|
this.store = deps.store;
|
|
@@ -526,11 +383,7 @@ class AgentVariantsOrchestrator {
|
|
|
526
383
|
this.devServerRestartDelayMs =
|
|
527
384
|
deps.devServerRestartDelayMs ?? DEV_SERVER_RESTART_DELAY_MS;
|
|
528
385
|
}
|
|
529
|
-
// --- Pure delegations (no side effects) ---------------------------------
|
|
530
386
|
propose(args) {
|
|
531
|
-
// A new session means any lingering committed dev server from a prior
|
|
532
|
-
// session is no longer needed — the next session opens its own preview.
|
|
533
|
-
// Best-effort stop; failures here don't block propose.
|
|
534
387
|
void this.stopLingeringCommittedDevServers().catch((err) => {
|
|
535
388
|
log.warn('Stopping lingering committed dev servers failed', err);
|
|
536
389
|
});
|
|
@@ -577,36 +430,18 @@ class AgentVariantsOrchestrator {
|
|
|
577
430
|
this.emitChange();
|
|
578
431
|
return result;
|
|
579
432
|
}
|
|
580
|
-
/** Returns the most recent agent-variants sessionId (or null). */
|
|
581
433
|
getActiveSessionId() {
|
|
582
434
|
return this.activeSessionId;
|
|
583
435
|
}
|
|
584
|
-
/** Subscribe to active-snapshot pushes. Returns an unsubscribe fn. */
|
|
585
436
|
subscribeToEvents(listener) {
|
|
586
437
|
this.events.on('change', listener);
|
|
587
438
|
return () => {
|
|
588
439
|
this.events.off('change', listener);
|
|
589
440
|
};
|
|
590
441
|
}
|
|
591
|
-
/** Number of live Rivet UI clients subscribed to the variants SSE stream.
|
|
592
|
-
* A subscribed client means a Rivet page is open in the browser. */
|
|
593
442
|
uiClientCount = 0;
|
|
594
|
-
/** Wall-clock of the last UI-client connect/disconnect. `hasUiClients`
|
|
595
|
-
* treats a very recent disconnect as still-connected to ride out the brief
|
|
596
|
-
* gap when an EventSource drops and auto-reconnects (default retry ~3s) —
|
|
597
|
-
* otherwise a `propose`/`start` landing in that window reads zero clients
|
|
598
|
-
* and spawns a duplicate browser tab. */
|
|
599
443
|
lastUiClientActivityAt = 0;
|
|
600
|
-
/** Grace window covering an EventSource reconnect (its default retry is ~3s;
|
|
601
|
-
* the SSE heartbeat is 30s). Long enough to span a reconnect, short enough
|
|
602
|
-
* that a genuine page close frees the "reopen on next propose" path quickly. */
|
|
603
444
|
static UI_CLIENT_GRACE_MS = 6000;
|
|
604
|
-
/**
|
|
605
|
-
* Register a live Rivet UI client (called when the variants SSE stream opens).
|
|
606
|
-
* Returns a release fn to call on disconnect. Used as the "a Rivet page is
|
|
607
|
-
* already open" signal so the MCP server can avoid spawning a duplicate tab
|
|
608
|
-
* every time the variants flow re-enters an already-active editor session.
|
|
609
|
-
*/
|
|
610
445
|
registerUiClient() {
|
|
611
446
|
this.uiClientCount += 1;
|
|
612
447
|
this.lastUiClientActivityAt = Date.now();
|
|
@@ -620,8 +455,6 @@ class AgentVariantsOrchestrator {
|
|
|
620
455
|
this.lastUiClientActivityAt = Date.now();
|
|
621
456
|
};
|
|
622
457
|
}
|
|
623
|
-
/** True when at least one Rivet UI page is currently connected — or one
|
|
624
|
-
* disconnected within the grace window (an EventSource mid-reconnect). */
|
|
625
458
|
hasUiClients() {
|
|
626
459
|
if (this.uiClientCount > 0)
|
|
627
460
|
return true;
|
|
@@ -630,21 +463,17 @@ class AgentVariantsOrchestrator {
|
|
|
630
463
|
return (Date.now() - this.lastUiClientActivityAt <
|
|
631
464
|
AgentVariantsOrchestrator.UI_CLIENT_GRACE_MS);
|
|
632
465
|
}
|
|
633
|
-
/** @effect Records activity for the current variants session, if one exists. */
|
|
634
466
|
touchActiveSession() {
|
|
635
467
|
if (!this.activeSessionId)
|
|
636
468
|
return;
|
|
637
469
|
this.touchSession(this.activeSessionId);
|
|
638
470
|
}
|
|
639
|
-
/** @effect Resets idle cleanup for active variant preview servers. */
|
|
640
471
|
touchSession(sessionId) {
|
|
641
472
|
const resources = this.resources.get(sessionId);
|
|
642
473
|
if (!resources || resources.cleanupStarted)
|
|
643
474
|
return;
|
|
644
475
|
this.scheduleActivePreviewIdleTimer(resources);
|
|
645
476
|
}
|
|
646
|
-
/** Build the snapshot the chip cares about. Reads from SessionStore +
|
|
647
|
-
* per-resource state; safe to call at any time. */
|
|
648
477
|
buildActiveSnapshot() {
|
|
649
478
|
const sessionId = this.activeSessionId;
|
|
650
479
|
if (!sessionId || !this.store.hasSession(sessionId)) {
|
|
@@ -683,25 +512,22 @@ class AgentVariantsOrchestrator {
|
|
|
683
512
|
...(workerRuntime ? { workerRuntime } : {}),
|
|
684
513
|
};
|
|
685
514
|
}
|
|
686
|
-
/** Record which worker runtime this session's current batch leases to —
|
|
687
|
-
* called by the generation services right after the lease-owner decision
|
|
688
|
-
* so `variants start`/status can answer "what is running these?". */
|
|
689
515
|
setWorkerRuntime(sessionId, summary) {
|
|
690
516
|
if (!this.store.hasSession(sessionId))
|
|
691
517
|
return;
|
|
692
518
|
this.store.setWorkerRuntime(sessionId, summary);
|
|
693
|
-
// Push a fresh snapshot to SSE subscribers: startUnified/requestWork
|
|
694
|
-
// already emitted before this setter ran, and without an emit here a
|
|
695
|
-
// subscribed client would not see workerRuntime until the next state
|
|
696
|
-
// transition (possibly the first worker completion).
|
|
697
519
|
this.emitChange();
|
|
698
520
|
}
|
|
699
|
-
/** User reference files stored in the work item's context bundle (uploaded
|
|
700
|
-
* or copied local images). Surfaced on the snapshot so briefings can point
|
|
701
|
-
* workers at the files directly — one Read instead of a bundle walk. */
|
|
702
521
|
static contextFilesOf(context) {
|
|
522
|
+
const paths = new Set();
|
|
703
523
|
const files = (context?.userContext ?? [])
|
|
704
524
|
.filter((source) => source.transport === 'file')
|
|
525
|
+
.filter((source) => {
|
|
526
|
+
if (paths.has(source.path))
|
|
527
|
+
return false;
|
|
528
|
+
paths.add(source.path);
|
|
529
|
+
return true;
|
|
530
|
+
})
|
|
705
531
|
.map((source) => ({
|
|
706
532
|
path: source.path,
|
|
707
533
|
...((source.label ?? source.originalFilename)
|
|
@@ -1050,8 +876,6 @@ class AgentVariantsOrchestrator {
|
|
|
1050
876
|
if (projectContext.variantContext) {
|
|
1051
877
|
(0, variantContext_1.writeVariantContextBundle)(projectContext.variantContext);
|
|
1052
878
|
}
|
|
1053
|
-
// Source-context quality is now measured off the raw context bundle plus
|
|
1054
|
-
// the action metadata the agent reported, not the legacy summary fields.
|
|
1055
879
|
const bundle = projectContext.kind === 'fresh'
|
|
1056
880
|
? projectContext.variantContext
|
|
1057
881
|
: undefined;
|
|
@@ -1113,9 +937,6 @@ class AgentVariantsOrchestrator {
|
|
|
1113
937
|
}
|
|
1114
938
|
throw error;
|
|
1115
939
|
}
|
|
1116
|
-
// Record lease times so variant_completed can report lease→report
|
|
1117
|
-
// duration. (We don't fire a separate code_gen_leased event — the
|
|
1118
|
-
// funnel signal we care about is per-variant completion duration.)
|
|
1119
940
|
const resources = this.resources.get(args.sessionId);
|
|
1120
941
|
if (resources) {
|
|
1121
942
|
const now = Date.now();
|
|
@@ -1125,10 +946,6 @@ class AgentVariantsOrchestrator {
|
|
|
1125
946
|
}
|
|
1126
947
|
this.writeLeasedWorkItemBriefings(args.sessionId, result.leasedWorkItems.map((item) => item.id));
|
|
1127
948
|
this.trackRefinementLeased({ sessionId: args.sessionId, lease: result });
|
|
1128
|
-
// Decorate each leased item's input with the worktreePath provisioned
|
|
1129
|
-
// by approve(). The skill instructs agents to write files to
|
|
1130
|
-
// `input.worktreePath` — without this decoration that field would be
|
|
1131
|
-
// missing and the agent would have no idea where to edit.
|
|
1132
949
|
const decorated = {
|
|
1133
950
|
...result,
|
|
1134
951
|
leasedWorkItems: result.leasedWorkItems.map((item) => {
|
|
@@ -1145,7 +962,6 @@ class AgentVariantsOrchestrator {
|
|
|
1145
962
|
this.emitChange();
|
|
1146
963
|
return decorated;
|
|
1147
964
|
}
|
|
1148
|
-
/** @effect Copies caller-supplied context assets into each leased workspace. */
|
|
1149
965
|
materializeContextAssets(sessionId, items) {
|
|
1150
966
|
const resources = this.ensureResources(sessionId);
|
|
1151
967
|
for (const item of items) {
|
|
@@ -1166,10 +982,6 @@ class AgentVariantsOrchestrator {
|
|
|
1166
982
|
resources.contextAssets.set(item.id, (0, contextAssets_1.materializeContextAssets)({ assets, workspace, previewKind }));
|
|
1167
983
|
}
|
|
1168
984
|
}
|
|
1169
|
-
/**
|
|
1170
|
-
* @effect Records how an existing project's worktrees will be previewed so
|
|
1171
|
-
* context assets receive references that resolve on that serving surface.
|
|
1172
|
-
*/
|
|
1173
985
|
async resolveContextAssetPreviewKind(sessionId) {
|
|
1174
986
|
const resources = this.ensureResources(sessionId);
|
|
1175
987
|
try {
|
|
@@ -1182,13 +994,6 @@ class AgentVariantsOrchestrator {
|
|
|
1182
994
|
log.warn(`Failed to resolve context asset preview kind for ${sessionId}; using dev-server references`, error);
|
|
1183
995
|
}
|
|
1184
996
|
}
|
|
1185
|
-
/**
|
|
1186
|
-
* @effect Writes each leased implementation item's server-authored briefing
|
|
1187
|
-
* BESIDE its workspace so the coordinating host dispatches workers with a
|
|
1188
|
-
* short pointer prompt instead of composing prose per worker. Best-effort:
|
|
1189
|
-
* a briefing write failure never blocks the lease (the host guidance's
|
|
1190
|
-
* packet fields still carry the same data).
|
|
1191
|
-
*/
|
|
1192
997
|
writeLeasedWorkItemBriefings(sessionId, leasedWorkItemIds) {
|
|
1193
998
|
if (leasedWorkItemIds.length === 0)
|
|
1194
999
|
return;
|
|
@@ -1218,13 +1023,9 @@ class AgentVariantsOrchestrator {
|
|
|
1218
1023
|
}
|
|
1219
1024
|
}
|
|
1220
1025
|
}
|
|
1221
|
-
/** @effect Assigns isolated, server-owned artifact workspaces to leased static work. */
|
|
1222
1026
|
ensureStaticWorkspaces(sessionId, items) {
|
|
1223
1027
|
const resources = this.ensureResources(sessionId);
|
|
1224
1028
|
const projectContext = this.store.getProjectContext(sessionId);
|
|
1225
|
-
// This lane provisions by copying the source artifact tree (vary forks) or
|
|
1226
|
-
// seeding an entry file — it bypasses provisionWorktrees, so it gets its
|
|
1227
|
-
// own provisioning telemetry here.
|
|
1228
1029
|
const provisionStartedAt = Date.now();
|
|
1229
1030
|
let assignedCount = 0;
|
|
1230
1031
|
for (const item of items) {
|
|
@@ -1271,7 +1072,6 @@ class AgentVariantsOrchestrator {
|
|
|
1271
1072
|
});
|
|
1272
1073
|
}
|
|
1273
1074
|
}
|
|
1274
|
-
/** Reads a completed static artifact while enforcing its assigned directory boundary. */
|
|
1275
1075
|
readAssignedStaticArtifact(sessionId, workItemId) {
|
|
1276
1076
|
const workspaceManager = this.resources.get(sessionId)?.workspaceManager;
|
|
1277
1077
|
if (!workspaceManager) {
|
|
@@ -1281,15 +1081,7 @@ class AgentVariantsOrchestrator {
|
|
|
1281
1081
|
}
|
|
1282
1082
|
beginStaticPreviewRefinements(args) {
|
|
1283
1083
|
const seenVariantIds = new Set();
|
|
1284
|
-
// Targets whose in-place refinement could neither be created nor folded
|
|
1285
|
-
// into a pending one (e.g. the variant was already sent). We finish the
|
|
1286
|
-
// batch's other targets, then RETURN these so the caller can surface them
|
|
1287
|
-
// in its response — rather than throwing (which would break the agent poll
|
|
1288
|
-
// and lose the already-consumed batch) or silently dropping them.
|
|
1289
1084
|
const droppedRefinements = [];
|
|
1290
|
-
// Work items THIS batch created, so the caller can tell the agent to lease
|
|
1291
|
-
// exactly these — letting concurrent runs (several watchers) each pick up
|
|
1292
|
-
// their own batch instead of one greedily leasing everything.
|
|
1293
1085
|
const createdWorkItemIds = [];
|
|
1294
1086
|
for (const target of args.targets) {
|
|
1295
1087
|
if (seenVariantIds.has(target.variantId))
|
|
@@ -1310,9 +1102,6 @@ class AgentVariantsOrchestrator {
|
|
|
1310
1102
|
});
|
|
1311
1103
|
const currentHtml = this.getStaticPreviewHtml(args.sessionId, target.variantId);
|
|
1312
1104
|
if (target.count == null) {
|
|
1313
|
-
// Plain Apply (no variantRequest) → refine the variant IN PLACE: one
|
|
1314
|
-
// edit that overwrites the source, no new sibling cards. Only an
|
|
1315
|
-
// explicit "Vary" (which carries a count) fans out new variants.
|
|
1316
1105
|
try {
|
|
1317
1106
|
const refineItem = this.store.createRefineVariantWorkItem({
|
|
1318
1107
|
sessionId: args.sessionId,
|
|
@@ -1327,8 +1116,6 @@ class AgentVariantsOrchestrator {
|
|
|
1327
1116
|
createdWorkItemIds.push(refineItem.id);
|
|
1328
1117
|
}
|
|
1329
1118
|
catch (error) {
|
|
1330
|
-
// A refinement is already queued for this variant — fold the newer
|
|
1331
|
-
// instruction in rather than dropping it (mirrors the apply queue).
|
|
1332
1119
|
if (error instanceof errors_1.AgentVariantsError &&
|
|
1333
1120
|
error.code === 'PENDING_CHANGE_CONFLICT') {
|
|
1334
1121
|
const folded = this.store.appendPendingRefineVariantInstruction({
|
|
@@ -1338,8 +1125,6 @@ class AgentVariantsOrchestrator {
|
|
|
1338
1125
|
fidelity: target.fidelity,
|
|
1339
1126
|
});
|
|
1340
1127
|
if (!folded) {
|
|
1341
|
-
// Nothing to fold into — the conflict is terminal (the variant
|
|
1342
|
-
// was already sent / is no longer editable). Don't swallow it.
|
|
1343
1128
|
droppedRefinements.push({
|
|
1344
1129
|
variantId: target.variantId,
|
|
1345
1130
|
reason: error.message,
|
|
@@ -1359,10 +1144,15 @@ class AgentVariantsOrchestrator {
|
|
|
1359
1144
|
}
|
|
1360
1145
|
continue;
|
|
1361
1146
|
}
|
|
1362
|
-
// "Vary" fans out: create `count` NEW sibling variants seeded from the
|
|
1363
|
-
// source HTML + instruction, rather than overwriting the source in place.
|
|
1364
|
-
// The agent leases them through the standard request-work path.
|
|
1365
1147
|
try {
|
|
1148
|
+
const source = this.store.getWorkItemInput(args.sessionId, target.variantId);
|
|
1149
|
+
const additionalContext = target.additionalContext
|
|
1150
|
+
? (0, variantContext_1.extendVariantContextBundle)({
|
|
1151
|
+
sessionId: args.sessionId,
|
|
1152
|
+
source: source.context,
|
|
1153
|
+
additional: target.additionalContext,
|
|
1154
|
+
})
|
|
1155
|
+
: undefined;
|
|
1366
1156
|
const forks = this.store.createForkedStaticPreviewWorkItems({
|
|
1367
1157
|
sessionId: args.sessionId,
|
|
1368
1158
|
sourceVariantId: target.variantId,
|
|
@@ -1375,18 +1165,15 @@ class AgentVariantsOrchestrator {
|
|
|
1375
1165
|
targetElement: target.element,
|
|
1376
1166
|
relevantFiles: target.relevantFiles,
|
|
1377
1167
|
requestId: target.requestId,
|
|
1168
|
+
additionalContext,
|
|
1378
1169
|
});
|
|
1379
1170
|
createdWorkItemIds.push(...forks.map((item) => item.id));
|
|
1380
1171
|
}
|
|
1381
1172
|
catch (error) {
|
|
1382
|
-
// Terminal conflict — the source is no longer editable, or a variant
|
|
1383
|
-
// was already sent for this session (the fork path has nothing to fold
|
|
1384
|
-
// into). Surface it structurally like the in-place branch instead of
|
|
1385
|
-
// throwing, which would break the agent poll AND lose this batch (the
|
|
1386
|
-
// server already consumed it from the FIFO before calling us).
|
|
1387
1173
|
if (error instanceof errors_1.AgentVariantsError &&
|
|
1388
1174
|
(error.code === 'PENDING_CHANGE_CONFLICT' ||
|
|
1389
|
-
error.code === 'VARIANT_NOT_EDITABLE'
|
|
1175
|
+
error.code === 'VARIANT_NOT_EDITABLE' ||
|
|
1176
|
+
error.code === 'SOURCE_CONTEXT_INVALID')) {
|
|
1390
1177
|
droppedRefinements.push({
|
|
1391
1178
|
variantId: target.variantId,
|
|
1392
1179
|
reason: error.message,
|
|
@@ -1410,24 +1197,6 @@ class AgentVariantsOrchestrator {
|
|
|
1410
1197
|
this.emitChange();
|
|
1411
1198
|
return { droppedRefinements, createdWorkItemIds };
|
|
1412
1199
|
}
|
|
1413
|
-
/**
|
|
1414
|
-
* Adopt a PAST variant (from a prior session's persisted history) into the
|
|
1415
|
-
* active session, rehydrating it from its on-disk static snapshot so the
|
|
1416
|
-
* comment / refine / Vary machinery treats it as a live, first-class variant.
|
|
1417
|
-
*
|
|
1418
|
-
* Triggered when the user makes their first edit on a selected past direction.
|
|
1419
|
-
* The store appends an already-`succeeded` `static_preview` work item keyed by
|
|
1420
|
-
* the past identity (idempotent); this method registers the matching static-
|
|
1421
|
-
* preview record so {@link getStaticPreviewHtml}, {@link getVariants}
|
|
1422
|
-
* (preview.kind = 'static_artifact', view enabled), and the
|
|
1423
|
-
* `/api/variants/:sid/static/:vid` routes all light up exactly as they do for a
|
|
1424
|
-
* freshly-generated static_preview variant.
|
|
1425
|
-
*
|
|
1426
|
-
* `filesDir` is the absolute path to the persisted `files/` snapshot and
|
|
1427
|
-
* `entryPath` is its selected HTML document. Returns the stable active-session
|
|
1428
|
-
* `workItemId` so the caller can route the triggering edit to it, plus whether
|
|
1429
|
-
* it was already adopted.
|
|
1430
|
-
*/
|
|
1431
1200
|
async adoptPastVariant(args) {
|
|
1432
1201
|
const { assetBase, hasAssets } = await this.resolveAdoptedStaticPreviewFiles(args.filesDir, args.entryPath);
|
|
1433
1202
|
const append = this.store.appendAdoptedStaticVariant({
|
|
@@ -1435,6 +1204,7 @@ class AgentVariantsOrchestrator {
|
|
|
1435
1204
|
source: args.source,
|
|
1436
1205
|
label: args.label,
|
|
1437
1206
|
description: args.description,
|
|
1207
|
+
references: args.references,
|
|
1438
1208
|
runLabel: args.runLabel,
|
|
1439
1209
|
});
|
|
1440
1210
|
this.telemetry.trackAgentVariantsRequestStarted?.({
|
|
@@ -1445,8 +1215,6 @@ class AgentVariantsOrchestrator {
|
|
|
1445
1215
|
requestedCount: 1,
|
|
1446
1216
|
sourceVariantId: args.source.variantId,
|
|
1447
1217
|
});
|
|
1448
|
-
// Register (or re-register, harmlessly) the static-preview record so the
|
|
1449
|
-
// snapshot surfaces the adopted variant as a static_artifact.
|
|
1450
1218
|
const resources = this.ensureResources(args.sessionId);
|
|
1451
1219
|
resources.staticPreviews.set(append.workItemId, {
|
|
1452
1220
|
workItemId: append.workItemId,
|
|
@@ -1471,11 +1239,6 @@ class AgentVariantsOrchestrator {
|
|
|
1471
1239
|
alreadyAdopted: !append.created,
|
|
1472
1240
|
};
|
|
1473
1241
|
}
|
|
1474
|
-
/**
|
|
1475
|
-
* Rehydrate a static history variant into the current active session when it
|
|
1476
|
-
* can still accept edits; otherwise create a replacement active session whose
|
|
1477
|
-
* only visible direction is the selected history artifact.
|
|
1478
|
-
*/
|
|
1479
1242
|
async bootstrapPastVariantSession(args) {
|
|
1480
1243
|
const usableSessionId = this.getUsableActiveSessionId();
|
|
1481
1244
|
if (usableSessionId) {
|
|
@@ -1486,6 +1249,7 @@ class AgentVariantsOrchestrator {
|
|
|
1486
1249
|
entryPath: args.entryPath,
|
|
1487
1250
|
label: args.label,
|
|
1488
1251
|
description: args.description,
|
|
1252
|
+
references: args.references,
|
|
1489
1253
|
runLabel: args.runLabel,
|
|
1490
1254
|
});
|
|
1491
1255
|
return {
|
|
@@ -1504,6 +1268,7 @@ class AgentVariantsOrchestrator {
|
|
|
1504
1268
|
prompt: args.prompt ?? args.description ?? args.label,
|
|
1505
1269
|
label: args.label,
|
|
1506
1270
|
description: args.description,
|
|
1271
|
+
references: args.references,
|
|
1507
1272
|
runLabel: args.runLabel,
|
|
1508
1273
|
projectContext: args.projectContext,
|
|
1509
1274
|
});
|
|
@@ -1556,12 +1321,6 @@ class AgentVariantsOrchestrator {
|
|
|
1556
1321
|
}
|
|
1557
1322
|
return { assetBase, hasAssets };
|
|
1558
1323
|
}
|
|
1559
|
-
/**
|
|
1560
|
-
* True when the variant is an HTML-only static_preview work item. Adopted past
|
|
1561
|
-
* variants and fresh `static_preview` variants both qualify. Existing-project
|
|
1562
|
-
* `code_gen` variants can still expose a static artifact for preview, but Vary
|
|
1563
|
-
* must keep those on the worktree-backed code_gen append path.
|
|
1564
|
-
*/
|
|
1565
1324
|
isStaticPreviewVariant(sessionId, workItemId) {
|
|
1566
1325
|
try {
|
|
1567
1326
|
return (this.store.getWorkItemKind(sessionId, workItemId) === 'static_preview');
|
|
@@ -1570,11 +1329,6 @@ class AgentVariantsOrchestrator {
|
|
|
1570
1329
|
return false;
|
|
1571
1330
|
}
|
|
1572
1331
|
}
|
|
1573
|
-
/**
|
|
1574
|
-
* Resolve the history source for a forked Vary row. If the immediate parent
|
|
1575
|
-
* is an adopted past direction, collapse against that original history row;
|
|
1576
|
-
* otherwise collapse against the same-session parent variant.
|
|
1577
|
-
*/
|
|
1578
1332
|
resolveHistoryParentVariant(sessionId, sourceVariantId) {
|
|
1579
1333
|
if (!sourceVariantId)
|
|
1580
1334
|
return undefined;
|
|
@@ -1641,10 +1395,6 @@ class AgentVariantsOrchestrator {
|
|
|
1641
1395
|
workItemCount: 1,
|
|
1642
1396
|
instructionLength: args.instruction.length,
|
|
1643
1397
|
});
|
|
1644
|
-
// Lease the just-created refine item by id. A generic
|
|
1645
|
-
// requestWork({ requestedLeaseCount: 1 }) takes the first leasable item in
|
|
1646
|
-
// work-item order, which could be an unrelated still-pending static_preview
|
|
1647
|
-
// rather than this refinement.
|
|
1648
1398
|
return this.requestWork({
|
|
1649
1399
|
sessionId: args.sessionId,
|
|
1650
1400
|
leaseOwner: args.leaseOwner,
|
|
@@ -1657,7 +1407,6 @@ class AgentVariantsOrchestrator {
|
|
|
1657
1407
|
getWorkItemInput(sessionId, workItemId) {
|
|
1658
1408
|
return this.store.getWorkItemInput(sessionId, workItemId);
|
|
1659
1409
|
}
|
|
1660
|
-
/** Returns status after orchestration QA and refinement post-processing. */
|
|
1661
1410
|
getWorkItemStatus(sessionId, workItemId) {
|
|
1662
1411
|
return this.store.getWorkItemStatus(sessionId, workItemId);
|
|
1663
1412
|
}
|
|
@@ -1674,16 +1423,10 @@ class AgentVariantsOrchestrator {
|
|
|
1674
1423
|
const resources = this.resources.get(sessionId);
|
|
1675
1424
|
return this.store.getVariants(sessionId).map((variant) => {
|
|
1676
1425
|
const port = this.getDevServerPort(sessionId, variant.workItemId);
|
|
1677
|
-
// Captured worktree diff (existing-project code_gen). Surfaced as a
|
|
1678
|
-
// changed-files count so a diff-only variant (no dev server / static
|
|
1679
|
-
// artifact) still reads as a real result in the panel.
|
|
1680
1426
|
const capturedDiff = resources?.worktrees.get(variant.workItemId)?.diff;
|
|
1681
1427
|
const changedFilesCount = typeof capturedDiff === 'string' && capturedDiff.length > 0
|
|
1682
1428
|
? countDiffFiles(capturedDiff)
|
|
1683
1429
|
: undefined;
|
|
1684
|
-
// For fresh sessions, static_preview items ARE the variants — look up
|
|
1685
|
-
// directly by workItemId. Fall back to briefId search for existing-project
|
|
1686
|
-
// sessions where code_gen items were paired with companion static_preview items.
|
|
1687
1430
|
const staticPreview = resources?.staticPreviews.get(variant.workItemId) ??
|
|
1688
1431
|
this.getStaticPreviewByBriefId(sessionId, variant.briefId);
|
|
1689
1432
|
let preview;
|
|
@@ -1694,11 +1437,6 @@ class AgentVariantsOrchestrator {
|
|
|
1694
1437
|
};
|
|
1695
1438
|
}
|
|
1696
1439
|
else if (!port) {
|
|
1697
|
-
// handleSucceededReport is fire-and-forget so staticPreviews may not be
|
|
1698
|
-
// populated yet when getVariants is called (e.g. in the terminal response).
|
|
1699
|
-
// item.output is set synchronously by store.reportComplete, so it's always
|
|
1700
|
-
// available. Read it directly as a fallback so previewUrls in terminal
|
|
1701
|
-
// responses include the variant that just triggered terminal state.
|
|
1702
1440
|
try {
|
|
1703
1441
|
const output = this.store.getWorkItemOutput(sessionId, variant.workItemId);
|
|
1704
1442
|
if (typeof output?.html === 'string' && output.html.length > 0) {
|
|
@@ -1708,9 +1446,7 @@ class AgentVariantsOrchestrator {
|
|
|
1708
1446
|
};
|
|
1709
1447
|
}
|
|
1710
1448
|
}
|
|
1711
|
-
catch {
|
|
1712
|
-
/* work item may not exist in edge cases */
|
|
1713
|
-
}
|
|
1449
|
+
catch { }
|
|
1714
1450
|
}
|
|
1715
1451
|
if (!preview && port) {
|
|
1716
1452
|
preview = { kind: 'dev_server', port };
|
|
@@ -1719,9 +1455,6 @@ class AgentVariantsOrchestrator {
|
|
|
1719
1455
|
const isSucceeded = variant.status === 'succeeded';
|
|
1720
1456
|
const qaFailed = qa?.status === 'failed';
|
|
1721
1457
|
const canView = Boolean(preview) || (isSucceeded && Boolean(port));
|
|
1722
|
-
// A succeeded variant with no live preview whose dev server we tried and
|
|
1723
|
-
// failed to start: surface the cause so the UI can show an accurate
|
|
1724
|
-
// per-direction message instead of the generic disconnected overlay.
|
|
1725
1458
|
const previewFailure = resources?.previewFailures.get(variant.workItemId);
|
|
1726
1459
|
const previewUnavailable = !canView && isSucceeded && previewFailure
|
|
1727
1460
|
? {
|
|
@@ -1765,36 +1498,19 @@ class AgentVariantsOrchestrator {
|
|
|
1765
1498
|
hasSession(sessionId) {
|
|
1766
1499
|
return this.store.hasSession(sessionId);
|
|
1767
1500
|
}
|
|
1768
|
-
/** Read the projectContext for a session — used by Express routes that
|
|
1769
|
-
* build the chip snapshot via `stateForSession`. */
|
|
1770
1501
|
getProjectContext(sessionId) {
|
|
1771
1502
|
return this.store.getProjectContext(sessionId);
|
|
1772
1503
|
}
|
|
1773
|
-
/** Resolve a worktree path for a code-gen work item, if provisioned. */
|
|
1774
1504
|
getWorktreePath(sessionId, workItemId) {
|
|
1775
1505
|
return this.resources.get(sessionId)?.worktrees.get(workItemId)
|
|
1776
1506
|
?.worktreePath;
|
|
1777
1507
|
}
|
|
1778
|
-
/**
|
|
1779
|
-
* Resolve the project cwd inside a worktree so subdirectory projects run
|
|
1780
|
-
* from the same repo-relative location.
|
|
1781
|
-
*/
|
|
1782
1508
|
getProjectCwdInWorktree(worktreePath) {
|
|
1783
1509
|
return this.worktrees.getProjectCwdInWorktree(worktreePath);
|
|
1784
1510
|
}
|
|
1785
|
-
/** Resolve the dev server port for a code-gen work item, if running. */
|
|
1786
1511
|
getDevServerPort(sessionId, workItemId) {
|
|
1787
1512
|
return this.resources.get(sessionId)?.worktrees.get(workItemId)?.port;
|
|
1788
1513
|
}
|
|
1789
|
-
/**
|
|
1790
|
-
* Restores a Rivet-owned preview after idle reclamation or an explicit retry
|
|
1791
|
-
* of a failed start. Reuses the saved worktree without leasing generation work.
|
|
1792
|
-
*
|
|
1793
|
-
* @effect Clears the idle marker and prior crash budget, starts the worktree
|
|
1794
|
-
* dev server, and emits preview-state snapshots.
|
|
1795
|
-
* @deps Uses the live session resources, project context, and dev-server
|
|
1796
|
-
* manager owned by this orchestrator.
|
|
1797
|
-
*/
|
|
1798
1514
|
async restoreVariantPreview(sessionId, workItemId, options = {}) {
|
|
1799
1515
|
const resources = this.resources.get(sessionId);
|
|
1800
1516
|
const record = resources?.worktrees.get(workItemId);
|
|
@@ -1836,10 +1552,6 @@ class AgentVariantsOrchestrator {
|
|
|
1836
1552
|
record.previewRestoration = undefined;
|
|
1837
1553
|
}
|
|
1838
1554
|
}
|
|
1839
|
-
/**
|
|
1840
|
-
* @effect Resolves the dev server port for a preview request and refreshes
|
|
1841
|
-
* active-preview retention for that session while the port is still live.
|
|
1842
|
-
*/
|
|
1843
1555
|
resolveDevServerPortForPreview(sessionId, workItemId) {
|
|
1844
1556
|
const port = this.getDevServerPort(sessionId, workItemId);
|
|
1845
1557
|
if (typeof port === 'number') {
|
|
@@ -1847,14 +1559,6 @@ class AgentVariantsOrchestrator {
|
|
|
1847
1559
|
}
|
|
1848
1560
|
return port;
|
|
1849
1561
|
}
|
|
1850
|
-
/**
|
|
1851
|
-
* True work-item kind for a variant, or undefined when the session/item is
|
|
1852
|
-
* unknown. This is the authoritative routing signal for Vary/refine intakes:
|
|
1853
|
-
* an existing-project `code_gen` variant materialized as a static preview
|
|
1854
|
-
* (registerExistingStaticPreview) DISPLAYS as `static_artifact` and serves
|
|
1855
|
-
* HTML, but must fork via the code_gen/worktree path — HTML presence is not
|
|
1856
|
-
* a valid discriminator.
|
|
1857
|
-
*/
|
|
1858
1562
|
getVariantWorkItemKind(sessionId, workItemId) {
|
|
1859
1563
|
try {
|
|
1860
1564
|
return this.store.getWorkItemKind(sessionId, workItemId);
|
|
@@ -1864,9 +1568,6 @@ class AgentVariantsOrchestrator {
|
|
|
1864
1568
|
}
|
|
1865
1569
|
}
|
|
1866
1570
|
getStaticPreviewHtml(sessionId, workItemId) {
|
|
1867
|
-
// Primary: read the materialized entry from the variant's per-variant
|
|
1868
|
-
// directory (written by handleSucceededReport). The directory is the source
|
|
1869
|
-
// of truth for the static deliverable.
|
|
1870
1571
|
const preview = this.resources
|
|
1871
1572
|
.get(sessionId)
|
|
1872
1573
|
?.staticPreviews.get(workItemId);
|
|
@@ -1876,13 +1577,8 @@ class AgentVariantsOrchestrator {
|
|
|
1876
1577
|
if (fromDisk.length > 0)
|
|
1877
1578
|
return fromDisk;
|
|
1878
1579
|
}
|
|
1879
|
-
catch {
|
|
1880
|
-
// fall through to the work-item output fallback below
|
|
1881
|
-
}
|
|
1580
|
+
catch { }
|
|
1882
1581
|
}
|
|
1883
|
-
// Fallback: read directly from the work item's stored output — available
|
|
1884
|
-
// as soon as reportComplete runs, before handleSucceededReport fires (so
|
|
1885
|
-
// the per-variant directory may not exist yet).
|
|
1886
1582
|
try {
|
|
1887
1583
|
const output = this.store.getWorkItemOutput(sessionId, workItemId);
|
|
1888
1584
|
return typeof output?.html === 'string' && output.html.length > 0
|
|
@@ -1893,38 +1589,20 @@ class AgentVariantsOrchestrator {
|
|
|
1893
1589
|
return undefined;
|
|
1894
1590
|
}
|
|
1895
1591
|
}
|
|
1896
|
-
/** Resolve the DESIGN.md markdown behind an artifact link. */
|
|
1897
1592
|
getDesignContextMarkdown(sessionId, artifactId) {
|
|
1898
1593
|
const artifact = findDesignContextArtifact(this.store.getProjectContext(sessionId), artifactId);
|
|
1899
1594
|
return artifact?.content;
|
|
1900
1595
|
}
|
|
1901
|
-
/** Build the rendered DesignMD document for an artifact link. */
|
|
1902
1596
|
getDesignContextViewerHtml(sessionId, artifactId) {
|
|
1903
1597
|
const artifact = findDesignContextArtifact(this.store.getProjectContext(sessionId), artifactId);
|
|
1904
1598
|
return artifact ? buildDesignContextViewerDocument(artifact) : undefined;
|
|
1905
1599
|
}
|
|
1906
|
-
/**
|
|
1907
|
-
* `true` when the variant has a non-empty `assetBase` — i.e. its inlined
|
|
1908
|
-
* HTML references sibling files served by the asset route. The route
|
|
1909
|
-
* uses this to decide whether to inject a `<base href>` (only needed
|
|
1910
|
-
* when relative URLs in the HTML must resolve against the asset
|
|
1911
|
-
* sub-path). Self-contained HTML keeps its natural URL resolution.
|
|
1912
|
-
*/
|
|
1913
1600
|
hasStaticPreviewAssets(sessionId, workItemId) {
|
|
1914
1601
|
const record = this.resources
|
|
1915
1602
|
.get(sessionId)
|
|
1916
1603
|
?.staticPreviews.get(workItemId);
|
|
1917
1604
|
return Boolean(record?.hasAssets);
|
|
1918
1605
|
}
|
|
1919
|
-
/**
|
|
1920
|
-
* Resolve an absolute, sandboxed path for a sibling asset that the
|
|
1921
|
-
* variant's inlined HTML references (e.g. `./avatar.glb`, `./hero.png`).
|
|
1922
|
-
* Returns `undefined` when the variant has no `assetBase`, the requested
|
|
1923
|
-
* path escapes the base (path traversal), or the file does not exist.
|
|
1924
|
-
*
|
|
1925
|
-
* Used by the `/api/variants/:sessionId/static/:variantId/<asset>` route
|
|
1926
|
-
* to serve assets from the agent's on-disk variant workspace pre-commit.
|
|
1927
|
-
*/
|
|
1928
1606
|
resolveStaticPreviewAssetPath(sessionId, workItemId, requestedPath) {
|
|
1929
1607
|
const record = this.resources
|
|
1930
1608
|
.get(sessionId)
|
|
@@ -1933,12 +1611,6 @@ class AgentVariantsOrchestrator {
|
|
|
1933
1611
|
return undefined;
|
|
1934
1612
|
if (!requestedPath || requestedPath.length === 0)
|
|
1935
1613
|
return undefined;
|
|
1936
|
-
// Resolve against the variant's own directory first so any asset the agent
|
|
1937
|
-
// actually wrote/modified wins. Only when the worktree clone lacks the file
|
|
1938
|
-
// do we fall back to the host project root — that recovers git-ignored or
|
|
1939
|
-
// binary assets the worktree provisioning couldn't carry over, which the
|
|
1940
|
-
// original preview already serves (see `assetFallbackBase`). Both roots are
|
|
1941
|
-
// held to the identical traversal/realpath/hardlink sandbox.
|
|
1942
1614
|
return (resolveAssetWithinBase(record.assetBase, requestedPath) ??
|
|
1943
1615
|
(record.assetFallbackBase
|
|
1944
1616
|
? resolveAssetWithinBase(record.assetFallbackBase, requestedPath)
|
|
@@ -1955,7 +1627,6 @@ class AgentVariantsOrchestrator {
|
|
|
1955
1627
|
const safeWorkItemId = encodeURIComponent(workItemId);
|
|
1956
1628
|
return `/api/variants/${safeSessionId}/static/${safeWorkItemId}`;
|
|
1957
1629
|
}
|
|
1958
|
-
// --- Mutation wrappers (state + side effects) ---------------------------
|
|
1959
1630
|
async approve(args) {
|
|
1960
1631
|
const result = this.store.approve(args);
|
|
1961
1632
|
const resources = this.ensureResources(args.sessionId);
|
|
@@ -1976,11 +1647,6 @@ class AgentVariantsOrchestrator {
|
|
|
1976
1647
|
workItemIds,
|
|
1977
1648
|
});
|
|
1978
1649
|
this.emitChange();
|
|
1979
|
-
// Await provisioning before returning so request_work always sees a
|
|
1980
|
-
// populated worktreePath on each leased item. Provisioning creates a
|
|
1981
|
-
// git worktree and copies dependencies for each variant, and the
|
|
1982
|
-
// agent has nothing useful to do between approve and request_work
|
|
1983
|
-
// anyway — running them serially is the contract the skill assumes.
|
|
1984
1650
|
try {
|
|
1985
1651
|
if (projectContext.kind === 'existing') {
|
|
1986
1652
|
await this.resolveContextAssetPreviewKind(args.sessionId);
|
|
@@ -1994,50 +1660,19 @@ class AgentVariantsOrchestrator {
|
|
|
1994
1660
|
}
|
|
1995
1661
|
return result;
|
|
1996
1662
|
}
|
|
1997
|
-
/**
|
|
1998
|
-
* Unified one-call kickoff that collapses propose → report_briefs →
|
|
1999
|
-
* approve. Uses AI-authored briefs supplied by agent callers, with a
|
|
2000
|
-
* deterministic prompt-derived fallback for human-direct calls, and
|
|
2001
|
-
* immediately approves so the session lands in `work_items_ready`.
|
|
2002
|
-
*
|
|
2003
|
-
* Supports both existing-project sessions (spawns code_gen work items
|
|
2004
|
-
* for the agent to lease) and zero-to-one sessions (spawns
|
|
2005
|
-
* static_preview work items; the server runs scaffold_base in the
|
|
2006
|
-
* background). This is the single-call path; source-grounded zero-to-one
|
|
2007
|
-
* sessions (source URLs / inspiration extraction) run through `propose`
|
|
2008
|
-
* instead so the source-research flow can gate generation — start_variants
|
|
2009
|
-
* routes them there. This method does not run source research.
|
|
2010
|
-
*
|
|
2011
|
-
* Host-agnostic: no LLM calls happen here. The agent (Claude Code,
|
|
2012
|
-
* Cursor, Codex) generates the label and code when it leases the
|
|
2013
|
-
* work items via continue_variants(action="request_work").
|
|
2014
|
-
*/
|
|
2015
1663
|
async startUnified(args) {
|
|
1664
|
+
args.assertContext?.();
|
|
2016
1665
|
const count = args.briefs?.length ?? args.count ?? contracts_1.DEFAULT_VARIANT_COUNT;
|
|
2017
1666
|
const projectContext = args.projectContext ?? {
|
|
2018
1667
|
kind: 'existing',
|
|
2019
1668
|
};
|
|
2020
1669
|
const designContextCount = projectContext.designContext?.length ?? 0;
|
|
2021
|
-
// Fresh source-grounded sessions (a captured context bundle on a fresh
|
|
2022
|
-
// project) must run through `propose` so the source-research/source_plan
|
|
2023
|
-
// flow gates generation; start_variants routes them there before reaching
|
|
2024
|
-
// here, so this guard is an internal invariant. Existing-project sessions
|
|
2025
|
-
// keep the single-call path even with a bundle — they have no source_plan
|
|
2026
|
-
// stage, and the bundle's raw context is threaded straight into code_gen.
|
|
2027
|
-
// Brief-driven fresh starts are exempt for the same reason: the caller
|
|
2028
|
-
// already did its source research when it authored the briefs, so the
|
|
2029
|
-
// bundle is raw worker context (reference images), not research input.
|
|
2030
1670
|
const isSourceGrounded = projectContext.kind === 'fresh' &&
|
|
2031
1671
|
Boolean(projectContext.variantContext) &&
|
|
2032
1672
|
!args.briefs?.length;
|
|
2033
1673
|
if (isSourceGrounded) {
|
|
2034
1674
|
throw new errors_1.AgentVariantsError('INVALID_STAGE_ACTION', 'Source-grounded sessions must run through the source-research flow (propose), not the single-call startUnified path.');
|
|
2035
1675
|
}
|
|
2036
|
-
// A second "Vary" on an existing project that still has a live session
|
|
2037
|
-
// ACCUMULATES into that session instead of starting a fresh one that
|
|
2038
|
-
// would orphan the prior variants (and overwrite `activeSessionId`, so
|
|
2039
|
-
// the RHS would only ever show the latest batch). Gated to existing
|
|
2040
|
-
// projects so fresh 0→1 generation is unaffected.
|
|
2041
1676
|
const appendSessionId = args.allowAccumulate &&
|
|
2042
1677
|
projectContext.kind === 'existing' &&
|
|
2043
1678
|
projectContext.projectPath
|
|
@@ -2075,8 +1710,6 @@ class AgentVariantsOrchestrator {
|
|
|
2075
1710
|
};
|
|
2076
1711
|
const { createdWorkItemIds } = this.store.appendCodeGenVariants({
|
|
2077
1712
|
...forkArgs,
|
|
2078
|
-
// Fork parent (Vary on a variant): seeds each new worktree from the
|
|
2079
|
-
// parent's tree instead of the base tree. Absent for a plain append.
|
|
2080
1713
|
...(args.sourceVariantId
|
|
2081
1714
|
? { sourceVariantId: args.sourceVariantId }
|
|
2082
1715
|
: {}),
|
|
@@ -2115,8 +1748,6 @@ class AgentVariantsOrchestrator {
|
|
|
2115
1748
|
projectContext,
|
|
2116
1749
|
runLabel: args.runLabel,
|
|
2117
1750
|
...(args.fidelity ? { fidelity: args.fidelity } : {}),
|
|
2118
|
-
// Briefs land via reportBriefs immediately below — never enter the
|
|
2119
|
-
// source-plan stage, even for a fresh session carrying a bundle.
|
|
2120
1751
|
hasPreparedBriefs: true,
|
|
2121
1752
|
...(args.sessionId ? { sessionId: args.sessionId } : {}),
|
|
2122
1753
|
});
|
|
@@ -2147,18 +1778,11 @@ class AgentVariantsOrchestrator {
|
|
|
2147
1778
|
});
|
|
2148
1779
|
sessionId = proposeResult.sessionId;
|
|
2149
1780
|
scaffoldBaseWorkItemId = approveResult.scaffoldBaseWorkItemId ?? null;
|
|
2150
|
-
// For existing-project sessions, approve() returns the new code_gen
|
|
2151
|
-
// ids in codeGenWorkItemIds. For zero-to-one, approve() spawns
|
|
2152
|
-
// static_preview items instead — those ids aren't in codeGenWorkItemIds,
|
|
2153
|
-
// so read them out of the active-variants snapshot which covers both
|
|
2154
|
-
// kinds. Snapshot order mirrors brief order (insertion order).
|
|
2155
1781
|
variantIds =
|
|
2156
1782
|
projectContext.kind === 'fresh'
|
|
2157
1783
|
? this.store.getVariants(sessionId).map((v) => v.workItemId)
|
|
2158
1784
|
: approveResult.codeGenWorkItemIds;
|
|
2159
1785
|
}
|
|
2160
|
-
// Stamp the UI correlation id so the panel maps its optimistic placeholders
|
|
2161
|
-
// to these real cards (the same mechanism the static-preview fork uses).
|
|
2162
1786
|
if (args.requestId) {
|
|
2163
1787
|
this.store.assignVariantRequestId(sessionId, variantIds, args.requestId);
|
|
2164
1788
|
}
|
|
@@ -2188,12 +1812,17 @@ class AgentVariantsOrchestrator {
|
|
|
2188
1812
|
let leaseId;
|
|
2189
1813
|
let leaseTtlMs;
|
|
2190
1814
|
let leasedWorkItems;
|
|
1815
|
+
try {
|
|
1816
|
+
args.assertContext?.();
|
|
1817
|
+
}
|
|
1818
|
+
catch (error) {
|
|
1819
|
+
await Promise.all(variantIds.map((variantId) => this.cancelVariant({ sessionId, variantId })));
|
|
1820
|
+
throw error;
|
|
1821
|
+
}
|
|
2191
1822
|
if (args.leaseOwner) {
|
|
2192
1823
|
const lease = this.requestWork({
|
|
2193
1824
|
sessionId,
|
|
2194
1825
|
leaseOwner: args.leaseOwner,
|
|
2195
|
-
// Append: lease ONLY the new batch so a still-leasable prior item
|
|
2196
|
-
// (e.g. a re-leased one) isn't swept into this Vary's lease.
|
|
2197
1826
|
...(appendSessionId ? { workItemIds: variantIds } : {}),
|
|
2198
1827
|
});
|
|
2199
1828
|
leaseId = lease.leaseId;
|
|
@@ -2209,15 +1838,6 @@ class AgentVariantsOrchestrator {
|
|
|
2209
1838
|
leasedWorkItems,
|
|
2210
1839
|
};
|
|
2211
1840
|
}
|
|
2212
|
-
/**
|
|
2213
|
-
* Build the per-variant briefs for a unified start. Supplied briefs keep
|
|
2214
|
-
* meaningful direction labels, while duplicate or empty labels are made
|
|
2215
|
-
* unique against the visible session rows. The fallback derives a short
|
|
2216
|
-
* run-intent label from the prompt (e.g. "make it brighter" →
|
|
2217
|
-
* "Brighter 1/2/…") rather than an indistinct "Variant N". `uniqueBriefIds`
|
|
2218
|
-
* is set for the append path so the new batch's briefIds can't collide with
|
|
2219
|
-
* the live session's existing ones.
|
|
2220
|
-
*/
|
|
2221
1841
|
buildUnifiedBriefs(args) {
|
|
2222
1842
|
const briefId = (i) => args.uniqueBriefIds ? `v-${(0, crypto_1.randomUUID)().slice(0, 8)}` : `v${i + 1}`;
|
|
2223
1843
|
const runLabel = args.runLabel?.trim() || (0, runLabel_1.deriveRunLabel)(args.prompt);
|
|
@@ -2247,13 +1867,6 @@ class AgentVariantsOrchestrator {
|
|
|
2247
1867
|
body: synthesizeUnifiedBriefBody(args.prompt, i + 1, args.count),
|
|
2248
1868
|
}, i));
|
|
2249
1869
|
}
|
|
2250
|
-
/**
|
|
2251
|
-
* The active sessionId IF it is an existing-project session for `projectPath`
|
|
2252
|
-
* that can still accept appended variants — i.e. not committed, not
|
|
2253
|
-
* cancelled/failed. Returns null otherwise, so start_variants falls back to
|
|
2254
|
-
* creating a fresh session (first Vary, a different project, or after the
|
|
2255
|
-
* prior session was committed/cancelled).
|
|
2256
|
-
*/
|
|
2257
1870
|
getAppendableExistingSessionId(projectPath) {
|
|
2258
1871
|
const sessionId = this.activeSessionId;
|
|
2259
1872
|
if (!sessionId || !this.store.hasSession(sessionId))
|
|
@@ -2268,7 +1881,6 @@ class AgentVariantsOrchestrator {
|
|
|
2268
1881
|
return null;
|
|
2269
1882
|
return sessionId;
|
|
2270
1883
|
}
|
|
2271
|
-
/** @effect Registers a provisioned git worktree with runtime and workspace state. */
|
|
2272
1884
|
async registerWorktreeWorkspace(resources, record) {
|
|
2273
1885
|
let projectPath = record.worktreePath;
|
|
2274
1886
|
try {
|
|
@@ -2284,15 +1896,6 @@ class AgentVariantsOrchestrator {
|
|
|
2284
1896
|
projectPath,
|
|
2285
1897
|
});
|
|
2286
1898
|
}
|
|
2287
|
-
/**
|
|
2288
|
-
* Provision a worktree for each appended existing-project variant. Mirrors
|
|
2289
|
-
* {@link provisionExistingWorktrees} but only for the newly appended ids, and
|
|
2290
|
-
* passes a per-batch `instanceKeyPrefix` so the new worktree dirs do not
|
|
2291
|
-
* collide with the first batch's `${sessionId}-${i}` paths.
|
|
2292
|
-
*/
|
|
2293
|
-
/** Emits provisioning started/completed/failed telemetry around `run` for
|
|
2294
|
-
* the vary-fork/append lanes that bypass provisionWorktrees (and its
|
|
2295
|
-
* telemetry). Rethrows failures untouched. */
|
|
2296
1899
|
async withProvisioningTelemetry(args, run) {
|
|
2297
1900
|
const startedAt = Date.now();
|
|
2298
1901
|
this.telemetry.track('agent_variants.provisioning_started', {
|
|
@@ -2347,11 +1950,6 @@ class AgentVariantsOrchestrator {
|
|
|
2347
1950
|
})));
|
|
2348
1951
|
});
|
|
2349
1952
|
}
|
|
2350
|
-
/**
|
|
2351
|
-
* Provision worktrees for a code_gen Vary forked from a parent variant.
|
|
2352
|
-
* Copies the parent's worktree tree so each sibling starts from the parent's
|
|
2353
|
-
* diff rather than git HEAD / Original.
|
|
2354
|
-
*/
|
|
2355
1953
|
async provisionForkedFromVariantWorktrees(sessionId, sourceVariantId, workItemIds) {
|
|
2356
1954
|
if (workItemIds.length === 0)
|
|
2357
1955
|
return;
|
|
@@ -2359,13 +1957,14 @@ class AgentVariantsOrchestrator {
|
|
|
2359
1957
|
if (!sourcePath) {
|
|
2360
1958
|
throw new errors_1.AgentVariantsError('VARIANT_NOT_EDITABLE', `Cannot fork from variant ${sourceVariantId}: no worktree path`);
|
|
2361
1959
|
}
|
|
2362
|
-
|
|
1960
|
+
const forkWorktreesFrom = this.worktrees.forkWorktreesFrom?.bind(this.worktrees);
|
|
1961
|
+
if (!forkWorktreesFrom) {
|
|
2363
1962
|
throw new errors_1.AgentVariantsError('RUNTIME_VALIDATION_FAILED', 'worktreeManager does not implement forkWorktreesFrom');
|
|
2364
1963
|
}
|
|
2365
1964
|
await this.withProvisioningTelemetry({ sessionId, kind: 'forked_variant', variantCount: workItemIds.length }, async () => {
|
|
2366
1965
|
const resources = this.ensureResources(sessionId);
|
|
2367
1966
|
const instanceKeyPrefix = `f${(0, crypto_1.randomUUID)().slice(0, 8)}-`;
|
|
2368
|
-
const paths = await withProvisionTimeout(
|
|
1967
|
+
const paths = await withProvisionTimeout(forkWorktreesFrom(sourcePath, sessionId, workItemIds.length, instanceKeyPrefix), this.provisionTimeoutMs);
|
|
2369
1968
|
await Promise.all(workItemIds.map((id, index) => this.registerWorktreeWorkspace(resources, {
|
|
2370
1969
|
workItemId: id,
|
|
2371
1970
|
worktreePath: paths[index],
|
|
@@ -2373,15 +1972,7 @@ class AgentVariantsOrchestrator {
|
|
|
2373
1972
|
});
|
|
2374
1973
|
}
|
|
2375
1974
|
async reportComplete(args) {
|
|
2376
|
-
// Phase-timing anchor: lease→report (agent work) vs report→recorded
|
|
2377
|
-
// (QA gate + post-processing) are attributed separately on
|
|
2378
|
-
// `variant_completed` so latency work can tell them apart.
|
|
2379
1975
|
const reportReceivedAt = Date.now();
|
|
2380
|
-
// Cooperative abort short-circuit: if the work item was removed/cancelled
|
|
2381
|
-
// while in flight (delete-while-loading, cancel_variant, session cancel),
|
|
2382
|
-
// skip the schema and QA gates entirely — there is no point validating or
|
|
2383
|
-
// QA-ing output we are about to discard — and hand back the store's
|
|
2384
|
-
// `aborted` signal so the agent stops this work item now.
|
|
2385
1976
|
if (this.store.hasSession(args.sessionId) &&
|
|
2386
1977
|
this.store.isWorkItemAborted(args.sessionId, args.workItemId)) {
|
|
2387
1978
|
return this.store.reportComplete(args);
|
|
@@ -2405,9 +1996,6 @@ class AgentVariantsOrchestrator {
|
|
|
2405
1996
|
output: this.readAssignedStaticArtifact(args.sessionId, args.workItemId),
|
|
2406
1997
|
}
|
|
2407
1998
|
: args;
|
|
2408
|
-
// Contract validation keeps internal callers that provide an explicit
|
|
2409
|
-
// static output honest. Host workers complete assigned artifacts without
|
|
2410
|
-
// transporting the HTML through this report.
|
|
2411
1999
|
if (resolvedArgs.status === 'succeeded' &&
|
|
2412
2000
|
this.store.hasSession(args.sessionId) &&
|
|
2413
2001
|
(workItemKind === 'static_preview' ||
|
|
@@ -2425,27 +2013,15 @@ class AgentVariantsOrchestrator {
|
|
|
2425
2013
|
}
|
|
2426
2014
|
throw new errors_1.AgentVariantsError('SCHEMA_VALIDATION_FAILED', `${workItemKind} output.html must be a string and non-empty when explicit output is provided. Host workers should write the assigned index.html instead.`);
|
|
2427
2015
|
}
|
|
2428
|
-
// Check Rivet-owned output integrity synchronously before recording
|
|
2429
|
-
// success. A terminal failure uses `VARIANT_QA_FAILED` so the variant never
|
|
2430
|
-
// reaches `ready` and `getVariants` can disable its commit action.
|
|
2431
2016
|
const qaStartedAt = Date.now();
|
|
2432
2017
|
const qaEval = workItemKind === 'refine_variant'
|
|
2433
2018
|
? null
|
|
2434
2019
|
: await this.evaluateQaForReport(resolvedArgs);
|
|
2435
2020
|
const qaMs = qaEval === null ? null : Date.now() - qaStartedAt;
|
|
2436
|
-
// A `retry` verdict re-leases the variant for one structural repair instead
|
|
2437
|
-
// of recording success, so short-circuit the normal record path.
|
|
2438
2021
|
if (qaEval?.decision === 'retry') {
|
|
2439
2022
|
return this.handleQaRegenRetry(resolvedArgs, qaEval.qa);
|
|
2440
2023
|
}
|
|
2441
2024
|
let effectiveArgs = qaEval?.decision === 'fail_terminal' ? qaEval.overrideArgs : resolvedArgs;
|
|
2442
|
-
// For a successful refine_variant, swap the refined static preview into
|
|
2443
|
-
// place and persist history BEFORE recording success in the store. This
|
|
2444
|
-
// keeps the user-visible `refinement.status: succeeded` (and the snapshot
|
|
2445
|
-
// emitted below) from ever being observable while the variant still serves
|
|
2446
|
-
// stale HTML. If post-processing throws, convert the report to `failed` so
|
|
2447
|
-
// the agent/UI surface the failure instead of a success pointing at
|
|
2448
|
-
// unrefreshed output.
|
|
2449
2025
|
if (workItemKind === 'refine_variant' &&
|
|
2450
2026
|
effectiveArgs.status === 'succeeded') {
|
|
2451
2027
|
try {
|
|
@@ -2492,9 +2068,6 @@ class AgentVariantsOrchestrator {
|
|
|
2492
2068
|
throw error;
|
|
2493
2069
|
}
|
|
2494
2070
|
this.emitChange();
|
|
2495
|
-
// Per-variant telemetry on terminal item statuses (skip 'running'
|
|
2496
|
-
// heartbeats and the brief work item — only code_gen / scaffold_base
|
|
2497
|
-
// matter for the funnel).
|
|
2498
2071
|
if (effectiveArgs.status === 'succeeded' ||
|
|
2499
2072
|
effectiveArgs.status === 'failed' ||
|
|
2500
2073
|
effectiveArgs.status === 'cancelled') {
|
|
@@ -2503,11 +2076,8 @@ class AgentVariantsOrchestrator {
|
|
|
2503
2076
|
const durationMs = leasedAt !== undefined ? Date.now() - leasedAt : null;
|
|
2504
2077
|
const approveStartedAt = resources?.approveStartedAt;
|
|
2505
2078
|
const approveToCompleteMs = approveStartedAt !== undefined ? Date.now() - approveStartedAt : null;
|
|
2506
|
-
// Byte size of generated output for HTML vs full-stack comparison.
|
|
2507
2079
|
const outputBytes = estimateOutputBytes(effectiveArgs.output);
|
|
2508
2080
|
const projectContextKind = this.store.getProjectContext(args.sessionId).kind;
|
|
2509
|
-
// Execution mode mirrors the host work-item snapshot derivation so
|
|
2510
|
-
// prod latency can finally segment vary vs create vs refine.
|
|
2511
2081
|
const mode = workItemKind !== undefined && isImplementationWorkItemKind(workItemKind)
|
|
2512
2082
|
? this.store.isVaryForkWorkItem(args.sessionId, args.workItemId)
|
|
2513
2083
|
? 'vary'
|
|
@@ -2523,15 +2093,11 @@ class AgentVariantsOrchestrator {
|
|
|
2523
2093
|
approveToCompleteMs,
|
|
2524
2094
|
kind: workItemKind ?? null,
|
|
2525
2095
|
mode,
|
|
2526
|
-
// Phase split of `durationMs`: agent work vs server-side gating.
|
|
2527
2096
|
leaseToReportMs: leasedAt !== undefined ? reportReceivedAt - leasedAt : null,
|
|
2528
2097
|
reportProcessingMs: Date.now() - reportReceivedAt,
|
|
2529
2098
|
qaMs,
|
|
2530
2099
|
hasError: Boolean(effectiveArgs.error),
|
|
2531
2100
|
errorCode: effectiveArgs.error?.code ?? null,
|
|
2532
|
-
// Failure detail + API status ride the event so field failures are
|
|
2533
|
-
// diagnosable from telemetry alone (the July 2026 EXECUTOR_WORKER_FAILED
|
|
2534
|
-
// incident took an hour of forensics for want of these).
|
|
2535
2101
|
errorMessage: effectiveArgs.error?.message ?? null,
|
|
2536
2102
|
errorApiStatus: effectiveArgs.error?.apiErrorStatus ?? null,
|
|
2537
2103
|
isScaffold: resources?.scaffoldBaseWorkItemId === args.workItemId,
|
|
@@ -2617,10 +2183,6 @@ class AgentVariantsOrchestrator {
|
|
|
2617
2183
|
log.error(`handleSucceededReport failed for ${args.sessionId}/${args.workItemId}`, err);
|
|
2618
2184
|
});
|
|
2619
2185
|
}
|
|
2620
|
-
// Teardown is deferred to commitVariant / cancel. Terminal stage just
|
|
2621
|
-
// means all variants are done; the user still needs to review and pick
|
|
2622
|
-
// one. Resources (worktrees + captured diffs) live until that pick lands
|
|
2623
|
-
// on the bridge.
|
|
2624
2186
|
return result;
|
|
2625
2187
|
}
|
|
2626
2188
|
async cancel(args) {
|
|
@@ -2651,13 +2213,6 @@ class AgentVariantsOrchestrator {
|
|
|
2651
2213
|
});
|
|
2652
2214
|
return result;
|
|
2653
2215
|
}
|
|
2654
|
-
/**
|
|
2655
|
-
* Cancel a single variant within a session. Siblings continue. Idempotent
|
|
2656
|
-
* on terminal states. Per-variant worktree teardown is deferred to a
|
|
2657
|
-
* follow-up; the lease is released, so requestWork won't re-surface this
|
|
2658
|
-
* variant and the agent's report_variant_complete for it (if it lands
|
|
2659
|
-
* after cancellation) is rejected by the stale-lease check.
|
|
2660
|
-
*/
|
|
2661
2216
|
async cancelVariant(args) {
|
|
2662
2217
|
const result = this.store.cancelWorkItem({
|
|
2663
2218
|
sessionId: args.sessionId,
|
|
@@ -2687,12 +2242,6 @@ class AgentVariantsOrchestrator {
|
|
|
2687
2242
|
alreadyTerminal: result.alreadyTerminal,
|
|
2688
2243
|
};
|
|
2689
2244
|
}
|
|
2690
|
-
/**
|
|
2691
|
-
* Remove a variant from the UI. Hides it from the active snapshot for good
|
|
2692
|
-
* (it's filtered out of progress/summary/terminal accounting too) while
|
|
2693
|
-
* retaining it in `.rivet/variants/` with status `removed` so the work is
|
|
2694
|
-
* kept, never rendered again. Mirrors `cancelVariant`'s shape; idempotent.
|
|
2695
|
-
*/
|
|
2696
2245
|
async removeVariant(args) {
|
|
2697
2246
|
const result = this.store.removeWorkItem({
|
|
2698
2247
|
sessionId: args.sessionId,
|
|
@@ -2720,13 +2269,6 @@ class AgentVariantsOrchestrator {
|
|
|
2720
2269
|
alreadyRemoved: result.alreadyRemoved,
|
|
2721
2270
|
};
|
|
2722
2271
|
}
|
|
2723
|
-
/**
|
|
2724
|
-
* Rename a variant's user-visible title. Patches the in-memory work item so
|
|
2725
|
-
* the next snapshot carries the new label, persists it to the variant's
|
|
2726
|
-
* `.rivet/variants/` manifest (best-effort — a never-persisted variant simply
|
|
2727
|
-
* skips the disk write), and pushes the updated snapshot over SSE. Mirrors
|
|
2728
|
-
* `removeVariant`'s shape.
|
|
2729
|
-
*/
|
|
2730
2272
|
async renameVariant(args) {
|
|
2731
2273
|
const result = this.store.renameWorkItem({
|
|
2732
2274
|
sessionId: args.sessionId,
|
|
@@ -2737,7 +2279,6 @@ class AgentVariantsOrchestrator {
|
|
|
2737
2279
|
source: 'mcp',
|
|
2738
2280
|
sessionId: args.sessionId,
|
|
2739
2281
|
variantId: args.variantId,
|
|
2740
|
-
// Telemetry policy: never the raw agent/user label text, only its length.
|
|
2741
2282
|
labelLength: args.label.length,
|
|
2742
2283
|
sessionStage: result.sessionStage,
|
|
2743
2284
|
});
|
|
@@ -2752,10 +2293,6 @@ class AgentVariantsOrchestrator {
|
|
|
2752
2293
|
sessionStage: result.sessionStage,
|
|
2753
2294
|
};
|
|
2754
2295
|
}
|
|
2755
|
-
/**
|
|
2756
|
-
* Rename a run folder: re-home one request batch in a single store pass,
|
|
2757
|
-
* persist each affected manifest best-effort, and push one updated snapshot.
|
|
2758
|
-
*/
|
|
2759
2296
|
async renameRun(args) {
|
|
2760
2297
|
const result = this.store.renameRun({
|
|
2761
2298
|
sessionId: args.sessionId,
|
|
@@ -2766,7 +2303,6 @@ class AgentVariantsOrchestrator {
|
|
|
2766
2303
|
this.telemetry.track('agent_variants.run_renamed', {
|
|
2767
2304
|
source: 'mcp',
|
|
2768
2305
|
sessionId: args.sessionId,
|
|
2769
|
-
// Telemetry policy: never the raw label text, only its length.
|
|
2770
2306
|
runLabelLength: args.label.length,
|
|
2771
2307
|
renamedCount: result.workItemIds.length,
|
|
2772
2308
|
sessionStage: result.sessionStage,
|
|
@@ -2785,18 +2321,7 @@ class AgentVariantsOrchestrator {
|
|
|
2785
2321
|
sessionStage: result.sessionStage,
|
|
2786
2322
|
};
|
|
2787
2323
|
}
|
|
2788
|
-
/**
|
|
2789
|
-
* User has reviewed the rendered variants and picked one. Look up the
|
|
2790
|
-
* captured diff or generated project, apply it to the destination, and record
|
|
2791
|
-
* the pick. Idempotent on (sessionId, variantId): repeating the call returns
|
|
2792
|
-
* duplicate=true without applying again.
|
|
2793
|
-
*/
|
|
2794
2324
|
async commitVariant(args) {
|
|
2795
|
-
// Serialize per-session so two overlapping commits can't both run
|
|
2796
|
-
// `applyDiffToProject` (or the fresh rename) before the first records
|
|
2797
|
-
// its pick. The second caller waits for the first to settle, then runs
|
|
2798
|
-
// commitVariantImpl which hits the idempotency check in
|
|
2799
|
-
// `getVariantPick` / `recordVariantPick`.
|
|
2800
2325
|
const prior = this.inflightCommits.get(args.sessionId);
|
|
2801
2326
|
const run = (async () => {
|
|
2802
2327
|
if (prior) {
|
|
@@ -2825,17 +2350,8 @@ class AgentVariantsOrchestrator {
|
|
|
2825
2350
|
}
|
|
2826
2351
|
}
|
|
2827
2352
|
async commitVariantImpl(args) {
|
|
2828
|
-
// Idempotent path — SessionStore.recordVariantPick is the source of truth
|
|
2829
|
-
// for which variant the user picked. If the same variant is being
|
|
2830
|
-
// committed again, replay the previously stored envelope's metadata
|
|
2831
|
-
// without going back through resources (which may have been torn down).
|
|
2832
2353
|
const existingPick = this.store.getVariantPick(args.sessionId);
|
|
2833
2354
|
if (existingPick && existingPick.variantId === args.variantId) {
|
|
2834
|
-
// Retry-safe history flip. If the first commit attempt applied
|
|
2835
|
-
// successfully but the history-persist task crashed, the chosen variant
|
|
2836
|
-
// stays at `completed` instead of `committed` on disk. Re-run the flip on
|
|
2837
|
-
// every duplicate attempt; the terminal-status guard in `markStatus`
|
|
2838
|
-
// makes this safely idempotent.
|
|
2839
2355
|
const projectContext = this.store.getProjectContext(args.sessionId);
|
|
2840
2356
|
let historyProjectPath;
|
|
2841
2357
|
if (projectContext.kind === 'fresh') {
|
|
@@ -2861,9 +2377,6 @@ class AgentVariantsOrchestrator {
|
|
|
2861
2377
|
log.warn(`persistVariantHistoryAtCommit (duplicate retry) failed for session ${args.sessionId}`, err);
|
|
2862
2378
|
});
|
|
2863
2379
|
}
|
|
2864
|
-
// If the committed dev/static server is still running (either tracked
|
|
2865
|
-
// on resources, or handed off to the lingering registry), surface its
|
|
2866
|
-
// URL so a retry restores the iframe to the live project.
|
|
2867
2380
|
const lingering = this.lingeringCommittedDevServers.get(args.sessionId);
|
|
2868
2381
|
const live = this.resources.get(args.sessionId)?.committedDevServer;
|
|
2869
2382
|
const replayPort = lingering?.port ?? live?.port;
|
|
@@ -2898,19 +2411,9 @@ class AgentVariantsOrchestrator {
|
|
|
2898
2411
|
let envelopeDestination;
|
|
2899
2412
|
let changedFilesCount;
|
|
2900
2413
|
let runnablePaths;
|
|
2901
|
-
// Port of the committed dev/static server, when one was spawned during
|
|
2902
|
-
// this commit. Surfaced on the response as `previewUrl` so the UI can
|
|
2903
|
-
// restore the iframe to the committed project without falling through to
|
|
2904
|
-
// the auto-static fallback.
|
|
2905
2414
|
let committedPreviewPort;
|
|
2906
2415
|
if (projectContext.kind === 'fresh') {
|
|
2907
2416
|
const destinationPath = projectContext.workspacePath;
|
|
2908
|
-
// Realpath the destination ONCE for both the empty-check (below) and
|
|
2909
|
-
// the static_preview flatten step (further down). Computing it twice
|
|
2910
|
-
// could diverge if the path's realpath status changes between calls
|
|
2911
|
-
// (e.g. the directory was a symlink during the empty check but got
|
|
2912
|
-
// resolved between then and `mkdirSync`). `undefined` means realpath
|
|
2913
|
-
// failed — caller branches treat that as "no canonical form known".
|
|
2914
2417
|
let realDestination;
|
|
2915
2418
|
try {
|
|
2916
2419
|
realDestination = fs_1.default.realpathSync(destinationPath);
|
|
@@ -2918,34 +2421,13 @@ class AgentVariantsOrchestrator {
|
|
|
2918
2421
|
catch {
|
|
2919
2422
|
realDestination = undefined;
|
|
2920
2423
|
}
|
|
2921
|
-
// Read the commit policy off the canonical run plan rather than
|
|
2922
|
-
// re-deriving from executionPlan.mode. `materialize_project` is the
|
|
2923
|
-
// vite_app lane (rename/copy the whole worktree); `write_static_site`
|
|
2924
|
-
// is the static_preview lane (inline HTML + sibling assets).
|
|
2925
2424
|
const commitPolicy = (0, runPlan_1.resolveRunPlanPolicy)(projectContext).commit;
|
|
2926
2425
|
const isViteApp = commitPolicy === 'materialize_project';
|
|
2927
|
-
// vite_app: strict emptiness check — that lane renames a worktree into
|
|
2928
|
-
// destinationPath and would clobber user files.
|
|
2929
|
-
// static_preview: the agent intentionally wrote sibling assets under
|
|
2930
|
-
// workspacePath (via `output.assetBase`) before reporting succeeded —
|
|
2931
|
-
// those per-variant subdirs ARE the deliverable. Allow exactly the
|
|
2932
|
-
// assetBase entries known to this session; anything else still
|
|
2933
|
-
// triggers DESTINATION_NOT_EMPTY.
|
|
2934
2426
|
if (isViteApp) {
|
|
2935
2427
|
this.assertDestinationAvailable(destinationPath);
|
|
2936
2428
|
}
|
|
2937
2429
|
else {
|
|
2938
|
-
// Compare assetBase entries (which are realpath'd by
|
|
2939
|
-
// resolveStaticPreviewAssetBase) against the realpath'd destination
|
|
2940
|
-
// — on macOS `/tmp` is a symlink to `/private/tmp`, and a raw
|
|
2941
|
-
// string comparison would falsely reject every entry.
|
|
2942
2430
|
const compareBase = realDestination ?? destinationPath;
|
|
2943
|
-
// When ANY variant's assetBase is the destination itself (the agent
|
|
2944
|
-
// wrote files directly at the workspace root rather than under a
|
|
2945
|
-
// per-variant subdir), the empty-check would treat the agent's own
|
|
2946
|
-
// deliverable as foreign content. Skip the check in that case — the
|
|
2947
|
-
// workspace IS the deliverable; commit will overwrite index.html
|
|
2948
|
-
// below.
|
|
2949
2431
|
const anyAssetBaseIsDestination = [
|
|
2950
2432
|
...resources.staticPreviews.values(),
|
|
2951
2433
|
].some((sp) => sp.assetBase === compareBase);
|
|
@@ -2960,16 +2442,6 @@ class AgentVariantsOrchestrator {
|
|
|
2960
2442
|
}
|
|
2961
2443
|
}
|
|
2962
2444
|
if (isViteApp) {
|
|
2963
|
-
// Vite_app: the deliverable is the entire variant worktree, not a
|
|
2964
|
-
// single HTML file. When the worktree lives on the same volume as
|
|
2965
|
-
// the destination (the common case — provisionFreshWorktrees scaffolds
|
|
2966
|
-
// under destinationParent/.rivet-variants/) we can rename it into
|
|
2967
|
-
// place. That moves the entire tree — including the materialized
|
|
2968
|
-
// node_modules — in O(1) with no copy, and the rename is atomic.
|
|
2969
|
-
// For cross-volume cases (user passed a destinationParent on a
|
|
2970
|
-
// different mount than the .rivet-variants dir, e.g. tests stubbing
|
|
2971
|
-
// workspacePath to a tmp dir), fall back to the recursive-copy +
|
|
2972
|
-
// background-install path so the feature still works.
|
|
2973
2445
|
const record = resources.worktrees.get(args.variantId);
|
|
2974
2446
|
if (!record) {
|
|
2975
2447
|
throw new errors_1.AgentVariantsError('WORK_ITEM_NOT_FOUND', `Unknown variantId ${args.variantId} for session ${args.sessionId}`);
|
|
@@ -2978,18 +2450,6 @@ class AgentVariantsOrchestrator {
|
|
|
2978
2450
|
let isDependencyInstallRequired = false;
|
|
2979
2451
|
try {
|
|
2980
2452
|
if (areSameVolume(record.worktreePath, destinationPath)) {
|
|
2981
|
-
// Vite's dev server writes its module cache to `<worktreePath>/.vite/`
|
|
2982
|
-
// and recreates that directory on the fly whenever it's missing. If
|
|
2983
|
-
// we rename a worktree out from under a running dev server, Vite
|
|
2984
|
-
// will materialize an empty `.vite/` shell back at the OLD path —
|
|
2985
|
-
// leaving behind orphan stub dirs in `.rivet-variants/` and
|
|
2986
|
-
// confusing later cleanup. Stop every variant's dev server first
|
|
2987
|
-
// (including the chosen variant, which is about to move) so no
|
|
2988
|
-
// process is holding the old paths open during the rename.
|
|
2989
|
-
//
|
|
2990
|
-
// We stop them eagerly here rather than relying on teardownSession
|
|
2991
|
-
// because teardown runs AFTER the rename — too late to prevent the
|
|
2992
|
-
// stub-dir race.
|
|
2993
2453
|
await this.stopAllDevServersForSession(resources);
|
|
2994
2454
|
isDependencyInstallRequired = await resolveNodeModulesSymlink(record.worktreePath);
|
|
2995
2455
|
await this.renameWorktreeIntoDestination(record.worktreePath, destinationPath);
|
|
@@ -3005,21 +2465,6 @@ class AgentVariantsOrchestrator {
|
|
|
3005
2465
|
}
|
|
3006
2466
|
changedFilesCount = countWorktreeFiles(destinationPath);
|
|
3007
2467
|
if (!usedRename) {
|
|
3008
|
-
// Cross-volume fallback: materializeProject excludes node_modules
|
|
3009
|
-
// so we have to re-install at the destination. Don't await the
|
|
3010
|
-
// install — the agent's commit_variant call should return
|
|
3011
|
-
// immediately — but chain the dev-server start to it so the iframe
|
|
3012
|
-
// recovers without manual intervention once deps are ready.
|
|
3013
|
-
//
|
|
3014
|
-
// NOTE: `committedPreviewPort` stays undefined on this branch by
|
|
3015
|
-
// design — the install + start sequence takes minutes, far longer
|
|
3016
|
-
// than the response can wait. The iframe's `switchPreviewPort`
|
|
3017
|
-
// callback (invoked from `startCommittedDevServer` when the
|
|
3018
|
-
// server finally comes up) retargets the proxy then, so the
|
|
3019
|
-
// iframe reaches the new server without the URL being on the
|
|
3020
|
-
// commit response. The response surface stays `previewUrl?:` (the
|
|
3021
|
-
// field is optional) and consumers fall back to the proxy
|
|
3022
|
-
// upstream when it's absent.
|
|
3023
2468
|
void this.installDependencies(destinationPath)
|
|
3024
2469
|
.then(() => this.startCommittedDevServer({
|
|
3025
2470
|
resources,
|
|
@@ -3033,9 +2478,6 @@ class AgentVariantsOrchestrator {
|
|
|
3033
2478
|
await this.installDependencies(destinationPath);
|
|
3034
2479
|
}
|
|
3035
2480
|
if (usedRename) {
|
|
3036
|
-
// Preserve the unchosen variants as runnable siblings of the
|
|
3037
|
-
// chosen project. Best-effort: failures here log and continue so
|
|
3038
|
-
// a partial history never blocks the commit handoff.
|
|
3039
2481
|
try {
|
|
3040
2482
|
runnablePaths = this.preserveUnchosenVariants({
|
|
3041
2483
|
sessionId: args.sessionId,
|
|
@@ -3046,12 +2488,6 @@ class AgentVariantsOrchestrator {
|
|
|
3046
2488
|
catch (err) {
|
|
3047
2489
|
log.warn(`preserveUnchosenVariants failed for session ${args.sessionId}; continuing without history`, err);
|
|
3048
2490
|
}
|
|
3049
|
-
// Stopped every dev server pre-rename to dodge the .vite/ stub-dir
|
|
3050
|
-
// race. The iframe is still pointed at the (now-dead) chosen
|
|
3051
|
-
// variant's port via the proxy, so without a fresh server at the
|
|
3052
|
-
// destination the user would see "preview disconnected" the moment
|
|
3053
|
-
// they commit. Spawn one and retarget the proxy. Best-effort: if
|
|
3054
|
-
// it fails, the user can `npm run dev` themselves at destination.
|
|
3055
2491
|
committedPreviewPort = await this.startCommittedDevServer({
|
|
3056
2492
|
resources,
|
|
3057
2493
|
destinationPath,
|
|
@@ -3069,18 +2505,7 @@ class AgentVariantsOrchestrator {
|
|
|
3069
2505
|
envelopeDestination = destinationPath;
|
|
3070
2506
|
}
|
|
3071
2507
|
else {
|
|
3072
|
-
// Static_preview: HTML is the entire deliverable. Write index.html.
|
|
3073
|
-
// Prefer the in-memory record; fall back to the persisted history at
|
|
3074
|
-
// `<workspacePath>/.rivet/variants/<sessionId>/<variantId>/files/index.html`
|
|
3075
|
-
// so a process restart between report_variant_complete and commit
|
|
3076
|
-
// doesn't strand the variant.
|
|
3077
2508
|
const staticPreview = resources.staticPreviews.get(args.variantId);
|
|
3078
|
-
// Resolve the committed index.html before the flatten step below
|
|
3079
|
-
// moves/removes the per-variant dir. `getStaticPreviewHtml` reads the
|
|
3080
|
-
// materialized `<dir>/index.html` and falls back to the work-item's
|
|
3081
|
-
// stored output (the reported HTML) when the on-disk file is missing
|
|
3082
|
-
// or empty — so a failed materialization still commits real content
|
|
3083
|
-
// rather than an empty file.
|
|
3084
2509
|
const htmlFromDir = staticPreview
|
|
3085
2510
|
? this.getStaticPreviewHtml(args.sessionId, args.variantId)
|
|
3086
2511
|
: undefined;
|
|
@@ -3094,21 +2519,6 @@ class AgentVariantsOrchestrator {
|
|
|
3094
2519
|
}
|
|
3095
2520
|
try {
|
|
3096
2521
|
fs_1.default.mkdirSync(destinationPath, { recursive: true });
|
|
3097
|
-
// If the chosen variant has an `assetBase` subdir under
|
|
3098
|
-
// destinationPath (e.g. `<workspace>/var-1` containing
|
|
3099
|
-
// `avatar.glb`), move its contents up to the destination root so
|
|
3100
|
-
// the committed HTML can reference them as `./avatar.glb`. Then
|
|
3101
|
-
// delete every OTHER static_preview record's assetBase — the
|
|
3102
|
-
// unchosen variants' sibling assets are no longer relevant once
|
|
3103
|
-
// the user picked. Both steps run before the canonical index.html
|
|
3104
|
-
// is written so the chosen variant's on-disk index.html (if any)
|
|
3105
|
-
// gets overwritten by the inlined version below.
|
|
3106
|
-
// assetBase entries are realpath'd; compare against the realpath
|
|
3107
|
-
// of destinationPath so symlink-stripped paths line up (macOS:
|
|
3108
|
-
// `/tmp` → `/private/tmp`). `realDestination` was computed once
|
|
3109
|
-
// at the top of the fresh branch — re-realpath in case `mkdirSync`
|
|
3110
|
-
// above just created the directory (the initial computation may
|
|
3111
|
-
// have returned undefined when the dir didn't yet exist).
|
|
3112
2522
|
let flattenBase = realDestination;
|
|
3113
2523
|
if (!flattenBase) {
|
|
3114
2524
|
try {
|
|
@@ -3119,32 +2529,17 @@ class AgentVariantsOrchestrator {
|
|
|
3119
2529
|
}
|
|
3120
2530
|
}
|
|
3121
2531
|
const chosenAssetBase = staticPreview?.assetBase;
|
|
3122
|
-
// Skip flattening when assetBase IS the destination — the agent
|
|
3123
|
-
// wrote files directly at the workspace root, so there's no subdir
|
|
3124
|
-
// to flatten. Only move when assetBase is a strict descendant.
|
|
3125
2532
|
if (chosenAssetBase &&
|
|
3126
2533
|
isStrictlyInside(chosenAssetBase, flattenBase)) {
|
|
3127
2534
|
for (const entry of fs_1.default.readdirSync(chosenAssetBase)) {
|
|
3128
2535
|
const src = path_1.default.join(chosenAssetBase, entry);
|
|
3129
2536
|
const dst = path_1.default.join(flattenBase, entry);
|
|
3130
|
-
// Self-collision guard: when an agent names a child the same
|
|
3131
|
-
// as the parent dir (e.g. `var-1/var-1/`), `dst` resolves to
|
|
3132
|
-
// `chosenAssetBase` itself. The rmSync below would then delete
|
|
3133
|
-
// the parent — including every remaining entry we're about to
|
|
3134
|
-
// move — and the next iteration's `renameSync` would fail
|
|
3135
|
-
// with ENOENT. The agent's last attempted variant would also
|
|
3136
|
-
// be silently dropped. Skip this entry; we still rm the
|
|
3137
|
-
// parent at the end of the loop.
|
|
3138
2537
|
if (path_1.default.resolve(dst) === path_1.default.resolve(chosenAssetBase)) {
|
|
3139
2538
|
continue;
|
|
3140
2539
|
}
|
|
3141
2540
|
if (fs_1.default.existsSync(dst)) {
|
|
3142
2541
|
fs_1.default.rmSync(dst, { recursive: true, force: true });
|
|
3143
2542
|
}
|
|
3144
|
-
// Cross-volume safety: rename fails with EXDEV when src and
|
|
3145
|
-
// dst are on different mounts (possible when the user's
|
|
3146
|
-
// workspacePath crosses a symlink to another volume). Fall
|
|
3147
|
-
// back to recursive copy + remove so the commit doesn't die.
|
|
3148
2543
|
try {
|
|
3149
2544
|
fs_1.default.renameSync(src, dst);
|
|
3150
2545
|
}
|
|
@@ -3173,10 +2568,6 @@ class AgentVariantsOrchestrator {
|
|
|
3173
2568
|
throw new errors_1.AgentVariantsError('RUNTIME_VALIDATION_FAILED', `Failed to write static preview to ${destinationPath}: ${message}`);
|
|
3174
2569
|
}
|
|
3175
2570
|
changedFilesCount = countWorktreeFiles(destinationPath);
|
|
3176
|
-
// Spawn a static file server at destinationPath and retarget the
|
|
3177
|
-
// proxy so the iframe stays live across commit (parity with the
|
|
3178
|
-
// vite_app rename path). Best-effort: a failure leaves the iframe
|
|
3179
|
-
// showing "preview disconnected" but doesn't fail the commit.
|
|
3180
2571
|
committedPreviewPort = await this.startCommittedDevServer({
|
|
3181
2572
|
resources,
|
|
3182
2573
|
destinationPath,
|
|
@@ -3192,10 +2583,6 @@ class AgentVariantsOrchestrator {
|
|
|
3192
2583
|
}
|
|
3193
2584
|
}
|
|
3194
2585
|
else {
|
|
3195
|
-
// Existing project: diff against the user's repo. resolveEnv lives in
|
|
3196
|
-
// this branch only — fresh sessions don't have a user-supplied project
|
|
3197
|
-
// and the bridge.getProjectPath() it reads from would either be stale
|
|
3198
|
-
// or empty for them.
|
|
3199
2586
|
const env = await this.resolveEnv(args.sessionId);
|
|
3200
2587
|
const record = resources.worktrees.get(args.variantId);
|
|
3201
2588
|
if (!record) {
|
|
@@ -3205,8 +2592,6 @@ class AgentVariantsOrchestrator {
|
|
|
3205
2592
|
throw new errors_1.AgentVariantsError('INVALID_STAGE_ACTION', `Variant ${args.variantId} has no captured diff yet — wait for report_variant_complete(succeeded) first`);
|
|
3206
2593
|
}
|
|
3207
2594
|
changedFilesCount = countDiffFiles(record.diff);
|
|
3208
|
-
// Apply the diff to the user's working tree so the variant lands on the
|
|
3209
|
-
// current branch uncommitted.
|
|
3210
2595
|
if (!this.worktrees.applyDiffToProject) {
|
|
3211
2596
|
throw new errors_1.AgentVariantsError('RUNTIME_VALIDATION_FAILED', 'WorktreeManager does not support applying diffs to the project tree');
|
|
3212
2597
|
}
|
|
@@ -3234,17 +2619,10 @@ class AgentVariantsOrchestrator {
|
|
|
3234
2619
|
changedFilesCount,
|
|
3235
2620
|
payload,
|
|
3236
2621
|
};
|
|
3237
|
-
// Record the pick in the SessionStore so future commitVariant calls with
|
|
3238
|
-
// the same variantId are idempotent and a different variantId returns
|
|
3239
|
-
// PENDING_CHANGE_CONFLICT (already picked).
|
|
3240
2622
|
this.store.recordVariantPick({
|
|
3241
2623
|
sessionId: args.sessionId,
|
|
3242
2624
|
envelope,
|
|
3243
2625
|
});
|
|
3244
|
-
// History: flip every persisted variant in this session to its terminal
|
|
3245
|
-
// status. Variants are persisted at code_gen success time; this patches
|
|
3246
|
-
// the status and destinationPath for the chosen one. Best-effort, never
|
|
3247
|
-
// blocks the commit.
|
|
3248
2626
|
const historyProjectPath = projectContext.kind === 'fresh'
|
|
3249
2627
|
? projectContext.workspacePath
|
|
3250
2628
|
: envelopeDestination;
|
|
@@ -3262,13 +2640,6 @@ class AgentVariantsOrchestrator {
|
|
|
3262
2640
|
log.warn(`persistVariantHistoryAtCommit failed for session ${args.sessionId}`, err);
|
|
3263
2641
|
}
|
|
3264
2642
|
resources.committedVariantIds.add(args.variantId);
|
|
3265
|
-
// For fresh `new-project` commits the committed variant IS the user's
|
|
3266
|
-
// final result — there's no dev server to fall back to. Keep the session
|
|
3267
|
-
// active so SSE keeps pushing snapshots with the chosen variant; the UI's
|
|
3268
|
-
// iframe stays on it instead of unmounting to about:blank (which would
|
|
3269
|
-
// surface a misleading "Preview isn't connected" overlay). For diff /
|
|
3270
|
-
// diff-applied commits the user moves on to their own dev server, so
|
|
3271
|
-
// clearing is correct — that's the original behavior preserved below.
|
|
3272
2643
|
if (this.activeSessionId === args.sessionId &&
|
|
3273
2644
|
payload.kind !== 'project-created') {
|
|
3274
2645
|
this.activeSessionId = null;
|
|
@@ -3288,9 +2659,6 @@ class AgentVariantsOrchestrator {
|
|
|
3288
2659
|
this.emitChange();
|
|
3289
2660
|
log.info(`Variant ${args.variantId} (${input.briefLabel}) committed by user`);
|
|
3290
2661
|
if (!args.skipTeardown) {
|
|
3291
|
-
// Once a variant is committed, the unpicked worktrees are no longer
|
|
3292
|
-
// useful. Schedule teardown in the background so the agent's
|
|
3293
|
-
// commit_variant call returns immediately.
|
|
3294
2662
|
void this.teardownSession(args.sessionId, 'committed').catch((err) => {
|
|
3295
2663
|
log.warn(`teardownSession after commit failed for ${args.sessionId}`, err);
|
|
3296
2664
|
});
|
|
@@ -3311,25 +2679,7 @@ class AgentVariantsOrchestrator {
|
|
|
3311
2679
|
async cleanupCommittedSession(sessionId) {
|
|
3312
2680
|
await this.teardownSession(sessionId, 'committed');
|
|
3313
2681
|
}
|
|
3314
|
-
|
|
3315
|
-
* Ensure the user-facing destination path can receive the new project.
|
|
3316
|
-
* Rejects when the path exists and is non-empty.
|
|
3317
|
-
*
|
|
3318
|
-
* `.rivet/` (pre-commit snapshots + history manifests) and `.gitignore`
|
|
3319
|
-
* (written by VariantHistoryService.ensureGitignore when variants persist
|
|
3320
|
-
* at success time) are both tolerated — neither is user-authored content
|
|
3321
|
-
* that would be clobbered by the materialize step.
|
|
3322
|
-
*/
|
|
3323
|
-
assertDestinationAvailable(destinationPath,
|
|
3324
|
-
/**
|
|
3325
|
-
* Top-level entries the caller knows it owns and can safely overwrite.
|
|
3326
|
-
* Used by the fresh static_preview commit path so a directory holding
|
|
3327
|
-
* only this session's per-variant `assetBase` subdirs still counts as
|
|
3328
|
-
* "available" — those came from the agent during generation. Any entry
|
|
3329
|
-
* NOT in this set (and not the standard `.rivet`/`.gitignore` exemptions)
|
|
3330
|
-
* still triggers DESTINATION_NOT_EMPTY.
|
|
3331
|
-
*/
|
|
3332
|
-
additionalAllowedEntries = new Set()) {
|
|
2682
|
+
assertDestinationAvailable(destinationPath, additionalAllowedEntries = new Set()) {
|
|
3333
2683
|
if (!fs_1.default.existsSync(destinationPath))
|
|
3334
2684
|
return;
|
|
3335
2685
|
const entries = fs_1.default.readdirSync(destinationPath);
|
|
@@ -3340,18 +2690,13 @@ class AgentVariantsOrchestrator {
|
|
|
3340
2690
|
return;
|
|
3341
2691
|
throw new errors_1.AgentVariantsError('DESTINATION_NOT_EMPTY', `Destination ${destinationPath} is not empty (${userVisibleEntries.length} entries) — refuse to materialize.`);
|
|
3342
2692
|
}
|
|
3343
|
-
/** Read the captured diff for a code-gen variant, if available. */
|
|
3344
2693
|
getVariantDiff(sessionId, variantId) {
|
|
3345
2694
|
return this.resources.get(sessionId)?.worktrees.get(variantId)?.diff;
|
|
3346
2695
|
}
|
|
3347
|
-
// --- Side-effect implementations ----------------------------------------
|
|
3348
2696
|
async provisionWorktrees(sessionId, approveResult) {
|
|
3349
2697
|
const projectContext = this.store.getProjectContext(sessionId);
|
|
3350
2698
|
const variantCount = approveResult.codeGenWorkItemIds.length +
|
|
3351
2699
|
(approveResult.scaffoldBaseWorkItemId ? 1 : 0);
|
|
3352
|
-
// Generated + static_preview provisions nothing (HTML is the deliverable)
|
|
3353
|
-
// — skip the timing/telemetry wrapper so the fast path stays untouched.
|
|
3354
|
-
// `provision: 'none'` is exactly the no-scaffold generated-static lane.
|
|
3355
2700
|
if ((0, runPlan_1.resolveRunPlanPolicy)(projectContext).provision === 'none') {
|
|
3356
2701
|
return;
|
|
3357
2702
|
}
|
|
@@ -3364,10 +2709,6 @@ class AgentVariantsOrchestrator {
|
|
|
3364
2709
|
});
|
|
3365
2710
|
const run = async () => {
|
|
3366
2711
|
if (projectContext.kind === 'fresh') {
|
|
3367
|
-
// Fresh + vite_app: provision a Vite skeleton per variant and copy the
|
|
3368
|
-
// agent-planned assetPlan files before the agent leases its code_gen
|
|
3369
|
-
// items. (Background `npm install` is dispatched inside and is NOT
|
|
3370
|
-
// awaited here — the timeout bounds worktree creation, not install.)
|
|
3371
2712
|
await this.provisionFreshWorktrees(sessionId, approveResult, projectContext);
|
|
3372
2713
|
return;
|
|
3373
2714
|
}
|
|
@@ -3398,9 +2739,6 @@ class AgentVariantsOrchestrator {
|
|
|
3398
2739
|
? err.code
|
|
3399
2740
|
: 'PROVISION_FAILED',
|
|
3400
2741
|
});
|
|
3401
|
-
// Cancel synchronously before cleanup so a retry does not see this
|
|
3402
|
-
// failed session as active. cancel() schedules teardown without blocking
|
|
3403
|
-
// the provisioning error on git cleanup.
|
|
3404
2742
|
void this.cancel({ sessionId, reason: 'provisioning_failed' }).catch((teardownErr) => {
|
|
3405
2743
|
log.warn(`cleanup after provisioning failure for ${sessionId} failed`, teardownErr);
|
|
3406
2744
|
});
|
|
@@ -3415,10 +2753,6 @@ class AgentVariantsOrchestrator {
|
|
|
3415
2753
|
throw err;
|
|
3416
2754
|
}
|
|
3417
2755
|
}
|
|
3418
|
-
/**
|
|
3419
|
-
* Existing-project flow: clone the user's repo N times via git worktree.
|
|
3420
|
-
* Waits for source and dependency copies before making work available.
|
|
3421
|
-
*/
|
|
3422
2756
|
async provisionExistingWorktrees(sessionId, approveResult) {
|
|
3423
2757
|
const resources = this.ensureResources(sessionId);
|
|
3424
2758
|
const totalCount = approveResult.codeGenWorkItemIds.length +
|
|
@@ -3445,19 +2779,6 @@ class AgentVariantsOrchestrator {
|
|
|
3445
2779
|
});
|
|
3446
2780
|
}
|
|
3447
2781
|
}
|
|
3448
|
-
/**
|
|
3449
|
-
* Fresh-project flow: scaffold one template per variant + DESIGN.md per
|
|
3450
|
-
* slot synchronously (fast — just file writes + git init), then dispatch a
|
|
3451
|
-
* background `npm install` task per worktree. Returns immediately so the
|
|
3452
|
-
* `approve_variant_briefs` MCP tool doesn't time out on cold installs.
|
|
3453
|
-
*
|
|
3454
|
-
* On install success: `sessionStore.completeInternal(scaffold_base)` runs,
|
|
3455
|
-
* which unblocks the dependent code_gen items.
|
|
3456
|
-
*
|
|
3457
|
-
* On install failure: the scaffold_base work item is marked failed via
|
|
3458
|
-
* `failInternal`, which cascades DEPENDENCY_FAILED to all dependent
|
|
3459
|
-
* code_gen items so the session degrades cleanly.
|
|
3460
|
-
*/
|
|
3461
2782
|
async provisionFreshWorktrees(sessionId, approveResult, projectContext) {
|
|
3462
2783
|
const resources = this.ensureResources(sessionId);
|
|
3463
2784
|
const scaffoldId = approveResult.scaffoldBaseWorkItemId;
|
|
@@ -3484,33 +2805,14 @@ class AgentVariantsOrchestrator {
|
|
|
3484
2805
|
designContext: summarizeDesignContext(designContext),
|
|
3485
2806
|
});
|
|
3486
2807
|
log.info(`Provisioning ${codeGenIds.length} fresh worktree(s) for session ${sessionId}`);
|
|
3487
|
-
// destinationParent for fresh worktrees: the user's workspace root
|
|
3488
|
-
// (sibling to `.rivet/`). Keeping the worktree on the same volume as
|
|
3489
|
-
// the materialize destination turns commit into a directory rename
|
|
3490
|
-
// instead of a recursive copy. `path.dirname(workspacePath)` *used*
|
|
3491
|
-
// to equal `workspaceRoot`, but after nesting subprojects under
|
|
3492
|
-
// `<workspaceRoot>/.rivet/<slug>/` the dirname is now `.rivet/`,
|
|
3493
|
-
// which would stage worktrees inside `.rivet/.rivet-variants/`.
|
|
3494
|
-
// Use workspaceRoot directly so staging lives at
|
|
3495
|
-
// `<workspaceRoot>/.rivet-variants/` as originally intended.
|
|
3496
2808
|
const destinationParent = projectContext.workspaceRoot;
|
|
3497
2809
|
const paths = await createFresh.call(this.worktrees, sessionId, codeGenIds.length, viteReactTs_1.VITE_REACT_TS_TEMPLATE, designContext, destinationParent);
|
|
3498
2810
|
resources.scaffoldBaseWorkItemId = scaffoldId;
|
|
3499
2811
|
resources.freshDestinationParent = destinationParent;
|
|
3500
|
-
// Each code_gen item maps 1:1 to a fresh worktree. The scaffold_base
|
|
3501
|
-
// work item is internal — no dedicated worktree.
|
|
3502
2812
|
await Promise.all(codeGenIds.map((workItemId, index) => this.registerWorktreeWorkspace(resources, {
|
|
3503
2813
|
workItemId,
|
|
3504
2814
|
worktreePath: paths[index],
|
|
3505
2815
|
})));
|
|
3506
|
-
// Copy agent-planned assets (e.g. avatar.glb) into each worktree so
|
|
3507
|
-
// generated code can reference them via plan.referenceAs. Done before
|
|
3508
|
-
// the background install so the assets are on disk by the time the
|
|
3509
|
-
// agent leases its code_gen item.
|
|
3510
|
-
// If copy throws (e.g. source asset deleted between planning and
|
|
3511
|
-
// provisioning), fail scaffold_base immediately so dependent code_gen
|
|
3512
|
-
// items cascade DEPENDENCY_FAILED instead of leaving the session
|
|
3513
|
-
// permanently stuck in `work_items_ready`.
|
|
3514
2816
|
const assetPlan = projectContext.executionPlan?.assetPlan ?? [];
|
|
3515
2817
|
if (assetPlan.length > 0) {
|
|
3516
2818
|
try {
|
|
@@ -3542,18 +2844,10 @@ class AgentVariantsOrchestrator {
|
|
|
3542
2844
|
return;
|
|
3543
2845
|
}
|
|
3544
2846
|
}
|
|
3545
|
-
// Background install: don't await. The orchestrator finishes the
|
|
3546
|
-
// approve→provision call immediately; the agent polls for scaffold
|
|
3547
|
-
// completion via continue_variants(action='check').
|
|
3548
2847
|
void this.runBackgroundInstall(sessionId, scaffoldId, paths, scaffoldStartedAt).catch((err) => {
|
|
3549
2848
|
log.error(`runBackgroundInstall failed for session ${sessionId}`, err);
|
|
3550
2849
|
});
|
|
3551
2850
|
}
|
|
3552
|
-
/**
|
|
3553
|
-
* Run `npm install` in parallel across all fresh worktrees. On all-success,
|
|
3554
|
-
* mark scaffold_base succeeded via `completeInternal`. On any failure,
|
|
3555
|
-
* mark scaffold_base failed via `failInternal` and emit telemetry.
|
|
3556
|
-
*/
|
|
3557
2851
|
async runBackgroundInstall(sessionId, scaffoldWorkItemId, worktreePaths, scaffoldStartedAt) {
|
|
3558
2852
|
const installStartedAt = Date.now();
|
|
3559
2853
|
try {
|
|
@@ -3563,8 +2857,6 @@ class AgentVariantsOrchestrator {
|
|
|
3563
2857
|
})));
|
|
3564
2858
|
}
|
|
3565
2859
|
catch (err) {
|
|
3566
|
-
// Teardown aborts in-flight preparation; a cancelled session is not a
|
|
3567
|
-
// scaffold failure.
|
|
3568
2860
|
const resources = this.resources.get(sessionId);
|
|
3569
2861
|
if (!resources || resources.cleanupStarted)
|
|
3570
2862
|
return;
|
|
@@ -3606,12 +2898,6 @@ class AgentVariantsOrchestrator {
|
|
|
3606
2898
|
variantCount: worktreePaths.length,
|
|
3607
2899
|
});
|
|
3608
2900
|
}
|
|
3609
|
-
/**
|
|
3610
|
-
* Checks succeeded implementation reports before they reach the store.
|
|
3611
|
-
* Static previews must contain a structurally complete local artifact;
|
|
3612
|
-
* applicable existing-project variants must contain an added diff. Returns
|
|
3613
|
-
* a pass, a single repair retry, or a terminal integrity failure.
|
|
3614
|
-
*/
|
|
3615
2901
|
async evaluateQaForReport(args) {
|
|
3616
2902
|
if (args.status !== 'succeeded')
|
|
3617
2903
|
return null;
|
|
@@ -3619,15 +2905,12 @@ class AgentVariantsOrchestrator {
|
|
|
3619
2905
|
return null;
|
|
3620
2906
|
const projectContext = this.store.getProjectContext(args.sessionId);
|
|
3621
2907
|
const kind = this.store.getWorkItemKind(args.sessionId, args.workItemId);
|
|
3622
|
-
// Existing-project code_gen has no owned preview document to inspect. Its
|
|
3623
|
-
// structural contract is a captured diff containing added source content.
|
|
3624
2908
|
if (projectContext.kind !== 'fresh') {
|
|
3625
2909
|
if (kind === 'code_gen') {
|
|
3626
2910
|
return this.evaluateExistingCodeGenQa(args);
|
|
3627
2911
|
}
|
|
3628
2912
|
return null;
|
|
3629
2913
|
}
|
|
3630
|
-
// Resolve the objective base QA for this deliverable kind.
|
|
3631
2914
|
let baseQa = null;
|
|
3632
2915
|
const checkedSource = undefined;
|
|
3633
2916
|
if (kind === 'static_preview') {
|
|
@@ -3637,8 +2920,6 @@ class AgentVariantsOrchestrator {
|
|
|
3637
2920
|
baseQa = await this.runPreviewQaSafely(args, parsed.html);
|
|
3638
2921
|
}
|
|
3639
2922
|
else if (kind === 'code_gen') {
|
|
3640
|
-
// Fresh vite_app variants run agent-authored dev-server code. No
|
|
3641
|
-
// preview document to inspect — behave exactly as before.
|
|
3642
2923
|
return null;
|
|
3643
2924
|
}
|
|
3644
2925
|
else {
|
|
@@ -3656,7 +2937,6 @@ class AgentVariantsOrchestrator {
|
|
|
3656
2937
|
},
|
|
3657
2938
|
};
|
|
3658
2939
|
}
|
|
3659
|
-
// Synthesize a passing base verdict for vite_app (no objective layer).
|
|
3660
2940
|
const passedBase = baseQa ?? {
|
|
3661
2941
|
status: 'passed',
|
|
3662
2942
|
issues: [],
|
|
@@ -3740,8 +3020,6 @@ class AgentVariantsOrchestrator {
|
|
|
3740
3020
|
},
|
|
3741
3021
|
};
|
|
3742
3022
|
}
|
|
3743
|
-
/** Run the injected preview QA runner, converting a thrown runner into a
|
|
3744
|
-
* failed `VariantQaResult` (mirrors the prior inline behavior). */
|
|
3745
3023
|
async runPreviewQaSafely(args, html) {
|
|
3746
3024
|
try {
|
|
3747
3025
|
return await this.previewQaRunner({
|
|
@@ -3768,11 +3046,6 @@ class AgentVariantsOrchestrator {
|
|
|
3768
3046
|
memoizeQa(sessionId, workItemId, qa) {
|
|
3769
3047
|
this.ensureResources(sessionId).qaResults.set(workItemId, qa);
|
|
3770
3048
|
}
|
|
3771
|
-
/**
|
|
3772
|
-
* Handle a `retry` QA verdict: consume the agent's report, re-open the
|
|
3773
|
-
* variant work item so it can be re-leased and regenerated against the QA
|
|
3774
|
-
* notes, and record that it has now used its single retry.
|
|
3775
|
-
*/
|
|
3776
3049
|
async handleQaRegenRetry(args, qa) {
|
|
3777
3050
|
const resources = this.ensureResources(args.sessionId);
|
|
3778
3051
|
const result = this.store.requeueForRegeneration({
|
|
@@ -3794,11 +3067,6 @@ class AgentVariantsOrchestrator {
|
|
|
3794
3067
|
overall: null,
|
|
3795
3068
|
});
|
|
3796
3069
|
this.emitChange();
|
|
3797
|
-
// Carry the requeue signal + critique so the tool layer can tell the agent
|
|
3798
|
-
// to re-lease and regenerate. The store result is an opaque
|
|
3799
|
-
// `waiting_for_results` (the variant is pending again); on its own that is
|
|
3800
|
-
// indistinguishable from a sibling still in flight, so the agent would
|
|
3801
|
-
// otherwise abandon the variant and the session would stall at ready:0.
|
|
3802
3070
|
const completionResult = { ...result, requeuedForRegeneration: true, qa };
|
|
3803
3071
|
resources.repairCompletionResults.set(repairCompletionKey(args), completionResult);
|
|
3804
3072
|
return completionResult;
|
|
@@ -3817,16 +3085,6 @@ class AgentVariantsOrchestrator {
|
|
|
3817
3085
|
args.record.pendingAutoRestart !== args.autoRestartTimer;
|
|
3818
3086
|
return Boolean(resources && !resources.cleanupStarted && !isAutoRestartCancelled);
|
|
3819
3087
|
};
|
|
3820
|
-
// Bring up a dev server in the variant's worktree so the user can cycle
|
|
3821
|
-
// through live variants in the iframe via the chip. Failures here are
|
|
3822
|
-
// logged but non-fatal — the user can still pick by reading the diff.
|
|
3823
|
-
//
|
|
3824
|
-
// Pick a sensible port near the framework's default (3000 for Next, 5173
|
|
3825
|
-
// for Vite) and inject it via PORT + the CLI flag (see buildDevServerCommand)
|
|
3826
|
-
// so the server actually binds it — that's what moves a preview off a port
|
|
3827
|
-
// the user's own dev server already holds instead of colliding on it. On a
|
|
3828
|
-
// retry we scan past the port we just tried, so a transient race or a
|
|
3829
|
-
// briefly-held port resolves onto the next free one.
|
|
3830
3088
|
const previewStartedAt = Date.now();
|
|
3831
3089
|
const projectContextKind = args.isFresh ? 'fresh' : 'existing';
|
|
3832
3090
|
trackPreviewStarted(this.telemetry, {
|
|
@@ -3838,13 +3096,9 @@ class AgentVariantsOrchestrator {
|
|
|
3838
3096
|
const startPort = await this.resolveDevServerStartPort(args.sessionId, args.isFresh);
|
|
3839
3097
|
let scanFrom = startPort;
|
|
3840
3098
|
const maxAttempts = DEV_SERVER_START_MAX_ATTEMPTS;
|
|
3841
|
-
// At most one install-then-retry per start: a second missing-module exit
|
|
3842
|
-
// after a fresh install means the install can't fix it.
|
|
3843
3099
|
let installRetried = false;
|
|
3844
3100
|
let lastDev;
|
|
3845
3101
|
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
3846
|
-
// Teardown can begin while a prior attempt waits for dependency
|
|
3847
|
-
// installation. Do not start more work against a removed worktree.
|
|
3848
3102
|
if (!canContinueStart())
|
|
3849
3103
|
return undefined;
|
|
3850
3104
|
let port;
|
|
@@ -3855,10 +3109,6 @@ class AgentVariantsOrchestrator {
|
|
|
3855
3109
|
if (!canContinueStart())
|
|
3856
3110
|
return undefined;
|
|
3857
3111
|
const proc = await this.worktrees.startDevServer(dev.cwd, port, dev.cmd, dev.args, dev.env);
|
|
3858
|
-
// The boot can outlive the session (a cancel during the readiness
|
|
3859
|
-
// wait, or during an auto-restart's delay). At this point the child
|
|
3860
|
-
// isn't on the record yet, so teardown's stop loop can't see it —
|
|
3861
|
-
// kill it here instead of leaking an orphaned dev server.
|
|
3862
3112
|
if (!canContinueStart()) {
|
|
3863
3113
|
log.info(`Variant ${args.workItemId} dev server booted after preview cleanup; stopping it`);
|
|
3864
3114
|
void this.worktrees.stopDevServer(proc).catch(() => undefined);
|
|
@@ -3870,16 +3120,6 @@ class AgentVariantsOrchestrator {
|
|
|
3870
3120
|
args.record.port = port;
|
|
3871
3121
|
args.record.devServerProcess = proc;
|
|
3872
3122
|
args.record.devCommand = dev;
|
|
3873
|
-
// If the dev server dies on its own (crash, OOM, Vite hard-fail),
|
|
3874
|
-
// clear the port so the iframe stops routing the chip onto a dead
|
|
3875
|
-
// socket, then bring a replacement up automatically. A ready server
|
|
3876
|
-
// that later crashes is almost always recoverable by a clean restart
|
|
3877
|
-
// (transient OOM, watcher crash, HMR wedge) — without one, every such
|
|
3878
|
-
// crash surfaced as a permanent "preview unavailable" plus a burst of
|
|
3879
|
-
// upstream_lost noise until the user regenerated the variant. The
|
|
3880
|
-
// restart budget keeps a genuinely broken build (crash loop) from
|
|
3881
|
-
// restarting forever. Intentional stops clear `devServerProcess`
|
|
3882
|
-
// before killing, so the guard below filters them out.
|
|
3883
3123
|
proc.once('exit', (code, signal) => {
|
|
3884
3124
|
if (args.record.devServerProcess !== proc)
|
|
3885
3125
|
return;
|
|
@@ -3898,8 +3138,6 @@ class AgentVariantsOrchestrator {
|
|
|
3898
3138
|
args.record.devServerAutoRestarts = restartsUsed + 1;
|
|
3899
3139
|
this.emitChange();
|
|
3900
3140
|
const timer = setTimeout(() => {
|
|
3901
|
-
// Re-check: the session may have been torn down while the
|
|
3902
|
-
// restart was pending — don't spawn into a cleaned-up worktree.
|
|
3903
3141
|
const current = this.resources.get(args.sessionId);
|
|
3904
3142
|
if (!current ||
|
|
3905
3143
|
current.cleanupStarted ||
|
|
@@ -3927,8 +3165,6 @@ class AgentVariantsOrchestrator {
|
|
|
3927
3165
|
});
|
|
3928
3166
|
this.emitChange();
|
|
3929
3167
|
});
|
|
3930
|
-
// A prior failure record (startup failure before a successful retry,
|
|
3931
|
-
// idle reclaim, crash before this restart) is now stale.
|
|
3932
3168
|
this.resources
|
|
3933
3169
|
.get(args.sessionId)
|
|
3934
3170
|
?.previewFailures.delete(args.workItemId);
|
|
@@ -3957,16 +3193,6 @@ class AgentVariantsOrchestrator {
|
|
|
3957
3193
|
const devErr = (0, devServerError_1.isDevServerStartError)(err) ? err : undefined;
|
|
3958
3194
|
const portInUse = devErr?.portInUse ?? false;
|
|
3959
3195
|
const reason = devErr?.reason ?? 'unknown';
|
|
3960
|
-
// Classify what a retry can actually fix:
|
|
3961
|
-
// - port_in_use: a fresh port fixes it (also step past unmatched
|
|
3962
|
-
// collision messages via the blanket exited retry below).
|
|
3963
|
-
// - missing/stale dependencies (module-resolution errors in the
|
|
3964
|
-
// output): an install fixes it — install, then retry once.
|
|
3965
|
-
// - any other early exit: retry once; exits fail fast, so one clean
|
|
3966
|
-
// attempt is cheap insurance against transient races (fs churn from
|
|
3967
|
-
// sibling provisioning, npm cache contention).
|
|
3968
|
-
// - timeout / spawn_error / missing_dev_script: deterministic; a
|
|
3969
|
-
// retry just doubles the wait, so fail with the actionable cause.
|
|
3970
3196
|
const missingDepsOutput = (0, devServerError_1.isMissingDependencyOutput)(devErr?.detail ?? '');
|
|
3971
3197
|
const missingDeps = missingDepsOutput &&
|
|
3972
3198
|
reason === 'exited' &&
|
|
@@ -3975,8 +3201,6 @@ class AgentVariantsOrchestrator {
|
|
|
3975
3201
|
canInstallWithoutTouchingHost(lastDev.cwd);
|
|
3976
3202
|
const willRetry = attempt < maxAttempts &&
|
|
3977
3203
|
(portInUse || missingDeps || (reason === 'exited' && attempt === 1));
|
|
3978
|
-
// Next attempt scans past the port we just tried so we don't re-pick a
|
|
3979
|
-
// port that's persistently held (vs. a transient race that freed it).
|
|
3980
3204
|
scanFrom = (port ?? scanFrom) + 1;
|
|
3981
3205
|
log.warn(`Failed to start dev server for variant ${args.workItemId} on port ${port ?? 'unallocated'} ` +
|
|
3982
3206
|
`(attempt ${attempt}/${maxAttempts}, reason=${reason}, portInUse=${portInUse}, missingDeps=${missingDeps})` +
|
|
@@ -4020,9 +3244,6 @@ class AgentVariantsOrchestrator {
|
|
|
4020
3244
|
}
|
|
4021
3245
|
continue;
|
|
4022
3246
|
}
|
|
4023
|
-
// Record the failure so getVariants can tell the UI this direction's
|
|
4024
|
-
// preview couldn't start (and why), then push a snapshot so the chip
|
|
4025
|
-
// updates from "loading" to the accurate per-direction message.
|
|
4026
3247
|
this.resources
|
|
4027
3248
|
.get(args.sessionId)
|
|
4028
3249
|
?.previewFailures.set(args.workItemId, {
|
|
@@ -4034,10 +3255,6 @@ class AgentVariantsOrchestrator {
|
|
|
4034
3255
|
errorCode = 'DEPENDENCY_INSTALL_FAILED';
|
|
4035
3256
|
if (reason === 'missing_dev_script')
|
|
4036
3257
|
errorCode = 'DEV_SCRIPT_MISSING';
|
|
4037
|
-
// Telemetry gets structured classification only — never the raw
|
|
4038
|
-
// output tail, which routinely carries absolute project paths and
|
|
4039
|
-
// source frames (see AGENTS.md "What NEVER to capture"). The full
|
|
4040
|
-
// tail still reaches the local logs via `err` above.
|
|
4041
3258
|
trackFreshDevServerFailed(this.telemetry, {
|
|
4042
3259
|
sessionId: args.sessionId,
|
|
4043
3260
|
variantId: args.workItemId,
|
|
@@ -4065,9 +3282,6 @@ class AgentVariantsOrchestrator {
|
|
|
4065
3282
|
return undefined;
|
|
4066
3283
|
}
|
|
4067
3284
|
finally {
|
|
4068
|
-
// Hand the reservation back whether the dev server bound the port
|
|
4069
|
-
// (now visible to the listener check, so the reservation is redundant),
|
|
4070
|
-
// it failed (port free again), or we're about to retry on the next port.
|
|
4071
3285
|
if (port !== undefined)
|
|
4072
3286
|
this.worktrees.releasePort?.(port);
|
|
4073
3287
|
}
|
|
@@ -4095,12 +3309,6 @@ class AgentVariantsOrchestrator {
|
|
|
4095
3309
|
assetBase: staticPreview.assetBase,
|
|
4096
3310
|
projectContext,
|
|
4097
3311
|
});
|
|
4098
|
-
// Materialize the variant into a per-variant directory so every
|
|
4099
|
-
// static variant is directory-backed (the same shape as the
|
|
4100
|
-
// worktree-based variants). Reuse the agent's assetBase dir when it
|
|
4101
|
-
// wrote sibling assets; otherwise create a Rivet-managed per-variant
|
|
4102
|
-
// dir under workspacePath. `staticPreview.html` is the complete built
|
|
4103
|
-
// document (html + css + js), written as index.html.
|
|
4104
3312
|
const workspacePath = projectContext.kind === 'fresh'
|
|
4105
3313
|
? projectContext.workspacePath
|
|
4106
3314
|
: undefined;
|
|
@@ -4123,17 +3331,10 @@ class AgentVariantsOrchestrator {
|
|
|
4123
3331
|
}
|
|
4124
3332
|
try {
|
|
4125
3333
|
fs_1.default.mkdirSync(dir, { recursive: true });
|
|
4126
|
-
// Realpath the dir so it lines up with the realpath'd destination
|
|
4127
|
-
// the commit emptiness-check compares against (macOS symlinks
|
|
4128
|
-
// `/var` → `/private/var`). `resolveStaticPreviewAssetBase`
|
|
4129
|
-
// already realpaths the agent-provided case; do the same for the
|
|
4130
|
-
// Rivet-created dir.
|
|
4131
3334
|
try {
|
|
4132
3335
|
dir = fs_1.default.realpathSync(dir);
|
|
4133
3336
|
}
|
|
4134
|
-
catch {
|
|
4135
|
-
// keep the un-realpath'd path if realpath fails
|
|
4136
|
-
}
|
|
3337
|
+
catch { }
|
|
4137
3338
|
fs_1.default.writeFileSync(path_1.default.join(dir, 'index.html'), staticPreview.html, 'utf8');
|
|
4138
3339
|
}
|
|
4139
3340
|
catch (err) {
|
|
@@ -4153,8 +3354,6 @@ class AgentVariantsOrchestrator {
|
|
|
4153
3354
|
resources.workspaceManager.removeArtifactWorkspace(workItemId);
|
|
4154
3355
|
}
|
|
4155
3356
|
if (this.store.getProjectContext(sessionId).kind === 'fresh') {
|
|
4156
|
-
// History at `<workspacePath>/.rivet/variants/<sessionId>/<variantId>/`
|
|
4157
|
-
// is the on-disk record for this generated project.
|
|
4158
3357
|
this.trackHistoryPersist(this.persistCompletedFreshVariant({
|
|
4159
3358
|
sessionId,
|
|
4160
3359
|
workItemId,
|
|
@@ -4185,8 +3384,6 @@ class AgentVariantsOrchestrator {
|
|
|
4185
3384
|
log.warn(`No worktree record for ${sessionId}/${workItemId}; skipping diff capture`);
|
|
4186
3385
|
return;
|
|
4187
3386
|
}
|
|
4188
|
-
// scaffold_base sets up the base for dependent code_gen items. No diff
|
|
4189
|
-
// to capture from it — its result is the disk state of the worktree.
|
|
4190
3387
|
if (resources.scaffoldBaseWorkItemId === workItemId) {
|
|
4191
3388
|
log.info(`scaffold_base ${workItemId} succeeded; awaiting dependent code-gen`);
|
|
4192
3389
|
return;
|
|
@@ -4202,14 +3399,6 @@ class AgentVariantsOrchestrator {
|
|
|
4202
3399
|
catch (err) {
|
|
4203
3400
|
log.warn(`getDiff failed for ${record.worktreePath}`, err);
|
|
4204
3401
|
}
|
|
4205
|
-
// History: persist every completed variant immediately to
|
|
4206
|
-
// `<projectPath>/.rivet/variants/`. Existing projects pass the captured
|
|
4207
|
-
// diff (or an empty string when capture itself failed — the variant
|
|
4208
|
-
// still succeeded code-gen-wise, and the history row is the only
|
|
4209
|
-
// record the UI has). Fresh-project variants copy their worktree
|
|
4210
|
-
// (vite_app) or the staged HTML (static_preview). Best-effort — a
|
|
4211
|
-
// failure here must never block dev-server startup or the user's pick
|
|
4212
|
-
// flow.
|
|
4213
3402
|
if (!isFresh) {
|
|
4214
3403
|
this.trackHistoryPersist(this.persistCompletedExistingVariant({
|
|
4215
3404
|
sessionId,
|
|
@@ -4227,19 +3416,8 @@ class AgentVariantsOrchestrator {
|
|
|
4227
3416
|
log.warn(`persistCompletedFreshVariant failed for ${sessionId}/${workItemId}`, err);
|
|
4228
3417
|
}));
|
|
4229
3418
|
}
|
|
4230
|
-
// Static existing-mode projects (framework='static', no dev command) have
|
|
4231
|
-
// no per-variant dev server to proxy the iframe at. Serve the variant's
|
|
4232
|
-
// materialized static files directly — the same renderer the chip/iframe
|
|
4233
|
-
// already uses for fresh static_preview variants — so the variant is
|
|
4234
|
-
// viewable/cyclable instead of being silently stuck on "Preview is
|
|
4235
|
-
// unavailable for this variant". When this succeeds there is no dev server
|
|
4236
|
-
// to bring up, so skip the proxy path below.
|
|
4237
3419
|
if (!isFresh) {
|
|
4238
3420
|
const staticPreview = await this.registerExistingStaticPreview(sessionId, workItemId, record);
|
|
4239
|
-
// Existing projects resolve their preview surface at success time (the
|
|
4240
|
-
// one genuinely-late axis of the run plan): a framework='static' project
|
|
4241
|
-
// materializes static files → static_artifact and needs no dev server;
|
|
4242
|
-
// anything else falls through to the dev-server proxy below.
|
|
4243
3421
|
if (staticPreview !== 'not_static') {
|
|
4244
3422
|
this.emitChange();
|
|
4245
3423
|
return;
|
|
@@ -4273,17 +3451,8 @@ class AgentVariantsOrchestrator {
|
|
|
4273
3451
|
assetBase: parsed.assetBase,
|
|
4274
3452
|
projectContext: this.store.getProjectContext(args.sessionId),
|
|
4275
3453
|
});
|
|
4276
|
-
// A refinement that only rewrites HTML won't re-declare an assetBase, but
|
|
4277
|
-
// the refined markup can still reference the original sibling assets
|
|
4278
|
-
// (images, GLB, fonts). Fall back to the variant's existing asset base so
|
|
4279
|
-
// those relative URLs keep resolving instead of 404ing after the swap.
|
|
4280
3454
|
const previousRecord = resources.staticPreviews.get(input.variantId);
|
|
4281
3455
|
const dir = resolvedAssetBase ?? previousRecord?.assetBase;
|
|
4282
|
-
// Re-materialize index.html in the per-variant dir FIRST. The directory is
|
|
4283
|
-
// the source of truth (`getStaticPreviewHtml` reads it disk-first), so the
|
|
4284
|
-
// write must succeed before we swap any in-memory / stored-output state to
|
|
4285
|
-
// the refined HTML. If it fails we throw — converting to a `failed` report
|
|
4286
|
-
// rather than a success that still serves the pre-refine document on disk.
|
|
4287
3456
|
if (dir) {
|
|
4288
3457
|
try {
|
|
4289
3458
|
fs_1.default.mkdirSync(dir, { recursive: true });
|
|
@@ -4293,9 +3462,6 @@ class AgentVariantsOrchestrator {
|
|
|
4293
3462
|
throw new errors_1.AgentVariantsError('RUNTIME_VALIDATION_FAILED', `Failed to materialize refined static preview for ${input.variantId}: ${err instanceof Error ? err.message : String(err)}`);
|
|
4294
3463
|
}
|
|
4295
3464
|
}
|
|
4296
|
-
// Swap the served preview to the refined HTML. Runs before
|
|
4297
|
-
// store.reportComplete so any failure above converts to a `failed` report
|
|
4298
|
-
// rather than a success pointing at unrefreshed output.
|
|
4299
3465
|
this.store.replaceWorkItemOutput(args.sessionId, input.variantId, {
|
|
4300
3466
|
...parsed,
|
|
4301
3467
|
...(dir ? { assetBase: dir } : {}),
|
|
@@ -4317,10 +3483,6 @@ class AgentVariantsOrchestrator {
|
|
|
4317
3483
|
targetWorkItemId: input.variantId,
|
|
4318
3484
|
});
|
|
4319
3485
|
}
|
|
4320
|
-
// History persistence is best-effort, mirroring handleSucceededReport's
|
|
4321
|
-
// fire-and-forget persistence for freshly completed variants. A failure
|
|
4322
|
-
// here (e.g. a transient filesystem race) must not fail the refinement or
|
|
4323
|
-
// discard the already-serving refined HTML.
|
|
4324
3486
|
try {
|
|
4325
3487
|
await this.persistCompletedFreshVariant({
|
|
4326
3488
|
sessionId: args.sessionId,
|
|
@@ -4330,22 +3492,10 @@ class AgentVariantsOrchestrator {
|
|
|
4330
3492
|
catch (err) {
|
|
4331
3493
|
log.warn(`persistCompletedFreshVariant failed for refined variant ${input.variantId} (session ${args.sessionId}); preview already swapped`, err);
|
|
4332
3494
|
}
|
|
4333
|
-
// The caller (reportComplete) emits the change after recording success so
|
|
4334
|
-
// the snapshot reflects both the swapped HTML and refinement.status.
|
|
4335
3495
|
}
|
|
4336
|
-
/** The worktree/dev-server manager this orchestrator boots previews with.
|
|
4337
|
-
* Exposed so HistoryReplayService shares the SAME instance: the
|
|
4338
|
-
* reserved-but-not-yet-bound port set is per-instance, and a second
|
|
4339
|
-
* manager scanning the same range can hand a live variant's pending port
|
|
4340
|
-
* to a replay (EADDRINUSE for the loser). */
|
|
4341
3496
|
get devServerManager() {
|
|
4342
3497
|
return this.worktrees;
|
|
4343
3498
|
}
|
|
4344
|
-
/** In-flight fire-and-forget history persists. Tree-store snapshots spawn
|
|
4345
|
-
* git subprocesses, so these can outlive the microtask flushes that used
|
|
4346
|
-
* to be enough to drain them — {@link teardownSession} (and the test
|
|
4347
|
-
* helpers' settleBackgroundWork) await {@link settleHistoryPersists}
|
|
4348
|
-
* instead of racing the writes. */
|
|
4349
3499
|
pendingHistoryPersists = new Set();
|
|
4350
3500
|
trackHistoryPersist(persist) {
|
|
4351
3501
|
this.pendingHistoryPersists.add(persist);
|
|
@@ -4355,20 +3505,11 @@ class AgentVariantsOrchestrator {
|
|
|
4355
3505
|
this.pendingHistoryPersists.delete(persist);
|
|
4356
3506
|
});
|
|
4357
3507
|
}
|
|
4358
|
-
/** Await every in-flight history persist, including ones that start while
|
|
4359
|
-
* draining (a refine can persist mid-settle). */
|
|
4360
3508
|
async settleHistoryPersists() {
|
|
4361
3509
|
while (this.pendingHistoryPersists.size > 0) {
|
|
4362
3510
|
await Promise.allSettled([...this.pendingHistoryPersists]);
|
|
4363
3511
|
}
|
|
4364
3512
|
}
|
|
4365
|
-
/**
|
|
4366
|
-
* Persist a completed existing-project code_gen variant into
|
|
4367
|
-
* `<env.projectPath>/.rivet/variants/<sessionId>/<variantId>/`. Called from
|
|
4368
|
-
* `handleSucceededReport` once the worktree diff has been captured but
|
|
4369
|
-
* before the user picks. Status is `completed` until `commitVariant` or a
|
|
4370
|
-
* cancellation transitions it.
|
|
4371
|
-
*/
|
|
4372
3513
|
async persistCompletedExistingVariant(args) {
|
|
4373
3514
|
const projectContext = this.store.getProjectContext(args.sessionId);
|
|
4374
3515
|
if (projectContext.kind !== 'existing')
|
|
@@ -4396,13 +3537,7 @@ class AgentVariantsOrchestrator {
|
|
|
4396
3537
|
}
|
|
4397
3538
|
const input = this.store.getWorkItemInput(args.sessionId, args.workItemId);
|
|
4398
3539
|
const sessionPrompt = this.store.getPrompt(args.sessionId);
|
|
4399
|
-
// Tree-store snapshot inputs (dual-write). The snapshot root is the
|
|
4400
|
-
// worktree root — the git root, per the tree-root contract — for EVERY
|
|
4401
|
-
// framework, not just static: this is what makes dev-server (Vite /
|
|
4402
|
-
// fullstack) variants replayable from history instead of diff-only.
|
|
4403
3540
|
const snapshotDir = record?.worktreePath;
|
|
4404
|
-
// Lazy per-session base snapshot from the host repo root. Best-effort:
|
|
4405
|
-
// resolution failure just means no base ref (variant commits still land).
|
|
4406
3541
|
let baseDir;
|
|
4407
3542
|
try {
|
|
4408
3543
|
baseDir = await this.worktrees.getGitRoot?.();
|
|
@@ -4412,9 +3547,6 @@ class AgentVariantsOrchestrator {
|
|
|
4412
3547
|
}
|
|
4413
3548
|
let serve;
|
|
4414
3549
|
if (sourceDir && record && staticEntryPath) {
|
|
4415
|
-
// Static framework: entryPath is relative to the snapshot root (the
|
|
4416
|
-
// worktree root), pointing into the nested project dir when the
|
|
4417
|
-
// project lives below the git root.
|
|
4418
3550
|
const entryPath = path_1.default.relative(record.worktreePath, path_1.default.join(sourceDir, staticEntryPath));
|
|
4419
3551
|
serve = { kind: 'static', entryPath };
|
|
4420
3552
|
}
|
|
@@ -4425,12 +3557,6 @@ class AgentVariantsOrchestrator {
|
|
|
4425
3557
|
};
|
|
4426
3558
|
}
|
|
4427
3559
|
else if (record) {
|
|
4428
|
-
// Persist fires at code-gen success, BEFORE the dev server boots (the
|
|
4429
|
-
// boot is what stashes record.devCommand/port) — so for the common
|
|
4430
|
-
// path the live invocation isn't available yet. Run the same
|
|
4431
|
-
// deterministic resolution the boot will use, against a sentinel port
|
|
4432
|
-
// that becomes the ${PORT} placeholder. No dependency install here —
|
|
4433
|
-
// resolveDevServerCommand is the side-effect-free half of the split.
|
|
4434
3560
|
try {
|
|
4435
3561
|
const dev = await this.resolveDevServerCommand(args.sessionId, record.worktreePath, RECIPE_PORT_SENTINEL, false);
|
|
4436
3562
|
serve = {
|
|
@@ -4449,6 +3575,12 @@ class AgentVariantsOrchestrator {
|
|
|
4449
3575
|
...(input.requestId ? { requestId: input.requestId } : {}),
|
|
4450
3576
|
label: input.briefLabel,
|
|
4451
3577
|
brief: input.briefBody,
|
|
3578
|
+
references: input.references,
|
|
3579
|
+
referenceContext: input.context,
|
|
3580
|
+
referenceContextRoots: [
|
|
3581
|
+
path_1.default.join(this.variantHistory.store.storage.resolve(env.projectPath)
|
|
3582
|
+
.dataDirectory, 'variant-context'),
|
|
3583
|
+
],
|
|
4452
3584
|
sessionPrompt,
|
|
4453
3585
|
runLabel: input.runLabel ?? this.store.getRunLabel(args.sessionId),
|
|
4454
3586
|
kind: 'diff',
|
|
@@ -4470,22 +3602,6 @@ class AgentVariantsOrchestrator {
|
|
|
4470
3602
|
: {}),
|
|
4471
3603
|
});
|
|
4472
3604
|
}
|
|
4473
|
-
/**
|
|
4474
|
-
* Existing-mode `framework: 'static'` projects have no dev command, so there
|
|
4475
|
-
* is no per-variant dev server for the iframe to proxy. Register the variant's
|
|
4476
|
-
* materialized static site as a {@link StaticPreviewRecord} so the existing
|
|
4477
|
-
* static-file plumbing — the `/api/variants/:sid/static/:vid[/asset]` routes,
|
|
4478
|
-
* {@link getStaticPreviewHtml}, and {@link getVariants} (preview.kind=
|
|
4479
|
-
* 'static_artifact', view enabled) — all light up exactly as they do for
|
|
4480
|
-
* fresh `static_preview` variants. The entry HTML and its sibling assets are
|
|
4481
|
-
* served straight from the variant's worktree project root (session-scoped,
|
|
4482
|
-
* pre-commit; the persisted `.rivet/variants/.../files/` copy backs the
|
|
4483
|
-
* post-session history route separately).
|
|
4484
|
-
*
|
|
4485
|
-
* Returns `registered` when the static preview is ready, `unavailable` when
|
|
4486
|
-
* the project is static but its selected entry cannot be served, and
|
|
4487
|
-
* `not_static` when the caller should start a dev server instead.
|
|
4488
|
-
*/
|
|
4489
3605
|
async registerExistingStaticPreview(sessionId, workItemId, record) {
|
|
4490
3606
|
let env;
|
|
4491
3607
|
try {
|
|
@@ -4518,9 +3634,6 @@ class AgentVariantsOrchestrator {
|
|
|
4518
3634
|
log.warn(`registerExistingStaticPreview: project cwd failed for ${sessionId}/${workItemId}`, err);
|
|
4519
3635
|
return 'unavailable';
|
|
4520
3636
|
}
|
|
4521
|
-
// The materialized worktree IS the per-variant directory. Require its
|
|
4522
|
-
// selected entry to exist; the directory is then served directly (no
|
|
4523
|
-
// in-memory HTML copy — getStaticPreviewHtml reads it from here).
|
|
4524
3637
|
const entryFile = path_1.default.join(projectCwd, env.entryPath);
|
|
4525
3638
|
try {
|
|
4526
3639
|
await fs_1.default.promises.access(entryFile, fs_1.default.constants.R_OK);
|
|
@@ -4542,41 +3655,25 @@ class AgentVariantsOrchestrator {
|
|
|
4542
3655
|
});
|
|
4543
3656
|
return 'unavailable';
|
|
4544
3657
|
}
|
|
4545
|
-
// The dir must be realpath'd so resolveStaticPreviewAssetPath's sandbox
|
|
4546
|
-
// comparison lines up; sibling assets (css/js/images) then resolve from the
|
|
4547
|
-
// same static root the entry HTML lives in.
|
|
4548
3658
|
let dir;
|
|
4549
3659
|
try {
|
|
4550
3660
|
dir = fs_1.default.realpathSync(projectCwd);
|
|
4551
3661
|
}
|
|
4552
3662
|
catch {
|
|
4553
|
-
// Fall back to the un-realpath'd cwd; serving still works, only the
|
|
4554
|
-
// sandbox symlink-normalization is skipped.
|
|
4555
3663
|
dir = projectCwd;
|
|
4556
3664
|
}
|
|
4557
|
-
// Host project root, used as a read-only fallback for assets the worktree
|
|
4558
|
-
// clone is missing (git-ignored or binary files that `git worktree add` +
|
|
4559
|
-
// text-patch + untracked-copy can't carry). Without this the original
|
|
4560
|
-
// preview shows such an asset while the variant 404s. Realpath'd so the
|
|
4561
|
-
// sandbox containment check in `resolveAssetWithinBase` lines up.
|
|
4562
3665
|
let assetFallbackBase;
|
|
4563
3666
|
try {
|
|
4564
3667
|
const hostRealRoot = fs_1.default.realpathSync(env.projectPath);
|
|
4565
|
-
// Skip the fallback if it would collapse onto the worktree root (can't
|
|
4566
|
-
// happen in practice, but keeps the two roots genuinely distinct).
|
|
4567
3668
|
if (hostRealRoot !== dir)
|
|
4568
3669
|
assetFallbackBase = hostRealRoot;
|
|
4569
3670
|
}
|
|
4570
|
-
catch {
|
|
4571
|
-
// No host root resolvable — serve worktree assets only.
|
|
4572
|
-
}
|
|
3671
|
+
catch { }
|
|
4573
3672
|
resources.staticPreviews.set(workItemId, {
|
|
4574
3673
|
workItemId,
|
|
4575
3674
|
briefId: input.briefId,
|
|
4576
3675
|
entryPath: env.entryPath,
|
|
4577
3676
|
assetBase: dir,
|
|
4578
|
-
// Existing-mode static projects are real multi-file sites — assume
|
|
4579
|
-
// sibling assets so the preview route resolves relative URLs.
|
|
4580
3677
|
hasAssets: true,
|
|
4581
3678
|
...(assetFallbackBase ? { assetFallbackBase } : {}),
|
|
4582
3679
|
});
|
|
@@ -4592,25 +3689,10 @@ class AgentVariantsOrchestrator {
|
|
|
4592
3689
|
});
|
|
4593
3690
|
return 'registered';
|
|
4594
3691
|
}
|
|
4595
|
-
/**
|
|
4596
|
-
* Persist a completed fresh-project variant into
|
|
4597
|
-
* `<projectContext.workspacePath>/.rivet/variants/<sessionId>/<variantId>/`.
|
|
4598
|
-
* Called from `handleSucceededReport` right after the per-variant snapshot
|
|
4599
|
-
* lands on disk — for static_preview that's the `.rivet/<slug>/` snapshot
|
|
4600
|
-
* dir; for vite_app fresh variants it's the worktree itself. Status starts
|
|
4601
|
-
* as 'completed' and transitions to 'committed' / 'rejected' / 'cancelled'
|
|
4602
|
-
* via `markStatus` at commit or teardown time.
|
|
4603
|
-
*
|
|
4604
|
-
* Running at success time (rather than commit time) means the history panel
|
|
4605
|
-
* populates live as variants generate — including when the user never picks
|
|
4606
|
-
* one. Mirrors the existing-project persistCompletedExistingVariant flow.
|
|
4607
|
-
*/
|
|
4608
3692
|
async persistCompletedFreshVariant(args) {
|
|
4609
3693
|
const projectContext = this.store.getProjectContext(args.sessionId);
|
|
4610
3694
|
if (projectContext.kind !== 'fresh')
|
|
4611
3695
|
return;
|
|
4612
|
-
// Variant history lives in the generated project folder so reopening that
|
|
4613
|
-
// folder gives the history panel the same owner path that wrote it.
|
|
4614
3696
|
const historyProjectPath = projectContext.workspacePath;
|
|
4615
3697
|
const input = this.store.getWorkItemInput(args.sessionId, args.workItemId);
|
|
4616
3698
|
const sessionPrompt = this.store.getPrompt(args.sessionId);
|
|
@@ -4618,11 +3700,6 @@ class AgentVariantsOrchestrator {
|
|
|
4618
3700
|
const resources = this.resources.get(args.sessionId);
|
|
4619
3701
|
const worktreeRecord = resources?.worktrees.get(args.workItemId);
|
|
4620
3702
|
const staticPreview = resources?.staticPreviews.get(args.workItemId);
|
|
4621
|
-
// Vite_app deliverables are full scaffolded worktrees — pass the worktree
|
|
4622
|
-
// directory as sourceDir and let copyDirFiltered handle it (excludes
|
|
4623
|
-
// node_modules, .rivet, etc). Static_preview deliverables are inline HTML
|
|
4624
|
-
// captured in `resources.staticPreviews`; stage them in a tmp dir so the
|
|
4625
|
-
// existing copy path works without poking the user's workspace.
|
|
4626
3703
|
let sourceDir = null;
|
|
4627
3704
|
let tmpStagingDir = null;
|
|
4628
3705
|
if (worktreeRecord && fs_1.default.existsSync(worktreeRecord.worktreePath)) {
|
|
@@ -4631,7 +3708,6 @@ class AgentVariantsOrchestrator {
|
|
|
4631
3708
|
else if (staticPreview) {
|
|
4632
3709
|
tmpStagingDir = fs_1.default.mkdtempSync(path_1.default.join(os_1.default.tmpdir(), `rivet-variant-${args.workItemId}-`));
|
|
4633
3710
|
copyStaticPreviewDirectory(staticPreview.assetBase, tmpStagingDir);
|
|
4634
|
-
// Read the materialized index.html from the variant's per-variant dir.
|
|
4635
3711
|
let stagedHtml = '';
|
|
4636
3712
|
try {
|
|
4637
3713
|
stagedHtml = fs_1.default.readFileSync(path_1.default.join(staticPreview.assetBase, 'index.html'), 'utf8');
|
|
@@ -4647,10 +3723,6 @@ class AgentVariantsOrchestrator {
|
|
|
4647
3723
|
log.warn(`persistCompletedFreshVariant: no source for ${args.workItemId} (session ${args.sessionId}); skipping`);
|
|
4648
3724
|
return;
|
|
4649
3725
|
}
|
|
4650
|
-
// For static_preview, only `index.html` is a real deliverable — `brief.md`
|
|
4651
|
-
// is implementation-detail staging that we copy alongside it. Hardcode
|
|
4652
|
-
// the count so the history row matches what `commit_variant` reports
|
|
4653
|
-
// (always 1) instead of double-counting the brief.
|
|
4654
3726
|
const changedFilesCount = staticPreview ? 1 : countWorktreeFiles(sourceDir);
|
|
4655
3727
|
const preview = staticPreview
|
|
4656
3728
|
? { kind: 'static', entryPath: 'index.html' }
|
|
@@ -4662,12 +3734,6 @@ class AgentVariantsOrchestrator {
|
|
|
4662
3734
|
script: 'dev',
|
|
4663
3735
|
},
|
|
4664
3736
|
};
|
|
4665
|
-
// Tree-store serve contract. Fresh worktrees prefer the live record's
|
|
4666
|
-
// resolved invocation (stashed at dev-server start); the fallback recipe
|
|
4667
|
-
// mirrors resolveDevServer's fresh branch, which is fully deterministic
|
|
4668
|
-
// for the Vite template. Static previews serve their staged index.html.
|
|
4669
|
-
// Fresh sessions have no host project, so there is no base snapshot —
|
|
4670
|
-
// variant commits are root commits.
|
|
4671
3737
|
const serve = staticPreview
|
|
4672
3738
|
? { kind: 'static', entryPath: 'index.html' }
|
|
4673
3739
|
: worktreeRecord?.devCommand && worktreeRecord.port !== undefined
|
|
@@ -4700,6 +3766,15 @@ class AgentVariantsOrchestrator {
|
|
|
4700
3766
|
...(input.requestId ? { requestId: input.requestId } : {}),
|
|
4701
3767
|
label: input.briefLabel,
|
|
4702
3768
|
brief: input.briefBody,
|
|
3769
|
+
references: input.references,
|
|
3770
|
+
referenceContext: input.context,
|
|
3771
|
+
referenceContextRoots: [
|
|
3772
|
+
projectContext.workspacePath,
|
|
3773
|
+
projectContext.workspaceRoot,
|
|
3774
|
+
]
|
|
3775
|
+
.filter((projectPath) => Boolean(projectPath))
|
|
3776
|
+
.map((projectPath) => path_1.default.join(this.variantHistory.store.storage.resolve(projectPath)
|
|
3777
|
+
.dataDirectory, 'variant-context')),
|
|
4703
3778
|
sessionPrompt,
|
|
4704
3779
|
runLabel: input.runLabel ?? this.store.getRunLabel(args.sessionId),
|
|
4705
3780
|
kind: 'project-created',
|
|
@@ -4730,10 +3805,6 @@ class AgentVariantsOrchestrator {
|
|
|
4730
3805
|
}
|
|
4731
3806
|
}
|
|
4732
3807
|
}
|
|
4733
|
-
/**
|
|
4734
|
-
* @effect Drains fresh-project history writes before commit moves or rewrites
|
|
4735
|
-
* the generated project folder.
|
|
4736
|
-
*/
|
|
4737
3808
|
async persistCompletedFreshVariantsForCommit(sessionId) {
|
|
4738
3809
|
const projectContext = this.store.getProjectContext(sessionId);
|
|
4739
3810
|
if (projectContext.kind !== 'fresh')
|
|
@@ -4753,14 +3824,6 @@ class AgentVariantsOrchestrator {
|
|
|
4753
3824
|
}
|
|
4754
3825
|
}
|
|
4755
3826
|
}
|
|
4756
|
-
/**
|
|
4757
|
-
* At commit time, flip persisted variant manifests to terminal statuses
|
|
4758
|
-
* ('committed' for the chosen, 'rejected' for the rest). Both existing- and
|
|
4759
|
-
* fresh-project variants have already been persisted at code_gen success
|
|
4760
|
-
* time, so this is a pure status update — no source-dir copy required.
|
|
4761
|
-
* Also records the destination path on the chosen variant so history can
|
|
4762
|
-
* surface "this variant became <path>".
|
|
4763
|
-
*/
|
|
4764
3827
|
async persistVariantHistoryAtCommit(args) {
|
|
4765
3828
|
const variants = this.store.getVariants(args.sessionId);
|
|
4766
3829
|
for (const variant of variants) {
|
|
@@ -4781,13 +3844,6 @@ class AgentVariantsOrchestrator {
|
|
|
4781
3844
|
});
|
|
4782
3845
|
}
|
|
4783
3846
|
}
|
|
4784
|
-
/**
|
|
4785
|
-
* Flip persisted variant manifests to status='cancelled' for every variant
|
|
4786
|
-
* in the session that was already snapshotted to disk. Fresh- and existing-
|
|
4787
|
-
* project variants both persist at success time now, so both need their
|
|
4788
|
-
* manifests flipped here. Best-effort — missing manifests are silently
|
|
4789
|
-
* skipped by VariantHistoryService.markStatus.
|
|
4790
|
-
*/
|
|
4791
3847
|
async markPersistedVariantsCancelled(sessionId) {
|
|
4792
3848
|
if (!this.store.hasSession(sessionId))
|
|
4793
3849
|
return;
|
|
@@ -4823,9 +3879,6 @@ class AgentVariantsOrchestrator {
|
|
|
4823
3879
|
const projectPath = await this.resolveHistoryProjectPath(sessionId);
|
|
4824
3880
|
if (!projectPath)
|
|
4825
3881
|
return;
|
|
4826
|
-
// No-ops (ENOENT) when the variant was never persisted — e.g. removing a
|
|
4827
|
-
// still-pending variant that produced no artifact. Completed variants have
|
|
4828
|
-
// a manifest, which flips to `removed` and is retained on disk.
|
|
4829
3882
|
await this.variantHistory.markStatus({
|
|
4830
3883
|
projectPath,
|
|
4831
3884
|
sessionId,
|
|
@@ -4839,9 +3892,6 @@ class AgentVariantsOrchestrator {
|
|
|
4839
3892
|
const projectPath = await this.resolveHistoryProjectPath(sessionId);
|
|
4840
3893
|
if (!projectPath)
|
|
4841
3894
|
return;
|
|
4842
|
-
// No-ops (ENOENT) when the variant has no manifest yet — e.g. renaming a
|
|
4843
|
-
// still-generating direction before its artifact lands. The in-memory
|
|
4844
|
-
// label still updates; the disk copy catches up when the variant persists.
|
|
4845
3895
|
await this.variantHistory.renameVariant({
|
|
4846
3896
|
projectPath,
|
|
4847
3897
|
sessionId,
|
|
@@ -4850,11 +3900,6 @@ class AgentVariantsOrchestrator {
|
|
|
4850
3900
|
runLabel,
|
|
4851
3901
|
});
|
|
4852
3902
|
}
|
|
4853
|
-
/**
|
|
4854
|
-
* Resolve the project path that owns `.rivet/variants/` for a session.
|
|
4855
|
-
* Existing sessions use the user's project. Fresh sessions use the generated
|
|
4856
|
-
* project folder. Must match what `persistCompletedFreshVariant` writes to.
|
|
4857
|
-
*/
|
|
4858
3903
|
async resolveHistoryProjectPath(sessionId) {
|
|
4859
3904
|
const projectContext = this.store.getProjectContext(sessionId);
|
|
4860
3905
|
if (projectContext.kind === 'fresh') {
|
|
@@ -4881,13 +3926,6 @@ class AgentVariantsOrchestrator {
|
|
|
4881
3926
|
return undefined;
|
|
4882
3927
|
}
|
|
4883
3928
|
}
|
|
4884
|
-
/**
|
|
4885
|
-
* The port to start scanning from when allocating a variant's preview dev
|
|
4886
|
-
* server. Fresh worktrees run the Vite template (5173); existing projects use
|
|
4887
|
-
* their detected framework's default (3000 for Next, etc.), falling back to
|
|
4888
|
-
* 3000 if detection fails. Scanning upward from here lands the preview on a
|
|
4889
|
-
* sensible, predictable port near the project's normal one.
|
|
4890
|
-
*/
|
|
4891
3929
|
async resolveDevServerStartPort(sessionId, isFresh) {
|
|
4892
3930
|
if (isFresh)
|
|
4893
3931
|
return FRESH_DEV_SERVER_DEFAULT_PORT;
|
|
@@ -4899,11 +3937,6 @@ class AgentVariantsOrchestrator {
|
|
|
4899
3937
|
return 3000;
|
|
4900
3938
|
}
|
|
4901
3939
|
}
|
|
4902
|
-
/**
|
|
4903
|
-
* Resolve dev server invocation for a worktree. Fresh-project worktrees
|
|
4904
|
-
* always use the Vite template's npm command at the worktree root; existing
|
|
4905
|
-
* projects defer to the user's framework/packageManager config.
|
|
4906
|
-
*/
|
|
4907
3940
|
async resolveDevServer(sessionId, worktreePath, port, isFresh) {
|
|
4908
3941
|
const resolved = await this.resolveDevServerCommand(sessionId, worktreePath, port, isFresh);
|
|
4909
3942
|
await this.ensureProjectDependencies({
|
|
@@ -4913,13 +3946,6 @@ class AgentVariantsOrchestrator {
|
|
|
4913
3946
|
});
|
|
4914
3947
|
return resolved;
|
|
4915
3948
|
}
|
|
4916
|
-
/**
|
|
4917
|
-
* Pure invocation resolution — no dependency installs, no side effects.
|
|
4918
|
-
* Split from {@link resolveDevServer} so history persistence can capture
|
|
4919
|
-
* the SAME deterministic resolution the boot path uses without booting:
|
|
4920
|
-
* persist fires at code-gen success, before the dev server starts, so the
|
|
4921
|
-
* live record's stashed command usually isn't available yet.
|
|
4922
|
-
*/
|
|
4923
3949
|
async resolveDevServerCommand(sessionId, worktreePath, port, isFresh) {
|
|
4924
3950
|
if (isFresh) {
|
|
4925
3951
|
return {
|
|
@@ -4943,9 +3969,6 @@ class AgentVariantsOrchestrator {
|
|
|
4943
3969
|
throw new Error('Static projects do not have a dev server command');
|
|
4944
3970
|
}
|
|
4945
3971
|
const cwd = await this.resolveExistingProjectCwd(sessionId, worktreePath, env);
|
|
4946
|
-
// Every branch below — including the production buildDevCommand recipes
|
|
4947
|
-
// from utils/devServerCommand.ts — invokes the package.json script named
|
|
4948
|
-
// by env.devCommand, so the preflight applies to all of them.
|
|
4949
3972
|
if (env.devCommand) {
|
|
4950
3973
|
assertDevScriptExists(cwd, env.devCommand);
|
|
4951
3974
|
}
|
|
@@ -4981,7 +4004,6 @@ class AgentVariantsOrchestrator {
|
|
|
4981
4004
|
packageManager,
|
|
4982
4005
|
};
|
|
4983
4006
|
}
|
|
4984
|
-
/** Prepares the direction's declared dependencies before each server start. */
|
|
4985
4007
|
async ensureProjectDependencies(args) {
|
|
4986
4008
|
if (!fs_1.default.existsSync(path_1.default.join(args.cwd, 'package.json')))
|
|
4987
4009
|
return;
|
|
@@ -4990,13 +4012,6 @@ class AgentVariantsOrchestrator {
|
|
|
4990
4012
|
signal: args.signal,
|
|
4991
4013
|
});
|
|
4992
4014
|
}
|
|
4993
|
-
/**
|
|
4994
|
-
* Resolve the dev-server working directory for an existing-project variant.
|
|
4995
|
-
* WorktreeManager is constructed around the editor/root project, but
|
|
4996
|
-
* `start_variants` can target a nested app (for example `examples/blog`).
|
|
4997
|
-
* In that case the worktree root is still the git root clone, while the dev
|
|
4998
|
-
* server must run from the nested project path.
|
|
4999
|
-
*/
|
|
5000
4015
|
async resolveExistingProjectCwd(sessionId, worktreePath, env) {
|
|
5001
4016
|
const fallback = await this.worktrees.getProjectCwdInWorktree(worktreePath);
|
|
5002
4017
|
try {
|
|
@@ -5014,16 +4029,6 @@ class AgentVariantsOrchestrator {
|
|
|
5014
4029
|
return fallback;
|
|
5015
4030
|
}
|
|
5016
4031
|
}
|
|
5017
|
-
/**
|
|
5018
|
-
* After the chosen variant has been renamed into `destinationPath`, move
|
|
5019
|
-
* each unchosen sibling worktree into a `<destinationParent>/<slug>-variants/NN-<label>/`
|
|
5020
|
-
* folder with its own prepared dependency installation. Writes a manifest documenting all 5 variants (the chosen
|
|
5021
|
-
* one with `folder: null` and `chosenPath: '../<slug>'`).
|
|
5022
|
-
*
|
|
5023
|
-
* Sets `vitePreservedSiblings = true` on session resources so the
|
|
5024
|
-
* subsequent teardown skips `cleanupFreshWorktrees` (which would otherwise
|
|
5025
|
-
* delete the just-preserved history). Dev servers still get stopped.
|
|
5026
|
-
*/
|
|
5027
4032
|
preserveUnchosenVariants(args) {
|
|
5028
4033
|
const resources = this.resources.get(args.sessionId);
|
|
5029
4034
|
const runnablePaths = new Map();
|
|
@@ -5059,8 +4064,6 @@ class AgentVariantsOrchestrator {
|
|
|
5059
4064
|
}
|
|
5060
4065
|
const record = resources.worktrees.get(variant.workItemId);
|
|
5061
4066
|
if (!record) {
|
|
5062
|
-
// No worktree (e.g. failed variant) — still list it in manifest with
|
|
5063
|
-
// null folder so the user can see why it's absent.
|
|
5064
4067
|
manifestEntries.push({
|
|
5065
4068
|
variantId: variant.workItemId,
|
|
5066
4069
|
label,
|
|
@@ -5089,8 +4092,6 @@ class AgentVariantsOrchestrator {
|
|
|
5089
4092
|
fs_1.default.renameSync(record.worktreePath, dest);
|
|
5090
4093
|
return dest;
|
|
5091
4094
|
})();
|
|
5092
|
-
// Update the in-memory record so teardown doesn't try to operate on
|
|
5093
|
-
// the stale path.
|
|
5094
4095
|
record.worktreePath = newPath;
|
|
5095
4096
|
runnablePaths.set(variant.workItemId, `${path_1.default.basename(historyDir)}/${folderName}`);
|
|
5096
4097
|
manifestEntries.push({
|
|
@@ -5129,22 +4130,7 @@ class AgentVariantsOrchestrator {
|
|
|
5129
4130
|
resources.vitePreservedSiblings = true;
|
|
5130
4131
|
return runnablePaths;
|
|
5131
4132
|
}
|
|
5132
|
-
/**
|
|
5133
|
-
* Rename `sourceWorktreePath` into `destinationPath`, then replace the
|
|
5134
|
-
* worktree's `.git` with a fresh-history init + initial commit. Matches
|
|
5135
|
-
* the historical materializeProject behavior of "user sees a fresh repo
|
|
5136
|
-
* at destinationPath" so we don't surprise them with a `rivet: variant
|
|
5137
|
-
* baseline` commit they didn't intend.
|
|
5138
|
-
*
|
|
5139
|
-
* The rename is the load-bearing operation: it moves the entire variant
|
|
5140
|
-
* tree (template files + materialized node_modules) in O(1) when the
|
|
5141
|
-
* source and destination share a volume. The git reset that follows is
|
|
5142
|
-
* best-effort housekeeping; a failure there leaves files in place.
|
|
5143
|
-
*/
|
|
5144
4133
|
async renameWorktreeIntoDestination(sourceWorktreePath, destinationPath) {
|
|
5145
|
-
// destinationPath must not exist for fs.rename to behave as a move.
|
|
5146
|
-
// assertDestinationAvailable already enforced that any existing directory
|
|
5147
|
-
// contains only `.rivet`, which we preserve across the move.
|
|
5148
4134
|
const destinationParent = path_1.default.dirname(destinationPath);
|
|
5149
4135
|
await fs_1.default.promises.mkdir(destinationParent, { recursive: true });
|
|
5150
4136
|
let preservedRivetParent;
|
|
@@ -5191,16 +4177,11 @@ class AgentVariantsOrchestrator {
|
|
|
5191
4177
|
force: true,
|
|
5192
4178
|
});
|
|
5193
4179
|
}
|
|
5194
|
-
// Replace the variant-baseline git history with a fresh init so the
|
|
5195
|
-
// user doesn't inherit a `rivet: variant baseline` commit.
|
|
5196
4180
|
const dotGit = path_1.default.join(destinationPath, '.git');
|
|
5197
4181
|
try {
|
|
5198
4182
|
fs_1.default.rmSync(dotGit, { recursive: true, force: true });
|
|
5199
4183
|
}
|
|
5200
|
-
catch {
|
|
5201
|
-
// Best-effort — leaving the baseline .git is preferable to failing
|
|
5202
|
-
// the commit after we've moved the tree.
|
|
5203
|
-
}
|
|
4184
|
+
catch { }
|
|
5204
4185
|
try {
|
|
5205
4186
|
const git = (0, simple_git_1.simpleGit)(destinationPath);
|
|
5206
4187
|
await git.raw(['init']);
|
|
@@ -5216,23 +4197,12 @@ class AgentVariantsOrchestrator {
|
|
|
5216
4197
|
'-m',
|
|
5217
4198
|
'Initial commit (created with Rivet)',
|
|
5218
4199
|
])
|
|
5219
|
-
.catch(() => {
|
|
5220
|
-
// Best-effort: missing user identity or empty tree leaves the
|
|
5221
|
-
// commit step un-applied. Files are still in place.
|
|
5222
|
-
});
|
|
4200
|
+
.catch(() => { });
|
|
5223
4201
|
}
|
|
5224
4202
|
catch (err) {
|
|
5225
4203
|
log.warn(`Initial git history setup at ${destinationPath} failed`, err);
|
|
5226
4204
|
}
|
|
5227
4205
|
}
|
|
5228
|
-
/**
|
|
5229
|
-
* Stop every variant dev server currently running for `resources`. Clears
|
|
5230
|
-
* the `devServerProcess` / `port` fields on each record so subsequent
|
|
5231
|
-
* teardown logic doesn't try to stop them a second time. Called from
|
|
5232
|
-
* `commitVariant` (vite_app rename path) BEFORE the worktree directory is
|
|
5233
|
-
* renamed — leaving Vite alive across the rename leaks empty `.vite/`
|
|
5234
|
-
* stub dirs at the old paths.
|
|
5235
|
-
*/
|
|
5236
4206
|
async stopAllDevServersForSession(resources) {
|
|
5237
4207
|
this.clearActivePreviewIdleTimer(resources);
|
|
5238
4208
|
const stops = [];
|
|
@@ -5271,7 +4241,6 @@ class AgentVariantsOrchestrator {
|
|
|
5271
4241
|
clearTimeout(resources.activePreviewIdleTimer);
|
|
5272
4242
|
resources.activePreviewIdleTimer = undefined;
|
|
5273
4243
|
}
|
|
5274
|
-
/** @effect Stops idle variant child processes and clears dead preview ports. */
|
|
5275
4244
|
async stopIdleVariantDevServers(sessionId) {
|
|
5276
4245
|
const resources = this.resources.get(sessionId);
|
|
5277
4246
|
if (!resources || resources.cleanupStarted)
|
|
@@ -5300,8 +4269,6 @@ class AgentVariantsOrchestrator {
|
|
|
5300
4269
|
}
|
|
5301
4270
|
log.info(`Reclaimed ${expiringWorkItemIds.length} idle variant preview(s) for session ${sessionId} ` +
|
|
5302
4271
|
`(${stoppedCount} running, ${pendingRestartCount} restarting)`);
|
|
5303
|
-
// The next selection restores only the requested Rivet-owned preview;
|
|
5304
|
-
// siblings remain stopped until the user asks to view them.
|
|
5305
4272
|
try {
|
|
5306
4273
|
this.switchPreviewPort?.(null);
|
|
5307
4274
|
}
|
|
@@ -5317,18 +4284,6 @@ class AgentVariantsOrchestrator {
|
|
|
5317
4284
|
resources.activePreviewIdleStop = stop;
|
|
5318
4285
|
await stop;
|
|
5319
4286
|
}
|
|
5320
|
-
/**
|
|
5321
|
-
* Spawn a fresh dev server at the user-facing destinationPath and retarget
|
|
5322
|
-
* the proxy so the iframe stays live across commit. Stores the process on
|
|
5323
|
-
* `resources.committedDevServer` so teardown can hand it off to the
|
|
5324
|
-
* lingering registry instead of killing it. Best-effort: a failure here is
|
|
5325
|
-
* non-fatal — the commit still succeeds; the user just has to run
|
|
5326
|
-
* `npm run dev` themselves to bring the preview back.
|
|
5327
|
-
*
|
|
5328
|
-
* `mode` selects the server flavor: `vite_app` spawns Vite via `npm run
|
|
5329
|
-
* dev`; `static_preview` spawns the in-tree static file server bound to
|
|
5330
|
-
* the destination directory (no install, no build, ~ms startup).
|
|
5331
|
-
*/
|
|
5332
4287
|
async startCommittedDevServer(args) {
|
|
5333
4288
|
const mode = args.mode ?? 'vite_app';
|
|
5334
4289
|
try {
|
|
@@ -5353,14 +4308,6 @@ class AgentVariantsOrchestrator {
|
|
|
5353
4308
|
port,
|
|
5354
4309
|
path: args.destinationPath,
|
|
5355
4310
|
};
|
|
5356
|
-
// Advertise the Rivet-owned server on devServerHealth so the iframe's
|
|
5357
|
-
// upstream probe stops reporting `ownership: 'none'`. Distinct from
|
|
5358
|
-
// switchPreviewPort: this updates health metadata, switchPreviewPort
|
|
5359
|
-
// retargets the proxy. Both fire here because the commit-handoff is
|
|
5360
|
-
// the only place Rivet legitimately takes ownership of the dev
|
|
5361
|
-
// server — variant cycling and cancel only retarget, they don't
|
|
5362
|
-
// touch health (which the user's external dev server owns during a
|
|
5363
|
-
// regular session).
|
|
5364
4311
|
try {
|
|
5365
4312
|
this.setCommittedDevServerHealth?.(port);
|
|
5366
4313
|
}
|
|
@@ -5381,19 +4328,9 @@ class AgentVariantsOrchestrator {
|
|
|
5381
4328
|
return undefined;
|
|
5382
4329
|
}
|
|
5383
4330
|
}
|
|
5384
|
-
/**
|
|
5385
|
-
* Stop any committed dev servers that were left alive past their session's
|
|
5386
|
-
* teardown. Called at the start of a new `propose` (so the next session's
|
|
5387
|
-
* preview doesn't compete with stale processes) and exposed for explicit
|
|
5388
|
-
* shutdown hooks. Best-effort: per-server failures are logged but don't
|
|
5389
|
-
* propagate.
|
|
5390
|
-
*/
|
|
5391
4331
|
async stopLingeringCommittedDevServers() {
|
|
5392
4332
|
const entries = [...this.lingeringCommittedDevServers.entries()];
|
|
5393
4333
|
this.lingeringCommittedDevServers.clear();
|
|
5394
|
-
// Clear the Rivet-owned-server advertisement on `devServerHealth` so the
|
|
5395
|
-
// probe doesn't keep reporting a port that's about to stop listening.
|
|
5396
|
-
// Safe to call even when no committed server existed for this process.
|
|
5397
4334
|
if (entries.length > 0) {
|
|
5398
4335
|
try {
|
|
5399
4336
|
this.setCommittedDevServerHealth?.(null);
|
|
@@ -5422,40 +4359,20 @@ class AgentVariantsOrchestrator {
|
|
|
5422
4359
|
log.info(`Tearing down session ${sessionId} (reason: ${reason})`);
|
|
5423
4360
|
resources.dependencyAbortController.abort();
|
|
5424
4361
|
await Promise.all([...resources.worktrees.values()].map((record) => DependencyPreparationService_1.previewDependencies.settle(record.worktreePath)));
|
|
5425
|
-
// Drain in-flight history persists BEFORE deleting worktrees: a tree
|
|
5426
|
-
// snapshot's `git add -A --work-tree <worktree>` racing the deletion
|
|
5427
|
-
// below doesn't fail — it stages whatever files remain, publishing a
|
|
5428
|
-
// silently truncated snapshot. The design doc's ordering constraint
|
|
5429
|
-
// ("tree committed before worktree teardown") is enforced here, not
|
|
5430
|
-
// just in tests. Best-effort with a bound: never let a wedged git call
|
|
5431
|
-
// stall teardown forever.
|
|
5432
4362
|
await Promise.race([
|
|
5433
4363
|
this.settleHistoryPersists(),
|
|
5434
4364
|
new Promise((resolve) => setTimeout(resolve, SETTLE_PERSISTS_TEARDOWN_TIMEOUT_MS)),
|
|
5435
4365
|
]);
|
|
5436
|
-
// Stop dev servers in parallel; ignore individual failures.
|
|
5437
|
-
// NOTE: For the fresh vite_app rename path, commitVariant already stopped
|
|
5438
|
-
// these dev servers BEFORE the rename (so Vite couldn't recreate `.vite/`
|
|
5439
|
-
// stub dirs at the old worktree paths). In that case devServerProcess is
|
|
5440
|
-
// already cleared and this loop is a no-op — exactly the desired behavior.
|
|
5441
4366
|
const stops = [...resources.worktrees.values()]
|
|
5442
4367
|
.filter((r) => r.devServerProcess)
|
|
5443
4368
|
.map((r) => this.worktrees
|
|
5444
4369
|
.stopDevServer(r.devServerProcess)
|
|
5445
4370
|
.catch((err) => log.warn(`stopDevServer failed for ${sessionId}/${r.workItemId}`, err)));
|
|
5446
4371
|
await Promise.all(stops);
|
|
5447
|
-
// The committed dev server (spawned at destinationPath after a fresh
|
|
5448
|
-
// vite_app commit) intentionally outlives this teardown — the iframe is
|
|
5449
|
-
// pointed at it via the proxy and the user just chose this project. Hand
|
|
5450
|
-
// it off to the lingering registry; it'll be stopped on the next
|
|
5451
|
-
// `propose` or explicit shutdown.
|
|
5452
4372
|
if (resources.committedDevServer && reason === 'committed') {
|
|
5453
4373
|
this.lingeringCommittedDevServers.set(sessionId, resources.committedDevServer);
|
|
5454
4374
|
}
|
|
5455
4375
|
else if (resources.committedDevServer) {
|
|
5456
|
-
// Non-committed teardown (cancel/shutdown) with a committed dev server
|
|
5457
|
-
// shouldn't happen in current code paths, but stop it defensively so we
|
|
5458
|
-
// don't leak procs.
|
|
5459
4376
|
try {
|
|
5460
4377
|
await this.worktrees.stopDevServer(resources.committedDevServer.proc);
|
|
5461
4378
|
}
|
|
@@ -5463,10 +4380,6 @@ class AgentVariantsOrchestrator {
|
|
|
5463
4380
|
log.warn(`stopDevServer for committed dev server (session ${sessionId}) failed`, err);
|
|
5464
4381
|
}
|
|
5465
4382
|
}
|
|
5466
|
-
// When a vite_app commit already moved the unchosen worktrees into a
|
|
5467
|
-
// sibling history dir, calling cleanupSession would re-delete them. Skip
|
|
5468
|
-
// the worktree removal step in that case — the move already cleared the
|
|
5469
|
-
// .rivet-variants/ entries for the chosen + preserved variants.
|
|
5470
4383
|
if (!resources.vitePreservedSiblings) {
|
|
5471
4384
|
try {
|
|
5472
4385
|
await this.worktrees.cleanupSession(sessionId, resources.freshDestinationParent);
|
|
@@ -5475,10 +4388,6 @@ class AgentVariantsOrchestrator {
|
|
|
5475
4388
|
log.warn(`cleanupSession (worktree removal) failed for ${sessionId}`, err);
|
|
5476
4389
|
}
|
|
5477
4390
|
}
|
|
5478
|
-
// Assigned static workspaces are always Rivet-owned, including existing-
|
|
5479
|
-
// project refinement work staged under `.rivet/variant-work` or /tmp.
|
|
5480
|
-
// Fresh staticPreviews are also Rivet staging unless commit already moved
|
|
5481
|
-
// the selected directory into the destination.
|
|
5482
4391
|
const ownedArtifactRoots = new Set(resources.workspaceManager.getOwnedArtifactRoots());
|
|
5483
4392
|
resources.workspaceManager.removeOwnedArtifactWorkspaces();
|
|
5484
4393
|
const staticDirectories = new Set();
|
|
@@ -5536,10 +4445,6 @@ class AgentVariantsOrchestrator {
|
|
|
5536
4445
|
}
|
|
5537
4446
|
}
|
|
5538
4447
|
exports.AgentVariantsOrchestrator = AgentVariantsOrchestrator;
|
|
5539
|
-
/** MCP bridges sometimes serialize the output field as a JSON string instead
|
|
5540
|
-
* of a parsed object. Normalize it before field-level inspection. */
|
|
5541
|
-
/** Rough byte-size of the agent's output. Used as a proxy for "how much
|
|
5542
|
-
* code did the agent write" when comparing HTML vs full-stack flows. */
|
|
5543
4448
|
function estimateOutputBytes(output) {
|
|
5544
4449
|
if (output === undefined || output === null)
|
|
5545
4450
|
return 0;
|
|
@@ -5563,28 +4468,11 @@ function normalizeOutput(output) {
|
|
|
5563
4468
|
}
|
|
5564
4469
|
return output;
|
|
5565
4470
|
}
|
|
5566
|
-
/**
|
|
5567
|
-
* `true` when `child` is a strict descendant of `parent` (resolved). Used by
|
|
5568
|
-
* the static_preview commit branch before rm/rename to make sure we never
|
|
5569
|
-
* touch anything outside the variant's workspace.
|
|
5570
|
-
*/
|
|
5571
4471
|
function isStrictlyInside(child, parent) {
|
|
5572
4472
|
const c = path_1.default.resolve(child);
|
|
5573
4473
|
const p = path_1.default.resolve(parent);
|
|
5574
4474
|
return c !== p && c.startsWith(p + path_1.default.sep);
|
|
5575
4475
|
}
|
|
5576
|
-
/**
|
|
5577
|
-
* Resolve `requestedPath` to an absolute, sandboxed file under `base`, or
|
|
5578
|
-
* `undefined` if it escapes the base, doesn't exist, isn't a regular file, or
|
|
5579
|
-
* is a hardlink. Shared by `resolveStaticPreviewAssetPath` across the variant's
|
|
5580
|
-
* own directory and the host-root fallback so both get identical containment.
|
|
5581
|
-
*
|
|
5582
|
-
* `base` is expected to be realpath'd by the caller. The requested target is
|
|
5583
|
-
* realpath'd here too — without it, a symlink planted under the base (e.g. via
|
|
5584
|
-
* a follow-up Write tool call) could pivot outside the sandbox. `requestedPath`
|
|
5585
|
-
* is used as Express delivered it (already URL-decoded); decoding again would
|
|
5586
|
-
* mangle filenames that legitimately contain `%` (e.g. `100%25.png` on disk).
|
|
5587
|
-
*/
|
|
5588
4476
|
function resolveAssetWithinBase(base, requestedPath) {
|
|
5589
4477
|
const target = path_1.default.resolve(base, '.' + path_1.default.sep + requestedPath);
|
|
5590
4478
|
if (target !== base && !target.startsWith(base + path_1.default.sep)) {
|
|
@@ -5604,11 +4492,6 @@ function resolveAssetWithinBase(base, requestedPath) {
|
|
|
5604
4492
|
const stat = fs_1.default.statSync(realTarget);
|
|
5605
4493
|
if (!stat.isFile())
|
|
5606
4494
|
return undefined;
|
|
5607
|
-
// Hardlinks aren't dereferenced by `realpath` — they ARE the file from a
|
|
5608
|
-
// path-resolution perspective, so the realpath check above can't detect
|
|
5609
|
-
// them. An agent could `ln /path/to/.env base/x.glb` (hardlink, not
|
|
5610
|
-
// symlink) and the resolver would happily serve the secret. Reject
|
|
5611
|
-
// anything with multiple links — legitimate assets always have nlink === 1.
|
|
5612
4495
|
if (stat.nlink !== 1)
|
|
5613
4496
|
return undefined;
|
|
5614
4497
|
return realTarget;
|
|
@@ -5617,19 +4500,6 @@ function resolveAssetWithinBase(base, requestedPath) {
|
|
|
5617
4500
|
return undefined;
|
|
5618
4501
|
}
|
|
5619
4502
|
}
|
|
5620
|
-
/**
|
|
5621
|
-
* Sandbox the agent's `output.assetBase` to a path inside the session
|
|
5622
|
-
* workspace. Accepts either an absolute path (used as-is after the
|
|
5623
|
-
* within-workspace check) or a path relative to the fresh-session
|
|
5624
|
-
* `workspacePath`. Returns `undefined` for non-fresh sessions, missing
|
|
5625
|
-
* directories, or paths that escape the workspace via `..` or symlinks.
|
|
5626
|
-
*
|
|
5627
|
-
* `assetBase` is agent-controlled, so a prompt-injected variant could point
|
|
5628
|
-
* it at a symlink whose real target is outside `workspacePath` — and the
|
|
5629
|
-
* asset endpoint would then happily serve files like `~/.ssh/id_rsa` or
|
|
5630
|
-
* `.env`. Resolving with `fs.realpathSync` collapses symlinks before the
|
|
5631
|
-
* containment check, so the check applies to the real target, not the link.
|
|
5632
|
-
*/
|
|
5633
4503
|
function resolveStaticPreviewAssetBase(args) {
|
|
5634
4504
|
if (!args.assetBase)
|
|
5635
4505
|
return undefined;
|
|
@@ -5638,23 +4508,6 @@ function resolveStaticPreviewAssetBase(args) {
|
|
|
5638
4508
|
let workspace;
|
|
5639
4509
|
let resolved;
|
|
5640
4510
|
try {
|
|
5641
|
-
// Defense against an agent that subverts the sandbox by replacing the
|
|
5642
|
-
// Rivet-created `workspacePath` directory with a symlink. Plain
|
|
5643
|
-
// `realpath` would silently follow that symlink and the containment
|
|
5644
|
-
// check below would then trust the wrong root.
|
|
5645
|
-
//
|
|
5646
|
-
// Two layers:
|
|
5647
|
-
// 1. `lstat` the workspacePath itself — if it's a symlink (rather
|
|
5648
|
-
// than a real directory Rivet created), reject outright. This
|
|
5649
|
-
// catches the obvious swap `ln -sf $HOME <workspacePath>` and the
|
|
5650
|
-
// subtler swap to a sibling like `<workspaceRoot>` itself
|
|
5651
|
-
// (which would pass any subsequent containment check based on
|
|
5652
|
-
// ancestor matching).
|
|
5653
|
-
// 2. realpath both and require the resolved workspacePath to be a
|
|
5654
|
-
// STRICT descendant of the resolved workspaceRoot — equal is not
|
|
5655
|
-
// enough (a symlink to workspaceRoot would otherwise be accepted
|
|
5656
|
-
// and the asset route would then serve files at the project
|
|
5657
|
-
// root, e.g. `.env`).
|
|
5658
4511
|
const wsStat = fs_1.default.lstatSync(args.projectContext.workspacePath);
|
|
5659
4512
|
if (wsStat.isSymbolicLink()) {
|
|
5660
4513
|
log.warn(`Static preview workspacePath ${args.projectContext.workspacePath} is a symlink — refusing assetBase`);
|
|
@@ -5716,11 +4569,6 @@ function buildStaticPreviewDocument(input) {
|
|
|
5716
4569
|
const style = input.css ? `<style>\n${input.css}\n</style>` : '';
|
|
5717
4570
|
const script = input.js ? `<script>\n${input.js}\n</script>` : '';
|
|
5718
4571
|
if (/<!doctype html>|<html[\s>]/i.test(input.html)) {
|
|
5719
|
-
// Full document: inject css before </head> and js before </body>. The
|
|
5720
|
-
// agent often passes a complete `<!doctype html>...` blob with css/js
|
|
5721
|
-
// alongside; without this they're silently dropped and the variant ships
|
|
5722
|
-
// unstyled and non-interactive. Falls back to appending to the end if
|
|
5723
|
-
// the closing tag isn't found.
|
|
5724
4572
|
let doc = input.html;
|
|
5725
4573
|
if (style) {
|
|
5726
4574
|
if (/<\/head>/i.test(doc)) {
|
|
@@ -5754,15 +4602,8 @@ ${input.html}
|
|
|
5754
4602
|
</html>`;
|
|
5755
4603
|
}
|
|
5756
4604
|
function countDiffFiles(diff) {
|
|
5757
|
-
// Each file in a unified diff starts with "diff --git ".
|
|
5758
4605
|
return (diff.match(/^diff --git /gm) ?? []).length;
|
|
5759
4606
|
}
|
|
5760
|
-
/**
|
|
5761
|
-
* Count source files under a materialized fresh-project destination,
|
|
5762
|
-
* skipping install artifacts (`node_modules`, `.git`, build outputs) so the
|
|
5763
|
-
* commit telemetry / chip count reflects the agent-visible surface area
|
|
5764
|
-
* rather than the install footprint.
|
|
5765
|
-
*/
|
|
5766
4607
|
function countWorktreeFiles(destinationPath) {
|
|
5767
4608
|
let count = 0;
|
|
5768
4609
|
const walk = (dir) => {
|
|
@@ -5795,8 +4636,6 @@ const enrichDesignSource = (design) => {
|
|
|
5795
4636
|
};
|
|
5796
4637
|
};
|
|
5797
4638
|
const toActiveProjectContext = (projectContext) => {
|
|
5798
|
-
// Source count + grounding are derived purely from the read-only context
|
|
5799
|
-
// bundle now that `sourceContext` intake is gone.
|
|
5800
4639
|
const sourceCount = projectContext.variantContext?.userContext.filter((source) => source.transport !== 'prompt').length ?? 0;
|
|
5801
4640
|
const hasSourceContextSummary = Boolean(sourceCount > 0 ||
|
|
5802
4641
|
(projectContext.variantContext?.rivetMetadata.length ?? 0) > 0);
|
|
@@ -5839,18 +4678,6 @@ const toActiveProjectContext = (projectContext) => {
|
|
|
5839
4678
|
: {}),
|
|
5840
4679
|
};
|
|
5841
4680
|
};
|
|
5842
|
-
/**
|
|
5843
|
-
* Resolve the user-facing supporting artifacts for a session.
|
|
5844
|
-
*
|
|
5845
|
-
* For 0→1 (`fresh`) sessions with a populated `designContext`, each slot is
|
|
5846
|
-
* turned into a `design_context` artifact that links to Rivet-hosted
|
|
5847
|
-
* DESIGN.md views:
|
|
5848
|
-
* - `slug` entries resolve bundled catalog markdown via the design catalog.
|
|
5849
|
-
* - `markdown` entries (Agent Browser / inspiration extractor output) carry
|
|
5850
|
-
* their stored markdown when the linked route is requested.
|
|
5851
|
-
* Slots whose markdown can't be resolved are skipped so the UI never renders
|
|
5852
|
-
* a metadata-only DESIGN.md row.
|
|
5853
|
-
*/
|
|
5854
4681
|
const buildSessionArtifacts = (sessionId, projectContext) => {
|
|
5855
4682
|
const artifacts = buildResolvedDesignContextArtifacts(projectContext);
|
|
5856
4683
|
return artifacts.map(({ content: _content, ...artifact }) => ({
|
|
@@ -6188,7 +5015,6 @@ const renderDesignMarkdown = (markdown, artifactLabel) => {
|
|
|
6188
5015
|
const headingText = headingMatch[2].trim();
|
|
6189
5016
|
const isDuplicateTitle = headingText === artifactLabel ||
|
|
6190
5017
|
headingText === `${artifactLabel} DESIGN.md`;
|
|
6191
|
-
// The viewer header already renders the artifact title.
|
|
6192
5018
|
if (level === 1 && !skippedFirstH1 && isDuplicateTitle) {
|
|
6193
5019
|
skippedFirstH1 = true;
|
|
6194
5020
|
return;
|
|
@@ -6230,14 +5056,6 @@ const escapeHtml = (value) => {
|
|
|
6230
5056
|
.replace(/"/g, '"')
|
|
6231
5057
|
.replace(/'/g, ''');
|
|
6232
5058
|
};
|
|
6233
|
-
/**
|
|
6234
|
-
* Resolve a per-variant design context entry into the raw DESIGN.md markdown
|
|
6235
|
-
* the worktree scaffolder writes, plus a small `designSource` descriptor for
|
|
6236
|
-
* the variant manifest. Slug entries resolve through the bundled catalog;
|
|
6237
|
-
* markdown entries (Agent Browser / inspiration extractor output) carry their
|
|
6238
|
-
* stored markdown verbatim. Returns null when the entry is missing or the
|
|
6239
|
-
* slug doesn't resolve to bundled markdown.
|
|
6240
|
-
*/
|
|
6241
5059
|
const resolveDesignArtifact = (entry) => {
|
|
6242
5060
|
if (!entry)
|
|
6243
5061
|
return null;
|
|
@@ -6462,7 +5280,6 @@ function copyStaticPreviewDirectory(src, dest) {
|
|
|
6462
5280
|
}
|
|
6463
5281
|
}
|
|
6464
5282
|
}
|
|
6465
|
-
/** Prepares an isolated project through its selected package manager. */
|
|
6466
5283
|
const defaultInstallDependencies = async (worktreePath, options) => {
|
|
6467
5284
|
await DependencyPreparationService_1.previewDependencies.prepare({
|
|
6468
5285
|
cwd: worktreePath,
|
|
@@ -6471,14 +5288,6 @@ const defaultInstallDependencies = async (worktreePath, options) => {
|
|
|
6471
5288
|
signal: options?.signal,
|
|
6472
5289
|
});
|
|
6473
5290
|
};
|
|
6474
|
-
/**
|
|
6475
|
-
* Turn the invocation a live dev server actually booted with into a
|
|
6476
|
-
* port-parameterized replay recipe. The resolution bakes the allocated port
|
|
6477
|
-
* into args/env (`--port <n>`, `PORT=<n>`) — storing that verbatim would
|
|
6478
|
-
* bake in a dead port, so occurrences of the port (digit-boundary-guarded so
|
|
6479
|
-
* incidental digit runs survive) become `${PORT}` for replay to substitute.
|
|
6480
|
-
* `cwd` is stored relative to the snapshot root per the tree-root contract.
|
|
6481
|
-
*/
|
|
6482
5291
|
const buildServeRecipeFromResolved = (snapshotRoot, dev, port) => {
|
|
6483
5292
|
const portPattern = new RegExp(`(?<![0-9])${port}(?![0-9])`, 'g');
|
|
6484
5293
|
const sub = (value) => value.replace(portPattern, '${PORT}');
|
|
@@ -6490,19 +5299,6 @@ const buildServeRecipeFromResolved = (snapshotRoot, dev, port) => {
|
|
|
6490
5299
|
envTemplate: Object.fromEntries(Object.entries(dev.env).map(([key, value]) => [key, sub(value)])),
|
|
6491
5300
|
};
|
|
6492
5301
|
};
|
|
6493
|
-
/**
|
|
6494
|
-
* Whether an install at `cwd` stays inside the Rivet-owned worktree.
|
|
6495
|
-
* A linked `node_modules` can point at another project's install; running a
|
|
6496
|
-
* package manager through it would mutate dependencies outside this worktree.
|
|
6497
|
-
* Install is safe only
|
|
6498
|
-
* when `node_modules` is absent (a nested standalone package — the install
|
|
6499
|
-
* creates a worktree-local dir) or a real directory owned by the worktree.
|
|
6500
|
-
*
|
|
6501
|
-
* Complements DependencyPreparationService.assertOwnedInstall rather than
|
|
6502
|
-
* duplicating it: this stricter check (any symlink, even one resolving
|
|
6503
|
-
* inside the worktree) decides whether an install RETRY is worth attempting,
|
|
6504
|
-
* while the service enforces containment on every install it runs.
|
|
6505
|
-
*/
|
|
6506
5302
|
const canInstallWithoutTouchingHost = (cwd) => {
|
|
6507
5303
|
try {
|
|
6508
5304
|
return !fs_1.default.lstatSync(path_1.default.join(cwd, 'node_modules')).isSymbolicLink();
|
|
@@ -6511,15 +5307,6 @@ const canInstallWithoutTouchingHost = (cwd) => {
|
|
|
6511
5307
|
return true;
|
|
6512
5308
|
}
|
|
6513
5309
|
};
|
|
6514
|
-
/**
|
|
6515
|
-
* Fail fast — before spawning anything — when the package.json at `cwd`
|
|
6516
|
-
* positively lacks the dev script we're about to invoke. Without this the
|
|
6517
|
-
* spawn exits with the package manager's "missing script" error after a full
|
|
6518
|
-
* boot round-trip and surfaces as an opaque `exited` failure; with it the
|
|
6519
|
-
* user gets an actionable message naming the scripts that DO exist. Missing
|
|
6520
|
-
* or unparseable package.json is NOT treated as a failure here — other paths
|
|
6521
|
-
* own those cases, and the spawn's own error is more specific.
|
|
6522
|
-
*/
|
|
6523
5310
|
const assertDevScriptExists = (cwd, scriptName) => {
|
|
6524
5311
|
let scripts;
|
|
6525
5312
|
try {
|
|
@@ -6548,16 +5335,6 @@ const assertDevScriptExists = (cwd, scriptName) => {
|
|
|
6548
5335
|
: '',
|
|
6549
5336
|
});
|
|
6550
5337
|
};
|
|
6551
|
-
/**
|
|
6552
|
-
* True when `a` and `b` (or the closest existing ancestor of each) live on
|
|
6553
|
-
* the same filesystem volume. Used by commitVariant to decide between an
|
|
6554
|
-
* O(1) rename and a recursive copy-with-reinstall fallback.
|
|
6555
|
-
*
|
|
6556
|
-
* `destinationPath` for fresh sessions does not exist yet (we'd fail the
|
|
6557
|
-
* "destination must be empty" guard otherwise), so we compare against its
|
|
6558
|
-
* parent directory which is guaranteed to exist (createZeroToOneTool either
|
|
6559
|
-
* created it or validated it).
|
|
6560
|
-
*/
|
|
6561
5338
|
function areSameVolume(a, b) {
|
|
6562
5339
|
try {
|
|
6563
5340
|
const statA = fs_1.default.statSync(a);
|
|
@@ -6569,7 +5346,6 @@ function areSameVolume(a, b) {
|
|
|
6569
5346
|
return false;
|
|
6570
5347
|
}
|
|
6571
5348
|
}
|
|
6572
|
-
/** Clears a borrowed install so a moved generated project prepares its own dependencies. */
|
|
6573
5349
|
async function resolveNodeModulesSymlink(worktreePath) {
|
|
6574
5350
|
const nodeModulesPath = path_1.default.join(worktreePath, 'node_modules');
|
|
6575
5351
|
try {
|
|
@@ -6610,17 +5386,8 @@ const defaultMaterializeProject = async (sourceWorktreePath, destinationPath) =>
|
|
|
6610
5386
|
'-m',
|
|
6611
5387
|
'Initial commit (created with Rivet)',
|
|
6612
5388
|
])
|
|
6613
|
-
.catch(() => {
|
|
6614
|
-
// Best-effort: a missing user identity or empty tree leaves the
|
|
6615
|
-
// commit step un-applied. The destination still has the files.
|
|
6616
|
-
});
|
|
5389
|
+
.catch(() => { });
|
|
6617
5390
|
};
|
|
6618
|
-
/**
|
|
6619
|
-
* Synthesize a fallback brief body for a human-direct unified start slot.
|
|
6620
|
-
* Agent callers provide structured briefs before starting. Human-direct
|
|
6621
|
-
* batches get stable, slot-specific focus statements without another model
|
|
6622
|
-
* call so workers do not independently invent overlapping directions.
|
|
6623
|
-
*/
|
|
6624
5391
|
function synthesizeUnifiedBriefBody(prompt, index, total) {
|
|
6625
5392
|
const trimmed = prompt.trim().replace(/\s+/g, ' ').slice(0, 200);
|
|
6626
5393
|
const intent = trimmed.length > 0 ? trimmed : 'Create this variant';
|