@mindstudio-ai/remy 0.1.174 → 0.1.176
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 +362 -162
- package/dist/index.js +398 -180
- package/dist/prompt/compiled/interfaces.md +27 -3
- package/dist/prompt/static/coding.md +5 -7
- package/dist/subagents/browserAutomation/prompt.md +3 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -55,14 +55,14 @@ function initLoggerHeadless(level = "info") {
|
|
|
55
55
|
}
|
|
56
56
|
function initLoggerInteractive(level = "error") {
|
|
57
57
|
currentLevel = LEVELS[level];
|
|
58
|
-
let
|
|
58
|
+
let fd2 = null;
|
|
59
59
|
writeFn = (line) => {
|
|
60
60
|
try {
|
|
61
|
-
if (
|
|
61
|
+
if (fd2 === null) {
|
|
62
62
|
fs.mkdirSync(".logs", { recursive: true });
|
|
63
|
-
|
|
63
|
+
fd2 = fs.openSync(".logs/agent.ndjson", "a");
|
|
64
64
|
}
|
|
65
|
-
fs.writeSync(
|
|
65
|
+
fs.writeSync(fd2, line + "\n");
|
|
66
66
|
} catch {
|
|
67
67
|
}
|
|
68
68
|
};
|
|
@@ -209,8 +209,10 @@ async function* streamChat(params) {
|
|
|
209
209
|
...subAgentId && { subAgentId },
|
|
210
210
|
durationMs: elapsed,
|
|
211
211
|
stopReason: event.stopReason,
|
|
212
|
+
modelId: event.modelId,
|
|
212
213
|
inputTokens: event.usage.inputTokens,
|
|
213
|
-
outputTokens: event.usage.outputTokens
|
|
214
|
+
outputTokens: event.usage.outputTokens,
|
|
215
|
+
cost: event.cost
|
|
214
216
|
});
|
|
215
217
|
} else if (event.type === "error") {
|
|
216
218
|
log.error("SSE error event", {
|
|
@@ -296,6 +298,7 @@ async function generateBackgroundAck(params) {
|
|
|
296
298
|
Authorization: `Bearer ${params.apiConfig.apiKey}`
|
|
297
299
|
},
|
|
298
300
|
body: JSON.stringify({
|
|
301
|
+
appId: params.apiConfig.appId,
|
|
299
302
|
agentName: params.agentName,
|
|
300
303
|
task: params.task
|
|
301
304
|
}),
|
|
@@ -1237,12 +1240,127 @@ var init_sdkConsultant = __esm({
|
|
|
1237
1240
|
}
|
|
1238
1241
|
});
|
|
1239
1242
|
|
|
1243
|
+
// src/usageLedger.ts
|
|
1244
|
+
import fs8 from "fs";
|
|
1245
|
+
function nanoToDollars(nano) {
|
|
1246
|
+
return typeof nano === "number" ? nano / 1e9 : void 0;
|
|
1247
|
+
}
|
|
1248
|
+
function recordUsage(entry) {
|
|
1249
|
+
try {
|
|
1250
|
+
if (fd === null) {
|
|
1251
|
+
fs8.mkdirSync(".logs", { recursive: true });
|
|
1252
|
+
fd = fs8.openSync(LEDGER_FILE, "a");
|
|
1253
|
+
}
|
|
1254
|
+
fs8.writeSync(fd, JSON.stringify(entry) + "\n");
|
|
1255
|
+
} catch {
|
|
1256
|
+
}
|
|
1257
|
+
}
|
|
1258
|
+
var LEDGER_FILE, fd;
|
|
1259
|
+
var init_usageLedger = __esm({
|
|
1260
|
+
"src/usageLedger.ts"() {
|
|
1261
|
+
"use strict";
|
|
1262
|
+
LEDGER_FILE = ".logs/usage.ndjson";
|
|
1263
|
+
fd = null;
|
|
1264
|
+
}
|
|
1265
|
+
});
|
|
1266
|
+
|
|
1267
|
+
// src/subagents/common/runMindstudioCli.ts
|
|
1268
|
+
function stripFlags(args2) {
|
|
1269
|
+
const out = [];
|
|
1270
|
+
for (let i = 0; i < args2.length; i++) {
|
|
1271
|
+
const arg = args2[i];
|
|
1272
|
+
if (arg === "--no-meta") {
|
|
1273
|
+
continue;
|
|
1274
|
+
}
|
|
1275
|
+
if (arg === "--output-key") {
|
|
1276
|
+
i++;
|
|
1277
|
+
continue;
|
|
1278
|
+
}
|
|
1279
|
+
out.push(arg);
|
|
1280
|
+
}
|
|
1281
|
+
return out;
|
|
1282
|
+
}
|
|
1283
|
+
async function runMindstudioCli(args2, options) {
|
|
1284
|
+
const cleanArgs = stripFlags(args2);
|
|
1285
|
+
const cliAction = args2[0];
|
|
1286
|
+
const agentName = options?.caller ?? "mindstudio-cli";
|
|
1287
|
+
const start = Date.now();
|
|
1288
|
+
const raw = await runCli("mindstudio", cleanArgs, options);
|
|
1289
|
+
let envelope;
|
|
1290
|
+
try {
|
|
1291
|
+
envelope = JSON.parse(raw);
|
|
1292
|
+
} catch {
|
|
1293
|
+
return raw;
|
|
1294
|
+
}
|
|
1295
|
+
if (envelope && typeof envelope === "object" && Array.isArray(envelope.results)) {
|
|
1296
|
+
const durationMs = Date.now() - start;
|
|
1297
|
+
for (const step of envelope.results) {
|
|
1298
|
+
if (typeof step?.billingCost === "number") {
|
|
1299
|
+
recordUsage({
|
|
1300
|
+
ts: Date.now(),
|
|
1301
|
+
agentName,
|
|
1302
|
+
cliAction: `${cliAction}:${step.stepType ?? "step"}`,
|
|
1303
|
+
cost: nanoToDollars(step.billingCost),
|
|
1304
|
+
inputTokens: 0,
|
|
1305
|
+
outputTokens: 0,
|
|
1306
|
+
durationMs,
|
|
1307
|
+
toolNames: []
|
|
1308
|
+
});
|
|
1309
|
+
}
|
|
1310
|
+
}
|
|
1311
|
+
return JSON.stringify(envelope.results);
|
|
1312
|
+
}
|
|
1313
|
+
if (typeof envelope?.$billingCost === "number") {
|
|
1314
|
+
recordUsage({
|
|
1315
|
+
ts: Date.now(),
|
|
1316
|
+
agentName,
|
|
1317
|
+
cliAction,
|
|
1318
|
+
cost: nanoToDollars(envelope.$billingCost),
|
|
1319
|
+
billingEvents: envelope.$billingEvents,
|
|
1320
|
+
// CLI billing isn't expressed as input/output tokens for most actions
|
|
1321
|
+
// (image gen is per-image, scrape per-page, etc). `numUnits` inside each
|
|
1322
|
+
// billingEvent carries the per-event unit count.
|
|
1323
|
+
inputTokens: 0,
|
|
1324
|
+
outputTokens: 0,
|
|
1325
|
+
durationMs: Date.now() - start,
|
|
1326
|
+
toolNames: []
|
|
1327
|
+
});
|
|
1328
|
+
}
|
|
1329
|
+
if (options?.outputKey) {
|
|
1330
|
+
const v = envelope?.[options.outputKey];
|
|
1331
|
+
if (v === void 0 || v === null) {
|
|
1332
|
+
return JSON.stringify(stripDollarKeys(envelope));
|
|
1333
|
+
}
|
|
1334
|
+
return typeof v === "string" ? v : JSON.stringify(v);
|
|
1335
|
+
}
|
|
1336
|
+
return JSON.stringify(stripDollarKeys(envelope));
|
|
1337
|
+
}
|
|
1338
|
+
function stripDollarKeys(envelope) {
|
|
1339
|
+
if (!envelope || typeof envelope !== "object" || Array.isArray(envelope)) {
|
|
1340
|
+
return envelope;
|
|
1341
|
+
}
|
|
1342
|
+
const out = {};
|
|
1343
|
+
for (const [k, v] of Object.entries(envelope)) {
|
|
1344
|
+
if (!k.startsWith("$")) {
|
|
1345
|
+
out[k] = v;
|
|
1346
|
+
}
|
|
1347
|
+
}
|
|
1348
|
+
return out;
|
|
1349
|
+
}
|
|
1350
|
+
var init_runMindstudioCli = __esm({
|
|
1351
|
+
"src/subagents/common/runMindstudioCli.ts"() {
|
|
1352
|
+
"use strict";
|
|
1353
|
+
init_runCli();
|
|
1354
|
+
init_usageLedger();
|
|
1355
|
+
}
|
|
1356
|
+
});
|
|
1357
|
+
|
|
1240
1358
|
// src/tools/common/searchGoogle.ts
|
|
1241
1359
|
var searchGoogleTool;
|
|
1242
1360
|
var init_searchGoogle = __esm({
|
|
1243
1361
|
"src/tools/common/searchGoogle.ts"() {
|
|
1244
1362
|
"use strict";
|
|
1245
|
-
|
|
1363
|
+
init_runMindstudioCli();
|
|
1246
1364
|
searchGoogleTool = {
|
|
1247
1365
|
clearable: false,
|
|
1248
1366
|
definition: {
|
|
@@ -1261,19 +1379,9 @@ var init_searchGoogle = __esm({
|
|
|
1261
1379
|
},
|
|
1262
1380
|
async execute(input, context) {
|
|
1263
1381
|
const query = input.query;
|
|
1264
|
-
return
|
|
1265
|
-
"
|
|
1266
|
-
|
|
1267
|
-
"search-google",
|
|
1268
|
-
"--query",
|
|
1269
|
-
query,
|
|
1270
|
-
"--export-type",
|
|
1271
|
-
"json",
|
|
1272
|
-
"--output-key",
|
|
1273
|
-
"results",
|
|
1274
|
-
"--no-meta"
|
|
1275
|
-
],
|
|
1276
|
-
{ maxBuffer: 512 * 1024, onLog: context?.onLog }
|
|
1382
|
+
return runMindstudioCli(
|
|
1383
|
+
["search-google", "--query", query, "--export-type", "json"],
|
|
1384
|
+
{ outputKey: "results", maxBuffer: 512 * 1024, onLog: context?.onLog }
|
|
1277
1385
|
);
|
|
1278
1386
|
}
|
|
1279
1387
|
};
|
|
@@ -1320,12 +1428,12 @@ var init_setProjectMetadata = __esm({
|
|
|
1320
1428
|
});
|
|
1321
1429
|
|
|
1322
1430
|
// src/assets.ts
|
|
1323
|
-
import
|
|
1431
|
+
import fs9 from "fs";
|
|
1324
1432
|
import path3 from "path";
|
|
1325
1433
|
function findRoot(start) {
|
|
1326
1434
|
let dir = start;
|
|
1327
1435
|
while (dir !== path3.dirname(dir)) {
|
|
1328
|
-
if (
|
|
1436
|
+
if (fs9.existsSync(path3.join(dir, "package.json"))) {
|
|
1329
1437
|
return dir;
|
|
1330
1438
|
}
|
|
1331
1439
|
dir = path3.dirname(dir);
|
|
@@ -1338,7 +1446,7 @@ function assetPath(...segments) {
|
|
|
1338
1446
|
function readAsset(...segments) {
|
|
1339
1447
|
const full = assetPath(...segments);
|
|
1340
1448
|
try {
|
|
1341
|
-
return
|
|
1449
|
+
return fs9.readFileSync(full, "utf-8").trim();
|
|
1342
1450
|
} catch {
|
|
1343
1451
|
throw new Error(`Required asset missing: ${full}`);
|
|
1344
1452
|
}
|
|
@@ -1346,7 +1454,7 @@ function readAsset(...segments) {
|
|
|
1346
1454
|
function readJsonAsset(fallback, ...segments) {
|
|
1347
1455
|
const full = assetPath(...segments);
|
|
1348
1456
|
try {
|
|
1349
|
-
return JSON.parse(
|
|
1457
|
+
return JSON.parse(fs9.readFileSync(full, "utf-8"));
|
|
1350
1458
|
} catch {
|
|
1351
1459
|
return fallback;
|
|
1352
1460
|
}
|
|
@@ -1358,7 +1466,7 @@ var init_assets = __esm({
|
|
|
1358
1466
|
ROOT = findRoot(
|
|
1359
1467
|
import.meta.dirname ?? path3.dirname(new URL(import.meta.url).pathname)
|
|
1360
1468
|
);
|
|
1361
|
-
ASSETS_BASE =
|
|
1469
|
+
ASSETS_BASE = fs9.existsSync(path3.join(ROOT, "dist", "prompt")) ? path3.join(ROOT, "dist") : path3.join(ROOT, "src");
|
|
1362
1470
|
}
|
|
1363
1471
|
});
|
|
1364
1472
|
|
|
@@ -1571,6 +1679,7 @@ async function generateSummary(apiConfig, name, compactionPrompt, messagesToSumm
|
|
|
1571
1679
|
Conversation to summarize:
|
|
1572
1680
|
|
|
1573
1681
|
${serialized}` : serialized;
|
|
1682
|
+
const iterStart = Date.now();
|
|
1574
1683
|
for await (const event of streamChat({
|
|
1575
1684
|
...apiConfig,
|
|
1576
1685
|
subAgentId: "conversationSummarizer",
|
|
@@ -1580,6 +1689,20 @@ ${serialized}` : serialized;
|
|
|
1580
1689
|
})) {
|
|
1581
1690
|
if (event.type === "text") {
|
|
1582
1691
|
summaryText += event.text;
|
|
1692
|
+
} else if (event.type === "done") {
|
|
1693
|
+
recordUsage({
|
|
1694
|
+
ts: Date.now(),
|
|
1695
|
+
agentName: "conversationSummarizer",
|
|
1696
|
+
modelId: event.modelId,
|
|
1697
|
+
inputTokens: event.usage.inputTokens,
|
|
1698
|
+
outputTokens: event.usage.outputTokens,
|
|
1699
|
+
cacheCreationTokens: event.usage.cacheCreationTokens,
|
|
1700
|
+
cacheReadTokens: event.usage.cacheReadTokens,
|
|
1701
|
+
cost: nanoToDollars(event.cost),
|
|
1702
|
+
billingEvents: event.billingEvents,
|
|
1703
|
+
durationMs: Date.now() - iterStart,
|
|
1704
|
+
toolNames: []
|
|
1705
|
+
});
|
|
1583
1706
|
} else if (event.type === "error") {
|
|
1584
1707
|
log2.error("Summary generation failed", { name, error: event.error });
|
|
1585
1708
|
return null;
|
|
@@ -1599,6 +1722,7 @@ var init_compaction = __esm({
|
|
|
1599
1722
|
init_api();
|
|
1600
1723
|
init_assets();
|
|
1601
1724
|
init_logger();
|
|
1725
|
+
init_usageLedger();
|
|
1602
1726
|
log2 = createLogger("compaction");
|
|
1603
1727
|
CONVERSATION_SUMMARY_PROMPT = readAsset("compaction", "conversation.md");
|
|
1604
1728
|
SUBAGENT_SUMMARY_PROMPT = readAsset("compaction", "subagent.md");
|
|
@@ -1608,11 +1732,11 @@ var init_compaction = __esm({
|
|
|
1608
1732
|
});
|
|
1609
1733
|
|
|
1610
1734
|
// src/prompt/static/projectContext.ts
|
|
1611
|
-
import
|
|
1735
|
+
import fs10 from "fs";
|
|
1612
1736
|
import path4 from "path";
|
|
1613
1737
|
function loadProjectManifest() {
|
|
1614
1738
|
try {
|
|
1615
|
-
const manifest =
|
|
1739
|
+
const manifest = fs10.readFileSync("mindstudio.json", "utf-8");
|
|
1616
1740
|
return `
|
|
1617
1741
|
## Project Manifest (mindstudio.json)
|
|
1618
1742
|
\`\`\`json
|
|
@@ -1653,7 +1777,7 @@ ${entries.join("\n")}`;
|
|
|
1653
1777
|
function walkMdFiles(dir) {
|
|
1654
1778
|
const results = [];
|
|
1655
1779
|
try {
|
|
1656
|
-
const entries =
|
|
1780
|
+
const entries = fs10.readdirSync(dir, { withFileTypes: true });
|
|
1657
1781
|
for (const entry of entries) {
|
|
1658
1782
|
const full = path4.join(dir, entry.name);
|
|
1659
1783
|
if (entry.isDirectory()) {
|
|
@@ -1668,7 +1792,7 @@ function walkMdFiles(dir) {
|
|
|
1668
1792
|
}
|
|
1669
1793
|
function parseFrontmatter(filePath) {
|
|
1670
1794
|
try {
|
|
1671
|
-
const content =
|
|
1795
|
+
const content = fs10.readFileSync(filePath, "utf-8");
|
|
1672
1796
|
const match = content.match(/^---\n([\s\S]*?)\n---/);
|
|
1673
1797
|
if (!match) {
|
|
1674
1798
|
return { name: "", description: "", type: "" };
|
|
@@ -1684,7 +1808,7 @@ function parseFrontmatter(filePath) {
|
|
|
1684
1808
|
}
|
|
1685
1809
|
function loadPlanStatus() {
|
|
1686
1810
|
try {
|
|
1687
|
-
const content =
|
|
1811
|
+
const content = fs10.readFileSync(".remy-plan.md", "utf-8");
|
|
1688
1812
|
const match = content.match(/^---\n([\s\S]*?)\n---/);
|
|
1689
1813
|
const status = match?.[1]?.match(/^status:\s*(.+)$/m)?.[1]?.trim();
|
|
1690
1814
|
if (status === "pending") {
|
|
@@ -1706,7 +1830,7 @@ The user has approved your implementation plan in .remy-plan.md. You may referen
|
|
|
1706
1830
|
}
|
|
1707
1831
|
function loadProjectFileListing() {
|
|
1708
1832
|
try {
|
|
1709
|
-
const entries =
|
|
1833
|
+
const entries = fs10.readdirSync(".", { withFileTypes: true });
|
|
1710
1834
|
const listing = entries.filter((e) => e.name !== ".git" && e.name !== "node_modules").sort((a, b) => {
|
|
1711
1835
|
if (a.isDirectory() && !b.isDirectory()) {
|
|
1712
1836
|
return -1;
|
|
@@ -1961,7 +2085,7 @@ var init_compactConversation = __esm({
|
|
|
1961
2085
|
});
|
|
1962
2086
|
|
|
1963
2087
|
// src/tools/code/readFile.ts
|
|
1964
|
-
import
|
|
2088
|
+
import fs11 from "fs/promises";
|
|
1965
2089
|
function isBinary(buffer) {
|
|
1966
2090
|
const sample = buffer.subarray(0, 8192);
|
|
1967
2091
|
for (let i = 0; i < sample.length; i++) {
|
|
@@ -2002,7 +2126,7 @@ var init_readFile = __esm({
|
|
|
2002
2126
|
},
|
|
2003
2127
|
async execute(input) {
|
|
2004
2128
|
try {
|
|
2005
|
-
const buffer = await
|
|
2129
|
+
const buffer = await fs11.readFile(input.path);
|
|
2006
2130
|
if (isBinary(buffer)) {
|
|
2007
2131
|
const size = buffer.length;
|
|
2008
2132
|
const unit = size > 1024 * 1024 ? `${(size / (1024 * 1024)).toFixed(1)}MB` : `${(size / 1024).toFixed(1)}KB`;
|
|
@@ -2038,7 +2162,7 @@ var init_readFile = __esm({
|
|
|
2038
2162
|
});
|
|
2039
2163
|
|
|
2040
2164
|
// src/tools/code/writeFile.ts
|
|
2041
|
-
import
|
|
2165
|
+
import fs12 from "fs/promises";
|
|
2042
2166
|
import path5 from "path";
|
|
2043
2167
|
var writeFileTool;
|
|
2044
2168
|
var init_writeFile = __esm({
|
|
@@ -2082,7 +2206,7 @@ var init_writeFile = __esm({
|
|
|
2082
2206
|
lastNewlineCount = newlineCount;
|
|
2083
2207
|
const lastNewline = partial.content.lastIndexOf("\n");
|
|
2084
2208
|
const completeContent = partial.content.substring(0, lastNewline + 1);
|
|
2085
|
-
const oldContent = await
|
|
2209
|
+
const oldContent = await fs12.readFile(partial.path, "utf-8").catch(() => "");
|
|
2086
2210
|
return `Writing ${partial.path} (${newlineCount} lines)
|
|
2087
2211
|
${unifiedDiff(partial.path, oldContent, completeContent)}`;
|
|
2088
2212
|
}
|
|
@@ -2091,13 +2215,13 @@ ${unifiedDiff(partial.path, oldContent, completeContent)}`;
|
|
|
2091
2215
|
async execute(input) {
|
|
2092
2216
|
const release = await acquireFileLock(input.path);
|
|
2093
2217
|
try {
|
|
2094
|
-
await
|
|
2218
|
+
await fs12.mkdir(path5.dirname(input.path), { recursive: true });
|
|
2095
2219
|
let oldContent = null;
|
|
2096
2220
|
try {
|
|
2097
|
-
oldContent = await
|
|
2221
|
+
oldContent = await fs12.readFile(input.path, "utf-8");
|
|
2098
2222
|
} catch {
|
|
2099
2223
|
}
|
|
2100
|
-
await
|
|
2224
|
+
await fs12.writeFile(input.path, input.content, "utf-8");
|
|
2101
2225
|
const lineCount = input.content.split("\n").length;
|
|
2102
2226
|
const label = oldContent !== null ? "Wrote" : "Created";
|
|
2103
2227
|
return `${label} ${input.path} (${lineCount} lines)
|
|
@@ -2197,7 +2321,7 @@ var init_helpers2 = __esm({
|
|
|
2197
2321
|
});
|
|
2198
2322
|
|
|
2199
2323
|
// src/tools/code/editFile/index.ts
|
|
2200
|
-
import
|
|
2324
|
+
import fs13 from "fs/promises";
|
|
2201
2325
|
var editFileTool;
|
|
2202
2326
|
var init_editFile = __esm({
|
|
2203
2327
|
"src/tools/code/editFile/index.ts"() {
|
|
@@ -2236,7 +2360,7 @@ var init_editFile = __esm({
|
|
|
2236
2360
|
async execute(input) {
|
|
2237
2361
|
const release = await acquireFileLock(input.path);
|
|
2238
2362
|
try {
|
|
2239
|
-
const content = await
|
|
2363
|
+
const content = await fs13.readFile(input.path, "utf-8");
|
|
2240
2364
|
const { old_string, new_string, replace_all } = input;
|
|
2241
2365
|
const occurrences = findOccurrences(content, old_string);
|
|
2242
2366
|
if (replace_all) {
|
|
@@ -2252,7 +2376,7 @@ var init_editFile = __esm({
|
|
|
2252
2376
|
new_string
|
|
2253
2377
|
);
|
|
2254
2378
|
}
|
|
2255
|
-
await
|
|
2379
|
+
await fs13.writeFile(input.path, updated, "utf-8");
|
|
2256
2380
|
return `Replaced ${occurrences.length} occurrence${occurrences.length > 1 ? "s" : ""} in ${input.path}
|
|
2257
2381
|
${unifiedDiff(input.path, content, updated)}`;
|
|
2258
2382
|
}
|
|
@@ -2263,7 +2387,7 @@ ${unifiedDiff(input.path, content, updated)}`;
|
|
|
2263
2387
|
old_string.length,
|
|
2264
2388
|
new_string
|
|
2265
2389
|
);
|
|
2266
|
-
await
|
|
2390
|
+
await fs13.writeFile(input.path, updated, "utf-8");
|
|
2267
2391
|
return `Updated ${input.path}
|
|
2268
2392
|
${unifiedDiff(input.path, content, updated)}`;
|
|
2269
2393
|
}
|
|
@@ -2279,7 +2403,7 @@ ${unifiedDiff(input.path, content, updated)}`;
|
|
|
2279
2403
|
flex.matchedText.length,
|
|
2280
2404
|
new_string
|
|
2281
2405
|
);
|
|
2282
|
-
await
|
|
2406
|
+
await fs13.writeFile(input.path, updated, "utf-8");
|
|
2283
2407
|
return `Updated ${input.path} (matched with flexible whitespace at line ${flex.line})
|
|
2284
2408
|
${unifiedDiff(input.path, content, updated)}`;
|
|
2285
2409
|
}
|
|
@@ -2531,10 +2655,10 @@ var init_glob = __esm({
|
|
|
2531
2655
|
});
|
|
2532
2656
|
|
|
2533
2657
|
// src/tools/code/listDir.ts
|
|
2534
|
-
import
|
|
2658
|
+
import fs14 from "fs/promises";
|
|
2535
2659
|
import path6 from "path";
|
|
2536
2660
|
async function readAndSort(dirPath) {
|
|
2537
|
-
const entries = await
|
|
2661
|
+
const entries = await fs14.readdir(dirPath, { withFileTypes: true });
|
|
2538
2662
|
return entries.filter((e) => !EXCLUDE.has(e.name)).sort((a, b) => {
|
|
2539
2663
|
if (a.isDirectory() && !b.isDirectory()) {
|
|
2540
2664
|
return -1;
|
|
@@ -2575,7 +2699,7 @@ function formatSize(bytes) {
|
|
|
2575
2699
|
}
|
|
2576
2700
|
async function formatFile(dirPath, name, indent) {
|
|
2577
2701
|
try {
|
|
2578
|
-
const stat = await
|
|
2702
|
+
const stat = await fs14.stat(path6.join(dirPath, name));
|
|
2579
2703
|
return `${indent}${name}${" ".repeat(Math.max(1, 30 - indent.length - name.length))}${formatSize(stat.size)}`;
|
|
2580
2704
|
} catch {
|
|
2581
2705
|
return `${indent}${name}`;
|
|
@@ -2940,8 +3064,7 @@ var init_queryDatabase = __esm({
|
|
|
2940
3064
|
// src/subagents/common/analyzeImage.ts
|
|
2941
3065
|
async function analyzeImage(params) {
|
|
2942
3066
|
const { prompt, imageUrl, timeout = 2e5, onLog } = params;
|
|
2943
|
-
return
|
|
2944
|
-
"mindstudio",
|
|
3067
|
+
return runMindstudioCli(
|
|
2945
3068
|
[
|
|
2946
3069
|
"analyze-image",
|
|
2947
3070
|
"--prompt",
|
|
@@ -2949,24 +3072,21 @@ async function analyzeImage(params) {
|
|
|
2949
3072
|
"--image-url",
|
|
2950
3073
|
imageUrl,
|
|
2951
3074
|
"--vision-model-override",
|
|
2952
|
-
JSON.stringify(VISION_MODEL_OVERRIDE)
|
|
2953
|
-
"--output-key",
|
|
2954
|
-
"analysis",
|
|
2955
|
-
"--no-meta"
|
|
3075
|
+
JSON.stringify(VISION_MODEL_OVERRIDE)
|
|
2956
3076
|
],
|
|
2957
|
-
{ timeout, onLog }
|
|
3077
|
+
{ outputKey: "analysis", timeout, onLog }
|
|
2958
3078
|
);
|
|
2959
3079
|
}
|
|
2960
3080
|
var VISION_MODEL, VISION_MODEL_OVERRIDE;
|
|
2961
3081
|
var init_analyzeImage = __esm({
|
|
2962
3082
|
"src/subagents/common/analyzeImage.ts"() {
|
|
2963
3083
|
"use strict";
|
|
2964
|
-
|
|
3084
|
+
init_runMindstudioCli();
|
|
2965
3085
|
VISION_MODEL = "claude-4-6-sonnet";
|
|
2966
|
-
VISION_MODEL_OVERRIDE =
|
|
3086
|
+
VISION_MODEL_OVERRIDE = {
|
|
2967
3087
|
model: VISION_MODEL,
|
|
2968
3088
|
config: { thinkingBudget: "off" }
|
|
2969
|
-
}
|
|
3089
|
+
};
|
|
2970
3090
|
}
|
|
2971
3091
|
});
|
|
2972
3092
|
|
|
@@ -3006,11 +3126,11 @@ async function captureAndAnalyzeScreenshot(promptOrOptions) {
|
|
|
3006
3126
|
let prompt;
|
|
3007
3127
|
let existingUrl;
|
|
3008
3128
|
let onLog;
|
|
3009
|
-
let
|
|
3129
|
+
let path13;
|
|
3010
3130
|
if (typeof promptOrOptions === "object" && promptOrOptions !== null) {
|
|
3011
3131
|
prompt = promptOrOptions.prompt;
|
|
3012
3132
|
existingUrl = promptOrOptions.imageUrl;
|
|
3013
|
-
|
|
3133
|
+
path13 = promptOrOptions.path;
|
|
3014
3134
|
onLog = promptOrOptions.onLog;
|
|
3015
3135
|
} else {
|
|
3016
3136
|
prompt = promptOrOptions;
|
|
@@ -3022,7 +3142,7 @@ async function captureAndAnalyzeScreenshot(promptOrOptions) {
|
|
|
3022
3142
|
} else {
|
|
3023
3143
|
const ssResult = await sidecarRequest(
|
|
3024
3144
|
"/screenshot-full-page",
|
|
3025
|
-
|
|
3145
|
+
path13 ? { path: path13 } : void 0,
|
|
3026
3146
|
{ timeout: 12e4 }
|
|
3027
3147
|
);
|
|
3028
3148
|
url = ssResult?.url || ssResult?.screenshotUrl;
|
|
@@ -3097,7 +3217,7 @@ function startStatusWatcher(config) {
|
|
|
3097
3217
|
"Content-Type": "application/json",
|
|
3098
3218
|
Authorization: `Bearer ${apiConfig.apiKey}`
|
|
3099
3219
|
},
|
|
3100
|
-
body: JSON.stringify({ context }),
|
|
3220
|
+
body: JSON.stringify({ appId: apiConfig.appId, context }),
|
|
3101
3221
|
signal
|
|
3102
3222
|
});
|
|
3103
3223
|
if (!res.ok || stopped) {
|
|
@@ -3299,8 +3419,14 @@ ${content}` : attachmentHeader;
|
|
|
3299
3419
|
const text = blocks.filter((b) => b.type === "text").map((b) => b.text).join("");
|
|
3300
3420
|
const toolCalls = blocks.filter((b) => b.type === "tool").map((b) => ({ id: b.id, name: b.name, input: b.input }));
|
|
3301
3421
|
const thinking = blocks.filter(
|
|
3302
|
-
(b) => b.type === "thinking"
|
|
3303
|
-
).map(
|
|
3422
|
+
(b) => b.type === "thinking" || b.type === "redacted_thinking"
|
|
3423
|
+
).map(
|
|
3424
|
+
(b) => b.type === "thinking" ? {
|
|
3425
|
+
type: "thinking",
|
|
3426
|
+
thinking: b.thinking,
|
|
3427
|
+
signature: b.signature
|
|
3428
|
+
} : { type: "redacted_thinking", data: b.data }
|
|
3429
|
+
);
|
|
3304
3430
|
const cleaned2 = {
|
|
3305
3431
|
role: msg.role,
|
|
3306
3432
|
content: text
|
|
@@ -3395,10 +3521,13 @@ ${partial}` : "[INTERRUPTED] Agent was interrupted before producing output.",
|
|
|
3395
3521
|
if (signal?.aborted) {
|
|
3396
3522
|
return abortResult([]);
|
|
3397
3523
|
}
|
|
3524
|
+
const iterStart = Date.now();
|
|
3398
3525
|
const contentBlocks = [];
|
|
3399
3526
|
let thinkingStartedAt = 0;
|
|
3527
|
+
let lastThinkingRelatedStartedAt;
|
|
3400
3528
|
let stopReason = "end_turn";
|
|
3401
3529
|
let currentToolNames = "";
|
|
3530
|
+
let lastUsage;
|
|
3402
3531
|
const statusWatcher = startStatusWatcher({
|
|
3403
3532
|
apiConfig,
|
|
3404
3533
|
getContext: () => {
|
|
@@ -3473,8 +3602,20 @@ ${partial}` : "[INTERRUPTED] Agent was interrupted before producing output.",
|
|
|
3473
3602
|
startedAt: thinkingStartedAt,
|
|
3474
3603
|
completedAt: event.ts
|
|
3475
3604
|
});
|
|
3605
|
+
lastThinkingRelatedStartedAt = thinkingStartedAt;
|
|
3476
3606
|
thinkingStartedAt = 0;
|
|
3477
3607
|
break;
|
|
3608
|
+
case "redacted_thinking_complete": {
|
|
3609
|
+
const startedAt = lastThinkingRelatedStartedAt !== void 0 ? lastThinkingRelatedStartedAt + 1 : event.ts;
|
|
3610
|
+
contentBlocks.push({
|
|
3611
|
+
type: "redacted_thinking",
|
|
3612
|
+
data: event.data,
|
|
3613
|
+
startedAt,
|
|
3614
|
+
completedAt: event.ts
|
|
3615
|
+
});
|
|
3616
|
+
lastThinkingRelatedStartedAt = startedAt;
|
|
3617
|
+
break;
|
|
3618
|
+
}
|
|
3478
3619
|
case "tool_use":
|
|
3479
3620
|
contentBlocks.push({
|
|
3480
3621
|
type: "tool",
|
|
@@ -3492,6 +3633,30 @@ ${partial}` : "[INTERRUPTED] Agent was interrupted before producing output.",
|
|
|
3492
3633
|
break;
|
|
3493
3634
|
case "done":
|
|
3494
3635
|
stopReason = event.stopReason;
|
|
3636
|
+
lastUsage = {
|
|
3637
|
+
inputTokens: event.usage.inputTokens,
|
|
3638
|
+
outputTokens: event.usage.outputTokens,
|
|
3639
|
+
cacheCreationTokens: event.usage.cacheCreationTokens,
|
|
3640
|
+
cacheReadTokens: event.usage.cacheReadTokens,
|
|
3641
|
+
llmCalls: 1
|
|
3642
|
+
};
|
|
3643
|
+
recordUsage({
|
|
3644
|
+
ts: Date.now(),
|
|
3645
|
+
requestId,
|
|
3646
|
+
agentName: subAgentId || "sub-agent",
|
|
3647
|
+
parentToolId,
|
|
3648
|
+
modelId: event.modelId,
|
|
3649
|
+
inputTokens: event.usage.inputTokens,
|
|
3650
|
+
outputTokens: event.usage.outputTokens,
|
|
3651
|
+
cacheCreationTokens: event.usage.cacheCreationTokens,
|
|
3652
|
+
cacheReadTokens: event.usage.cacheReadTokens,
|
|
3653
|
+
cost: nanoToDollars(event.cost),
|
|
3654
|
+
billingEvents: event.billingEvents,
|
|
3655
|
+
durationMs: Date.now() - iterStart,
|
|
3656
|
+
toolNames: contentBlocks.filter(
|
|
3657
|
+
(b) => b.type === "tool"
|
|
3658
|
+
).map((b) => b.name)
|
|
3659
|
+
});
|
|
3495
3660
|
break;
|
|
3496
3661
|
case "error":
|
|
3497
3662
|
return {
|
|
@@ -3511,7 +3676,8 @@ ${partial}` : "[INTERRUPTED] Agent was interrupted before producing output.",
|
|
|
3511
3676
|
}
|
|
3512
3677
|
messages.push({
|
|
3513
3678
|
role: "assistant",
|
|
3514
|
-
content: contentBlocks
|
|
3679
|
+
content: contentBlocks,
|
|
3680
|
+
...lastUsage ? { usage: lastUsage } : {}
|
|
3515
3681
|
});
|
|
3516
3682
|
const toolCalls = contentBlocks.filter(
|
|
3517
3683
|
(b) => b.type === "tool"
|
|
@@ -3708,6 +3874,7 @@ var init_runner = __esm({
|
|
|
3708
3874
|
"use strict";
|
|
3709
3875
|
init_api();
|
|
3710
3876
|
init_logger();
|
|
3877
|
+
init_usageLedger();
|
|
3711
3878
|
init_statusWatcher();
|
|
3712
3879
|
init_cleanMessages();
|
|
3713
3880
|
log5 = createLogger("sub-agent");
|
|
@@ -3854,10 +4021,10 @@ var init_tools = __esm({
|
|
|
3854
4021
|
});
|
|
3855
4022
|
|
|
3856
4023
|
// src/subagents/browserAutomation/prompt.ts
|
|
3857
|
-
import
|
|
4024
|
+
import fs15 from "fs";
|
|
3858
4025
|
function getBrowserAutomationPrompt() {
|
|
3859
4026
|
try {
|
|
3860
|
-
const appSpec =
|
|
4027
|
+
const appSpec = fs15.readFileSync("src/app.md", "utf-8").trim();
|
|
3861
4028
|
return `${BASE_PROMPT}
|
|
3862
4029
|
|
|
3863
4030
|
<!-- cache_breakpoint -->
|
|
@@ -3889,14 +4056,15 @@ var init_browserAutomation = __esm({
|
|
|
3889
4056
|
init_sidecar();
|
|
3890
4057
|
init_browserLock();
|
|
3891
4058
|
init_screenshot();
|
|
3892
|
-
|
|
4059
|
+
init_runMindstudioCli();
|
|
4060
|
+
init_analyzeImage();
|
|
3893
4061
|
init_logger();
|
|
3894
4062
|
log6 = createLogger("browser-automation");
|
|
3895
4063
|
browserAutomationTool = {
|
|
3896
4064
|
clearable: true,
|
|
3897
4065
|
definition: {
|
|
3898
4066
|
name: "runAutomatedBrowserTest",
|
|
3899
|
-
description: "Run an automated browser test against the live preview. Describe what to test \u2014 the agent figures out how. Use after meaningful changes to frontend code, to reproduce user-reported issues, or to test end-to-end flows.
|
|
4067
|
+
description: "Run an automated browser test against the live preview. Describe what to test \u2014 the agent figures out how. Use after meaningful changes to frontend code, to reproduce user-reported issues, or to test end-to-end flows. Never give it explicit values to use when filling out forms or creating accounts \u2014 it will use its own judgement (often it needs specific values to trigger dev-mode bypasses of things like login verification codes).",
|
|
3900
4068
|
inputSchema: {
|
|
3901
4069
|
type: "object",
|
|
3902
4070
|
properties: {
|
|
@@ -3972,13 +4140,13 @@ var init_browserAutomation = __esm({
|
|
|
3972
4140
|
imageUrl: s.result.url,
|
|
3973
4141
|
prompt: buildScreenshotAnalysisPrompt({
|
|
3974
4142
|
styleMap: s.result.styleMap
|
|
3975
|
-
})
|
|
4143
|
+
}),
|
|
4144
|
+
visionModelOverride: VISION_MODEL_OVERRIDE
|
|
3976
4145
|
}
|
|
3977
4146
|
}));
|
|
3978
|
-
const batchResult = await
|
|
3979
|
-
"
|
|
3980
|
-
|
|
3981
|
-
{ timeout: 2e5 }
|
|
4147
|
+
const batchResult = await runMindstudioCli(
|
|
4148
|
+
["batch", JSON.stringify(batchInput)],
|
|
4149
|
+
{ timeout: 2e5, caller: "browserAutomation" }
|
|
3982
4150
|
);
|
|
3983
4151
|
try {
|
|
3984
4152
|
const analyses = JSON.parse(batchResult);
|
|
@@ -4032,7 +4200,7 @@ var init_screenshot2 = __esm({
|
|
|
4032
4200
|
clearable: true,
|
|
4033
4201
|
definition: {
|
|
4034
4202
|
name: "screenshot",
|
|
4035
|
-
description: "Capture a full-height screenshot of the app preview and get a description of what's on screen. Captures the settled page state \u2014 it cannot
|
|
4203
|
+
description: "Capture a full-height screenshot of the app preview and get a description of what's on screen. Captures the settled page state \u2014 it cannot catch animations, transitions, or transient state. Optionally provide specific questions about what you're looking for. Use a bulleted list to ask many questions at once. To ask additional questions about a screenshot you have already captured, pass its URL as imageUrl to skip recapture. If the screenshot requires interaction first (logging in, clicking a tab, dismissing a modal), use the instructions param to describe the steps.",
|
|
4036
4204
|
inputSchema: {
|
|
4037
4205
|
type: "object",
|
|
4038
4206
|
properties: {
|
|
@@ -4203,26 +4371,16 @@ __export(searchGoogle_exports, {
|
|
|
4203
4371
|
execute: () => execute
|
|
4204
4372
|
});
|
|
4205
4373
|
async function execute(input, onLog) {
|
|
4206
|
-
return
|
|
4207
|
-
"
|
|
4208
|
-
|
|
4209
|
-
"search-google",
|
|
4210
|
-
"--query",
|
|
4211
|
-
input.query,
|
|
4212
|
-
"--export-type",
|
|
4213
|
-
"json",
|
|
4214
|
-
"--output-key",
|
|
4215
|
-
"results",
|
|
4216
|
-
"--no-meta"
|
|
4217
|
-
],
|
|
4218
|
-
{ onLog }
|
|
4374
|
+
return runMindstudioCli(
|
|
4375
|
+
["search-google", "--query", input.query, "--export-type", "json"],
|
|
4376
|
+
{ outputKey: "results", onLog, caller: "designExpert" }
|
|
4219
4377
|
);
|
|
4220
4378
|
}
|
|
4221
4379
|
var definition;
|
|
4222
4380
|
var init_searchGoogle2 = __esm({
|
|
4223
4381
|
"src/subagents/designExpert/tools/searchGoogle.ts"() {
|
|
4224
4382
|
"use strict";
|
|
4225
|
-
|
|
4383
|
+
init_runMindstudioCli();
|
|
4226
4384
|
definition = {
|
|
4227
4385
|
clearable: false,
|
|
4228
4386
|
name: "searchGoogle",
|
|
@@ -4252,24 +4410,22 @@ async function execute2(input, onLog) {
|
|
|
4252
4410
|
if (input.screenshot) {
|
|
4253
4411
|
pageOptions.screenshot = true;
|
|
4254
4412
|
}
|
|
4255
|
-
return
|
|
4256
|
-
"mindstudio",
|
|
4413
|
+
return runMindstudioCli(
|
|
4257
4414
|
[
|
|
4258
4415
|
"scrape-url",
|
|
4259
4416
|
"--url",
|
|
4260
4417
|
input.url,
|
|
4261
4418
|
"--page-options",
|
|
4262
|
-
JSON.stringify(pageOptions)
|
|
4263
|
-
"--no-meta"
|
|
4419
|
+
JSON.stringify(pageOptions)
|
|
4264
4420
|
],
|
|
4265
|
-
{ onLog }
|
|
4421
|
+
{ onLog, caller: "designExpert" }
|
|
4266
4422
|
);
|
|
4267
4423
|
}
|
|
4268
4424
|
var definition2;
|
|
4269
4425
|
var init_scrapeWebUrl = __esm({
|
|
4270
4426
|
"src/subagents/designExpert/tools/scrapeWebUrl.ts"() {
|
|
4271
4427
|
"use strict";
|
|
4272
|
-
|
|
4428
|
+
init_runMindstudioCli();
|
|
4273
4429
|
definition2 = {
|
|
4274
4430
|
clearable: false,
|
|
4275
4431
|
name: "scrapeWebUrl",
|
|
@@ -4300,8 +4456,7 @@ async function execute3(input, onLog) {
|
|
|
4300
4456
|
const isImageUrl = /\.(png|jpe?g|webp|gif|svg|avif)(\?|$)/i.test(url);
|
|
4301
4457
|
let imageUrl = url;
|
|
4302
4458
|
if (!isImageUrl) {
|
|
4303
|
-
const ssUrl = await
|
|
4304
|
-
"mindstudio",
|
|
4459
|
+
const ssUrl = await runMindstudioCli(
|
|
4305
4460
|
[
|
|
4306
4461
|
"screenshot-url",
|
|
4307
4462
|
"--url",
|
|
@@ -4311,12 +4466,14 @@ async function execute3(input, onLog) {
|
|
|
4311
4466
|
"--width",
|
|
4312
4467
|
"1440",
|
|
4313
4468
|
"--delay",
|
|
4314
|
-
"2000"
|
|
4315
|
-
"--output-key",
|
|
4316
|
-
"screenshotUrl",
|
|
4317
|
-
"--no-meta"
|
|
4469
|
+
"2000"
|
|
4318
4470
|
],
|
|
4319
|
-
{
|
|
4471
|
+
{
|
|
4472
|
+
outputKey: "screenshotUrl",
|
|
4473
|
+
timeout: 12e4,
|
|
4474
|
+
onLog,
|
|
4475
|
+
caller: "designExpert"
|
|
4476
|
+
}
|
|
4320
4477
|
);
|
|
4321
4478
|
if (ssUrl.startsWith("Error")) {
|
|
4322
4479
|
return `Could not screenshot ${url}: ${ssUrl}`;
|
|
@@ -4334,7 +4491,7 @@ var DESIGN_REFERENCE_PROMPT, definition3;
|
|
|
4334
4491
|
var init_analyzeDesign = __esm({
|
|
4335
4492
|
"src/subagents/designExpert/tools/analyzeDesign.ts"() {
|
|
4336
4493
|
"use strict";
|
|
4337
|
-
|
|
4494
|
+
init_runMindstudioCli();
|
|
4338
4495
|
init_analyzeImage();
|
|
4339
4496
|
DESIGN_REFERENCE_PROMPT = `
|
|
4340
4497
|
You are analyzing a screenshot of a real website or app for a designer's personal technique/inspiration reference notes.
|
|
@@ -4526,19 +4683,15 @@ ${context}
|
|
|
4526
4683
|
<brief>
|
|
4527
4684
|
${brief}
|
|
4528
4685
|
</brief>`;
|
|
4529
|
-
const enhanced = await
|
|
4530
|
-
"mindstudio",
|
|
4686
|
+
const enhanced = await runMindstudioCli(
|
|
4531
4687
|
[
|
|
4532
4688
|
"generate-text",
|
|
4533
4689
|
"--message",
|
|
4534
4690
|
message,
|
|
4535
4691
|
"--model-override",
|
|
4536
|
-
JSON.stringify(MODEL_OVERRIDE)
|
|
4537
|
-
"--output-key",
|
|
4538
|
-
"content",
|
|
4539
|
-
"--no-meta"
|
|
4692
|
+
JSON.stringify(MODEL_OVERRIDE)
|
|
4540
4693
|
],
|
|
4541
|
-
{ timeout: 6e4, onLog }
|
|
4694
|
+
{ outputKey: "content", timeout: 6e4, onLog, caller: "designExpert" }
|
|
4542
4695
|
);
|
|
4543
4696
|
return enhanced.trim();
|
|
4544
4697
|
}
|
|
@@ -4546,13 +4699,13 @@ var ENHANCE_MODEL, MODEL_OVERRIDE, SYSTEM_PROMPT;
|
|
|
4546
4699
|
var init_enhancePrompt = __esm({
|
|
4547
4700
|
"src/subagents/designExpert/tools/images/enhancePrompt.ts"() {
|
|
4548
4701
|
"use strict";
|
|
4549
|
-
|
|
4702
|
+
init_runMindstudioCli();
|
|
4550
4703
|
init_assets();
|
|
4551
4704
|
ENHANCE_MODEL = "claude-4-6-sonnet";
|
|
4552
|
-
MODEL_OVERRIDE =
|
|
4705
|
+
MODEL_OVERRIDE = {
|
|
4553
4706
|
model: ENHANCE_MODEL,
|
|
4554
4707
|
config: { reasoning: "false" }
|
|
4555
|
-
}
|
|
4708
|
+
};
|
|
4556
4709
|
SYSTEM_PROMPT = readAsset(
|
|
4557
4710
|
"subagents/designExpert/tools/images/enhance-image-prompt.md"
|
|
4558
4711
|
);
|
|
@@ -4589,11 +4742,14 @@ async function generateImageAssets(opts) {
|
|
|
4589
4742
|
config
|
|
4590
4743
|
}
|
|
4591
4744
|
});
|
|
4592
|
-
const url = await
|
|
4593
|
-
"
|
|
4594
|
-
|
|
4595
|
-
|
|
4596
|
-
|
|
4745
|
+
const url = await runMindstudioCli(["generate-image"], {
|
|
4746
|
+
outputKey: "imageUrl",
|
|
4747
|
+
jsonLogs: true,
|
|
4748
|
+
timeout: 2e5,
|
|
4749
|
+
onLog,
|
|
4750
|
+
stdin: step,
|
|
4751
|
+
caller: "designExpert"
|
|
4752
|
+
});
|
|
4597
4753
|
imageUrls = [url];
|
|
4598
4754
|
} else {
|
|
4599
4755
|
const steps = enhancedPrompts.map((prompt) => ({
|
|
@@ -4606,11 +4762,12 @@ async function generateImageAssets(opts) {
|
|
|
4606
4762
|
}
|
|
4607
4763
|
}
|
|
4608
4764
|
}));
|
|
4609
|
-
const batchResult = await
|
|
4765
|
+
const batchResult = await runMindstudioCli(["batch"], {
|
|
4610
4766
|
jsonLogs: true,
|
|
4611
4767
|
timeout: 2e5,
|
|
4612
4768
|
onLog,
|
|
4613
|
-
stdin: JSON.stringify(steps)
|
|
4769
|
+
stdin: JSON.stringify(steps),
|
|
4770
|
+
caller: "designExpert"
|
|
4614
4771
|
});
|
|
4615
4772
|
try {
|
|
4616
4773
|
const parsed = JSON.parse(batchResult);
|
|
@@ -4627,17 +4784,14 @@ async function generateImageAssets(opts) {
|
|
|
4627
4784
|
if (url.startsWith("Error")) {
|
|
4628
4785
|
return url;
|
|
4629
4786
|
}
|
|
4630
|
-
const result = await
|
|
4631
|
-
"
|
|
4632
|
-
|
|
4633
|
-
"
|
|
4634
|
-
|
|
4635
|
-
|
|
4636
|
-
"
|
|
4637
|
-
|
|
4638
|
-
"--no-meta"
|
|
4639
|
-
],
|
|
4640
|
-
{ timeout: 2e5, onLog }
|
|
4787
|
+
const result = await runMindstudioCli(
|
|
4788
|
+
["remove-background-from-image", "--image-url", url],
|
|
4789
|
+
{
|
|
4790
|
+
outputKey: "imageUrl",
|
|
4791
|
+
timeout: 2e5,
|
|
4792
|
+
onLog,
|
|
4793
|
+
caller: "designExpert"
|
|
4794
|
+
}
|
|
4641
4795
|
);
|
|
4642
4796
|
return result.startsWith("Error") ? url : result;
|
|
4643
4797
|
})
|
|
@@ -4673,7 +4827,7 @@ var ANALYZE_PROMPT;
|
|
|
4673
4827
|
var init_imageGenerator = __esm({
|
|
4674
4828
|
"src/subagents/designExpert/tools/images/imageGenerator.ts"() {
|
|
4675
4829
|
"use strict";
|
|
4676
|
-
|
|
4830
|
+
init_runMindstudioCli();
|
|
4677
4831
|
init_analyzeImage();
|
|
4678
4832
|
init_enhancePrompt();
|
|
4679
4833
|
ANALYZE_PROMPT = 'You are reviewing this image for a visual designer sourcing assets for a project. Describe: what the image depicts, the mood and color palette, how the lighting and composition work, any text present in the image, whether there are any issues (artifacts, distortions), and how it could be used in a layout for an app or website. Be concise and practical. Respond only with your analysis as Markdown (starting with the title "Asset Review") and absolutely no other text. Do not use emojis - use unicode if you need symbols.';
|
|
@@ -4833,12 +4987,12 @@ var init_tools3 = __esm({
|
|
|
4833
4987
|
});
|
|
4834
4988
|
|
|
4835
4989
|
// src/subagents/common/context.ts
|
|
4836
|
-
import
|
|
4990
|
+
import fs16 from "fs";
|
|
4837
4991
|
import path7 from "path";
|
|
4838
4992
|
function walkMdFiles2(dir, skip) {
|
|
4839
4993
|
const files = [];
|
|
4840
4994
|
try {
|
|
4841
|
-
for (const entry of
|
|
4995
|
+
for (const entry of fs16.readdirSync(dir, { withFileTypes: true })) {
|
|
4842
4996
|
const full = path7.join(dir, entry.name);
|
|
4843
4997
|
if (entry.isDirectory()) {
|
|
4844
4998
|
if (!skip?.has(entry.name)) {
|
|
@@ -4854,7 +5008,7 @@ function walkMdFiles2(dir, skip) {
|
|
|
4854
5008
|
}
|
|
4855
5009
|
function parseFrontmatter2(filePath) {
|
|
4856
5010
|
try {
|
|
4857
|
-
const content =
|
|
5011
|
+
const content = fs16.readFileSync(filePath, "utf-8");
|
|
4858
5012
|
const match = content.match(/^---\n([\s\S]*?)\n---/);
|
|
4859
5013
|
if (!match) {
|
|
4860
5014
|
return {};
|
|
@@ -4900,7 +5054,7 @@ function loadRoadmapIndex() {
|
|
|
4900
5054
|
const parts = [];
|
|
4901
5055
|
try {
|
|
4902
5056
|
const indexJson = JSON.parse(
|
|
4903
|
-
|
|
5057
|
+
fs16.readFileSync("src/roadmap/index.json", "utf-8")
|
|
4904
5058
|
);
|
|
4905
5059
|
if (indexJson.lanes?.length > 0) {
|
|
4906
5060
|
const laneLines = indexJson.lanes.map(
|
|
@@ -5008,7 +5162,7 @@ var init_context = __esm({
|
|
|
5008
5162
|
});
|
|
5009
5163
|
|
|
5010
5164
|
// src/subagents/designExpert/data/sampleCache.ts
|
|
5011
|
-
import
|
|
5165
|
+
import fs17 from "fs";
|
|
5012
5166
|
function generateIndices(poolSize, sampleSize) {
|
|
5013
5167
|
const n = Math.min(sampleSize, poolSize);
|
|
5014
5168
|
const indices = Array.from({ length: poolSize }, (_, i) => i);
|
|
@@ -5020,14 +5174,14 @@ function generateIndices(poolSize, sampleSize) {
|
|
|
5020
5174
|
}
|
|
5021
5175
|
function load() {
|
|
5022
5176
|
try {
|
|
5023
|
-
return JSON.parse(
|
|
5177
|
+
return JSON.parse(fs17.readFileSync(SAMPLE_FILE, "utf-8"));
|
|
5024
5178
|
} catch {
|
|
5025
5179
|
return null;
|
|
5026
5180
|
}
|
|
5027
5181
|
}
|
|
5028
5182
|
function save(indices) {
|
|
5029
5183
|
try {
|
|
5030
|
-
|
|
5184
|
+
fs17.writeFileSync(SAMPLE_FILE, JSON.stringify(indices));
|
|
5031
5185
|
} catch {
|
|
5032
5186
|
}
|
|
5033
5187
|
}
|
|
@@ -5424,7 +5578,7 @@ var init_tools4 = __esm({
|
|
|
5424
5578
|
});
|
|
5425
5579
|
|
|
5426
5580
|
// src/subagents/productVision/executor.ts
|
|
5427
|
-
import
|
|
5581
|
+
import fs18 from "fs";
|
|
5428
5582
|
import path8 from "path";
|
|
5429
5583
|
function resolve(filePath) {
|
|
5430
5584
|
return path8.join(ROADMAP_DIR, filePath);
|
|
@@ -5434,13 +5588,13 @@ async function executeVisionTool(name, input, context) {
|
|
|
5434
5588
|
case "writeFile": {
|
|
5435
5589
|
const filePath = resolve(input.path);
|
|
5436
5590
|
try {
|
|
5437
|
-
|
|
5591
|
+
fs18.mkdirSync(ROADMAP_DIR, { recursive: true });
|
|
5438
5592
|
let oldContent = null;
|
|
5439
5593
|
try {
|
|
5440
|
-
oldContent =
|
|
5594
|
+
oldContent = fs18.readFileSync(filePath, "utf-8");
|
|
5441
5595
|
} catch {
|
|
5442
5596
|
}
|
|
5443
|
-
|
|
5597
|
+
fs18.writeFileSync(filePath, input.content, "utf-8");
|
|
5444
5598
|
const lineCount = input.content.split("\n").length;
|
|
5445
5599
|
const label = oldContent !== null ? "Wrote" : "Created";
|
|
5446
5600
|
return `${label} ${filePath} (${lineCount} lines)
|
|
@@ -5452,11 +5606,11 @@ ${unifiedDiff(filePath, oldContent ?? "", input.content)}`;
|
|
|
5452
5606
|
case "deleteFile": {
|
|
5453
5607
|
const filePath = resolve(input.path);
|
|
5454
5608
|
try {
|
|
5455
|
-
if (!
|
|
5609
|
+
if (!fs18.existsSync(filePath)) {
|
|
5456
5610
|
return `Error: ${filePath} does not exist`;
|
|
5457
5611
|
}
|
|
5458
|
-
const oldContent =
|
|
5459
|
-
|
|
5612
|
+
const oldContent = fs18.readFileSync(filePath, "utf-8");
|
|
5613
|
+
fs18.unlinkSync(filePath);
|
|
5460
5614
|
return `Deleted ${filePath}
|
|
5461
5615
|
${unifiedDiff(filePath, oldContent, "")}`;
|
|
5462
5616
|
} catch (err) {
|
|
@@ -5469,8 +5623,8 @@ ${unifiedDiff(filePath, oldContent, "")}`;
|
|
|
5469
5623
|
}
|
|
5470
5624
|
const filePath = resolve("pitch.html");
|
|
5471
5625
|
try {
|
|
5472
|
-
|
|
5473
|
-
const existing =
|
|
5626
|
+
fs18.mkdirSync(ROADMAP_DIR, { recursive: true });
|
|
5627
|
+
const existing = fs18.existsSync(filePath) ? fs18.readFileSync(filePath, "utf-8").trim() : "";
|
|
5474
5628
|
const currentDeck = existing || PITCH_DECK_SHELL;
|
|
5475
5629
|
const task = `
|
|
5476
5630
|
<pitch_content>${input.task}</pitch_content>
|
|
@@ -5495,7 +5649,7 @@ Respond only with the complete HTML file and absolutely no other text. Your resp
|
|
|
5495
5649
|
/```(?:html|wireframe)\n([\s\S]*?)```/
|
|
5496
5650
|
);
|
|
5497
5651
|
const html = htmlMatch ? htmlMatch[1].trim() : result;
|
|
5498
|
-
|
|
5652
|
+
fs18.writeFileSync(filePath, html, "utf-8");
|
|
5499
5653
|
return `Pitch deck written successfully.`;
|
|
5500
5654
|
} catch (err) {
|
|
5501
5655
|
return `Error generating pitch deck: ${err.message}`;
|
|
@@ -5744,7 +5898,7 @@ var scrapeWebUrlTool;
|
|
|
5744
5898
|
var init_scrapeWebUrl2 = __esm({
|
|
5745
5899
|
"src/tools/common/scrapeWebUrl.ts"() {
|
|
5746
5900
|
"use strict";
|
|
5747
|
-
|
|
5901
|
+
init_runMindstudioCli();
|
|
5748
5902
|
scrapeWebUrlTool = {
|
|
5749
5903
|
clearable: false,
|
|
5750
5904
|
definition: {
|
|
@@ -5772,15 +5926,13 @@ var init_scrapeWebUrl2 = __esm({
|
|
|
5772
5926
|
if (screenshot) {
|
|
5773
5927
|
pageOptions.screenshot = true;
|
|
5774
5928
|
}
|
|
5775
|
-
return
|
|
5776
|
-
"mindstudio",
|
|
5929
|
+
return runMindstudioCli(
|
|
5777
5930
|
[
|
|
5778
5931
|
"scrape-url",
|
|
5779
5932
|
"--url",
|
|
5780
5933
|
url,
|
|
5781
5934
|
"--page-options",
|
|
5782
|
-
JSON.stringify(pageOptions)
|
|
5783
|
-
"--no-meta"
|
|
5935
|
+
JSON.stringify(pageOptions)
|
|
5784
5936
|
],
|
|
5785
5937
|
{ onLog: context?.onLog }
|
|
5786
5938
|
);
|
|
@@ -5890,10 +6042,11 @@ var init_tools6 = __esm({
|
|
|
5890
6042
|
});
|
|
5891
6043
|
|
|
5892
6044
|
// src/session.ts
|
|
5893
|
-
import
|
|
6045
|
+
import fs19 from "fs";
|
|
6046
|
+
import path9 from "path";
|
|
5894
6047
|
function loadSession(state) {
|
|
5895
6048
|
try {
|
|
5896
|
-
const raw =
|
|
6049
|
+
const raw = fs19.readFileSync(SESSION_FILE, "utf-8");
|
|
5897
6050
|
const data = JSON.parse(raw);
|
|
5898
6051
|
if (Array.isArray(data.messages) && data.messages.length > 0) {
|
|
5899
6052
|
state.messages = sanitizeMessages(data.messages);
|
|
@@ -5942,7 +6095,7 @@ function sanitizeMessages(messages) {
|
|
|
5942
6095
|
}
|
|
5943
6096
|
function saveSession(state) {
|
|
5944
6097
|
try {
|
|
5945
|
-
|
|
6098
|
+
fs19.writeFileSync(
|
|
5946
6099
|
SESSION_FILE,
|
|
5947
6100
|
JSON.stringify({ messages: state.messages }, null, 2),
|
|
5948
6101
|
"utf-8"
|
|
@@ -5955,17 +6108,31 @@ function saveSession(state) {
|
|
|
5955
6108
|
function clearSession(state) {
|
|
5956
6109
|
state.messages = [];
|
|
5957
6110
|
try {
|
|
5958
|
-
|
|
5959
|
-
|
|
6111
|
+
if (fs19.existsSync(SESSION_FILE)) {
|
|
6112
|
+
fs19.mkdirSync(ARCHIVE_DIR, { recursive: true });
|
|
6113
|
+
const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
6114
|
+
const dest = path9.join(ARCHIVE_DIR, `cleared-${ts}.json`);
|
|
6115
|
+
fs19.renameSync(SESSION_FILE, dest);
|
|
6116
|
+
log7.info("Session archived on clear", { dest });
|
|
6117
|
+
}
|
|
6118
|
+
} catch (err) {
|
|
6119
|
+
log7.warn("Session archive on clear failed, deleting instead", {
|
|
6120
|
+
error: err.message
|
|
6121
|
+
});
|
|
6122
|
+
try {
|
|
6123
|
+
fs19.unlinkSync(SESSION_FILE);
|
|
6124
|
+
} catch {
|
|
6125
|
+
}
|
|
5960
6126
|
}
|
|
5961
6127
|
}
|
|
5962
|
-
var log7, SESSION_FILE;
|
|
6128
|
+
var log7, SESSION_FILE, ARCHIVE_DIR;
|
|
5963
6129
|
var init_session = __esm({
|
|
5964
6130
|
"src/session.ts"() {
|
|
5965
6131
|
"use strict";
|
|
5966
6132
|
init_logger();
|
|
5967
6133
|
log7 = createLogger("session");
|
|
5968
6134
|
SESSION_FILE = ".remy-session.json";
|
|
6135
|
+
ARCHIVE_DIR = ".logs/sessions";
|
|
5969
6136
|
}
|
|
5970
6137
|
});
|
|
5971
6138
|
|
|
@@ -6175,8 +6342,8 @@ var init_errors = __esm({
|
|
|
6175
6342
|
});
|
|
6176
6343
|
|
|
6177
6344
|
// src/brandExtraction/index.ts
|
|
6178
|
-
import
|
|
6179
|
-
import
|
|
6345
|
+
import fs20 from "fs";
|
|
6346
|
+
import path10 from "path";
|
|
6180
6347
|
import { createHash } from "crypto";
|
|
6181
6348
|
async function runExtraction(apiConfig) {
|
|
6182
6349
|
const inputHash = computeInputHash();
|
|
@@ -6198,7 +6365,7 @@ async function runExtraction(apiConfig) {
|
|
|
6198
6365
|
function computeInputHash() {
|
|
6199
6366
|
const entries = [];
|
|
6200
6367
|
for (const filePath of walkMdFiles3("src")) {
|
|
6201
|
-
if (filePath ===
|
|
6368
|
+
if (filePath === path10.join("src", "app.md")) {
|
|
6202
6369
|
entries.push({ path: filePath, content: readSafe(filePath) });
|
|
6203
6370
|
continue;
|
|
6204
6371
|
}
|
|
@@ -6220,7 +6387,7 @@ function sha256(input) {
|
|
|
6220
6387
|
}
|
|
6221
6388
|
function readSafe(filePath) {
|
|
6222
6389
|
try {
|
|
6223
|
-
return
|
|
6390
|
+
return fs20.readFileSync(filePath, "utf-8");
|
|
6224
6391
|
} catch {
|
|
6225
6392
|
return "";
|
|
6226
6393
|
}
|
|
@@ -6228,9 +6395,9 @@ function readSafe(filePath) {
|
|
|
6228
6395
|
function walkMdFiles3(dir) {
|
|
6229
6396
|
const results = [];
|
|
6230
6397
|
try {
|
|
6231
|
-
const entries =
|
|
6398
|
+
const entries = fs20.readdirSync(dir, { withFileTypes: true });
|
|
6232
6399
|
for (const entry of entries) {
|
|
6233
|
-
const full =
|
|
6400
|
+
const full = path10.join(dir, entry.name);
|
|
6234
6401
|
if (entry.isDirectory()) {
|
|
6235
6402
|
results.push(...walkMdFiles3(full));
|
|
6236
6403
|
} else if (entry.name.endsWith(".md")) {
|
|
@@ -6243,7 +6410,7 @@ function walkMdFiles3(dir) {
|
|
|
6243
6410
|
}
|
|
6244
6411
|
function parseFrontmatter3(filePath) {
|
|
6245
6412
|
try {
|
|
6246
|
-
const content =
|
|
6413
|
+
const content = fs20.readFileSync(filePath, "utf-8");
|
|
6247
6414
|
const match = content.match(/^---\n([\s\S]*?)\n---/);
|
|
6248
6415
|
if (!match) {
|
|
6249
6416
|
return { type: "" };
|
|
@@ -6262,6 +6429,7 @@ async function extractBrand(apiConfig) {
|
|
|
6262
6429
|
return { version: 1 };
|
|
6263
6430
|
}
|
|
6264
6431
|
let responseText = "";
|
|
6432
|
+
const iterStart = Date.now();
|
|
6265
6433
|
try {
|
|
6266
6434
|
for await (const event of streamChat({
|
|
6267
6435
|
...apiConfig,
|
|
@@ -6272,6 +6440,20 @@ async function extractBrand(apiConfig) {
|
|
|
6272
6440
|
})) {
|
|
6273
6441
|
if (event.type === "text") {
|
|
6274
6442
|
responseText += event.text;
|
|
6443
|
+
} else if (event.type === "done") {
|
|
6444
|
+
recordUsage({
|
|
6445
|
+
ts: Date.now(),
|
|
6446
|
+
agentName: "brandExtractor",
|
|
6447
|
+
modelId: event.modelId,
|
|
6448
|
+
inputTokens: event.usage.inputTokens,
|
|
6449
|
+
outputTokens: event.usage.outputTokens,
|
|
6450
|
+
cacheCreationTokens: event.usage.cacheCreationTokens,
|
|
6451
|
+
cacheReadTokens: event.usage.cacheReadTokens,
|
|
6452
|
+
cost: nanoToDollars(event.cost),
|
|
6453
|
+
billingEvents: event.billingEvents,
|
|
6454
|
+
durationMs: Date.now() - iterStart,
|
|
6455
|
+
toolNames: []
|
|
6456
|
+
});
|
|
6275
6457
|
} else if (event.type === "error") {
|
|
6276
6458
|
log8.error("Brand extraction stream error", { error: event.error });
|
|
6277
6459
|
return null;
|
|
@@ -6406,14 +6588,14 @@ function pickFont(raw) {
|
|
|
6406
6588
|
}
|
|
6407
6589
|
function persistBrand(brand, inputHash) {
|
|
6408
6590
|
const tmp = `${BRAND_FILE}.tmp`;
|
|
6409
|
-
|
|
6410
|
-
|
|
6591
|
+
fs20.writeFileSync(tmp, JSON.stringify(brand, null, 2), "utf-8");
|
|
6592
|
+
fs20.renameSync(tmp, BRAND_FILE);
|
|
6411
6593
|
const cache = { inputHash, generatedAt: Date.now() };
|
|
6412
|
-
|
|
6594
|
+
fs20.writeFileSync(CACHE_FILE, JSON.stringify(cache, null, 2), "utf-8");
|
|
6413
6595
|
}
|
|
6414
6596
|
function readCache() {
|
|
6415
6597
|
try {
|
|
6416
|
-
const raw =
|
|
6598
|
+
const raw = fs20.readFileSync(CACHE_FILE, "utf-8");
|
|
6417
6599
|
const parsed = JSON.parse(raw);
|
|
6418
6600
|
if (parsed && typeof parsed.inputHash === "string" && typeof parsed.generatedAt === "number") {
|
|
6419
6601
|
return parsed;
|
|
@@ -6430,6 +6612,7 @@ var init_brandExtraction = __esm({
|
|
|
6430
6612
|
init_api();
|
|
6431
6613
|
init_assets();
|
|
6432
6614
|
init_logger();
|
|
6615
|
+
init_usageLedger();
|
|
6433
6616
|
log8 = createLogger("brandExtraction");
|
|
6434
6617
|
EXTRACT_PROMPT = readAsset("brandExtraction", "extract.md");
|
|
6435
6618
|
BRAND_FILE = ".remy-brand.json";
|
|
@@ -6561,9 +6744,11 @@ async function runTurn(params) {
|
|
|
6561
6744
|
saveSession(state);
|
|
6562
6745
|
return;
|
|
6563
6746
|
}
|
|
6747
|
+
const iterStart = Date.now();
|
|
6564
6748
|
const contentBlocks = [];
|
|
6565
6749
|
const thinkingBlockStartTimes = [];
|
|
6566
6750
|
let thinkingCompleteCount = 0;
|
|
6751
|
+
let lastThinkingRelatedStartedAt;
|
|
6567
6752
|
let textBlockOpen = false;
|
|
6568
6753
|
const toolInputAccumulators = /* @__PURE__ */ new Map();
|
|
6569
6754
|
let stopReason = "end_turn";
|
|
@@ -6695,16 +6880,30 @@ async function runTurn(params) {
|
|
|
6695
6880
|
}
|
|
6696
6881
|
onEvent({ type: "thinking", text: event.text });
|
|
6697
6882
|
break;
|
|
6698
|
-
case "thinking_complete":
|
|
6883
|
+
case "thinking_complete": {
|
|
6884
|
+
const startedAt = thinkingBlockStartTimes[thinkingCompleteCount] ?? event.ts;
|
|
6699
6885
|
contentBlocks.push({
|
|
6700
6886
|
type: "thinking",
|
|
6701
6887
|
thinking: event.thinking,
|
|
6702
6888
|
signature: event.signature,
|
|
6703
|
-
startedAt
|
|
6889
|
+
startedAt,
|
|
6704
6890
|
completedAt: event.ts
|
|
6705
6891
|
});
|
|
6706
6892
|
thinkingCompleteCount++;
|
|
6893
|
+
lastThinkingRelatedStartedAt = startedAt;
|
|
6894
|
+
break;
|
|
6895
|
+
}
|
|
6896
|
+
case "redacted_thinking_complete": {
|
|
6897
|
+
const startedAt = lastThinkingRelatedStartedAt !== void 0 ? lastThinkingRelatedStartedAt + 1 : event.ts;
|
|
6898
|
+
contentBlocks.push({
|
|
6899
|
+
type: "redacted_thinking",
|
|
6900
|
+
data: event.data,
|
|
6901
|
+
startedAt,
|
|
6902
|
+
completedAt: event.ts
|
|
6903
|
+
});
|
|
6904
|
+
lastThinkingRelatedStartedAt = startedAt;
|
|
6707
6905
|
break;
|
|
6906
|
+
}
|
|
6708
6907
|
case "tool_input_delta": {
|
|
6709
6908
|
const acc = getOrCreateAccumulator2(event.id, event.name);
|
|
6710
6909
|
acc.json += event.delta;
|
|
@@ -6758,6 +6957,22 @@ async function runTurn(params) {
|
|
|
6758
6957
|
turnOutputTokens += event.usage.outputTokens;
|
|
6759
6958
|
turnCacheCreation += lastCallCacheCreation;
|
|
6760
6959
|
turnCacheRead += lastCallCacheRead;
|
|
6960
|
+
recordUsage({
|
|
6961
|
+
ts: Date.now(),
|
|
6962
|
+
requestId,
|
|
6963
|
+
agentName: "parent",
|
|
6964
|
+
modelId: event.modelId,
|
|
6965
|
+
inputTokens: event.usage.inputTokens,
|
|
6966
|
+
outputTokens: event.usage.outputTokens,
|
|
6967
|
+
cacheCreationTokens: event.usage.cacheCreationTokens,
|
|
6968
|
+
cacheReadTokens: event.usage.cacheReadTokens,
|
|
6969
|
+
cost: nanoToDollars(event.cost),
|
|
6970
|
+
billingEvents: event.billingEvents,
|
|
6971
|
+
durationMs: Date.now() - iterStart,
|
|
6972
|
+
toolNames: contentBlocks.filter(
|
|
6973
|
+
(b) => b.type === "tool"
|
|
6974
|
+
).map((b) => b.name)
|
|
6975
|
+
});
|
|
6761
6976
|
break;
|
|
6762
6977
|
case "error":
|
|
6763
6978
|
onEvent({ type: "error", error: friendlyError(event.error) });
|
|
@@ -7004,6 +7219,7 @@ var init_agent = __esm({
|
|
|
7004
7219
|
init_tools6();
|
|
7005
7220
|
init_session();
|
|
7006
7221
|
init_logger();
|
|
7222
|
+
init_usageLedger();
|
|
7007
7223
|
init_parsePartialJson();
|
|
7008
7224
|
init_statusWatcher();
|
|
7009
7225
|
init_errors();
|
|
@@ -7033,12 +7249,12 @@ var init_agent = __esm({
|
|
|
7033
7249
|
});
|
|
7034
7250
|
|
|
7035
7251
|
// src/config.ts
|
|
7036
|
-
import
|
|
7037
|
-
import
|
|
7252
|
+
import fs21 from "fs";
|
|
7253
|
+
import path11 from "path";
|
|
7038
7254
|
import os from "os";
|
|
7039
7255
|
function loadConfigFile() {
|
|
7040
7256
|
try {
|
|
7041
|
-
const raw =
|
|
7257
|
+
const raw = fs21.readFileSync(CONFIG_PATH, "utf-8");
|
|
7042
7258
|
log11.debug("Loaded config file", { path: CONFIG_PATH });
|
|
7043
7259
|
return JSON.parse(raw);
|
|
7044
7260
|
} catch (err) {
|
|
@@ -7055,6 +7271,7 @@ function resolveConfig(flags2) {
|
|
|
7055
7271
|
const env = file.environments?.[activeEnv];
|
|
7056
7272
|
const apiKey = flags2?.apiKey || process.env.MINDSTUDIO_API_KEY || env?.apiKey || "";
|
|
7057
7273
|
const baseUrl2 = flags2?.baseUrl || process.env.MINDSTUDIO_BASE_URL || env?.apiBaseUrl || DEFAULT_BASE_URL;
|
|
7274
|
+
const appId = process.env.MINDSTUDIO_APP_ID || void 0;
|
|
7058
7275
|
if (!apiKey) {
|
|
7059
7276
|
log11.error("No API key found");
|
|
7060
7277
|
throw new Error(
|
|
@@ -7065,9 +7282,10 @@ function resolveConfig(flags2) {
|
|
|
7065
7282
|
log11.info("Config resolved", {
|
|
7066
7283
|
baseUrl: baseUrl2,
|
|
7067
7284
|
keySource,
|
|
7068
|
-
environment: activeEnv
|
|
7285
|
+
environment: activeEnv,
|
|
7286
|
+
appId
|
|
7069
7287
|
});
|
|
7070
|
-
return { apiKey, baseUrl: baseUrl2 };
|
|
7288
|
+
return { apiKey, baseUrl: baseUrl2, appId };
|
|
7071
7289
|
}
|
|
7072
7290
|
var log11, CONFIG_PATH, DEFAULT_BASE_URL;
|
|
7073
7291
|
var init_config = __esm({
|
|
@@ -7075,7 +7293,7 @@ var init_config = __esm({
|
|
|
7075
7293
|
"use strict";
|
|
7076
7294
|
init_logger();
|
|
7077
7295
|
log11 = createLogger("config");
|
|
7078
|
-
CONFIG_PATH =
|
|
7296
|
+
CONFIG_PATH = path11.join(
|
|
7079
7297
|
os.homedir(),
|
|
7080
7298
|
".mindstudio-local-tunnel",
|
|
7081
7299
|
"config.json"
|
|
@@ -8321,8 +8539,8 @@ var init_headless = __esm({
|
|
|
8321
8539
|
// src/index.tsx
|
|
8322
8540
|
import { render } from "ink";
|
|
8323
8541
|
import os2 from "os";
|
|
8324
|
-
import
|
|
8325
|
-
import
|
|
8542
|
+
import fs22 from "fs";
|
|
8543
|
+
import path12 from "path";
|
|
8326
8544
|
|
|
8327
8545
|
// src/tui/App.tsx
|
|
8328
8546
|
import { useState as useState2, useCallback, useRef } from "react";
|
|
@@ -8640,8 +8858,8 @@ for (let i = 0; i < args.length; i++) {
|
|
|
8640
8858
|
var startupLog = createLogger("startup");
|
|
8641
8859
|
function printDebugInfo(config) {
|
|
8642
8860
|
const pkg = JSON.parse(
|
|
8643
|
-
|
|
8644
|
-
|
|
8861
|
+
fs22.readFileSync(
|
|
8862
|
+
path12.join(import.meta.dirname, "..", "package.json"),
|
|
8645
8863
|
"utf-8"
|
|
8646
8864
|
)
|
|
8647
8865
|
);
|