@mindstudio-ai/remy 0.1.243 → 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 +48 -13
- package/dist/index.js +49 -14
- package/dist/prompt/compiled/auth.md +4 -4
- package/dist/prompt/static/team.md +1 -1
- package/dist/subagents/designExpert/prompts/images.md +3 -1
- package/dist/subagents/designExpert/prompts/ui-patterns.md +1 -1
- package/dist/subagents/designExpert/tools/images/enhance-image-prompt.md +0 -6
- package/package.json +1 -1
package/dist/headless.js
CHANGED
|
@@ -557,24 +557,31 @@ function getOrgContext() {
|
|
|
557
557
|
function renderOrgContextBlock() {
|
|
558
558
|
const ctx = cached;
|
|
559
559
|
const auth = ctx?.auth;
|
|
560
|
-
|
|
560
|
+
const hasAuth = !!auth && (auth.delegatedAvailable || !!auth.requireDelegatedOnly);
|
|
561
|
+
const hasDesignSystem = !!ctx?.designSystem;
|
|
562
|
+
if (!hasAuth && !hasDesignSystem) {
|
|
561
563
|
return "";
|
|
562
564
|
}
|
|
563
|
-
const lines = ["<
|
|
565
|
+
const lines = ["<org_context>"];
|
|
564
566
|
if (ctx?.org?.name && ctx?.org?.name !== "Personal Workspace") {
|
|
565
567
|
lines.push(`This app is owned by the organization "${ctx.org.name}".`);
|
|
566
568
|
}
|
|
567
|
-
if (auth
|
|
569
|
+
if (auth?.delegatedAvailable) {
|
|
568
570
|
lines.push(
|
|
569
571
|
'"Sign in with Remy" (platform-delegated sign-in) is an available auth type for this app: organization members can sign in without a verification code.'
|
|
570
572
|
);
|
|
571
573
|
}
|
|
572
|
-
if (auth
|
|
574
|
+
if (auth?.requireDelegatedOnly) {
|
|
573
575
|
lines.push(
|
|
574
576
|
"This organization requires delegated sign-in: non-delegated human auth methods (email-code, sms-code) are blocked at the platform edge for its apps."
|
|
575
577
|
);
|
|
576
578
|
}
|
|
577
|
-
|
|
579
|
+
if (hasDesignSystem) {
|
|
580
|
+
lines.push(
|
|
581
|
+
"This organization maintains shared brand/design foundations. The design expert has access to these and applies them automatically. You don't need to gather foundational visual style or branding requirements from the user."
|
|
582
|
+
);
|
|
583
|
+
}
|
|
584
|
+
lines.push("</org_context>");
|
|
578
585
|
return lines.join("\n");
|
|
579
586
|
}
|
|
580
587
|
|
|
@@ -1874,11 +1881,11 @@ var setProjectMetadataTool = {
|
|
|
1874
1881
|
},
|
|
1875
1882
|
iconUrl: {
|
|
1876
1883
|
type: "string",
|
|
1877
|
-
description: "URL for the app icon (square."
|
|
1884
|
+
description: "URL for the app icon (square)."
|
|
1878
1885
|
},
|
|
1879
1886
|
openGraphShareImageUrl: {
|
|
1880
1887
|
type: "string",
|
|
1881
|
-
description: "URL for the Open Graph share image (
|
|
1888
|
+
description: "URL for the Open Graph share image (1200\xD7630 PNG)."
|
|
1882
1889
|
}
|
|
1883
1890
|
}
|
|
1884
1891
|
}
|
|
@@ -2812,9 +2819,7 @@ async function analyzeImage(params) {
|
|
|
2812
2819
|
|
|
2813
2820
|
// src/tools/_helpers/screenshot.ts
|
|
2814
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).`;
|
|
2815
|
-
var
|
|
2816
|
-
|
|
2817
|
-
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.`;
|
|
2818
2823
|
function buildScreenshotAnalysisPrompt(opts) {
|
|
2819
2824
|
let p = opts?.prompt || SCREENSHOT_ANALYSIS_PROMPT;
|
|
2820
2825
|
if (opts?.styleMap) {
|
|
@@ -2828,7 +2833,7 @@ ${opts.styleMap}
|
|
|
2828
2833
|
}
|
|
2829
2834
|
p += `
|
|
2830
2835
|
|
|
2831
|
-
${
|
|
2836
|
+
${ANALYSIS_RESPONSE_FORMAT}`;
|
|
2832
2837
|
return p;
|
|
2833
2838
|
}
|
|
2834
2839
|
async function streamScreenshotAnalysis(opts) {
|
|
@@ -2854,6 +2859,9 @@ async function captureAndAnalyzeScreenshot(promptOrOptions) {
|
|
|
2854
2859
|
let model;
|
|
2855
2860
|
let path13;
|
|
2856
2861
|
let fullPage = true;
|
|
2862
|
+
let width;
|
|
2863
|
+
let height;
|
|
2864
|
+
let format;
|
|
2857
2865
|
if (typeof promptOrOptions === "object" && promptOrOptions !== null) {
|
|
2858
2866
|
prompt = promptOrOptions.prompt;
|
|
2859
2867
|
existingUrl = promptOrOptions.imageUrl;
|
|
@@ -2861,11 +2869,17 @@ async function captureAndAnalyzeScreenshot(promptOrOptions) {
|
|
|
2861
2869
|
if (promptOrOptions.fullPage !== void 0) {
|
|
2862
2870
|
fullPage = promptOrOptions.fullPage;
|
|
2863
2871
|
}
|
|
2872
|
+
width = promptOrOptions.width;
|
|
2873
|
+
height = promptOrOptions.height;
|
|
2874
|
+
format = promptOrOptions.format;
|
|
2864
2875
|
onLog = promptOrOptions.onLog;
|
|
2865
2876
|
model = promptOrOptions.model;
|
|
2866
2877
|
} else {
|
|
2867
2878
|
prompt = promptOrOptions;
|
|
2868
2879
|
}
|
|
2880
|
+
if (width != null && height != null) {
|
|
2881
|
+
fullPage = false;
|
|
2882
|
+
}
|
|
2869
2883
|
let url;
|
|
2870
2884
|
let styleMap;
|
|
2871
2885
|
if (existingUrl) {
|
|
@@ -2873,7 +2887,12 @@ async function captureAndAnalyzeScreenshot(promptOrOptions) {
|
|
|
2873
2887
|
} else {
|
|
2874
2888
|
const ssResult = await sidecarRequest(
|
|
2875
2889
|
fullPage ? "/screenshot-full-page" : "/screenshot-viewport",
|
|
2876
|
-
|
|
2890
|
+
{
|
|
2891
|
+
...path13 ? { path: path13 } : {},
|
|
2892
|
+
...width != null ? { width } : {},
|
|
2893
|
+
...height != null ? { height } : {},
|
|
2894
|
+
...format ? { format } : {}
|
|
2895
|
+
},
|
|
2877
2896
|
{ timeout: fullPage ? 12e4 : 3e4 }
|
|
2878
2897
|
);
|
|
2879
2898
|
url = ssResult?.url || ssResult?.screenshotUrl;
|
|
@@ -4002,7 +4021,7 @@ var screenshotTool = {
|
|
|
4002
4021
|
clearable: true,
|
|
4003
4022
|
definition: {
|
|
4004
4023
|
name: "screenshot",
|
|
4005
|
-
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.",
|
|
4006
4025
|
inputSchema: {
|
|
4007
4026
|
type: "object",
|
|
4008
4027
|
properties: {
|
|
@@ -4022,6 +4041,19 @@ var screenshotTool = {
|
|
|
4022
4041
|
type: "string",
|
|
4023
4042
|
description: 'Navigate to this path before capturing (e.g. "/settings", "/dashboard"). If omitted, screenshots the current page.'
|
|
4024
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
|
+
},
|
|
4025
4057
|
instructions: {
|
|
4026
4058
|
type: "string",
|
|
4027
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."
|
|
@@ -4064,6 +4096,9 @@ var screenshotTool = {
|
|
|
4064
4096
|
prompt: input.prompt,
|
|
4065
4097
|
path: input.path,
|
|
4066
4098
|
fullPage,
|
|
4099
|
+
width: input.width,
|
|
4100
|
+
height: input.height,
|
|
4101
|
+
format: input.format,
|
|
4067
4102
|
onLog: context?.onLog,
|
|
4068
4103
|
model: resolveModel("imageAnalysis", context?.models, context?.model)
|
|
4069
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 (
|
|
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
|
-
${
|
|
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
|
-
|
|
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,
|
|
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
|
-
|
|
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
|
});
|
|
@@ -5718,24 +5746,31 @@ function getOrgContext() {
|
|
|
5718
5746
|
function renderOrgContextBlock() {
|
|
5719
5747
|
const ctx = cached;
|
|
5720
5748
|
const auth = ctx?.auth;
|
|
5721
|
-
|
|
5749
|
+
const hasAuth = !!auth && (auth.delegatedAvailable || !!auth.requireDelegatedOnly);
|
|
5750
|
+
const hasDesignSystem = !!ctx?.designSystem;
|
|
5751
|
+
if (!hasAuth && !hasDesignSystem) {
|
|
5722
5752
|
return "";
|
|
5723
5753
|
}
|
|
5724
|
-
const lines = ["<
|
|
5754
|
+
const lines = ["<org_context>"];
|
|
5725
5755
|
if (ctx?.org?.name && ctx?.org?.name !== "Personal Workspace") {
|
|
5726
5756
|
lines.push(`This app is owned by the organization "${ctx.org.name}".`);
|
|
5727
5757
|
}
|
|
5728
|
-
if (auth
|
|
5758
|
+
if (auth?.delegatedAvailable) {
|
|
5729
5759
|
lines.push(
|
|
5730
5760
|
'"Sign in with Remy" (platform-delegated sign-in) is an available auth type for this app: organization members can sign in without a verification code.'
|
|
5731
5761
|
);
|
|
5732
5762
|
}
|
|
5733
|
-
if (auth
|
|
5763
|
+
if (auth?.requireDelegatedOnly) {
|
|
5734
5764
|
lines.push(
|
|
5735
5765
|
"This organization requires delegated sign-in: non-delegated human auth methods (email-code, sms-code) are blocked at the platform edge for its apps."
|
|
5736
5766
|
);
|
|
5737
5767
|
}
|
|
5738
|
-
|
|
5768
|
+
if (hasDesignSystem) {
|
|
5769
|
+
lines.push(
|
|
5770
|
+
"This organization maintains shared brand/design foundations. The design expert has access to these and applies them automatically. You don't need to gather foundational visual style or branding requirements from the user."
|
|
5771
|
+
);
|
|
5772
|
+
}
|
|
5773
|
+
lines.push("</org_context>");
|
|
5739
5774
|
return lines.join("\n");
|
|
5740
5775
|
}
|
|
5741
5776
|
var log9, cached;
|
|
@@ -34,7 +34,7 @@ Remy apps can have and manage their own users. Auth is opt-in: configure it in t
|
|
|
34
34
|
- `email-code` — 6-digit code sent via email
|
|
35
35
|
- `sms-code` — 6-digit code sent via SMS
|
|
36
36
|
- `api-key` — programmatic access via `Authorization: Bearer sk_...` header. Resolves to a user with full RBAC.
|
|
37
|
-
- `remy` — platform-delegated sign-in ("Sign in with Remy"). The platform resolves who the user is; roles and verification are platform-managed. Only usable when the app's owning organization has it enabled — the `<
|
|
37
|
+
- `remy` — platform-delegated sign-in ("Sign in with Remy"). The platform resolves who the user is; roles and verification are platform-managed. Only usable when the app's owning organization has it enabled — the `<org_context>` block signals availability. See *Organization-Managed Sign-In* above.
|
|
38
38
|
- **`auth.table.name`** — name of the `defineTable` table that holds user records.
|
|
39
39
|
- **`auth.table.columns`** — maps platform-managed fields to column names in the developer's table.
|
|
40
40
|
- `email` — required if `email-code` is in methods
|
|
@@ -135,12 +135,12 @@ const user = await auth.verifySmsCode(verificationId, '123456');
|
|
|
135
135
|
|
|
136
136
|
## Organization-Managed Sign-In ("Sign in with Remy")
|
|
137
137
|
|
|
138
|
-
Some apps are owned by an organization that centralizes sign-in. When that applies to the current app, the system prompt includes an `<
|
|
138
|
+
Some apps are owned by an organization that centralizes sign-in. When that applies to the current app, the system prompt includes an `<org_context>` block (near the end); for org-managed sign-in it states the organization name and whether delegated sign-in is available. Sign in with Remy is a way to make authentication seamless for internal apps - it should not be used for public-facing applications. The app owner will need to add users to their workspace's team on the Remy platform and those users will need Remy accounts for it to work.
|
|
139
139
|
|
|
140
140
|
- **When it says "Sign in with Remy" is available** — offer delegated sign-in: a **"Continue with {Org}"** button wired to the `remy` method (see *Sign in with Remy (delegated)* below). Use the exact organization name from the block for the label. For an org-owned app this is usually the primary sign-in — the members already have platform identities, so a verification-code form is redundant.
|
|
141
141
|
- **When it says the organization requires delegated sign-in** — `remy` is the *only* human method: do not add `email-code` or `sms-code`. Those are blocked at the platform edge for the org's apps, so building them yields a login that can't work.
|
|
142
142
|
|
|
143
|
-
When
|
|
143
|
+
When the `<org_context>` block is absent, or present without a delegated-sign-in line — the common case — do not build it or offer to build it. This is an auth scheme for enterprises building internal apps only, and it requires a Remy enterprise plan to use. When enabled, the platform decides who the user is (like "Sign in with Google"); the app just starts the flow and reads the result.
|
|
144
144
|
|
|
145
145
|
```typescript
|
|
146
146
|
// "Continue with {Org}" button — must be triggered by a user gesture (click).
|
|
@@ -399,7 +399,7 @@ Consult the `visualDesignExpert` to help you work through authentication at a hi
|
|
|
399
399
|
### Rules for Building Auth Screens
|
|
400
400
|
**Auth modes:** Think about which mode(s) makes the most sense for the type of app you are building. Consumer apps likely to be used on mobile should probably tend toward SMS auth as the default - business apps used on desktop make more sense to use email verification - or allow both, there's no harm in giving the user choice!
|
|
401
401
|
|
|
402
|
-
**"Continue with {Org}" (delegated):** When `<
|
|
402
|
+
**"Continue with {Org}" (delegated):** When the `<org_context>` block says delegated sign-in is available, a single "Continue with {Org}" button is the primary path — often the *only* one — and there's no verification-code step to design at all (the platform handles it). Give the button real weight in the branded login moment rather than treating it as a secondary option, and use the exact organization name. If the org also allows code methods, delegated goes first with the code form beneath. On return from the handshake (and on dashboard launch), render a brief "Completing sign-in…" state driven by `auth.authStatus === 'authenticating'` — never the login form — so a successful sign-in doesn't flash the logged-out screen.
|
|
403
403
|
|
|
404
404
|
**Verification code input:** The 6-digit code entry is the critical moment. Prefer to design it as individual digit boxes (not a single text input), with auto-advance between digits, a beautiful animation and auto-submit on paste, and clear visual feedback. The boxes should be large enough to tap easily on mobile. Show a subtle animation on successful verification. Error states should be inline and immediate, not a separate alert. Make sure there is no layout shift when loading in the success/error states - loading spinners must never pop in below the input and shift the content, for example.
|
|
405
405
|
|
|
@@ -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
|
|
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.
|
|
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
|
|
|
@@ -20,7 +20,7 @@ Login and signup screens set the tone for the user's entire experience with the
|
|
|
20
20
|
|
|
21
21
|
Authentication moments must feel natural and intuitive - they should not feel jarring or surprising. Take care to integrate them into the entire experience when building. Remy apps support SMS code verification, email verification, delegated "Sign in with Remy", or a combination, depending on how the app is configured.
|
|
22
22
|
|
|
23
|
-
**"Continue with {Org}" (delegated sign-in):** Some apps are internal business tools that are owned by an organization and sign members in through the platform — a single "Continue with {Org}" button, no verification-code step at all. For these apps this button is often the primary (sometimes only) path, so give it real presence in the branded login moment rather than tucking it away, and label it with the organization's actual name. If the app also offers code methods, lead with the delegated button and place the code form beneath. This scheme should ONLY be used for internal apps AND when it is explicitly enabled in <
|
|
23
|
+
**"Continue with {Org}" (delegated sign-in):** Some apps are internal business tools that are owned by an organization and sign members in through the platform — a single "Continue with {Org}" button, no verification-code step at all. For these apps this button is often the primary (sometimes only) path, so give it real presence in the branded login moment rather than tucking it away, and label it with the organization's actual name. If the app also offers code methods, lead with the delegated button and place the code form beneath. This scheme should ONLY be used for internal apps AND when it is explicitly enabled in <org_context> - it should not be used for public-facing apps.
|
|
24
24
|
|
|
25
25
|
**Verification code input:** The 6-digit code entry is the critical moment. Prefer to design it as individual digit boxes (not a single text input), with auto-advance between digits, auto-submit on paste, and clear visual feedback. The boxes should be large enough to tap easily on mobile. Show a subtle animation on successful verification. Error states should be inline and immediate, not a separate alert.
|
|
26
26
|
|
|
@@ -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.
|