@12ui/design 0.2.90 → 0.2.92
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/README.md +3 -3
- package/SKILL.md +1 -1
- package/codex-plugin/plugin.json +14 -14
- package/dist/agent-plugin-step.d.ts +3 -1
- package/dist/agent-plugin-step.d.ts.map +1 -1
- package/dist/agent-plugin-step.js +35 -6
- package/dist/agent-plugin-step.js.map +1 -1
- package/dist/branch-client.d.ts +8 -0
- package/dist/branch-client.d.ts.map +1 -1
- package/dist/branch-client.js.map +1 -1
- package/dist/branch-core/branch-canvas.d.ts +41 -0
- package/dist/branch-core/branch-canvas.d.ts.map +1 -0
- package/dist/branch-core/branch-canvas.js +87 -0
- package/dist/branch-core/branch-canvas.js.map +1 -0
- package/dist/branch-core/branch-gates.d.ts +62 -0
- package/dist/branch-core/branch-gates.d.ts.map +1 -0
- package/dist/branch-core/branch-gates.js +56 -0
- package/dist/branch-core/branch-gates.js.map +1 -0
- package/dist/branch-core/branch-plan-model.d.ts +115 -0
- package/dist/branch-core/branch-plan-model.d.ts.map +1 -0
- package/dist/branch-core/branch-plan-model.js +75 -0
- package/dist/branch-core/branch-plan-model.js.map +1 -0
- package/dist/branch-core/branch-planner.d.ts +78 -0
- package/dist/branch-core/branch-planner.d.ts.map +1 -0
- package/dist/branch-core/branch-planner.js +441 -0
- package/dist/branch-core/branch-planner.js.map +1 -0
- package/dist/branch-core/branch-prompt.d.ts +40 -0
- package/dist/branch-core/branch-prompt.d.ts.map +1 -0
- package/dist/branch-core/branch-prompt.js +180 -0
- package/dist/branch-core/branch-prompt.js.map +1 -0
- package/dist/branch-core/index.d.ts +17 -0
- package/dist/branch-core/index.d.ts.map +1 -0
- package/dist/branch-core/index.js +19 -0
- package/dist/branch-core/index.js.map +1 -0
- package/dist/branch-dispatch-loop.d.ts +2 -2
- package/dist/branch-dispatch-loop.d.ts.map +1 -1
- package/dist/branch-dispatch-loop.js +4 -0
- package/dist/branch-dispatch-loop.js.map +1 -1
- package/dist/branch-downloads.d.ts +2 -2
- package/dist/branch-downloads.d.ts.map +1 -1
- package/dist/branch-engine.d.ts +61 -0
- package/dist/branch-engine.d.ts.map +1 -0
- package/dist/branch-engine.js +94 -0
- package/dist/branch-engine.js.map +1 -0
- package/dist/branch-execution-types.d.ts +5 -0
- package/dist/branch-execution-types.d.ts.map +1 -1
- package/dist/branch-execution.d.ts +2 -2
- package/dist/branch-execution.d.ts.map +1 -1
- package/dist/branch-execution.js +27 -4
- package/dist/branch-execution.js.map +1 -1
- package/dist/branch-local-call-wait.d.ts +58 -0
- package/dist/branch-local-call-wait.d.ts.map +1 -0
- package/dist/branch-local-call-wait.js +122 -0
- package/dist/branch-local-call-wait.js.map +1 -0
- package/dist/branch-local-client.d.ts +108 -0
- package/dist/branch-local-client.d.ts.map +1 -0
- package/dist/branch-local-client.js +477 -0
- package/dist/branch-local-client.js.map +1 -0
- package/dist/branch-local-plan.d.ts +64 -0
- package/dist/branch-local-plan.d.ts.map +1 -0
- package/dist/branch-local-plan.js +281 -0
- package/dist/branch-local-plan.js.map +1 -0
- package/dist/branch-local-session-adoption.d.ts +35 -0
- package/dist/branch-local-session-adoption.d.ts.map +1 -0
- package/dist/branch-local-session-adoption.js +185 -0
- package/dist/branch-local-session-adoption.js.map +1 -0
- package/dist/branch-materialize.d.ts +2 -2
- package/dist/branch-materialize.d.ts.map +1 -1
- package/dist/branch-run-observation.d.ts +2 -2
- package/dist/branch-run-observation.d.ts.map +1 -1
- package/dist/branch-run-observation.js.map +1 -1
- package/dist/branch-run-record.d.ts +8 -0
- package/dist/branch-run-record.d.ts.map +1 -1
- package/dist/branch-run-record.js.map +1 -1
- package/dist/branch-schedule.d.ts +1 -1
- package/dist/branch-schedule.js +1 -1
- package/dist/cli-branch-command.d.ts +9 -2
- package/dist/cli-branch-command.d.ts.map +1 -1
- package/dist/cli-branch-command.js +61 -16
- package/dist/cli-branch-command.js.map +1 -1
- package/dist/cli-help/design.d.ts +1 -1
- package/dist/cli-help/design.d.ts.map +1 -1
- package/dist/cli-help/design.js +1 -0
- package/dist/cli-help/design.js.map +1 -1
- package/dist/cli-help/index.d.ts +1 -1
- package/dist/cli-local-dispatch.d.ts.map +1 -1
- package/dist/cli-local-dispatch.js +6 -2
- package/dist/cli-local-dispatch.js.map +1 -1
- package/dist/cli-next-command.d.ts.map +1 -1
- package/dist/cli-next-command.js +3 -1
- package/dist/cli-next-command.js.map +1 -1
- package/dist/cli-skill-command.d.ts.map +1 -1
- package/dist/cli-skill-command.js +3 -0
- package/dist/cli-skill-command.js.map +1 -1
- package/dist/cli-usage.js +1 -1
- package/dist/codex-plugin-installer.d.ts +7 -1
- package/dist/codex-plugin-installer.d.ts.map +1 -1
- package/dist/codex-plugin-installer.js +39 -63
- package/dist/codex-plugin-installer.js.map +1 -1
- package/dist/codex-skill-config.d.ts +33 -9
- package/dist/codex-skill-config.d.ts.map +1 -1
- package/dist/codex-skill-config.js +271 -104
- package/dist/codex-skill-config.js.map +1 -1
- package/dist/codex-toml.d.ts +15 -0
- package/dist/codex-toml.d.ts.map +1 -0
- package/dist/codex-toml.js +45 -0
- package/dist/codex-toml.js.map +1 -0
- package/dist/legacy-codex-cleanup.d.ts +4 -0
- package/dist/legacy-codex-cleanup.d.ts.map +1 -1
- package/dist/legacy-codex-cleanup.js +53 -32
- package/dist/legacy-codex-cleanup.js.map +1 -1
- package/dist/legacy-skill-catalog.d.ts.map +1 -1
- package/dist/legacy-skill-catalog.js +10 -0
- package/dist/legacy-skill-catalog.js.map +1 -1
- package/dist/slate-branch-runner.d.ts +9 -3
- package/dist/slate-branch-runner.d.ts.map +1 -1
- package/dist/slate-branch-runner.js +22 -6
- package/dist/slate-branch-runner.js.map +1 -1
- package/dist/slate-image-executor.d.ts +1 -0
- package/dist/slate-image-executor.d.ts.map +1 -1
- package/dist/slate-image-executor.js +1 -1
- package/dist/slate-image-executor.js.map +1 -1
- package/dist/slate-runner-context.d.ts +6 -0
- package/dist/slate-runner-context.d.ts.map +1 -1
- package/dist/slate-runner-context.js.map +1 -1
- package/dist/slate-runner-main.d.ts +3 -0
- package/dist/slate-runner-main.d.ts.map +1 -1
- package/dist/slate-runner-main.js +4 -0
- package/dist/slate-runner-main.js.map +1 -1
- package/dist/workspace-draw-branch.d.ts +5 -2
- package/dist/workspace-draw-branch.d.ts.map +1 -1
- package/dist/workspace-draw-branch.js +28 -22
- package/dist/workspace-draw-branch.js.map +1 -1
- package/dist/workspace-draw-codex.d.ts +5 -1
- package/dist/workspace-draw-codex.d.ts.map +1 -1
- package/dist/workspace-draw-codex.js +1 -0
- package/dist/workspace-draw-codex.js.map +1 -1
- package/dist/workspace-draw-run.d.ts +2 -1
- package/dist/workspace-draw-run.d.ts.map +1 -1
- package/dist/workspace-draw-run.js +7 -2
- package/dist/workspace-draw-run.js.map +1 -1
- package/open-design.json +2 -2
- package/package.json +3 -2
- package/skills/12ui-design/outputs.md +1 -1
|
@@ -0,0 +1,477 @@
|
|
|
1
|
+
import { createHash, randomUUID } from 'node:crypto';
|
|
2
|
+
import { closeSync, openSync, readFileSync, unlinkSync, writeSync } from 'node:fs';
|
|
3
|
+
import { mkdir, readFile, rename, rm, writeFile } from 'node:fs/promises';
|
|
4
|
+
import { hostname } from 'node:os';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
import { BUILD_SLOTS, CREATE_ASPECT_SIZES, MAX_BRANCH_CELLS, branchAspectForCanvas, branchConceptText, branchFooterSeedSlot, branchGenerationSourceKeys, branchPlanCells, branchPlanParseOptions, branchPromptFor, branchProviderCanvas, evaluateBranchDispatchGate, parseBranchPlan, resolveBranchPlanCanvases, } from './branch-core/index.js';
|
|
7
|
+
import { BranchApiError, } from './branch-client.js';
|
|
8
|
+
import { runBranchPlanCall, waitForProcessGroup } from './branch-local-plan.js';
|
|
9
|
+
import { readImageDimensions } from './image-dimensions.js';
|
|
10
|
+
import { IMAGE_CALL_TIMEOUT_MS } from './slate-image-executor.js';
|
|
11
|
+
import { adoptUnannouncedSession } from './branch-local-session-adoption.js';
|
|
12
|
+
import { imageCallFinished, waitForUnrecordedCall } from './branch-local-call-wait.js';
|
|
13
|
+
import { callDirectoryOf, drawOptionWithCodex, retryCallIdOf } from './workspace-draw-codex.js';
|
|
14
|
+
import { OPTION_FAILURES } from './workspace-draw-messages.js';
|
|
15
|
+
/**
|
|
16
|
+
* The branch build process on the person's own Codex, behind the same four
|
|
17
|
+
* methods the hosted client answers (`BranchRunClient`), so `executeBranchRun`,
|
|
18
|
+
* the dispatch loop, the records and both workspaces' followers run unchanged.
|
|
19
|
+
* Every decision is the hosted one, from the shared branch core: the planner
|
|
20
|
+
* call (branch-local-plan.ts) and its parse with the bounded retry, the trim,
|
|
21
|
+
* derived chrome, canvases and slots, the dispatch gates (a continuation waits
|
|
22
|
+
* for its preceding viewport, a footer for the footer seed unless the seed
|
|
23
|
+
* failed), the reference order (approved design, preceding viewport, footer
|
|
24
|
+
* seed) and the per-screen prompt rebuilt from the references that arrived.
|
|
25
|
+
* Each screen is one native Codex image call through the workspace's own
|
|
26
|
+
* executor (`drawOptionWithCodex`: the prompt copied verbatim into the image
|
|
27
|
+
* tool, one more sample only when the tool refused the first).
|
|
28
|
+
*
|
|
29
|
+
* State lives in `<branchDir>/local/`: `run.json` (the ledger: plan, cells and
|
|
30
|
+
* every slot's status, call id, prompt and references), `winner.<ext>`,
|
|
31
|
+
* `screens/<slot>.png` (each delivered screen: the bytes the board receives
|
|
32
|
+
* and the bytes a later screen is conditioned on) and `calls/` (the run-store
|
|
33
|
+
* custody of every Codex call). Call ids are stable (`branch-plan:<run>:<n>`,
|
|
34
|
+
* `branch:<run>:<slot>`), so a resumed run settles each call by the store's
|
|
35
|
+
* rule — an answer that landed is reused, a dispatched call is recovered from
|
|
36
|
+
* its own session or refused — and never pays for one twice.
|
|
37
|
+
*/
|
|
38
|
+
export const LOCAL_BRANCH_DIRECTORY = 'local';
|
|
39
|
+
const RUN_FILE = 'run.json';
|
|
40
|
+
const LOCK_FILE = 'run.lock';
|
|
41
|
+
const sha256 = (bytes) => createHash('sha256').update(bytes).digest('hex');
|
|
42
|
+
export const localBranchRunId = (runKey) => `local-${sha256(runKey).slice(0, 40)}`;
|
|
43
|
+
export const localBranchCallId = (runId, slot) => `branch:${runId}:${slot}`;
|
|
44
|
+
const writeAtomically = async (file, bytes) => {
|
|
45
|
+
await mkdir(path.dirname(file), { recursive: true });
|
|
46
|
+
const temporary = `${file}.${randomUUID()}.tmp`;
|
|
47
|
+
try {
|
|
48
|
+
await writeFile(temporary, bytes, { flag: 'wx', mode: 0o600 });
|
|
49
|
+
await rename(temporary, file);
|
|
50
|
+
}
|
|
51
|
+
finally {
|
|
52
|
+
await rm(temporary, { force: true });
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
const readJson = async (file) => {
|
|
56
|
+
try {
|
|
57
|
+
return JSON.parse(await readFile(file, 'utf8'));
|
|
58
|
+
}
|
|
59
|
+
catch (error) {
|
|
60
|
+
if (error.code === 'ENOENT')
|
|
61
|
+
return null;
|
|
62
|
+
throw error;
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
export const localBranchDirectory = (branchDir) => path.join(path.resolve(branchDir), LOCAL_BRANCH_DIRECTORY);
|
|
66
|
+
/** The run as the hosted create route projects it (workers/api/src/create/runEnvelope.ts). */
|
|
67
|
+
export const localBranchEnvelope = (run, inFlight = new Set()) => {
|
|
68
|
+
const winnerCanvas = { width: run.winner.width, height: run.winner.height };
|
|
69
|
+
const statusOf = (slot) => {
|
|
70
|
+
const status = run.slots[slot].status;
|
|
71
|
+
// A call this process is not running is offered again; its dispatch settles it by its call id.
|
|
72
|
+
return status === 'dispatched' && !inFlight.has(slot) ? 'pending' : status;
|
|
73
|
+
};
|
|
74
|
+
return {
|
|
75
|
+
id: run.runId,
|
|
76
|
+
concept: run.concept,
|
|
77
|
+
aspect: run.aspect,
|
|
78
|
+
mode: 'inspiration',
|
|
79
|
+
imageModel: null,
|
|
80
|
+
imageProfile: null,
|
|
81
|
+
retain: null,
|
|
82
|
+
source: 'build',
|
|
83
|
+
createdAt: run.createdAt,
|
|
84
|
+
plan: {
|
|
85
|
+
sitePurpose: run.plan.sitePurpose,
|
|
86
|
+
statusUpdate: run.plan.statusUpdate,
|
|
87
|
+
approvedScreenSummary: run.plan.approvedScreenSummary,
|
|
88
|
+
...(run.plan.winnerCanvas ? { winnerCanvas: run.plan.winnerCanvas } : {}),
|
|
89
|
+
pages: run.plan.pages.map((page) => ({
|
|
90
|
+
index: page.index,
|
|
91
|
+
kind: page.kind,
|
|
92
|
+
title: page.title,
|
|
93
|
+
pageType: page.pageType,
|
|
94
|
+
surfaceType: page.surfaceType,
|
|
95
|
+
purpose: page.purpose,
|
|
96
|
+
...(page.sourceEndsHere === undefined ? {} : { sourceEndsHere: page.sourceEndsHere }),
|
|
97
|
+
slots: run.cells.filter((cell) => cell.placement.pageIndex === page.index).map((cell) => cell.slot),
|
|
98
|
+
})),
|
|
99
|
+
},
|
|
100
|
+
candidates: run.cells.map((cell) => {
|
|
101
|
+
const { placement } = cell;
|
|
102
|
+
const slot = run.slots[cell.slot];
|
|
103
|
+
const canvas = branchProviderCanvas(placement.canvasDecision?.sourceCanvas ?? winnerCanvas);
|
|
104
|
+
const status = statusOf(cell.slot);
|
|
105
|
+
return {
|
|
106
|
+
slot: cell.slot,
|
|
107
|
+
status,
|
|
108
|
+
direction: cell.label,
|
|
109
|
+
width: canvas.width,
|
|
110
|
+
height: canvas.height,
|
|
111
|
+
pageIndex: placement.pageIndex,
|
|
112
|
+
viewportOrdinal: placement.viewportOrdinal,
|
|
113
|
+
header: placement.header,
|
|
114
|
+
footer: placement.footer,
|
|
115
|
+
pageEndsHere: placement.pageEndsHere,
|
|
116
|
+
dependsOnSlot: placement.dependsOnSlot,
|
|
117
|
+
content: placement.content,
|
|
118
|
+
...(placement.contentSlotId ? { contentSlotId: placement.contentSlotId } : {}),
|
|
119
|
+
...(placement.slotType ? { slotType: placement.slotType } : {}),
|
|
120
|
+
...(placement.targetWords !== undefined ? { targetWords: placement.targetWords } : {}),
|
|
121
|
+
...(placement.canvasDecision ? { canvasDecision: placement.canvasDecision } : {}),
|
|
122
|
+
...(status === 'succeeded' ? { image: `local:screens/${cell.slot}.png` } : {}),
|
|
123
|
+
...(status === 'failed' && slot.error ? { error: slot.error } : {}),
|
|
124
|
+
};
|
|
125
|
+
}),
|
|
126
|
+
};
|
|
127
|
+
};
|
|
128
|
+
/** The recorded run of a local branch, read only (`12ui next` refreshes a codex run from it). */
|
|
129
|
+
export const readLocalBranchEnvelope = async (branchDir) => {
|
|
130
|
+
const run = await readJson(path.join(localBranchDirectory(branchDir), RUN_FILE));
|
|
131
|
+
// A reader outside the run reports a dispatched screen as the ledger records it (another process may be drawing it).
|
|
132
|
+
const dispatched = new Set(Object.entries(run?.slots ?? {}).filter(([, slot]) => slot.status === 'dispatched').map(([slot]) => slot));
|
|
133
|
+
return run ? localBranchEnvelope(run, dispatched) : null;
|
|
134
|
+
};
|
|
135
|
+
/** One exclusive holder per run folder across processes: two writers would race the same paid calls. */
|
|
136
|
+
const takeRunLock = (directory) => {
|
|
137
|
+
const file = path.join(directory, LOCK_FILE);
|
|
138
|
+
const owner = JSON.stringify({ pid: process.pid, hostname: hostname(), at: new Date().toISOString() });
|
|
139
|
+
const acquire = () => {
|
|
140
|
+
try {
|
|
141
|
+
const handle = openSync(file, 'wx', 0o600);
|
|
142
|
+
writeSync(handle, owner);
|
|
143
|
+
closeSync(handle);
|
|
144
|
+
return true;
|
|
145
|
+
}
|
|
146
|
+
catch (error) {
|
|
147
|
+
if (error.code !== 'EEXIST')
|
|
148
|
+
throw error;
|
|
149
|
+
return false;
|
|
150
|
+
}
|
|
151
|
+
};
|
|
152
|
+
if (!acquire()) {
|
|
153
|
+
let previous = null;
|
|
154
|
+
try {
|
|
155
|
+
previous = JSON.parse(readFileSync(file, 'utf8'));
|
|
156
|
+
}
|
|
157
|
+
catch {
|
|
158
|
+
previous = null;
|
|
159
|
+
}
|
|
160
|
+
const alive = previous?.hostname === hostname() && Number.isInteger(previous.pid) && (() => {
|
|
161
|
+
try {
|
|
162
|
+
process.kill(previous.pid, 0);
|
|
163
|
+
return true;
|
|
164
|
+
}
|
|
165
|
+
catch (error) {
|
|
166
|
+
return error.code === 'EPERM';
|
|
167
|
+
}
|
|
168
|
+
})();
|
|
169
|
+
if (alive || (previous && previous.hostname !== hostname())) {
|
|
170
|
+
throw new BranchApiError(`Another 12ui process is running this branch (${file}).`, 409, 'run_locked');
|
|
171
|
+
}
|
|
172
|
+
try {
|
|
173
|
+
unlinkSync(file);
|
|
174
|
+
}
|
|
175
|
+
catch { /* raced: the acquire below decides */ }
|
|
176
|
+
if (!acquire())
|
|
177
|
+
throw new BranchApiError(`Another 12ui process is running this branch (${file}).`, 409, 'run_locked');
|
|
178
|
+
}
|
|
179
|
+
let released = false;
|
|
180
|
+
const release = () => {
|
|
181
|
+
if (released)
|
|
182
|
+
return;
|
|
183
|
+
released = true;
|
|
184
|
+
try {
|
|
185
|
+
unlinkSync(file);
|
|
186
|
+
}
|
|
187
|
+
catch { /* already gone */ }
|
|
188
|
+
process.removeListener('exit', release);
|
|
189
|
+
};
|
|
190
|
+
process.once('exit', release);
|
|
191
|
+
return release;
|
|
192
|
+
};
|
|
193
|
+
/** Model-class outcomes keep the hosted failure codes; the sentence is the workspace's fixed one. */
|
|
194
|
+
const failureCode = (failure) => (failure === OPTION_FAILURES.timeout ? 'provider_timeout'
|
|
195
|
+
: failure === OPTION_FAILURES.changed ? 'request_changed'
|
|
196
|
+
: 'provider_error');
|
|
197
|
+
export const createLocalBranchClient = (options) => {
|
|
198
|
+
const directory = localBranchDirectory(options.branchDir);
|
|
199
|
+
const imageTimeoutMs = options.timeouts?.imageMs ?? IMAGE_CALL_TIMEOUT_MS;
|
|
200
|
+
const runFile = path.join(directory, RUN_FILE);
|
|
201
|
+
const inFlight = new Set();
|
|
202
|
+
let release = null;
|
|
203
|
+
let cached = null;
|
|
204
|
+
let winnerBytes = null;
|
|
205
|
+
// Every read-modify-write of run.json happens on this one chain, so parallel screens never lose each other's updates.
|
|
206
|
+
let chain = Promise.resolve();
|
|
207
|
+
const serialized = (work) => {
|
|
208
|
+
const next = chain.then(work, work);
|
|
209
|
+
chain = next.catch(() => undefined);
|
|
210
|
+
return next;
|
|
211
|
+
};
|
|
212
|
+
const lock = async () => {
|
|
213
|
+
if (release)
|
|
214
|
+
return;
|
|
215
|
+
await mkdir(directory, { recursive: true, mode: 0o700 });
|
|
216
|
+
release = takeRunLock(directory);
|
|
217
|
+
};
|
|
218
|
+
const load = async (runId) => {
|
|
219
|
+
await lock();
|
|
220
|
+
cached ??= await readJson(runFile);
|
|
221
|
+
if (!cached || (runId !== undefined && cached.runId !== runId)) {
|
|
222
|
+
throw new BranchApiError(`This local branch run does not exist in ${directory}.`, 404, 'not_found');
|
|
223
|
+
}
|
|
224
|
+
return cached;
|
|
225
|
+
};
|
|
226
|
+
const save = async (run) => {
|
|
227
|
+
cached = run;
|
|
228
|
+
await writeAtomically(runFile, `${JSON.stringify(run, null, 2)}\n`);
|
|
229
|
+
};
|
|
230
|
+
const update = (mutate) => serialized(async () => {
|
|
231
|
+
const run = await load();
|
|
232
|
+
mutate(run);
|
|
233
|
+
await save(run);
|
|
234
|
+
return run;
|
|
235
|
+
});
|
|
236
|
+
const winner = async (run) => (winnerBytes ??= await readFile(path.join(directory, run.winner.file)));
|
|
237
|
+
const screenFile = (slot) => path.join(directory, 'screens', `${slot}.png`);
|
|
238
|
+
const plan = async (input, runKey) => {
|
|
239
|
+
if (!input.referenceImage) {
|
|
240
|
+
throw new BranchApiError('A local branch starts from the approved design image itself.', 400, 'invalid_request');
|
|
241
|
+
}
|
|
242
|
+
if (input.maxScreens !== undefined && (!Number.isSafeInteger(input.maxScreens) || input.maxScreens < 1 || input.maxScreens > MAX_BRANCH_CELLS)) {
|
|
243
|
+
throw new BranchApiError(`maxScreens must be an integer from 1 to ${MAX_BRANCH_CELLS}.`, 400, 'invalid_max_screens');
|
|
244
|
+
}
|
|
245
|
+
const concept = branchConceptText(input.concept);
|
|
246
|
+
if (!concept)
|
|
247
|
+
throw new BranchApiError('concept must be a non-empty string.', 400, 'invalid_concept');
|
|
248
|
+
const bytes = Buffer.from(input.referenceImage.data, 'base64');
|
|
249
|
+
if (sha256(bytes) !== input.referenceImage.sha256) {
|
|
250
|
+
throw new BranchApiError('The starting design does not match its sha256.', 400, 'invalid_reference_image');
|
|
251
|
+
}
|
|
252
|
+
const winnerCanvas = await readImageDimensions(bytes);
|
|
253
|
+
const runId = localBranchRunId(runKey);
|
|
254
|
+
const extension = input.referenceImage.mediaType === 'image/jpeg' ? 'jpg' : input.referenceImage.mediaType === 'image/webp' ? 'webp' : 'png';
|
|
255
|
+
const winnerFile = `winner.${extension}`;
|
|
256
|
+
await writeAtomically(path.join(directory, winnerFile), bytes);
|
|
257
|
+
winnerBytes = bytes;
|
|
258
|
+
// The hosted bounded retry: a second planner call only when the first answer fails the structural parse.
|
|
259
|
+
const calls = [];
|
|
260
|
+
let parsed = null;
|
|
261
|
+
for (let attempt = 0; attempt < 2 && !parsed; attempt += 1) {
|
|
262
|
+
let answer;
|
|
263
|
+
try {
|
|
264
|
+
answer = await runBranchPlanCall({
|
|
265
|
+
root: directory,
|
|
266
|
+
runId,
|
|
267
|
+
attempt,
|
|
268
|
+
concept,
|
|
269
|
+
...(input.maxScreens === undefined ? {} : { maxScreens: input.maxScreens }),
|
|
270
|
+
winner: { bytes, mediaType: input.referenceImage.mediaType, sha256: input.referenceImage.sha256 },
|
|
271
|
+
env: options.env,
|
|
272
|
+
...(options.processOptions ? { processOptions: options.processOptions } : {}),
|
|
273
|
+
...(options.timeouts?.planMs === undefined ? {} : { timeoutMs: options.timeouts.planMs }),
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
catch (error) {
|
|
277
|
+
if (error.code === 'NEEDS_RECONCILIATION') {
|
|
278
|
+
// Settled only once the call is over or past the window it is allowed (branch-local-plan.ts): no answer is still coming.
|
|
279
|
+
throw new BranchApiError(`The branch planner call on Codex ended without a plan (${directory}). Start a new branch run.`, 502, 'build_plan_failed');
|
|
280
|
+
}
|
|
281
|
+
throw new BranchApiError(`Codex could not plan this branch: ${error instanceof Error ? error.message : String(error)}`, 424, 'codex_unavailable');
|
|
282
|
+
}
|
|
283
|
+
try {
|
|
284
|
+
parsed = parseBranchPlan(answer.raw, branchPlanParseOptions(concept, input.maxScreens));
|
|
285
|
+
calls.push({ callId: answer.callId, reused: answer.reused });
|
|
286
|
+
}
|
|
287
|
+
catch (error) {
|
|
288
|
+
calls.push({ callId: answer.callId, reused: answer.reused, parseError: error instanceof Error ? error.message : String(error) });
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
if (!parsed) {
|
|
292
|
+
throw new BranchApiError(`The branch planner returned no valid plan after a bounded retry: ${calls.map((call) => call.parseError).join(' / ')}`, 502, 'build_plan_failed');
|
|
293
|
+
}
|
|
294
|
+
const resolved = resolveBranchPlanCanvases({
|
|
295
|
+
plan: parsed,
|
|
296
|
+
winnerCanvas,
|
|
297
|
+
...(input.aspect ? { defaultDeclaredCanvas: CREATE_ASPECT_SIZES[input.aspect] } : {}),
|
|
298
|
+
});
|
|
299
|
+
const cells = branchPlanCells(resolved, BUILD_SLOTS);
|
|
300
|
+
const run = {
|
|
301
|
+
version: 1,
|
|
302
|
+
engine: 'codex',
|
|
303
|
+
runId,
|
|
304
|
+
runKey,
|
|
305
|
+
concept,
|
|
306
|
+
aspect: input.aspect ?? branchAspectForCanvas(winnerCanvas),
|
|
307
|
+
...(input.maxScreens === undefined ? {} : { maxScreens: input.maxScreens }),
|
|
308
|
+
createdAt: new Date().toISOString(),
|
|
309
|
+
winner: { file: winnerFile, sha256: input.referenceImage.sha256, mediaType: input.referenceImage.mediaType, ...winnerCanvas },
|
|
310
|
+
planner: { calls },
|
|
311
|
+
plan: resolved,
|
|
312
|
+
cells,
|
|
313
|
+
footerSeedSlot: branchFooterSeedSlot(cells),
|
|
314
|
+
slots: Object.fromEntries(cells.map((cell) => [cell.slot, { status: 'pending' }])),
|
|
315
|
+
};
|
|
316
|
+
await save(run);
|
|
317
|
+
return run;
|
|
318
|
+
};
|
|
319
|
+
const settle = async (run, cell, slot) => {
|
|
320
|
+
const images = await Promise.all(slot.references.map(async (reference) => (reference.key === 'winner' ? await winner(run) : await readFile(screenFile(reference.key)))));
|
|
321
|
+
// A call an earlier process left running is waited out, then settled by its id (never dispatched again): by its
|
|
322
|
+
// process group when that was recorded, else until its session shows it finished or its window closed (a process
|
|
323
|
+
// that died between the spawn and the record left no group to wait on: branch-local-call-wait.ts).
|
|
324
|
+
const callIds = [slot.callId, retryCallIdOf(slot.callId)];
|
|
325
|
+
const callWaits = [];
|
|
326
|
+
for (const callId of callIds) {
|
|
327
|
+
if (slot.pgid && slot.pgidCallId === callId) {
|
|
328
|
+
await waitForProcessGroup(slot.pgid, imageTimeoutMs + 60_000);
|
|
329
|
+
continue;
|
|
330
|
+
}
|
|
331
|
+
const callDir = callDirectoryOf(directory, callId);
|
|
332
|
+
const wait = await waitForUnrecordedCall({ callDir, timeoutMs: imageTimeoutMs, finished: imageCallFinished(callDir) });
|
|
333
|
+
if (wait)
|
|
334
|
+
callWaits.push(wait);
|
|
335
|
+
}
|
|
336
|
+
// A call whose process died before its child's thread id reached the call's events: its session is found in the
|
|
337
|
+
// Codex home by its own inputs, so the store's recovery can adopt the image (branch-local-session-adoption.ts).
|
|
338
|
+
const sessionSearches = (await Promise.all(callIds.map((callId) => (adoptUnannouncedSession(callDirectoryOf(directory, callId)))))).filter((search) => search !== null);
|
|
339
|
+
const searched = { ...(callWaits.length ? { callWaits } : {}), ...(sessionSearches.length ? { sessionSearches } : {}) };
|
|
340
|
+
const frame = branchProviderCanvas(cell.placement.canvasDecision?.sourceCanvas ?? { width: run.winner.width, height: run.winner.height });
|
|
341
|
+
const processOptions = {
|
|
342
|
+
...options.processOptions,
|
|
343
|
+
onSpawn: async (child) => {
|
|
344
|
+
const pgidCallId = callIds.find((callId) => callDirectoryOf(directory, callId) === child.callDir);
|
|
345
|
+
await update((current) => { Object.assign(current.slots[cell.slot], { pgid: child.pgid, pgidCallId }); });
|
|
346
|
+
await options.processOptions?.onSpawn?.(child);
|
|
347
|
+
},
|
|
348
|
+
};
|
|
349
|
+
const result = await drawOptionWithCodex({
|
|
350
|
+
root: directory,
|
|
351
|
+
env: options.env,
|
|
352
|
+
option: { callId: slot.callId, prompt: slot.prompt, frame },
|
|
353
|
+
images,
|
|
354
|
+
processOptions,
|
|
355
|
+
timeoutMs: imageTimeoutMs,
|
|
356
|
+
});
|
|
357
|
+
if (result.kind === 'drawn') {
|
|
358
|
+
await writeAtomically(screenFile(cell.slot), result.png);
|
|
359
|
+
const dimensions = await readImageDimensions(result.png);
|
|
360
|
+
await update((current) => {
|
|
361
|
+
current.slots[cell.slot] = {
|
|
362
|
+
...current.slots[cell.slot],
|
|
363
|
+
status: 'succeeded',
|
|
364
|
+
settledAt: new Date().toISOString(),
|
|
365
|
+
screen: { sha256: sha256(result.png), ...dimensions },
|
|
366
|
+
codex: { ...result.details, reused: result.reused, ...searched },
|
|
367
|
+
};
|
|
368
|
+
delete current.slots[cell.slot].pgid;
|
|
369
|
+
delete current.slots[cell.slot].pgidCallId;
|
|
370
|
+
});
|
|
371
|
+
return;
|
|
372
|
+
}
|
|
373
|
+
if (result.kind === 'failed') {
|
|
374
|
+
await update((current) => {
|
|
375
|
+
current.slots[cell.slot] = {
|
|
376
|
+
...current.slots[cell.slot],
|
|
377
|
+
status: 'failed',
|
|
378
|
+
settledAt: new Date().toISOString(),
|
|
379
|
+
error: { code: failureCode(result.failure), message: result.failure },
|
|
380
|
+
codex: { ...result.details, ...searched },
|
|
381
|
+
};
|
|
382
|
+
delete current.slots[cell.slot].pgid;
|
|
383
|
+
delete current.slots[cell.slot].pgidCallId;
|
|
384
|
+
});
|
|
385
|
+
return;
|
|
386
|
+
}
|
|
387
|
+
// Codex itself could not draw: the slot goes back to waiting with its call identity kept, and the run stops.
|
|
388
|
+
await update((current) => {
|
|
389
|
+
current.slots[cell.slot] = { ...current.slots[cell.slot], status: 'pending', codex: { ...result.details, environment: result.error, ...searched } };
|
|
390
|
+
delete current.slots[cell.slot].pgid;
|
|
391
|
+
delete current.slots[cell.slot].pgidCallId;
|
|
392
|
+
});
|
|
393
|
+
throw new BranchApiError(`Codex stopped drawing this branch: ${result.error}`, 424, 'codex_unavailable');
|
|
394
|
+
};
|
|
395
|
+
return {
|
|
396
|
+
startBuildRun: async (input, runKey) => serialized(async () => {
|
|
397
|
+
await lock();
|
|
398
|
+
const existing = cached ?? await readJson(runFile);
|
|
399
|
+
if (existing) {
|
|
400
|
+
if (existing.runKey !== runKey) {
|
|
401
|
+
throw new BranchApiError('This folder holds a different local branch run.', 409, 'idempotency_conflict');
|
|
402
|
+
}
|
|
403
|
+
cached = existing;
|
|
404
|
+
return localBranchEnvelope(existing, inFlight);
|
|
405
|
+
}
|
|
406
|
+
return localBranchEnvelope(await plan(input, runKey), inFlight);
|
|
407
|
+
}),
|
|
408
|
+
getRun: async (runId) => localBranchEnvelope(await serialized(() => load(runId)), inFlight),
|
|
409
|
+
dispatchScreen: async (runId, slotName) => {
|
|
410
|
+
const claimed = await serialized(async () => {
|
|
411
|
+
const run = await load(runId);
|
|
412
|
+
const cell = run.cells.find((entry) => entry.slot === slotName);
|
|
413
|
+
if (!cell)
|
|
414
|
+
throw new BranchApiError('This candidate does not exist.', 404, 'not_found');
|
|
415
|
+
const slot = run.slots[slotName];
|
|
416
|
+
if (slot.status === 'succeeded' || slot.status === 'failed')
|
|
417
|
+
return null;
|
|
418
|
+
if (inFlight.has(slotName))
|
|
419
|
+
throw new BranchApiError('This candidate is already generating.', 409, 'candidate_in_flight');
|
|
420
|
+
if (!slot.callId) {
|
|
421
|
+
const gate = evaluateBranchDispatchGate({
|
|
422
|
+
slot: slotName,
|
|
423
|
+
placement: cell.placement,
|
|
424
|
+
candidates: run.cells.map((entry) => ({
|
|
425
|
+
slot: entry.slot,
|
|
426
|
+
status: run.slots[entry.slot].status,
|
|
427
|
+
outputKey: run.slots[entry.slot].status === 'succeeded' ? entry.slot : null,
|
|
428
|
+
placement: entry.placement,
|
|
429
|
+
})),
|
|
430
|
+
});
|
|
431
|
+
if (!gate.ok) {
|
|
432
|
+
throw new BranchApiError(gate.code === 'dependency_pending'
|
|
433
|
+
? `Screen ${slotName} continues screen ${gate.dependsOn}; generate ${gate.dependsOn} first.`
|
|
434
|
+
: `Screen ${slotName} closes a page and waits for the site footer drawn by screen ${gate.dependsOn}.`, 409, gate.code, { dependsOn: gate.dependsOn });
|
|
435
|
+
}
|
|
436
|
+
const references = branchGenerationSourceKeys({
|
|
437
|
+
rootKey: 'winner',
|
|
438
|
+
dependencyKey: gate.dependencyKey,
|
|
439
|
+
footerReferenceKey: gate.footerReferenceKey,
|
|
440
|
+
});
|
|
441
|
+
slot.callId = localBranchCallId(run.runId, slotName);
|
|
442
|
+
slot.references = references;
|
|
443
|
+
slot.prompt = branchPromptFor(run.plan, cell.placement, {
|
|
444
|
+
hasDependencyReference: references.some((entry) => entry.role === 'dependency'),
|
|
445
|
+
hasFooterReference: references.some((entry) => entry.role === 'footer'),
|
|
446
|
+
});
|
|
447
|
+
}
|
|
448
|
+
// A slot with a call id keeps it, its prompt and its references: a resumed dispatch is the same call.
|
|
449
|
+
slot.status = 'dispatched';
|
|
450
|
+
slot.dispatchedAt ??= new Date().toISOString();
|
|
451
|
+
delete slot.error;
|
|
452
|
+
await save(run);
|
|
453
|
+
inFlight.add(slotName);
|
|
454
|
+
return { run, cell, slot: { ...slot } };
|
|
455
|
+
});
|
|
456
|
+
if (claimed) {
|
|
457
|
+
try {
|
|
458
|
+
await settle(claimed.run, claimed.cell, claimed.slot);
|
|
459
|
+
}
|
|
460
|
+
finally {
|
|
461
|
+
inFlight.delete(slotName);
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
return localBranchEnvelope(await serialized(() => load(runId)), inFlight);
|
|
465
|
+
},
|
|
466
|
+
downloadScreen: async (runId, slot) => {
|
|
467
|
+
await serialized(() => load(runId));
|
|
468
|
+
const bytes = new Uint8Array(await readFile(screenFile(slot)));
|
|
469
|
+
return { bytes, sha256: sha256(bytes) };
|
|
470
|
+
},
|
|
471
|
+
close: () => {
|
|
472
|
+
release?.();
|
|
473
|
+
release = null;
|
|
474
|
+
},
|
|
475
|
+
};
|
|
476
|
+
};
|
|
477
|
+
//# sourceMappingURL=branch-local-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"branch-local-client.js","sourceRoot":"","sources":["../src/branch-local-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import type { CodexProcessOptions } from './slate-image-executor.js';
|
|
2
|
+
/**
|
|
3
|
+
* The branch planner on the person's own Codex: the hosted planner call
|
|
4
|
+
* (workers/api/src/create/buildPlan.ts `deriveBuildPlan`) made as one
|
|
5
|
+
* `codex exec` turn. Same model and effort (gpt-6.1-sol, low), the same system
|
|
6
|
+
* text (as Codex's developer instructions), the same prompt on stdin, the same
|
|
7
|
+
* strict `create_branch_plan` schema as `--output-schema`, and the approved
|
|
8
|
+
* design as its one image. Tools are off, the sandbox is read-only, the sign-in
|
|
9
|
+
* is ChatGPT only, and the child gets an allowlisted environment, so no provider
|
|
10
|
+
* key reaches it.
|
|
11
|
+
*
|
|
12
|
+
* Each attempt is one call in the run-store under a stable id
|
|
13
|
+
* (`branch-plan:<run>:<attempt>`): its request, prompt, system text, schema and
|
|
14
|
+
* image are written into the call's own folder before it runs, and its events,
|
|
15
|
+
* stderr and final answer are written by the Codex process itself (file
|
|
16
|
+
* descriptors, a detached process group), so a `branch execute` that dies
|
|
17
|
+
* mid-plan leaves the call able to finish and a resume reads its answer instead
|
|
18
|
+
* of planning again. A call that ended without a usable answer is never
|
|
19
|
+
* dispatched again.
|
|
20
|
+
*/
|
|
21
|
+
export declare const BRANCH_PLAN_EFFORT = "low";
|
|
22
|
+
/** One planner turn may run this long before its process group is stopped. */
|
|
23
|
+
export declare const BRANCH_PLAN_TIMEOUT_MS: number;
|
|
24
|
+
export declare const branchPlanCallId: (runId: string, attempt: number) => string;
|
|
25
|
+
/** The `codex exec` argv of one planner turn. Every value is ours; nothing the person typed is in it. */
|
|
26
|
+
export declare const branchPlannerArgv: (spec: {
|
|
27
|
+
workDir: string;
|
|
28
|
+
finalPath: string;
|
|
29
|
+
schemaPath: string;
|
|
30
|
+
imagePath: string;
|
|
31
|
+
disabledFeatures: readonly string[];
|
|
32
|
+
serviceTier?: string | null;
|
|
33
|
+
}) => string[];
|
|
34
|
+
/** A call whose process outlived the `branch execute` that started it is waited for, never run twice. */
|
|
35
|
+
export declare const waitForProcessGroup: (pgid: number | undefined, timeoutMs: number, pollMs?: number) => Promise<void>;
|
|
36
|
+
export type BranchPlanCall = {
|
|
37
|
+
/** Where the call's store lives (`<branchDir>/local`). */
|
|
38
|
+
root: string;
|
|
39
|
+
runId: string;
|
|
40
|
+
attempt: number;
|
|
41
|
+
concept: string;
|
|
42
|
+
maxScreens?: number;
|
|
43
|
+
winner: {
|
|
44
|
+
bytes: Uint8Array;
|
|
45
|
+
mediaType: string;
|
|
46
|
+
sha256: string;
|
|
47
|
+
};
|
|
48
|
+
env: NodeJS.ProcessEnv;
|
|
49
|
+
processOptions?: CodexProcessOptions;
|
|
50
|
+
timeoutMs?: number;
|
|
51
|
+
};
|
|
52
|
+
export type BranchPlanCallResult = {
|
|
53
|
+
raw: string;
|
|
54
|
+
reused: boolean;
|
|
55
|
+
callId: string;
|
|
56
|
+
};
|
|
57
|
+
/**
|
|
58
|
+
* One planner attempt. Throws the store's `NEEDS_RECONCILIATION` when a call
|
|
59
|
+
* that was dispatched ended without a usable answer (never re-dispatched), and
|
|
60
|
+
* any other error when Codex could not be started at all (nothing was sent, so
|
|
61
|
+
* a resume may try the same call again).
|
|
62
|
+
*/
|
|
63
|
+
export declare const runBranchPlanCall: (call: BranchPlanCall) => Promise<BranchPlanCallResult>;
|
|
64
|
+
//# sourceMappingURL=branch-local-plan.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"branch-local-plan.d.ts","sourceRoot":"","sources":["../src/branch-local-plan.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAErE;;;;;;;;;;;;;;;;;;GAkBG;AAEH,eAAO,MAAM,kBAAkB,QAAQ,CAAC;AACxC,8EAA8E;AAC9E,eAAO,MAAM,sBAAsB,QAAc,CAAC;AAElD,eAAO,MAAM,gBAAgB,GAAI,OAAO,MAAM,EAAE,SAAS,MAAM,KAAG,MAA2C,CAAC;AAmC9G,yGAAyG;AACzG,eAAO,MAAM,iBAAiB,GAAI,MAAM;IACtC,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B,KAAG,MAAM,EAYT,CAAC;AAmDF,yGAAyG;AACzG,eAAO,MAAM,mBAAmB,GAAU,MAAM,MAAM,GAAG,SAAS,EAAE,WAAW,MAAM,EAAE,eAAc,KAAG,OAAO,CAAC,IAAI,CAKnH,CAAC;AAkBF,MAAM,MAAM,cAAc,GAAG;IAC3B,0DAA0D;IAC1D,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE;QAAE,KAAK,EAAE,UAAU,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IACjE,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;IACvB,cAAc,CAAC,EAAE,mBAAmB,CAAC;IACrC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEpF;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,GAAU,MAAM,cAAc,KAAG,OAAO,CAAC,oBAAoB,CA0G1F,CAAC"}
|