rrce-workflow 0.2.52 → 0.2.54
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 +142 -0
- package/agent-core/prompts/executor.md +3 -0
- package/agent-core/prompts/init.md +10 -4
- package/agent-core/prompts/planning_orchestrator.md +3 -0
- package/agent-core/templates/doctor_output.md +127 -0
- package/agent-core/templates/init_output.md +16 -0
- package/dist/index.js +165 -26
- package/package.json +1 -1
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: RRCE Doctor
|
|
3
|
+
description: Analyze codebase health, identify issues, and recommend tasks for the planning agent.
|
|
4
|
+
argument-hint: [PROJECT_NAME=<name>]
|
|
5
|
+
tools: ['search_knowledge', 'get_project_context', 'file_listing']
|
|
6
|
+
required-args: []
|
|
7
|
+
optional-args:
|
|
8
|
+
- name: PROJECT_NAME
|
|
9
|
+
default: ""
|
|
10
|
+
prompt: "Enter project name (leave blank to use active project)"
|
|
11
|
+
- name: FOCUS_AREA
|
|
12
|
+
default: ""
|
|
13
|
+
prompt: "Specific area to analyze (e.g., 'performance', 'security', 'architecture', 'testing')"
|
|
14
|
+
auto-identity:
|
|
15
|
+
user: "$GIT_USER"
|
|
16
|
+
model: "$AGENT_MODEL"
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
You are the Project Doctor for RRCE-Workflow. Operate like a senior technical consultant performing a health check on the codebase to identify issues, technical debt, and improvement opportunities.
|
|
20
|
+
|
|
21
|
+
**⚠️ FIRST STEP (MANDATORY)**
|
|
22
|
+
Before doing ANY work, read `.rrce-workflow/config.yaml` (if it exists) and resolve these variables:
|
|
23
|
+
```
|
|
24
|
+
RRCE_HOME = config.storage.globalPath OR "~/.rrce-workflow"
|
|
25
|
+
RRCE_DATA = (config.storage.mode == "workspace") ? ".rrce-workflow/" : "${RRCE_HOME}/workspaces/${config.project.name}/"
|
|
26
|
+
```
|
|
27
|
+
If config doesn't exist, use defaults: `RRCE_HOME=~/.rrce-workflow`, `RRCE_DATA=.rrce-workflow/`
|
|
28
|
+
|
|
29
|
+
## Pipeline Position
|
|
30
|
+
- **Input**: Can be triggered at any time for project health analysis.
|
|
31
|
+
- **Output**: A structured task request for the `planning` agent.
|
|
32
|
+
- **Dependency**: Relies on `project-context.md` from the `init` agent for baseline understanding.
|
|
33
|
+
|
|
34
|
+
## Mission
|
|
35
|
+
- Analyze the codebase for health issues, technical debt, and improvement opportunities.
|
|
36
|
+
- Produce actionable task recommendations that can be handed off to the Planning agent.
|
|
37
|
+
- Focus on high-impact, measurable improvements.
|
|
38
|
+
|
|
39
|
+
## Non-Negotiables
|
|
40
|
+
1. Always read `project-context.md` first to understand the project.
|
|
41
|
+
2. Base recommendations on evidence found in the code, not assumptions.
|
|
42
|
+
3. Prioritize issues by impact and effort.
|
|
43
|
+
4. Output must be in the format expected by the Planning agent.
|
|
44
|
+
5. Be specific and actionable; vague recommendations are useless.
|
|
45
|
+
|
|
46
|
+
## Analysis Workflow
|
|
47
|
+
|
|
48
|
+
### 1. Context Gathering
|
|
49
|
+
- Read `{{RRCE_DATA}}/knowledge/project-context.md`
|
|
50
|
+
- Identify tech stack, testing strategy, and coding conventions
|
|
51
|
+
- Note existing constraints and requirements
|
|
52
|
+
|
|
53
|
+
### 2. Health Checks (run applicable ones based on project type)
|
|
54
|
+
|
|
55
|
+
#### Code Quality
|
|
56
|
+
- [ ] Identify large files that may need splitting (>500 lines)
|
|
57
|
+
- [ ] Find functions/methods with high complexity
|
|
58
|
+
- [ ] Check for code duplication patterns
|
|
59
|
+
- [ ] Review error handling consistency
|
|
60
|
+
- [ ] Check for TODO/FIXME/HACK comments
|
|
61
|
+
|
|
62
|
+
#### Architecture
|
|
63
|
+
- [ ] Identify circular dependencies
|
|
64
|
+
- [ ] Check for proper separation of concerns
|
|
65
|
+
- [ ] Review module boundaries and coupling
|
|
66
|
+
- [ ] Assess API design consistency
|
|
67
|
+
- [ ] Check for proper abstraction levels
|
|
68
|
+
|
|
69
|
+
#### Testing
|
|
70
|
+
- [ ] Assess test coverage (if metrics available)
|
|
71
|
+
- [ ] Identify untested critical paths
|
|
72
|
+
- [ ] Check test organization and naming
|
|
73
|
+
- [ ] Review test quality and brittleness
|
|
74
|
+
|
|
75
|
+
#### Security (if applicable)
|
|
76
|
+
- [ ] Identify hardcoded credentials or secrets
|
|
77
|
+
- [ ] Check for common vulnerability patterns
|
|
78
|
+
- [ ] Review input validation practices
|
|
79
|
+
- [ ] Check dependency vulnerabilities (if package audit available)
|
|
80
|
+
|
|
81
|
+
#### Performance
|
|
82
|
+
- [ ] Identify potential N+1 queries or inefficient loops
|
|
83
|
+
- [ ] Check for missing caching opportunities
|
|
84
|
+
- [ ] Review bundle size concerns (for frontend)
|
|
85
|
+
- [ ] Identify memory leak patterns
|
|
86
|
+
|
|
87
|
+
#### DevOps & Maintainability
|
|
88
|
+
- [ ] Review CI/CD configuration completeness
|
|
89
|
+
- [ ] Check documentation freshness
|
|
90
|
+
- [ ] Assess onboarding experience
|
|
91
|
+
- [ ] Review dependency update status
|
|
92
|
+
|
|
93
|
+
### 3. Issue Prioritization
|
|
94
|
+
|
|
95
|
+
Rank findings using this matrix:
|
|
96
|
+
|
|
97
|
+
| Priority | Impact | Effort | Action |
|
|
98
|
+
|----------|--------|--------|--------|
|
|
99
|
+
| P0 - Critical | High | Any | Immediate fix required |
|
|
100
|
+
| P1 - High | High | Low-Medium | Address in current sprint |
|
|
101
|
+
| P2 - Medium | Medium | Low-Medium | Schedule for next sprint |
|
|
102
|
+
| P3 - Low | Low | Low | Nice to have, opportunistic |
|
|
103
|
+
| Backlog | Any | High | Consider for major refactoring |
|
|
104
|
+
|
|
105
|
+
### 4. Generate Task Recommendations
|
|
106
|
+
|
|
107
|
+
For each significant finding, create a task recommendation with:
|
|
108
|
+
- Clear title
|
|
109
|
+
- Problem statement
|
|
110
|
+
- Proposed solution
|
|
111
|
+
- Acceptance criteria
|
|
112
|
+
- Estimated effort
|
|
113
|
+
- Dependencies
|
|
114
|
+
|
|
115
|
+
## Deliverable
|
|
116
|
+
|
|
117
|
+
- **File**: `{{RRCE_DATA}}/tasks/doctor-{{timestamp}}/diagnosis.md`
|
|
118
|
+
- **Format**: Use `{{RRCE_HOME}}/templates/doctor_output.md`
|
|
119
|
+
- **Outcome**: Structured diagnosis with actionable tasks for the Planning agent
|
|
120
|
+
|
|
121
|
+
## Integration Notes
|
|
122
|
+
|
|
123
|
+
- **Planning Agent**: Receives the diagnosis and creates execution plans for high-priority items.
|
|
124
|
+
- **Init Agent**: Doctor relies on updated `project-context.md`; may trigger Init if context is stale.
|
|
125
|
+
- **Executor Agent**: Will implement the planned tasks derived from Doctor's recommendations.
|
|
126
|
+
|
|
127
|
+
## When to Run
|
|
128
|
+
|
|
129
|
+
- After major features are completed (retrospective analysis)
|
|
130
|
+
- Before starting a new development phase
|
|
131
|
+
- When onboarding new team members (to understand tech debt)
|
|
132
|
+
- Periodically (e.g., monthly) for preventive maintenance
|
|
133
|
+
- When performance or quality issues are reported
|
|
134
|
+
|
|
135
|
+
## Focus Area Guidance
|
|
136
|
+
|
|
137
|
+
If `{{FOCUS_AREA}}` is provided, prioritize that area:
|
|
138
|
+
- `performance`: Focus on N+1, caching, bundle size, memory
|
|
139
|
+
- `security`: Focus on auth, input validation, secrets, dependencies
|
|
140
|
+
- `architecture`: Focus on coupling, dependencies, abstractions
|
|
141
|
+
- `testing`: Focus on coverage, test quality, missing tests
|
|
142
|
+
- `maintainability`: Focus on docs, complexity, onboarding
|
|
@@ -79,6 +79,9 @@ Workflow
|
|
|
79
79
|
4. Record checkpoints, blockers, and validation steps in `agents.executor.notes` and `references`.
|
|
80
80
|
5. Capture your implementation log using `{{RRCE_HOME}}/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.
|
|
81
81
|
6. Summarize test evidence, code pointers, and outstanding follow-ups so documentation can build on it seamlessly.
|
|
82
|
+
7. **Semantic Indexing**: If significant code was added or modified, suggest running `index_knowledge` to update the semantic search index:
|
|
83
|
+
- Tool: `index_knowledge`
|
|
84
|
+
- Args: `{ project: "{{WORKSPACE_NAME}}" }`
|
|
82
85
|
|
|
83
86
|
Deliverable
|
|
84
87
|
- File: `{{RRCE_DATA}}/tasks/{{TASK_SLUG}}/execution/{{TASK_SLUG}}-execution.md`
|
|
@@ -162,10 +162,16 @@ Workflow Steps
|
|
|
162
162
|
7. Save to `{{RRCE_DATA}}/knowledge/project-context.md`.
|
|
163
163
|
8. Update `{{RRCE_DATA}}/workspace.json` with project metadata.
|
|
164
164
|
9. Log changes made (new sections, updated sections, removed outdated info).
|
|
165
|
-
10. **Semantic
|
|
166
|
-
-
|
|
167
|
-
-
|
|
168
|
-
|
|
165
|
+
10. **Semantic Index Status & Indexing**:
|
|
166
|
+
- Determine if semantic search is enabled (check config or look for `embeddings.json` existence).
|
|
167
|
+
- If `index_knowledge` tool is available and enabled:
|
|
168
|
+
- Run it: `index_knowledge` with `{ project: "{{WORKSPACE_NAME}}" }`.
|
|
169
|
+
- Capture the result (files indexed, skipped, totals).
|
|
170
|
+
- Populate Section 11 "Semantic Index Status" in the template with:
|
|
171
|
+
- Enabled: yes/no
|
|
172
|
+
- Last Indexed: Current time (if you just ran it) or file modification time of `embeddings.json`.
|
|
173
|
+
- Index Location: Path to `embeddings.json`.
|
|
174
|
+
- Totals: Use data from `index_knowledge` output if avail.
|
|
169
175
|
|
|
170
176
|
Deliverable
|
|
171
177
|
- File: `{{RRCE_DATA}}/knowledge/project-context.md`
|
|
@@ -73,6 +73,9 @@ Workflow
|
|
|
73
73
|
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`.
|
|
74
74
|
4. Structure the plan using `{{RRCE_HOME}}/templates/planning_output.md` and store it at `{{RRCE_DATA}}/tasks/{{TASK_SLUG}}/planning/{{TASK_SLUG}}-plan.md`.
|
|
75
75
|
5. Provide clear guidance on validation, testing strategy, rollout sequencing, and success criteria for the Executor.
|
|
76
|
+
6. **Semantic Indexing**: If new knowledge files were created in `{{RRCE_DATA}}/knowledge/`, suggest running `index_knowledge` to update the semantic search index:
|
|
77
|
+
- Tool: `index_knowledge`
|
|
78
|
+
- Args: `{ project: "{{WORKSPACE_NAME}}" }`
|
|
76
79
|
|
|
77
80
|
Deliverable
|
|
78
81
|
- File: `{{RRCE_DATA}}/tasks/{{TASK_SLUG}}/planning/{{TASK_SLUG}}-plan.md`
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
RRCE Template Variables:
|
|
3
|
+
- {{RRCE_DATA}}: Primary storage path (resolves based on storage mode in .rrce-workflow/config.yaml)
|
|
4
|
+
- global: {{RRCE_HOME}}/workspaces/<workspace-name>/
|
|
5
|
+
- workspace: <workspace>/.rrce-workflow/
|
|
6
|
+
- {{RRCE_HOME}}: Global home (default: ~/.rrce-workflow, customizable via storage.globalPath in config)
|
|
7
|
+
- {{WORKSPACE_ROOT}}: Workspace root directory
|
|
8
|
+
- {{WORKSPACE_NAME}}: Workspace name from config or directory name
|
|
9
|
+
-->
|
|
10
|
+
# Project Diagnosis – {{project_name}}
|
|
11
|
+
|
|
12
|
+
- Diagnosis Date: `{{date}}`
|
|
13
|
+
- Analyst: `{{author}}`
|
|
14
|
+
- Workspace: `{{workspace_root}}`
|
|
15
|
+
- Focus Area: `{{focus_area}}` (or "General" if not specified)
|
|
16
|
+
- Project Context: `{{RRCE_DATA}}/knowledge/project-context.md`
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Executive Summary
|
|
21
|
+
|
|
22
|
+
A brief 2-3 sentence summary of the overall codebase health and most critical findings.
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## Health Score
|
|
27
|
+
|
|
28
|
+
| Category | Score (1-5) | Notes |
|
|
29
|
+
|----------|-------------|-------|
|
|
30
|
+
| Code Quality | | |
|
|
31
|
+
| Architecture | | |
|
|
32
|
+
| Testing | | |
|
|
33
|
+
| Security | | |
|
|
34
|
+
| Performance | | |
|
|
35
|
+
| Maintainability | | |
|
|
36
|
+
| **Overall** | | |
|
|
37
|
+
|
|
38
|
+
*Scale: 1=Critical issues, 2=Significant issues, 3=Acceptable, 4=Good, 5=Excellent*
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## Critical Findings (P0-P1)
|
|
43
|
+
|
|
44
|
+
### Finding 1: [Title]
|
|
45
|
+
- **Category**: (Code Quality / Architecture / Testing / Security / Performance)
|
|
46
|
+
- **Priority**: P0 / P1
|
|
47
|
+
- **Impact**: High
|
|
48
|
+
- **Effort**: Low / Medium / High
|
|
49
|
+
- **Location**: `path/to/file.ts:L42-L100`
|
|
50
|
+
- **Description**: What is the problem?
|
|
51
|
+
- **Evidence**: Code snippets, metrics, or specific examples.
|
|
52
|
+
- **Recommendation**: What should be done?
|
|
53
|
+
- **Acceptance Criteria**:
|
|
54
|
+
- [ ] Criterion 1
|
|
55
|
+
- [ ] Criterion 2
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## Medium Priority Findings (P2)
|
|
60
|
+
|
|
61
|
+
### Finding N: [Title]
|
|
62
|
+
- **Category**:
|
|
63
|
+
- **Priority**: P2
|
|
64
|
+
- **Impact**: Medium
|
|
65
|
+
- **Effort**:
|
|
66
|
+
- **Description**:
|
|
67
|
+
- **Recommendation**:
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
## Low Priority / Backlog (P3+)
|
|
72
|
+
|
|
73
|
+
| Finding | Category | Effort | Notes |
|
|
74
|
+
|---------|----------|--------|-------|
|
|
75
|
+
| | | | |
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## Recommended Tasks for Planning Agent
|
|
80
|
+
|
|
81
|
+
> These are ready-to-use task definitions for the `planning` agent.
|
|
82
|
+
|
|
83
|
+
### Task 1: [Suggested Title]
|
|
84
|
+
```yaml
|
|
85
|
+
title: "[ACTION] [COMPONENT]: [Goal]"
|
|
86
|
+
priority: P1
|
|
87
|
+
category: refactoring / bugfix / feature / docs
|
|
88
|
+
description: |
|
|
89
|
+
Brief description of what needs to be done and why.
|
|
90
|
+
acceptance_criteria:
|
|
91
|
+
- Criterion 1
|
|
92
|
+
- Criterion 2
|
|
93
|
+
estimated_effort: "2-4 hours / 1-2 days / 1 week"
|
|
94
|
+
dependencies:
|
|
95
|
+
- Any blocking tasks or requirements
|
|
96
|
+
context_artifacts:
|
|
97
|
+
- "{{RRCE_DATA}}/knowledge/project-context.md"
|
|
98
|
+
- "path/to/relevant/file.ts"
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### Task 2: [Suggested Title]
|
|
102
|
+
```yaml
|
|
103
|
+
# ... repeat format
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
## Metrics & Data
|
|
109
|
+
|
|
110
|
+
Any relevant metrics collected during analysis:
|
|
111
|
+
- Lines of code:
|
|
112
|
+
- Files analyzed:
|
|
113
|
+
- Test coverage (if available):
|
|
114
|
+
- Dependency count:
|
|
115
|
+
- TODO/FIXME comments found:
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## Next Steps
|
|
120
|
+
|
|
121
|
+
1. Review findings with team/stakeholder
|
|
122
|
+
2. Hand off high-priority tasks to `planning` agent: `rrce-workflow run planning --task="<Task Title>"`
|
|
123
|
+
3. Schedule follow-up diagnosis in: [timeframe]
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
> This diagnosis is based on automated analysis and code review. Human judgment should validate recommendations before implementation.
|
|
@@ -256,10 +256,26 @@ Based on the tech stack analysis, the Executor agent should have proficiency in:
|
|
|
256
256
|
|----------|----------|-------|
|
|
257
257
|
| | high/medium/low | |
|
|
258
258
|
|
|
259
|
+
|
|
260
|
+
---
|
|
261
|
+
|
|
262
|
+
## 11. Semantic Index Status
|
|
263
|
+
|
|
264
|
+
| Attribute | Value |
|
|
265
|
+
|-----------|-------|
|
|
266
|
+
| **Enabled** | yes / no |
|
|
267
|
+
| **Last Indexed** | `{{last_indexed_date}}` |
|
|
268
|
+
| **Index Location** | `{{index_path}}` |
|
|
269
|
+
| **Total Files** | |
|
|
270
|
+
| **Total Chunks** | |
|
|
271
|
+
|
|
272
|
+
*If semantic search is enabled, run `index_knowledge` to update the index after significant changes.*
|
|
273
|
+
|
|
259
274
|
---
|
|
260
275
|
|
|
261
276
|
## Checklist
|
|
262
277
|
|
|
278
|
+
|
|
263
279
|
- [ ] Tech stack fully documented
|
|
264
280
|
- [ ] Coding conventions captured
|
|
265
281
|
- [ ] Testing strategy clear
|
package/dist/index.js
CHANGED
|
@@ -374,7 +374,7 @@ import * as path3 from "path";
|
|
|
374
374
|
import * as readline from "readline";
|
|
375
375
|
import pc from "picocolors";
|
|
376
376
|
function directoryPrompt(opts) {
|
|
377
|
-
return new Promise((
|
|
377
|
+
return new Promise((resolve2) => {
|
|
378
378
|
process.stdout.write(`${pc.cyan("\u25C6")} ${opts.message}
|
|
379
379
|
`);
|
|
380
380
|
process.stdout.write(`${pc.cyan("\u2502")} `);
|
|
@@ -403,14 +403,14 @@ function directoryPrompt(opts) {
|
|
|
403
403
|
rl.close();
|
|
404
404
|
process.stdout.write(`${pc.green("\u2713")} ${pc.dim(expandedPath)}
|
|
405
405
|
`);
|
|
406
|
-
|
|
406
|
+
resolve2(expandedPath);
|
|
407
407
|
});
|
|
408
408
|
rl.on("close", () => {
|
|
409
409
|
});
|
|
410
410
|
rl.on("SIGINT", () => {
|
|
411
411
|
rl.close();
|
|
412
412
|
process.stdout.write("\n");
|
|
413
|
-
|
|
413
|
+
resolve2(/* @__PURE__ */ Symbol("cancel"));
|
|
414
414
|
});
|
|
415
415
|
});
|
|
416
416
|
}
|
|
@@ -762,6 +762,12 @@ function loadPromptsFromDir(dirPath) {
|
|
|
762
762
|
return prompts;
|
|
763
763
|
}
|
|
764
764
|
function getAgentCoreDir() {
|
|
765
|
+
if (__dirname.includes("/src/") || __dirname.includes("\\src\\")) {
|
|
766
|
+
if (fs5.existsSync(path6.join(process.cwd(), "agent-core"))) {
|
|
767
|
+
return path6.join(process.cwd(), "agent-core");
|
|
768
|
+
}
|
|
769
|
+
return path6.resolve(__dirname, "../..", "agent-core");
|
|
770
|
+
}
|
|
765
771
|
return path6.join(__dirname, "..", "agent-core");
|
|
766
772
|
}
|
|
767
773
|
function getAgentCorePromptsDir() {
|
|
@@ -1468,11 +1474,25 @@ var init_rag = __esm({
|
|
|
1468
1474
|
}
|
|
1469
1475
|
}
|
|
1470
1476
|
/**
|
|
1471
|
-
* Index a file
|
|
1477
|
+
* Index a file (smart: skips if mtime unchanged)
|
|
1478
|
+
* @param filePath Absolute path to the file
|
|
1479
|
+
* @param content File content
|
|
1480
|
+
* @param mtime Optional modification time (if not provided, always re-indexes)
|
|
1481
|
+
* @returns true if file was indexed, false if skipped
|
|
1472
1482
|
*/
|
|
1473
|
-
async indexFile(filePath, content) {
|
|
1483
|
+
async indexFile(filePath, content, mtime) {
|
|
1474
1484
|
this.loadIndex();
|
|
1475
1485
|
if (!this.index) throw new Error("Index not initialized");
|
|
1486
|
+
if (!this.index.fileMetadata) {
|
|
1487
|
+
this.index.fileMetadata = {};
|
|
1488
|
+
}
|
|
1489
|
+
if (mtime !== void 0 && this.index.fileMetadata[filePath]) {
|
|
1490
|
+
const existingMeta = this.index.fileMetadata[filePath];
|
|
1491
|
+
if (existingMeta.mtime === mtime) {
|
|
1492
|
+
logger.debug(`RAG: Skipping unchanged file ${filePath}`);
|
|
1493
|
+
return false;
|
|
1494
|
+
}
|
|
1495
|
+
}
|
|
1476
1496
|
logger.info(`RAG: Indexing file ${filePath}`);
|
|
1477
1497
|
this.index.chunks = this.index.chunks.filter((c) => c.filePath !== filePath);
|
|
1478
1498
|
const chunks = this.chunkContent(content);
|
|
@@ -1482,10 +1502,16 @@ var init_rag = __esm({
|
|
|
1482
1502
|
id: `${filePath}-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
|
|
1483
1503
|
filePath,
|
|
1484
1504
|
content: chunkText,
|
|
1485
|
-
embedding
|
|
1505
|
+
embedding,
|
|
1506
|
+
mtime
|
|
1486
1507
|
});
|
|
1487
1508
|
}
|
|
1509
|
+
this.index.fileMetadata[filePath] = {
|
|
1510
|
+
mtime: mtime ?? Date.now(),
|
|
1511
|
+
chunkCount: chunks.length
|
|
1512
|
+
};
|
|
1488
1513
|
this.saveIndex();
|
|
1514
|
+
return true;
|
|
1489
1515
|
}
|
|
1490
1516
|
/**
|
|
1491
1517
|
* Remove a file from index
|
|
@@ -1495,11 +1521,36 @@ var init_rag = __esm({
|
|
|
1495
1521
|
if (!this.index) return;
|
|
1496
1522
|
const initialCount = this.index.chunks.length;
|
|
1497
1523
|
this.index.chunks = this.index.chunks.filter((c) => c.filePath !== filePath);
|
|
1524
|
+
if (this.index.fileMetadata) {
|
|
1525
|
+
delete this.index.fileMetadata[filePath];
|
|
1526
|
+
}
|
|
1498
1527
|
if (this.index.chunks.length !== initialCount) {
|
|
1499
1528
|
logger.info(`RAG: Removed file ${filePath} from index (${initialCount - this.index.chunks.length} chunks removed)`);
|
|
1500
1529
|
this.saveIndex();
|
|
1501
1530
|
}
|
|
1502
1531
|
}
|
|
1532
|
+
/**
|
|
1533
|
+
* Get index statistics
|
|
1534
|
+
*/
|
|
1535
|
+
getStats() {
|
|
1536
|
+
this.loadIndex();
|
|
1537
|
+
if (!this.index) return { totalChunks: 0, totalFiles: 0 };
|
|
1538
|
+
const fileCount = this.index.fileMetadata ? Object.keys(this.index.fileMetadata).length : 0;
|
|
1539
|
+
return {
|
|
1540
|
+
totalChunks: this.index.chunks.length,
|
|
1541
|
+
totalFiles: fileCount,
|
|
1542
|
+
lastFullIndex: this.index.lastFullIndex
|
|
1543
|
+
};
|
|
1544
|
+
}
|
|
1545
|
+
/**
|
|
1546
|
+
* Mark the last full index timestamp
|
|
1547
|
+
*/
|
|
1548
|
+
markFullIndex() {
|
|
1549
|
+
this.loadIndex();
|
|
1550
|
+
if (!this.index) return;
|
|
1551
|
+
this.index.lastFullIndex = Date.now();
|
|
1552
|
+
this.saveIndex();
|
|
1553
|
+
}
|
|
1503
1554
|
/**
|
|
1504
1555
|
* Search the index
|
|
1505
1556
|
*/
|
|
@@ -1735,31 +1786,102 @@ async function indexKnowledge(projectName, force = false) {
|
|
|
1735
1786
|
const projects = getExposedProjects();
|
|
1736
1787
|
const project = projects.find((p) => p.name === projectName || p.path && p.path === projectName);
|
|
1737
1788
|
if (!project) {
|
|
1738
|
-
return { success: false, message: `Project '${projectName}' not found`, filesIndexed: 0 };
|
|
1789
|
+
return { success: false, message: `Project '${projectName}' not found`, filesIndexed: 0, filesSkipped: 0 };
|
|
1739
1790
|
}
|
|
1740
1791
|
const projConfig = config.projects.find(
|
|
1741
1792
|
(p) => p.path && p.path === project.dataPath || !p.path && p.name === project.name
|
|
1742
1793
|
);
|
|
1743
1794
|
if (!projConfig?.semanticSearch?.enabled) {
|
|
1744
|
-
return { success: false, message: "Semantic Search is not enabled for this project", filesIndexed: 0 };
|
|
1745
|
-
}
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1795
|
+
return { success: false, message: "Semantic Search is not enabled for this project", filesIndexed: 0, filesSkipped: 0 };
|
|
1796
|
+
}
|
|
1797
|
+
const scanRoot = project.path || project.dataPath;
|
|
1798
|
+
if (!fs13.existsSync(scanRoot)) {
|
|
1799
|
+
return { success: false, message: "Project root not found", filesIndexed: 0, filesSkipped: 0 };
|
|
1800
|
+
}
|
|
1801
|
+
const INDEXABLE_EXTENSIONS = [
|
|
1802
|
+
".ts",
|
|
1803
|
+
".tsx",
|
|
1804
|
+
".js",
|
|
1805
|
+
".jsx",
|
|
1806
|
+
".mjs",
|
|
1807
|
+
".cjs",
|
|
1808
|
+
".py",
|
|
1809
|
+
".pyw",
|
|
1810
|
+
".go",
|
|
1811
|
+
".rs",
|
|
1812
|
+
".java",
|
|
1813
|
+
".kt",
|
|
1814
|
+
".kts",
|
|
1815
|
+
".c",
|
|
1816
|
+
".cpp",
|
|
1817
|
+
".h",
|
|
1818
|
+
".hpp",
|
|
1819
|
+
".cs",
|
|
1820
|
+
".rb",
|
|
1821
|
+
".php",
|
|
1822
|
+
".swift",
|
|
1823
|
+
".md",
|
|
1824
|
+
".mdx",
|
|
1825
|
+
".json",
|
|
1826
|
+
".yaml",
|
|
1827
|
+
".yml",
|
|
1828
|
+
".toml",
|
|
1829
|
+
".sh",
|
|
1830
|
+
".bash",
|
|
1831
|
+
".zsh",
|
|
1832
|
+
".sql",
|
|
1833
|
+
".html",
|
|
1834
|
+
".css",
|
|
1835
|
+
".scss",
|
|
1836
|
+
".sass",
|
|
1837
|
+
".less"
|
|
1838
|
+
];
|
|
1839
|
+
const SKIP_DIRS = ["node_modules", ".git", "dist", "build", ".next", "__pycache__", "venv", ".venv", "target", "vendor"];
|
|
1749
1840
|
try {
|
|
1750
|
-
const indexPath = path14.join(project.knowledgePath, "embeddings.json");
|
|
1841
|
+
const indexPath = path14.join(project.knowledgePath || path14.join(scanRoot, ".rrce-workflow", "knowledge"), "embeddings.json");
|
|
1751
1842
|
const rag = new RAGService(indexPath, projConfig.semanticSearch.model);
|
|
1752
|
-
|
|
1753
|
-
let
|
|
1754
|
-
|
|
1755
|
-
const
|
|
1756
|
-
const
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1843
|
+
let indexed = 0;
|
|
1844
|
+
let skipped = 0;
|
|
1845
|
+
const scanDir = async (dir) => {
|
|
1846
|
+
const entries = fs13.readdirSync(dir, { withFileTypes: true });
|
|
1847
|
+
for (const entry of entries) {
|
|
1848
|
+
const fullPath = path14.join(dir, entry.name);
|
|
1849
|
+
if (entry.isDirectory()) {
|
|
1850
|
+
if (SKIP_DIRS.includes(entry.name) || entry.name.startsWith(".")) {
|
|
1851
|
+
continue;
|
|
1852
|
+
}
|
|
1853
|
+
await scanDir(fullPath);
|
|
1854
|
+
} else if (entry.isFile()) {
|
|
1855
|
+
const ext = path14.extname(entry.name).toLowerCase();
|
|
1856
|
+
if (!INDEXABLE_EXTENSIONS.includes(ext)) {
|
|
1857
|
+
continue;
|
|
1858
|
+
}
|
|
1859
|
+
try {
|
|
1860
|
+
const stat = fs13.statSync(fullPath);
|
|
1861
|
+
const mtime = force ? void 0 : stat.mtimeMs;
|
|
1862
|
+
const content = fs13.readFileSync(fullPath, "utf-8");
|
|
1863
|
+
const wasIndexed = await rag.indexFile(fullPath, content, mtime);
|
|
1864
|
+
if (wasIndexed) {
|
|
1865
|
+
indexed++;
|
|
1866
|
+
} else {
|
|
1867
|
+
skipped++;
|
|
1868
|
+
}
|
|
1869
|
+
} catch (err) {
|
|
1870
|
+
}
|
|
1871
|
+
}
|
|
1872
|
+
}
|
|
1873
|
+
};
|
|
1874
|
+
await scanDir(scanRoot);
|
|
1875
|
+
rag.markFullIndex();
|
|
1876
|
+
const stats = rag.getStats();
|
|
1877
|
+
return {
|
|
1878
|
+
success: true,
|
|
1879
|
+
message: `Indexed ${indexed} files, skipped ${skipped} unchanged. Total: ${stats.totalChunks} chunks from ${stats.totalFiles} files.`,
|
|
1880
|
+
filesIndexed: indexed,
|
|
1881
|
+
filesSkipped: skipped
|
|
1882
|
+
};
|
|
1761
1883
|
} catch (error) {
|
|
1762
|
-
return { success: false, message: `Indexing failed: ${error}`, filesIndexed: 0 };
|
|
1884
|
+
return { success: false, message: `Indexing failed: ${error}`, filesIndexed: 0, filesSkipped: 0 };
|
|
1763
1885
|
}
|
|
1764
1886
|
}
|
|
1765
1887
|
function getContextPreamble() {
|
|
@@ -2644,7 +2766,12 @@ var init_Overview = __esm({
|
|
|
2644
2766
|
/* @__PURE__ */ jsx2(Text2, { children: "Server Port: " }),
|
|
2645
2767
|
/* @__PURE__ */ jsx2(Text2, { color: "cyan", children: serverStatus.port })
|
|
2646
2768
|
] }),
|
|
2647
|
-
/* @__PURE__ */
|
|
2769
|
+
/* @__PURE__ */ jsxs(Box2, { marginTop: 1, flexDirection: "column", children: [
|
|
2770
|
+
/* @__PURE__ */ jsx2(Text2, { color: "dim", children: "Controls:" }),
|
|
2771
|
+
/* @__PURE__ */ jsx2(Text2, { color: "dim", children: " \u2022 Press 'r' to restart server" }),
|
|
2772
|
+
/* @__PURE__ */ jsx2(Text2, { color: "dim", children: " \u2022 Use 1-4 or \u25C4/\u25BA to navigate tabs" }),
|
|
2773
|
+
/* @__PURE__ */ jsx2(Text2, { color: "dim", children: " \u2022 Press 'q' to stop server and exit" })
|
|
2774
|
+
] })
|
|
2648
2775
|
] })
|
|
2649
2776
|
] });
|
|
2650
2777
|
};
|
|
@@ -3034,7 +3161,7 @@ var init_App = __esm({
|
|
|
3034
3161
|
];
|
|
3035
3162
|
App = ({ onExit, initialPort }) => {
|
|
3036
3163
|
const { exit } = useApp();
|
|
3037
|
-
const [activeTab, setActiveTab] = useState4("
|
|
3164
|
+
const [activeTab, setActiveTab] = useState4("overview");
|
|
3038
3165
|
const [logs, setLogs] = useState4([]);
|
|
3039
3166
|
const [serverInfo, setServerInfo] = useState4({
|
|
3040
3167
|
port: initialPort,
|
|
@@ -3107,12 +3234,24 @@ var init_App = __esm({
|
|
|
3107
3234
|
}, 500);
|
|
3108
3235
|
return () => clearInterval(interval);
|
|
3109
3236
|
}, []);
|
|
3110
|
-
useInput3((input, key) => {
|
|
3237
|
+
useInput3(async (input, key) => {
|
|
3111
3238
|
if (input === "q" || key.ctrl && input === "c") {
|
|
3112
3239
|
stopMCPServer();
|
|
3113
3240
|
onExit();
|
|
3114
3241
|
exit();
|
|
3115
3242
|
}
|
|
3243
|
+
if (input === "r") {
|
|
3244
|
+
setLogs((prev) => [...prev, "[INFO] Restarting server..."]);
|
|
3245
|
+
stopMCPServer();
|
|
3246
|
+
setServerInfo((prev) => ({ ...prev, running: false }));
|
|
3247
|
+
try {
|
|
3248
|
+
const res = await startMCPServer({ interactive: true });
|
|
3249
|
+
setServerInfo((prev) => ({ ...prev, running: true, port: res.port, pid: res.pid }));
|
|
3250
|
+
setLogs((prev) => [...prev, "[INFO] Server restarted successfully"]);
|
|
3251
|
+
} catch (e) {
|
|
3252
|
+
setLogs((prev) => [...prev, `[ERROR] Failed to restart: ${e}`]);
|
|
3253
|
+
}
|
|
3254
|
+
}
|
|
3116
3255
|
});
|
|
3117
3256
|
const termHeight = process.stdout.rows || 24;
|
|
3118
3257
|
const contentHeight = termHeight - 8;
|