roughbook 0.0.0-stage → 0.1.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.
Files changed (144) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +166 -2
  3. package/dist/agents/claude.js +214 -0
  4. package/dist/agents/claude.js.map +1 -0
  5. package/dist/agents/codex.js +179 -0
  6. package/dist/agents/codex.js.map +1 -0
  7. package/dist/agents/command.js +47 -0
  8. package/dist/agents/command.js.map +1 -0
  9. package/dist/agents/index.js +21 -0
  10. package/dist/agents/index.js.map +1 -0
  11. package/dist/agents/process.js +76 -0
  12. package/dist/agents/process.js.map +1 -0
  13. package/dist/agents/session.js +26 -0
  14. package/dist/agents/session.js.map +1 -0
  15. package/dist/agents/types.js +2 -0
  16. package/dist/agents/types.js.map +1 -0
  17. package/dist/api/client.js +138 -0
  18. package/dist/api/client.js.map +1 -0
  19. package/dist/api/errors.js +40 -0
  20. package/dist/api/errors.js.map +1 -0
  21. package/dist/api/outbox.js +105 -0
  22. package/dist/api/outbox.js.map +1 -0
  23. package/dist/api/types.js +4 -0
  24. package/dist/api/types.js.map +1 -0
  25. package/dist/cli.js +10 -0
  26. package/dist/cli.js.map +1 -0
  27. package/dist/commands/agents.js +39 -0
  28. package/dist/commands/agents.js.map +1 -0
  29. package/dist/commands/context.js +27 -0
  30. package/dist/commands/context.js.map +1 -0
  31. package/dist/commands/done.js +125 -0
  32. package/dist/commands/done.js.map +1 -0
  33. package/dist/commands/index.js +101 -0
  34. package/dist/commands/index.js.map +1 -0
  35. package/dist/commands/init.js +203 -0
  36. package/dist/commands/init.js.map +1 -0
  37. package/dist/commands/login.js +93 -0
  38. package/dist/commands/login.js.map +1 -0
  39. package/dist/commands/logout.js +34 -0
  40. package/dist/commands/logout.js.map +1 -0
  41. package/dist/commands/promote.js +105 -0
  42. package/dist/commands/promote.js.map +1 -0
  43. package/dist/commands/pull.js +45 -0
  44. package/dist/commands/pull.js.map +1 -0
  45. package/dist/commands/revert.js +39 -0
  46. package/dist/commands/revert.js.map +1 -0
  47. package/dist/commands/review.js +73 -0
  48. package/dist/commands/review.js.map +1 -0
  49. package/dist/commands/run.js +147 -0
  50. package/dist/commands/run.js.map +1 -0
  51. package/dist/commands/shared.js +81 -0
  52. package/dist/commands/shared.js.map +1 -0
  53. package/dist/commands/start.js +119 -0
  54. package/dist/commands/start.js.map +1 -0
  55. package/dist/commands/status.js +62 -0
  56. package/dist/commands/status.js.map +1 -0
  57. package/dist/config/credentials.js +17 -0
  58. package/dist/config/credentials.js.map +1 -0
  59. package/dist/config/server.js +29 -0
  60. package/dist/config/server.js.map +1 -0
  61. package/dist/config/settings.js +21 -0
  62. package/dist/config/settings.js.map +1 -0
  63. package/dist/config/userDir.js +18 -0
  64. package/dist/config/userDir.js.map +1 -0
  65. package/dist/fs/json.js +44 -0
  66. package/dist/fs/json.js.map +1 -0
  67. package/dist/fs/lock.js +38 -0
  68. package/dist/fs/lock.js.map +1 -0
  69. package/dist/io.js +26 -0
  70. package/dist/io.js.map +1 -0
  71. package/dist/launch/open.js +48 -0
  72. package/dist/launch/open.js.map +1 -0
  73. package/dist/launch/platform.js +38 -0
  74. package/dist/launch/platform.js.map +1 -0
  75. package/dist/launch/pty.js +61 -0
  76. package/dist/launch/pty.js.map +1 -0
  77. package/dist/launch/terminal.js +194 -0
  78. package/dist/launch/terminal.js.map +1 -0
  79. package/dist/launch/which.js +59 -0
  80. package/dist/launch/which.js.map +1 -0
  81. package/dist/repo/diff.js +26 -0
  82. package/dist/repo/diff.js.map +1 -0
  83. package/dist/repo/framework.js +41 -0
  84. package/dist/repo/framework.js.map +1 -0
  85. package/dist/repo/link.js +28 -0
  86. package/dist/repo/link.js.map +1 -0
  87. package/dist/repo/prep.js +447 -0
  88. package/dist/repo/prep.js.map +1 -0
  89. package/dist/repo/preview.js +144 -0
  90. package/dist/repo/preview.js.map +1 -0
  91. package/dist/repo/root.js +48 -0
  92. package/dist/repo/root.js.map +1 -0
  93. package/dist/repo/scratch.js +111 -0
  94. package/dist/repo/scratch.js.map +1 -0
  95. package/dist/runs/checks.js +160 -0
  96. package/dist/runs/checks.js.map +1 -0
  97. package/dist/runs/lifecycle.js +142 -0
  98. package/dist/runs/lifecycle.js.map +1 -0
  99. package/dist/runs/promote.js +185 -0
  100. package/dist/runs/promote.js.map +1 -0
  101. package/dist/runs/pull.js +182 -0
  102. package/dist/runs/pull.js.map +1 -0
  103. package/dist/runs/reviews.js +34 -0
  104. package/dist/runs/reviews.js.map +1 -0
  105. package/dist/runs/slots.js +96 -0
  106. package/dist/runs/slots.js.map +1 -0
  107. package/dist/runs/snapshot.js +265 -0
  108. package/dist/runs/snapshot.js.map +1 -0
  109. package/dist/runs/store.js +38 -0
  110. package/dist/runs/store.js.map +1 -0
  111. package/dist/runs/types.js +3 -0
  112. package/dist/runs/types.js.map +1 -0
  113. package/dist/runs/watch.js +42 -0
  114. package/dist/runs/watch.js.map +1 -0
  115. package/dist/screenshot/browser.js +163 -0
  116. package/dist/screenshot/browser.js.map +1 -0
  117. package/dist/screenshot/iteration.js +37 -0
  118. package/dist/screenshot/iteration.js.map +1 -0
  119. package/dist/server/app.js +321 -0
  120. package/dist/server/app.js.map +1 -0
  121. package/dist/server/security.js +44 -0
  122. package/dist/server/security.js.map +1 -0
  123. package/dist/server/studio.js +618 -0
  124. package/dist/server/studio.js.map +1 -0
  125. package/dist/server/terminals.js +142 -0
  126. package/dist/server/terminals.js.map +1 -0
  127. package/dist/ui/assets/ibm-plex-mono-latin-400-normal-CvHOgSBP.woff +0 -0
  128. package/dist/ui/assets/ibm-plex-mono-latin-400-normal-DMJ8VG8y.woff2 +0 -0
  129. package/dist/ui/assets/ibm-plex-mono-latin-500-normal-CB9ihrfo.woff +0 -0
  130. package/dist/ui/assets/ibm-plex-mono-latin-500-normal-DSY6xOcd.woff2 +0 -0
  131. package/dist/ui/assets/index-D-TSXfvz.css +1 -0
  132. package/dist/ui/assets/index-HGV8FKwI.js +27 -0
  133. package/dist/ui/assets/inter-latin-400-normal-C38fXH4l.woff2 +0 -0
  134. package/dist/ui/assets/inter-latin-400-normal-CyCys3Eg.woff +0 -0
  135. package/dist/ui/assets/inter-latin-500-normal-BL9OpVg8.woff +0 -0
  136. package/dist/ui/assets/inter-latin-500-normal-Cerq10X2.woff2 +0 -0
  137. package/dist/ui/assets/space-grotesk-latin-400-normal-BnQMeOim.woff +0 -0
  138. package/dist/ui/assets/space-grotesk-latin-400-normal-CJ-V5oYT.woff2 +0 -0
  139. package/dist/ui/assets/space-grotesk-latin-500-normal-CNSSEhBt.woff +0 -0
  140. package/dist/ui/assets/space-grotesk-latin-500-normal-lFbtlQH6.woff2 +0 -0
  141. package/dist/ui/index.html +14 -0
  142. package/dist/version.js +4 -0
  143. package/dist/version.js.map +1 -0
  144. package/package.json +68 -4
@@ -0,0 +1,185 @@
1
+ // Promote, the studio's half: a selected local iteration becomes a production component in this
2
+ // repo. The backend renders the prompt from the brief; the studio copies the assets the iteration
3
+ // uses into the app's public folder and the approved copy beside the reference, fills in the
4
+ // paths the server never sees, and hands the prompt to the designer's agent. Ported from roughbook
5
+ // src/lib/delivery/promote.ts (v2-local). The studio never edits the app's code and never commits.
6
+ import fs from 'node:fs';
7
+ import path from 'node:path';
8
+ import { iterationDir } from '../repo/preview.js';
9
+ import { ROUGH_DIR } from '../repo/root.js';
10
+ import { assertTarget } from './slots.js';
11
+ import { assertRunId } from './store.js';
12
+ const ASSET_URL = /\/api\/files\/(project\/([a-z0-9][a-z0-9-]*)|library)\/([A-Za-z0-9._%-]+)/g;
13
+ const TEXT_FILE = /\.(tsx?|jsx?|css|json|md|svg)$/i;
14
+ const FILE_NAME = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;
15
+ /** The project and library asset files an iteration's source refers to, each once. */
16
+ export function referencedAssets(sources, projectSlug) {
17
+ const seen = new Map();
18
+ for (const source of sources) {
19
+ for (const match of source.matchAll(ASSET_URL)) {
20
+ const scope = match[1] === 'library' ? 'library' : 'project';
21
+ // Another project's files are not this client's to ship.
22
+ if (scope === 'project' && match[2] !== projectSlug)
23
+ continue;
24
+ let file;
25
+ try {
26
+ file = decodeURIComponent(match[3]);
27
+ }
28
+ catch {
29
+ continue;
30
+ }
31
+ if (FILE_NAME.test(file))
32
+ seen.set(`${scope}/${file}`, { scope, file });
33
+ }
34
+ }
35
+ return [...seen.values()];
36
+ }
37
+ export function pascalCase(text) {
38
+ const name = text
39
+ .split(/[^A-Za-z0-9]+/)
40
+ .filter(Boolean)
41
+ .map(part => part[0].toUpperCase() + part.slice(1))
42
+ .join('');
43
+ return /^[A-Za-z]/.test(name) ? name : `Section${name}`;
44
+ }
45
+ export function defaultComponentFile(componentsDir, componentName) {
46
+ return `${componentsDir}/${pascalCase(componentName)}.tsx`;
47
+ }
48
+ /** A component path inside the repo, outside rough/ and the public folder; the problem, or null. */
49
+ export function checkTargetFile(file, publicDir) {
50
+ const normalized = file.replace(/\\/g, '/');
51
+ if (!/^[A-Za-z0-9_@()[\]./-]+\.(tsx|jsx)$/.test(normalized)) {
52
+ return 'The component file must be a .tsx or .jsx path inside the repo.';
53
+ }
54
+ if (normalized.startsWith('/') ||
55
+ /^[a-z]:/i.test(normalized) ||
56
+ normalized.split('/').includes('..')) {
57
+ return 'The component file must be a relative path inside the repo.';
58
+ }
59
+ if (normalized.startsWith(`${ROUGH_DIR}/`) || normalized.startsWith(`${publicDir}/`)) {
60
+ return 'The component cannot live in rough/ or the public folder.';
61
+ }
62
+ return null;
63
+ }
64
+ /** A folder inside the repo, relative with forward slashes, or null. */
65
+ function repoFolder(text) {
66
+ const folder = text.replace(/\\/g, '/').replace(/^\.?\/+|\/+$/g, '');
67
+ if (!folder || folder.split('/').includes('..') || /^[a-z]:/i.test(folder))
68
+ return null;
69
+ return folder;
70
+ }
71
+ /** The server's prompt with this repo's paths in place of its stand-ins. */
72
+ export function fillInPrompt(promotion, targetFile, publicDir) {
73
+ // Functions, so a "$" in a path is not read as a replacement pattern.
74
+ return promotion.prompt
75
+ .replaceAll(promotion.placeholders.targetFile, () => targetFile)
76
+ .replaceAll(promotion.placeholders.targetDir, () => path.posix.dirname(targetFile))
77
+ .replaceAll(promotion.placeholders.publicDir, () => publicDir);
78
+ }
79
+ export function promotePromptFile(page, component, promotionId) {
80
+ return `${ROUGH_DIR}/${page}/${component}/prompts/promote-${assertRunId(promotionId)}.md`;
81
+ }
82
+ function toDisk(repoRoot, relative) {
83
+ return path.join(repoRoot, ...relative.split('/'));
84
+ }
85
+ function textFiles(dir) {
86
+ if (!fs.existsSync(dir))
87
+ return [];
88
+ return fs.readdirSync(dir, { withFileTypes: true }).flatMap(entry => {
89
+ const full = path.join(dir, entry.name);
90
+ if (entry.isDirectory())
91
+ return textFiles(full);
92
+ return TEXT_FILE.test(entry.name) ? [full] : [];
93
+ });
94
+ }
95
+ export function findComponent(tree, page, component) {
96
+ const found = tree.pages
97
+ .find(item => item.slug === page)
98
+ ?.components.find(item => item.slug === component);
99
+ if (!found)
100
+ throw new Error(`${page}/${component} is not a component of ${tree.name}.`);
101
+ return found;
102
+ }
103
+ /** The iteration to promote: the one named, or the component's selected one. */
104
+ export function iterationToPromote(component, named) {
105
+ if (named)
106
+ return named;
107
+ if (component.selectedIteration === null) {
108
+ throw new Error(`No iteration of ${component.name} is selected. Select one first, or name it with --iteration.`);
109
+ }
110
+ return `iteration-${String(component.selectedIteration).padStart(2, '0')}`;
111
+ }
112
+ /** The app's public folder: given, beside the App Router app's package.json, or the project's. */
113
+ export function publicDirFor(repoRoot, link, tree, given) {
114
+ if (given !== undefined) {
115
+ const folder = repoFolder(given);
116
+ if (!folder)
117
+ throw new Error('The public folder must be a folder inside the repo.');
118
+ return folder;
119
+ }
120
+ if (link.appDir) {
121
+ let dir = toDisk(repoRoot, link.appDir);
122
+ while (dir.startsWith(repoRoot) && !fs.existsSync(path.join(dir, 'package.json'))) {
123
+ const parent = path.dirname(dir);
124
+ if (parent === dir)
125
+ break;
126
+ dir = parent;
127
+ }
128
+ const relative = path.relative(repoRoot, dir).split(path.sep).join('/');
129
+ if (!relative.startsWith('..'))
130
+ return relative ? `${relative}/public` : 'public';
131
+ }
132
+ return repoFolder(tree.delivery.publicDir) ?? 'public';
133
+ }
134
+ export async function preparePromotion(repoRoot, api, link, tree, options) {
135
+ const { page, component, iteration } = options;
136
+ assertTarget(page, component, iteration);
137
+ const record = findComponent(tree, page, component);
138
+ const folder = toDisk(repoRoot, iterationDir(page, component, iteration));
139
+ if (!fs.existsSync(path.join(folder, 'index.tsx'))) {
140
+ throw new Error(`${iterationDir(page, component, iteration)} has no index.tsx in this repo.`);
141
+ }
142
+ const publicDir = publicDirFor(repoRoot, link, tree, options.publicDir);
143
+ const targetFile = (options.targetFile ?? defaultComponentFile(tree.delivery.componentsDir, record.name)).replace(/\\/g, '/');
144
+ const problem = checkTargetFile(targetFile, publicDir);
145
+ if (problem)
146
+ throw new Error(problem);
147
+ if (fs.existsSync(toDisk(repoRoot, targetFile))) {
148
+ throw new Error(`${targetFile} already exists. Choose another file with --to; Roughbook never overwrites the app's code.`);
149
+ }
150
+ const sources = textFiles(folder).map(file => fs.readFileSync(file, 'utf8'));
151
+ const promotion = await api.promote(link.orgId, link.project, {
152
+ page,
153
+ component,
154
+ iteration,
155
+ assets: referencedAssets(sources, link.project)
156
+ });
157
+ const copied = [];
158
+ const missing = [...promotion.missingAssets];
159
+ for (const asset of promotion.assets) {
160
+ if (!FILE_NAME.test(asset.file))
161
+ continue;
162
+ const to = `${publicDir}/rough/${page}/${component}/${asset.file}`;
163
+ const bytes = await api.file(link.orgId, link.project, asset.scope, asset.file);
164
+ fs.mkdirSync(path.dirname(toDisk(repoRoot, to)), { recursive: true });
165
+ fs.writeFileSync(toDisk(repoRoot, to), bytes);
166
+ copied.push(to);
167
+ }
168
+ const workspace = `${ROUGH_DIR}/${page}/${component}`;
169
+ if (promotion.copyMarkdown !== null) {
170
+ fs.writeFileSync(toDisk(repoRoot, `${workspace}/copy.md`), promotion.copyMarkdown);
171
+ }
172
+ const promptFile = promotePromptFile(page, component, promotion.promotionId);
173
+ fs.mkdirSync(path.dirname(toDisk(repoRoot, promptFile)), { recursive: true });
174
+ fs.writeFileSync(toDisk(repoRoot, promptFile), fillInPrompt(promotion, targetFile, publicDir));
175
+ return {
176
+ promotionId: promotion.promotionId,
177
+ promptFile,
178
+ targetFile,
179
+ publicDir,
180
+ copied,
181
+ missing,
182
+ wroteCopy: promotion.copyMarkdown !== null
183
+ };
184
+ }
185
+ //# sourceMappingURL=promote.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"promote.js","sourceRoot":"","sources":["../../src/runs/promote.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,182 @@
1
+ // Sketch → local (decision 10 of the split plan): a web sketch becomes the starting point of a
2
+ // local iteration, a fork whose parent is the sketch. The backend allocates the iteration and
3
+ // sends the sketch's files; the studio writes them into rough/, points their asset URLs at its
4
+ // own server, and says what the app still needs to render them. Nothing goes back up.
5
+ import fs from 'node:fs';
6
+ import path from 'node:path';
7
+ import { ApiError } from '../api/errors.js';
8
+ import { iterationDir, writePreviewRegistry } from '../repo/preview.js';
9
+ import { assertTarget, iterationExists } from './slots.js';
10
+ import { recordOwnWrites } from './snapshot.js';
11
+ import { listRuns } from './store.js';
12
+ /** A sketch's files as the backend's build allows them: a few folders deep, known types only. */
13
+ const SKETCH_PATH = /^(?:[A-Za-z0-9][A-Za-z0-9._-]*\/){0,3}[A-Za-z0-9][A-Za-z0-9._-]*\.(?:tsx|ts|jsx|js|css|json|svg|png|jpe?g|gif|webp)$/;
14
+ const CODE_FILE = /\.(?:tsx|ts|jsx|js)$/;
15
+ const TEXT_FILE = /\.(?:tsx|ts|jsx|js|css|json|svg)$/;
16
+ /** Far above what the backend allows a sketch, so only a broken answer is refused. */
17
+ const MAX_FILES = 64;
18
+ const MAX_BYTES = 8 * 1024 * 1024;
19
+ /** What the backend's refusals mean here. */
20
+ const REFUSALS = {
21
+ SKETCH_RUNNING: sketch => `${sketch} is still being made on the web. Pull it when it has finished.`,
22
+ SKETCH_HAS_NO_SOURCE: sketch => `${sketch} has no files to pull: its run did not finish.`,
23
+ ITERATION_IS_LOCAL: sketch => `${sketch} is a local iteration, not a web sketch. Fork it with roughbook run --fork.`,
24
+ ITERATION_NOT_FOUND: sketch => `There is no ${sketch} in this component.`
25
+ };
26
+ /**
27
+ * The sketch's asset URLs, which load beside the sandbox's page, made absolute on the studio's
28
+ * server, where local iterations load the project's and library's files.
29
+ */
30
+ export function localAssetUrls(text, assetOrigin) {
31
+ return text.replace(/(["'`(])\/api\/files\/(project|library)\//g, (_match, before, scope) => `${before}${assetOrigin}/api/files/${scope}/`);
32
+ }
33
+ /** Every file the backend sent, checked before anything is written. */
34
+ function checkFiles(files) {
35
+ if (!Array.isArray(files) || !files.length || files.length > MAX_FILES) {
36
+ throw new Error('The server sent a sketch this studio cannot write.');
37
+ }
38
+ let total = 0;
39
+ const seen = new Set();
40
+ for (const file of files) {
41
+ const { path: name, encoding, content } = file ?? {};
42
+ if (typeof name !== 'string' ||
43
+ !SKETCH_PATH.test(name) ||
44
+ seen.has(name.toLowerCase()) ||
45
+ (encoding !== 'utf8' && encoding !== 'base64') ||
46
+ typeof content !== 'string') {
47
+ throw new Error('The server sent a sketch file this studio will not write.');
48
+ }
49
+ seen.add(name.toLowerCase());
50
+ total += content.length;
51
+ if (total > MAX_BYTES)
52
+ throw new Error('The server sent a sketch larger than any it makes.');
53
+ }
54
+ return files;
55
+ }
56
+ /** The package an import names, or null for a relative or absolute one. */
57
+ function packageOf(specifier) {
58
+ if (/^[./]/.test(specifier) || specifier.includes(':'))
59
+ return null;
60
+ const parts = specifier.split('/');
61
+ return specifier.startsWith('@') ? parts.slice(0, 2).join('/') : (parts[0] ?? null);
62
+ }
63
+ /** The packages code imports, each once, in the order they appear. */
64
+ export function importedPackages(sources) {
65
+ const found = new Set();
66
+ const patterns = [
67
+ /\bfrom\s*["']([^"']+)["']/g,
68
+ /\bimport\s*["']([^"']+)["']/g,
69
+ /\bimport\s*\(\s*["']([^"']+)["']\s*\)/g
70
+ ];
71
+ for (const source of sources) {
72
+ for (const pattern of patterns) {
73
+ for (const match of source.matchAll(pattern)) {
74
+ const name = packageOf(match[1]);
75
+ if (name)
76
+ found.add(name);
77
+ }
78
+ }
79
+ }
80
+ return [...found];
81
+ }
82
+ /** The app's dependencies, or null when its package.json cannot be read. */
83
+ function appDependencies(repoRoot) {
84
+ try {
85
+ const pkg = JSON.parse(fs.readFileSync(path.join(repoRoot, 'package.json'), 'utf8'));
86
+ return new Set([
87
+ ...Object.keys(pkg.dependencies ?? {}),
88
+ ...Object.keys(pkg.devDependencies ?? {})
89
+ ]);
90
+ }
91
+ catch {
92
+ return null;
93
+ }
94
+ }
95
+ /** How this app adds packages, from its lockfile. */
96
+ export function installCommand(repoRoot, packages) {
97
+ if (!packages.length)
98
+ return null;
99
+ const has = (file) => fs.existsSync(path.join(repoRoot, file));
100
+ const tool = has('pnpm-lock.yaml')
101
+ ? 'pnpm add'
102
+ : has('yarn.lock')
103
+ ? 'yarn add'
104
+ : has('bun.lock') || has('bun.lockb')
105
+ ? 'bun add'
106
+ : 'npm install';
107
+ return `${tool} ${packages.join(' ')}`;
108
+ }
109
+ /** What the designer should do before the pulled iteration renders, in sentences. */
110
+ export function pullAdvice(result) {
111
+ const lines = [];
112
+ if (result.missingPackages.length) {
113
+ const names = result.missingPackages.join(', ');
114
+ lines.push(`It imports ${names}, which this app does not list. Add ${result.missingPackages.length === 1 ? 'it' : 'them'} with: ${result.installCommand}`);
115
+ }
116
+ if (result.needsTailwind) {
117
+ lines.push('It is styled with Tailwind classes, and this app does not list tailwindcss, so it will render unstyled here.');
118
+ }
119
+ return lines;
120
+ }
121
+ /**
122
+ * Pulls a web sketch into rough/ as the component's next local iteration. Every path the server
123
+ * sends is checked first; an existing iteration is never written over.
124
+ */
125
+ export async function pullSketch(repoRoot, api, link, target, options) {
126
+ const { page, component, sketch } = target;
127
+ assertTarget(page, component, sketch);
128
+ let pulled;
129
+ try {
130
+ pulled = await api.pullSketch(link.orgId, link.project, page, component, sketch);
131
+ }
132
+ catch (error) {
133
+ const refusal = error instanceof ApiError ? REFUSALS[error.code] : undefined;
134
+ throw refusal ? new Error(refusal(sketch)) : error;
135
+ }
136
+ assertTarget(page, component, pulled.iteration);
137
+ const files = checkFiles(pulled.files);
138
+ const folder = iterationDir(page, component, pulled.iteration);
139
+ if (iterationExists(repoRoot, page, component, pulled.iteration)) {
140
+ throw new Error(`${folder} already exists. An existing iteration is never written over.`);
141
+ }
142
+ const dir = path.join(repoRoot, ...folder.split('/'));
143
+ try {
144
+ for (const file of files) {
145
+ const to = path.join(dir, ...file.path.split('/'));
146
+ fs.mkdirSync(path.dirname(to), { recursive: true });
147
+ if (file.encoding === 'base64')
148
+ fs.writeFileSync(to, Buffer.from(file.content, 'base64'));
149
+ else {
150
+ const text = TEXT_FILE.test(file.path)
151
+ ? localAssetUrls(file.content, options.assetOrigin)
152
+ : file.content;
153
+ fs.writeFileSync(to, text.replace(/\r\n/g, '\n'));
154
+ }
155
+ }
156
+ }
157
+ catch (error) {
158
+ fs.rmSync(dir, { recursive: true, force: true });
159
+ throw error;
160
+ }
161
+ writePreviewRegistry(repoRoot);
162
+ // Runs going now did not write these, so their Done does not count them.
163
+ const open = (await listRuns(repoRoot)).filter(run => run.status === 'started');
164
+ await recordOwnWrites(repoRoot, open.map(run => run.runId), files.map(file => `${folder}/${file.path}`));
165
+ const code = files.filter(file => CODE_FILE.test(file.path) && file.encoding === 'utf8');
166
+ const dependencies = appDependencies(repoRoot);
167
+ const missingPackages = dependencies
168
+ ? importedPackages(code.map(file => file.content)).filter(name => !dependencies.has(name))
169
+ : [];
170
+ return {
171
+ iteration: pulled.iteration,
172
+ parent: pulled.parent,
173
+ folder,
174
+ files: files.map(file => file.path),
175
+ missingPackages,
176
+ installCommand: installCommand(repoRoot, missingPackages),
177
+ needsTailwind: dependencies !== null &&
178
+ !dependencies.has('tailwindcss') &&
179
+ code.some(file => /\bclassName\s*=/.test(file.content))
180
+ };
181
+ }
182
+ //# sourceMappingURL=pull.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pull.js","sourceRoot":"","sources":["../../src/runs/pull.ts"],"names":[],"mappings":"AAAA,+FAA+F;AAC/F,8FAA8F;AAC9F,+FAA+F;AAC/F,sFAAsF;AACtF,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAG5C,OAAO,EAAE,YAAY,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AACxE,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAC3D,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEtC,iGAAiG;AACjG,MAAM,WAAW,GACf,sHAAsH,CAAC;AACzH,MAAM,SAAS,GAAG,sBAAsB,CAAC;AACzC,MAAM,SAAS,GAAG,mCAAmC,CAAC;AACtD,sFAAsF;AACtF,MAAM,SAAS,GAAG,EAAE,CAAC;AACrB,MAAM,SAAS,GAAG,CAAC,GAAG,IAAI,GAAG,IAAI,CAAC;AAElC,6CAA6C;AAC7C,MAAM,QAAQ,GAA+C;IAC3D,cAAc,EAAE,MAAM,CAAC,EAAE,CACvB,GAAG,MAAM,gEAAgE;IAC3E,oBAAoB,EAAE,MAAM,CAAC,EAAE,CAAC,GAAG,MAAM,gDAAgD;IACzF,kBAAkB,EAAE,MAAM,CAAC,EAAE,CAC3B,GAAG,MAAM,6EAA6E;IACxF,mBAAmB,EAAE,MAAM,CAAC,EAAE,CAAC,eAAe,MAAM,qBAAqB;CAC1E,CAAC;AAmBF;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,IAAY,EAAE,WAAmB;IAC9D,OAAO,IAAI,CAAC,OAAO,CACjB,4CAA4C,EAC5C,CAAC,MAAM,EAAE,MAAc,EAAE,KAAa,EAAE,EAAE,CAAC,GAAG,MAAM,GAAG,WAAW,cAAc,KAAK,GAAG,CACzF,CAAC;AACJ,CAAC;AAED,uEAAuE;AACvE,SAAS,UAAU,CAAC,KAAc;IAChC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,MAAM,GAAG,SAAS,EAAE,CAAC;QACvE,MAAM,IAAI,KAAK,CAAC,oDAAoD,CAAC,CAAC;IACxE,CAAC;IACD,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,KAAK,MAAM,IAAI,IAAI,KAAqB,EAAE,CAAC;QACzC,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,IAAI,IAAI,EAAE,CAAC;QACrD,IACE,OAAO,IAAI,KAAK,QAAQ;YACxB,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC;YACvB,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;YAC5B,CAAC,QAAQ,KAAK,MAAM,IAAI,QAAQ,KAAK,QAAQ,CAAC;YAC9C,OAAO,OAAO,KAAK,QAAQ,EAC3B,CAAC;YACD,MAAM,IAAI,KAAK,CAAC,2DAA2D,CAAC,CAAC;QAC/E,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;QAC7B,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC;QACxB,IAAI,KAAK,GAAG,SAAS;YAAE,MAAM,IAAI,KAAK,CAAC,oDAAoD,CAAC,CAAC;IAC/F,CAAC;IACD,OAAO,KAAqB,CAAC;AAC/B,CAAC;AAED,2EAA2E;AAC3E,SAAS,SAAS,CAAC,SAAiB;IAClC,IAAI,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IACpE,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACnC,OAAO,SAAS,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC;AACtF,CAAC;AAED,sEAAsE;AACtE,MAAM,UAAU,gBAAgB,CAAC,OAAiB;IAChD,MAAM,KAAK,GAAG,IAAI,GAAG,EAAU,CAAC;IAChC,MAAM,QAAQ,GAAG;QACf,4BAA4B;QAC5B,8BAA8B;QAC9B,wCAAwC;KACzC,CAAC;IACF,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;YAC/B,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC7C,MAAM,IAAI,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC,CAAE,CAAC,CAAC;gBAClC,IAAI,IAAI;oBAAE,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAC5B,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,CAAC,GAAG,KAAK,CAAC,CAAC;AACpB,CAAC;AAED,4EAA4E;AAC5E,SAAS,eAAe,CAAC,QAAgB;IACvC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,cAAc,CAAC,EAAE,MAAM,CAAC,CAGlF,CAAC;QACF,OAAO,IAAI,GAAG,CAAC;YACb,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,YAAY,IAAI,EAAE,CAAC;YACtC,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,eAAe,IAAI,EAAE,CAAC;SAC1C,CAAC,CAAC;IACL,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,qDAAqD;AACrD,MAAM,UAAU,cAAc,CAAC,QAAgB,EAAE,QAAkB;IACjE,IAAI,CAAC,QAAQ,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IAClC,MAAM,GAAG,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAC;IACvE,MAAM,IAAI,GAAG,GAAG,CAAC,gBAAgB,CAAC;QAChC,CAAC,CAAC,UAAU;QACZ,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC;YAChB,CAAC,CAAC,UAAU;YACZ,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,GAAG,CAAC,WAAW,CAAC;gBACnC,CAAC,CAAC,SAAS;gBACX,CAAC,CAAC,aAAa,CAAC;IACtB,OAAO,GAAG,IAAI,IAAI,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;AACzC,CAAC;AAED,qFAAqF;AACrF,MAAM,UAAU,UAAU,CAAC,MAAkB;IAC3C,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,MAAM,CAAC,eAAe,CAAC,MAAM,EAAE,CAAC;QAClC,MAAM,KAAK,GAAG,MAAM,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAChD,KAAK,CAAC,IAAI,CACR,cAAc,KAAK,uCAAuC,MAAM,CAAC,eAAe,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,UAAU,MAAM,CAAC,cAAc,EAAE,CAC/I,CAAC;IACJ,CAAC;IACD,IAAI,MAAM,CAAC,aAAa,EAAE,CAAC;QACzB,KAAK,CAAC,IAAI,CACR,8GAA8G,CAC/G,CAAC;IACJ,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,QAAgB,EAChB,GAAc,EACd,IAAc,EACd,MAA2D,EAC3D,OAAgC;IAEhC,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC;IAC3C,YAAY,CAAC,IAAI,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC;IACtC,IAAI,MAAoB,CAAC;IACzB,IAAI,CAAC;QACH,MAAM,GAAG,MAAM,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC;IACnF,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,OAAO,GAAG,KAAK,YAAY,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAC7E,MAAM,OAAO,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;IACrD,CAAC;IACD,YAAY,CAAC,IAAI,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC;IAChD,MAAM,KAAK,GAAG,UAAU,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACvC,MAAM,MAAM,GAAG,YAAY,CAAC,IAAI,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC;IAC/D,IAAI,eAAe,CAAC,QAAQ,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC;QACjE,MAAM,IAAI,KAAK,CAAC,GAAG,MAAM,+DAA+D,CAAC,CAAC;IAC5F,CAAC;IAED,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;IACtD,IAAI,CAAC;QACH,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;YACnD,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YACpD,IAAI,IAAI,CAAC,QAAQ,KAAK,QAAQ;gBAAE,EAAE,CAAC,aAAa,CAAC,EAAE,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC;iBACrF,CAAC;gBACJ,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;oBACpC,CAAC,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,WAAW,CAAC;oBACnD,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC;gBACjB,EAAE,CAAC,aAAa,CAAC,EAAE,EAAE,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC;YACpD,CAAC;QACH,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,EAAE,CAAC,MAAM,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QACjD,MAAM,KAAK,CAAC;IACd,CAAC;IACD,oBAAoB,CAAC,QAAQ,CAAC,CAAC;IAC/B,yEAAyE;IACzE,MAAM,IAAI,GAAG,CAAC,MAAM,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC;IAChF,MAAM,eAAe,CACnB,QAAQ,EACR,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,EAC1B,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,MAAM,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC,CAC5C,CAAC;IAEF,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,QAAQ,KAAK,MAAM,CAAC,CAAC;IACzF,MAAM,YAAY,GAAG,eAAe,CAAC,QAAQ,CAAC,CAAC;IAC/C,MAAM,eAAe,GAAG,YAAY;QAClC,CAAC,CAAC,gBAAgB,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC1F,CAAC,CAAC,EAAE,CAAC;IACP,OAAO;QACL,SAAS,EAAE,MAAM,CAAC,SAAS;QAC3B,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,MAAM;QACN,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC;QACnC,eAAe;QACf,cAAc,EAAE,cAAc,CAAC,QAAQ,EAAE,eAAe,CAAC;QACzD,aAAa,EACX,YAAY,KAAK,IAAI;YACrB,CAAC,YAAY,CAAC,GAAG,CAAC,aAAa,CAAC;YAChC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;KAC1D,CAAC;AACJ,CAAC"}
@@ -0,0 +1,34 @@
1
+ // Review decisions on local iterations: select, reject with a reason, a review with
2
+ // observations, notes, or a status. They go to the backend through the outbox, so they are kept while offline and
3
+ // reach the server before the next run asks for a prompt, which is where rejection memory works.
4
+ import { iterationPath } from '../api/client.js';
5
+ import { assertTarget } from './slots.js';
6
+ function request(decision) {
7
+ switch (decision.kind) {
8
+ case 'select':
9
+ return { route: 'select', body: { reason: decision.reason ?? '' } };
10
+ case 'reject':
11
+ return {
12
+ route: 'reject',
13
+ body: { reason: decision.reason, ...(decision.why ? { why: decision.why } : {}) }
14
+ };
15
+ case 'review': {
16
+ const { kind: _kind, ...review } = decision;
17
+ return { route: 'reviews', body: review };
18
+ }
19
+ case 'notes': {
20
+ const { kind: _kind, ...notes } = decision;
21
+ return { route: 'feedback', body: notes };
22
+ }
23
+ case 'status':
24
+ return { route: 'status', body: { status: decision.status } };
25
+ }
26
+ }
27
+ /** Sends one decision with the server's answer, or queues it when the server cannot be reached. */
28
+ export async function sendDecision(api, outbox, link, target, decision) {
29
+ assertTarget(target.page, target.component, target.iteration);
30
+ const { route, body } = request(decision);
31
+ const path = `${iterationPath(link.orgId, link.project, target.page, target.component, target.iteration)}/${route}`;
32
+ return outbox.send(api, path, body);
33
+ }
34
+ //# sourceMappingURL=reviews.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reviews.js","sourceRoot":"","sources":["../../src/runs/reviews.ts"],"names":[],"mappings":"AAAA,oFAAoF;AACpF,kHAAkH;AAClH,iGAAiG;AACjG,OAAO,EAAE,aAAa,EAAoC,MAAM,kBAAkB,CAAC;AAGnF,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAwB1C,SAAS,OAAO,CAAC,QAAkB;IACjC,QAAQ,QAAQ,CAAC,IAAI,EAAE,CAAC;QACtB,KAAK,QAAQ;YACX,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,IAAI,EAAE,EAAE,EAAE,CAAC;QACtE,KAAK,QAAQ;YACX,OAAO;gBACL,KAAK,EAAE,QAAQ;gBACf,IAAI,EAAE,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,QAAQ,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE;aAClF,CAAC;QACJ,KAAK,QAAQ,CAAC,CAAC,CAAC;YACd,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,EAAE,GAAG,QAAQ,CAAC;YAC5C,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;QAC5C,CAAC;QACD,KAAK,OAAO,CAAC,CAAC,CAAC;YACb,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,KAAK,EAAE,GAAG,QAAQ,CAAC;YAC3C,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;QAC5C,CAAC;QACD,KAAK,QAAQ;YACX,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC;IAClE,CAAC;AACH,CAAC;AAED,mGAAmG;AACnG,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,GAAc,EACd,MAAc,EACd,IAAc,EACd,MAAoB,EACpB,QAAkB;IAElB,YAAY,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC;IAC9D,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC1C,MAAM,IAAI,GAAG,GAAG,aAAa,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,SAAS,CAAC,IAAI,KAAK,EAAE,CAAC;IACpH,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;AACtC,CAAC"}
@@ -0,0 +1,96 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { ITERATION, SLUG, iterationDir } from '../repo/preview.js';
4
+ import { ROUGH_DIR } from '../repo/root.js';
5
+ import { assertRunId } from './store.js';
6
+ /** What a new slot shows until its agent has written it. */
7
+ export const PLACEHOLDER_INDEX = `export default function NotYetGenerated() {
8
+ return (
9
+ <div
10
+ style={{
11
+ display: "flex",
12
+ alignItems: "center",
13
+ justifyContent: "center",
14
+ minHeight: "100vh",
15
+ padding: "2rem",
16
+ textAlign: "center",
17
+ fontFamily: "system-ui, sans-serif",
18
+ color: "#5b6274",
19
+ background: "#f6f8fa",
20
+ }}
21
+ >
22
+ <p>Not yet generated. Your agent writes this iteration from its prompt in rough/.</p>
23
+ </div>
24
+ );
25
+ }
26
+ `;
27
+ /** v2's placeholder, which named Claude Code; a repo it prepared may still have some. */
28
+ const V2_PLACEHOLDER_LINE = 'Not yet generated. Paste the compiled prompt into Claude Code to fill this iteration.';
29
+ export function isPlaceholder(text) {
30
+ const trimmed = text.trim();
31
+ return trimmed === PLACEHOLDER_INDEX.trim() || trimmed.includes(V2_PLACEHOLDER_LINE);
32
+ }
33
+ export function assertTarget(page, component, iteration) {
34
+ if (!SLUG.test(page) || !SLUG.test(component) || !ITERATION.test(iteration)) {
35
+ throw new Error(`Not an iteration: ${page}/${component}/${iteration}`);
36
+ }
37
+ }
38
+ /** Where a run's prompt is kept, repo-relative with forward slashes. Committed with rough/. */
39
+ export function promptFile(page, component, runId) {
40
+ return `${ROUGH_DIR}/${page}/${component}/prompts/${assertRunId(runId)}.md`;
41
+ }
42
+ /** The one line every agent is given, whichever agent it is. */
43
+ export function handoffLine(prompt) {
44
+ return `Follow the instructions in ${prompt}`;
45
+ }
46
+ function toDisk(repoRoot, relative) {
47
+ return path.join(repoRoot, ...relative.split('/'));
48
+ }
49
+ function filesIn(dir, base = dir) {
50
+ if (!fs.existsSync(dir))
51
+ return [];
52
+ return fs.readdirSync(dir, { withFileTypes: true }).flatMap(entry => {
53
+ const full = path.join(dir, entry.name);
54
+ return entry.isDirectory() ? filesIn(full, base) : [path.relative(base, full)];
55
+ });
56
+ }
57
+ /** Whether an iteration's folder exists in rough/ with any file in it. */
58
+ export function iterationExists(repoRoot, page, component, id) {
59
+ return filesIn(toDisk(repoRoot, iterationDir(page, component, id))).length > 0;
60
+ }
61
+ /**
62
+ * Makes a run's folder: the placeholder for a new direction, or a copy of the parent for a fork
63
+ * or refinement, which the agent then changes. An existing iteration is never written over.
64
+ */
65
+ export function createSlot(repoRoot, slot) {
66
+ assertTarget(slot.page, slot.component, slot.iteration);
67
+ const relative = iterationDir(slot.page, slot.component, slot.iteration);
68
+ const dir = toDisk(repoRoot, relative);
69
+ if (filesIn(dir).length) {
70
+ throw new Error(`${relative} already exists. An existing iteration is never written over.`);
71
+ }
72
+ if (slot.parent) {
73
+ assertTarget(slot.page, slot.component, slot.parent);
74
+ const from = toDisk(repoRoot, iterationDir(slot.page, slot.component, slot.parent));
75
+ const files = filesIn(from);
76
+ if (!files.length) {
77
+ throw new Error(`${iterationDir(slot.page, slot.component, slot.parent)} is not in this repo, so it cannot be forked here.`);
78
+ }
79
+ for (const file of files) {
80
+ fs.mkdirSync(path.dirname(path.join(dir, file)), { recursive: true });
81
+ fs.copyFileSync(path.join(from, file), path.join(dir, file));
82
+ }
83
+ }
84
+ else {
85
+ fs.mkdirSync(dir, { recursive: true });
86
+ fs.writeFileSync(path.join(dir, 'index.tsx'), PLACEHOLDER_INDEX);
87
+ }
88
+ return relative;
89
+ }
90
+ /** Writes a run's prompt beside its component, with `\n` line endings. */
91
+ export function writePrompt(repoRoot, file, prompt) {
92
+ const target = toDisk(repoRoot, file);
93
+ fs.mkdirSync(path.dirname(target), { recursive: true });
94
+ fs.writeFileSync(target, prompt.replace(/\r\n/g, '\n'));
95
+ }
96
+ //# sourceMappingURL=slots.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slots.js","sourceRoot":"","sources":["../../src/runs/slots.ts"],"names":[],"mappings":"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"}