rrce-workflow 0.2.71 → 0.2.73
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 +3 -3
- package/agent-core/prompts/documentation.md +3 -3
- package/agent-core/prompts/executor.md +3 -3
- package/agent-core/prompts/init.md +3 -3
- package/agent-core/prompts/planning_orchestrator.md +4 -4
- package/agent-core/prompts/research_discussion.md +4 -4
- package/agent-core/prompts/sync.md +1 -1
- package/dist/index.js +210 -135
- package/package.json +1 -1
|
@@ -20,7 +20,7 @@ You are the Project Doctor for RRCE-Workflow. Perform a health check on the code
|
|
|
20
20
|
|
|
21
21
|
## Path Resolution
|
|
22
22
|
Use the pre-resolved paths from the "System Resolved Paths" table in the context preamble.
|
|
23
|
-
For details, see: `{{
|
|
23
|
+
For details, see: `{{RRCE_DATA}}/docs/path-resolution.md`
|
|
24
24
|
|
|
25
25
|
## Pipeline Position
|
|
26
26
|
- **Input**: Can be triggered at any time for project health analysis
|
|
@@ -142,7 +142,7 @@ Rank findings using this matrix:
|
|
|
142
142
|
### Step 6: Generate Output
|
|
143
143
|
|
|
144
144
|
1. Create task directory: `{{RRCE_DATA}}/tasks/doctor-{{YYYYMMDD}}/`
|
|
145
|
-
2. Write diagnosis using template: `{{
|
|
145
|
+
2. Write diagnosis using template: `{{RRCE_DATA}}/templates/doctor_output.md`
|
|
146
146
|
3. Save to: `{{RRCE_DATA}}/tasks/doctor-{{YYYYMMDD}}/diagnosis.md`
|
|
147
147
|
|
|
148
148
|
**Output includes:**
|
|
@@ -176,7 +176,7 @@ Report:
|
|
|
176
176
|
## Deliverable
|
|
177
177
|
|
|
178
178
|
- **File**: `{{RRCE_DATA}}/tasks/doctor-{{YYYYMMDD}}/diagnosis.md`
|
|
179
|
-
- **Template**: `{{
|
|
179
|
+
- **Template**: `{{RRCE_DATA}}/templates/doctor_output.md`
|
|
180
180
|
- **Outcome**: Structured diagnosis with prioritized, actionable tasks
|
|
181
181
|
|
|
182
182
|
## Focus Area Deep Dive
|
|
@@ -22,7 +22,7 @@ You are the Documentation Lead for the project. Operate like a senior engineerin
|
|
|
22
22
|
|
|
23
23
|
## Path Resolution
|
|
24
24
|
Use the pre-resolved paths from the "System Resolved Paths" table in the context preamble.
|
|
25
|
-
For details, see: `{{
|
|
25
|
+
For details, see: `{{RRCE_DATA}}/docs/path-resolution.md`
|
|
26
26
|
|
|
27
27
|
## Supported DOC_TYPE Values
|
|
28
28
|
|
|
@@ -68,7 +68,7 @@ Workflow
|
|
|
68
68
|
- If `TASK_SLUG` is provided, ensure `{{RRCE_DATA}}/tasks/{{TASK_SLUG}}/docs` exists and target `{{RRCE_DATA}}/tasks/{{TASK_SLUG}}/docs/{{TASK_SLUG}}-{{DOC_TYPE}}.md`.
|
|
69
69
|
- Else if `TARGET_PATH` is provided, ensure its parent directory exists (must remain under `{{RRCE_DATA}}/`) and target `{{RRCE_DATA}}/{{TARGET_PATH}}`.
|
|
70
70
|
- Otherwise, default to `{{RRCE_DATA}}/knowledge/{{DOC_TYPE}}.md` and ensure `{{RRCE_DATA}}/knowledge` exists.
|
|
71
|
-
3. Select a template: prefer `{{
|
|
71
|
+
3. Select a template: prefer `{{RRCE_DATA}}/templates/docs/{{DOC_TYPE}}.md`; fallback to `{{RRCE_DATA}}/templates/documentation_output.md`.
|
|
72
72
|
4. Populate contextual metadata (`AUTHOR`, `RELEASE_REF`, task references, dates) and render the document using the chosen template.
|
|
73
73
|
5. If operating on a task slug, update `{{RRCE_DATA}}/tasks/{{TASK_SLUG}}/meta.json` with documentation artifact paths, new references, final decisions, checklist completions, and remaining follow-ups.
|
|
74
74
|
6. When broader knowledge changed, update the relevant `{{RRCE_DATA}}/knowledge/*.md` entries with `Updated: YYYY-MM-DD` markers, lean changelog bullets, and a small checklist of follow-ups.
|
|
@@ -76,5 +76,5 @@ Workflow
|
|
|
76
76
|
|
|
77
77
|
Deliverable
|
|
78
78
|
- File: Resolved from `DOC_TYPE` plus either `TASK_SLUG`, `TARGET_PATH`, or default knowledge location.
|
|
79
|
-
- Format: `{{
|
|
79
|
+
- Format: `{{RRCE_DATA}}/templates/docs/{{DOC_TYPE}}.md` when available; otherwise `{{RRCE_DATA}}/templates/documentation_output.md`.
|
|
80
80
|
- Outcome: Documentation tailored to the requested type, summarizing scope, implementation, validations, decisions, references, and leftover work while keeping project knowledge synchronized.
|
|
@@ -18,7 +18,7 @@ You are the Executor for the project. Operate like a senior individual contribut
|
|
|
18
18
|
|
|
19
19
|
## Path Resolution
|
|
20
20
|
Use the pre-resolved paths from the "System Resolved Paths" table in the context preamble.
|
|
21
|
-
For details, see: `{{
|
|
21
|
+
For details, see: `{{RRCE_DATA}}/docs/path-resolution.md`
|
|
22
22
|
|
|
23
23
|
Pipeline Position
|
|
24
24
|
- **Requires**: Planning phase must be complete before execution can begin.
|
|
@@ -85,7 +85,7 @@ Workflow
|
|
|
85
85
|
2. Set `agents.executor.status` in `meta.json` to `in_progress` while working and `complete` after delivering.
|
|
86
86
|
3. Maintain checklist entries with current progress markers and timestamps where helpful.
|
|
87
87
|
4. Record checkpoints, blockers, and validation steps in `agents.executor.notes` and `references`.
|
|
88
|
-
5. Capture your implementation log using `{{
|
|
88
|
+
5. Capture your implementation log using `{{RRCE_DATA}}/templates/executor_output.md` and save it to `{{RRCE_DATA}}/tasks/{{TASK_SLUG}}/execution/{{TASK_SLUG}}-execution.md`, noting the provided `BRANCH` or current git ref.
|
|
89
89
|
6. Summarize test evidence, code pointers, and outstanding follow-ups so documentation can build on it seamlessly.
|
|
90
90
|
7. **Semantic Indexing**: If significant code was added or modified, suggest running `index_knowledge` to update the semantic search index:
|
|
91
91
|
- Tool: `index_knowledge`
|
|
@@ -93,5 +93,5 @@ Workflow
|
|
|
93
93
|
|
|
94
94
|
Deliverable
|
|
95
95
|
- File: `{{RRCE_DATA}}/tasks/{{TASK_SLUG}}/execution/{{TASK_SLUG}}-execution.md`
|
|
96
|
-
- Format: `{{
|
|
96
|
+
- Format: `{{RRCE_DATA}}/templates/executor_output.md`
|
|
97
97
|
- Outcome: Implementation log covering what was built, how it was validated, and what remains, kept lean and actionable.
|
|
@@ -17,7 +17,7 @@ You are the Project Initializer for RRCE-Workflow. Your mission: create a compre
|
|
|
17
17
|
|
|
18
18
|
## Path Resolution
|
|
19
19
|
Use the pre-resolved paths from the "System Resolved Paths" table in the context preamble.
|
|
20
|
-
For details, see: `{{
|
|
20
|
+
For details, see: `{{RRCE_DATA}}/docs/path-resolution.md`
|
|
21
21
|
|
|
22
22
|
## Pipeline Position
|
|
23
23
|
- **Entry Point**: Run before any other agent for new projects
|
|
@@ -122,7 +122,7 @@ Scan in this priority order. Stop early if sufficient information gathered:
|
|
|
122
122
|
### Step 3: Generate Project Context
|
|
123
123
|
|
|
124
124
|
1. Ensure `{{RRCE_DATA}}/knowledge/` directory exists (create if absent)
|
|
125
|
-
2. Compile findings using template: `{{
|
|
125
|
+
2. Compile findings using template: `{{RRCE_DATA}}/templates/init_output.md`
|
|
126
126
|
3. Save to: `{{RRCE_DATA}}/knowledge/project-context.md`
|
|
127
127
|
4. Update `{{RRCE_DATA}}/workspace.json` with project metadata if it exists
|
|
128
128
|
|
|
@@ -160,7 +160,7 @@ Provide a brief summary:
|
|
|
160
160
|
## Deliverable
|
|
161
161
|
|
|
162
162
|
- **File**: `{{RRCE_DATA}}/knowledge/project-context.md`
|
|
163
|
-
- **Template**: `{{
|
|
163
|
+
- **Template**: `{{RRCE_DATA}}/templates/init_output.md`
|
|
164
164
|
- **Index**: `{{RRCE_DATA}}/knowledge/embeddings.json`
|
|
165
165
|
- **Outcome**: Comprehensive project context + searchable semantic index
|
|
166
166
|
|
|
@@ -15,7 +15,7 @@ You are the Planning & Task Orchestrator for the project. Operate like an engine
|
|
|
15
15
|
|
|
16
16
|
## Path Resolution
|
|
17
17
|
Use the pre-resolved paths from the "System Resolved Paths" table in the context preamble.
|
|
18
|
-
For details, see: `{{
|
|
18
|
+
For details, see: `{{RRCE_DATA}}/docs/path-resolution.md`
|
|
19
19
|
|
|
20
20
|
Pipeline Position
|
|
21
21
|
- **Requires**: Research phase must be complete before planning can begin.
|
|
@@ -58,12 +58,12 @@ Non-Negotiables
|
|
|
58
58
|
|
|
59
59
|
Workflow
|
|
60
60
|
1. Confirm `TASK_SLUG` (prompt if missing) and ensure directories exist at `{{RRCE_DATA}}/tasks/{{TASK_SLUG}}/planning` and `{{RRCE_DATA}}/knowledge`, creating them automatically if absent.
|
|
61
|
-
2. Update `{{RRCE_DATA}}/tasks/{{TASK_SLUG}}/meta.json` (copy the template from `{{
|
|
61
|
+
2. Update `{{RRCE_DATA}}/tasks/{{TASK_SLUG}}/meta.json` (copy the template from `{{RRCE_DATA}}/templates/meta.template.json` if it is not already present):
|
|
62
62
|
- Mark `agents.planning.status` as `in_progress` while drafting and `complete` upon handoff.
|
|
63
63
|
- Link the plan artifact path in `agents.planning.artifact`.
|
|
64
64
|
- Populate or refresh `summary`, `references`, `milestones`, `checklist`, and `open_questions`.
|
|
65
65
|
3. Where new persistent knowledge is created (API notes, domain decisions, etc.), append or create records in `{{RRCE_DATA}}/knowledge/{{DOMAIN}}.md` and log the file path inside `meta.json.references`.
|
|
66
|
-
4. Structure the plan using `{{
|
|
66
|
+
4. Structure the plan using `{{RRCE_DATA}}/templates/planning_output.md` and store it at `{{RRCE_DATA}}/tasks/{{TASK_SLUG}}/planning/{{TASK_SLUG}}-plan.md`.
|
|
67
67
|
5. Provide clear guidance on validation, testing strategy, rollout sequencing, and success criteria for the Executor.
|
|
68
68
|
6. **Semantic Indexing**: If new knowledge files were created in `{{RRCE_DATA}}/knowledge/`, suggest running `index_knowledge` to update the semantic search index:
|
|
69
69
|
- Tool: `index_knowledge`
|
|
@@ -71,5 +71,5 @@ Workflow
|
|
|
71
71
|
|
|
72
72
|
Deliverable
|
|
73
73
|
- File: `{{RRCE_DATA}}/tasks/{{TASK_SLUG}}/planning/{{TASK_SLUG}}-plan.md`
|
|
74
|
-
- Format: `{{
|
|
74
|
+
- Format: `{{RRCE_DATA}}/templates/planning_output.md`
|
|
75
75
|
- Outcome: Ordered, actionable roadmap with dependencies, acceptance criteria, context links, and knowledge updates ready for implementation.
|
|
@@ -22,7 +22,7 @@ You are the Research & Discussion Lead for RRCE-Workflow. Your mission: refine i
|
|
|
22
22
|
|
|
23
23
|
## Path Resolution
|
|
24
24
|
Use the pre-resolved paths from the "System Resolved Paths" table in the context preamble.
|
|
25
|
-
For details, see: `{{
|
|
25
|
+
For details, see: `{{RRCE_DATA}}/docs/path-resolution.md`
|
|
26
26
|
|
|
27
27
|
## Pipeline Position
|
|
28
28
|
- **Entry Point**: First agent invoked for new tasks
|
|
@@ -83,7 +83,7 @@ Based on knowledge search, create a gap analysis:
|
|
|
83
83
|
### Step 3: Setup Task Structure
|
|
84
84
|
|
|
85
85
|
1. Ensure directory exists: `{{RRCE_DATA}}/tasks/{{TASK_SLUG}}/research/`
|
|
86
|
-
2. Copy meta template if new task: `{{
|
|
86
|
+
2. Copy meta template if new task: `{{RRCE_DATA}}/templates/meta.template.json` → `{{RRCE_DATA}}/tasks/{{TASK_SLUG}}/meta.json`
|
|
87
87
|
3. Populate initial metadata:
|
|
88
88
|
- `task_id`: Generate UUID
|
|
89
89
|
- `task_slug`: From argument
|
|
@@ -127,7 +127,7 @@ Document the decision in `meta.json.decisions`.
|
|
|
127
127
|
|
|
128
128
|
### Step 6: Generate Research Brief
|
|
129
129
|
|
|
130
|
-
1. Compile findings using template: `{{
|
|
130
|
+
1. Compile findings using template: `{{RRCE_DATA}}/templates/research_output.md`
|
|
131
131
|
2. Save to: `{{RRCE_DATA}}/tasks/{{TASK_SLUG}}/research/{{TASK_SLUG}}-research.md`
|
|
132
132
|
|
|
133
133
|
**Brief includes:**
|
|
@@ -188,7 +188,7 @@ Research is complete when:
|
|
|
188
188
|
## Deliverable
|
|
189
189
|
|
|
190
190
|
- **File**: `{{RRCE_DATA}}/tasks/{{TASK_SLUG}}/research/{{TASK_SLUG}}-research.md`
|
|
191
|
-
- **Template**: `{{
|
|
191
|
+
- **Template**: `{{RRCE_DATA}}/templates/research_output.md`
|
|
192
192
|
- **Metadata**: `{{RRCE_DATA}}/tasks/{{TASK_SLUG}}/meta.json` with status `complete`
|
|
193
193
|
- **Outcome**: Planning agent can proceed without re-asking the same questions
|
|
194
194
|
|
|
@@ -16,7 +16,7 @@ You are the Knowledge Sync Lead. Act like a senior architect charged with keepin
|
|
|
16
16
|
|
|
17
17
|
## Path Resolution
|
|
18
18
|
Use the pre-resolved paths from the "System Resolved Paths" table in the context preamble.
|
|
19
|
-
For details, see: `{{
|
|
19
|
+
For details, see: `{{RRCE_DATA}}/docs/path-resolution.md`
|
|
20
20
|
|
|
21
21
|
Pipeline Position
|
|
22
22
|
- **Maintenance Agent**: Sync runs periodically or after significant codebase changes to keep knowledge current.
|
package/dist/index.js
CHANGED
|
@@ -1390,7 +1390,7 @@ var init_types = __esm({
|
|
|
1390
1390
|
},
|
|
1391
1391
|
projects: [],
|
|
1392
1392
|
defaults: {
|
|
1393
|
-
includeNew:
|
|
1393
|
+
includeNew: false,
|
|
1394
1394
|
permissions: {
|
|
1395
1395
|
knowledge: true,
|
|
1396
1396
|
tasks: true,
|
|
@@ -1407,15 +1407,27 @@ var init_types = __esm({
|
|
|
1407
1407
|
});
|
|
1408
1408
|
|
|
1409
1409
|
// src/mcp/config-utils.ts
|
|
1410
|
+
import * as path10 from "path";
|
|
1411
|
+
function normalizeProjectPath(projectPath) {
|
|
1412
|
+
if (projectPath.endsWith(".rrce-workflow")) {
|
|
1413
|
+
return path10.dirname(projectPath);
|
|
1414
|
+
}
|
|
1415
|
+
if (projectPath.endsWith(".rrce-workflow/")) {
|
|
1416
|
+
return path10.dirname(projectPath.slice(0, -1));
|
|
1417
|
+
}
|
|
1418
|
+
return projectPath;
|
|
1419
|
+
}
|
|
1410
1420
|
function findProjectConfig(config, identifier) {
|
|
1421
|
+
const targetPath = identifier.path ? normalizeProjectPath(identifier.path) : void 0;
|
|
1411
1422
|
return config.projects.find((p) => {
|
|
1412
|
-
|
|
1413
|
-
|
|
1423
|
+
const configPath = p.path ? normalizeProjectPath(p.path) : void 0;
|
|
1424
|
+
if (targetPath && configPath) {
|
|
1425
|
+
return configPath === targetPath;
|
|
1414
1426
|
}
|
|
1415
|
-
if (!
|
|
1427
|
+
if (!targetPath && !configPath) {
|
|
1416
1428
|
return p.name === identifier.name;
|
|
1417
1429
|
}
|
|
1418
|
-
if (
|
|
1430
|
+
if (targetPath && !configPath) {
|
|
1419
1431
|
return p.name === identifier.name;
|
|
1420
1432
|
}
|
|
1421
1433
|
return false;
|
|
@@ -1441,18 +1453,46 @@ __export(config_exports, {
|
|
|
1441
1453
|
setProjectConfig: () => setProjectConfig
|
|
1442
1454
|
});
|
|
1443
1455
|
import * as fs9 from "fs";
|
|
1444
|
-
import * as
|
|
1456
|
+
import * as path11 from "path";
|
|
1445
1457
|
import YAML from "yaml";
|
|
1458
|
+
function migrateConfig(config) {
|
|
1459
|
+
let changed = false;
|
|
1460
|
+
config.projects = config.projects.map((p) => {
|
|
1461
|
+
if (p.path) {
|
|
1462
|
+
const normalized = normalizeProjectPath(p.path);
|
|
1463
|
+
if (normalized !== p.path) {
|
|
1464
|
+
changed = true;
|
|
1465
|
+
return { ...p, path: normalized };
|
|
1466
|
+
}
|
|
1467
|
+
}
|
|
1468
|
+
return p;
|
|
1469
|
+
});
|
|
1470
|
+
return config;
|
|
1471
|
+
}
|
|
1446
1472
|
function getMCPConfigPath() {
|
|
1447
1473
|
const workspaceRoot = detectWorkspaceRoot();
|
|
1448
1474
|
const rrceHome = getEffectiveRRCEHome(workspaceRoot);
|
|
1449
|
-
return
|
|
1475
|
+
return path11.join(rrceHome, "mcp.yaml");
|
|
1476
|
+
}
|
|
1477
|
+
function loadMCPConfig() {
|
|
1478
|
+
const configPath = getMCPConfigPath();
|
|
1479
|
+
if (!fs9.existsSync(configPath)) {
|
|
1480
|
+
return { ...DEFAULT_MCP_CONFIG };
|
|
1481
|
+
}
|
|
1482
|
+
try {
|
|
1483
|
+
const content = fs9.readFileSync(configPath, "utf-8");
|
|
1484
|
+
let config = parseMCPConfig(content);
|
|
1485
|
+
config = migrateConfig(config);
|
|
1486
|
+
return config;
|
|
1487
|
+
} catch {
|
|
1488
|
+
return { ...DEFAULT_MCP_CONFIG };
|
|
1489
|
+
}
|
|
1450
1490
|
}
|
|
1451
1491
|
function ensureMCPGlobalPath() {
|
|
1452
1492
|
const workspaceRoot = detectWorkspaceRoot();
|
|
1453
1493
|
const rrceHome = getEffectiveRRCEHome(workspaceRoot);
|
|
1454
1494
|
if (rrceHome.startsWith(".") || rrceHome.includes(".rrce-workflow/")) {
|
|
1455
|
-
const configPath =
|
|
1495
|
+
const configPath = path11.join(workspaceRoot, ".rrce-workflow", "config.yaml");
|
|
1456
1496
|
if (fs9.existsSync(configPath)) {
|
|
1457
1497
|
const content = fs9.readFileSync(configPath, "utf-8");
|
|
1458
1498
|
const modeMatch = content.match(/mode:\s*(global|workspace)/);
|
|
@@ -1470,21 +1510,9 @@ function ensureMCPGlobalPath() {
|
|
|
1470
1510
|
path: rrceHome
|
|
1471
1511
|
};
|
|
1472
1512
|
}
|
|
1473
|
-
function loadMCPConfig() {
|
|
1474
|
-
const configPath = getMCPConfigPath();
|
|
1475
|
-
if (!fs9.existsSync(configPath)) {
|
|
1476
|
-
return { ...DEFAULT_MCP_CONFIG };
|
|
1477
|
-
}
|
|
1478
|
-
try {
|
|
1479
|
-
const content = fs9.readFileSync(configPath, "utf-8");
|
|
1480
|
-
return parseMCPConfig(content);
|
|
1481
|
-
} catch {
|
|
1482
|
-
return { ...DEFAULT_MCP_CONFIG };
|
|
1483
|
-
}
|
|
1484
|
-
}
|
|
1485
1513
|
function saveMCPConfig(config) {
|
|
1486
1514
|
const configPath = getMCPConfigPath();
|
|
1487
|
-
const dir =
|
|
1515
|
+
const dir = path11.dirname(configPath);
|
|
1488
1516
|
if (!fs9.existsSync(dir)) {
|
|
1489
1517
|
fs9.mkdirSync(dir, { recursive: true });
|
|
1490
1518
|
}
|
|
@@ -1576,7 +1604,7 @@ function getProjectPermissions(config, name, projectPath) {
|
|
|
1576
1604
|
}
|
|
1577
1605
|
function cleanStaleProjects(config) {
|
|
1578
1606
|
const rrceHome = getEffectiveGlobalPath();
|
|
1579
|
-
const globalWorkspacesDir =
|
|
1607
|
+
const globalWorkspacesDir = path11.join(rrceHome, "workspaces");
|
|
1580
1608
|
const validProjects = [];
|
|
1581
1609
|
const removed = [];
|
|
1582
1610
|
for (const project of config.projects) {
|
|
@@ -1584,7 +1612,7 @@ function cleanStaleProjects(config) {
|
|
|
1584
1612
|
if (project.path) {
|
|
1585
1613
|
exists = fs9.existsSync(project.path);
|
|
1586
1614
|
} else {
|
|
1587
|
-
const globalPath =
|
|
1615
|
+
const globalPath = path11.join(globalWorkspacesDir, project.name);
|
|
1588
1616
|
exists = fs9.existsSync(globalPath);
|
|
1589
1617
|
}
|
|
1590
1618
|
if (exists) {
|
|
@@ -1609,23 +1637,29 @@ var init_config = __esm({
|
|
|
1609
1637
|
|
|
1610
1638
|
// src/commands/wizard/setup-actions.ts
|
|
1611
1639
|
import * as fs10 from "fs";
|
|
1612
|
-
import * as
|
|
1640
|
+
import * as path12 from "path";
|
|
1613
1641
|
import pc4 from "picocolors";
|
|
1614
1642
|
import { note as note2 } from "@clack/prompts";
|
|
1615
1643
|
function createDirectoryStructure(dataPaths) {
|
|
1616
1644
|
for (const dataPath of dataPaths) {
|
|
1617
1645
|
ensureDir(dataPath);
|
|
1618
|
-
ensureDir(
|
|
1619
|
-
ensureDir(
|
|
1620
|
-
ensureDir(
|
|
1621
|
-
ensureDir(
|
|
1646
|
+
ensureDir(path12.join(dataPath, "knowledge"));
|
|
1647
|
+
ensureDir(path12.join(dataPath, "refs"));
|
|
1648
|
+
ensureDir(path12.join(dataPath, "tasks"));
|
|
1649
|
+
ensureDir(path12.join(dataPath, "templates"));
|
|
1622
1650
|
}
|
|
1623
1651
|
}
|
|
1624
1652
|
function installAgentPrompts(config, workspacePath, dataPaths) {
|
|
1625
1653
|
const agentCoreDir = getAgentCoreDir();
|
|
1626
1654
|
syncMetadataToAll(agentCoreDir, dataPaths);
|
|
1627
|
-
copyDirToAllStoragePaths(
|
|
1628
|
-
copyDirToAllStoragePaths(
|
|
1655
|
+
copyDirToAllStoragePaths(path12.join(agentCoreDir, "templates"), "templates", dataPaths);
|
|
1656
|
+
copyDirToAllStoragePaths(path12.join(agentCoreDir, "prompts"), "prompts", dataPaths);
|
|
1657
|
+
copyDirToAllStoragePaths(path12.join(agentCoreDir, "docs"), "docs", dataPaths);
|
|
1658
|
+
const rrceHome = config.globalPath || getDefaultRRCEHome2();
|
|
1659
|
+
ensureDir(path12.join(rrceHome, "templates"));
|
|
1660
|
+
ensureDir(path12.join(rrceHome, "docs"));
|
|
1661
|
+
copyDirRecursive(path12.join(agentCoreDir, "templates"), path12.join(rrceHome, "templates"));
|
|
1662
|
+
copyDirRecursive(path12.join(agentCoreDir, "docs"), path12.join(rrceHome, "docs"));
|
|
1629
1663
|
const needsIDEPrompts = config.storageMode === "workspace" && (config.tools.includes("copilot") || config.tools.includes("antigravity")) || config.tools.includes("opencode");
|
|
1630
1664
|
if (needsIDEPrompts) {
|
|
1631
1665
|
const prompts = loadPromptsFromDir(getAgentCorePromptsDir());
|
|
@@ -1642,12 +1676,12 @@ function installAgentPrompts(config, workspacePath, dataPaths) {
|
|
|
1642
1676
|
}
|
|
1643
1677
|
}
|
|
1644
1678
|
if (config.tools.includes("opencode")) {
|
|
1645
|
-
const opencodePath =
|
|
1679
|
+
const opencodePath = path12.join(workspacePath, ".opencode", "agent");
|
|
1646
1680
|
ensureDir(opencodePath);
|
|
1647
1681
|
for (const prompt of prompts) {
|
|
1648
|
-
const baseName =
|
|
1682
|
+
const baseName = path12.basename(prompt.filePath, ".md");
|
|
1649
1683
|
const content = convertToOpenCodeAgent(prompt);
|
|
1650
|
-
fs10.writeFileSync(
|
|
1684
|
+
fs10.writeFileSync(path12.join(opencodePath, `${baseName}.md`), content);
|
|
1651
1685
|
}
|
|
1652
1686
|
}
|
|
1653
1687
|
}
|
|
@@ -1656,11 +1690,11 @@ function createWorkspaceConfig(config, workspacePath, workspaceName) {
|
|
|
1656
1690
|
let configPath;
|
|
1657
1691
|
if (config.storageMode === "global") {
|
|
1658
1692
|
const rrceHome = config.globalPath || getDefaultRRCEHome2();
|
|
1659
|
-
configPath =
|
|
1693
|
+
configPath = path12.join(rrceHome, "workspaces", workspaceName, "config.yaml");
|
|
1660
1694
|
} else {
|
|
1661
|
-
configPath =
|
|
1695
|
+
configPath = path12.join(workspacePath, ".rrce-workflow", "config.yaml");
|
|
1662
1696
|
}
|
|
1663
|
-
ensureDir(
|
|
1697
|
+
ensureDir(path12.dirname(configPath));
|
|
1664
1698
|
let content = `# RRCE-Workflow Configuration
|
|
1665
1699
|
version: 1
|
|
1666
1700
|
|
|
@@ -1723,8 +1757,8 @@ You can configure MCP later: ${pc4.cyan("npx rrce-workflow mcp")}`,
|
|
|
1723
1757
|
}
|
|
1724
1758
|
}
|
|
1725
1759
|
function getDataPaths(mode, workspaceName, workspaceRoot, customGlobalPath) {
|
|
1726
|
-
const globalPath =
|
|
1727
|
-
const workspacePath =
|
|
1760
|
+
const globalPath = path12.join(customGlobalPath || getDefaultRRCEHome2(), "workspaces", workspaceName);
|
|
1761
|
+
const workspacePath = path12.join(workspaceRoot, ".rrce-workflow");
|
|
1728
1762
|
switch (mode) {
|
|
1729
1763
|
case "global":
|
|
1730
1764
|
return [globalPath];
|
|
@@ -1778,9 +1812,9 @@ __export(gitignore_exports, {
|
|
|
1778
1812
|
updateGitignore: () => updateGitignore
|
|
1779
1813
|
});
|
|
1780
1814
|
import * as fs11 from "fs";
|
|
1781
|
-
import * as
|
|
1815
|
+
import * as path13 from "path";
|
|
1782
1816
|
function updateGitignore(workspacePath, storageMode, tools) {
|
|
1783
|
-
const gitignorePath =
|
|
1817
|
+
const gitignorePath = path13.join(workspacePath, ".gitignore");
|
|
1784
1818
|
const entries = [];
|
|
1785
1819
|
if (storageMode === "workspace") {
|
|
1786
1820
|
entries.push(".rrce-workflow/");
|
|
@@ -1820,11 +1854,11 @@ var init_gitignore = __esm({
|
|
|
1820
1854
|
|
|
1821
1855
|
// src/mcp/logger.ts
|
|
1822
1856
|
import * as fs12 from "fs";
|
|
1823
|
-
import * as
|
|
1857
|
+
import * as path14 from "path";
|
|
1824
1858
|
function getLogFilePath() {
|
|
1825
1859
|
const workspaceRoot = detectWorkspaceRoot();
|
|
1826
1860
|
const rrceHome = getEffectiveRRCEHome(workspaceRoot);
|
|
1827
|
-
return
|
|
1861
|
+
return path14.join(rrceHome, "mcp-server.log");
|
|
1828
1862
|
}
|
|
1829
1863
|
var Logger, logger;
|
|
1830
1864
|
var init_logger = __esm({
|
|
@@ -1855,7 +1889,7 @@ ${JSON.stringify(data, null, 2)}`;
|
|
|
1855
1889
|
}
|
|
1856
1890
|
logMessage += "\n";
|
|
1857
1891
|
try {
|
|
1858
|
-
const dir =
|
|
1892
|
+
const dir = path14.dirname(this.logPath);
|
|
1859
1893
|
if (!fs12.existsSync(dir)) {
|
|
1860
1894
|
fs12.mkdirSync(dir, { recursive: true });
|
|
1861
1895
|
}
|
|
@@ -1884,7 +1918,7 @@ ${JSON.stringify(data, null, 2)}`;
|
|
|
1884
1918
|
|
|
1885
1919
|
// src/mcp/services/rag.ts
|
|
1886
1920
|
import * as fs13 from "fs";
|
|
1887
|
-
import * as
|
|
1921
|
+
import * as path15 from "path";
|
|
1888
1922
|
var INDEX_VERSION, DEFAULT_MODEL, RAGService;
|
|
1889
1923
|
var init_rag = __esm({
|
|
1890
1924
|
"src/mcp/services/rag.ts"() {
|
|
@@ -1966,7 +2000,7 @@ var init_rag = __esm({
|
|
|
1966
2000
|
saveIndex() {
|
|
1967
2001
|
if (!this.index) return;
|
|
1968
2002
|
try {
|
|
1969
|
-
const dir =
|
|
2003
|
+
const dir = path15.dirname(this.indexPath);
|
|
1970
2004
|
if (!fs13.existsSync(dir)) {
|
|
1971
2005
|
fs13.mkdirSync(dir, { recursive: true });
|
|
1972
2006
|
}
|
|
@@ -2132,21 +2166,19 @@ var init_rag = __esm({
|
|
|
2132
2166
|
|
|
2133
2167
|
// src/mcp/resources.ts
|
|
2134
2168
|
import * as fs14 from "fs";
|
|
2135
|
-
import * as
|
|
2169
|
+
import * as path16 from "path";
|
|
2136
2170
|
function getExposedProjects() {
|
|
2137
2171
|
const config = loadMCPConfig();
|
|
2138
2172
|
const knownPaths = config.projects.map((p) => p.path).filter((p) => !!p);
|
|
2139
2173
|
const allProjects = projectService.scan({ knownPaths });
|
|
2140
|
-
const
|
|
2141
|
-
const
|
|
2142
|
-
let linkedProjects = [];
|
|
2174
|
+
const activeProject = detectActiveProject(allProjects);
|
|
2175
|
+
const potentialProjects = [...allProjects];
|
|
2143
2176
|
if (activeProject) {
|
|
2144
|
-
const localConfigPath = path15.join(activeProject.dataPath, "config.yaml");
|
|
2145
2177
|
let cfgContent = null;
|
|
2146
|
-
if (fs14.existsSync(
|
|
2147
|
-
cfgContent = fs14.readFileSync(
|
|
2148
|
-
} else if (fs14.existsSync(
|
|
2149
|
-
cfgContent = fs14.readFileSync(
|
|
2178
|
+
if (fs14.existsSync(path16.join(activeProject.dataPath, ".rrce-workflow", "config.yaml"))) {
|
|
2179
|
+
cfgContent = fs14.readFileSync(path16.join(activeProject.dataPath, ".rrce-workflow", "config.yaml"), "utf-8");
|
|
2180
|
+
} else if (fs14.existsSync(path16.join(activeProject.dataPath, ".rrce-workflow.yaml"))) {
|
|
2181
|
+
cfgContent = fs14.readFileSync(path16.join(activeProject.dataPath, ".rrce-workflow.yaml"), "utf-8");
|
|
2150
2182
|
}
|
|
2151
2183
|
if (cfgContent) {
|
|
2152
2184
|
if (cfgContent.includes("linked_projects:")) {
|
|
@@ -2166,10 +2198,10 @@ function getExposedProjects() {
|
|
|
2166
2198
|
if (inLinked && trimmed.startsWith("-")) {
|
|
2167
2199
|
const val = trimmed.replace(/^-\s*/, "").trim();
|
|
2168
2200
|
const [pName] = val.split(":");
|
|
2169
|
-
if (!
|
|
2201
|
+
if (!potentialProjects.some((p) => p.name === pName)) {
|
|
2170
2202
|
const found = allProjects.find((p) => p.name === pName);
|
|
2171
2203
|
if (found) {
|
|
2172
|
-
|
|
2204
|
+
potentialProjects.push(found);
|
|
2173
2205
|
}
|
|
2174
2206
|
}
|
|
2175
2207
|
}
|
|
@@ -2178,11 +2210,11 @@ function getExposedProjects() {
|
|
|
2178
2210
|
}
|
|
2179
2211
|
}
|
|
2180
2212
|
}
|
|
2181
|
-
return
|
|
2213
|
+
return potentialProjects.filter((project) => isProjectExposed(config, project.name, project.path));
|
|
2182
2214
|
}
|
|
2183
2215
|
function getRAGIndexPath(project) {
|
|
2184
2216
|
const scanRoot = project.path || project.dataPath;
|
|
2185
|
-
return
|
|
2217
|
+
return path16.join(project.knowledgePath || path16.join(scanRoot, ".rrce-workflow", "knowledge"), "embeddings.json");
|
|
2186
2218
|
}
|
|
2187
2219
|
function detectActiveProject(knownProjects) {
|
|
2188
2220
|
let scanList = knownProjects;
|
|
@@ -2190,25 +2222,25 @@ function detectActiveProject(knownProjects) {
|
|
|
2190
2222
|
const config = loadMCPConfig();
|
|
2191
2223
|
const knownPaths = config.projects.map((p) => p.path).filter((p) => !!p);
|
|
2192
2224
|
const all = projectService.scan({ knownPaths });
|
|
2193
|
-
scanList = all.filter((project) => isProjectExposed(config, project.name, project.
|
|
2225
|
+
scanList = all.filter((project) => isProjectExposed(config, project.name, project.path));
|
|
2194
2226
|
}
|
|
2195
2227
|
return findClosestProject(scanList);
|
|
2196
2228
|
}
|
|
2197
2229
|
function getProjectContext(projectName) {
|
|
2198
2230
|
const config = loadMCPConfig();
|
|
2199
2231
|
const projects = projectService.scan();
|
|
2200
|
-
const project = projects.find((p) => p.name === projectName && isProjectExposed(config, p.name, p.
|
|
2232
|
+
const project = projects.find((p) => p.name === projectName && isProjectExposed(config, p.name, p.path));
|
|
2201
2233
|
if (!project) {
|
|
2202
2234
|
return null;
|
|
2203
2235
|
}
|
|
2204
|
-
const permissions = getProjectPermissions(config, projectName, project.
|
|
2236
|
+
const permissions = getProjectPermissions(config, projectName, project.path);
|
|
2205
2237
|
if (!permissions.knowledge) {
|
|
2206
2238
|
return null;
|
|
2207
2239
|
}
|
|
2208
2240
|
if (!project.knowledgePath) {
|
|
2209
2241
|
return null;
|
|
2210
2242
|
}
|
|
2211
|
-
const contextPath =
|
|
2243
|
+
const contextPath = path16.join(project.knowledgePath, "project-context.md");
|
|
2212
2244
|
if (!fs14.existsSync(contextPath)) {
|
|
2213
2245
|
return null;
|
|
2214
2246
|
}
|
|
@@ -2217,11 +2249,11 @@ function getProjectContext(projectName) {
|
|
|
2217
2249
|
function getProjectTasks(projectName) {
|
|
2218
2250
|
const config = loadMCPConfig();
|
|
2219
2251
|
const projects = projectService.scan();
|
|
2220
|
-
const project = projects.find((p) => p.name === projectName && isProjectExposed(config, p.name, p.
|
|
2252
|
+
const project = projects.find((p) => p.name === projectName && isProjectExposed(config, p.name, p.path));
|
|
2221
2253
|
if (!project) {
|
|
2222
2254
|
return [];
|
|
2223
2255
|
}
|
|
2224
|
-
const permissions = getProjectPermissions(config, projectName, project.
|
|
2256
|
+
const permissions = getProjectPermissions(config, projectName, project.path);
|
|
2225
2257
|
if (!permissions.tasks) {
|
|
2226
2258
|
return [];
|
|
2227
2259
|
}
|
|
@@ -2233,7 +2265,7 @@ function getProjectTasks(projectName) {
|
|
|
2233
2265
|
const taskDirs = fs14.readdirSync(project.tasksPath, { withFileTypes: true });
|
|
2234
2266
|
for (const dir of taskDirs) {
|
|
2235
2267
|
if (!dir.isDirectory()) continue;
|
|
2236
|
-
const metaPath =
|
|
2268
|
+
const metaPath = path16.join(project.tasksPath, dir.name, "meta.json");
|
|
2237
2269
|
if (fs14.existsSync(metaPath)) {
|
|
2238
2270
|
try {
|
|
2239
2271
|
const meta = JSON.parse(fs14.readFileSync(metaPath, "utf-8"));
|
|
@@ -2253,21 +2285,21 @@ async function searchKnowledge(query, projectFilter) {
|
|
|
2253
2285
|
const queryLower = query.toLowerCase();
|
|
2254
2286
|
for (const project of projects) {
|
|
2255
2287
|
if (projectFilter && project.name !== projectFilter) continue;
|
|
2256
|
-
const permissions = getProjectPermissions(config, project.name, project.
|
|
2288
|
+
const permissions = getProjectPermissions(config, project.name, project.path);
|
|
2257
2289
|
if (!permissions.knowledge || !project.knowledgePath) continue;
|
|
2258
2290
|
const projConfig = config.projects.find(
|
|
2259
|
-
(p) => p.path && p.path === project.
|
|
2291
|
+
(p) => p.path && normalizeProjectPath(p.path) === normalizeProjectPath(project.path) || !p.path && p.name === project.name
|
|
2260
2292
|
);
|
|
2261
2293
|
const useRAG = projConfig?.semanticSearch?.enabled;
|
|
2262
2294
|
if (useRAG) {
|
|
2263
2295
|
try {
|
|
2264
|
-
const indexPath =
|
|
2296
|
+
const indexPath = path16.join(project.knowledgePath, "embeddings.json");
|
|
2265
2297
|
const rag = new RAGService(indexPath, projConfig?.semanticSearch?.model);
|
|
2266
2298
|
const ragResults = await rag.search(query, 5);
|
|
2267
2299
|
for (const r of ragResults) {
|
|
2268
2300
|
results.push({
|
|
2269
2301
|
project: project.name,
|
|
2270
|
-
file:
|
|
2302
|
+
file: path16.relative(project.knowledgePath, r.filePath),
|
|
2271
2303
|
matches: [r.content],
|
|
2272
2304
|
// The chunk content is the match
|
|
2273
2305
|
score: r.score
|
|
@@ -2281,7 +2313,7 @@ async function searchKnowledge(query, projectFilter) {
|
|
|
2281
2313
|
const files = fs14.readdirSync(project.knowledgePath);
|
|
2282
2314
|
for (const file of files) {
|
|
2283
2315
|
if (!file.endsWith(".md")) continue;
|
|
2284
|
-
const filePath =
|
|
2316
|
+
const filePath = path16.join(project.knowledgePath, file);
|
|
2285
2317
|
const content = fs14.readFileSync(filePath, "utf-8");
|
|
2286
2318
|
const lines = content.split("\n");
|
|
2287
2319
|
const matches = [];
|
|
@@ -2312,7 +2344,7 @@ async function indexKnowledge(projectName, force = false) {
|
|
|
2312
2344
|
return { success: false, message: `Project '${projectName}' not found`, filesIndexed: 0, filesSkipped: 0 };
|
|
2313
2345
|
}
|
|
2314
2346
|
const projConfig = config.projects.find(
|
|
2315
|
-
(p) => p.path && p.path === project.
|
|
2347
|
+
(p) => p.path && normalizeProjectPath(p.path) === normalizeProjectPath(project.path) || !p.path && p.name === project.name
|
|
2316
2348
|
) || (project.source === "global" ? { semanticSearch: { enabled: true, model: "Xenova/all-MiniLM-L6-v2" } } : void 0);
|
|
2317
2349
|
const isEnabled = projConfig?.semanticSearch?.enabled || project.semanticSearchEnabled;
|
|
2318
2350
|
if (!isEnabled) {
|
|
@@ -2362,7 +2394,7 @@ async function indexKnowledge(projectName, force = false) {
|
|
|
2362
2394
|
];
|
|
2363
2395
|
const SKIP_DIRS = ["node_modules", ".git", "dist", "build", ".next", "__pycache__", "venv", ".venv", "target", "vendor"];
|
|
2364
2396
|
try {
|
|
2365
|
-
const indexPath =
|
|
2397
|
+
const indexPath = path16.join(project.knowledgePath || path16.join(scanRoot, ".rrce-workflow", "knowledge"), "embeddings.json");
|
|
2366
2398
|
const model = projConfig?.semanticSearch?.model || "Xenova/all-MiniLM-L6-v2";
|
|
2367
2399
|
const rag = new RAGService(indexPath, model);
|
|
2368
2400
|
let indexed = 0;
|
|
@@ -2370,14 +2402,14 @@ async function indexKnowledge(projectName, force = false) {
|
|
|
2370
2402
|
const scanDir = async (dir) => {
|
|
2371
2403
|
const entries = fs14.readdirSync(dir, { withFileTypes: true });
|
|
2372
2404
|
for (const entry of entries) {
|
|
2373
|
-
const fullPath =
|
|
2405
|
+
const fullPath = path16.join(dir, entry.name);
|
|
2374
2406
|
if (entry.isDirectory()) {
|
|
2375
2407
|
if (SKIP_DIRS.includes(entry.name) || entry.name.startsWith(".")) {
|
|
2376
2408
|
continue;
|
|
2377
2409
|
}
|
|
2378
2410
|
await scanDir(fullPath);
|
|
2379
2411
|
} else if (entry.isFile()) {
|
|
2380
|
-
const ext =
|
|
2412
|
+
const ext = path16.extname(entry.name).toLowerCase();
|
|
2381
2413
|
if (!INDEXABLE_EXTENSIONS.includes(ext)) {
|
|
2382
2414
|
continue;
|
|
2383
2415
|
}
|
|
@@ -2414,7 +2446,7 @@ function getContextPreamble() {
|
|
|
2414
2446
|
const activeProject = detectActiveProject();
|
|
2415
2447
|
let contextPreamble = "";
|
|
2416
2448
|
if (activeProject) {
|
|
2417
|
-
const rrceHome = process.env.RRCE_HOME ||
|
|
2449
|
+
const rrceHome = process.env.RRCE_HOME || path16.join(__require("os").homedir(), ".rrce-workflow");
|
|
2418
2450
|
const workspaceRoot = activeProject.sourcePath || activeProject.path || activeProject.dataPath;
|
|
2419
2451
|
const rrceData = activeProject.dataPath;
|
|
2420
2452
|
contextPreamble += `
|
|
@@ -2431,7 +2463,7 @@ Use these values directly in your operations. Do NOT manually resolve paths.
|
|
|
2431
2463
|
`;
|
|
2432
2464
|
}
|
|
2433
2465
|
const projectList = projects.map((p) => {
|
|
2434
|
-
const isActive = activeProject && p.
|
|
2466
|
+
const isActive = activeProject && normalizeProjectPath(p.path) === normalizeProjectPath(activeProject.path);
|
|
2435
2467
|
return `- ${p.name} (${p.source}) ${isActive ? "**[ACTIVE]**" : ""}`;
|
|
2436
2468
|
}).join("\n");
|
|
2437
2469
|
contextPreamble += `
|
|
@@ -2459,6 +2491,7 @@ var init_resources = __esm({
|
|
|
2459
2491
|
"src/mcp/resources.ts"() {
|
|
2460
2492
|
"use strict";
|
|
2461
2493
|
init_config();
|
|
2494
|
+
init_config_utils();
|
|
2462
2495
|
init_detection();
|
|
2463
2496
|
init_detection_service();
|
|
2464
2497
|
init_rag();
|
|
@@ -2549,6 +2582,7 @@ var init_resources2 = __esm({
|
|
|
2549
2582
|
});
|
|
2550
2583
|
|
|
2551
2584
|
// src/mcp/prompts.ts
|
|
2585
|
+
import * as path17 from "path";
|
|
2552
2586
|
function getAllPrompts() {
|
|
2553
2587
|
const prompts = loadPromptsFromDir(getAgentCorePromptsDir());
|
|
2554
2588
|
return prompts.map((p) => {
|
|
@@ -2585,6 +2619,40 @@ function getPromptDef(name) {
|
|
|
2585
2619
|
(p) => p.name === name || p.id === name || p.name.toLowerCase() === search || p.id.toLowerCase() === search
|
|
2586
2620
|
);
|
|
2587
2621
|
}
|
|
2622
|
+
function renderPromptWithContext(content, args) {
|
|
2623
|
+
const renderArgs = { ...args };
|
|
2624
|
+
const activeProject = detectActiveProject();
|
|
2625
|
+
const DEFAULT_RRCE_HOME = getEffectiveGlobalPath();
|
|
2626
|
+
let resolvedRrceData = ".rrce-workflow/";
|
|
2627
|
+
let resolvedRrceHome = DEFAULT_RRCE_HOME;
|
|
2628
|
+
let resolvedWorkspaceRoot = process.cwd();
|
|
2629
|
+
let resolvedWorkspaceName = "current-project";
|
|
2630
|
+
if (activeProject) {
|
|
2631
|
+
resolvedRrceData = activeProject.dataPath;
|
|
2632
|
+
if (!resolvedRrceData.endsWith("/") && !resolvedRrceData.endsWith("\\")) {
|
|
2633
|
+
resolvedRrceData += "/";
|
|
2634
|
+
}
|
|
2635
|
+
resolvedWorkspaceRoot = activeProject.sourcePath || activeProject.path || activeProject.dataPath;
|
|
2636
|
+
resolvedWorkspaceName = activeProject.name;
|
|
2637
|
+
if (activeProject.source === "global") {
|
|
2638
|
+
const workspacesDir = path17.dirname(activeProject.dataPath);
|
|
2639
|
+
resolvedRrceHome = path17.dirname(workspacesDir);
|
|
2640
|
+
}
|
|
2641
|
+
}
|
|
2642
|
+
if (!renderArgs["RRCE_DATA"]) renderArgs["RRCE_DATA"] = resolvedRrceData;
|
|
2643
|
+
if (!renderArgs["RRCE_HOME"]) renderArgs["RRCE_HOME"] = resolvedRrceHome;
|
|
2644
|
+
if (!renderArgs["WORKSPACE_ROOT"]) renderArgs["WORKSPACE_ROOT"] = resolvedWorkspaceRoot;
|
|
2645
|
+
if (!renderArgs["WORKSPACE_NAME"]) renderArgs["WORKSPACE_NAME"] = resolvedWorkspaceName;
|
|
2646
|
+
return {
|
|
2647
|
+
rendered: renderPrompt(content, renderArgs),
|
|
2648
|
+
context: {
|
|
2649
|
+
RRCE_DATA: resolvedRrceData,
|
|
2650
|
+
RRCE_HOME: resolvedRrceHome,
|
|
2651
|
+
WORKSPACE_ROOT: resolvedWorkspaceRoot,
|
|
2652
|
+
WORKSPACE_NAME: resolvedWorkspaceName
|
|
2653
|
+
}
|
|
2654
|
+
};
|
|
2655
|
+
}
|
|
2588
2656
|
function renderPrompt(content, args) {
|
|
2589
2657
|
let rendered = content;
|
|
2590
2658
|
for (const [key, val] of Object.entries(args)) {
|
|
@@ -2596,6 +2664,8 @@ var init_prompts2 = __esm({
|
|
|
2596
2664
|
"src/mcp/prompts.ts"() {
|
|
2597
2665
|
"use strict";
|
|
2598
2666
|
init_prompts();
|
|
2667
|
+
init_resources();
|
|
2668
|
+
init_paths();
|
|
2599
2669
|
}
|
|
2600
2670
|
});
|
|
2601
2671
|
|
|
@@ -2737,9 +2807,17 @@ Available projects: ${projects}`;
|
|
|
2737
2807
|
for (const [key, val] of Object.entries(renderArgs)) {
|
|
2738
2808
|
stringArgs[key] = String(val);
|
|
2739
2809
|
}
|
|
2740
|
-
const
|
|
2741
|
-
|
|
2742
|
-
|
|
2810
|
+
const { rendered, context } = renderPromptWithContext(promptDef.content, stringArgs);
|
|
2811
|
+
let contextPreamble = getContextPreamble();
|
|
2812
|
+
contextPreamble += `
|
|
2813
|
+
### System Resolved Paths (OVERRIDE)
|
|
2814
|
+
The system has pre-resolved the configuration for this project. Use these values instead of manual resolution:
|
|
2815
|
+
- **RRCE_DATA**: \`${context.RRCE_DATA}\` (Stores knowledge, tasks, refs)
|
|
2816
|
+
- **WORKSPACE_ROOT**: \`${context.WORKSPACE_ROOT}\` (Source code location)
|
|
2817
|
+
- **RRCE_HOME**: \`${context.RRCE_HOME}\`
|
|
2818
|
+
- **Current Project**: ${context.WORKSPACE_NAME}
|
|
2819
|
+
`;
|
|
2820
|
+
return { content: [{ type: "text", text: contextPreamble + rendered }] };
|
|
2743
2821
|
}
|
|
2744
2822
|
case "help_setup": {
|
|
2745
2823
|
const msg = `
|
|
@@ -2777,7 +2855,6 @@ import {
|
|
|
2777
2855
|
ListPromptsRequestSchema,
|
|
2778
2856
|
GetPromptRequestSchema
|
|
2779
2857
|
} from "@modelcontextprotocol/sdk/types.js";
|
|
2780
|
-
import * as path16 from "path";
|
|
2781
2858
|
function registerPromptHandlers(server) {
|
|
2782
2859
|
server.setRequestHandler(ListPromptsRequestSchema, async () => {
|
|
2783
2860
|
logger.debug("Listing prompts");
|
|
@@ -2812,34 +2889,15 @@ function registerPromptHandlers(server) {
|
|
|
2812
2889
|
for (const [key, val] of Object.entries(providedArgs)) {
|
|
2813
2890
|
renderArgs[key] = String(val);
|
|
2814
2891
|
}
|
|
2815
|
-
const
|
|
2816
|
-
const DEFAULT_RRCE_HOME = getEffectiveGlobalPath();
|
|
2817
|
-
let resolvedRrceData = ".rrce-workflow/";
|
|
2818
|
-
let resolvedRrceHome = DEFAULT_RRCE_HOME;
|
|
2819
|
-
let resolvedWorkspaceRoot = process.cwd();
|
|
2820
|
-
let resolvedWorkspaceName = "current-project";
|
|
2821
|
-
if (activeProject) {
|
|
2822
|
-
resolvedRrceData = activeProject.dataPath + "/";
|
|
2823
|
-
resolvedWorkspaceRoot = activeProject.sourcePath || activeProject.path || activeProject.dataPath;
|
|
2824
|
-
resolvedWorkspaceName = activeProject.name;
|
|
2825
|
-
if (activeProject.source === "global") {
|
|
2826
|
-
const workspacesDir = path16.dirname(activeProject.dataPath);
|
|
2827
|
-
resolvedRrceHome = path16.dirname(workspacesDir);
|
|
2828
|
-
}
|
|
2829
|
-
}
|
|
2830
|
-
if (!renderArgs["RRCE_DATA"]) renderArgs["RRCE_DATA"] = resolvedRrceData;
|
|
2831
|
-
if (!renderArgs["RRCE_HOME"]) renderArgs["RRCE_HOME"] = resolvedRrceHome;
|
|
2832
|
-
if (!renderArgs["WORKSPACE_ROOT"]) renderArgs["WORKSPACE_ROOT"] = resolvedWorkspaceRoot;
|
|
2833
|
-
if (!renderArgs["WORKSPACE_NAME"]) renderArgs["WORKSPACE_NAME"] = resolvedWorkspaceName;
|
|
2834
|
-
const content = renderPrompt(promptDef.content, renderArgs);
|
|
2892
|
+
const { rendered, context } = renderPromptWithContext(promptDef.content, renderArgs);
|
|
2835
2893
|
let contextPreamble = getContextPreamble();
|
|
2836
2894
|
contextPreamble += `
|
|
2837
2895
|
### System Resolved Paths (OVERRIDE)
|
|
2838
2896
|
The system has pre-resolved the configuration for this project. Use these values instead of manual resolution:
|
|
2839
|
-
- **RRCE_DATA**: \`${
|
|
2840
|
-
- **WORKSPACE_ROOT**: \`${
|
|
2841
|
-
- **RRCE_HOME**: \`${
|
|
2842
|
-
- **Current Project**: ${
|
|
2897
|
+
- **RRCE_DATA**: \`${context.RRCE_DATA}\` (Stores knowledge, tasks, refs)
|
|
2898
|
+
- **WORKSPACE_ROOT**: \`${context.WORKSPACE_ROOT}\` (Source code location)
|
|
2899
|
+
- **RRCE_HOME**: \`${context.RRCE_HOME}\`
|
|
2900
|
+
- **Current Project**: ${context.WORKSPACE_NAME}
|
|
2843
2901
|
`;
|
|
2844
2902
|
return {
|
|
2845
2903
|
messages: [
|
|
@@ -2847,7 +2905,7 @@ The system has pre-resolved the configuration for this project. Use these values
|
|
|
2847
2905
|
role: "user",
|
|
2848
2906
|
content: {
|
|
2849
2907
|
type: "text",
|
|
2850
|
-
text: contextPreamble +
|
|
2908
|
+
text: contextPreamble + rendered
|
|
2851
2909
|
}
|
|
2852
2910
|
}
|
|
2853
2911
|
]
|
|
@@ -3028,7 +3086,7 @@ Hidden projects: ${projects.length - exposedCount}`,
|
|
|
3028
3086
|
async function handleConfigureGlobalPath() {
|
|
3029
3087
|
const { resolveGlobalPath: resolveGlobalPath2 } = await Promise.resolve().then(() => (init_tui_utils(), tui_utils_exports));
|
|
3030
3088
|
const fs21 = await import("fs");
|
|
3031
|
-
const
|
|
3089
|
+
const path21 = await import("path");
|
|
3032
3090
|
note3(
|
|
3033
3091
|
`MCP Hub requires a ${pc5.bold("global storage path")} to store its configuration
|
|
3034
3092
|
and coordinate across projects.
|
|
@@ -3051,7 +3109,7 @@ locally in each project. MCP needs a central location.`,
|
|
|
3051
3109
|
`${pc5.green("\u2713")} Global path configured: ${pc5.cyan(resolvedPath)}
|
|
3052
3110
|
|
|
3053
3111
|
MCP config will be stored at:
|
|
3054
|
-
${
|
|
3112
|
+
${path21.join(resolvedPath, "mcp.yaml")}`,
|
|
3055
3113
|
"Configuration Saved"
|
|
3056
3114
|
);
|
|
3057
3115
|
return true;
|
|
@@ -3293,7 +3351,7 @@ var init_SimpleSelect = __esm({
|
|
|
3293
3351
|
|
|
3294
3352
|
// src/mcp/ui/ProjectsView.tsx
|
|
3295
3353
|
import { useState as useState2 } from "react";
|
|
3296
|
-
import { Box as Box4, Text as Text4 } from "ink";
|
|
3354
|
+
import { Box as Box4, Text as Text4, useInput as useInput2 } from "ink";
|
|
3297
3355
|
import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
3298
3356
|
var ProjectsView;
|
|
3299
3357
|
var init_ProjectsView = __esm({
|
|
@@ -3303,6 +3361,20 @@ var init_ProjectsView = __esm({
|
|
|
3303
3361
|
init_config();
|
|
3304
3362
|
ProjectsView = ({ config: initialConfig, projects: allProjects, onConfigChange }) => {
|
|
3305
3363
|
const [config, setConfig] = useState2(initialConfig);
|
|
3364
|
+
useInput2((input) => {
|
|
3365
|
+
if (input === "a") {
|
|
3366
|
+
const newConfig = {
|
|
3367
|
+
...config,
|
|
3368
|
+
defaults: {
|
|
3369
|
+
...config.defaults,
|
|
3370
|
+
includeNew: !config.defaults.includeNew
|
|
3371
|
+
}
|
|
3372
|
+
};
|
|
3373
|
+
saveMCPConfig(newConfig);
|
|
3374
|
+
setConfig(newConfig);
|
|
3375
|
+
if (onConfigChange) onConfigChange();
|
|
3376
|
+
}
|
|
3377
|
+
});
|
|
3306
3378
|
const projectItems = allProjects.map((p) => {
|
|
3307
3379
|
const projectConfig = config.projects.find(
|
|
3308
3380
|
(c) => c.path && c.path === p.path || p.source === "global" && c.name === p.name || !c.path && c.name === p.name
|
|
@@ -3310,9 +3382,9 @@ var init_ProjectsView = __esm({
|
|
|
3310
3382
|
const isExposed = projectConfig ? projectConfig.expose : config.defaults.includeNew;
|
|
3311
3383
|
return {
|
|
3312
3384
|
label: p.name + ` (${p.source})` + (p.path ? ` - ${p.path}` : ""),
|
|
3313
|
-
value: p.
|
|
3314
|
-
//
|
|
3315
|
-
key: p.
|
|
3385
|
+
value: p.path,
|
|
3386
|
+
// Standardized ID: Use root path
|
|
3387
|
+
key: p.path,
|
|
3316
3388
|
exposed: isExposed
|
|
3317
3389
|
};
|
|
3318
3390
|
});
|
|
@@ -3321,7 +3393,7 @@ var init_ProjectsView = __esm({
|
|
|
3321
3393
|
let newConfig = { ...config };
|
|
3322
3394
|
projectItems.forEach((item) => {
|
|
3323
3395
|
const isSelected = selectedIds.includes(item.value);
|
|
3324
|
-
const project = allProjects.find((p) => p.
|
|
3396
|
+
const project = allProjects.find((p) => p.path === item.value);
|
|
3325
3397
|
if (project) {
|
|
3326
3398
|
const existingConfig = newConfig.projects.find((p) => p.name === project.name);
|
|
3327
3399
|
const projectPath = project.source === "global" && existingConfig?.path ? existingConfig.path : project.path;
|
|
@@ -3339,7 +3411,14 @@ var init_ProjectsView = __esm({
|
|
|
3339
3411
|
if (onConfigChange) onConfigChange();
|
|
3340
3412
|
};
|
|
3341
3413
|
return /* @__PURE__ */ jsxs3(Box4, { flexDirection: "column", padding: 1, borderStyle: "round", borderColor: "cyan", flexGrow: 1, children: [
|
|
3342
|
-
/* @__PURE__ */
|
|
3414
|
+
/* @__PURE__ */ jsxs3(Box4, { justifyContent: "space-between", children: [
|
|
3415
|
+
/* @__PURE__ */ jsx4(Text4, { bold: true, color: "cyan", children: " Exposed Projects " }),
|
|
3416
|
+
/* @__PURE__ */ jsxs3(Box4, { children: [
|
|
3417
|
+
/* @__PURE__ */ jsx4(Text4, { dimColor: true, children: "Auto-expose new: " }),
|
|
3418
|
+
/* @__PURE__ */ jsx4(Text4, { color: config.defaults.includeNew ? "green" : "red", children: config.defaults.includeNew ? "ON" : "OFF" }),
|
|
3419
|
+
/* @__PURE__ */ jsx4(Text4, { dimColor: true, children: " (Press 'a' to toggle)" })
|
|
3420
|
+
] })
|
|
3421
|
+
] }),
|
|
3343
3422
|
/* @__PURE__ */ jsx4(Text4, { color: "dim", children: " Select projects to expose via the MCP server. Use Space to toggle, Enter to save." }),
|
|
3344
3423
|
/* @__PURE__ */ jsx4(Box4, { marginTop: 1, flexDirection: "column", children: /* @__PURE__ */ jsx4(
|
|
3345
3424
|
SimpleSelect,
|
|
@@ -3354,7 +3433,7 @@ var init_ProjectsView = __esm({
|
|
|
3354
3433
|
onCancel: () => {
|
|
3355
3434
|
}
|
|
3356
3435
|
},
|
|
3357
|
-
JSON.stringify(initialSelected)
|
|
3436
|
+
JSON.stringify(initialSelected) + config.defaults.includeNew
|
|
3358
3437
|
) })
|
|
3359
3438
|
] });
|
|
3360
3439
|
};
|
|
@@ -3620,14 +3699,14 @@ var init_IndexingStatus = __esm({
|
|
|
3620
3699
|
|
|
3621
3700
|
// src/mcp/ui/components/TabBar.tsx
|
|
3622
3701
|
import "react";
|
|
3623
|
-
import { Box as Box10, Text as Text10, useInput as
|
|
3702
|
+
import { Box as Box10, Text as Text10, useInput as useInput3 } from "ink";
|
|
3624
3703
|
import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
3625
3704
|
var TabBar;
|
|
3626
3705
|
var init_TabBar = __esm({
|
|
3627
3706
|
"src/mcp/ui/components/TabBar.tsx"() {
|
|
3628
3707
|
"use strict";
|
|
3629
3708
|
TabBar = ({ tabs, activeTab, onChange }) => {
|
|
3630
|
-
|
|
3709
|
+
useInput3((input, key) => {
|
|
3631
3710
|
if (key.leftArrow) {
|
|
3632
3711
|
const index = tabs.findIndex((t) => t.id === activeTab);
|
|
3633
3712
|
if (index !== -1) {
|
|
@@ -3674,7 +3753,7 @@ __export(App_exports, {
|
|
|
3674
3753
|
App: () => App
|
|
3675
3754
|
});
|
|
3676
3755
|
import { useState as useState5, useEffect as useEffect4, useMemo as useMemo2, useCallback } from "react";
|
|
3677
|
-
import { Box as Box11, useInput as
|
|
3756
|
+
import { Box as Box11, useInput as useInput4, useApp } from "ink";
|
|
3678
3757
|
import fs15 from "fs";
|
|
3679
3758
|
import { jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
3680
3759
|
var App;
|
|
@@ -3693,6 +3772,7 @@ var init_App = __esm({
|
|
|
3693
3772
|
init_detection();
|
|
3694
3773
|
init_logger();
|
|
3695
3774
|
init_server();
|
|
3775
|
+
init_resources();
|
|
3696
3776
|
init_install();
|
|
3697
3777
|
init_paths();
|
|
3698
3778
|
App = ({ onExit, initialPort }) => {
|
|
@@ -3711,12 +3791,7 @@ var init_App = __esm({
|
|
|
3711
3791
|
setProjects(scanForProjects());
|
|
3712
3792
|
}, []);
|
|
3713
3793
|
const exposedProjects = useMemo2(
|
|
3714
|
-
() => projects.filter((p) =>
|
|
3715
|
-
const cfg = config.projects.find(
|
|
3716
|
-
(c) => c.path && c.path === p.path || p.source === "global" && c.name === p.name || !c.path && c.name === p.name
|
|
3717
|
-
);
|
|
3718
|
-
return cfg?.expose ?? config.defaults.includeNew;
|
|
3719
|
-
}),
|
|
3794
|
+
() => projects.filter((p) => isProjectExposed(config, p.name, p.path)),
|
|
3720
3795
|
[projects, config]
|
|
3721
3796
|
);
|
|
3722
3797
|
const isRAGEnabled = useMemo2(() => {
|
|
@@ -3788,7 +3863,7 @@ var init_App = __esm({
|
|
|
3788
3863
|
}, 500);
|
|
3789
3864
|
return () => clearInterval(interval);
|
|
3790
3865
|
}, []);
|
|
3791
|
-
|
|
3866
|
+
useInput4(async (input, key) => {
|
|
3792
3867
|
if (input === "q" || key.ctrl && input === "c") {
|
|
3793
3868
|
stopMCPServer();
|
|
3794
3869
|
onExit();
|
|
@@ -4531,14 +4606,14 @@ var init_link_flow = __esm({
|
|
|
4531
4606
|
import { confirm as confirm8, spinner as spinner5, note as note11, outro as outro4, cancel as cancel5, isCancel as isCancel10 } from "@clack/prompts";
|
|
4532
4607
|
import pc13 from "picocolors";
|
|
4533
4608
|
import * as fs17 from "fs";
|
|
4534
|
-
import * as
|
|
4609
|
+
import * as path18 from "path";
|
|
4535
4610
|
async function runSyncToGlobalFlow(workspacePath, workspaceName) {
|
|
4536
4611
|
const localPath = getLocalWorkspacePath(workspacePath);
|
|
4537
4612
|
const customGlobalPath = getEffectiveRRCEHome(workspacePath);
|
|
4538
|
-
const globalPath =
|
|
4613
|
+
const globalPath = path18.join(customGlobalPath, "workspaces", workspaceName);
|
|
4539
4614
|
const subdirs = ["knowledge", "prompts", "templates", "tasks", "refs"];
|
|
4540
4615
|
const existingDirs = subdirs.filter(
|
|
4541
|
-
(dir) => fs17.existsSync(
|
|
4616
|
+
(dir) => fs17.existsSync(path18.join(localPath, dir))
|
|
4542
4617
|
);
|
|
4543
4618
|
if (existingDirs.length === 0) {
|
|
4544
4619
|
outro4(pc13.yellow("No data found in workspace storage to sync."));
|
|
@@ -4564,8 +4639,8 @@ Destination: ${pc13.cyan(globalPath)}`,
|
|
|
4564
4639
|
try {
|
|
4565
4640
|
ensureDir(globalPath);
|
|
4566
4641
|
for (const dir of existingDirs) {
|
|
4567
|
-
const srcDir =
|
|
4568
|
-
const destDir =
|
|
4642
|
+
const srcDir = path18.join(localPath, dir);
|
|
4643
|
+
const destDir = path18.join(globalPath, dir);
|
|
4569
4644
|
ensureDir(destDir);
|
|
4570
4645
|
copyDirRecursive(srcDir, destDir);
|
|
4571
4646
|
}
|
|
@@ -4598,7 +4673,7 @@ var init_sync_flow = __esm({
|
|
|
4598
4673
|
import { confirm as confirm9, spinner as spinner6, note as note12, outro as outro5, cancel as cancel6, isCancel as isCancel11 } from "@clack/prompts";
|
|
4599
4674
|
import pc14 from "picocolors";
|
|
4600
4675
|
import * as fs18 from "fs";
|
|
4601
|
-
import * as
|
|
4676
|
+
import * as path19 from "path";
|
|
4602
4677
|
async function runUpdateFlow(workspacePath, workspaceName, currentStorageMode) {
|
|
4603
4678
|
const s = spinner6();
|
|
4604
4679
|
s.start("Checking for updates");
|
|
@@ -4628,7 +4703,7 @@ ${dataPaths.map((p) => ` \u2022 ${p}`).join("\n")}`,
|
|
|
4628
4703
|
}
|
|
4629
4704
|
s.start("Updating from package");
|
|
4630
4705
|
for (const dataPath of dataPaths) {
|
|
4631
|
-
copyDirToAllStoragePaths(
|
|
4706
|
+
copyDirToAllStoragePaths(path19.join(agentCoreDir, "templates"), "templates", [dataPath]);
|
|
4632
4707
|
}
|
|
4633
4708
|
const configFilePath = getConfigPath(workspacePath);
|
|
4634
4709
|
if (fs18.existsSync(configFilePath)) {
|
|
@@ -4661,8 +4736,8 @@ ${dataPaths.map((p) => ` \u2022 ${p}`).join("\n")}`,
|
|
|
4661
4736
|
}
|
|
4662
4737
|
}
|
|
4663
4738
|
function resolveAllDataPathsWithCustomGlobal(mode, workspaceName, workspaceRoot, customGlobalPath) {
|
|
4664
|
-
const globalPath =
|
|
4665
|
-
const workspacePath =
|
|
4739
|
+
const globalPath = path19.join(customGlobalPath, "workspaces", workspaceName);
|
|
4740
|
+
const workspacePath = path19.join(workspaceRoot, ".rrce-workflow");
|
|
4666
4741
|
switch (mode) {
|
|
4667
4742
|
case "global":
|
|
4668
4743
|
return [globalPath];
|
|
@@ -4894,9 +4969,9 @@ init_wizard();
|
|
|
4894
4969
|
init_prompts();
|
|
4895
4970
|
import { intro as intro3, select as select6, note as note15, cancel as cancel9, isCancel as isCancel14, outro as outro8 } from "@clack/prompts";
|
|
4896
4971
|
import pc17 from "picocolors";
|
|
4897
|
-
import * as
|
|
4972
|
+
import * as path20 from "path";
|
|
4898
4973
|
async function runSelector() {
|
|
4899
|
-
const workspaceName =
|
|
4974
|
+
const workspaceName = path20.basename(process.cwd());
|
|
4900
4975
|
intro3(pc17.cyan(pc17.inverse(` RRCE-Workflow | ${workspaceName} `)));
|
|
4901
4976
|
const prompts = loadPromptsFromDir(getAgentCorePromptsDir());
|
|
4902
4977
|
if (prompts.length === 0) {
|