@12ui/design 0.2.13 → 0.2.14

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 (172) hide show
  1. package/README.md +35 -9
  2. package/dist/branch-client.d.ts +155 -0
  3. package/dist/branch-client.d.ts.map +1 -0
  4. package/dist/branch-client.js +179 -0
  5. package/dist/branch-client.js.map +1 -0
  6. package/dist/branch-completion.d.ts +37 -0
  7. package/dist/branch-completion.d.ts.map +1 -0
  8. package/dist/branch-completion.js +137 -0
  9. package/dist/branch-completion.js.map +1 -0
  10. package/dist/branch-dispatch-loop.d.ts +84 -0
  11. package/dist/branch-dispatch-loop.d.ts.map +1 -0
  12. package/dist/branch-dispatch-loop.js +206 -0
  13. package/dist/branch-dispatch-loop.js.map +1 -0
  14. package/dist/branch-downloads.d.ts +43 -0
  15. package/dist/branch-downloads.d.ts.map +1 -0
  16. package/dist/branch-downloads.js +94 -0
  17. package/dist/branch-downloads.js.map +1 -0
  18. package/dist/branch-execution-types.d.ts +54 -0
  19. package/dist/branch-execution-types.d.ts.map +1 -0
  20. package/dist/branch-execution-types.js +2 -0
  21. package/dist/branch-execution-types.js.map +1 -0
  22. package/dist/branch-execution.d.ts +18 -0
  23. package/dist/branch-execution.d.ts.map +1 -0
  24. package/dist/branch-execution.js +261 -0
  25. package/dist/branch-execution.js.map +1 -0
  26. package/dist/branch-identity.d.ts +71 -0
  27. package/dist/branch-identity.d.ts.map +1 -0
  28. package/dist/branch-identity.js +72 -0
  29. package/dist/branch-identity.js.map +1 -0
  30. package/dist/branch-materialize.d.ts +22 -0
  31. package/dist/branch-materialize.d.ts.map +1 -0
  32. package/dist/branch-materialize.js +47 -0
  33. package/dist/branch-materialize.js.map +1 -0
  34. package/dist/branch-page-conversion.d.ts +39 -0
  35. package/dist/branch-page-conversion.d.ts.map +1 -0
  36. package/dist/branch-page-conversion.js +206 -0
  37. package/dist/branch-page-conversion.js.map +1 -0
  38. package/dist/branch-plan.d.ts +63 -0
  39. package/dist/branch-plan.d.ts.map +1 -0
  40. package/dist/branch-plan.js +95 -0
  41. package/dist/branch-plan.js.map +1 -0
  42. package/dist/branch-progress.d.ts +75 -0
  43. package/dist/branch-progress.d.ts.map +1 -0
  44. package/dist/branch-progress.js +159 -0
  45. package/dist/branch-progress.js.map +1 -0
  46. package/dist/branch-run-record.d.ts +153 -0
  47. package/dist/branch-run-record.d.ts.map +1 -0
  48. package/dist/branch-run-record.js +94 -0
  49. package/dist/branch-run-record.js.map +1 -0
  50. package/dist/branch-schedule.d.ts +74 -0
  51. package/dist/branch-schedule.d.ts.map +1 -0
  52. package/dist/branch-schedule.js +130 -0
  53. package/dist/branch-schedule.js.map +1 -0
  54. package/dist/branch-status.d.ts +11 -0
  55. package/dist/branch-status.d.ts.map +1 -0
  56. package/dist/branch-status.js +115 -0
  57. package/dist/branch-status.js.map +1 -0
  58. package/dist/branch-viewport-normalization.d.ts +74 -0
  59. package/dist/branch-viewport-normalization.d.ts.map +1 -0
  60. package/dist/branch-viewport-normalization.js +120 -0
  61. package/dist/branch-viewport-normalization.js.map +1 -0
  62. package/dist/cli-arguments.d.ts.map +1 -1
  63. package/dist/cli-arguments.js +4 -0
  64. package/dist/cli-arguments.js.map +1 -1
  65. package/dist/cli-branch-command.d.ts +46 -0
  66. package/dist/cli-branch-command.d.ts.map +1 -0
  67. package/dist/cli-branch-command.js +426 -0
  68. package/dist/cli-branch-command.js.map +1 -0
  69. package/dist/cli-capabilities.d.ts +28 -0
  70. package/dist/cli-capabilities.d.ts.map +1 -1
  71. package/dist/cli-capabilities.js +29 -1
  72. package/dist/cli-capabilities.js.map +1 -1
  73. package/dist/cli-create-command.d.ts +21 -0
  74. package/dist/cli-create-command.d.ts.map +1 -0
  75. package/dist/cli-create-command.js +319 -0
  76. package/dist/cli-create-command.js.map +1 -0
  77. package/dist/cli-detach.d.ts +62 -0
  78. package/dist/cli-detach.d.ts.map +1 -0
  79. package/dist/cli-detach.js +123 -0
  80. package/dist/cli-detach.js.map +1 -0
  81. package/dist/cli-draft-command.d.ts +63 -0
  82. package/dist/cli-draft-command.d.ts.map +1 -0
  83. package/dist/cli-draft-command.js +220 -0
  84. package/dist/cli-draft-command.js.map +1 -0
  85. package/dist/cli-export-command.d.ts.map +1 -1
  86. package/dist/cli-export-command.js +2 -3
  87. package/dist/cli-export-command.js.map +1 -1
  88. package/dist/cli-image-batch-command.d.ts +21 -0
  89. package/dist/cli-image-batch-command.d.ts.map +1 -1
  90. package/dist/cli-image-batch-command.js +65 -4
  91. package/dist/cli-image-batch-command.js.map +1 -1
  92. package/dist/cli-image-batch-resume.d.ts +7 -0
  93. package/dist/cli-image-batch-resume.d.ts.map +1 -1
  94. package/dist/cli-image-batch-resume.js +19 -2
  95. package/dist/cli-image-batch-resume.js.map +1 -1
  96. package/dist/cli-package-command.d.ts +18 -0
  97. package/dist/cli-package-command.d.ts.map +1 -0
  98. package/dist/cli-package-command.js +112 -0
  99. package/dist/cli-package-command.js.map +1 -0
  100. package/dist/cli-progress.d.ts +61 -0
  101. package/dist/cli-progress.d.ts.map +1 -1
  102. package/dist/cli-progress.js +53 -0
  103. package/dist/cli-progress.js.map +1 -1
  104. package/dist/cli-select-command.d.ts +12 -0
  105. package/dist/cli-select-command.d.ts.map +1 -0
  106. package/dist/cli-select-command.js +66 -0
  107. package/dist/cli-select-command.js.map +1 -0
  108. package/dist/cli.js +140 -7
  109. package/dist/cli.js.map +1 -1
  110. package/dist/create-identity.d.ts +25 -0
  111. package/dist/create-identity.d.ts.map +1 -0
  112. package/dist/create-identity.js +0 -0
  113. package/dist/create-identity.js.map +1 -0
  114. package/dist/draft-identity.d.ts +30 -0
  115. package/dist/draft-identity.d.ts.map +1 -0
  116. package/dist/draft-identity.js +0 -0
  117. package/dist/draft-identity.js.map +1 -0
  118. package/dist/draft-prompts.d.ts +35 -0
  119. package/dist/draft-prompts.d.ts.map +1 -0
  120. package/dist/draft-prompts.js +51 -0
  121. package/dist/draft-prompts.js.map +1 -0
  122. package/dist/draft-run.d.ts +32 -0
  123. package/dist/draft-run.d.ts.map +1 -0
  124. package/dist/draft-run.js +152 -0
  125. package/dist/draft-run.js.map +1 -0
  126. package/dist/draft-workspace.d.ts +90 -0
  127. package/dist/draft-workspace.d.ts.map +1 -0
  128. package/dist/draft-workspace.js +64 -0
  129. package/dist/draft-workspace.js.map +1 -0
  130. package/dist/image-batch-status.d.ts +42 -0
  131. package/dist/image-batch-status.d.ts.map +1 -0
  132. package/dist/image-batch-status.js +142 -0
  133. package/dist/image-batch-status.js.map +1 -0
  134. package/dist/image-dimensions.d.ts +12 -0
  135. package/dist/image-dimensions.d.ts.map +1 -0
  136. package/dist/image-dimensions.js +14 -0
  137. package/dist/image-dimensions.js.map +1 -0
  138. package/dist/image-generation-resume.d.ts +13 -0
  139. package/dist/image-generation-resume.d.ts.map +1 -1
  140. package/dist/image-generation-resume.js +13 -0
  141. package/dist/image-generation-resume.js.map +1 -1
  142. package/dist/index.d.ts +5 -0
  143. package/dist/index.d.ts.map +1 -1
  144. package/dist/index.js +4 -0
  145. package/dist/index.js.map +1 -1
  146. package/dist/legacy-skill-catalog.d.ts.map +1 -1
  147. package/dist/legacy-skill-catalog.js +115 -0
  148. package/dist/legacy-skill-catalog.js.map +1 -1
  149. package/dist/package-manifest-file.d.ts +21 -0
  150. package/dist/package-manifest-file.d.ts.map +1 -0
  151. package/dist/package-manifest-file.js +119 -0
  152. package/dist/package-manifest-file.js.map +1 -0
  153. package/dist/package-manifest-template.d.ts +23 -0
  154. package/dist/package-manifest-template.d.ts.map +1 -0
  155. package/dist/package-manifest-template.js +60 -0
  156. package/dist/package-manifest-template.js.map +1 -0
  157. package/dist/package-submission.d.ts +103 -0
  158. package/dist/package-submission.d.ts.map +1 -0
  159. package/dist/package-submission.js +173 -0
  160. package/dist/package-submission.js.map +1 -0
  161. package/dist/selection-record.d.ts +95 -0
  162. package/dist/selection-record.d.ts.map +1 -0
  163. package/dist/selection-record.js +121 -0
  164. package/dist/selection-record.js.map +1 -0
  165. package/package.json +1 -1
  166. package/skills/design/SKILL.md +40 -266
  167. package/skills/design-branch/SKILL.md +36 -116
  168. package/skills/design-convert/SKILL.md +62 -148
  169. package/skills/design-draft/SKILL.md +71 -135
  170. package/skills/design-search/SKILL.md +29 -78
  171. package/skills/design/references/continuation-contract.md +0 -60
  172. package/skills/design/references/selection-contract.md +0 -112
@@ -0,0 +1,119 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { readFile } from 'node:fs/promises';
3
+ import path from 'node:path';
4
+ import { isConversionModel } from './conversion-models.js';
5
+ import { isConversionOutput } from './conversion-outputs.js';
6
+ import { classifyLocalConversionInput } from './local-conversion-input.js';
7
+ import { isResponsiveConversionQuality, } from './responsive-quality.js';
8
+ const record = (value, label) => {
9
+ if (!value || typeof value !== 'object' || Array.isArray(value)) {
10
+ throw new Error(`${label} must be a JSON object`);
11
+ }
12
+ return value;
13
+ };
14
+ const text = (value, label, required = false) => {
15
+ if (value === undefined) {
16
+ if (required)
17
+ throw new Error(`${label} is required`);
18
+ return undefined;
19
+ }
20
+ if (typeof value !== 'string' || !value.trim())
21
+ throw new Error(`${label} must be non-empty text`);
22
+ return value.trim();
23
+ };
24
+ const ordinalOr = (value, fallback, label) => {
25
+ if (value === undefined)
26
+ return fallback;
27
+ if (!Number.isSafeInteger(value) || Number(value) < 0) {
28
+ throw new Error(`${label} must be a non-negative integer`);
29
+ }
30
+ return Number(value);
31
+ };
32
+ export const readLocalPackageManifest = async (manifestPath) => {
33
+ const source = await readFile(manifestPath, 'utf8');
34
+ const manifestSha256 = createHash('sha256').update(source).digest('hex');
35
+ const root = record(JSON.parse(source), 'The package manifest');
36
+ if (root.version !== 1)
37
+ throw new Error('The package manifest version must be 1');
38
+ const output = root.output === undefined ? 'html' : root.output;
39
+ if (!isConversionOutput(output)) {
40
+ throw new Error('The package manifest output is not a supported conversion output');
41
+ }
42
+ if (output === 'web_project' || output === 'app_project') {
43
+ throw new Error('12ui convert package does not submit project outputs; export them from a conversion instead');
44
+ }
45
+ const model = root.model === undefined ? undefined : root.model;
46
+ if (model !== undefined && !isConversionModel(model)) {
47
+ throw new Error('The package manifest model must be fast, standard, or pro');
48
+ }
49
+ const responsiveQuality = root.responsiveQuality;
50
+ if (responsiveQuality !== undefined && !isResponsiveConversionQuality(responsiveQuality)) {
51
+ throw new Error('The package manifest responsiveQuality must be standard or pro');
52
+ }
53
+ if (responsiveQuality !== undefined && output !== 'html') {
54
+ throw new Error('The package manifest responsiveQuality is only valid with output html');
55
+ }
56
+ if (!Array.isArray(root.pages) || root.pages.length === 0) {
57
+ throw new Error('The package manifest must declare at least one page');
58
+ }
59
+ const manifestDirectory = path.dirname(path.resolve(manifestPath));
60
+ const pageIds = new Set();
61
+ const pages = [];
62
+ for (const [pageIndex, pageValue] of root.pages.entries()) {
63
+ const page = record(pageValue, `pages[${pageIndex}]`);
64
+ const id = text(page.id, `pages[${pageIndex}].id`, true);
65
+ if (pageIds.has(id))
66
+ throw new Error(`Page id ${id} is declared twice`);
67
+ pageIds.add(id);
68
+ if (page.kind !== undefined && page.kind !== 'source' && page.kind !== 'additional') {
69
+ throw new Error(`pages[${pageIndex}].kind must be source or additional`);
70
+ }
71
+ if (!Array.isArray(page.viewports) || page.viewports.length === 0) {
72
+ throw new Error(`pages[${pageIndex}].viewports must list at least one screenshot`);
73
+ }
74
+ const viewportIds = new Set();
75
+ const viewports = [];
76
+ for (const [viewportIndex, viewportValue] of page.viewports.entries()) {
77
+ const viewport = record(viewportValue, `pages[${pageIndex}].viewports[${viewportIndex}]`);
78
+ const viewportId = text(viewport.id, `pages[${pageIndex}].viewports[${viewportIndex}].id`, true);
79
+ if (viewportIds.has(viewportId)) {
80
+ throw new Error(`Viewport id ${viewportId} is declared twice on page ${id}`);
81
+ }
82
+ viewportIds.add(viewportId);
83
+ const image = text(viewport.image, `pages[${pageIndex}].viewports[${viewportIndex}].image`, true);
84
+ const imagePath = path.resolve(manifestDirectory, image);
85
+ const classified = classifyLocalConversionInput(imagePath);
86
+ if (classified.kind !== 'image') {
87
+ throw new Error(`Viewport ${viewportId} must name a PNG, JPEG, or WebP screenshot`);
88
+ }
89
+ const bytes = new Uint8Array(await readFile(imagePath));
90
+ const sourceConversionId = text(viewport.sourceConversionId, `pages[${pageIndex}].viewports[${viewportIndex}].sourceConversionId`);
91
+ viewports.push({
92
+ id: viewportId,
93
+ ordinal: ordinalOr(viewport.ordinal, viewportIndex + 1, `pages[${pageIndex}].viewports[${viewportIndex}].ordinal`),
94
+ imagePath,
95
+ bytes,
96
+ mediaType: classified.mediaType,
97
+ ...(sourceConversionId ? { sourceConversionId } : {}),
98
+ });
99
+ }
100
+ pages.push({
101
+ id,
102
+ ordinal: ordinalOr(page.ordinal, pageIndex, `pages[${pageIndex}].ordinal`),
103
+ ...(page.kind ? { kind: page.kind } : {}),
104
+ ...(text(page.title, `pages[${pageIndex}].title`) ? { title: text(page.title, '') } : {}),
105
+ ...(text(page.purpose, `pages[${pageIndex}].purpose`) ? { purpose: text(page.purpose, '') } : {}),
106
+ ...(text(page.path, `pages[${pageIndex}].path`) ? { path: text(page.path, '') } : {}),
107
+ viewports,
108
+ });
109
+ }
110
+ return {
111
+ version: 1,
112
+ output,
113
+ ...(model ? { model } : {}),
114
+ ...(responsiveQuality ? { responsiveQuality } : {}),
115
+ pages,
116
+ manifestSha256,
117
+ };
118
+ };
119
+ //# sourceMappingURL=package-manifest-file.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"package-manifest-file.js","sourceRoot":"","sources":["../src/package-manifest-file.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,iBAAiB,EAAwB,MAAM,wBAAwB,CAAC;AACjF,OAAO,EAAE,kBAAkB,EAAyB,MAAM,yBAAyB,CAAC;AACpF,OAAO,EAAE,4BAA4B,EAAE,MAAM,6BAA6B,CAAC;AAC3E,OAAO,EACL,6BAA6B,GAE9B,MAAM,yBAAyB,CAAC;AAwBjC,MAAM,MAAM,GAAG,CAAC,KAAc,EAAE,KAAa,EAA2B,EAAE;IACxE,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QAChE,MAAM,IAAI,KAAK,CAAC,GAAG,KAAK,wBAAwB,CAAC,CAAC;IACpD,CAAC;IACD,OAAO,KAAgC,CAAC;AAC1C,CAAC,CAAC;AAEF,MAAM,IAAI,GAAG,CAAC,KAAc,EAAE,KAAa,EAAE,QAAQ,GAAG,KAAK,EAAsB,EAAE;IACnF,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,IAAI,QAAQ;YAAE,MAAM,IAAI,KAAK,CAAC,GAAG,KAAK,cAAc,CAAC,CAAC;QACtD,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,GAAG,KAAK,yBAAyB,CAAC,CAAC;IACnG,OAAO,KAAK,CAAC,IAAI,EAAE,CAAC;AACtB,CAAC,CAAC;AAEF,MAAM,SAAS,GAAG,CAAC,KAAc,EAAE,QAAgB,EAAE,KAAa,EAAU,EAAE;IAC5E,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,QAAQ,CAAC;IACzC,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QACtD,MAAM,IAAI,KAAK,CAAC,GAAG,KAAK,iCAAiC,CAAC,CAAC;IAC7D,CAAC;IACD,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;AACvB,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,wBAAwB,GAAG,KAAK,EAC3C,YAAoB,EACW,EAAE;IACjC,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;IACpD,MAAM,cAAc,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACzE,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAY,EAAE,sBAAsB,CAAC,CAAC;IAC3E,IAAI,IAAI,CAAC,OAAO,KAAK,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;IAClF,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC;IAChE,IAAI,CAAC,kBAAkB,CAAC,MAAM,CAAC,EAAE,CAAC;QAChC,MAAM,IAAI,KAAK,CAAC,kEAAkE,CAAC,CAAC;IACtF,CAAC;IACD,IAAI,MAAM,KAAK,aAAa,IAAI,MAAM,KAAK,aAAa,EAAE,CAAC;QACzD,MAAM,IAAI,KAAK,CAAC,6FAA6F,CAAC,CAAC;IACjH,CAAC;IACD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC;IAChE,IAAI,KAAK,KAAK,SAAS,IAAI,CAAC,iBAAiB,CAAC,KAAK,CAAC,EAAE,CAAC;QACrD,MAAM,IAAI,KAAK,CAAC,2DAA2D,CAAC,CAAC;IAC/E,CAAC;IACD,MAAM,iBAAiB,GAAG,IAAI,CAAC,iBAAiB,CAAC;IACjD,IAAI,iBAAiB,KAAK,SAAS,IAAI,CAAC,6BAA6B,CAAC,iBAAiB,CAAC,EAAE,CAAC;QACzF,MAAM,IAAI,KAAK,CAAC,gEAAgE,CAAC,CAAC;IACpF,CAAC;IACD,IAAI,iBAAiB,KAAK,SAAS,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;QACzD,MAAM,IAAI,KAAK,CAAC,uEAAuE,CAAC,CAAC;IAC3F,CAAC;IACD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1D,MAAM,IAAI,KAAK,CAAC,qDAAqD,CAAC,CAAC;IACzE,CAAC;IAED,MAAM,iBAAiB,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC;IACnE,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;IAClC,MAAM,KAAK,GAAuB,EAAE,CAAC;IACrC,KAAK,MAAM,CAAC,SAAS,EAAE,SAAS,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC;QAC1D,MAAM,IAAI,GAAG,MAAM,CAAC,SAAS,EAAE,SAAS,SAAS,GAAG,CAAC,CAAC;QACtD,MAAM,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,SAAS,MAAM,EAAE,IAAI,CAAE,CAAC;QAC1D,IAAI,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,WAAW,EAAE,oBAAoB,CAAC,CAAC;QACxE,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAChB,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;YACpF,MAAM,IAAI,KAAK,CAAC,SAAS,SAAS,qCAAqC,CAAC,CAAC;QAC3E,CAAC;QACD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAClE,MAAM,IAAI,KAAK,CAAC,SAAS,SAAS,+CAA+C,CAAC,CAAC;QACrF,CAAC;QACD,MAAM,WAAW,GAAG,IAAI,GAAG,EAAU,CAAC;QACtC,MAAM,SAAS,GAA2B,EAAE,CAAC;QAC7C,KAAK,MAAM,CAAC,aAAa,EAAE,aAAa,CAAC,IAAI,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,EAAE,CAAC;YACtE,MAAM,QAAQ,GAAG,MAAM,CAAC,aAAa,EAAE,SAAS,SAAS,eAAe,aAAa,GAAG,CAAC,CAAC;YAC1F,MAAM,UAAU,GAAG,IAAI,CACrB,QAAQ,CAAC,EAAE,EACX,SAAS,SAAS,eAAe,aAAa,MAAM,EACpD,IAAI,CACJ,CAAC;YACH,IAAI,WAAW,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC;gBAChC,MAAM,IAAI,KAAK,CAAC,eAAe,UAAU,8BAA8B,EAAE,EAAE,CAAC,CAAC;YAC/E,CAAC;YACD,WAAW,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;YAC5B,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,SAAS,SAAS,eAAe,aAAa,SAAS,EAAE,IAAI,CAAE,CAAC;YACnG,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,iBAAiB,EAAE,KAAK,CAAC,CAAC;YACzD,MAAM,UAAU,GAAG,4BAA4B,CAAC,SAAS,CAAC,CAAC;YAC3D,IAAI,UAAU,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;gBAChC,MAAM,IAAI,KAAK,CAAC,YAAY,UAAU,4CAA4C,CAAC,CAAC;YACtF,CAAC;YACD,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,MAAM,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC;YACxD,MAAM,kBAAkB,GAAG,IAAI,CAC7B,QAAQ,CAAC,kBAAkB,EAC3B,SAAS,SAAS,eAAe,aAAa,sBAAsB,CACrE,CAAC;YACF,SAAS,CAAC,IAAI,CAAC;gBACb,EAAE,EAAE,UAAU;gBACd,OAAO,EAAE,SAAS,CAChB,QAAQ,CAAC,OAAO,EAChB,aAAa,GAAG,CAAC,EACjB,SAAS,SAAS,eAAe,aAAa,WAAW,CAC1D;gBACD,SAAS;gBACT,KAAK;gBACL,SAAS,EAAE,UAAU,CAAC,SAAkC;gBACxD,GAAG,CAAC,kBAAkB,CAAC,CAAC,CAAC,EAAE,kBAAkB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aACtD,CAAC,CAAC;QACL,CAAC;QACD,KAAK,CAAC,IAAI,CAAC;YACT,EAAE;YACF,OAAO,EAAE,SAAS,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,EAAE,SAAS,SAAS,WAAW,CAAC;YAC1E,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAA+B,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACpE,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,SAAS,SAAS,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,CAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC1F,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,SAAS,WAAW,CAAC,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,CAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAClG,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,SAAS,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,CAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACtF,SAAS;SACV,CAAC,CAAC;IACL,CAAC;IAED,OAAO;QACL,OAAO,EAAE,CAAC;QACV,MAAM;QACN,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC3B,GAAG,CAAC,iBAAiB,CAAC,CAAC,CAAC,EAAE,iBAAiB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACnD,KAAK;QACL,cAAc;KACf,CAAC;AACJ,CAAC,CAAC"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * The starting manifest `12ui convert package --template` prints.
3
+ *
4
+ * The manifest shape used to exist only as an example in skill prose, which
5
+ * made the format a thing an agent had to remember rather than a thing the tool
6
+ * hands out. This module is the single authored copy, and its test feeds it
7
+ * straight back through `readLocalPackageManifest` so the template cannot drift
8
+ * away from the parser that consumes it.
9
+ *
10
+ * Guidance goes to stderr in the command, never in here: stdout stays clean
11
+ * JSON so `12ui convert package --template > package.json` writes a file that
12
+ * parses.
13
+ */
14
+ export declare const PACKAGE_MANIFEST_TEMPLATE_IMAGES: readonly ["screens/home-viewport-1.png", "screens/home-viewport-2.png", "screens/pricing-viewport-1.png"];
15
+ export declare const packageManifestTemplate: () => Record<string, unknown>;
16
+ export declare const renderPackageManifestTemplate: () => string;
17
+ /**
18
+ * Printed to stderr beside the template. Says the things the JSON cannot: what
19
+ * a viewport is, and which field avoids paying twice for an image that already
20
+ * has a conversion.
21
+ */
22
+ export declare const PACKAGE_MANIFEST_TEMPLATE_NOTES: string;
23
+ //# sourceMappingURL=package-manifest-template.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"package-manifest-template.d.ts","sourceRoot":"","sources":["../src/package-manifest-template.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,eAAO,MAAM,gCAAgC,2GAInC,CAAC;AAEX,eAAO,MAAM,uBAAuB,QAAO,MAAM,CAAC,MAAM,EAAE,OAAO,CA4B/D,CAAC;AAEH,eAAO,MAAM,6BAA6B,QAAO,MAEhD,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,+BAA+B,QAKhC,CAAC"}
@@ -0,0 +1,60 @@
1
+ /**
2
+ * The starting manifest `12ui convert package --template` prints.
3
+ *
4
+ * The manifest shape used to exist only as an example in skill prose, which
5
+ * made the format a thing an agent had to remember rather than a thing the tool
6
+ * hands out. This module is the single authored copy, and its test feeds it
7
+ * straight back through `readLocalPackageManifest` so the template cannot drift
8
+ * away from the parser that consumes it.
9
+ *
10
+ * Guidance goes to stderr in the command, never in here: stdout stays clean
11
+ * JSON so `12ui convert package --template > package.json` writes a file that
12
+ * parses.
13
+ */
14
+ export const PACKAGE_MANIFEST_TEMPLATE_IMAGES = [
15
+ 'screens/home-viewport-1.png',
16
+ 'screens/home-viewport-2.png',
17
+ 'screens/pricing-viewport-1.png',
18
+ ];
19
+ export const packageManifestTemplate = () => ({
20
+ version: 1,
21
+ output: 'html',
22
+ responsiveQuality: 'standard',
23
+ pages: [
24
+ {
25
+ id: 'home',
26
+ kind: 'source',
27
+ title: 'Home',
28
+ path: '/',
29
+ // Ordered viewports of ONE continuous page. Two entries here means one
30
+ // page that scrolls, not two pages — that is the whole reason a package
31
+ // exists rather than two separate conversions.
32
+ viewports: [
33
+ { id: 'home-1', image: PACKAGE_MANIFEST_TEMPLATE_IMAGES[0] },
34
+ { id: 'home-2', image: PACKAGE_MANIFEST_TEMPLATE_IMAGES[1] },
35
+ ],
36
+ },
37
+ {
38
+ id: 'pricing',
39
+ kind: 'additional',
40
+ title: 'Pricing',
41
+ path: '/pricing',
42
+ viewports: [
43
+ { id: 'pricing-1', image: PACKAGE_MANIFEST_TEMPLATE_IMAGES[2] },
44
+ ],
45
+ },
46
+ ],
47
+ });
48
+ export const renderPackageManifestTemplate = () => (`${JSON.stringify(packageManifestTemplate(), null, 2)}\n`);
49
+ /**
50
+ * Printed to stderr beside the template. Says the things the JSON cannot: what
51
+ * a viewport is, and which field avoids paying twice for an image that already
52
+ * has a conversion.
53
+ */
54
+ export const PACKAGE_MANIFEST_TEMPLATE_NOTES = [
55
+ 'Paths are relative to the manifest file.',
56
+ 'Viewports are the ordered slices of one scrolling page; ordinals are filled in by position.',
57
+ 'Add "sourceConversionId" to a viewport whose image already converted, to reuse it instead of buying it again.',
58
+ 'Supported outputs: html and layerdoc. Export web_project or app_project from a finished conversion instead.',
59
+ ].join('\n');
60
+ //# sourceMappingURL=package-manifest-template.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"package-manifest-template.js","sourceRoot":"","sources":["../src/package-manifest-template.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,MAAM,CAAC,MAAM,gCAAgC,GAAG;IAC9C,6BAA6B;IAC7B,6BAA6B;IAC7B,gCAAgC;CACxB,CAAC;AAEX,MAAM,CAAC,MAAM,uBAAuB,GAAG,GAA4B,EAAE,CAAC,CAAC;IACrE,OAAO,EAAE,CAAC;IACV,MAAM,EAAE,MAAM;IACd,iBAAiB,EAAE,UAAU;IAC7B,KAAK,EAAE;QACL;YACE,EAAE,EAAE,MAAM;YACV,IAAI,EAAE,QAAQ;YACd,KAAK,EAAE,MAAM;YACb,IAAI,EAAE,GAAG;YACT,uEAAuE;YACvE,wEAAwE;YACxE,+CAA+C;YAC/C,SAAS,EAAE;gBACT,EAAE,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,gCAAgC,CAAC,CAAC,CAAC,EAAE;gBAC5D,EAAE,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,gCAAgC,CAAC,CAAC,CAAC,EAAE;aAC7D;SACF;QACD;YACE,EAAE,EAAE,SAAS;YACb,IAAI,EAAE,YAAY;YAClB,KAAK,EAAE,SAAS;YAChB,IAAI,EAAE,UAAU;YAChB,SAAS,EAAE;gBACT,EAAE,EAAE,EAAE,WAAW,EAAE,KAAK,EAAE,gCAAgC,CAAC,CAAC,CAAC,EAAE;aAChE;SACF;KACF;CACF,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,6BAA6B,GAAG,GAAW,EAAE,CAAC,CACzD,GAAG,IAAI,CAAC,SAAS,CAAC,uBAAuB,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAC1D,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,+BAA+B,GAAG;IAC7C,0CAA0C;IAC1C,6FAA6F;IAC7F,+GAA+G;IAC/G,6GAA6G;CAC9G,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC"}
@@ -0,0 +1,103 @@
1
+ import type { ConversionModel } from './conversion-models.js';
2
+ import { type ConversionOutput } from './conversion-outputs.js';
3
+ import type { ResponsiveConversionQuality } from './responsive-quality.js';
4
+ import { TwelveUiConversionPackageClient, type ConversionPackageFile, type ConversionPackageLegacyManifest, type ConversionPackageOperation } from './package-client.js';
5
+ /**
6
+ * One page, submitted as ONE package conversion of its ordered viewports.
7
+ *
8
+ * Converting a continuous page one screenshot at a time throws away page order
9
+ * and the stitching between viewports, which is the entire reason to have
10
+ * branched. This module is the single owner of that submission for both
11
+ * `12ui convert package` and `12ui branch execute --convert`.
12
+ */
13
+ export declare const PACKAGE_RESULT_FILENAME = "package.result.json";
14
+ export declare const PACKAGE_POLL_INTERVAL_MS = 4000;
15
+ export declare const PACKAGE_TIMEOUT_MS: number;
16
+ export type PackageImageMediaType = 'image/png' | 'image/jpeg' | 'image/webp';
17
+ export type PackageViewportInput = {
18
+ id: string;
19
+ ordinal: number;
20
+ imagePath: string;
21
+ bytes: Uint8Array;
22
+ mediaType: PackageImageMediaType;
23
+ /**
24
+ * An already-succeeded conversion of exactly these bytes. Attaching it skips
25
+ * both the upload and a second paid conversion of the same image — the reuse
26
+ * path that keeps a base conversion of the winner from being orphaned work.
27
+ */
28
+ sourceConversionId?: string;
29
+ };
30
+ export type PackagePageInput = {
31
+ id: string;
32
+ ordinal: number;
33
+ kind?: 'source' | 'additional';
34
+ title?: string;
35
+ purpose?: string;
36
+ path?: string;
37
+ viewports: PackageViewportInput[];
38
+ };
39
+ export type PackageSubmission = {
40
+ output: ConversionOutput;
41
+ model?: ConversionModel;
42
+ responsiveQuality?: ResponsiveConversionQuality;
43
+ pages: PackagePageInput[];
44
+ idempotencyKey: string;
45
+ };
46
+ export type PackagePageResult = {
47
+ id: string;
48
+ ordinal: number;
49
+ title?: string;
50
+ conversionId?: string;
51
+ outFile?: string;
52
+ sha256?: string;
53
+ bytes?: number;
54
+ mediaType?: string;
55
+ status: 'succeeded' | 'failed';
56
+ error?: string;
57
+ };
58
+ export type PackageSubmissionResult = {
59
+ packageId: string;
60
+ status: ConversionPackageOperation['status'];
61
+ output: ConversionOutput;
62
+ idempotencyKey: string;
63
+ pages: PackagePageResult[];
64
+ resultPath?: string;
65
+ };
66
+ export type PackageProgressEvent = {
67
+ stage: string;
68
+ percent?: number;
69
+ completed?: number;
70
+ total?: number;
71
+ };
72
+ /**
73
+ * The stitch precondition, checked HERE rather than at admission. Composition
74
+ * joins a page's viewports into one tall source, so a width disagreement is
75
+ * fatal — and the server discovers it only after every viewport is paid for.
76
+ */
77
+ export declare const assertPackagePageWidths: (pages: readonly PackagePageInput[]) => Promise<Map<string, {
78
+ width: number;
79
+ height: number;
80
+ }>>;
81
+ export declare const buildConversionPackageRequest: (submission: PackageSubmission) => Promise<{
82
+ manifest: ConversionPackageLegacyManifest;
83
+ screenshots: ConversionPackageFile[];
84
+ }>;
85
+ /**
86
+ * Submit, wait, and materialize. The package's own operation record is the
87
+ * durable identity: a retry under the same derived key replays it rather than
88
+ * buying the pages again.
89
+ */
90
+ export declare const submitConversionPackage: (args: {
91
+ client: TwelveUiConversionPackageClient;
92
+ submission: PackageSubmission;
93
+ outDir: string;
94
+ timeoutMs?: number;
95
+ pollIntervalMs?: number;
96
+ /** Fires as soon as the package has an id, before the long wait begins. */
97
+ onSubmitted?: (packageId: string) => void;
98
+ onProgress?: (event: PackageProgressEvent) => void;
99
+ sleep?: (milliseconds: number, signal?: AbortSignal) => Promise<void>;
100
+ signal?: AbortSignal;
101
+ }) => Promise<PackageSubmissionResult>;
102
+ export declare const writePackageResultRecord: (outDir: string, result: PackageSubmissionResult) => Promise<string>;
103
+ //# sourceMappingURL=package-submission.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"package-submission.d.ts","sourceRoot":"","sources":["../src/package-submission.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,173 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { mkdir, writeFile } from 'node:fs/promises';
3
+ import path from 'node:path';
4
+ import { CONVERSION_OUTPUT_EXTENSIONS, } from './conversion-outputs.js';
5
+ import { readImageDimensions } from './image-dimensions.js';
6
+ /**
7
+ * One page, submitted as ONE package conversion of its ordered viewports.
8
+ *
9
+ * Converting a continuous page one screenshot at a time throws away page order
10
+ * and the stitching between viewports, which is the entire reason to have
11
+ * branched. This module is the single owner of that submission for both
12
+ * `12ui convert package` and `12ui branch execute --convert`.
13
+ */
14
+ export const PACKAGE_RESULT_FILENAME = 'package.result.json';
15
+ export const PACKAGE_POLL_INTERVAL_MS = 4_000;
16
+ export const PACKAGE_TIMEOUT_MS = 30 * 60_000;
17
+ /**
18
+ * The stitch precondition, checked HERE rather than at admission. Composition
19
+ * joins a page's viewports into one tall source, so a width disagreement is
20
+ * fatal — and the server discovers it only after every viewport is paid for.
21
+ */
22
+ export const assertPackagePageWidths = async (pages) => {
23
+ const dimensions = new Map();
24
+ for (const page of pages) {
25
+ if (page.viewports.length === 0) {
26
+ throw new Error(`Page ${page.id} has no viewports to convert.`);
27
+ }
28
+ for (const viewport of page.viewports) {
29
+ dimensions.set(`${page.id}/${viewport.id}`, await readImageDimensions(viewport.bytes));
30
+ }
31
+ const first = dimensions.get(`${page.id}/${page.viewports[0].id}`);
32
+ const mismatched = page.viewports.find((viewport) => (dimensions.get(`${page.id}/${viewport.id}`).width !== first.width));
33
+ if (mismatched) {
34
+ const actual = dimensions.get(`${page.id}/${mismatched.id}`);
35
+ throw new Error(`Page ${page.id} screen ${mismatched.id} (${mismatched.imagePath}) is ${actual.width}px`
36
+ + ` wide but the page is ${first.width}px wide; every viewport of a page must share one`
37
+ + ' width. Re-render or crop the odd screen before submitting the page.');
38
+ }
39
+ }
40
+ return dimensions;
41
+ };
42
+ export const buildConversionPackageRequest = async (submission) => {
43
+ const dimensions = await assertPackagePageWidths(submission.pages);
44
+ const screenshots = [];
45
+ const manifest = {
46
+ version: 1,
47
+ output: submission.output,
48
+ ...(submission.model ? { model: submission.model } : {}),
49
+ ...(submission.responsiveQuality && submission.output === 'html'
50
+ ? { responsive_quality: submission.responsiveQuality }
51
+ : {}),
52
+ pages: submission.pages.map((page) => ({
53
+ id: page.id,
54
+ ordinal: page.ordinal,
55
+ ...(page.kind ? { kind: page.kind } : {}),
56
+ ...(page.title ? { title: page.title } : {}),
57
+ ...(page.purpose ? { purpose: page.purpose } : {}),
58
+ ...(page.path ? { path: page.path } : {}),
59
+ viewports: page.viewports.map((viewport) => {
60
+ const size = dimensions.get(`${page.id}/${viewport.id}`);
61
+ if (viewport.sourceConversionId) {
62
+ return {
63
+ id: viewport.id,
64
+ ordinal: viewport.ordinal,
65
+ source_conversion_id: viewport.sourceConversionId,
66
+ screenshot: {
67
+ sha256: createHash('sha256').update(viewport.bytes).digest('hex'),
68
+ media_type: viewport.mediaType,
69
+ size_bytes: viewport.bytes.byteLength,
70
+ width: size.width,
71
+ height: size.height,
72
+ },
73
+ };
74
+ }
75
+ const partId = `${page.id}--${viewport.id}`;
76
+ screenshots.push({ partId, bytes: viewport.bytes, mediaType: viewport.mediaType });
77
+ return { id: viewport.id, ordinal: viewport.ordinal, screenshot_part: partId };
78
+ }),
79
+ })),
80
+ };
81
+ return { manifest, screenshots };
82
+ };
83
+ const delay = async (milliseconds, signal) => (new Promise((resolve, reject) => {
84
+ const timer = setTimeout(resolve, milliseconds);
85
+ signal?.addEventListener('abort', () => {
86
+ clearTimeout(timer);
87
+ reject(signal.reason ?? new Error('Package wait aborted'));
88
+ }, { once: true });
89
+ }));
90
+ /**
91
+ * Submit, wait, and materialize. The package's own operation record is the
92
+ * durable identity: a retry under the same derived key replays it rather than
93
+ * buying the pages again.
94
+ */
95
+ export const submitConversionPackage = async (args) => {
96
+ const { manifest, screenshots } = await buildConversionPackageRequest(args.submission);
97
+ const sleep = args.sleep ?? delay;
98
+ const created = await args.client.createPackage({
99
+ manifest,
100
+ screenshots,
101
+ idempotencyKey: args.submission.idempotencyKey,
102
+ ...(args.signal ? { signal: args.signal } : {}),
103
+ });
104
+ args.onSubmitted?.(created.id);
105
+ const deadline = Date.now() + (args.timeoutMs ?? PACKAGE_TIMEOUT_MS);
106
+ let operation = created;
107
+ while (operation.status === 'queued' || operation.status === 'running') {
108
+ if (Date.now() >= deadline) {
109
+ throw new Error(`Timed out waiting for package ${created.id}. It is still running server-side; read it`
110
+ + ` back with GET /api/v1/convert/package/${created.id} rather than submitting again.`);
111
+ }
112
+ args.onProgress?.({
113
+ stage: operation.progress?.stage ?? operation.status,
114
+ ...(operation.progress?.percent === undefined ? {} : { percent: operation.progress.percent }),
115
+ ...(operation.progress?.completed === undefined
116
+ ? {}
117
+ : { completed: operation.progress.completed, total: operation.progress.total }),
118
+ });
119
+ await sleep(args.pollIntervalMs ?? PACKAGE_POLL_INTERVAL_MS, args.signal);
120
+ operation = await args.client.getPackage(created.id, args.signal);
121
+ }
122
+ args.onProgress?.({ stage: operation.status });
123
+ await mkdir(args.outDir, { recursive: true });
124
+ const extension = CONVERSION_OUTPUT_EXTENSIONS[args.submission.output];
125
+ const pages = [];
126
+ for (const page of operation.pages) {
127
+ if (page.status !== 'succeeded' || !page.href) {
128
+ pages.push({
129
+ id: page.id,
130
+ ordinal: page.ordinal,
131
+ ...(page.title ? { title: page.title } : {}),
132
+ status: 'failed',
133
+ error: operation.error?.detail ?? `Page ${page.id} finished ${page.status}.`,
134
+ });
135
+ continue;
136
+ }
137
+ const downloaded = await args.client.downloadPage(operation, page.id, args.signal);
138
+ const outFile = path.join(args.outDir, `${page.id}.${extension}`);
139
+ await writeFile(outFile, downloaded.bytes);
140
+ pages.push({
141
+ id: page.id,
142
+ ordinal: page.ordinal,
143
+ ...(page.title ? { title: page.title } : {}),
144
+ ...(page.conversion_id ? { conversionId: page.conversion_id } : {}),
145
+ outFile,
146
+ sha256: createHash('sha256').update(downloaded.bytes).digest('hex'),
147
+ bytes: downloaded.bytes.byteLength,
148
+ mediaType: downloaded.mediaType,
149
+ status: 'succeeded',
150
+ });
151
+ }
152
+ if (operation.status !== 'succeeded' && pages.every((page) => page.status === 'failed')) {
153
+ throw new Error(operation.error?.detail
154
+ ?? `Package ${operation.id} finished ${operation.status} with no converted page.`);
155
+ }
156
+ return {
157
+ packageId: operation.id,
158
+ status: operation.status,
159
+ output: args.submission.output,
160
+ idempotencyKey: args.submission.idempotencyKey,
161
+ pages,
162
+ };
163
+ };
164
+ export const writePackageResultRecord = async (outDir, result) => {
165
+ const file = path.join(outDir, PACKAGE_RESULT_FILENAME);
166
+ await mkdir(outDir, { recursive: true });
167
+ await writeFile(file, `${JSON.stringify({ version: 1, ...result }, null, 2)}\n`, {
168
+ encoding: 'utf8',
169
+ mode: 0o600,
170
+ });
171
+ return file;
172
+ };
173
+ //# sourceMappingURL=package-submission.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"package-submission.js","sourceRoot":"","sources":["../src/package-submission.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,95 @@
1
+ import type { DraftRecord } from './draft-workspace.js';
2
+ /**
3
+ * `selection.json`, version 6 — the same contract the skill used to ask an
4
+ * agent to hand-assemble from four other files. Every field here is copied
5
+ * from durable evidence the run already wrote, which is the point: a record
6
+ * assembled by hand can disagree with the run it describes, and this one
7
+ * cannot.
8
+ *
9
+ * The recommendation protocol is preserved exactly: `recommended` when the
10
+ * winner is the recommended candidate, `override` when it is not (and then a
11
+ * specific reason is required), `no-recommendation` when the run indicated
12
+ * none.
13
+ */
14
+ export declare const SELECTION_RECORD_VERSION = 6;
15
+ export type SelectionRecord = {
16
+ version: 6;
17
+ createdAt: string;
18
+ requestSummary: string;
19
+ viewportMode: 'first-viewport';
20
+ designMode: DraftRecord['mode'];
21
+ redesignSource: {
22
+ originalPath: string | null;
23
+ originalSha256: string | null;
24
+ preparedPath: string | null;
25
+ preparedSha256: string | null;
26
+ preparation: 'none' | 'first-viewport-crop';
27
+ };
28
+ contract: {
29
+ preserve: string[];
30
+ change: string[];
31
+ };
32
+ referencePolicy: {
33
+ retrieval: 'text-only' | 'text-and-redesign-source';
34
+ generation: 'one-corpus-image-per-candidate' | 'redesign-source-only';
35
+ imagesPerGeneration: 1;
36
+ };
37
+ corpus: {
38
+ query: string;
39
+ mode: string;
40
+ fallback: null;
41
+ idempotencyKey: string;
42
+ setId: string;
43
+ references: {
44
+ id: string;
45
+ path: string;
46
+ sha256: string;
47
+ aspect: string;
48
+ }[];
49
+ };
50
+ generation: {
51
+ referenceMode: 'inspiration' | 'preserve-structure';
52
+ manifestPath: string;
53
+ manifestSha256: string;
54
+ batchAttemptPath: string;
55
+ };
56
+ candidates: {
57
+ id: string;
58
+ path: string;
59
+ sha256: string | null;
60
+ prompt: string;
61
+ promptSha256: string;
62
+ directionReferenceId: string | null;
63
+ direction: string;
64
+ generationReferencePath: string;
65
+ generationReferenceSha256: string;
66
+ referenceMode: 'inspiration' | 'preserve-structure';
67
+ provider: string | null;
68
+ idempotencyKey: string;
69
+ providerIdempotencyEnforced: boolean;
70
+ attemptEvidencePath: string;
71
+ rejectionReasons: string[];
72
+ }[];
73
+ recommendation: {
74
+ candidateId: string | null;
75
+ source: string | null;
76
+ };
77
+ winner: string;
78
+ selectionSource: 'recommended' | 'override' | 'no-recommendation';
79
+ selectionOverrideReason: string | null;
80
+ rationale: string;
81
+ };
82
+ export declare const buildSelectionRecord: (args: {
83
+ draft: DraftRecord;
84
+ winner: string;
85
+ reason: string;
86
+ recommendation?: {
87
+ candidateId: string | null;
88
+ source: string | null;
89
+ };
90
+ rejectionReasons?: Record<string, string[]>;
91
+ now?: () => Date;
92
+ }) => Promise<SelectionRecord>;
93
+ export declare const writeSelectionRecord: (file: string, record: SelectionRecord) => Promise<void>;
94
+ export declare const readSelectionRecord: (file: string) => Promise<SelectionRecord | undefined>;
95
+ //# sourceMappingURL=selection-record.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"selection-record.d.ts","sourceRoot":"","sources":["../src/selection-record.ts"],"names":[],"mappings":"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"}