@mindstudio-ai/remy 0.1.312 → 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.d.ts +3 -2
- package/dist/headless.js +443 -277
- package/dist/index.js +502 -328
- 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/index.js
CHANGED
|
@@ -1389,179 +1389,6 @@ var init_sdkConsultant = __esm({
|
|
|
1389
1389
|
}
|
|
1390
1390
|
});
|
|
1391
1391
|
|
|
1392
|
-
// src/usageLedger.ts
|
|
1393
|
-
import fs8 from "fs";
|
|
1394
|
-
function nanoToDollars(nano) {
|
|
1395
|
-
return typeof nano === "number" ? nano / 1e9 : void 0;
|
|
1396
|
-
}
|
|
1397
|
-
function recordUsage(entry) {
|
|
1398
|
-
try {
|
|
1399
|
-
if (fd === null) {
|
|
1400
|
-
fs8.mkdirSync(".logs", { recursive: true });
|
|
1401
|
-
fd = fs8.openSync(LEDGER_FILE, "a");
|
|
1402
|
-
}
|
|
1403
|
-
fs8.writeSync(fd, JSON.stringify(entry) + "\n");
|
|
1404
|
-
} catch {
|
|
1405
|
-
}
|
|
1406
|
-
}
|
|
1407
|
-
var LEDGER_FILE, fd;
|
|
1408
|
-
var init_usageLedger = __esm({
|
|
1409
|
-
"src/usageLedger.ts"() {
|
|
1410
|
-
"use strict";
|
|
1411
|
-
LEDGER_FILE = ".logs/usage.ndjson";
|
|
1412
|
-
fd = null;
|
|
1413
|
-
}
|
|
1414
|
-
});
|
|
1415
|
-
|
|
1416
|
-
// src/subagents/common/runMindstudioCli.ts
|
|
1417
|
-
function stripFlags(args2) {
|
|
1418
|
-
const out = [];
|
|
1419
|
-
for (let i = 0; i < args2.length; i++) {
|
|
1420
|
-
const arg = args2[i];
|
|
1421
|
-
if (arg === "--no-meta") {
|
|
1422
|
-
continue;
|
|
1423
|
-
}
|
|
1424
|
-
if (arg === "--output-key") {
|
|
1425
|
-
i++;
|
|
1426
|
-
continue;
|
|
1427
|
-
}
|
|
1428
|
-
out.push(arg);
|
|
1429
|
-
}
|
|
1430
|
-
return out;
|
|
1431
|
-
}
|
|
1432
|
-
async function runMindstudioCliResult(args2, options) {
|
|
1433
|
-
const cleanArgs = stripFlags(args2);
|
|
1434
|
-
const cliAction = args2[0];
|
|
1435
|
-
const agentName = options?.caller ?? "mindstudio-cli";
|
|
1436
|
-
const start = Date.now();
|
|
1437
|
-
const res = await runCli("mindstudio", cleanArgs, options);
|
|
1438
|
-
if (!res.ok) {
|
|
1439
|
-
return { ok: false, value: formatCliResult(res) };
|
|
1440
|
-
}
|
|
1441
|
-
const truncNote = res.truncated ? "\n\n[output truncated]" : "";
|
|
1442
|
-
let envelope;
|
|
1443
|
-
try {
|
|
1444
|
-
envelope = JSON.parse(res.output);
|
|
1445
|
-
} catch {
|
|
1446
|
-
return { ok: true, value: res.output + truncNote };
|
|
1447
|
-
}
|
|
1448
|
-
if (envelope && typeof envelope === "object" && Array.isArray(envelope.results)) {
|
|
1449
|
-
const durationMs = Date.now() - start;
|
|
1450
|
-
for (const step of envelope.results) {
|
|
1451
|
-
if (typeof step?.billingCost === "number") {
|
|
1452
|
-
recordUsage({
|
|
1453
|
-
ts: Date.now(),
|
|
1454
|
-
agentName,
|
|
1455
|
-
cliAction: `${cliAction}:${step.stepType ?? "step"}`,
|
|
1456
|
-
cost: nanoToDollars(step.billingCost),
|
|
1457
|
-
inputTokens: 0,
|
|
1458
|
-
outputTokens: 0,
|
|
1459
|
-
durationMs,
|
|
1460
|
-
toolNames: []
|
|
1461
|
-
});
|
|
1462
|
-
}
|
|
1463
|
-
}
|
|
1464
|
-
return { ok: true, value: JSON.stringify(envelope.results) + truncNote };
|
|
1465
|
-
}
|
|
1466
|
-
if (typeof envelope?.$billingCost === "number") {
|
|
1467
|
-
recordUsage({
|
|
1468
|
-
ts: Date.now(),
|
|
1469
|
-
agentName,
|
|
1470
|
-
cliAction,
|
|
1471
|
-
cost: nanoToDollars(envelope.$billingCost),
|
|
1472
|
-
billingEvents: envelope.$billingEvents,
|
|
1473
|
-
// CLI billing isn't expressed as input/output tokens for most actions
|
|
1474
|
-
// (image gen is per-image, scrape per-page, etc). `numUnits` inside each
|
|
1475
|
-
// billingEvent carries the per-event unit count.
|
|
1476
|
-
inputTokens: 0,
|
|
1477
|
-
outputTokens: 0,
|
|
1478
|
-
durationMs: Date.now() - start,
|
|
1479
|
-
toolNames: []
|
|
1480
|
-
});
|
|
1481
|
-
}
|
|
1482
|
-
if (options?.outputKey) {
|
|
1483
|
-
const v = envelope?.[options.outputKey];
|
|
1484
|
-
if (v === void 0 || v === null) {
|
|
1485
|
-
return { ok: false, value: JSON.stringify(stripDollarKeys(envelope)) };
|
|
1486
|
-
}
|
|
1487
|
-
const value = typeof v === "string" ? v : JSON.stringify(v);
|
|
1488
|
-
return { ok: true, value: value + truncNote };
|
|
1489
|
-
}
|
|
1490
|
-
return {
|
|
1491
|
-
ok: true,
|
|
1492
|
-
value: JSON.stringify(stripDollarKeys(envelope)) + truncNote
|
|
1493
|
-
};
|
|
1494
|
-
}
|
|
1495
|
-
async function runMindstudioCli(args2, options) {
|
|
1496
|
-
return (await runMindstudioCliResult(args2, options)).value;
|
|
1497
|
-
}
|
|
1498
|
-
function stripDollarKeys(envelope) {
|
|
1499
|
-
if (!envelope || typeof envelope !== "object" || Array.isArray(envelope)) {
|
|
1500
|
-
return envelope;
|
|
1501
|
-
}
|
|
1502
|
-
const out = {};
|
|
1503
|
-
for (const [k, v] of Object.entries(envelope)) {
|
|
1504
|
-
if (!k.startsWith("$")) {
|
|
1505
|
-
out[k] = v;
|
|
1506
|
-
}
|
|
1507
|
-
}
|
|
1508
|
-
return out;
|
|
1509
|
-
}
|
|
1510
|
-
var init_runMindstudioCli = __esm({
|
|
1511
|
-
"src/subagents/common/runMindstudioCli.ts"() {
|
|
1512
|
-
"use strict";
|
|
1513
|
-
init_runCli();
|
|
1514
|
-
init_usageLedger();
|
|
1515
|
-
}
|
|
1516
|
-
});
|
|
1517
|
-
|
|
1518
|
-
// src/tools/common/searchGoogle.ts
|
|
1519
|
-
var FETCH_TOP_N, searchGoogleTool;
|
|
1520
|
-
var init_searchGoogle = __esm({
|
|
1521
|
-
"src/tools/common/searchGoogle.ts"() {
|
|
1522
|
-
"use strict";
|
|
1523
|
-
init_runMindstudioCli();
|
|
1524
|
-
init_runCli();
|
|
1525
|
-
FETCH_TOP_N = 5;
|
|
1526
|
-
searchGoogleTool = {
|
|
1527
|
-
definition: {
|
|
1528
|
-
name: "searchGoogle",
|
|
1529
|
-
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.",
|
|
1530
|
-
inputSchema: {
|
|
1531
|
-
type: "object",
|
|
1532
|
-
properties: {
|
|
1533
|
-
query: {
|
|
1534
|
-
type: "string",
|
|
1535
|
-
description: "The search query."
|
|
1536
|
-
}
|
|
1537
|
-
},
|
|
1538
|
-
required: ["query"]
|
|
1539
|
-
}
|
|
1540
|
-
},
|
|
1541
|
-
async execute(input, context) {
|
|
1542
|
-
const query = input.query;
|
|
1543
|
-
return runMindstudioCli(
|
|
1544
|
-
[
|
|
1545
|
-
"search-google",
|
|
1546
|
-
"--query",
|
|
1547
|
-
query,
|
|
1548
|
-
"--export-type",
|
|
1549
|
-
"json",
|
|
1550
|
-
"--fetch-top-n",
|
|
1551
|
-
String(FETCH_TOP_N)
|
|
1552
|
-
],
|
|
1553
|
-
{
|
|
1554
|
-
outputKey: "results",
|
|
1555
|
-
maxBuffer: SEARCH_MAX_BUFFER,
|
|
1556
|
-
onLog: context?.onLog,
|
|
1557
|
-
caller: "parent"
|
|
1558
|
-
}
|
|
1559
|
-
);
|
|
1560
|
-
}
|
|
1561
|
-
};
|
|
1562
|
-
}
|
|
1563
|
-
});
|
|
1564
|
-
|
|
1565
1392
|
// src/tools/common/setProjectMetadata.ts
|
|
1566
1393
|
var setProjectMetadataTool;
|
|
1567
1394
|
var init_setProjectMetadata = __esm({
|
|
@@ -1601,7 +1428,7 @@ var init_setProjectMetadata = __esm({
|
|
|
1601
1428
|
});
|
|
1602
1429
|
|
|
1603
1430
|
// src/assets.ts
|
|
1604
|
-
import
|
|
1431
|
+
import fs8 from "fs";
|
|
1605
1432
|
import path3 from "path";
|
|
1606
1433
|
function assetPath(...segments) {
|
|
1607
1434
|
return path3.join(ASSETS_BASE, ...segments);
|
|
@@ -1609,7 +1436,7 @@ function assetPath(...segments) {
|
|
|
1609
1436
|
function readAsset(...segments) {
|
|
1610
1437
|
const full = assetPath(...segments);
|
|
1611
1438
|
try {
|
|
1612
|
-
return
|
|
1439
|
+
return fs8.readFileSync(full, "utf-8").trim();
|
|
1613
1440
|
} catch {
|
|
1614
1441
|
throw new Error(`Required asset missing: ${full}`);
|
|
1615
1442
|
}
|
|
@@ -1617,7 +1444,7 @@ function readAsset(...segments) {
|
|
|
1617
1444
|
function readJsonAsset(fallback, ...segments) {
|
|
1618
1445
|
const full = assetPath(...segments);
|
|
1619
1446
|
try {
|
|
1620
|
-
return JSON.parse(
|
|
1447
|
+
return JSON.parse(fs8.readFileSync(full, "utf-8"));
|
|
1621
1448
|
} catch {
|
|
1622
1449
|
return fallback;
|
|
1623
1450
|
}
|
|
@@ -1683,6 +1510,30 @@ var init_sentinel = __esm({
|
|
|
1683
1510
|
}
|
|
1684
1511
|
});
|
|
1685
1512
|
|
|
1513
|
+
// src/usageLedger.ts
|
|
1514
|
+
import fs9 from "fs";
|
|
1515
|
+
function nanoToDollars(nano) {
|
|
1516
|
+
return typeof nano === "number" ? nano / 1e9 : void 0;
|
|
1517
|
+
}
|
|
1518
|
+
function recordUsage(entry) {
|
|
1519
|
+
try {
|
|
1520
|
+
if (fd === null) {
|
|
1521
|
+
fs9.mkdirSync(".logs", { recursive: true });
|
|
1522
|
+
fd = fs9.openSync(LEDGER_FILE, "a");
|
|
1523
|
+
}
|
|
1524
|
+
fs9.writeSync(fd, JSON.stringify(entry) + "\n");
|
|
1525
|
+
} catch {
|
|
1526
|
+
}
|
|
1527
|
+
}
|
|
1528
|
+
var LEDGER_FILE, fd;
|
|
1529
|
+
var init_usageLedger = __esm({
|
|
1530
|
+
"src/usageLedger.ts"() {
|
|
1531
|
+
"use strict";
|
|
1532
|
+
LEDGER_FILE = ".logs/usage.ndjson";
|
|
1533
|
+
fd = null;
|
|
1534
|
+
}
|
|
1535
|
+
});
|
|
1536
|
+
|
|
1686
1537
|
// src/compaction/index.ts
|
|
1687
1538
|
async function compactConversation(messages, apiConfig, model, signal) {
|
|
1688
1539
|
const endIndex = findSafeInsertionPoint(messages);
|
|
@@ -2096,7 +1947,7 @@ var init_compaction = __esm({
|
|
|
2096
1947
|
init_api();
|
|
2097
1948
|
init_assets();
|
|
2098
1949
|
init_sentinel();
|
|
2099
|
-
|
|
1950
|
+
init_tools9();
|
|
2100
1951
|
init_logger();
|
|
2101
1952
|
init_usageLedger();
|
|
2102
1953
|
log2 = createLogger("compaction");
|
|
@@ -2111,6 +1962,12 @@ var init_compaction = __esm({
|
|
|
2111
1962
|
});
|
|
2112
1963
|
|
|
2113
1964
|
// src/models/surfaces.ts
|
|
1965
|
+
function getContextLimits(modelId) {
|
|
1966
|
+
return TEXT_MODELS[modelId] ?? DEFAULT_CONTEXT_LIMITS;
|
|
1967
|
+
}
|
|
1968
|
+
function getSuggestCompactAt(modelId) {
|
|
1969
|
+
return getContextLimits(modelId).suggestCompactAt ?? DEFAULT_SUGGEST_COMPACT_AT;
|
|
1970
|
+
}
|
|
2114
1971
|
function setOrgDefaultModels(models) {
|
|
2115
1972
|
orgDefaultModels = models;
|
|
2116
1973
|
}
|
|
@@ -2149,7 +2006,12 @@ function getEffectiveModelSurfaces() {
|
|
|
2149
2006
|
function resolveModel(surfaceId, models, fallback) {
|
|
2150
2007
|
return models?.[surfaceId] ?? fallback ?? orgDefaultModels[surfaceId] ?? MODEL_SURFACES[surfaceId].default;
|
|
2151
2008
|
}
|
|
2152
|
-
|
|
2009
|
+
function resolveParentModel(models, fallback, buildModel) {
|
|
2010
|
+
const override = buildModel ? filterModelPicks({ parent: buildModel }).parent : void 0;
|
|
2011
|
+
const baseline = resolveModel("parent", models, fallback);
|
|
2012
|
+
return { baseline, effective: override ?? baseline };
|
|
2013
|
+
}
|
|
2014
|
+
var MODEL_SURFACES, DEFAULT_SUGGEST_COMPACT_AT, TEXT_MODELS, DEFAULT_CONTEXT_LIMITS, ALLOWED_MODELS_BY_TYPE, orgDefaultModels;
|
|
2153
2015
|
var init_surfaces = __esm({
|
|
2154
2016
|
"src/models/surfaces.ts"() {
|
|
2155
2017
|
"use strict";
|
|
@@ -2189,6 +2051,13 @@ var init_surfaces = __esm({
|
|
|
2189
2051
|
modelType: "text",
|
|
2190
2052
|
userPickable: true
|
|
2191
2053
|
},
|
|
2054
|
+
research: {
|
|
2055
|
+
default: "claude-5-sonnet",
|
|
2056
|
+
label: "Research Agent",
|
|
2057
|
+
description: "Researches using the web and reports back with citations.",
|
|
2058
|
+
modelType: "text",
|
|
2059
|
+
userPickable: true
|
|
2060
|
+
},
|
|
2192
2061
|
copyEditor: {
|
|
2193
2062
|
default: "claude-5-sonnet",
|
|
2194
2063
|
label: "Copy Agent",
|
|
@@ -2241,37 +2110,53 @@ var init_surfaces = __esm({
|
|
|
2241
2110
|
userPickable: false
|
|
2242
2111
|
}
|
|
2243
2112
|
};
|
|
2113
|
+
DEFAULT_SUGGEST_COMPACT_AT = 3e5;
|
|
2114
|
+
TEXT_MODELS = {
|
|
2115
|
+
// Anthropic 1M-context, flat-priced.
|
|
2116
|
+
"claude-5-opus": { forceCompactAt: 85e4 },
|
|
2117
|
+
"claude-4-8-opus": { forceCompactAt: 85e4 },
|
|
2118
|
+
"claude-4-7-opus": { forceCompactAt: 85e4 },
|
|
2119
|
+
// Anthropic 1M-context with 2x long-context pricing above 200K input.
|
|
2120
|
+
"claude-4-6-opus": { forceCompactAt: 85e4, suggestCompactAt: 18e4 },
|
|
2121
|
+
"claude-4-6-sonnet": { forceCompactAt: 85e4, suggestCompactAt: 18e4 },
|
|
2122
|
+
"claude-fable-5": { forceCompactAt: 85e4 },
|
|
2123
|
+
"claude-fable-5-1": { forceCompactAt: 85e4 },
|
|
2124
|
+
"claude-5-sonnet": { forceCompactAt: 85e4 },
|
|
2125
|
+
// OpenAI gpt-5.5/5.6: ~1M window, but the usable input ceiling under
|
|
2126
|
+
// `truncation: 'auto'` is ~794K (output + reasoning reserve), and all
|
|
2127
|
+
// rates double above 272K input.
|
|
2128
|
+
"gpt-5.5": { forceCompactAt: 6e5, suggestCompactAt: 25e4 },
|
|
2129
|
+
"gpt-5.6-sol": { forceCompactAt: 6e5, suggestCompactAt: 25e4 },
|
|
2130
|
+
"gpt-5.6-terra": { forceCompactAt: 6e5, suggestCompactAt: 25e4 },
|
|
2131
|
+
"gpt-5.6-luna": { forceCompactAt: 6e5, suggestCompactAt: 25e4 },
|
|
2132
|
+
// Google ~1M-context; only 3.1-pro is tiered (higher rates above 200K).
|
|
2133
|
+
"gemini-3-pro": { forceCompactAt: 85e4 },
|
|
2134
|
+
"gemini-3.1-pro": { forceCompactAt: 85e4, suggestCompactAt: 18e4 },
|
|
2135
|
+
"gemini-3-flash": { forceCompactAt: 85e4 },
|
|
2136
|
+
"gemini-3.5-flash": { forceCompactAt: 85e4 },
|
|
2137
|
+
"gemini-3.7-flash": { forceCompactAt: 85e4 },
|
|
2138
|
+
// 256K window; its 200K pricing tier sits above the gate, so no nudge.
|
|
2139
|
+
"grok-build-0.1": { forceCompactAt: 18e4 },
|
|
2140
|
+
"grok-4.5": { forceCompactAt: 4e5 },
|
|
2141
|
+
// 500K window
|
|
2142
|
+
"grok-4.6": { forceCompactAt: 4e5 },
|
|
2143
|
+
// 500K window
|
|
2144
|
+
"glm-5.2": { forceCompactAt: 85e4 },
|
|
2145
|
+
"muse-spark-1.1": { forceCompactAt: 85e4 },
|
|
2146
|
+
"kimi-k2-7-code": { forceCompactAt: 2e5 },
|
|
2147
|
+
// 262K window
|
|
2148
|
+
"kimi-k3": { forceCompactAt: 85e4 },
|
|
2149
|
+
"deepseek-v4-flash-0731": { forceCompactAt: 85e4 },
|
|
2150
|
+
"qwen3.8-2.4t-a95b-deepinfra": { forceCompactAt: 2e5 },
|
|
2151
|
+
// 262K window
|
|
2152
|
+
"qwen3.8-27b-deepinfra": { forceCompactAt: 2e5 },
|
|
2153
|
+
// 262K window
|
|
2154
|
+
"minimax-m3": { forceCompactAt: 42e4 }
|
|
2155
|
+
// 524K window
|
|
2156
|
+
};
|
|
2157
|
+
DEFAULT_CONTEXT_LIMITS = { forceCompactAt: 85e4 };
|
|
2244
2158
|
ALLOWED_MODELS_BY_TYPE = {
|
|
2245
|
-
text:
|
|
2246
|
-
"claude-5-opus",
|
|
2247
|
-
"claude-4-8-opus",
|
|
2248
|
-
"claude-4-7-opus",
|
|
2249
|
-
"claude-4-6-opus",
|
|
2250
|
-
"claude-4-6-sonnet",
|
|
2251
|
-
"claude-fable-5",
|
|
2252
|
-
"claude-fable-5-1",
|
|
2253
|
-
"claude-5-sonnet",
|
|
2254
|
-
"gpt-5.5",
|
|
2255
|
-
"gpt-5.6-sol",
|
|
2256
|
-
"gpt-5.6-terra",
|
|
2257
|
-
"gpt-5.6-luna",
|
|
2258
|
-
"gemini-3-pro",
|
|
2259
|
-
"gemini-3.1-pro",
|
|
2260
|
-
"gemini-3-flash",
|
|
2261
|
-
"gemini-3.5-flash",
|
|
2262
|
-
"gemini-3.7-flash",
|
|
2263
|
-
"grok-build-0.1",
|
|
2264
|
-
"grok-4.5",
|
|
2265
|
-
"grok-4.6",
|
|
2266
|
-
"glm-5.2",
|
|
2267
|
-
"muse-spark-1.1",
|
|
2268
|
-
"kimi-k2-7-code",
|
|
2269
|
-
"kimi-k3",
|
|
2270
|
-
"deepseek-v4-flash-0731",
|
|
2271
|
-
"qwen3.8-2.4t-a95b-deepinfra",
|
|
2272
|
-
"qwen3.8-27b-deepinfra",
|
|
2273
|
-
"minimax-m3"
|
|
2274
|
-
]
|
|
2159
|
+
text: Object.keys(TEXT_MODELS)
|
|
2275
2160
|
// vision: undefined — unconstrained
|
|
2276
2161
|
// image_generation: undefined — unconstrained
|
|
2277
2162
|
};
|
|
@@ -4295,6 +4180,108 @@ var init_queryDatabase = __esm({
|
|
|
4295
4180
|
}
|
|
4296
4181
|
});
|
|
4297
4182
|
|
|
4183
|
+
// src/subagents/common/runMindstudioCli.ts
|
|
4184
|
+
function stripFlags(args2) {
|
|
4185
|
+
const out = [];
|
|
4186
|
+
for (let i = 0; i < args2.length; i++) {
|
|
4187
|
+
const arg = args2[i];
|
|
4188
|
+
if (arg === "--no-meta") {
|
|
4189
|
+
continue;
|
|
4190
|
+
}
|
|
4191
|
+
if (arg === "--output-key") {
|
|
4192
|
+
i++;
|
|
4193
|
+
continue;
|
|
4194
|
+
}
|
|
4195
|
+
out.push(arg);
|
|
4196
|
+
}
|
|
4197
|
+
return out;
|
|
4198
|
+
}
|
|
4199
|
+
async function runMindstudioCliResult(args2, options) {
|
|
4200
|
+
const cleanArgs = stripFlags(args2);
|
|
4201
|
+
const cliAction = args2[0];
|
|
4202
|
+
const agentName = options?.caller ?? "mindstudio-cli";
|
|
4203
|
+
const start = Date.now();
|
|
4204
|
+
const res = await runCli("mindstudio", cleanArgs, options);
|
|
4205
|
+
if (!res.ok) {
|
|
4206
|
+
return { ok: false, value: formatCliResult(res) };
|
|
4207
|
+
}
|
|
4208
|
+
const truncNote = res.truncated ? "\n\n[output truncated]" : "";
|
|
4209
|
+
let envelope;
|
|
4210
|
+
try {
|
|
4211
|
+
envelope = JSON.parse(res.output);
|
|
4212
|
+
} catch {
|
|
4213
|
+
return { ok: true, value: res.output + truncNote };
|
|
4214
|
+
}
|
|
4215
|
+
if (envelope && typeof envelope === "object" && Array.isArray(envelope.results)) {
|
|
4216
|
+
const durationMs = Date.now() - start;
|
|
4217
|
+
for (const step of envelope.results) {
|
|
4218
|
+
if (typeof step?.billingCost === "number") {
|
|
4219
|
+
recordUsage({
|
|
4220
|
+
ts: Date.now(),
|
|
4221
|
+
agentName,
|
|
4222
|
+
cliAction: `${cliAction}:${step.stepType ?? "step"}`,
|
|
4223
|
+
cost: nanoToDollars(step.billingCost),
|
|
4224
|
+
inputTokens: 0,
|
|
4225
|
+
outputTokens: 0,
|
|
4226
|
+
durationMs,
|
|
4227
|
+
toolNames: []
|
|
4228
|
+
});
|
|
4229
|
+
}
|
|
4230
|
+
}
|
|
4231
|
+
return { ok: true, value: JSON.stringify(envelope.results) + truncNote };
|
|
4232
|
+
}
|
|
4233
|
+
if (typeof envelope?.$billingCost === "number") {
|
|
4234
|
+
recordUsage({
|
|
4235
|
+
ts: Date.now(),
|
|
4236
|
+
agentName,
|
|
4237
|
+
cliAction,
|
|
4238
|
+
cost: nanoToDollars(envelope.$billingCost),
|
|
4239
|
+
billingEvents: envelope.$billingEvents,
|
|
4240
|
+
// CLI billing isn't expressed as input/output tokens for most actions
|
|
4241
|
+
// (image gen is per-image, scrape per-page, etc). `numUnits` inside each
|
|
4242
|
+
// billingEvent carries the per-event unit count.
|
|
4243
|
+
inputTokens: 0,
|
|
4244
|
+
outputTokens: 0,
|
|
4245
|
+
durationMs: Date.now() - start,
|
|
4246
|
+
toolNames: []
|
|
4247
|
+
});
|
|
4248
|
+
}
|
|
4249
|
+
if (options?.outputKey) {
|
|
4250
|
+
const v = envelope?.[options.outputKey];
|
|
4251
|
+
if (v === void 0 || v === null) {
|
|
4252
|
+
return { ok: false, value: JSON.stringify(stripDollarKeys(envelope)) };
|
|
4253
|
+
}
|
|
4254
|
+
const value = typeof v === "string" ? v : JSON.stringify(v);
|
|
4255
|
+
return { ok: true, value: value + truncNote };
|
|
4256
|
+
}
|
|
4257
|
+
return {
|
|
4258
|
+
ok: true,
|
|
4259
|
+
value: JSON.stringify(stripDollarKeys(envelope)) + truncNote
|
|
4260
|
+
};
|
|
4261
|
+
}
|
|
4262
|
+
async function runMindstudioCli(args2, options) {
|
|
4263
|
+
return (await runMindstudioCliResult(args2, options)).value;
|
|
4264
|
+
}
|
|
4265
|
+
function stripDollarKeys(envelope) {
|
|
4266
|
+
if (!envelope || typeof envelope !== "object" || Array.isArray(envelope)) {
|
|
4267
|
+
return envelope;
|
|
4268
|
+
}
|
|
4269
|
+
const out = {};
|
|
4270
|
+
for (const [k, v] of Object.entries(envelope)) {
|
|
4271
|
+
if (!k.startsWith("$")) {
|
|
4272
|
+
out[k] = v;
|
|
4273
|
+
}
|
|
4274
|
+
}
|
|
4275
|
+
return out;
|
|
4276
|
+
}
|
|
4277
|
+
var init_runMindstudioCli = __esm({
|
|
4278
|
+
"src/subagents/common/runMindstudioCli.ts"() {
|
|
4279
|
+
"use strict";
|
|
4280
|
+
init_runCli();
|
|
4281
|
+
init_usageLedger();
|
|
4282
|
+
}
|
|
4283
|
+
});
|
|
4284
|
+
|
|
4298
4285
|
// src/tools/_helpers/uploadImage.ts
|
|
4299
4286
|
import { readFile, stat } from "fs/promises";
|
|
4300
4287
|
import { basename, extname, resolve } from "path";
|
|
@@ -5626,7 +5613,7 @@ The first-party SDK (@mindstudio-ai/agent) provides access to 200+ AI models (Op
|
|
|
5626
5613
|
## What Remy apps are NOT good for
|
|
5627
5614
|
|
|
5628
5615
|
- Native mobile apps (iOS/Android). Mobile-responsive web apps are fine.
|
|
5629
|
-
-
|
|
5616
|
+
- 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.
|
|
5630
5617
|
</platform_brief>`;
|
|
5631
5618
|
}
|
|
5632
5619
|
var init_context = __esm({
|
|
@@ -5791,7 +5778,7 @@ var log9, CAPTURE_COMMANDS, browserAutomationTool;
|
|
|
5791
5778
|
var init_browserAutomation = __esm({
|
|
5792
5779
|
"src/subagents/browserAutomation/index.ts"() {
|
|
5793
5780
|
"use strict";
|
|
5794
|
-
|
|
5781
|
+
init_tools9();
|
|
5795
5782
|
init_runner();
|
|
5796
5783
|
init_tools2();
|
|
5797
5784
|
init_tools();
|
|
@@ -5956,62 +5943,175 @@ var init_screenshot2 = __esm({
|
|
|
5956
5943
|
}
|
|
5957
5944
|
});
|
|
5958
5945
|
|
|
5959
|
-
// src/subagents/
|
|
5960
|
-
|
|
5961
|
-
|
|
5962
|
-
definition: () => definition,
|
|
5963
|
-
execute: () => execute
|
|
5964
|
-
});
|
|
5965
|
-
async function execute(input, onLog) {
|
|
5946
|
+
// src/subagents/research/tools.ts
|
|
5947
|
+
async function executeSearchGoogle(input, onLog, caller) {
|
|
5948
|
+
const fetchTopN = Math.max(0, Math.round(Number(input.fetchTopN) || 0));
|
|
5966
5949
|
return runMindstudioCli(
|
|
5967
5950
|
[
|
|
5968
5951
|
"search-google",
|
|
5969
5952
|
"--query",
|
|
5970
|
-
input.query,
|
|
5953
|
+
String(input.query),
|
|
5971
5954
|
"--export-type",
|
|
5972
5955
|
"json",
|
|
5973
5956
|
"--fetch-top-n",
|
|
5974
|
-
String(
|
|
5957
|
+
String(fetchTopN)
|
|
5975
5958
|
],
|
|
5976
5959
|
{
|
|
5977
5960
|
outputKey: "results",
|
|
5961
|
+
maxBuffer: SEARCH_MAX_BUFFER,
|
|
5978
5962
|
onLog,
|
|
5979
|
-
caller
|
|
5980
|
-
maxBuffer: SEARCH_MAX_BUFFER
|
|
5963
|
+
caller
|
|
5981
5964
|
}
|
|
5982
5965
|
);
|
|
5983
5966
|
}
|
|
5984
|
-
|
|
5985
|
-
|
|
5986
|
-
|
|
5967
|
+
async function executeScrapeWebUrl(input, onLog, caller) {
|
|
5968
|
+
return runMindstudioCli(
|
|
5969
|
+
[
|
|
5970
|
+
"scrape-url",
|
|
5971
|
+
"--url",
|
|
5972
|
+
String(input.url),
|
|
5973
|
+
"--page-options",
|
|
5974
|
+
JSON.stringify({ onlyMainContent: true })
|
|
5975
|
+
],
|
|
5976
|
+
{
|
|
5977
|
+
maxBuffer: SCRAPE_MAX_BUFFER,
|
|
5978
|
+
onLog,
|
|
5979
|
+
caller
|
|
5980
|
+
}
|
|
5981
|
+
);
|
|
5982
|
+
}
|
|
5983
|
+
var searchGoogleDefinition, scrapeWebUrlDefinition, RESEARCH_TOOLS;
|
|
5984
|
+
var init_tools3 = __esm({
|
|
5985
|
+
"src/subagents/research/tools.ts"() {
|
|
5987
5986
|
"use strict";
|
|
5987
|
+
init_tools();
|
|
5988
5988
|
init_runMindstudioCli();
|
|
5989
5989
|
init_runCli();
|
|
5990
|
-
|
|
5991
|
-
|
|
5990
|
+
init_bash();
|
|
5991
|
+
searchGoogleDefinition = {
|
|
5992
5992
|
name: "searchGoogle",
|
|
5993
|
-
description:
|
|
5993
|
+
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.",
|
|
5994
5994
|
inputSchema: {
|
|
5995
5995
|
type: "object",
|
|
5996
5996
|
properties: {
|
|
5997
5997
|
query: {
|
|
5998
5998
|
type: "string",
|
|
5999
5999
|
description: "The search query."
|
|
6000
|
+
},
|
|
6001
|
+
fetchTopN: {
|
|
6002
|
+
type: "number",
|
|
6003
|
+
description: "Also fetch page content (capped ~4,000 chars each) for this many top results. Omit for a fast SERP-only search."
|
|
6000
6004
|
}
|
|
6001
6005
|
},
|
|
6002
6006
|
required: ["query"]
|
|
6003
6007
|
}
|
|
6004
6008
|
};
|
|
6009
|
+
scrapeWebUrlDefinition = {
|
|
6010
|
+
name: "scrapeWebUrl",
|
|
6011
|
+
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.",
|
|
6012
|
+
inputSchema: {
|
|
6013
|
+
type: "object",
|
|
6014
|
+
properties: {
|
|
6015
|
+
url: {
|
|
6016
|
+
type: "string",
|
|
6017
|
+
description: "The URL to fetch."
|
|
6018
|
+
}
|
|
6019
|
+
},
|
|
6020
|
+
required: ["url"]
|
|
6021
|
+
}
|
|
6022
|
+
};
|
|
6023
|
+
RESEARCH_TOOLS = [
|
|
6024
|
+
...COMMON_READ_TOOLS,
|
|
6025
|
+
searchGoogleDefinition,
|
|
6026
|
+
scrapeWebUrlDefinition,
|
|
6027
|
+
bashTool.definition
|
|
6028
|
+
];
|
|
6029
|
+
}
|
|
6030
|
+
});
|
|
6031
|
+
|
|
6032
|
+
// src/subagents/research/index.ts
|
|
6033
|
+
async function runResearch(task, context) {
|
|
6034
|
+
const specIndex = loadSpecIndex();
|
|
6035
|
+
const parts = [BASE_PROMPT2, loadPlatformBrief()];
|
|
6036
|
+
parts.push("<!-- cache_breakpoint -->");
|
|
6037
|
+
if (specIndex) {
|
|
6038
|
+
parts.push(specIndex);
|
|
6039
|
+
}
|
|
6040
|
+
const system = parts.join("\n\n");
|
|
6041
|
+
const result = await runSubAgent({
|
|
6042
|
+
system,
|
|
6043
|
+
task,
|
|
6044
|
+
tools: RESEARCH_TOOLS,
|
|
6045
|
+
externalTools: /* @__PURE__ */ new Set(),
|
|
6046
|
+
executeTool: (name, toolInput, toolCallId, onLog, sams) => {
|
|
6047
|
+
const childCtx = toolCallId ? {
|
|
6048
|
+
...deriveContext(context, toolCallId, onLog),
|
|
6049
|
+
subAgentMessages: sams
|
|
6050
|
+
} : context;
|
|
6051
|
+
if (name === "searchGoogle") {
|
|
6052
|
+
return executeSearchGoogle(toolInput, childCtx.onLog, "research");
|
|
6053
|
+
}
|
|
6054
|
+
if (name === "scrapeWebUrl") {
|
|
6055
|
+
return executeScrapeWebUrl(toolInput, childCtx.onLog, "research");
|
|
6056
|
+
}
|
|
6057
|
+
return executeTool(name, toolInput, childCtx);
|
|
6058
|
+
},
|
|
6059
|
+
apiConfig: context.apiConfig,
|
|
6060
|
+
model: resolveModel("research", context.models, context.model),
|
|
6061
|
+
subAgentId: "research",
|
|
6062
|
+
signal: context.signal,
|
|
6063
|
+
parentToolId: context.toolCallId,
|
|
6064
|
+
requestId: context.requestId,
|
|
6065
|
+
onEvent: context.onEvent,
|
|
6066
|
+
resolveExternalTool: context.resolveExternalTool,
|
|
6067
|
+
toolRegistry: context.toolRegistry
|
|
6068
|
+
});
|
|
6069
|
+
context.subAgentMessages?.set(context.toolCallId, result.messages);
|
|
6070
|
+
return result.text;
|
|
6071
|
+
}
|
|
6072
|
+
var BASE_PROMPT2, researchTool;
|
|
6073
|
+
var init_research = __esm({
|
|
6074
|
+
"src/subagents/research/index.ts"() {
|
|
6075
|
+
"use strict";
|
|
6076
|
+
init_assets();
|
|
6077
|
+
init_runner();
|
|
6078
|
+
init_context();
|
|
6079
|
+
init_tools9();
|
|
6080
|
+
init_tools3();
|
|
6081
|
+
init_surfaces();
|
|
6082
|
+
BASE_PROMPT2 = readAsset("subagents/research", "prompt.md");
|
|
6083
|
+
researchTool = {
|
|
6084
|
+
definition: {
|
|
6085
|
+
name: "research",
|
|
6086
|
+
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.",
|
|
6087
|
+
inputSchema: {
|
|
6088
|
+
type: "object",
|
|
6089
|
+
properties: {
|
|
6090
|
+
task: {
|
|
6091
|
+
type: "string",
|
|
6092
|
+
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."
|
|
6093
|
+
}
|
|
6094
|
+
},
|
|
6095
|
+
required: ["task"]
|
|
6096
|
+
}
|
|
6097
|
+
},
|
|
6098
|
+
async execute(input, context) {
|
|
6099
|
+
if (!context) {
|
|
6100
|
+
return "Error: research requires execution context";
|
|
6101
|
+
}
|
|
6102
|
+
return runResearch(input.task, context);
|
|
6103
|
+
}
|
|
6104
|
+
};
|
|
6005
6105
|
}
|
|
6006
6106
|
});
|
|
6007
6107
|
|
|
6008
6108
|
// src/subagents/designExpert/tools/scrapeWebUrl.ts
|
|
6009
6109
|
var scrapeWebUrl_exports = {};
|
|
6010
6110
|
__export(scrapeWebUrl_exports, {
|
|
6011
|
-
definition: () =>
|
|
6012
|
-
execute: () =>
|
|
6111
|
+
definition: () => definition,
|
|
6112
|
+
execute: () => execute
|
|
6013
6113
|
});
|
|
6014
|
-
async function
|
|
6114
|
+
async function execute(input, onLog) {
|
|
6015
6115
|
const pageOptions = { onlyMainContent: true };
|
|
6016
6116
|
return runMindstudioCli(
|
|
6017
6117
|
[
|
|
@@ -6024,15 +6124,15 @@ async function execute2(input, onLog) {
|
|
|
6024
6124
|
{ onLog, caller: "designExpert", maxBuffer: SCRAPE_MAX_BUFFER }
|
|
6025
6125
|
);
|
|
6026
6126
|
}
|
|
6027
|
-
var
|
|
6127
|
+
var definition;
|
|
6028
6128
|
var init_scrapeWebUrl = __esm({
|
|
6029
6129
|
"src/subagents/designExpert/tools/scrapeWebUrl.ts"() {
|
|
6030
6130
|
"use strict";
|
|
6031
6131
|
init_runMindstudioCli();
|
|
6032
6132
|
init_runCli();
|
|
6033
|
-
|
|
6133
|
+
definition = {
|
|
6034
6134
|
name: "scrapeWebUrl",
|
|
6035
|
-
description: "Fetch the content of a web page as markdown. Use
|
|
6135
|
+
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.",
|
|
6036
6136
|
inputSchema: {
|
|
6037
6137
|
type: "object",
|
|
6038
6138
|
properties: {
|
|
@@ -6051,14 +6151,14 @@ var init_scrapeWebUrl = __esm({
|
|
|
6051
6151
|
var renderImage_exports = {};
|
|
6052
6152
|
__export(renderImage_exports, {
|
|
6053
6153
|
RENDER_ANALYZE_PROMPT: () => RENDER_ANALYZE_PROMPT,
|
|
6054
|
-
definition: () =>
|
|
6055
|
-
execute: () =>
|
|
6154
|
+
definition: () => definition2,
|
|
6155
|
+
execute: () => execute2
|
|
6056
6156
|
});
|
|
6057
6157
|
import { mkdir, unlink, writeFile } from "fs/promises";
|
|
6058
6158
|
import { tmpdir } from "os";
|
|
6059
6159
|
import { dirname, join, resolve as resolve2, sep } from "path";
|
|
6060
6160
|
import { randomUUID } from "crypto";
|
|
6061
|
-
async function
|
|
6161
|
+
async function execute2(input, onLog, context) {
|
|
6062
6162
|
const html = typeof input.html === "string" ? input.html : "";
|
|
6063
6163
|
const width = Math.round(Number(input.width));
|
|
6064
6164
|
const height = Math.round(Number(input.height));
|
|
@@ -6142,7 +6242,7 @@ async function execute3(input, onLog, context) {
|
|
|
6142
6242
|
]
|
|
6143
6243
|
});
|
|
6144
6244
|
}
|
|
6145
|
-
var MIN_DIMENSION, MAX_DIMENSION, RENDER_ANALYZE_PROMPT,
|
|
6245
|
+
var MIN_DIMENSION, MAX_DIMENSION, RENDER_ANALYZE_PROMPT, definition2;
|
|
6146
6246
|
var init_renderImage = __esm({
|
|
6147
6247
|
"src/subagents/designExpert/tools/images/renderImage.ts"() {
|
|
6148
6248
|
"use strict";
|
|
@@ -6155,7 +6255,7 @@ var init_renderImage = __esm({
|
|
|
6155
6255
|
MIN_DIMENSION = 16;
|
|
6156
6256
|
MAX_DIMENSION = 4096;
|
|
6157
6257
|
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.';
|
|
6158
|
-
|
|
6258
|
+
definition2 = {
|
|
6159
6259
|
name: "renderImage",
|
|
6160
6260
|
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.",
|
|
6161
6261
|
inputSchema: {
|
|
@@ -6195,8 +6295,8 @@ var init_renderImage = __esm({
|
|
|
6195
6295
|
// src/subagents/designExpert/tools/analyzeDesign.ts
|
|
6196
6296
|
var analyzeDesign_exports = {};
|
|
6197
6297
|
__export(analyzeDesign_exports, {
|
|
6198
|
-
definition: () =>
|
|
6199
|
-
execute: () =>
|
|
6298
|
+
definition: () => definition3,
|
|
6299
|
+
execute: () => execute3
|
|
6200
6300
|
});
|
|
6201
6301
|
import { readFile as readFile2 } from "fs/promises";
|
|
6202
6302
|
import { extname as extname2, join as join2 } from "path";
|
|
@@ -6218,7 +6318,7 @@ function splitFrontmatter(raw) {
|
|
|
6218
6318
|
html: raw.slice(match[0].length)
|
|
6219
6319
|
};
|
|
6220
6320
|
}
|
|
6221
|
-
async function
|
|
6321
|
+
async function execute3(input, onLog, context) {
|
|
6222
6322
|
const url = String(input.url ?? "").trim();
|
|
6223
6323
|
if (!url) {
|
|
6224
6324
|
return "Error: url is required.";
|
|
@@ -6322,7 +6422,7 @@ ${basePrompt}` : basePrompt;
|
|
|
6322
6422
|
renderedHeight: rendered.height
|
|
6323
6423
|
});
|
|
6324
6424
|
}
|
|
6325
|
-
var DESIGN_REFERENCE_PROMPT,
|
|
6425
|
+
var DESIGN_REFERENCE_PROMPT, definition3, IMAGE_EXT_RE, HTML_EXTS, HTML_RENDER_WIDTH, HTML_RENDER_START_HEIGHT;
|
|
6326
6426
|
var init_analyzeDesign = __esm({
|
|
6327
6427
|
"src/subagents/designExpert/tools/analyzeDesign.ts"() {
|
|
6328
6428
|
"use strict";
|
|
@@ -6357,7 +6457,7 @@ Identify the specific design moves that make this page interesting and unique, d
|
|
|
6357
6457
|
|
|
6358
6458
|
Respond only with your analysis as Markdown and absolutely no other text. Do not use emojis - use unicode if you need symbols.
|
|
6359
6459
|
`;
|
|
6360
|
-
|
|
6460
|
+
definition3 = {
|
|
6361
6461
|
name: "analyzeDesign",
|
|
6362
6462
|
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.",
|
|
6363
6463
|
inputSchema: {
|
|
@@ -6385,10 +6485,10 @@ Respond only with your analysis as Markdown and absolutely no other text. Do not
|
|
|
6385
6485
|
// src/subagents/designExpert/tools/analyzeImage.ts
|
|
6386
6486
|
var analyzeImage_exports = {};
|
|
6387
6487
|
__export(analyzeImage_exports, {
|
|
6388
|
-
definition: () =>
|
|
6389
|
-
execute: () =>
|
|
6488
|
+
definition: () => definition4,
|
|
6489
|
+
execute: () => execute4
|
|
6390
6490
|
});
|
|
6391
|
-
async function
|
|
6491
|
+
async function execute4(input, onLog, context) {
|
|
6392
6492
|
const prompt = buildScreenshotAnalysisPrompt({
|
|
6393
6493
|
prompt: input.prompt
|
|
6394
6494
|
});
|
|
@@ -6401,14 +6501,14 @@ async function execute5(input, onLog, context) {
|
|
|
6401
6501
|
});
|
|
6402
6502
|
return JSON.stringify({ url, analysis });
|
|
6403
6503
|
}
|
|
6404
|
-
var
|
|
6504
|
+
var definition4;
|
|
6405
6505
|
var init_analyzeImage2 = __esm({
|
|
6406
6506
|
"src/subagents/designExpert/tools/analyzeImage.ts"() {
|
|
6407
6507
|
"use strict";
|
|
6408
6508
|
init_analyzeImage();
|
|
6409
6509
|
init_screenshot();
|
|
6410
6510
|
init_surfaces();
|
|
6411
|
-
|
|
6511
|
+
definition4 = {
|
|
6412
6512
|
name: "analyzeImage",
|
|
6413
6513
|
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.",
|
|
6414
6514
|
inputSchema: {
|
|
@@ -6676,10 +6776,10 @@ var init_imageGenerator = __esm({
|
|
|
6676
6776
|
// src/subagents/designExpert/tools/images/generateImages.ts
|
|
6677
6777
|
var generateImages_exports = {};
|
|
6678
6778
|
__export(generateImages_exports, {
|
|
6679
|
-
definition: () =>
|
|
6680
|
-
execute: () =>
|
|
6779
|
+
definition: () => definition5,
|
|
6780
|
+
execute: () => execute5
|
|
6681
6781
|
});
|
|
6682
|
-
async function
|
|
6782
|
+
async function execute5(input, onLog, context) {
|
|
6683
6783
|
return generateImageAssets({
|
|
6684
6784
|
prompts: input.prompts,
|
|
6685
6785
|
width: input.width,
|
|
@@ -6706,13 +6806,13 @@ async function execute6(input, onLog, context) {
|
|
|
6706
6806
|
)
|
|
6707
6807
|
});
|
|
6708
6808
|
}
|
|
6709
|
-
var
|
|
6809
|
+
var definition5;
|
|
6710
6810
|
var init_generateImages = __esm({
|
|
6711
6811
|
"src/subagents/designExpert/tools/images/generateImages.ts"() {
|
|
6712
6812
|
"use strict";
|
|
6713
6813
|
init_imageGenerator();
|
|
6714
6814
|
init_surfaces();
|
|
6715
|
-
|
|
6815
|
+
definition5 = {
|
|
6716
6816
|
name: "generateImages",
|
|
6717
6817
|
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.",
|
|
6718
6818
|
inputSchema: {
|
|
@@ -6751,10 +6851,10 @@ var init_generateImages = __esm({
|
|
|
6751
6851
|
// src/subagents/designExpert/tools/images/editImages.ts
|
|
6752
6852
|
var editImages_exports = {};
|
|
6753
6853
|
__export(editImages_exports, {
|
|
6754
|
-
definition: () =>
|
|
6755
|
-
execute: () =>
|
|
6854
|
+
definition: () => definition6,
|
|
6855
|
+
execute: () => execute6
|
|
6756
6856
|
});
|
|
6757
|
-
async function
|
|
6857
|
+
async function execute6(input, onLog, context) {
|
|
6758
6858
|
return generateImageAssets({
|
|
6759
6859
|
prompts: input.prompts,
|
|
6760
6860
|
sourceImages: input.sourceImages,
|
|
@@ -6781,13 +6881,13 @@ async function execute7(input, onLog, context) {
|
|
|
6781
6881
|
)
|
|
6782
6882
|
});
|
|
6783
6883
|
}
|
|
6784
|
-
var
|
|
6884
|
+
var definition6;
|
|
6785
6885
|
var init_editImages = __esm({
|
|
6786
6886
|
"src/subagents/designExpert/tools/images/editImages.ts"() {
|
|
6787
6887
|
"use strict";
|
|
6788
6888
|
init_imageGenerator();
|
|
6789
6889
|
init_surfaces();
|
|
6790
|
-
|
|
6890
|
+
definition6 = {
|
|
6791
6891
|
name: "editImages",
|
|
6792
6892
|
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.",
|
|
6793
6893
|
inputSchema: {
|
|
@@ -6828,7 +6928,7 @@ var init_editImages = __esm({
|
|
|
6828
6928
|
|
|
6829
6929
|
// src/subagents/copyEditor/tools.ts
|
|
6830
6930
|
var COPY_EDITOR_TOOLS;
|
|
6831
|
-
var
|
|
6931
|
+
var init_tools4 = __esm({
|
|
6832
6932
|
"src/subagents/copyEditor/tools.ts"() {
|
|
6833
6933
|
"use strict";
|
|
6834
6934
|
init_tools();
|
|
@@ -6837,17 +6937,17 @@ var init_tools3 = __esm({
|
|
|
6837
6937
|
});
|
|
6838
6938
|
|
|
6839
6939
|
// src/subagents/copyEditor/index.ts
|
|
6840
|
-
var
|
|
6940
|
+
var BASE_PROMPT3, copyEditorTool;
|
|
6841
6941
|
var init_copyEditor = __esm({
|
|
6842
6942
|
"src/subagents/copyEditor/index.ts"() {
|
|
6843
6943
|
"use strict";
|
|
6844
6944
|
init_assets();
|
|
6845
6945
|
init_runner();
|
|
6846
6946
|
init_context();
|
|
6847
|
-
|
|
6848
|
-
|
|
6947
|
+
init_tools9();
|
|
6948
|
+
init_tools4();
|
|
6849
6949
|
init_surfaces();
|
|
6850
|
-
|
|
6950
|
+
BASE_PROMPT3 = readAsset("subagents/copyEditor", "prompt.md");
|
|
6851
6951
|
copyEditorTool = {
|
|
6852
6952
|
definition: {
|
|
6853
6953
|
name: "copyEditor",
|
|
@@ -6868,7 +6968,7 @@ var init_copyEditor = __esm({
|
|
|
6868
6968
|
return "Error: copy editor requires execution context";
|
|
6869
6969
|
}
|
|
6870
6970
|
const specIndex = loadSpecIndex();
|
|
6871
|
-
const parts = [
|
|
6971
|
+
const parts = [BASE_PROMPT3];
|
|
6872
6972
|
parts.push("<!-- cache_breakpoint -->");
|
|
6873
6973
|
if (specIndex) {
|
|
6874
6974
|
parts.push(specIndex);
|
|
@@ -6906,18 +7006,18 @@ var init_copyEditor = __esm({
|
|
|
6906
7006
|
// src/subagents/designExpert/tools/polishCopy.ts
|
|
6907
7007
|
var polishCopy_exports = {};
|
|
6908
7008
|
__export(polishCopy_exports, {
|
|
6909
|
-
definition: () =>
|
|
6910
|
-
execute: () =>
|
|
7009
|
+
definition: () => definition7,
|
|
7010
|
+
execute: () => execute7
|
|
6911
7011
|
});
|
|
6912
|
-
async function
|
|
7012
|
+
async function execute7(input, _onLog, context) {
|
|
6913
7013
|
return copyEditorTool.execute(input, context);
|
|
6914
7014
|
}
|
|
6915
|
-
var
|
|
7015
|
+
var definition7;
|
|
6916
7016
|
var init_polishCopy = __esm({
|
|
6917
7017
|
"src/subagents/designExpert/tools/polishCopy.ts"() {
|
|
6918
7018
|
"use strict";
|
|
6919
7019
|
init_copyEditor();
|
|
6920
|
-
|
|
7020
|
+
definition7 = {
|
|
6921
7021
|
name: "polishCopy",
|
|
6922
7022
|
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).",
|
|
6923
7023
|
inputSchema: {
|
|
@@ -6955,10 +7055,10 @@ A loaded reference drops out of the conversation once it ages out. Re-read it at
|
|
|
6955
7055
|
// src/subagents/designExpert/tools/loadSkill.ts
|
|
6956
7056
|
var loadSkill_exports = {};
|
|
6957
7057
|
__export(loadSkill_exports, {
|
|
6958
|
-
definition: () =>
|
|
6959
|
-
execute: () =>
|
|
7058
|
+
definition: () => definition8,
|
|
7059
|
+
execute: () => execute8
|
|
6960
7060
|
});
|
|
6961
|
-
async function
|
|
7061
|
+
async function execute8(input) {
|
|
6962
7062
|
const id = String(input.skill ?? "");
|
|
6963
7063
|
const skill = designSkillCatalog.get(id);
|
|
6964
7064
|
if (!skill) {
|
|
@@ -6974,12 +7074,12 @@ This reference lives at ${skill.path}. Re-read it with readFile if you need it a
|
|
|
6974
7074
|
return `Error loading skill "${id}": ${err.message}`;
|
|
6975
7075
|
}
|
|
6976
7076
|
}
|
|
6977
|
-
var
|
|
7077
|
+
var definition8;
|
|
6978
7078
|
var init_loadSkill2 = __esm({
|
|
6979
7079
|
"src/subagents/designExpert/tools/loadSkill.ts"() {
|
|
6980
7080
|
"use strict";
|
|
6981
7081
|
init_catalog2();
|
|
6982
|
-
|
|
7082
|
+
definition8 = {
|
|
6983
7083
|
name: "loadSkill",
|
|
6984
7084
|
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.",
|
|
6985
7085
|
inputSchema: {
|
|
@@ -7004,8 +7104,8 @@ var init_loadSkill2 = __esm({
|
|
|
7004
7104
|
var createWireframe_exports = {};
|
|
7005
7105
|
__export(createWireframe_exports, {
|
|
7006
7106
|
WIREFRAMES_DIR: () => WIREFRAMES_DIR,
|
|
7007
|
-
definition: () =>
|
|
7008
|
-
execute: () =>
|
|
7107
|
+
definition: () => definition9,
|
|
7108
|
+
execute: () => execute9
|
|
7009
7109
|
});
|
|
7010
7110
|
import { mkdir as mkdir2, stat as stat2, writeFile as writeFile2 } from "fs/promises";
|
|
7011
7111
|
import { join as join3 } from "path";
|
|
@@ -7076,7 +7176,7 @@ async function uploadMirror(context, slug, content) {
|
|
|
7076
7176
|
return { ok: false, note: err.message };
|
|
7077
7177
|
}
|
|
7078
7178
|
}
|
|
7079
|
-
async function
|
|
7179
|
+
async function execute9(input, onLog, context) {
|
|
7080
7180
|
if (!context) {
|
|
7081
7181
|
return "Error: createWireframe requires execution context";
|
|
7082
7182
|
}
|
|
@@ -7122,7 +7222,7 @@ async function execute10(input, onLog, context) {
|
|
|
7122
7222
|
}
|
|
7123
7223
|
return lines.join("\n");
|
|
7124
7224
|
}
|
|
7125
|
-
var log10, WIREFRAMES_DIR, UPLOAD_TIMEOUT_MS2,
|
|
7225
|
+
var log10, WIREFRAMES_DIR, UPLOAD_TIMEOUT_MS2, definition9, SLUG_RE;
|
|
7126
7226
|
var init_createWireframe = __esm({
|
|
7127
7227
|
"src/subagents/designExpert/tools/createWireframe.ts"() {
|
|
7128
7228
|
"use strict";
|
|
@@ -7131,7 +7231,7 @@ var init_createWireframe = __esm({
|
|
|
7131
7231
|
log10 = createLogger("createWireframe");
|
|
7132
7232
|
WIREFRAMES_DIR = "src/.wireframes";
|
|
7133
7233
|
UPLOAD_TIMEOUT_MS2 = 3e4;
|
|
7134
|
-
|
|
7234
|
+
definition9 = {
|
|
7135
7235
|
name: "createWireframe",
|
|
7136
7236
|
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.",
|
|
7137
7237
|
inputSchema: {
|
|
@@ -7170,13 +7270,13 @@ async function executeDesignExpertTool(name, input, context, toolCallId, onLog)
|
|
|
7170
7270
|
const childContext = context && toolCallId ? deriveContext(context, toolCallId, onLog) : context;
|
|
7171
7271
|
return tool.execute(input, onLog, childContext);
|
|
7172
7272
|
}
|
|
7173
|
-
var tools, DESIGN_EXPERT_TOOLS;
|
|
7174
|
-
var
|
|
7273
|
+
var research, tools, DESIGN_EXPERT_TOOLS;
|
|
7274
|
+
var init_tools5 = __esm({
|
|
7175
7275
|
"src/subagents/designExpert/tools/index.ts"() {
|
|
7176
7276
|
"use strict";
|
|
7177
|
-
|
|
7277
|
+
init_tools9();
|
|
7178
7278
|
init_tools();
|
|
7179
|
-
|
|
7279
|
+
init_research();
|
|
7180
7280
|
init_scrapeWebUrl();
|
|
7181
7281
|
init_analyzeDesign();
|
|
7182
7282
|
init_analyzeImage2();
|
|
@@ -7187,8 +7287,29 @@ var init_tools4 = __esm({
|
|
|
7187
7287
|
init_loadSkill2();
|
|
7188
7288
|
init_createWireframe();
|
|
7189
7289
|
init_screenshot2();
|
|
7290
|
+
research = {
|
|
7291
|
+
definition: {
|
|
7292
|
+
name: "research",
|
|
7293
|
+
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.",
|
|
7294
|
+
inputSchema: {
|
|
7295
|
+
type: "object",
|
|
7296
|
+
properties: {
|
|
7297
|
+
task: {
|
|
7298
|
+
type: "string",
|
|
7299
|
+
description: "What you need to find out, in natural language, with enough product context to make the findings relevant."
|
|
7300
|
+
}
|
|
7301
|
+
},
|
|
7302
|
+
required: ["task"]
|
|
7303
|
+
}
|
|
7304
|
+
},
|
|
7305
|
+
execute: (input, _onLog, context) => {
|
|
7306
|
+
if (!context) {
|
|
7307
|
+
return Promise.resolve("Error: research requires execution context");
|
|
7308
|
+
}
|
|
7309
|
+
return runResearch(input.task, context);
|
|
7310
|
+
}
|
|
7311
|
+
};
|
|
7190
7312
|
tools = {
|
|
7191
|
-
searchGoogle: searchGoogle_exports,
|
|
7192
7313
|
scrapeWebUrl: scrapeWebUrl_exports,
|
|
7193
7314
|
analyzeDesign: analyzeDesign_exports,
|
|
7194
7315
|
analyzeImage: analyzeImage_exports,
|
|
@@ -7202,7 +7323,8 @@ var init_tools4 = __esm({
|
|
|
7202
7323
|
polishCopy: polishCopy_exports,
|
|
7203
7324
|
loadSkill: loadSkill_exports,
|
|
7204
7325
|
// Appended last: tool order is part of the subagent's prompt-cache prefix.
|
|
7205
|
-
createWireframe: createWireframe_exports
|
|
7326
|
+
createWireframe: createWireframe_exports,
|
|
7327
|
+
research
|
|
7206
7328
|
};
|
|
7207
7329
|
DESIGN_EXPERT_TOOLS = [
|
|
7208
7330
|
...COMMON_READ_TOOLS,
|
|
@@ -7681,9 +7803,9 @@ var DESCRIPTION, RENDER_WRITE_TOOL_NAMES, DESIGN_EXPERT_RENDER_TOOLS, designExpe
|
|
|
7681
7803
|
var init_designExpert = __esm({
|
|
7682
7804
|
"src/subagents/designExpert/index.ts"() {
|
|
7683
7805
|
"use strict";
|
|
7684
|
-
|
|
7806
|
+
init_tools9();
|
|
7685
7807
|
init_runner();
|
|
7686
|
-
|
|
7808
|
+
init_tools5();
|
|
7687
7809
|
init_tools();
|
|
7688
7810
|
init_prompt2();
|
|
7689
7811
|
init_validateWireframeRefs();
|
|
@@ -7739,7 +7861,7 @@ Visual design expert. Describe the situation and what you need \u2014 the agent
|
|
|
7739
7861
|
|
|
7740
7862
|
// src/subagents/productVision/tools.ts
|
|
7741
7863
|
var VISION_TOOLS;
|
|
7742
|
-
var
|
|
7864
|
+
var init_tools6 = __esm({
|
|
7743
7865
|
"src/subagents/productVision/tools.ts"() {
|
|
7744
7866
|
"use strict";
|
|
7745
7867
|
init_tools();
|
|
@@ -7909,7 +8031,7 @@ var init_executor = __esm({
|
|
|
7909
8031
|
function getProductVisionPrompt() {
|
|
7910
8032
|
const specIndex = loadSpecIndex();
|
|
7911
8033
|
const roadmapIndex = loadRoadmapIndex();
|
|
7912
|
-
const parts = [
|
|
8034
|
+
const parts = [BASE_PROMPT4, loadPlatformBrief()];
|
|
7913
8035
|
parts.push("<!-- cache_breakpoint -->");
|
|
7914
8036
|
if (specIndex) {
|
|
7915
8037
|
parts.push(specIndex);
|
|
@@ -7919,13 +8041,13 @@ function getProductVisionPrompt() {
|
|
|
7919
8041
|
}
|
|
7920
8042
|
return parts.join("\n\n");
|
|
7921
8043
|
}
|
|
7922
|
-
var
|
|
8044
|
+
var BASE_PROMPT4;
|
|
7923
8045
|
var init_prompt3 = __esm({
|
|
7924
8046
|
"src/subagents/productVision/prompt.ts"() {
|
|
7925
8047
|
"use strict";
|
|
7926
8048
|
init_assets();
|
|
7927
8049
|
init_context();
|
|
7928
|
-
|
|
8050
|
+
BASE_PROMPT4 = readAsset("subagents/productVision", "prompt.md");
|
|
7929
8051
|
}
|
|
7930
8052
|
});
|
|
7931
8053
|
|
|
@@ -7934,9 +8056,9 @@ var productVisionTool;
|
|
|
7934
8056
|
var init_productVision = __esm({
|
|
7935
8057
|
"src/subagents/productVision/index.ts"() {
|
|
7936
8058
|
"use strict";
|
|
7937
|
-
|
|
8059
|
+
init_tools9();
|
|
7938
8060
|
init_runner();
|
|
7939
|
-
|
|
8061
|
+
init_tools6();
|
|
7940
8062
|
init_tools();
|
|
7941
8063
|
init_executor();
|
|
7942
8064
|
init_prompt3();
|
|
@@ -8012,7 +8134,7 @@ var init_productVision = __esm({
|
|
|
8012
8134
|
|
|
8013
8135
|
// src/subagents/codeSanityCheck/tools.ts
|
|
8014
8136
|
var SANITY_CHECK_TOOLS;
|
|
8015
|
-
var
|
|
8137
|
+
var init_tools7 = __esm({
|
|
8016
8138
|
"src/subagents/codeSanityCheck/tools.ts"() {
|
|
8017
8139
|
"use strict";
|
|
8018
8140
|
init_tools();
|
|
@@ -8061,23 +8183,40 @@ var init_tools6 = __esm({
|
|
|
8061
8183
|
},
|
|
8062
8184
|
required: ["command"]
|
|
8063
8185
|
}
|
|
8186
|
+
},
|
|
8187
|
+
// Appended last: tool order is part of the subagent's prompt-cache prefix.
|
|
8188
|
+
{
|
|
8189
|
+
name: "research",
|
|
8190
|
+
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.",
|
|
8191
|
+
inputSchema: {
|
|
8192
|
+
type: "object",
|
|
8193
|
+
properties: {
|
|
8194
|
+
task: {
|
|
8195
|
+
type: "string",
|
|
8196
|
+
description: "What you need to find out, in natural language."
|
|
8197
|
+
}
|
|
8198
|
+
},
|
|
8199
|
+
required: ["task"]
|
|
8200
|
+
}
|
|
8064
8201
|
}
|
|
8065
8202
|
];
|
|
8066
8203
|
}
|
|
8067
8204
|
});
|
|
8068
8205
|
|
|
8069
8206
|
// src/subagents/codeSanityCheck/index.ts
|
|
8070
|
-
var
|
|
8207
|
+
var BASE_PROMPT5, codeSanityCheckTool;
|
|
8071
8208
|
var init_codeSanityCheck = __esm({
|
|
8072
8209
|
"src/subagents/codeSanityCheck/index.ts"() {
|
|
8073
8210
|
"use strict";
|
|
8074
8211
|
init_assets();
|
|
8075
8212
|
init_runner();
|
|
8076
8213
|
init_context();
|
|
8077
|
-
|
|
8078
|
-
|
|
8214
|
+
init_tools9();
|
|
8215
|
+
init_tools7();
|
|
8216
|
+
init_research();
|
|
8217
|
+
init_tools3();
|
|
8079
8218
|
init_surfaces();
|
|
8080
|
-
|
|
8219
|
+
BASE_PROMPT5 = readAsset("subagents/codeSanityCheck", "prompt.md");
|
|
8081
8220
|
codeSanityCheckTool = {
|
|
8082
8221
|
definition: {
|
|
8083
8222
|
name: "codeSanityCheck",
|
|
@@ -8098,7 +8237,7 @@ var init_codeSanityCheck = __esm({
|
|
|
8098
8237
|
return "Error: code sanity check requires execution context";
|
|
8099
8238
|
}
|
|
8100
8239
|
const specIndex = loadSpecIndex();
|
|
8101
|
-
const parts = [
|
|
8240
|
+
const parts = [BASE_PROMPT5, loadPlatformBrief()];
|
|
8102
8241
|
parts.push("<!-- cache_breakpoint -->");
|
|
8103
8242
|
if (specIndex) {
|
|
8104
8243
|
parts.push(specIndex);
|
|
@@ -8114,6 +8253,16 @@ var init_codeSanityCheck = __esm({
|
|
|
8114
8253
|
...deriveContext(context, toolCallId, onLog),
|
|
8115
8254
|
subAgentMessages: sams
|
|
8116
8255
|
} : context;
|
|
8256
|
+
if (name === "searchGoogle") {
|
|
8257
|
+
return executeSearchGoogle(
|
|
8258
|
+
{ ...toolInput, fetchTopN: 5 },
|
|
8259
|
+
childCtx.onLog,
|
|
8260
|
+
"codeSanityCheck"
|
|
8261
|
+
);
|
|
8262
|
+
}
|
|
8263
|
+
if (name === "research") {
|
|
8264
|
+
return runResearch(String(toolInput.task ?? ""), childCtx);
|
|
8265
|
+
}
|
|
8117
8266
|
return executeTool(name, toolInput, childCtx);
|
|
8118
8267
|
},
|
|
8119
8268
|
apiConfig: context.apiConfig,
|
|
@@ -8257,7 +8406,7 @@ The copy in <overview_copy> is final \u2014 it was authored and edited before it
|
|
|
8257
8406
|
|
|
8258
8407
|
// src/subagents/specSync/tools.ts
|
|
8259
8408
|
var SPEC_SYNC_TOOLS;
|
|
8260
|
-
var
|
|
8409
|
+
var init_tools8 = __esm({
|
|
8261
8410
|
"src/subagents/specSync/tools.ts"() {
|
|
8262
8411
|
"use strict";
|
|
8263
8412
|
init_tools();
|
|
@@ -8292,19 +8441,19 @@ var init_lock = __esm({
|
|
|
8292
8441
|
});
|
|
8293
8442
|
|
|
8294
8443
|
// src/subagents/specSync/index.ts
|
|
8295
|
-
var
|
|
8444
|
+
var BASE_PROMPT6, MSFM_DOCS, specSyncTool;
|
|
8296
8445
|
var init_specSync = __esm({
|
|
8297
8446
|
"src/subagents/specSync/index.ts"() {
|
|
8298
8447
|
"use strict";
|
|
8299
8448
|
init_assets();
|
|
8300
8449
|
init_runner();
|
|
8301
8450
|
init_context();
|
|
8302
|
-
|
|
8451
|
+
init_tools9();
|
|
8303
8452
|
init_writeBuildOverview();
|
|
8304
|
-
|
|
8453
|
+
init_tools8();
|
|
8305
8454
|
init_lock();
|
|
8306
8455
|
init_surfaces();
|
|
8307
|
-
|
|
8456
|
+
BASE_PROMPT6 = readAsset("subagents/specSync", "prompt.md");
|
|
8308
8457
|
MSFM_DOCS = `<mindstudio_flavored_markdown_spec_docs>
|
|
8309
8458
|
${readAsset(
|
|
8310
8459
|
"prompt",
|
|
@@ -8343,7 +8492,7 @@ ${readAsset(
|
|
|
8343
8492
|
}
|
|
8344
8493
|
const specIndex = loadSpecIndex();
|
|
8345
8494
|
const parts = [
|
|
8346
|
-
|
|
8495
|
+
BASE_PROMPT6,
|
|
8347
8496
|
loadPlatformBrief(),
|
|
8348
8497
|
MSFM_DOCS,
|
|
8349
8498
|
"<!-- cache_breakpoint -->"
|
|
@@ -8475,7 +8624,7 @@ function executeTool(name, input, context) {
|
|
|
8475
8624
|
return tool.execute(input, context);
|
|
8476
8625
|
}
|
|
8477
8626
|
var ALL_TOOLS, SUBAGENT_TOOL_NAMES;
|
|
8478
|
-
var
|
|
8627
|
+
var init_tools9 = __esm({
|
|
8479
8628
|
"src/tools/index.ts"() {
|
|
8480
8629
|
"use strict";
|
|
8481
8630
|
init_readSpec();
|
|
@@ -8489,7 +8638,6 @@ var init_tools8 = __esm({
|
|
|
8489
8638
|
init_promptUser();
|
|
8490
8639
|
init_confirmDestructiveAction();
|
|
8491
8640
|
init_sdkConsultant();
|
|
8492
|
-
init_searchGoogle();
|
|
8493
8641
|
init_setProjectMetadata();
|
|
8494
8642
|
init_compactConversation();
|
|
8495
8643
|
init_loadSkill();
|
|
@@ -8514,6 +8662,7 @@ var init_tools8 = __esm({
|
|
|
8514
8662
|
init_codeSanityCheck();
|
|
8515
8663
|
init_copyEditor();
|
|
8516
8664
|
init_specSync();
|
|
8665
|
+
init_research();
|
|
8517
8666
|
init_scrapeWebUrl2();
|
|
8518
8667
|
init_writeBuildOverview();
|
|
8519
8668
|
ALL_TOOLS = [
|
|
@@ -8523,7 +8672,6 @@ var init_tools8 = __esm({
|
|
|
8523
8672
|
confirmDestructiveActionTool,
|
|
8524
8673
|
askMindStudioSdkTool,
|
|
8525
8674
|
scrapeWebUrlTool,
|
|
8526
|
-
searchGoogleTool,
|
|
8527
8675
|
setProjectMetadataTool,
|
|
8528
8676
|
designExpertTool,
|
|
8529
8677
|
productVisionTool,
|
|
@@ -8562,7 +8710,8 @@ var init_tools8 = __esm({
|
|
|
8562
8710
|
// Appended rather than grouped: position is part of the cache prefix, so a
|
|
8563
8711
|
// new tool goes at the end to leave every existing session's prefix intact.
|
|
8564
8712
|
loadSkillTool,
|
|
8565
|
-
testJewelTool
|
|
8713
|
+
testJewelTool,
|
|
8714
|
+
researchTool
|
|
8566
8715
|
];
|
|
8567
8716
|
SUBAGENT_TOOL_NAMES = /* @__PURE__ */ new Set([
|
|
8568
8717
|
"visualDesignExpert",
|
|
@@ -8571,7 +8720,8 @@ var init_tools8 = __esm({
|
|
|
8571
8720
|
"copyEditor",
|
|
8572
8721
|
"specSync",
|
|
8573
8722
|
"runAutomatedBrowserTest",
|
|
8574
|
-
"askMindStudioSdk"
|
|
8723
|
+
"askMindStudioSdk",
|
|
8724
|
+
"research"
|
|
8575
8725
|
]);
|
|
8576
8726
|
}
|
|
8577
8727
|
});
|
|
@@ -8921,6 +9071,12 @@ function classify(line, matches) {
|
|
|
8921
9071
|
tailClean = SEPARATORS_ONLY.test(gap);
|
|
8922
9072
|
}
|
|
8923
9073
|
}
|
|
9074
|
+
function chipCase(label) {
|
|
9075
|
+
if (label.startsWith("`")) {
|
|
9076
|
+
return label;
|
|
9077
|
+
}
|
|
9078
|
+
return label.charAt(0).toUpperCase() + label.slice(1);
|
|
9079
|
+
}
|
|
8924
9080
|
function parseSuggestions(raw) {
|
|
8925
9081
|
if (!raw.includes(SUGGEST_MARKER)) {
|
|
8926
9082
|
return { text: raw, suggestions: [] };
|
|
@@ -8950,7 +9106,7 @@ function parseSuggestions(raw) {
|
|
|
8950
9106
|
const key = `${m.label}::${m.message}`;
|
|
8951
9107
|
if (!seen.has(key)) {
|
|
8952
9108
|
seen.add(key);
|
|
8953
|
-
suggestions.push({ label: m.label, message: m.message });
|
|
9109
|
+
suggestions.push({ label: chipCase(m.label), message: m.message });
|
|
8954
9110
|
}
|
|
8955
9111
|
}
|
|
8956
9112
|
let rebuilt = "";
|
|
@@ -9401,10 +9557,12 @@ async function runTurn(params) {
|
|
|
9401
9557
|
onBackgroundComplete
|
|
9402
9558
|
} = params;
|
|
9403
9559
|
const tools2 = getToolDefinitions();
|
|
9404
|
-
const
|
|
9405
|
-
|
|
9406
|
-
|
|
9407
|
-
|
|
9560
|
+
const { baseline, effective: parentModel } = resolveParentModel(
|
|
9561
|
+
state.models,
|
|
9562
|
+
model,
|
|
9563
|
+
buildModel
|
|
9564
|
+
);
|
|
9565
|
+
const modelOverride = parentModel !== baseline ? { from: baseline } : void 0;
|
|
9408
9566
|
const totalAttachments = entries.reduce(
|
|
9409
9567
|
(n, e) => n + (e.attachments?.length ?? 0),
|
|
9410
9568
|
0
|
|
@@ -9412,7 +9570,7 @@ async function runTurn(params) {
|
|
|
9412
9570
|
log14.info("Turn started", {
|
|
9413
9571
|
requestId,
|
|
9414
9572
|
model,
|
|
9415
|
-
buildModel:
|
|
9573
|
+
buildModel: modelOverride ? parentModel : void 0,
|
|
9416
9574
|
toolCount: tools2.length,
|
|
9417
9575
|
...entries.length > 1 && { entryCount: entries.length },
|
|
9418
9576
|
...totalAttachments > 0 && { attachmentCount: totalAttachments }
|
|
@@ -10075,7 +10233,7 @@ var init_agent = __esm({
|
|
|
10075
10233
|
"src/agent.ts"() {
|
|
10076
10234
|
"use strict";
|
|
10077
10235
|
init_api();
|
|
10078
|
-
|
|
10236
|
+
init_tools9();
|
|
10079
10237
|
init_session();
|
|
10080
10238
|
init_logger();
|
|
10081
10239
|
init_usageLedger();
|
|
@@ -10551,12 +10709,13 @@ function loadPassiveResults() {
|
|
|
10551
10709
|
}
|
|
10552
10710
|
return [];
|
|
10553
10711
|
}
|
|
10554
|
-
function writeStats(stats, queue, passiveResults) {
|
|
10712
|
+
function writeStats(stats, queue, passiveResults, suggestCompactAt) {
|
|
10555
10713
|
try {
|
|
10556
10714
|
writeFileAtomicSync(
|
|
10557
10715
|
STATS_FILE,
|
|
10558
10716
|
JSON.stringify({
|
|
10559
10717
|
...stats,
|
|
10718
|
+
suggestCompactAt,
|
|
10560
10719
|
queue,
|
|
10561
10720
|
passiveResults
|
|
10562
10721
|
})
|
|
@@ -10767,7 +10926,7 @@ var headless_exports = {};
|
|
|
10767
10926
|
__export(headless_exports, {
|
|
10768
10927
|
HeadlessSession: () => HeadlessSession
|
|
10769
10928
|
});
|
|
10770
|
-
var log17, EXTERNAL_TOOL_TIMEOUT_MS, LONG_RUNNING_TOOLS, LONG_RUNNING_TOOL_TIMEOUT_MS, USER_FACING_TOOLS,
|
|
10929
|
+
var log17, EXTERNAL_TOOL_TIMEOUT_MS, LONG_RUNNING_TOOLS, LONG_RUNNING_TOOL_TIMEOUT_MS, USER_FACING_TOOLS, HeadlessSession;
|
|
10771
10930
|
var init_headless = __esm({
|
|
10772
10931
|
"src/headless/index.ts"() {
|
|
10773
10932
|
"use strict";
|
|
@@ -10785,7 +10944,7 @@ var init_headless = __esm({
|
|
|
10785
10944
|
init_attachments();
|
|
10786
10945
|
init_planFile();
|
|
10787
10946
|
init_stats();
|
|
10788
|
-
|
|
10947
|
+
init_tools9();
|
|
10789
10948
|
init_messageQueue();
|
|
10790
10949
|
init_resolve();
|
|
10791
10950
|
init_sentinel();
|
|
@@ -10798,7 +10957,6 @@ var init_headless = __esm({
|
|
|
10798
10957
|
"confirmDestructiveAction",
|
|
10799
10958
|
"presentPublishPlan"
|
|
10800
10959
|
]);
|
|
10801
|
-
FORCED_COMPACTION_THRESHOLD_TOKENS = 85e4;
|
|
10802
10960
|
HeadlessSession = class {
|
|
10803
10961
|
// Configuration
|
|
10804
10962
|
opts;
|
|
@@ -11071,7 +11229,15 @@ var init_headless = __esm({
|
|
|
11071
11229
|
/** Persist sessionStats + queue snapshot + passive pen to .remy-stats.json. */
|
|
11072
11230
|
persistStats() {
|
|
11073
11231
|
this.sessionStats.updatedAt = Date.now();
|
|
11074
|
-
|
|
11232
|
+
const suggestCompactAt = getSuggestCompactAt(
|
|
11233
|
+
resolveParentModel(this.state.models, this.opts.model).effective
|
|
11234
|
+
);
|
|
11235
|
+
writeStats(
|
|
11236
|
+
this.sessionStats,
|
|
11237
|
+
this.queue.snapshot(),
|
|
11238
|
+
this.passivePen,
|
|
11239
|
+
suggestCompactAt
|
|
11240
|
+
);
|
|
11075
11241
|
}
|
|
11076
11242
|
//////////////////////////////////////////////////////////////////////////////
|
|
11077
11243
|
// Background completions (tool-block mutation; message delivery via queue)
|
|
@@ -11101,8 +11267,9 @@ var init_headless = __esm({
|
|
|
11101
11267
|
saveSession(this.state);
|
|
11102
11268
|
}
|
|
11103
11269
|
/**
|
|
11104
|
-
* Forced compaction gate. If lastContextSize exceeds the
|
|
11105
|
-
*
|
|
11270
|
+
* Forced compaction gate. If lastContextSize exceeds the upcoming turn's
|
|
11271
|
+
* model threshold (per-model — see ModelContextLimits in models/surfaces),
|
|
11272
|
+
* compact before letting the turn run. Coalesces with any in-flight
|
|
11106
11273
|
* compaction (e.g., one already started by /compact or a tool call). No
|
|
11107
11274
|
* timeout — compaction takes as long as it takes.
|
|
11108
11275
|
*
|
|
@@ -11113,13 +11280,15 @@ var init_headless = __esm({
|
|
|
11113
11280
|
* On compaction failure we don't bail — the turn proceeds and surfaces any
|
|
11114
11281
|
* downstream overflow through the existing "prompt is too long" path.
|
|
11115
11282
|
*/
|
|
11116
|
-
async runForcedCompactionIfNeeded(requestId) {
|
|
11117
|
-
|
|
11283
|
+
async runForcedCompactionIfNeeded(requestId, parentModel) {
|
|
11284
|
+
const threshold = getContextLimits(parentModel).forceCompactAt;
|
|
11285
|
+
if (this.sessionStats.lastContextSize <= threshold) {
|
|
11118
11286
|
return;
|
|
11119
11287
|
}
|
|
11120
11288
|
log17.info("Forced compaction gate triggered", {
|
|
11121
11289
|
contextSize: this.sessionStats.lastContextSize,
|
|
11122
|
-
threshold
|
|
11290
|
+
threshold,
|
|
11291
|
+
model: parentModel,
|
|
11123
11292
|
requestId
|
|
11124
11293
|
});
|
|
11125
11294
|
try {
|
|
@@ -11601,7 +11770,12 @@ var init_headless = __esm({
|
|
|
11601
11770
|
}
|
|
11602
11771
|
return steered;
|
|
11603
11772
|
};
|
|
11604
|
-
|
|
11773
|
+
const parentModel = resolveParentModel(
|
|
11774
|
+
this.state.models,
|
|
11775
|
+
this.opts.model,
|
|
11776
|
+
params.buildModel
|
|
11777
|
+
).effective;
|
|
11778
|
+
await this.runForcedCompactionIfNeeded(requestId, parentModel);
|
|
11605
11779
|
try {
|
|
11606
11780
|
await runTurn({
|
|
11607
11781
|
state: this.state,
|