@mindstudio-ai/remy 0.1.342 → 0.1.344
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/README.md +13 -6
- package/dist/headless.js +145 -165
- package/dist/index.js +145 -165
- package/dist/prompt/compiled/sdk-actions.md +1 -1
- package/package.json +1 -1
package/dist/headless.js
CHANGED
|
@@ -5,9 +5,9 @@ var __export = (target, all) => {
|
|
|
5
5
|
};
|
|
6
6
|
|
|
7
7
|
// src/headless/index.ts
|
|
8
|
-
import
|
|
9
|
-
import
|
|
10
|
-
import
|
|
8
|
+
import os from "os";
|
|
9
|
+
import fs21 from "fs";
|
|
10
|
+
import path12 from "path";
|
|
11
11
|
|
|
12
12
|
// src/logger.ts
|
|
13
13
|
var LEVELS = {
|
|
@@ -58,49 +58,20 @@ function createLogger(module) {
|
|
|
58
58
|
}
|
|
59
59
|
|
|
60
60
|
// src/config.ts
|
|
61
|
-
import fs from "fs";
|
|
62
|
-
import path from "path";
|
|
63
|
-
import os from "os";
|
|
64
61
|
var log = createLogger("config");
|
|
65
|
-
var CONFIG_PATH = path.join(
|
|
66
|
-
os.homedir(),
|
|
67
|
-
".mindstudio-local-tunnel",
|
|
68
|
-
"config.json"
|
|
69
|
-
);
|
|
70
62
|
var DEFAULT_BASE_URL = "https://api.mindstudio.ai";
|
|
71
|
-
function loadConfigFile() {
|
|
72
|
-
try {
|
|
73
|
-
const raw = fs.readFileSync(CONFIG_PATH, "utf-8");
|
|
74
|
-
log.debug("Loaded config file", { path: CONFIG_PATH });
|
|
75
|
-
return JSON.parse(raw);
|
|
76
|
-
} catch (err) {
|
|
77
|
-
log.debug("No config file found", {
|
|
78
|
-
path: CONFIG_PATH,
|
|
79
|
-
error: err.message
|
|
80
|
-
});
|
|
81
|
-
return {};
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
63
|
function resolveConfig(flags) {
|
|
85
|
-
const
|
|
86
|
-
const
|
|
87
|
-
const env = file.environments?.[activeEnv];
|
|
88
|
-
const apiKey = flags?.apiKey || process.env.MINDSTUDIO_API_KEY || env?.apiKey || "";
|
|
89
|
-
const baseUrl2 = flags?.baseUrl || process.env.MINDSTUDIO_BASE_URL || env?.apiBaseUrl || DEFAULT_BASE_URL;
|
|
64
|
+
const apiKey = flags?.apiKey || process.env.MINDSTUDIO_API_KEY || "";
|
|
65
|
+
const baseUrl2 = flags?.baseUrl || process.env.MINDSTUDIO_BASE_URL || DEFAULT_BASE_URL;
|
|
90
66
|
const appId = process.env.MINDSTUDIO_APP_ID || void 0;
|
|
91
67
|
if (!apiKey) {
|
|
92
68
|
log.error("No API key found");
|
|
93
69
|
throw new Error(
|
|
94
|
-
"No API key found.
|
|
70
|
+
"No API key found. Pass --api-key or set MINDSTUDIO_API_KEY. Inside a dev box the C&C server sets it when it spawns this process."
|
|
95
71
|
);
|
|
96
72
|
}
|
|
97
|
-
const keySource = flags?.apiKey ? "cli flag" :
|
|
98
|
-
log.info("Config resolved", {
|
|
99
|
-
baseUrl: baseUrl2,
|
|
100
|
-
keySource,
|
|
101
|
-
environment: activeEnv,
|
|
102
|
-
appId
|
|
103
|
-
});
|
|
73
|
+
const keySource = flags?.apiKey ? "cli flag" : "env var";
|
|
74
|
+
log.info("Config resolved", { baseUrl: baseUrl2, keySource, appId });
|
|
104
75
|
return { apiKey, baseUrl: baseUrl2, appId };
|
|
105
76
|
}
|
|
106
77
|
|
|
@@ -777,16 +748,16 @@ async function initModelRegistry(config) {
|
|
|
777
748
|
}
|
|
778
749
|
|
|
779
750
|
// src/assets.ts
|
|
780
|
-
import
|
|
781
|
-
import
|
|
782
|
-
var ASSETS_BASE = import.meta.dirname ??
|
|
751
|
+
import fs from "fs";
|
|
752
|
+
import path from "path";
|
|
753
|
+
var ASSETS_BASE = import.meta.dirname ?? path.dirname(new URL(import.meta.url).pathname);
|
|
783
754
|
function assetPath(...segments) {
|
|
784
|
-
return
|
|
755
|
+
return path.join(ASSETS_BASE, ...segments);
|
|
785
756
|
}
|
|
786
757
|
function readAsset(...segments) {
|
|
787
758
|
const full = assetPath(...segments);
|
|
788
759
|
try {
|
|
789
|
-
return
|
|
760
|
+
return fs.readFileSync(full, "utf-8").trim();
|
|
790
761
|
} catch {
|
|
791
762
|
throw new Error(`Required asset missing: ${full}`);
|
|
792
763
|
}
|
|
@@ -794,14 +765,14 @@ function readAsset(...segments) {
|
|
|
794
765
|
function readJsonAsset(fallback, ...segments) {
|
|
795
766
|
const full = assetPath(...segments);
|
|
796
767
|
try {
|
|
797
|
-
return JSON.parse(
|
|
768
|
+
return JSON.parse(fs.readFileSync(full, "utf-8"));
|
|
798
769
|
} catch {
|
|
799
770
|
return fallback;
|
|
800
771
|
}
|
|
801
772
|
}
|
|
802
773
|
|
|
803
774
|
// src/prompt/static/projectContext.ts
|
|
804
|
-
import
|
|
775
|
+
import fs2 from "fs";
|
|
805
776
|
|
|
806
777
|
// src/projectRoot.ts
|
|
807
778
|
var PROJECT_ROOT = process.cwd();
|
|
@@ -816,7 +787,7 @@ File paths are relative to this directory. Every tool operates here and bash com
|
|
|
816
787
|
}
|
|
817
788
|
function loadAppIdentity() {
|
|
818
789
|
try {
|
|
819
|
-
const manifest = JSON.parse(
|
|
790
|
+
const manifest = JSON.parse(fs2.readFileSync("mindstudio.json", "utf-8"));
|
|
820
791
|
const name = typeof manifest.name === "string" ? manifest.name.trim() : "";
|
|
821
792
|
if (!name) {
|
|
822
793
|
return "";
|
|
@@ -833,7 +804,7 @@ Full manifest: \`mindstudio.json\` (read it when you need the app's structure, t
|
|
|
833
804
|
}
|
|
834
805
|
function loadPlanStatus(onboardingState) {
|
|
835
806
|
try {
|
|
836
|
-
const content =
|
|
807
|
+
const content = fs2.readFileSync(".remy-plan.md", "utf-8");
|
|
837
808
|
const match = content.match(/^---\n([\s\S]*?)\n---/);
|
|
838
809
|
const status = match?.[1]?.match(/^status:\s*(.+)$/m)?.[1]?.trim();
|
|
839
810
|
if (status === "pending" && onboardingState === "intake") {
|
|
@@ -861,8 +832,8 @@ The user has approved your implementation plan in .remy-plan.md. You may referen
|
|
|
861
832
|
}
|
|
862
833
|
|
|
863
834
|
// src/skillCatalog.ts
|
|
864
|
-
import
|
|
865
|
-
import
|
|
835
|
+
import fs3 from "fs";
|
|
836
|
+
import path2 from "path";
|
|
866
837
|
function parseFrontmatter(content) {
|
|
867
838
|
const match = content.match(/^---\n([\s\S]*?)\n---/);
|
|
868
839
|
if (!match) {
|
|
@@ -880,15 +851,15 @@ function parseFrontmatter(content) {
|
|
|
880
851
|
function buildSkillCatalog(opts) {
|
|
881
852
|
let files;
|
|
882
853
|
try {
|
|
883
|
-
files =
|
|
854
|
+
files = fs3.readdirSync(opts.dir).filter((f) => f.endsWith(".md"));
|
|
884
855
|
} catch {
|
|
885
856
|
files = [];
|
|
886
857
|
}
|
|
887
858
|
const skills = [];
|
|
888
859
|
for (const file of files.sort()) {
|
|
889
|
-
const full =
|
|
860
|
+
const full = path2.join(opts.dir, file);
|
|
890
861
|
const id = file.replace(/\.md$/, "");
|
|
891
|
-
const fields = parseFrontmatter(
|
|
862
|
+
const fields = parseFrontmatter(fs3.readFileSync(full, "utf-8"));
|
|
892
863
|
if (!fields.name || !fields.what || !fields.when) {
|
|
893
864
|
continue;
|
|
894
865
|
}
|
|
@@ -907,7 +878,7 @@ function buildSkillCatalog(opts) {
|
|
|
907
878
|
return skills.find((s) => s.id === id);
|
|
908
879
|
},
|
|
909
880
|
readBody(skill) {
|
|
910
|
-
return
|
|
881
|
+
return fs3.readFileSync(skill.path, "utf-8").replace(/^---[\s\S]*?---\s*/, "").trim();
|
|
911
882
|
},
|
|
912
883
|
renderCatalogBlock() {
|
|
913
884
|
if (skills.length === 0) {
|
|
@@ -1179,7 +1150,7 @@ function mergeBackgroundResultsMessages(messages) {
|
|
|
1179
1150
|
}
|
|
1180
1151
|
|
|
1181
1152
|
// src/tools/spec/readSpec.ts
|
|
1182
|
-
import
|
|
1153
|
+
import fs4 from "fs/promises";
|
|
1183
1154
|
|
|
1184
1155
|
// src/tools/spec/_helpers.ts
|
|
1185
1156
|
function validateSpecPath(filePath) {
|
|
@@ -1233,7 +1204,7 @@ var readSpecTool = {
|
|
|
1233
1204
|
return `Error: ${err.message}`;
|
|
1234
1205
|
}
|
|
1235
1206
|
try {
|
|
1236
|
-
const content = await
|
|
1207
|
+
const content = await fs4.readFile(input.path, "utf-8");
|
|
1237
1208
|
const allLines = content.split("\n");
|
|
1238
1209
|
const totalLines = allLines.length;
|
|
1239
1210
|
const maxLines = input.maxLines === 0 ? Infinity : input.maxLines || DEFAULT_MAX_LINES;
|
|
@@ -1261,8 +1232,8 @@ var readSpecTool = {
|
|
|
1261
1232
|
};
|
|
1262
1233
|
|
|
1263
1234
|
// src/tools/spec/writeSpec.ts
|
|
1264
|
-
import
|
|
1265
|
-
import
|
|
1235
|
+
import fs5 from "fs/promises";
|
|
1236
|
+
import path3 from "path";
|
|
1266
1237
|
|
|
1267
1238
|
// src/tools/_helpers/diff.ts
|
|
1268
1239
|
var CONTEXT_LINES = 3;
|
|
@@ -1337,7 +1308,7 @@ var writeSpecTool = {
|
|
|
1337
1308
|
},
|
|
1338
1309
|
streaming: {
|
|
1339
1310
|
transform: async (partial) => {
|
|
1340
|
-
const oldContent = await
|
|
1311
|
+
const oldContent = await fs5.readFile(partial.path, "utf-8").catch(() => "");
|
|
1341
1312
|
const lineCount = partial.content.split("\n").length;
|
|
1342
1313
|
return `Writing ${partial.path} (${lineCount} lines)
|
|
1343
1314
|
${unifiedDiff(partial.path, oldContent, partial.content)}`;
|
|
@@ -1351,13 +1322,13 @@ ${unifiedDiff(partial.path, oldContent, partial.content)}`;
|
|
|
1351
1322
|
}
|
|
1352
1323
|
const release = await acquireFileLock(input.path);
|
|
1353
1324
|
try {
|
|
1354
|
-
await
|
|
1325
|
+
await fs5.mkdir(path3.dirname(input.path), { recursive: true });
|
|
1355
1326
|
let oldContent = null;
|
|
1356
1327
|
try {
|
|
1357
|
-
oldContent = await
|
|
1328
|
+
oldContent = await fs5.readFile(input.path, "utf-8");
|
|
1358
1329
|
} catch {
|
|
1359
1330
|
}
|
|
1360
|
-
await
|
|
1331
|
+
await fs5.writeFile(input.path, input.content, "utf-8");
|
|
1361
1332
|
const lineCount = input.content.split("\n").length;
|
|
1362
1333
|
const label = oldContent !== null ? "Wrote" : "Created";
|
|
1363
1334
|
return `${label} ${input.path} (${lineCount} lines)
|
|
@@ -1371,7 +1342,7 @@ ${unifiedDiff(input.path, oldContent ?? "", input.content)}`;
|
|
|
1371
1342
|
};
|
|
1372
1343
|
|
|
1373
1344
|
// src/tools/spec/editSpec.ts
|
|
1374
|
-
import
|
|
1345
|
+
import fs6 from "fs/promises";
|
|
1375
1346
|
|
|
1376
1347
|
// src/tools/code/editFile/_helpers.ts
|
|
1377
1348
|
function buildLineOffsets(content) {
|
|
@@ -1490,7 +1461,7 @@ var editSpecTool = {
|
|
|
1490
1461
|
try {
|
|
1491
1462
|
let content;
|
|
1492
1463
|
try {
|
|
1493
|
-
content = await
|
|
1464
|
+
content = await fs6.readFile(input.path, "utf-8");
|
|
1494
1465
|
} catch (err) {
|
|
1495
1466
|
return `Error reading file: ${err.message}`;
|
|
1496
1467
|
}
|
|
@@ -1543,7 +1514,7 @@ var editSpecTool = {
|
|
|
1543
1514
|
return `Error: that edit would remove or malform the spec's YAML frontmatter (the leading \`--- \u2026 ---\` block, which holds required fields like \`name\`). Narrow old_string to the body content you meant to change and leave the frontmatter block intact.`;
|
|
1544
1515
|
}
|
|
1545
1516
|
try {
|
|
1546
|
-
await
|
|
1517
|
+
await fs6.writeFile(input.path, updated, "utf-8");
|
|
1547
1518
|
} catch (err) {
|
|
1548
1519
|
return `Error writing file: ${err.message}`;
|
|
1549
1520
|
}
|
|
@@ -1555,8 +1526,8 @@ var editSpecTool = {
|
|
|
1555
1526
|
};
|
|
1556
1527
|
|
|
1557
1528
|
// src/tools/spec/listSpecFiles.ts
|
|
1558
|
-
import
|
|
1559
|
-
import
|
|
1529
|
+
import fs7 from "fs/promises";
|
|
1530
|
+
import path4 from "path";
|
|
1560
1531
|
var listSpecFilesTool = {
|
|
1561
1532
|
definition: {
|
|
1562
1533
|
name: "listSpecFiles",
|
|
@@ -1584,7 +1555,7 @@ var listSpecFilesTool = {
|
|
|
1584
1555
|
};
|
|
1585
1556
|
async function listRecursive(dir) {
|
|
1586
1557
|
const results = [];
|
|
1587
|
-
const entries = await
|
|
1558
|
+
const entries = await fs7.readdir(dir, { withFileTypes: true });
|
|
1588
1559
|
entries.sort((a, b) => {
|
|
1589
1560
|
if (a.isDirectory() && !b.isDirectory()) {
|
|
1590
1561
|
return -1;
|
|
@@ -1595,7 +1566,7 @@ async function listRecursive(dir) {
|
|
|
1595
1566
|
return a.name.localeCompare(b.name);
|
|
1596
1567
|
});
|
|
1597
1568
|
for (const entry of entries) {
|
|
1598
|
-
const fullPath =
|
|
1569
|
+
const fullPath = path4.join(dir, entry.name);
|
|
1599
1570
|
if (entry.isDirectory()) {
|
|
1600
1571
|
if (entry.name.startsWith(".")) {
|
|
1601
1572
|
continue;
|
|
@@ -1632,18 +1603,18 @@ var presentPublishPlanTool = {
|
|
|
1632
1603
|
};
|
|
1633
1604
|
|
|
1634
1605
|
// src/atomicWrite.ts
|
|
1635
|
-
import
|
|
1606
|
+
import fs8 from "fs";
|
|
1636
1607
|
import fsp from "fs/promises";
|
|
1637
1608
|
var writeFileAtomicSync = (file, data) => {
|
|
1638
1609
|
const tmp = `${file}.${process.pid}.tmp`;
|
|
1639
|
-
const fd2 =
|
|
1610
|
+
const fd2 = fs8.openSync(tmp, "w");
|
|
1640
1611
|
try {
|
|
1641
|
-
|
|
1642
|
-
|
|
1612
|
+
fs8.writeSync(fd2, data);
|
|
1613
|
+
fs8.fsyncSync(fd2);
|
|
1643
1614
|
} finally {
|
|
1644
|
-
|
|
1615
|
+
fs8.closeSync(fd2);
|
|
1645
1616
|
}
|
|
1646
|
-
|
|
1617
|
+
fs8.renameSync(tmp, file);
|
|
1647
1618
|
};
|
|
1648
1619
|
var writeFileAtomic = async (file, data) => {
|
|
1649
1620
|
const tmp = `${file}.${process.pid}.tmp`;
|
|
@@ -1687,7 +1658,7 @@ ${content}`;
|
|
|
1687
1658
|
};
|
|
1688
1659
|
|
|
1689
1660
|
// src/tools/spec/updatePlanStatus.ts
|
|
1690
|
-
import
|
|
1661
|
+
import fs9 from "fs/promises";
|
|
1691
1662
|
var PLAN_FILE2 = ".remy-plan.md";
|
|
1692
1663
|
var updatePlanStatusTool = {
|
|
1693
1664
|
definition: {
|
|
@@ -1712,12 +1683,12 @@ var updatePlanStatusTool = {
|
|
|
1712
1683
|
}
|
|
1713
1684
|
let content;
|
|
1714
1685
|
try {
|
|
1715
|
-
content = await
|
|
1686
|
+
content = await fs9.readFile(PLAN_FILE2, "utf-8");
|
|
1716
1687
|
} catch {
|
|
1717
1688
|
return "No plan file found.";
|
|
1718
1689
|
}
|
|
1719
1690
|
if (status === "rejected") {
|
|
1720
|
-
await
|
|
1691
|
+
await fs9.unlink(PLAN_FILE2).catch(() => {
|
|
1721
1692
|
});
|
|
1722
1693
|
return "Plan rejected and removed.";
|
|
1723
1694
|
}
|
|
@@ -2192,7 +2163,7 @@ This reference lives at ${skill.path}. Re-read it with readFile if you need it a
|
|
|
2192
2163
|
};
|
|
2193
2164
|
|
|
2194
2165
|
// src/tools/code/readFile.ts
|
|
2195
|
-
import
|
|
2166
|
+
import fs10 from "fs/promises";
|
|
2196
2167
|
var DEFAULT_WINDOW = 500;
|
|
2197
2168
|
var MAX_BYTES = 64 * 1024;
|
|
2198
2169
|
function isBinary(buffer) {
|
|
@@ -2233,7 +2204,7 @@ var readFileTool = {
|
|
|
2233
2204
|
},
|
|
2234
2205
|
async execute(input) {
|
|
2235
2206
|
try {
|
|
2236
|
-
const buffer = await
|
|
2207
|
+
const buffer = await fs10.readFile(input.path);
|
|
2237
2208
|
if (isBinary(buffer)) {
|
|
2238
2209
|
const size = buffer.length;
|
|
2239
2210
|
const unit = size > 1024 * 1024 ? `${(size / (1024 * 1024)).toFixed(1)}MB` : `${(size / 1024).toFixed(1)}KB`;
|
|
@@ -2305,8 +2276,8 @@ var readFileTool = {
|
|
|
2305
2276
|
};
|
|
2306
2277
|
|
|
2307
2278
|
// src/tools/code/writeFile.ts
|
|
2308
|
-
import
|
|
2309
|
-
import
|
|
2279
|
+
import fs11 from "fs/promises";
|
|
2280
|
+
import path5 from "path";
|
|
2310
2281
|
var writeFileTool = {
|
|
2311
2282
|
definition: {
|
|
2312
2283
|
name: "writeFile",
|
|
@@ -2342,7 +2313,7 @@ var writeFileTool = {
|
|
|
2342
2313
|
lastNewlineCount = newlineCount;
|
|
2343
2314
|
const lastNewline = partial.content.lastIndexOf("\n");
|
|
2344
2315
|
const completeContent = partial.content.substring(0, lastNewline + 1);
|
|
2345
|
-
const oldContent = await
|
|
2316
|
+
const oldContent = await fs11.readFile(partial.path, "utf-8").catch(() => "");
|
|
2346
2317
|
return `Writing ${partial.path} (${newlineCount} lines)
|
|
2347
2318
|
${unifiedDiff(partial.path, oldContent, completeContent)}`;
|
|
2348
2319
|
}
|
|
@@ -2351,13 +2322,13 @@ ${unifiedDiff(partial.path, oldContent, completeContent)}`;
|
|
|
2351
2322
|
async execute(input) {
|
|
2352
2323
|
const release = await acquireFileLock(input.path);
|
|
2353
2324
|
try {
|
|
2354
|
-
await
|
|
2325
|
+
await fs11.mkdir(path5.dirname(input.path), { recursive: true });
|
|
2355
2326
|
let oldContent = null;
|
|
2356
2327
|
try {
|
|
2357
|
-
oldContent = await
|
|
2328
|
+
oldContent = await fs11.readFile(input.path, "utf-8");
|
|
2358
2329
|
} catch {
|
|
2359
2330
|
}
|
|
2360
|
-
await
|
|
2331
|
+
await fs11.writeFile(input.path, input.content, "utf-8");
|
|
2361
2332
|
const lineCount = input.content.split("\n").length;
|
|
2362
2333
|
const label = oldContent !== null ? "Wrote" : "Created";
|
|
2363
2334
|
return `${label} ${input.path} (${lineCount} lines)
|
|
@@ -2371,7 +2342,7 @@ ${unifiedDiff(input.path, oldContent ?? "", input.content)}`;
|
|
|
2371
2342
|
};
|
|
2372
2343
|
|
|
2373
2344
|
// src/tools/code/editFile/index.ts
|
|
2374
|
-
import
|
|
2345
|
+
import fs12 from "fs/promises";
|
|
2375
2346
|
var editFileTool = {
|
|
2376
2347
|
definition: {
|
|
2377
2348
|
name: "editFile",
|
|
@@ -2402,7 +2373,7 @@ var editFileTool = {
|
|
|
2402
2373
|
async execute(input) {
|
|
2403
2374
|
const release = await acquireFileLock(input.path);
|
|
2404
2375
|
try {
|
|
2405
|
-
const content = await
|
|
2376
|
+
const content = await fs12.readFile(input.path, "utf-8");
|
|
2406
2377
|
const { old_string, new_string, replace_all } = input;
|
|
2407
2378
|
const occurrences = findOccurrences(content, old_string);
|
|
2408
2379
|
if (replace_all) {
|
|
@@ -2418,7 +2389,7 @@ var editFileTool = {
|
|
|
2418
2389
|
new_string
|
|
2419
2390
|
);
|
|
2420
2391
|
}
|
|
2421
|
-
await
|
|
2392
|
+
await fs12.writeFile(input.path, updated, "utf-8");
|
|
2422
2393
|
return `Replaced ${occurrences.length} occurrence${occurrences.length > 1 ? "s" : ""} in ${input.path}
|
|
2423
2394
|
${unifiedDiff(input.path, content, updated)}`;
|
|
2424
2395
|
}
|
|
@@ -2429,7 +2400,7 @@ ${unifiedDiff(input.path, content, updated)}`;
|
|
|
2429
2400
|
old_string.length,
|
|
2430
2401
|
new_string
|
|
2431
2402
|
);
|
|
2432
|
-
await
|
|
2403
|
+
await fs12.writeFile(input.path, updated, "utf-8");
|
|
2433
2404
|
return `Updated ${input.path}
|
|
2434
2405
|
${unifiedDiff(input.path, content, updated)}`;
|
|
2435
2406
|
}
|
|
@@ -2445,7 +2416,7 @@ ${unifiedDiff(input.path, content, updated)}`;
|
|
|
2445
2416
|
flex.matchedText.length,
|
|
2446
2417
|
new_string
|
|
2447
2418
|
);
|
|
2448
|
-
await
|
|
2419
|
+
await fs12.writeFile(input.path, updated, "utf-8");
|
|
2449
2420
|
return `Updated ${input.path} (matched with flexible whitespace at line ${flex.line})
|
|
2450
2421
|
${unifiedDiff(input.path, content, updated)}`;
|
|
2451
2422
|
}
|
|
@@ -2460,7 +2431,7 @@ ${unifiedDiff(input.path, content, updated)}`;
|
|
|
2460
2431
|
|
|
2461
2432
|
// src/tools/code/bash.ts
|
|
2462
2433
|
import { spawn as spawn2 } from "child_process";
|
|
2463
|
-
import
|
|
2434
|
+
import path6 from "path";
|
|
2464
2435
|
var DEFAULT_TIMEOUT_MS = 12e4;
|
|
2465
2436
|
var DEFAULT_MAX_LINES2 = 500;
|
|
2466
2437
|
var MAX_OUTPUT_BYTES = 3e4;
|
|
@@ -2498,7 +2469,7 @@ var bashTool = {
|
|
|
2498
2469
|
const child = spawn2("bash", ["-c", input.command], {
|
|
2499
2470
|
// Pinned rather than inherited. `undefined` here means "wherever the
|
|
2500
2471
|
// process happens to be", which is the project root only by luck.
|
|
2501
|
-
cwd: input.cwd ?
|
|
2472
|
+
cwd: input.cwd ? path6.resolve(PROJECT_ROOT, input.cwd) : PROJECT_ROOT,
|
|
2502
2473
|
// Output is rendered in a terminal view in the IDE, so ask tools for
|
|
2503
2474
|
// color. The devbox image sets none of these — it declares only
|
|
2504
2475
|
// WORKSPACE_DIR, LANG, LC_ALL, PIP_BREAK_SYSTEM_PACKAGES,
|
|
@@ -2783,12 +2754,12 @@ var globTool = {
|
|
|
2783
2754
|
};
|
|
2784
2755
|
|
|
2785
2756
|
// src/tools/code/listDir.ts
|
|
2786
|
-
import
|
|
2787
|
-
import
|
|
2757
|
+
import fs13 from "fs/promises";
|
|
2758
|
+
import path7 from "path";
|
|
2788
2759
|
var EXCLUDE = /* @__PURE__ */ new Set([".git", "node_modules"]);
|
|
2789
2760
|
var MAX_CHILDREN = 15;
|
|
2790
2761
|
async function readAndSort(dirPath) {
|
|
2791
|
-
const entries = await
|
|
2762
|
+
const entries = await fs13.readdir(dirPath, { withFileTypes: true });
|
|
2792
2763
|
return entries.filter((e) => !EXCLUDE.has(e.name)).sort((a, b) => {
|
|
2793
2764
|
if (a.isDirectory() && !b.isDirectory()) {
|
|
2794
2765
|
return -1;
|
|
@@ -2801,7 +2772,7 @@ async function readAndSort(dirPath) {
|
|
|
2801
2772
|
}
|
|
2802
2773
|
async function collapsePath(basePath, name) {
|
|
2803
2774
|
let display = name;
|
|
2804
|
-
let current =
|
|
2775
|
+
let current = path7.join(basePath, name);
|
|
2805
2776
|
while (true) {
|
|
2806
2777
|
let children;
|
|
2807
2778
|
try {
|
|
@@ -2811,7 +2782,7 @@ async function collapsePath(basePath, name) {
|
|
|
2811
2782
|
}
|
|
2812
2783
|
if (children.length === 1 && children[0].isDirectory()) {
|
|
2813
2784
|
display += "/" + children[0].name;
|
|
2814
|
-
current =
|
|
2785
|
+
current = path7.join(current, children[0].name);
|
|
2815
2786
|
} else {
|
|
2816
2787
|
break;
|
|
2817
2788
|
}
|
|
@@ -2829,7 +2800,7 @@ function formatSize(bytes) {
|
|
|
2829
2800
|
}
|
|
2830
2801
|
async function formatFile(dirPath, name, indent) {
|
|
2831
2802
|
try {
|
|
2832
|
-
const stat6 = await
|
|
2803
|
+
const stat6 = await fs13.stat(path7.join(dirPath, name));
|
|
2833
2804
|
return `${indent}${name}${" ".repeat(Math.max(1, 30 - indent.length - name.length))}${formatSize(stat6.size)}`;
|
|
2834
2805
|
} catch {
|
|
2835
2806
|
return `${indent}${name}`;
|
|
@@ -3162,7 +3133,7 @@ var queryDatabaseTool = {
|
|
|
3162
3133
|
};
|
|
3163
3134
|
|
|
3164
3135
|
// src/usageLedger.ts
|
|
3165
|
-
import
|
|
3136
|
+
import fs14 from "fs";
|
|
3166
3137
|
var LEDGER_FILE = ".logs/usage.ndjson";
|
|
3167
3138
|
function thinkingTokensFromBilling(billingEvents, outputTokens) {
|
|
3168
3139
|
if (!billingEvents?.length) {
|
|
@@ -3178,10 +3149,10 @@ function nanoToDollars(nano) {
|
|
|
3178
3149
|
function recordUsage(entry) {
|
|
3179
3150
|
try {
|
|
3180
3151
|
if (fd === null) {
|
|
3181
|
-
|
|
3182
|
-
fd =
|
|
3152
|
+
fs14.mkdirSync(".logs", { recursive: true });
|
|
3153
|
+
fd = fs14.openSync(LEDGER_FILE, "a");
|
|
3183
3154
|
}
|
|
3184
|
-
|
|
3155
|
+
fs14.writeSync(fd, JSON.stringify(entry) + "\n");
|
|
3185
3156
|
} catch {
|
|
3186
3157
|
}
|
|
3187
3158
|
}
|
|
@@ -3472,7 +3443,7 @@ async function captureAndAnalyzeScreenshot(promptOrOptions) {
|
|
|
3472
3443
|
let onLog;
|
|
3473
3444
|
let model;
|
|
3474
3445
|
let apiConfig;
|
|
3475
|
-
let
|
|
3446
|
+
let path13;
|
|
3476
3447
|
let fullPage = true;
|
|
3477
3448
|
let width;
|
|
3478
3449
|
let height;
|
|
@@ -3480,7 +3451,7 @@ async function captureAndAnalyzeScreenshot(promptOrOptions) {
|
|
|
3480
3451
|
if (typeof promptOrOptions === "object" && promptOrOptions !== null) {
|
|
3481
3452
|
prompt = promptOrOptions.prompt;
|
|
3482
3453
|
existingImage = promptOrOptions.image;
|
|
3483
|
-
|
|
3454
|
+
path13 = promptOrOptions.path;
|
|
3484
3455
|
if (promptOrOptions.fullPage !== void 0) {
|
|
3485
3456
|
fullPage = promptOrOptions.fullPage;
|
|
3486
3457
|
}
|
|
@@ -3504,7 +3475,7 @@ async function captureAndAnalyzeScreenshot(promptOrOptions) {
|
|
|
3504
3475
|
const ssResult = await sidecarRequest(
|
|
3505
3476
|
fullPage ? "/screenshot-full-page" : "/screenshot-viewport",
|
|
3506
3477
|
{
|
|
3507
|
-
...
|
|
3478
|
+
...path13 ? { path: path13 } : {},
|
|
3508
3479
|
...width != null ? { width } : {},
|
|
3509
3480
|
...height != null ? { height } : {},
|
|
3510
3481
|
...format ? { format } : {}
|
|
@@ -4568,13 +4539,13 @@ var BROWSER_TOOLS = [
|
|
|
4568
4539
|
var BROWSER_EXTERNAL_TOOLS = /* @__PURE__ */ new Set(["browserCommand"]);
|
|
4569
4540
|
|
|
4570
4541
|
// src/subagents/common/context.ts
|
|
4571
|
-
import
|
|
4572
|
-
import
|
|
4542
|
+
import fs15 from "fs";
|
|
4543
|
+
import path8 from "path";
|
|
4573
4544
|
function walkMdFiles(dir, skip) {
|
|
4574
4545
|
const files = [];
|
|
4575
4546
|
try {
|
|
4576
|
-
for (const entry of
|
|
4577
|
-
const full =
|
|
4547
|
+
for (const entry of fs15.readdirSync(dir, { withFileTypes: true })) {
|
|
4548
|
+
const full = path8.join(dir, entry.name);
|
|
4578
4549
|
if (entry.isDirectory()) {
|
|
4579
4550
|
if (!skip?.has(entry.name) && !entry.name.startsWith(".")) {
|
|
4580
4551
|
files.push(...walkMdFiles(full, skip));
|
|
@@ -4589,7 +4560,7 @@ function walkMdFiles(dir, skip) {
|
|
|
4589
4560
|
}
|
|
4590
4561
|
function parseFrontmatter2(filePath) {
|
|
4591
4562
|
try {
|
|
4592
|
-
const content =
|
|
4563
|
+
const content = fs15.readFileSync(filePath, "utf-8");
|
|
4593
4564
|
const match = content.match(/^---\n([\s\S]*?)\n---/);
|
|
4594
4565
|
if (!match) {
|
|
4595
4566
|
return {};
|
|
@@ -4635,7 +4606,7 @@ function loadRoadmapIndex() {
|
|
|
4635
4606
|
const parts = [];
|
|
4636
4607
|
try {
|
|
4637
4608
|
const indexJson = JSON.parse(
|
|
4638
|
-
|
|
4609
|
+
fs15.readFileSync("src/roadmap/index.json", "utf-8")
|
|
4639
4610
|
);
|
|
4640
4611
|
if (indexJson.lanes?.length > 0) {
|
|
4641
4612
|
const laneLines = indexJson.lanes.map(
|
|
@@ -5534,18 +5505,18 @@ async function analyze(image, prompt, onLog, context, extra) {
|
|
|
5534
5505
|
...extra
|
|
5535
5506
|
});
|
|
5536
5507
|
}
|
|
5537
|
-
async function analyzeLocalHtml(
|
|
5508
|
+
async function analyzeLocalHtml(path13, customPrompt, onLog, context) {
|
|
5538
5509
|
let raw;
|
|
5539
5510
|
try {
|
|
5540
|
-
raw = await readFile2(join2(PROJECT_ROOT,
|
|
5511
|
+
raw = await readFile2(join2(PROJECT_ROOT, path13), "utf8");
|
|
5541
5512
|
} catch {
|
|
5542
|
-
return `No file at "${
|
|
5513
|
+
return `No file at "${path13}". Paths resolve from the project root; list the directory to check the name.`;
|
|
5543
5514
|
}
|
|
5544
5515
|
const { name, description, html } = splitFrontmatter(raw);
|
|
5545
5516
|
if (!html.trim()) {
|
|
5546
|
-
return `"${
|
|
5517
|
+
return `"${path13}" has no HTML to render.`;
|
|
5547
5518
|
}
|
|
5548
|
-
onLog?.(`Rendering ${
|
|
5519
|
+
onLog?.(`Rendering ${path13} in the sandbox browser...`);
|
|
5549
5520
|
const release = await acquireBrowserLock();
|
|
5550
5521
|
let rendered;
|
|
5551
5522
|
try {
|
|
@@ -5556,7 +5527,7 @@ async function analyzeLocalHtml(path14, customPrompt, onLog, context) {
|
|
|
5556
5527
|
autoHeight: true
|
|
5557
5528
|
});
|
|
5558
5529
|
} catch (err) {
|
|
5559
|
-
return `Could not render ${
|
|
5530
|
+
return `Could not render ${path13}: ${err?.message ?? err}`;
|
|
5560
5531
|
} finally {
|
|
5561
5532
|
release();
|
|
5562
5533
|
}
|
|
@@ -6309,7 +6280,7 @@ async function executeDesignExpertTool(name, input, context, toolCallId, onLog)
|
|
|
6309
6280
|
}
|
|
6310
6281
|
|
|
6311
6282
|
// src/subagents/designExpert/data/sampleCache.ts
|
|
6312
|
-
import
|
|
6283
|
+
import fs16 from "fs";
|
|
6313
6284
|
var SAMPLE_FILE = ".remy-design-sample.json";
|
|
6314
6285
|
var cached2 = null;
|
|
6315
6286
|
function generateIndices(poolSize, sampleSize) {
|
|
@@ -6323,7 +6294,7 @@ function generateIndices(poolSize, sampleSize) {
|
|
|
6323
6294
|
}
|
|
6324
6295
|
function load() {
|
|
6325
6296
|
try {
|
|
6326
|
-
return JSON.parse(
|
|
6297
|
+
return JSON.parse(fs16.readFileSync(SAMPLE_FILE, "utf-8"));
|
|
6327
6298
|
} catch {
|
|
6328
6299
|
return null;
|
|
6329
6300
|
}
|
|
@@ -6747,28 +6718,28 @@ var VISION_TOOLS = [
|
|
|
6747
6718
|
];
|
|
6748
6719
|
|
|
6749
6720
|
// src/subagents/productVision/executor.ts
|
|
6750
|
-
import
|
|
6751
|
-
import
|
|
6721
|
+
import fs17 from "fs";
|
|
6722
|
+
import path9 from "path";
|
|
6752
6723
|
var ROADMAP_DIR = "src/roadmap";
|
|
6753
6724
|
var PITCH_DECK_SHELL = readAsset(
|
|
6754
6725
|
"subagents/productVision",
|
|
6755
6726
|
"pitch-deck-shell.html"
|
|
6756
6727
|
);
|
|
6757
6728
|
function resolve3(filePath) {
|
|
6758
|
-
return
|
|
6729
|
+
return path9.join(ROADMAP_DIR, filePath);
|
|
6759
6730
|
}
|
|
6760
6731
|
async function executeVisionTool(name, input, context) {
|
|
6761
6732
|
switch (name) {
|
|
6762
6733
|
case "writeFile": {
|
|
6763
6734
|
const filePath = resolve3(input.path);
|
|
6764
6735
|
try {
|
|
6765
|
-
|
|
6736
|
+
fs17.mkdirSync(ROADMAP_DIR, { recursive: true });
|
|
6766
6737
|
let oldContent = null;
|
|
6767
6738
|
try {
|
|
6768
|
-
oldContent =
|
|
6739
|
+
oldContent = fs17.readFileSync(filePath, "utf-8");
|
|
6769
6740
|
} catch {
|
|
6770
6741
|
}
|
|
6771
|
-
|
|
6742
|
+
fs17.writeFileSync(filePath, input.content, "utf-8");
|
|
6772
6743
|
const lineCount = input.content.split("\n").length;
|
|
6773
6744
|
const label = oldContent !== null ? "Wrote" : "Created";
|
|
6774
6745
|
return `${label} ${filePath} (${lineCount} lines)
|
|
@@ -6780,11 +6751,11 @@ ${unifiedDiff(filePath, oldContent ?? "", input.content)}`;
|
|
|
6780
6751
|
case "deleteFile": {
|
|
6781
6752
|
const filePath = resolve3(input.path);
|
|
6782
6753
|
try {
|
|
6783
|
-
if (!
|
|
6754
|
+
if (!fs17.existsSync(filePath)) {
|
|
6784
6755
|
return `Error: ${filePath} does not exist`;
|
|
6785
6756
|
}
|
|
6786
|
-
const oldContent =
|
|
6787
|
-
|
|
6757
|
+
const oldContent = fs17.readFileSync(filePath, "utf-8");
|
|
6758
|
+
fs17.unlinkSync(filePath);
|
|
6788
6759
|
return `Deleted ${filePath}
|
|
6789
6760
|
${unifiedDiff(filePath, oldContent, "")}`;
|
|
6790
6761
|
} catch (err) {
|
|
@@ -6794,9 +6765,9 @@ ${unifiedDiff(filePath, oldContent, "")}`;
|
|
|
6794
6765
|
case "writePitchDeck": {
|
|
6795
6766
|
const filePath = resolve3("pitch.html");
|
|
6796
6767
|
try {
|
|
6797
|
-
|
|
6798
|
-
const exists =
|
|
6799
|
-
const before = exists ?
|
|
6768
|
+
fs17.mkdirSync(ROADMAP_DIR, { recursive: true });
|
|
6769
|
+
const exists = fs17.existsSync(filePath);
|
|
6770
|
+
const before = exists ? fs17.statSync(filePath).mtimeMs : null;
|
|
6800
6771
|
const delivery = exists ? `### Your deliverable
|
|
6801
6772
|
The pitch deck already exists at \`${filePath}\`. Read it, then update it for the new <pitch_content>, keeping the presentation scaffolding intact \u2014 change only what needs to change.
|
|
6802
6773
|
|
|
@@ -6826,11 +6797,11 @@ Maintain the bones of the presentation scaffolding. Always keep the progress bar
|
|
|
6826
6797
|
${delivery}`;
|
|
6827
6798
|
const result = await runDesignExpertRender({ task }, context);
|
|
6828
6799
|
context.subAgentMessages?.set(context.toolCallId, result.messages);
|
|
6829
|
-
if (!
|
|
6800
|
+
if (!fs17.existsSync(filePath)) {
|
|
6830
6801
|
return `Error: the design expert did not write ${filePath}. Its reply was:
|
|
6831
6802
|
${result.text}`;
|
|
6832
6803
|
}
|
|
6833
|
-
if (before !== null &&
|
|
6804
|
+
if (before !== null && fs17.statSync(filePath).mtimeMs === before) {
|
|
6834
6805
|
return `Error: the pitch deck at ${filePath} was not modified. The design expert's reply was:
|
|
6835
6806
|
${result.text}`;
|
|
6836
6807
|
}
|
|
@@ -7051,7 +7022,7 @@ var codeSanityCheckTool = {
|
|
|
7051
7022
|
};
|
|
7052
7023
|
|
|
7053
7024
|
// src/tools/spec/writeBuildOverview.ts
|
|
7054
|
-
import
|
|
7025
|
+
import fs18 from "fs";
|
|
7055
7026
|
var OVERVIEW_FILE = "src/overview.html";
|
|
7056
7027
|
var DESIGN_BRIEF = `We are building the Build Overview for this app \u2014 the home page of its Spec tab. It is a calm, dense, one-page reference of everything the app actually contains, including the parts the user can't see. It renders flush inside the Spec tab's content panel (the IDE supplies the surrounding nav).
|
|
7057
7028
|
|
|
@@ -7111,7 +7082,7 @@ async function renderBuildOverview(content, context, opts) {
|
|
|
7111
7082
|
if (!content) {
|
|
7112
7083
|
return "Error: writeBuildOverview requires non-empty `content` (the overview copy).";
|
|
7113
7084
|
}
|
|
7114
|
-
const exists =
|
|
7085
|
+
const exists = fs18.existsSync(OVERVIEW_FILE);
|
|
7115
7086
|
const task = `<overview_copy>${content}</overview_copy>
|
|
7116
7087
|
|
|
7117
7088
|
${DESIGN_BRIEF}
|
|
@@ -7128,7 +7099,7 @@ ${exists ? refreshDelivery() : initialDelivery()}`;
|
|
|
7128
7099
|
}
|
|
7129
7100
|
const result = await runDesignExpertRender({ task }, context);
|
|
7130
7101
|
context.subAgentMessages?.set(context.toolCallId, result.messages);
|
|
7131
|
-
if (!
|
|
7102
|
+
if (!fs18.existsSync(OVERVIEW_FILE)) {
|
|
7132
7103
|
return `Error: the design expert did not write ${OVERVIEW_FILE}. Its reply was:
|
|
7133
7104
|
${result.text}`;
|
|
7134
7105
|
}
|
|
@@ -7154,7 +7125,7 @@ var buildOverviewTool = {
|
|
|
7154
7125
|
},
|
|
7155
7126
|
async execute(input, context) {
|
|
7156
7127
|
const content = (input.content ?? "").trim();
|
|
7157
|
-
const background = Boolean(content) &&
|
|
7128
|
+
const background = Boolean(content) && fs18.existsSync(OVERVIEW_FILE);
|
|
7158
7129
|
if (background) {
|
|
7159
7130
|
input.background = true;
|
|
7160
7131
|
}
|
|
@@ -7905,8 +7876,8 @@ Write the summary of the conversation above, following your instructions.`;
|
|
|
7905
7876
|
}
|
|
7906
7877
|
|
|
7907
7878
|
// src/session.ts
|
|
7908
|
-
import
|
|
7909
|
-
import
|
|
7879
|
+
import fs19 from "fs";
|
|
7880
|
+
import path10 from "path";
|
|
7910
7881
|
var log12 = createLogger("session");
|
|
7911
7882
|
var SESSION_FILE = ".remy-session.json";
|
|
7912
7883
|
var ARCHIVE_DIR = ".logs/sessions";
|
|
@@ -7919,7 +7890,7 @@ var ARCHIVE_MSG_CACHE_MAX = 3;
|
|
|
7919
7890
|
function loadSession(state) {
|
|
7920
7891
|
pruneArchives();
|
|
7921
7892
|
try {
|
|
7922
|
-
const raw =
|
|
7893
|
+
const raw = fs19.readFileSync(SESSION_FILE, "utf-8");
|
|
7923
7894
|
const data = JSON.parse(raw);
|
|
7924
7895
|
if (data.models && typeof data.models === "object") {
|
|
7925
7896
|
state.models = data.models;
|
|
@@ -7935,7 +7906,7 @@ function loadSession(state) {
|
|
|
7935
7906
|
} catch {
|
|
7936
7907
|
try {
|
|
7937
7908
|
const quarantine = `${SESSION_FILE}.corrupt-${Date.now()}`;
|
|
7938
|
-
|
|
7909
|
+
fs19.renameSync(SESSION_FILE, quarantine);
|
|
7939
7910
|
log12.warn(`Session file unreadable \u2014 quarantined to ${quarantine}`);
|
|
7940
7911
|
} catch {
|
|
7941
7912
|
}
|
|
@@ -7987,33 +7958,33 @@ function buildPayload(state) {
|
|
|
7987
7958
|
return payload;
|
|
7988
7959
|
}
|
|
7989
7960
|
function archiveMessages(messages, label, models) {
|
|
7990
|
-
|
|
7961
|
+
fs19.mkdirSync(ARCHIVE_DIR, { recursive: true });
|
|
7991
7962
|
const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
7992
7963
|
const count = messages.length;
|
|
7993
|
-
let dest =
|
|
7964
|
+
let dest = path10.join(ARCHIVE_DIR, `${label}-${ts}.c${count}.json`);
|
|
7994
7965
|
let n = 1;
|
|
7995
|
-
while (
|
|
7996
|
-
dest =
|
|
7966
|
+
while (fs19.existsSync(dest)) {
|
|
7967
|
+
dest = path10.join(ARCHIVE_DIR, `${label}-${ts}-${n++}.c${count}.json`);
|
|
7997
7968
|
}
|
|
7998
7969
|
const payload = { messages };
|
|
7999
7970
|
if (models && Object.keys(models).length > 0) {
|
|
8000
7971
|
payload.models = models;
|
|
8001
7972
|
}
|
|
8002
7973
|
writeFileAtomicSync(dest, JSON.stringify(payload));
|
|
8003
|
-
archiveCountCache.set(
|
|
7974
|
+
archiveCountCache.set(path10.basename(dest), count);
|
|
8004
7975
|
log12.info("Session archived", { label, dest, messageCount: count });
|
|
8005
7976
|
pruneArchives();
|
|
8006
7977
|
return dest;
|
|
8007
7978
|
}
|
|
8008
7979
|
function pruneArchives() {
|
|
8009
7980
|
try {
|
|
8010
|
-
const entries =
|
|
7981
|
+
const entries = fs19.readdirSync(ARCHIVE_DIR).filter((name) => ARCHIVE_NAME_RE.test(name));
|
|
8011
7982
|
if (entries.length <= 1) {
|
|
8012
7983
|
return;
|
|
8013
7984
|
}
|
|
8014
7985
|
const archives = entries.map((name) => ({
|
|
8015
7986
|
name,
|
|
8016
|
-
size:
|
|
7987
|
+
size: fs19.statSync(path10.join(ARCHIVE_DIR, name)).size
|
|
8017
7988
|
})).sort(
|
|
8018
7989
|
(a, b) => archiveSortKey(b.name).localeCompare(archiveSortKey(a.name))
|
|
8019
7990
|
);
|
|
@@ -8031,7 +8002,7 @@ function pruneArchives() {
|
|
|
8031
8002
|
let freed = 0;
|
|
8032
8003
|
for (let i = cut; i < archives.length; i++) {
|
|
8033
8004
|
try {
|
|
8034
|
-
|
|
8005
|
+
fs19.unlinkSync(path10.join(ARCHIVE_DIR, archives[i].name));
|
|
8035
8006
|
freed += archives[i].size;
|
|
8036
8007
|
removed++;
|
|
8037
8008
|
} catch {
|
|
@@ -8055,7 +8026,7 @@ function parseArchive(name) {
|
|
|
8055
8026
|
return cached3;
|
|
8056
8027
|
}
|
|
8057
8028
|
try {
|
|
8058
|
-
const raw =
|
|
8029
|
+
const raw = fs19.readFileSync(path10.join(ARCHIVE_DIR, name), "utf-8");
|
|
8059
8030
|
const data = JSON.parse(raw);
|
|
8060
8031
|
const messages = Array.isArray(data?.messages) ? data.messages : [];
|
|
8061
8032
|
for (const msg of messages) {
|
|
@@ -8096,7 +8067,7 @@ function readArchiveMessages(name) {
|
|
|
8096
8067
|
function listConversationArchives() {
|
|
8097
8068
|
let names;
|
|
8098
8069
|
try {
|
|
8099
|
-
names =
|
|
8070
|
+
names = fs19.readdirSync(ARCHIVE_DIR).filter((n) => ARCHIVE_NAME_RE.test(n));
|
|
8100
8071
|
} catch {
|
|
8101
8072
|
return { slots: [], archivedCount: 0 };
|
|
8102
8073
|
}
|
|
@@ -8382,8 +8353,8 @@ function triggerCompaction(state, apiConfig, opts = {}) {
|
|
|
8382
8353
|
}
|
|
8383
8354
|
|
|
8384
8355
|
// src/brandExtraction/index.ts
|
|
8385
|
-
import
|
|
8386
|
-
import
|
|
8356
|
+
import fs20 from "fs";
|
|
8357
|
+
import path11 from "path";
|
|
8387
8358
|
import { createHash } from "crypto";
|
|
8388
8359
|
var log14 = createLogger("brandExtraction");
|
|
8389
8360
|
var EXTRACT_PROMPT = readAsset("brandExtraction", "extract.md");
|
|
@@ -8407,7 +8378,7 @@ async function runExtraction(apiConfig, model) {
|
|
|
8407
8378
|
return brand;
|
|
8408
8379
|
}
|
|
8409
8380
|
function isDedicatedBrandFile(filePath) {
|
|
8410
|
-
if (filePath.split(
|
|
8381
|
+
if (filePath.split(path11.sep).includes("@brand")) {
|
|
8411
8382
|
return true;
|
|
8412
8383
|
}
|
|
8413
8384
|
const { type } = parseFrontmatter3(filePath);
|
|
@@ -8433,7 +8404,7 @@ function sha256(input) {
|
|
|
8433
8404
|
}
|
|
8434
8405
|
function readSafe(filePath) {
|
|
8435
8406
|
try {
|
|
8436
|
-
return
|
|
8407
|
+
return fs20.readFileSync(filePath, "utf-8");
|
|
8437
8408
|
} catch {
|
|
8438
8409
|
return "";
|
|
8439
8410
|
}
|
|
@@ -8459,9 +8430,9 @@ function readBrandManifest() {
|
|
|
8459
8430
|
function walkMdFiles2(dir) {
|
|
8460
8431
|
const results = [];
|
|
8461
8432
|
try {
|
|
8462
|
-
const entries =
|
|
8433
|
+
const entries = fs20.readdirSync(dir, { withFileTypes: true });
|
|
8463
8434
|
for (const entry of entries) {
|
|
8464
|
-
const full =
|
|
8435
|
+
const full = path11.join(dir, entry.name);
|
|
8465
8436
|
if (entry.isDirectory()) {
|
|
8466
8437
|
if (!entry.name.startsWith(".")) {
|
|
8467
8438
|
results.push(...walkMdFiles2(full));
|
|
@@ -8476,7 +8447,7 @@ function walkMdFiles2(dir) {
|
|
|
8476
8447
|
}
|
|
8477
8448
|
function parseFrontmatter3(filePath) {
|
|
8478
8449
|
try {
|
|
8479
|
-
const content =
|
|
8450
|
+
const content = fs20.readFileSync(filePath, "utf-8");
|
|
8480
8451
|
const match = content.match(/^---\n([\s\S]*?)\n---/);
|
|
8481
8452
|
if (!match) {
|
|
8482
8453
|
return { type: "" };
|
|
@@ -8694,7 +8665,7 @@ function persistBrand(brand, inputHash) {
|
|
|
8694
8665
|
}
|
|
8695
8666
|
function readCache() {
|
|
8696
8667
|
try {
|
|
8697
|
-
const raw =
|
|
8668
|
+
const raw = fs20.readFileSync(CACHE_FILE, "utf-8");
|
|
8698
8669
|
const parsed = JSON.parse(raw);
|
|
8699
8670
|
if (parsed && typeof parsed.inputHash === "string" && typeof parsed.generatedAt === "number") {
|
|
8700
8671
|
return parsed;
|
|
@@ -9773,7 +9744,11 @@ async function runTurn(params) {
|
|
|
9773
9744
|
});
|
|
9774
9745
|
break;
|
|
9775
9746
|
case "error":
|
|
9776
|
-
streamError = {
|
|
9747
|
+
streamError = {
|
|
9748
|
+
error: event.error,
|
|
9749
|
+
code: event.code,
|
|
9750
|
+
badModelId: event.badModelId
|
|
9751
|
+
};
|
|
9777
9752
|
break;
|
|
9778
9753
|
}
|
|
9779
9754
|
if (streamError) {
|
|
@@ -9823,7 +9798,7 @@ async function runTurn(params) {
|
|
|
9823
9798
|
return;
|
|
9824
9799
|
}
|
|
9825
9800
|
if (streamError) {
|
|
9826
|
-
const { error, code } = streamError;
|
|
9801
|
+
const { error, code, badModelId } = streamError;
|
|
9827
9802
|
if (code === "repetition_loop") {
|
|
9828
9803
|
if (recoveries < MAX_RECOVERIES && !signal?.aborted) {
|
|
9829
9804
|
recoveries++;
|
|
@@ -9863,6 +9838,7 @@ async function runTurn(params) {
|
|
|
9863
9838
|
type: "error",
|
|
9864
9839
|
error: friendlyError(error),
|
|
9865
9840
|
...code ? { code } : {},
|
|
9841
|
+
...badModelId ? { badModelId } : {},
|
|
9866
9842
|
lastCallInputTokens
|
|
9867
9843
|
});
|
|
9868
9844
|
return;
|
|
@@ -10669,8 +10645,8 @@ function logStartup(config, model, flagApiKey) {
|
|
|
10669
10645
|
let version = "(unknown)";
|
|
10670
10646
|
try {
|
|
10671
10647
|
version = JSON.parse(
|
|
10672
|
-
|
|
10673
|
-
|
|
10648
|
+
fs21.readFileSync(
|
|
10649
|
+
path12.join(import.meta.dirname, "..", "package.json"),
|
|
10674
10650
|
"utf-8"
|
|
10675
10651
|
)
|
|
10676
10652
|
).version;
|
|
@@ -10679,8 +10655,8 @@ function logStartup(config, model, flagApiKey) {
|
|
|
10679
10655
|
startupLog.info("Startup", {
|
|
10680
10656
|
version,
|
|
10681
10657
|
node: process.version,
|
|
10682
|
-
platform: `${
|
|
10683
|
-
os: `${
|
|
10658
|
+
platform: `${os.platform()} ${os.arch()}`,
|
|
10659
|
+
os: `${os.type()} ${os.release()}`,
|
|
10684
10660
|
cwd: process.cwd(),
|
|
10685
10661
|
bin: process.argv[1],
|
|
10686
10662
|
model: model || "(default)",
|
|
@@ -11358,7 +11334,11 @@ var HeadlessSession = class {
|
|
|
11358
11334
|
}
|
|
11359
11335
|
this.emit(
|
|
11360
11336
|
"error",
|
|
11361
|
-
{
|
|
11337
|
+
{
|
|
11338
|
+
error: e.error,
|
|
11339
|
+
...e.code ? { code: e.code } : {},
|
|
11340
|
+
...e.badModelId ? { badModelId: e.badModelId } : {}
|
|
11341
|
+
},
|
|
11362
11342
|
rid
|
|
11363
11343
|
);
|
|
11364
11344
|
return;
|