@mindstudio-ai/remy 0.1.140 → 0.1.142
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 +1 -7
- package/dist/automatedActions/approvePlan.md +5 -0
- package/dist/automatedActions/buildFromRoadmap.md +1 -1
- package/dist/automatedActions/codeCleanup.md +1 -1
- package/dist/automatedActions/rejectPlan.md +5 -0
- package/dist/automatedActions/sync.md +3 -14
- package/dist/headless.js +131 -89
- package/dist/index.js +157 -122
- package/dist/prompt/compiled/auth.md +11 -0
- package/dist/prompt/static/instructions.md +2 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -773,44 +773,22 @@ var init_listSpecFiles = __esm({
|
|
|
773
773
|
}
|
|
774
774
|
});
|
|
775
775
|
|
|
776
|
-
// src/tools/spec/
|
|
777
|
-
var
|
|
778
|
-
var
|
|
779
|
-
"src/tools/spec/
|
|
780
|
-
"use strict";
|
|
781
|
-
clearSyncStatusTool = {
|
|
782
|
-
clearable: false,
|
|
783
|
-
definition: {
|
|
784
|
-
name: "clearSyncStatus",
|
|
785
|
-
description: "Clear the sync status flags after syncing spec and code. Call this after finishing a sync operation.",
|
|
786
|
-
inputSchema: {
|
|
787
|
-
type: "object",
|
|
788
|
-
properties: {}
|
|
789
|
-
}
|
|
790
|
-
},
|
|
791
|
-
async execute() {
|
|
792
|
-
return "ok";
|
|
793
|
-
}
|
|
794
|
-
};
|
|
795
|
-
}
|
|
796
|
-
});
|
|
797
|
-
|
|
798
|
-
// src/tools/spec/presentSyncPlan.ts
|
|
799
|
-
var presentSyncPlanTool;
|
|
800
|
-
var init_presentSyncPlan = __esm({
|
|
801
|
-
"src/tools/spec/presentSyncPlan.ts"() {
|
|
776
|
+
// src/tools/spec/presentPublishPlan.ts
|
|
777
|
+
var presentPublishPlanTool;
|
|
778
|
+
var init_presentPublishPlan = __esm({
|
|
779
|
+
"src/tools/spec/presentPublishPlan.ts"() {
|
|
802
780
|
"use strict";
|
|
803
|
-
|
|
781
|
+
presentPublishPlanTool = {
|
|
804
782
|
clearable: false,
|
|
805
783
|
definition: {
|
|
806
|
-
name: "
|
|
807
|
-
description: "Present a
|
|
784
|
+
name: "presentPublishPlan",
|
|
785
|
+
description: "Present a publish changelog to the user for approval. Write a clear markdown summary of what changed since the last deploy. The user will see this in a full-screen view and can approve or dismiss. Call this BEFORE committing or pushing.",
|
|
808
786
|
inputSchema: {
|
|
809
787
|
type: "object",
|
|
810
788
|
properties: {
|
|
811
789
|
content: {
|
|
812
790
|
type: "string",
|
|
813
|
-
description: "Markdown
|
|
791
|
+
description: "Markdown changelog describing what changed and what will be deployed."
|
|
814
792
|
}
|
|
815
793
|
},
|
|
816
794
|
required: ["content"]
|
|
@@ -824,59 +802,85 @@ var init_presentSyncPlan = __esm({
|
|
|
824
802
|
}
|
|
825
803
|
});
|
|
826
804
|
|
|
827
|
-
// src/tools/spec/
|
|
828
|
-
|
|
829
|
-
var
|
|
830
|
-
|
|
805
|
+
// src/tools/spec/writePlan.ts
|
|
806
|
+
import fs6 from "fs/promises";
|
|
807
|
+
var PLAN_FILE, writePlanTool;
|
|
808
|
+
var init_writePlan = __esm({
|
|
809
|
+
"src/tools/spec/writePlan.ts"() {
|
|
831
810
|
"use strict";
|
|
832
|
-
|
|
811
|
+
PLAN_FILE = ".remy-plan.md";
|
|
812
|
+
writePlanTool = {
|
|
833
813
|
clearable: false,
|
|
834
814
|
definition: {
|
|
835
|
-
name: "
|
|
836
|
-
description: "
|
|
815
|
+
name: "writePlan",
|
|
816
|
+
description: "Write an implementation plan for user approval before making changes. Use this only for large, multi-step changes like new features, new interface types, or when the user explicitly asks to see a plan. Most work should be done autonomously without a plan. Write a clear markdown summary of what you intend to do in plain language \u2014 describe the changes from the user's perspective, not as a list of files and code paths. The plan is saved to .remy-plan.md and the user can review, discuss, and approve or reject it. If the user asks for revisions, call this tool again with updated content to overwrite the plan.",
|
|
837
817
|
inputSchema: {
|
|
838
818
|
type: "object",
|
|
839
819
|
properties: {
|
|
840
820
|
content: {
|
|
841
821
|
type: "string",
|
|
842
|
-
description: "Markdown
|
|
822
|
+
description: "Markdown plan describing what you intend to do."
|
|
843
823
|
}
|
|
844
824
|
},
|
|
845
825
|
required: ["content"]
|
|
846
826
|
}
|
|
847
827
|
},
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
828
|
+
async execute(input) {
|
|
829
|
+
const content = input.content;
|
|
830
|
+
const file = `---
|
|
831
|
+
status: pending
|
|
832
|
+
---
|
|
833
|
+
|
|
834
|
+
${content}`;
|
|
835
|
+
await fs6.writeFile(PLAN_FILE, file, "utf-8");
|
|
836
|
+
return "Plan written to .remy-plan.md. Waiting for user approval.";
|
|
851
837
|
}
|
|
852
838
|
};
|
|
853
839
|
}
|
|
854
840
|
});
|
|
855
841
|
|
|
856
|
-
// src/tools/spec/
|
|
857
|
-
|
|
858
|
-
var
|
|
859
|
-
|
|
842
|
+
// src/tools/spec/updatePlanStatus.ts
|
|
843
|
+
import fs7 from "fs/promises";
|
|
844
|
+
var PLAN_FILE2, updatePlanStatusTool;
|
|
845
|
+
var init_updatePlanStatus = __esm({
|
|
846
|
+
"src/tools/spec/updatePlanStatus.ts"() {
|
|
860
847
|
"use strict";
|
|
861
|
-
|
|
848
|
+
PLAN_FILE2 = ".remy-plan.md";
|
|
849
|
+
updatePlanStatusTool = {
|
|
862
850
|
clearable: false,
|
|
863
851
|
definition: {
|
|
864
|
-
name: "
|
|
865
|
-
description:
|
|
852
|
+
name: "updatePlanStatus",
|
|
853
|
+
description: 'Update the status of the current implementation plan. Use when the user approves or rejects the plan via chat (e.g. "looks good, go ahead" or "scrap it"). Approving sets the plan to active so you can begin implementation. Rejecting deletes the plan.',
|
|
866
854
|
inputSchema: {
|
|
867
855
|
type: "object",
|
|
868
856
|
properties: {
|
|
869
|
-
|
|
857
|
+
status: {
|
|
870
858
|
type: "string",
|
|
871
|
-
|
|
859
|
+
enum: ["approved", "rejected"],
|
|
860
|
+
description: "The new plan status."
|
|
872
861
|
}
|
|
873
862
|
},
|
|
874
|
-
required: ["
|
|
863
|
+
required: ["status"]
|
|
875
864
|
}
|
|
876
865
|
},
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
866
|
+
async execute(input) {
|
|
867
|
+
const status = input.status;
|
|
868
|
+
let content;
|
|
869
|
+
try {
|
|
870
|
+
content = await fs7.readFile(PLAN_FILE2, "utf-8");
|
|
871
|
+
} catch {
|
|
872
|
+
return "No plan file found.";
|
|
873
|
+
}
|
|
874
|
+
if (status === "rejected") {
|
|
875
|
+
await fs7.unlink(PLAN_FILE2);
|
|
876
|
+
return "Plan rejected and removed.";
|
|
877
|
+
}
|
|
878
|
+
await fs7.writeFile(
|
|
879
|
+
PLAN_FILE2,
|
|
880
|
+
content.replace(/^status:\s*\w+/m, `status: ${status}`),
|
|
881
|
+
"utf-8"
|
|
882
|
+
);
|
|
883
|
+
return "Plan approved. Proceeding with implementation.";
|
|
880
884
|
}
|
|
881
885
|
};
|
|
882
886
|
}
|
|
@@ -1058,7 +1062,7 @@ var init_confirmDestructiveAction = __esm({
|
|
|
1058
1062
|
clearable: false,
|
|
1059
1063
|
definition: {
|
|
1060
1064
|
name: "confirmDestructiveAction",
|
|
1061
|
-
description: "Confirm a destructive or irreversible action with the user. Use for things like deleting data, resetting the database, or discarding draft work. Do not use after
|
|
1065
|
+
description: "Confirm a destructive or irreversible action with the user. Use for things like deleting data, resetting the database, or discarding draft work. Do not use after presentPublishPlan or writePlan (those already include approval). Do not use before onboarding state transitions.",
|
|
1062
1066
|
inputSchema: {
|
|
1063
1067
|
type: "object",
|
|
1064
1068
|
properties: {
|
|
@@ -1279,12 +1283,12 @@ var init_setProjectMetadata = __esm({
|
|
|
1279
1283
|
});
|
|
1280
1284
|
|
|
1281
1285
|
// src/assets.ts
|
|
1282
|
-
import
|
|
1286
|
+
import fs8 from "fs";
|
|
1283
1287
|
import path3 from "path";
|
|
1284
1288
|
function findRoot(start) {
|
|
1285
1289
|
let dir = start;
|
|
1286
1290
|
while (dir !== path3.dirname(dir)) {
|
|
1287
|
-
if (
|
|
1291
|
+
if (fs8.existsSync(path3.join(dir, "package.json"))) {
|
|
1288
1292
|
return dir;
|
|
1289
1293
|
}
|
|
1290
1294
|
dir = path3.dirname(dir);
|
|
@@ -1297,7 +1301,7 @@ function assetPath(...segments) {
|
|
|
1297
1301
|
function readAsset(...segments) {
|
|
1298
1302
|
const full = assetPath(...segments);
|
|
1299
1303
|
try {
|
|
1300
|
-
return
|
|
1304
|
+
return fs8.readFileSync(full, "utf-8").trim();
|
|
1301
1305
|
} catch {
|
|
1302
1306
|
throw new Error(`Required asset missing: ${full}`);
|
|
1303
1307
|
}
|
|
@@ -1305,7 +1309,7 @@ function readAsset(...segments) {
|
|
|
1305
1309
|
function readJsonAsset(fallback, ...segments) {
|
|
1306
1310
|
const full = assetPath(...segments);
|
|
1307
1311
|
try {
|
|
1308
|
-
return JSON.parse(
|
|
1312
|
+
return JSON.parse(fs8.readFileSync(full, "utf-8"));
|
|
1309
1313
|
} catch {
|
|
1310
1314
|
return fallback;
|
|
1311
1315
|
}
|
|
@@ -1317,7 +1321,7 @@ var init_assets = __esm({
|
|
|
1317
1321
|
ROOT = findRoot(
|
|
1318
1322
|
import.meta.dirname ?? path3.dirname(new URL(import.meta.url).pathname)
|
|
1319
1323
|
);
|
|
1320
|
-
ASSETS_BASE =
|
|
1324
|
+
ASSETS_BASE = fs8.existsSync(path3.join(ROOT, "dist", "prompt")) ? path3.join(ROOT, "dist") : path3.join(ROOT, "src");
|
|
1321
1325
|
}
|
|
1322
1326
|
});
|
|
1323
1327
|
|
|
@@ -1606,12 +1610,12 @@ var init_lsp = __esm({
|
|
|
1606
1610
|
});
|
|
1607
1611
|
|
|
1608
1612
|
// src/prompt/static/projectContext.ts
|
|
1609
|
-
import
|
|
1613
|
+
import fs9 from "fs";
|
|
1610
1614
|
import path4 from "path";
|
|
1611
1615
|
function loadProjectInstructions() {
|
|
1612
1616
|
for (const file of AGENT_INSTRUCTION_FILES) {
|
|
1613
1617
|
try {
|
|
1614
|
-
const content =
|
|
1618
|
+
const content = fs9.readFileSync(file, "utf-8").trim();
|
|
1615
1619
|
if (content) {
|
|
1616
1620
|
return `
|
|
1617
1621
|
## Project Instructions (${file})
|
|
@@ -1624,7 +1628,7 @@ ${content}`;
|
|
|
1624
1628
|
}
|
|
1625
1629
|
function loadProjectManifest() {
|
|
1626
1630
|
try {
|
|
1627
|
-
const manifest =
|
|
1631
|
+
const manifest = fs9.readFileSync("mindstudio.json", "utf-8");
|
|
1628
1632
|
return `
|
|
1629
1633
|
## Project Manifest (mindstudio.json)
|
|
1630
1634
|
\`\`\`json
|
|
@@ -1665,7 +1669,7 @@ ${entries.join("\n")}`;
|
|
|
1665
1669
|
function walkMdFiles(dir) {
|
|
1666
1670
|
const results = [];
|
|
1667
1671
|
try {
|
|
1668
|
-
const entries =
|
|
1672
|
+
const entries = fs9.readdirSync(dir, { withFileTypes: true });
|
|
1669
1673
|
for (const entry of entries) {
|
|
1670
1674
|
const full = path4.join(dir, entry.name);
|
|
1671
1675
|
if (entry.isDirectory()) {
|
|
@@ -1680,7 +1684,7 @@ function walkMdFiles(dir) {
|
|
|
1680
1684
|
}
|
|
1681
1685
|
function parseFrontmatter(filePath) {
|
|
1682
1686
|
try {
|
|
1683
|
-
const content =
|
|
1687
|
+
const content = fs9.readFileSync(filePath, "utf-8");
|
|
1684
1688
|
const match = content.match(/^---\n([\s\S]*?)\n---/);
|
|
1685
1689
|
if (!match) {
|
|
1686
1690
|
return { name: "", description: "", type: "" };
|
|
@@ -1694,9 +1698,31 @@ function parseFrontmatter(filePath) {
|
|
|
1694
1698
|
return { name: "", description: "", type: "" };
|
|
1695
1699
|
}
|
|
1696
1700
|
}
|
|
1701
|
+
function loadPlanStatus() {
|
|
1702
|
+
try {
|
|
1703
|
+
const content = fs9.readFileSync(".remy-plan.md", "utf-8");
|
|
1704
|
+
const match = content.match(/^---\n([\s\S]*?)\n---/);
|
|
1705
|
+
const status = match?.[1]?.match(/^status:\s*(.+)$/m)?.[1]?.trim();
|
|
1706
|
+
if (status === "pending") {
|
|
1707
|
+
return `
|
|
1708
|
+
<pending_plan>
|
|
1709
|
+
You have a pending implementation plan in .remy-plan.md awaiting user approval. Do NOT begin implementing the plan until the user approves it. You may continue chatting, answering questions, and revising the plan if asked. To revise, call writePlan again with updated content. When the user approves the plan (via chat or any other signal), call updatePlanStatus with status "approved" before beginning any implementation work.
|
|
1710
|
+
</pending_plan>`;
|
|
1711
|
+
}
|
|
1712
|
+
if (status === "approved") {
|
|
1713
|
+
return `
|
|
1714
|
+
<approved_plan>
|
|
1715
|
+
The user has approved your implementation plan in .remy-plan.md. You may reference it during implementation. Delete the file when you have finished all planned work.
|
|
1716
|
+
</approved_plan>`;
|
|
1717
|
+
}
|
|
1718
|
+
return "";
|
|
1719
|
+
} catch {
|
|
1720
|
+
return "";
|
|
1721
|
+
}
|
|
1722
|
+
}
|
|
1697
1723
|
function loadProjectFileListing() {
|
|
1698
1724
|
try {
|
|
1699
|
-
const entries =
|
|
1725
|
+
const entries = fs9.readdirSync(".", { withFileTypes: true });
|
|
1700
1726
|
const listing = entries.filter((e) => e.name !== ".git" && e.name !== "node_modules").sort((a, b) => {
|
|
1701
1727
|
if (a.isDirectory() && !b.isDirectory()) {
|
|
1702
1728
|
return -1;
|
|
@@ -1845,7 +1871,7 @@ ${isLspConfigured() ? `<typescript_lsp>
|
|
|
1845
1871
|
</code_authoring_instructions>
|
|
1846
1872
|
|
|
1847
1873
|
{{static/instructions.md}}
|
|
1848
|
-
|
|
1874
|
+
${loadPlanStatus()}
|
|
1849
1875
|
<conversation_summaries>
|
|
1850
1876
|
Your conversation history may include <prior_conversation_summary> blocks in the user's messages. These are automated summaries of earlier messages that have been compacted to save context space. The user does not see this summary, they see the full conversation history in their UI. Treat the summary as ground truth for what happened before, but do not reference it directly to the user ("as mentioned in the summary..."). Just continue naturally as if you remember the prior work.
|
|
1851
1877
|
|
|
@@ -1884,10 +1910,10 @@ var init_prompt = __esm({
|
|
|
1884
1910
|
});
|
|
1885
1911
|
|
|
1886
1912
|
// src/session.ts
|
|
1887
|
-
import
|
|
1913
|
+
import fs10 from "fs";
|
|
1888
1914
|
function loadSession(state) {
|
|
1889
1915
|
try {
|
|
1890
|
-
const raw =
|
|
1916
|
+
const raw = fs10.readFileSync(SESSION_FILE, "utf-8");
|
|
1891
1917
|
const data = JSON.parse(raw);
|
|
1892
1918
|
if (Array.isArray(data.messages) && data.messages.length > 0) {
|
|
1893
1919
|
state.messages = sanitizeMessages(data.messages);
|
|
@@ -1936,7 +1962,7 @@ function sanitizeMessages(messages) {
|
|
|
1936
1962
|
}
|
|
1937
1963
|
function saveSession(state) {
|
|
1938
1964
|
try {
|
|
1939
|
-
|
|
1965
|
+
fs10.writeFileSync(
|
|
1940
1966
|
SESSION_FILE,
|
|
1941
1967
|
JSON.stringify({ messages: state.messages }, null, 2),
|
|
1942
1968
|
"utf-8"
|
|
@@ -1949,7 +1975,7 @@ function saveSession(state) {
|
|
|
1949
1975
|
function clearSession(state) {
|
|
1950
1976
|
state.messages = [];
|
|
1951
1977
|
try {
|
|
1952
|
-
|
|
1978
|
+
fs10.unlinkSync(SESSION_FILE);
|
|
1953
1979
|
} catch {
|
|
1954
1980
|
}
|
|
1955
1981
|
}
|
|
@@ -2023,7 +2049,7 @@ var init_compactConversation = __esm({
|
|
|
2023
2049
|
});
|
|
2024
2050
|
|
|
2025
2051
|
// src/tools/code/readFile.ts
|
|
2026
|
-
import
|
|
2052
|
+
import fs11 from "fs/promises";
|
|
2027
2053
|
function isBinary(buffer) {
|
|
2028
2054
|
const sample = buffer.subarray(0, 8192);
|
|
2029
2055
|
for (let i = 0; i < sample.length; i++) {
|
|
@@ -2064,7 +2090,7 @@ var init_readFile = __esm({
|
|
|
2064
2090
|
},
|
|
2065
2091
|
async execute(input) {
|
|
2066
2092
|
try {
|
|
2067
|
-
const buffer = await
|
|
2093
|
+
const buffer = await fs11.readFile(input.path);
|
|
2068
2094
|
if (isBinary(buffer)) {
|
|
2069
2095
|
const size = buffer.length;
|
|
2070
2096
|
const unit = size > 1024 * 1024 ? `${(size / (1024 * 1024)).toFixed(1)}MB` : `${(size / 1024).toFixed(1)}KB`;
|
|
@@ -2100,7 +2126,7 @@ var init_readFile = __esm({
|
|
|
2100
2126
|
});
|
|
2101
2127
|
|
|
2102
2128
|
// src/tools/code/writeFile.ts
|
|
2103
|
-
import
|
|
2129
|
+
import fs12 from "fs/promises";
|
|
2104
2130
|
import path5 from "path";
|
|
2105
2131
|
var writeFileTool;
|
|
2106
2132
|
var init_writeFile = __esm({
|
|
@@ -2144,7 +2170,7 @@ var init_writeFile = __esm({
|
|
|
2144
2170
|
lastNewlineCount = newlineCount;
|
|
2145
2171
|
const lastNewline = partial.content.lastIndexOf("\n");
|
|
2146
2172
|
const completeContent = partial.content.substring(0, lastNewline + 1);
|
|
2147
|
-
const oldContent = await
|
|
2173
|
+
const oldContent = await fs12.readFile(partial.path, "utf-8").catch(() => "");
|
|
2148
2174
|
return `Writing ${partial.path} (${newlineCount} lines)
|
|
2149
2175
|
${unifiedDiff(partial.path, oldContent, completeContent)}`;
|
|
2150
2176
|
}
|
|
@@ -2153,13 +2179,13 @@ ${unifiedDiff(partial.path, oldContent, completeContent)}`;
|
|
|
2153
2179
|
async execute(input) {
|
|
2154
2180
|
const release = await acquireFileLock(input.path);
|
|
2155
2181
|
try {
|
|
2156
|
-
await
|
|
2182
|
+
await fs12.mkdir(path5.dirname(input.path), { recursive: true });
|
|
2157
2183
|
let oldContent = null;
|
|
2158
2184
|
try {
|
|
2159
|
-
oldContent = await
|
|
2185
|
+
oldContent = await fs12.readFile(input.path, "utf-8");
|
|
2160
2186
|
} catch {
|
|
2161
2187
|
}
|
|
2162
|
-
await
|
|
2188
|
+
await fs12.writeFile(input.path, input.content, "utf-8");
|
|
2163
2189
|
const lineCount = input.content.split("\n").length;
|
|
2164
2190
|
const label = oldContent !== null ? "Wrote" : "Created";
|
|
2165
2191
|
return `${label} ${input.path} (${lineCount} lines)
|
|
@@ -2259,7 +2285,7 @@ var init_helpers2 = __esm({
|
|
|
2259
2285
|
});
|
|
2260
2286
|
|
|
2261
2287
|
// src/tools/code/editFile/index.ts
|
|
2262
|
-
import
|
|
2288
|
+
import fs13 from "fs/promises";
|
|
2263
2289
|
var editFileTool;
|
|
2264
2290
|
var init_editFile = __esm({
|
|
2265
2291
|
"src/tools/code/editFile/index.ts"() {
|
|
@@ -2298,7 +2324,7 @@ var init_editFile = __esm({
|
|
|
2298
2324
|
async execute(input) {
|
|
2299
2325
|
const release = await acquireFileLock(input.path);
|
|
2300
2326
|
try {
|
|
2301
|
-
const content = await
|
|
2327
|
+
const content = await fs13.readFile(input.path, "utf-8");
|
|
2302
2328
|
const { old_string, new_string, replace_all } = input;
|
|
2303
2329
|
const occurrences = findOccurrences(content, old_string);
|
|
2304
2330
|
if (replace_all) {
|
|
@@ -2314,7 +2340,7 @@ var init_editFile = __esm({
|
|
|
2314
2340
|
new_string
|
|
2315
2341
|
);
|
|
2316
2342
|
}
|
|
2317
|
-
await
|
|
2343
|
+
await fs13.writeFile(input.path, updated, "utf-8");
|
|
2318
2344
|
return `Replaced ${occurrences.length} occurrence${occurrences.length > 1 ? "s" : ""} in ${input.path}
|
|
2319
2345
|
${unifiedDiff(input.path, content, updated)}`;
|
|
2320
2346
|
}
|
|
@@ -2325,7 +2351,7 @@ ${unifiedDiff(input.path, content, updated)}`;
|
|
|
2325
2351
|
old_string.length,
|
|
2326
2352
|
new_string
|
|
2327
2353
|
);
|
|
2328
|
-
await
|
|
2354
|
+
await fs13.writeFile(input.path, updated, "utf-8");
|
|
2329
2355
|
return `Updated ${input.path}
|
|
2330
2356
|
${unifiedDiff(input.path, content, updated)}`;
|
|
2331
2357
|
}
|
|
@@ -2341,7 +2367,7 @@ ${unifiedDiff(input.path, content, updated)}`;
|
|
|
2341
2367
|
flex.matchedText.length,
|
|
2342
2368
|
new_string
|
|
2343
2369
|
);
|
|
2344
|
-
await
|
|
2370
|
+
await fs13.writeFile(input.path, updated, "utf-8");
|
|
2345
2371
|
return `Updated ${input.path} (matched with flexible whitespace at line ${flex.line})
|
|
2346
2372
|
${unifiedDiff(input.path, content, updated)}`;
|
|
2347
2373
|
}
|
|
@@ -2572,10 +2598,10 @@ var init_glob = __esm({
|
|
|
2572
2598
|
});
|
|
2573
2599
|
|
|
2574
2600
|
// src/tools/code/listDir.ts
|
|
2575
|
-
import
|
|
2601
|
+
import fs14 from "fs/promises";
|
|
2576
2602
|
import path6 from "path";
|
|
2577
2603
|
async function readAndSort(dirPath) {
|
|
2578
|
-
const entries = await
|
|
2604
|
+
const entries = await fs14.readdir(dirPath, { withFileTypes: true });
|
|
2579
2605
|
return entries.filter((e) => !EXCLUDE.has(e.name)).sort((a, b) => {
|
|
2580
2606
|
if (a.isDirectory() && !b.isDirectory()) {
|
|
2581
2607
|
return -1;
|
|
@@ -2616,7 +2642,7 @@ function formatSize(bytes) {
|
|
|
2616
2642
|
}
|
|
2617
2643
|
async function formatFile(dirPath, name, indent) {
|
|
2618
2644
|
try {
|
|
2619
|
-
const stat = await
|
|
2645
|
+
const stat = await fs14.stat(path6.join(dirPath, name));
|
|
2620
2646
|
return `${indent}${name}${" ".repeat(Math.max(1, 30 - indent.length - name.length))}${formatSize(stat.size)}`;
|
|
2621
2647
|
} catch {
|
|
2622
2648
|
return `${indent}${name}`;
|
|
@@ -3777,10 +3803,10 @@ var init_tools = __esm({
|
|
|
3777
3803
|
});
|
|
3778
3804
|
|
|
3779
3805
|
// src/subagents/browserAutomation/prompt.ts
|
|
3780
|
-
import
|
|
3806
|
+
import fs15 from "fs";
|
|
3781
3807
|
function getBrowserAutomationPrompt() {
|
|
3782
3808
|
try {
|
|
3783
|
-
const appSpec =
|
|
3809
|
+
const appSpec = fs15.readFileSync("src/app.md", "utf-8").trim();
|
|
3784
3810
|
return `${BASE_PROMPT}
|
|
3785
3811
|
|
|
3786
3812
|
<!-- cache_breakpoint -->
|
|
@@ -4744,12 +4770,12 @@ var init_tools3 = __esm({
|
|
|
4744
4770
|
});
|
|
4745
4771
|
|
|
4746
4772
|
// src/subagents/common/context.ts
|
|
4747
|
-
import
|
|
4773
|
+
import fs16 from "fs";
|
|
4748
4774
|
import path7 from "path";
|
|
4749
4775
|
function walkMdFiles2(dir, skip) {
|
|
4750
4776
|
const files = [];
|
|
4751
4777
|
try {
|
|
4752
|
-
for (const entry of
|
|
4778
|
+
for (const entry of fs16.readdirSync(dir, { withFileTypes: true })) {
|
|
4753
4779
|
const full = path7.join(dir, entry.name);
|
|
4754
4780
|
if (entry.isDirectory()) {
|
|
4755
4781
|
if (!skip?.has(entry.name)) {
|
|
@@ -4765,7 +4791,7 @@ function walkMdFiles2(dir, skip) {
|
|
|
4765
4791
|
}
|
|
4766
4792
|
function parseFrontmatter2(filePath) {
|
|
4767
4793
|
try {
|
|
4768
|
-
const content =
|
|
4794
|
+
const content = fs16.readFileSync(filePath, "utf-8");
|
|
4769
4795
|
const match = content.match(/^---\n([\s\S]*?)\n---/);
|
|
4770
4796
|
if (!match) {
|
|
4771
4797
|
return {};
|
|
@@ -4811,7 +4837,7 @@ function loadRoadmapIndex() {
|
|
|
4811
4837
|
const parts = [];
|
|
4812
4838
|
try {
|
|
4813
4839
|
const indexJson = JSON.parse(
|
|
4814
|
-
|
|
4840
|
+
fs16.readFileSync("src/roadmap/index.json", "utf-8")
|
|
4815
4841
|
);
|
|
4816
4842
|
if (indexJson.lanes?.length > 0) {
|
|
4817
4843
|
const laneLines = indexJson.lanes.map(
|
|
@@ -4919,7 +4945,7 @@ var init_context = __esm({
|
|
|
4919
4945
|
});
|
|
4920
4946
|
|
|
4921
4947
|
// src/subagents/designExpert/data/sampleCache.ts
|
|
4922
|
-
import
|
|
4948
|
+
import fs17 from "fs";
|
|
4923
4949
|
function generateIndices(poolSize, sampleSize) {
|
|
4924
4950
|
const n = Math.min(sampleSize, poolSize);
|
|
4925
4951
|
const indices = Array.from({ length: poolSize }, (_, i) => i);
|
|
@@ -4931,14 +4957,14 @@ function generateIndices(poolSize, sampleSize) {
|
|
|
4931
4957
|
}
|
|
4932
4958
|
function load() {
|
|
4933
4959
|
try {
|
|
4934
|
-
return JSON.parse(
|
|
4960
|
+
return JSON.parse(fs17.readFileSync(SAMPLE_FILE, "utf-8"));
|
|
4935
4961
|
} catch {
|
|
4936
4962
|
return null;
|
|
4937
4963
|
}
|
|
4938
4964
|
}
|
|
4939
4965
|
function save(indices) {
|
|
4940
4966
|
try {
|
|
4941
|
-
|
|
4967
|
+
fs17.writeFileSync(SAMPLE_FILE, JSON.stringify(indices));
|
|
4942
4968
|
} catch {
|
|
4943
4969
|
}
|
|
4944
4970
|
}
|
|
@@ -5335,7 +5361,7 @@ var init_tools4 = __esm({
|
|
|
5335
5361
|
});
|
|
5336
5362
|
|
|
5337
5363
|
// src/subagents/productVision/executor.ts
|
|
5338
|
-
import
|
|
5364
|
+
import fs18 from "fs";
|
|
5339
5365
|
import path8 from "path";
|
|
5340
5366
|
function resolve(filePath) {
|
|
5341
5367
|
return path8.join(ROADMAP_DIR, filePath);
|
|
@@ -5345,13 +5371,13 @@ async function executeVisionTool(name, input, context) {
|
|
|
5345
5371
|
case "writeFile": {
|
|
5346
5372
|
const filePath = resolve(input.path);
|
|
5347
5373
|
try {
|
|
5348
|
-
|
|
5374
|
+
fs18.mkdirSync(ROADMAP_DIR, { recursive: true });
|
|
5349
5375
|
let oldContent = null;
|
|
5350
5376
|
try {
|
|
5351
|
-
oldContent =
|
|
5377
|
+
oldContent = fs18.readFileSync(filePath, "utf-8");
|
|
5352
5378
|
} catch {
|
|
5353
5379
|
}
|
|
5354
|
-
|
|
5380
|
+
fs18.writeFileSync(filePath, input.content, "utf-8");
|
|
5355
5381
|
const lineCount = input.content.split("\n").length;
|
|
5356
5382
|
const label = oldContent !== null ? "Wrote" : "Created";
|
|
5357
5383
|
return `${label} ${filePath} (${lineCount} lines)
|
|
@@ -5363,11 +5389,11 @@ ${unifiedDiff(filePath, oldContent ?? "", input.content)}`;
|
|
|
5363
5389
|
case "deleteFile": {
|
|
5364
5390
|
const filePath = resolve(input.path);
|
|
5365
5391
|
try {
|
|
5366
|
-
if (!
|
|
5392
|
+
if (!fs18.existsSync(filePath)) {
|
|
5367
5393
|
return `Error: ${filePath} does not exist`;
|
|
5368
5394
|
}
|
|
5369
|
-
const oldContent =
|
|
5370
|
-
|
|
5395
|
+
const oldContent = fs18.readFileSync(filePath, "utf-8");
|
|
5396
|
+
fs18.unlinkSync(filePath);
|
|
5371
5397
|
return `Deleted ${filePath}
|
|
5372
5398
|
${unifiedDiff(filePath, oldContent, "")}`;
|
|
5373
5399
|
} catch (err) {
|
|
@@ -5380,8 +5406,8 @@ ${unifiedDiff(filePath, oldContent, "")}`;
|
|
|
5380
5406
|
}
|
|
5381
5407
|
const filePath = resolve("pitch.html");
|
|
5382
5408
|
try {
|
|
5383
|
-
|
|
5384
|
-
const existing =
|
|
5409
|
+
fs18.mkdirSync(ROADMAP_DIR, { recursive: true });
|
|
5410
|
+
const existing = fs18.existsSync(filePath) ? fs18.readFileSync(filePath, "utf-8").trim() : "";
|
|
5385
5411
|
const currentDeck = existing || PITCH_DECK_SHELL;
|
|
5386
5412
|
const task = `
|
|
5387
5413
|
<pitch_content>${input.task}</pitch_content>
|
|
@@ -5406,7 +5432,7 @@ Respond only with the complete HTML file and absolutely no other text. Your resp
|
|
|
5406
5432
|
/```(?:html|wireframe)\n([\s\S]*?)```/
|
|
5407
5433
|
);
|
|
5408
5434
|
const html = htmlMatch ? htmlMatch[1].trim() : result;
|
|
5409
|
-
|
|
5435
|
+
fs18.writeFileSync(filePath, html, "utf-8");
|
|
5410
5436
|
return `Pitch deck written successfully.`;
|
|
5411
5437
|
} catch (err) {
|
|
5412
5438
|
return `Error generating pitch deck: ${err.message}`;
|
|
@@ -5717,10 +5743,9 @@ var init_tools6 = __esm({
|
|
|
5717
5743
|
init_writeSpec();
|
|
5718
5744
|
init_editSpec();
|
|
5719
5745
|
init_listSpecFiles();
|
|
5720
|
-
init_clearSyncStatus();
|
|
5721
|
-
init_presentSyncPlan();
|
|
5722
5746
|
init_presentPublishPlan();
|
|
5723
|
-
|
|
5747
|
+
init_writePlan();
|
|
5748
|
+
init_updatePlanStatus();
|
|
5724
5749
|
init_setProjectOnboardingState();
|
|
5725
5750
|
init_promptUser();
|
|
5726
5751
|
init_confirmDestructiveAction();
|
|
@@ -5761,10 +5786,9 @@ var init_tools6 = __esm({
|
|
|
5761
5786
|
codeSanityCheckTool,
|
|
5762
5787
|
compactConversationTool,
|
|
5763
5788
|
// Post-onboarding
|
|
5764
|
-
clearSyncStatusTool,
|
|
5765
|
-
presentSyncPlanTool,
|
|
5766
5789
|
presentPublishPlanTool,
|
|
5767
|
-
|
|
5790
|
+
writePlanTool,
|
|
5791
|
+
updatePlanStatusTool,
|
|
5768
5792
|
// Spec
|
|
5769
5793
|
readSpecTool,
|
|
5770
5794
|
writeSpecTool,
|
|
@@ -6058,7 +6082,6 @@ async function runTurn(params) {
|
|
|
6058
6082
|
const STATUS_EXCLUDED_TOOLS = /* @__PURE__ */ new Set([
|
|
6059
6083
|
"setProjectOnboardingState",
|
|
6060
6084
|
"setProjectMetadata",
|
|
6061
|
-
"clearSyncStatus",
|
|
6062
6085
|
"editsFinished"
|
|
6063
6086
|
]);
|
|
6064
6087
|
let lastCompletedTools = "";
|
|
@@ -6517,10 +6540,7 @@ var init_agent = __esm({
|
|
|
6517
6540
|
EXTERNAL_TOOLS = /* @__PURE__ */ new Set([
|
|
6518
6541
|
"promptUser",
|
|
6519
6542
|
"setProjectOnboardingState",
|
|
6520
|
-
"clearSyncStatus",
|
|
6521
|
-
"presentSyncPlan",
|
|
6522
6543
|
"presentPublishPlan",
|
|
6523
|
-
"presentPlan",
|
|
6524
6544
|
"confirmDestructiveAction",
|
|
6525
6545
|
"runScenario",
|
|
6526
6546
|
"runMethod",
|
|
@@ -6532,12 +6552,12 @@ var init_agent = __esm({
|
|
|
6532
6552
|
});
|
|
6533
6553
|
|
|
6534
6554
|
// src/config.ts
|
|
6535
|
-
import
|
|
6555
|
+
import fs19 from "fs";
|
|
6536
6556
|
import path9 from "path";
|
|
6537
6557
|
import os from "os";
|
|
6538
6558
|
function loadConfigFile() {
|
|
6539
6559
|
try {
|
|
6540
|
-
const raw =
|
|
6560
|
+
const raw = fs19.readFileSync(CONFIG_PATH, "utf-8");
|
|
6541
6561
|
log9.debug("Loaded config file", { path: CONFIG_PATH });
|
|
6542
6562
|
return JSON.parse(raw);
|
|
6543
6563
|
} catch (err) {
|
|
@@ -6707,7 +6727,7 @@ __export(headless_exports, {
|
|
|
6707
6727
|
startHeadless: () => startHeadless
|
|
6708
6728
|
});
|
|
6709
6729
|
import { createInterface } from "readline";
|
|
6710
|
-
import { writeFileSync } from "fs";
|
|
6730
|
+
import { writeFileSync, readFileSync, unlinkSync } from "fs";
|
|
6711
6731
|
function emit(event, data, requestId) {
|
|
6712
6732
|
const payload = { event, ...data };
|
|
6713
6733
|
if (requestId) {
|
|
@@ -6848,8 +6868,6 @@ ${xmlParts}
|
|
|
6848
6868
|
const USER_FACING_TOOLS = /* @__PURE__ */ new Set([
|
|
6849
6869
|
"promptUser",
|
|
6850
6870
|
"confirmDestructiveAction",
|
|
6851
|
-
"presentPlan",
|
|
6852
|
-
"presentSyncPlan",
|
|
6853
6871
|
"presentPublishPlan"
|
|
6854
6872
|
]);
|
|
6855
6873
|
function resolveExternalTool(id, name, _input) {
|
|
@@ -7066,6 +7084,23 @@ ${xmlParts}
|
|
|
7066
7084
|
userMessage = resolved;
|
|
7067
7085
|
}
|
|
7068
7086
|
const isHidden = resolved !== null || !!parsed.hidden;
|
|
7087
|
+
const rawText = parsed.text ?? "";
|
|
7088
|
+
if (rawText.startsWith("@@automated::approvePlan@@")) {
|
|
7089
|
+
try {
|
|
7090
|
+
const plan = readFileSync(".remy-plan.md", "utf-8");
|
|
7091
|
+
writeFileSync(
|
|
7092
|
+
".remy-plan.md",
|
|
7093
|
+
plan.replace(/^status:\s*pending/m, "status: approved"),
|
|
7094
|
+
"utf-8"
|
|
7095
|
+
);
|
|
7096
|
+
} catch {
|
|
7097
|
+
}
|
|
7098
|
+
} else if (rawText.startsWith("@@automated::rejectPlan@@")) {
|
|
7099
|
+
try {
|
|
7100
|
+
unlinkSync(".remy-plan.md");
|
|
7101
|
+
} catch {
|
|
7102
|
+
}
|
|
7103
|
+
}
|
|
7069
7104
|
const onboardingState = parsed.onboardingState ?? "onboardingFinished";
|
|
7070
7105
|
const system = buildSystemPrompt(
|
|
7071
7106
|
onboardingState,
|
|
@@ -7263,7 +7298,7 @@ var init_headless = __esm({
|
|
|
7263
7298
|
// src/index.tsx
|
|
7264
7299
|
import { render } from "ink";
|
|
7265
7300
|
import os2 from "os";
|
|
7266
|
-
import
|
|
7301
|
+
import fs20 from "fs";
|
|
7267
7302
|
import path10 from "path";
|
|
7268
7303
|
|
|
7269
7304
|
// src/tui/App.tsx
|
|
@@ -7582,7 +7617,7 @@ for (let i = 0; i < args.length; i++) {
|
|
|
7582
7617
|
var startupLog = createLogger("startup");
|
|
7583
7618
|
function printDebugInfo(config) {
|
|
7584
7619
|
const pkg = JSON.parse(
|
|
7585
|
-
|
|
7620
|
+
fs20.readFileSync(
|
|
7586
7621
|
path10.join(import.meta.dirname, "..", "package.json"),
|
|
7587
7622
|
"utf-8"
|
|
7588
7623
|
)
|