@mindstudio-ai/remy 0.1.313 → 0.1.314
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 +347 -232
- package/dist/index.js +404 -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",
|
|
@@ -1884,158 +1891,6 @@ var askMindStudioSdkTool = {
|
|
|
1884
1891
|
}
|
|
1885
1892
|
};
|
|
1886
1893
|
|
|
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
1894
|
// src/tools/common/setProjectMetadata.ts
|
|
2040
1895
|
var setProjectMetadataTool = {
|
|
2041
1896
|
definition: {
|
|
@@ -2160,7 +2015,7 @@ This reference lives at ${skill.path}. Re-read it with readFile if you need it a
|
|
|
2160
2015
|
};
|
|
2161
2016
|
|
|
2162
2017
|
// src/tools/code/readFile.ts
|
|
2163
|
-
import
|
|
2018
|
+
import fs12 from "fs/promises";
|
|
2164
2019
|
var DEFAULT_WINDOW = 500;
|
|
2165
2020
|
var MAX_BYTES = 64 * 1024;
|
|
2166
2021
|
function isBinary(buffer) {
|
|
@@ -2201,7 +2056,7 @@ var readFileTool = {
|
|
|
2201
2056
|
},
|
|
2202
2057
|
async execute(input) {
|
|
2203
2058
|
try {
|
|
2204
|
-
const buffer = await
|
|
2059
|
+
const buffer = await fs12.readFile(input.path);
|
|
2205
2060
|
if (isBinary(buffer)) {
|
|
2206
2061
|
const size = buffer.length;
|
|
2207
2062
|
const unit = size > 1024 * 1024 ? `${(size / (1024 * 1024)).toFixed(1)}MB` : `${(size / 1024).toFixed(1)}KB`;
|
|
@@ -2273,7 +2128,7 @@ var readFileTool = {
|
|
|
2273
2128
|
};
|
|
2274
2129
|
|
|
2275
2130
|
// src/tools/code/writeFile.ts
|
|
2276
|
-
import
|
|
2131
|
+
import fs13 from "fs/promises";
|
|
2277
2132
|
import path6 from "path";
|
|
2278
2133
|
var writeFileTool = {
|
|
2279
2134
|
definition: {
|
|
@@ -2310,7 +2165,7 @@ var writeFileTool = {
|
|
|
2310
2165
|
lastNewlineCount = newlineCount;
|
|
2311
2166
|
const lastNewline = partial.content.lastIndexOf("\n");
|
|
2312
2167
|
const completeContent = partial.content.substring(0, lastNewline + 1);
|
|
2313
|
-
const oldContent = await
|
|
2168
|
+
const oldContent = await fs13.readFile(partial.path, "utf-8").catch(() => "");
|
|
2314
2169
|
return `Writing ${partial.path} (${newlineCount} lines)
|
|
2315
2170
|
${unifiedDiff(partial.path, oldContent, completeContent)}`;
|
|
2316
2171
|
}
|
|
@@ -2319,13 +2174,13 @@ ${unifiedDiff(partial.path, oldContent, completeContent)}`;
|
|
|
2319
2174
|
async execute(input) {
|
|
2320
2175
|
const release = await acquireFileLock(input.path);
|
|
2321
2176
|
try {
|
|
2322
|
-
await
|
|
2177
|
+
await fs13.mkdir(path6.dirname(input.path), { recursive: true });
|
|
2323
2178
|
let oldContent = null;
|
|
2324
2179
|
try {
|
|
2325
|
-
oldContent = await
|
|
2180
|
+
oldContent = await fs13.readFile(input.path, "utf-8");
|
|
2326
2181
|
} catch {
|
|
2327
2182
|
}
|
|
2328
|
-
await
|
|
2183
|
+
await fs13.writeFile(input.path, input.content, "utf-8");
|
|
2329
2184
|
const lineCount = input.content.split("\n").length;
|
|
2330
2185
|
const label = oldContent !== null ? "Wrote" : "Created";
|
|
2331
2186
|
return `${label} ${input.path} (${lineCount} lines)
|
|
@@ -2339,7 +2194,7 @@ ${unifiedDiff(input.path, oldContent ?? "", input.content)}`;
|
|
|
2339
2194
|
};
|
|
2340
2195
|
|
|
2341
2196
|
// src/tools/code/editFile/index.ts
|
|
2342
|
-
import
|
|
2197
|
+
import fs14 from "fs/promises";
|
|
2343
2198
|
var editFileTool = {
|
|
2344
2199
|
definition: {
|
|
2345
2200
|
name: "editFile",
|
|
@@ -2370,7 +2225,7 @@ var editFileTool = {
|
|
|
2370
2225
|
async execute(input) {
|
|
2371
2226
|
const release = await acquireFileLock(input.path);
|
|
2372
2227
|
try {
|
|
2373
|
-
const content = await
|
|
2228
|
+
const content = await fs14.readFile(input.path, "utf-8");
|
|
2374
2229
|
const { old_string, new_string, replace_all } = input;
|
|
2375
2230
|
const occurrences = findOccurrences(content, old_string);
|
|
2376
2231
|
if (replace_all) {
|
|
@@ -2386,7 +2241,7 @@ var editFileTool = {
|
|
|
2386
2241
|
new_string
|
|
2387
2242
|
);
|
|
2388
2243
|
}
|
|
2389
|
-
await
|
|
2244
|
+
await fs14.writeFile(input.path, updated, "utf-8");
|
|
2390
2245
|
return `Replaced ${occurrences.length} occurrence${occurrences.length > 1 ? "s" : ""} in ${input.path}
|
|
2391
2246
|
${unifiedDiff(input.path, content, updated)}`;
|
|
2392
2247
|
}
|
|
@@ -2397,7 +2252,7 @@ ${unifiedDiff(input.path, content, updated)}`;
|
|
|
2397
2252
|
old_string.length,
|
|
2398
2253
|
new_string
|
|
2399
2254
|
);
|
|
2400
|
-
await
|
|
2255
|
+
await fs14.writeFile(input.path, updated, "utf-8");
|
|
2401
2256
|
return `Updated ${input.path}
|
|
2402
2257
|
${unifiedDiff(input.path, content, updated)}`;
|
|
2403
2258
|
}
|
|
@@ -2413,7 +2268,7 @@ ${unifiedDiff(input.path, content, updated)}`;
|
|
|
2413
2268
|
flex.matchedText.length,
|
|
2414
2269
|
new_string
|
|
2415
2270
|
);
|
|
2416
|
-
await
|
|
2271
|
+
await fs14.writeFile(input.path, updated, "utf-8");
|
|
2417
2272
|
return `Updated ${input.path} (matched with flexible whitespace at line ${flex.line})
|
|
2418
2273
|
${unifiedDiff(input.path, content, updated)}`;
|
|
2419
2274
|
}
|
|
@@ -2739,12 +2594,12 @@ var globTool = {
|
|
|
2739
2594
|
};
|
|
2740
2595
|
|
|
2741
2596
|
// src/tools/code/listDir.ts
|
|
2742
|
-
import
|
|
2597
|
+
import fs15 from "fs/promises";
|
|
2743
2598
|
import path8 from "path";
|
|
2744
2599
|
var EXCLUDE = /* @__PURE__ */ new Set([".git", "node_modules"]);
|
|
2745
2600
|
var MAX_CHILDREN = 15;
|
|
2746
2601
|
async function readAndSort(dirPath) {
|
|
2747
|
-
const entries = await
|
|
2602
|
+
const entries = await fs15.readdir(dirPath, { withFileTypes: true });
|
|
2748
2603
|
return entries.filter((e) => !EXCLUDE.has(e.name)).sort((a, b) => {
|
|
2749
2604
|
if (a.isDirectory() && !b.isDirectory()) {
|
|
2750
2605
|
return -1;
|
|
@@ -2785,7 +2640,7 @@ function formatSize(bytes) {
|
|
|
2785
2640
|
}
|
|
2786
2641
|
async function formatFile(dirPath, name, indent) {
|
|
2787
2642
|
try {
|
|
2788
|
-
const stat4 = await
|
|
2643
|
+
const stat4 = await fs15.stat(path8.join(dirPath, name));
|
|
2789
2644
|
return `${indent}${name}${" ".repeat(Math.max(1, 30 - indent.length - name.length))}${formatSize(stat4.size)}`;
|
|
2790
2645
|
} catch {
|
|
2791
2646
|
return `${indent}${name}`;
|
|
@@ -3117,6 +2972,119 @@ var queryDatabaseTool = {
|
|
|
3117
2972
|
}
|
|
3118
2973
|
};
|
|
3119
2974
|
|
|
2975
|
+
// src/usageLedger.ts
|
|
2976
|
+
import fs16 from "fs";
|
|
2977
|
+
var LEDGER_FILE = ".logs/usage.ndjson";
|
|
2978
|
+
var fd = null;
|
|
2979
|
+
function nanoToDollars(nano) {
|
|
2980
|
+
return typeof nano === "number" ? nano / 1e9 : void 0;
|
|
2981
|
+
}
|
|
2982
|
+
function recordUsage(entry) {
|
|
2983
|
+
try {
|
|
2984
|
+
if (fd === null) {
|
|
2985
|
+
fs16.mkdirSync(".logs", { recursive: true });
|
|
2986
|
+
fd = fs16.openSync(LEDGER_FILE, "a");
|
|
2987
|
+
}
|
|
2988
|
+
fs16.writeSync(fd, JSON.stringify(entry) + "\n");
|
|
2989
|
+
} catch {
|
|
2990
|
+
}
|
|
2991
|
+
}
|
|
2992
|
+
|
|
2993
|
+
// src/subagents/common/runMindstudioCli.ts
|
|
2994
|
+
function stripFlags(args) {
|
|
2995
|
+
const out = [];
|
|
2996
|
+
for (let i = 0; i < args.length; i++) {
|
|
2997
|
+
const arg = args[i];
|
|
2998
|
+
if (arg === "--no-meta") {
|
|
2999
|
+
continue;
|
|
3000
|
+
}
|
|
3001
|
+
if (arg === "--output-key") {
|
|
3002
|
+
i++;
|
|
3003
|
+
continue;
|
|
3004
|
+
}
|
|
3005
|
+
out.push(arg);
|
|
3006
|
+
}
|
|
3007
|
+
return out;
|
|
3008
|
+
}
|
|
3009
|
+
async function runMindstudioCliResult(args, options) {
|
|
3010
|
+
const cleanArgs = stripFlags(args);
|
|
3011
|
+
const cliAction = args[0];
|
|
3012
|
+
const agentName = options?.caller ?? "mindstudio-cli";
|
|
3013
|
+
const start = Date.now();
|
|
3014
|
+
const res = await runCli("mindstudio", cleanArgs, options);
|
|
3015
|
+
if (!res.ok) {
|
|
3016
|
+
return { ok: false, value: formatCliResult(res) };
|
|
3017
|
+
}
|
|
3018
|
+
const truncNote = res.truncated ? "\n\n[output truncated]" : "";
|
|
3019
|
+
let envelope;
|
|
3020
|
+
try {
|
|
3021
|
+
envelope = JSON.parse(res.output);
|
|
3022
|
+
} catch {
|
|
3023
|
+
return { ok: true, value: res.output + truncNote };
|
|
3024
|
+
}
|
|
3025
|
+
if (envelope && typeof envelope === "object" && Array.isArray(envelope.results)) {
|
|
3026
|
+
const durationMs = Date.now() - start;
|
|
3027
|
+
for (const step of envelope.results) {
|
|
3028
|
+
if (typeof step?.billingCost === "number") {
|
|
3029
|
+
recordUsage({
|
|
3030
|
+
ts: Date.now(),
|
|
3031
|
+
agentName,
|
|
3032
|
+
cliAction: `${cliAction}:${step.stepType ?? "step"}`,
|
|
3033
|
+
cost: nanoToDollars(step.billingCost),
|
|
3034
|
+
inputTokens: 0,
|
|
3035
|
+
outputTokens: 0,
|
|
3036
|
+
durationMs,
|
|
3037
|
+
toolNames: []
|
|
3038
|
+
});
|
|
3039
|
+
}
|
|
3040
|
+
}
|
|
3041
|
+
return { ok: true, value: JSON.stringify(envelope.results) + truncNote };
|
|
3042
|
+
}
|
|
3043
|
+
if (typeof envelope?.$billingCost === "number") {
|
|
3044
|
+
recordUsage({
|
|
3045
|
+
ts: Date.now(),
|
|
3046
|
+
agentName,
|
|
3047
|
+
cliAction,
|
|
3048
|
+
cost: nanoToDollars(envelope.$billingCost),
|
|
3049
|
+
billingEvents: envelope.$billingEvents,
|
|
3050
|
+
// CLI billing isn't expressed as input/output tokens for most actions
|
|
3051
|
+
// (image gen is per-image, scrape per-page, etc). `numUnits` inside each
|
|
3052
|
+
// billingEvent carries the per-event unit count.
|
|
3053
|
+
inputTokens: 0,
|
|
3054
|
+
outputTokens: 0,
|
|
3055
|
+
durationMs: Date.now() - start,
|
|
3056
|
+
toolNames: []
|
|
3057
|
+
});
|
|
3058
|
+
}
|
|
3059
|
+
if (options?.outputKey) {
|
|
3060
|
+
const v = envelope?.[options.outputKey];
|
|
3061
|
+
if (v === void 0 || v === null) {
|
|
3062
|
+
return { ok: false, value: JSON.stringify(stripDollarKeys(envelope)) };
|
|
3063
|
+
}
|
|
3064
|
+
const value = typeof v === "string" ? v : JSON.stringify(v);
|
|
3065
|
+
return { ok: true, value: value + truncNote };
|
|
3066
|
+
}
|
|
3067
|
+
return {
|
|
3068
|
+
ok: true,
|
|
3069
|
+
value: JSON.stringify(stripDollarKeys(envelope)) + truncNote
|
|
3070
|
+
};
|
|
3071
|
+
}
|
|
3072
|
+
async function runMindstudioCli(args, options) {
|
|
3073
|
+
return (await runMindstudioCliResult(args, options)).value;
|
|
3074
|
+
}
|
|
3075
|
+
function stripDollarKeys(envelope) {
|
|
3076
|
+
if (!envelope || typeof envelope !== "object" || Array.isArray(envelope)) {
|
|
3077
|
+
return envelope;
|
|
3078
|
+
}
|
|
3079
|
+
const out = {};
|
|
3080
|
+
for (const [k, v] of Object.entries(envelope)) {
|
|
3081
|
+
if (!k.startsWith("$")) {
|
|
3082
|
+
out[k] = v;
|
|
3083
|
+
}
|
|
3084
|
+
}
|
|
3085
|
+
return out;
|
|
3086
|
+
}
|
|
3087
|
+
|
|
3120
3088
|
// src/tools/_helpers/uploadImage.ts
|
|
3121
3089
|
import { readFile, stat } from "fs/promises";
|
|
3122
3090
|
import { basename, extname, resolve } from "path";
|
|
@@ -4595,7 +4563,7 @@ The first-party SDK (@mindstudio-ai/agent) provides access to 200+ AI models (Op
|
|
|
4595
4563
|
## What Remy apps are NOT good for
|
|
4596
4564
|
|
|
4597
4565
|
- Native mobile apps (iOS/Android). Mobile-responsive web apps are fine.
|
|
4598
|
-
-
|
|
4566
|
+
- 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
4567
|
</platform_brief>`;
|
|
4600
4568
|
}
|
|
4601
4569
|
|
|
@@ -4884,56 +4852,155 @@ var screenshotTool = {
|
|
|
4884
4852
|
execute: (input, context) => executeScreenshot(input, context?.onLog, context)
|
|
4885
4853
|
};
|
|
4886
4854
|
|
|
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 = {
|
|
4855
|
+
// src/subagents/research/tools.ts
|
|
4856
|
+
var searchGoogleDefinition = {
|
|
4895
4857
|
name: "searchGoogle",
|
|
4896
|
-
description:
|
|
4858
|
+
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
4859
|
inputSchema: {
|
|
4898
4860
|
type: "object",
|
|
4899
4861
|
properties: {
|
|
4900
4862
|
query: {
|
|
4901
4863
|
type: "string",
|
|
4902
4864
|
description: "The search query."
|
|
4865
|
+
},
|
|
4866
|
+
fetchTopN: {
|
|
4867
|
+
type: "number",
|
|
4868
|
+
description: "Also fetch page content (capped ~4,000 chars each) for this many top results. Omit for a fast SERP-only search."
|
|
4903
4869
|
}
|
|
4904
4870
|
},
|
|
4905
4871
|
required: ["query"]
|
|
4906
4872
|
}
|
|
4907
4873
|
};
|
|
4908
|
-
|
|
4874
|
+
var scrapeWebUrlDefinition = {
|
|
4875
|
+
name: "scrapeWebUrl",
|
|
4876
|
+
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.",
|
|
4877
|
+
inputSchema: {
|
|
4878
|
+
type: "object",
|
|
4879
|
+
properties: {
|
|
4880
|
+
url: {
|
|
4881
|
+
type: "string",
|
|
4882
|
+
description: "The URL to fetch."
|
|
4883
|
+
}
|
|
4884
|
+
},
|
|
4885
|
+
required: ["url"]
|
|
4886
|
+
}
|
|
4887
|
+
};
|
|
4888
|
+
var RESEARCH_TOOLS = [
|
|
4889
|
+
...COMMON_READ_TOOLS,
|
|
4890
|
+
searchGoogleDefinition,
|
|
4891
|
+
scrapeWebUrlDefinition,
|
|
4892
|
+
bashTool.definition
|
|
4893
|
+
];
|
|
4894
|
+
async function executeSearchGoogle(input, onLog, caller) {
|
|
4895
|
+
const fetchTopN = Math.max(0, Math.round(Number(input.fetchTopN) || 0));
|
|
4909
4896
|
return runMindstudioCli(
|
|
4910
4897
|
[
|
|
4911
4898
|
"search-google",
|
|
4912
4899
|
"--query",
|
|
4913
|
-
input.query,
|
|
4900
|
+
String(input.query),
|
|
4914
4901
|
"--export-type",
|
|
4915
4902
|
"json",
|
|
4916
4903
|
"--fetch-top-n",
|
|
4917
|
-
String(
|
|
4904
|
+
String(fetchTopN)
|
|
4918
4905
|
],
|
|
4919
4906
|
{
|
|
4920
4907
|
outputKey: "results",
|
|
4908
|
+
maxBuffer: SEARCH_MAX_BUFFER,
|
|
4909
|
+
onLog,
|
|
4910
|
+
caller
|
|
4911
|
+
}
|
|
4912
|
+
);
|
|
4913
|
+
}
|
|
4914
|
+
async function executeScrapeWebUrl(input, onLog, caller) {
|
|
4915
|
+
return runMindstudioCli(
|
|
4916
|
+
[
|
|
4917
|
+
"scrape-url",
|
|
4918
|
+
"--url",
|
|
4919
|
+
String(input.url),
|
|
4920
|
+
"--page-options",
|
|
4921
|
+
JSON.stringify({ onlyMainContent: true })
|
|
4922
|
+
],
|
|
4923
|
+
{
|
|
4924
|
+
maxBuffer: SCRAPE_MAX_BUFFER,
|
|
4921
4925
|
onLog,
|
|
4922
|
-
caller
|
|
4923
|
-
maxBuffer: SEARCH_MAX_BUFFER
|
|
4926
|
+
caller
|
|
4924
4927
|
}
|
|
4925
4928
|
);
|
|
4926
4929
|
}
|
|
4927
4930
|
|
|
4931
|
+
// src/subagents/research/index.ts
|
|
4932
|
+
var BASE_PROMPT2 = readAsset("subagents/research", "prompt.md");
|
|
4933
|
+
async function runResearch(task, context) {
|
|
4934
|
+
const specIndex = loadSpecIndex();
|
|
4935
|
+
const parts = [BASE_PROMPT2, loadPlatformBrief()];
|
|
4936
|
+
parts.push("<!-- cache_breakpoint -->");
|
|
4937
|
+
if (specIndex) {
|
|
4938
|
+
parts.push(specIndex);
|
|
4939
|
+
}
|
|
4940
|
+
const system = parts.join("\n\n");
|
|
4941
|
+
const result = await runSubAgent({
|
|
4942
|
+
system,
|
|
4943
|
+
task,
|
|
4944
|
+
tools: RESEARCH_TOOLS,
|
|
4945
|
+
externalTools: /* @__PURE__ */ new Set(),
|
|
4946
|
+
executeTool: (name, toolInput, toolCallId, onLog, sams) => {
|
|
4947
|
+
const childCtx = toolCallId ? {
|
|
4948
|
+
...deriveContext(context, toolCallId, onLog),
|
|
4949
|
+
subAgentMessages: sams
|
|
4950
|
+
} : context;
|
|
4951
|
+
if (name === "searchGoogle") {
|
|
4952
|
+
return executeSearchGoogle(toolInput, childCtx.onLog, "research");
|
|
4953
|
+
}
|
|
4954
|
+
if (name === "scrapeWebUrl") {
|
|
4955
|
+
return executeScrapeWebUrl(toolInput, childCtx.onLog, "research");
|
|
4956
|
+
}
|
|
4957
|
+
return executeTool(name, toolInput, childCtx);
|
|
4958
|
+
},
|
|
4959
|
+
apiConfig: context.apiConfig,
|
|
4960
|
+
model: resolveModel("research", context.models, context.model),
|
|
4961
|
+
subAgentId: "research",
|
|
4962
|
+
signal: context.signal,
|
|
4963
|
+
parentToolId: context.toolCallId,
|
|
4964
|
+
requestId: context.requestId,
|
|
4965
|
+
onEvent: context.onEvent,
|
|
4966
|
+
resolveExternalTool: context.resolveExternalTool,
|
|
4967
|
+
toolRegistry: context.toolRegistry
|
|
4968
|
+
});
|
|
4969
|
+
context.subAgentMessages?.set(context.toolCallId, result.messages);
|
|
4970
|
+
return result.text;
|
|
4971
|
+
}
|
|
4972
|
+
var researchTool = {
|
|
4973
|
+
definition: {
|
|
4974
|
+
name: "research",
|
|
4975
|
+
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.",
|
|
4976
|
+
inputSchema: {
|
|
4977
|
+
type: "object",
|
|
4978
|
+
properties: {
|
|
4979
|
+
task: {
|
|
4980
|
+
type: "string",
|
|
4981
|
+
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."
|
|
4982
|
+
}
|
|
4983
|
+
},
|
|
4984
|
+
required: ["task"]
|
|
4985
|
+
}
|
|
4986
|
+
},
|
|
4987
|
+
async execute(input, context) {
|
|
4988
|
+
if (!context) {
|
|
4989
|
+
return "Error: research requires execution context";
|
|
4990
|
+
}
|
|
4991
|
+
return runResearch(input.task, context);
|
|
4992
|
+
}
|
|
4993
|
+
};
|
|
4994
|
+
|
|
4928
4995
|
// src/subagents/designExpert/tools/scrapeWebUrl.ts
|
|
4929
4996
|
var scrapeWebUrl_exports = {};
|
|
4930
4997
|
__export(scrapeWebUrl_exports, {
|
|
4931
|
-
definition: () =>
|
|
4932
|
-
execute: () =>
|
|
4998
|
+
definition: () => definition,
|
|
4999
|
+
execute: () => execute
|
|
4933
5000
|
});
|
|
4934
|
-
var
|
|
5001
|
+
var definition = {
|
|
4935
5002
|
name: "scrapeWebUrl",
|
|
4936
|
-
description: "Fetch the content of a web page as markdown. Use
|
|
5003
|
+
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
5004
|
inputSchema: {
|
|
4938
5005
|
type: "object",
|
|
4939
5006
|
properties: {
|
|
@@ -4945,7 +5012,7 @@ var definition2 = {
|
|
|
4945
5012
|
required: ["url"]
|
|
4946
5013
|
}
|
|
4947
5014
|
};
|
|
4948
|
-
async function
|
|
5015
|
+
async function execute(input, onLog) {
|
|
4949
5016
|
const pageOptions = { onlyMainContent: true };
|
|
4950
5017
|
return runMindstudioCli(
|
|
4951
5018
|
[
|
|
@@ -4962,8 +5029,8 @@ async function execute2(input, onLog) {
|
|
|
4962
5029
|
// src/subagents/designExpert/tools/analyzeDesign.ts
|
|
4963
5030
|
var analyzeDesign_exports = {};
|
|
4964
5031
|
__export(analyzeDesign_exports, {
|
|
4965
|
-
definition: () =>
|
|
4966
|
-
execute: () =>
|
|
5032
|
+
definition: () => definition3,
|
|
5033
|
+
execute: () => execute3
|
|
4967
5034
|
});
|
|
4968
5035
|
import { readFile as readFile2 } from "fs/promises";
|
|
4969
5036
|
import { extname as extname2, join as join2 } from "path";
|
|
@@ -4972,8 +5039,8 @@ import { extname as extname2, join as join2 } from "path";
|
|
|
4972
5039
|
var renderImage_exports = {};
|
|
4973
5040
|
__export(renderImage_exports, {
|
|
4974
5041
|
RENDER_ANALYZE_PROMPT: () => RENDER_ANALYZE_PROMPT,
|
|
4975
|
-
definition: () =>
|
|
4976
|
-
execute: () =>
|
|
5042
|
+
definition: () => definition2,
|
|
5043
|
+
execute: () => execute2
|
|
4977
5044
|
});
|
|
4978
5045
|
import { mkdir, unlink, writeFile } from "fs/promises";
|
|
4979
5046
|
import { tmpdir } from "os";
|
|
@@ -4982,7 +5049,7 @@ import { randomUUID } from "crypto";
|
|
|
4982
5049
|
var MIN_DIMENSION = 16;
|
|
4983
5050
|
var MAX_DIMENSION = 4096;
|
|
4984
5051
|
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
|
|
5052
|
+
var definition2 = {
|
|
4986
5053
|
name: "renderImage",
|
|
4987
5054
|
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
5055
|
inputSchema: {
|
|
@@ -5016,7 +5083,7 @@ var definition3 = {
|
|
|
5016
5083
|
required: ["html", "width", "height"]
|
|
5017
5084
|
}
|
|
5018
5085
|
};
|
|
5019
|
-
async function
|
|
5086
|
+
async function execute2(input, onLog, context) {
|
|
5020
5087
|
const html = typeof input.html === "string" ? input.html : "";
|
|
5021
5088
|
const width = Math.round(Number(input.width));
|
|
5022
5089
|
const height = Math.round(Number(input.height));
|
|
@@ -5125,7 +5192,7 @@ Identify the specific design moves that make this page interesting and unique, d
|
|
|
5125
5192
|
|
|
5126
5193
|
Respond only with your analysis as Markdown and absolutely no other text. Do not use emojis - use unicode if you need symbols.
|
|
5127
5194
|
`;
|
|
5128
|
-
var
|
|
5195
|
+
var definition3 = {
|
|
5129
5196
|
name: "analyzeDesign",
|
|
5130
5197
|
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
5198
|
inputSchema: {
|
|
@@ -5165,7 +5232,7 @@ function splitFrontmatter(raw) {
|
|
|
5165
5232
|
html: raw.slice(match[0].length)
|
|
5166
5233
|
};
|
|
5167
5234
|
}
|
|
5168
|
-
async function
|
|
5235
|
+
async function execute3(input, onLog, context) {
|
|
5169
5236
|
const url = String(input.url ?? "").trim();
|
|
5170
5237
|
if (!url) {
|
|
5171
5238
|
return "Error: url is required.";
|
|
@@ -5273,10 +5340,10 @@ ${basePrompt}` : basePrompt;
|
|
|
5273
5340
|
// src/subagents/designExpert/tools/analyzeImage.ts
|
|
5274
5341
|
var analyzeImage_exports = {};
|
|
5275
5342
|
__export(analyzeImage_exports, {
|
|
5276
|
-
definition: () =>
|
|
5277
|
-
execute: () =>
|
|
5343
|
+
definition: () => definition4,
|
|
5344
|
+
execute: () => execute4
|
|
5278
5345
|
});
|
|
5279
|
-
var
|
|
5346
|
+
var definition4 = {
|
|
5280
5347
|
name: "analyzeImage",
|
|
5281
5348
|
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
5349
|
inputSchema: {
|
|
@@ -5297,7 +5364,7 @@ var definition5 = {
|
|
|
5297
5364
|
required: ["imageUrl"]
|
|
5298
5365
|
}
|
|
5299
5366
|
};
|
|
5300
|
-
async function
|
|
5367
|
+
async function execute4(input, onLog, context) {
|
|
5301
5368
|
const prompt = buildScreenshotAnalysisPrompt({
|
|
5302
5369
|
prompt: input.prompt
|
|
5303
5370
|
});
|
|
@@ -5314,8 +5381,8 @@ async function execute5(input, onLog, context) {
|
|
|
5314
5381
|
// src/subagents/designExpert/tools/images/generateImages.ts
|
|
5315
5382
|
var generateImages_exports = {};
|
|
5316
5383
|
__export(generateImages_exports, {
|
|
5317
|
-
definition: () =>
|
|
5318
|
-
execute: () =>
|
|
5384
|
+
definition: () => definition5,
|
|
5385
|
+
execute: () => execute5
|
|
5319
5386
|
});
|
|
5320
5387
|
|
|
5321
5388
|
// src/subagents/designExpert/tools/images/enhancePrompt.ts
|
|
@@ -5542,7 +5609,7 @@ async function generateImageAssets(opts) {
|
|
|
5542
5609
|
}
|
|
5543
5610
|
|
|
5544
5611
|
// src/subagents/designExpert/tools/images/generateImages.ts
|
|
5545
|
-
var
|
|
5612
|
+
var definition5 = {
|
|
5546
5613
|
name: "generateImages",
|
|
5547
5614
|
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
5615
|
inputSchema: {
|
|
@@ -5575,7 +5642,7 @@ var definition6 = {
|
|
|
5575
5642
|
required: ["prompts"]
|
|
5576
5643
|
}
|
|
5577
5644
|
};
|
|
5578
|
-
async function
|
|
5645
|
+
async function execute5(input, onLog, context) {
|
|
5579
5646
|
return generateImageAssets({
|
|
5580
5647
|
prompts: input.prompts,
|
|
5581
5648
|
width: input.width,
|
|
@@ -5606,10 +5673,10 @@ async function execute6(input, onLog, context) {
|
|
|
5606
5673
|
// src/subagents/designExpert/tools/images/editImages.ts
|
|
5607
5674
|
var editImages_exports = {};
|
|
5608
5675
|
__export(editImages_exports, {
|
|
5609
|
-
definition: () =>
|
|
5610
|
-
execute: () =>
|
|
5676
|
+
definition: () => definition6,
|
|
5677
|
+
execute: () => execute6
|
|
5611
5678
|
});
|
|
5612
|
-
var
|
|
5679
|
+
var definition6 = {
|
|
5613
5680
|
name: "editImages",
|
|
5614
5681
|
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
5682
|
inputSchema: {
|
|
@@ -5645,7 +5712,7 @@ var definition7 = {
|
|
|
5645
5712
|
required: ["prompts", "sourceImages"]
|
|
5646
5713
|
}
|
|
5647
5714
|
};
|
|
5648
|
-
async function
|
|
5715
|
+
async function execute6(input, onLog, context) {
|
|
5649
5716
|
return generateImageAssets({
|
|
5650
5717
|
prompts: input.prompts,
|
|
5651
5718
|
sourceImages: input.sourceImages,
|
|
@@ -5676,15 +5743,15 @@ async function execute7(input, onLog, context) {
|
|
|
5676
5743
|
// src/subagents/designExpert/tools/polishCopy.ts
|
|
5677
5744
|
var polishCopy_exports = {};
|
|
5678
5745
|
__export(polishCopy_exports, {
|
|
5679
|
-
definition: () =>
|
|
5680
|
-
execute: () =>
|
|
5746
|
+
definition: () => definition7,
|
|
5747
|
+
execute: () => execute7
|
|
5681
5748
|
});
|
|
5682
5749
|
|
|
5683
5750
|
// src/subagents/copyEditor/tools.ts
|
|
5684
5751
|
var COPY_EDITOR_TOOLS = [...COMMON_READ_TOOLS];
|
|
5685
5752
|
|
|
5686
5753
|
// src/subagents/copyEditor/index.ts
|
|
5687
|
-
var
|
|
5754
|
+
var BASE_PROMPT3 = readAsset("subagents/copyEditor", "prompt.md");
|
|
5688
5755
|
var copyEditorTool = {
|
|
5689
5756
|
definition: {
|
|
5690
5757
|
name: "copyEditor",
|
|
@@ -5705,7 +5772,7 @@ var copyEditorTool = {
|
|
|
5705
5772
|
return "Error: copy editor requires execution context";
|
|
5706
5773
|
}
|
|
5707
5774
|
const specIndex = loadSpecIndex();
|
|
5708
|
-
const parts = [
|
|
5775
|
+
const parts = [BASE_PROMPT3];
|
|
5709
5776
|
parts.push("<!-- cache_breakpoint -->");
|
|
5710
5777
|
if (specIndex) {
|
|
5711
5778
|
parts.push(specIndex);
|
|
@@ -5739,7 +5806,7 @@ var copyEditorTool = {
|
|
|
5739
5806
|
};
|
|
5740
5807
|
|
|
5741
5808
|
// src/subagents/designExpert/tools/polishCopy.ts
|
|
5742
|
-
var
|
|
5809
|
+
var definition7 = {
|
|
5743
5810
|
name: "polishCopy",
|
|
5744
5811
|
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
5812
|
inputSchema: {
|
|
@@ -5753,15 +5820,15 @@ var definition8 = {
|
|
|
5753
5820
|
required: ["task"]
|
|
5754
5821
|
}
|
|
5755
5822
|
};
|
|
5756
|
-
async function
|
|
5823
|
+
async function execute7(input, _onLog, context) {
|
|
5757
5824
|
return copyEditorTool.execute(input, context);
|
|
5758
5825
|
}
|
|
5759
5826
|
|
|
5760
5827
|
// src/subagents/designExpert/tools/loadSkill.ts
|
|
5761
5828
|
var loadSkill_exports = {};
|
|
5762
5829
|
__export(loadSkill_exports, {
|
|
5763
|
-
definition: () =>
|
|
5764
|
-
execute: () =>
|
|
5830
|
+
definition: () => definition8,
|
|
5831
|
+
execute: () => execute8
|
|
5765
5832
|
});
|
|
5766
5833
|
|
|
5767
5834
|
// src/subagents/designExpert/skills/_catalog.ts
|
|
@@ -5775,7 +5842,7 @@ var designSkillCatalog = buildSkillCatalog({
|
|
|
5775
5842
|
});
|
|
5776
5843
|
|
|
5777
5844
|
// src/subagents/designExpert/tools/loadSkill.ts
|
|
5778
|
-
var
|
|
5845
|
+
var definition8 = {
|
|
5779
5846
|
name: "loadSkill",
|
|
5780
5847
|
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
5848
|
inputSchema: {
|
|
@@ -5793,7 +5860,7 @@ var definition9 = {
|
|
|
5793
5860
|
required: ["skill"]
|
|
5794
5861
|
}
|
|
5795
5862
|
};
|
|
5796
|
-
async function
|
|
5863
|
+
async function execute8(input) {
|
|
5797
5864
|
const id = String(input.skill ?? "");
|
|
5798
5865
|
const skill = designSkillCatalog.get(id);
|
|
5799
5866
|
if (!skill) {
|
|
@@ -5814,15 +5881,15 @@ This reference lives at ${skill.path}. Re-read it with readFile if you need it a
|
|
|
5814
5881
|
var createWireframe_exports = {};
|
|
5815
5882
|
__export(createWireframe_exports, {
|
|
5816
5883
|
WIREFRAMES_DIR: () => WIREFRAMES_DIR,
|
|
5817
|
-
definition: () =>
|
|
5818
|
-
execute: () =>
|
|
5884
|
+
definition: () => definition9,
|
|
5885
|
+
execute: () => execute9
|
|
5819
5886
|
});
|
|
5820
5887
|
import { mkdir as mkdir2, stat as stat2, writeFile as writeFile2 } from "fs/promises";
|
|
5821
5888
|
import { join as join3 } from "path";
|
|
5822
5889
|
var log9 = createLogger("createWireframe");
|
|
5823
5890
|
var WIREFRAMES_DIR = "src/.wireframes";
|
|
5824
5891
|
var UPLOAD_TIMEOUT_MS2 = 3e4;
|
|
5825
|
-
var
|
|
5892
|
+
var definition9 = {
|
|
5826
5893
|
name: "createWireframe",
|
|
5827
5894
|
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
5895
|
inputSchema: {
|
|
@@ -5916,7 +5983,7 @@ async function uploadMirror(context, slug, content) {
|
|
|
5916
5983
|
return { ok: false, note: err.message };
|
|
5917
5984
|
}
|
|
5918
5985
|
}
|
|
5919
|
-
async function
|
|
5986
|
+
async function execute9(input, onLog, context) {
|
|
5920
5987
|
if (!context) {
|
|
5921
5988
|
return "Error: createWireframe requires execution context";
|
|
5922
5989
|
}
|
|
@@ -5964,8 +6031,29 @@ async function execute10(input, onLog, context) {
|
|
|
5964
6031
|
}
|
|
5965
6032
|
|
|
5966
6033
|
// src/subagents/designExpert/tools/index.ts
|
|
6034
|
+
var research = {
|
|
6035
|
+
definition: {
|
|
6036
|
+
name: "research",
|
|
6037
|
+
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.",
|
|
6038
|
+
inputSchema: {
|
|
6039
|
+
type: "object",
|
|
6040
|
+
properties: {
|
|
6041
|
+
task: {
|
|
6042
|
+
type: "string",
|
|
6043
|
+
description: "What you need to find out, in natural language, with enough product context to make the findings relevant."
|
|
6044
|
+
}
|
|
6045
|
+
},
|
|
6046
|
+
required: ["task"]
|
|
6047
|
+
}
|
|
6048
|
+
},
|
|
6049
|
+
execute: (input, _onLog, context) => {
|
|
6050
|
+
if (!context) {
|
|
6051
|
+
return Promise.resolve("Error: research requires execution context");
|
|
6052
|
+
}
|
|
6053
|
+
return runResearch(input.task, context);
|
|
6054
|
+
}
|
|
6055
|
+
};
|
|
5967
6056
|
var tools = {
|
|
5968
|
-
searchGoogle: searchGoogle_exports,
|
|
5969
6057
|
scrapeWebUrl: scrapeWebUrl_exports,
|
|
5970
6058
|
analyzeDesign: analyzeDesign_exports,
|
|
5971
6059
|
analyzeImage: analyzeImage_exports,
|
|
@@ -5979,7 +6067,8 @@ var tools = {
|
|
|
5979
6067
|
polishCopy: polishCopy_exports,
|
|
5980
6068
|
loadSkill: loadSkill_exports,
|
|
5981
6069
|
// Appended last: tool order is part of the subagent's prompt-cache prefix.
|
|
5982
|
-
createWireframe: createWireframe_exports
|
|
6070
|
+
createWireframe: createWireframe_exports,
|
|
6071
|
+
research
|
|
5983
6072
|
};
|
|
5984
6073
|
var DESIGN_EXPERT_TOOLS = [
|
|
5985
6074
|
...COMMON_READ_TOOLS,
|
|
@@ -6537,11 +6626,11 @@ ${result.text}`;
|
|
|
6537
6626
|
}
|
|
6538
6627
|
|
|
6539
6628
|
// src/subagents/productVision/prompt.ts
|
|
6540
|
-
var
|
|
6629
|
+
var BASE_PROMPT4 = readAsset("subagents/productVision", "prompt.md");
|
|
6541
6630
|
function getProductVisionPrompt() {
|
|
6542
6631
|
const specIndex = loadSpecIndex();
|
|
6543
6632
|
const roadmapIndex = loadRoadmapIndex();
|
|
6544
|
-
const parts = [
|
|
6633
|
+
const parts = [BASE_PROMPT4, loadPlatformBrief()];
|
|
6545
6634
|
parts.push("<!-- cache_breakpoint -->");
|
|
6546
6635
|
if (specIndex) {
|
|
6547
6636
|
parts.push(specIndex);
|
|
@@ -6665,11 +6754,26 @@ var SANITY_CHECK_TOOLS = [
|
|
|
6665
6754
|
},
|
|
6666
6755
|
required: ["command"]
|
|
6667
6756
|
}
|
|
6757
|
+
},
|
|
6758
|
+
// Appended last: tool order is part of the subagent's prompt-cache prefix.
|
|
6759
|
+
{
|
|
6760
|
+
name: "research",
|
|
6761
|
+
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.",
|
|
6762
|
+
inputSchema: {
|
|
6763
|
+
type: "object",
|
|
6764
|
+
properties: {
|
|
6765
|
+
task: {
|
|
6766
|
+
type: "string",
|
|
6767
|
+
description: "What you need to find out, in natural language."
|
|
6768
|
+
}
|
|
6769
|
+
},
|
|
6770
|
+
required: ["task"]
|
|
6771
|
+
}
|
|
6668
6772
|
}
|
|
6669
6773
|
];
|
|
6670
6774
|
|
|
6671
6775
|
// src/subagents/codeSanityCheck/index.ts
|
|
6672
|
-
var
|
|
6776
|
+
var BASE_PROMPT5 = readAsset("subagents/codeSanityCheck", "prompt.md");
|
|
6673
6777
|
var codeSanityCheckTool = {
|
|
6674
6778
|
definition: {
|
|
6675
6779
|
name: "codeSanityCheck",
|
|
@@ -6690,7 +6794,7 @@ var codeSanityCheckTool = {
|
|
|
6690
6794
|
return "Error: code sanity check requires execution context";
|
|
6691
6795
|
}
|
|
6692
6796
|
const specIndex = loadSpecIndex();
|
|
6693
|
-
const parts = [
|
|
6797
|
+
const parts = [BASE_PROMPT5, loadPlatformBrief()];
|
|
6694
6798
|
parts.push("<!-- cache_breakpoint -->");
|
|
6695
6799
|
if (specIndex) {
|
|
6696
6800
|
parts.push(specIndex);
|
|
@@ -6706,6 +6810,16 @@ var codeSanityCheckTool = {
|
|
|
6706
6810
|
...deriveContext(context, toolCallId, onLog),
|
|
6707
6811
|
subAgentMessages: sams
|
|
6708
6812
|
} : context;
|
|
6813
|
+
if (name === "searchGoogle") {
|
|
6814
|
+
return executeSearchGoogle(
|
|
6815
|
+
{ ...toolInput, fetchTopN: 5 },
|
|
6816
|
+
childCtx.onLog,
|
|
6817
|
+
"codeSanityCheck"
|
|
6818
|
+
);
|
|
6819
|
+
}
|
|
6820
|
+
if (name === "research") {
|
|
6821
|
+
return runResearch(String(toolInput.task ?? ""), childCtx);
|
|
6822
|
+
}
|
|
6709
6823
|
return executeTool(name, toolInput, childCtx);
|
|
6710
6824
|
},
|
|
6711
6825
|
apiConfig: context.apiConfig,
|
|
@@ -6859,7 +6973,7 @@ function acquireSpecSyncLock() {
|
|
|
6859
6973
|
}
|
|
6860
6974
|
|
|
6861
6975
|
// src/subagents/specSync/index.ts
|
|
6862
|
-
var
|
|
6976
|
+
var BASE_PROMPT6 = readAsset("subagents/specSync", "prompt.md");
|
|
6863
6977
|
var MSFM_DOCS = `<mindstudio_flavored_markdown_spec_docs>
|
|
6864
6978
|
${readAsset(
|
|
6865
6979
|
"prompt",
|
|
@@ -6898,7 +7012,7 @@ var specSyncTool = {
|
|
|
6898
7012
|
}
|
|
6899
7013
|
const specIndex = loadSpecIndex();
|
|
6900
7014
|
const parts = [
|
|
6901
|
-
|
|
7015
|
+
BASE_PROMPT6,
|
|
6902
7016
|
loadPlatformBrief(),
|
|
6903
7017
|
MSFM_DOCS,
|
|
6904
7018
|
"<!-- cache_breakpoint -->"
|
|
@@ -7013,7 +7127,6 @@ var ALL_TOOLS = [
|
|
|
7013
7127
|
confirmDestructiveActionTool,
|
|
7014
7128
|
askMindStudioSdkTool,
|
|
7015
7129
|
scrapeWebUrlTool,
|
|
7016
|
-
searchGoogleTool,
|
|
7017
7130
|
setProjectMetadataTool,
|
|
7018
7131
|
designExpertTool,
|
|
7019
7132
|
productVisionTool,
|
|
@@ -7052,7 +7165,8 @@ var ALL_TOOLS = [
|
|
|
7052
7165
|
// Appended rather than grouped: position is part of the cache prefix, so a
|
|
7053
7166
|
// new tool goes at the end to leave every existing session's prefix intact.
|
|
7054
7167
|
loadSkillTool,
|
|
7055
|
-
testJewelTool
|
|
7168
|
+
testJewelTool,
|
|
7169
|
+
researchTool
|
|
7056
7170
|
];
|
|
7057
7171
|
var SUBAGENT_TOOL_NAMES = /* @__PURE__ */ new Set([
|
|
7058
7172
|
"visualDesignExpert",
|
|
@@ -7061,7 +7175,8 @@ var SUBAGENT_TOOL_NAMES = /* @__PURE__ */ new Set([
|
|
|
7061
7175
|
"copyEditor",
|
|
7062
7176
|
"specSync",
|
|
7063
7177
|
"runAutomatedBrowserTest",
|
|
7064
|
-
"askMindStudioSdk"
|
|
7178
|
+
"askMindStudioSdk",
|
|
7179
|
+
"research"
|
|
7065
7180
|
]);
|
|
7066
7181
|
function getToolDefinitions() {
|
|
7067
7182
|
return ALL_TOOLS.map((t) => t.definition);
|