@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/index.js
CHANGED
|
@@ -6,9 +6,9 @@ var __export = (target, all) => {
|
|
|
6
6
|
};
|
|
7
7
|
|
|
8
8
|
// src/headless/index.ts
|
|
9
|
-
import
|
|
10
|
-
import
|
|
11
|
-
import
|
|
9
|
+
import os from "os";
|
|
10
|
+
import fs21 from "fs";
|
|
11
|
+
import path12 from "path";
|
|
12
12
|
|
|
13
13
|
// src/logger.ts
|
|
14
14
|
var LEVELS = {
|
|
@@ -65,49 +65,20 @@ function initLoggerHeadless(level = "info") {
|
|
|
65
65
|
}
|
|
66
66
|
|
|
67
67
|
// src/config.ts
|
|
68
|
-
import fs from "fs";
|
|
69
|
-
import path from "path";
|
|
70
|
-
import os from "os";
|
|
71
68
|
var log = createLogger("config");
|
|
72
|
-
var CONFIG_PATH = path.join(
|
|
73
|
-
os.homedir(),
|
|
74
|
-
".mindstudio-local-tunnel",
|
|
75
|
-
"config.json"
|
|
76
|
-
);
|
|
77
69
|
var DEFAULT_BASE_URL = "https://api.mindstudio.ai";
|
|
78
|
-
function loadConfigFile() {
|
|
79
|
-
try {
|
|
80
|
-
const raw = fs.readFileSync(CONFIG_PATH, "utf-8");
|
|
81
|
-
log.debug("Loaded config file", { path: CONFIG_PATH });
|
|
82
|
-
return JSON.parse(raw);
|
|
83
|
-
} catch (err) {
|
|
84
|
-
log.debug("No config file found", {
|
|
85
|
-
path: CONFIG_PATH,
|
|
86
|
-
error: err.message
|
|
87
|
-
});
|
|
88
|
-
return {};
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
70
|
function resolveConfig(flags2) {
|
|
92
|
-
const
|
|
93
|
-
const
|
|
94
|
-
const env = file.environments?.[activeEnv];
|
|
95
|
-
const apiKey = flags2?.apiKey || process.env.MINDSTUDIO_API_KEY || env?.apiKey || "";
|
|
96
|
-
const baseUrl2 = flags2?.baseUrl || process.env.MINDSTUDIO_BASE_URL || env?.apiBaseUrl || DEFAULT_BASE_URL;
|
|
71
|
+
const apiKey = flags2?.apiKey || process.env.MINDSTUDIO_API_KEY || "";
|
|
72
|
+
const baseUrl2 = flags2?.baseUrl || process.env.MINDSTUDIO_BASE_URL || DEFAULT_BASE_URL;
|
|
97
73
|
const appId = process.env.MINDSTUDIO_APP_ID || void 0;
|
|
98
74
|
if (!apiKey) {
|
|
99
75
|
log.error("No API key found");
|
|
100
76
|
throw new Error(
|
|
101
|
-
"No API key found.
|
|
77
|
+
"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."
|
|
102
78
|
);
|
|
103
79
|
}
|
|
104
|
-
const keySource = flags2?.apiKey ? "cli flag" :
|
|
105
|
-
log.info("Config resolved", {
|
|
106
|
-
baseUrl: baseUrl2,
|
|
107
|
-
keySource,
|
|
108
|
-
environment: activeEnv,
|
|
109
|
-
appId
|
|
110
|
-
});
|
|
80
|
+
const keySource = flags2?.apiKey ? "cli flag" : "env var";
|
|
81
|
+
log.info("Config resolved", { baseUrl: baseUrl2, keySource, appId });
|
|
111
82
|
return { apiKey, baseUrl: baseUrl2, appId };
|
|
112
83
|
}
|
|
113
84
|
|
|
@@ -784,16 +755,16 @@ async function initModelRegistry(config) {
|
|
|
784
755
|
}
|
|
785
756
|
|
|
786
757
|
// src/assets.ts
|
|
787
|
-
import
|
|
788
|
-
import
|
|
789
|
-
var ASSETS_BASE = import.meta.dirname ??
|
|
758
|
+
import fs from "fs";
|
|
759
|
+
import path from "path";
|
|
760
|
+
var ASSETS_BASE = import.meta.dirname ?? path.dirname(new URL(import.meta.url).pathname);
|
|
790
761
|
function assetPath(...segments) {
|
|
791
|
-
return
|
|
762
|
+
return path.join(ASSETS_BASE, ...segments);
|
|
792
763
|
}
|
|
793
764
|
function readAsset(...segments) {
|
|
794
765
|
const full = assetPath(...segments);
|
|
795
766
|
try {
|
|
796
|
-
return
|
|
767
|
+
return fs.readFileSync(full, "utf-8").trim();
|
|
797
768
|
} catch {
|
|
798
769
|
throw new Error(`Required asset missing: ${full}`);
|
|
799
770
|
}
|
|
@@ -801,14 +772,14 @@ function readAsset(...segments) {
|
|
|
801
772
|
function readJsonAsset(fallback, ...segments) {
|
|
802
773
|
const full = assetPath(...segments);
|
|
803
774
|
try {
|
|
804
|
-
return JSON.parse(
|
|
775
|
+
return JSON.parse(fs.readFileSync(full, "utf-8"));
|
|
805
776
|
} catch {
|
|
806
777
|
return fallback;
|
|
807
778
|
}
|
|
808
779
|
}
|
|
809
780
|
|
|
810
781
|
// src/prompt/static/projectContext.ts
|
|
811
|
-
import
|
|
782
|
+
import fs2 from "fs";
|
|
812
783
|
|
|
813
784
|
// src/projectRoot.ts
|
|
814
785
|
var PROJECT_ROOT = process.cwd();
|
|
@@ -823,7 +794,7 @@ File paths are relative to this directory. Every tool operates here and bash com
|
|
|
823
794
|
}
|
|
824
795
|
function loadAppIdentity() {
|
|
825
796
|
try {
|
|
826
|
-
const manifest = JSON.parse(
|
|
797
|
+
const manifest = JSON.parse(fs2.readFileSync("mindstudio.json", "utf-8"));
|
|
827
798
|
const name = typeof manifest.name === "string" ? manifest.name.trim() : "";
|
|
828
799
|
if (!name) {
|
|
829
800
|
return "";
|
|
@@ -840,7 +811,7 @@ Full manifest: \`mindstudio.json\` (read it when you need the app's structure, t
|
|
|
840
811
|
}
|
|
841
812
|
function loadPlanStatus(onboardingState) {
|
|
842
813
|
try {
|
|
843
|
-
const content =
|
|
814
|
+
const content = fs2.readFileSync(".remy-plan.md", "utf-8");
|
|
844
815
|
const match = content.match(/^---\n([\s\S]*?)\n---/);
|
|
845
816
|
const status = match?.[1]?.match(/^status:\s*(.+)$/m)?.[1]?.trim();
|
|
846
817
|
if (status === "pending" && onboardingState === "intake") {
|
|
@@ -868,8 +839,8 @@ The user has approved your implementation plan in .remy-plan.md. You may referen
|
|
|
868
839
|
}
|
|
869
840
|
|
|
870
841
|
// src/skillCatalog.ts
|
|
871
|
-
import
|
|
872
|
-
import
|
|
842
|
+
import fs3 from "fs";
|
|
843
|
+
import path2 from "path";
|
|
873
844
|
function parseFrontmatter(content) {
|
|
874
845
|
const match = content.match(/^---\n([\s\S]*?)\n---/);
|
|
875
846
|
if (!match) {
|
|
@@ -887,15 +858,15 @@ function parseFrontmatter(content) {
|
|
|
887
858
|
function buildSkillCatalog(opts) {
|
|
888
859
|
let files;
|
|
889
860
|
try {
|
|
890
|
-
files =
|
|
861
|
+
files = fs3.readdirSync(opts.dir).filter((f) => f.endsWith(".md"));
|
|
891
862
|
} catch {
|
|
892
863
|
files = [];
|
|
893
864
|
}
|
|
894
865
|
const skills = [];
|
|
895
866
|
for (const file of files.sort()) {
|
|
896
|
-
const full =
|
|
867
|
+
const full = path2.join(opts.dir, file);
|
|
897
868
|
const id = file.replace(/\.md$/, "");
|
|
898
|
-
const fields = parseFrontmatter(
|
|
869
|
+
const fields = parseFrontmatter(fs3.readFileSync(full, "utf-8"));
|
|
899
870
|
if (!fields.name || !fields.what || !fields.when) {
|
|
900
871
|
continue;
|
|
901
872
|
}
|
|
@@ -914,7 +885,7 @@ function buildSkillCatalog(opts) {
|
|
|
914
885
|
return skills.find((s) => s.id === id);
|
|
915
886
|
},
|
|
916
887
|
readBody(skill) {
|
|
917
|
-
return
|
|
888
|
+
return fs3.readFileSync(skill.path, "utf-8").replace(/^---[\s\S]*?---\s*/, "").trim();
|
|
918
889
|
},
|
|
919
890
|
renderCatalogBlock() {
|
|
920
891
|
if (skills.length === 0) {
|
|
@@ -1186,7 +1157,7 @@ function mergeBackgroundResultsMessages(messages) {
|
|
|
1186
1157
|
}
|
|
1187
1158
|
|
|
1188
1159
|
// src/tools/spec/readSpec.ts
|
|
1189
|
-
import
|
|
1160
|
+
import fs4 from "fs/promises";
|
|
1190
1161
|
|
|
1191
1162
|
// src/tools/spec/_helpers.ts
|
|
1192
1163
|
function validateSpecPath(filePath) {
|
|
@@ -1240,7 +1211,7 @@ var readSpecTool = {
|
|
|
1240
1211
|
return `Error: ${err.message}`;
|
|
1241
1212
|
}
|
|
1242
1213
|
try {
|
|
1243
|
-
const content = await
|
|
1214
|
+
const content = await fs4.readFile(input.path, "utf-8");
|
|
1244
1215
|
const allLines = content.split("\n");
|
|
1245
1216
|
const totalLines = allLines.length;
|
|
1246
1217
|
const maxLines = input.maxLines === 0 ? Infinity : input.maxLines || DEFAULT_MAX_LINES;
|
|
@@ -1268,8 +1239,8 @@ var readSpecTool = {
|
|
|
1268
1239
|
};
|
|
1269
1240
|
|
|
1270
1241
|
// src/tools/spec/writeSpec.ts
|
|
1271
|
-
import
|
|
1272
|
-
import
|
|
1242
|
+
import fs5 from "fs/promises";
|
|
1243
|
+
import path3 from "path";
|
|
1273
1244
|
|
|
1274
1245
|
// src/tools/_helpers/diff.ts
|
|
1275
1246
|
var CONTEXT_LINES = 3;
|
|
@@ -1344,7 +1315,7 @@ var writeSpecTool = {
|
|
|
1344
1315
|
},
|
|
1345
1316
|
streaming: {
|
|
1346
1317
|
transform: async (partial) => {
|
|
1347
|
-
const oldContent = await
|
|
1318
|
+
const oldContent = await fs5.readFile(partial.path, "utf-8").catch(() => "");
|
|
1348
1319
|
const lineCount = partial.content.split("\n").length;
|
|
1349
1320
|
return `Writing ${partial.path} (${lineCount} lines)
|
|
1350
1321
|
${unifiedDiff(partial.path, oldContent, partial.content)}`;
|
|
@@ -1358,13 +1329,13 @@ ${unifiedDiff(partial.path, oldContent, partial.content)}`;
|
|
|
1358
1329
|
}
|
|
1359
1330
|
const release = await acquireFileLock(input.path);
|
|
1360
1331
|
try {
|
|
1361
|
-
await
|
|
1332
|
+
await fs5.mkdir(path3.dirname(input.path), { recursive: true });
|
|
1362
1333
|
let oldContent = null;
|
|
1363
1334
|
try {
|
|
1364
|
-
oldContent = await
|
|
1335
|
+
oldContent = await fs5.readFile(input.path, "utf-8");
|
|
1365
1336
|
} catch {
|
|
1366
1337
|
}
|
|
1367
|
-
await
|
|
1338
|
+
await fs5.writeFile(input.path, input.content, "utf-8");
|
|
1368
1339
|
const lineCount = input.content.split("\n").length;
|
|
1369
1340
|
const label = oldContent !== null ? "Wrote" : "Created";
|
|
1370
1341
|
return `${label} ${input.path} (${lineCount} lines)
|
|
@@ -1378,7 +1349,7 @@ ${unifiedDiff(input.path, oldContent ?? "", input.content)}`;
|
|
|
1378
1349
|
};
|
|
1379
1350
|
|
|
1380
1351
|
// src/tools/spec/editSpec.ts
|
|
1381
|
-
import
|
|
1352
|
+
import fs6 from "fs/promises";
|
|
1382
1353
|
|
|
1383
1354
|
// src/tools/code/editFile/_helpers.ts
|
|
1384
1355
|
function buildLineOffsets(content) {
|
|
@@ -1497,7 +1468,7 @@ var editSpecTool = {
|
|
|
1497
1468
|
try {
|
|
1498
1469
|
let content;
|
|
1499
1470
|
try {
|
|
1500
|
-
content = await
|
|
1471
|
+
content = await fs6.readFile(input.path, "utf-8");
|
|
1501
1472
|
} catch (err) {
|
|
1502
1473
|
return `Error reading file: ${err.message}`;
|
|
1503
1474
|
}
|
|
@@ -1550,7 +1521,7 @@ var editSpecTool = {
|
|
|
1550
1521
|
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.`;
|
|
1551
1522
|
}
|
|
1552
1523
|
try {
|
|
1553
|
-
await
|
|
1524
|
+
await fs6.writeFile(input.path, updated, "utf-8");
|
|
1554
1525
|
} catch (err) {
|
|
1555
1526
|
return `Error writing file: ${err.message}`;
|
|
1556
1527
|
}
|
|
@@ -1562,8 +1533,8 @@ var editSpecTool = {
|
|
|
1562
1533
|
};
|
|
1563
1534
|
|
|
1564
1535
|
// src/tools/spec/listSpecFiles.ts
|
|
1565
|
-
import
|
|
1566
|
-
import
|
|
1536
|
+
import fs7 from "fs/promises";
|
|
1537
|
+
import path4 from "path";
|
|
1567
1538
|
var listSpecFilesTool = {
|
|
1568
1539
|
definition: {
|
|
1569
1540
|
name: "listSpecFiles",
|
|
@@ -1591,7 +1562,7 @@ var listSpecFilesTool = {
|
|
|
1591
1562
|
};
|
|
1592
1563
|
async function listRecursive(dir) {
|
|
1593
1564
|
const results = [];
|
|
1594
|
-
const entries = await
|
|
1565
|
+
const entries = await fs7.readdir(dir, { withFileTypes: true });
|
|
1595
1566
|
entries.sort((a, b) => {
|
|
1596
1567
|
if (a.isDirectory() && !b.isDirectory()) {
|
|
1597
1568
|
return -1;
|
|
@@ -1602,7 +1573,7 @@ async function listRecursive(dir) {
|
|
|
1602
1573
|
return a.name.localeCompare(b.name);
|
|
1603
1574
|
});
|
|
1604
1575
|
for (const entry of entries) {
|
|
1605
|
-
const fullPath =
|
|
1576
|
+
const fullPath = path4.join(dir, entry.name);
|
|
1606
1577
|
if (entry.isDirectory()) {
|
|
1607
1578
|
if (entry.name.startsWith(".")) {
|
|
1608
1579
|
continue;
|
|
@@ -1639,18 +1610,18 @@ var presentPublishPlanTool = {
|
|
|
1639
1610
|
};
|
|
1640
1611
|
|
|
1641
1612
|
// src/atomicWrite.ts
|
|
1642
|
-
import
|
|
1613
|
+
import fs8 from "fs";
|
|
1643
1614
|
import fsp from "fs/promises";
|
|
1644
1615
|
var writeFileAtomicSync = (file, data) => {
|
|
1645
1616
|
const tmp = `${file}.${process.pid}.tmp`;
|
|
1646
|
-
const fd2 =
|
|
1617
|
+
const fd2 = fs8.openSync(tmp, "w");
|
|
1647
1618
|
try {
|
|
1648
|
-
|
|
1649
|
-
|
|
1619
|
+
fs8.writeSync(fd2, data);
|
|
1620
|
+
fs8.fsyncSync(fd2);
|
|
1650
1621
|
} finally {
|
|
1651
|
-
|
|
1622
|
+
fs8.closeSync(fd2);
|
|
1652
1623
|
}
|
|
1653
|
-
|
|
1624
|
+
fs8.renameSync(tmp, file);
|
|
1654
1625
|
};
|
|
1655
1626
|
var writeFileAtomic = async (file, data) => {
|
|
1656
1627
|
const tmp = `${file}.${process.pid}.tmp`;
|
|
@@ -1694,7 +1665,7 @@ ${content}`;
|
|
|
1694
1665
|
};
|
|
1695
1666
|
|
|
1696
1667
|
// src/tools/spec/updatePlanStatus.ts
|
|
1697
|
-
import
|
|
1668
|
+
import fs9 from "fs/promises";
|
|
1698
1669
|
var PLAN_FILE2 = ".remy-plan.md";
|
|
1699
1670
|
var updatePlanStatusTool = {
|
|
1700
1671
|
definition: {
|
|
@@ -1719,12 +1690,12 @@ var updatePlanStatusTool = {
|
|
|
1719
1690
|
}
|
|
1720
1691
|
let content;
|
|
1721
1692
|
try {
|
|
1722
|
-
content = await
|
|
1693
|
+
content = await fs9.readFile(PLAN_FILE2, "utf-8");
|
|
1723
1694
|
} catch {
|
|
1724
1695
|
return "No plan file found.";
|
|
1725
1696
|
}
|
|
1726
1697
|
if (status === "rejected") {
|
|
1727
|
-
await
|
|
1698
|
+
await fs9.unlink(PLAN_FILE2).catch(() => {
|
|
1728
1699
|
});
|
|
1729
1700
|
return "Plan rejected and removed.";
|
|
1730
1701
|
}
|
|
@@ -2199,7 +2170,7 @@ This reference lives at ${skill.path}. Re-read it with readFile if you need it a
|
|
|
2199
2170
|
};
|
|
2200
2171
|
|
|
2201
2172
|
// src/tools/code/readFile.ts
|
|
2202
|
-
import
|
|
2173
|
+
import fs10 from "fs/promises";
|
|
2203
2174
|
var DEFAULT_WINDOW = 500;
|
|
2204
2175
|
var MAX_BYTES = 64 * 1024;
|
|
2205
2176
|
function isBinary(buffer) {
|
|
@@ -2240,7 +2211,7 @@ var readFileTool = {
|
|
|
2240
2211
|
},
|
|
2241
2212
|
async execute(input) {
|
|
2242
2213
|
try {
|
|
2243
|
-
const buffer = await
|
|
2214
|
+
const buffer = await fs10.readFile(input.path);
|
|
2244
2215
|
if (isBinary(buffer)) {
|
|
2245
2216
|
const size = buffer.length;
|
|
2246
2217
|
const unit = size > 1024 * 1024 ? `${(size / (1024 * 1024)).toFixed(1)}MB` : `${(size / 1024).toFixed(1)}KB`;
|
|
@@ -2312,8 +2283,8 @@ var readFileTool = {
|
|
|
2312
2283
|
};
|
|
2313
2284
|
|
|
2314
2285
|
// src/tools/code/writeFile.ts
|
|
2315
|
-
import
|
|
2316
|
-
import
|
|
2286
|
+
import fs11 from "fs/promises";
|
|
2287
|
+
import path5 from "path";
|
|
2317
2288
|
var writeFileTool = {
|
|
2318
2289
|
definition: {
|
|
2319
2290
|
name: "writeFile",
|
|
@@ -2349,7 +2320,7 @@ var writeFileTool = {
|
|
|
2349
2320
|
lastNewlineCount = newlineCount;
|
|
2350
2321
|
const lastNewline = partial.content.lastIndexOf("\n");
|
|
2351
2322
|
const completeContent = partial.content.substring(0, lastNewline + 1);
|
|
2352
|
-
const oldContent = await
|
|
2323
|
+
const oldContent = await fs11.readFile(partial.path, "utf-8").catch(() => "");
|
|
2353
2324
|
return `Writing ${partial.path} (${newlineCount} lines)
|
|
2354
2325
|
${unifiedDiff(partial.path, oldContent, completeContent)}`;
|
|
2355
2326
|
}
|
|
@@ -2358,13 +2329,13 @@ ${unifiedDiff(partial.path, oldContent, completeContent)}`;
|
|
|
2358
2329
|
async execute(input) {
|
|
2359
2330
|
const release = await acquireFileLock(input.path);
|
|
2360
2331
|
try {
|
|
2361
|
-
await
|
|
2332
|
+
await fs11.mkdir(path5.dirname(input.path), { recursive: true });
|
|
2362
2333
|
let oldContent = null;
|
|
2363
2334
|
try {
|
|
2364
|
-
oldContent = await
|
|
2335
|
+
oldContent = await fs11.readFile(input.path, "utf-8");
|
|
2365
2336
|
} catch {
|
|
2366
2337
|
}
|
|
2367
|
-
await
|
|
2338
|
+
await fs11.writeFile(input.path, input.content, "utf-8");
|
|
2368
2339
|
const lineCount = input.content.split("\n").length;
|
|
2369
2340
|
const label = oldContent !== null ? "Wrote" : "Created";
|
|
2370
2341
|
return `${label} ${input.path} (${lineCount} lines)
|
|
@@ -2378,7 +2349,7 @@ ${unifiedDiff(input.path, oldContent ?? "", input.content)}`;
|
|
|
2378
2349
|
};
|
|
2379
2350
|
|
|
2380
2351
|
// src/tools/code/editFile/index.ts
|
|
2381
|
-
import
|
|
2352
|
+
import fs12 from "fs/promises";
|
|
2382
2353
|
var editFileTool = {
|
|
2383
2354
|
definition: {
|
|
2384
2355
|
name: "editFile",
|
|
@@ -2409,7 +2380,7 @@ var editFileTool = {
|
|
|
2409
2380
|
async execute(input) {
|
|
2410
2381
|
const release = await acquireFileLock(input.path);
|
|
2411
2382
|
try {
|
|
2412
|
-
const content = await
|
|
2383
|
+
const content = await fs12.readFile(input.path, "utf-8");
|
|
2413
2384
|
const { old_string, new_string, replace_all } = input;
|
|
2414
2385
|
const occurrences = findOccurrences(content, old_string);
|
|
2415
2386
|
if (replace_all) {
|
|
@@ -2425,7 +2396,7 @@ var editFileTool = {
|
|
|
2425
2396
|
new_string
|
|
2426
2397
|
);
|
|
2427
2398
|
}
|
|
2428
|
-
await
|
|
2399
|
+
await fs12.writeFile(input.path, updated, "utf-8");
|
|
2429
2400
|
return `Replaced ${occurrences.length} occurrence${occurrences.length > 1 ? "s" : ""} in ${input.path}
|
|
2430
2401
|
${unifiedDiff(input.path, content, updated)}`;
|
|
2431
2402
|
}
|
|
@@ -2436,7 +2407,7 @@ ${unifiedDiff(input.path, content, updated)}`;
|
|
|
2436
2407
|
old_string.length,
|
|
2437
2408
|
new_string
|
|
2438
2409
|
);
|
|
2439
|
-
await
|
|
2410
|
+
await fs12.writeFile(input.path, updated, "utf-8");
|
|
2440
2411
|
return `Updated ${input.path}
|
|
2441
2412
|
${unifiedDiff(input.path, content, updated)}`;
|
|
2442
2413
|
}
|
|
@@ -2452,7 +2423,7 @@ ${unifiedDiff(input.path, content, updated)}`;
|
|
|
2452
2423
|
flex.matchedText.length,
|
|
2453
2424
|
new_string
|
|
2454
2425
|
);
|
|
2455
|
-
await
|
|
2426
|
+
await fs12.writeFile(input.path, updated, "utf-8");
|
|
2456
2427
|
return `Updated ${input.path} (matched with flexible whitespace at line ${flex.line})
|
|
2457
2428
|
${unifiedDiff(input.path, content, updated)}`;
|
|
2458
2429
|
}
|
|
@@ -2467,7 +2438,7 @@ ${unifiedDiff(input.path, content, updated)}`;
|
|
|
2467
2438
|
|
|
2468
2439
|
// src/tools/code/bash.ts
|
|
2469
2440
|
import { spawn as spawn2 } from "child_process";
|
|
2470
|
-
import
|
|
2441
|
+
import path6 from "path";
|
|
2471
2442
|
var DEFAULT_TIMEOUT_MS = 12e4;
|
|
2472
2443
|
var DEFAULT_MAX_LINES2 = 500;
|
|
2473
2444
|
var MAX_OUTPUT_BYTES = 3e4;
|
|
@@ -2505,7 +2476,7 @@ var bashTool = {
|
|
|
2505
2476
|
const child = spawn2("bash", ["-c", input.command], {
|
|
2506
2477
|
// Pinned rather than inherited. `undefined` here means "wherever the
|
|
2507
2478
|
// process happens to be", which is the project root only by luck.
|
|
2508
|
-
cwd: input.cwd ?
|
|
2479
|
+
cwd: input.cwd ? path6.resolve(PROJECT_ROOT, input.cwd) : PROJECT_ROOT,
|
|
2509
2480
|
// Output is rendered in a terminal view in the IDE, so ask tools for
|
|
2510
2481
|
// color. The devbox image sets none of these — it declares only
|
|
2511
2482
|
// WORKSPACE_DIR, LANG, LC_ALL, PIP_BREAK_SYSTEM_PACKAGES,
|
|
@@ -2790,12 +2761,12 @@ var globTool = {
|
|
|
2790
2761
|
};
|
|
2791
2762
|
|
|
2792
2763
|
// src/tools/code/listDir.ts
|
|
2793
|
-
import
|
|
2794
|
-
import
|
|
2764
|
+
import fs13 from "fs/promises";
|
|
2765
|
+
import path7 from "path";
|
|
2795
2766
|
var EXCLUDE = /* @__PURE__ */ new Set([".git", "node_modules"]);
|
|
2796
2767
|
var MAX_CHILDREN = 15;
|
|
2797
2768
|
async function readAndSort(dirPath) {
|
|
2798
|
-
const entries = await
|
|
2769
|
+
const entries = await fs13.readdir(dirPath, { withFileTypes: true });
|
|
2799
2770
|
return entries.filter((e) => !EXCLUDE.has(e.name)).sort((a, b) => {
|
|
2800
2771
|
if (a.isDirectory() && !b.isDirectory()) {
|
|
2801
2772
|
return -1;
|
|
@@ -2808,7 +2779,7 @@ async function readAndSort(dirPath) {
|
|
|
2808
2779
|
}
|
|
2809
2780
|
async function collapsePath(basePath, name) {
|
|
2810
2781
|
let display = name;
|
|
2811
|
-
let current =
|
|
2782
|
+
let current = path7.join(basePath, name);
|
|
2812
2783
|
while (true) {
|
|
2813
2784
|
let children;
|
|
2814
2785
|
try {
|
|
@@ -2818,7 +2789,7 @@ async function collapsePath(basePath, name) {
|
|
|
2818
2789
|
}
|
|
2819
2790
|
if (children.length === 1 && children[0].isDirectory()) {
|
|
2820
2791
|
display += "/" + children[0].name;
|
|
2821
|
-
current =
|
|
2792
|
+
current = path7.join(current, children[0].name);
|
|
2822
2793
|
} else {
|
|
2823
2794
|
break;
|
|
2824
2795
|
}
|
|
@@ -2836,7 +2807,7 @@ function formatSize(bytes) {
|
|
|
2836
2807
|
}
|
|
2837
2808
|
async function formatFile(dirPath, name, indent) {
|
|
2838
2809
|
try {
|
|
2839
|
-
const stat6 = await
|
|
2810
|
+
const stat6 = await fs13.stat(path7.join(dirPath, name));
|
|
2840
2811
|
return `${indent}${name}${" ".repeat(Math.max(1, 30 - indent.length - name.length))}${formatSize(stat6.size)}`;
|
|
2841
2812
|
} catch {
|
|
2842
2813
|
return `${indent}${name}`;
|
|
@@ -3169,7 +3140,7 @@ var queryDatabaseTool = {
|
|
|
3169
3140
|
};
|
|
3170
3141
|
|
|
3171
3142
|
// src/usageLedger.ts
|
|
3172
|
-
import
|
|
3143
|
+
import fs14 from "fs";
|
|
3173
3144
|
var LEDGER_FILE = ".logs/usage.ndjson";
|
|
3174
3145
|
function thinkingTokensFromBilling(billingEvents, outputTokens) {
|
|
3175
3146
|
if (!billingEvents?.length) {
|
|
@@ -3185,10 +3156,10 @@ function nanoToDollars(nano) {
|
|
|
3185
3156
|
function recordUsage(entry) {
|
|
3186
3157
|
try {
|
|
3187
3158
|
if (fd === null) {
|
|
3188
|
-
|
|
3189
|
-
fd =
|
|
3159
|
+
fs14.mkdirSync(".logs", { recursive: true });
|
|
3160
|
+
fd = fs14.openSync(LEDGER_FILE, "a");
|
|
3190
3161
|
}
|
|
3191
|
-
|
|
3162
|
+
fs14.writeSync(fd, JSON.stringify(entry) + "\n");
|
|
3192
3163
|
} catch {
|
|
3193
3164
|
}
|
|
3194
3165
|
}
|
|
@@ -3479,7 +3450,7 @@ async function captureAndAnalyzeScreenshot(promptOrOptions) {
|
|
|
3479
3450
|
let onLog;
|
|
3480
3451
|
let model;
|
|
3481
3452
|
let apiConfig;
|
|
3482
|
-
let
|
|
3453
|
+
let path13;
|
|
3483
3454
|
let fullPage = true;
|
|
3484
3455
|
let width;
|
|
3485
3456
|
let height;
|
|
@@ -3487,7 +3458,7 @@ async function captureAndAnalyzeScreenshot(promptOrOptions) {
|
|
|
3487
3458
|
if (typeof promptOrOptions === "object" && promptOrOptions !== null) {
|
|
3488
3459
|
prompt = promptOrOptions.prompt;
|
|
3489
3460
|
existingImage = promptOrOptions.image;
|
|
3490
|
-
|
|
3461
|
+
path13 = promptOrOptions.path;
|
|
3491
3462
|
if (promptOrOptions.fullPage !== void 0) {
|
|
3492
3463
|
fullPage = promptOrOptions.fullPage;
|
|
3493
3464
|
}
|
|
@@ -3511,7 +3482,7 @@ async function captureAndAnalyzeScreenshot(promptOrOptions) {
|
|
|
3511
3482
|
const ssResult = await sidecarRequest(
|
|
3512
3483
|
fullPage ? "/screenshot-full-page" : "/screenshot-viewport",
|
|
3513
3484
|
{
|
|
3514
|
-
...
|
|
3485
|
+
...path13 ? { path: path13 } : {},
|
|
3515
3486
|
...width != null ? { width } : {},
|
|
3516
3487
|
...height != null ? { height } : {},
|
|
3517
3488
|
...format ? { format } : {}
|
|
@@ -4575,13 +4546,13 @@ var BROWSER_TOOLS = [
|
|
|
4575
4546
|
var BROWSER_EXTERNAL_TOOLS = /* @__PURE__ */ new Set(["browserCommand"]);
|
|
4576
4547
|
|
|
4577
4548
|
// src/subagents/common/context.ts
|
|
4578
|
-
import
|
|
4579
|
-
import
|
|
4549
|
+
import fs15 from "fs";
|
|
4550
|
+
import path8 from "path";
|
|
4580
4551
|
function walkMdFiles(dir, skip) {
|
|
4581
4552
|
const files = [];
|
|
4582
4553
|
try {
|
|
4583
|
-
for (const entry of
|
|
4584
|
-
const full =
|
|
4554
|
+
for (const entry of fs15.readdirSync(dir, { withFileTypes: true })) {
|
|
4555
|
+
const full = path8.join(dir, entry.name);
|
|
4585
4556
|
if (entry.isDirectory()) {
|
|
4586
4557
|
if (!skip?.has(entry.name) && !entry.name.startsWith(".")) {
|
|
4587
4558
|
files.push(...walkMdFiles(full, skip));
|
|
@@ -4596,7 +4567,7 @@ function walkMdFiles(dir, skip) {
|
|
|
4596
4567
|
}
|
|
4597
4568
|
function parseFrontmatter2(filePath) {
|
|
4598
4569
|
try {
|
|
4599
|
-
const content =
|
|
4570
|
+
const content = fs15.readFileSync(filePath, "utf-8");
|
|
4600
4571
|
const match = content.match(/^---\n([\s\S]*?)\n---/);
|
|
4601
4572
|
if (!match) {
|
|
4602
4573
|
return {};
|
|
@@ -4642,7 +4613,7 @@ function loadRoadmapIndex() {
|
|
|
4642
4613
|
const parts = [];
|
|
4643
4614
|
try {
|
|
4644
4615
|
const indexJson = JSON.parse(
|
|
4645
|
-
|
|
4616
|
+
fs15.readFileSync("src/roadmap/index.json", "utf-8")
|
|
4646
4617
|
);
|
|
4647
4618
|
if (indexJson.lanes?.length > 0) {
|
|
4648
4619
|
const laneLines = indexJson.lanes.map(
|
|
@@ -5541,18 +5512,18 @@ async function analyze(image, prompt, onLog, context, extra) {
|
|
|
5541
5512
|
...extra
|
|
5542
5513
|
});
|
|
5543
5514
|
}
|
|
5544
|
-
async function analyzeLocalHtml(
|
|
5515
|
+
async function analyzeLocalHtml(path13, customPrompt, onLog, context) {
|
|
5545
5516
|
let raw;
|
|
5546
5517
|
try {
|
|
5547
|
-
raw = await readFile2(join2(PROJECT_ROOT,
|
|
5518
|
+
raw = await readFile2(join2(PROJECT_ROOT, path13), "utf8");
|
|
5548
5519
|
} catch {
|
|
5549
|
-
return `No file at "${
|
|
5520
|
+
return `No file at "${path13}". Paths resolve from the project root; list the directory to check the name.`;
|
|
5550
5521
|
}
|
|
5551
5522
|
const { name, description, html } = splitFrontmatter(raw);
|
|
5552
5523
|
if (!html.trim()) {
|
|
5553
|
-
return `"${
|
|
5524
|
+
return `"${path13}" has no HTML to render.`;
|
|
5554
5525
|
}
|
|
5555
|
-
onLog?.(`Rendering ${
|
|
5526
|
+
onLog?.(`Rendering ${path13} in the sandbox browser...`);
|
|
5556
5527
|
const release = await acquireBrowserLock();
|
|
5557
5528
|
let rendered;
|
|
5558
5529
|
try {
|
|
@@ -5563,7 +5534,7 @@ async function analyzeLocalHtml(path14, customPrompt, onLog, context) {
|
|
|
5563
5534
|
autoHeight: true
|
|
5564
5535
|
});
|
|
5565
5536
|
} catch (err) {
|
|
5566
|
-
return `Could not render ${
|
|
5537
|
+
return `Could not render ${path13}: ${err?.message ?? err}`;
|
|
5567
5538
|
} finally {
|
|
5568
5539
|
release();
|
|
5569
5540
|
}
|
|
@@ -6316,7 +6287,7 @@ async function executeDesignExpertTool(name, input, context, toolCallId, onLog)
|
|
|
6316
6287
|
}
|
|
6317
6288
|
|
|
6318
6289
|
// src/subagents/designExpert/data/sampleCache.ts
|
|
6319
|
-
import
|
|
6290
|
+
import fs16 from "fs";
|
|
6320
6291
|
var SAMPLE_FILE = ".remy-design-sample.json";
|
|
6321
6292
|
var cached2 = null;
|
|
6322
6293
|
function generateIndices(poolSize, sampleSize) {
|
|
@@ -6330,7 +6301,7 @@ function generateIndices(poolSize, sampleSize) {
|
|
|
6330
6301
|
}
|
|
6331
6302
|
function load() {
|
|
6332
6303
|
try {
|
|
6333
|
-
return JSON.parse(
|
|
6304
|
+
return JSON.parse(fs16.readFileSync(SAMPLE_FILE, "utf-8"));
|
|
6334
6305
|
} catch {
|
|
6335
6306
|
return null;
|
|
6336
6307
|
}
|
|
@@ -6754,28 +6725,28 @@ var VISION_TOOLS = [
|
|
|
6754
6725
|
];
|
|
6755
6726
|
|
|
6756
6727
|
// src/subagents/productVision/executor.ts
|
|
6757
|
-
import
|
|
6758
|
-
import
|
|
6728
|
+
import fs17 from "fs";
|
|
6729
|
+
import path9 from "path";
|
|
6759
6730
|
var ROADMAP_DIR = "src/roadmap";
|
|
6760
6731
|
var PITCH_DECK_SHELL = readAsset(
|
|
6761
6732
|
"subagents/productVision",
|
|
6762
6733
|
"pitch-deck-shell.html"
|
|
6763
6734
|
);
|
|
6764
6735
|
function resolve3(filePath) {
|
|
6765
|
-
return
|
|
6736
|
+
return path9.join(ROADMAP_DIR, filePath);
|
|
6766
6737
|
}
|
|
6767
6738
|
async function executeVisionTool(name, input, context) {
|
|
6768
6739
|
switch (name) {
|
|
6769
6740
|
case "writeFile": {
|
|
6770
6741
|
const filePath = resolve3(input.path);
|
|
6771
6742
|
try {
|
|
6772
|
-
|
|
6743
|
+
fs17.mkdirSync(ROADMAP_DIR, { recursive: true });
|
|
6773
6744
|
let oldContent = null;
|
|
6774
6745
|
try {
|
|
6775
|
-
oldContent =
|
|
6746
|
+
oldContent = fs17.readFileSync(filePath, "utf-8");
|
|
6776
6747
|
} catch {
|
|
6777
6748
|
}
|
|
6778
|
-
|
|
6749
|
+
fs17.writeFileSync(filePath, input.content, "utf-8");
|
|
6779
6750
|
const lineCount = input.content.split("\n").length;
|
|
6780
6751
|
const label = oldContent !== null ? "Wrote" : "Created";
|
|
6781
6752
|
return `${label} ${filePath} (${lineCount} lines)
|
|
@@ -6787,11 +6758,11 @@ ${unifiedDiff(filePath, oldContent ?? "", input.content)}`;
|
|
|
6787
6758
|
case "deleteFile": {
|
|
6788
6759
|
const filePath = resolve3(input.path);
|
|
6789
6760
|
try {
|
|
6790
|
-
if (!
|
|
6761
|
+
if (!fs17.existsSync(filePath)) {
|
|
6791
6762
|
return `Error: ${filePath} does not exist`;
|
|
6792
6763
|
}
|
|
6793
|
-
const oldContent =
|
|
6794
|
-
|
|
6764
|
+
const oldContent = fs17.readFileSync(filePath, "utf-8");
|
|
6765
|
+
fs17.unlinkSync(filePath);
|
|
6795
6766
|
return `Deleted ${filePath}
|
|
6796
6767
|
${unifiedDiff(filePath, oldContent, "")}`;
|
|
6797
6768
|
} catch (err) {
|
|
@@ -6801,9 +6772,9 @@ ${unifiedDiff(filePath, oldContent, "")}`;
|
|
|
6801
6772
|
case "writePitchDeck": {
|
|
6802
6773
|
const filePath = resolve3("pitch.html");
|
|
6803
6774
|
try {
|
|
6804
|
-
|
|
6805
|
-
const exists =
|
|
6806
|
-
const before = exists ?
|
|
6775
|
+
fs17.mkdirSync(ROADMAP_DIR, { recursive: true });
|
|
6776
|
+
const exists = fs17.existsSync(filePath);
|
|
6777
|
+
const before = exists ? fs17.statSync(filePath).mtimeMs : null;
|
|
6807
6778
|
const delivery = exists ? `### Your deliverable
|
|
6808
6779
|
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.
|
|
6809
6780
|
|
|
@@ -6833,11 +6804,11 @@ Maintain the bones of the presentation scaffolding. Always keep the progress bar
|
|
|
6833
6804
|
${delivery}`;
|
|
6834
6805
|
const result = await runDesignExpertRender({ task }, context);
|
|
6835
6806
|
context.subAgentMessages?.set(context.toolCallId, result.messages);
|
|
6836
|
-
if (!
|
|
6807
|
+
if (!fs17.existsSync(filePath)) {
|
|
6837
6808
|
return `Error: the design expert did not write ${filePath}. Its reply was:
|
|
6838
6809
|
${result.text}`;
|
|
6839
6810
|
}
|
|
6840
|
-
if (before !== null &&
|
|
6811
|
+
if (before !== null && fs17.statSync(filePath).mtimeMs === before) {
|
|
6841
6812
|
return `Error: the pitch deck at ${filePath} was not modified. The design expert's reply was:
|
|
6842
6813
|
${result.text}`;
|
|
6843
6814
|
}
|
|
@@ -7058,7 +7029,7 @@ var codeSanityCheckTool = {
|
|
|
7058
7029
|
};
|
|
7059
7030
|
|
|
7060
7031
|
// src/tools/spec/writeBuildOverview.ts
|
|
7061
|
-
import
|
|
7032
|
+
import fs18 from "fs";
|
|
7062
7033
|
var OVERVIEW_FILE = "src/overview.html";
|
|
7063
7034
|
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).
|
|
7064
7035
|
|
|
@@ -7118,7 +7089,7 @@ async function renderBuildOverview(content, context, opts) {
|
|
|
7118
7089
|
if (!content) {
|
|
7119
7090
|
return "Error: writeBuildOverview requires non-empty `content` (the overview copy).";
|
|
7120
7091
|
}
|
|
7121
|
-
const exists =
|
|
7092
|
+
const exists = fs18.existsSync(OVERVIEW_FILE);
|
|
7122
7093
|
const task = `<overview_copy>${content}</overview_copy>
|
|
7123
7094
|
|
|
7124
7095
|
${DESIGN_BRIEF}
|
|
@@ -7135,7 +7106,7 @@ ${exists ? refreshDelivery() : initialDelivery()}`;
|
|
|
7135
7106
|
}
|
|
7136
7107
|
const result = await runDesignExpertRender({ task }, context);
|
|
7137
7108
|
context.subAgentMessages?.set(context.toolCallId, result.messages);
|
|
7138
|
-
if (!
|
|
7109
|
+
if (!fs18.existsSync(OVERVIEW_FILE)) {
|
|
7139
7110
|
return `Error: the design expert did not write ${OVERVIEW_FILE}. Its reply was:
|
|
7140
7111
|
${result.text}`;
|
|
7141
7112
|
}
|
|
@@ -7161,7 +7132,7 @@ var buildOverviewTool = {
|
|
|
7161
7132
|
},
|
|
7162
7133
|
async execute(input, context) {
|
|
7163
7134
|
const content = (input.content ?? "").trim();
|
|
7164
|
-
const background = Boolean(content) &&
|
|
7135
|
+
const background = Boolean(content) && fs18.existsSync(OVERVIEW_FILE);
|
|
7165
7136
|
if (background) {
|
|
7166
7137
|
input.background = true;
|
|
7167
7138
|
}
|
|
@@ -7912,8 +7883,8 @@ Write the summary of the conversation above, following your instructions.`;
|
|
|
7912
7883
|
}
|
|
7913
7884
|
|
|
7914
7885
|
// src/session.ts
|
|
7915
|
-
import
|
|
7916
|
-
import
|
|
7886
|
+
import fs19 from "fs";
|
|
7887
|
+
import path10 from "path";
|
|
7917
7888
|
var log12 = createLogger("session");
|
|
7918
7889
|
var SESSION_FILE = ".remy-session.json";
|
|
7919
7890
|
var ARCHIVE_DIR = ".logs/sessions";
|
|
@@ -7926,7 +7897,7 @@ var ARCHIVE_MSG_CACHE_MAX = 3;
|
|
|
7926
7897
|
function loadSession(state) {
|
|
7927
7898
|
pruneArchives();
|
|
7928
7899
|
try {
|
|
7929
|
-
const raw =
|
|
7900
|
+
const raw = fs19.readFileSync(SESSION_FILE, "utf-8");
|
|
7930
7901
|
const data = JSON.parse(raw);
|
|
7931
7902
|
if (data.models && typeof data.models === "object") {
|
|
7932
7903
|
state.models = data.models;
|
|
@@ -7942,7 +7913,7 @@ function loadSession(state) {
|
|
|
7942
7913
|
} catch {
|
|
7943
7914
|
try {
|
|
7944
7915
|
const quarantine = `${SESSION_FILE}.corrupt-${Date.now()}`;
|
|
7945
|
-
|
|
7916
|
+
fs19.renameSync(SESSION_FILE, quarantine);
|
|
7946
7917
|
log12.warn(`Session file unreadable \u2014 quarantined to ${quarantine}`);
|
|
7947
7918
|
} catch {
|
|
7948
7919
|
}
|
|
@@ -7994,33 +7965,33 @@ function buildPayload(state) {
|
|
|
7994
7965
|
return payload;
|
|
7995
7966
|
}
|
|
7996
7967
|
function archiveMessages(messages, label, models) {
|
|
7997
|
-
|
|
7968
|
+
fs19.mkdirSync(ARCHIVE_DIR, { recursive: true });
|
|
7998
7969
|
const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
7999
7970
|
const count = messages.length;
|
|
8000
|
-
let dest =
|
|
7971
|
+
let dest = path10.join(ARCHIVE_DIR, `${label}-${ts}.c${count}.json`);
|
|
8001
7972
|
let n = 1;
|
|
8002
|
-
while (
|
|
8003
|
-
dest =
|
|
7973
|
+
while (fs19.existsSync(dest)) {
|
|
7974
|
+
dest = path10.join(ARCHIVE_DIR, `${label}-${ts}-${n++}.c${count}.json`);
|
|
8004
7975
|
}
|
|
8005
7976
|
const payload = { messages };
|
|
8006
7977
|
if (models && Object.keys(models).length > 0) {
|
|
8007
7978
|
payload.models = models;
|
|
8008
7979
|
}
|
|
8009
7980
|
writeFileAtomicSync(dest, JSON.stringify(payload));
|
|
8010
|
-
archiveCountCache.set(
|
|
7981
|
+
archiveCountCache.set(path10.basename(dest), count);
|
|
8011
7982
|
log12.info("Session archived", { label, dest, messageCount: count });
|
|
8012
7983
|
pruneArchives();
|
|
8013
7984
|
return dest;
|
|
8014
7985
|
}
|
|
8015
7986
|
function pruneArchives() {
|
|
8016
7987
|
try {
|
|
8017
|
-
const entries =
|
|
7988
|
+
const entries = fs19.readdirSync(ARCHIVE_DIR).filter((name) => ARCHIVE_NAME_RE.test(name));
|
|
8018
7989
|
if (entries.length <= 1) {
|
|
8019
7990
|
return;
|
|
8020
7991
|
}
|
|
8021
7992
|
const archives = entries.map((name) => ({
|
|
8022
7993
|
name,
|
|
8023
|
-
size:
|
|
7994
|
+
size: fs19.statSync(path10.join(ARCHIVE_DIR, name)).size
|
|
8024
7995
|
})).sort(
|
|
8025
7996
|
(a, b) => archiveSortKey(b.name).localeCompare(archiveSortKey(a.name))
|
|
8026
7997
|
);
|
|
@@ -8038,7 +8009,7 @@ function pruneArchives() {
|
|
|
8038
8009
|
let freed = 0;
|
|
8039
8010
|
for (let i = cut; i < archives.length; i++) {
|
|
8040
8011
|
try {
|
|
8041
|
-
|
|
8012
|
+
fs19.unlinkSync(path10.join(ARCHIVE_DIR, archives[i].name));
|
|
8042
8013
|
freed += archives[i].size;
|
|
8043
8014
|
removed++;
|
|
8044
8015
|
} catch {
|
|
@@ -8062,7 +8033,7 @@ function parseArchive(name) {
|
|
|
8062
8033
|
return cached3;
|
|
8063
8034
|
}
|
|
8064
8035
|
try {
|
|
8065
|
-
const raw =
|
|
8036
|
+
const raw = fs19.readFileSync(path10.join(ARCHIVE_DIR, name), "utf-8");
|
|
8066
8037
|
const data = JSON.parse(raw);
|
|
8067
8038
|
const messages = Array.isArray(data?.messages) ? data.messages : [];
|
|
8068
8039
|
for (const msg of messages) {
|
|
@@ -8103,7 +8074,7 @@ function readArchiveMessages(name) {
|
|
|
8103
8074
|
function listConversationArchives() {
|
|
8104
8075
|
let names;
|
|
8105
8076
|
try {
|
|
8106
|
-
names =
|
|
8077
|
+
names = fs19.readdirSync(ARCHIVE_DIR).filter((n) => ARCHIVE_NAME_RE.test(n));
|
|
8107
8078
|
} catch {
|
|
8108
8079
|
return { slots: [], archivedCount: 0 };
|
|
8109
8080
|
}
|
|
@@ -8389,8 +8360,8 @@ function triggerCompaction(state, apiConfig, opts = {}) {
|
|
|
8389
8360
|
}
|
|
8390
8361
|
|
|
8391
8362
|
// src/brandExtraction/index.ts
|
|
8392
|
-
import
|
|
8393
|
-
import
|
|
8363
|
+
import fs20 from "fs";
|
|
8364
|
+
import path11 from "path";
|
|
8394
8365
|
import { createHash } from "crypto";
|
|
8395
8366
|
var log14 = createLogger("brandExtraction");
|
|
8396
8367
|
var EXTRACT_PROMPT = readAsset("brandExtraction", "extract.md");
|
|
@@ -8414,7 +8385,7 @@ async function runExtraction(apiConfig, model) {
|
|
|
8414
8385
|
return brand;
|
|
8415
8386
|
}
|
|
8416
8387
|
function isDedicatedBrandFile(filePath) {
|
|
8417
|
-
if (filePath.split(
|
|
8388
|
+
if (filePath.split(path11.sep).includes("@brand")) {
|
|
8418
8389
|
return true;
|
|
8419
8390
|
}
|
|
8420
8391
|
const { type } = parseFrontmatter3(filePath);
|
|
@@ -8440,7 +8411,7 @@ function sha256(input) {
|
|
|
8440
8411
|
}
|
|
8441
8412
|
function readSafe(filePath) {
|
|
8442
8413
|
try {
|
|
8443
|
-
return
|
|
8414
|
+
return fs20.readFileSync(filePath, "utf-8");
|
|
8444
8415
|
} catch {
|
|
8445
8416
|
return "";
|
|
8446
8417
|
}
|
|
@@ -8466,9 +8437,9 @@ function readBrandManifest() {
|
|
|
8466
8437
|
function walkMdFiles2(dir) {
|
|
8467
8438
|
const results = [];
|
|
8468
8439
|
try {
|
|
8469
|
-
const entries =
|
|
8440
|
+
const entries = fs20.readdirSync(dir, { withFileTypes: true });
|
|
8470
8441
|
for (const entry of entries) {
|
|
8471
|
-
const full =
|
|
8442
|
+
const full = path11.join(dir, entry.name);
|
|
8472
8443
|
if (entry.isDirectory()) {
|
|
8473
8444
|
if (!entry.name.startsWith(".")) {
|
|
8474
8445
|
results.push(...walkMdFiles2(full));
|
|
@@ -8483,7 +8454,7 @@ function walkMdFiles2(dir) {
|
|
|
8483
8454
|
}
|
|
8484
8455
|
function parseFrontmatter3(filePath) {
|
|
8485
8456
|
try {
|
|
8486
|
-
const content =
|
|
8457
|
+
const content = fs20.readFileSync(filePath, "utf-8");
|
|
8487
8458
|
const match = content.match(/^---\n([\s\S]*?)\n---/);
|
|
8488
8459
|
if (!match) {
|
|
8489
8460
|
return { type: "" };
|
|
@@ -8701,7 +8672,7 @@ function persistBrand(brand, inputHash) {
|
|
|
8701
8672
|
}
|
|
8702
8673
|
function readCache() {
|
|
8703
8674
|
try {
|
|
8704
|
-
const raw =
|
|
8675
|
+
const raw = fs20.readFileSync(CACHE_FILE, "utf-8");
|
|
8705
8676
|
const parsed = JSON.parse(raw);
|
|
8706
8677
|
if (parsed && typeof parsed.inputHash === "string" && typeof parsed.generatedAt === "number") {
|
|
8707
8678
|
return parsed;
|
|
@@ -9780,7 +9751,11 @@ async function runTurn(params) {
|
|
|
9780
9751
|
});
|
|
9781
9752
|
break;
|
|
9782
9753
|
case "error":
|
|
9783
|
-
streamError = {
|
|
9754
|
+
streamError = {
|
|
9755
|
+
error: event.error,
|
|
9756
|
+
code: event.code,
|
|
9757
|
+
badModelId: event.badModelId
|
|
9758
|
+
};
|
|
9784
9759
|
break;
|
|
9785
9760
|
}
|
|
9786
9761
|
if (streamError) {
|
|
@@ -9830,7 +9805,7 @@ async function runTurn(params) {
|
|
|
9830
9805
|
return;
|
|
9831
9806
|
}
|
|
9832
9807
|
if (streamError) {
|
|
9833
|
-
const { error, code } = streamError;
|
|
9808
|
+
const { error, code, badModelId } = streamError;
|
|
9834
9809
|
if (code === "repetition_loop") {
|
|
9835
9810
|
if (recoveries < MAX_RECOVERIES && !signal?.aborted) {
|
|
9836
9811
|
recoveries++;
|
|
@@ -9870,6 +9845,7 @@ async function runTurn(params) {
|
|
|
9870
9845
|
type: "error",
|
|
9871
9846
|
error: friendlyError(error),
|
|
9872
9847
|
...code ? { code } : {},
|
|
9848
|
+
...badModelId ? { badModelId } : {},
|
|
9873
9849
|
lastCallInputTokens
|
|
9874
9850
|
});
|
|
9875
9851
|
return;
|
|
@@ -10676,8 +10652,8 @@ function logStartup(config, model, flagApiKey) {
|
|
|
10676
10652
|
let version = "(unknown)";
|
|
10677
10653
|
try {
|
|
10678
10654
|
version = JSON.parse(
|
|
10679
|
-
|
|
10680
|
-
|
|
10655
|
+
fs21.readFileSync(
|
|
10656
|
+
path12.join(import.meta.dirname, "..", "package.json"),
|
|
10681
10657
|
"utf-8"
|
|
10682
10658
|
)
|
|
10683
10659
|
).version;
|
|
@@ -10686,8 +10662,8 @@ function logStartup(config, model, flagApiKey) {
|
|
|
10686
10662
|
startupLog.info("Startup", {
|
|
10687
10663
|
version,
|
|
10688
10664
|
node: process.version,
|
|
10689
|
-
platform: `${
|
|
10690
|
-
os: `${
|
|
10665
|
+
platform: `${os.platform()} ${os.arch()}`,
|
|
10666
|
+
os: `${os.type()} ${os.release()}`,
|
|
10691
10667
|
cwd: process.cwd(),
|
|
10692
10668
|
bin: process.argv[1],
|
|
10693
10669
|
model: model || "(default)",
|
|
@@ -11365,7 +11341,11 @@ var HeadlessSession = class {
|
|
|
11365
11341
|
}
|
|
11366
11342
|
this.emit(
|
|
11367
11343
|
"error",
|
|
11368
|
-
{
|
|
11344
|
+
{
|
|
11345
|
+
error: e.error,
|
|
11346
|
+
...e.code ? { code: e.code } : {},
|
|
11347
|
+
...e.badModelId ? { badModelId: e.badModelId } : {}
|
|
11348
|
+
},
|
|
11369
11349
|
rid
|
|
11370
11350
|
);
|
|
11371
11351
|
return;
|