rivet-design 0.9.3 → 0.9.5

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.
Files changed (105) hide show
  1. package/dist/mcp/agent-variants/SessionStore.d.ts +26 -10
  2. package/dist/mcp/agent-variants/SessionStore.d.ts.map +1 -1
  3. package/dist/mcp/agent-variants/SessionStore.js +189 -44
  4. package/dist/mcp/agent-variants/SessionStore.js.map +1 -1
  5. package/dist/mcp/agent-variants/WorktreeOrchestrator.d.ts +209 -13
  6. package/dist/mcp/agent-variants/WorktreeOrchestrator.d.ts.map +1 -1
  7. package/dist/mcp/agent-variants/WorktreeOrchestrator.js +1489 -61
  8. package/dist/mcp/agent-variants/WorktreeOrchestrator.js.map +1 -1
  9. package/dist/mcp/agent-variants/WorktreeOrchestrator.testHelpers.d.ts +65 -0
  10. package/dist/mcp/agent-variants/WorktreeOrchestrator.testHelpers.d.ts.map +1 -0
  11. package/dist/mcp/agent-variants/WorktreeOrchestrator.testHelpers.js +162 -0
  12. package/dist/mcp/agent-variants/WorktreeOrchestrator.testHelpers.js.map +1 -0
  13. package/dist/mcp/agent-variants/contracts.d.ts +1576 -64
  14. package/dist/mcp/agent-variants/contracts.d.ts.map +1 -1
  15. package/dist/mcp/agent-variants/contracts.js +202 -9
  16. package/dist/mcp/agent-variants/contracts.js.map +1 -1
  17. package/dist/mcp/agent-variants/createProjectArtifacts.d.ts +78 -0
  18. package/dist/mcp/agent-variants/createProjectArtifacts.d.ts.map +1 -0
  19. package/dist/mcp/agent-variants/createProjectArtifacts.js +123 -0
  20. package/dist/mcp/agent-variants/createProjectArtifacts.js.map +1 -0
  21. package/dist/mcp/agent-variants/createZeroToOneTool.d.ts +67 -25
  22. package/dist/mcp/agent-variants/createZeroToOneTool.d.ts.map +1 -1
  23. package/dist/mcp/agent-variants/createZeroToOneTool.js +60 -126
  24. package/dist/mcp/agent-variants/createZeroToOneTool.js.map +1 -1
  25. package/dist/mcp/agent-variants/errors.d.ts +1 -1
  26. package/dist/mcp/agent-variants/errors.d.ts.map +1 -1
  27. package/dist/mcp/agent-variants/errors.js +1 -0
  28. package/dist/mcp/agent-variants/errors.js.map +1 -1
  29. package/dist/mcp/agent-variants/index.d.ts +3 -4
  30. package/dist/mcp/agent-variants/index.d.ts.map +1 -1
  31. package/dist/mcp/agent-variants/index.js +2 -2
  32. package/dist/mcp/agent-variants/index.js.map +1 -1
  33. package/dist/mcp/agent-variants/inspirationDesignContext.d.ts +10 -0
  34. package/dist/mcp/agent-variants/inspirationDesignContext.d.ts.map +1 -1
  35. package/dist/mcp/agent-variants/inspirationDesignContext.js +104 -16
  36. package/dist/mcp/agent-variants/inspirationDesignContext.js.map +1 -1
  37. package/dist/mcp/agent-variants/pendingChangesAdapter.d.ts.map +1 -1
  38. package/dist/mcp/agent-variants/pendingChangesAdapter.js +11 -0
  39. package/dist/mcp/agent-variants/pendingChangesAdapter.js.map +1 -1
  40. package/dist/mcp/agent-variants/previewQa.d.ts +61 -0
  41. package/dist/mcp/agent-variants/previewQa.d.ts.map +1 -0
  42. package/dist/mcp/agent-variants/previewQa.js +374 -0
  43. package/dist/mcp/agent-variants/previewQa.js.map +1 -0
  44. package/dist/mcp/agent-variants/sourceContext.d.ts +1 -0
  45. package/dist/mcp/agent-variants/sourceContext.d.ts.map +1 -1
  46. package/dist/mcp/agent-variants/sourceContext.js +28 -3
  47. package/dist/mcp/agent-variants/sourceContext.js.map +1 -1
  48. package/dist/mcp/agent-variants/tools.d.ts +40 -3
  49. package/dist/mcp/agent-variants/tools.d.ts.map +1 -1
  50. package/dist/mcp/agent-variants/tools.js +262 -38
  51. package/dist/mcp/agent-variants/tools.js.map +1 -1
  52. package/dist/mcp/server.d.ts.map +1 -1
  53. package/dist/mcp/server.js +32 -7
  54. package/dist/mcp/server.js.map +1 -1
  55. package/dist/prompts/agentModPrompts.d.ts.map +1 -1
  56. package/dist/prompts/agentModPrompts.js +11 -10
  57. package/dist/prompts/agentModPrompts.js.map +1 -1
  58. package/dist/proxy-middleware/proxy-config.d.ts +2 -2
  59. package/dist/proxy-middleware/proxy-config.d.ts.map +1 -1
  60. package/dist/proxy-middleware/proxy-config.js +66 -22
  61. package/dist/proxy-middleware/proxy-config.js.map +1 -1
  62. package/dist/routes/agentVariants.d.ts +2 -13
  63. package/dist/routes/agentVariants.d.ts.map +1 -1
  64. package/dist/routes/agentVariants.js +156 -2
  65. package/dist/routes/agentVariants.js.map +1 -1
  66. package/dist/server.d.ts.map +1 -1
  67. package/dist/server.js +79 -4
  68. package/dist/server.js.map +1 -1
  69. package/dist/services/ProjectDetectionService.d.ts.map +1 -1
  70. package/dist/services/ProjectDetectionService.js +21 -0
  71. package/dist/services/ProjectDetectionService.js.map +1 -1
  72. package/dist/services/VariantHistoryService.d.ts +117 -0
  73. package/dist/services/VariantHistoryService.d.ts.map +1 -0
  74. package/dist/services/VariantHistoryService.js +385 -0
  75. package/dist/services/VariantHistoryService.js.map +1 -0
  76. package/dist/services/WorktreeManager.d.ts +67 -9
  77. package/dist/services/WorktreeManager.d.ts.map +1 -1
  78. package/dist/services/WorktreeManager.js +209 -26
  79. package/dist/services/WorktreeManager.js.map +1 -1
  80. package/dist/services/agent/AgentCore.d.ts +1 -1
  81. package/dist/services/agent/AgentCore.d.ts.map +1 -1
  82. package/dist/services/agent/AgentCore.js +24 -1
  83. package/dist/services/agent/AgentCore.js.map +1 -1
  84. package/dist/services/agent/AgentModService.d.ts +1 -1
  85. package/dist/services/agent/AgentModService.js +7 -7
  86. package/dist/services/agent/AgentModService.js.map +1 -1
  87. package/dist/services/templates/viteReactTs.d.ts +6 -0
  88. package/dist/services/templates/viteReactTs.d.ts.map +1 -1
  89. package/dist/services/templates/viteReactTs.js +8 -1
  90. package/dist/services/templates/viteReactTs.js.map +1 -1
  91. package/dist/types/change-request-types.d.ts +14 -0
  92. package/dist/types/change-request-types.d.ts.map +1 -1
  93. package/dist/utils/skills/claude-skill.d.ts +1 -1
  94. package/dist/utils/skills/claude-skill.js +2 -2
  95. package/dist/utils/skills/cursor-rules.d.ts +1 -1
  96. package/dist/utils/skills/cursor-rules.js +1 -1
  97. package/dist/utils/skills/shared-variants-protocol.d.ts +1 -1
  98. package/dist/utils/skills/shared-variants-protocol.d.ts.map +1 -1
  99. package/dist/utils/skills/shared-variants-protocol.js +31 -32
  100. package/dist/utils/skills/shared-variants-protocol.js.map +1 -1
  101. package/package.json +4 -5
  102. package/src/ui/dist/assets/main-OdmwI8Od.css +1 -0
  103. package/src/ui/dist/assets/{main-DejhsBWR.js → main-SuZlKEi0.js} +115 -115
  104. package/src/ui/dist/index.html +2 -2
  105. package/src/ui/dist/assets/main-C9jfEp80.css +0 -1
@@ -0,0 +1,117 @@
1
+ export type VariantHistoryStatus = 'completed' | 'committed' | 'rejected' | 'cancelled';
2
+ export type VariantHistoryKind = 'diff' | 'project-created';
3
+ /** Where the persisted DESIGN.md came from. Slug entries point at a curated
4
+ * catalog inspiration; markdown entries carry user-supplied / Agent Browser
5
+ * extracted content. `label` is always human-readable for the history UI. */
6
+ export interface VariantDesignSource {
7
+ kind: 'slug' | 'markdown';
8
+ label: string;
9
+ /** Catalog slug — present only when `kind === 'slug'`. */
10
+ slug?: string;
11
+ }
12
+ export interface VariantHistoryManifest {
13
+ schemaVersion: number;
14
+ variantId: string;
15
+ sessionId: string;
16
+ label: string;
17
+ brief: string;
18
+ sessionPrompt: string;
19
+ kind: VariantHistoryKind;
20
+ status: VariantHistoryStatus;
21
+ createdAt: string;
22
+ statusChangedAt: string;
23
+ baseSha?: string;
24
+ destinationPath?: string;
25
+ changedFilesCount: number;
26
+ designSource?: VariantDesignSource;
27
+ }
28
+ export interface VariantHistorySessionFile {
29
+ schemaVersion: number;
30
+ sessionId: string;
31
+ createdAt: string;
32
+ sessionPrompt: string;
33
+ projectKind: 'existing' | 'fresh';
34
+ }
35
+ export interface PersistVariantArgs {
36
+ projectPath: string;
37
+ sessionId: string;
38
+ variantId: string;
39
+ label: string;
40
+ brief: string;
41
+ sessionPrompt: string;
42
+ kind: VariantHistoryKind;
43
+ /** Required when kind === 'diff'. */
44
+ diff?: string;
45
+ /** Required when kind === 'project-created'. Directory whose contents are copied into `files/`. */
46
+ sourceDir?: string;
47
+ baseSha?: string;
48
+ destinationPath?: string;
49
+ changedFilesCount: number;
50
+ /** Defaults to 'completed'. Use 'committed' / 'rejected' when persisting at commit time. */
51
+ initialStatus?: VariantHistoryStatus;
52
+ projectKind: 'existing' | 'fresh';
53
+ /** Generated DESIGN.md body to persist as a top-level artifact alongside
54
+ * the diff/files. Currently only populated for fresh-project variants —
55
+ * existing-project variants don't generate a DESIGN.md. */
56
+ designMarkdown?: string;
57
+ designSource?: VariantDesignSource;
58
+ }
59
+ export interface ListVariantsArgs {
60
+ projectPath: string;
61
+ limit?: number;
62
+ status?: VariantHistoryStatus;
63
+ }
64
+ export interface VariantHistoryEntry {
65
+ manifest: VariantHistoryManifest;
66
+ /** Absolute path to the variant's directory under `.rivet/variants/<sessionId>/<variantId>/`. */
67
+ variantDir: string;
68
+ /** True when `files/index.html` exists on disk — i.e. the variant can be
69
+ * rendered as a static preview in an iframe. Vite_app variants and diff
70
+ * variants are false. Computed at list/get time so the UI can filter
71
+ * click-to-preview affordances without poking the disk itself. */
72
+ hasStaticPreview: boolean;
73
+ }
74
+ export interface VariantHistoryDetail extends VariantHistoryEntry {
75
+ /** Diff body — present for `kind: 'diff'` variants. */
76
+ diff?: string;
77
+ /** Project-relative file list under `files/` — present for `kind: 'project-created'` variants. */
78
+ files?: string[];
79
+ /** Generated DESIGN.md body — present when the variant was scaffolded with
80
+ * a design context (fresh-project variants only). */
81
+ designMarkdown?: string;
82
+ }
83
+ export declare class VariantHistoryService {
84
+ variantsRoot(projectPath: string): string;
85
+ sessionDir(projectPath: string, sessionId: string): string;
86
+ variantDir(projectPath: string, sessionId: string, variantId: string): string;
87
+ persistVariant(args: PersistVariantArgs): Promise<void>;
88
+ markStatus(args: {
89
+ projectPath: string;
90
+ sessionId: string;
91
+ variantId: string;
92
+ status: VariantHistoryStatus;
93
+ /** Optional manifest patch applied alongside the status flip. Used at
94
+ * commit time so the chosen fresh-project variant records the path
95
+ * the materialized project landed at. */
96
+ destinationPath?: string;
97
+ }): Promise<void>;
98
+ listVariants(args: ListVariantsArgs): Promise<VariantHistoryEntry[]>;
99
+ getVariant(args: {
100
+ projectPath: string;
101
+ sessionId: string;
102
+ variantId: string;
103
+ }): Promise<VariantHistoryDetail | null>;
104
+ /**
105
+ * Read the persisted static-preview HTML for a variant. Returns null when
106
+ * the variant isn't on disk or doesn't have a `files/index.html`. Used by
107
+ * the REST history-static endpoint that backs the AgentVariantsPanel
108
+ * iframe when a past variant is clicked.
109
+ */
110
+ readStaticPreview(args: {
111
+ projectPath: string;
112
+ sessionId: string;
113
+ variantId: string;
114
+ }): Promise<string | null>;
115
+ ensureGitignore(projectPath: string): Promise<void>;
116
+ }
117
+ //# sourceMappingURL=VariantHistoryService.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VariantHistoryService.d.ts","sourceRoot":"","sources":["../../src/services/VariantHistoryService.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,385 @@
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.VariantHistoryService = void 0;
7
+ const fs_1 = __importDefault(require("fs"));
8
+ const promises_1 = __importDefault(require("fs/promises"));
9
+ const path_1 = __importDefault(require("path"));
10
+ const logger_1 = require("../utils/logger");
11
+ const log = (0, logger_1.createLogger)('VariantHistoryService');
12
+ const HISTORY_SCHEMA_VERSION = 1;
13
+ const RIVET_DIRNAME = '.rivet';
14
+ const VARIANTS_DIRNAME = 'variants';
15
+ const SESSION_FILENAME = 'session.json';
16
+ const MANIFEST_FILENAME = 'manifest.json';
17
+ const DIFF_FILENAME = 'diff.patch';
18
+ const FILES_DIRNAME = 'files';
19
+ const DESIGN_FILENAME = 'DESIGN.md';
20
+ const STATIC_INDEX_FILENAME = 'index.html';
21
+ const GITIGNORE_FILENAME = '.gitignore';
22
+ const GITIGNORE_LINE = '.rivet/';
23
+ const COPY_EXCLUDE = new Set([
24
+ 'node_modules',
25
+ '.git',
26
+ '.vite',
27
+ '.rivet',
28
+ 'dist',
29
+ 'build',
30
+ '.next',
31
+ '.cache',
32
+ ]);
33
+ /** Statuses that are end-states from the user's perspective — once a variant
34
+ * reaches one of these, history must not silently regress it (e.g. a late
35
+ * `persistVariant` from the success path shouldn't reset a `committed`
36
+ * manifest to `completed`, and `markPersistedVariantsCancelled` shouldn't
37
+ * overwrite the chosen variant's `committed` status with `cancelled`). */
38
+ const TERMINAL_STATUSES = new Set([
39
+ 'committed',
40
+ 'rejected',
41
+ ]);
42
+ /** Reject ids containing path separators, `..`, or NUL bytes so caller-
43
+ * controlled REST/MCP input can't escape `<project>/.rivet/variants/`. ids
44
+ * are produced by `crypto.randomUUID()` and stored slugs, both of which fit
45
+ * this character class. */
46
+ const SAFE_ID_PATTERN = /^[A-Za-z0-9_-]+$/;
47
+ const assertSafeId = (value, name) => {
48
+ if (!SAFE_ID_PATTERN.test(value)) {
49
+ throw new Error(`VariantHistoryService: invalid ${name} '${value}' — must match ${SAFE_ID_PATTERN}`);
50
+ }
51
+ };
52
+ class VariantHistoryService {
53
+ variantsRoot(projectPath) {
54
+ return path_1.default.join(projectPath, RIVET_DIRNAME, VARIANTS_DIRNAME);
55
+ }
56
+ sessionDir(projectPath, sessionId) {
57
+ return path_1.default.join(this.variantsRoot(projectPath), sessionId);
58
+ }
59
+ variantDir(projectPath, sessionId, variantId) {
60
+ return path_1.default.join(this.sessionDir(projectPath, sessionId), variantId);
61
+ }
62
+ async persistVariant(args) {
63
+ assertSafeId(args.sessionId, 'sessionId');
64
+ assertSafeId(args.variantId, 'variantId');
65
+ if (args.kind === 'diff' && args.diff === undefined) {
66
+ throw new Error(`persistVariant: kind='diff' requires a diff body (sessionId=${args.sessionId} variantId=${args.variantId})`);
67
+ }
68
+ if (args.kind === 'project-created' && !args.sourceDir) {
69
+ throw new Error(`persistVariant: kind='project-created' requires sourceDir (sessionId=${args.sessionId} variantId=${args.variantId})`);
70
+ }
71
+ const sessionDir = this.sessionDir(args.projectPath, args.sessionId);
72
+ const variantDir = this.variantDir(args.projectPath, args.sessionId, args.variantId);
73
+ await promises_1.default.mkdir(variantDir, { recursive: true });
74
+ // Race guard: persistVariant runs at code_gen success and again on retries
75
+ // / late callbacks. If the manifest has already reached a terminal status
76
+ // via markStatus (committed/rejected), preserve that status so the late
77
+ // persist doesn't silently reset the user's pick to `completed`.
78
+ const existingManifestPath = path_1.default.join(variantDir, MANIFEST_FILENAME);
79
+ let preservedStatus;
80
+ let preservedStatusChangedAt;
81
+ let preservedDestinationPath;
82
+ try {
83
+ const raw = await promises_1.default.readFile(existingManifestPath, 'utf8');
84
+ const prior = JSON.parse(raw);
85
+ if (TERMINAL_STATUSES.has(prior.status)) {
86
+ preservedStatus = prior.status;
87
+ preservedStatusChangedAt = prior.statusChangedAt;
88
+ preservedDestinationPath = prior.destinationPath;
89
+ }
90
+ }
91
+ catch (err) {
92
+ const code = err.code;
93
+ if (code !== 'ENOENT') {
94
+ log.warn(`persistVariant: prior manifest read failed at ${existingManifestPath}`, err);
95
+ }
96
+ }
97
+ const sessionPath = path_1.default.join(sessionDir, SESSION_FILENAME);
98
+ if (!fs_1.default.existsSync(sessionPath)) {
99
+ const sessionFile = {
100
+ schemaVersion: HISTORY_SCHEMA_VERSION,
101
+ sessionId: args.sessionId,
102
+ createdAt: new Date().toISOString(),
103
+ sessionPrompt: args.sessionPrompt,
104
+ projectKind: args.projectKind,
105
+ };
106
+ await promises_1.default.writeFile(sessionPath, `${JSON.stringify(sessionFile, null, 2)}\n`, 'utf8');
107
+ }
108
+ const now = new Date().toISOString();
109
+ const manifest = {
110
+ schemaVersion: HISTORY_SCHEMA_VERSION,
111
+ variantId: args.variantId,
112
+ sessionId: args.sessionId,
113
+ label: args.label,
114
+ brief: args.brief,
115
+ sessionPrompt: args.sessionPrompt,
116
+ kind: args.kind,
117
+ status: preservedStatus ?? args.initialStatus ?? 'completed',
118
+ createdAt: now,
119
+ statusChangedAt: preservedStatusChangedAt ?? now,
120
+ baseSha: args.baseSha,
121
+ destinationPath: preservedDestinationPath ?? args.destinationPath,
122
+ changedFilesCount: args.changedFilesCount,
123
+ designSource: args.designSource,
124
+ };
125
+ await promises_1.default.writeFile(path_1.default.join(variantDir, MANIFEST_FILENAME), `${JSON.stringify(manifest, null, 2)}\n`, 'utf8');
126
+ if (args.kind === 'diff') {
127
+ await promises_1.default.writeFile(path_1.default.join(variantDir, DIFF_FILENAME), args.diff ?? '', 'utf8');
128
+ }
129
+ else {
130
+ const filesDir = path_1.default.join(variantDir, FILES_DIRNAME);
131
+ await promises_1.default.rm(filesDir, { recursive: true, force: true });
132
+ await copyDirFiltered(args.sourceDir, filesDir);
133
+ }
134
+ if (args.designMarkdown !== undefined) {
135
+ await promises_1.default.writeFile(path_1.default.join(variantDir, DESIGN_FILENAME), args.designMarkdown, 'utf8');
136
+ }
137
+ await this.ensureGitignore(args.projectPath);
138
+ log.info(`Persisted variant ${args.variantId} (session ${args.sessionId}, kind ${args.kind}, status ${manifest.status})`);
139
+ }
140
+ async markStatus(args) {
141
+ assertSafeId(args.sessionId, 'sessionId');
142
+ assertSafeId(args.variantId, 'variantId');
143
+ const manifestPath = path_1.default.join(this.variantDir(args.projectPath, args.sessionId, args.variantId), MANIFEST_FILENAME);
144
+ let manifest;
145
+ try {
146
+ const raw = await promises_1.default.readFile(manifestPath, 'utf8');
147
+ manifest = JSON.parse(raw);
148
+ }
149
+ catch (err) {
150
+ // ENOENT is the expected "variant was never persisted" case — any
151
+ // caller that drives the state machine via stubs skips the persistence
152
+ // hook. Only surface unexpected errors (permission denied, corrupt JSON).
153
+ const code = err.code;
154
+ if (code !== 'ENOENT') {
155
+ log.warn(`markStatus: manifest read failed at ${manifestPath} (session ${args.sessionId} variant ${args.variantId})`, err);
156
+ }
157
+ return;
158
+ }
159
+ // Refuse to downgrade a terminal status. Specifically blocks
160
+ // markPersistedVariantsCancelled from rewriting a committed/rejected
161
+ // variant as `cancelled` when the session tears down post-commit, and
162
+ // prevents stray late-cancels from clobbering a finalized pick.
163
+ if (TERMINAL_STATUSES.has(manifest.status) &&
164
+ manifest.status !== args.status) {
165
+ return;
166
+ }
167
+ const destinationChanged = args.destinationPath !== undefined &&
168
+ manifest.destinationPath !== args.destinationPath;
169
+ if (manifest.status === args.status && !destinationChanged)
170
+ return;
171
+ manifest.status = args.status;
172
+ manifest.statusChangedAt = new Date().toISOString();
173
+ if (args.destinationPath !== undefined) {
174
+ manifest.destinationPath = args.destinationPath;
175
+ }
176
+ await promises_1.default.writeFile(manifestPath, `${JSON.stringify(manifest, null, 2)}\n`, 'utf8');
177
+ }
178
+ async listVariants(args) {
179
+ const root = this.variantsRoot(args.projectPath);
180
+ if (!fs_1.default.existsSync(root))
181
+ return [];
182
+ let sessionIds;
183
+ try {
184
+ sessionIds = await promises_1.default.readdir(root);
185
+ }
186
+ catch (err) {
187
+ log.warn(`listVariants: failed to read ${root}`, err);
188
+ return [];
189
+ }
190
+ const entries = [];
191
+ for (const sessionId of sessionIds) {
192
+ const sessionDir = path_1.default.join(root, sessionId);
193
+ const stat = await safeStat(sessionDir);
194
+ if (!stat?.isDirectory())
195
+ continue;
196
+ let variantIds;
197
+ try {
198
+ variantIds = await promises_1.default.readdir(sessionDir);
199
+ }
200
+ catch {
201
+ continue;
202
+ }
203
+ for (const variantId of variantIds) {
204
+ const variantDir = path_1.default.join(sessionDir, variantId);
205
+ const vStat = await safeStat(variantDir);
206
+ if (!vStat?.isDirectory())
207
+ continue;
208
+ const manifest = await readManifest(path_1.default.join(variantDir, MANIFEST_FILENAME));
209
+ if (!manifest)
210
+ continue;
211
+ if (args.status && manifest.status !== args.status)
212
+ continue;
213
+ const hasStaticPreview = await fileExists(path_1.default.join(variantDir, FILES_DIRNAME, STATIC_INDEX_FILENAME));
214
+ entries.push({ manifest, variantDir, hasStaticPreview });
215
+ }
216
+ }
217
+ entries.sort((a, b) => b.manifest.createdAt.localeCompare(a.manifest.createdAt));
218
+ if (args.limit !== undefined && args.limit > 0) {
219
+ return entries.slice(0, args.limit);
220
+ }
221
+ return entries;
222
+ }
223
+ async getVariant(args) {
224
+ assertSafeId(args.sessionId, 'sessionId');
225
+ assertSafeId(args.variantId, 'variantId');
226
+ const variantDir = this.variantDir(args.projectPath, args.sessionId, args.variantId);
227
+ const manifest = await readManifest(path_1.default.join(variantDir, MANIFEST_FILENAME));
228
+ if (!manifest)
229
+ return null;
230
+ const hasStaticPreview = await fileExists(path_1.default.join(variantDir, FILES_DIRNAME, STATIC_INDEX_FILENAME));
231
+ const detail = {
232
+ manifest,
233
+ variantDir,
234
+ hasStaticPreview,
235
+ };
236
+ if (manifest.kind === 'diff') {
237
+ try {
238
+ detail.diff = await promises_1.default.readFile(path_1.default.join(variantDir, DIFF_FILENAME), 'utf8');
239
+ }
240
+ catch {
241
+ detail.diff = '';
242
+ }
243
+ }
244
+ else {
245
+ detail.files = await listFilesRecursive(path_1.default.join(variantDir, FILES_DIRNAME));
246
+ }
247
+ try {
248
+ detail.designMarkdown = await promises_1.default.readFile(path_1.default.join(variantDir, DESIGN_FILENAME), 'utf8');
249
+ }
250
+ catch (err) {
251
+ const code = err.code;
252
+ if (code !== 'ENOENT') {
253
+ log.warn(`getVariant: DESIGN.md read failed at ${variantDir}`, err);
254
+ }
255
+ }
256
+ return detail;
257
+ }
258
+ /**
259
+ * Read the persisted static-preview HTML for a variant. Returns null when
260
+ * the variant isn't on disk or doesn't have a `files/index.html`. Used by
261
+ * the REST history-static endpoint that backs the AgentVariantsPanel
262
+ * iframe when a past variant is clicked.
263
+ */
264
+ async readStaticPreview(args) {
265
+ assertSafeId(args.sessionId, 'sessionId');
266
+ assertSafeId(args.variantId, 'variantId');
267
+ const indexPath = path_1.default.join(this.variantDir(args.projectPath, args.sessionId, args.variantId), FILES_DIRNAME, STATIC_INDEX_FILENAME);
268
+ try {
269
+ return await promises_1.default.readFile(indexPath, 'utf8');
270
+ }
271
+ catch (err) {
272
+ const code = err.code;
273
+ if (code !== 'ENOENT') {
274
+ log.warn(`readStaticPreview: failed at ${indexPath}`, err);
275
+ }
276
+ return null;
277
+ }
278
+ }
279
+ async ensureGitignore(projectPath) {
280
+ const gitignorePath = path_1.default.join(projectPath, GITIGNORE_FILENAME);
281
+ let current = '';
282
+ try {
283
+ current = await promises_1.default.readFile(gitignorePath, 'utf8');
284
+ }
285
+ catch (err) {
286
+ const code = err.code;
287
+ if (code !== 'ENOENT') {
288
+ log.warn(`ensureGitignore: read ${gitignorePath} failed`, err);
289
+ return;
290
+ }
291
+ }
292
+ // Any line that, on its own, already excludes the whole `.rivet/` tree.
293
+ // Narrower patterns like `.rivet/variants/` (what older Rivet versions
294
+ // wrote) do NOT count — we want `.rivet/<slug>/` snapshots, manifests, and
295
+ // history all covered by a single broad rule, so we append the broader
296
+ // pattern alongside.
297
+ const lines = current.split(/\r?\n/);
298
+ const alreadyCoversAll = lines.some((line) => {
299
+ const trimmed = line.trim();
300
+ return (trimmed === '.rivet' ||
301
+ trimmed === '.rivet/' ||
302
+ trimmed === '/.rivet' ||
303
+ trimmed === '/.rivet/' ||
304
+ trimmed === '**/.rivet' ||
305
+ trimmed === '**/.rivet/');
306
+ });
307
+ if (alreadyCoversAll)
308
+ return;
309
+ const needsNewline = current.length > 0 && !current.endsWith('\n');
310
+ const appended = `${current}${needsNewline ? '\n' : ''}${GITIGNORE_LINE}\n`;
311
+ await promises_1.default.writeFile(gitignorePath, appended, 'utf8');
312
+ log.info(`Appended ${GITIGNORE_LINE} to ${gitignorePath}`);
313
+ }
314
+ }
315
+ exports.VariantHistoryService = VariantHistoryService;
316
+ async function readManifest(manifestPath) {
317
+ try {
318
+ const raw = await promises_1.default.readFile(manifestPath, 'utf8');
319
+ const parsed = JSON.parse(raw);
320
+ if (typeof parsed.variantId !== 'string')
321
+ return null;
322
+ return parsed;
323
+ }
324
+ catch {
325
+ return null;
326
+ }
327
+ }
328
+ async function safeStat(p) {
329
+ try {
330
+ return await promises_1.default.stat(p);
331
+ }
332
+ catch {
333
+ return null;
334
+ }
335
+ }
336
+ async function fileExists(p) {
337
+ try {
338
+ const s = await promises_1.default.stat(p);
339
+ return s.isFile();
340
+ }
341
+ catch {
342
+ return false;
343
+ }
344
+ }
345
+ async function copyDirFiltered(src, dest) {
346
+ await promises_1.default.mkdir(dest, { recursive: true });
347
+ const entries = await promises_1.default.readdir(src, { withFileTypes: true });
348
+ for (const entry of entries) {
349
+ if (COPY_EXCLUDE.has(entry.name))
350
+ continue;
351
+ const from = path_1.default.join(src, entry.name);
352
+ const to = path_1.default.join(dest, entry.name);
353
+ if (entry.isDirectory()) {
354
+ await copyDirFiltered(from, to);
355
+ }
356
+ else if (entry.isFile()) {
357
+ await promises_1.default.copyFile(from, to);
358
+ }
359
+ // Symlinks are deliberately dropped. Source dirs are agent-controlled
360
+ // (variant worktrees) and `readStaticPreview` later serves whatever
361
+ // `files/index.html` points at through the history static route —
362
+ // preserving a symlink to e.g. ~/.ssh/id_rsa would turn that route into
363
+ // a host-file read primitive.
364
+ }
365
+ }
366
+ async function listFilesRecursive(root) {
367
+ if (!fs_1.default.existsSync(root))
368
+ return [];
369
+ const out = [];
370
+ const walk = async (dir, prefix) => {
371
+ const entries = await promises_1.default.readdir(dir, { withFileTypes: true });
372
+ for (const entry of entries) {
373
+ const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
374
+ if (entry.isDirectory()) {
375
+ await walk(path_1.default.join(dir, entry.name), rel);
376
+ }
377
+ else if (entry.isFile()) {
378
+ out.push(rel);
379
+ }
380
+ }
381
+ };
382
+ await walk(root, '');
383
+ return out.sort();
384
+ }
385
+ //# sourceMappingURL=VariantHistoryService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VariantHistoryService.js","sourceRoot":"","sources":["../../src/services/VariantHistoryService.ts"],"names":[],"mappings":"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"}
@@ -2,6 +2,7 @@ import { type ChildProcess } from 'child_process';
2
2
  import { type TemplateBundle } from './templates/viteReactTs';
3
3
  import type { DesignContextEntry } from '../mcp/agent-variants/contracts';
4
4
  import type { SourceContextInput } from '../mcp/agent-variants/contracts';
5
+ export declare const FRESH_WORKTREES_DIRNAME = ".rivet-variants";
5
6
  export declare const INSTANCE_PREFIX: string;
6
7
  export declare class WorktreeManager {
7
8
  private readonly resolveProjectPath;
@@ -69,6 +70,13 @@ export declare class WorktreeManager {
69
70
  * which would wipe the user's pre-existing work.
70
71
  */
71
72
  applyDiff(diff: string, reverse: boolean): Promise<void>;
73
+ /**
74
+ * Apply a unified diff to an arbitrary project path. Same engine as
75
+ * `applyDiff` but the cwd is a parameter, so callers (e.g. the variants
76
+ * orchestrator) can target the user's project regardless of which path this
77
+ * manager instance was constructed with.
78
+ */
79
+ applyDiffToProject(diff: string, projectPath: string): Promise<void>;
72
80
  /** Bind port 0 to get an OS-assigned free port */
73
81
  getFreePort(): Promise<number>;
74
82
  /** Validate a diff via `git apply --check` without modifying files */
@@ -85,22 +93,34 @@ export declare class WorktreeManager {
85
93
  * For existing-project sessions, asks git to unregister the worktree
86
94
  * (handles `.git/worktrees/*` cleanup) and falls back to plain rm. For
87
95
  * fresh-project sessions (no projectPath) the worktrees are detached
88
- * directories with their own `.git` git registry cleanup is a no-op
89
- * and we just rm the matching `/tmp` directories.
96
+ * directories with their own `.git` under `<destinationParent>/.rivet-variants/`
97
+ * — git registry cleanup is a no-op and we just rm the matching dirs.
98
+ *
99
+ * `freshDestinationParent` is required when the session was fresh; pass
100
+ * `path.dirname(projectContext.workspacePath)` so we know which
101
+ * `.rivet-variants/` root to sweep.
90
102
  */
91
- cleanupSession(sessionId: string): Promise<void>;
103
+ cleanupSession(sessionId: string, freshDestinationParent?: string): Promise<void>;
92
104
  /**
93
105
  * Create N worktrees for a fresh-project session by writing a template
94
- * bundle into each `/tmp/rivet-variants-pid<PID>-<sessionId>-<i>` directory,
95
- * optionally writing a DESIGN.md per slot, and committing a baseline.
106
+ * bundle into each `<destinationParent>/.rivet-variants/rivet-variants-pid<PID>-<sessionId>-<i>`
107
+ * directory, optionally writing a DESIGN.md per slot, and committing a
108
+ * baseline.
109
+ *
110
+ * Worktrees live under the user's destinationParent (not /tmp) so commit
111
+ * time can be a same-volume rename instead of a cross-volume copy. The
112
+ * destinationParent is registered to a small JSON file so a future MCP
113
+ * startup can sweep orphans even when the original process crashed.
96
114
  *
97
115
  * Does NOT run `npm install` — the orchestrator dispatches that as a
98
116
  * background task so failures surface via work-item state without blocking
99
117
  * the MCP tool response.
100
118
  *
101
- * @effect Creates /tmp directories, writes template files, runs git init/add/commit.
119
+ * @effect Creates directories under destinationParent, writes template
120
+ * files, runs git init/add/commit, appends destinationParent to
121
+ * the fresh-worktree-roots registry.
102
122
  */
103
- createFreshWorktrees(sessionId: string, count: number, template: TemplateBundle, designContext?: ReadonlyArray<DesignContextEntry | undefined>, sourceContext?: SourceContextInput): Promise<string[]>;
123
+ createFreshWorktrees(sessionId: string, count: number, template: TemplateBundle, designContext: ReadonlyArray<DesignContextEntry | undefined> | undefined, sourceContext: SourceContextInput | undefined, destinationParent: string): Promise<string[]>;
104
124
  /**
105
125
  * Write SOURCE_CONTEXT.md when source context exists for the session.
106
126
  *
@@ -113,13 +133,51 @@ export declare class WorktreeManager {
113
133
  * @effect Writes DESIGN.md when a design context is available.
114
134
  */
115
135
  private writeDesignContext;
136
+ /**
137
+ * Move a worktree to its history location preserving contents. Used by the
138
+ * orchestrator at commit time so unchosen variants survive on disk as
139
+ * runnable references (siblings of the chosen project).
140
+ *
141
+ * Returns the destination path (`<historyDir>/<folderName>`).
142
+ *
143
+ * @effect renames `srcWorktreePath` → `<historyDir>/<folderName>`, creating
144
+ * the historyDir if needed.
145
+ */
146
+ moveWorktreeToHistory(srcWorktreePath: string, historyDir: string, folderName: string): string;
147
+ /**
148
+ * Repoint a worktree's `node_modules` at a relative symlink so it tracks
149
+ * the chosen variant's real install after both have moved into their new
150
+ * permanent homes. Idempotent — removes any existing entry first.
151
+ */
152
+ repointNodeModulesSymlink(worktreePath: string, sharedNodeModulesAbsPath: string): void;
116
153
  /** Remove all fresh worktrees for a session.
117
154
  *
118
- * @effect Removes /tmp directories matching ${INSTANCE_PREFIX}-<sessionId>-*.
155
+ * @effect Removes directories under <destinationParent>/.rivet-variants/
156
+ * matching ${INSTANCE_PREFIX}-<sessionId>-*. Also removes the
157
+ * .rivet-variants/ parent if it becomes empty so the editor file
158
+ * tree doesn't accumulate noise.
159
+ *
160
+ * When `preserve` is provided, entries whose basenames are in the set are
161
+ * skipped — used by the orchestrator after a vite_app commit, where the
162
+ * unchosen variant worktrees have already been moved to a sibling history
163
+ * dir and must not be re-deleted.
119
164
  */
120
- cleanupFreshWorktrees(sessionId: string): void;
165
+ cleanupFreshWorktrees(sessionId: string, destinationParent: string, preserve?: ReadonlySet<string>): void;
121
166
  private assertSafeSessionId;
122
167
  }
168
+ /**
169
+ * Append a freshRoot path to the registry (de-duped). Called by
170
+ * createFreshWorktrees so future MCP startups can sweep orphans even if
171
+ * the original process crashed before teardown ran.
172
+ */
173
+ export declare const registerFreshWorktreeRoot: (freshRoot: string) => void;
174
+ /**
175
+ * Sweep orphan worktrees from /tmp (existing-project flow) and from every
176
+ * registered fresh-worktree root (fresh-project flow). Filters by
177
+ * INSTANCE_PREFIX (includes PID) so each server instance only removes its
178
+ * own worktrees and never touches those of sibling instances. Prunes
179
+ * registry entries whose directory no longer exists so the file stays small.
180
+ */
123
181
  export declare const cleanupOrphanedWorktrees: () => void;
124
182
  /**
125
183
  * Prune stale worktree registry entries for a project (`.git/worktrees/<name>`