rrce-workflow 0.2.78 → 0.2.80
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 +308 -19
- package/docs/architecture.md +14 -0
- package/package.json +1 -1
- package/agent-core/prompts/planning_orchestrator.md +0 -85
|
@@ -18,48 +18,150 @@
|
|
|
18
18
|
- {{date}}: ISO date (YYYY-MM-DD)
|
|
19
19
|
- {{source}}: URL or reference to original request
|
|
20
20
|
- {{workspace_name}}: Project name
|
|
21
|
+
|
|
22
|
+
NOTE: This document is the output of an interactive research session.
|
|
23
|
+
The Research agent engaged in constructive dialogue with the user to
|
|
24
|
+
achieve 100% understanding before this brief was generated.
|
|
21
25
|
-->
|
|
22
26
|
# Research Brief – {{task_title}}
|
|
23
27
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
28
|
+
| Field | Value |
|
|
29
|
+
|-------|-------|
|
|
30
|
+
| Task ID | `{{task_id}}` |
|
|
31
|
+
| Task Slug | `{{task_slug}}` |
|
|
32
|
+
| Author | `{{author}}` |
|
|
33
|
+
| Date | `{{date}}` |
|
|
34
|
+
| Source Request | `{{source}}` |
|
|
35
|
+
| Workspace | `{{workspace_name}}` |
|
|
36
|
+
|
|
37
|
+
---
|
|
30
38
|
|
|
31
39
|
## 1. Request Summary
|
|
32
|
-
- Concise restatement of the user's ask.
|
|
33
|
-
- Highlight explicit goals, constraints, and success metrics.
|
|
34
40
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
41
|
+
> **Original Request**: [Quote the user's initial request]
|
|
42
|
+
|
|
43
|
+
**Refined Understanding** (after clarification):
|
|
44
|
+
- [Clear, specific statement of what needs to be built]
|
|
45
|
+
- [Why it needs to be built - problem/opportunity]
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## 2. Clarification Summary
|
|
50
|
+
|
|
51
|
+
The following was clarified through interactive dialogue:
|
|
52
|
+
|
|
53
|
+
| Topic | Question Asked | User Response | Impact on Scope |
|
|
54
|
+
|-------|----------------|---------------|-----------------|
|
|
55
|
+
| Intent | | | |
|
|
56
|
+
| Constraints | | | |
|
|
57
|
+
| Success Criteria | | | |
|
|
58
|
+
| Edge Cases | | | |
|
|
59
|
+
|
|
60
|
+
**Key Decisions Made**:
|
|
61
|
+
- [Decision 1 and rationale]
|
|
62
|
+
- [Decision 2 and rationale]
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## 3. Current Knowledge Snapshot
|
|
67
|
+
|
|
68
|
+
Relevant prior work and context from project knowledge:
|
|
69
|
+
|
|
70
|
+
| Source | Relevance |
|
|
71
|
+
|--------|-----------|
|
|
72
|
+
| `{{RRCE_DATA}}/knowledge/...` | [How it applies] |
|
|
73
|
+
| [Search result] | [How it applies] |
|
|
74
|
+
|
|
75
|
+
**Patterns to Follow**:
|
|
76
|
+
- [Existing pattern 1 from codebase]
|
|
77
|
+
- [Existing pattern 2 from codebase]
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## 4. Requirements
|
|
82
|
+
|
|
83
|
+
### Functional Requirements
|
|
84
|
+
- [ ] [FR-1]: [Requirement description]
|
|
85
|
+
- [ ] [FR-2]: [Requirement description]
|
|
86
|
+
- [ ] [FR-3]: [Requirement description]
|
|
87
|
+
|
|
88
|
+
### Non-Functional Requirements
|
|
89
|
+
- [ ] [NFR-1]: [Performance/Security/etc. requirement]
|
|
90
|
+
- [ ] [NFR-2]: [Requirement description]
|
|
91
|
+
|
|
92
|
+
### Success Criteria
|
|
93
|
+
How we'll know this is done:
|
|
94
|
+
1. [Measurable outcome 1]
|
|
95
|
+
2. [Measurable outcome 2]
|
|
96
|
+
3. [Measurable outcome 3]
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
## 5. Scope Boundaries
|
|
101
|
+
|
|
102
|
+
### In Scope
|
|
103
|
+
- [Explicit inclusion 1]
|
|
104
|
+
- [Explicit inclusion 2]
|
|
105
|
+
|
|
106
|
+
### Out of Scope
|
|
107
|
+
- [Explicit exclusion 1]
|
|
108
|
+
- [Explicit exclusion 2]
|
|
109
|
+
|
|
110
|
+
### Constraints
|
|
111
|
+
- [Hard constraint 1 - e.g., timeline, tech, resources]
|
|
112
|
+
- [Hard constraint 2]
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## 6. Assumptions & Risks
|
|
117
|
+
|
|
118
|
+
### Assumptions
|
|
119
|
+
| ID | Assumption | Confidence | Validation Needed |
|
|
120
|
+
|----|------------|------------|-------------------|
|
|
121
|
+
| A1 | [Assumption] | High/Medium/Low | [How to validate] |
|
|
122
|
+
| A2 | [Assumption] | High/Medium/Low | [How to validate] |
|
|
123
|
+
|
|
124
|
+
### Risks
|
|
125
|
+
| ID | Risk | Impact | Likelihood | Mitigation |
|
|
126
|
+
|----|------|--------|------------|------------|
|
|
127
|
+
| R1 | [Risk description] | High/Medium/Low | High/Medium/Low | [Mitigation] |
|
|
128
|
+
| R2 | [Risk description] | High/Medium/Low | High/Medium/Low | [Mitigation] |
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## 7. Opportunity & Alternative Approaches
|
|
133
|
+
|
|
134
|
+
Approaches considered during research:
|
|
135
|
+
|
|
136
|
+
| Approach | Pros | Cons | Recommendation |
|
|
137
|
+
|----------|------|------|----------------|
|
|
138
|
+
| [Approach A] | | | Chosen / Rejected |
|
|
139
|
+
| [Approach B] | | | Chosen / Rejected |
|
|
140
|
+
|
|
141
|
+
**Rationale for chosen approach**: [Explanation]
|
|
142
|
+
|
|
143
|
+
---
|
|
38
144
|
|
|
39
|
-
##
|
|
40
|
-
- Relevant prior work or documents from `{{RRCE_DATA}}/knowledge` or workspace.
|
|
41
|
-
- Key facts that shape feasibility or scope.
|
|
145
|
+
## 8. Hand-off Notes for Planning
|
|
42
146
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
147
|
+
### Ready for Planning
|
|
148
|
+
- [ ] Core requirements are clear and specific
|
|
149
|
+
- [ ] Success criteria are measurable
|
|
150
|
+
- [ ] Scope boundaries are explicit
|
|
151
|
+
- [ ] No blocking open questions remain
|
|
47
152
|
|
|
48
|
-
|
|
49
|
-
-
|
|
50
|
-
-
|
|
153
|
+
### Context for Planning Agent
|
|
154
|
+
- [Important context the planner needs to know]
|
|
155
|
+
- [Technical considerations for task breakdown]
|
|
51
156
|
|
|
52
|
-
|
|
53
|
-
-
|
|
54
|
-
- Trade-offs or spikes recommended before execution.
|
|
157
|
+
### Open Questions (Non-Blocking)
|
|
158
|
+
- [Question that can be resolved during planning or execution]
|
|
55
159
|
|
|
56
|
-
|
|
57
|
-
-
|
|
58
|
-
- Note acceptance signals or metrics where available.
|
|
160
|
+
### References Added to meta.json
|
|
161
|
+
- [List of knowledge files referenced]
|
|
59
162
|
|
|
60
|
-
|
|
61
|
-
- Immediate next steps for Planning.
|
|
62
|
-
- Pending clarifications or decisions to resolve.
|
|
63
|
-
- References added to `meta.json`.
|
|
163
|
+
---
|
|
64
164
|
|
|
65
|
-
>
|
|
165
|
+
> **Next Step**: `/plan TASK_SLUG={{task_slug}}`
|
|
166
|
+
>
|
|
167
|
+
> Keep this document under 500 lines. Replace placeholders with concise entries and trim empty sections.
|
package/dist/index.js
CHANGED
|
@@ -1260,27 +1260,24 @@ function copyPromptsToDir(prompts, targetDir, extension) {
|
|
|
1260
1260
|
fs7.writeFileSync(targetPath, content);
|
|
1261
1261
|
}
|
|
1262
1262
|
}
|
|
1263
|
-
function convertToOpenCodeAgent(prompt) {
|
|
1263
|
+
function convertToOpenCodeAgent(prompt, useFileReference = false, promptFilePath) {
|
|
1264
1264
|
const { frontmatter, content } = prompt;
|
|
1265
|
-
const tools = {
|
|
1266
|
-
|
|
1267
|
-
"read": true,
|
|
1268
|
-
"write": true,
|
|
1269
|
-
"edit": true,
|
|
1270
|
-
"bash": true,
|
|
1271
|
-
"grep": true,
|
|
1272
|
-
"glob": true,
|
|
1273
|
-
"webfetch": true
|
|
1274
|
-
};
|
|
1265
|
+
const tools = {};
|
|
1266
|
+
const hostTools = ["read", "write", "edit", "bash", "grep", "glob", "webfetch", "terminalLastCommand"];
|
|
1275
1267
|
if (frontmatter.tools) {
|
|
1276
1268
|
for (const tool of frontmatter.tools) {
|
|
1277
|
-
|
|
1269
|
+
if (hostTools.includes(tool)) {
|
|
1270
|
+
tools[tool] = true;
|
|
1271
|
+
} else {
|
|
1272
|
+
tools[`rrce_${tool}`] = true;
|
|
1273
|
+
}
|
|
1278
1274
|
}
|
|
1279
1275
|
}
|
|
1276
|
+
tools["webfetch"] = true;
|
|
1280
1277
|
return {
|
|
1281
1278
|
description: frontmatter.description,
|
|
1282
1279
|
mode: "primary",
|
|
1283
|
-
prompt: content,
|
|
1280
|
+
prompt: useFileReference && promptFilePath ? `{file:${promptFilePath}}` : content,
|
|
1284
1281
|
tools
|
|
1285
1282
|
};
|
|
1286
1283
|
}
|
|
@@ -1697,6 +1694,8 @@ async function installAgentPrompts(config, workspacePath, dataPaths) {
|
|
|
1697
1694
|
if (primaryDataPath) {
|
|
1698
1695
|
if (config.storageMode === "global") {
|
|
1699
1696
|
try {
|
|
1697
|
+
const promptsDir = path12.join(path12.dirname(OPENCODE_CONFIG), "prompts");
|
|
1698
|
+
ensureDir(promptsDir);
|
|
1700
1699
|
let opencodeConfig = { $schema: "https://opencode.ai/config.json" };
|
|
1701
1700
|
if (fs10.existsSync(OPENCODE_CONFIG)) {
|
|
1702
1701
|
opencodeConfig = JSON.parse(fs10.readFileSync(OPENCODE_CONFIG, "utf-8"));
|
|
@@ -1704,7 +1703,10 @@ async function installAgentPrompts(config, workspacePath, dataPaths) {
|
|
|
1704
1703
|
if (!opencodeConfig.agent) opencodeConfig.agent = {};
|
|
1705
1704
|
for (const prompt of prompts) {
|
|
1706
1705
|
const baseName = path12.basename(prompt.filePath, ".md");
|
|
1707
|
-
const
|
|
1706
|
+
const promptFileName = `rrce-${baseName}.md`;
|
|
1707
|
+
const promptFilePath = path12.join(promptsDir, promptFileName);
|
|
1708
|
+
fs10.writeFileSync(promptFilePath, prompt.content);
|
|
1709
|
+
const agentConfig = convertToOpenCodeAgent(prompt, true, `./prompts/${promptFileName}`);
|
|
1708
1710
|
opencodeConfig.agent[baseName] = agentConfig;
|
|
1709
1711
|
}
|
|
1710
1712
|
fs10.writeFileSync(OPENCODE_CONFIG, JSON.stringify(opencodeConfig, null, 2) + "\n");
|
|
@@ -2214,6 +2216,7 @@ var init_rag = __esm({
|
|
|
2214
2216
|
// src/mcp/resources.ts
|
|
2215
2217
|
import * as fs14 from "fs";
|
|
2216
2218
|
import * as path16 from "path";
|
|
2219
|
+
import * as crypto from "crypto";
|
|
2217
2220
|
function getExposedProjects() {
|
|
2218
2221
|
const config = loadMCPConfig();
|
|
2219
2222
|
const knownPaths = config.projects.map((p) => p.path).filter((p) => !!p);
|
|
@@ -2534,9 +2537,101 @@ All file operations should be relative to WORKSPACE_ROOT shown above.
|
|
|
2534
2537
|
`;
|
|
2535
2538
|
return contextPreamble;
|
|
2536
2539
|
}
|
|
2540
|
+
function getTask(projectName, taskSlug) {
|
|
2541
|
+
const config = loadMCPConfig();
|
|
2542
|
+
const projects = projectService.scan();
|
|
2543
|
+
const project = projects.find((p) => p.name === projectName && isProjectExposed(config, p.name, p.path));
|
|
2544
|
+
if (!project || !project.tasksPath) return null;
|
|
2545
|
+
const metaPath = path16.join(project.tasksPath, taskSlug, "meta.json");
|
|
2546
|
+
if (!fs14.existsSync(metaPath)) return null;
|
|
2547
|
+
try {
|
|
2548
|
+
return JSON.parse(fs14.readFileSync(metaPath, "utf-8"));
|
|
2549
|
+
} catch {
|
|
2550
|
+
return null;
|
|
2551
|
+
}
|
|
2552
|
+
}
|
|
2553
|
+
async function createTask(projectName, taskSlug, taskData) {
|
|
2554
|
+
const config = loadMCPConfig();
|
|
2555
|
+
const projects = projectService.scan();
|
|
2556
|
+
const project = projects.find((p) => p.name === projectName && isProjectExposed(config, p.name, p.path));
|
|
2557
|
+
if (!project || !project.tasksPath) {
|
|
2558
|
+
throw new Error(`Project '${projectName}' not found or not configured with a tasks path.`);
|
|
2559
|
+
}
|
|
2560
|
+
const taskDir = path16.join(project.tasksPath, taskSlug);
|
|
2561
|
+
if (fs14.existsSync(taskDir)) {
|
|
2562
|
+
throw new Error(`Task with slug '${taskSlug}' already exists.`);
|
|
2563
|
+
}
|
|
2564
|
+
fs14.mkdirSync(taskDir, { recursive: true });
|
|
2565
|
+
fs14.mkdirSync(path16.join(taskDir, "research"), { recursive: true });
|
|
2566
|
+
fs14.mkdirSync(path16.join(taskDir, "planning"), { recursive: true });
|
|
2567
|
+
fs14.mkdirSync(path16.join(taskDir, "execution"), { recursive: true });
|
|
2568
|
+
fs14.mkdirSync(path16.join(taskDir, "docs"), { recursive: true });
|
|
2569
|
+
const rrceHome = process.env.RRCE_HOME || path16.join(__require("os").homedir(), ".rrce-workflow");
|
|
2570
|
+
const templatePath = path16.join(rrceHome, "templates", "meta.template.json");
|
|
2571
|
+
let meta = {
|
|
2572
|
+
task_id: crypto.randomUUID(),
|
|
2573
|
+
task_slug: taskSlug,
|
|
2574
|
+
status: "draft",
|
|
2575
|
+
agents: {}
|
|
2576
|
+
};
|
|
2577
|
+
if (fs14.existsSync(templatePath)) {
|
|
2578
|
+
try {
|
|
2579
|
+
const template = JSON.parse(fs14.readFileSync(templatePath, "utf-8"));
|
|
2580
|
+
meta = { ...template, ...meta };
|
|
2581
|
+
} catch (e) {
|
|
2582
|
+
logger.error("Failed to load meta template", e);
|
|
2583
|
+
}
|
|
2584
|
+
}
|
|
2585
|
+
meta.created_at = (/* @__PURE__ */ new Date()).toISOString();
|
|
2586
|
+
meta.updated_at = meta.created_at;
|
|
2587
|
+
meta.workspace = {
|
|
2588
|
+
name: project.name,
|
|
2589
|
+
path: project.path || project.dataPath,
|
|
2590
|
+
hash: project.name
|
|
2591
|
+
};
|
|
2592
|
+
Object.assign(meta, taskData);
|
|
2593
|
+
const metaPath = path16.join(taskDir, "meta.json");
|
|
2594
|
+
fs14.writeFileSync(metaPath, JSON.stringify(meta, null, 2));
|
|
2595
|
+
return meta;
|
|
2596
|
+
}
|
|
2597
|
+
async function updateTask(projectName, taskSlug, taskData) {
|
|
2598
|
+
const meta = getTask(projectName, taskSlug);
|
|
2599
|
+
if (!meta) throw new Error(`Task '${taskSlug}' not found.`);
|
|
2600
|
+
const updatedMeta = {
|
|
2601
|
+
...meta,
|
|
2602
|
+
...taskData,
|
|
2603
|
+
updated_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2604
|
+
// Ensure nested objects are merged if they exist in taskData
|
|
2605
|
+
agents: taskData.agents ? { ...meta.agents, ...taskData.agents } : meta.agents,
|
|
2606
|
+
workspace: meta.workspace
|
|
2607
|
+
// Protect workspace metadata
|
|
2608
|
+
};
|
|
2609
|
+
const config = loadMCPConfig();
|
|
2610
|
+
const projects = projectService.scan();
|
|
2611
|
+
const project = projects.find((p) => p.name === projectName && isProjectExposed(config, p.name, p.path));
|
|
2612
|
+
if (!project || !project.tasksPath) return null;
|
|
2613
|
+
const metaPath = path16.join(project.tasksPath, taskSlug, "meta.json");
|
|
2614
|
+
fs14.writeFileSync(metaPath, JSON.stringify(updatedMeta, null, 2));
|
|
2615
|
+
return updatedMeta;
|
|
2616
|
+
}
|
|
2617
|
+
function deleteTask(projectName, taskSlug) {
|
|
2618
|
+
const config = loadMCPConfig();
|
|
2619
|
+
const projects = projectService.scan();
|
|
2620
|
+
const project = projects.find((p) => p.name === projectName && isProjectExposed(config, p.name, p.path));
|
|
2621
|
+
if (!project || !project.tasksPath) return false;
|
|
2622
|
+
const taskDir = path16.join(project.tasksPath, taskSlug);
|
|
2623
|
+
if (!fs14.existsSync(taskDir)) return false;
|
|
2624
|
+
if (fs14.rmSync) {
|
|
2625
|
+
fs14.rmSync(taskDir, { recursive: true, force: true });
|
|
2626
|
+
} else {
|
|
2627
|
+
fs14.rmdirSync(taskDir, { recursive: true });
|
|
2628
|
+
}
|
|
2629
|
+
return true;
|
|
2630
|
+
}
|
|
2537
2631
|
var init_resources = __esm({
|
|
2538
2632
|
"src/mcp/resources.ts"() {
|
|
2539
2633
|
"use strict";
|
|
2634
|
+
init_logger();
|
|
2540
2635
|
init_config();
|
|
2541
2636
|
init_config_utils();
|
|
2542
2637
|
init_detection();
|
|
@@ -2779,6 +2874,66 @@ function registerToolHandlers(server) {
|
|
|
2779
2874
|
},
|
|
2780
2875
|
required: ["agent"]
|
|
2781
2876
|
}
|
|
2877
|
+
},
|
|
2878
|
+
{
|
|
2879
|
+
name: "list_tasks",
|
|
2880
|
+
description: "List all tasks for a project",
|
|
2881
|
+
inputSchema: {
|
|
2882
|
+
type: "object",
|
|
2883
|
+
properties: { project: { type: "string", description: "Name of the project" } },
|
|
2884
|
+
required: ["project"]
|
|
2885
|
+
}
|
|
2886
|
+
},
|
|
2887
|
+
{
|
|
2888
|
+
name: "get_task",
|
|
2889
|
+
description: "Get details of a specific task",
|
|
2890
|
+
inputSchema: {
|
|
2891
|
+
type: "object",
|
|
2892
|
+
properties: {
|
|
2893
|
+
project: { type: "string", description: "Name of the project" },
|
|
2894
|
+
task_slug: { type: "string", description: "The slug of the task" }
|
|
2895
|
+
},
|
|
2896
|
+
required: ["project", "task_slug"]
|
|
2897
|
+
}
|
|
2898
|
+
},
|
|
2899
|
+
{
|
|
2900
|
+
name: "create_task",
|
|
2901
|
+
description: "Create a new task in the project",
|
|
2902
|
+
inputSchema: {
|
|
2903
|
+
type: "object",
|
|
2904
|
+
properties: {
|
|
2905
|
+
project: { type: "string", description: "Name of the project" },
|
|
2906
|
+
task_slug: { type: "string", description: "The slug for the new task (kebab-case)" },
|
|
2907
|
+
title: { type: "string", description: "The title of the task" },
|
|
2908
|
+
summary: { type: "string", description: "Brief summary of the task" }
|
|
2909
|
+
},
|
|
2910
|
+
required: ["project", "task_slug"]
|
|
2911
|
+
}
|
|
2912
|
+
},
|
|
2913
|
+
{
|
|
2914
|
+
name: "update_task",
|
|
2915
|
+
description: "Update an existing task",
|
|
2916
|
+
inputSchema: {
|
|
2917
|
+
type: "object",
|
|
2918
|
+
properties: {
|
|
2919
|
+
project: { type: "string", description: "Name of the project" },
|
|
2920
|
+
task_slug: { type: "string", description: "The slug of the task" },
|
|
2921
|
+
updates: { type: "object", description: "The fields to update in meta.json", additionalProperties: true }
|
|
2922
|
+
},
|
|
2923
|
+
required: ["project", "task_slug", "updates"]
|
|
2924
|
+
}
|
|
2925
|
+
},
|
|
2926
|
+
{
|
|
2927
|
+
name: "delete_task",
|
|
2928
|
+
description: "Delete a task from the project",
|
|
2929
|
+
inputSchema: {
|
|
2930
|
+
type: "object",
|
|
2931
|
+
properties: {
|
|
2932
|
+
project: { type: "string", description: "Name of the project" },
|
|
2933
|
+
task_slug: { type: "string", description: "The slug of the task to delete" }
|
|
2934
|
+
},
|
|
2935
|
+
required: ["project", "task_slug"]
|
|
2936
|
+
}
|
|
2782
2937
|
}
|
|
2783
2938
|
];
|
|
2784
2939
|
const projects = getExposedProjects();
|
|
@@ -2866,6 +3021,38 @@ The system has pre-resolved the configuration for this project. Use these values
|
|
|
2866
3021
|
`;
|
|
2867
3022
|
return { content: [{ type: "text", text: contextPreamble + rendered }] };
|
|
2868
3023
|
}
|
|
3024
|
+
case "list_tasks": {
|
|
3025
|
+
const params = args;
|
|
3026
|
+
const tasks = getProjectTasks(params.project);
|
|
3027
|
+
return { content: [{ type: "text", text: JSON.stringify(tasks, null, 2) }] };
|
|
3028
|
+
}
|
|
3029
|
+
case "get_task": {
|
|
3030
|
+
const params = args;
|
|
3031
|
+
const task = getTask(params.project, params.task_slug);
|
|
3032
|
+
if (!task) {
|
|
3033
|
+
return { content: [{ type: "text", text: `Task '${params.task_slug}' not found in project '${params.project}'.` }], isError: true };
|
|
3034
|
+
}
|
|
3035
|
+
return { content: [{ type: "text", text: JSON.stringify(task, null, 2) }] };
|
|
3036
|
+
}
|
|
3037
|
+
case "create_task": {
|
|
3038
|
+
const params = args;
|
|
3039
|
+
const taskData = {
|
|
3040
|
+
title: params.title || params.task_slug,
|
|
3041
|
+
summary: params.summary || ""
|
|
3042
|
+
};
|
|
3043
|
+
const task = await createTask(params.project, params.task_slug, taskData);
|
|
3044
|
+
return { content: [{ type: "text", text: JSON.stringify(task, null, 2) }] };
|
|
3045
|
+
}
|
|
3046
|
+
case "update_task": {
|
|
3047
|
+
const params = args;
|
|
3048
|
+
const task = await updateTask(params.project, params.task_slug, params.updates);
|
|
3049
|
+
return { content: [{ type: "text", text: JSON.stringify(task, null, 2) }] };
|
|
3050
|
+
}
|
|
3051
|
+
case "delete_task": {
|
|
3052
|
+
const params = args;
|
|
3053
|
+
const success = deleteTask(params.project, params.task_slug);
|
|
3054
|
+
return { content: [{ type: "text", text: success ? `Task '${params.task_slug}' deleted.` : `Failed to delete task '${params.task_slug}'.` }] };
|
|
3055
|
+
}
|
|
2869
3056
|
case "help_setup": {
|
|
2870
3057
|
const msg = `
|
|
2871
3058
|
RRCE MCP Server is running, but no projects are configured/exposed.
|
|
@@ -4729,6 +4916,7 @@ import { confirm as confirm9, spinner as spinner6, note as note12, outro as outr
|
|
|
4729
4916
|
import pc14 from "picocolors";
|
|
4730
4917
|
import * as fs18 from "fs";
|
|
4731
4918
|
import * as path19 from "path";
|
|
4919
|
+
import { stringify as stringify3 } from "yaml";
|
|
4732
4920
|
async function runUpdateFlow(workspacePath, workspaceName, currentStorageMode) {
|
|
4733
4921
|
const s = spinner6();
|
|
4734
4922
|
s.start("Checking for updates");
|
|
@@ -4739,10 +4927,25 @@ async function runUpdateFlow(workspacePath, workspaceName, currentStorageMode) {
|
|
|
4739
4927
|
const customGlobalPath = getEffectiveRRCEHome(workspacePath);
|
|
4740
4928
|
const dataPaths = resolveAllDataPathsWithCustomGlobal(mode, workspaceName, workspacePath, customGlobalPath);
|
|
4741
4929
|
s.stop("Updates found");
|
|
4930
|
+
const updateTargets = [
|
|
4931
|
+
` \u2022 prompts/ (${prompts.length} agent prompts)`,
|
|
4932
|
+
` \u2022 templates/ (output templates)`,
|
|
4933
|
+
` \u2022 docs/ (documentation)`
|
|
4934
|
+
];
|
|
4935
|
+
const configFilePath = getConfigPath(workspacePath);
|
|
4936
|
+
const ideTargets = [];
|
|
4937
|
+
if (fs18.existsSync(configFilePath)) {
|
|
4938
|
+
const configContent = fs18.readFileSync(configFilePath, "utf-8");
|
|
4939
|
+
if (configContent.includes("opencode: true")) ideTargets.push("OpenCode agents");
|
|
4940
|
+
if (configContent.includes("copilot: true")) ideTargets.push("GitHub Copilot");
|
|
4941
|
+
if (configContent.includes("antigravity: true")) ideTargets.push("Antigravity");
|
|
4942
|
+
}
|
|
4943
|
+
if (ideTargets.length > 0) {
|
|
4944
|
+
updateTargets.push(` \u2022 IDE integrations: ${ideTargets.join(", ")}`);
|
|
4945
|
+
}
|
|
4742
4946
|
note12(
|
|
4743
4947
|
`The following will be updated from the package:
|
|
4744
|
-
|
|
4745
|
-
\u2022 templates/ (output templates)
|
|
4948
|
+
${updateTargets.join("\n")}
|
|
4746
4949
|
|
|
4747
4950
|
Target locations:
|
|
4748
4951
|
${dataPaths.map((p) => ` \u2022 ${p}`).join("\n")}`,
|
|
@@ -4759,29 +4962,51 @@ ${dataPaths.map((p) => ` \u2022 ${p}`).join("\n")}`,
|
|
|
4759
4962
|
s.start("Updating from package");
|
|
4760
4963
|
for (const dataPath of dataPaths) {
|
|
4761
4964
|
copyDirToAllStoragePaths(path19.join(agentCoreDir, "templates"), "templates", [dataPath]);
|
|
4965
|
+
copyDirToAllStoragePaths(path19.join(agentCoreDir, "prompts"), "prompts", [dataPath]);
|
|
4966
|
+
copyDirToAllStoragePaths(path19.join(agentCoreDir, "docs"), "docs", [dataPath]);
|
|
4762
4967
|
}
|
|
4763
|
-
const
|
|
4968
|
+
const rrceHome = customGlobalPath || getDefaultRRCEHome2();
|
|
4969
|
+
ensureDir(path19.join(rrceHome, "templates"));
|
|
4970
|
+
ensureDir(path19.join(rrceHome, "docs"));
|
|
4971
|
+
copyDirRecursive(path19.join(agentCoreDir, "templates"), path19.join(rrceHome, "templates"));
|
|
4972
|
+
copyDirRecursive(path19.join(agentCoreDir, "docs"), path19.join(rrceHome, "docs"));
|
|
4764
4973
|
if (fs18.existsSync(configFilePath)) {
|
|
4765
4974
|
const configContent = fs18.readFileSync(configFilePath, "utf-8");
|
|
4766
4975
|
if (configContent.includes("copilot: true")) {
|
|
4767
4976
|
const copilotPath = getAgentPromptPath(workspacePath, "copilot");
|
|
4768
4977
|
ensureDir(copilotPath);
|
|
4978
|
+
clearDirectory(copilotPath);
|
|
4769
4979
|
copyPromptsToDir(prompts, copilotPath, ".agent.md");
|
|
4770
4980
|
}
|
|
4771
4981
|
if (configContent.includes("antigravity: true")) {
|
|
4772
4982
|
const antigravityPath = getAgentPromptPath(workspacePath, "antigravity");
|
|
4773
4983
|
ensureDir(antigravityPath);
|
|
4984
|
+
clearDirectory(antigravityPath);
|
|
4774
4985
|
copyPromptsToDir(prompts, antigravityPath, ".md");
|
|
4775
4986
|
}
|
|
4987
|
+
if (configContent.includes("opencode: true")) {
|
|
4988
|
+
const primaryDataPath = dataPaths[0];
|
|
4989
|
+
if (primaryDataPath) {
|
|
4990
|
+
updateOpenCodeAgents(prompts, mode, primaryDataPath);
|
|
4991
|
+
}
|
|
4992
|
+
}
|
|
4776
4993
|
}
|
|
4777
4994
|
s.stop("Update complete");
|
|
4778
4995
|
const summary = [
|
|
4779
4996
|
`Updated:`,
|
|
4780
4997
|
` \u2713 ${prompts.length} agent prompts`,
|
|
4781
4998
|
` \u2713 Output templates`,
|
|
4782
|
-
|
|
4783
|
-
`Your configuration and knowledge files were preserved.`
|
|
4999
|
+
` \u2713 Documentation`
|
|
4784
5000
|
];
|
|
5001
|
+
if (ideTargets.length > 0) {
|
|
5002
|
+
summary.push(` \u2713 IDE integrations: ${ideTargets.join(", ")}`);
|
|
5003
|
+
}
|
|
5004
|
+
summary.push(
|
|
5005
|
+
``,
|
|
5006
|
+
`Your configuration and knowledge files were preserved.`,
|
|
5007
|
+
``,
|
|
5008
|
+
pc14.dim(`\u{1F4A1} If using OpenCode, you may need to reload for changes to take effect.`)
|
|
5009
|
+
);
|
|
4785
5010
|
note12(summary.join("\n"), "Update Summary");
|
|
4786
5011
|
outro5(pc14.green("\u2713 Successfully updated from package!"));
|
|
4787
5012
|
} catch (error) {
|
|
@@ -4790,6 +5015,69 @@ ${dataPaths.map((p) => ` \u2022 ${p}`).join("\n")}`,
|
|
|
4790
5015
|
process.exit(1);
|
|
4791
5016
|
}
|
|
4792
5017
|
}
|
|
5018
|
+
function updateOpenCodeAgents(prompts, mode, primaryDataPath) {
|
|
5019
|
+
if (mode === "global") {
|
|
5020
|
+
try {
|
|
5021
|
+
const promptsDir = path19.join(path19.dirname(OPENCODE_CONFIG), "prompts");
|
|
5022
|
+
ensureDir(promptsDir);
|
|
5023
|
+
let opencodeConfig = { $schema: "https://opencode.ai/config.json" };
|
|
5024
|
+
if (fs18.existsSync(OPENCODE_CONFIG)) {
|
|
5025
|
+
opencodeConfig = JSON.parse(fs18.readFileSync(OPENCODE_CONFIG, "utf-8"));
|
|
5026
|
+
}
|
|
5027
|
+
if (!opencodeConfig.agent) opencodeConfig.agent = {};
|
|
5028
|
+
const currentAgentNames = prompts.map((p) => path19.basename(p.filePath, ".md"));
|
|
5029
|
+
const existingAgentNames = Object.keys(opencodeConfig.agent);
|
|
5030
|
+
const rrceAgentPrefixes = ["init", "research", "planning", "executor", "doctor", "documentation", "sync"];
|
|
5031
|
+
for (const existingName of existingAgentNames) {
|
|
5032
|
+
const isRrceAgent = rrceAgentPrefixes.some((prefix) => existingName.startsWith(prefix));
|
|
5033
|
+
const stillExists = currentAgentNames.includes(existingName);
|
|
5034
|
+
if (isRrceAgent && !stillExists) {
|
|
5035
|
+
delete opencodeConfig.agent[existingName];
|
|
5036
|
+
const oldPromptFile = path19.join(promptsDir, `rrce-${existingName}.md`);
|
|
5037
|
+
if (fs18.existsSync(oldPromptFile)) {
|
|
5038
|
+
fs18.unlinkSync(oldPromptFile);
|
|
5039
|
+
}
|
|
5040
|
+
}
|
|
5041
|
+
}
|
|
5042
|
+
for (const prompt of prompts) {
|
|
5043
|
+
const baseName = path19.basename(prompt.filePath, ".md");
|
|
5044
|
+
const promptFileName = `rrce-${baseName}.md`;
|
|
5045
|
+
const promptFilePath = path19.join(promptsDir, promptFileName);
|
|
5046
|
+
fs18.writeFileSync(promptFilePath, prompt.content);
|
|
5047
|
+
const agentConfig = convertToOpenCodeAgent(prompt, true, `./prompts/${promptFileName}`);
|
|
5048
|
+
opencodeConfig.agent[baseName] = agentConfig;
|
|
5049
|
+
}
|
|
5050
|
+
fs18.writeFileSync(OPENCODE_CONFIG, JSON.stringify(opencodeConfig, null, 2) + "\n");
|
|
5051
|
+
} catch (e) {
|
|
5052
|
+
console.error("Failed to update global OpenCode config with agents:", e);
|
|
5053
|
+
}
|
|
5054
|
+
} else {
|
|
5055
|
+
const opencodeBaseDir = path19.join(primaryDataPath, ".opencode", "agent");
|
|
5056
|
+
ensureDir(opencodeBaseDir);
|
|
5057
|
+
clearDirectory(opencodeBaseDir);
|
|
5058
|
+
for (const prompt of prompts) {
|
|
5059
|
+
const baseName = path19.basename(prompt.filePath, ".md");
|
|
5060
|
+
const agentConfig = convertToOpenCodeAgent(prompt);
|
|
5061
|
+
const content = `---
|
|
5062
|
+
${stringify3({
|
|
5063
|
+
description: agentConfig.description,
|
|
5064
|
+
mode: agentConfig.mode,
|
|
5065
|
+
tools: agentConfig.tools
|
|
5066
|
+
})}---
|
|
5067
|
+
${agentConfig.prompt}`;
|
|
5068
|
+
fs18.writeFileSync(path19.join(opencodeBaseDir, `${baseName}.md`), content);
|
|
5069
|
+
}
|
|
5070
|
+
}
|
|
5071
|
+
}
|
|
5072
|
+
function clearDirectory(dirPath) {
|
|
5073
|
+
if (!fs18.existsSync(dirPath)) return;
|
|
5074
|
+
const entries = fs18.readdirSync(dirPath, { withFileTypes: true });
|
|
5075
|
+
for (const entry of entries) {
|
|
5076
|
+
if (entry.isFile()) {
|
|
5077
|
+
fs18.unlinkSync(path19.join(dirPath, entry.name));
|
|
5078
|
+
}
|
|
5079
|
+
}
|
|
5080
|
+
}
|
|
4793
5081
|
function resolveAllDataPathsWithCustomGlobal(mode, workspaceName, workspaceRoot, customGlobalPath) {
|
|
4794
5082
|
const globalPath = path19.join(customGlobalPath, "workspaces", workspaceName);
|
|
4795
5083
|
const workspacePath = path19.join(workspaceRoot, ".rrce-workflow");
|
|
@@ -4808,6 +5096,7 @@ var init_update_flow = __esm({
|
|
|
4808
5096
|
init_paths();
|
|
4809
5097
|
init_prompts();
|
|
4810
5098
|
init_utils();
|
|
5099
|
+
init_install();
|
|
4811
5100
|
}
|
|
4812
5101
|
});
|
|
4813
5102
|
|
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:
|