@artblocks/abx-cli 0.1.0-alpha.2 → 0.1.0-alpha.21

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 (137) hide show
  1. package/CHANGELOG.md +1991 -0
  2. package/assets/renderer-scaffold/src/interfaces/IAbxParams.sol +17 -0
  3. package/assets/renderer-scaffold/test/MyRenderer.t.sol +51 -2
  4. package/dist/commands/deploy.d.ts +206 -0
  5. package/dist/commands/deploy.d.ts.map +1 -0
  6. package/dist/commands/deploy.js +4273 -0
  7. package/dist/commands/deploy.js.map +1 -0
  8. package/dist/commands/project.d.ts +241 -0
  9. package/dist/commands/project.d.ts.map +1 -0
  10. package/dist/commands/project.js +1060 -0
  11. package/dist/commands/project.js.map +1 -0
  12. package/dist/commands/reads.d.ts +64 -0
  13. package/dist/commands/reads.d.ts.map +1 -0
  14. package/dist/commands/reads.js +697 -0
  15. package/dist/commands/reads.js.map +1 -0
  16. package/dist/commands/scaffold.d.ts +71 -0
  17. package/dist/commands/scaffold.d.ts.map +1 -0
  18. package/dist/commands/scaffold.js +552 -0
  19. package/dist/commands/scaffold.js.map +1 -0
  20. package/dist/commands/service.d.ts +41 -0
  21. package/dist/commands/service.d.ts.map +1 -0
  22. package/dist/commands/service.js +618 -0
  23. package/dist/commands/service.js.map +1 -0
  24. package/dist/commands/storage.d.ts +37 -0
  25. package/dist/commands/storage.d.ts.map +1 -0
  26. package/dist/commands/storage.js +343 -0
  27. package/dist/commands/storage.js.map +1 -0
  28. package/dist/config.d.ts +91 -2
  29. package/dist/config.d.ts.map +1 -1
  30. package/dist/config.js +244 -11
  31. package/dist/config.js.map +1 -1
  32. package/dist/conformance.d.ts +31 -0
  33. package/dist/conformance.d.ts.map +1 -0
  34. package/dist/conformance.js +371 -0
  35. package/dist/conformance.js.map +1 -0
  36. package/dist/deps.d.ts +6 -39
  37. package/dist/deps.d.ts.map +1 -1
  38. package/dist/deps.js +4 -68
  39. package/dist/deps.js.map +1 -1
  40. package/dist/errors.d.ts +20 -0
  41. package/dist/errors.d.ts.map +1 -0
  42. package/dist/errors.js +25 -0
  43. package/dist/errors.js.map +1 -0
  44. package/dist/flag-allowlists.d.ts +53 -0
  45. package/dist/flag-allowlists.d.ts.map +1 -0
  46. package/dist/flag-allowlists.js +148 -0
  47. package/dist/flag-allowlists.js.map +1 -0
  48. package/dist/flags.d.ts +41 -0
  49. package/dist/flags.d.ts.map +1 -1
  50. package/dist/flags.js +94 -1
  51. package/dist/flags.js.map +1 -1
  52. package/dist/jsonout.d.ts +37 -0
  53. package/dist/jsonout.d.ts.map +1 -0
  54. package/dist/jsonout.js +68 -0
  55. package/dist/jsonout.js.map +1 -0
  56. package/dist/kind.d.ts +53 -0
  57. package/dist/kind.d.ts.map +1 -0
  58. package/dist/kind.js +94 -0
  59. package/dist/kind.js.map +1 -0
  60. package/dist/main.js +534 -4708
  61. package/dist/main.js.map +1 -1
  62. package/dist/mintpage.d.ts +17 -2
  63. package/dist/mintpage.d.ts.map +1 -1
  64. package/dist/mintpage.js +214 -52
  65. package/dist/mintpage.js.map +1 -1
  66. package/dist/output.d.ts +148 -0
  67. package/dist/output.d.ts.map +1 -0
  68. package/dist/output.js +634 -0
  69. package/dist/output.js.map +1 -0
  70. package/dist/ownerops.d.ts +132 -44
  71. package/dist/ownerops.d.ts.map +1 -1
  72. package/dist/ownerops.js +1151 -329
  73. package/dist/ownerops.js.map +1 -1
  74. package/dist/preview.d.ts +81 -0
  75. package/dist/preview.d.ts.map +1 -0
  76. package/dist/preview.js +535 -0
  77. package/dist/preview.js.map +1 -0
  78. package/dist/prompt.d.ts +17 -0
  79. package/dist/prompt.d.ts.map +1 -0
  80. package/dist/prompt.js +19 -0
  81. package/dist/prompt.js.map +1 -0
  82. package/dist/provision.d.ts.map +1 -1
  83. package/dist/provision.js +10 -7
  84. package/dist/provision.js.map +1 -1
  85. package/dist/remote.d.ts +134 -53
  86. package/dist/remote.d.ts.map +1 -1
  87. package/dist/remote.js +358 -46
  88. package/dist/remote.js.map +1 -1
  89. package/dist/riskgate.d.ts +29 -0
  90. package/dist/riskgate.d.ts.map +1 -0
  91. package/dist/riskgate.js +91 -0
  92. package/dist/riskgate.js.map +1 -0
  93. package/dist/scaffold.d.ts +10 -0
  94. package/dist/scaffold.d.ts.map +1 -0
  95. package/dist/scaffold.js +52 -0
  96. package/dist/scaffold.js.map +1 -0
  97. package/dist/schema.d.ts +18 -1
  98. package/dist/schema.d.ts.map +1 -1
  99. package/dist/schema.js +74 -23
  100. package/dist/schema.js.map +1 -1
  101. package/dist/served.d.ts +30 -0
  102. package/dist/served.d.ts.map +1 -0
  103. package/dist/served.js +112 -0
  104. package/dist/served.js.map +1 -0
  105. package/dist/signer.d.ts +13 -0
  106. package/dist/signer.d.ts.map +1 -1
  107. package/dist/signer.js +80 -14
  108. package/dist/signer.js.map +1 -1
  109. package/dist/update-check.d.ts +83 -4
  110. package/dist/update-check.d.ts.map +1 -1
  111. package/dist/update-check.js +132 -17
  112. package/dist/update-check.js.map +1 -1
  113. package/package.json +10 -6
  114. package/skill/SKILL.md +108 -62
  115. package/skill/reference/code-projects.md +109 -13
  116. package/skill/reference/creator-token.md +86 -0
  117. package/skill/reference/decisions.md +87 -0
  118. package/skill/reference/hosting.md +48 -15
  119. package/skill/reference/operating.md +32 -8
  120. package/skill/reference/setup.md +10 -3
  121. package/skill/reference/troubleshooting.md +31 -4
  122. package/dist/inspect.d.ts +0 -48
  123. package/dist/inspect.d.ts.map +0 -1
  124. package/dist/inspect.js +0 -184
  125. package/dist/inspect.js.map +0 -1
  126. package/dist/migrate.d.ts +0 -65
  127. package/dist/migrate.d.ts.map +0 -1
  128. package/dist/migrate.js +0 -180
  129. package/dist/migrate.js.map +0 -1
  130. package/dist/onchain-uri.d.ts +0 -97
  131. package/dist/onchain-uri.d.ts.map +0 -1
  132. package/dist/onchain-uri.js +0 -243
  133. package/dist/onchain-uri.js.map +0 -1
  134. package/dist/upload.d.ts +0 -28
  135. package/dist/upload.d.ts.map +0 -1
  136. package/dist/upload.js +0 -41
  137. package/dist/upload.js.map +0 -1
@@ -0,0 +1,535 @@
1
+ /**
2
+ * `abx preview` — the studio lane: run a code project on localhost, live, before deploying it.
3
+ *
4
+ * The gap this closes: `abx inspect` proves a script is WIRED correctly (static analysis) and a
5
+ * testnet deploy shows the real thing, but neither lets a creator sit with a piece and refine it.
6
+ * A still-image sweep isn't enough either — it flattens every time-based piece, and `abx.done()`
7
+ * exists precisely because stills need a settle point. So the primary surface is a real browser
8
+ * page the creator opens, refreshes, and drives.
9
+ *
10
+ * FIDELITY IS THE WHOLE POINT: `/view` serves the *same* template-mode document
11
+ * `assembleGeneratorDocument` builds (same shape, same real `ABX_JS`, same dependency script tags,
12
+ * same canonical tokenData serialization) with a synthetic seed in place of a minted one. There is
13
+ * no second copy of the runtime to drift — that was the flaw in hand-rolled preview harnesses,
14
+ * which stub `window.abx` themselves and happily run a sketch that reads its seed the wrong way.
15
+ *
16
+ * The script is re-read from disk on every request, so edit-then-refresh needs no watcher.
17
+ *
18
+ * `--shoot <dir>` drives the SAME server headlessly (Playwright) and exits — that's how an agent,
19
+ * which can't open localhost, sees what the creator sees. Captures are a derived read of the
20
+ * preview document, never a parallel harness.
21
+ */
22
+ import { createServer } from 'node:http';
23
+ import { readFile, mkdir, writeFile } from 'node:fs/promises';
24
+ import { createHash, randomBytes } from 'node:crypto';
25
+ import { dirname, extname, join, resolve as resolvePath } from 'node:path';
26
+ import { createRequire } from 'node:module';
27
+ import { PARAM_TYPES, canonicalTokenDataJson } from '@artblocks/abx-sdk';
28
+ import { buildGeneratorDocument, injectTokenDataIntoHtml, registryDepUrl } from '@artblocks/abx-token-api';
29
+ import { parseSchemaSpecs } from './schema.js';
30
+ import { parseDepFlag } from './deps.js';
31
+ /** The studio's default port — deliberately not the resolver's (8787), so both can run at once. */
32
+ export const DEFAULT_PREVIEW_PORT = 8788;
33
+ /** A stand-in collection address. Real shape (20 bytes, lowercase) so `contractAddress` reads true. */
34
+ const PREVIEW_ADDRESS = '0x' + '11'.repeat(20);
35
+ const PREVIEW_CHAIN_ID = 84532;
36
+ // ── seeds ────────────────────────────────────────────────────────────────────────
37
+ /**
38
+ * A deterministic preview seed per index. The on-chain seed is a full bytes32, and sha256 hex is
39
+ * exactly 64 chars — real width, well mixed, and STABLE across runs, so re-rendering after an edit
40
+ * is a like-for-like comparison instead of a whole new set of art. (A short stub seed would starve
41
+ * the sketch's PRNG of entropy and can hide a distribution bug until it's permanent.)
42
+ */
43
+ export function previewSeed(index) {
44
+ return '0x' + createHash('sha256').update(`abx-preview-seed-${index}`).digest('hex');
45
+ }
46
+ /** A fresh unpredictable seed — what the studio's "new" button asks for. */
47
+ function randomSeed() {
48
+ return '0x' + randomBytes(32).toString('hex');
49
+ }
50
+ function normalizeSeed(raw, fallbackIndex = 0) {
51
+ const t = String(raw ?? '').trim();
52
+ if (/^0x[0-9a-fA-F]{64}$/.test(t))
53
+ return t.toLowerCase();
54
+ // Tolerate a short hex seed (someone pasting by hand) by left-padding to bytes32 — the same
55
+ // width the chain would give it, so the sketch sees production-shaped entropy either way.
56
+ if (/^0x[0-9a-fA-F]{1,64}$/.test(t))
57
+ return ('0x' + t.slice(2).toLowerCase().padStart(64, '0'));
58
+ return previewSeed(fallbackIndex);
59
+ }
60
+ /** Build the flat tokenData a token would carry, in the canonical shape `buildTokenData` produces. */
61
+ function previewTokenData(cfg, seed, tokenId, params) {
62
+ const data = {
63
+ chainId: PREVIEW_CHAIN_ID,
64
+ contractAddress: PREVIEW_ADDRESS,
65
+ tokenId,
66
+ seed,
67
+ };
68
+ // Inject ONLY params that actually have a value — exactly what production does. `buildTokenData`
69
+ // (the real path) walks the params that exist on-chain, so a declared schema key nobody has set is
70
+ // ABSENT from tokenData and the program's own `?? fallback` runs.
71
+ //
72
+ // This used to inject a per-type default for every declared key (Select → its FIRST option) on the
73
+ // theory that "a key that only appears once someone sets it is a preview that lies". That had it
74
+ // backwards: the fabricated value is the lie. An optional `theme:Select[Newsprint|…]` override made
75
+ // every frame render `theme: "Newsprint"` with nobody having set anything — nine seed-distinct
76
+ // puzzles collapsed into one palette here, while the deployed drop (where the key is absent) would
77
+ // take the program's other branch entirely. Unset must be indistinguishable from on-chain unset.
78
+ for (const s of cfg.schemas) {
79
+ const v = params[s.key];
80
+ if (v !== undefined && v !== '')
81
+ data[s.key] = v;
82
+ }
83
+ return { data, json: canonicalTokenDataJson(data) };
84
+ }
85
+ /**
86
+ * Dependency script tags for the preview. Without a chain we can't read registry on-chain bytes,
87
+ * so a `name@version` ref resolves through the SAME built-in CDN map the resolver falls back to,
88
+ * and a raw on-chain data-contract ref can't be fetched at all (reported, not silently dropped).
89
+ */
90
+ export function previewDepTags(deps) {
91
+ const tags = [];
92
+ const notes = [];
93
+ for (const d of deps) {
94
+ if (d.display.startsWith('0x')) {
95
+ notes.push(`${d.display} — an on-chain data contract; not fetchable offline, so it is NOT loaded in preview`);
96
+ continue;
97
+ }
98
+ const url = registryDepUrl(d.display);
99
+ if (url) {
100
+ tags.push(`<script src="${url}"></script>`);
101
+ notes.push(`${d.display} → ${url} (built-in CDN map; on-chain bytes are resolved at deploy)`);
102
+ }
103
+ else {
104
+ notes.push(`${d.display} — unresolvable to a CDN URL; not loaded in preview`);
105
+ }
106
+ }
107
+ return { tags, notes };
108
+ }
109
+ /**
110
+ * The template-mode document. This used to be a hand-maintained duplicate of
111
+ * `assembleGeneratorDocument`'s shape in @artblocks/abx-token-api (token-api/src/code.ts), kept
112
+ * byte-identical by a "if that changes, change this with it" comment and nothing else enforcing
113
+ * it. Now it just IS that shape: a re-export of the token-api package's own
114
+ * `buildGeneratorDocument`, the pure (chain-free) half `assembleGeneratorDocument` calls after
115
+ * fetching the script + dep tags from chain. One definition; the studio cannot drift from it.
116
+ */
117
+ export const buildPreviewDocument = buildGeneratorDocument;
118
+ /**
119
+ * The logical viewport every preview frame renders into, then CSS-scaled to fit its slot.
120
+ *
121
+ * Why not just size the iframe to the slot: a sketch that hardcodes a 1000×1000 canvas (most do)
122
+ * would be CLIPPED to the top-left corner of itself — which made an early grid look like a wall of
123
+ * blank tiles. Giving every frame the same generous square (a typical marketplace live-view size)
124
+ * and scaling the *result* means you always see the whole composition, and every tile is directly
125
+ * comparable. The sketch's own view of the world is unchanged, so nothing is misrepresented.
126
+ */
127
+ const STAGE_PX = 1000;
128
+ /** Fit-to-slot scaling for a fixed-size frame. Shared by the studio stage and every grid cell. */
129
+ const FIT_SNIPPET = `<script>(function(){
130
+ var LOGICAL = ${STAGE_PX};
131
+ function fit(){
132
+ for (var s of document.querySelectorAll('.stage')) {
133
+ s.style.setProperty('--k', (s.clientWidth / LOGICAL).toFixed(4));
134
+ }
135
+ }
136
+ window.addEventListener('resize', fit);
137
+ if (window.ResizeObserver) {
138
+ var ro = new ResizeObserver(fit);
139
+ for (var s of document.querySelectorAll('.stage')) ro.observe(s);
140
+ }
141
+ fit();
142
+ })();</script>`;
143
+ /** Stage CSS: a square slot holding a fixed-size frame, scaled down to fit it. */
144
+ const STAGE_CSS = `
145
+ .stage{position:relative;aspect-ratio:1;overflow:hidden;background:#000;border:1px solid #24242c}
146
+ .stage iframe{position:absolute;top:0;left:0;border:0;display:block;
147
+ width:${STAGE_PX}px;height:${STAGE_PX}px;transform:scale(var(--k,0.25));transform-origin:0 0}`;
148
+ /** Report traits + completion back to the studio chrome (and to --shoot). Preview-only chrome. */
149
+ const REPORT_SNIPPET = `<script>(function(){
150
+ function post(){
151
+ try {
152
+ parent.postMessage({abxPreview:true, traits: window.abx && window.abx.__traits,
153
+ done: !!(window.abx && window.abx.__done), t: Math.round(performance.now())}, '*');
154
+ } catch (e) {}
155
+ }
156
+ document.addEventListener('abx:traits', post);
157
+ document.addEventListener('abx:done', post);
158
+ setTimeout(post, 400); setTimeout(post, 1500);
159
+ })();</script>`;
160
+ async function renderViewDocument(cfg, seed, tokenId, params, withReport) {
161
+ const { json } = previewTokenData(cfg, seed, tokenId, params);
162
+ const { tags } = previewDepTags(cfg.deps);
163
+ if (cfg.source.kind === 'dir') {
164
+ // Directory mode mirrors the resolver's primary serving path: fetch the build's own entry
165
+ // document and inject tokenData into it (the build ships its own abx.js by convention).
166
+ const html = await readFile(join(cfg.source.path, 'index.html'), 'utf8');
167
+ const injected = injectTokenDataIntoHtml(html, json, '/__abx_code/');
168
+ return withReport ? injected.replace(/<\/body>/i, `${REPORT_SNIPPET}</body>`) : injected;
169
+ }
170
+ const script = await readFile(cfg.source.path, 'utf8'); // re-read per request → edit + refresh
171
+ const doc = buildPreviewDocument(script, json, tags);
172
+ return withReport ? doc.replace('</body>', `${REPORT_SNIPPET}</body>`) : doc;
173
+ }
174
+ // ── the studio chrome ────────────────────────────────────────────────────────────
175
+ function paramControl(s) {
176
+ const type = PARAM_TYPES[s.paramType];
177
+ const id = `p_${s.key}`;
178
+ const label = `<label for="${id}">${escapeHtml(s.key)}<span class="ty">${escapeHtml(type)}</span></label>`;
179
+ let input;
180
+ switch (type) {
181
+ case 'Bool':
182
+ input = `<input type="checkbox" id="${id}" data-key="${escapeHtml(s.key)}" data-kind="bool">`;
183
+ break;
184
+ case 'Select':
185
+ // "— unset —" is FIRST and therefore the default position, so a fresh studio frame renders like
186
+ // a fresh token: the key absent, the program's own fallback in charge. Without it, HTML selects
187
+ // the first real option and there is no way to express "nobody has set this yet" — the state
188
+ // every token is actually in until an owner writes one.
189
+ input = `<select id="${id}" data-key="${escapeHtml(s.key)}" data-kind="text"><option value="">— unset (program fallback) —</option>${s.selectOptions
190
+ .map((o) => `<option value="${escapeHtml(o)}">${escapeHtml(o)}</option>`)
191
+ .join('')}</select>`;
192
+ break;
193
+ case 'HexColor':
194
+ input = `<input type="color" id="${id}" value="#3355ff" data-key="${escapeHtml(s.key)}" data-kind="text">`;
195
+ break;
196
+ case 'Uint256Range':
197
+ case 'Int256Range':
198
+ case 'DecimalRange':
199
+ case 'Timestamp':
200
+ input = `<input type="number" id="${id}" value="0" data-key="${escapeHtml(s.key)}" data-kind="text">`;
201
+ break;
202
+ default:
203
+ input = `<input type="text" id="${id}" data-key="${escapeHtml(s.key)}" data-kind="text" placeholder="${escapeHtml(type)}">`;
204
+ }
205
+ return `<div class="ctl">${label}${input}</div>`;
206
+ }
207
+ function escapeHtml(s) {
208
+ return s.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
209
+ }
210
+ function studioPage(cfg, depNotes) {
211
+ const controls = cfg.schemas.map(paramControl).join('\n');
212
+ const sourceLabel = cfg.source.kind === 'dir' ? `${cfg.source.path}/ (directory build)` : cfg.source.path;
213
+ return `<!doctype html><html><head><meta charset="utf-8"><title>abx preview — studio</title>
214
+ <style>
215
+ :root{color-scheme:dark}
216
+ *{box-sizing:border-box}
217
+ body{margin:0;background:#0d0d10;color:#e6e6ea;font:13px/1.5 ui-sans-serif,system-ui,-apple-system,sans-serif}
218
+ header{display:flex;flex-wrap:wrap;gap:10px;align-items:center;padding:10px 14px;border-bottom:1px solid #24242c;background:#131318}
219
+ button{background:#22222b;color:#e6e6ea;border:1px solid #33333f;border-radius:6px;padding:5px 11px;font:inherit;cursor:pointer}
220
+ button:hover{background:#2c2c37}
221
+ .seed{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px;color:#9a9aa8;cursor:pointer}
222
+ .seed:hover{color:#e6e6ea}
223
+ .grow{flex:1}
224
+ .ctls{display:flex;flex-wrap:wrap;gap:14px;padding:8px 14px;border-bottom:1px solid #24242c;background:#101014}
225
+ .ctl{display:flex;align-items:center;gap:7px}
226
+ .ctl label{color:#9a9aa8}
227
+ .ctl .ty{color:#5b5b6b;margin-left:5px;font-size:11px}
228
+ input,select{background:#1b1b22;color:#e6e6ea;border:1px solid #33333f;border-radius:5px;padding:3px 6px;font:inherit}
229
+ input[type=color]{padding:1px;width:34px;height:24px}
230
+ main{padding:16px;display:flex;justify-content:center}
231
+ main .stage{width:min(78vh,100%)}
232
+ ${STAGE_CSS}
233
+ footer{padding:9px 14px;border-top:1px solid #24242c;background:#131318;display:flex;flex-wrap:wrap;gap:16px;align-items:center}
234
+ .traits{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px}
235
+ .warn{color:#e0a03a}.ok{color:#7ec07e}.dim{color:#6b6b7b}
236
+ a{color:#8fa8e0}
237
+ code{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;color:#9a9aa8;word-break:break-all}
238
+ .src{padding:0 14px 16px;font-size:12px}
239
+ </style></head><body>
240
+ <header>
241
+ <button id="new">↻ new seed</button>
242
+ <button id="prev">←</button><button id="next">→</button>
243
+ <span class="seed" id="seedLabel" title="click to copy"></span>
244
+ <span class="dim" id="idx"></span>
245
+ <span class="grow"></span>
246
+ <a href="/grid" target="_blank">grid ↗</a>
247
+ <a href="#" id="viewLink" target="_blank">bare view ↗</a>
248
+ </header>
249
+ ${controls ? `<div class="ctls">${controls}</div>` : ''}
250
+ <main><div class="stage"><iframe id="stage" title="preview"></iframe></div></main>
251
+ <footer>
252
+ <span class="dim">traits</span> <span class="traits" id="traits">—</span>
253
+ <span class="grow"></span>
254
+ <span id="done" class="dim">waiting…</span>
255
+ </footer>
256
+ <div class="src dim">
257
+ <code>${escapeHtml(sourceLabel)}</code> — re-read from disk on every render, so edit and refresh.
258
+ Rendered at ${STAGE_PX}×${STAGE_PX} and scaled to fit.
259
+ ${depNotes.length ? `<br>deps: ${depNotes.map((n) => escapeHtml(n)).join('<br>')}` : ''}
260
+ </div>
261
+ ${FIT_SNIPPET}
262
+ <script>
263
+ let index = 0, seed = null;
264
+ const stage = document.getElementById('stage');
265
+ function params() {
266
+ const out = {};
267
+ for (const el of document.querySelectorAll('[data-key]')) {
268
+ out[el.dataset.key] = el.dataset.kind === 'bool' ? String(el.checked) : String(el.value);
269
+ }
270
+ return out;
271
+ }
272
+ function url(extra) {
273
+ const q = new URLSearchParams({tokenId: String(index), ...params(), ...(extra || {})});
274
+ if (seed) q.set('seed', seed);
275
+ return '/view?' + q.toString();
276
+ }
277
+ function render() {
278
+ document.getElementById('traits').textContent = '—';
279
+ const d = document.getElementById('done'); d.textContent = 'waiting…'; d.className = 'dim';
280
+ const u = url();
281
+ stage.src = u;
282
+ document.getElementById('viewLink').href = u;
283
+ document.getElementById('idx').textContent = '#' + index;
284
+ }
285
+ function setSeed(s) { seed = s; document.getElementById('seedLabel').textContent = s.slice(0, 10) + '…' + s.slice(-4); }
286
+ document.getElementById('new').onclick = async () => {
287
+ const r = await fetch('/api/seed'); setSeed((await r.json()).seed); render();
288
+ };
289
+ document.getElementById('next').onclick = () => { index++; seed = null; boot(); };
290
+ document.getElementById('prev').onclick = () => { if (index > 0) { index--; seed = null; boot(); } };
291
+ document.getElementById('seedLabel').onclick = () => seed && navigator.clipboard?.writeText(seed);
292
+ for (const el of document.querySelectorAll('[data-key]')) el.addEventListener('change', render);
293
+ window.addEventListener('message', (e) => {
294
+ if (!e.data || !e.data.abxPreview) return;
295
+ const t = e.data.traits;
296
+ document.getElementById('traits').textContent = t && Object.keys(t).length
297
+ ? Object.entries(t).map(([k, v]) => k + ' ' + v).join(' · ')
298
+ : 'none reported — abx.traits({…}) is the ONLY thing that becomes attributes';
299
+ document.getElementById('traits').className = 'traits' + (t && Object.keys(t).length ? '' : ' warn');
300
+ const d = document.getElementById('done');
301
+ d.textContent = e.data.done ? 'abx.done() ✓ ' + e.data.t + 'ms' : 'no abx.done() yet — stills capture on a timeout fallback';
302
+ d.className = e.data.done ? 'ok' : 'warn';
303
+ });
304
+ async function boot() { const r = await fetch('/api/seed?index=' + index); setSeed((await r.json()).seed); render(); }
305
+ boot();
306
+ </script></body></html>`;
307
+ }
308
+ function gridPage(count) {
309
+ const cells = Array.from({ length: count }, (_, i) => {
310
+ const seed = previewSeed(i);
311
+ const src = `/view?tokenId=${i}&seed=${seed}`;
312
+ return `<figure><div class="stage"><iframe src="${src}" loading="lazy" title="seed ${i}"></iframe></div>
313
+ <figcaption><a href="${src}" target="_blank">#${i}</a> <span>${seed.slice(0, 10)}…</span></figcaption></figure>`;
314
+ }).join('\n');
315
+ return `<!doctype html><html><head><meta charset="utf-8"><title>abx preview — grid</title>
316
+ <style>
317
+ :root{color-scheme:dark}
318
+ body{margin:0;background:#0d0d10;color:#e6e6ea;font:13px/1.5 ui-sans-serif,system-ui,sans-serif}
319
+ h1{font-size:14px;font-weight:600;padding:12px 16px;margin:0;border-bottom:1px solid #24242c;background:#131318}
320
+ h1 span{color:#6b6b7b;font-weight:400}
321
+ .wrap{display:grid;grid-template-columns:repeat(auto-fill,minmax(240px,1fr));gap:14px;padding:16px}
322
+ figure{margin:0}
323
+ ${STAGE_CSS}
324
+ figcaption{padding:5px 2px;color:#9a9aa8;font-family:ui-monospace,Menlo,monospace;font-size:11px}
325
+ figcaption span{color:#5b5b6b}
326
+ figcaption a{color:#9a9aa8;text-decoration:none}figcaption a:hover{color:#e6e6ea}
327
+ </style></head><body>
328
+ <h1>${count} seeds, live <span>— every frame is the real preview document, animated. Rendered at ${STAGE_PX}×${STAGE_PX}, scaled to fit. Click a number to open one.</span></h1>
329
+ <div class="wrap">${cells}</div>
330
+ ${FIT_SNIPPET}</body></html>`;
331
+ }
332
+ // ── the server ───────────────────────────────────────────────────────────────────
333
+ const MIME = {
334
+ '.html': 'text/html; charset=utf-8', '.js': 'text/javascript; charset=utf-8',
335
+ '.mjs': 'text/javascript; charset=utf-8', '.css': 'text/css; charset=utf-8',
336
+ '.json': 'application/json; charset=utf-8', '.png': 'image/png', '.jpg': 'image/jpeg',
337
+ '.jpeg': 'image/jpeg', '.gif': 'image/gif', '.svg': 'image/svg+xml', '.webp': 'image/webp',
338
+ '.wasm': 'application/wasm', '.woff2': 'font/woff2', '.ttf': 'font/ttf', '.mp3': 'audio/mpeg',
339
+ };
340
+ export async function startPreviewServer(cfg, port) {
341
+ const { notes } = previewDepTags(cfg.deps);
342
+ const server = createServer((req, res) => {
343
+ void (async () => {
344
+ const u = new URL(req.url ?? '/', 'http://localhost');
345
+ const send = (code, type, body) => {
346
+ // Never cache: the whole point is that a refresh picks up the edit you just made.
347
+ res.writeHead(code, { 'content-type': type, 'cache-control': 'no-store' });
348
+ res.end(body);
349
+ };
350
+ try {
351
+ if (u.pathname === '/')
352
+ return send(200, MIME['.html'], studioPage(cfg, notes));
353
+ if (u.pathname === '/api/seed') {
354
+ const idx = u.searchParams.get('index');
355
+ const seed = idx === null ? randomSeed() : previewSeed(Number(idx) || 0);
356
+ return send(200, MIME['.json'], JSON.stringify({ seed }));
357
+ }
358
+ if (u.pathname === '/grid') {
359
+ const count = Math.min(Math.max(Number(u.searchParams.get('count') ?? 9) || 9, 1), 64);
360
+ return send(200, MIME['.html'], gridPage(count));
361
+ }
362
+ if (u.pathname === '/view') {
363
+ const tokenId = String(Number(u.searchParams.get('tokenId') ?? 0) || 0);
364
+ const seed = normalizeSeed(u.searchParams.get('seed') ?? undefined, Number(tokenId));
365
+ const params = {};
366
+ for (const s of cfg.schemas) {
367
+ const v = u.searchParams.get(s.key);
368
+ if (v !== null)
369
+ params[s.key] = v;
370
+ }
371
+ const report = u.searchParams.get('report') !== '0';
372
+ return send(200, MIME['.html'], await renderViewDocument(cfg, seed, tokenId, params, report));
373
+ }
374
+ // Directory mode: serve the build's own assets under a fixed base.
375
+ if (cfg.source.kind === 'dir' && u.pathname.startsWith('/__abx_code/')) {
376
+ const rel = decodeURIComponent(u.pathname.slice('/__abx_code/'.length));
377
+ const root = resolvePath(cfg.source.path);
378
+ const target = resolvePath(join(root, rel));
379
+ // Path-traversal guard: a build asset can never escape the declared root.
380
+ if (target !== root && !target.startsWith(root + '/'))
381
+ return send(403, 'text/plain', 'forbidden');
382
+ const body = await readFile(target);
383
+ return send(200, MIME[extname(target).toLowerCase()] ?? 'application/octet-stream', body);
384
+ }
385
+ send(404, 'text/plain', 'not found');
386
+ }
387
+ catch (err) {
388
+ send(500, 'text/plain', `preview error: ${err.message}`);
389
+ }
390
+ })();
391
+ });
392
+ const actual = await new Promise((res2, rej) => {
393
+ server.on('error', rej);
394
+ // Port 0 ⇒ let the OS pick, so a busy studio port never blocks a --shoot run.
395
+ server.listen(port, () => res2(server.address().port));
396
+ });
397
+ return {
398
+ port: actual,
399
+ url: `http://localhost:${actual}`,
400
+ close: () => new Promise((res2) => server.close(() => res2())),
401
+ };
402
+ }
403
+ /**
404
+ * Render `count` seeds from a running preview server to PNGs, collecting each frame's reported
405
+ * traits. This is how an agent (which cannot open localhost) sees the work — and because it drives
406
+ * the same `/view` document the creator sees, there is nothing to keep in sync.
407
+ */
408
+ export async function shootPreview(base, outDir, count, opts = {}) {
409
+ // Playwright is a BUILD-TIME type dependency only (a `devDependency` of this package), never a
410
+ // runtime one: `--shoot` is opt-in and the interactive studio needs no browser at all, so shipping
411
+ // it as a real dependency would force every `abx` install to pull a browser driver it won't use.
412
+ // Hence: declared for `tsc`, imported dynamically, and absence handled below.
413
+ // Do NOT promote this to `dependencies`, and do NOT drop the devDependency — an undeclared
414
+ // `import('playwright')` typechecks locally only if a stray copy sits in some PARENT directory of
415
+ // the checkout, then fails in CI with TS2307. That exact hole broke a release.
416
+ let chromium;
417
+ try {
418
+ ({ chromium } = await import('playwright'));
419
+ }
420
+ catch {
421
+ throw new Error('--shoot needs Playwright + its Chromium build (the interactive preview does not — that runs in YOUR browser).\n' +
422
+ ' install: npm i -D playwright && npx playwright install chromium\n' +
423
+ ' or drop --shoot and open the preview URL yourself.');
424
+ }
425
+ // Same logical square the interactive stage uses, so a shot frames the piece identically.
426
+ const width = opts.width ?? STAGE_PX;
427
+ const timeoutMs = opts.timeoutMs ?? 10_000;
428
+ await mkdir(outDir, { recursive: true });
429
+ // A missing BROWSER BUILD is a different failure from a missing package, and its stock message
430
+ // ("please run npx playwright install") can send you in a circle: `npx playwright install` resolves
431
+ // whatever playwright npm feels like, which may be a DIFFERENT version than the one that just
432
+ // launched — you download a browser revision this playwright won't use, get the identical error,
433
+ // and run the same command again. Name the install command for the playwright we ACTUALLY loaded.
434
+ let browser;
435
+ try {
436
+ browser = await chromium.launch();
437
+ }
438
+ catch (err) {
439
+ const msg = err.message ?? '';
440
+ if (!/Executable doesn't exist|playwright install/i.test(msg))
441
+ throw err;
442
+ let hint = 'npx playwright install chromium';
443
+ let version = '';
444
+ try {
445
+ const req = createRequire(import.meta.url);
446
+ const pkgDir = dirname(req.resolve('playwright/package.json'));
447
+ version = ` ${JSON.parse(await readFile(join(pkgDir, 'package.json'), 'utf8')).version}`;
448
+ hint = `node ${join(pkgDir, 'cli.js')} install chromium`;
449
+ }
450
+ catch {
451
+ /* fall back to the generic command */
452
+ }
453
+ throw new Error(`--shoot loaded Playwright${version} but its Chromium build is missing.\n` +
454
+ ` install the build THIS Playwright expects:\n ${hint}\n` +
455
+ ` (a bare \`npx playwright install\` may fetch a build for a different Playwright version — same error, again.)`);
456
+ }
457
+ try {
458
+ const page = await browser.newPage({ viewport: { width, height: width } });
459
+ const out = [];
460
+ for (let i = 0; i < count; i++) {
461
+ const seed = previewSeed(i);
462
+ // Forward any --param overrides, so a batch can answer "what does the collection look like when
463
+ // a collector HAS set this?" — previously unreachable: --shoot rendered only the unset state, and
464
+ // seeing the other one meant hand-rolling a Playwright script against /view.
465
+ const overrides = Object.entries(opts.params ?? {})
466
+ .map(([k, v]) => `&${encodeURIComponent(k)}=${encodeURIComponent(v)}`)
467
+ .join('');
468
+ await page.goto(`${base}/view?tokenId=${i}&seed=${seed}&report=0${overrides}`, { waitUntil: 'load' });
469
+ // Wait for the sketch's own completion signal; a piece that never calls abx.done() (or
470
+ // animates forever) still gets captured — same timeout fallback the render effect uses.
471
+ // A timeout here is NOT a verdict on the program — the machine may simply be loaded (a studio
472
+ // instance + a second Chromium is enough). Record it instead of swallowing it, so the caller
473
+ // can tell "the program reported nothing" from "we stopped waiting".
474
+ let timedOut = false;
475
+ await page
476
+ .waitForFunction('window.abx && (window.abx.__done || window.abx.__traits)', { timeout: timeoutMs })
477
+ .catch(() => { timedOut = true; });
478
+ const file = join(outDir, `seed-${i}.png`);
479
+ await page.screenshot({ path: file });
480
+ const probe = (await page.evaluate('({traits: (window.abx && window.abx.__traits) || null, done: !!(window.abx && window.abx.__done)})'));
481
+ // The wait can expire and the program still land its traits a moment later (the screenshot +
482
+ // probe cost real time) — so a frame that timed out but DID report is not a timeout for
483
+ // reporting purposes. Only an expiry that also produced nothing is worth flagging.
484
+ out.push({ seed, file, traits: probe.traits, done: probe.done, timedOut: timedOut && !probe.traits });
485
+ }
486
+ await writeFile(join(outDir, 'traits.json'), JSON.stringify(out.map(({ seed, traits, done }) => ({ seed, traits, done })), null, 2));
487
+ return out;
488
+ }
489
+ finally {
490
+ await browser.close();
491
+ }
492
+ }
493
+ // ── flag surface ─────────────────────────────────────────────────────────────────
494
+ export const PREVIEW_FLAGS = new Set([
495
+ 'script', 'code-dir', 'schema', 'dep', 'port', 'shoot', 'count', 'width', 'timeout-ms', 'param',
496
+ ]);
497
+ /**
498
+ * Parse `--param key=value` (repeatable, comma-joined by the flag parser) into overrides for a
499
+ * `--shoot` batch. Values are the same human form the studio's controls submit, so a Select takes its
500
+ * label. An empty value means "unset" — the same wire shape production uses for a param nobody has
501
+ * written — which makes `--param theme=` a way to shoot the fallback state explicitly.
502
+ */
503
+ export function parsePreviewParams(raw) {
504
+ const out = {};
505
+ for (const pair of String(raw ?? '').split(',')) {
506
+ const t = pair.trim();
507
+ if (!t)
508
+ continue;
509
+ const eq = t.indexOf('=');
510
+ if (eq === -1)
511
+ throw new Error(`--param "${t}" — expected key=value (a Select takes its label; an empty value means unset).`);
512
+ out[t.slice(0, eq).trim()] = t.slice(eq + 1).trim();
513
+ }
514
+ return out;
515
+ }
516
+ /** Resolve `--script`/`--code-dir` into a source, with the same either-or rule as `deploy-code`. */
517
+ export function previewSourceFromFlags(flags) {
518
+ const script = flags.script && flags.script !== 'true' ? String(flags.script) : undefined;
519
+ const dir = flags['code-dir'] && flags['code-dir'] !== 'true' ? String(flags['code-dir']) : undefined;
520
+ if (script && dir)
521
+ throw new Error('pass either --script <file> or --code-dir <dir>, not both.');
522
+ if (script)
523
+ return { kind: 'script', path: script };
524
+ if (dir)
525
+ return { kind: 'dir', path: dir };
526
+ throw new Error('abx preview needs the program: --script <file.js> (a single sketch) or --code-dir <dir> (a build).');
527
+ }
528
+ export function previewConfigFromFlags(flags) {
529
+ return {
530
+ source: previewSourceFromFlags(flags),
531
+ schemas: parseSchemaSpecs(flags.schema),
532
+ deps: parseDepFlag(flags.dep),
533
+ };
534
+ }
535
+ //# sourceMappingURL=preview.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"preview.js","sourceRoot":"","sources":["../src/preview.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Interactive-prompt helpers.
3
+ *
4
+ * These live outside `main.ts` on purpose: `main.ts` calls `main()` at module scope, so importing it
5
+ * from a test RUNS the CLI. Anything worth unit-testing belongs in a module that only defines things.
6
+ */
7
+ /**
8
+ * Does this answer to a `[Y/n]` prompt mean "no"?
9
+ *
10
+ * Used by `abx doctor`'s offer to install/resync the agent skill, which defaults to YES so the
11
+ * documented flow (`npm i -g @artblocks/abx-cli` → `abx doctor`) sets the agent up in one pass. Since
12
+ * Enter accepts, the exact refusal set is what matters: an over-eager match would refuse a "yes", and
13
+ * a sloppy `/^n/i` would swallow anything starting with n. Only the explicit forms decline; the caller
14
+ * maps EOF (Ctrl-D) to `'n'` so a closed stream never writes files.
15
+ */
16
+ export declare function declinesSkillInstall(answer: string): boolean;
17
+ //# sourceMappingURL=prompt.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompt.d.ts","sourceRoot":"","sources":["../src/prompt.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAE5D"}
package/dist/prompt.js ADDED
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Interactive-prompt helpers.
3
+ *
4
+ * These live outside `main.ts` on purpose: `main.ts` calls `main()` at module scope, so importing it
5
+ * from a test RUNS the CLI. Anything worth unit-testing belongs in a module that only defines things.
6
+ */
7
+ /**
8
+ * Does this answer to a `[Y/n]` prompt mean "no"?
9
+ *
10
+ * Used by `abx doctor`'s offer to install/resync the agent skill, which defaults to YES so the
11
+ * documented flow (`npm i -g @artblocks/abx-cli` → `abx doctor`) sets the agent up in one pass. Since
12
+ * Enter accepts, the exact refusal set is what matters: an over-eager match would refuse a "yes", and
13
+ * a sloppy `/^n/i` would swallow anything starting with n. Only the explicit forms decline; the caller
14
+ * maps EOF (Ctrl-D) to `'n'` so a closed stream never writes files.
15
+ */
16
+ export function declinesSkillInstall(answer) {
17
+ return /^n(o|ope)?$/i.test(answer.trim());
18
+ }
19
+ //# sourceMappingURL=prompt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompt.js","sourceRoot":"","sources":["../src/prompt.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;;;;;;GAQG;AACH,MAAM,UAAU,oBAAoB,CAAC,MAAc;IACjD,OAAO,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;AAC5C,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"provision.d.ts","sourceRoot":"","sources":["../src/provision.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAEH,MAAM,MAAM,gBAAgB,GAAG,KAAK,GAAG,QAAQ,GAAG,KAAK,CAAC;AAExD,MAAM,WAAW,gBAAgB;IAC/B,yDAAyD;IACzD,KAAK,EAAE,KAAK,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAC,CAAC,CAAC;IAC9C,oFAAoF;IACpF,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,+FAA+F;IAC/F,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,oDAAoD;IACpD,SAAS,EAAE,MAAM,CAAC;IAClB,2GAA2G;IAC3G,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,2DAA2D;IAC3D,GAAG,EAAE,MAAM,CAAC;IACZ,iGAAiG;IACjG,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,4DAA4D;IAC5D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,sFAAsF;IACtF,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,mGAAmG;IACnG,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,6FAA6F;IAC7F,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAkQD,MAAM,WAAW,cAAc;IAC7B,oEAAoE;IACpE,GAAG,EAAE,MAAM,CAAC;IACZ,uGAAuG;IACvG,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,yFAAyF;IACzF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,6GAA6G;IAC7G,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,qGAAqG;IACrG,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AA2BD;6FAC6F;AAC7F,wBAAgB,eAAe,CAAC,CAAC,EAAE,cAAc,GAAG,gBAAgB,CAuDnE;AAID,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,eAAe,GAAG,gBAAgB,CAIxE"}
1
+ {"version":3,"file":"provision.d.ts","sourceRoot":"","sources":["../src/provision.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAEH,MAAM,MAAM,gBAAgB,GAAG,KAAK,GAAG,QAAQ,GAAG,KAAK,CAAC;AAExD,MAAM,WAAW,gBAAgB;IAC/B,yDAAyD;IACzD,KAAK,EAAE,KAAK,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAC,CAAC,CAAC;IAC9C,oFAAoF;IACpF,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,+FAA+F;IAC/F,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,oDAAoD;IACpD,SAAS,EAAE,MAAM,CAAC;IAClB,2GAA2G;IAC3G,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,2DAA2D;IAC3D,GAAG,EAAE,MAAM,CAAC;IACZ,iGAAiG;IACjG,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,4DAA4D;IAC5D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,sFAAsF;IACtF,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,mGAAmG;IACnG,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,6FAA6F;IAC7F,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAoQD,MAAM,WAAW,cAAc;IAC7B,oEAAoE;IACpE,GAAG,EAAE,MAAM,CAAC;IACZ,uGAAuG;IACvG,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,yFAAyF;IACzF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,6GAA6G;IAC7G,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,qGAAqG;IACrG,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AA2BD;6FAC6F;AAC7F,wBAAgB,eAAe,CAAC,CAAC,EAAE,cAAc,GAAG,gBAAgB,CAwDnE;AAID,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,eAAe,GAAG,gBAAgB,CAIxE"}