@mindstudio-ai/remy 0.1.244 → 0.1.245

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
@@ -1881,11 +1881,11 @@ var setProjectMetadataTool = {
1881
1881
  },
1882
1882
  iconUrl: {
1883
1883
  type: "string",
1884
- description: "URL for the app icon (square."
1884
+ description: "URL for the app icon (square)."
1885
1885
  },
1886
1886
  openGraphShareImageUrl: {
1887
1887
  type: "string",
1888
- description: "URL for the Open Graph share image (1200x630)."
1888
+ description: "URL for the Open Graph share image (1200\xD7630 PNG)."
1889
1889
  }
1890
1890
  }
1891
1891
  }
@@ -2819,9 +2819,7 @@ async function analyzeImage(params) {
2819
2819
 
2820
2820
  // src/tools/_helpers/screenshot.ts
2821
2821
  var SCREENSHOT_ANALYSIS_PROMPT = `Describe everything visible on screen from top to bottom \u2014 every element, its position, its size relative to the viewport, its colors, its content. Be comprehensive, thorough, and spatial. After the inventory, note anything that looks visually broken (overlapping elements, clipped text, misaligned components).`;
2822
- var TEXT_WRAP_DISCLAIMER = `Note: ignore text wrapping issues. Screenshots occasionally show text wrapping onto an extra line compared to the live page \u2014 most noticeable in buttons, badges, and headings. This is a known limitation of SVG foreignObject rendering used the DOM-to-image capture library that took the screenshot. The browser's SVG renderer computes slightly wider text metrics than the HTML layout engine, so text that fits on one line in the live DOM can overflow by a fraction of a pixel in the capture - this is not a real issue.
2823
-
2824
- Respond only with your analysis as Markdown and absolutely no other text. Do not use emojis - use unicode if you need symbols.`;
2822
+ var ANALYSIS_RESPONSE_FORMAT = `Respond only with your analysis as Markdown and absolutely no other text. Do not use emojis - use unicode if you need symbols.`;
2825
2823
  function buildScreenshotAnalysisPrompt(opts) {
2826
2824
  let p = opts?.prompt || SCREENSHOT_ANALYSIS_PROMPT;
2827
2825
  if (opts?.styleMap) {
@@ -2835,7 +2833,7 @@ ${opts.styleMap}
2835
2833
  }
2836
2834
  p += `
2837
2835
 
2838
- ${TEXT_WRAP_DISCLAIMER}`;
2836
+ ${ANALYSIS_RESPONSE_FORMAT}`;
2839
2837
  return p;
2840
2838
  }
2841
2839
  async function streamScreenshotAnalysis(opts) {
@@ -2861,6 +2859,9 @@ async function captureAndAnalyzeScreenshot(promptOrOptions) {
2861
2859
  let model;
2862
2860
  let path13;
2863
2861
  let fullPage = true;
2862
+ let width;
2863
+ let height;
2864
+ let format;
2864
2865
  if (typeof promptOrOptions === "object" && promptOrOptions !== null) {
2865
2866
  prompt = promptOrOptions.prompt;
2866
2867
  existingUrl = promptOrOptions.imageUrl;
@@ -2868,11 +2869,17 @@ async function captureAndAnalyzeScreenshot(promptOrOptions) {
2868
2869
  if (promptOrOptions.fullPage !== void 0) {
2869
2870
  fullPage = promptOrOptions.fullPage;
2870
2871
  }
2872
+ width = promptOrOptions.width;
2873
+ height = promptOrOptions.height;
2874
+ format = promptOrOptions.format;
2871
2875
  onLog = promptOrOptions.onLog;
2872
2876
  model = promptOrOptions.model;
2873
2877
  } else {
2874
2878
  prompt = promptOrOptions;
2875
2879
  }
2880
+ if (width != null && height != null) {
2881
+ fullPage = false;
2882
+ }
2876
2883
  let url;
2877
2884
  let styleMap;
2878
2885
  if (existingUrl) {
@@ -2880,7 +2887,12 @@ async function captureAndAnalyzeScreenshot(promptOrOptions) {
2880
2887
  } else {
2881
2888
  const ssResult = await sidecarRequest(
2882
2889
  fullPage ? "/screenshot-full-page" : "/screenshot-viewport",
2883
- path13 ? { path: path13 } : void 0,
2890
+ {
2891
+ ...path13 ? { path: path13 } : {},
2892
+ ...width != null ? { width } : {},
2893
+ ...height != null ? { height } : {},
2894
+ ...format ? { format } : {}
2895
+ },
2884
2896
  { timeout: fullPage ? 12e4 : 3e4 }
2885
2897
  );
2886
2898
  url = ssResult?.url || ssResult?.screenshotUrl;
@@ -4009,7 +4021,7 @@ var screenshotTool = {
4009
4021
  clearable: true,
4010
4022
  definition: {
4011
4023
  name: "screenshot",
4012
- description: "Capture a screenshot of the app preview and get a description of what's on screen. Choose `fullPage`: `false` captures just the visible viewport (fast \u2014 for a specific section the page is scrolled to), `true` captures the entire page top-to-bottom (slower \u2014 for overall composition or content past the fold). Captures the settled page state \u2014 it cannot catch animations, transitions, or transient state. Optionally provide specific questions about what you're looking for. Use a bulleted list to ask many questions at once. To ask additional questions about a screenshot you have already captured, pass its URL as imageUrl to skip recapture. If the screenshot requires interaction first (logging in, clicking a tab, dismissing a modal, scrolling to a section), use the instructions param to describe the steps.",
4024
+ description: "Capture a screenshot of the app preview and get a description of what's on screen. Choose `fullPage`: `false` captures just the visible viewport (fast \u2014 for a specific section the page is scrolled to), `true` captures the entire page top-to-bottom (slower \u2014 for overall composition or content past the fold). Captures the settled page state \u2014 it cannot catch animations, transitions, or transient state. Optionally provide specific questions about what you're looking for. Use a bulleted list to ask many questions at once. To ask additional questions about a screenshot you have already captured, pass its URL as imageUrl to skip recapture. If the screenshot requires interaction first (logging in, clicking a tab, dismissing a modal, scrolling to a section), use the instructions param to describe the steps. To render a fixed-size image such as an Open Graph share card, set `width` and `height` (e.g. 1200 \xD7 630) and `format: 'png'`: the tool navigates to `path`, clips to exactly those pixel dimensions, and returns the image URL.",
4013
4025
  inputSchema: {
4014
4026
  type: "object",
4015
4027
  properties: {
@@ -4029,6 +4041,19 @@ var screenshotTool = {
4029
4041
  type: "string",
4030
4042
  description: 'Navigate to this path before capturing (e.g. "/settings", "/dashboard"). If omitted, screenshots the current page.'
4031
4043
  },
4044
+ width: {
4045
+ type: "number",
4046
+ description: "Exact capture width in pixels. Set together with `height` to render a fixed-size image; clips to exactly this viewport instead of the default preview size."
4047
+ },
4048
+ height: {
4049
+ type: "number",
4050
+ description: "Exact capture height in pixels. Set together with `width`."
4051
+ },
4052
+ format: {
4053
+ type: "string",
4054
+ enum: ["png", "jpeg"],
4055
+ description: "Output image format. Defaults to 'jpeg'. Use 'png' for crisp flat graphics like share cards, where JPEG artifacts show on sharp type and edges."
4056
+ },
4032
4057
  instructions: {
4033
4058
  type: "string",
4034
4059
  description: "If the screenshot you need requires interaction first (dismissing a modal, clicking a tab, filling out a form, navigating a flow, scrolling to a section, getting through a login/auth checkpoint), describe the steps to get there. A browser automation agent will follow these instructions, then capture per your `fullPage` choice \u2014 so with `fullPage: false` you can scroll to a section and capture just that viewport. It can bypass auth and get right to where it needs to be if you tell it to authenticate as a test user and give it the path/screen to start its test at. Never describe what names or values to use when applying the instructions - the browser automation agent must use its own values for it to work properly. If a specific auth role is required to access the content, be sure to note that - it can automatically assume it for the purpose of testing. Use only when interaction is required to *reach* the state you want to capture \u2014 log in, dismiss a modal, switch a tab, follow a route, scroll to a section. If your steps are exercising the app's functionality across multiple states (running flows, asserting behavior under interaction, multi-step QA), use `runAutomatedBrowserTest` instead."
@@ -4071,6 +4096,9 @@ var screenshotTool = {
4071
4096
  prompt: input.prompt,
4072
4097
  path: input.path,
4073
4098
  fullPage,
4099
+ width: input.width,
4100
+ height: input.height,
4101
+ format: input.format,
4074
4102
  onLog: context?.onLog,
4075
4103
  model: resolveModel("imageAnalysis", context?.models, context?.model)
4076
4104
  });
package/dist/index.js CHANGED
@@ -1462,11 +1462,11 @@ var init_setProjectMetadata = __esm({
1462
1462
  },
1463
1463
  iconUrl: {
1464
1464
  type: "string",
1465
- description: "URL for the app icon (square."
1465
+ description: "URL for the app icon (square)."
1466
1466
  },
1467
1467
  openGraphShareImageUrl: {
1468
1468
  type: "string",
1469
- description: "URL for the Open Graph share image (1200x630)."
1469
+ description: "URL for the Open Graph share image (1200\xD7630 PNG)."
1470
1470
  }
1471
1471
  }
1472
1472
  }
@@ -3555,7 +3555,7 @@ ${opts.styleMap}
3555
3555
  }
3556
3556
  p += `
3557
3557
 
3558
- ${TEXT_WRAP_DISCLAIMER}`;
3558
+ ${ANALYSIS_RESPONSE_FORMAT}`;
3559
3559
  return p;
3560
3560
  }
3561
3561
  async function streamScreenshotAnalysis(opts) {
@@ -3581,6 +3581,9 @@ async function captureAndAnalyzeScreenshot(promptOrOptions) {
3581
3581
  let model;
3582
3582
  let path14;
3583
3583
  let fullPage = true;
3584
+ let width;
3585
+ let height;
3586
+ let format;
3584
3587
  if (typeof promptOrOptions === "object" && promptOrOptions !== null) {
3585
3588
  prompt = promptOrOptions.prompt;
3586
3589
  existingUrl = promptOrOptions.imageUrl;
@@ -3588,11 +3591,17 @@ async function captureAndAnalyzeScreenshot(promptOrOptions) {
3588
3591
  if (promptOrOptions.fullPage !== void 0) {
3589
3592
  fullPage = promptOrOptions.fullPage;
3590
3593
  }
3594
+ width = promptOrOptions.width;
3595
+ height = promptOrOptions.height;
3596
+ format = promptOrOptions.format;
3591
3597
  onLog = promptOrOptions.onLog;
3592
3598
  model = promptOrOptions.model;
3593
3599
  } else {
3594
3600
  prompt = promptOrOptions;
3595
3601
  }
3602
+ if (width != null && height != null) {
3603
+ fullPage = false;
3604
+ }
3596
3605
  let url;
3597
3606
  let styleMap;
3598
3607
  if (existingUrl) {
@@ -3600,7 +3609,12 @@ async function captureAndAnalyzeScreenshot(promptOrOptions) {
3600
3609
  } else {
3601
3610
  const ssResult = await sidecarRequest(
3602
3611
  fullPage ? "/screenshot-full-page" : "/screenshot-viewport",
3603
- path14 ? { path: path14 } : void 0,
3612
+ {
3613
+ ...path14 ? { path: path14 } : {},
3614
+ ...width != null ? { width } : {},
3615
+ ...height != null ? { height } : {},
3616
+ ...format ? { format } : {}
3617
+ },
3604
3618
  { timeout: fullPage ? 12e4 : 3e4 }
3605
3619
  );
3606
3620
  url = ssResult?.url || ssResult?.screenshotUrl;
@@ -3627,16 +3641,14 @@ async function captureAndAnalyzeScreenshot(promptOrOptions) {
3627
3641
  model
3628
3642
  });
3629
3643
  }
3630
- var SCREENSHOT_ANALYSIS_PROMPT, TEXT_WRAP_DISCLAIMER;
3644
+ var SCREENSHOT_ANALYSIS_PROMPT, ANALYSIS_RESPONSE_FORMAT;
3631
3645
  var init_screenshot = __esm({
3632
3646
  "src/tools/_helpers/screenshot.ts"() {
3633
3647
  "use strict";
3634
3648
  init_sidecar();
3635
3649
  init_analyzeImage();
3636
3650
  SCREENSHOT_ANALYSIS_PROMPT = `Describe everything visible on screen from top to bottom \u2014 every element, its position, its size relative to the viewport, its colors, its content. Be comprehensive, thorough, and spatial. After the inventory, note anything that looks visually broken (overlapping elements, clipped text, misaligned components).`;
3637
- TEXT_WRAP_DISCLAIMER = `Note: ignore text wrapping issues. Screenshots occasionally show text wrapping onto an extra line compared to the live page \u2014 most noticeable in buttons, badges, and headings. This is a known limitation of SVG foreignObject rendering used the DOM-to-image capture library that took the screenshot. The browser's SVG renderer computes slightly wider text metrics than the HTML layout engine, so text that fits on one line in the live DOM can overflow by a fraction of a pixel in the capture - this is not a real issue.
3638
-
3639
- Respond only with your analysis as Markdown and absolutely no other text. Do not use emojis - use unicode if you need symbols.`;
3651
+ ANALYSIS_RESPONSE_FORMAT = `Respond only with your analysis as Markdown and absolutely no other text. Do not use emojis - use unicode if you need symbols.`;
3640
3652
  }
3641
3653
  });
3642
3654
 
@@ -4622,7 +4634,7 @@ var init_screenshot2 = __esm({
4622
4634
  clearable: true,
4623
4635
  definition: {
4624
4636
  name: "screenshot",
4625
- description: "Capture a screenshot of the app preview and get a description of what's on screen. Choose `fullPage`: `false` captures just the visible viewport (fast \u2014 for a specific section the page is scrolled to), `true` captures the entire page top-to-bottom (slower \u2014 for overall composition or content past the fold). Captures the settled page state \u2014 it cannot catch animations, transitions, or transient state. Optionally provide specific questions about what you're looking for. Use a bulleted list to ask many questions at once. To ask additional questions about a screenshot you have already captured, pass its URL as imageUrl to skip recapture. If the screenshot requires interaction first (logging in, clicking a tab, dismissing a modal, scrolling to a section), use the instructions param to describe the steps.",
4637
+ description: "Capture a screenshot of the app preview and get a description of what's on screen. Choose `fullPage`: `false` captures just the visible viewport (fast \u2014 for a specific section the page is scrolled to), `true` captures the entire page top-to-bottom (slower \u2014 for overall composition or content past the fold). Captures the settled page state \u2014 it cannot catch animations, transitions, or transient state. Optionally provide specific questions about what you're looking for. Use a bulleted list to ask many questions at once. To ask additional questions about a screenshot you have already captured, pass its URL as imageUrl to skip recapture. If the screenshot requires interaction first (logging in, clicking a tab, dismissing a modal, scrolling to a section), use the instructions param to describe the steps. To render a fixed-size image such as an Open Graph share card, set `width` and `height` (e.g. 1200 \xD7 630) and `format: 'png'`: the tool navigates to `path`, clips to exactly those pixel dimensions, and returns the image URL.",
4626
4638
  inputSchema: {
4627
4639
  type: "object",
4628
4640
  properties: {
@@ -4642,6 +4654,19 @@ var init_screenshot2 = __esm({
4642
4654
  type: "string",
4643
4655
  description: 'Navigate to this path before capturing (e.g. "/settings", "/dashboard"). If omitted, screenshots the current page.'
4644
4656
  },
4657
+ width: {
4658
+ type: "number",
4659
+ description: "Exact capture width in pixels. Set together with `height` to render a fixed-size image; clips to exactly this viewport instead of the default preview size."
4660
+ },
4661
+ height: {
4662
+ type: "number",
4663
+ description: "Exact capture height in pixels. Set together with `width`."
4664
+ },
4665
+ format: {
4666
+ type: "string",
4667
+ enum: ["png", "jpeg"],
4668
+ description: "Output image format. Defaults to 'jpeg'. Use 'png' for crisp flat graphics like share cards, where JPEG artifacts show on sharp type and edges."
4669
+ },
4645
4670
  instructions: {
4646
4671
  type: "string",
4647
4672
  description: "If the screenshot you need requires interaction first (dismissing a modal, clicking a tab, filling out a form, navigating a flow, scrolling to a section, getting through a login/auth checkpoint), describe the steps to get there. A browser automation agent will follow these instructions, then capture per your `fullPage` choice \u2014 so with `fullPage: false` you can scroll to a section and capture just that viewport. It can bypass auth and get right to where it needs to be if you tell it to authenticate as a test user and give it the path/screen to start its test at. Never describe what names or values to use when applying the instructions - the browser automation agent must use its own values for it to work properly. If a specific auth role is required to access the content, be sure to note that - it can automatically assume it for the purpose of testing. Use only when interaction is required to *reach* the state you want to capture \u2014 log in, dismiss a modal, switch a tab, follow a route, scroll to a section. If your steps are exercising the app's functionality across multiple states (running flows, asserting behavior under interaction, multi-step QA), use `runAutomatedBrowserTest` instead."
@@ -4684,6 +4709,9 @@ var init_screenshot2 = __esm({
4684
4709
  prompt: input.prompt,
4685
4710
  path: input.path,
4686
4711
  fullPage,
4712
+ width: input.width,
4713
+ height: input.height,
4714
+ format: input.format,
4687
4715
  onLog: context?.onLog,
4688
4716
  model: resolveModel("imageAnalysis", context?.models, context?.model)
4689
4717
  });
@@ -76,6 +76,6 @@ When you receive background results:
76
76
 
77
77
  You can only background the following two tasks, unless the user specifically asks you to do work in the background:
78
78
  - `productVision` seeding the intiial roadmap after writing the spec for the first time or updating the roadmap after large work sessions. This task takes a while and we can allow the user to continue building while it happens in the background.
79
- - After writing the spec, once you have finalized the shape of the app, ask `visualDesignExpert` to create an icon and an open graph shring image for the app, then set them with `setProjectMetadata`, alongside the app's name and short description.
79
+ - After writing the spec, once you have finalized the shape of the app, ask `visualDesignExpert` to create an icon and to design an Open Graph share image, then set them with `setProjectMetadata` alongside the app's name and short description. The icon is a generated asset. The share image should be composed as a self-contained HTML card (real lockup, brand fonts, exact type) and captured — not generated: serve the card HTML from `dist/interfaces/web/public/`, screenshot it with the `screenshot` tool at `width: 1200, height: 630, format: 'png'`, and save the resulting PNG into the app's public assets so the deployed site hosts it.
80
80
 
81
81
  Do not background any other tasks. Be aware that sometimes tools like specSync will background on their own - this is not something that is within your control.
@@ -77,7 +77,9 @@ Keep logos and icons consistent - if you already have a logo, use `editImages` t
77
77
 
78
78
  #### Open Graph Sharing Images
79
79
 
80
- OG images show up in iMessage, Slack, Twitter, etc. at small sizes. They're a mood piece, not a messaging opportunity. Keep text minimal: the app name and at most a short tagline (three to five words). Think App Store feature card — one beautiful composition that makes someone want to tap. The text should feel integrated into the scene, not pasted on a background. Generate at 4096 × 2150 and return the CDN URL.
80
+ OG images show up in iMessage, Slack, Twitter, etc. at small sizes. They're a mood piece, not a messaging opportunity. Keep text minimal: the app name and at most a short tagline (three to five words). Think App Store feature card — one beautiful composition that makes someone want to tap. The text should feel integrated into the scene, not pasted on a background.
81
+
82
+ A share card is a wordmark, a short line, and a logo on a brand field — **compose it as HTML, don't generate it with the image model.** A generated image gives you odd letterforms and no brand fidelity; HTML gives you the real SVG lockup, the actual brand fonts, exact colors, and pixel-perfect spacing. Author a self-contained HTML document sized to 1200 × 630 — the lockup inline as SVG, the brand fonts inlined as base64 (so nothing loads late and captures as a fallback), the palette and type exact — then capture it with the `screenshot` tool at `width: 1200, height: 630, format: 'png'`, a faithful real-browser render. Don't route it through a document/HTML-to-image "openGraph" render mode; that pipeline strips CSS backgrounds. The same compose-and-capture approach beats generation for any precise brand graphic where letterforms and spacing carry the design.
81
83
 
82
84
  ### When to use images
83
85
 
@@ -69,12 +69,6 @@ For app icons and logos, the goal is something that reads clearly at phone home
69
69
  - You must specify that the image is full bleed - never say anything about rounded corners or there is a high likelihood that the image will come back as a rounded rectangle on a white background!
70
70
  - Apply the same material/lighting/color density as photography prompts, just to a single object. Describe the surface finish ("high-gloss lacquered finish with clean specular highlights," "soft matte ceramic with subtle surface texture"), the lighting behavior ("warm directional light from upper left producing a bright highlight streak across the curved surface and a soft shadow beneath"), and color as relationships ("deep coral body graduating to warm peach at the highlight edge, with a cream accent on the lens element"). Generic descriptors like "clean surfaces, soft lighting" produce generic icons.
71
71
 
72
- #### Open Graph Sharing Images
73
-
74
- OG images are often a user's first impression of the app — they show up in iMessage, Slack, Twitter, etc. at small sizes. Keep text minimal: the app name and at most a short tagline (three to five words). This is a mood piece, not a messaging opportunity. Think App Store feature card — one beautiful composition that makes someone want to tap.
75
-
76
- Apply the same material/lighting/color density as photography prompts. The text should feel integrated into the scene — typeset within the composition, not pasted on top. Describe the typography treatment (weight, size, color, position) as part of the overall image, and describe how the background interacts with the text (glow, depth, contrast). The whole image should read as one cohesive graphic, not layers.
77
-
78
72
  ## Output
79
73
 
80
74
  Respond with ONLY the enhanced prompt. Be detailed and specific — a good prompt is a dense paragraph of 80-150 words that paints a complete picture: style, subject, materials, lighting behavior, color relationships, atmosphere, and composition. Terse prompts produce generic images.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mindstudio-ai/remy",
3
- "version": "0.1.244",
3
+ "version": "0.1.245",
4
4
  "description": "Remy coding agent",
5
5
  "repository": {
6
6
  "type": "git",