rivet-design 0.11.17 → 0.12.1
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/dist/mcp/agent-variants/SessionStore.d.ts.map +1 -1
- package/dist/mcp/agent-variants/SessionStore.js +5 -3
- package/dist/mcp/agent-variants/SessionStore.js.map +1 -1
- package/dist/mcp/agent-variants/WorktreeOrchestrator.d.ts +29 -0
- package/dist/mcp/agent-variants/WorktreeOrchestrator.d.ts.map +1 -1
- package/dist/mcp/agent-variants/WorktreeOrchestrator.js +185 -14
- package/dist/mcp/agent-variants/WorktreeOrchestrator.js.map +1 -1
- package/dist/mcp/agent-variants/WorktreeOrchestrator.testHelpers.d.ts.map +1 -1
- package/dist/mcp/agent-variants/WorktreeOrchestrator.testHelpers.js +13 -0
- package/dist/mcp/agent-variants/WorktreeOrchestrator.testHelpers.js.map +1 -1
- package/dist/mcp/agent-variants/briefContent.d.ts +16 -0
- package/dist/mcp/agent-variants/briefContent.d.ts.map +1 -0
- package/dist/mcp/agent-variants/briefContent.js +42 -0
- package/dist/mcp/agent-variants/briefContent.js.map +1 -0
- package/dist/mcp/agent-variants/contracts.d.ts +1 -0
- package/dist/mcp/agent-variants/contracts.d.ts.map +1 -1
- package/dist/mcp/agent-variants/contracts.js +1 -1
- package/dist/mcp/agent-variants/contracts.js.map +1 -1
- package/dist/mcp/agent-variants/tools.d.ts +10 -0
- package/dist/mcp/agent-variants/tools.d.ts.map +1 -1
- package/dist/mcp/agent-variants/tools.js +11 -4
- package/dist/mcp/agent-variants/tools.js.map +1 -1
- package/dist/mcp/server.d.ts +57 -3
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +457 -48
- package/dist/mcp/server.js.map +1 -1
- package/dist/prototype-host.js +1 -1
- package/dist/routes/agentVariants.d.ts +15 -1
- package/dist/routes/agentVariants.d.ts.map +1 -1
- package/dist/routes/agentVariants.js +173 -7
- package/dist/routes/agentVariants.js.map +1 -1
- package/dist/routes/comments.d.ts +3 -0
- package/dist/routes/comments.d.ts.map +1 -0
- package/dist/routes/comments.js +113 -0
- package/dist/routes/comments.js.map +1 -0
- package/dist/routes/prototypeHost.d.ts +1 -1
- package/dist/routes/prototypeHost.d.ts.map +1 -1
- package/dist/routes/prototypeHost.js +164 -12
- package/dist/routes/prototypeHost.js.map +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +2 -0
- package/dist/server.js.map +1 -1
- package/dist/services/BundleStore.d.ts +14 -0
- package/dist/services/BundleStore.d.ts.map +1 -1
- package/dist/services/BundleStore.js +77 -13
- package/dist/services/BundleStore.js.map +1 -1
- package/dist/services/HistoryReplayService.d.ts +78 -0
- package/dist/services/HistoryReplayService.d.ts.map +1 -0
- package/dist/services/HistoryReplayService.js +265 -0
- package/dist/services/HistoryReplayService.js.map +1 -0
- package/dist/services/ProjectDetectionService.d.ts.map +1 -1
- package/dist/services/ProjectDetectionService.js +14 -5
- package/dist/services/ProjectDetectionService.js.map +1 -1
- package/dist/services/PrototypeBuildService.d.ts +2 -2
- package/dist/services/PrototypeBuildService.js +2 -2
- package/dist/services/PrototypeDeployService.d.ts +11 -3
- package/dist/services/PrototypeDeployService.d.ts.map +1 -1
- package/dist/services/PrototypeDeployService.js +22 -9
- package/dist/services/PrototypeDeployService.js.map +1 -1
- package/dist/services/TreeStore.d.ts +118 -0
- package/dist/services/TreeStore.d.ts.map +1 -0
- package/dist/services/TreeStore.js +386 -0
- package/dist/services/TreeStore.js.map +1 -0
- package/dist/services/VariantHistoryService.d.ts +83 -0
- package/dist/services/VariantHistoryService.d.ts.map +1 -1
- package/dist/services/VariantHistoryService.js +169 -30
- package/dist/services/VariantHistoryService.js.map +1 -1
- package/dist/utils/skills/claude-skill.d.ts +1 -1
- package/dist/utils/skills/claude-skill.js +1 -1
- package/dist/utils/skills/cursor-rules.d.ts +1 -1
- package/dist/utils/skills/cursor-rules.js +1 -1
- package/dist/utils/skills/shared-variants-protocol.d.ts +2 -2
- package/dist/utils/skills/shared-variants-protocol.d.ts.map +1 -1
- package/dist/utils/skills/shared-variants-protocol.js +8 -6
- package/dist/utils/skills/shared-variants-protocol.js.map +1 -1
- package/package.json +1 -1
- package/src/ui/dist/assets/arena-Db0j1set.png +0 -0
- package/src/ui/dist/assets/main-DH8bmUcZ.css +1 -0
- package/src/ui/dist/assets/main-Utev2DA9.js +655 -0
- package/src/ui/dist/favicon-16.png +0 -0
- package/src/ui/dist/favicon-32.png +0 -0
- package/src/ui/dist/favicon.ico +0 -0
- package/src/ui/dist/index.html +4 -2
- package/src/ui/dist/assets/main-C8R68t8Q.css +0 -1
- package/src/ui/dist/assets/main-CwQdqqea.js +0 -655
|
@@ -17,6 +17,7 @@ const devServerError_1 = require("../../utils/devServerError");
|
|
|
17
17
|
const errors_1 = require("./errors");
|
|
18
18
|
const createProjectArtifacts_1 = require("./createProjectArtifacts");
|
|
19
19
|
const contracts_1 = require("./contracts");
|
|
20
|
+
const briefContent_1 = require("./briefContent");
|
|
20
21
|
const runLabel_1 = require("./runLabel");
|
|
21
22
|
const runPlan_1 = require("./runPlan");
|
|
22
23
|
const viteReactTs_1 = require("../../services/templates/viteReactTs");
|
|
@@ -28,6 +29,17 @@ const VariantHistoryService_1 = require("../../services/VariantHistoryService");
|
|
|
28
29
|
const variantContext_1 = require("./variantContext");
|
|
29
30
|
const log = (0, logger_1.createLogger)('AgentVariantsOrchestrator');
|
|
30
31
|
const FRESH_DEV_SERVER_HOST = '127.0.0.1';
|
|
32
|
+
// Upper bound on waiting for in-flight history persists during session
|
|
33
|
+
// teardown. Generous enough for a full-repo snapshot on a large project;
|
|
34
|
+
// small enough that a wedged git subprocess (which has its own 120s block
|
|
35
|
+
// timeout) can't make commit/cancel appear hung.
|
|
36
|
+
const SETTLE_PERSISTS_TEARDOWN_TIMEOUT_MS = 20_000;
|
|
37
|
+
// Sentinel port for deriving a persist-time serve recipe when the dev server
|
|
38
|
+
// hasn't booted yet: resolved into the command, then reverse-substituted to
|
|
39
|
+
// the ${PORT} placeholder. Digit-boundary-guarded substitution means only an
|
|
40
|
+
// exact standalone occurrence is replaced, and 65535 never appears in any
|
|
41
|
+
// framework's default invocation.
|
|
42
|
+
const RECIPE_PORT_SENTINEL = 65535;
|
|
31
43
|
// Fresh worktrees run the Vite React template, whose dev server defaults to
|
|
32
44
|
// 5173. Used as the scan start when allocating a fresh variant's preview port.
|
|
33
45
|
const FRESH_DEV_SERVER_DEFAULT_PORT = 5173;
|
|
@@ -1663,7 +1675,7 @@ class AgentVariantsOrchestrator {
|
|
|
1663
1675
|
buildUnifiedBriefs(args) {
|
|
1664
1676
|
const briefId = (i) => args.uniqueBriefIds ? `v-${(0, crypto_1.randomUUID)().slice(0, 8)}` : `v${i + 1}`;
|
|
1665
1677
|
if (args.briefs) {
|
|
1666
|
-
return args.briefs.map((b, i) => ({
|
|
1678
|
+
return args.briefs.map((b, i) => (0, briefContent_1.normalizeBriefContent)({
|
|
1667
1679
|
briefId: briefId(i),
|
|
1668
1680
|
label: b.label,
|
|
1669
1681
|
body: b.body,
|
|
@@ -3207,6 +3219,7 @@ class AgentVariantsOrchestrator {
|
|
|
3207
3219
|
const proc = await this.worktrees.startDevServer(dev.cwd, port, dev.cmd, dev.args, dev.env);
|
|
3208
3220
|
args.record.port = port;
|
|
3209
3221
|
args.record.devServerProcess = proc;
|
|
3222
|
+
args.record.devCommand = dev;
|
|
3210
3223
|
// If the dev server dies on its own (crash, OOM, Vite hard-fail),
|
|
3211
3224
|
// clear the port so the iframe stops routing the chip onto a dead
|
|
3212
3225
|
// socket. Without this the proxy retargets onto an unreachable port
|
|
@@ -3366,12 +3379,12 @@ class AgentVariantsOrchestrator {
|
|
|
3366
3379
|
if (this.store.getProjectContext(sessionId).kind === 'fresh') {
|
|
3367
3380
|
// History at `<workspacePath>/.rivet/variants/<sessionId>/<variantId>/`
|
|
3368
3381
|
// is the on-disk record for this generated project.
|
|
3369
|
-
this.persistCompletedFreshVariant({
|
|
3382
|
+
this.trackHistoryPersist(this.persistCompletedFreshVariant({
|
|
3370
3383
|
sessionId,
|
|
3371
3384
|
workItemId,
|
|
3372
3385
|
}).catch((err) => {
|
|
3373
3386
|
log.warn(`persistCompletedFreshVariant failed for ${sessionId}/${workItemId}`, err);
|
|
3374
|
-
});
|
|
3387
|
+
}));
|
|
3375
3388
|
}
|
|
3376
3389
|
const leasedAt = resources.leasedAt.get(workItemId);
|
|
3377
3390
|
trackStaticPreviewCompleted(this.telemetry, {
|
|
@@ -3422,21 +3435,21 @@ class AgentVariantsOrchestrator {
|
|
|
3422
3435
|
// failure here must never block dev-server startup or the user's pick
|
|
3423
3436
|
// flow.
|
|
3424
3437
|
if (!isFresh) {
|
|
3425
|
-
this.persistCompletedExistingVariant({
|
|
3438
|
+
this.trackHistoryPersist(this.persistCompletedExistingVariant({
|
|
3426
3439
|
sessionId,
|
|
3427
3440
|
workItemId,
|
|
3428
3441
|
diff: record.diff ?? '',
|
|
3429
3442
|
}).catch((err) => {
|
|
3430
3443
|
log.warn(`persistCompletedExistingVariant failed for ${sessionId}/${workItemId}`, err);
|
|
3431
|
-
});
|
|
3444
|
+
}));
|
|
3432
3445
|
}
|
|
3433
3446
|
else {
|
|
3434
|
-
this.persistCompletedFreshVariant({
|
|
3447
|
+
this.trackHistoryPersist(this.persistCompletedFreshVariant({
|
|
3435
3448
|
sessionId,
|
|
3436
3449
|
workItemId,
|
|
3437
3450
|
}).catch((err) => {
|
|
3438
3451
|
log.warn(`persistCompletedFreshVariant failed for ${sessionId}/${workItemId}`, err);
|
|
3439
|
-
});
|
|
3452
|
+
}));
|
|
3440
3453
|
}
|
|
3441
3454
|
// Static existing-mode projects (framework='static', no dev command) have
|
|
3442
3455
|
// no per-variant dev server to proxy the iframe at. Serve the variant's
|
|
@@ -3535,6 +3548,35 @@ class AgentVariantsOrchestrator {
|
|
|
3535
3548
|
// The caller (reportComplete) emits the change after recording success so
|
|
3536
3549
|
// the snapshot reflects both the swapped HTML and refinement.status.
|
|
3537
3550
|
}
|
|
3551
|
+
/** The worktree/dev-server manager this orchestrator boots previews with.
|
|
3552
|
+
* Exposed so HistoryReplayService shares the SAME instance: the
|
|
3553
|
+
* reserved-but-not-yet-bound port set is per-instance, and a second
|
|
3554
|
+
* manager scanning the same range can hand a live variant's pending port
|
|
3555
|
+
* to a replay (EADDRINUSE for the loser). */
|
|
3556
|
+
get devServerManager() {
|
|
3557
|
+
return this.worktrees;
|
|
3558
|
+
}
|
|
3559
|
+
/** In-flight fire-and-forget history persists. Tree-store snapshots spawn
|
|
3560
|
+
* git subprocesses, so these can outlive the microtask flushes that used
|
|
3561
|
+
* to be enough to drain them — {@link teardownSession} (and the test
|
|
3562
|
+
* helpers' settleBackgroundWork) await {@link settleHistoryPersists}
|
|
3563
|
+
* instead of racing the writes. */
|
|
3564
|
+
pendingHistoryPersists = new Set();
|
|
3565
|
+
trackHistoryPersist(persist) {
|
|
3566
|
+
this.pendingHistoryPersists.add(persist);
|
|
3567
|
+
void persist
|
|
3568
|
+
.catch(() => undefined)
|
|
3569
|
+
.finally(() => {
|
|
3570
|
+
this.pendingHistoryPersists.delete(persist);
|
|
3571
|
+
});
|
|
3572
|
+
}
|
|
3573
|
+
/** Await every in-flight history persist, including ones that start while
|
|
3574
|
+
* draining (a refine can persist mid-settle). */
|
|
3575
|
+
async settleHistoryPersists() {
|
|
3576
|
+
while (this.pendingHistoryPersists.size > 0) {
|
|
3577
|
+
await Promise.allSettled([...this.pendingHistoryPersists]);
|
|
3578
|
+
}
|
|
3579
|
+
}
|
|
3538
3580
|
/**
|
|
3539
3581
|
* Persist a completed existing-project code_gen variant into
|
|
3540
3582
|
* `<env.projectPath>/.rivet/variants/<sessionId>/<variantId>/`. Called from
|
|
@@ -3568,10 +3610,57 @@ class AgentVariantsOrchestrator {
|
|
|
3568
3610
|
}
|
|
3569
3611
|
const input = this.store.getWorkItemInput(args.sessionId, args.workItemId);
|
|
3570
3612
|
const sessionPrompt = this.store.getPrompt(args.sessionId);
|
|
3613
|
+
// Tree-store snapshot inputs (dual-write). The snapshot root is the
|
|
3614
|
+
// worktree root — the git root, per the tree-root contract — for EVERY
|
|
3615
|
+
// framework, not just static: this is what makes dev-server (Vite /
|
|
3616
|
+
// fullstack) variants replayable from history instead of diff-only.
|
|
3617
|
+
const snapshotDir = record?.worktreePath;
|
|
3618
|
+
// Lazy per-session base snapshot from the host repo root. Best-effort:
|
|
3619
|
+
// resolution failure just means no base ref (variant commits still land).
|
|
3620
|
+
let baseDir;
|
|
3621
|
+
try {
|
|
3622
|
+
baseDir = await this.worktrees.getGitRoot?.();
|
|
3623
|
+
}
|
|
3624
|
+
catch (err) {
|
|
3625
|
+
log.warn(`persistCompletedExistingVariant: git root resolution failed for ${args.sessionId}`, err);
|
|
3626
|
+
}
|
|
3627
|
+
let serve;
|
|
3628
|
+
if (sourceDir && record) {
|
|
3629
|
+
// Static framework: entryPath is relative to the snapshot root (the
|
|
3630
|
+
// worktree root), pointing into the nested project dir when the
|
|
3631
|
+
// project lives below the git root.
|
|
3632
|
+
const entryPath = path_1.default.relative(record.worktreePath, path_1.default.join(sourceDir, 'index.html'));
|
|
3633
|
+
serve = { kind: 'static', entryPath };
|
|
3634
|
+
}
|
|
3635
|
+
else if (record?.devCommand && record.port !== undefined) {
|
|
3636
|
+
serve = {
|
|
3637
|
+
kind: 'dev-server',
|
|
3638
|
+
recipe: buildServeRecipeFromResolved(record.worktreePath, record.devCommand, record.port),
|
|
3639
|
+
};
|
|
3640
|
+
}
|
|
3641
|
+
else if (record) {
|
|
3642
|
+
// Persist fires at code-gen success, BEFORE the dev server boots (the
|
|
3643
|
+
// boot is what stashes record.devCommand/port) — so for the common
|
|
3644
|
+
// path the live invocation isn't available yet. Run the same
|
|
3645
|
+
// deterministic resolution the boot will use, against a sentinel port
|
|
3646
|
+
// that becomes the ${PORT} placeholder. No dependency install here —
|
|
3647
|
+
// resolveDevServerCommand is the side-effect-free half of the split.
|
|
3648
|
+
try {
|
|
3649
|
+
const dev = await this.resolveDevServerCommand(args.sessionId, record.worktreePath, RECIPE_PORT_SENTINEL, false);
|
|
3650
|
+
serve = {
|
|
3651
|
+
kind: 'dev-server',
|
|
3652
|
+
recipe: buildServeRecipeFromResolved(record.worktreePath, dev, RECIPE_PORT_SENTINEL),
|
|
3653
|
+
};
|
|
3654
|
+
}
|
|
3655
|
+
catch (err) {
|
|
3656
|
+
log.warn(`persistCompletedExistingVariant: dev command resolution failed for ${args.sessionId}/${args.workItemId} — persisting without a serve recipe`, err);
|
|
3657
|
+
}
|
|
3658
|
+
}
|
|
3571
3659
|
await this.variantHistory.persistVariant({
|
|
3572
3660
|
projectPath: env.projectPath,
|
|
3573
3661
|
sessionId: args.sessionId,
|
|
3574
3662
|
variantId: args.workItemId,
|
|
3663
|
+
...(input.requestId ? { requestId: input.requestId } : {}),
|
|
3575
3664
|
label: input.briefLabel,
|
|
3576
3665
|
brief: input.briefBody,
|
|
3577
3666
|
sessionPrompt,
|
|
@@ -3584,6 +3673,9 @@ class AgentVariantsOrchestrator {
|
|
|
3584
3673
|
: { kind: 'none', reason: 'diff_only' },
|
|
3585
3674
|
changedFilesCount: countDiffFiles(args.diff),
|
|
3586
3675
|
projectKind: 'existing',
|
|
3676
|
+
snapshotDir,
|
|
3677
|
+
baseDir,
|
|
3678
|
+
serve,
|
|
3587
3679
|
});
|
|
3588
3680
|
}
|
|
3589
3681
|
/**
|
|
@@ -3772,11 +3864,42 @@ class AgentVariantsOrchestrator {
|
|
|
3772
3864
|
script: 'dev',
|
|
3773
3865
|
},
|
|
3774
3866
|
};
|
|
3867
|
+
// Tree-store serve contract. Fresh worktrees prefer the live record's
|
|
3868
|
+
// resolved invocation (stashed at dev-server start); the fallback recipe
|
|
3869
|
+
// mirrors resolveDevServer's fresh branch, which is fully deterministic
|
|
3870
|
+
// for the Vite template. Static previews serve their staged index.html.
|
|
3871
|
+
// Fresh sessions have no host project, so there is no base snapshot —
|
|
3872
|
+
// variant commits are root commits.
|
|
3873
|
+
const serve = staticPreview
|
|
3874
|
+
? { kind: 'static', entryPath: 'index.html' }
|
|
3875
|
+
: worktreeRecord?.devCommand && worktreeRecord.port !== undefined
|
|
3876
|
+
? {
|
|
3877
|
+
kind: 'dev-server',
|
|
3878
|
+
recipe: buildServeRecipeFromResolved(worktreeRecord.worktreePath, worktreeRecord.devCommand, worktreeRecord.port),
|
|
3879
|
+
}
|
|
3880
|
+
: {
|
|
3881
|
+
kind: 'dev-server',
|
|
3882
|
+
recipe: {
|
|
3883
|
+
cwd: '.',
|
|
3884
|
+
cmd: 'npm',
|
|
3885
|
+
argsTemplate: [
|
|
3886
|
+
'run',
|
|
3887
|
+
'dev',
|
|
3888
|
+
'--',
|
|
3889
|
+
'--port',
|
|
3890
|
+
'${PORT}',
|
|
3891
|
+
'--host',
|
|
3892
|
+
FRESH_DEV_SERVER_HOST,
|
|
3893
|
+
],
|
|
3894
|
+
envTemplate: { PORT: '${PORT}' },
|
|
3895
|
+
},
|
|
3896
|
+
};
|
|
3775
3897
|
try {
|
|
3776
3898
|
await this.variantHistory.persistVariant({
|
|
3777
3899
|
projectPath: historyProjectPath,
|
|
3778
3900
|
sessionId: args.sessionId,
|
|
3779
3901
|
variantId: args.workItemId,
|
|
3902
|
+
...(input.requestId ? { requestId: input.requestId } : {}),
|
|
3780
3903
|
label: input.briefLabel,
|
|
3781
3904
|
brief: input.briefBody,
|
|
3782
3905
|
sessionPrompt,
|
|
@@ -3788,6 +3911,8 @@ class AgentVariantsOrchestrator {
|
|
|
3788
3911
|
projectKind: 'fresh',
|
|
3789
3912
|
designMarkdown: designArtifact?.markdown,
|
|
3790
3913
|
designSource: designArtifact?.source,
|
|
3914
|
+
snapshotDir: sourceDir,
|
|
3915
|
+
serve,
|
|
3791
3916
|
});
|
|
3792
3917
|
}
|
|
3793
3918
|
finally {
|
|
@@ -3975,6 +4100,25 @@ class AgentVariantsOrchestrator {
|
|
|
3975
4100
|
* projects defer to the user's framework/packageManager config.
|
|
3976
4101
|
*/
|
|
3977
4102
|
async resolveDevServer(sessionId, workItemId, worktreePath, port, isFresh) {
|
|
4103
|
+
const resolved = await this.resolveDevServerCommand(sessionId, worktreePath, port, isFresh);
|
|
4104
|
+
if (!isFresh) {
|
|
4105
|
+
await this.ensureExistingProjectDependencies({
|
|
4106
|
+
sessionId,
|
|
4107
|
+
workItemId,
|
|
4108
|
+
cwd: resolved.cwd,
|
|
4109
|
+
packageManager: resolved.packageManager,
|
|
4110
|
+
});
|
|
4111
|
+
}
|
|
4112
|
+
return resolved;
|
|
4113
|
+
}
|
|
4114
|
+
/**
|
|
4115
|
+
* Pure invocation resolution — no dependency installs, no side effects.
|
|
4116
|
+
* Split from {@link resolveDevServer} so history persistence can capture
|
|
4117
|
+
* the SAME deterministic resolution the boot path uses without booting:
|
|
4118
|
+
* persist fires at code-gen success, before the dev server starts, so the
|
|
4119
|
+
* live record's stashed command usually isn't available yet.
|
|
4120
|
+
*/
|
|
4121
|
+
async resolveDevServerCommand(sessionId, worktreePath, port, isFresh) {
|
|
3978
4122
|
if (isFresh) {
|
|
3979
4123
|
return {
|
|
3980
4124
|
cwd: worktreePath,
|
|
@@ -3989,31 +4133,28 @@ class AgentVariantsOrchestrator {
|
|
|
3989
4133
|
FRESH_DEV_SERVER_HOST,
|
|
3990
4134
|
],
|
|
3991
4135
|
env: { PORT: String(port) },
|
|
4136
|
+
packageManager: 'npm',
|
|
3992
4137
|
};
|
|
3993
4138
|
}
|
|
3994
4139
|
const env = await this.resolveEnv(sessionId);
|
|
3995
4140
|
const cwd = await this.resolveExistingProjectCwd(sessionId, worktreePath, env);
|
|
3996
4141
|
const packageManager = detectPackageManagerForCwd(cwd, env.packageManager);
|
|
3997
|
-
await this.ensureExistingProjectDependencies({
|
|
3998
|
-
sessionId,
|
|
3999
|
-
workItemId,
|
|
4000
|
-
cwd,
|
|
4001
|
-
packageManager,
|
|
4002
|
-
});
|
|
4003
4142
|
if (packageManager !== env.packageManager) {
|
|
4004
4143
|
return {
|
|
4005
4144
|
cwd,
|
|
4145
|
+
packageManager,
|
|
4006
4146
|
...buildExistingProjectDevCommand(packageManager, env.devCommand, port),
|
|
4007
4147
|
};
|
|
4008
4148
|
}
|
|
4009
4149
|
if (env.buildDevCommand) {
|
|
4010
|
-
return { cwd, ...env.buildDevCommand(port) };
|
|
4150
|
+
return { cwd, packageManager, ...env.buildDevCommand(port) };
|
|
4011
4151
|
}
|
|
4012
4152
|
return {
|
|
4013
4153
|
cwd,
|
|
4014
4154
|
cmd: env.packageManager,
|
|
4015
4155
|
args: [env.devCommand, '--port', String(port)],
|
|
4016
4156
|
env: { PORT: String(port) },
|
|
4157
|
+
packageManager,
|
|
4017
4158
|
};
|
|
4018
4159
|
}
|
|
4019
4160
|
/**
|
|
@@ -4411,6 +4552,17 @@ class AgentVariantsOrchestrator {
|
|
|
4411
4552
|
return;
|
|
4412
4553
|
resources.cleanupStarted = true;
|
|
4413
4554
|
log.info(`Tearing down session ${sessionId} (reason: ${reason})`);
|
|
4555
|
+
// Drain in-flight history persists BEFORE deleting worktrees: a tree
|
|
4556
|
+
// snapshot's `git add -A --work-tree <worktree>` racing the deletion
|
|
4557
|
+
// below doesn't fail — it stages whatever files remain, publishing a
|
|
4558
|
+
// silently truncated snapshot. The design doc's ordering constraint
|
|
4559
|
+
// ("tree committed before worktree teardown") is enforced here, not
|
|
4560
|
+
// just in tests. Best-effort with a bound: never let a wedged git call
|
|
4561
|
+
// stall teardown forever.
|
|
4562
|
+
await Promise.race([
|
|
4563
|
+
this.settleHistoryPersists(),
|
|
4564
|
+
new Promise((resolve) => setTimeout(resolve, SETTLE_PERSISTS_TEARDOWN_TIMEOUT_MS)),
|
|
4565
|
+
]);
|
|
4414
4566
|
// Stop dev servers in parallel; ignore individual failures.
|
|
4415
4567
|
// NOTE: For the fresh vite_app rename path, commitVariant already stopped
|
|
4416
4568
|
// these dev servers BEFORE the rename (so Vite couldn't recreate `.vite/`
|
|
@@ -5472,6 +5624,25 @@ const detectPackageManagerForCwd = (cwd, fallback) => {
|
|
|
5472
5624
|
}
|
|
5473
5625
|
return 'npm';
|
|
5474
5626
|
};
|
|
5627
|
+
/**
|
|
5628
|
+
* Turn the invocation a live dev server actually booted with into a
|
|
5629
|
+
* port-parameterized replay recipe. The resolution bakes the allocated port
|
|
5630
|
+
* into args/env (`--port <n>`, `PORT=<n>`) — storing that verbatim would
|
|
5631
|
+
* bake in a dead port, so occurrences of the port (digit-boundary-guarded so
|
|
5632
|
+
* incidental digit runs survive) become `${PORT}` for replay to substitute.
|
|
5633
|
+
* `cwd` is stored relative to the snapshot root per the tree-root contract.
|
|
5634
|
+
*/
|
|
5635
|
+
const buildServeRecipeFromResolved = (snapshotRoot, dev, port) => {
|
|
5636
|
+
const portPattern = new RegExp(`(?<![0-9])${port}(?![0-9])`, 'g');
|
|
5637
|
+
const sub = (value) => value.replace(portPattern, '${PORT}');
|
|
5638
|
+
const relativeCwd = path_1.default.relative(snapshotRoot, dev.cwd);
|
|
5639
|
+
return {
|
|
5640
|
+
cwd: relativeCwd === '' ? '.' : relativeCwd,
|
|
5641
|
+
cmd: dev.cmd,
|
|
5642
|
+
argsTemplate: dev.args.map(sub),
|
|
5643
|
+
envTemplate: Object.fromEntries(Object.entries(dev.env).map(([key, value]) => [key, sub(value)])),
|
|
5644
|
+
};
|
|
5645
|
+
};
|
|
5475
5646
|
const buildExistingProjectDevCommand = (packageManager, devCommand, port) => {
|
|
5476
5647
|
const env = { PORT: String(port) };
|
|
5477
5648
|
if (packageManager === 'npm') {
|