@mindstudio-ai/remy 0.1.313 → 0.1.315
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 +349 -232
- package/dist/index.js +406 -281
- package/dist/prompt/compiled/platform.md +1 -1
- package/dist/prompt/skills/realtimeEvents.md +32 -6
- package/dist/prompt/static/coding.md +1 -1
- package/dist/prompt/static/intake.md +1 -1
- package/dist/prompt/static/team.md +8 -0
- package/dist/subagents/codeSanityCheck/prompt.md +2 -0
- package/dist/subagents/research/prompt.md +25 -0
- package/package.json +1 -1
package/dist/headless.js
CHANGED
|
@@ -434,6 +434,13 @@ var MODEL_SURFACES = {
|
|
|
434
434
|
modelType: "text",
|
|
435
435
|
userPickable: true
|
|
436
436
|
},
|
|
437
|
+
research: {
|
|
438
|
+
default: "claude-5-sonnet",
|
|
439
|
+
label: "Research Agent",
|
|
440
|
+
description: "Researches using the web and reports back with citations.",
|
|
441
|
+
modelType: "text",
|
|
442
|
+
userPickable: true
|
|
443
|
+
},
|
|
437
444
|
copyEditor: {
|
|
438
445
|
default: "claude-5-sonnet",
|
|
439
446
|
label: "Copy Agent",
|
|
@@ -519,6 +526,8 @@ var TEXT_MODELS = {
|
|
|
519
526
|
// 500K window
|
|
520
527
|
"glm-5.2": { forceCompactAt: 85e4 },
|
|
521
528
|
"muse-spark-1.1": { forceCompactAt: 85e4 },
|
|
529
|
+
"muse-spark-1.2": { forceCompactAt: 85e4 },
|
|
530
|
+
"muse-spark-1.3": { forceCompactAt: 85e4 },
|
|
522
531
|
"kimi-k2-7-code": { forceCompactAt: 2e5 },
|
|
523
532
|
// 262K window
|
|
524
533
|
"kimi-k3": { forceCompactAt: 85e4 },
|
|
@@ -1884,158 +1893,6 @@ var askMindStudioSdkTool = {
|
|
|
1884
1893
|
}
|
|
1885
1894
|
};
|
|
1886
1895
|
|
|
1887
|
-
// src/usageLedger.ts
|
|
1888
|
-
import fs12 from "fs";
|
|
1889
|
-
var LEDGER_FILE = ".logs/usage.ndjson";
|
|
1890
|
-
var fd = null;
|
|
1891
|
-
function nanoToDollars(nano) {
|
|
1892
|
-
return typeof nano === "number" ? nano / 1e9 : void 0;
|
|
1893
|
-
}
|
|
1894
|
-
function recordUsage(entry) {
|
|
1895
|
-
try {
|
|
1896
|
-
if (fd === null) {
|
|
1897
|
-
fs12.mkdirSync(".logs", { recursive: true });
|
|
1898
|
-
fd = fs12.openSync(LEDGER_FILE, "a");
|
|
1899
|
-
}
|
|
1900
|
-
fs12.writeSync(fd, JSON.stringify(entry) + "\n");
|
|
1901
|
-
} catch {
|
|
1902
|
-
}
|
|
1903
|
-
}
|
|
1904
|
-
|
|
1905
|
-
// src/subagents/common/runMindstudioCli.ts
|
|
1906
|
-
function stripFlags(args) {
|
|
1907
|
-
const out = [];
|
|
1908
|
-
for (let i = 0; i < args.length; i++) {
|
|
1909
|
-
const arg = args[i];
|
|
1910
|
-
if (arg === "--no-meta") {
|
|
1911
|
-
continue;
|
|
1912
|
-
}
|
|
1913
|
-
if (arg === "--output-key") {
|
|
1914
|
-
i++;
|
|
1915
|
-
continue;
|
|
1916
|
-
}
|
|
1917
|
-
out.push(arg);
|
|
1918
|
-
}
|
|
1919
|
-
return out;
|
|
1920
|
-
}
|
|
1921
|
-
async function runMindstudioCliResult(args, options) {
|
|
1922
|
-
const cleanArgs = stripFlags(args);
|
|
1923
|
-
const cliAction = args[0];
|
|
1924
|
-
const agentName = options?.caller ?? "mindstudio-cli";
|
|
1925
|
-
const start = Date.now();
|
|
1926
|
-
const res = await runCli("mindstudio", cleanArgs, options);
|
|
1927
|
-
if (!res.ok) {
|
|
1928
|
-
return { ok: false, value: formatCliResult(res) };
|
|
1929
|
-
}
|
|
1930
|
-
const truncNote = res.truncated ? "\n\n[output truncated]" : "";
|
|
1931
|
-
let envelope;
|
|
1932
|
-
try {
|
|
1933
|
-
envelope = JSON.parse(res.output);
|
|
1934
|
-
} catch {
|
|
1935
|
-
return { ok: true, value: res.output + truncNote };
|
|
1936
|
-
}
|
|
1937
|
-
if (envelope && typeof envelope === "object" && Array.isArray(envelope.results)) {
|
|
1938
|
-
const durationMs = Date.now() - start;
|
|
1939
|
-
for (const step of envelope.results) {
|
|
1940
|
-
if (typeof step?.billingCost === "number") {
|
|
1941
|
-
recordUsage({
|
|
1942
|
-
ts: Date.now(),
|
|
1943
|
-
agentName,
|
|
1944
|
-
cliAction: `${cliAction}:${step.stepType ?? "step"}`,
|
|
1945
|
-
cost: nanoToDollars(step.billingCost),
|
|
1946
|
-
inputTokens: 0,
|
|
1947
|
-
outputTokens: 0,
|
|
1948
|
-
durationMs,
|
|
1949
|
-
toolNames: []
|
|
1950
|
-
});
|
|
1951
|
-
}
|
|
1952
|
-
}
|
|
1953
|
-
return { ok: true, value: JSON.stringify(envelope.results) + truncNote };
|
|
1954
|
-
}
|
|
1955
|
-
if (typeof envelope?.$billingCost === "number") {
|
|
1956
|
-
recordUsage({
|
|
1957
|
-
ts: Date.now(),
|
|
1958
|
-
agentName,
|
|
1959
|
-
cliAction,
|
|
1960
|
-
cost: nanoToDollars(envelope.$billingCost),
|
|
1961
|
-
billingEvents: envelope.$billingEvents,
|
|
1962
|
-
// CLI billing isn't expressed as input/output tokens for most actions
|
|
1963
|
-
// (image gen is per-image, scrape per-page, etc). `numUnits` inside each
|
|
1964
|
-
// billingEvent carries the per-event unit count.
|
|
1965
|
-
inputTokens: 0,
|
|
1966
|
-
outputTokens: 0,
|
|
1967
|
-
durationMs: Date.now() - start,
|
|
1968
|
-
toolNames: []
|
|
1969
|
-
});
|
|
1970
|
-
}
|
|
1971
|
-
if (options?.outputKey) {
|
|
1972
|
-
const v = envelope?.[options.outputKey];
|
|
1973
|
-
if (v === void 0 || v === null) {
|
|
1974
|
-
return { ok: false, value: JSON.stringify(stripDollarKeys(envelope)) };
|
|
1975
|
-
}
|
|
1976
|
-
const value = typeof v === "string" ? v : JSON.stringify(v);
|
|
1977
|
-
return { ok: true, value: value + truncNote };
|
|
1978
|
-
}
|
|
1979
|
-
return {
|
|
1980
|
-
ok: true,
|
|
1981
|
-
value: JSON.stringify(stripDollarKeys(envelope)) + truncNote
|
|
1982
|
-
};
|
|
1983
|
-
}
|
|
1984
|
-
async function runMindstudioCli(args, options) {
|
|
1985
|
-
return (await runMindstudioCliResult(args, options)).value;
|
|
1986
|
-
}
|
|
1987
|
-
function stripDollarKeys(envelope) {
|
|
1988
|
-
if (!envelope || typeof envelope !== "object" || Array.isArray(envelope)) {
|
|
1989
|
-
return envelope;
|
|
1990
|
-
}
|
|
1991
|
-
const out = {};
|
|
1992
|
-
for (const [k, v] of Object.entries(envelope)) {
|
|
1993
|
-
if (!k.startsWith("$")) {
|
|
1994
|
-
out[k] = v;
|
|
1995
|
-
}
|
|
1996
|
-
}
|
|
1997
|
-
return out;
|
|
1998
|
-
}
|
|
1999
|
-
|
|
2000
|
-
// src/tools/common/searchGoogle.ts
|
|
2001
|
-
var FETCH_TOP_N = 5;
|
|
2002
|
-
var searchGoogleTool = {
|
|
2003
|
-
definition: {
|
|
2004
|
-
name: "searchGoogle",
|
|
2005
|
-
description: "Search Google and return results. Use for research, finding documentation, looking up APIs, or any task where web search would help. The top results come back with their page content already included, so read those before reaching for scrapeWebUrl \u2014 you only need that for URLs this did not return, or for a result further down the list.",
|
|
2006
|
-
inputSchema: {
|
|
2007
|
-
type: "object",
|
|
2008
|
-
properties: {
|
|
2009
|
-
query: {
|
|
2010
|
-
type: "string",
|
|
2011
|
-
description: "The search query."
|
|
2012
|
-
}
|
|
2013
|
-
},
|
|
2014
|
-
required: ["query"]
|
|
2015
|
-
}
|
|
2016
|
-
},
|
|
2017
|
-
async execute(input, context) {
|
|
2018
|
-
const query = input.query;
|
|
2019
|
-
return runMindstudioCli(
|
|
2020
|
-
[
|
|
2021
|
-
"search-google",
|
|
2022
|
-
"--query",
|
|
2023
|
-
query,
|
|
2024
|
-
"--export-type",
|
|
2025
|
-
"json",
|
|
2026
|
-
"--fetch-top-n",
|
|
2027
|
-
String(FETCH_TOP_N)
|
|
2028
|
-
],
|
|
2029
|
-
{
|
|
2030
|
-
outputKey: "results",
|
|
2031
|
-
maxBuffer: SEARCH_MAX_BUFFER,
|
|
2032
|
-
onLog: context?.onLog,
|
|
2033
|
-
caller: "parent"
|
|
2034
|
-
}
|
|
2035
|
-
);
|
|
2036
|
-
}
|
|
2037
|
-
};
|
|
2038
|
-
|
|
2039
1896
|
// src/tools/common/setProjectMetadata.ts
|
|
2040
1897
|
var setProjectMetadataTool = {
|
|
2041
1898
|
definition: {
|
|
@@ -2160,7 +2017,7 @@ This reference lives at ${skill.path}. Re-read it with readFile if you need it a
|
|
|
2160
2017
|
};
|
|
2161
2018
|
|
|
2162
2019
|
// src/tools/code/readFile.ts
|
|
2163
|
-
import
|
|
2020
|
+
import fs12 from "fs/promises";
|
|
2164
2021
|
var DEFAULT_WINDOW = 500;
|
|
2165
2022
|
var MAX_BYTES = 64 * 1024;
|
|
2166
2023
|
function isBinary(buffer) {
|
|
@@ -2201,7 +2058,7 @@ var readFileTool = {
|
|
|
2201
2058
|
},
|
|
2202
2059
|
async execute(input) {
|
|
2203
2060
|
try {
|
|
2204
|
-
const buffer = await
|
|
2061
|
+
const buffer = await fs12.readFile(input.path);
|
|
2205
2062
|
if (isBinary(buffer)) {
|
|
2206
2063
|
const size = buffer.length;
|
|
2207
2064
|
const unit = size > 1024 * 1024 ? `${(size / (1024 * 1024)).toFixed(1)}MB` : `${(size / 1024).toFixed(1)}KB`;
|
|
@@ -2273,7 +2130,7 @@ var readFileTool = {
|
|
|
2273
2130
|
};
|
|
2274
2131
|
|
|
2275
2132
|
// src/tools/code/writeFile.ts
|
|
2276
|
-
import
|
|
2133
|
+
import fs13 from "fs/promises";
|
|
2277
2134
|
import path6 from "path";
|
|
2278
2135
|
var writeFileTool = {
|
|
2279
2136
|
definition: {
|
|
@@ -2310,7 +2167,7 @@ var writeFileTool = {
|
|
|
2310
2167
|
lastNewlineCount = newlineCount;
|
|
2311
2168
|
const lastNewline = partial.content.lastIndexOf("\n");
|
|
2312
2169
|
const completeContent = partial.content.substring(0, lastNewline + 1);
|
|
2313
|
-
const oldContent = await
|
|
2170
|
+
const oldContent = await fs13.readFile(partial.path, "utf-8").catch(() => "");
|
|
2314
2171
|
return `Writing ${partial.path} (${newlineCount} lines)
|
|
2315
2172
|
${unifiedDiff(partial.path, oldContent, completeContent)}`;
|
|
2316
2173
|
}
|
|
@@ -2319,13 +2176,13 @@ ${unifiedDiff(partial.path, oldContent, completeContent)}`;
|
|
|
2319
2176
|
async execute(input) {
|
|
2320
2177
|
const release = await acquireFileLock(input.path);
|
|
2321
2178
|
try {
|
|
2322
|
-
await
|
|
2179
|
+
await fs13.mkdir(path6.dirname(input.path), { recursive: true });
|
|
2323
2180
|
let oldContent = null;
|
|
2324
2181
|
try {
|
|
2325
|
-
oldContent = await
|
|
2182
|
+
oldContent = await fs13.readFile(input.path, "utf-8");
|
|
2326
2183
|
} catch {
|
|
2327
2184
|
}
|
|
2328
|
-
await
|
|
2185
|
+
await fs13.writeFile(input.path, input.content, "utf-8");
|
|
2329
2186
|
const lineCount = input.content.split("\n").length;
|
|
2330
2187
|
const label = oldContent !== null ? "Wrote" : "Created";
|
|
2331
2188
|
return `${label} ${input.path} (${lineCount} lines)
|
|
@@ -2339,7 +2196,7 @@ ${unifiedDiff(input.path, oldContent ?? "", input.content)}`;
|
|
|
2339
2196
|
};
|
|
2340
2197
|
|
|
2341
2198
|
// src/tools/code/editFile/index.ts
|
|
2342
|
-
import
|
|
2199
|
+
import fs14 from "fs/promises";
|
|
2343
2200
|
var editFileTool = {
|
|
2344
2201
|
definition: {
|
|
2345
2202
|
name: "editFile",
|
|
@@ -2370,7 +2227,7 @@ var editFileTool = {
|
|
|
2370
2227
|
async execute(input) {
|
|
2371
2228
|
const release = await acquireFileLock(input.path);
|
|
2372
2229
|
try {
|
|
2373
|
-
const content = await
|
|
2230
|
+
const content = await fs14.readFile(input.path, "utf-8");
|
|
2374
2231
|
const { old_string, new_string, replace_all } = input;
|
|
2375
2232
|
const occurrences = findOccurrences(content, old_string);
|
|
2376
2233
|
if (replace_all) {
|
|
@@ -2386,7 +2243,7 @@ var editFileTool = {
|
|
|
2386
2243
|
new_string
|
|
2387
2244
|
);
|
|
2388
2245
|
}
|
|
2389
|
-
await
|
|
2246
|
+
await fs14.writeFile(input.path, updated, "utf-8");
|
|
2390
2247
|
return `Replaced ${occurrences.length} occurrence${occurrences.length > 1 ? "s" : ""} in ${input.path}
|
|
2391
2248
|
${unifiedDiff(input.path, content, updated)}`;
|
|
2392
2249
|
}
|
|
@@ -2397,7 +2254,7 @@ ${unifiedDiff(input.path, content, updated)}`;
|
|
|
2397
2254
|
old_string.length,
|
|
2398
2255
|
new_string
|
|
2399
2256
|
);
|
|
2400
|
-
await
|
|
2257
|
+
await fs14.writeFile(input.path, updated, "utf-8");
|
|
2401
2258
|
return `Updated ${input.path}
|
|
2402
2259
|
${unifiedDiff(input.path, content, updated)}`;
|
|
2403
2260
|
}
|
|
@@ -2413,7 +2270,7 @@ ${unifiedDiff(input.path, content, updated)}`;
|
|
|
2413
2270
|
flex.matchedText.length,
|
|
2414
2271
|
new_string
|
|
2415
2272
|
);
|
|
2416
|
-
await
|
|
2273
|
+
await fs14.writeFile(input.path, updated, "utf-8");
|
|
2417
2274
|
return `Updated ${input.path} (matched with flexible whitespace at line ${flex.line})
|
|
2418
2275
|
${unifiedDiff(input.path, content, updated)}`;
|
|
2419
2276
|
}
|
|
@@ -2739,12 +2596,12 @@ var globTool = {
|
|
|
2739
2596
|
};
|
|
2740
2597
|
|
|
2741
2598
|
// src/tools/code/listDir.ts
|
|
2742
|
-
import
|
|
2599
|
+
import fs15 from "fs/promises";
|
|
2743
2600
|
import path8 from "path";
|
|
2744
2601
|
var EXCLUDE = /* @__PURE__ */ new Set([".git", "node_modules"]);
|
|
2745
2602
|
var MAX_CHILDREN = 15;
|
|
2746
2603
|
async function readAndSort(dirPath) {
|
|
2747
|
-
const entries = await
|
|
2604
|
+
const entries = await fs15.readdir(dirPath, { withFileTypes: true });
|
|
2748
2605
|
return entries.filter((e) => !EXCLUDE.has(e.name)).sort((a, b) => {
|
|
2749
2606
|
if (a.isDirectory() && !b.isDirectory()) {
|
|
2750
2607
|
return -1;
|
|
@@ -2785,7 +2642,7 @@ function formatSize(bytes) {
|
|
|
2785
2642
|
}
|
|
2786
2643
|
async function formatFile(dirPath, name, indent) {
|
|
2787
2644
|
try {
|
|
2788
|
-
const stat4 = await
|
|
2645
|
+
const stat4 = await fs15.stat(path8.join(dirPath, name));
|
|
2789
2646
|
return `${indent}${name}${" ".repeat(Math.max(1, 30 - indent.length - name.length))}${formatSize(stat4.size)}`;
|
|
2790
2647
|
} catch {
|
|
2791
2648
|
return `${indent}${name}`;
|
|
@@ -3117,6 +2974,119 @@ var queryDatabaseTool = {
|
|
|
3117
2974
|
}
|
|
3118
2975
|
};
|
|
3119
2976
|
|
|
2977
|
+
// src/usageLedger.ts
|
|
2978
|
+
import fs16 from "fs";
|
|
2979
|
+
var LEDGER_FILE = ".logs/usage.ndjson";
|
|
2980
|
+
var fd = null;
|
|
2981
|
+
function nanoToDollars(nano) {
|
|
2982
|
+
return typeof nano === "number" ? nano / 1e9 : void 0;
|
|
2983
|
+
}
|
|
2984
|
+
function recordUsage(entry) {
|
|
2985
|
+
try {
|
|
2986
|
+
if (fd === null) {
|
|
2987
|
+
fs16.mkdirSync(".logs", { recursive: true });
|
|
2988
|
+
fd = fs16.openSync(LEDGER_FILE, "a");
|
|
2989
|
+
}
|
|
2990
|
+
fs16.writeSync(fd, JSON.stringify(entry) + "\n");
|
|
2991
|
+
} catch {
|
|
2992
|
+
}
|
|
2993
|
+
}
|
|
2994
|
+
|
|
2995
|
+
// src/subagents/common/runMindstudioCli.ts
|
|
2996
|
+
function stripFlags(args) {
|
|
2997
|
+
const out = [];
|
|
2998
|
+
for (let i = 0; i < args.length; i++) {
|
|
2999
|
+
const arg = args[i];
|
|
3000
|
+
if (arg === "--no-meta") {
|
|
3001
|
+
continue;
|
|
3002
|
+
}
|
|
3003
|
+
if (arg === "--output-key") {
|
|
3004
|
+
i++;
|
|
3005
|
+
continue;
|
|
3006
|
+
}
|
|
3007
|
+
out.push(arg);
|
|
3008
|
+
}
|
|
3009
|
+
return out;
|
|
3010
|
+
}
|
|
3011
|
+
async function runMindstudioCliResult(args, options) {
|
|
3012
|
+
const cleanArgs = stripFlags(args);
|
|
3013
|
+
const cliAction = args[0];
|
|
3014
|
+
const agentName = options?.caller ?? "mindstudio-cli";
|
|
3015
|
+
const start = Date.now();
|
|
3016
|
+
const res = await runCli("mindstudio", cleanArgs, options);
|
|
3017
|
+
if (!res.ok) {
|
|
3018
|
+
return { ok: false, value: formatCliResult(res) };
|
|
3019
|
+
}
|
|
3020
|
+
const truncNote = res.truncated ? "\n\n[output truncated]" : "";
|
|
3021
|
+
let envelope;
|
|
3022
|
+
try {
|
|
3023
|
+
envelope = JSON.parse(res.output);
|
|
3024
|
+
} catch {
|
|
3025
|
+
return { ok: true, value: res.output + truncNote };
|
|
3026
|
+
}
|
|
3027
|
+
if (envelope && typeof envelope === "object" && Array.isArray(envelope.results)) {
|
|
3028
|
+
const durationMs = Date.now() - start;
|
|
3029
|
+
for (const step of envelope.results) {
|
|
3030
|
+
if (typeof step?.billingCost === "number") {
|
|
3031
|
+
recordUsage({
|
|
3032
|
+
ts: Date.now(),
|
|
3033
|
+
agentName,
|
|
3034
|
+
cliAction: `${cliAction}:${step.stepType ?? "step"}`,
|
|
3035
|
+
cost: nanoToDollars(step.billingCost),
|
|
3036
|
+
inputTokens: 0,
|
|
3037
|
+
outputTokens: 0,
|
|
3038
|
+
durationMs,
|
|
3039
|
+
toolNames: []
|
|
3040
|
+
});
|
|
3041
|
+
}
|
|
3042
|
+
}
|
|
3043
|
+
return { ok: true, value: JSON.stringify(envelope.results) + truncNote };
|
|
3044
|
+
}
|
|
3045
|
+
if (typeof envelope?.$billingCost === "number") {
|
|
3046
|
+
recordUsage({
|
|
3047
|
+
ts: Date.now(),
|
|
3048
|
+
agentName,
|
|
3049
|
+
cliAction,
|
|
3050
|
+
cost: nanoToDollars(envelope.$billingCost),
|
|
3051
|
+
billingEvents: envelope.$billingEvents,
|
|
3052
|
+
// CLI billing isn't expressed as input/output tokens for most actions
|
|
3053
|
+
// (image gen is per-image, scrape per-page, etc). `numUnits` inside each
|
|
3054
|
+
// billingEvent carries the per-event unit count.
|
|
3055
|
+
inputTokens: 0,
|
|
3056
|
+
outputTokens: 0,
|
|
3057
|
+
durationMs: Date.now() - start,
|
|
3058
|
+
toolNames: []
|
|
3059
|
+
});
|
|
3060
|
+
}
|
|
3061
|
+
if (options?.outputKey) {
|
|
3062
|
+
const v = envelope?.[options.outputKey];
|
|
3063
|
+
if (v === void 0 || v === null) {
|
|
3064
|
+
return { ok: false, value: JSON.stringify(stripDollarKeys(envelope)) };
|
|
3065
|
+
}
|
|
3066
|
+
const value = typeof v === "string" ? v : JSON.stringify(v);
|
|
3067
|
+
return { ok: true, value: value + truncNote };
|
|
3068
|
+
}
|
|
3069
|
+
return {
|
|
3070
|
+
ok: true,
|
|
3071
|
+
value: JSON.stringify(stripDollarKeys(envelope)) + truncNote
|
|
3072
|
+
};
|
|
3073
|
+
}
|
|
3074
|
+
async function runMindstudioCli(args, options) {
|
|
3075
|
+
return (await runMindstudioCliResult(args, options)).value;
|
|
3076
|
+
}
|
|
3077
|
+
function stripDollarKeys(envelope) {
|
|
3078
|
+
if (!envelope || typeof envelope !== "object" || Array.isArray(envelope)) {
|
|
3079
|
+
return envelope;
|
|
3080
|
+
}
|
|
3081
|
+
const out = {};
|
|
3082
|
+
for (const [k, v] of Object.entries(envelope)) {
|
|
3083
|
+
if (!k.startsWith("$")) {
|
|
3084
|
+
out[k] = v;
|
|
3085
|
+
}
|
|
3086
|
+
}
|
|
3087
|
+
return out;
|
|
3088
|
+
}
|
|
3089
|
+
|
|
3120
3090
|
// src/tools/_helpers/uploadImage.ts
|
|
3121
3091
|
import { readFile, stat } from "fs/promises";
|
|
3122
3092
|
import { basename, extname, resolve } from "path";
|
|
@@ -4595,7 +4565,7 @@ The first-party SDK (@mindstudio-ai/agent) provides access to 200+ AI models (Op
|
|
|
4595
4565
|
## What Remy apps are NOT good for
|
|
4596
4566
|
|
|
4597
4567
|
- Native mobile apps (iOS/Android). Mobile-responsive web apps are fine.
|
|
4598
|
-
-
|
|
4568
|
+
- Real-time action games (server-authoritative simulation, guaranteed-order sync) \u2014 event delivery is at-most-once and ordering is the app's job, so there is no server tick to build one on.
|
|
4599
4569
|
</platform_brief>`;
|
|
4600
4570
|
}
|
|
4601
4571
|
|
|
@@ -4884,56 +4854,155 @@ var screenshotTool = {
|
|
|
4884
4854
|
execute: (input, context) => executeScreenshot(input, context?.onLog, context)
|
|
4885
4855
|
};
|
|
4886
4856
|
|
|
4887
|
-
// src/subagents/
|
|
4888
|
-
var
|
|
4889
|
-
__export(searchGoogle_exports, {
|
|
4890
|
-
definition: () => definition,
|
|
4891
|
-
execute: () => execute
|
|
4892
|
-
});
|
|
4893
|
-
var FETCH_TOP_N2 = 5;
|
|
4894
|
-
var definition = {
|
|
4857
|
+
// src/subagents/research/tools.ts
|
|
4858
|
+
var searchGoogleDefinition = {
|
|
4895
4859
|
name: "searchGoogle",
|
|
4896
|
-
description:
|
|
4860
|
+
description: "Search Google. Returns ~25 results (title, description, URL) \u2014 fast (~5s) when `fetchTopN` is omitted. Set `fetchTopN` (3\u20135) to also get the top results' page content inline, capped at ~4,000 chars per page \u2014 one call delivers excerpts, but it is much slower (~30\u201360s). Default pattern: fire SERP-only searches in parallel, then scrape the specific pages worth reading in full.",
|
|
4897
4861
|
inputSchema: {
|
|
4898
4862
|
type: "object",
|
|
4899
4863
|
properties: {
|
|
4900
4864
|
query: {
|
|
4901
4865
|
type: "string",
|
|
4902
4866
|
description: "The search query."
|
|
4867
|
+
},
|
|
4868
|
+
fetchTopN: {
|
|
4869
|
+
type: "number",
|
|
4870
|
+
description: "Also fetch page content (capped ~4,000 chars each) for this many top results. Omit for a fast SERP-only search."
|
|
4903
4871
|
}
|
|
4904
4872
|
},
|
|
4905
4873
|
required: ["query"]
|
|
4906
4874
|
}
|
|
4907
4875
|
};
|
|
4908
|
-
|
|
4876
|
+
var scrapeWebUrlDefinition = {
|
|
4877
|
+
name: "scrapeWebUrl",
|
|
4878
|
+
description: "Fetch a web page as markdown. Renders JavaScript, so client-rendered pages come back complete. Returns the full page \u2014 long docs can run tens of thousands of tokens, so fetch only pages you have chosen to read, and fire independent fetches in parallel. For code hosted on GitHub/npm, prefer cloning with bash over scraping the repo page.",
|
|
4879
|
+
inputSchema: {
|
|
4880
|
+
type: "object",
|
|
4881
|
+
properties: {
|
|
4882
|
+
url: {
|
|
4883
|
+
type: "string",
|
|
4884
|
+
description: "The URL to fetch."
|
|
4885
|
+
}
|
|
4886
|
+
},
|
|
4887
|
+
required: ["url"]
|
|
4888
|
+
}
|
|
4889
|
+
};
|
|
4890
|
+
var RESEARCH_TOOLS = [
|
|
4891
|
+
...COMMON_READ_TOOLS,
|
|
4892
|
+
searchGoogleDefinition,
|
|
4893
|
+
scrapeWebUrlDefinition,
|
|
4894
|
+
bashTool.definition
|
|
4895
|
+
];
|
|
4896
|
+
async function executeSearchGoogle(input, onLog, caller) {
|
|
4897
|
+
const fetchTopN = Math.max(0, Math.round(Number(input.fetchTopN) || 0));
|
|
4909
4898
|
return runMindstudioCli(
|
|
4910
4899
|
[
|
|
4911
4900
|
"search-google",
|
|
4912
4901
|
"--query",
|
|
4913
|
-
input.query,
|
|
4902
|
+
String(input.query),
|
|
4914
4903
|
"--export-type",
|
|
4915
4904
|
"json",
|
|
4916
4905
|
"--fetch-top-n",
|
|
4917
|
-
String(
|
|
4906
|
+
String(fetchTopN)
|
|
4918
4907
|
],
|
|
4919
4908
|
{
|
|
4920
4909
|
outputKey: "results",
|
|
4910
|
+
maxBuffer: SEARCH_MAX_BUFFER,
|
|
4911
|
+
onLog,
|
|
4912
|
+
caller
|
|
4913
|
+
}
|
|
4914
|
+
);
|
|
4915
|
+
}
|
|
4916
|
+
async function executeScrapeWebUrl(input, onLog, caller) {
|
|
4917
|
+
return runMindstudioCli(
|
|
4918
|
+
[
|
|
4919
|
+
"scrape-url",
|
|
4920
|
+
"--url",
|
|
4921
|
+
String(input.url),
|
|
4922
|
+
"--page-options",
|
|
4923
|
+
JSON.stringify({ onlyMainContent: true })
|
|
4924
|
+
],
|
|
4925
|
+
{
|
|
4926
|
+
maxBuffer: SCRAPE_MAX_BUFFER,
|
|
4921
4927
|
onLog,
|
|
4922
|
-
caller
|
|
4923
|
-
maxBuffer: SEARCH_MAX_BUFFER
|
|
4928
|
+
caller
|
|
4924
4929
|
}
|
|
4925
4930
|
);
|
|
4926
4931
|
}
|
|
4927
4932
|
|
|
4933
|
+
// src/subagents/research/index.ts
|
|
4934
|
+
var BASE_PROMPT2 = readAsset("subagents/research", "prompt.md");
|
|
4935
|
+
async function runResearch(task, context) {
|
|
4936
|
+
const specIndex = loadSpecIndex();
|
|
4937
|
+
const parts = [BASE_PROMPT2, loadPlatformBrief()];
|
|
4938
|
+
parts.push("<!-- cache_breakpoint -->");
|
|
4939
|
+
if (specIndex) {
|
|
4940
|
+
parts.push(specIndex);
|
|
4941
|
+
}
|
|
4942
|
+
const system = parts.join("\n\n");
|
|
4943
|
+
const result = await runSubAgent({
|
|
4944
|
+
system,
|
|
4945
|
+
task,
|
|
4946
|
+
tools: RESEARCH_TOOLS,
|
|
4947
|
+
externalTools: /* @__PURE__ */ new Set(),
|
|
4948
|
+
executeTool: (name, toolInput, toolCallId, onLog, sams) => {
|
|
4949
|
+
const childCtx = toolCallId ? {
|
|
4950
|
+
...deriveContext(context, toolCallId, onLog),
|
|
4951
|
+
subAgentMessages: sams
|
|
4952
|
+
} : context;
|
|
4953
|
+
if (name === "searchGoogle") {
|
|
4954
|
+
return executeSearchGoogle(toolInput, childCtx.onLog, "research");
|
|
4955
|
+
}
|
|
4956
|
+
if (name === "scrapeWebUrl") {
|
|
4957
|
+
return executeScrapeWebUrl(toolInput, childCtx.onLog, "research");
|
|
4958
|
+
}
|
|
4959
|
+
return executeTool(name, toolInput, childCtx);
|
|
4960
|
+
},
|
|
4961
|
+
apiConfig: context.apiConfig,
|
|
4962
|
+
model: resolveModel("research", context.models, context.model),
|
|
4963
|
+
subAgentId: "research",
|
|
4964
|
+
signal: context.signal,
|
|
4965
|
+
parentToolId: context.toolCallId,
|
|
4966
|
+
requestId: context.requestId,
|
|
4967
|
+
onEvent: context.onEvent,
|
|
4968
|
+
resolveExternalTool: context.resolveExternalTool,
|
|
4969
|
+
toolRegistry: context.toolRegistry
|
|
4970
|
+
});
|
|
4971
|
+
context.subAgentMessages?.set(context.toolCallId, result.messages);
|
|
4972
|
+
return result.text;
|
|
4973
|
+
}
|
|
4974
|
+
var researchTool = {
|
|
4975
|
+
definition: {
|
|
4976
|
+
name: "research",
|
|
4977
|
+
description: "Your researcher. Hand it a question and it searches the web, reads the pages and source code that matter, and returns a distilled, citation-backed report. Use it for both objective research like third-party APIs and services, as well as for subjective things like current trends, patterns, and approaches (from architecture to UI to even just high-level framings and ideas). Brief it neutrally: state the question and the relevant project context, not the answer you expect.",
|
|
4978
|
+
inputSchema: {
|
|
4979
|
+
type: "object",
|
|
4980
|
+
properties: {
|
|
4981
|
+
task: {
|
|
4982
|
+
type: "string",
|
|
4983
|
+
description: "What you need to find out, in natural language, plus any project context it cannot get from reading the spec. Phrase it as a question to answer, not a conclusion to confirm."
|
|
4984
|
+
}
|
|
4985
|
+
},
|
|
4986
|
+
required: ["task"]
|
|
4987
|
+
}
|
|
4988
|
+
},
|
|
4989
|
+
async execute(input, context) {
|
|
4990
|
+
if (!context) {
|
|
4991
|
+
return "Error: research requires execution context";
|
|
4992
|
+
}
|
|
4993
|
+
return runResearch(input.task, context);
|
|
4994
|
+
}
|
|
4995
|
+
};
|
|
4996
|
+
|
|
4928
4997
|
// src/subagents/designExpert/tools/scrapeWebUrl.ts
|
|
4929
4998
|
var scrapeWebUrl_exports = {};
|
|
4930
4999
|
__export(scrapeWebUrl_exports, {
|
|
4931
|
-
definition: () =>
|
|
4932
|
-
execute: () =>
|
|
5000
|
+
definition: () => definition,
|
|
5001
|
+
execute: () => execute
|
|
4933
5002
|
});
|
|
4934
|
-
var
|
|
5003
|
+
var definition = {
|
|
4935
5004
|
name: "scrapeWebUrl",
|
|
4936
|
-
description: "Fetch the content of a web page as markdown. Use
|
|
5005
|
+
description: "Fetch the content of a web page as markdown. Use for reading a specific URL \u2014 a site the user referenced, a brand to match, a page the researcher cited that you want in full.",
|
|
4937
5006
|
inputSchema: {
|
|
4938
5007
|
type: "object",
|
|
4939
5008
|
properties: {
|
|
@@ -4945,7 +5014,7 @@ var definition2 = {
|
|
|
4945
5014
|
required: ["url"]
|
|
4946
5015
|
}
|
|
4947
5016
|
};
|
|
4948
|
-
async function
|
|
5017
|
+
async function execute(input, onLog) {
|
|
4949
5018
|
const pageOptions = { onlyMainContent: true };
|
|
4950
5019
|
return runMindstudioCli(
|
|
4951
5020
|
[
|
|
@@ -4962,8 +5031,8 @@ async function execute2(input, onLog) {
|
|
|
4962
5031
|
// src/subagents/designExpert/tools/analyzeDesign.ts
|
|
4963
5032
|
var analyzeDesign_exports = {};
|
|
4964
5033
|
__export(analyzeDesign_exports, {
|
|
4965
|
-
definition: () =>
|
|
4966
|
-
execute: () =>
|
|
5034
|
+
definition: () => definition3,
|
|
5035
|
+
execute: () => execute3
|
|
4967
5036
|
});
|
|
4968
5037
|
import { readFile as readFile2 } from "fs/promises";
|
|
4969
5038
|
import { extname as extname2, join as join2 } from "path";
|
|
@@ -4972,8 +5041,8 @@ import { extname as extname2, join as join2 } from "path";
|
|
|
4972
5041
|
var renderImage_exports = {};
|
|
4973
5042
|
__export(renderImage_exports, {
|
|
4974
5043
|
RENDER_ANALYZE_PROMPT: () => RENDER_ANALYZE_PROMPT,
|
|
4975
|
-
definition: () =>
|
|
4976
|
-
execute: () =>
|
|
5044
|
+
definition: () => definition2,
|
|
5045
|
+
execute: () => execute2
|
|
4977
5046
|
});
|
|
4978
5047
|
import { mkdir, unlink, writeFile } from "fs/promises";
|
|
4979
5048
|
import { tmpdir } from "os";
|
|
@@ -4982,7 +5051,7 @@ import { randomUUID } from "crypto";
|
|
|
4982
5051
|
var MIN_DIMENSION = 16;
|
|
4983
5052
|
var MAX_DIMENSION = 4096;
|
|
4984
5053
|
var RENDER_ANALYZE_PROMPT = 'You are reviewing a browser-rendered graphic (composed from HTML/CSS by a designer) for fidelity. Report: whether the composition fills the full canvas or leaves unintended gaps at any edge, any clipped or overflowing text, whether custom webfonts appear to have loaded (distinctive letterforms vs generic fallback serif/sans), any misalignment or uneven spacing, any unintended scrollbars or default-styling artifacts, and \u2014 if the background is transparent \u2014 any fringing or stray opaque pixels at the edges. Then briefly describe the overall composition and how polished it looks. Be concise and practical. Respond only with your analysis as Markdown (starting with the title "Render Review") and absolutely no other text. Do not use emojis - use unicode if you need symbols.';
|
|
4985
|
-
var
|
|
5054
|
+
var definition2 = {
|
|
4986
5055
|
name: "renderImage",
|
|
4987
5056
|
description: "Render a self-contained HTML document in a real browser and capture it as a hosted PNG at exact pixel dimensions, with a fidelity review included. Deterministic \u2014 exact hex colors, real loaded webfonts, precise geometry \u2014 unlike generateImages, which is an image model. Use for token-exact graphics: Open Graph share cards, wordmarks, flat/geometric icon tiles, badges, any composition where letterforms and spacing carry the design. Compose with HTML/CSS (link webfonts from CDNs \u2014 the renderer waits for them to load); inline existing SVG markup when needed, but never hand-write new SVG path data.",
|
|
4988
5057
|
inputSchema: {
|
|
@@ -5016,7 +5085,7 @@ var definition3 = {
|
|
|
5016
5085
|
required: ["html", "width", "height"]
|
|
5017
5086
|
}
|
|
5018
5087
|
};
|
|
5019
|
-
async function
|
|
5088
|
+
async function execute2(input, onLog, context) {
|
|
5020
5089
|
const html = typeof input.html === "string" ? input.html : "";
|
|
5021
5090
|
const width = Math.round(Number(input.width));
|
|
5022
5091
|
const height = Math.round(Number(input.height));
|
|
@@ -5125,7 +5194,7 @@ Identify the specific design moves that make this page interesting and unique, d
|
|
|
5125
5194
|
|
|
5126
5195
|
Respond only with your analysis as Markdown and absolutely no other text. Do not use emojis - use unicode if you need symbols.
|
|
5127
5196
|
`;
|
|
5128
|
-
var
|
|
5197
|
+
var definition3 = {
|
|
5129
5198
|
name: "analyzeDesign",
|
|
5130
5199
|
description: "Analyze the visual design of a website, an image (URL or file on disk), or an HTML document on disk. Websites are screenshotted first; an HTML file is rendered in a real browser first and the render is analyzed, which is how you look at a wireframe you authored. Provides static image analysis only, will not capture animations or video. With no prompt, a website or image gets a full design reference analysis (mood, color, typography, layout, distinctiveness) and a rendered HTML document gets a fidelity review (clipping, overflow, webfont loading, alignment). Provide a custom prompt to ask a specific design question instead. Use a bulleted list to ask many questions at once.",
|
|
5131
5200
|
inputSchema: {
|
|
@@ -5165,7 +5234,7 @@ function splitFrontmatter(raw) {
|
|
|
5165
5234
|
html: raw.slice(match[0].length)
|
|
5166
5235
|
};
|
|
5167
5236
|
}
|
|
5168
|
-
async function
|
|
5237
|
+
async function execute3(input, onLog, context) {
|
|
5169
5238
|
const url = String(input.url ?? "").trim();
|
|
5170
5239
|
if (!url) {
|
|
5171
5240
|
return "Error: url is required.";
|
|
@@ -5273,10 +5342,10 @@ ${basePrompt}` : basePrompt;
|
|
|
5273
5342
|
// src/subagents/designExpert/tools/analyzeImage.ts
|
|
5274
5343
|
var analyzeImage_exports = {};
|
|
5275
5344
|
__export(analyzeImage_exports, {
|
|
5276
|
-
definition: () =>
|
|
5277
|
-
execute: () =>
|
|
5345
|
+
definition: () => definition4,
|
|
5346
|
+
execute: () => execute4
|
|
5278
5347
|
});
|
|
5279
|
-
var
|
|
5348
|
+
var definition4 = {
|
|
5280
5349
|
name: "analyzeImage",
|
|
5281
5350
|
description: "Analyze an image using a vision model. Provides static image analysis only, will not capture animations or video. Returns an objective description of what is visible \u2014 shapes, colors, layout, text, artifacts. Use for factual inventory of image contents, not for subjective design judgment - the vision model providing the analysis has no sense of design. You are the design expert - use the analysis tool for factual inventory, then apply your own expertise for quality and suitability assessments. Optionally provide specific questions about what you're looking for. Use a bulleted list to ask many questions at once. If you are analyzing a screenshot of the app preview, you can reuse the same screenshot URL multiple times to ask multiple questions.",
|
|
5282
5351
|
inputSchema: {
|
|
@@ -5297,7 +5366,7 @@ var definition5 = {
|
|
|
5297
5366
|
required: ["imageUrl"]
|
|
5298
5367
|
}
|
|
5299
5368
|
};
|
|
5300
|
-
async function
|
|
5369
|
+
async function execute4(input, onLog, context) {
|
|
5301
5370
|
const prompt = buildScreenshotAnalysisPrompt({
|
|
5302
5371
|
prompt: input.prompt
|
|
5303
5372
|
});
|
|
@@ -5314,8 +5383,8 @@ async function execute5(input, onLog, context) {
|
|
|
5314
5383
|
// src/subagents/designExpert/tools/images/generateImages.ts
|
|
5315
5384
|
var generateImages_exports = {};
|
|
5316
5385
|
__export(generateImages_exports, {
|
|
5317
|
-
definition: () =>
|
|
5318
|
-
execute: () =>
|
|
5386
|
+
definition: () => definition5,
|
|
5387
|
+
execute: () => execute5
|
|
5319
5388
|
});
|
|
5320
5389
|
|
|
5321
5390
|
// src/subagents/designExpert/tools/images/enhancePrompt.ts
|
|
@@ -5542,7 +5611,7 @@ async function generateImageAssets(opts) {
|
|
|
5542
5611
|
}
|
|
5543
5612
|
|
|
5544
5613
|
// src/subagents/designExpert/tools/images/generateImages.ts
|
|
5545
|
-
var
|
|
5614
|
+
var definition5 = {
|
|
5546
5615
|
name: "generateImages",
|
|
5547
5616
|
description: "Generate images. 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.",
|
|
5548
5617
|
inputSchema: {
|
|
@@ -5575,7 +5644,7 @@ var definition6 = {
|
|
|
5575
5644
|
required: ["prompts"]
|
|
5576
5645
|
}
|
|
5577
5646
|
};
|
|
5578
|
-
async function
|
|
5647
|
+
async function execute5(input, onLog, context) {
|
|
5579
5648
|
return generateImageAssets({
|
|
5580
5649
|
prompts: input.prompts,
|
|
5581
5650
|
width: input.width,
|
|
@@ -5606,10 +5675,10 @@ async function execute6(input, onLog, context) {
|
|
|
5606
5675
|
// src/subagents/designExpert/tools/images/editImages.ts
|
|
5607
5676
|
var editImages_exports = {};
|
|
5608
5677
|
__export(editImages_exports, {
|
|
5609
|
-
definition: () =>
|
|
5610
|
-
execute: () =>
|
|
5678
|
+
definition: () => definition6,
|
|
5679
|
+
execute: () => execute6
|
|
5611
5680
|
});
|
|
5612
|
-
var
|
|
5681
|
+
var definition6 = {
|
|
5613
5682
|
name: "editImages",
|
|
5614
5683
|
description: "Edit or transform existing images. 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 references into something new. Returns CDN URLs with analysis.",
|
|
5615
5684
|
inputSchema: {
|
|
@@ -5645,7 +5714,7 @@ var definition7 = {
|
|
|
5645
5714
|
required: ["prompts", "sourceImages"]
|
|
5646
5715
|
}
|
|
5647
5716
|
};
|
|
5648
|
-
async function
|
|
5717
|
+
async function execute6(input, onLog, context) {
|
|
5649
5718
|
return generateImageAssets({
|
|
5650
5719
|
prompts: input.prompts,
|
|
5651
5720
|
sourceImages: input.sourceImages,
|
|
@@ -5676,15 +5745,15 @@ async function execute7(input, onLog, context) {
|
|
|
5676
5745
|
// src/subagents/designExpert/tools/polishCopy.ts
|
|
5677
5746
|
var polishCopy_exports = {};
|
|
5678
5747
|
__export(polishCopy_exports, {
|
|
5679
|
-
definition: () =>
|
|
5680
|
-
execute: () =>
|
|
5748
|
+
definition: () => definition7,
|
|
5749
|
+
execute: () => execute7
|
|
5681
5750
|
});
|
|
5682
5751
|
|
|
5683
5752
|
// src/subagents/copyEditor/tools.ts
|
|
5684
5753
|
var COPY_EDITOR_TOOLS = [...COMMON_READ_TOOLS];
|
|
5685
5754
|
|
|
5686
5755
|
// src/subagents/copyEditor/index.ts
|
|
5687
|
-
var
|
|
5756
|
+
var BASE_PROMPT3 = readAsset("subagents/copyEditor", "prompt.md");
|
|
5688
5757
|
var copyEditorTool = {
|
|
5689
5758
|
definition: {
|
|
5690
5759
|
name: "copyEditor",
|
|
@@ -5705,7 +5774,7 @@ var copyEditorTool = {
|
|
|
5705
5774
|
return "Error: copy editor requires execution context";
|
|
5706
5775
|
}
|
|
5707
5776
|
const specIndex = loadSpecIndex();
|
|
5708
|
-
const parts = [
|
|
5777
|
+
const parts = [BASE_PROMPT3];
|
|
5709
5778
|
parts.push("<!-- cache_breakpoint -->");
|
|
5710
5779
|
if (specIndex) {
|
|
5711
5780
|
parts.push(specIndex);
|
|
@@ -5739,7 +5808,7 @@ var copyEditorTool = {
|
|
|
5739
5808
|
};
|
|
5740
5809
|
|
|
5741
5810
|
// src/subagents/designExpert/tools/polishCopy.ts
|
|
5742
|
-
var
|
|
5811
|
+
var definition7 = {
|
|
5743
5812
|
name: "polishCopy",
|
|
5744
5813
|
description: "Hand off any user-facing copy you've written \u2014 headlines, captions, labels, body text \u2014 and get back a sharper version: better built for its audience and free of the fingerprints that make writing read as AI. It elevates how the copy communicates without inventing facts or claims you didn't give it. Give it the text plus what it's for (where it appears, the audience).",
|
|
5745
5814
|
inputSchema: {
|
|
@@ -5753,15 +5822,15 @@ var definition8 = {
|
|
|
5753
5822
|
required: ["task"]
|
|
5754
5823
|
}
|
|
5755
5824
|
};
|
|
5756
|
-
async function
|
|
5825
|
+
async function execute7(input, _onLog, context) {
|
|
5757
5826
|
return copyEditorTool.execute(input, context);
|
|
5758
5827
|
}
|
|
5759
5828
|
|
|
5760
5829
|
// src/subagents/designExpert/tools/loadSkill.ts
|
|
5761
5830
|
var loadSkill_exports = {};
|
|
5762
5831
|
__export(loadSkill_exports, {
|
|
5763
|
-
definition: () =>
|
|
5764
|
-
execute: () =>
|
|
5832
|
+
definition: () => definition8,
|
|
5833
|
+
execute: () => execute8
|
|
5765
5834
|
});
|
|
5766
5835
|
|
|
5767
5836
|
// src/subagents/designExpert/skills/_catalog.ts
|
|
@@ -5775,7 +5844,7 @@ var designSkillCatalog = buildSkillCatalog({
|
|
|
5775
5844
|
});
|
|
5776
5845
|
|
|
5777
5846
|
// src/subagents/designExpert/tools/loadSkill.ts
|
|
5778
|
-
var
|
|
5847
|
+
var definition8 = {
|
|
5779
5848
|
name: "loadSkill",
|
|
5780
5849
|
description: "Load the full craft reference for a design surface that isn't in your prompt. The available skills and the trigger for each are listed in <available_skills>. Load one before designing in its area, not after \u2014 these are hard-won technique recipes, and the defaulted version of these surfaces is exactly what they exist to prevent. Calling this is cheap and expected \u2014 if you're unsure whether you need it, load it.",
|
|
5781
5850
|
inputSchema: {
|
|
@@ -5793,7 +5862,7 @@ var definition9 = {
|
|
|
5793
5862
|
required: ["skill"]
|
|
5794
5863
|
}
|
|
5795
5864
|
};
|
|
5796
|
-
async function
|
|
5865
|
+
async function execute8(input) {
|
|
5797
5866
|
const id = String(input.skill ?? "");
|
|
5798
5867
|
const skill = designSkillCatalog.get(id);
|
|
5799
5868
|
if (!skill) {
|
|
@@ -5814,15 +5883,15 @@ This reference lives at ${skill.path}. Re-read it with readFile if you need it a
|
|
|
5814
5883
|
var createWireframe_exports = {};
|
|
5815
5884
|
__export(createWireframe_exports, {
|
|
5816
5885
|
WIREFRAMES_DIR: () => WIREFRAMES_DIR,
|
|
5817
|
-
definition: () =>
|
|
5818
|
-
execute: () =>
|
|
5886
|
+
definition: () => definition9,
|
|
5887
|
+
execute: () => execute9
|
|
5819
5888
|
});
|
|
5820
5889
|
import { mkdir as mkdir2, stat as stat2, writeFile as writeFile2 } from "fs/promises";
|
|
5821
5890
|
import { join as join3 } from "path";
|
|
5822
5891
|
var log9 = createLogger("createWireframe");
|
|
5823
5892
|
var WIREFRAMES_DIR = "src/.wireframes";
|
|
5824
5893
|
var UPLOAD_TIMEOUT_MS2 = 3e4;
|
|
5825
|
-
var
|
|
5894
|
+
var definition9 = {
|
|
5826
5895
|
name: "createWireframe",
|
|
5827
5896
|
description: "Generate a wireframe from self-contained HTML+CSS you author and write it to disk as a design artifact. This is how a wireframe comes to exist \u2014 the way generateImages is how an image comes to exist \u2014 and the developer builds from the file it creates. The result also hands back the reference line that embeds the wireframe in your response and in specs; paste it wherever the wireframe belongs and it renders as a live preview. Calling again with the same slug revises the wireframe in place, so existing references stay current \u2014 a revision is a call to this tool, never a prose description of changes to an earlier wireframe.",
|
|
5828
5897
|
inputSchema: {
|
|
@@ -5916,7 +5985,7 @@ async function uploadMirror(context, slug, content) {
|
|
|
5916
5985
|
return { ok: false, note: err.message };
|
|
5917
5986
|
}
|
|
5918
5987
|
}
|
|
5919
|
-
async function
|
|
5988
|
+
async function execute9(input, onLog, context) {
|
|
5920
5989
|
if (!context) {
|
|
5921
5990
|
return "Error: createWireframe requires execution context";
|
|
5922
5991
|
}
|
|
@@ -5964,8 +6033,29 @@ async function execute10(input, onLog, context) {
|
|
|
5964
6033
|
}
|
|
5965
6034
|
|
|
5966
6035
|
// src/subagents/designExpert/tools/index.ts
|
|
6036
|
+
var research = {
|
|
6037
|
+
definition: {
|
|
6038
|
+
name: "research",
|
|
6039
|
+
description: "Your researcher, for design questions your built-in catalogs and expertise do not settle: how leading products present a specific kind of data or interaction, current conventions or best practices for a pattern, general-purpose ideas and inspiration. It searches the web, reads the sources that matter, and returns a distilled report with citations and concrete specifics. Brief it neutrally: the question or topic, not the answer you expect.",
|
|
6040
|
+
inputSchema: {
|
|
6041
|
+
type: "object",
|
|
6042
|
+
properties: {
|
|
6043
|
+
task: {
|
|
6044
|
+
type: "string",
|
|
6045
|
+
description: "What you need to find out, in natural language, with enough product context to make the findings relevant."
|
|
6046
|
+
}
|
|
6047
|
+
},
|
|
6048
|
+
required: ["task"]
|
|
6049
|
+
}
|
|
6050
|
+
},
|
|
6051
|
+
execute: (input, _onLog, context) => {
|
|
6052
|
+
if (!context) {
|
|
6053
|
+
return Promise.resolve("Error: research requires execution context");
|
|
6054
|
+
}
|
|
6055
|
+
return runResearch(input.task, context);
|
|
6056
|
+
}
|
|
6057
|
+
};
|
|
5967
6058
|
var tools = {
|
|
5968
|
-
searchGoogle: searchGoogle_exports,
|
|
5969
6059
|
scrapeWebUrl: scrapeWebUrl_exports,
|
|
5970
6060
|
analyzeDesign: analyzeDesign_exports,
|
|
5971
6061
|
analyzeImage: analyzeImage_exports,
|
|
@@ -5979,7 +6069,8 @@ var tools = {
|
|
|
5979
6069
|
polishCopy: polishCopy_exports,
|
|
5980
6070
|
loadSkill: loadSkill_exports,
|
|
5981
6071
|
// Appended last: tool order is part of the subagent's prompt-cache prefix.
|
|
5982
|
-
createWireframe: createWireframe_exports
|
|
6072
|
+
createWireframe: createWireframe_exports,
|
|
6073
|
+
research
|
|
5983
6074
|
};
|
|
5984
6075
|
var DESIGN_EXPERT_TOOLS = [
|
|
5985
6076
|
...COMMON_READ_TOOLS,
|
|
@@ -6537,11 +6628,11 @@ ${result.text}`;
|
|
|
6537
6628
|
}
|
|
6538
6629
|
|
|
6539
6630
|
// src/subagents/productVision/prompt.ts
|
|
6540
|
-
var
|
|
6631
|
+
var BASE_PROMPT4 = readAsset("subagents/productVision", "prompt.md");
|
|
6541
6632
|
function getProductVisionPrompt() {
|
|
6542
6633
|
const specIndex = loadSpecIndex();
|
|
6543
6634
|
const roadmapIndex = loadRoadmapIndex();
|
|
6544
|
-
const parts = [
|
|
6635
|
+
const parts = [BASE_PROMPT4, loadPlatformBrief()];
|
|
6545
6636
|
parts.push("<!-- cache_breakpoint -->");
|
|
6546
6637
|
if (specIndex) {
|
|
6547
6638
|
parts.push(specIndex);
|
|
@@ -6665,11 +6756,26 @@ var SANITY_CHECK_TOOLS = [
|
|
|
6665
6756
|
},
|
|
6666
6757
|
required: ["command"]
|
|
6667
6758
|
}
|
|
6759
|
+
},
|
|
6760
|
+
// Appended last: tool order is part of the subagent's prompt-cache prefix.
|
|
6761
|
+
{
|
|
6762
|
+
name: "research",
|
|
6763
|
+
description: "Deep researcher. When the plan hinges on an unfamiliar third-party service, API, or claim you cannot settle with a quick search, hand it the question \u2014 it researches properly (multiple sources, official docs, reading real source code) and returns a distilled, citation-backed report. Quick package-liveness checks stay on searchGoogle; use this when being wrong would be expensive. Brief it neutrally: the question, not the answer you expect.",
|
|
6764
|
+
inputSchema: {
|
|
6765
|
+
type: "object",
|
|
6766
|
+
properties: {
|
|
6767
|
+
task: {
|
|
6768
|
+
type: "string",
|
|
6769
|
+
description: "What you need to find out, in natural language."
|
|
6770
|
+
}
|
|
6771
|
+
},
|
|
6772
|
+
required: ["task"]
|
|
6773
|
+
}
|
|
6668
6774
|
}
|
|
6669
6775
|
];
|
|
6670
6776
|
|
|
6671
6777
|
// src/subagents/codeSanityCheck/index.ts
|
|
6672
|
-
var
|
|
6778
|
+
var BASE_PROMPT5 = readAsset("subagents/codeSanityCheck", "prompt.md");
|
|
6673
6779
|
var codeSanityCheckTool = {
|
|
6674
6780
|
definition: {
|
|
6675
6781
|
name: "codeSanityCheck",
|
|
@@ -6690,7 +6796,7 @@ var codeSanityCheckTool = {
|
|
|
6690
6796
|
return "Error: code sanity check requires execution context";
|
|
6691
6797
|
}
|
|
6692
6798
|
const specIndex = loadSpecIndex();
|
|
6693
|
-
const parts = [
|
|
6799
|
+
const parts = [BASE_PROMPT5, loadPlatformBrief()];
|
|
6694
6800
|
parts.push("<!-- cache_breakpoint -->");
|
|
6695
6801
|
if (specIndex) {
|
|
6696
6802
|
parts.push(specIndex);
|
|
@@ -6706,6 +6812,16 @@ var codeSanityCheckTool = {
|
|
|
6706
6812
|
...deriveContext(context, toolCallId, onLog),
|
|
6707
6813
|
subAgentMessages: sams
|
|
6708
6814
|
} : context;
|
|
6815
|
+
if (name === "searchGoogle") {
|
|
6816
|
+
return executeSearchGoogle(
|
|
6817
|
+
{ ...toolInput, fetchTopN: 5 },
|
|
6818
|
+
childCtx.onLog,
|
|
6819
|
+
"codeSanityCheck"
|
|
6820
|
+
);
|
|
6821
|
+
}
|
|
6822
|
+
if (name === "research") {
|
|
6823
|
+
return runResearch(String(toolInput.task ?? ""), childCtx);
|
|
6824
|
+
}
|
|
6709
6825
|
return executeTool(name, toolInput, childCtx);
|
|
6710
6826
|
},
|
|
6711
6827
|
apiConfig: context.apiConfig,
|
|
@@ -6859,7 +6975,7 @@ function acquireSpecSyncLock() {
|
|
|
6859
6975
|
}
|
|
6860
6976
|
|
|
6861
6977
|
// src/subagents/specSync/index.ts
|
|
6862
|
-
var
|
|
6978
|
+
var BASE_PROMPT6 = readAsset("subagents/specSync", "prompt.md");
|
|
6863
6979
|
var MSFM_DOCS = `<mindstudio_flavored_markdown_spec_docs>
|
|
6864
6980
|
${readAsset(
|
|
6865
6981
|
"prompt",
|
|
@@ -6898,7 +7014,7 @@ var specSyncTool = {
|
|
|
6898
7014
|
}
|
|
6899
7015
|
const specIndex = loadSpecIndex();
|
|
6900
7016
|
const parts = [
|
|
6901
|
-
|
|
7017
|
+
BASE_PROMPT6,
|
|
6902
7018
|
loadPlatformBrief(),
|
|
6903
7019
|
MSFM_DOCS,
|
|
6904
7020
|
"<!-- cache_breakpoint -->"
|
|
@@ -7013,7 +7129,6 @@ var ALL_TOOLS = [
|
|
|
7013
7129
|
confirmDestructiveActionTool,
|
|
7014
7130
|
askMindStudioSdkTool,
|
|
7015
7131
|
scrapeWebUrlTool,
|
|
7016
|
-
searchGoogleTool,
|
|
7017
7132
|
setProjectMetadataTool,
|
|
7018
7133
|
designExpertTool,
|
|
7019
7134
|
productVisionTool,
|
|
@@ -7052,7 +7167,8 @@ var ALL_TOOLS = [
|
|
|
7052
7167
|
// Appended rather than grouped: position is part of the cache prefix, so a
|
|
7053
7168
|
// new tool goes at the end to leave every existing session's prefix intact.
|
|
7054
7169
|
loadSkillTool,
|
|
7055
|
-
testJewelTool
|
|
7170
|
+
testJewelTool,
|
|
7171
|
+
researchTool
|
|
7056
7172
|
];
|
|
7057
7173
|
var SUBAGENT_TOOL_NAMES = /* @__PURE__ */ new Set([
|
|
7058
7174
|
"visualDesignExpert",
|
|
@@ -7061,7 +7177,8 @@ var SUBAGENT_TOOL_NAMES = /* @__PURE__ */ new Set([
|
|
|
7061
7177
|
"copyEditor",
|
|
7062
7178
|
"specSync",
|
|
7063
7179
|
"runAutomatedBrowserTest",
|
|
7064
|
-
"askMindStudioSdk"
|
|
7180
|
+
"askMindStudioSdk",
|
|
7181
|
+
"research"
|
|
7065
7182
|
]);
|
|
7066
7183
|
function getToolDefinitions() {
|
|
7067
7184
|
return ALL_TOOLS.map((t) => t.definition);
|