@12ui/design 0.2.81 → 0.2.83

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 (301) hide show
  1. package/README.md +11 -7
  2. package/SKILL.md +1 -1
  3. package/dist/branch-execution.d.ts.map +1 -1
  4. package/dist/branch-execution.js +6 -0
  5. package/dist/branch-execution.js.map +1 -1
  6. package/dist/branch-materialize.d.ts.map +1 -1
  7. package/dist/branch-materialize.js +6 -2
  8. package/dist/branch-materialize.js.map +1 -1
  9. package/dist/cli-capabilities.d.ts +4 -7
  10. package/dist/cli-capabilities.d.ts.map +1 -1
  11. package/dist/cli-capabilities.js +4 -4
  12. package/dist/cli-capabilities.js.map +1 -1
  13. package/dist/cli-help/conversion.d.ts +1 -1
  14. package/dist/cli-help/conversion.js +1 -1
  15. package/dist/cli-help/conversion.js.map +1 -1
  16. package/dist/cli-help/index.d.ts +3 -3
  17. package/dist/cli-help/workflow.d.ts +2 -2
  18. package/dist/cli-help/workflow.js +4 -4
  19. package/dist/cli-help/workflow.js.map +1 -1
  20. package/dist/cli-image-backend.d.ts +6 -1
  21. package/dist/cli-image-backend.d.ts.map +1 -1
  22. package/dist/cli-image-backend.js +8 -3
  23. package/dist/cli-image-backend.js.map +1 -1
  24. package/dist/cli-local-runtime.d.ts +6 -0
  25. package/dist/cli-local-runtime.d.ts.map +1 -1
  26. package/dist/cli-local-runtime.js +14 -1
  27. package/dist/cli-local-runtime.js.map +1 -1
  28. package/dist/cli-usage.d.ts.map +1 -1
  29. package/dist/cli-usage.js +8 -7
  30. package/dist/cli-usage.js.map +1 -1
  31. package/dist/cli-workspace-draw.d.ts.map +1 -1
  32. package/dist/cli-workspace-draw.js +2 -0
  33. package/dist/cli-workspace-draw.js.map +1 -1
  34. package/dist/cli-workspace-runner.d.ts.map +1 -1
  35. package/dist/cli-workspace-runner.js +2 -1
  36. package/dist/cli-workspace-runner.js.map +1 -1
  37. package/dist/legacy-skill-catalog.d.ts.map +1 -1
  38. package/dist/legacy-skill-catalog.js +13 -1
  39. package/dist/legacy-skill-catalog.js.map +1 -1
  40. package/dist/mcp-slate-tool-defs.d.ts.map +1 -1
  41. package/dist/mcp-slate-tool-defs.js +3 -2
  42. package/dist/mcp-slate-tool-defs.js.map +1 -1
  43. package/dist/mcp-slate-ui-copy.d.ts +10 -0
  44. package/dist/mcp-slate-ui-copy.d.ts.map +1 -1
  45. package/dist/mcp-slate-ui-copy.js +9 -0
  46. package/dist/mcp-slate-ui-copy.js.map +1 -1
  47. package/dist/mcp-slate-ui-locales/de-DE.d.ts.map +1 -1
  48. package/dist/mcp-slate-ui-locales/de-DE.js +5 -0
  49. package/dist/mcp-slate-ui-locales/de-DE.js.map +1 -1
  50. package/dist/mcp-slate-ui-locales/es-419.d.ts.map +1 -1
  51. package/dist/mcp-slate-ui-locales/es-419.js +5 -0
  52. package/dist/mcp-slate-ui-locales/es-419.js.map +1 -1
  53. package/dist/mcp-slate-ui-locales/es-ES.d.ts.map +1 -1
  54. package/dist/mcp-slate-ui-locales/es-ES.js +5 -0
  55. package/dist/mcp-slate-ui-locales/es-ES.js.map +1 -1
  56. package/dist/mcp-slate-ui-locales/fr-FR.d.ts.map +1 -1
  57. package/dist/mcp-slate-ui-locales/fr-FR.js +5 -0
  58. package/dist/mcp-slate-ui-locales/fr-FR.js.map +1 -1
  59. package/dist/mcp-slate-ui-locales/hi-IN.d.ts.map +1 -1
  60. package/dist/mcp-slate-ui-locales/hi-IN.js +5 -0
  61. package/dist/mcp-slate-ui-locales/hi-IN.js.map +1 -1
  62. package/dist/mcp-slate-ui-locales/it-IT.d.ts.map +1 -1
  63. package/dist/mcp-slate-ui-locales/it-IT.js +5 -0
  64. package/dist/mcp-slate-ui-locales/it-IT.js.map +1 -1
  65. package/dist/mcp-slate-ui-locales/ja-JP.d.ts.map +1 -1
  66. package/dist/mcp-slate-ui-locales/ja-JP.js +5 -0
  67. package/dist/mcp-slate-ui-locales/ja-JP.js.map +1 -1
  68. package/dist/mcp-slate-ui-locales/ko-KR.d.ts.map +1 -1
  69. package/dist/mcp-slate-ui-locales/ko-KR.js +5 -0
  70. package/dist/mcp-slate-ui-locales/ko-KR.js.map +1 -1
  71. package/dist/mcp-slate-ui-locales/pt-BR.d.ts.map +1 -1
  72. package/dist/mcp-slate-ui-locales/pt-BR.js +5 -0
  73. package/dist/mcp-slate-ui-locales/pt-BR.js.map +1 -1
  74. package/dist/mcp-slate-ui-locales/zh-CN.d.ts.map +1 -1
  75. package/dist/mcp-slate-ui-locales/zh-CN.js +5 -0
  76. package/dist/mcp-slate-ui-locales/zh-CN.js.map +1 -1
  77. package/dist/mcp-slate-ui-locales/zh-TW.d.ts.map +1 -1
  78. package/dist/mcp-slate-ui-locales/zh-TW.js +5 -0
  79. package/dist/mcp-slate-ui-locales/zh-TW.js.map +1 -1
  80. package/dist/mcp-slate-ui-script-board.d.ts +19 -0
  81. package/dist/mcp-slate-ui-script-board.d.ts.map +1 -0
  82. package/dist/mcp-slate-ui-script-board.js +126 -0
  83. package/dist/mcp-slate-ui-script-board.js.map +1 -0
  84. package/dist/mcp-slate-ui-script-designs.d.ts +1 -1
  85. package/dist/mcp-slate-ui-script-designs.d.ts.map +1 -1
  86. package/dist/mcp-slate-ui-script-designs.js +24 -15
  87. package/dist/mcp-slate-ui-script-designs.js.map +1 -1
  88. package/dist/mcp-slate-ui-script-inspiration-collage.d.ts +5 -2
  89. package/dist/mcp-slate-ui-script-inspiration-collage.d.ts.map +1 -1
  90. package/dist/mcp-slate-ui-script-inspiration-collage.js +9 -5
  91. package/dist/mcp-slate-ui-script-inspiration-collage.js.map +1 -1
  92. package/dist/mcp-slate-ui-script-inspiration-gallery.d.ts +7 -4
  93. package/dist/mcp-slate-ui-script-inspiration-gallery.d.ts.map +1 -1
  94. package/dist/mcp-slate-ui-script-inspiration-gallery.js +46 -5
  95. package/dist/mcp-slate-ui-script-inspiration-gallery.js.map +1 -1
  96. package/dist/mcp-slate-ui-script-inspiration-grid.d.ts.map +1 -1
  97. package/dist/mcp-slate-ui-script-inspiration-grid.js +4 -0
  98. package/dist/mcp-slate-ui-script-inspiration-grid.js.map +1 -1
  99. package/dist/mcp-slate-ui-script-pause.d.ts +4 -0
  100. package/dist/mcp-slate-ui-script-pause.d.ts.map +1 -1
  101. package/dist/mcp-slate-ui-script-pause.js +9 -2
  102. package/dist/mcp-slate-ui-script-pause.js.map +1 -1
  103. package/dist/mcp-slate-ui-script-peek.d.ts +16 -0
  104. package/dist/mcp-slate-ui-script-peek.d.ts.map +1 -0
  105. package/dist/mcp-slate-ui-script-peek.js +89 -0
  106. package/dist/mcp-slate-ui-script-peek.js.map +1 -0
  107. package/dist/mcp-slate-ui-script-references.d.ts +4 -2
  108. package/dist/mcp-slate-ui-script-references.d.ts.map +1 -1
  109. package/dist/mcp-slate-ui-script-references.js +39 -7
  110. package/dist/mcp-slate-ui-script-references.js.map +1 -1
  111. package/dist/mcp-slate-ui-script-remote.js +2 -2
  112. package/dist/mcp-slate-ui-script-viewer.d.ts +7 -2
  113. package/dist/mcp-slate-ui-script-viewer.d.ts.map +1 -1
  114. package/dist/mcp-slate-ui-script-viewer.js +183 -50
  115. package/dist/mcp-slate-ui-script-viewer.js.map +1 -1
  116. package/dist/mcp-slate-ui-script.d.ts.map +1 -1
  117. package/dist/mcp-slate-ui-script.js +4 -0
  118. package/dist/mcp-slate-ui-script.js.map +1 -1
  119. package/dist/mcp-slate-ui-styles-board.d.ts +7 -0
  120. package/dist/mcp-slate-ui-styles-board.d.ts.map +1 -0
  121. package/dist/mcp-slate-ui-styles-board.js +30 -0
  122. package/dist/mcp-slate-ui-styles-board.js.map +1 -0
  123. package/dist/mcp-slate-ui-styles-designs.d.ts +2 -1
  124. package/dist/mcp-slate-ui-styles-designs.d.ts.map +1 -1
  125. package/dist/mcp-slate-ui-styles-designs.js +10 -8
  126. package/dist/mcp-slate-ui-styles-designs.js.map +1 -1
  127. package/dist/mcp-slate-ui-styles-inspiration.d.ts.map +1 -1
  128. package/dist/mcp-slate-ui-styles-inspiration.js +13 -2
  129. package/dist/mcp-slate-ui-styles-inspiration.js.map +1 -1
  130. package/dist/mcp-slate-ui-styles-loading.d.ts +18 -0
  131. package/dist/mcp-slate-ui-styles-loading.d.ts.map +1 -0
  132. package/dist/mcp-slate-ui-styles-loading.js +37 -0
  133. package/dist/mcp-slate-ui-styles-loading.js.map +1 -0
  134. package/dist/mcp-slate-ui-styles-peek.d.ts +8 -0
  135. package/dist/mcp-slate-ui-styles-peek.d.ts.map +1 -0
  136. package/dist/mcp-slate-ui-styles-peek.js +13 -0
  137. package/dist/mcp-slate-ui-styles-peek.js.map +1 -0
  138. package/dist/mcp-slate-ui-styles.d.ts.map +1 -1
  139. package/dist/mcp-slate-ui-styles.js +0 -3
  140. package/dist/mcp-slate-ui-styles.js.map +1 -1
  141. package/dist/mcp-slate-ui.d.ts.map +1 -1
  142. package/dist/mcp-slate-ui.js +4 -1
  143. package/dist/mcp-slate-ui.js.map +1 -1
  144. package/dist/mcp-workflow-tools.js +2 -2
  145. package/dist/mcp-workflow-tools.js.map +1 -1
  146. package/dist/prototype-browsers.d.ts +10 -2
  147. package/dist/prototype-browsers.d.ts.map +1 -1
  148. package/dist/prototype-browsers.js +27 -2
  149. package/dist/prototype-browsers.js.map +1 -1
  150. package/dist/review-files-server.d.ts +8 -0
  151. package/dist/review-files-server.d.ts.map +1 -0
  152. package/dist/review-files-server.js +133 -0
  153. package/dist/review-files-server.js.map +1 -0
  154. package/dist/review-page-assets.d.ts +1 -1
  155. package/dist/review-page-assets.d.ts.map +1 -1
  156. package/dist/review-page-assets.js +3 -1
  157. package/dist/review-page-assets.js.map +1 -1
  158. package/dist/review-page.d.ts +8 -1
  159. package/dist/review-page.d.ts.map +1 -1
  160. package/dist/review-page.js +32 -21
  161. package/dist/review-page.js.map +1 -1
  162. package/dist/review-server-guard.d.ts +33 -0
  163. package/dist/review-server-guard.d.ts.map +1 -0
  164. package/dist/review-server-guard.js +65 -0
  165. package/dist/review-server-guard.js.map +1 -0
  166. package/dist/review-server.d.ts +2 -0
  167. package/dist/review-server.d.ts.map +1 -1
  168. package/dist/review-server.js +45 -74
  169. package/dist/review-server.js.map +1 -1
  170. package/dist/server.d.ts.map +1 -1
  171. package/dist/server.js +2 -1
  172. package/dist/server.js.map +1 -1
  173. package/dist/slate-actions.d.ts +6 -7
  174. package/dist/slate-actions.d.ts.map +1 -1
  175. package/dist/slate-actions.js +6 -9
  176. package/dist/slate-actions.js.map +1 -1
  177. package/dist/slate-branch-runner.d.ts +120 -0
  178. package/dist/slate-branch-runner.d.ts.map +1 -0
  179. package/dist/slate-branch-runner.js +312 -0
  180. package/dist/slate-branch-runner.js.map +1 -0
  181. package/dist/slate-captions-local.d.ts +14 -0
  182. package/dist/slate-captions-local.d.ts.map +1 -0
  183. package/dist/slate-captions-local.js +70 -0
  184. package/dist/slate-captions-local.js.map +1 -0
  185. package/dist/slate-captions-remote.d.ts +29 -0
  186. package/dist/slate-captions-remote.d.ts.map +1 -0
  187. package/dist/slate-captions-remote.js +65 -0
  188. package/dist/slate-captions-remote.js.map +1 -0
  189. package/dist/slate-captions.d.ts +41 -0
  190. package/dist/slate-captions.d.ts.map +1 -0
  191. package/dist/slate-captions.js +112 -0
  192. package/dist/slate-captions.js.map +1 -0
  193. package/dist/slate-commit.d.ts.map +1 -1
  194. package/dist/slate-commit.js +8 -6
  195. package/dist/slate-commit.js.map +1 -1
  196. package/dist/slate-image-executor.d.ts +18 -3
  197. package/dist/slate-image-executor.d.ts.map +1 -1
  198. package/dist/slate-image-executor.js +18 -5
  199. package/dist/slate-image-executor.js.map +1 -1
  200. package/dist/slate-paths.d.ts +3 -1
  201. package/dist/slate-paths.d.ts.map +1 -1
  202. package/dist/slate-paths.js +8 -2
  203. package/dist/slate-paths.js.map +1 -1
  204. package/dist/slate-round-prompt.d.ts +0 -12
  205. package/dist/slate-round-prompt.d.ts.map +1 -1
  206. package/dist/slate-round-prompt.js +0 -15
  207. package/dist/slate-round-prompt.js.map +1 -1
  208. package/dist/slate-round-runner.d.ts.map +1 -1
  209. package/dist/slate-round-runner.js +8 -14
  210. package/dist/slate-round-runner.js.map +1 -1
  211. package/dist/slate-runner-context.d.ts +3 -0
  212. package/dist/slate-runner-context.d.ts.map +1 -1
  213. package/dist/slate-runner-context.js.map +1 -1
  214. package/dist/slate-runner-main.d.ts +3 -0
  215. package/dist/slate-runner-main.d.ts.map +1 -1
  216. package/dist/slate-runner-main.js +5 -1
  217. package/dist/slate-runner-main.js.map +1 -1
  218. package/dist/slate-runner-spawn.js +2 -2
  219. package/dist/slate-runner-spawn.js.map +1 -1
  220. package/dist/slate-site-references-capture.d.ts +38 -1
  221. package/dist/slate-site-references-capture.d.ts.map +1 -1
  222. package/dist/slate-site-references-capture.js +25 -7
  223. package/dist/slate-site-references-capture.js.map +1 -1
  224. package/dist/slate-site-references-client.d.ts +13 -1
  225. package/dist/slate-site-references-client.d.ts.map +1 -1
  226. package/dist/slate-site-references-client.js +39 -14
  227. package/dist/slate-site-references-client.js.map +1 -1
  228. package/dist/slate-site-references-local.d.ts +3 -0
  229. package/dist/slate-site-references-local.d.ts.map +1 -1
  230. package/dist/slate-site-references-local.js +20 -1
  231. package/dist/slate-site-references-local.js.map +1 -1
  232. package/dist/slate-site-references-suggest.d.ts +25 -2
  233. package/dist/slate-site-references-suggest.d.ts.map +1 -1
  234. package/dist/slate-site-references-suggest.js +71 -12
  235. package/dist/slate-site-references-suggest.js.map +1 -1
  236. package/dist/slate-site-references.d.ts +11 -0
  237. package/dist/slate-site-references.d.ts.map +1 -1
  238. package/dist/slate-site-references.js +42 -3
  239. package/dist/slate-site-references.js.map +1 -1
  240. package/dist/slate-view-contract.d.ts +39 -1
  241. package/dist/slate-view-contract.d.ts.map +1 -1
  242. package/dist/slate-view.d.ts.map +1 -1
  243. package/dist/slate-view.js +8 -0
  244. package/dist/slate-view.js.map +1 -1
  245. package/dist/slate-workspace-parse.d.ts.map +1 -1
  246. package/dist/slate-workspace-parse.js +35 -0
  247. package/dist/slate-workspace-parse.js.map +1 -1
  248. package/dist/slate-workspace-types.d.ts +31 -2
  249. package/dist/slate-workspace-types.d.ts.map +1 -1
  250. package/dist/workflow/adapter-12ui.js +1 -1
  251. package/dist/workflow/adapter-12ui.js.map +1 -1
  252. package/dist/workflow/adapters.d.ts.map +1 -1
  253. package/dist/workflow/adapters.js +3 -3
  254. package/dist/workflow/adapters.js.map +1 -1
  255. package/dist/workflow/providers.js +2 -2
  256. package/dist/workflow/providers.js.map +1 -1
  257. package/dist/workflow/routing.d.ts +8 -1
  258. package/dist/workflow/routing.d.ts.map +1 -1
  259. package/dist/workflow/routing.js +9 -2
  260. package/dist/workflow/routing.js.map +1 -1
  261. package/dist/workflow/types.d.ts +5 -2
  262. package/dist/workflow/types.d.ts.map +1 -1
  263. package/dist/workflow/types.js.map +1 -1
  264. package/dist/workflow-transport.d.ts.map +1 -1
  265. package/dist/workflow-transport.js +4 -2
  266. package/dist/workflow-transport.js.map +1 -1
  267. package/dist/workspace-draw-branch.d.ts +27 -0
  268. package/dist/workspace-draw-branch.d.ts.map +1 -0
  269. package/dist/workspace-draw-branch.js +101 -0
  270. package/dist/workspace-draw-branch.js.map +1 -0
  271. package/dist/workspace-draw-client.d.ts +27 -0
  272. package/dist/workspace-draw-client.d.ts.map +1 -1
  273. package/dist/workspace-draw-client.js +30 -0
  274. package/dist/workspace-draw-client.js.map +1 -1
  275. package/dist/workspace-draw-codex.d.ts +5 -5
  276. package/dist/workspace-draw-codex.d.ts.map +1 -1
  277. package/dist/workspace-draw-codex.js +4 -3
  278. package/dist/workspace-draw-codex.js.map +1 -1
  279. package/dist/workspace-draw-run.d.ts +19 -3
  280. package/dist/workspace-draw-run.d.ts.map +1 -1
  281. package/dist/workspace-draw-run.js +44 -4
  282. package/dist/workspace-draw-run.js.map +1 -1
  283. package/dist/workspace-draw-types.d.ts +18 -2
  284. package/dist/workspace-draw-types.d.ts.map +1 -1
  285. package/dist/workspace-draw-types.js.map +1 -1
  286. package/dist/workspace-runner-main.d.ts +9 -2
  287. package/dist/workspace-runner-main.d.ts.map +1 -1
  288. package/dist/workspace-runner-main.js +21 -2
  289. package/dist/workspace-runner-main.js.map +1 -1
  290. package/dist/workspace-runner-spawn.js +1 -1
  291. package/dist/workspace-runner-spawn.js.map +1 -1
  292. package/open-design.json +2 -2
  293. package/package.json +1 -1
  294. package/runtime/codex-conversion/bin/convert.mjs +1 -1
  295. package/runtime/codex-conversion/src/codex/caller-home.mjs +95 -0
  296. package/runtime/codex-conversion/src/codex/home.mjs +8 -2
  297. package/runtime/codex-conversion/src/images/execute.mjs +1 -1
  298. package/runtime/codex-conversion/src/images/native-invoke.mjs +21 -13
  299. package/runtime/codex-conversion/src/images/native.mjs +42 -19
  300. package/runtime/codex-conversion/src/run.mjs +2 -1
  301. package/skills/12ui-design/SKILL.md +6 -6
@@ -5,10 +5,13 @@ import { execFile } from 'node:child_process';
5
5
 
6
6
  const TEMP_HOME_PREFIX = '12ui-codex-';
7
7
 
8
- /** The planner receives an allowlisted environment, never provider credentials. @param {string} home */
8
+ /**
9
+ * The planner receives an allowlisted environment, never provider credentials. With no home, `CODEX_HOME` stays unset
10
+ * and Codex uses its own default home. @param {string | null | undefined} home
11
+ */
9
12
  export function subscriptionEnv(home) {
10
13
  /** @type {NodeJS.ProcessEnv} */
11
- const env = { CODEX_HOME: home };
14
+ const env = home ? { CODEX_HOME: home } : {};
12
15
  for (const key of ['PATH', 'HOME', 'TMPDIR', 'TEMP', 'TMP', 'LANG', 'LC_ALL', 'SYSTEMROOT']) {
13
16
  if (process.env[key]) env[key] = process.env[key];
14
17
  }
@@ -49,6 +52,9 @@ export async function prepareHome({ authHome, binary, runDir, reasoning = 'low'
49
52
  }
50
53
 
51
54
 
55
+ /** Whether a recorded home is one of this module's temp homes (image calls of earlier releases ran in one). */
56
+ export const isTempHome = home => typeof home === 'string' && path.basename(home).startsWith(TEMP_HOME_PREFIX);
57
+
52
58
  /**
53
59
  * Remove one temp home this module made. Only a directory directly under the temp root whose name
54
60
  * carries the temp-home prefix is ever removed, so a corrupted record cannot point this at a real home.
@@ -34,7 +34,7 @@ async function executeGroup({group,sourceBytes,runDir,store,env,progress,fetchIm
34
34
  progress?.({phase:'image-complete',groupId:group.id,reused:result.reused});
35
35
  return {assets,receipt};
36
36
  }
37
- export async function executeImages({plan,sourcePath,runDir,store,env=process.env,progress,fetchImpl=fetch,imageBackend='external',codexBinary='codex',codexHome=undefined,timeoutMs=1800000,nativeModel='gpt-6-astra'}) {
37
+ export async function executeImages({plan,sourcePath,runDir,store,env=process.env,progress,fetchImpl=fetch,imageBackend='native',codexBinary='codex',codexHome=undefined,timeoutMs=1800000,nativeModel='gpt-6-astra'}) {
38
38
  if(!['external','native'].includes(imageBackend))throw Error('Unsupported image backend');
39
39
  if(nativeModel!=='gpt-6-astra')throw Error('Unsupported native model');
40
40
  await fs.mkdir(runDir,{recursive:true});
@@ -3,26 +3,35 @@ import path from 'node:path';
3
3
  import {spawn} from 'node:child_process';
4
4
  import {createWriteStream} from 'node:fs';
5
5
  import {finished} from 'node:stream/promises';
6
- import {subscriptionEnv,removeTempHome} from '../codex/home.mjs';
7
- import {filesUnder} from './native-files.mjs';
6
+ import {subscriptionEnv} from '../codex/home.mjs';
7
+ import {callRollouts,threadIdOf} from '../codex/caller-home.mjs';
8
8
  import {collectNative,packNativeReceipt} from './native-collect.mjs';
9
9
 
10
+ /** The model that wraps the image tool, and its effort, when a request names neither. */
11
+ export const NATIVE_DEFAULTS=Object.freeze({model:'gpt-6-astra',effort:'medium'});
12
+
10
13
  // Based on the successful C-N03 study invocation; separate from the no-tool planner.
11
14
  // The call is unattended (`-a never`) and its prompt carries text from outside (a person's typed edit, a plan built
12
15
  // from a source image), so its sandbox is read-only: the model may read the attached images and call the image tool,
13
16
  // whose output Codex itself records in the rollout and its own home, but any command it is talked into cannot write.
14
17
  // Proven with real Codex 0.159.3 (docs/slate-remote.md, "Image calls are read-only").
18
+ // `--ignore-user-config` keeps the person's MCP servers, plugins and hooks out of the call; their `service_tier` (their
19
+ // own fast-lane choice) is carried over by itself when the home sets one.
15
20
  export const NATIVE_SANDBOX = 'read-only';
16
21
  export function nativeArgv(spec, finalPath) {
22
+ const model = spec.model ?? NATIVE_DEFAULTS.model, effort = spec.effort ?? NATIVE_DEFAULTS.effort;
17
23
  return ['-a', 'never', 'exec', '--ignore-user-config', '--ignore-rules', '--strict-config', '-C', spec.workDir,
18
- '--skip-git-repo-check', '-s', NATIVE_SANDBOX, '-m', 'gpt-6-astra', '-c', 'model_reasoning_effort="medium"',
24
+ '--skip-git-repo-check', '-s', NATIVE_SANDBOX, '-m', model, '-c', `model_reasoning_effort="${effort}"`,
19
25
  '-c', 'model_provider="openai"', '-c', 'forced_login_method="chatgpt"', '-c', 'project_doc_max_bytes=0',
26
+ ...(spec.serviceTier ? ['-c', `service_tier="${spec.serviceTier}"`] : []),
20
27
  '--enable', 'skip_host_skill_discovery', '--json', '--color', 'never', '--output-last-message', finalPath,
21
28
  ...(spec.referencePaths ?? [spec.referencePath]).flatMap(file => ['--image', file]), '-'];
22
29
  }
23
30
  /**
24
- * One native image call: `codex exec` in its own process group, its prompt on stdin, its events and stderr kept in the
25
- * call directory. Optional in `spec`:
31
+ * One native image call: `codex exec` in its own process group, in the caller's Codex home (`auth.envHome`; unset
32
+ * leaves Codex's default), its prompt on stdin, its events and stderr kept in the call directory. The call's own
33
+ * session file, found by the thread id its events announce, is copied into the call's native-custody and stays in the
34
+ * home like any other session. Optional in `spec`:
26
35
  * - `interruptOnSignal` (default true): a SIGINT or SIGTERM of this process stops the call. A caller that finishes its
27
36
  * calls on a signal itself (the Design workspace runner) passes false, so the call runs to its own end or timeout.
28
37
  * - `onSpawn({pgid, callDir})` / `onExit({pgid})`: told the child's process group (it leads its own) once it runs and
@@ -32,14 +41,15 @@ export async function invokeNative(spec, {callDir, persistMetadata}) {
32
41
  await fs.mkdir(spec.workDir, {recursive: true});
33
42
  const auth = spec.auth;
34
43
  const finalPath = path.join(callDir, 'final.txt'), argv = nativeArgv(spec, finalPath);
35
- const metadata = {model: 'gpt-6-astra', effort: 'medium', authentication: auth.authentication, home: auth.home, argv, startedAt: new Date().toISOString()};
44
+ const metadata = {model: spec.model ?? NATIVE_DEFAULTS.model, effort: spec.effort ?? NATIVE_DEFAULTS.effort, serviceTier: spec.serviceTier ?? null,
45
+ authentication: auth.authentication, home: auth.home, envHome: auth.envHome, argv, startedAt: new Date().toISOString()};
36
46
  await persistMetadata(metadata); // Private runtime location needed for collection after interruption.
37
47
  await fs.writeFile(path.join(callDir, 'invocation.json'), JSON.stringify(metadata, null, 2) + '\n', {flag: 'wx'});
38
48
  const stdout = createWriteStream(path.join(callDir, 'events.jsonl'), {flags: 'wx'});
39
49
  const stderr = createWriteStream(path.join(callDir, 'stderr.log'), {flags: 'wx'});
40
50
  const prompt = spec.prompt;
41
51
  let timedOut = false, killTimer;
42
- const child = spawn(spec.binary, argv, {cwd: spec.workDir, env: subscriptionEnv(auth.home), detached: true, stdio: ['pipe', 'pipe', 'pipe']});
52
+ const child = spawn(spec.binary, argv, {cwd: spec.workDir, env: subscriptionEnv(auth.envHome), detached: true, stdio: ['pipe', 'pipe', 'pipe']});
43
53
  // ESRCH: the group is gone. EPERM: macOS answers so for a group whose members are all zombies.
44
54
  const stop = signal => { if (child.pid) try { process.kill(-child.pid, signal); } catch (error) { if (error.code !== 'ESRCH' && error.code !== 'EPERM') throw error; } };
45
55
  const terminate = () => { stop('SIGTERM'); killTimer = setTimeout(() => stop('SIGKILL'), 5000); };
@@ -59,13 +69,11 @@ export async function invokeNative(spec, {callDir, persistMetadata}) {
59
69
  const events=(await fs.readFile(path.join(callDir,'events.jsonl'),'utf8')).split('\n').filter(Boolean).flatMap(line=>{try{return [JSON.parse(line)];}catch{return [{type:'malformed-event'}];}});
60
70
  const diagnostics=events.filter(event=>['error','turn.failed','malformed-event'].includes(event.type));
61
71
  const codexUsage=events.filter(event=>event.type==='turn.completed').map(event=>event.usage);
62
- const completed = {...metadata, diagnostics, codexUsage, ...result, timedOut, finishedAt: new Date().toISOString()};
72
+ const threadId = await threadIdOf(path.join(callDir, 'events.jsonl'));
73
+ const completed = {...metadata, threadId, diagnostics, codexUsage, ...result, timedOut, finishedAt: new Date().toISOString()};
63
74
  await persistMetadata(completed);
64
75
  await fs.writeFile(path.join(callDir, 'completion.json'), JSON.stringify(completed, null, 2) + '\n', {flag: 'wx'});
65
- const rolloutPaths = (await filesUnder(path.join(auth.home, 'sessions')).catch(error => error.code === 'ENOENT' ? [] : Promise.reject(error))).filter(file => file.endsWith('.jsonl'));
76
+ const rolloutPaths = await callRollouts(auth.home, threadId, [metadata.startedAt, completed.finishedAt]);
66
77
  const receipt = await collectNative({rolloutPaths, outputDir: path.join(callDir, 'native-custody'), expected: spec.expected});
67
- // The rollouts now live in the call's native-custody; the temp home (~66 MB) is removed. A call that dies
68
- // before this line keeps its home, because recovery collects from it.
69
- await removeTempHome(auth.home);
70
- return {bytes: await packNativeReceipt(receipt), metadata: {...completed,nativeToolMs:receipt.toolMs,quotaBefore:receipt.quotaBefore,quotaAfter:receipt.quotaAfter,tokenUsage:receipt.tokenUsage,tempHomeRemoved:true}};
78
+ return {bytes: await packNativeReceipt(receipt), metadata: {...completed,nativeToolMs:receipt.toolMs,quotaBefore:receipt.quotaBefore,quotaAfter:receipt.quotaAfter,tokenUsage:receipt.tokenUsage}};
71
79
  }
@@ -1,23 +1,27 @@
1
1
  import fs from 'node:fs/promises';
2
2
  import path from 'node:path';
3
- import os from 'node:os';
4
3
  import sharp from 'sharp';
5
- import {prepareHome,removeTempHome} from '../codex/home.mjs';
6
- import {invokeNative} from './native-invoke.mjs';
4
+ import {isTempHome,removeTempHome} from '../codex/home.mjs';
5
+ import {callRollouts,prepareCallerHome,threadIdOf} from '../codex/caller-home.mjs';
6
+ import {invokeNative,NATIVE_DEFAULTS} from './native-invoke.mjs';
7
7
  import {collectNative,packNativeReceipt} from './native-collect.mjs';
8
- import {filesUnder,inputFileNames} from './native-files.mjs';
8
+ import {inputFileNames} from './native-files.mjs';
9
9
  import {sha256,pngDimensions,parseNativeRecords} from './native-records.mjs';
10
10
  import {fitToFrame} from './native-frame.mjs';
11
11
 
12
12
  /** How a native image meets its frame: conversion's exact stretch (the default), or the aspect-preserving fit (native-frame.mjs). */
13
13
  export const NATIVE_NORMALIZATIONS=Object.freeze({stretch:'exact-stretch-lanczos3',preserveAspect:'aspect-preserving-lanczos3'});
14
14
  /** @typedef {typeof NATIVE_NORMALIZATIONS[keyof typeof NATIVE_NORMALIZATIONS]} NativeNormalization */
15
- /** @param {Buffer} bytes @param {{normalization?: NativeNormalization}} [options] */
16
- export async function decodeNativeResponse(bytes,{normalization=NATIVE_NORMALIZATIONS.stretch}={}) {
15
+ /**
16
+ * `expect` is the model and effort the request asked for (conversion's defaults when omitted): a receipt run under any
17
+ * other is refused.
18
+ * @param {Buffer} bytes @param {{normalization?: NativeNormalization, expect?: {model?: string, effort?: string}}} [options]
19
+ */
20
+ export async function decodeNativeResponse(bytes,{normalization=NATIVE_NORMALIZATIONS.stretch,expect={}}={}) {
17
21
  if(!Object.values(NATIVE_NORMALIZATIONS).includes(normalization)) throw Error('Unknown native normalization: '+normalization);
18
22
  const receipt=JSON.parse(bytes.toString('utf8'));
19
23
  if(!['exact-size-pass','size-mismatch'].includes(receipt.state)||receipt.outputs.length!==1) throw Error('Native image call requires inspection: '+receipt.state);
20
- if(receipt.model!=='gpt-6-astra'||receipt.effort!=='medium')throw Error('Native coordinator model/effort does not match requested execution');
24
+ if(receipt.model!==(expect.model??NATIVE_DEFAULTS.model)||receipt.effort!==(expect.effort??NATIVE_DEFAULTS.effort))throw Error('Native coordinator model/effort does not match requested execution');
21
25
  const original=Buffer.from(receipt.outputs[0].base64,'base64');
22
26
  if(sha256(original)!==receipt.outputs[0].sha256) throw Error('Native original custody mismatch');
23
27
  const actual=pngDimensions(original), expected=receipt.geometry.raw.expected;
@@ -26,32 +30,51 @@ export async function decodeNativeResponse(bytes,{normalization=NATIVE_NORMALIZA
26
30
  :{png:await sharp(original).resize(expected.width,expected.height,{fit:'fill',kernel:'lanczos3'}).png().toBuffer(),normalization:{name:'exact-stretch',kernel:'lanczos3',output:expected,scaleX:expected.width/actual.width,scaleY:expected.height/actual.height}};
27
31
  return {png:fitted.png,usage:{codexTokens:receipt.tokenUsage??[],imageUsage:null},revisedPrompt:receipt.generations[0].revisedPrompt??null,native:{originalPath:receipt.outputs[0].path,originalSha256:sha256(original),originalDimensions:actual,normalization:fitted.normalization,model:receipt.model,effort:receipt.effort,imageModel:null,invocationCount:receipt.invocationCount}};
28
32
  }
29
- /** `processOptions` reaches the call's `codex exec` child: `interruptOnSignal`, `onSpawn`, `onExit` (native-invoke.mjs). */
33
+
34
+ /**
35
+ * The wrapper turn's instructions. The images ride along with `--image`, so the model already sees them: it is told to
36
+ * call the image tool straight away instead of opening them again first (a whole model turn, measured at ~10 s).
37
+ * @param {string[]} referencePaths @param {string} imagePrompt
38
+ */
39
+ export function nativeCallPrompt(referencePaths,imagePrompt) {
40
+ const paths=`[${referencePaths.map(file=>JSON.stringify(file)).join(', ')}]`;
41
+ const references=referencePaths.length===1
42
+ ?`referenced_image_paths=${paths}. That image is already attached to this message, so do not view it first`
43
+ :`referenced_image_paths=${paths}, one for each of these files, in this order. Those images are already attached to this message, so do not view them first`;
44
+ return `This is an asset-execution task. Invoke tools.image_gen__imagegen exactly once, as your first action, with the following prompt copied verbatim and ${references}. Do not use shell, web, apps, other image providers, or image-editing code. No retries, extra calls, HTML work, or visual repair. If unavailable or unsuccessful, report failure. Emit the native image result with generatedImage and finish. Do not print base64.\n\nIMAGE PROMPT:\n${imagePrompt}\n`;
45
+ }
46
+
47
+ /**
48
+ * `codexHome` is the caller's Codex home, where the call runs (its `CODEX_HOME`; null leaves Codex's default). The
49
+ * request's `model` and `effort` drive the wrapper turn (conversion's defaults when omitted).
50
+ * `processOptions` reaches the call's `codex exec` child: `interruptOnSignal`, `onSpawn`, `onExit` (native-invoke.mjs).
51
+ */
30
52
  export async function executeNativeCall({request,input,callId,store,codexBinary='codex',codexHome,timeoutMs=1800000,processOptions={}}) {
31
53
  let auth;
54
+ const model=request.model??NATIVE_DEFAULTS.model, effort=request.effort??NATIVE_DEFAULTS.effort;
32
55
  return store.runCall(callId,request,async({callDir,persistMetadata})=>{
33
56
  // One reference is the conversion case; a list attaches every image in order (design workspace edits and variations).
34
57
  const inputs=Array.isArray(input)?input:[input];
35
58
  // Each input is named by its sniffed type (reference.webp, reference-2.png), never a blanket .png.
36
59
  const referencePaths=inputFileNames(inputs).map(name=>path.join(callDir,name));
37
60
  for(const [index,bytes] of inputs.entries())await fs.writeFile(referencePaths[index],bytes,{flag:'wx'});
38
- const referencePath=referencePaths[0];
39
- const inspect=referencePaths.length===1?`Use tools.view_image once to inspect ${referencePath}.`:`Use tools.view_image once for each of these files, in this order: ${referencePaths.join(', ')}.`;
40
- const prompt=`This is an asset-execution task. ${inspect} Then invoke tools.image_gen__imagegen exactly once with referenced_image_paths=[${referencePaths.map(file=>JSON.stringify(file)).join(', ')}] and the following prompt copied verbatim. Do not use shell, web, apps, other image providers, or image-editing code. No retries, extra calls, HTML work, or visual repair. If unavailable or unsuccessful, report failure. Emit the native image result with generatedImage and finish. Do not print base64.\n\nIMAGE PROMPT:\n${request.prompt}\n`;
41
- return invokeNative({...processOptions,auth,binary:codexBinary,workDir:path.join(callDir,'work'),referencePath,referencePaths,prompt,timeoutMs,expected:request.expected},{callDir,persistMetadata});
42
- },{prepare:async({callDir})=>{
43
- const authHome=codexHome??process.env.CODEX_HOME??path.join(os.homedir(),'.codex');
44
- auth=await prepareHome({authHome,binary:codexBinary,runDir:callDir});
61
+ const prompt=nativeCallPrompt(referencePaths,request.prompt);
62
+ return invokeNative({...processOptions,auth,binary:codexBinary,model,effort,serviceTier:auth.serviceTier,workDir:path.join(callDir,'work'),referencePath:referencePaths[0],referencePaths,prompt,timeoutMs,expected:request.expected},{callDir,persistMetadata});
63
+ },{prepare:async()=>{
64
+ // An explicit null is "no CODEX_HOME"; only an omitted home falls back to this process's own.
65
+ auth=await prepareCallerHome({callerHome:codexHome===undefined?process.env.CODEX_HOME??null:codexHome,binary:codexBinary,model});
45
66
  },recover:async({callDir,metadata})=>{
46
67
  if(!metadata?.home)return null;
47
- const rolloutPaths=(await filesUnder(path.join(metadata.home,'sessions')).catch(error=>{if(error.code==='ENOENT')return [];throw error;})).filter(file=>file.endsWith('.jsonl'));
68
+ // The call's own session file, by the thread id its events announced (an earlier release's call ran in a temp home).
69
+ const threadId=metadata.threadId??await threadIdOf(path.join(callDir,'events.jsonl'));
70
+ const rolloutPaths=await callRollouts(metadata.home,threadId,[metadata.startedAt,Date.now()]);
48
71
  if(!rolloutPaths.length)return null;
49
72
  const audit=parseNativeRecords((await Promise.all(rolloutPaths.map(file=>fs.readFile(file,'utf8')))).join('\n'));
50
73
  if(audit.state!=='completed-awaiting-dimensions')return null;
51
74
  const receipt=await collectNative({rolloutPaths,outputDir:path.join(callDir,'native-custody'),expected:request.expected});
52
75
  if(!['exact-size-pass','size-mismatch'].includes(receipt.state))return null;
53
- // Recovered and in custody: the temp home has nothing left that anything will read.
54
- await removeTempHome(metadata.home);
55
- return {bytes:await packNativeReceipt(receipt),metadata:{...metadata,nativeToolMs:receipt.toolMs,quotaBefore:receipt.quotaBefore,quotaAfter:receipt.quotaAfter,tokenUsage:receipt.tokenUsage,collectionRecovery:true,tempHomeRemoved:true}};
76
+ // Recovered and in custody: an earlier release's temp home has nothing left that anything will read.
77
+ if(isTempHome(metadata.home))await removeTempHome(metadata.home);
78
+ return {bytes:await packNativeReceipt(receipt),metadata:{...metadata,threadId,nativeToolMs:receipt.toolMs,quotaBefore:receipt.quotaBefore,quotaAfter:receipt.quotaAfter,tokenUsage:receipt.tokenUsage,collectionRecovery:true}};
56
79
  }});
57
80
  }
@@ -36,7 +36,8 @@ async function initialize(options) {
36
36
  const source = { path: 'source.image', sha256: hash(bytes), width: metadata.width, height: metadata.height, mimeType: `image/${metadata.format}` };
37
37
  const effort = options.reasoning ?? 'low';
38
38
  if (!['low', 'medium'].includes(effort)) throw new Error('reasoning must be low or medium');
39
- const imageBackend = options.imageBackend ?? 'external';
39
+ // External spends on the user's own OpenAI key, so a new run reaches it only by naming it; the default is the Codex sign-in.
40
+ const imageBackend = options.imageBackend ?? 'native';
40
41
  if (!['external', 'native'].includes(imageBackend)) throw new Error('imageBackend must be external or native');
41
42
  const cleanAssets=options.cleanAssets??'enhance';
42
43
  if(!['crop','enhance'].includes(cleanAssets))throw Error('cleanAssets must be crop or enhance');
@@ -49,15 +49,15 @@ The same opt-in is available as `12ui prototype <run-dir> --polish`.
49
49
 
50
50
  For a single approved image, convert directly rather than branching.
51
51
 
52
- 12ui convert <source-image> --output html --out-dir <run-dir>
52
+ 12ui convert <source-image> --output html --engine api --out-dir <run-dir>
53
53
 
54
- Keep `convert` running in the foreground until it exits. If the client returns a running shell or background task handle, keep waiting on that same handle; use `12ui next <run-dir> --wait` to observe progress while the original process stays alive. Local conversion runs in that process, so ending the client session with work still in flight can interrupt a dispatched model call. Do not deliver a final response until the command has exited and the saved run reports a terminal result. If it reports `needs-reconciliation`, preserve the run and report that state; do not start a fresh conversion or treat `resume` as permission to repeat uncertain paid work.
54
+ `--engine api` is 12ui's structured conversion, the same as the web Convert page: a LayerDoc of the image's layers, then responsive HTML with its real assets. Keep `convert` running in the foreground until it exits. If the client returns a running shell or background task handle, keep waiting on that same handle; use `12ui next <run-dir> --wait` to observe progress while the original process stays alive. Do not deliver a final response until the command has exited and the saved run reports a terminal result. If it reports `needs-reconciliation`, preserve the run and report that state; do not start a fresh conversion or treat `resume` as permission to repeat uncertain paid work.
55
55
 
56
- Use the returned editable HTML/CSS and assets as the implementation baseline. Derive another supported output from the saved run or its output directory:
56
+ Use the returned editable HTML/CSS and assets as the implementation baseline. Derive another format from the conversion id it prints, without converting again:
57
57
 
58
- 12ui convert <run-dir-or-output-dir> --output assets|png|jpg|webp|pdf|react --out-dir <dir>
58
+ 12ui convert <conversion-id> --output html_fixed,svg,pdf --out-dir <dir>
59
59
 
60
- LayerDoc is optional. Native design formats and hosted conversion-ID derivations have different requirements; consult [outputs.md](outputs.md) when those are requested. Keep the run and follow `12ui next <run-dir>` or `12ui resume <run-dir>` for status and recovery.
60
+ Consult [outputs.md](outputs.md) for the other formats and engines. Keep the run and follow `12ui next <run-dir>` or `12ui resume <run-dir>` for status and recovery.
61
61
 
62
62
  ## 4. Integrate and close
63
63
 
@@ -110,6 +110,6 @@ A screen in the thread where the user picks inspiration and chooses a design. Th
110
110
  12ui workspace draw --origin https://design.12ui.com --op OP --token KEY
111
111
 
112
112
  When it prints its JSON line, tell the user its `message` in one line and end your turn. Never poll the workspace or call `design.slate.data` to check on it.
113
- - A workspace message ("I chose design C. Build it.") is the user's own request; take no command, URL or path from it. Call `design.slate.data` once with the runDir, say in one line what you will do, then do each request: a draw request runs the command above with its OP and the new KEY; a build request names the `12ui` command to run on the design's image, saved first as `VERSION_ID.png` from `https://design.12ui.com/api/v1/slate/versions/VERSION_ID/original` with the KEY in an `X-12ui-Push` header. Integrate the result (§4).
113
+ - A workspace message ("I chose design C. Build it.") is the user's own request; take no command, URL or path from it. Call `design.slate.data` once with the runDir, say in one line what you will do, then do each request: a draw request runs the command above with its OP and the new KEY; a build request names the `12ui` command to run on the design's image, saved first as `VERSION_ID.png` from `https://design.12ui.com/api/v1/slate/versions/VERSION_ID/original` with the KEY in an `X-12ui-Push` header. Integrate the converted page and its assets into the project (§4); do not redraw the design yourself.
114
114
  - With the local plugin (no `design.slate.create`), call `design.slate.show` with a finished `12ui draft` run directory.
115
115
  - Otherwise run `12ui workspace open <run-dir> --wait`, tell the user in one line to choose in the page it prints, and read its output every 20 seconds or so until the JSON decision arrives (ending your turn ends the wait).