@mindstudio-ai/remy 0.1.282 → 0.1.283
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/headless.js
CHANGED
|
@@ -2709,8 +2709,8 @@ function formatSize(bytes) {
|
|
|
2709
2709
|
}
|
|
2710
2710
|
async function formatFile(dirPath, name, indent) {
|
|
2711
2711
|
try {
|
|
2712
|
-
const
|
|
2713
|
-
return `${indent}${name}${" ".repeat(Math.max(1, 30 - indent.length - name.length))}${formatSize(
|
|
2712
|
+
const stat3 = await fs16.stat(path8.join(dirPath, name));
|
|
2713
|
+
return `${indent}${name}${" ".repeat(Math.max(1, 30 - indent.length - name.length))}${formatSize(stat3.size)}`;
|
|
2714
2714
|
} catch {
|
|
2715
2715
|
return `${indent}${name}`;
|
|
2716
2716
|
}
|
|
@@ -5570,20 +5570,24 @@ __export(createWireframe_exports, {
|
|
|
5570
5570
|
definition: () => definition10,
|
|
5571
5571
|
execute: () => execute10
|
|
5572
5572
|
});
|
|
5573
|
-
import { mkdir as mkdir2, writeFile as writeFile2 } from "fs/promises";
|
|
5573
|
+
import { mkdir as mkdir2, stat as stat2, writeFile as writeFile2 } from "fs/promises";
|
|
5574
5574
|
import { join as join2 } from "path";
|
|
5575
5575
|
var log9 = createLogger("createWireframe");
|
|
5576
5576
|
var WIREFRAMES_DIR = "src/.wireframes";
|
|
5577
5577
|
var UPLOAD_TIMEOUT_MS2 = 3e4;
|
|
5578
5578
|
var definition10 = {
|
|
5579
5579
|
name: "createWireframe",
|
|
5580
|
-
description: "Create a wireframe from self-contained HTML+CSS.
|
|
5580
|
+
description: "Create (or revise) a wireframe from self-contained HTML+CSS. The wireframe is saved to src/.wireframes/{slug}.html \u2014 reference it in your response and in specs as , with your notes in the surrounding prose. Calling again with the same slug overwrites the wireframe in place, so a revision keeps its path and existing references stay current.",
|
|
5581
5581
|
inputSchema: {
|
|
5582
5582
|
type: "object",
|
|
5583
5583
|
properties: {
|
|
5584
5584
|
name: {
|
|
5585
5585
|
type: "string",
|
|
5586
|
-
description: 'Short display name, e.g. "Feed Post Card". Becomes the caption
|
|
5586
|
+
description: 'Short display name, e.g. "Feed Post Card". Becomes the caption.'
|
|
5587
|
+
},
|
|
5588
|
+
slug: {
|
|
5589
|
+
type: "string",
|
|
5590
|
+
description: 'Filename stem, lowercase kebab-case (e.g. "feed-post-card"). The wireframe lives at src/.wireframes/{slug}.html. Re-use a slug to revise that wireframe in place.'
|
|
5587
5591
|
},
|
|
5588
5592
|
description: {
|
|
5589
5593
|
type: "string",
|
|
@@ -5594,20 +5598,24 @@ var definition10 = {
|
|
|
5594
5598
|
description: "The complete HTML document (<html>\u2026</html>), self-contained vanilla HTML/CSS/JS. No frontmatter \u2014 it is added for you."
|
|
5595
5599
|
}
|
|
5596
5600
|
},
|
|
5597
|
-
required: ["name", "description", "html"]
|
|
5601
|
+
required: ["name", "slug", "description", "html"]
|
|
5598
5602
|
}
|
|
5599
5603
|
};
|
|
5600
|
-
|
|
5601
|
-
return name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 40).replace(/-+$/, "") || "wireframe";
|
|
5602
|
-
}
|
|
5604
|
+
var SLUG_RE = /^[a-z0-9][a-z0-9-]{0,79}$/;
|
|
5603
5605
|
function singleLine(value) {
|
|
5604
5606
|
return value.replace(/\s+/g, " ").trim();
|
|
5605
5607
|
}
|
|
5606
|
-
function validate(name, html) {
|
|
5608
|
+
function validate(name, slug, html) {
|
|
5607
5609
|
const warnings = [];
|
|
5608
5610
|
if (!name.trim()) {
|
|
5609
5611
|
return { error: "Error: name is required.", warnings };
|
|
5610
5612
|
}
|
|
5613
|
+
if (!SLUG_RE.test(slug)) {
|
|
5614
|
+
return {
|
|
5615
|
+
error: 'Error: slug must be lowercase kebab-case ([a-z0-9-], starting with a letter or digit, \u2264 80 chars), e.g. "feed-post-card".',
|
|
5616
|
+
warnings
|
|
5617
|
+
};
|
|
5618
|
+
}
|
|
5611
5619
|
if (!html.trim()) {
|
|
5612
5620
|
return { error: "Error: html is required.", warnings };
|
|
5613
5621
|
}
|
|
@@ -5666,13 +5674,13 @@ async function execute10(input, onLog, context) {
|
|
|
5666
5674
|
return "Error: createWireframe requires execution context";
|
|
5667
5675
|
}
|
|
5668
5676
|
const name = String(input.name ?? "");
|
|
5677
|
+
const slug = String(input.slug ?? "");
|
|
5669
5678
|
const description = String(input.description ?? "");
|
|
5670
5679
|
const html = String(input.html ?? "");
|
|
5671
|
-
const { error, warnings } = validate(name, html);
|
|
5680
|
+
const { error, warnings } = validate(name, slug, html);
|
|
5672
5681
|
if (error) {
|
|
5673
5682
|
return error;
|
|
5674
5683
|
}
|
|
5675
|
-
const slug = `${slugify(name)}-${Math.random().toString(36).slice(2, 8)}`;
|
|
5676
5684
|
const relPath = `${WIREFRAMES_DIR}/${slug}.html`;
|
|
5677
5685
|
const content = [
|
|
5678
5686
|
"---",
|
|
@@ -5683,6 +5691,10 @@ async function execute10(input, onLog, context) {
|
|
|
5683
5691
|
""
|
|
5684
5692
|
].join("\n");
|
|
5685
5693
|
await mkdir2(join2(PROJECT_ROOT, WIREFRAMES_DIR), { recursive: true });
|
|
5694
|
+
const existed = await stat2(join2(PROJECT_ROOT, relPath)).then(
|
|
5695
|
+
() => true,
|
|
5696
|
+
() => false
|
|
5697
|
+
);
|
|
5686
5698
|
await writeFile2(join2(PROJECT_ROOT, relPath), content, "utf8");
|
|
5687
5699
|
onLog?.(`Wrote ${relPath}, mirroring for preview...`);
|
|
5688
5700
|
const mirror = await uploadMirror(context, slug, content);
|
|
@@ -5690,7 +5702,7 @@ async function execute10(input, onLog, context) {
|
|
|
5690
5702
|
log9.warn("Wireframe mirror upload failed", { slug, note: mirror.note });
|
|
5691
5703
|
}
|
|
5692
5704
|
const lines = [
|
|
5693
|
-
|
|
5705
|
+
`${existed ? "Revised" : "Created"} wireframe "${singleLine(name)}" at ${relPath}.${existed ? " Existing references to this path now show the new version." : ""}`,
|
|
5694
5706
|
`Reference it in your response and in specs with exactly: `
|
|
5695
5707
|
];
|
|
5696
5708
|
if (!mirror.ok) {
|
package/dist/index.js
CHANGED
|
@@ -3816,8 +3816,8 @@ function formatSize(bytes) {
|
|
|
3816
3816
|
}
|
|
3817
3817
|
async function formatFile(dirPath, name, indent) {
|
|
3818
3818
|
try {
|
|
3819
|
-
const
|
|
3820
|
-
return `${indent}${name}${" ".repeat(Math.max(1, 30 - indent.length - name.length))}${formatSize(
|
|
3819
|
+
const stat3 = await fs15.stat(path8.join(dirPath, name));
|
|
3820
|
+
return `${indent}${name}${" ".repeat(Math.max(1, 30 - indent.length - name.length))}${formatSize(stat3.size)}`;
|
|
3821
3821
|
} catch {
|
|
3822
3822
|
return `${indent}${name}`;
|
|
3823
3823
|
}
|
|
@@ -6752,19 +6752,22 @@ __export(createWireframe_exports, {
|
|
|
6752
6752
|
definition: () => definition10,
|
|
6753
6753
|
execute: () => execute10
|
|
6754
6754
|
});
|
|
6755
|
-
import { mkdir as mkdir2, writeFile as writeFile2 } from "fs/promises";
|
|
6755
|
+
import { mkdir as mkdir2, stat as stat2, writeFile as writeFile2 } from "fs/promises";
|
|
6756
6756
|
import { join as join2 } from "path";
|
|
6757
|
-
function slugify(name) {
|
|
6758
|
-
return name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 40).replace(/-+$/, "") || "wireframe";
|
|
6759
|
-
}
|
|
6760
6757
|
function singleLine(value) {
|
|
6761
6758
|
return value.replace(/\s+/g, " ").trim();
|
|
6762
6759
|
}
|
|
6763
|
-
function validate(name, html) {
|
|
6760
|
+
function validate(name, slug, html) {
|
|
6764
6761
|
const warnings = [];
|
|
6765
6762
|
if (!name.trim()) {
|
|
6766
6763
|
return { error: "Error: name is required.", warnings };
|
|
6767
6764
|
}
|
|
6765
|
+
if (!SLUG_RE.test(slug)) {
|
|
6766
|
+
return {
|
|
6767
|
+
error: 'Error: slug must be lowercase kebab-case ([a-z0-9-], starting with a letter or digit, \u2264 80 chars), e.g. "feed-post-card".',
|
|
6768
|
+
warnings
|
|
6769
|
+
};
|
|
6770
|
+
}
|
|
6768
6771
|
if (!html.trim()) {
|
|
6769
6772
|
return { error: "Error: html is required.", warnings };
|
|
6770
6773
|
}
|
|
@@ -6823,13 +6826,13 @@ async function execute10(input, onLog, context) {
|
|
|
6823
6826
|
return "Error: createWireframe requires execution context";
|
|
6824
6827
|
}
|
|
6825
6828
|
const name = String(input.name ?? "");
|
|
6829
|
+
const slug = String(input.slug ?? "");
|
|
6826
6830
|
const description = String(input.description ?? "");
|
|
6827
6831
|
const html = String(input.html ?? "");
|
|
6828
|
-
const { error, warnings } = validate(name, html);
|
|
6832
|
+
const { error, warnings } = validate(name, slug, html);
|
|
6829
6833
|
if (error) {
|
|
6830
6834
|
return error;
|
|
6831
6835
|
}
|
|
6832
|
-
const slug = `${slugify(name)}-${Math.random().toString(36).slice(2, 8)}`;
|
|
6833
6836
|
const relPath = `${WIREFRAMES_DIR}/${slug}.html`;
|
|
6834
6837
|
const content = [
|
|
6835
6838
|
"---",
|
|
@@ -6840,6 +6843,10 @@ async function execute10(input, onLog, context) {
|
|
|
6840
6843
|
""
|
|
6841
6844
|
].join("\n");
|
|
6842
6845
|
await mkdir2(join2(PROJECT_ROOT, WIREFRAMES_DIR), { recursive: true });
|
|
6846
|
+
const existed = await stat2(join2(PROJECT_ROOT, relPath)).then(
|
|
6847
|
+
() => true,
|
|
6848
|
+
() => false
|
|
6849
|
+
);
|
|
6843
6850
|
await writeFile2(join2(PROJECT_ROOT, relPath), content, "utf8");
|
|
6844
6851
|
onLog?.(`Wrote ${relPath}, mirroring for preview...`);
|
|
6845
6852
|
const mirror = await uploadMirror(context, slug, content);
|
|
@@ -6847,7 +6854,7 @@ async function execute10(input, onLog, context) {
|
|
|
6847
6854
|
log10.warn("Wireframe mirror upload failed", { slug, note: mirror.note });
|
|
6848
6855
|
}
|
|
6849
6856
|
const lines = [
|
|
6850
|
-
|
|
6857
|
+
`${existed ? "Revised" : "Created"} wireframe "${singleLine(name)}" at ${relPath}.${existed ? " Existing references to this path now show the new version." : ""}`,
|
|
6851
6858
|
`Reference it in your response and in specs with exactly: `
|
|
6852
6859
|
];
|
|
6853
6860
|
if (!mirror.ok) {
|
|
@@ -6860,7 +6867,7 @@ async function execute10(input, onLog, context) {
|
|
|
6860
6867
|
}
|
|
6861
6868
|
return lines.join("\n");
|
|
6862
6869
|
}
|
|
6863
|
-
var log10, WIREFRAMES_DIR, UPLOAD_TIMEOUT_MS2, definition10;
|
|
6870
|
+
var log10, WIREFRAMES_DIR, UPLOAD_TIMEOUT_MS2, definition10, SLUG_RE;
|
|
6864
6871
|
var init_createWireframe = __esm({
|
|
6865
6872
|
"src/subagents/designExpert/tools/createWireframe.ts"() {
|
|
6866
6873
|
"use strict";
|
|
@@ -6871,13 +6878,17 @@ var init_createWireframe = __esm({
|
|
|
6871
6878
|
UPLOAD_TIMEOUT_MS2 = 3e4;
|
|
6872
6879
|
definition10 = {
|
|
6873
6880
|
name: "createWireframe",
|
|
6874
|
-
description: "Create a wireframe from self-contained HTML+CSS.
|
|
6881
|
+
description: "Create (or revise) a wireframe from self-contained HTML+CSS. The wireframe is saved to src/.wireframes/{slug}.html \u2014 reference it in your response and in specs as , with your notes in the surrounding prose. Calling again with the same slug overwrites the wireframe in place, so a revision keeps its path and existing references stay current.",
|
|
6875
6882
|
inputSchema: {
|
|
6876
6883
|
type: "object",
|
|
6877
6884
|
properties: {
|
|
6878
6885
|
name: {
|
|
6879
6886
|
type: "string",
|
|
6880
|
-
description: 'Short display name, e.g. "Feed Post Card". Becomes the caption
|
|
6887
|
+
description: 'Short display name, e.g. "Feed Post Card". Becomes the caption.'
|
|
6888
|
+
},
|
|
6889
|
+
slug: {
|
|
6890
|
+
type: "string",
|
|
6891
|
+
description: 'Filename stem, lowercase kebab-case (e.g. "feed-post-card"). The wireframe lives at src/.wireframes/{slug}.html. Re-use a slug to revise that wireframe in place.'
|
|
6881
6892
|
},
|
|
6882
6893
|
description: {
|
|
6883
6894
|
type: "string",
|
|
@@ -6888,9 +6899,10 @@ var init_createWireframe = __esm({
|
|
|
6888
6899
|
description: "The complete HTML document (<html>\u2026</html>), self-contained vanilla HTML/CSS/JS. No frontmatter \u2014 it is added for you."
|
|
6889
6900
|
}
|
|
6890
6901
|
},
|
|
6891
|
-
required: ["name", "description", "html"]
|
|
6902
|
+
required: ["name", "slug", "description", "html"]
|
|
6892
6903
|
}
|
|
6893
6904
|
};
|
|
6905
|
+
SLUG_RE = /^[a-z0-9][a-z0-9-]{0,79}$/;
|
|
6894
6906
|
}
|
|
6895
6907
|
});
|
|
6896
6908
|
|
|
@@ -12,7 +12,7 @@ Your designer. Consult for any visual decision — choosing a color, picking fon
|
|
|
12
12
|
|
|
13
13
|
The design expert cannot see your conversation with the user, so include relevant context and requirements in your task. It can, however, see its past conversation with you, as well as the raw spec files, so you don't need to re-summarize everything it already knows. Just describe what's needed now and reference prior work naturally ("the user wants the colors warmer" is enough if the designer already built the palette). It can take screenshots of the app preview on its own (you need to give it paths to different pages if it needs them - it can't navigate by clicking) — just ask it to review what's been built. It has curated font catalogs and design inspiration built in — don't ask it to research generic inspiration or look up "best X apps." Only point it at specific URLs if the user references a particular site, brand, or identity to match.
|
|
14
14
|
|
|
15
|
-
The designer will return concrete resources: hex values, font names with CSS URLs, image URLs, layout descriptions, as well as specific techniques, CSS properties, animation timings, code snippets, and other values. Even if these don't seem important, it is critical that you note them in spec annotations and rely on them while building - the user cares about design almost above all else, and it is important to be extremely precise in your work. The designer can also return code-fenced typography and color schemes (self-contained HTML and CSS) - write these directly into specs for future reference. Wireframes arrive as file references like ` - write these directly into specs for future reference. Wireframes arrive as file references like ``: copy the reference line into specs verbatim (it renders as a visual preview in chat and in the spec), and read the file at that path while building to get the exact markup and CSS the designer specified. When the designer revises a wireframe it overwrites the same path, so existing references stay current.
|
|
16
16
|
|
|
17
17
|
When delegating, describe the design problem — where the asset will be used, what it needs to communicate, what the brand feels like. Do not specify technical details like image formats, pixel dimensions, generation techniques, or workarounds. The design expert makes those decisions.
|
|
18
18
|
|
|
@@ -16,7 +16,7 @@ Think about the ways you can truly elevate the design. Use image generation to c
|
|
|
16
16
|
- After you've taken a screenshot, use analyze image to ask different questions about it - don't re-screenshot the page unnecessarily.
|
|
17
17
|
- Match the image engine to the job: `renderImage` (a browser rendering HTML you author) for token-exact graphics — share cards, wordmarks, flat icon tiles; `generateImages` (an image model) for organic, photographic, and illustrated work. Don't ask the image model to hit exact hex codes or typography, and don't hand-write SVG path data — compose HTML/CSS and render it.
|
|
18
18
|
- When you write user-facing copy (headlines, captions, labels, body text), hand it to `polishCopy` before finalizing. It tightens prose so it reads like a person wrote it rather than a machine, without changing what it says. Cheap and fast — use it on any copy that will ship.
|
|
19
|
-
- Deliver wireframes with `createWireframe`. Include the
|
|
19
|
+
- Deliver wireframes with `createWireframe`. Include the `` line in your response where the wireframe belongs — it renders as a live preview, and the developer reads the file for the exact markup. Same slug = revise in place; new slug = new wireframe.
|
|
20
20
|
|
|
21
21
|
## Voice
|
|
22
22
|
- No emoji, no filler.
|
|
@@ -25,7 +25,7 @@ Some surfaces are deep enough to carry their own craft reference in <available_s
|
|
|
25
25
|
|
|
26
26
|
### Wireframes
|
|
27
27
|
|
|
28
|
-
When you need to show a layout, component, interaction, or animation, create a wireframe with the `createWireframe` tool: pass a `name`, a one-line `description`, and self-contained HTML+CSS. The
|
|
28
|
+
When you need to show a layout, component, interaction, or animation, create a wireframe with the `createWireframe` tool: pass a `name`, a kebab-case `slug`, a one-line `description`, and self-contained HTML+CSS. The wireframe is saved to `src/.wireframes/{slug}.html`, and you reference it as `` — include that line in your response wherever the wireframe belongs, with your notes in the surrounding prose. The reference line renders as a live visual preview, and the developer reads the file itself for the exact markup and CSS. A reference only renders once its wireframe exists, so make the `createWireframe` call for every reference you write — in the same response is fine.
|
|
29
29
|
|
|
30
30
|
Never use ASCII art, box-drawing characters, or code-block diagrams to describe layouts. Always use a wireframe instead, even if it's just grey rectangles with labels. A 20-line wireframe with placeholder boxes communicates proportions, spacing, and hierarchy better than any text diagram. For abstract layouts, use skeleton-style placeholders (grey boxes, rounded rects) rather than mocking up real content.
|
|
31
31
|
|
|
@@ -35,9 +35,9 @@ Wireframes render in a small transparent iframe. Set a background color and shad
|
|
|
35
35
|
|
|
36
36
|
Wireframes are vanilla HTML/CSS/JS (no React). For animations beyond CSS, use GSAP via CDN: `<script src="https://cdn.jsdelivr.net/npm/gsap@3/dist/gsap.min.js"></script>`
|
|
37
37
|
|
|
38
|
-
|
|
38
|
+
To revise a wireframe, call `createWireframe` again with the same slug — the file is overwritten in place and every existing reference to that path (in chat and in specs) shows the new version. Read the current file first if you're iterating on it. Use a new slug when it's genuinely a different wireframe, not a revision.
|
|
39
39
|
|
|
40
|
-
Quick skeleton wireframe (grey boxes, just showing layout and hierarchy) — `createWireframe` with name "Content Card Layout", description "Card with image area, title, metadata row, rating, and actions. Skeleton placeholders showing proportions and hierarchy.", and this html:
|
|
40
|
+
Quick skeleton wireframe (grey boxes, just showing layout and hierarchy) — `createWireframe` with name "Content Card Layout", slug "content-card-layout", description "Card with image area, title, metadata row, rating, and actions. Skeleton placeholders showing proportions and hierarchy.", and this html:
|
|
41
41
|
|
|
42
42
|
```html
|
|
43
43
|
<html lang="en"><head>
|
|
@@ -72,7 +72,7 @@ Quick skeleton wireframe (grey boxes, just showing layout and hierarchy) — `cr
|
|
|
72
72
|
</html>
|
|
73
73
|
```
|
|
74
74
|
|
|
75
|
-
Detailed component wireframe (showing specific design decisions) — `createWireframe` with name "Feed Post Card", description "Photo post card with header, image frame, action row (like/comment/share/bookmark), like count, and caption. Shows spacing, typography hierarchy, and icon placement.", and this html:
|
|
75
|
+
Detailed component wireframe (showing specific design decisions) — `createWireframe` with name "Feed Post Card", slug "feed-post-card", description "Photo post card with header, image frame, action row (like/comment/share/bookmark), like count, and caption. Shows spacing, typography hierarchy, and icon placement.", and this html:
|
|
76
76
|
|
|
77
77
|
```html
|
|
78
78
|
<html lang="en"><head>
|