@mindstudio-ai/remy 0.1.44 → 0.1.46
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 +39 -8
- package/dist/index.js +40 -9
- package/dist/prompt/compiled/design.md +1 -0
- package/dist/prompt/compiled/interfaces.md +15 -3
- package/dist/prompt/static/coding.md +8 -5
- package/dist/prompt/static/team.md +2 -2
- package/dist/subagents/codeSanityCheck/prompt.md +1 -0
- package/dist/subagents/designExpert/prompts/instructions.md +5 -1
- package/dist/subagents/designExpert/prompts/ui-patterns.md +5 -0
- package/package.json +1 -1
package/dist/headless.js
CHANGED
|
@@ -429,11 +429,10 @@ async function* streamChat(params) {
|
|
|
429
429
|
const { baseUrl: baseUrl2, apiKey, signal, requestId, ...body } = params;
|
|
430
430
|
const url = `${baseUrl2}/_internal/v2/agent/remy/chat`;
|
|
431
431
|
const startTime = Date.now();
|
|
432
|
-
const
|
|
433
|
-
(m) => m.attachments && m.attachments.length > 0
|
|
434
|
-
);
|
|
432
|
+
const subAgentId = body.subAgentId;
|
|
435
433
|
log3.info("API request", {
|
|
436
434
|
requestId,
|
|
435
|
+
...subAgentId && { subAgentId },
|
|
437
436
|
model: body.model,
|
|
438
437
|
messageCount: body.messages.length,
|
|
439
438
|
toolCount: body.tools.length
|
|
@@ -451,15 +450,27 @@ async function* streamChat(params) {
|
|
|
451
450
|
});
|
|
452
451
|
} catch (err) {
|
|
453
452
|
if (signal?.aborted) {
|
|
454
|
-
log3.warn("Request aborted", {
|
|
453
|
+
log3.warn("Request aborted", {
|
|
454
|
+
requestId,
|
|
455
|
+
...subAgentId && { subAgentId }
|
|
456
|
+
});
|
|
455
457
|
throw err;
|
|
456
458
|
}
|
|
457
|
-
log3.error("Network error", {
|
|
459
|
+
log3.error("Network error", {
|
|
460
|
+
requestId,
|
|
461
|
+
...subAgentId && { subAgentId },
|
|
462
|
+
error: err.message
|
|
463
|
+
});
|
|
458
464
|
yield { type: "error", error: `Network error: ${err.message}` };
|
|
459
465
|
return;
|
|
460
466
|
}
|
|
461
467
|
const ttfb = Date.now() - startTime;
|
|
462
|
-
log3.info("API response", {
|
|
468
|
+
log3.info("API response", {
|
|
469
|
+
requestId,
|
|
470
|
+
...subAgentId && { subAgentId },
|
|
471
|
+
status: res.status,
|
|
472
|
+
ttfbMs: ttfb
|
|
473
|
+
});
|
|
463
474
|
if (!res.ok) {
|
|
464
475
|
let errorMessage = `HTTP ${res.status}`;
|
|
465
476
|
try {
|
|
@@ -474,6 +485,7 @@ async function* streamChat(params) {
|
|
|
474
485
|
}
|
|
475
486
|
log3.error("API error", {
|
|
476
487
|
requestId,
|
|
488
|
+
...subAgentId && { subAgentId },
|
|
477
489
|
status: res.status,
|
|
478
490
|
error: errorMessage
|
|
479
491
|
});
|
|
@@ -503,6 +515,7 @@ async function* streamChat(params) {
|
|
|
503
515
|
await reader.cancel();
|
|
504
516
|
log3.error("Stream stalled", {
|
|
505
517
|
requestId,
|
|
518
|
+
...subAgentId && { subAgentId },
|
|
506
519
|
durationMs: Date.now() - startTime
|
|
507
520
|
});
|
|
508
521
|
yield {
|
|
@@ -528,6 +541,7 @@ async function* streamChat(params) {
|
|
|
528
541
|
const elapsed = Date.now() - startTime;
|
|
529
542
|
log3.info("Stream complete", {
|
|
530
543
|
requestId,
|
|
544
|
+
...subAgentId && { subAgentId },
|
|
531
545
|
durationMs: elapsed,
|
|
532
546
|
stopReason: event.stopReason,
|
|
533
547
|
inputTokens: event.usage.inputTokens,
|
|
@@ -2143,7 +2157,10 @@ var runMethodTool = {
|
|
|
2143
2157
|
|
|
2144
2158
|
// src/subagents/common/analyzeImage.ts
|
|
2145
2159
|
var VISION_MODEL = "gemini-3-flash";
|
|
2146
|
-
var VISION_MODEL_OVERRIDE = JSON.stringify({
|
|
2160
|
+
var VISION_MODEL_OVERRIDE = JSON.stringify({
|
|
2161
|
+
model: VISION_MODEL,
|
|
2162
|
+
config: { thinkingBudget: "off" }
|
|
2163
|
+
});
|
|
2147
2164
|
async function analyzeImage(params) {
|
|
2148
2165
|
const { prompt, imageUrl, timeout = 2e5, onLog } = params;
|
|
2149
2166
|
return runCli(
|
|
@@ -2540,9 +2557,18 @@ Current date/time: ${(/* @__PURE__ */ new Date()).toISOString().replace("T", " "
|
|
|
2540
2557
|
}
|
|
2541
2558
|
};
|
|
2542
2559
|
toolRegistry?.register(entry);
|
|
2560
|
+
const toolStart = Date.now();
|
|
2543
2561
|
run2(tc.input);
|
|
2544
2562
|
const r = await resultPromise;
|
|
2545
2563
|
toolRegistry?.unregister(tc.id);
|
|
2564
|
+
log4.info("Tool completed", {
|
|
2565
|
+
requestId,
|
|
2566
|
+
parentToolId,
|
|
2567
|
+
toolCallId: tc.id,
|
|
2568
|
+
name: tc.name,
|
|
2569
|
+
durationMs: Date.now() - toolStart,
|
|
2570
|
+
isError: r.isError
|
|
2571
|
+
});
|
|
2546
2572
|
emit2({
|
|
2547
2573
|
type: "tool_done",
|
|
2548
2574
|
id: tc.id,
|
|
@@ -3057,6 +3083,11 @@ __export(generateImages_exports, {
|
|
|
3057
3083
|
});
|
|
3058
3084
|
|
|
3059
3085
|
// src/subagents/designExpert/tools/images/enhancePrompt.ts
|
|
3086
|
+
var ENHANCE_MODEL = "gemini-3-flash";
|
|
3087
|
+
var MODEL_OVERRIDE = JSON.stringify({
|
|
3088
|
+
model: ENHANCE_MODEL,
|
|
3089
|
+
config: { thinkingBudget: "off" }
|
|
3090
|
+
});
|
|
3060
3091
|
var SYSTEM_PROMPT = readAsset(
|
|
3061
3092
|
"subagents/designExpert/tools/images/enhance-image-prompt.md"
|
|
3062
3093
|
);
|
|
@@ -3081,7 +3112,7 @@ ${context}
|
|
|
3081
3112
|
${brief}
|
|
3082
3113
|
</brief>`;
|
|
3083
3114
|
const enhanced = await runCli(
|
|
3084
|
-
`mindstudio generate-text --message ${JSON.stringify(message)} --output-key content --no-meta`,
|
|
3115
|
+
`mindstudio generate-text --message ${JSON.stringify(message)} --model-override ${JSON.stringify(MODEL_OVERRIDE)} --output-key content --no-meta`,
|
|
3085
3116
|
{ timeout: 6e4, onLog }
|
|
3086
3117
|
);
|
|
3087
3118
|
return enhanced.trim();
|
package/dist/index.js
CHANGED
|
@@ -89,11 +89,10 @@ async function* streamChat(params) {
|
|
|
89
89
|
const { baseUrl: baseUrl2, apiKey, signal, requestId, ...body } = params;
|
|
90
90
|
const url = `${baseUrl2}/_internal/v2/agent/remy/chat`;
|
|
91
91
|
const startTime = Date.now();
|
|
92
|
-
const
|
|
93
|
-
(m) => m.attachments && m.attachments.length > 0
|
|
94
|
-
);
|
|
92
|
+
const subAgentId = body.subAgentId;
|
|
95
93
|
log.info("API request", {
|
|
96
94
|
requestId,
|
|
95
|
+
...subAgentId && { subAgentId },
|
|
97
96
|
model: body.model,
|
|
98
97
|
messageCount: body.messages.length,
|
|
99
98
|
toolCount: body.tools.length
|
|
@@ -111,15 +110,27 @@ async function* streamChat(params) {
|
|
|
111
110
|
});
|
|
112
111
|
} catch (err) {
|
|
113
112
|
if (signal?.aborted) {
|
|
114
|
-
log.warn("Request aborted", {
|
|
113
|
+
log.warn("Request aborted", {
|
|
114
|
+
requestId,
|
|
115
|
+
...subAgentId && { subAgentId }
|
|
116
|
+
});
|
|
115
117
|
throw err;
|
|
116
118
|
}
|
|
117
|
-
log.error("Network error", {
|
|
119
|
+
log.error("Network error", {
|
|
120
|
+
requestId,
|
|
121
|
+
...subAgentId && { subAgentId },
|
|
122
|
+
error: err.message
|
|
123
|
+
});
|
|
118
124
|
yield { type: "error", error: `Network error: ${err.message}` };
|
|
119
125
|
return;
|
|
120
126
|
}
|
|
121
127
|
const ttfb = Date.now() - startTime;
|
|
122
|
-
log.info("API response", {
|
|
128
|
+
log.info("API response", {
|
|
129
|
+
requestId,
|
|
130
|
+
...subAgentId && { subAgentId },
|
|
131
|
+
status: res.status,
|
|
132
|
+
ttfbMs: ttfb
|
|
133
|
+
});
|
|
123
134
|
if (!res.ok) {
|
|
124
135
|
let errorMessage = `HTTP ${res.status}`;
|
|
125
136
|
try {
|
|
@@ -134,6 +145,7 @@ async function* streamChat(params) {
|
|
|
134
145
|
}
|
|
135
146
|
log.error("API error", {
|
|
136
147
|
requestId,
|
|
148
|
+
...subAgentId && { subAgentId },
|
|
137
149
|
status: res.status,
|
|
138
150
|
error: errorMessage
|
|
139
151
|
});
|
|
@@ -163,6 +175,7 @@ async function* streamChat(params) {
|
|
|
163
175
|
await reader.cancel();
|
|
164
176
|
log.error("Stream stalled", {
|
|
165
177
|
requestId,
|
|
178
|
+
...subAgentId && { subAgentId },
|
|
166
179
|
durationMs: Date.now() - startTime
|
|
167
180
|
});
|
|
168
181
|
yield {
|
|
@@ -188,6 +201,7 @@ async function* streamChat(params) {
|
|
|
188
201
|
const elapsed = Date.now() - startTime;
|
|
189
202
|
log.info("Stream complete", {
|
|
190
203
|
requestId,
|
|
204
|
+
...subAgentId && { subAgentId },
|
|
191
205
|
durationMs: elapsed,
|
|
192
206
|
stopReason: event.stopReason,
|
|
193
207
|
inputTokens: event.usage.inputTokens,
|
|
@@ -2071,7 +2085,10 @@ var init_analyzeImage = __esm({
|
|
|
2071
2085
|
"use strict";
|
|
2072
2086
|
init_runCli();
|
|
2073
2087
|
VISION_MODEL = "gemini-3-flash";
|
|
2074
|
-
VISION_MODEL_OVERRIDE = JSON.stringify({
|
|
2088
|
+
VISION_MODEL_OVERRIDE = JSON.stringify({
|
|
2089
|
+
model: VISION_MODEL,
|
|
2090
|
+
config: { thinkingBudget: "off" }
|
|
2091
|
+
});
|
|
2075
2092
|
}
|
|
2076
2093
|
});
|
|
2077
2094
|
|
|
@@ -2487,9 +2504,18 @@ Current date/time: ${(/* @__PURE__ */ new Date()).toISOString().replace("T", " "
|
|
|
2487
2504
|
}
|
|
2488
2505
|
};
|
|
2489
2506
|
toolRegistry?.register(entry);
|
|
2507
|
+
const toolStart = Date.now();
|
|
2490
2508
|
run2(tc.input);
|
|
2491
2509
|
const r = await resultPromise;
|
|
2492
2510
|
toolRegistry?.unregister(tc.id);
|
|
2511
|
+
log3.info("Tool completed", {
|
|
2512
|
+
requestId,
|
|
2513
|
+
parentToolId,
|
|
2514
|
+
toolCallId: tc.id,
|
|
2515
|
+
name: tc.name,
|
|
2516
|
+
durationMs: Date.now() - toolStart,
|
|
2517
|
+
isError: r.isError
|
|
2518
|
+
});
|
|
2493
2519
|
emit2({
|
|
2494
2520
|
type: "tool_done",
|
|
2495
2521
|
id: tc.id,
|
|
@@ -3134,17 +3160,22 @@ ${context}
|
|
|
3134
3160
|
${brief}
|
|
3135
3161
|
</brief>`;
|
|
3136
3162
|
const enhanced = await runCli(
|
|
3137
|
-
`mindstudio generate-text --message ${JSON.stringify(message)} --output-key content --no-meta`,
|
|
3163
|
+
`mindstudio generate-text --message ${JSON.stringify(message)} --model-override ${JSON.stringify(MODEL_OVERRIDE)} --output-key content --no-meta`,
|
|
3138
3164
|
{ timeout: 6e4, onLog }
|
|
3139
3165
|
);
|
|
3140
3166
|
return enhanced.trim();
|
|
3141
3167
|
}
|
|
3142
|
-
var SYSTEM_PROMPT;
|
|
3168
|
+
var ENHANCE_MODEL, MODEL_OVERRIDE, SYSTEM_PROMPT;
|
|
3143
3169
|
var init_enhancePrompt = __esm({
|
|
3144
3170
|
"src/subagents/designExpert/tools/images/enhancePrompt.ts"() {
|
|
3145
3171
|
"use strict";
|
|
3146
3172
|
init_runCli();
|
|
3147
3173
|
init_assets();
|
|
3174
|
+
ENHANCE_MODEL = "gemini-3-flash";
|
|
3175
|
+
MODEL_OVERRIDE = JSON.stringify({
|
|
3176
|
+
model: ENHANCE_MODEL,
|
|
3177
|
+
config: { thinkingBudget: "off" }
|
|
3178
|
+
});
|
|
3148
3179
|
SYSTEM_PROMPT = readAsset(
|
|
3149
3180
|
"subagents/designExpert/tools/images/enhance-image-prompt.md"
|
|
3150
3181
|
);
|
|
@@ -55,6 +55,7 @@ Forms should feel like interactions, not paperwork.
|
|
|
55
55
|
- Inline validation — show errors as the user types, not after submit. Validation must never introduce layout shift.
|
|
56
56
|
- Loading states after submission. Always indicate that something is happening.
|
|
57
57
|
- Disabled states should be visually distinct but not jarring.
|
|
58
|
+
- Media uploads should optimistically load in a local preview of an image or video and show upload progress
|
|
58
59
|
- Even data entry can be beautiful. Pay attention to alignment, padding, and spacing. Consistency is key.
|
|
59
60
|
|
|
60
61
|
#### Form Elements
|
|
@@ -54,9 +54,21 @@ const api = createClient<{
|
|
|
54
54
|
const { vendorId } = await api.submitVendorRequest({ name: 'Acme' });
|
|
55
55
|
const { vendors } = await api.listVendors();
|
|
56
56
|
|
|
57
|
-
// File
|
|
58
|
-
const
|
|
59
|
-
|
|
57
|
+
// File upload (returns CDN URL)
|
|
58
|
+
const url = await platform.uploadFile(file);
|
|
59
|
+
|
|
60
|
+
// With progress tracking
|
|
61
|
+
const url = await platform.uploadFile(file, {
|
|
62
|
+
onProgress: (fraction) => setProgress(fraction), // 0 to 1
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
// With abort support
|
|
66
|
+
const controller = new AbortController();
|
|
67
|
+
const url = await platform.uploadFile(file, {
|
|
68
|
+
signal: controller.signal,
|
|
69
|
+
onProgress: (f) => setProgress(f),
|
|
70
|
+
});
|
|
71
|
+
controller.abort(); // cancels the upload
|
|
60
72
|
|
|
61
73
|
// Current user (display only)
|
|
62
74
|
auth.userId;
|
|
@@ -16,11 +16,14 @@ After editing code, check your work with `lspDiagnostics` or by reading the file
|
|
|
16
16
|
Aim for confidence that the core happy paths work. If the 80% case is solid, the remaining edge cases are likely fine and the user can surface them in chat. Don't screenshot every page, test every permutation, or verify every secondary flow. One or two runtime checks that confirm the app loads and data flows through is enough.
|
|
17
17
|
|
|
18
18
|
### Process Logs
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
- `.logs/
|
|
22
|
-
- `.logs/
|
|
23
|
-
- `.logs/
|
|
19
|
+
|
|
20
|
+
Process logs are available at .logs/ in NDJSON format (one JSON object per line) for debugging. Each line has at minimum ts (unix millis) and msg fields, plus structured context like level, module, requestId, toolCallId where available. You can use `jq` to examine logs and debug failures. Tools like run method or run scenario execute synchronously, so log data will be available by the time those tools return their results to you, there is no need to `sleep` before querying logfiles.
|
|
21
|
+
- `.logs/tunnel.ndjson`: method execution, schema sync, session lifecycle, platform connection
|
|
22
|
+
- `.logs/devServer.ndjson`: frontend build errors, HMR, module resolution failures
|
|
23
|
+
- `.logs/system.ndjson`: sandbox server logs — agent lifecycle, tool dispatch, file watching, process management
|
|
24
|
+
- `.logs/agent.ndjson`: coding agent protocol events and errors
|
|
25
|
+
- `.logs/requests.ndjson`: structured log of every method and scenario execution with full input, output, errors (including stack traces), console output, and duration
|
|
26
|
+
- `.logs/browser.ndjson`: browser-side events from the web preview — console output, uncaught JS errors with stack traces, failed network requests, user interactions
|
|
24
27
|
|
|
25
28
|
### MindStudio SDK
|
|
26
29
|
For any work involving AI models, external actions (web scraping, email, SMS), or third-party API/OAuth connections, prefer the `@mindstudio-ai/agent` SDK. It removes the need to research API methods, configure keys and tokens, or require the user to set up developer accounts.
|
|
@@ -10,9 +10,9 @@ Note: when you talk about the team to the user, refer to them by their name or a
|
|
|
10
10
|
|
|
11
11
|
Your designer. Consult for any visual decision — choosing a color, picking fonts, proposing a layout, soucing images, reviewing whether something looks good. Not just during intake or big design moments. If you're about to write CSS and you're not sure about a color, ask. If you just built a page and want a gut check, ask the designer to take a quick look. If the user says "I don't like how this looks," ask the design expert what to change rather than guessing yourself, or if they say "I want a different image," that's the designer's problem, not yours. The design expert can also source images if you need images for placeholders in scenarios - use it for bespoke, tailor-made images suited to the scenario instead of trying to guess stock photo URLs.
|
|
12
12
|
|
|
13
|
-
The design expert cannot see your conversation with the user, so include all relevant context and requirements in your task. It also can not see its own conversation history, so if you want an audit you need to provide the exact values to check, or any other necessary context for it to do its job. It can take screenshots of the app preview on its own — just ask it to review what's been built.
|
|
13
|
+
The design expert cannot see your conversation with the user, so include all relevant context and requirements in your task. It also can not see its own conversation history, so if you want an audit you need to provide the exact values to check, or any other necessary context for it to do its job. It can take screenshots of the app preview on its own — 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
|
-
|
|
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, 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.
|
|
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
|
|
|
@@ -22,6 +22,7 @@ These are things we already know about and have decided to accept:
|
|
|
22
22
|
- swr
|
|
23
23
|
- framer-motion
|
|
24
24
|
- styled-components
|
|
25
|
+
- @tabler/icons-react
|
|
25
26
|
- Preferences:
|
|
26
27
|
- use [wouter](https://github.com/molefrog/wouter) for React routing instead of reaching for react-router
|
|
27
28
|
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
## Initial Design
|
|
2
2
|
|
|
3
|
-
Rendering the initial design for a new app is your chance to do amazing work and truly impress the user, because after that it's going to be all refinement and working within constraints. Truly greenfield design work is rare, so don't take these moments for granted.
|
|
3
|
+
Rendering the initial design for a new app is your chance to do amazing work and truly impress the user, because after that it's going to be all refinement and working within constraints. Truly greenfield design work is rare, so don't take these moments for granted.
|
|
4
|
+
|
|
5
|
+
The user has engaged you specifically to elevate their design - they have the seed of an idea and it is your job to help them fully realize its potential. This can be tricky, as sometimes people use design language to describe what they need in a way that *sounds* precise, but in actuality they don't know what they really want and are simply aping language they have heard elsewhere. Your job is to not only listen to their request but to really get to the core of what they *need*, and show them heights they never thought possible. This is what separates good designers from exceptional designers. Be an *exceptional* designer.
|
|
6
|
+
|
|
7
|
+
Be creative and inspired, and spend time thinking about your references. Discuss them aloud during your thinking. What can you draw upon from <visual_design_references> and <ui_case_studies> (e.g., "I think the XYZ pattern from ABC could be really compelling for..."), even if it might be from an unrelated domain or vertical (the best designs often come from surprising places!)? What fonts and colors should form the base of the brand's identity? They're going to appear in other things beyond just this app - marketing materials, swag, etc - so make them compelling.
|
|
4
8
|
|
|
5
9
|
Then, think about the layout and UI patterns - these are the core of the user's interaction with the app and provide the frame and context for every interfaction. Think about individual components, animation, icons, and images.
|
|
6
10
|
|
|
@@ -5,3 +5,8 @@ UI patterns are the core of any good app. Anyone can make a simple form or list
|
|
|
5
5
|
Study the patterns provided in <ui_case_studies> and actually spend time breaking them down, and think about what can be applied to the current project to elevate it into something truly world-class.
|
|
6
6
|
|
|
7
7
|
When descirbing UI patterns to the developer, be verbose and explicit. Describe every aspect - don't leave room for interpretation by the developer because it ain't gonna be pretty.
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
### Dated Patterns to Avoid
|
|
11
|
+
|
|
12
|
+
The design should look like it could be an Apple iOS/macOS app of the year winner for 2026. Avoid long pages, things that feel like blogs, things that borrow from "dated" app store apps, and the like. It should feel like an award winner from the past two years, not an award winner from a decade ago.
|