@12ui/design 0.2.13 → 0.2.15
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 +35 -9
- package/dist/bounded-concurrency.d.ts +13 -0
- package/dist/bounded-concurrency.d.ts.map +1 -0
- package/dist/bounded-concurrency.js +43 -0
- package/dist/bounded-concurrency.js.map +1 -0
- package/dist/branch-client.d.ts +155 -0
- package/dist/branch-client.d.ts.map +1 -0
- package/dist/branch-client.js +179 -0
- package/dist/branch-client.js.map +1 -0
- package/dist/branch-completion.d.ts +37 -0
- package/dist/branch-completion.d.ts.map +1 -0
- package/dist/branch-completion.js +137 -0
- package/dist/branch-completion.js.map +1 -0
- package/dist/branch-dispatch-loop.d.ts +84 -0
- package/dist/branch-dispatch-loop.d.ts.map +1 -0
- package/dist/branch-dispatch-loop.js +206 -0
- package/dist/branch-dispatch-loop.js.map +1 -0
- package/dist/branch-downloads.d.ts +53 -0
- package/dist/branch-downloads.d.ts.map +1 -0
- package/dist/branch-downloads.js +114 -0
- package/dist/branch-downloads.js.map +1 -0
- package/dist/branch-execution-types.d.ts +54 -0
- package/dist/branch-execution-types.d.ts.map +1 -0
- package/dist/branch-execution-types.js +2 -0
- package/dist/branch-execution-types.js.map +1 -0
- package/dist/branch-execution.d.ts +20 -0
- package/dist/branch-execution.d.ts.map +1 -0
- package/dist/branch-execution.js +380 -0
- package/dist/branch-execution.js.map +1 -0
- package/dist/branch-identity.d.ts +71 -0
- package/dist/branch-identity.d.ts.map +1 -0
- package/dist/branch-identity.js +72 -0
- package/dist/branch-identity.js.map +1 -0
- package/dist/branch-materialize.d.ts +33 -0
- package/dist/branch-materialize.d.ts.map +1 -0
- package/dist/branch-materialize.js +64 -0
- package/dist/branch-materialize.js.map +1 -0
- package/dist/branch-page-conversion.d.ts +127 -0
- package/dist/branch-page-conversion.d.ts.map +1 -0
- package/dist/branch-page-conversion.js +382 -0
- package/dist/branch-page-conversion.js.map +1 -0
- package/dist/branch-plan.d.ts +63 -0
- package/dist/branch-plan.d.ts.map +1 -0
- package/dist/branch-plan.js +95 -0
- package/dist/branch-plan.js.map +1 -0
- package/dist/branch-progress.d.ts +99 -0
- package/dist/branch-progress.d.ts.map +1 -0
- package/dist/branch-progress.js +188 -0
- package/dist/branch-progress.js.map +1 -0
- package/dist/branch-run-record.d.ts +164 -0
- package/dist/branch-run-record.d.ts.map +1 -0
- package/dist/branch-run-record.js +94 -0
- package/dist/branch-run-record.js.map +1 -0
- package/dist/branch-schedule.d.ts +74 -0
- package/dist/branch-schedule.d.ts.map +1 -0
- package/dist/branch-schedule.js +130 -0
- package/dist/branch-schedule.js.map +1 -0
- package/dist/branch-status.d.ts +11 -0
- package/dist/branch-status.d.ts.map +1 -0
- package/dist/branch-status.js +118 -0
- package/dist/branch-status.js.map +1 -0
- package/dist/branch-viewport-normalization.d.ts +74 -0
- package/dist/branch-viewport-normalization.d.ts.map +1 -0
- package/dist/branch-viewport-normalization.js +120 -0
- package/dist/branch-viewport-normalization.js.map +1 -0
- package/dist/cli-arguments.d.ts.map +1 -1
- package/dist/cli-arguments.js +5 -0
- package/dist/cli-arguments.js.map +1 -1
- package/dist/cli-branch-command.d.ts +55 -0
- package/dist/cli-branch-command.d.ts.map +1 -0
- package/dist/cli-branch-command.js +475 -0
- package/dist/cli-branch-command.js.map +1 -0
- package/dist/cli-capabilities.d.ts +51 -0
- package/dist/cli-capabilities.d.ts.map +1 -1
- package/dist/cli-capabilities.js +52 -1
- package/dist/cli-capabilities.js.map +1 -1
- package/dist/cli-create-command.d.ts +21 -0
- package/dist/cli-create-command.d.ts.map +1 -0
- package/dist/cli-create-command.js +319 -0
- package/dist/cli-create-command.js.map +1 -0
- package/dist/cli-detach.d.ts +62 -0
- package/dist/cli-detach.d.ts.map +1 -0
- package/dist/cli-detach.js +123 -0
- package/dist/cli-detach.js.map +1 -0
- package/dist/cli-draft-command.d.ts +63 -0
- package/dist/cli-draft-command.d.ts.map +1 -0
- package/dist/cli-draft-command.js +220 -0
- package/dist/cli-draft-command.js.map +1 -0
- package/dist/cli-export-command.d.ts.map +1 -1
- package/dist/cli-export-command.js +2 -3
- package/dist/cli-export-command.js.map +1 -1
- package/dist/cli-image-batch-command.d.ts +21 -0
- package/dist/cli-image-batch-command.d.ts.map +1 -1
- package/dist/cli-image-batch-command.js +65 -4
- package/dist/cli-image-batch-command.js.map +1 -1
- package/dist/cli-image-batch-resume.d.ts +7 -0
- package/dist/cli-image-batch-resume.d.ts.map +1 -1
- package/dist/cli-image-batch-resume.js +19 -2
- package/dist/cli-image-batch-resume.js.map +1 -1
- package/dist/cli-package-command.d.ts +29 -0
- package/dist/cli-package-command.d.ts.map +1 -0
- package/dist/cli-package-command.js +128 -0
- package/dist/cli-package-command.js.map +1 -0
- package/dist/cli-progress.d.ts +137 -0
- package/dist/cli-progress.d.ts.map +1 -1
- package/dist/cli-progress.js +156 -0
- package/dist/cli-progress.js.map +1 -1
- package/dist/cli-select-command.d.ts +12 -0
- package/dist/cli-select-command.d.ts.map +1 -0
- package/dist/cli-select-command.js +66 -0
- package/dist/cli-select-command.js.map +1 -0
- package/dist/cli.js +150 -7
- package/dist/cli.js.map +1 -1
- package/dist/conversion-receipt.d.ts +127 -0
- package/dist/conversion-receipt.d.ts.map +1 -0
- package/dist/conversion-receipt.js +184 -0
- package/dist/conversion-receipt.js.map +1 -0
- package/dist/create-identity.d.ts +25 -0
- package/dist/create-identity.d.ts.map +1 -0
- package/dist/create-identity.js +0 -0
- package/dist/create-identity.js.map +1 -0
- package/dist/draft-identity.d.ts +30 -0
- package/dist/draft-identity.d.ts.map +1 -0
- package/dist/draft-identity.js +0 -0
- package/dist/draft-identity.js.map +1 -0
- package/dist/draft-prompts.d.ts +35 -0
- package/dist/draft-prompts.d.ts.map +1 -0
- package/dist/draft-prompts.js +51 -0
- package/dist/draft-prompts.js.map +1 -0
- package/dist/draft-run.d.ts +32 -0
- package/dist/draft-run.d.ts.map +1 -0
- package/dist/draft-run.js +152 -0
- package/dist/draft-run.js.map +1 -0
- package/dist/draft-workspace.d.ts +90 -0
- package/dist/draft-workspace.d.ts.map +1 -0
- package/dist/draft-workspace.js +64 -0
- package/dist/draft-workspace.js.map +1 -0
- package/dist/image-batch-status.d.ts +42 -0
- package/dist/image-batch-status.d.ts.map +1 -0
- package/dist/image-batch-status.js +142 -0
- package/dist/image-batch-status.js.map +1 -0
- package/dist/image-dimensions.d.ts +12 -0
- package/dist/image-dimensions.d.ts.map +1 -0
- package/dist/image-dimensions.js +14 -0
- package/dist/image-dimensions.js.map +1 -0
- package/dist/image-generation-resume.d.ts +13 -0
- package/dist/image-generation-resume.d.ts.map +1 -1
- package/dist/image-generation-resume.js +13 -0
- package/dist/image-generation-resume.js.map +1 -1
- package/dist/index.d.ts +6 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -1
- package/dist/index.js.map +1 -1
- package/dist/legacy-skill-catalog.d.ts.map +1 -1
- package/dist/legacy-skill-catalog.js +140 -0
- package/dist/legacy-skill-catalog.js.map +1 -1
- package/dist/package-client.d.ts +28 -0
- package/dist/package-client.d.ts.map +1 -1
- package/dist/package-client.js +21 -1
- package/dist/package-client.js.map +1 -1
- package/dist/package-manifest-file.d.ts +21 -0
- package/dist/package-manifest-file.d.ts.map +1 -0
- package/dist/package-manifest-file.js +119 -0
- package/dist/package-manifest-file.js.map +1 -0
- package/dist/package-manifest-template.d.ts +23 -0
- package/dist/package-manifest-template.d.ts.map +1 -0
- package/dist/package-manifest-template.js +60 -0
- package/dist/package-manifest-template.js.map +1 -0
- package/dist/package-source-refusal.d.ts +17 -0
- package/dist/package-source-refusal.d.ts.map +1 -0
- package/dist/package-source-refusal.js +61 -0
- package/dist/package-source-refusal.js.map +1 -0
- package/dist/package-submission.d.ts +134 -0
- package/dist/package-submission.d.ts.map +1 -0
- package/dist/package-submission.js +196 -0
- package/dist/package-submission.js.map +1 -0
- package/dist/selection-record.d.ts +95 -0
- package/dist/selection-record.d.ts.map +1 -0
- package/dist/selection-record.js +121 -0
- package/dist/selection-record.js.map +1 -0
- package/package.json +1 -1
- package/skills/design/SKILL.md +43 -266
- package/skills/design-branch/SKILL.md +37 -116
- package/skills/design-convert/SKILL.md +62 -148
- package/skills/design-draft/SKILL.md +71 -135
- package/skills/design-search/SKILL.md +29 -78
- package/skills/design/references/continuation-contract.md +0 -60
- package/skills/design/references/selection-contract.md +0 -112
package/README.md
CHANGED
|
@@ -52,24 +52,27 @@ name) to install one skill instead of the complete bundle.
|
|
|
52
52
|
## Five visual interface skills
|
|
53
53
|
|
|
54
54
|
- `design` routes UI, web, and mobile work. Finished screenshots go directly
|
|
55
|
-
to conversion, tiny edits stay code-only, and rough briefs
|
|
55
|
+
to conversion, tiny edits stay code-only, and rough briefs classify the
|
|
56
|
+
deliverable as one fold, one full page, or a multi-page app, retrieve exactly
|
|
56
57
|
four references, generate four candidates using one different reference per
|
|
57
|
-
candidate, select one,
|
|
58
|
-
real surface.
|
|
58
|
+
candidate, select one, execute the recorded scope, integrate the result, and
|
|
59
|
+
verify the real surface.
|
|
59
60
|
- `design-search` returns a ranked, diverse set of real Design Corpus
|
|
60
61
|
references while preserving endpoint order and metrics.
|
|
61
62
|
- `design-draft` drafts candidates from a brief by claiming one
|
|
62
63
|
`/api/v1/create` run, dispatches each candidate slot once, and downloads the
|
|
63
64
|
images without re-buying a settled slot.
|
|
64
|
-
- `design-branch`
|
|
65
|
-
|
|
66
|
-
|
|
65
|
+
- `design-branch` is required whenever the deliverable is more than one
|
|
66
|
+
viewport. One `12ui branch execute` run expands one approved design into the
|
|
67
|
+
2-8 screens the server plans, dispatching each only once its dependency and
|
|
68
|
+
footer gates clear, and converts each page as one ordered package.
|
|
67
69
|
- `design-convert` turns a finished PNG, JPEG, or WebP into LayerDoc and any
|
|
68
|
-
supported responsive, fixed, project, or document export
|
|
70
|
+
supported responsive, fixed, project, or document export, and converts the
|
|
71
|
+
ordered viewports of one page as a single package.
|
|
69
72
|
|
|
70
73
|
`design-search`, `design-draft`, and `design-branch` are pipeline stages the
|
|
71
|
-
`design` skill
|
|
72
|
-
that stage.
|
|
74
|
+
`design` skill also runs end to end as part of its main flow; install one when
|
|
75
|
+
an agent only needs that stage.
|
|
73
76
|
|
|
74
77
|
The design workflow exists because code-first agents often converge on safe,
|
|
75
78
|
generic visual defaults. Corpus-conditioned image generation expands the
|
|
@@ -85,6 +88,14 @@ manual recreation.
|
|
|
85
88
|
--out-dir ./references \
|
|
86
89
|
--count 4
|
|
87
90
|
12ui image generate-batch --manifest ./generation.json
|
|
91
|
+
12ui image batch-status --manifest ./generation.json
|
|
92
|
+
12ui branch execute \
|
|
93
|
+
--winner-image ./candidates/A.png \
|
|
94
|
+
--concept "Editorial architecture studio site" \
|
|
95
|
+
--scope site \
|
|
96
|
+
--out-dir ./branch \
|
|
97
|
+
--convert html
|
|
98
|
+
12ui branch status --out-dir ./branch
|
|
88
99
|
12ui export <base-layerdoc-conversion-id> \
|
|
89
100
|
--output html,pdf,psd,pptx,sketch,web_project \
|
|
90
101
|
--out-dir ./exports \
|
|
@@ -256,9 +267,24 @@ export TWELVE_UI_API_KEY=your-key
|
|
|
256
267
|
12ui convert ./screen.layerdoc.json --output pptx --out ./screen.pptx --idempotency-key screen-pptx-v1
|
|
257
268
|
12ui convert ./screen.layerdoc.json --output web_project --profile ./react-tailwind.json --out ./screen-react.zip
|
|
258
269
|
12ui convert ./screen.layerdoc.json --output app_project --profile '{"version":1,"framework":"swiftui","styling":"native","language":"swift","packaging":"project"}' --out ./screen-ios.zip
|
|
270
|
+
12ui convert package --manifest ./package.json --out-dir ./pages
|
|
259
271
|
12ui resume conversion-id --output layerdoc --out ./screen.layerdoc.json
|
|
260
272
|
```
|
|
261
273
|
|
|
274
|
+
`convert package` submits the ordered viewports of one continuous page as ONE
|
|
275
|
+
package conversion per page, which is what preserves page order and stitching;
|
|
276
|
+
converting a stacked page one image at a time loses both. Every viewport of a
|
|
277
|
+
page must share one width, checked locally before anything is bought. A viewport
|
|
278
|
+
may name `sourceConversionId` to reuse an already succeeded conversion of
|
|
279
|
+
exactly those bytes instead of paying for it twice.
|
|
280
|
+
|
|
281
|
+
Long commands block until they finish, and `--wait` names that default
|
|
282
|
+
explicitly. While one runs, `12ui branch status --out-dir <dir>` and
|
|
283
|
+
`12ui image batch-status --manifest <file>` report forward motion — per-item
|
|
284
|
+
state, elapsed against typical, and what to do next — without touching the run.
|
|
285
|
+
Do not infer progress from a directory listing: staged work is materialized in
|
|
286
|
+
one atomic pass at the end.
|
|
287
|
+
|
|
262
288
|
Each conversion also writes a verified `<out>.assets/manifest.json` plus every
|
|
263
289
|
signed raster artifact beside the requested result. Set `TWELVE_UI_ORIGIN` to
|
|
264
290
|
override `https://12ui.com`; waits default to the operation expiry and can be
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A bounded worker pool expressed as a function: `limiter(task)` starts the
|
|
3
|
+
* task as soon as fewer than `limit` of them are running, and never more.
|
|
4
|
+
*
|
|
5
|
+
* Independent work runs in parallel, but the bound is real rather than
|
|
6
|
+
* decorative: every concurrent branch page holds two or three viewport children
|
|
7
|
+
* on the server, admission is measured at the account boundary, and an
|
|
8
|
+
* unbounded fan-out would spend the run's admission slots queueing instead of
|
|
9
|
+
* converting.
|
|
10
|
+
*/
|
|
11
|
+
export type ConcurrencyLimiter = <T>(task: () => Promise<T>) => Promise<T>;
|
|
12
|
+
export declare const createConcurrencyLimiter: (limit: number) => ConcurrencyLimiter;
|
|
13
|
+
//# sourceMappingURL=bounded-concurrency.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bounded-concurrency.d.ts","sourceRoot":"","sources":["../src/bounded-concurrency.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;AAE3E,eAAO,MAAM,wBAAwB,GAAI,OAAO,MAAM,KAAG,kBAiCxD,CAAC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A bounded worker pool expressed as a function: `limiter(task)` starts the
|
|
3
|
+
* task as soon as fewer than `limit` of them are running, and never more.
|
|
4
|
+
*
|
|
5
|
+
* Independent work runs in parallel, but the bound is real rather than
|
|
6
|
+
* decorative: every concurrent branch page holds two or three viewport children
|
|
7
|
+
* on the server, admission is measured at the account boundary, and an
|
|
8
|
+
* unbounded fan-out would spend the run's admission slots queueing instead of
|
|
9
|
+
* converting.
|
|
10
|
+
*/
|
|
11
|
+
export const createConcurrencyLimiter = (limit) => {
|
|
12
|
+
const bound = Math.max(1, Math.floor(limit));
|
|
13
|
+
let running = 0;
|
|
14
|
+
const waiting = [];
|
|
15
|
+
const acquire = async () => {
|
|
16
|
+
if (running < bound) {
|
|
17
|
+
running += 1;
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
await new Promise((resolve) => { waiting.push(resolve); });
|
|
21
|
+
};
|
|
22
|
+
// The finishing task hands its slot straight to the next waiter rather than
|
|
23
|
+
// decrementing: a released count would let a caller that arrives before the
|
|
24
|
+
// waiter wakes overtake it and put `bound + 1` tasks in flight.
|
|
25
|
+
const release = () => {
|
|
26
|
+
const next = waiting.shift();
|
|
27
|
+
if (next) {
|
|
28
|
+
next();
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
running -= 1;
|
|
32
|
+
};
|
|
33
|
+
return async (task) => {
|
|
34
|
+
await acquire();
|
|
35
|
+
try {
|
|
36
|
+
return await task();
|
|
37
|
+
}
|
|
38
|
+
finally {
|
|
39
|
+
release();
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
};
|
|
43
|
+
//# sourceMappingURL=bounded-concurrency.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bounded-concurrency.js","sourceRoot":"","sources":["../src/bounded-concurrency.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,KAAa,EAAsB,EAAE;IAC5E,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;IAC7C,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,MAAM,OAAO,GAAmB,EAAE,CAAC;IAEnC,MAAM,OAAO,GAAG,KAAK,IAAmB,EAAE;QACxC,IAAI,OAAO,GAAG,KAAK,EAAE,CAAC;YACpB,OAAO,IAAI,CAAC,CAAC;YACb,OAAO;QACT,CAAC;QACD,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACnE,CAAC,CAAC;IAEF,4EAA4E;IAC5E,4EAA4E;IAC5E,gEAAgE;IAChE,MAAM,OAAO,GAAG,GAAS,EAAE;QACzB,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;QAC7B,IAAI,IAAI,EAAE,CAAC;YACT,IAAI,EAAE,CAAC;YACP,OAAO;QACT,CAAC;QACD,OAAO,IAAI,CAAC,CAAC;IACf,CAAC,CAAC;IAEF,OAAO,KAAK,EAAK,IAAsB,EAAc,EAAE;QACrD,MAAM,OAAO,EAAE,CAAC;QAChB,IAAI,CAAC;YACH,OAAO,MAAM,IAAI,EAAE,CAAC;QACtB,CAAC;gBAAS,CAAC;YACT,OAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC,CAAC;AACJ,CAAC,CAAC"}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import type { ConversionConfig } from './config.js';
|
|
2
|
+
/**
|
|
3
|
+
* The create/build API as the CLI needs it: a port of the web app's
|
|
4
|
+
* `apps/web/src/pages/create/createApi.ts` with the browser identity, Turnstile,
|
|
5
|
+
* and object-URL machinery removed and Bearer key auth in their place.
|
|
6
|
+
*
|
|
7
|
+
* The wire envelope is deliberately NOT `BranchPlan` verbatim. `plan.pages[]`
|
|
8
|
+
* carries the ordering (`slots`), while every per-screen fact —
|
|
9
|
+
* `viewportOrdinal`, `header`, `footer`, `pageEndsHere`, `dependsOnSlot`,
|
|
10
|
+
* `content` — lives on `candidates[]`. Those are two different places and both
|
|
11
|
+
* are needed to reconstruct the page grouping.
|
|
12
|
+
*/
|
|
13
|
+
export declare const BRANCH_MAX_CONCEPT_CHARACTERS = 600;
|
|
14
|
+
export type BranchAspect = 'landscape' | 'portrait' | 'square';
|
|
15
|
+
export type BranchPageKind = 'source' | 'additional';
|
|
16
|
+
export type BranchScreenStatus = 'pending' | 'dispatched' | 'succeeded' | 'failed';
|
|
17
|
+
export type BranchPlanPageEnvelope = {
|
|
18
|
+
index: number;
|
|
19
|
+
kind: BranchPageKind;
|
|
20
|
+
title: string;
|
|
21
|
+
pageType: string;
|
|
22
|
+
surfaceType: string;
|
|
23
|
+
purpose: string;
|
|
24
|
+
/** Source page only: the approved screen already reaches its natural end. */
|
|
25
|
+
sourceEndsHere?: boolean;
|
|
26
|
+
/** This page's slots, in viewport order. */
|
|
27
|
+
slots: string[];
|
|
28
|
+
};
|
|
29
|
+
export type BranchPlanEnvelope = {
|
|
30
|
+
sitePurpose: string;
|
|
31
|
+
/** First person, written for the user. Safe to render verbatim. */
|
|
32
|
+
statusUpdate: string;
|
|
33
|
+
approvedScreenSummary: string;
|
|
34
|
+
pages: BranchPlanPageEnvelope[];
|
|
35
|
+
};
|
|
36
|
+
export type BranchCandidateEnvelope = {
|
|
37
|
+
slot: string;
|
|
38
|
+
status: BranchScreenStatus;
|
|
39
|
+
direction: string;
|
|
40
|
+
width: number;
|
|
41
|
+
height: number;
|
|
42
|
+
image?: string;
|
|
43
|
+
error?: {
|
|
44
|
+
code: string;
|
|
45
|
+
message: string;
|
|
46
|
+
};
|
|
47
|
+
pageIndex?: number;
|
|
48
|
+
/** 1-based within an additional page; source continuations begin at 2. */
|
|
49
|
+
viewportOrdinal?: number;
|
|
50
|
+
/** null means webpage chrome semantics do not apply to this surface. */
|
|
51
|
+
header?: boolean | null;
|
|
52
|
+
footer?: boolean | null;
|
|
53
|
+
pageEndsHere?: boolean;
|
|
54
|
+
/** The previous viewport of the same page, which must succeed first. */
|
|
55
|
+
dependsOnSlot?: string | null;
|
|
56
|
+
content?: string;
|
|
57
|
+
};
|
|
58
|
+
export type BranchRunEnvelope = {
|
|
59
|
+
id: string;
|
|
60
|
+
concept: string;
|
|
61
|
+
aspect: BranchAspect;
|
|
62
|
+
source?: 'create' | 'build';
|
|
63
|
+
createdAt?: string;
|
|
64
|
+
expiresAt?: string;
|
|
65
|
+
plan?: BranchPlanEnvelope;
|
|
66
|
+
candidates: BranchCandidateEnvelope[];
|
|
67
|
+
};
|
|
68
|
+
export type BranchStartInput = {
|
|
69
|
+
concept: string;
|
|
70
|
+
aspect?: BranchAspect;
|
|
71
|
+
winner?: {
|
|
72
|
+
createRunId: string;
|
|
73
|
+
slot: string;
|
|
74
|
+
};
|
|
75
|
+
referenceImage?: {
|
|
76
|
+
data: string;
|
|
77
|
+
mediaType: string;
|
|
78
|
+
sha256: string;
|
|
79
|
+
};
|
|
80
|
+
};
|
|
81
|
+
/**
|
|
82
|
+
* The other shape the same endpoint accepts: an explicit candidate list rather
|
|
83
|
+
* than a planned build. `12ui draft` covers the four-candidate case; this is
|
|
84
|
+
* the one with per-slot directions and references.
|
|
85
|
+
*/
|
|
86
|
+
export type CreateStartInput = {
|
|
87
|
+
concept: string;
|
|
88
|
+
aspect?: BranchAspect;
|
|
89
|
+
mode?: 'inspiration' | 'preserve-structure';
|
|
90
|
+
candidates: readonly {
|
|
91
|
+
slot: string;
|
|
92
|
+
direction?: string;
|
|
93
|
+
referenceId?: string;
|
|
94
|
+
useReferenceImage?: boolean;
|
|
95
|
+
}[];
|
|
96
|
+
referenceImage?: {
|
|
97
|
+
data: string;
|
|
98
|
+
mediaType: string;
|
|
99
|
+
sha256: string;
|
|
100
|
+
};
|
|
101
|
+
};
|
|
102
|
+
export declare class BranchApiError extends Error {
|
|
103
|
+
readonly status: number;
|
|
104
|
+
readonly code: string;
|
|
105
|
+
readonly retryAfterSeconds?: number;
|
|
106
|
+
/** Branch gating only: the slot that must succeed before this one runs. */
|
|
107
|
+
readonly dependsOn?: string;
|
|
108
|
+
constructor(message: string, status: number, code: string, options?: {
|
|
109
|
+
retryAfterSeconds?: number;
|
|
110
|
+
dependsOn?: string;
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* TWO error shapes live behind one status. The dependency gates answer 409 with
|
|
115
|
+
* a NESTED object — `{"error":{"code","dependsOn","message"}}` — while every
|
|
116
|
+
* other refusal, `candidate_in_flight` included, uses the FLAT helper —
|
|
117
|
+
* `{"error":"candidate_in_flight","message":…}` — where `error.code` is
|
|
118
|
+
* undefined. Reading only one of the two silently mis-routes the other, which
|
|
119
|
+
* is exactly the trap the branch skill used to invite.
|
|
120
|
+
*/
|
|
121
|
+
export declare const parseBranchFailure: (status: number, body: unknown, retryAfterHeader?: string | null) => BranchApiError;
|
|
122
|
+
export type BranchClientOptions = ConversionConfig & {
|
|
123
|
+
fetch?: typeof fetch;
|
|
124
|
+
};
|
|
125
|
+
export declare class TwelveUiBranchClient {
|
|
126
|
+
#private;
|
|
127
|
+
readonly origin: string;
|
|
128
|
+
constructor(options: BranchClientOptions);
|
|
129
|
+
/**
|
|
130
|
+
* Claim the build run. The planner runs inline — 10 to 20 seconds — and buys
|
|
131
|
+
* no image. The key derives the run id, so replaying it returns the same run.
|
|
132
|
+
*/
|
|
133
|
+
startBuildRun(input: BranchStartInput, idempotencyKey: string, signal?: AbortSignal): Promise<BranchRunEnvelope>;
|
|
134
|
+
/**
|
|
135
|
+
* Claim a candidate run. Buys no image; the key derives the run, so replaying
|
|
136
|
+
* it returns the same run and its stored images rather than a second set.
|
|
137
|
+
*/
|
|
138
|
+
startCreateRun(input: CreateStartInput, idempotencyKey: string, signal?: AbortSignal): Promise<BranchRunEnvelope>;
|
|
139
|
+
/**
|
|
140
|
+
* Dispatch one screen. Unkeyed by default and by design: an unkeyed repeat
|
|
141
|
+
* replays the settled screen for free, while a NEW key on a settled slot buys
|
|
142
|
+
* another image. Only an explicit redraw passes one.
|
|
143
|
+
*/
|
|
144
|
+
dispatchScreen(runId: string, slot: string, options?: {
|
|
145
|
+
idempotencyKey?: string;
|
|
146
|
+
signal?: AbortSignal;
|
|
147
|
+
}): Promise<BranchRunEnvelope>;
|
|
148
|
+
getRun(runId: string, signal?: AbortSignal): Promise<BranchRunEnvelope>;
|
|
149
|
+
/** Candidate images are owner-authenticated rather than signed. */
|
|
150
|
+
downloadScreen(runId: string, slot: string, signal?: AbortSignal): Promise<{
|
|
151
|
+
bytes: Uint8Array;
|
|
152
|
+
sha256: string;
|
|
153
|
+
}>;
|
|
154
|
+
}
|
|
155
|
+
//# sourceMappingURL=branch-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"branch-client.d.ts","sourceRoot":"","sources":["../src/branch-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { appendClientAuthGuidance } from './client-auth-guidance.js';
|
|
3
|
+
import { normalizeConversionOrigin } from './config.js';
|
|
4
|
+
/**
|
|
5
|
+
* The create/build API as the CLI needs it: a port of the web app's
|
|
6
|
+
* `apps/web/src/pages/create/createApi.ts` with the browser identity, Turnstile,
|
|
7
|
+
* and object-URL machinery removed and Bearer key auth in their place.
|
|
8
|
+
*
|
|
9
|
+
* The wire envelope is deliberately NOT `BranchPlan` verbatim. `plan.pages[]`
|
|
10
|
+
* carries the ordering (`slots`), while every per-screen fact —
|
|
11
|
+
* `viewportOrdinal`, `header`, `footer`, `pageEndsHere`, `dependsOnSlot`,
|
|
12
|
+
* `content` — lives on `candidates[]`. Those are two different places and both
|
|
13
|
+
* are needed to reconstruct the page grouping.
|
|
14
|
+
*/
|
|
15
|
+
export const BRANCH_MAX_CONCEPT_CHARACTERS = 600;
|
|
16
|
+
export class BranchApiError extends Error {
|
|
17
|
+
status;
|
|
18
|
+
code;
|
|
19
|
+
retryAfterSeconds;
|
|
20
|
+
/** Branch gating only: the slot that must succeed before this one runs. */
|
|
21
|
+
dependsOn;
|
|
22
|
+
constructor(message, status, code, options = {}) {
|
|
23
|
+
super(message);
|
|
24
|
+
this.name = 'BranchApiError';
|
|
25
|
+
this.status = status;
|
|
26
|
+
this.code = code;
|
|
27
|
+
if (options.retryAfterSeconds !== undefined)
|
|
28
|
+
this.retryAfterSeconds = options.retryAfterSeconds;
|
|
29
|
+
if (options.dependsOn !== undefined)
|
|
30
|
+
this.dependsOn = options.dependsOn;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* TWO error shapes live behind one status. The dependency gates answer 409 with
|
|
35
|
+
* a NESTED object — `{"error":{"code","dependsOn","message"}}` — while every
|
|
36
|
+
* other refusal, `candidate_in_flight` included, uses the FLAT helper —
|
|
37
|
+
* `{"error":"candidate_in_flight","message":…}` — where `error.code` is
|
|
38
|
+
* undefined. Reading only one of the two silently mis-routes the other, which
|
|
39
|
+
* is exactly the trap the branch skill used to invite.
|
|
40
|
+
*/
|
|
41
|
+
export const parseBranchFailure = (status, body, retryAfterHeader) => {
|
|
42
|
+
const parsed = (body && typeof body === 'object' && !Array.isArray(body)
|
|
43
|
+
? body
|
|
44
|
+
: null);
|
|
45
|
+
const nested = parsed?.error && typeof parsed.error === 'object' && !Array.isArray(parsed.error)
|
|
46
|
+
? parsed.error
|
|
47
|
+
: null;
|
|
48
|
+
const flat = typeof parsed?.error === 'string' ? parsed.error : undefined;
|
|
49
|
+
const code = nested?.code ?? flat ?? 'error';
|
|
50
|
+
const message = nested?.message
|
|
51
|
+
?? parsed?.message
|
|
52
|
+
?? (status === 429
|
|
53
|
+
? 'The daily generation allowance is used up.'
|
|
54
|
+
: `The create service failed (${status}).`);
|
|
55
|
+
const retryAfter = Number(retryAfterHeader ?? '');
|
|
56
|
+
return new BranchApiError(appendClientAuthGuidance(message, status), status, code, {
|
|
57
|
+
...(Number.isFinite(retryAfter) && retryAfter > 0
|
|
58
|
+
? { retryAfterSeconds: Math.round(retryAfter) }
|
|
59
|
+
: {}),
|
|
60
|
+
...(typeof nested?.dependsOn === 'string' ? { dependsOn: nested.dependsOn } : {}),
|
|
61
|
+
});
|
|
62
|
+
};
|
|
63
|
+
const parseEnvelope = (payload) => {
|
|
64
|
+
const record = payload;
|
|
65
|
+
if (!record || typeof record.id !== 'string' || !Array.isArray(record.candidates)) {
|
|
66
|
+
throw new BranchApiError('The create service returned an unexpected response.', 0, 'error');
|
|
67
|
+
}
|
|
68
|
+
return record;
|
|
69
|
+
};
|
|
70
|
+
export class TwelveUiBranchClient {
|
|
71
|
+
origin;
|
|
72
|
+
#apiKey;
|
|
73
|
+
#fetch;
|
|
74
|
+
constructor(options) {
|
|
75
|
+
this.origin = normalizeConversionOrigin(options.origin);
|
|
76
|
+
this.#apiKey = options.apiKey.trim();
|
|
77
|
+
this.#fetch = options.fetch ?? fetch;
|
|
78
|
+
if (!this.#apiKey)
|
|
79
|
+
throw new Error('A 12ui API key is required');
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Claim the build run. The planner runs inline — 10 to 20 seconds — and buys
|
|
83
|
+
* no image. The key derives the run id, so replaying it returns the same run.
|
|
84
|
+
*/
|
|
85
|
+
async startBuildRun(input, idempotencyKey, signal) {
|
|
86
|
+
const body = {
|
|
87
|
+
source: 'build',
|
|
88
|
+
concept: input.concept,
|
|
89
|
+
...(input.aspect ? { aspect: input.aspect } : {}),
|
|
90
|
+
...(input.winner ? { winner: input.winner } : {}),
|
|
91
|
+
...(input.referenceImage ? { referenceImage: input.referenceImage } : {}),
|
|
92
|
+
};
|
|
93
|
+
return parseEnvelope(await this.#json('/api/v1/create', {
|
|
94
|
+
method: 'POST',
|
|
95
|
+
headers: { 'content-type': 'application/json', 'Idempotency-Key': idempotencyKey },
|
|
96
|
+
body: JSON.stringify(body),
|
|
97
|
+
...(signal ? { signal } : {}),
|
|
98
|
+
}, [200, 201]));
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Claim a candidate run. Buys no image; the key derives the run, so replaying
|
|
102
|
+
* it returns the same run and its stored images rather than a second set.
|
|
103
|
+
*/
|
|
104
|
+
async startCreateRun(input, idempotencyKey, signal) {
|
|
105
|
+
const body = {
|
|
106
|
+
concept: input.concept,
|
|
107
|
+
...(input.aspect ? { aspect: input.aspect } : {}),
|
|
108
|
+
...(input.mode ? { mode: input.mode } : {}),
|
|
109
|
+
candidates: input.candidates.map((candidate) => ({
|
|
110
|
+
slot: candidate.slot,
|
|
111
|
+
...(candidate.direction ? { direction: candidate.direction } : {}),
|
|
112
|
+
...(candidate.referenceId ? { referenceId: candidate.referenceId } : {}),
|
|
113
|
+
...(candidate.useReferenceImage ? { useReferenceImage: true } : {}),
|
|
114
|
+
})),
|
|
115
|
+
...(input.referenceImage ? { referenceImage: input.referenceImage } : {}),
|
|
116
|
+
};
|
|
117
|
+
return parseEnvelope(await this.#json('/api/v1/create', {
|
|
118
|
+
method: 'POST',
|
|
119
|
+
headers: { 'content-type': 'application/json', 'Idempotency-Key': idempotencyKey },
|
|
120
|
+
body: JSON.stringify(body),
|
|
121
|
+
...(signal ? { signal } : {}),
|
|
122
|
+
}, [200, 201]));
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Dispatch one screen. Unkeyed by default and by design: an unkeyed repeat
|
|
126
|
+
* replays the settled screen for free, while a NEW key on a settled slot buys
|
|
127
|
+
* another image. Only an explicit redraw passes one.
|
|
128
|
+
*/
|
|
129
|
+
async dispatchScreen(runId, slot, options = {}) {
|
|
130
|
+
return parseEnvelope(await this.#json(`/api/v1/create/${encodeURIComponent(runId)}/candidates/${encodeURIComponent(slot)}`, {
|
|
131
|
+
method: 'POST',
|
|
132
|
+
headers: {
|
|
133
|
+
'content-length': '0',
|
|
134
|
+
...(options.idempotencyKey ? { 'Idempotency-Key': options.idempotencyKey } : {}),
|
|
135
|
+
},
|
|
136
|
+
...(options.signal ? { signal: options.signal } : {}),
|
|
137
|
+
}));
|
|
138
|
+
}
|
|
139
|
+
async getRun(runId, signal) {
|
|
140
|
+
return parseEnvelope(await this.#json(`/api/v1/create/${encodeURIComponent(runId)}`, { method: 'GET', ...(signal ? { signal } : {}) }));
|
|
141
|
+
}
|
|
142
|
+
/** Candidate images are owner-authenticated rather than signed. */
|
|
143
|
+
async downloadScreen(runId, slot, signal) {
|
|
144
|
+
const response = await this.#fetch(`${this.origin}/api/v1/create/${encodeURIComponent(runId)}/candidates/${encodeURIComponent(slot)}/image`, {
|
|
145
|
+
method: 'GET',
|
|
146
|
+
headers: this.#headers({ accept: 'image/png' }),
|
|
147
|
+
...(signal ? { signal } : {}),
|
|
148
|
+
});
|
|
149
|
+
if (!response.ok) {
|
|
150
|
+
throw parseBranchFailure(response.status, await response.json().catch(() => null), response.headers.get('retry-after'));
|
|
151
|
+
}
|
|
152
|
+
const bytes = new Uint8Array(await response.arrayBuffer());
|
|
153
|
+
return { bytes, sha256: createHash('sha256').update(bytes).digest('hex') };
|
|
154
|
+
}
|
|
155
|
+
async #json(path, init, okStatuses = [200]) {
|
|
156
|
+
let response;
|
|
157
|
+
try {
|
|
158
|
+
response = await this.#fetch(`${this.origin}${path}`, {
|
|
159
|
+
...init,
|
|
160
|
+
headers: this.#headers({ accept: 'application/json', ...init.headers }),
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
catch (error) {
|
|
164
|
+
if (error instanceof Error && error.name === 'AbortError')
|
|
165
|
+
throw error;
|
|
166
|
+
throw new BranchApiError('Could not reach the create service.', 0, 'network');
|
|
167
|
+
}
|
|
168
|
+
if (!response.ok && !okStatuses.includes(response.status)) {
|
|
169
|
+
throw parseBranchFailure(response.status, await response.json().catch(() => null), response.headers.get('retry-after'));
|
|
170
|
+
}
|
|
171
|
+
return await response.json().catch(() => null);
|
|
172
|
+
}
|
|
173
|
+
#headers(values) {
|
|
174
|
+
const headers = new Headers(values);
|
|
175
|
+
headers.set('authorization', `Bearer ${this.#apiKey}`);
|
|
176
|
+
return headers;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
//# sourceMappingURL=branch-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"branch-client.js","sourceRoot":"","sources":["../src/branch-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { BranchDispatchStop } from './branch-dispatch-loop.js';
|
|
2
|
+
import type { BranchDownloadedScreen } from './branch-downloads.js';
|
|
3
|
+
import type { BranchExecutionInputs } from './branch-execution-types.js';
|
|
4
|
+
import type { BranchNormalizedPlan } from './branch-plan.js';
|
|
5
|
+
import { type BranchCompletion, type BranchCompletionPage } from './branch-run-record.js';
|
|
6
|
+
/**
|
|
7
|
+
* The completion sentinel and the exit disposition: the two things that decide
|
|
8
|
+
* what a caller believes happened. Every screen is accounted for as succeeded,
|
|
9
|
+
* failed, or blocked-by-a-failure, so a run always reaches a terminal story
|
|
10
|
+
* rather than leaving a screen that will never move looking merely pending.
|
|
11
|
+
*/
|
|
12
|
+
export declare const buildCompletion: (args: {
|
|
13
|
+
plan: BranchNormalizedPlan;
|
|
14
|
+
inputs: BranchExecutionInputs;
|
|
15
|
+
runKey: string;
|
|
16
|
+
origin: string;
|
|
17
|
+
outDir: string;
|
|
18
|
+
attemptFile: string;
|
|
19
|
+
startedAt: string;
|
|
20
|
+
screens: ReadonlyMap<string, BranchDownloadedScreen>;
|
|
21
|
+
winner?: BranchDownloadedScreen;
|
|
22
|
+
conversions: ReadonlyMap<string, BranchCompletionPage["conversion"]>;
|
|
23
|
+
stopped: BranchDispatchStop | null;
|
|
24
|
+
}) => BranchCompletion;
|
|
25
|
+
/**
|
|
26
|
+
* Park or fail, per CLAUDE.md §5. A run that lost some screens still delivered
|
|
27
|
+
* the pages that are whole, so it exits 0 with the gaps named. A run that lost
|
|
28
|
+
* everything, was cut off by quota or funds, or converted nothing it attempted
|
|
29
|
+
* has no artifact to hand over and says so.
|
|
30
|
+
*/
|
|
31
|
+
export declare const terminalFailure: (args: {
|
|
32
|
+
completion: BranchCompletion;
|
|
33
|
+
stopped: BranchDispatchStop | null;
|
|
34
|
+
completionFile: string;
|
|
35
|
+
convert: boolean;
|
|
36
|
+
}) => Error | null;
|
|
37
|
+
//# sourceMappingURL=branch-completion.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"branch-completion.d.ts","sourceRoot":"","sources":["../src/branch-completion.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AACpE,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AACpE,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AACzE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAE7D,OAAO,EAEL,KAAK,gBAAgB,EACrB,KAAK,oBAAoB,EAE1B,MAAM,wBAAwB,CAAC;AAEhC;;;;;GAKG;AAEH,eAAO,MAAM,eAAe,GAAI,MAAM;IACpC,IAAI,EAAE,oBAAoB,CAAC;IAC3B,MAAM,EAAE,qBAAqB,CAAC;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,WAAW,CAAC,MAAM,EAAE,sBAAsB,CAAC,CAAC;IACrD,MAAM,CAAC,EAAE,sBAAsB,CAAC;IAChC,WAAW,EAAE,WAAW,CAAC,MAAM,EAAE,oBAAoB,CAAC,YAAY,CAAC,CAAC,CAAC;IACrE,OAAO,EAAE,kBAAkB,GAAG,IAAI,CAAC;CACpC,KAAG,gBA6GH,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,eAAe,GAAI,MAAM;IACpC,UAAU,EAAE,gBAAgB,CAAC;IAC7B,OAAO,EAAE,kBAAkB,GAAG,IAAI,CAAC;IACnC,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,OAAO,CAAC;CAClB,KAAG,KAAK,GAAG,IAwBX,CAAC"}
|