@mindstudio-ai/remy 0.1.74 → 0.1.76
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 +135 -68
- package/dist/index.js +160 -76
- package/dist/prompt/compiled/auth.md +3 -3
- package/dist/prompt/compiled/methods.md +5 -5
- package/dist/prompt/compiled/tables.md +19 -7
- package/dist/subagents/designExpert/data/sources/ui_inspiration.json +49 -1
- package/dist/subagents/designExpert/data/sources/ui_inspiration_compiled.json +192 -0
- package/dist/subagents/designExpert/prompts/images.md +13 -0
- package/dist/subagents/designExpert/tools/images/enhance-image-prompt.md +12 -0
- package/package.json +1 -1
package/dist/headless.js
CHANGED
|
@@ -1706,9 +1706,9 @@ var setProjectMetadataTool = {
|
|
|
1706
1706
|
import fs9 from "fs/promises";
|
|
1707
1707
|
var DEFAULT_MAX_LINES2 = 500;
|
|
1708
1708
|
function isBinary(buffer) {
|
|
1709
|
-
const
|
|
1710
|
-
for (let i = 0; i <
|
|
1711
|
-
if (
|
|
1709
|
+
const sample = buffer.subarray(0, 8192);
|
|
1710
|
+
for (let i = 0; i < sample.length; i++) {
|
|
1711
|
+
if (sample[i] === 0) {
|
|
1712
1712
|
return true;
|
|
1713
1713
|
}
|
|
1714
1714
|
}
|
|
@@ -2328,13 +2328,17 @@ var runScenarioTool = {
|
|
|
2328
2328
|
clearable: true,
|
|
2329
2329
|
definition: {
|
|
2330
2330
|
name: "runScenario",
|
|
2331
|
-
description: "Run a scenario to seed the dev database with test data.
|
|
2331
|
+
description: "Run a scenario to seed the dev database with test data. By default truncates all tables first, then executes the seed function and impersonates the scenario roles. Use skipTruncate to run the seed function against existing data without resetting. Blocks until complete. Scenario IDs are defined in mindstudio.json. If it fails, check .logs/tunnel.log or .logs/requests.ndjson for details. Return synchronously - no need to sleep before checking results.",
|
|
2332
2332
|
inputSchema: {
|
|
2333
2333
|
type: "object",
|
|
2334
2334
|
properties: {
|
|
2335
2335
|
scenarioId: {
|
|
2336
2336
|
type: "string",
|
|
2337
2337
|
description: "The scenario ID from mindstudio.json."
|
|
2338
|
+
},
|
|
2339
|
+
skipTruncate: {
|
|
2340
|
+
type: "boolean",
|
|
2341
|
+
description: "When true, skip the database reset step and run the seed function against existing data. Defaults to false (clean-slate)."
|
|
2338
2342
|
}
|
|
2339
2343
|
},
|
|
2340
2344
|
required: ["scenarioId"]
|
|
@@ -2371,6 +2375,28 @@ var runMethodTool = {
|
|
|
2371
2375
|
}
|
|
2372
2376
|
};
|
|
2373
2377
|
|
|
2378
|
+
// src/tools/code/queryDatabase.ts
|
|
2379
|
+
var queryDatabaseTool = {
|
|
2380
|
+
clearable: true,
|
|
2381
|
+
definition: {
|
|
2382
|
+
name: "queryDatabase",
|
|
2383
|
+
description: "Execute a raw SQL query against the dev database and return the results. Use for inspecting data and debugging issues.",
|
|
2384
|
+
inputSchema: {
|
|
2385
|
+
type: "object",
|
|
2386
|
+
properties: {
|
|
2387
|
+
sql: {
|
|
2388
|
+
type: "string",
|
|
2389
|
+
description: "The SQL query to execute."
|
|
2390
|
+
}
|
|
2391
|
+
},
|
|
2392
|
+
required: ["sql"]
|
|
2393
|
+
}
|
|
2394
|
+
},
|
|
2395
|
+
async execute() {
|
|
2396
|
+
return "ok";
|
|
2397
|
+
}
|
|
2398
|
+
};
|
|
2399
|
+
|
|
2374
2400
|
// src/subagents/common/analyzeImage.ts
|
|
2375
2401
|
var VISION_MODEL = "gemini-3-flash";
|
|
2376
2402
|
var VISION_MODEL_OVERRIDE = JSON.stringify({
|
|
@@ -3739,7 +3765,7 @@ async function executeDesignExpertTool(name, input, context, toolCallId, onLog)
|
|
|
3739
3765
|
}
|
|
3740
3766
|
|
|
3741
3767
|
// src/subagents/designExpert/prompt.ts
|
|
3742
|
-
import
|
|
3768
|
+
import fs16 from "fs";
|
|
3743
3769
|
|
|
3744
3770
|
// src/subagents/common/context.ts
|
|
3745
3771
|
import fs14 from "fs";
|
|
@@ -3841,25 +3867,74 @@ The first-party SDK (@mindstudio-ai/agent) provides access to 200+ AI models (Op
|
|
|
3841
3867
|
</platform_brief>`;
|
|
3842
3868
|
}
|
|
3843
3869
|
|
|
3870
|
+
// src/subagents/designExpert/data/sampleCache.ts
|
|
3871
|
+
import fs15 from "fs";
|
|
3872
|
+
var SAMPLE_FILE = ".remy-design-sample.json";
|
|
3873
|
+
var cached = null;
|
|
3874
|
+
function generateIndices(poolSize, sampleSize) {
|
|
3875
|
+
const n = Math.min(sampleSize, poolSize);
|
|
3876
|
+
const indices = Array.from({ length: poolSize }, (_, i) => i);
|
|
3877
|
+
for (let i = indices.length - 1; i > 0; i--) {
|
|
3878
|
+
const j = Math.floor(Math.random() * (i + 1));
|
|
3879
|
+
[indices[i], indices[j]] = [indices[j], indices[i]];
|
|
3880
|
+
}
|
|
3881
|
+
return indices.slice(0, n);
|
|
3882
|
+
}
|
|
3883
|
+
function load() {
|
|
3884
|
+
try {
|
|
3885
|
+
return JSON.parse(fs15.readFileSync(SAMPLE_FILE, "utf-8"));
|
|
3886
|
+
} catch {
|
|
3887
|
+
return null;
|
|
3888
|
+
}
|
|
3889
|
+
}
|
|
3890
|
+
function save(indices) {
|
|
3891
|
+
try {
|
|
3892
|
+
fs15.writeFileSync(SAMPLE_FILE, JSON.stringify(indices));
|
|
3893
|
+
} catch {
|
|
3894
|
+
}
|
|
3895
|
+
}
|
|
3896
|
+
function getSampleIndices(pools, sizes) {
|
|
3897
|
+
if (cached) {
|
|
3898
|
+
return cached;
|
|
3899
|
+
}
|
|
3900
|
+
const loaded = load();
|
|
3901
|
+
if (loaded) {
|
|
3902
|
+
let dirty = false;
|
|
3903
|
+
for (const key of ["uiInspiration", "designReferences", "fonts"]) {
|
|
3904
|
+
const before = loaded[key].length;
|
|
3905
|
+
loaded[key] = loaded[key].filter((i) => i < pools[key]);
|
|
3906
|
+
if (loaded[key].length < before) {
|
|
3907
|
+
dirty = true;
|
|
3908
|
+
}
|
|
3909
|
+
}
|
|
3910
|
+
if (dirty) {
|
|
3911
|
+
save(loaded);
|
|
3912
|
+
}
|
|
3913
|
+
cached = loaded;
|
|
3914
|
+
return cached;
|
|
3915
|
+
}
|
|
3916
|
+
cached = {
|
|
3917
|
+
uiInspiration: generateIndices(pools.uiInspiration, sizes.uiInspiration),
|
|
3918
|
+
designReferences: generateIndices(
|
|
3919
|
+
pools.designReferences,
|
|
3920
|
+
sizes.designReferences
|
|
3921
|
+
),
|
|
3922
|
+
fonts: generateIndices(pools.fonts, sizes.fonts)
|
|
3923
|
+
};
|
|
3924
|
+
save(cached);
|
|
3925
|
+
return cached;
|
|
3926
|
+
}
|
|
3927
|
+
function pickByIndices(arr, indices) {
|
|
3928
|
+
return indices.filter((i) => i < arr.length).map((i) => arr[i]);
|
|
3929
|
+
}
|
|
3930
|
+
|
|
3844
3931
|
// src/subagents/designExpert/data/getFontLibrarySample.ts
|
|
3845
3932
|
var fontData = readJsonAsset(
|
|
3846
|
-
{ cssUrlPattern: "", fonts: []
|
|
3933
|
+
{ cssUrlPattern: "", fonts: [] },
|
|
3847
3934
|
"subagents/designExpert/data/sources/fonts.json"
|
|
3848
3935
|
);
|
|
3849
|
-
function
|
|
3850
|
-
|
|
3851
|
-
return [...arr];
|
|
3852
|
-
}
|
|
3853
|
-
const copy = [...arr];
|
|
3854
|
-
for (let i = copy.length - 1; i > 0; i--) {
|
|
3855
|
-
const j = Math.floor(Math.random() * (i + 1));
|
|
3856
|
-
[copy[i], copy[j]] = [copy[j], copy[i]];
|
|
3857
|
-
}
|
|
3858
|
-
return copy.slice(0, n);
|
|
3859
|
-
}
|
|
3860
|
-
function getFontLibrarySample() {
|
|
3861
|
-
const fonts = sample(fontData.fonts, 60);
|
|
3862
|
-
const pairings = sample(fontData.pairings, 30);
|
|
3936
|
+
function getFontLibrarySample(fontIndices) {
|
|
3937
|
+
const fonts = pickByIndices(fontData.fonts, fontIndices);
|
|
3863
3938
|
if (!fonts.length) {
|
|
3864
3939
|
return "";
|
|
3865
3940
|
}
|
|
@@ -3875,16 +3950,11 @@ function getFontLibrarySample() {
|
|
|
3875
3950
|
const desc = f.description ? ` ${f.description}` : "";
|
|
3876
3951
|
return `- **${f.name}** \u2014 ${f.category}. Weights: ${f.weights.join(", ")}.${f.variable ? " Variable." : ""}${f.italics ? " Has italics." : ""}${cssInfo}${desc}`;
|
|
3877
3952
|
}).join("\n");
|
|
3878
|
-
const pairingList = pairings.map(
|
|
3879
|
-
(p) => `- **${p.heading.font}** (${p.heading.weight}) heading + **${p.body.font}** (${p.body.weight}) body`
|
|
3880
|
-
).join("\n");
|
|
3881
3953
|
return `
|
|
3882
3954
|
## Font Library
|
|
3883
3955
|
|
|
3884
3956
|
This is your personal library of fonts you love. Use it as a starting point when thinking about anything related to typography.
|
|
3885
3957
|
|
|
3886
|
-
### Fonts
|
|
3887
|
-
|
|
3888
3958
|
${fontList}`.trim();
|
|
3889
3959
|
}
|
|
3890
3960
|
|
|
@@ -3893,19 +3963,8 @@ var inspirationImages = readJsonAsset(
|
|
|
3893
3963
|
{ images: [] },
|
|
3894
3964
|
"subagents/designExpert/data/sources/inspiration.json"
|
|
3895
3965
|
).images;
|
|
3896
|
-
function
|
|
3897
|
-
|
|
3898
|
-
return [...arr];
|
|
3899
|
-
}
|
|
3900
|
-
const copy = [...arr];
|
|
3901
|
-
for (let i = copy.length - 1; i > 0; i--) {
|
|
3902
|
-
const j = Math.floor(Math.random() * (i + 1));
|
|
3903
|
-
[copy[i], copy[j]] = [copy[j], copy[i]];
|
|
3904
|
-
}
|
|
3905
|
-
return copy.slice(0, n);
|
|
3906
|
-
}
|
|
3907
|
-
function getDesignReferencesSample() {
|
|
3908
|
-
const images = sample2(inspirationImages, 25);
|
|
3966
|
+
function getDesignReferencesSample(indices) {
|
|
3967
|
+
const images = pickByIndices(inspirationImages, indices);
|
|
3909
3968
|
if (!images.length) {
|
|
3910
3969
|
return "";
|
|
3911
3970
|
}
|
|
@@ -3924,19 +3983,8 @@ var uiScreens = readJsonAsset(
|
|
|
3924
3983
|
{ screens: [] },
|
|
3925
3984
|
"subagents/designExpert/data/sources/ui_inspiration_compiled.json"
|
|
3926
3985
|
).screens;
|
|
3927
|
-
function
|
|
3928
|
-
|
|
3929
|
-
return [...arr];
|
|
3930
|
-
}
|
|
3931
|
-
const copy = [...arr];
|
|
3932
|
-
for (let i = copy.length - 1; i > 0; i--) {
|
|
3933
|
-
const j = Math.floor(Math.random() * (i + 1));
|
|
3934
|
-
[copy[i], copy[j]] = [copy[j], copy[i]];
|
|
3935
|
-
}
|
|
3936
|
-
return copy.slice(0, n);
|
|
3937
|
-
}
|
|
3938
|
-
function getUiInspirationSample() {
|
|
3939
|
-
const screens = sample3(uiScreens, 25);
|
|
3986
|
+
function getUiInspirationSample(indices) {
|
|
3987
|
+
const screens = pickByIndices(uiScreens, indices);
|
|
3940
3988
|
if (!screens.length) {
|
|
3941
3989
|
return "";
|
|
3942
3990
|
}
|
|
@@ -3963,10 +4011,28 @@ var PROMPT_TEMPLATE = readAsset(SUBAGENT, "prompt.md").replace(/\{\{([^}]+)\}\}/
|
|
|
3963
4011
|
}).replace(/\n{3,}/g, "\n\n");
|
|
3964
4012
|
function getDesignExpertPrompt() {
|
|
3965
4013
|
const specContext = loadSpecContext();
|
|
4014
|
+
const indices = getSampleIndices(
|
|
4015
|
+
{
|
|
4016
|
+
uiInspiration: uiScreens.length,
|
|
4017
|
+
designReferences: inspirationImages.length,
|
|
4018
|
+
fonts: fontData.fonts.length
|
|
4019
|
+
},
|
|
4020
|
+
{
|
|
4021
|
+
uiInspiration: 50,
|
|
4022
|
+
designReferences: 50,
|
|
4023
|
+
fonts: 50
|
|
4024
|
+
}
|
|
4025
|
+
);
|
|
3966
4026
|
let prompt = PROMPT_TEMPLATE.replace(
|
|
3967
4027
|
"{{font_library}}",
|
|
3968
|
-
getFontLibrarySample()
|
|
3969
|
-
).replace(
|
|
4028
|
+
getFontLibrarySample(indices.fonts)
|
|
4029
|
+
).replace(
|
|
4030
|
+
"{{visual_design_references}}",
|
|
4031
|
+
getDesignReferencesSample(indices.designReferences)
|
|
4032
|
+
).replace(
|
|
4033
|
+
"{{ui_case_studies}}",
|
|
4034
|
+
getUiInspirationSample(indices.uiInspiration)
|
|
4035
|
+
);
|
|
3970
4036
|
prompt += "\n\n<!-- cache_breakpoint -->";
|
|
3971
4037
|
if (specContext) {
|
|
3972
4038
|
prompt += `
|
|
@@ -3974,7 +4040,7 @@ function getDesignExpertPrompt() {
|
|
|
3974
4040
|
${specContext}`;
|
|
3975
4041
|
}
|
|
3976
4042
|
try {
|
|
3977
|
-
|
|
4043
|
+
fs16.writeFileSync(`.design-prompt.md`, prompt);
|
|
3978
4044
|
} catch {
|
|
3979
4045
|
}
|
|
3980
4046
|
return prompt;
|
|
@@ -4183,7 +4249,7 @@ var VISION_TOOLS = [
|
|
|
4183
4249
|
];
|
|
4184
4250
|
|
|
4185
4251
|
// src/subagents/productVision/executor.ts
|
|
4186
|
-
import
|
|
4252
|
+
import fs17 from "fs";
|
|
4187
4253
|
import path8 from "path";
|
|
4188
4254
|
var ROADMAP_DIR = "src/roadmap";
|
|
4189
4255
|
function formatRequires(requires) {
|
|
@@ -4202,8 +4268,8 @@ async function executeVisionTool(name, input) {
|
|
|
4202
4268
|
} = input;
|
|
4203
4269
|
const filePath = path8.join(ROADMAP_DIR, `${slug}.md`);
|
|
4204
4270
|
try {
|
|
4205
|
-
|
|
4206
|
-
const oldContent =
|
|
4271
|
+
fs17.mkdirSync(ROADMAP_DIR, { recursive: true });
|
|
4272
|
+
const oldContent = fs17.existsSync(filePath) ? fs17.readFileSync(filePath, "utf-8") : "";
|
|
4207
4273
|
const content = `---
|
|
4208
4274
|
name: ${itemName}
|
|
4209
4275
|
type: roadmap
|
|
@@ -4215,7 +4281,7 @@ requires: ${formatRequires(requires)}
|
|
|
4215
4281
|
|
|
4216
4282
|
${body}
|
|
4217
4283
|
`;
|
|
4218
|
-
|
|
4284
|
+
fs17.writeFileSync(filePath, content, "utf-8");
|
|
4219
4285
|
const lineCount = content.split("\n").length;
|
|
4220
4286
|
const label = oldContent ? "Updated" : "Wrote";
|
|
4221
4287
|
return `${label} ${filePath} (${lineCount} lines)
|
|
@@ -4228,10 +4294,10 @@ ${unifiedDiff(filePath, oldContent, content)}`;
|
|
|
4228
4294
|
const { slug } = input;
|
|
4229
4295
|
const filePath = path8.join(ROADMAP_DIR, `${slug}.md`);
|
|
4230
4296
|
try {
|
|
4231
|
-
if (!
|
|
4297
|
+
if (!fs17.existsSync(filePath)) {
|
|
4232
4298
|
return `Error: ${filePath} does not exist`;
|
|
4233
4299
|
}
|
|
4234
|
-
const oldContent =
|
|
4300
|
+
const oldContent = fs17.readFileSync(filePath, "utf-8");
|
|
4235
4301
|
let content = oldContent;
|
|
4236
4302
|
if (input.status) {
|
|
4237
4303
|
content = content.replace(
|
|
@@ -4284,7 +4350,7 @@ ${input.appendHistory}
|
|
|
4284
4350
|
`;
|
|
4285
4351
|
}
|
|
4286
4352
|
}
|
|
4287
|
-
|
|
4353
|
+
fs17.writeFileSync(filePath, content, "utf-8");
|
|
4288
4354
|
const lineCount = content.split("\n").length;
|
|
4289
4355
|
return `Updated ${filePath} (${lineCount} lines)
|
|
4290
4356
|
${unifiedDiff(filePath, oldContent, content)}`;
|
|
@@ -4296,11 +4362,11 @@ ${unifiedDiff(filePath, oldContent, content)}`;
|
|
|
4296
4362
|
const { slug } = input;
|
|
4297
4363
|
const filePath = path8.join(ROADMAP_DIR, `${slug}.md`);
|
|
4298
4364
|
try {
|
|
4299
|
-
if (!
|
|
4365
|
+
if (!fs17.existsSync(filePath)) {
|
|
4300
4366
|
return `Error: ${filePath} does not exist`;
|
|
4301
4367
|
}
|
|
4302
|
-
const oldContent =
|
|
4303
|
-
|
|
4368
|
+
const oldContent = fs17.readFileSync(filePath, "utf-8");
|
|
4369
|
+
fs17.unlinkSync(filePath);
|
|
4304
4370
|
return `Deleted ${filePath}
|
|
4305
4371
|
${unifiedDiff(filePath, oldContent, "")}`;
|
|
4306
4372
|
} catch (err) {
|
|
@@ -4595,6 +4661,7 @@ var ALL_TOOLS = [
|
|
|
4595
4661
|
editsFinishedTool,
|
|
4596
4662
|
runScenarioTool,
|
|
4597
4663
|
runMethodTool,
|
|
4664
|
+
queryDatabaseTool,
|
|
4598
4665
|
screenshotTool,
|
|
4599
4666
|
browserAutomationTool,
|
|
4600
4667
|
// LSP
|
|
@@ -4619,12 +4686,12 @@ function executeTool(name, input, context) {
|
|
|
4619
4686
|
}
|
|
4620
4687
|
|
|
4621
4688
|
// src/session.ts
|
|
4622
|
-
import
|
|
4689
|
+
import fs18 from "fs";
|
|
4623
4690
|
var log7 = createLogger("session");
|
|
4624
4691
|
var SESSION_FILE = ".remy-session.json";
|
|
4625
4692
|
function loadSession(state) {
|
|
4626
4693
|
try {
|
|
4627
|
-
const raw =
|
|
4694
|
+
const raw = fs18.readFileSync(SESSION_FILE, "utf-8");
|
|
4628
4695
|
const data = JSON.parse(raw);
|
|
4629
4696
|
if (Array.isArray(data.messages) && data.messages.length > 0) {
|
|
4630
4697
|
state.messages = sanitizeMessages(data.messages);
|
|
@@ -4673,7 +4740,7 @@ function sanitizeMessages(messages) {
|
|
|
4673
4740
|
}
|
|
4674
4741
|
function saveSession(state) {
|
|
4675
4742
|
try {
|
|
4676
|
-
|
|
4743
|
+
fs18.writeFileSync(
|
|
4677
4744
|
SESSION_FILE,
|
|
4678
4745
|
JSON.stringify({ messages: state.messages }, null, 2),
|
|
4679
4746
|
"utf-8"
|
|
@@ -4686,7 +4753,7 @@ function saveSession(state) {
|
|
|
4686
4753
|
function clearSession(state) {
|
|
4687
4754
|
state.messages = [];
|
|
4688
4755
|
try {
|
|
4689
|
-
|
|
4756
|
+
fs18.unlinkSync(SESSION_FILE);
|
|
4690
4757
|
} catch {
|
|
4691
4758
|
}
|
|
4692
4759
|
}
|