rrce-workflow 0.2.77 → 0.2.79
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/agent-core/prompts/doctor.md +20 -4
- package/agent-core/prompts/executor.md +224 -56
- package/agent-core/prompts/init.md +2 -1
- package/agent-core/prompts/planning_discussion.md +292 -0
- package/agent-core/prompts/research_discussion.md +167 -65
- package/agent-core/templates/planning_output.md +154 -29
- package/agent-core/templates/research_output.md +134 -32
- package/dist/index.js +347 -56
- package/docs/architecture.md +14 -0
- package/package.json +1 -1
- package/agent-core/prompts/planning_orchestrator.md +0 -85
package/dist/index.js
CHANGED
|
@@ -1032,14 +1032,15 @@ function isVSCodeInstalled() {
|
|
|
1032
1032
|
const configDir = path6.join(os.homedir(), ".config/Code/User");
|
|
1033
1033
|
return fs5.existsSync(configDir);
|
|
1034
1034
|
}
|
|
1035
|
-
var ANTIGRAVITY_CONFIG, CLAUDE_CONFIG, VSCODE_GLOBAL_CONFIG, OPENCODE_CONFIG;
|
|
1035
|
+
var ANTIGRAVITY_CONFIG, CLAUDE_CONFIG, VSCODE_GLOBAL_CONFIG, OPENCODE_CONFIG_DIR, OPENCODE_CONFIG;
|
|
1036
1036
|
var init_install = __esm({
|
|
1037
1037
|
"src/mcp/install.ts"() {
|
|
1038
1038
|
"use strict";
|
|
1039
1039
|
ANTIGRAVITY_CONFIG = path6.join(os.homedir(), ".gemini/antigravity/mcp_config.json");
|
|
1040
1040
|
CLAUDE_CONFIG = path6.join(os.homedir(), ".config/claude/claude_desktop_config.json");
|
|
1041
1041
|
VSCODE_GLOBAL_CONFIG = path6.join(os.homedir(), ".config/Code/User/settings.json");
|
|
1042
|
-
|
|
1042
|
+
OPENCODE_CONFIG_DIR = path6.join(os.homedir(), ".config/opencode");
|
|
1043
|
+
OPENCODE_CONFIG = path6.join(OPENCODE_CONFIG_DIR, "opencode.json");
|
|
1043
1044
|
}
|
|
1044
1045
|
});
|
|
1045
1046
|
|
|
@@ -1249,7 +1250,7 @@ var init_prompts = __esm({
|
|
|
1249
1250
|
// src/commands/wizard/utils.ts
|
|
1250
1251
|
import * as fs7 from "fs";
|
|
1251
1252
|
import * as path8 from "path";
|
|
1252
|
-
import
|
|
1253
|
+
import "yaml";
|
|
1253
1254
|
function copyPromptsToDir(prompts, targetDir, extension) {
|
|
1254
1255
|
for (const prompt of prompts) {
|
|
1255
1256
|
const baseName = path8.basename(prompt.filePath, ".md");
|
|
@@ -1261,29 +1262,24 @@ function copyPromptsToDir(prompts, targetDir, extension) {
|
|
|
1261
1262
|
}
|
|
1262
1263
|
function convertToOpenCodeAgent(prompt) {
|
|
1263
1264
|
const { frontmatter, content } = prompt;
|
|
1264
|
-
const tools = {
|
|
1265
|
-
|
|
1266
|
-
"read": true,
|
|
1267
|
-
"write": true,
|
|
1268
|
-
"edit": true,
|
|
1269
|
-
"bash": true,
|
|
1270
|
-
"grep": true,
|
|
1271
|
-
"glob": true,
|
|
1272
|
-
"webfetch": true
|
|
1273
|
-
};
|
|
1265
|
+
const tools = {};
|
|
1266
|
+
const hostTools = ["read", "write", "edit", "bash", "grep", "glob", "webfetch", "terminalLastCommand"];
|
|
1274
1267
|
if (frontmatter.tools) {
|
|
1275
1268
|
for (const tool of frontmatter.tools) {
|
|
1276
|
-
|
|
1269
|
+
if (hostTools.includes(tool)) {
|
|
1270
|
+
tools[tool] = true;
|
|
1271
|
+
} else {
|
|
1272
|
+
tools[`rrce_${tool}`] = true;
|
|
1273
|
+
}
|
|
1277
1274
|
}
|
|
1278
1275
|
}
|
|
1279
|
-
|
|
1276
|
+
tools["webfetch"] = true;
|
|
1277
|
+
return {
|
|
1280
1278
|
description: frontmatter.description,
|
|
1281
1279
|
mode: "primary",
|
|
1280
|
+
prompt: content,
|
|
1282
1281
|
tools
|
|
1283
1282
|
};
|
|
1284
|
-
return `---
|
|
1285
|
-
${stringify(opencodeFrontmatter)}---
|
|
1286
|
-
${content}`;
|
|
1287
1283
|
}
|
|
1288
1284
|
function copyDirRecursive(src, dest) {
|
|
1289
1285
|
const entries = fs7.readdirSync(src, { withFileTypes: true });
|
|
@@ -1657,6 +1653,7 @@ import * as fs10 from "fs";
|
|
|
1657
1653
|
import * as path12 from "path";
|
|
1658
1654
|
import pc4 from "picocolors";
|
|
1659
1655
|
import { note as note2 } from "@clack/prompts";
|
|
1656
|
+
import { stringify as stringify2 } from "yaml";
|
|
1660
1657
|
function createDirectoryStructure(dataPaths) {
|
|
1661
1658
|
for (const dataPath of dataPaths) {
|
|
1662
1659
|
ensureDir(dataPath);
|
|
@@ -1666,7 +1663,7 @@ function createDirectoryStructure(dataPaths) {
|
|
|
1666
1663
|
ensureDir(path12.join(dataPath, "templates"));
|
|
1667
1664
|
}
|
|
1668
1665
|
}
|
|
1669
|
-
function installAgentPrompts(config, workspacePath, dataPaths) {
|
|
1666
|
+
async function installAgentPrompts(config, workspacePath, dataPaths) {
|
|
1670
1667
|
const agentCoreDir = getAgentCoreDir();
|
|
1671
1668
|
syncMetadataToAll(agentCoreDir, dataPaths);
|
|
1672
1669
|
copyDirToAllStoragePaths(path12.join(agentCoreDir, "templates"), "templates", dataPaths);
|
|
@@ -1695,30 +1692,36 @@ function installAgentPrompts(config, workspacePath, dataPaths) {
|
|
|
1695
1692
|
if (config.tools.includes("opencode")) {
|
|
1696
1693
|
const primaryDataPath = dataPaths[0];
|
|
1697
1694
|
if (primaryDataPath) {
|
|
1698
|
-
const opencodePath = path12.join(primaryDataPath, ".opencode", "agent");
|
|
1699
|
-
ensureDir(opencodePath);
|
|
1700
|
-
for (const prompt of prompts) {
|
|
1701
|
-
const baseName = path12.basename(prompt.filePath, ".md");
|
|
1702
|
-
const content = convertToOpenCodeAgent(prompt);
|
|
1703
|
-
fs10.writeFileSync(path12.join(opencodePath, `${baseName}.md`), content);
|
|
1704
|
-
}
|
|
1705
1695
|
if (config.storageMode === "global") {
|
|
1706
|
-
const workspaceOpencode = path12.join(workspacePath, ".opencode");
|
|
1707
|
-
const globalOpencode = path12.join(primaryDataPath, ".opencode");
|
|
1708
1696
|
try {
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
try {
|
|
1713
|
-
if (fs10.lstatSync(workspaceOpencode).isSymbolicLink()) {
|
|
1714
|
-
fs10.unlinkSync(workspaceOpencode);
|
|
1715
|
-
}
|
|
1716
|
-
} catch (e) {
|
|
1717
|
-
}
|
|
1697
|
+
let opencodeConfig = { $schema: "https://opencode.ai/config.json" };
|
|
1698
|
+
if (fs10.existsSync(OPENCODE_CONFIG)) {
|
|
1699
|
+
opencodeConfig = JSON.parse(fs10.readFileSync(OPENCODE_CONFIG, "utf-8"));
|
|
1718
1700
|
}
|
|
1719
|
-
|
|
1701
|
+
if (!opencodeConfig.agent) opencodeConfig.agent = {};
|
|
1702
|
+
for (const prompt of prompts) {
|
|
1703
|
+
const baseName = path12.basename(prompt.filePath, ".md");
|
|
1704
|
+
const agentConfig = convertToOpenCodeAgent(prompt);
|
|
1705
|
+
opencodeConfig.agent[baseName] = agentConfig;
|
|
1706
|
+
}
|
|
1707
|
+
fs10.writeFileSync(OPENCODE_CONFIG, JSON.stringify(opencodeConfig, null, 2) + "\n");
|
|
1720
1708
|
} catch (e) {
|
|
1721
|
-
console.error(
|
|
1709
|
+
console.error("Failed to update global OpenCode config with agents:", e);
|
|
1710
|
+
}
|
|
1711
|
+
} else {
|
|
1712
|
+
const opencodeBaseDir = path12.join(primaryDataPath, ".opencode", "agent");
|
|
1713
|
+
ensureDir(opencodeBaseDir);
|
|
1714
|
+
for (const prompt of prompts) {
|
|
1715
|
+
const baseName = path12.basename(prompt.filePath, ".md");
|
|
1716
|
+
const agentConfig = convertToOpenCodeAgent(prompt);
|
|
1717
|
+
const content = `---
|
|
1718
|
+
${stringify2({
|
|
1719
|
+
description: agentConfig.description,
|
|
1720
|
+
mode: agentConfig.mode,
|
|
1721
|
+
tools: agentConfig.tools
|
|
1722
|
+
})}---
|
|
1723
|
+
${agentConfig.prompt}`;
|
|
1724
|
+
fs10.writeFileSync(path12.join(opencodeBaseDir, `${baseName}.md`), content);
|
|
1722
1725
|
}
|
|
1723
1726
|
}
|
|
1724
1727
|
}
|
|
@@ -1857,13 +1860,15 @@ function updateGitignore(workspacePath, storageMode, tools) {
|
|
|
1857
1860
|
const entries = [];
|
|
1858
1861
|
if (storageMode === "workspace") {
|
|
1859
1862
|
entries.push(".rrce-workflow/");
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1863
|
+
if (tools.includes("opencode")) {
|
|
1864
|
+
entries.push(".opencode/");
|
|
1865
|
+
}
|
|
1866
|
+
if (tools.includes("copilot")) {
|
|
1867
|
+
entries.push(".github/agents/");
|
|
1868
|
+
}
|
|
1869
|
+
if (tools.includes("antigravity")) {
|
|
1870
|
+
entries.push(".agent/workflows/");
|
|
1871
|
+
}
|
|
1867
1872
|
}
|
|
1868
1873
|
entries.push("*.code-workspace");
|
|
1869
1874
|
if (entries.length === 0) {
|
|
@@ -2206,6 +2211,7 @@ var init_rag = __esm({
|
|
|
2206
2211
|
// src/mcp/resources.ts
|
|
2207
2212
|
import * as fs14 from "fs";
|
|
2208
2213
|
import * as path16 from "path";
|
|
2214
|
+
import * as crypto from "crypto";
|
|
2209
2215
|
function getExposedProjects() {
|
|
2210
2216
|
const config = loadMCPConfig();
|
|
2211
2217
|
const knownPaths = config.projects.map((p) => p.path).filter((p) => !!p);
|
|
@@ -2526,9 +2532,101 @@ All file operations should be relative to WORKSPACE_ROOT shown above.
|
|
|
2526
2532
|
`;
|
|
2527
2533
|
return contextPreamble;
|
|
2528
2534
|
}
|
|
2535
|
+
function getTask(projectName, taskSlug) {
|
|
2536
|
+
const config = loadMCPConfig();
|
|
2537
|
+
const projects = projectService.scan();
|
|
2538
|
+
const project = projects.find((p) => p.name === projectName && isProjectExposed(config, p.name, p.path));
|
|
2539
|
+
if (!project || !project.tasksPath) return null;
|
|
2540
|
+
const metaPath = path16.join(project.tasksPath, taskSlug, "meta.json");
|
|
2541
|
+
if (!fs14.existsSync(metaPath)) return null;
|
|
2542
|
+
try {
|
|
2543
|
+
return JSON.parse(fs14.readFileSync(metaPath, "utf-8"));
|
|
2544
|
+
} catch {
|
|
2545
|
+
return null;
|
|
2546
|
+
}
|
|
2547
|
+
}
|
|
2548
|
+
async function createTask(projectName, taskSlug, taskData) {
|
|
2549
|
+
const config = loadMCPConfig();
|
|
2550
|
+
const projects = projectService.scan();
|
|
2551
|
+
const project = projects.find((p) => p.name === projectName && isProjectExposed(config, p.name, p.path));
|
|
2552
|
+
if (!project || !project.tasksPath) {
|
|
2553
|
+
throw new Error(`Project '${projectName}' not found or not configured with a tasks path.`);
|
|
2554
|
+
}
|
|
2555
|
+
const taskDir = path16.join(project.tasksPath, taskSlug);
|
|
2556
|
+
if (fs14.existsSync(taskDir)) {
|
|
2557
|
+
throw new Error(`Task with slug '${taskSlug}' already exists.`);
|
|
2558
|
+
}
|
|
2559
|
+
fs14.mkdirSync(taskDir, { recursive: true });
|
|
2560
|
+
fs14.mkdirSync(path16.join(taskDir, "research"), { recursive: true });
|
|
2561
|
+
fs14.mkdirSync(path16.join(taskDir, "planning"), { recursive: true });
|
|
2562
|
+
fs14.mkdirSync(path16.join(taskDir, "execution"), { recursive: true });
|
|
2563
|
+
fs14.mkdirSync(path16.join(taskDir, "docs"), { recursive: true });
|
|
2564
|
+
const rrceHome = process.env.RRCE_HOME || path16.join(__require("os").homedir(), ".rrce-workflow");
|
|
2565
|
+
const templatePath = path16.join(rrceHome, "templates", "meta.template.json");
|
|
2566
|
+
let meta = {
|
|
2567
|
+
task_id: crypto.randomUUID(),
|
|
2568
|
+
task_slug: taskSlug,
|
|
2569
|
+
status: "draft",
|
|
2570
|
+
agents: {}
|
|
2571
|
+
};
|
|
2572
|
+
if (fs14.existsSync(templatePath)) {
|
|
2573
|
+
try {
|
|
2574
|
+
const template = JSON.parse(fs14.readFileSync(templatePath, "utf-8"));
|
|
2575
|
+
meta = { ...template, ...meta };
|
|
2576
|
+
} catch (e) {
|
|
2577
|
+
logger.error("Failed to load meta template", e);
|
|
2578
|
+
}
|
|
2579
|
+
}
|
|
2580
|
+
meta.created_at = (/* @__PURE__ */ new Date()).toISOString();
|
|
2581
|
+
meta.updated_at = meta.created_at;
|
|
2582
|
+
meta.workspace = {
|
|
2583
|
+
name: project.name,
|
|
2584
|
+
path: project.path || project.dataPath,
|
|
2585
|
+
hash: project.name
|
|
2586
|
+
};
|
|
2587
|
+
Object.assign(meta, taskData);
|
|
2588
|
+
const metaPath = path16.join(taskDir, "meta.json");
|
|
2589
|
+
fs14.writeFileSync(metaPath, JSON.stringify(meta, null, 2));
|
|
2590
|
+
return meta;
|
|
2591
|
+
}
|
|
2592
|
+
async function updateTask(projectName, taskSlug, taskData) {
|
|
2593
|
+
const meta = getTask(projectName, taskSlug);
|
|
2594
|
+
if (!meta) throw new Error(`Task '${taskSlug}' not found.`);
|
|
2595
|
+
const updatedMeta = {
|
|
2596
|
+
...meta,
|
|
2597
|
+
...taskData,
|
|
2598
|
+
updated_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2599
|
+
// Ensure nested objects are merged if they exist in taskData
|
|
2600
|
+
agents: taskData.agents ? { ...meta.agents, ...taskData.agents } : meta.agents,
|
|
2601
|
+
workspace: meta.workspace
|
|
2602
|
+
// Protect workspace metadata
|
|
2603
|
+
};
|
|
2604
|
+
const config = loadMCPConfig();
|
|
2605
|
+
const projects = projectService.scan();
|
|
2606
|
+
const project = projects.find((p) => p.name === projectName && isProjectExposed(config, p.name, p.path));
|
|
2607
|
+
if (!project || !project.tasksPath) return null;
|
|
2608
|
+
const metaPath = path16.join(project.tasksPath, taskSlug, "meta.json");
|
|
2609
|
+
fs14.writeFileSync(metaPath, JSON.stringify(updatedMeta, null, 2));
|
|
2610
|
+
return updatedMeta;
|
|
2611
|
+
}
|
|
2612
|
+
function deleteTask(projectName, taskSlug) {
|
|
2613
|
+
const config = loadMCPConfig();
|
|
2614
|
+
const projects = projectService.scan();
|
|
2615
|
+
const project = projects.find((p) => p.name === projectName && isProjectExposed(config, p.name, p.path));
|
|
2616
|
+
if (!project || !project.tasksPath) return false;
|
|
2617
|
+
const taskDir = path16.join(project.tasksPath, taskSlug);
|
|
2618
|
+
if (!fs14.existsSync(taskDir)) return false;
|
|
2619
|
+
if (fs14.rmSync) {
|
|
2620
|
+
fs14.rmSync(taskDir, { recursive: true, force: true });
|
|
2621
|
+
} else {
|
|
2622
|
+
fs14.rmdirSync(taskDir, { recursive: true });
|
|
2623
|
+
}
|
|
2624
|
+
return true;
|
|
2625
|
+
}
|
|
2529
2626
|
var init_resources = __esm({
|
|
2530
2627
|
"src/mcp/resources.ts"() {
|
|
2531
2628
|
"use strict";
|
|
2629
|
+
init_logger();
|
|
2532
2630
|
init_config();
|
|
2533
2631
|
init_config_utils();
|
|
2534
2632
|
init_detection();
|
|
@@ -2771,6 +2869,66 @@ function registerToolHandlers(server) {
|
|
|
2771
2869
|
},
|
|
2772
2870
|
required: ["agent"]
|
|
2773
2871
|
}
|
|
2872
|
+
},
|
|
2873
|
+
{
|
|
2874
|
+
name: "list_tasks",
|
|
2875
|
+
description: "List all tasks for a project",
|
|
2876
|
+
inputSchema: {
|
|
2877
|
+
type: "object",
|
|
2878
|
+
properties: { project: { type: "string", description: "Name of the project" } },
|
|
2879
|
+
required: ["project"]
|
|
2880
|
+
}
|
|
2881
|
+
},
|
|
2882
|
+
{
|
|
2883
|
+
name: "get_task",
|
|
2884
|
+
description: "Get details of a specific task",
|
|
2885
|
+
inputSchema: {
|
|
2886
|
+
type: "object",
|
|
2887
|
+
properties: {
|
|
2888
|
+
project: { type: "string", description: "Name of the project" },
|
|
2889
|
+
task_slug: { type: "string", description: "The slug of the task" }
|
|
2890
|
+
},
|
|
2891
|
+
required: ["project", "task_slug"]
|
|
2892
|
+
}
|
|
2893
|
+
},
|
|
2894
|
+
{
|
|
2895
|
+
name: "create_task",
|
|
2896
|
+
description: "Create a new task in the project",
|
|
2897
|
+
inputSchema: {
|
|
2898
|
+
type: "object",
|
|
2899
|
+
properties: {
|
|
2900
|
+
project: { type: "string", description: "Name of the project" },
|
|
2901
|
+
task_slug: { type: "string", description: "The slug for the new task (kebab-case)" },
|
|
2902
|
+
title: { type: "string", description: "The title of the task" },
|
|
2903
|
+
summary: { type: "string", description: "Brief summary of the task" }
|
|
2904
|
+
},
|
|
2905
|
+
required: ["project", "task_slug"]
|
|
2906
|
+
}
|
|
2907
|
+
},
|
|
2908
|
+
{
|
|
2909
|
+
name: "update_task",
|
|
2910
|
+
description: "Update an existing task",
|
|
2911
|
+
inputSchema: {
|
|
2912
|
+
type: "object",
|
|
2913
|
+
properties: {
|
|
2914
|
+
project: { type: "string", description: "Name of the project" },
|
|
2915
|
+
task_slug: { type: "string", description: "The slug of the task" },
|
|
2916
|
+
updates: { type: "object", description: "The fields to update in meta.json", additionalProperties: true }
|
|
2917
|
+
},
|
|
2918
|
+
required: ["project", "task_slug", "updates"]
|
|
2919
|
+
}
|
|
2920
|
+
},
|
|
2921
|
+
{
|
|
2922
|
+
name: "delete_task",
|
|
2923
|
+
description: "Delete a task from the project",
|
|
2924
|
+
inputSchema: {
|
|
2925
|
+
type: "object",
|
|
2926
|
+
properties: {
|
|
2927
|
+
project: { type: "string", description: "Name of the project" },
|
|
2928
|
+
task_slug: { type: "string", description: "The slug of the task to delete" }
|
|
2929
|
+
},
|
|
2930
|
+
required: ["project", "task_slug"]
|
|
2931
|
+
}
|
|
2774
2932
|
}
|
|
2775
2933
|
];
|
|
2776
2934
|
const projects = getExposedProjects();
|
|
@@ -2858,6 +3016,38 @@ The system has pre-resolved the configuration for this project. Use these values
|
|
|
2858
3016
|
`;
|
|
2859
3017
|
return { content: [{ type: "text", text: contextPreamble + rendered }] };
|
|
2860
3018
|
}
|
|
3019
|
+
case "list_tasks": {
|
|
3020
|
+
const params = args;
|
|
3021
|
+
const tasks = getProjectTasks(params.project);
|
|
3022
|
+
return { content: [{ type: "text", text: JSON.stringify(tasks, null, 2) }] };
|
|
3023
|
+
}
|
|
3024
|
+
case "get_task": {
|
|
3025
|
+
const params = args;
|
|
3026
|
+
const task = getTask(params.project, params.task_slug);
|
|
3027
|
+
if (!task) {
|
|
3028
|
+
return { content: [{ type: "text", text: `Task '${params.task_slug}' not found in project '${params.project}'.` }], isError: true };
|
|
3029
|
+
}
|
|
3030
|
+
return { content: [{ type: "text", text: JSON.stringify(task, null, 2) }] };
|
|
3031
|
+
}
|
|
3032
|
+
case "create_task": {
|
|
3033
|
+
const params = args;
|
|
3034
|
+
const taskData = {
|
|
3035
|
+
title: params.title || params.task_slug,
|
|
3036
|
+
summary: params.summary || ""
|
|
3037
|
+
};
|
|
3038
|
+
const task = await createTask(params.project, params.task_slug, taskData);
|
|
3039
|
+
return { content: [{ type: "text", text: JSON.stringify(task, null, 2) }] };
|
|
3040
|
+
}
|
|
3041
|
+
case "update_task": {
|
|
3042
|
+
const params = args;
|
|
3043
|
+
const task = await updateTask(params.project, params.task_slug, params.updates);
|
|
3044
|
+
return { content: [{ type: "text", text: JSON.stringify(task, null, 2) }] };
|
|
3045
|
+
}
|
|
3046
|
+
case "delete_task": {
|
|
3047
|
+
const params = args;
|
|
3048
|
+
const success = deleteTask(params.project, params.task_slug);
|
|
3049
|
+
return { content: [{ type: "text", text: success ? `Task '${params.task_slug}' deleted.` : `Failed to delete task '${params.task_slug}'.` }] };
|
|
3050
|
+
}
|
|
2861
3051
|
case "help_setup": {
|
|
2862
3052
|
const msg = `
|
|
2863
3053
|
RRCE MCP Server is running, but no projects are configured/exposed.
|
|
@@ -4363,8 +4553,8 @@ async function runExpressSetup(workspacePath, workspaceName, existingProjects, s
|
|
|
4363
4553
|
\u2022 Storage: ${storageMode === "global" ? "Global" : "Workspace"}
|
|
4364
4554
|
\u2022 MCP Server: Enabled
|
|
4365
4555
|
\u2022 Semantic Search (RAG): Enabled
|
|
4366
|
-
|
|
4367
|
-
|
|
4556
|
+
` + (storageMode === "workspace" ? `\u2022 Git ignore entries: Added
|
|
4557
|
+
` : "") + `\u2022 AI Tools: ${toolsText}`,
|
|
4368
4558
|
"Configuration Preview"
|
|
4369
4559
|
);
|
|
4370
4560
|
const confirmed = await confirm6({
|
|
@@ -4389,6 +4579,10 @@ async function runExpressSetup(workspacePath, workspaceName, existingProjects, s
|
|
|
4389
4579
|
enableRAG: true
|
|
4390
4580
|
};
|
|
4391
4581
|
await executeSetup(config, workspacePath, workspaceName, existingProjects, s);
|
|
4582
|
+
if (config.storageMode === "workspace") {
|
|
4583
|
+
const { updateGitignore: updateGitignore2 } = await Promise.resolve().then(() => (init_gitignore(), gitignore_exports));
|
|
4584
|
+
updateGitignore2(workspacePath, config.storageMode, config.tools);
|
|
4585
|
+
}
|
|
4392
4586
|
const startMCP = await confirm6({
|
|
4393
4587
|
message: "Start MCP server now?",
|
|
4394
4588
|
initialValue: true
|
|
@@ -4432,7 +4626,7 @@ async function runSetupFlow(workspacePath, workspaceName, existingProjects) {
|
|
|
4432
4626
|
if (storageMode !== "global") {
|
|
4433
4627
|
linkedProjects = await promptLinkedProjects(existingProjects);
|
|
4434
4628
|
}
|
|
4435
|
-
const addToGitignore = await promptGitignore();
|
|
4629
|
+
const addToGitignore = storageMode === "workspace" ? await promptGitignore() : false;
|
|
4436
4630
|
const enableRAG = await promptRAG();
|
|
4437
4631
|
const confirmed = await promptConfirmation();
|
|
4438
4632
|
if (!confirmed) {
|
|
@@ -4449,6 +4643,10 @@ async function runSetupFlow(workspacePath, workspaceName, existingProjects) {
|
|
|
4449
4643
|
enableRAG
|
|
4450
4644
|
};
|
|
4451
4645
|
await executeSetup(config, workspacePath, workspaceName, existingProjects, s);
|
|
4646
|
+
if (config.storageMode === "workspace" && config.addToGitignore) {
|
|
4647
|
+
const { updateGitignore: updateGitignore2 } = await Promise.resolve().then(() => (init_gitignore(), gitignore_exports));
|
|
4648
|
+
updateGitignore2(workspacePath, config.storageMode, config.tools);
|
|
4649
|
+
}
|
|
4452
4650
|
await handlePostSetup(config, workspacePath, workspaceName, linkedProjects);
|
|
4453
4651
|
}
|
|
4454
4652
|
async function executeSetup(config, workspacePath, workspaceName, allProjects, s) {
|
|
@@ -4456,9 +4654,9 @@ async function executeSetup(config, workspacePath, workspaceName, allProjects, s
|
|
|
4456
4654
|
try {
|
|
4457
4655
|
const dataPaths = getDataPaths(config.storageMode, workspaceName, workspacePath, config.globalPath);
|
|
4458
4656
|
createDirectoryStructure(dataPaths);
|
|
4459
|
-
installAgentPrompts(config, workspacePath, dataPaths);
|
|
4657
|
+
await installAgentPrompts(config, workspacePath, dataPaths);
|
|
4460
4658
|
createWorkspaceConfig(config, workspacePath, workspaceName);
|
|
4461
|
-
if (config.addToGitignore) {
|
|
4659
|
+
if (config.storageMode === "workspace" && config.addToGitignore) {
|
|
4462
4660
|
const { updateGitignore: updateGitignore2 } = await Promise.resolve().then(() => (init_gitignore(), gitignore_exports));
|
|
4463
4661
|
updateGitignore2(workspacePath, config.storageMode, config.tools);
|
|
4464
4662
|
}
|
|
@@ -4713,6 +4911,7 @@ import { confirm as confirm9, spinner as spinner6, note as note12, outro as outr
|
|
|
4713
4911
|
import pc14 from "picocolors";
|
|
4714
4912
|
import * as fs18 from "fs";
|
|
4715
4913
|
import * as path19 from "path";
|
|
4914
|
+
import { stringify as stringify3 } from "yaml";
|
|
4716
4915
|
async function runUpdateFlow(workspacePath, workspaceName, currentStorageMode) {
|
|
4717
4916
|
const s = spinner6();
|
|
4718
4917
|
s.start("Checking for updates");
|
|
@@ -4723,10 +4922,25 @@ async function runUpdateFlow(workspacePath, workspaceName, currentStorageMode) {
|
|
|
4723
4922
|
const customGlobalPath = getEffectiveRRCEHome(workspacePath);
|
|
4724
4923
|
const dataPaths = resolveAllDataPathsWithCustomGlobal(mode, workspaceName, workspacePath, customGlobalPath);
|
|
4725
4924
|
s.stop("Updates found");
|
|
4925
|
+
const updateTargets = [
|
|
4926
|
+
` \u2022 prompts/ (${prompts.length} agent prompts)`,
|
|
4927
|
+
` \u2022 templates/ (output templates)`,
|
|
4928
|
+
` \u2022 docs/ (documentation)`
|
|
4929
|
+
];
|
|
4930
|
+
const configFilePath = getConfigPath(workspacePath);
|
|
4931
|
+
const ideTargets = [];
|
|
4932
|
+
if (fs18.existsSync(configFilePath)) {
|
|
4933
|
+
const configContent = fs18.readFileSync(configFilePath, "utf-8");
|
|
4934
|
+
if (configContent.includes("opencode: true")) ideTargets.push("OpenCode agents");
|
|
4935
|
+
if (configContent.includes("copilot: true")) ideTargets.push("GitHub Copilot");
|
|
4936
|
+
if (configContent.includes("antigravity: true")) ideTargets.push("Antigravity");
|
|
4937
|
+
}
|
|
4938
|
+
if (ideTargets.length > 0) {
|
|
4939
|
+
updateTargets.push(` \u2022 IDE integrations: ${ideTargets.join(", ")}`);
|
|
4940
|
+
}
|
|
4726
4941
|
note12(
|
|
4727
4942
|
`The following will be updated from the package:
|
|
4728
|
-
|
|
4729
|
-
\u2022 templates/ (output templates)
|
|
4943
|
+
${updateTargets.join("\n")}
|
|
4730
4944
|
|
|
4731
4945
|
Target locations:
|
|
4732
4946
|
${dataPaths.map((p) => ` \u2022 ${p}`).join("\n")}`,
|
|
@@ -4743,29 +4957,51 @@ ${dataPaths.map((p) => ` \u2022 ${p}`).join("\n")}`,
|
|
|
4743
4957
|
s.start("Updating from package");
|
|
4744
4958
|
for (const dataPath of dataPaths) {
|
|
4745
4959
|
copyDirToAllStoragePaths(path19.join(agentCoreDir, "templates"), "templates", [dataPath]);
|
|
4960
|
+
copyDirToAllStoragePaths(path19.join(agentCoreDir, "prompts"), "prompts", [dataPath]);
|
|
4961
|
+
copyDirToAllStoragePaths(path19.join(agentCoreDir, "docs"), "docs", [dataPath]);
|
|
4746
4962
|
}
|
|
4747
|
-
const
|
|
4963
|
+
const rrceHome = customGlobalPath || getDefaultRRCEHome2();
|
|
4964
|
+
ensureDir(path19.join(rrceHome, "templates"));
|
|
4965
|
+
ensureDir(path19.join(rrceHome, "docs"));
|
|
4966
|
+
copyDirRecursive(path19.join(agentCoreDir, "templates"), path19.join(rrceHome, "templates"));
|
|
4967
|
+
copyDirRecursive(path19.join(agentCoreDir, "docs"), path19.join(rrceHome, "docs"));
|
|
4748
4968
|
if (fs18.existsSync(configFilePath)) {
|
|
4749
4969
|
const configContent = fs18.readFileSync(configFilePath, "utf-8");
|
|
4750
4970
|
if (configContent.includes("copilot: true")) {
|
|
4751
4971
|
const copilotPath = getAgentPromptPath(workspacePath, "copilot");
|
|
4752
4972
|
ensureDir(copilotPath);
|
|
4973
|
+
clearDirectory(copilotPath);
|
|
4753
4974
|
copyPromptsToDir(prompts, copilotPath, ".agent.md");
|
|
4754
4975
|
}
|
|
4755
4976
|
if (configContent.includes("antigravity: true")) {
|
|
4756
4977
|
const antigravityPath = getAgentPromptPath(workspacePath, "antigravity");
|
|
4757
4978
|
ensureDir(antigravityPath);
|
|
4979
|
+
clearDirectory(antigravityPath);
|
|
4758
4980
|
copyPromptsToDir(prompts, antigravityPath, ".md");
|
|
4759
4981
|
}
|
|
4982
|
+
if (configContent.includes("opencode: true")) {
|
|
4983
|
+
const primaryDataPath = dataPaths[0];
|
|
4984
|
+
if (primaryDataPath) {
|
|
4985
|
+
updateOpenCodeAgents(prompts, mode, primaryDataPath);
|
|
4986
|
+
}
|
|
4987
|
+
}
|
|
4760
4988
|
}
|
|
4761
4989
|
s.stop("Update complete");
|
|
4762
4990
|
const summary = [
|
|
4763
4991
|
`Updated:`,
|
|
4764
4992
|
` \u2713 ${prompts.length} agent prompts`,
|
|
4765
4993
|
` \u2713 Output templates`,
|
|
4766
|
-
|
|
4767
|
-
`Your configuration and knowledge files were preserved.`
|
|
4994
|
+
` \u2713 Documentation`
|
|
4768
4995
|
];
|
|
4996
|
+
if (ideTargets.length > 0) {
|
|
4997
|
+
summary.push(` \u2713 IDE integrations: ${ideTargets.join(", ")}`);
|
|
4998
|
+
}
|
|
4999
|
+
summary.push(
|
|
5000
|
+
``,
|
|
5001
|
+
`Your configuration and knowledge files were preserved.`,
|
|
5002
|
+
``,
|
|
5003
|
+
pc14.dim(`\u{1F4A1} If using OpenCode, you may need to reload for changes to take effect.`)
|
|
5004
|
+
);
|
|
4769
5005
|
note12(summary.join("\n"), "Update Summary");
|
|
4770
5006
|
outro5(pc14.green("\u2713 Successfully updated from package!"));
|
|
4771
5007
|
} catch (error) {
|
|
@@ -4774,6 +5010,60 @@ ${dataPaths.map((p) => ` \u2022 ${p}`).join("\n")}`,
|
|
|
4774
5010
|
process.exit(1);
|
|
4775
5011
|
}
|
|
4776
5012
|
}
|
|
5013
|
+
function updateOpenCodeAgents(prompts, mode, primaryDataPath) {
|
|
5014
|
+
if (mode === "global") {
|
|
5015
|
+
try {
|
|
5016
|
+
let opencodeConfig = { $schema: "https://opencode.ai/config.json" };
|
|
5017
|
+
if (fs18.existsSync(OPENCODE_CONFIG)) {
|
|
5018
|
+
opencodeConfig = JSON.parse(fs18.readFileSync(OPENCODE_CONFIG, "utf-8"));
|
|
5019
|
+
}
|
|
5020
|
+
if (!opencodeConfig.agent) opencodeConfig.agent = {};
|
|
5021
|
+
const currentAgentNames = prompts.map((p) => path19.basename(p.filePath, ".md"));
|
|
5022
|
+
const existingAgentNames = Object.keys(opencodeConfig.agent);
|
|
5023
|
+
const rrceAgentPrefixes = ["init", "research", "planning", "executor", "doctor", "documentation", "sync"];
|
|
5024
|
+
for (const existingName of existingAgentNames) {
|
|
5025
|
+
const isRrceAgent = rrceAgentPrefixes.some((prefix) => existingName.startsWith(prefix));
|
|
5026
|
+
const stillExists = currentAgentNames.includes(existingName);
|
|
5027
|
+
if (isRrceAgent && !stillExists) {
|
|
5028
|
+
delete opencodeConfig.agent[existingName];
|
|
5029
|
+
}
|
|
5030
|
+
}
|
|
5031
|
+
for (const prompt of prompts) {
|
|
5032
|
+
const baseName = path19.basename(prompt.filePath, ".md");
|
|
5033
|
+
const agentConfig = convertToOpenCodeAgent(prompt);
|
|
5034
|
+
opencodeConfig.agent[baseName] = agentConfig;
|
|
5035
|
+
}
|
|
5036
|
+
fs18.writeFileSync(OPENCODE_CONFIG, JSON.stringify(opencodeConfig, null, 2) + "\n");
|
|
5037
|
+
} catch (e) {
|
|
5038
|
+
console.error("Failed to update global OpenCode config with agents:", e);
|
|
5039
|
+
}
|
|
5040
|
+
} else {
|
|
5041
|
+
const opencodeBaseDir = path19.join(primaryDataPath, ".opencode", "agent");
|
|
5042
|
+
ensureDir(opencodeBaseDir);
|
|
5043
|
+
clearDirectory(opencodeBaseDir);
|
|
5044
|
+
for (const prompt of prompts) {
|
|
5045
|
+
const baseName = path19.basename(prompt.filePath, ".md");
|
|
5046
|
+
const agentConfig = convertToOpenCodeAgent(prompt);
|
|
5047
|
+
const content = `---
|
|
5048
|
+
${stringify3({
|
|
5049
|
+
description: agentConfig.description,
|
|
5050
|
+
mode: agentConfig.mode,
|
|
5051
|
+
tools: agentConfig.tools
|
|
5052
|
+
})}---
|
|
5053
|
+
${agentConfig.prompt}`;
|
|
5054
|
+
fs18.writeFileSync(path19.join(opencodeBaseDir, `${baseName}.md`), content);
|
|
5055
|
+
}
|
|
5056
|
+
}
|
|
5057
|
+
}
|
|
5058
|
+
function clearDirectory(dirPath) {
|
|
5059
|
+
if (!fs18.existsSync(dirPath)) return;
|
|
5060
|
+
const entries = fs18.readdirSync(dirPath, { withFileTypes: true });
|
|
5061
|
+
for (const entry of entries) {
|
|
5062
|
+
if (entry.isFile()) {
|
|
5063
|
+
fs18.unlinkSync(path19.join(dirPath, entry.name));
|
|
5064
|
+
}
|
|
5065
|
+
}
|
|
5066
|
+
}
|
|
4777
5067
|
function resolveAllDataPathsWithCustomGlobal(mode, workspaceName, workspaceRoot, customGlobalPath) {
|
|
4778
5068
|
const globalPath = path19.join(customGlobalPath, "workspaces", workspaceName);
|
|
4779
5069
|
const workspacePath = path19.join(workspaceRoot, ".rrce-workflow");
|
|
@@ -4792,6 +5082,7 @@ var init_update_flow = __esm({
|
|
|
4792
5082
|
init_paths();
|
|
4793
5083
|
init_prompts();
|
|
4794
5084
|
init_utils();
|
|
5085
|
+
init_install();
|
|
4795
5086
|
}
|
|
4796
5087
|
});
|
|
4797
5088
|
|
package/docs/architecture.md
CHANGED
|
@@ -7,7 +7,9 @@
|
|
|
7
7
|
RRCE-Workflow is a TUI-based agentic code workflow generator designed to work seamlessly across:
|
|
8
8
|
- **GitHub Copilot CLI**
|
|
9
9
|
- **Antigravity IDE** (Google's agentic coding environment)
|
|
10
|
+
- **OpenCode** (Native agentic TUI environment)
|
|
10
11
|
- **VS Code** (with Copilot and other AI extensions)
|
|
12
|
+
- **Claude Desktop**
|
|
11
13
|
|
|
12
14
|
The system provides a structured multi-agent pipeline for software development tasks, with persistent knowledge caching and workspace-aware context management.
|
|
13
15
|
|
|
@@ -243,6 +245,7 @@ RRCE-Workflow prompts are designed to work across multiple AI coding tools:
|
|
|
243
245
|
| Tool | Prompt Location | Extension | Notes |
|
|
244
246
|
|------|----------------|-----------|-------|
|
|
245
247
|
| **Antigravity IDE** | `.agent/workflows/` | `.md` | Native workflow support |
|
|
248
|
+
| **OpenCode** | `.opencode/agent/` | `.md` | Custom Primary Agents |
|
|
246
249
|
| **GitHub Copilot (VSCode)** | `.github/agents/` | `.agent.md` | Custom agents format |
|
|
247
250
|
| **Copilot CLI** | Any location | `.md` | Reference via file path |
|
|
248
251
|
|
|
@@ -298,6 +301,17 @@ When you run `rrce-workflow wizard`, it creates:
|
|
|
298
301
|
└── sync.md
|
|
299
302
|
```
|
|
300
303
|
|
|
304
|
+
**For OpenCode:**
|
|
305
|
+
```
|
|
306
|
+
.opencode/agent/
|
|
307
|
+
├── rrce-init.md
|
|
308
|
+
├── rrce-research.md
|
|
309
|
+
├── rrce-planning.md
|
|
310
|
+
├── rrce-executor.md
|
|
311
|
+
├── rrce-documentation.md
|
|
312
|
+
└── rrce-sync.md
|
|
313
|
+
```
|
|
314
|
+
|
|
301
315
|
### Copilot-Specific Features
|
|
302
316
|
|
|
303
317
|
Our prompts include Copilot-compatible frontmatter:
|