@mindstudio-ai/remy 0.1.34 → 0.1.35
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 +578 -393
- package/dist/index.js +652 -385
- package/dist/prompt/sources/llms.txt +1618 -0
- package/dist/prompt/static/instructions.md +1 -1
- package/dist/prompt/static/team.md +1 -1
- package/dist/subagents/.notes-background-agents.md +60 -48
- package/dist/subagents/browserAutomation/prompt.md +14 -11
- package/dist/subagents/designExpert/data/sources/dev/index.html +901 -0
- package/dist/subagents/designExpert/data/sources/dev/serve.mjs +244 -0
- package/dist/subagents/designExpert/data/sources/dev/specimens-fonts.html +126 -0
- package/dist/subagents/designExpert/data/sources/dev/specimens-pairings.html +114 -0
- package/dist/subagents/designExpert/data/{fonts.json → sources/fonts.json} +0 -97
- package/dist/subagents/designExpert/data/sources/inspiration.json +392 -0
- package/dist/subagents/designExpert/prompt.md +36 -12
- package/dist/subagents/designExpert/prompts/animation.md +14 -6
- package/dist/subagents/designExpert/prompts/color.md +25 -5
- package/dist/subagents/designExpert/prompts/{icons.md → components.md} +17 -5
- package/dist/subagents/designExpert/prompts/frontend-design-notes.md +17 -122
- package/dist/subagents/designExpert/prompts/identity.md +15 -61
- package/dist/subagents/designExpert/prompts/images.md +35 -10
- package/dist/subagents/designExpert/prompts/layout.md +14 -9
- package/dist/subagents/designExpert/prompts/typography.md +39 -0
- package/package.json +2 -2
- package/dist/actions/buildFromInitialSpec.md +0 -15
- package/dist/actions/publish.md +0 -12
- package/dist/actions/sync.md +0 -19
- package/dist/compiled/README.md +0 -100
- package/dist/compiled/auth.md +0 -77
- package/dist/compiled/design.md +0 -251
- package/dist/compiled/dev-and-deploy.md +0 -69
- package/dist/compiled/interfaces.md +0 -238
- package/dist/compiled/manifest.md +0 -107
- package/dist/compiled/media-cdn.md +0 -51
- package/dist/compiled/methods.md +0 -225
- package/dist/compiled/msfm.md +0 -222
- package/dist/compiled/platform.md +0 -105
- package/dist/compiled/scenarios.md +0 -103
- package/dist/compiled/sdk-actions.md +0 -146
- package/dist/compiled/tables.md +0 -263
- package/dist/static/authoring.md +0 -101
- package/dist/static/coding.md +0 -29
- package/dist/static/identity.md +0 -1
- package/dist/static/instructions.md +0 -31
- package/dist/static/intake.md +0 -44
- package/dist/static/lsp.md +0 -4
- package/dist/static/projectContext.ts +0 -160
- package/dist/static/team.md +0 -39
- package/dist/subagents/designExpert/data/inspiration.json +0 -392
- package/dist/subagents/designExpert/prompts/instructions.md +0 -18
- /package/dist/subagents/designExpert/data/{compile-font-descriptions.sh → sources/compile-font-descriptions.sh} +0 -0
- /package/dist/subagents/designExpert/data/{compile-inspiration.sh → sources/compile-inspiration.sh} +0 -0
- /package/dist/subagents/designExpert/data/{inspiration.raw.json → sources/inspiration.raw.json} +0 -0
- /package/dist/subagents/designExpert/{prompts/tool-prompts → data/sources/prompts}/design-analysis.md +0 -0
- /package/dist/subagents/designExpert/{prompts/tool-prompts → data/sources/prompts}/font-analysis.md +0 -0
package/dist/index.js
CHANGED
|
@@ -1057,7 +1057,12 @@ function runCli(cmd, options) {
|
|
|
1057
1057
|
const entry = JSON.parse(trimmed);
|
|
1058
1058
|
if (entry.type === "log" && entry.value) {
|
|
1059
1059
|
const prefix = entry.tag ? `[${entry.tag}]` : "[log]";
|
|
1060
|
-
|
|
1060
|
+
const formatted = `${prefix} ${entry.value}`;
|
|
1061
|
+
if (options?.onLog) {
|
|
1062
|
+
options.onLog(formatted);
|
|
1063
|
+
} else {
|
|
1064
|
+
logs.push(formatted);
|
|
1065
|
+
}
|
|
1061
1066
|
}
|
|
1062
1067
|
} catch {
|
|
1063
1068
|
}
|
|
@@ -1069,7 +1074,7 @@ function runCli(cmd, options) {
|
|
|
1069
1074
|
}, timeout);
|
|
1070
1075
|
child.on("close", (code) => {
|
|
1071
1076
|
clearTimeout(timer);
|
|
1072
|
-
const logBlock = logs.length > 0 ? logs.join("\n") + "\n\n" : "";
|
|
1077
|
+
const logBlock = !options?.onLog && logs.length > 0 ? logs.join("\n") + "\n\n" : "";
|
|
1073
1078
|
const out = stdout.trim();
|
|
1074
1079
|
if (out) {
|
|
1075
1080
|
resolve(logBlock + out);
|
|
@@ -1111,11 +1116,12 @@ var init_sdkConsultant = __esm({
|
|
|
1111
1116
|
required: ["query"]
|
|
1112
1117
|
}
|
|
1113
1118
|
},
|
|
1114
|
-
async execute(input) {
|
|
1119
|
+
async execute(input, context) {
|
|
1115
1120
|
const query = input.query;
|
|
1116
1121
|
return runCli(`mindstudio ask ${JSON.stringify(query)}`, {
|
|
1117
1122
|
timeout: 2e5,
|
|
1118
|
-
maxBuffer: 512 * 1024
|
|
1123
|
+
maxBuffer: 512 * 1024,
|
|
1124
|
+
onLog: context?.onLog
|
|
1119
1125
|
});
|
|
1120
1126
|
}
|
|
1121
1127
|
};
|
|
@@ -1147,7 +1153,7 @@ var init_fetchUrl = __esm({
|
|
|
1147
1153
|
required: ["url"]
|
|
1148
1154
|
}
|
|
1149
1155
|
},
|
|
1150
|
-
async execute(input) {
|
|
1156
|
+
async execute(input, context) {
|
|
1151
1157
|
const url = input.url;
|
|
1152
1158
|
const screenshot = input.screenshot;
|
|
1153
1159
|
const pageOptions = { onlyMainContent: true };
|
|
@@ -1155,7 +1161,8 @@ var init_fetchUrl = __esm({
|
|
|
1155
1161
|
pageOptions.screenshot = true;
|
|
1156
1162
|
}
|
|
1157
1163
|
return runCli(
|
|
1158
|
-
`mindstudio scrape-url --url ${JSON.stringify(url)} --page-options ${JSON.stringify(JSON.stringify(pageOptions))} --no-meta
|
|
1164
|
+
`mindstudio scrape-url --url ${JSON.stringify(url)} --page-options ${JSON.stringify(JSON.stringify(pageOptions))} --no-meta`,
|
|
1165
|
+
{ onLog: context?.onLog }
|
|
1159
1166
|
);
|
|
1160
1167
|
}
|
|
1161
1168
|
};
|
|
@@ -1183,11 +1190,11 @@ var init_searchGoogle = __esm({
|
|
|
1183
1190
|
required: ["query"]
|
|
1184
1191
|
}
|
|
1185
1192
|
},
|
|
1186
|
-
async execute(input) {
|
|
1193
|
+
async execute(input, context) {
|
|
1187
1194
|
const query = input.query;
|
|
1188
1195
|
return runCli(
|
|
1189
1196
|
`mindstudio search-google --query ${JSON.stringify(query)} --export-type json --output-key results --no-meta`,
|
|
1190
|
-
{ maxBuffer: 512 * 1024 }
|
|
1197
|
+
{ maxBuffer: 512 * 1024, onLog: context?.onLog }
|
|
1191
1198
|
);
|
|
1192
1199
|
}
|
|
1193
1200
|
};
|
|
@@ -1224,9 +1231,9 @@ var init_setProjectName = __esm({
|
|
|
1224
1231
|
// src/tools/code/readFile.ts
|
|
1225
1232
|
import fs6 from "fs/promises";
|
|
1226
1233
|
function isBinary(buffer) {
|
|
1227
|
-
const
|
|
1228
|
-
for (let i = 0; i <
|
|
1229
|
-
if (
|
|
1234
|
+
const sample3 = buffer.subarray(0, 8192);
|
|
1235
|
+
for (let i = 0; i < sample3.length; i++) {
|
|
1236
|
+
if (sample3[i] === 0) {
|
|
1230
1237
|
return true;
|
|
1231
1238
|
}
|
|
1232
1239
|
}
|
|
@@ -2018,18 +2025,16 @@ var init_runMethod = __esm({
|
|
|
2018
2025
|
// src/tools/_helpers/screenshot.ts
|
|
2019
2026
|
async function captureAndAnalyzeScreenshot(promptOrOptions) {
|
|
2020
2027
|
let prompt;
|
|
2021
|
-
let
|
|
2028
|
+
let onLog;
|
|
2022
2029
|
if (typeof promptOrOptions === "object" && promptOrOptions !== null) {
|
|
2023
2030
|
prompt = promptOrOptions.prompt;
|
|
2024
|
-
|
|
2031
|
+
onLog = promptOrOptions.onLog;
|
|
2025
2032
|
} else {
|
|
2026
2033
|
prompt = promptOrOptions;
|
|
2027
2034
|
}
|
|
2028
|
-
const ssResult = await sidecarRequest(
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
{ timeout: 12e4 }
|
|
2032
|
-
);
|
|
2035
|
+
const ssResult = await sidecarRequest("/screenshot-full-page", void 0, {
|
|
2036
|
+
timeout: 12e4
|
|
2037
|
+
});
|
|
2033
2038
|
log.debug("Screenshot response", { ssResult });
|
|
2034
2039
|
const url = ssResult?.url || ssResult?.screenshotUrl;
|
|
2035
2040
|
if (!url) {
|
|
@@ -2043,7 +2048,7 @@ async function captureAndAnalyzeScreenshot(promptOrOptions) {
|
|
|
2043
2048
|
const analysisPrompt = prompt || SCREENSHOT_ANALYSIS_PROMPT;
|
|
2044
2049
|
const analysis = await runCli(
|
|
2045
2050
|
`mindstudio analyze-image --prompt ${JSON.stringify(analysisPrompt)} --image-url ${JSON.stringify(url)} --output-key analysis --no-meta`,
|
|
2046
|
-
{ timeout: 2e5 }
|
|
2051
|
+
{ timeout: 2e5, onLog }
|
|
2047
2052
|
);
|
|
2048
2053
|
return JSON.stringify({ url, analysis });
|
|
2049
2054
|
}
|
|
@@ -2067,26 +2072,22 @@ var init_screenshot2 = __esm({
|
|
|
2067
2072
|
screenshotTool = {
|
|
2068
2073
|
definition: {
|
|
2069
2074
|
name: "screenshot",
|
|
2070
|
-
description: "Capture a screenshot of the app preview and get a description of what's on screen. Optionally provide a specific question about what you're looking for
|
|
2075
|
+
description: "Capture a full-height screenshot of the app preview and get a description of what's on screen. Optionally provide a specific question about what you're looking for..",
|
|
2071
2076
|
inputSchema: {
|
|
2072
2077
|
type: "object",
|
|
2073
2078
|
properties: {
|
|
2074
2079
|
prompt: {
|
|
2075
2080
|
type: "string",
|
|
2076
2081
|
description: "Optional question about the screenshot. If omitted, returns a general description of what's visible."
|
|
2077
|
-
},
|
|
2078
|
-
fullPage: {
|
|
2079
|
-
type: "boolean",
|
|
2080
|
-
description: "Capture the full scrollable page instead of just the viewport. Use when you need to see below-the-fold content."
|
|
2081
2082
|
}
|
|
2082
2083
|
}
|
|
2083
2084
|
}
|
|
2084
2085
|
},
|
|
2085
|
-
async execute(input) {
|
|
2086
|
+
async execute(input, context) {
|
|
2086
2087
|
try {
|
|
2087
2088
|
return await captureAndAnalyzeScreenshot({
|
|
2088
2089
|
prompt: input.prompt,
|
|
2089
|
-
|
|
2090
|
+
onLog: context?.onLog
|
|
2090
2091
|
});
|
|
2091
2092
|
} catch (err) {
|
|
2092
2093
|
return `Error taking screenshot: ${err.message}`;
|
|
@@ -2135,7 +2136,7 @@ async function runSubAgent(config) {
|
|
|
2135
2136
|
const {
|
|
2136
2137
|
system,
|
|
2137
2138
|
task,
|
|
2138
|
-
tools,
|
|
2139
|
+
tools: tools2,
|
|
2139
2140
|
externalTools,
|
|
2140
2141
|
executeTool: executeTool2,
|
|
2141
2142
|
apiConfig,
|
|
@@ -2167,7 +2168,7 @@ Current date/time: ${(/* @__PURE__ */ new Date()).toISOString().replace("T", " "
|
|
|
2167
2168
|
subAgentId,
|
|
2168
2169
|
system: fullSystem,
|
|
2169
2170
|
messages: cleanMessagesForApi(messages),
|
|
2170
|
-
tools,
|
|
2171
|
+
tools: tools2,
|
|
2171
2172
|
signal
|
|
2172
2173
|
})) {
|
|
2173
2174
|
if (signal?.aborted) {
|
|
@@ -2260,7 +2261,13 @@ Current date/time: ${(/* @__PURE__ */ new Date()).toISOString().replace("T", " "
|
|
|
2260
2261
|
if (externalTools.has(tc.name) && resolveExternalTool) {
|
|
2261
2262
|
result = await resolveExternalTool(tc.id, tc.name, tc.input);
|
|
2262
2263
|
} else {
|
|
2263
|
-
|
|
2264
|
+
const onLog = (line) => emit2({
|
|
2265
|
+
type: "tool_input_delta",
|
|
2266
|
+
id: tc.id,
|
|
2267
|
+
name: tc.name,
|
|
2268
|
+
result: line
|
|
2269
|
+
});
|
|
2270
|
+
result = await executeTool2(tc.name, tc.input, tc.id, onLog);
|
|
2264
2271
|
}
|
|
2265
2272
|
const isError = result.startsWith("Error");
|
|
2266
2273
|
emit2({
|
|
@@ -2340,7 +2347,7 @@ var init_tools = __esm({
|
|
|
2340
2347
|
"styles",
|
|
2341
2348
|
"screenshot"
|
|
2342
2349
|
],
|
|
2343
|
-
description: "snapshot: accessibility tree of the page (waits for network to settle). click: click an element (animated cursor, full event sequence). type: type text into input (one char at a time, works with React/Vue/Svelte). select: select a dropdown option by text. wait: wait for an element to appear (polls 100ms, waits for network). navigate: navigate to a URL within the app (waits for load, subsequent steps run on new page). evaluate: run JS in the page. styles: read computed CSS styles from elements (pass properties array with camelCase names, or omit for defaults). screenshot: full-page viewport-stitched screenshot (returns
|
|
2350
|
+
description: "snapshot: accessibility tree of the page (waits for network to settle). click: click an element (animated cursor, full event sequence). type: type text into input (one char at a time, works with React/Vue/Svelte). select: select a dropdown option by text. wait: wait for an element to appear (polls 100ms, waits for network). navigate: navigate to a URL within the app (waits for load, subsequent steps run on new page). evaluate: run JS in the page. styles: read computed CSS styles from elements (pass properties array with camelCase names, or omit for defaults). screenshot: full-page viewport-stitched screenshot (returns CDN url with dimensions)."
|
|
2344
2351
|
},
|
|
2345
2352
|
ref: {
|
|
2346
2353
|
type: "string",
|
|
@@ -2396,8 +2403,8 @@ var init_tools = __esm({
|
|
|
2396
2403
|
}
|
|
2397
2404
|
},
|
|
2398
2405
|
{
|
|
2399
|
-
name: "
|
|
2400
|
-
description: "Capture a screenshot of the current page. Returns a CDN URL with
|
|
2406
|
+
name: "screenshotFullPage",
|
|
2407
|
+
description: "Capture a full-height screenshot of the current page. Returns a CDN URL with full text analysis and description.",
|
|
2401
2408
|
inputSchema: {
|
|
2402
2409
|
type: "object",
|
|
2403
2410
|
properties: {}
|
|
@@ -2416,12 +2423,54 @@ var init_tools = __esm({
|
|
|
2416
2423
|
}
|
|
2417
2424
|
});
|
|
2418
2425
|
|
|
2419
|
-
// src/
|
|
2426
|
+
// src/assets.ts
|
|
2420
2427
|
import fs10 from "fs";
|
|
2421
2428
|
import path4 from "path";
|
|
2429
|
+
function findRoot(start) {
|
|
2430
|
+
let dir = start;
|
|
2431
|
+
while (dir !== path4.dirname(dir)) {
|
|
2432
|
+
if (fs10.existsSync(path4.join(dir, "package.json"))) {
|
|
2433
|
+
return dir;
|
|
2434
|
+
}
|
|
2435
|
+
dir = path4.dirname(dir);
|
|
2436
|
+
}
|
|
2437
|
+
return start;
|
|
2438
|
+
}
|
|
2439
|
+
function assetPath(...segments) {
|
|
2440
|
+
return path4.join(ASSETS_BASE, ...segments);
|
|
2441
|
+
}
|
|
2442
|
+
function readAsset(...segments) {
|
|
2443
|
+
const full = assetPath(...segments);
|
|
2444
|
+
try {
|
|
2445
|
+
return fs10.readFileSync(full, "utf-8").trim();
|
|
2446
|
+
} catch {
|
|
2447
|
+
throw new Error(`Required asset missing: ${full}`);
|
|
2448
|
+
}
|
|
2449
|
+
}
|
|
2450
|
+
function readJsonAsset(fallback, ...segments) {
|
|
2451
|
+
const full = assetPath(...segments);
|
|
2452
|
+
try {
|
|
2453
|
+
return JSON.parse(fs10.readFileSync(full, "utf-8"));
|
|
2454
|
+
} catch {
|
|
2455
|
+
return fallback;
|
|
2456
|
+
}
|
|
2457
|
+
}
|
|
2458
|
+
var ROOT, ASSETS_BASE;
|
|
2459
|
+
var init_assets = __esm({
|
|
2460
|
+
"src/assets.ts"() {
|
|
2461
|
+
"use strict";
|
|
2462
|
+
ROOT = findRoot(
|
|
2463
|
+
import.meta.dirname ?? path4.dirname(new URL(import.meta.url).pathname)
|
|
2464
|
+
);
|
|
2465
|
+
ASSETS_BASE = fs10.existsSync(path4.join(ROOT, "dist", "prompt")) ? path4.join(ROOT, "dist") : path4.join(ROOT, "src");
|
|
2466
|
+
}
|
|
2467
|
+
});
|
|
2468
|
+
|
|
2469
|
+
// src/subagents/browserAutomation/prompt.ts
|
|
2470
|
+
import fs11 from "fs";
|
|
2422
2471
|
function getBrowserAutomationPrompt() {
|
|
2423
2472
|
try {
|
|
2424
|
-
const appSpec =
|
|
2473
|
+
const appSpec = fs11.readFileSync("src/app.md", "utf-8").trim();
|
|
2425
2474
|
return `${BASE_PROMPT}
|
|
2426
2475
|
|
|
2427
2476
|
<app_context>
|
|
@@ -2431,14 +2480,12 @@ ${appSpec}
|
|
|
2431
2480
|
return BASE_PROMPT;
|
|
2432
2481
|
}
|
|
2433
2482
|
}
|
|
2434
|
-
var
|
|
2483
|
+
var BASE_PROMPT;
|
|
2435
2484
|
var init_prompt = __esm({
|
|
2436
2485
|
"src/subagents/browserAutomation/prompt.ts"() {
|
|
2437
2486
|
"use strict";
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
PROMPT_PATH = fs10.existsSync(local) ? local : path4.join(base, "subagents", "browserAutomation", "prompt.md");
|
|
2441
|
-
BASE_PROMPT = fs10.readFileSync(PROMPT_PATH, "utf-8").trim();
|
|
2487
|
+
init_assets();
|
|
2488
|
+
BASE_PROMPT = readAsset("subagents/browserAutomation", "prompt.md");
|
|
2442
2489
|
}
|
|
2443
2490
|
});
|
|
2444
2491
|
|
|
@@ -2457,7 +2504,7 @@ var init_browserAutomation = __esm({
|
|
|
2457
2504
|
browserAutomationTool = {
|
|
2458
2505
|
definition: {
|
|
2459
2506
|
name: "runAutomatedBrowserTest",
|
|
2460
|
-
description: "Run an automated browser test against the live preview. Describe what to test \u2014 the agent figures out how. Use after
|
|
2507
|
+
description: "Run an automated browser test against the live preview. Describe what to test \u2014 the agent figures out how. Use after meaningful changes frontend code, to reproduce user-reported issues, or to test end-to-end flows.",
|
|
2461
2508
|
inputSchema: {
|
|
2462
2509
|
type: "object",
|
|
2463
2510
|
properties: {
|
|
@@ -2490,10 +2537,10 @@ var init_browserAutomation = __esm({
|
|
|
2490
2537
|
task: input.task,
|
|
2491
2538
|
tools: BROWSER_TOOLS,
|
|
2492
2539
|
externalTools: BROWSER_EXTERNAL_TOOLS,
|
|
2493
|
-
executeTool: async (name) => {
|
|
2494
|
-
if (name === "
|
|
2540
|
+
executeTool: async (name, _input, _toolCallId, onLog) => {
|
|
2541
|
+
if (name === "screenshotFullPage") {
|
|
2495
2542
|
try {
|
|
2496
|
-
return await captureAndAnalyzeScreenshot();
|
|
2543
|
+
return await captureAndAnalyzeScreenshot({ onLog });
|
|
2497
2544
|
} catch (err) {
|
|
2498
2545
|
return `Error taking screenshot: ${err.message}`;
|
|
2499
2546
|
}
|
|
@@ -2523,7 +2570,7 @@ var init_browserAutomation = __esm({
|
|
|
2523
2570
|
try {
|
|
2524
2571
|
const parsed = JSON.parse(result2);
|
|
2525
2572
|
const screenshotSteps = (parsed.steps || []).filter(
|
|
2526
|
-
(s) => s.command === "
|
|
2573
|
+
(s) => s.command === "screenshotViewport" && s.result?.url
|
|
2527
2574
|
);
|
|
2528
2575
|
if (screenshotSteps.length > 0) {
|
|
2529
2576
|
const batchInput = screenshotSteps.map((s) => ({
|
|
@@ -2541,7 +2588,7 @@ var init_browserAutomation = __esm({
|
|
|
2541
2588
|
const analyses = JSON.parse(batchResult);
|
|
2542
2589
|
let ai = 0;
|
|
2543
2590
|
for (const step of parsed.steps) {
|
|
2544
|
-
if (step.command === "
|
|
2591
|
+
if (step.command === "screenshotViewport" && step.result?.url && ai < analyses.length) {
|
|
2545
2592
|
step.result.analysis = analyses[ai]?.output?.analysis || analyses[ai]?.output || "";
|
|
2546
2593
|
ai++;
|
|
2547
2594
|
}
|
|
@@ -2566,262 +2613,471 @@ var init_browserAutomation = __esm({
|
|
|
2566
2613
|
}
|
|
2567
2614
|
});
|
|
2568
2615
|
|
|
2569
|
-
// src/subagents/designExpert/tools.ts
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
|
|
2574
|
-
|
|
2616
|
+
// src/subagents/designExpert/tools/searchGoogle.ts
|
|
2617
|
+
var searchGoogle_exports = {};
|
|
2618
|
+
__export(searchGoogle_exports, {
|
|
2619
|
+
definition: () => definition,
|
|
2620
|
+
execute: () => execute
|
|
2621
|
+
});
|
|
2622
|
+
async function execute(input, onLog) {
|
|
2623
|
+
return runCli(
|
|
2624
|
+
`mindstudio search-google --query ${JSON.stringify(input.query)} --export-type json --output-key results --no-meta`,
|
|
2625
|
+
{ onLog }
|
|
2626
|
+
);
|
|
2575
2627
|
}
|
|
2576
|
-
|
|
2577
|
-
|
|
2578
|
-
|
|
2579
|
-
|
|
2580
|
-
|
|
2581
|
-
|
|
2582
|
-
|
|
2583
|
-
|
|
2584
|
-
|
|
2585
|
-
|
|
2628
|
+
var definition;
|
|
2629
|
+
var init_searchGoogle2 = __esm({
|
|
2630
|
+
"src/subagents/designExpert/tools/searchGoogle.ts"() {
|
|
2631
|
+
"use strict";
|
|
2632
|
+
init_runCli();
|
|
2633
|
+
definition = {
|
|
2634
|
+
name: "searchGoogle",
|
|
2635
|
+
description: 'Search Google for web results. Reserch modern design trends in industries or verticals, "best [domain] apps 2026", ui patterns, or find something specific if the the user has an explicit reference. Prioritize authoritative sources like Figma and other design leaders, avoid random blog spam. Pick one or more URLs from the results and then use `fetchUrl` to get their text content.',
|
|
2636
|
+
inputSchema: {
|
|
2637
|
+
type: "object",
|
|
2638
|
+
properties: {
|
|
2639
|
+
query: {
|
|
2640
|
+
type: "string",
|
|
2641
|
+
description: "The search query."
|
|
2642
|
+
}
|
|
2643
|
+
},
|
|
2644
|
+
required: ["query"]
|
|
2586
2645
|
}
|
|
2587
|
-
}
|
|
2588
|
-
|
|
2589
|
-
|
|
2590
|
-
|
|
2591
|
-
|
|
2592
|
-
|
|
2593
|
-
|
|
2594
|
-
|
|
2595
|
-
|
|
2646
|
+
};
|
|
2647
|
+
}
|
|
2648
|
+
});
|
|
2649
|
+
|
|
2650
|
+
// src/subagents/designExpert/tools/fetchUrl.ts
|
|
2651
|
+
var fetchUrl_exports = {};
|
|
2652
|
+
__export(fetchUrl_exports, {
|
|
2653
|
+
definition: () => definition2,
|
|
2654
|
+
execute: () => execute2
|
|
2655
|
+
});
|
|
2656
|
+
async function execute2(input, onLog) {
|
|
2657
|
+
const pageOptions = { onlyMainContent: true };
|
|
2658
|
+
if (input.screenshot) {
|
|
2659
|
+
pageOptions.screenshot = true;
|
|
2660
|
+
}
|
|
2661
|
+
return runCli(
|
|
2662
|
+
`mindstudio scrape-url --url ${JSON.stringify(input.url)} --page-options ${JSON.stringify(JSON.stringify(pageOptions))} --no-meta`,
|
|
2663
|
+
{ onLog }
|
|
2664
|
+
);
|
|
2665
|
+
}
|
|
2666
|
+
var definition2;
|
|
2667
|
+
var init_fetchUrl2 = __esm({
|
|
2668
|
+
"src/subagents/designExpert/tools/fetchUrl.ts"() {
|
|
2669
|
+
"use strict";
|
|
2670
|
+
init_runCli();
|
|
2671
|
+
definition2 = {
|
|
2672
|
+
name: "fetchUrl",
|
|
2673
|
+
description: "Fetch the content of a web page as markdown. Use when reading sites from search results or specific things the user wants to incorporate.",
|
|
2674
|
+
inputSchema: {
|
|
2675
|
+
type: "object",
|
|
2676
|
+
properties: {
|
|
2677
|
+
url: {
|
|
2678
|
+
type: "string",
|
|
2679
|
+
description: "The URL to fetch."
|
|
2680
|
+
}
|
|
2681
|
+
},
|
|
2682
|
+
required: ["url"]
|
|
2596
2683
|
}
|
|
2597
|
-
|
|
2598
|
-
|
|
2599
|
-
|
|
2684
|
+
};
|
|
2685
|
+
}
|
|
2686
|
+
});
|
|
2687
|
+
|
|
2688
|
+
// src/subagents/designExpert/tools/analyzeDesign.ts
|
|
2689
|
+
var analyzeDesign_exports = {};
|
|
2690
|
+
__export(analyzeDesign_exports, {
|
|
2691
|
+
definition: () => definition3,
|
|
2692
|
+
execute: () => execute3
|
|
2693
|
+
});
|
|
2694
|
+
async function execute3(input, onLog) {
|
|
2695
|
+
const url = input.url;
|
|
2696
|
+
const analysisPrompt = input.prompt || DESIGN_REFERENCE_PROMPT;
|
|
2697
|
+
const isImageUrl = /\.(png|jpe?g|webp|gif|svg|avif)(\?|$)/i.test(url);
|
|
2698
|
+
let imageUrl = url;
|
|
2699
|
+
if (!isImageUrl) {
|
|
2700
|
+
const ssUrl = await runCli(
|
|
2701
|
+
`mindstudio screenshot-url --url ${JSON.stringify(url)} --mode viewport --width 1440 --delay 2000 --output-key screenshotUrl --no-meta`,
|
|
2702
|
+
{ timeout: 12e4, onLog }
|
|
2703
|
+
);
|
|
2704
|
+
if (ssUrl.startsWith("Error")) {
|
|
2705
|
+
return `Could not screenshot ${url}: ${ssUrl}`;
|
|
2600
2706
|
}
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
|
-
|
|
2607
|
-
|
|
2608
|
-
`mindstudio screenshot-url --url ${JSON.stringify(url)} --mode viewport --width 1440 --delay 2000 --output-key screenshotUrl --no-meta`,
|
|
2609
|
-
{ timeout: 12e4 }
|
|
2610
|
-
);
|
|
2611
|
-
if (ssUrl.startsWith("Error")) {
|
|
2612
|
-
return `Could not screenshot ${url}: ${ssUrl}`;
|
|
2613
|
-
}
|
|
2614
|
-
imageUrl = ssUrl;
|
|
2615
|
-
}
|
|
2616
|
-
const analysis = await runCli(
|
|
2617
|
-
`mindstudio analyze-image --prompt ${JSON.stringify(analysisPrompt)} --image-url ${JSON.stringify(imageUrl)} --output-key analysis --no-meta`,
|
|
2618
|
-
{ timeout: 2e5 }
|
|
2619
|
-
);
|
|
2620
|
-
return isImageUrl ? analysis : `Screenshot: ${imageUrl}
|
|
2707
|
+
imageUrl = ssUrl;
|
|
2708
|
+
}
|
|
2709
|
+
const analysis = await runCli(
|
|
2710
|
+
`mindstudio analyze-image --prompt ${JSON.stringify(analysisPrompt)} --image-url ${JSON.stringify(imageUrl)} --output-key analysis --no-meta`,
|
|
2711
|
+
{ timeout: 2e5, onLog }
|
|
2712
|
+
);
|
|
2713
|
+
return isImageUrl ? analysis : `Screenshot: ${imageUrl}
|
|
2621
2714
|
|
|
2622
2715
|
${analysis}`;
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
|
|
2629
|
-
|
|
2630
|
-
|
|
2631
|
-
|
|
2632
|
-
|
|
2633
|
-
|
|
2634
|
-
|
|
2635
|
-
|
|
2716
|
+
}
|
|
2717
|
+
var DESIGN_REFERENCE_PROMPT, definition3;
|
|
2718
|
+
var init_analyzeDesign = __esm({
|
|
2719
|
+
"src/subagents/designExpert/tools/analyzeDesign.ts"() {
|
|
2720
|
+
"use strict";
|
|
2721
|
+
init_runCli();
|
|
2722
|
+
DESIGN_REFERENCE_PROMPT = `
|
|
2723
|
+
You are analyzing a screenshot of a real website or app for a designer's personal technique/inspiration reference notes.
|
|
2724
|
+
|
|
2725
|
+
Analyze the image and think about what makes the site or app special and unique. What is it doing that is unique, different, original, and creative? What makes it special? What isn't working? What doesn't look or feel good?
|
|
2726
|
+
|
|
2727
|
+
Then, provide the following analysis:
|
|
2728
|
+
|
|
2729
|
+
## Context
|
|
2730
|
+
What is this page, and what does it look like? Very briefly note the industry/vertical and purpose, then describe the composition with enough context to frame the analysis that follows \u2014 what's on the page, where things are positioned, what does the viewport look and feel like. Give enough detail that someone who can't see the image could understand the spatial references in the techniques section. Do not mention specific brand names. Keep it concise.
|
|
2731
|
+
|
|
2732
|
+
## Colors
|
|
2733
|
+
List the palette as hex values with short labels. Just the swatches \u2014 no "strategy" paragraph.
|
|
2734
|
+
|
|
2735
|
+
## Typography
|
|
2736
|
+
Brief description of the types used on the page. If you can identify the actual typeface name, provide it, otherwise provide a concrete description (e.g., "ultra-condensed grotesque, ~900 weight, tracked tight at maybe -0.03em, all-caps"). Include size relationships if notable (e.g., "hero text is viewport-width, body is 14px").
|
|
2737
|
+
|
|
2738
|
+
## Techniques
|
|
2739
|
+
Identify the specific design moves that make this page interesting and unique, described in terms of how a designer with a technical background would write them down as notes in their notebook for inspiration. Focus only on the non-obvious, hard-to-think-of techniques \u2014 the things that make this page gallery-worthy. Skip basics like "high contrast CTA" or "generous whitespace" that any competent designer already knows.
|
|
2740
|
+
|
|
2741
|
+
Respond only with the analysis and absolutely no other text.
|
|
2742
|
+
`;
|
|
2743
|
+
definition3 = {
|
|
2744
|
+
name: "analyzeDesign",
|
|
2745
|
+
description: "Analyze the visual design of a website or image URL. Websites are automatically screenshotted first. If no prompt is provided, performs a full design reference analysis (mood, color, typography, layout, distinctiveness). Provide a custom prompt to ask a specific design question instead.",
|
|
2746
|
+
inputSchema: {
|
|
2747
|
+
type: "object",
|
|
2748
|
+
properties: {
|
|
2749
|
+
url: {
|
|
2750
|
+
type: "string",
|
|
2751
|
+
description: "URL to analyze. Can be an image URL or a website URL (will be screenshotted)."
|
|
2752
|
+
},
|
|
2753
|
+
prompt: {
|
|
2754
|
+
type: "string",
|
|
2755
|
+
description: "Optional custom analysis prompt. If omitted, performs the standard design reference analysis."
|
|
2636
2756
|
}
|
|
2637
|
-
}
|
|
2638
|
-
|
|
2639
|
-
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
|
-
|
|
2643
|
-
|
|
2644
|
-
|
|
2645
|
-
|
|
2646
|
-
|
|
2647
|
-
|
|
2648
|
-
|
|
2649
|
-
|
|
2650
|
-
|
|
2651
|
-
|
|
2757
|
+
},
|
|
2758
|
+
required: ["url"]
|
|
2759
|
+
}
|
|
2760
|
+
};
|
|
2761
|
+
}
|
|
2762
|
+
});
|
|
2763
|
+
|
|
2764
|
+
// src/subagents/designExpert/tools/analyzeImage.ts
|
|
2765
|
+
var analyzeImage_exports = {};
|
|
2766
|
+
__export(analyzeImage_exports, {
|
|
2767
|
+
definition: () => definition4,
|
|
2768
|
+
execute: () => execute4
|
|
2769
|
+
});
|
|
2770
|
+
async function execute4(input, onLog) {
|
|
2771
|
+
const imageUrl = input.imageUrl;
|
|
2772
|
+
const prompt = input.prompt || DEFAULT_PROMPT;
|
|
2773
|
+
const analysis = await runCli(
|
|
2774
|
+
`mindstudio analyze-image --prompt ${JSON.stringify(prompt)} --image-url ${JSON.stringify(imageUrl)} --output-key analysis --no-meta`,
|
|
2775
|
+
{ timeout: 2e5, onLog }
|
|
2776
|
+
);
|
|
2777
|
+
return JSON.stringify({ url: imageUrl, analysis });
|
|
2778
|
+
}
|
|
2779
|
+
var DEFAULT_PROMPT, definition4;
|
|
2780
|
+
var init_analyzeImage = __esm({
|
|
2781
|
+
"src/subagents/designExpert/tools/analyzeImage.ts"() {
|
|
2782
|
+
"use strict";
|
|
2783
|
+
init_runCli();
|
|
2784
|
+
DEFAULT_PROMPT = "Describe everything visible in this image \u2014 every element, its position, its size relative to the frame, its colors, its content. Be thorough and spatial. After the inventory, note anything that looks visually broken (overlapping elements, clipped text, misaligned components).";
|
|
2785
|
+
definition4 = {
|
|
2786
|
+
name: "analyzeImage",
|
|
2787
|
+
description: "Analyze an image by URL. Returns a detailed description of everything visible. Provide a custom prompt to ask a specific question instead of the default full description.",
|
|
2788
|
+
inputSchema: {
|
|
2789
|
+
type: "object",
|
|
2790
|
+
properties: {
|
|
2791
|
+
imageUrl: {
|
|
2792
|
+
type: "string",
|
|
2793
|
+
description: "The image URL to analyze."
|
|
2794
|
+
},
|
|
2795
|
+
prompt: {
|
|
2796
|
+
type: "string",
|
|
2797
|
+
description: "Optional custom analysis prompt. If omitted, describes everything visible in the image."
|
|
2652
2798
|
}
|
|
2653
|
-
}
|
|
2654
|
-
|
|
2655
|
-
`mindstudio batch '${JSON.stringify(steps)}' --no-meta`,
|
|
2656
|
-
{ jsonLogs: true, timeout: 2e5 }
|
|
2657
|
-
);
|
|
2658
|
-
try {
|
|
2659
|
-
const parsed = JSON.parse(batchResult);
|
|
2660
|
-
imageUrls = parsed.results.map(
|
|
2661
|
-
(r) => r.output?.imageUrl ?? `Error: ${r.error}`
|
|
2662
|
-
);
|
|
2663
|
-
} catch {
|
|
2664
|
-
return batchResult;
|
|
2665
|
-
}
|
|
2799
|
+
},
|
|
2800
|
+
required: ["imageUrl"]
|
|
2666
2801
|
}
|
|
2667
|
-
|
|
2668
|
-
|
|
2669
|
-
|
|
2670
|
-
|
|
2802
|
+
};
|
|
2803
|
+
}
|
|
2804
|
+
});
|
|
2805
|
+
|
|
2806
|
+
// src/subagents/designExpert/tools/screenshot.ts
|
|
2807
|
+
var screenshot_exports = {};
|
|
2808
|
+
__export(screenshot_exports, {
|
|
2809
|
+
definition: () => definition5,
|
|
2810
|
+
execute: () => execute5
|
|
2811
|
+
});
|
|
2812
|
+
async function execute5(input, onLog) {
|
|
2813
|
+
try {
|
|
2814
|
+
return await captureAndAnalyzeScreenshot({
|
|
2815
|
+
prompt: input.prompt,
|
|
2816
|
+
onLog
|
|
2817
|
+
});
|
|
2818
|
+
} catch (err) {
|
|
2819
|
+
return `Error taking screenshot: ${err.message}`;
|
|
2820
|
+
}
|
|
2821
|
+
}
|
|
2822
|
+
var definition5;
|
|
2823
|
+
var init_screenshot3 = __esm({
|
|
2824
|
+
"src/subagents/designExpert/tools/screenshot.ts"() {
|
|
2825
|
+
"use strict";
|
|
2826
|
+
init_screenshot();
|
|
2827
|
+
definition5 = {
|
|
2828
|
+
name: "screenshot",
|
|
2829
|
+
description: "Capture a full-height screenshot of the current app preview. Returns a CDN URL along with visual analysis. Use to review the current state of the UI being built. Remember, the screenshot analysis is not overly precise - for example, it cannot reliably identify specific fonts by name \u2014 it can only describe what letterforms look like.",
|
|
2830
|
+
inputSchema: {
|
|
2831
|
+
type: "object",
|
|
2832
|
+
properties: {
|
|
2833
|
+
prompt: {
|
|
2834
|
+
type: "string",
|
|
2835
|
+
description: "Optional specific question about the screenshot."
|
|
2671
2836
|
}
|
|
2672
|
-
|
|
2673
|
-
`mindstudio analyze-image --prompt ${JSON.stringify(ANALYZE_PROMPT)} --image-url ${JSON.stringify(url)} --output-key analysis --no-meta`,
|
|
2674
|
-
{ timeout: 2e5 }
|
|
2675
|
-
);
|
|
2676
|
-
return { url, prompt: prompts[i], analysis, width, height };
|
|
2677
|
-
})
|
|
2678
|
-
);
|
|
2679
|
-
return `%%JSON%%${JSON.stringify({ images })}`;
|
|
2680
|
-
}
|
|
2681
|
-
case "runBrowserTest": {
|
|
2682
|
-
if (!context) {
|
|
2683
|
-
return "Error: browser testing requires execution context (only available in headless mode)";
|
|
2837
|
+
}
|
|
2684
2838
|
}
|
|
2685
|
-
|
|
2686
|
-
|
|
2687
|
-
|
|
2688
|
-
|
|
2689
|
-
|
|
2839
|
+
};
|
|
2840
|
+
}
|
|
2841
|
+
});
|
|
2842
|
+
|
|
2843
|
+
// src/subagents/designExpert/tools/_seedream.ts
|
|
2844
|
+
async function seedreamGenerate(opts) {
|
|
2845
|
+
const { prompts, sourceImages, transparentBackground, onLog } = opts;
|
|
2846
|
+
const width = opts.width || 2048;
|
|
2847
|
+
const height = opts.height || 2048;
|
|
2848
|
+
const config = { width, height };
|
|
2849
|
+
if (sourceImages?.length) {
|
|
2850
|
+
config.images = sourceImages;
|
|
2851
|
+
}
|
|
2852
|
+
let imageUrls;
|
|
2853
|
+
if (prompts.length === 1) {
|
|
2854
|
+
const step = JSON.stringify({
|
|
2855
|
+
prompt: prompts[0],
|
|
2856
|
+
imageModelOverride: {
|
|
2857
|
+
model: "seedream-4.5",
|
|
2858
|
+
config
|
|
2859
|
+
}
|
|
2860
|
+
});
|
|
2861
|
+
const url = await runCli(
|
|
2862
|
+
`mindstudio generate-image ${JSON.stringify(step)} --output-key imageUrl --no-meta`,
|
|
2863
|
+
{ jsonLogs: true, timeout: 2e5, onLog }
|
|
2864
|
+
);
|
|
2865
|
+
imageUrls = [url];
|
|
2866
|
+
} else {
|
|
2867
|
+
const steps = prompts.map((prompt) => ({
|
|
2868
|
+
stepType: "generateImage",
|
|
2869
|
+
step: {
|
|
2870
|
+
prompt,
|
|
2871
|
+
imageModelOverride: {
|
|
2872
|
+
model: "seedream-4.5",
|
|
2873
|
+
config
|
|
2690
2874
|
}
|
|
2875
|
+
}
|
|
2876
|
+
}));
|
|
2877
|
+
const batchResult = await runCli(
|
|
2878
|
+
`mindstudio batch ${JSON.stringify(JSON.stringify(steps))} --no-meta`,
|
|
2879
|
+
{ jsonLogs: true, timeout: 2e5, onLog }
|
|
2880
|
+
);
|
|
2881
|
+
try {
|
|
2882
|
+
const parsed = JSON.parse(batchResult);
|
|
2883
|
+
imageUrls = parsed.results.map(
|
|
2884
|
+
(r) => r.output?.imageUrl ?? `Error: ${r.error}`
|
|
2691
2885
|
);
|
|
2886
|
+
} catch {
|
|
2887
|
+
return batchResult;
|
|
2692
2888
|
}
|
|
2693
|
-
default:
|
|
2694
|
-
return `Error: unknown tool "${name}"`;
|
|
2695
2889
|
}
|
|
2890
|
+
if (transparentBackground) {
|
|
2891
|
+
imageUrls = await Promise.all(
|
|
2892
|
+
imageUrls.map(async (url) => {
|
|
2893
|
+
if (url.startsWith("Error")) {
|
|
2894
|
+
return url;
|
|
2895
|
+
}
|
|
2896
|
+
const result = await runCli(
|
|
2897
|
+
`mindstudio remove-background-from-image --image-url ${JSON.stringify(url)} --output-key imageUrl --no-meta`,
|
|
2898
|
+
{ timeout: 2e5, onLog }
|
|
2899
|
+
);
|
|
2900
|
+
return result.startsWith("Error") ? url : result;
|
|
2901
|
+
})
|
|
2902
|
+
);
|
|
2903
|
+
}
|
|
2904
|
+
const images = await Promise.all(
|
|
2905
|
+
imageUrls.map(async (url, i) => {
|
|
2906
|
+
if (url.startsWith("Error")) {
|
|
2907
|
+
return { prompt: prompts[i], error: url };
|
|
2908
|
+
}
|
|
2909
|
+
const analysis = await runCli(
|
|
2910
|
+
`mindstudio analyze-image --prompt ${JSON.stringify(ANALYZE_PROMPT)} --image-url ${JSON.stringify(url)} --output-key analysis --no-meta`,
|
|
2911
|
+
{ timeout: 2e5, onLog }
|
|
2912
|
+
);
|
|
2913
|
+
return { url, prompt: prompts[i], analysis, width, height };
|
|
2914
|
+
})
|
|
2915
|
+
);
|
|
2916
|
+
return JSON.stringify({ images });
|
|
2696
2917
|
}
|
|
2697
|
-
var
|
|
2698
|
-
var
|
|
2699
|
-
"src/subagents/designExpert/tools.ts"() {
|
|
2918
|
+
var ANALYZE_PROMPT;
|
|
2919
|
+
var init_seedream = __esm({
|
|
2920
|
+
"src/subagents/designExpert/tools/_seedream.ts"() {
|
|
2700
2921
|
"use strict";
|
|
2701
2922
|
init_runCli();
|
|
2702
|
-
|
|
2703
|
-
|
|
2704
|
-
|
|
2705
|
-
|
|
2706
|
-
|
|
2707
|
-
|
|
2708
|
-
|
|
2709
|
-
|
|
2710
|
-
|
|
2711
|
-
|
|
2712
|
-
|
|
2713
|
-
|
|
2714
|
-
|
|
2715
|
-
|
|
2716
|
-
|
|
2717
|
-
|
|
2718
|
-
|
|
2719
|
-
|
|
2720
|
-
|
|
2721
|
-
|
|
2722
|
-
|
|
2723
|
-
|
|
2724
|
-
|
|
2725
|
-
|
|
2726
|
-
|
|
2727
|
-
|
|
2728
|
-
|
|
2729
|
-
|
|
2923
|
+
ANALYZE_PROMPT = "You are reviewing this image for a visual designer sourcing assets for a project. Describe: what the image depicts, the mood and color palette, how the lighting and composition work, whether there are any issues (unwanted text, artifacts, distortions), and how it could be used in a layout (hero background, feature section, card texture, etc). Be concise and practical.";
|
|
2924
|
+
}
|
|
2925
|
+
});
|
|
2926
|
+
|
|
2927
|
+
// src/subagents/designExpert/tools/generateImages.ts
|
|
2928
|
+
var generateImages_exports = {};
|
|
2929
|
+
__export(generateImages_exports, {
|
|
2930
|
+
definition: () => definition6,
|
|
2931
|
+
execute: () => execute6
|
|
2932
|
+
});
|
|
2933
|
+
async function execute6(input, onLog) {
|
|
2934
|
+
return seedreamGenerate({
|
|
2935
|
+
prompts: input.prompts,
|
|
2936
|
+
width: input.width,
|
|
2937
|
+
height: input.height,
|
|
2938
|
+
transparentBackground: input.transparentBackground,
|
|
2939
|
+
onLog
|
|
2940
|
+
});
|
|
2941
|
+
}
|
|
2942
|
+
var definition6;
|
|
2943
|
+
var init_generateImages = __esm({
|
|
2944
|
+
"src/subagents/designExpert/tools/generateImages.ts"() {
|
|
2945
|
+
"use strict";
|
|
2946
|
+
init_seedream();
|
|
2947
|
+
definition6 = {
|
|
2948
|
+
name: "generateImages",
|
|
2949
|
+
description: "Generate images using AI. Returns CDN URLs with a quality analysis for each image. Produces high-quality results for everything from photorealistic images and abstract/creative visuals. Pass multiple prompts to generate in parallel. No need to analyze images separately after generating \u2014 the analysis is included.",
|
|
2950
|
+
inputSchema: {
|
|
2951
|
+
type: "object",
|
|
2952
|
+
properties: {
|
|
2953
|
+
prompts: {
|
|
2954
|
+
type: "array",
|
|
2955
|
+
items: {
|
|
2956
|
+
type: "string"
|
|
2730
2957
|
},
|
|
2731
|
-
|
|
2732
|
-
type: "boolean",
|
|
2733
|
-
description: "Capture a screenshot of the page. Use when you need to see the visual design, not just the text."
|
|
2734
|
-
}
|
|
2958
|
+
description: "One or more image generation prompts. Be detailed: describe style, mood, composition, colors. Multiple prompts run in parallel."
|
|
2735
2959
|
},
|
|
2736
|
-
|
|
2737
|
-
|
|
2738
|
-
|
|
2739
|
-
{
|
|
2740
|
-
name: "analyzeReferenceImageOrUrl",
|
|
2741
|
-
description: "Analyze any visual \u2014 pass an image URL or a website URL. Websites are automatically screenshotted first. If no prompt is provided, performs a full design reference analysis (mood, color, typography, layout, distinctiveness). Provide a custom prompt to ask a specific question instead.",
|
|
2742
|
-
inputSchema: {
|
|
2743
|
-
type: "object",
|
|
2744
|
-
properties: {
|
|
2745
|
-
url: {
|
|
2746
|
-
type: "string",
|
|
2747
|
-
description: "URL to analyze. Can be an image URL or a website URL (will be screenshotted)."
|
|
2748
|
-
},
|
|
2749
|
-
prompt: {
|
|
2750
|
-
type: "string",
|
|
2751
|
-
description: "Optional custom analysis prompt. If omitted, performs the standard design reference analysis."
|
|
2752
|
-
}
|
|
2960
|
+
width: {
|
|
2961
|
+
type: "number",
|
|
2962
|
+
description: "Image width in pixels. Default 2048. Range: 2048-4096."
|
|
2753
2963
|
},
|
|
2754
|
-
|
|
2755
|
-
|
|
2756
|
-
|
|
2757
|
-
{
|
|
2758
|
-
name: "screenshot",
|
|
2759
|
-
description: "Capture a screenshot of the app preview. Returns a CDN URL with visual analysis. Use to review the current state of the UI being built. By default captures the viewport. Set fullPage to capture the entire scrollable page.",
|
|
2760
|
-
inputSchema: {
|
|
2761
|
-
type: "object",
|
|
2762
|
-
properties: {
|
|
2763
|
-
prompt: {
|
|
2764
|
-
type: "string",
|
|
2765
|
-
description: "Optional specific question about the screenshot."
|
|
2766
|
-
},
|
|
2767
|
-
fullPage: {
|
|
2768
|
-
type: "boolean",
|
|
2769
|
-
description: "Capture the full scrollable page instead of just the viewport. Use when you need to see below-the-fold content."
|
|
2770
|
-
}
|
|
2771
|
-
}
|
|
2772
|
-
}
|
|
2773
|
-
},
|
|
2774
|
-
{
|
|
2775
|
-
name: "runBrowserTest",
|
|
2776
|
-
description: "Run an automated browser test against the live app preview. Use to verify implementation details via getComputedStyle: font-family names, exact colors, spacing, borders, shadows, font sizes, transforms. Only use this to evaluate computed CSS properties that can't be deduced from sceenshots.",
|
|
2777
|
-
inputSchema: {
|
|
2778
|
-
type: "object",
|
|
2779
|
-
properties: {
|
|
2780
|
-
task: {
|
|
2781
|
-
type: "string",
|
|
2782
|
-
description: 'What to verify, in natural language. Focus on measurable properties: "Check the hero cards have border-radius: 24px and box-shadow" or "Verify the background color of the CTA section is #C4FF0D".'
|
|
2783
|
-
}
|
|
2964
|
+
height: {
|
|
2965
|
+
type: "number",
|
|
2966
|
+
description: "Image height in pixels. Default 2048. Range: 2048-4096."
|
|
2784
2967
|
},
|
|
2785
|
-
|
|
2786
|
-
|
|
2787
|
-
|
|
2788
|
-
|
|
2789
|
-
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
|
|
2793
|
-
|
|
2794
|
-
|
|
2795
|
-
|
|
2796
|
-
|
|
2797
|
-
|
|
2798
|
-
|
|
2799
|
-
|
|
2968
|
+
transparentBackground: {
|
|
2969
|
+
type: "boolean",
|
|
2970
|
+
description: "Remove the background from generated images, producing transparent PNGs. Useful for icons, logos, product shots, and assets that need to be composited onto other backgrounds."
|
|
2971
|
+
}
|
|
2972
|
+
},
|
|
2973
|
+
required: ["prompts"]
|
|
2974
|
+
}
|
|
2975
|
+
};
|
|
2976
|
+
}
|
|
2977
|
+
});
|
|
2978
|
+
|
|
2979
|
+
// src/subagents/designExpert/tools/editImages.ts
|
|
2980
|
+
var editImages_exports = {};
|
|
2981
|
+
__export(editImages_exports, {
|
|
2982
|
+
definition: () => definition7,
|
|
2983
|
+
execute: () => execute7
|
|
2984
|
+
});
|
|
2985
|
+
async function execute7(input, onLog) {
|
|
2986
|
+
return seedreamGenerate({
|
|
2987
|
+
prompts: input.prompts,
|
|
2988
|
+
sourceImages: input.sourceImages,
|
|
2989
|
+
width: input.width,
|
|
2990
|
+
height: input.height,
|
|
2991
|
+
transparentBackground: input.transparentBackground,
|
|
2992
|
+
onLog
|
|
2993
|
+
});
|
|
2994
|
+
}
|
|
2995
|
+
var definition7;
|
|
2996
|
+
var init_editImages = __esm({
|
|
2997
|
+
"src/subagents/designExpert/tools/editImages.ts"() {
|
|
2998
|
+
"use strict";
|
|
2999
|
+
init_seedream();
|
|
3000
|
+
definition7 = {
|
|
3001
|
+
name: "editImages",
|
|
3002
|
+
description: "Edit or transform existing images using AI. Provide one or more source image URLs as reference and a prompt describing the desired edit. Use for compositing, style transfer, subject transformation, blending multiple references, or incorporating one or more ferences into something new. Returns CDN URLs with analysis.",
|
|
3003
|
+
inputSchema: {
|
|
3004
|
+
type: "object",
|
|
3005
|
+
properties: {
|
|
3006
|
+
prompts: {
|
|
3007
|
+
type: "array",
|
|
3008
|
+
items: {
|
|
3009
|
+
type: "string"
|
|
2800
3010
|
},
|
|
2801
|
-
|
|
2802
|
-
|
|
2803
|
-
|
|
3011
|
+
description: "One or more edit prompts describing how to transform the source images. Multiple prompts run in parallel, each using the same source images."
|
|
3012
|
+
},
|
|
3013
|
+
sourceImages: {
|
|
3014
|
+
type: "array",
|
|
3015
|
+
items: {
|
|
3016
|
+
type: "string"
|
|
2804
3017
|
},
|
|
2805
|
-
|
|
2806
|
-
type: "number",
|
|
2807
|
-
description: "Image height in pixels. Default 2048. Range: 2048-4096."
|
|
2808
|
-
}
|
|
3018
|
+
description: "One or more source/reference image URLs. These are used as the basis for the edit \u2014 the AI will use them as reference for style, subject, or composition."
|
|
2809
3019
|
},
|
|
2810
|
-
|
|
2811
|
-
|
|
3020
|
+
width: {
|
|
3021
|
+
type: "number",
|
|
3022
|
+
description: "Output width in pixels. Default 2048. Range: 2048-4096."
|
|
3023
|
+
},
|
|
3024
|
+
height: {
|
|
3025
|
+
type: "number",
|
|
3026
|
+
description: "Output height in pixels. Default 2048. Range: 2048-4096."
|
|
3027
|
+
},
|
|
3028
|
+
transparentBackground: {
|
|
3029
|
+
type: "boolean",
|
|
3030
|
+
description: "Remove the background from output images, producing transparent PNGs."
|
|
3031
|
+
}
|
|
3032
|
+
},
|
|
3033
|
+
required: ["prompts", "sourceImages"]
|
|
2812
3034
|
}
|
|
2813
|
-
|
|
3035
|
+
};
|
|
3036
|
+
}
|
|
3037
|
+
});
|
|
3038
|
+
|
|
3039
|
+
// src/subagents/designExpert/tools/index.ts
|
|
3040
|
+
async function executeDesignExpertTool(name, input, context, toolCallId, onLog) {
|
|
3041
|
+
const tool = tools[name];
|
|
3042
|
+
if (!tool) {
|
|
3043
|
+
return `Error: unknown tool "${name}"`;
|
|
3044
|
+
}
|
|
3045
|
+
return tool.execute(input, onLog);
|
|
3046
|
+
}
|
|
3047
|
+
var tools, DESIGN_EXPERT_TOOLS;
|
|
3048
|
+
var init_tools2 = __esm({
|
|
3049
|
+
"src/subagents/designExpert/tools/index.ts"() {
|
|
3050
|
+
"use strict";
|
|
3051
|
+
init_searchGoogle2();
|
|
3052
|
+
init_fetchUrl2();
|
|
3053
|
+
init_analyzeDesign();
|
|
3054
|
+
init_analyzeImage();
|
|
3055
|
+
init_screenshot3();
|
|
3056
|
+
init_generateImages();
|
|
3057
|
+
init_editImages();
|
|
3058
|
+
tools = {
|
|
3059
|
+
searchGoogle: searchGoogle_exports,
|
|
3060
|
+
fetchUrl: fetchUrl_exports,
|
|
3061
|
+
analyzeDesign: analyzeDesign_exports,
|
|
3062
|
+
analyzeImage: analyzeImage_exports,
|
|
3063
|
+
screenshot: screenshot_exports,
|
|
3064
|
+
generateImages: generateImages_exports,
|
|
3065
|
+
editImages: editImages_exports
|
|
3066
|
+
};
|
|
3067
|
+
DESIGN_EXPERT_TOOLS = Object.values(tools).map(
|
|
3068
|
+
(t) => t.definition
|
|
3069
|
+
);
|
|
2814
3070
|
}
|
|
2815
3071
|
});
|
|
2816
3072
|
|
|
2817
3073
|
// src/subagents/common/context.ts
|
|
2818
3074
|
import fs12 from "fs";
|
|
2819
|
-
import
|
|
3075
|
+
import path5 from "path";
|
|
2820
3076
|
function walkMdFiles(dir, skip) {
|
|
2821
3077
|
const files = [];
|
|
2822
3078
|
try {
|
|
2823
3079
|
for (const entry of fs12.readdirSync(dir, { withFileTypes: true })) {
|
|
2824
|
-
const full =
|
|
3080
|
+
const full = path5.join(dir, entry.name);
|
|
2825
3081
|
if (entry.isDirectory()) {
|
|
2826
3082
|
if (!skip?.has(entry.name)) {
|
|
2827
3083
|
files.push(...walkMdFiles(full, skip));
|
|
@@ -2915,23 +3171,7 @@ var init_context = __esm({
|
|
|
2915
3171
|
}
|
|
2916
3172
|
});
|
|
2917
3173
|
|
|
2918
|
-
// src/subagents/designExpert/
|
|
2919
|
-
import fs13 from "fs";
|
|
2920
|
-
import path7 from "path";
|
|
2921
|
-
function resolvePath2(filename) {
|
|
2922
|
-
const local4 = path7.join(base3, filename);
|
|
2923
|
-
return fs13.existsSync(local4) ? local4 : path7.join(base3, "subagents", "designExpert", filename);
|
|
2924
|
-
}
|
|
2925
|
-
function readFile(filename) {
|
|
2926
|
-
return fs13.readFileSync(resolvePath2(filename), "utf-8").trim();
|
|
2927
|
-
}
|
|
2928
|
-
function readJson(filename, fallback) {
|
|
2929
|
-
try {
|
|
2930
|
-
return JSON.parse(fs13.readFileSync(resolvePath2(filename), "utf-8"));
|
|
2931
|
-
} catch {
|
|
2932
|
-
return fallback;
|
|
2933
|
-
}
|
|
2934
|
-
}
|
|
3174
|
+
// src/subagents/designExpert/data/getFontLibrarySample.ts
|
|
2935
3175
|
function sample(arr, n) {
|
|
2936
3176
|
if (arr.length <= n) {
|
|
2937
3177
|
return [...arr];
|
|
@@ -2943,10 +3183,12 @@ function sample(arr, n) {
|
|
|
2943
3183
|
}
|
|
2944
3184
|
return copy.slice(0, n);
|
|
2945
3185
|
}
|
|
2946
|
-
function
|
|
2947
|
-
const fonts = sample(fontData.fonts,
|
|
2948
|
-
const pairings = sample(fontData.pairings,
|
|
2949
|
-
|
|
3186
|
+
function getFontLibrarySample() {
|
|
3187
|
+
const fonts = sample(fontData.fonts, 60);
|
|
3188
|
+
const pairings = sample(fontData.pairings, 30);
|
|
3189
|
+
if (!fonts.length) {
|
|
3190
|
+
return "";
|
|
3191
|
+
}
|
|
2950
3192
|
const fontList = fonts.map((f) => {
|
|
2951
3193
|
let cssInfo = "";
|
|
2952
3194
|
if (f.source === "fontshare") {
|
|
@@ -2962,60 +3204,102 @@ function getDesignExpertPrompt() {
|
|
|
2962
3204
|
const pairingList = pairings.map(
|
|
2963
3205
|
(p) => `- **${p.heading.font}** (${p.heading.weight}) heading + **${p.body.font}** (${p.body.weight}) body`
|
|
2964
3206
|
).join("\n");
|
|
2965
|
-
|
|
2966
|
-
##
|
|
3207
|
+
return `
|
|
3208
|
+
## Font Library
|
|
3209
|
+
|
|
3210
|
+
A random sample from a curated font library. Use these as starting points for font selection.
|
|
2967
3211
|
|
|
2968
|
-
|
|
2969
|
-
CSS URL pattern: ${fontData.cssUrlPattern}
|
|
3212
|
+
### Fonts
|
|
2970
3213
|
|
|
2971
3214
|
${fontList}
|
|
2972
3215
|
|
|
2973
|
-
###
|
|
3216
|
+
### Pairings
|
|
2974
3217
|
|
|
2975
|
-
${pairingList}
|
|
2976
|
-
|
|
2977
|
-
|
|
2978
|
-
|
|
2979
|
-
|
|
3218
|
+
${pairingList}`.trim();
|
|
3219
|
+
}
|
|
3220
|
+
var fontData;
|
|
3221
|
+
var init_getFontLibrarySample = __esm({
|
|
3222
|
+
"src/subagents/designExpert/data/getFontLibrarySample.ts"() {
|
|
3223
|
+
"use strict";
|
|
3224
|
+
init_assets();
|
|
3225
|
+
fontData = readJsonAsset(
|
|
3226
|
+
{ cssUrlPattern: "", fonts: [], pairings: [] },
|
|
3227
|
+
"subagents/designExpert/data/sources/fonts.json"
|
|
3228
|
+
);
|
|
3229
|
+
}
|
|
3230
|
+
});
|
|
3231
|
+
|
|
3232
|
+
// src/subagents/designExpert/data/getDesignReferencesSample.ts
|
|
3233
|
+
function sample2(arr, n) {
|
|
3234
|
+
if (arr.length <= n) {
|
|
3235
|
+
return [...arr];
|
|
3236
|
+
}
|
|
3237
|
+
const copy = [...arr];
|
|
3238
|
+
for (let i = copy.length - 1; i > 0; i--) {
|
|
3239
|
+
const j = Math.floor(Math.random() * (i + 1));
|
|
3240
|
+
[copy[i], copy[j]] = [copy[j], copy[i]];
|
|
3241
|
+
}
|
|
3242
|
+
return copy.slice(0, n);
|
|
3243
|
+
}
|
|
3244
|
+
function getDesignReferencesSample() {
|
|
3245
|
+
const images = sample2(inspirationImages, 30);
|
|
3246
|
+
if (!images.length) {
|
|
3247
|
+
return "";
|
|
3248
|
+
}
|
|
3249
|
+
const imageList = images.map((img, i) => `### Reference ${i + 1}
|
|
3250
|
+
${img.analysis}`).join("\n\n");
|
|
3251
|
+
return `
|
|
3252
|
+
## Design References
|
|
2980
3253
|
|
|
2981
3254
|
This is what the bar looks like. These are real sites that made it onto curated design galleries because they did something bold, intentional, and memorable. Use them as inspiration and let the takeaways guide your work. Your designs should feel like they belong in this company.
|
|
2982
3255
|
|
|
2983
|
-
${imageList}
|
|
2984
|
-
|
|
3256
|
+
${imageList}`.trim();
|
|
3257
|
+
}
|
|
3258
|
+
var inspirationImages;
|
|
3259
|
+
var init_getDesignReferencesSample = __esm({
|
|
3260
|
+
"src/subagents/designExpert/data/getDesignReferencesSample.ts"() {
|
|
3261
|
+
"use strict";
|
|
3262
|
+
init_assets();
|
|
3263
|
+
inspirationImages = readJsonAsset(
|
|
3264
|
+
{ images: [] },
|
|
3265
|
+
"subagents/designExpert/data/sources/inspiration.json"
|
|
3266
|
+
).images;
|
|
3267
|
+
}
|
|
3268
|
+
});
|
|
3269
|
+
|
|
3270
|
+
// src/subagents/designExpert/prompt.ts
|
|
3271
|
+
import fs13 from "fs";
|
|
3272
|
+
function getDesignExpertPrompt() {
|
|
2985
3273
|
const specContext = loadSpecContext();
|
|
2986
3274
|
let prompt = PROMPT_TEMPLATE.replace(
|
|
2987
|
-
"{{
|
|
2988
|
-
|
|
2989
|
-
).replace("{{
|
|
3275
|
+
"{{font_library}}",
|
|
3276
|
+
getFontLibrarySample()
|
|
3277
|
+
).replace("{{design_references}}", getDesignReferencesSample());
|
|
2990
3278
|
if (specContext) {
|
|
2991
3279
|
prompt += `
|
|
2992
3280
|
|
|
2993
3281
|
${specContext}`;
|
|
3282
|
+
}
|
|
3283
|
+
try {
|
|
3284
|
+
fs13.writeFileSync(`.design-prompt.md`, prompt);
|
|
3285
|
+
} catch {
|
|
2994
3286
|
}
|
|
2995
3287
|
return prompt;
|
|
2996
3288
|
}
|
|
2997
|
-
var
|
|
3289
|
+
var SUBAGENT, RUNTIME_PLACEHOLDERS, PROMPT_TEMPLATE;
|
|
2998
3290
|
var init_prompt2 = __esm({
|
|
2999
3291
|
"src/subagents/designExpert/prompt.ts"() {
|
|
3000
3292
|
"use strict";
|
|
3293
|
+
init_assets();
|
|
3001
3294
|
init_context();
|
|
3002
|
-
|
|
3003
|
-
|
|
3004
|
-
|
|
3005
|
-
|
|
3006
|
-
])
|
|
3007
|
-
PROMPT_TEMPLATE = readFile("prompt.md").replace(/\{\{([^}]+)\}\}/g, (match, key) => {
|
|
3295
|
+
init_getFontLibrarySample();
|
|
3296
|
+
init_getDesignReferencesSample();
|
|
3297
|
+
SUBAGENT = "subagents/designExpert";
|
|
3298
|
+
RUNTIME_PLACEHOLDERS = /* @__PURE__ */ new Set(["font_library", "design_references"]);
|
|
3299
|
+
PROMPT_TEMPLATE = readAsset(SUBAGENT, "prompt.md").replace(/\{\{([^}]+)\}\}/g, (match, key) => {
|
|
3008
3300
|
const k = key.trim();
|
|
3009
|
-
return RUNTIME_PLACEHOLDERS.has(k) ? match :
|
|
3301
|
+
return RUNTIME_PLACEHOLDERS.has(k) ? match : readAsset(SUBAGENT, k);
|
|
3010
3302
|
}).replace(/\n{3,}/g, "\n\n");
|
|
3011
|
-
fontData = readJson("data/fonts.json", {
|
|
3012
|
-
cssUrlPattern: "",
|
|
3013
|
-
fonts: [],
|
|
3014
|
-
pairings: []
|
|
3015
|
-
});
|
|
3016
|
-
inspirationImages = readJson("data/inspiration.json", {
|
|
3017
|
-
images: []
|
|
3018
|
-
}).images;
|
|
3019
3303
|
}
|
|
3020
3304
|
});
|
|
3021
3305
|
|
|
@@ -3039,7 +3323,7 @@ Visual design expert. Describe the situation and what you need \u2014 the agent
|
|
|
3039
3323
|
properties: {
|
|
3040
3324
|
task: {
|
|
3041
3325
|
type: "string",
|
|
3042
|
-
description: "What you need, in natural language. Include context about the
|
|
3326
|
+
description: "What you need, in natural language. Include context about the project when relevant."
|
|
3043
3327
|
}
|
|
3044
3328
|
},
|
|
3045
3329
|
required: ["task"]
|
|
@@ -3054,7 +3338,7 @@ Visual design expert. Describe the situation and what you need \u2014 the agent
|
|
|
3054
3338
|
task: input.task,
|
|
3055
3339
|
tools: DESIGN_EXPERT_TOOLS,
|
|
3056
3340
|
externalTools: /* @__PURE__ */ new Set(),
|
|
3057
|
-
executeTool: (name, input2, toolCallId) => executeDesignExpertTool(name, input2, context, toolCallId),
|
|
3341
|
+
executeTool: (name, input2, toolCallId, onLog) => executeDesignExpertTool(name, input2, context, toolCallId, onLog),
|
|
3058
3342
|
apiConfig: context.apiConfig,
|
|
3059
3343
|
model: context.model,
|
|
3060
3344
|
subAgentId: "visualDesignExpert",
|
|
@@ -3176,7 +3460,7 @@ var init_tools3 = __esm({
|
|
|
3176
3460
|
|
|
3177
3461
|
// src/subagents/productVision/executor.ts
|
|
3178
3462
|
import fs14 from "fs";
|
|
3179
|
-
import
|
|
3463
|
+
import path6 from "path";
|
|
3180
3464
|
function formatRequires(requires) {
|
|
3181
3465
|
return requires.length === 0 ? "[]" : `[${requires.map((r) => `"${r}"`).join(", ")}]`;
|
|
3182
3466
|
}
|
|
@@ -3191,7 +3475,7 @@ async function executeVisionTool(name, input) {
|
|
|
3191
3475
|
requires,
|
|
3192
3476
|
body
|
|
3193
3477
|
} = input;
|
|
3194
|
-
const filePath =
|
|
3478
|
+
const filePath = path6.join(ROADMAP_DIR, `${slug}.md`);
|
|
3195
3479
|
try {
|
|
3196
3480
|
fs14.mkdirSync(ROADMAP_DIR, { recursive: true });
|
|
3197
3481
|
const oldContent = fs14.existsSync(filePath) ? fs14.readFileSync(filePath, "utf-8") : "";
|
|
@@ -3217,7 +3501,7 @@ ${unifiedDiff(filePath, oldContent, content)}`;
|
|
|
3217
3501
|
}
|
|
3218
3502
|
case "updateRoadmapItem": {
|
|
3219
3503
|
const { slug } = input;
|
|
3220
|
-
const filePath =
|
|
3504
|
+
const filePath = path6.join(ROADMAP_DIR, `${slug}.md`);
|
|
3221
3505
|
try {
|
|
3222
3506
|
if (!fs14.existsSync(filePath)) {
|
|
3223
3507
|
return `Error: ${filePath} does not exist`;
|
|
@@ -3285,7 +3569,7 @@ ${unifiedDiff(filePath, oldContent, content)}`;
|
|
|
3285
3569
|
}
|
|
3286
3570
|
case "deleteRoadmapItem": {
|
|
3287
3571
|
const { slug } = input;
|
|
3288
|
-
const filePath =
|
|
3572
|
+
const filePath = path6.join(ROADMAP_DIR, `${slug}.md`);
|
|
3289
3573
|
try {
|
|
3290
3574
|
if (!fs14.existsSync(filePath)) {
|
|
3291
3575
|
return `Error: ${filePath} does not exist`;
|
|
@@ -3313,8 +3597,6 @@ var init_executor = __esm({
|
|
|
3313
3597
|
});
|
|
3314
3598
|
|
|
3315
3599
|
// src/subagents/productVision/prompt.ts
|
|
3316
|
-
import fs15 from "fs";
|
|
3317
|
-
import path9 from "path";
|
|
3318
3600
|
function getProductVisionPrompt() {
|
|
3319
3601
|
const specContext = loadSpecContext();
|
|
3320
3602
|
const roadmapContext = loadRoadmapContext();
|
|
@@ -3327,16 +3609,14 @@ function getProductVisionPrompt() {
|
|
|
3327
3609
|
}
|
|
3328
3610
|
return parts.join("\n\n");
|
|
3329
3611
|
}
|
|
3330
|
-
var
|
|
3612
|
+
var BASE_PROMPT2;
|
|
3331
3613
|
var init_prompt3 = __esm({
|
|
3332
3614
|
"src/subagents/productVision/prompt.ts"() {
|
|
3333
3615
|
"use strict";
|
|
3616
|
+
init_assets();
|
|
3334
3617
|
init_executor();
|
|
3335
3618
|
init_context();
|
|
3336
|
-
|
|
3337
|
-
local2 = path9.join(base4, "prompt.md");
|
|
3338
|
-
PROMPT_PATH2 = fs15.existsSync(local2) ? local2 : path9.join(base4, "subagents", "productVision", "prompt.md");
|
|
3339
|
-
BASE_PROMPT2 = fs15.readFileSync(PROMPT_PATH2, "utf-8").trim();
|
|
3619
|
+
BASE_PROMPT2 = readAsset("subagents/productVision", "prompt.md");
|
|
3340
3620
|
}
|
|
3341
3621
|
});
|
|
3342
3622
|
|
|
@@ -3487,20 +3767,16 @@ var init_tools4 = __esm({
|
|
|
3487
3767
|
});
|
|
3488
3768
|
|
|
3489
3769
|
// src/subagents/codeSanityCheck/index.ts
|
|
3490
|
-
|
|
3491
|
-
import path10 from "path";
|
|
3492
|
-
var base5, local3, PROMPT_PATH3, BASE_PROMPT3, codeSanityCheckTool;
|
|
3770
|
+
var BASE_PROMPT3, codeSanityCheckTool;
|
|
3493
3771
|
var init_codeSanityCheck = __esm({
|
|
3494
3772
|
"src/subagents/codeSanityCheck/index.ts"() {
|
|
3495
3773
|
"use strict";
|
|
3774
|
+
init_assets();
|
|
3496
3775
|
init_runner();
|
|
3497
3776
|
init_context();
|
|
3498
3777
|
init_tools5();
|
|
3499
3778
|
init_tools4();
|
|
3500
|
-
|
|
3501
|
-
local3 = path10.join(base5, "prompt.md");
|
|
3502
|
-
PROMPT_PATH3 = fs16.existsSync(local3) ? local3 : path10.join(base5, "subagents", "codeSanityCheck", "prompt.md");
|
|
3503
|
-
BASE_PROMPT3 = fs16.readFileSync(PROMPT_PATH3, "utf-8").trim();
|
|
3779
|
+
BASE_PROMPT3 = readAsset("subagents/codeSanityCheck", "prompt.md");
|
|
3504
3780
|
codeSanityCheckTool = {
|
|
3505
3781
|
definition: {
|
|
3506
3782
|
name: "codeSanityCheck",
|
|
@@ -3552,7 +3828,7 @@ function getSpecTools() {
|
|
|
3552
3828
|
return [readSpecTool, writeSpecTool, editSpecTool, listSpecFilesTool];
|
|
3553
3829
|
}
|
|
3554
3830
|
function getCodeTools() {
|
|
3555
|
-
const
|
|
3831
|
+
const tools2 = [
|
|
3556
3832
|
readFileTool,
|
|
3557
3833
|
writeFileTool,
|
|
3558
3834
|
editFileTool,
|
|
@@ -3567,9 +3843,9 @@ function getCodeTools() {
|
|
|
3567
3843
|
browserAutomationTool
|
|
3568
3844
|
];
|
|
3569
3845
|
if (isLspConfigured()) {
|
|
3570
|
-
|
|
3846
|
+
tools2.push(lspDiagnosticsTool, restartProcessTool);
|
|
3571
3847
|
}
|
|
3572
|
-
return
|
|
3848
|
+
return tools2;
|
|
3573
3849
|
}
|
|
3574
3850
|
function getCommonTools() {
|
|
3575
3851
|
return [
|
|
@@ -3667,10 +3943,10 @@ var init_tools5 = __esm({
|
|
|
3667
3943
|
});
|
|
3668
3944
|
|
|
3669
3945
|
// src/session.ts
|
|
3670
|
-
import
|
|
3946
|
+
import fs15 from "fs";
|
|
3671
3947
|
function loadSession(state) {
|
|
3672
3948
|
try {
|
|
3673
|
-
const raw =
|
|
3949
|
+
const raw = fs15.readFileSync(SESSION_FILE, "utf-8");
|
|
3674
3950
|
const data = JSON.parse(raw);
|
|
3675
3951
|
if (Array.isArray(data.messages) && data.messages.length > 0) {
|
|
3676
3952
|
state.messages = sanitizeMessages(data.messages);
|
|
@@ -3718,7 +3994,7 @@ function sanitizeMessages(messages) {
|
|
|
3718
3994
|
}
|
|
3719
3995
|
function saveSession(state) {
|
|
3720
3996
|
try {
|
|
3721
|
-
|
|
3997
|
+
fs15.writeFileSync(
|
|
3722
3998
|
SESSION_FILE,
|
|
3723
3999
|
JSON.stringify({ messages: state.messages }, null, 2),
|
|
3724
4000
|
"utf-8"
|
|
@@ -3729,7 +4005,7 @@ function saveSession(state) {
|
|
|
3729
4005
|
function clearSession(state) {
|
|
3730
4006
|
state.messages = [];
|
|
3731
4007
|
try {
|
|
3732
|
-
|
|
4008
|
+
fs15.unlinkSync(SESSION_FILE);
|
|
3733
4009
|
} catch {
|
|
3734
4010
|
}
|
|
3735
4011
|
}
|
|
@@ -4053,11 +4329,11 @@ async function runTurn(params) {
|
|
|
4053
4329
|
resolveExternalTool,
|
|
4054
4330
|
hidden
|
|
4055
4331
|
} = params;
|
|
4056
|
-
const
|
|
4332
|
+
const tools2 = getToolDefinitions(onboardingState);
|
|
4057
4333
|
log.info("Turn started", {
|
|
4058
4334
|
messageLength: userMessage.length,
|
|
4059
|
-
toolCount:
|
|
4060
|
-
tools:
|
|
4335
|
+
toolCount: tools2.length,
|
|
4336
|
+
tools: tools2.map((t) => t.name),
|
|
4061
4337
|
...attachments && attachments.length > 0 && {
|
|
4062
4338
|
attachmentCount: attachments.length,
|
|
4063
4339
|
attachmentUrls: attachments.map((a) => a.url)
|
|
@@ -4186,7 +4462,7 @@ async function runTurn(params) {
|
|
|
4186
4462
|
model,
|
|
4187
4463
|
system,
|
|
4188
4464
|
messages: cleanMessagesForApi(state.messages),
|
|
4189
|
-
tools,
|
|
4465
|
+
tools: tools2,
|
|
4190
4466
|
signal
|
|
4191
4467
|
},
|
|
4192
4468
|
{
|
|
@@ -4384,7 +4660,13 @@ async function runTurn(params) {
|
|
|
4384
4660
|
onEvent: wrappedOnEvent,
|
|
4385
4661
|
resolveExternalTool,
|
|
4386
4662
|
toolCallId: tc.id,
|
|
4387
|
-
subAgentMessages
|
|
4663
|
+
subAgentMessages,
|
|
4664
|
+
onLog: (line) => wrappedOnEvent({
|
|
4665
|
+
type: "tool_input_delta",
|
|
4666
|
+
id: tc.id,
|
|
4667
|
+
name: tc.name,
|
|
4668
|
+
result: line
|
|
4669
|
+
})
|
|
4388
4670
|
});
|
|
4389
4671
|
}
|
|
4390
4672
|
const isError = result.startsWith("Error");
|
|
@@ -4475,12 +4757,12 @@ var init_agent = __esm({
|
|
|
4475
4757
|
});
|
|
4476
4758
|
|
|
4477
4759
|
// src/prompt/static/projectContext.ts
|
|
4478
|
-
import
|
|
4479
|
-
import
|
|
4760
|
+
import fs16 from "fs";
|
|
4761
|
+
import path7 from "path";
|
|
4480
4762
|
function loadProjectInstructions() {
|
|
4481
4763
|
for (const file of AGENT_INSTRUCTION_FILES) {
|
|
4482
4764
|
try {
|
|
4483
|
-
const content =
|
|
4765
|
+
const content = fs16.readFileSync(file, "utf-8").trim();
|
|
4484
4766
|
if (content) {
|
|
4485
4767
|
return `
|
|
4486
4768
|
## Project Instructions (${file})
|
|
@@ -4493,7 +4775,7 @@ ${content}`;
|
|
|
4493
4775
|
}
|
|
4494
4776
|
function loadProjectManifest() {
|
|
4495
4777
|
try {
|
|
4496
|
-
const manifest =
|
|
4778
|
+
const manifest = fs16.readFileSync("mindstudio.json", "utf-8");
|
|
4497
4779
|
return `
|
|
4498
4780
|
## Project Manifest (mindstudio.json)
|
|
4499
4781
|
\`\`\`json
|
|
@@ -4534,9 +4816,9 @@ ${entries.join("\n")}`;
|
|
|
4534
4816
|
function walkMdFiles2(dir) {
|
|
4535
4817
|
const results = [];
|
|
4536
4818
|
try {
|
|
4537
|
-
const entries =
|
|
4819
|
+
const entries = fs16.readdirSync(dir, { withFileTypes: true });
|
|
4538
4820
|
for (const entry of entries) {
|
|
4539
|
-
const full =
|
|
4821
|
+
const full = path7.join(dir, entry.name);
|
|
4540
4822
|
if (entry.isDirectory()) {
|
|
4541
4823
|
results.push(...walkMdFiles2(full));
|
|
4542
4824
|
} else if (entry.name.endsWith(".md")) {
|
|
@@ -4549,7 +4831,7 @@ function walkMdFiles2(dir) {
|
|
|
4549
4831
|
}
|
|
4550
4832
|
function parseFrontmatter(filePath) {
|
|
4551
4833
|
try {
|
|
4552
|
-
const content =
|
|
4834
|
+
const content = fs16.readFileSync(filePath, "utf-8");
|
|
4553
4835
|
const match = content.match(/^---\n([\s\S]*?)\n---/);
|
|
4554
4836
|
if (!match) {
|
|
4555
4837
|
return { name: "", description: "", type: "" };
|
|
@@ -4565,7 +4847,7 @@ function parseFrontmatter(filePath) {
|
|
|
4565
4847
|
}
|
|
4566
4848
|
function loadProjectFileListing() {
|
|
4567
4849
|
try {
|
|
4568
|
-
const entries =
|
|
4850
|
+
const entries = fs16.readdirSync(".", { withFileTypes: true });
|
|
4569
4851
|
const listing = entries.filter((e) => e.name !== ".git" && e.name !== "node_modules").sort((a, b) => {
|
|
4570
4852
|
if (a.isDirectory() && !b.isDirectory()) {
|
|
4571
4853
|
return -1;
|
|
@@ -4608,20 +4890,10 @@ var init_projectContext = __esm({
|
|
|
4608
4890
|
});
|
|
4609
4891
|
|
|
4610
4892
|
// src/prompt/index.ts
|
|
4611
|
-
import fs19 from "fs";
|
|
4612
|
-
import path12 from "path";
|
|
4613
|
-
function requireFile(filePath) {
|
|
4614
|
-
const full = path12.join(PROMPT_DIR, filePath);
|
|
4615
|
-
try {
|
|
4616
|
-
return fs19.readFileSync(full, "utf-8").trim();
|
|
4617
|
-
} catch {
|
|
4618
|
-
throw new Error(`Required prompt file missing: ${full}`);
|
|
4619
|
-
}
|
|
4620
|
-
}
|
|
4621
4893
|
function resolveIncludes(template) {
|
|
4622
4894
|
const result = template.replace(
|
|
4623
4895
|
/\{\{([^}]+)\}\}/g,
|
|
4624
|
-
(_, filePath) =>
|
|
4896
|
+
(_, filePath) => readAsset("prompt", filePath.trim())
|
|
4625
4897
|
);
|
|
4626
4898
|
return result.replace(/\n{3,}/g, "\n\n").trim();
|
|
4627
4899
|
}
|
|
@@ -4731,23 +5003,22 @@ ${viewContext?.activeFile ? `Active file: ${viewContext.activeFile}` : ""}
|
|
|
4731
5003
|
`;
|
|
4732
5004
|
return resolveIncludes(template);
|
|
4733
5005
|
}
|
|
4734
|
-
var PROMPT_DIR;
|
|
4735
5006
|
var init_prompt4 = __esm({
|
|
4736
5007
|
"src/prompt/index.ts"() {
|
|
4737
5008
|
"use strict";
|
|
5009
|
+
init_assets();
|
|
4738
5010
|
init_lsp();
|
|
4739
5011
|
init_projectContext();
|
|
4740
|
-
PROMPT_DIR = import.meta.dirname ?? path12.dirname(new URL(import.meta.url).pathname);
|
|
4741
5012
|
}
|
|
4742
5013
|
});
|
|
4743
5014
|
|
|
4744
5015
|
// src/config.ts
|
|
4745
|
-
import
|
|
4746
|
-
import
|
|
5016
|
+
import fs17 from "fs";
|
|
5017
|
+
import path8 from "path";
|
|
4747
5018
|
import os from "os";
|
|
4748
5019
|
function loadConfigFile() {
|
|
4749
5020
|
try {
|
|
4750
|
-
const raw =
|
|
5021
|
+
const raw = fs17.readFileSync(CONFIG_PATH, "utf-8");
|
|
4751
5022
|
log.debug("Loaded config file", { path: CONFIG_PATH });
|
|
4752
5023
|
return JSON.parse(raw);
|
|
4753
5024
|
} catch (err) {
|
|
@@ -4783,7 +5054,7 @@ var init_config = __esm({
|
|
|
4783
5054
|
"src/config.ts"() {
|
|
4784
5055
|
"use strict";
|
|
4785
5056
|
init_logger();
|
|
4786
|
-
CONFIG_PATH =
|
|
5057
|
+
CONFIG_PATH = path8.join(
|
|
4787
5058
|
os.homedir(),
|
|
4788
5059
|
".mindstudio-local-tunnel",
|
|
4789
5060
|
"config.json"
|
|
@@ -4798,10 +5069,8 @@ __export(headless_exports, {
|
|
|
4798
5069
|
startHeadless: () => startHeadless
|
|
4799
5070
|
});
|
|
4800
5071
|
import { createInterface } from "readline";
|
|
4801
|
-
import fs21 from "fs";
|
|
4802
|
-
import path14 from "path";
|
|
4803
5072
|
function loadActionPrompt(name) {
|
|
4804
|
-
return
|
|
5073
|
+
return readAsset("prompt", "actions", `${name}.md`);
|
|
4805
5074
|
}
|
|
4806
5075
|
function emit(event, data, requestId) {
|
|
4807
5076
|
const payload = { event, ...data };
|
|
@@ -5107,25 +5376,23 @@ async function startHeadless(opts = {}) {
|
|
|
5107
5376
|
process.on("SIGINT", shutdown);
|
|
5108
5377
|
emit("ready");
|
|
5109
5378
|
}
|
|
5110
|
-
var BASE_DIR, ACTIONS_DIR;
|
|
5111
5379
|
var init_headless = __esm({
|
|
5112
5380
|
"src/headless.ts"() {
|
|
5113
5381
|
"use strict";
|
|
5382
|
+
init_assets();
|
|
5114
5383
|
init_config();
|
|
5115
5384
|
init_prompt4();
|
|
5116
5385
|
init_lsp();
|
|
5117
5386
|
init_agent();
|
|
5118
5387
|
init_session();
|
|
5119
|
-
BASE_DIR = import.meta.dirname ?? path14.dirname(new URL(import.meta.url).pathname);
|
|
5120
|
-
ACTIONS_DIR = path14.join(BASE_DIR, "actions");
|
|
5121
5388
|
}
|
|
5122
5389
|
});
|
|
5123
5390
|
|
|
5124
5391
|
// src/index.tsx
|
|
5125
5392
|
import { render } from "ink";
|
|
5126
5393
|
import os2 from "os";
|
|
5127
|
-
import
|
|
5128
|
-
import
|
|
5394
|
+
import fs18 from "fs";
|
|
5395
|
+
import path9 from "path";
|
|
5129
5396
|
|
|
5130
5397
|
// src/tui/App.tsx
|
|
5131
5398
|
import { useState as useState2, useCallback, useRef } from "react";
|
|
@@ -5442,8 +5709,8 @@ for (let i = 0; i < args.length; i++) {
|
|
|
5442
5709
|
}
|
|
5443
5710
|
function printDebugInfo(config) {
|
|
5444
5711
|
const pkg = JSON.parse(
|
|
5445
|
-
|
|
5446
|
-
|
|
5712
|
+
fs18.readFileSync(
|
|
5713
|
+
path9.join(import.meta.dirname, "..", "package.json"),
|
|
5447
5714
|
"utf-8"
|
|
5448
5715
|
)
|
|
5449
5716
|
);
|