rivet-design 0.27.0 → 0.28.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/dist/agent-variants/DirectionRefReservations.d.ts +11 -0
- package/dist/agent-variants/DirectionRefReservations.js +47 -0
- package/dist/agent-variants/PreviewRuntime.d.ts +4 -0
- package/dist/agent-variants/PreviewRuntime.js +5 -3
- package/dist/agent-variants/SessionStore.d.ts +10 -1
- package/dist/agent-variants/SessionStore.js +25 -2
- package/dist/agent-variants/WorkItemRequestTimes.d.ts +6 -0
- package/dist/agent-variants/WorkItemRequestTimes.js +21 -0
- package/dist/agent-variants/WorktreeOrchestrator.d.ts +2 -1
- package/dist/agent-variants/WorktreeOrchestrator.js +92 -78
- package/dist/agent-variants/contracts.d.ts +8 -0
- package/dist/agent-variants/existingStaticEntry.d.ts +34 -0
- package/dist/agent-variants/existingStaticEntry.js +136 -0
- package/dist/agent-variants/staticPreviewFiles.js +1 -1
- package/dist/agent-variants/variant-project-runtime.d.ts +2 -1
- package/dist/agent-variants/variantsTelemetry.d.ts +4 -0
- package/dist/agent-variants/variantsTelemetry.js +2 -0
- package/dist/agent-variants/workItemInput.d.ts +22 -0
- package/dist/agent-variants/workItemInput.js +12 -1
- package/dist/cli/commands/directionTarget.d.ts +23 -0
- package/dist/cli/commands/directionTarget.js +87 -0
- package/dist/cli/commands/open.js +28 -4
- package/dist/cli/commands/variants.js +36 -43
- package/dist/cli/envelope.d.ts +1 -1
- package/dist/cli/envelope.js +1 -0
- package/dist/cli/projectRuntimeUpgrade.d.ts +11 -0
- package/dist/cli/projectRuntimeUpgrade.js +43 -11
- package/dist/config/pluginMetrics.js +2 -0
- package/dist/config/posthog.d.ts +2 -0
- package/dist/config/posthog.js +5 -0
- package/dist/mcp/explorationSchema.js +1 -1
- package/dist/mcp/getExploration.js +11 -5
- package/dist/proxy-middleware/proxy-config.js +7 -0
- package/dist/routes/agentVariants.js +4 -0
- package/dist/routes/cli.js +10 -1
- package/dist/server.js +12 -6
- package/dist/services/DependencyPreparationService.js +44 -6
- package/dist/services/FeatureFlagService.js +2 -2
- package/dist/services/ProjectLibrary.d.ts +4 -1
- package/dist/services/ProjectLibrary.js +14 -9
- package/dist/services/ProjectRuntimeService.d.ts +8 -0
- package/dist/services/ProjectRuntimeService.js +15 -2
- package/dist/services/TelemetryService.d.ts +5 -0
- package/dist/services/TelemetryService.js +21 -2
- package/dist/services/VariantHistoryService.d.ts +8 -0
- package/dist/services/VariantHistoryService.js +40 -0
- package/dist/services/WorktreeManager.d.ts +1 -0
- package/dist/services/WorktreeManager.js +12 -0
- package/dist/services/createAgentVariantsOrchestrator.js +9 -2
- package/dist/services/directionRefs.d.ts +21 -0
- package/dist/services/directionRefs.js +148 -0
- package/dist/services/projectDirections.d.ts +22 -0
- package/dist/services/projectDirections.js +38 -0
- package/dist/types/direction-ref.d.ts +36 -0
- package/dist/types/direction-ref.js +3 -0
- package/dist/types/variant-history.d.ts +3 -1
- package/dist/utils/failureReason.d.ts +1 -1
- package/dist/utils/failureReason.js +3 -0
- package/dist/utils/skills/cli-guidance.js +4 -3
- package/dist/utils/subprocessEnvironment.d.ts +1 -1
- package/dist/utils/subprocessEnvironment.js +0 -1
- package/package.json +4 -4
- package/src/ui/dist/assets/LibraryEntry-BE8nZneH.js +37 -0
- package/src/ui/dist/assets/logo.png +0 -0
- package/src/ui/dist/assets/main-1EDrDqgn.js +498 -0
- package/src/ui/dist/assets/main-qgqnlUkI.css +1 -0
- package/src/ui/dist/assets/rivet-wordmark-orange-CYKVQDmG.svg +7 -0
- package/src/ui/dist/index.html +2 -2
- package/dist/services/StaticPreviewServer.d.ts +0 -8
- package/dist/services/StaticPreviewServer.js +0 -207
- package/src/ui/dist/assets/LibraryEntry-RI9Lc7P3.js +0 -37
- package/src/ui/dist/assets/main-D0UmAaUe.css +0 -1
- package/src/ui/dist/assets/main-DgrLzS5j.js +0 -497
- package/src/ui/dist/assets/rivet.svg +0 -3
- package/src/ui/dist/fonts/Goldman-Bold.woff2 +0 -0
- package/src/ui/dist/fonts/Goldman-Regular.woff2 +0 -0
|
@@ -8,6 +8,7 @@ const workItemContextFiles_1 = require("./workItemContextFiles");
|
|
|
8
8
|
const staticPreviewFiles_1 = require("./staticPreviewFiles");
|
|
9
9
|
const workItemPreviewRoutes_1 = require("./workItemPreviewRoutes");
|
|
10
10
|
const staticPreviewRefinements_1 = require("./staticPreviewRefinements");
|
|
11
|
+
const WorkItemRequestTimes_1 = require("./WorkItemRequestTimes");
|
|
11
12
|
const crypto_1 = require("crypto");
|
|
12
13
|
const events_1 = require("events");
|
|
13
14
|
const fs_1 = __importDefault(require("fs"));
|
|
@@ -20,6 +21,7 @@ const workItemBriefing_1 = require("./workItemBriefing");
|
|
|
20
21
|
const briefContent_1 = require("./briefContent");
|
|
21
22
|
const runLabel_1 = require("./runLabel");
|
|
22
23
|
const previewQa_1 = require("./previewQa");
|
|
24
|
+
const workItemInput_1 = require("./workItemInput");
|
|
23
25
|
const WorkspaceInventory_1 = require("./WorkspaceInventory");
|
|
24
26
|
const WorkspaceProvisioning_1 = require("./WorkspaceProvisioning");
|
|
25
27
|
const PreviewRuntime_1 = require("./PreviewRuntime");
|
|
@@ -31,6 +33,7 @@ const variantsTelemetry_1 = require("./variantsTelemetry");
|
|
|
31
33
|
const variantWorkspaceFiles_1 = require("./variantWorkspaceFiles");
|
|
32
34
|
const errorMessage_1 = require("../utils/errorMessage");
|
|
33
35
|
const pathContainment_1 = require("../utils/pathContainment");
|
|
36
|
+
const existingStaticEntry_1 = require("./existingStaticEntry");
|
|
34
37
|
var variantWorkspaceFiles_2 = require("./variantWorkspaceFiles");
|
|
35
38
|
Object.defineProperty(exports, "buildStaticPreviewDocument", { enumerable: true, get: function () { return variantWorkspaceFiles_2.buildStaticPreviewDocument; } });
|
|
36
39
|
const log = (0, logger_1.createLogger)('AgentVariantsOrchestrator');
|
|
@@ -426,6 +429,7 @@ class AgentVariantsOrchestrator {
|
|
|
426
429
|
leaseExpiresAt: item.leaseExpiresAt,
|
|
427
430
|
workspace,
|
|
428
431
|
mode,
|
|
432
|
+
...(0, workItemInput_1.shownDirectionRef)(input),
|
|
429
433
|
direction: {
|
|
430
434
|
label: input.briefLabel ?? 'Variant',
|
|
431
435
|
brief: input.briefBody ?? input.instruction ?? 'Create this variant',
|
|
@@ -487,6 +491,7 @@ class AgentVariantsOrchestrator {
|
|
|
487
491
|
resources.currentRoundStartedAt = startedAt;
|
|
488
492
|
resources.currentRoundMode = args.mode;
|
|
489
493
|
resources.currentRoundWorkItemIds = workItemIds;
|
|
494
|
+
resources.requestTimes.record(workItemIds ?? [], startedAt);
|
|
490
495
|
const projectContext = this.store.getProjectContext(args.sessionId);
|
|
491
496
|
this.telemetry.trackAgentVariantsRoundStarted?.({
|
|
492
497
|
sessionId: args.sessionId,
|
|
@@ -565,6 +570,7 @@ class AgentVariantsOrchestrator {
|
|
|
565
570
|
const workItemIds = [...args.workItemIds];
|
|
566
571
|
round.workItemIds = workItemIds;
|
|
567
572
|
resources.currentRoundWorkItemIds = workItemIds;
|
|
573
|
+
resources.requestTimes.record(workItemIds, round.startedAt);
|
|
568
574
|
this.completeTerminalVariantsRounds(args.sessionId);
|
|
569
575
|
}
|
|
570
576
|
completeTerminalVariantsRounds(sessionId) {
|
|
@@ -646,6 +652,8 @@ class AgentVariantsOrchestrator {
|
|
|
646
652
|
};
|
|
647
653
|
}
|
|
648
654
|
trackRefinementLeased(args) {
|
|
655
|
+
const requestTimes = this.resources.get(args.sessionId)?.requestTimes;
|
|
656
|
+
const leasedAt = Date.now();
|
|
649
657
|
for (const item of args.lease.leasedWorkItems) {
|
|
650
658
|
const telemetry = this.refinementTelemetryForWorkItem({
|
|
651
659
|
sessionId: args.sessionId,
|
|
@@ -657,6 +665,7 @@ class AgentVariantsOrchestrator {
|
|
|
657
665
|
this.telemetry.trackAgentVariantsRefinementLeased?.({
|
|
658
666
|
...telemetry,
|
|
659
667
|
leaseDurationMs: args.lease.leaseTtlMs,
|
|
668
|
+
queueWaitMs: requestTimes?.elapsedSinceRequestMs(item.id, leasedAt) ?? undefined,
|
|
660
669
|
workItemCount: 1,
|
|
661
670
|
});
|
|
662
671
|
}
|
|
@@ -788,13 +797,16 @@ class AgentVariantsOrchestrator {
|
|
|
788
797
|
}
|
|
789
798
|
}
|
|
790
799
|
beginStaticPreviewRefinements(args) {
|
|
791
|
-
|
|
800
|
+
const result = (0, staticPreviewRefinements_1.createStaticPreviewRefinements)({
|
|
792
801
|
request: args,
|
|
793
802
|
store: this.store,
|
|
794
803
|
telemetry: this.telemetry,
|
|
795
804
|
getStaticPreviewHtml: (sessionId, workItemId) => this.getStaticPreviewHtml(sessionId, workItemId),
|
|
796
805
|
emitChange: () => this.emitChange(),
|
|
797
806
|
});
|
|
807
|
+
const requestTimes = this.resources.get(args.sessionId)?.requestTimes;
|
|
808
|
+
requestTimes?.record(result.createdWorkItemIds, Date.now());
|
|
809
|
+
return result;
|
|
798
810
|
}
|
|
799
811
|
async adoptPastVariant(args) {
|
|
800
812
|
const { assetBase, entryPath, hasAssets } = await (0, staticPreviewFiles_1.resolveStaticPreviewFiles)({
|
|
@@ -810,6 +822,7 @@ class AgentVariantsOrchestrator {
|
|
|
810
822
|
references: args.references,
|
|
811
823
|
previewRoutes: args.previewRoutes,
|
|
812
824
|
runLabel: args.runLabel,
|
|
825
|
+
sourceDirectionRef: args.directionRef,
|
|
813
826
|
});
|
|
814
827
|
this.telemetry.trackAgentVariantsRequestStarted?.({
|
|
815
828
|
sessionId: args.sessionId,
|
|
@@ -859,6 +872,7 @@ class AgentVariantsOrchestrator {
|
|
|
859
872
|
references: args.references,
|
|
860
873
|
previewRoutes: args.previewRoutes,
|
|
861
874
|
runLabel: args.runLabel,
|
|
875
|
+
directionRef: args.directionRef,
|
|
862
876
|
});
|
|
863
877
|
return {
|
|
864
878
|
sessionId: usableSessionId,
|
|
@@ -880,6 +894,7 @@ class AgentVariantsOrchestrator {
|
|
|
880
894
|
references: args.references,
|
|
881
895
|
previewRoutes: args.previewRoutes,
|
|
882
896
|
runLabel: args.runLabel,
|
|
897
|
+
sourceDirectionRef: args.directionRef,
|
|
883
898
|
projectContext: args.projectContext,
|
|
884
899
|
});
|
|
885
900
|
this.activeSessionId = created.sessionId;
|
|
@@ -1548,6 +1563,8 @@ class AgentVariantsOrchestrator {
|
|
|
1548
1563
|
const durationMs = leasedAt !== undefined ? Date.now() - leasedAt : null;
|
|
1549
1564
|
const approveStartedAt = resources?.approveStartedAt;
|
|
1550
1565
|
const approveToCompleteMs = approveStartedAt !== undefined ? Date.now() - approveStartedAt : null;
|
|
1566
|
+
const requestTimes = resources?.requestTimes;
|
|
1567
|
+
const elapsedSinceRequestMs = (at) => requestTimes?.elapsedSinceRequestMs(args.workItemId, at) ?? null;
|
|
1551
1568
|
const outputBytes = (0, variantWorkspaceFiles_1.estimateOutputBytes)(effectiveArgs.output);
|
|
1552
1569
|
const projectContextKind = this.store.getProjectContext(args.sessionId).kind;
|
|
1553
1570
|
const mode = workItemKind !== undefined && isImplementationWorkItemKind(workItemKind)
|
|
@@ -1563,6 +1580,8 @@ class AgentVariantsOrchestrator {
|
|
|
1563
1580
|
attempt: args.attempt,
|
|
1564
1581
|
durationMs,
|
|
1565
1582
|
approveToCompleteMs,
|
|
1583
|
+
requestToCompleteMs: elapsedSinceRequestMs(Date.now()),
|
|
1584
|
+
queueWaitMs: elapsedSinceRequestMs(leasedAt),
|
|
1566
1585
|
kind: workItemKind ?? null,
|
|
1567
1586
|
mode,
|
|
1568
1587
|
leaseToReportMs: leasedAt !== undefined ? reportReceivedAt - leasedAt : null,
|
|
@@ -2094,12 +2113,24 @@ class AgentVariantsOrchestrator {
|
|
|
2094
2113
|
catch (err) {
|
|
2095
2114
|
log.warn(`getDiff failed for ${record.worktreePath}`, err);
|
|
2096
2115
|
}
|
|
2116
|
+
const staticEntryResolution = isFresh
|
|
2117
|
+
? Promise.resolve(undefined)
|
|
2118
|
+
: (0, existingStaticEntry_1.resolveExistingStaticPreviewEntry)({
|
|
2119
|
+
sessionId,
|
|
2120
|
+
record,
|
|
2121
|
+
resolveEnv: this.resolveEnv,
|
|
2122
|
+
worktrees: this.worktrees,
|
|
2123
|
+
telemetry: this.telemetry,
|
|
2124
|
+
});
|
|
2097
2125
|
if (!isFresh) {
|
|
2098
|
-
this.trackHistoryPersist(
|
|
2126
|
+
this.trackHistoryPersist(staticEntryResolution
|
|
2127
|
+
.then((staticEntry) => this.persistCompletedExistingVariant({
|
|
2099
2128
|
sessionId,
|
|
2100
2129
|
workItemId,
|
|
2101
2130
|
diff: record.diff ?? '',
|
|
2102
|
-
|
|
2131
|
+
staticEntry,
|
|
2132
|
+
}))
|
|
2133
|
+
.catch((err) => {
|
|
2103
2134
|
log.warn(`persistCompletedExistingVariant failed for ${sessionId}/${workItemId}`, err);
|
|
2104
2135
|
}));
|
|
2105
2136
|
}
|
|
@@ -2111,12 +2142,11 @@ class AgentVariantsOrchestrator {
|
|
|
2111
2142
|
log.warn(`persistCompletedArtifactVariant failed for ${sessionId}/${workItemId}`, err);
|
|
2112
2143
|
}));
|
|
2113
2144
|
}
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
}
|
|
2145
|
+
const staticEntry = await staticEntryResolution;
|
|
2146
|
+
if (staticEntry) {
|
|
2147
|
+
await this.registerExistingStaticPreview(sessionId, workItemId, staticEntry);
|
|
2148
|
+
this.emitChange();
|
|
2149
|
+
return;
|
|
2120
2150
|
}
|
|
2121
2151
|
await this.previewRuntime.startVariant({
|
|
2122
2152
|
sessionId,
|
|
@@ -2224,6 +2254,12 @@ class AgentVariantsOrchestrator {
|
|
|
2224
2254
|
await Promise.allSettled([...this.pendingHistoryPersists]);
|
|
2225
2255
|
}
|
|
2226
2256
|
}
|
|
2257
|
+
loadDirectionRefs() {
|
|
2258
|
+
return this.store.directionRefs.load({
|
|
2259
|
+
projectPath: this.getProjectPath(),
|
|
2260
|
+
history: this.variantHistory,
|
|
2261
|
+
});
|
|
2262
|
+
}
|
|
2227
2263
|
async getSavedVariant(args) {
|
|
2228
2264
|
const saved = await this.variantHistory.getVariant(args);
|
|
2229
2265
|
if (saved)
|
|
@@ -2297,16 +2333,9 @@ class AgentVariantsOrchestrator {
|
|
|
2297
2333
|
return;
|
|
2298
2334
|
}
|
|
2299
2335
|
const record = this.workspaceInventory.getWorktree(args.sessionId, args.workItemId);
|
|
2300
|
-
|
|
2301
|
-
const
|
|
2302
|
-
|
|
2303
|
-
try {
|
|
2304
|
-
sourceDir = await this.worktrees.getProjectCwdInWorktree(record.worktreePath);
|
|
2305
|
-
}
|
|
2306
|
-
catch (err) {
|
|
2307
|
-
log.warn(`persistCompletedExistingVariant: static snapshot path failed for ${args.sessionId}/${args.workItemId}`, err);
|
|
2308
|
-
}
|
|
2309
|
-
}
|
|
2336
|
+
const staticSource = args.staticEntry?.kind === 'found' ? args.staticEntry : undefined;
|
|
2337
|
+
const sourceDir = staticSource?.projectDirectory;
|
|
2338
|
+
const staticEntryPath = staticSource?.entryPath;
|
|
2310
2339
|
const input = this.store.requireVariantWorkItemInput({
|
|
2311
2340
|
sessionId: args.sessionId,
|
|
2312
2341
|
workItemId: args.workItemId,
|
|
@@ -2333,7 +2362,7 @@ class AgentVariantsOrchestrator {
|
|
|
2333
2362
|
recipe: (0, variantWorkspaceFiles_1.buildServeRecipeFromResolved)(record.worktreePath, runningPreview.command, runningPreview.port),
|
|
2334
2363
|
};
|
|
2335
2364
|
}
|
|
2336
|
-
else if (record) {
|
|
2365
|
+
else if (record && env.framework !== 'static') {
|
|
2337
2366
|
try {
|
|
2338
2367
|
const dev = await this.previewRuntime.resolveCommand(args.sessionId, record.worktreePath, RECIPE_PORT_SENTINEL, false);
|
|
2339
2368
|
serve = {
|
|
@@ -2350,6 +2379,7 @@ class AgentVariantsOrchestrator {
|
|
|
2350
2379
|
sessionId: args.sessionId,
|
|
2351
2380
|
variantId: args.workItemId,
|
|
2352
2381
|
...(input.requestId ? { requestId: input.requestId } : {}),
|
|
2382
|
+
directionRef: this.store.claimDirectionRef(args),
|
|
2353
2383
|
label: input.briefLabel,
|
|
2354
2384
|
brief: input.briefBody,
|
|
2355
2385
|
references: input.references,
|
|
@@ -2380,92 +2410,74 @@ class AgentVariantsOrchestrator {
|
|
|
2380
2410
|
: {}),
|
|
2381
2411
|
});
|
|
2382
2412
|
}
|
|
2383
|
-
async registerExistingStaticPreview(sessionId, workItemId,
|
|
2384
|
-
let env;
|
|
2385
|
-
try {
|
|
2386
|
-
env = await this.resolveEnv(sessionId);
|
|
2387
|
-
}
|
|
2388
|
-
catch (err) {
|
|
2389
|
-
log.warn(`registerExistingStaticPreview: resolveEnv failed for ${sessionId}`, err);
|
|
2390
|
-
return 'not_static';
|
|
2391
|
-
}
|
|
2392
|
-
if (env.framework !== 'static')
|
|
2393
|
-
return 'not_static';
|
|
2394
|
-
const previewStartedAt = Date.now();
|
|
2395
|
-
(0, variantsTelemetry_1.trackPreviewStarted)(this.telemetry, {
|
|
2396
|
-
sessionId,
|
|
2397
|
-
variantId: workItemId,
|
|
2398
|
-
projectContextKind: 'existing',
|
|
2399
|
-
previewKind: 'static_artifact',
|
|
2400
|
-
});
|
|
2413
|
+
async registerExistingStaticPreview(sessionId, workItemId, entry) {
|
|
2401
2414
|
const resources = this.resources.get(sessionId);
|
|
2402
2415
|
if (!resources)
|
|
2403
|
-
return
|
|
2416
|
+
return;
|
|
2404
2417
|
const input = this.store.getVariantWorkItemInput(sessionId, workItemId);
|
|
2405
2418
|
if (!input?.briefId)
|
|
2406
|
-
return
|
|
2407
|
-
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
|
-
|
|
2411
|
-
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
|
|
2419
|
-
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
sessionId,
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
}
|
|
2434
|
-
return 'unavailable';
|
|
2419
|
+
return;
|
|
2420
|
+
switch (entry.kind) {
|
|
2421
|
+
case 'unresolved':
|
|
2422
|
+
return;
|
|
2423
|
+
case 'missing':
|
|
2424
|
+
log.warn(`registerExistingStaticPreview: no entry page (${entry.source}) for ${sessionId}/${workItemId}; preview unavailable`);
|
|
2425
|
+
(0, variantsTelemetry_1.trackPreviewFailed)(this.telemetry, {
|
|
2426
|
+
sessionId,
|
|
2427
|
+
variantId: workItemId,
|
|
2428
|
+
projectContextKind: 'existing',
|
|
2429
|
+
previewKind: 'static_artifact',
|
|
2430
|
+
errorCode: 'STATIC_PREVIEW_ENTRY_MISSING',
|
|
2431
|
+
reason: 'missing_static_entry',
|
|
2432
|
+
durationMs: Date.now() - entry.startedAt,
|
|
2433
|
+
staticEntrySource: entry.source,
|
|
2434
|
+
});
|
|
2435
|
+
this.previewRuntime.setFailure(sessionId, workItemId, {
|
|
2436
|
+
reason: 'missing_static_entry',
|
|
2437
|
+
portInUse: false,
|
|
2438
|
+
detail: entry.detail,
|
|
2439
|
+
});
|
|
2440
|
+
return;
|
|
2441
|
+
case 'found':
|
|
2442
|
+
break;
|
|
2443
|
+
default: {
|
|
2444
|
+
const unhandled = entry;
|
|
2445
|
+
throw new Error(`Unhandled static entry ${JSON.stringify(unhandled)}`);
|
|
2446
|
+
}
|
|
2435
2447
|
}
|
|
2436
2448
|
let dir;
|
|
2437
2449
|
try {
|
|
2438
|
-
dir = fs_1.default.realpathSync(
|
|
2450
|
+
dir = fs_1.default.realpathSync(entry.projectDirectory);
|
|
2439
2451
|
}
|
|
2440
2452
|
catch {
|
|
2441
|
-
dir =
|
|
2453
|
+
dir = entry.projectDirectory;
|
|
2442
2454
|
}
|
|
2443
2455
|
let siteFallbackBase;
|
|
2444
2456
|
try {
|
|
2445
|
-
const hostRealRoot = fs_1.default.realpathSync(
|
|
2457
|
+
const hostRealRoot = fs_1.default.realpathSync(entry.hostProjectPath);
|
|
2446
2458
|
if (hostRealRoot !== dir)
|
|
2447
|
-
siteFallbackBase = path_1.default.join(hostRealRoot, path_1.default.dirname(
|
|
2459
|
+
siteFallbackBase = path_1.default.join(hostRealRoot, path_1.default.dirname(entry.entryPath));
|
|
2448
2460
|
}
|
|
2449
2461
|
catch { }
|
|
2450
2462
|
this.workspaceInventory.setStaticPreview(sessionId, {
|
|
2451
2463
|
workItemId,
|
|
2452
2464
|
briefId: input.briefId,
|
|
2453
|
-
entryPath: path_1.default.basename(
|
|
2454
|
-
assetBase: path_1.default.dirname(path_1.default.join(dir,
|
|
2465
|
+
entryPath: path_1.default.basename(entry.entryPath),
|
|
2466
|
+
assetBase: path_1.default.dirname(path_1.default.join(dir, entry.entryPath)),
|
|
2455
2467
|
hasAssets: true,
|
|
2456
2468
|
...(siteFallbackBase ? { assetFallbackBase: siteFallbackBase } : {}),
|
|
2457
2469
|
});
|
|
2458
2470
|
this.previewRuntime.clearFailure(sessionId, workItemId);
|
|
2459
|
-
log.info(`Variant ${workItemId} served as a static preview (existing/static, no dev server; root ${
|
|
2471
|
+
log.info(`Variant ${workItemId} served as a static preview (existing/static, no dev server; root ${entry.projectDirectory})`);
|
|
2460
2472
|
(0, variantsTelemetry_1.trackPreviewReady)(this.telemetry, {
|
|
2461
2473
|
sessionId,
|
|
2462
2474
|
variantId: workItemId,
|
|
2463
2475
|
projectContextKind: 'existing',
|
|
2464
2476
|
previewKind: 'static_artifact',
|
|
2465
2477
|
hasPort: false,
|
|
2466
|
-
durationMs: Date.now() -
|
|
2478
|
+
durationMs: Date.now() - entry.startedAt,
|
|
2479
|
+
staticEntrySource: entry.source,
|
|
2467
2480
|
});
|
|
2468
|
-
return 'registered';
|
|
2469
2481
|
}
|
|
2470
2482
|
async prepareArtifactBase(sessionId) {
|
|
2471
2483
|
const { projectPath } = await this.resolveEnv(sessionId);
|
|
@@ -2478,7 +2490,7 @@ class AgentVariantsOrchestrator {
|
|
|
2478
2490
|
async createArtifactDiff(args) {
|
|
2479
2491
|
const base = await this.prepareArtifactBase(args.sessionId);
|
|
2480
2492
|
const env = await this.resolveEnv(args.sessionId);
|
|
2481
|
-
const entryPath = env.framework === 'static'
|
|
2493
|
+
const entryPath = (env.framework === 'static' && env.entryPath) || 'index.html';
|
|
2482
2494
|
const files = (0, staticPreviewFiles_1.prepareStaticPreviewProjectFiles)({
|
|
2483
2495
|
sourceDir: args.sourceDir,
|
|
2484
2496
|
entryPath,
|
|
@@ -2598,6 +2610,7 @@ class AgentVariantsOrchestrator {
|
|
|
2598
2610
|
sessionId: args.sessionId,
|
|
2599
2611
|
variantId: args.workItemId,
|
|
2600
2612
|
...(input.requestId ? { requestId: input.requestId } : {}),
|
|
2613
|
+
directionRef: this.store.claimDirectionRef(args),
|
|
2601
2614
|
label: input.briefLabel,
|
|
2602
2615
|
brief: input.briefBody ?? '',
|
|
2603
2616
|
references: input.references,
|
|
@@ -2746,6 +2759,7 @@ class AgentVariantsOrchestrator {
|
|
|
2746
2759
|
startedAt: Date.now(),
|
|
2747
2760
|
nextRoundIndex: 0,
|
|
2748
2761
|
rounds: new Map(),
|
|
2762
|
+
requestTimes: new WorkItemRequestTimes_1.WorkItemRequestTimes(),
|
|
2749
2763
|
leasedAt: new Map(),
|
|
2750
2764
|
qaResults: new Map(),
|
|
2751
2765
|
qaRegenRetried: new Set(),
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import type { GuidanceDocument } from '../types/guidance';
|
|
2
2
|
import type { WorkerSelection } from '../types/change-request-types';
|
|
3
|
+
import type { DirectionRef } from '../types/direction-ref';
|
|
4
|
+
import type { FailureReasonCode } from '../utils/failureReason';
|
|
3
5
|
import { type VariantReference } from '../types/variant-reference';
|
|
4
6
|
import { z } from 'zod/v3';
|
|
5
7
|
import { ERROR_CODES, type ErrorCode } from './errors';
|
|
@@ -6343,6 +6345,7 @@ export interface SavedVariantPreview {
|
|
|
6343
6345
|
references?: VariantReference[];
|
|
6344
6346
|
previewRoutes?: string[];
|
|
6345
6347
|
runLabel?: string;
|
|
6348
|
+
directionRef?: DirectionRef;
|
|
6346
6349
|
}
|
|
6347
6350
|
export interface AdoptPastVariantArgs extends SavedVariantPreview {
|
|
6348
6351
|
sessionId: string;
|
|
@@ -6361,6 +6364,7 @@ export interface ActiveVariantSnapshot {
|
|
|
6361
6364
|
previewRoutes?: string[];
|
|
6362
6365
|
workItemId: string;
|
|
6363
6366
|
briefId: string;
|
|
6367
|
+
directionRef?: DirectionRef;
|
|
6364
6368
|
label: string;
|
|
6365
6369
|
status: WorkItemStatus;
|
|
6366
6370
|
workItemKind?: 'code_gen' | 'static_preview';
|
|
@@ -6384,6 +6388,9 @@ export interface ActiveVariantSnapshot {
|
|
|
6384
6388
|
reason: 'spawn_error' | 'exited' | 'timeout' | 'compile_error' | 'dependency_install_failed' | 'missing_dev_script' | 'missing_static_entry' | 'idle_timeout' | 'unknown';
|
|
6385
6389
|
portInUse?: boolean;
|
|
6386
6390
|
detail?: string;
|
|
6391
|
+
reasonCode?: FailureReasonCode;
|
|
6392
|
+
reasonDetail?: string;
|
|
6393
|
+
nodeVersion?: string;
|
|
6387
6394
|
};
|
|
6388
6395
|
actions?: ActiveVariantActions;
|
|
6389
6396
|
refinement?: {
|
|
@@ -6443,6 +6450,7 @@ export interface HostVariantImplementationWorkItemSnapshot extends HostVariantWo
|
|
|
6443
6450
|
kind: 'static_preview' | 'refine_variant' | 'code_gen';
|
|
6444
6451
|
workspace: VariantAssignedWorkspace;
|
|
6445
6452
|
mode: VariantExecutionMode;
|
|
6453
|
+
directionRef?: DirectionRef;
|
|
6446
6454
|
direction: VariantWorkerDirection;
|
|
6447
6455
|
fidelity?: WorkerFidelity;
|
|
6448
6456
|
sourceDirection?: VariantWorkerDirection;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { WorktreeRecord } from './WorkspaceInventory';
|
|
2
|
+
import type { ProjectEnvironment, WorktreeManagerLike } from './variant-project-runtime';
|
|
3
|
+
import { type VariantsTelemetry } from './variantsTelemetry';
|
|
4
|
+
export type ExistingStaticEntrySource = 'configured' | 'root_page' | 'changed_page';
|
|
5
|
+
export type ExistingStaticEntry = {
|
|
6
|
+
kind: 'found';
|
|
7
|
+
entryPath: string;
|
|
8
|
+
source: ExistingStaticEntrySource;
|
|
9
|
+
} | {
|
|
10
|
+
kind: 'missing';
|
|
11
|
+
detail: string;
|
|
12
|
+
source: 'configured' | 'none';
|
|
13
|
+
};
|
|
14
|
+
export type ExistingStaticPreviewEntry = {
|
|
15
|
+
kind: 'unresolved';
|
|
16
|
+
} | (ExistingStaticEntry & {
|
|
17
|
+
hostProjectPath: string;
|
|
18
|
+
projectDirectory: string;
|
|
19
|
+
startedAt: number;
|
|
20
|
+
});
|
|
21
|
+
export declare const resolveExistingStaticEntry: (args: {
|
|
22
|
+
worktreePath: string;
|
|
23
|
+
projectDirectory: string;
|
|
24
|
+
configuredEntryPath: string | undefined;
|
|
25
|
+
changedFiles: string[];
|
|
26
|
+
}) => Promise<ExistingStaticEntry>;
|
|
27
|
+
export declare const resolveExistingStaticPreviewEntry: (args: {
|
|
28
|
+
sessionId: string;
|
|
29
|
+
record: WorktreeRecord;
|
|
30
|
+
resolveEnv: (sessionId: string) => Promise<ProjectEnvironment>;
|
|
31
|
+
worktrees: WorktreeManagerLike;
|
|
32
|
+
telemetry: VariantsTelemetry;
|
|
33
|
+
}) => Promise<ExistingStaticPreviewEntry | undefined>;
|
|
34
|
+
//# sourceMappingURL=existingStaticEntry.d.ts.map
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.resolveExistingStaticPreviewEntry = exports.resolveExistingStaticEntry = void 0;
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const staticProjectTarget_1 = require("../services/staticProjectTarget");
|
|
10
|
+
const pathContainment_1 = require("../utils/pathContainment");
|
|
11
|
+
const logger_1 = require("../utils/logger");
|
|
12
|
+
const variantsTelemetry_1 = require("./variantsTelemetry");
|
|
13
|
+
const log = (0, logger_1.createLogger)('ExistingStaticEntry');
|
|
14
|
+
const INDEX_PAGE = 'index.html';
|
|
15
|
+
const MISSING_PAGE_DETAIL = "This project has no index.html or package.json at its root, and this direction didn't add or change an HTML page. " +
|
|
16
|
+
"Run rivet open on the folder that contains your app's package.json or index.html, or pass --entry <page.html>.";
|
|
17
|
+
const missingConfiguredEntryDetail = (entryPath) => `${entryPath} isn't in this direction's copy of the project. Directions start from committed and untracked files; ` +
|
|
18
|
+
`git-ignored files are left out. Commit ${entryPath} or remove it from .gitignore, then generate the direction again.`;
|
|
19
|
+
const isPageInsideWorktree = async (worktreePath, pagePath) => {
|
|
20
|
+
const realPage = await (0, pathContainment_1.resolveRealPathWithinRoot)({
|
|
21
|
+
root: worktreePath,
|
|
22
|
+
candidate: pagePath,
|
|
23
|
+
containment: 'strict',
|
|
24
|
+
});
|
|
25
|
+
if (!realPage)
|
|
26
|
+
return false;
|
|
27
|
+
try {
|
|
28
|
+
await fs_1.default.promises.access(realPage, fs_1.default.constants.R_OK);
|
|
29
|
+
return (await fs_1.default.promises.stat(realPage)).isFile();
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
const pageDepth = (pagePath) => pagePath.split('/').length;
|
|
36
|
+
const isIndexPage = (pagePath) => path_1.default.posix.basename(pagePath).toLowerCase() === INDEX_PAGE;
|
|
37
|
+
const comparePreviewPages = (left, right) => pageDepth(left) - pageDepth(right) ||
|
|
38
|
+
Number(isIndexPage(right)) - Number(isIndexPage(left)) ||
|
|
39
|
+
left.localeCompare(right);
|
|
40
|
+
const findRootPage = (projectDirectory) => {
|
|
41
|
+
try {
|
|
42
|
+
return (0, staticProjectTarget_1.resolveStaticProjectTarget)({ targetPath: projectDirectory })
|
|
43
|
+
.entryPath;
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
return undefined;
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
const toProjectPagePaths = (args) => args.changedFiles
|
|
50
|
+
.map((changedFile) => path_1.default.join(args.worktreePath, changedFile))
|
|
51
|
+
.filter((changedPath) => (0, pathContainment_1.isPathStrictlyInsideRoot)(args.projectDirectory, changedPath) &&
|
|
52
|
+
(0, staticProjectTarget_1.isStaticHtmlFilePath)(changedPath))
|
|
53
|
+
.map((changedPath) => path_1.default
|
|
54
|
+
.relative(args.projectDirectory, changedPath)
|
|
55
|
+
.split(path_1.default.sep)
|
|
56
|
+
.join('/'))
|
|
57
|
+
.sort(comparePreviewPages);
|
|
58
|
+
const resolveExistingStaticEntry = async (args) => {
|
|
59
|
+
const isProjectPage = (entryPath) => isPageInsideWorktree(args.worktreePath, path_1.default.join(args.projectDirectory, entryPath));
|
|
60
|
+
if (args.configuredEntryPath) {
|
|
61
|
+
return (await isProjectPage(args.configuredEntryPath))
|
|
62
|
+
? {
|
|
63
|
+
kind: 'found',
|
|
64
|
+
entryPath: args.configuredEntryPath,
|
|
65
|
+
source: 'configured',
|
|
66
|
+
}
|
|
67
|
+
: {
|
|
68
|
+
kind: 'missing',
|
|
69
|
+
detail: missingConfiguredEntryDetail(args.configuredEntryPath),
|
|
70
|
+
source: 'configured',
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
const rootPage = findRootPage(args.projectDirectory);
|
|
74
|
+
if (rootPage && (await isProjectPage(rootPage))) {
|
|
75
|
+
return { kind: 'found', entryPath: rootPage, source: 'root_page' };
|
|
76
|
+
}
|
|
77
|
+
for (const changedPage of toProjectPagePaths(args)) {
|
|
78
|
+
if (await isProjectPage(changedPage)) {
|
|
79
|
+
return { kind: 'found', entryPath: changedPage, source: 'changed_page' };
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return { kind: 'missing', detail: MISSING_PAGE_DETAIL, source: 'none' };
|
|
83
|
+
};
|
|
84
|
+
exports.resolveExistingStaticEntry = resolveExistingStaticEntry;
|
|
85
|
+
const resolveExistingStaticPreviewEntry = async (args) => {
|
|
86
|
+
const { sessionId, record } = args;
|
|
87
|
+
let env;
|
|
88
|
+
try {
|
|
89
|
+
env = await args.resolveEnv(sessionId);
|
|
90
|
+
}
|
|
91
|
+
catch (err) {
|
|
92
|
+
log.warn(`resolveEnv failed for ${sessionId}`, err);
|
|
93
|
+
return undefined;
|
|
94
|
+
}
|
|
95
|
+
if (env.framework !== 'static')
|
|
96
|
+
return undefined;
|
|
97
|
+
const startedAt = Date.now();
|
|
98
|
+
(0, variantsTelemetry_1.trackPreviewStarted)(args.telemetry, {
|
|
99
|
+
sessionId,
|
|
100
|
+
variantId: record.workItemId,
|
|
101
|
+
projectContextKind: 'existing',
|
|
102
|
+
previewKind: 'static_artifact',
|
|
103
|
+
});
|
|
104
|
+
let projectDirectory;
|
|
105
|
+
try {
|
|
106
|
+
projectDirectory = await args.worktrees.getProjectCwdInWorktree(record.worktreePath);
|
|
107
|
+
}
|
|
108
|
+
catch (err) {
|
|
109
|
+
log.warn(`project cwd failed for ${sessionId}/${record.workItemId}`, err);
|
|
110
|
+
return { kind: 'unresolved' };
|
|
111
|
+
}
|
|
112
|
+
let changedFiles = [];
|
|
113
|
+
if (!env.entryPath) {
|
|
114
|
+
try {
|
|
115
|
+
changedFiles =
|
|
116
|
+
(await args.worktrees.getChangedFiles?.(record.worktreePath)) ?? [];
|
|
117
|
+
}
|
|
118
|
+
catch (err) {
|
|
119
|
+
log.warn(`changed files unavailable for ${sessionId}/${record.workItemId}`, err);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
const entry = await (0, exports.resolveExistingStaticEntry)({
|
|
123
|
+
worktreePath: record.worktreePath,
|
|
124
|
+
projectDirectory,
|
|
125
|
+
configuredEntryPath: env.entryPath,
|
|
126
|
+
changedFiles,
|
|
127
|
+
});
|
|
128
|
+
return {
|
|
129
|
+
...entry,
|
|
130
|
+
hostProjectPath: env.projectPath,
|
|
131
|
+
projectDirectory,
|
|
132
|
+
startedAt,
|
|
133
|
+
};
|
|
134
|
+
};
|
|
135
|
+
exports.resolveExistingStaticPreviewEntry = resolveExistingStaticPreviewEntry;
|
|
136
|
+
//# sourceMappingURL=existingStaticEntry.js.map
|
|
@@ -33,7 +33,7 @@ const prepareStaticPreviewProjectFiles = ({ sourceDir, entryPath, isWebsite, })
|
|
|
33
33
|
exports.prepareStaticPreviewProjectFiles = prepareStaticPreviewProjectFiles;
|
|
34
34
|
const stageStaticPreviewFiles = ({ preview, workItemId, environment, isWebsite, briefMarkdown, }) => {
|
|
35
35
|
const rootPath = fs_1.default.mkdtempSync(path_1.default.join(os_1.default.tmpdir(), `rivet-variant-${workItemId}-`));
|
|
36
|
-
const siteDirectory = isWebsite && environment?.framework === 'static'
|
|
36
|
+
const siteDirectory = isWebsite && environment?.framework === 'static' && environment.entryPath
|
|
37
37
|
? path_1.default.dirname(environment.entryPath)
|
|
38
38
|
: '.';
|
|
39
39
|
try {
|
|
@@ -14,6 +14,7 @@ export interface WorktreeManagerLike {
|
|
|
14
14
|
startDevServer(worktreePath: string, port: number, cmd: string, args: string[], env: Record<string, string>): Promise<ChildProcess>;
|
|
15
15
|
stopDevServer(proc: ChildProcess, timeoutMs?: number): Promise<void>;
|
|
16
16
|
getProjectCwdInWorktree(worktreePath: string): Promise<string>;
|
|
17
|
+
getChangedFiles?(worktreePath: string): Promise<string[]>;
|
|
17
18
|
createFreshWorktrees?(sessionId: string, count: number, template: TemplateBundle, designContext: ReadonlyArray<DesignContextEntry | undefined> | undefined, destinationParent: string): Promise<string[]>;
|
|
18
19
|
}
|
|
19
20
|
type DevServerProjectEnvironment = {
|
|
@@ -31,7 +32,7 @@ type DevServerProjectEnvironment = {
|
|
|
31
32
|
type StaticProjectEnvironment = {
|
|
32
33
|
projectPath: string;
|
|
33
34
|
framework: 'static';
|
|
34
|
-
entryPath
|
|
35
|
+
entryPath?: string;
|
|
35
36
|
};
|
|
36
37
|
export type ProjectEnvironment = DevServerProjectEnvironment | StaticProjectEnvironment;
|
|
37
38
|
export {};
|
|
@@ -64,6 +64,7 @@ export interface VariantsTelemetry {
|
|
|
64
64
|
hasPort: boolean;
|
|
65
65
|
port?: number;
|
|
66
66
|
durationMs?: number | null;
|
|
67
|
+
staticEntrySource?: string;
|
|
67
68
|
}) => void;
|
|
68
69
|
trackAgentVariantsPreviewFailed?: (data: {
|
|
69
70
|
sessionId: string;
|
|
@@ -77,6 +78,7 @@ export interface VariantsTelemetry {
|
|
|
77
78
|
exitCode?: number | null;
|
|
78
79
|
signal?: string | null;
|
|
79
80
|
missingDeps?: boolean;
|
|
81
|
+
staticEntrySource?: string;
|
|
80
82
|
error?: unknown;
|
|
81
83
|
}) => void;
|
|
82
84
|
trackAgentVariantsBriefQuality?: (data: {
|
|
@@ -150,6 +152,7 @@ export declare const trackPreviewReady: (telemetry: VariantsTelemetry, data: {
|
|
|
150
152
|
hasPort: boolean;
|
|
151
153
|
port?: number;
|
|
152
154
|
durationMs?: number | null;
|
|
155
|
+
staticEntrySource?: string;
|
|
153
156
|
}) => void;
|
|
154
157
|
export declare const trackPreviewFailed: (telemetry: VariantsTelemetry, data: {
|
|
155
158
|
sessionId: string;
|
|
@@ -163,6 +166,7 @@ export declare const trackPreviewFailed: (telemetry: VariantsTelemetry, data: {
|
|
|
163
166
|
exitCode?: number | null;
|
|
164
167
|
signal?: string | null;
|
|
165
168
|
missingDeps?: boolean;
|
|
169
|
+
staticEntrySource?: string;
|
|
166
170
|
error?: unknown;
|
|
167
171
|
}) => void;
|
|
168
172
|
export declare const trackStaticPreviewCompleted: (telemetry: VariantsTelemetry, data: {
|
|
@@ -122,6 +122,7 @@ const trackPreviewReady = (telemetry, data) => {
|
|
|
122
122
|
has_port: data.hasPort,
|
|
123
123
|
port: data.port,
|
|
124
124
|
duration_ms: data.durationMs,
|
|
125
|
+
static_entry_source: data.staticEntrySource,
|
|
125
126
|
});
|
|
126
127
|
};
|
|
127
128
|
exports.trackPreviewReady = trackPreviewReady;
|
|
@@ -143,6 +144,7 @@ const trackPreviewFailed = (telemetry, data) => {
|
|
|
143
144
|
exit_code: data.exitCode,
|
|
144
145
|
term_signal: data.signal,
|
|
145
146
|
missing_deps: data.missingDeps,
|
|
147
|
+
static_entry_source: data.staticEntrySource,
|
|
146
148
|
...(0, failureReason_1.failureReasonProperties)(data.error),
|
|
147
149
|
});
|
|
148
150
|
};
|