rrce-workflow 0.2.50 → 0.2.52
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/dist/index.js +148 -81
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -273,6 +273,11 @@ function parseWorkspaceConfig(configPath) {
|
|
|
273
273
|
return null;
|
|
274
274
|
}
|
|
275
275
|
}
|
|
276
|
+
function findClosestProject(projects, cwd = process.cwd()) {
|
|
277
|
+
const matches = projects.filter((p) => cwd.startsWith(p.path));
|
|
278
|
+
matches.sort((a, b) => b.path.length - a.path.length);
|
|
279
|
+
return matches[0];
|
|
280
|
+
}
|
|
276
281
|
var SKIP_DIRECTORIES;
|
|
277
282
|
var init_detection = __esm({
|
|
278
283
|
"src/lib/detection.ts"() {
|
|
@@ -301,6 +306,68 @@ var init_detection = __esm({
|
|
|
301
306
|
}
|
|
302
307
|
});
|
|
303
308
|
|
|
309
|
+
// src/lib/detection-service.ts
|
|
310
|
+
var ProjectDetectionService, projectService;
|
|
311
|
+
var init_detection_service = __esm({
|
|
312
|
+
"src/lib/detection-service.ts"() {
|
|
313
|
+
"use strict";
|
|
314
|
+
init_detection();
|
|
315
|
+
ProjectDetectionService = class {
|
|
316
|
+
cache = null;
|
|
317
|
+
cacheTime = 0;
|
|
318
|
+
TTL = 3e4;
|
|
319
|
+
// 30 seconds cache TTL (scanning is expensive)
|
|
320
|
+
lastOptions = null;
|
|
321
|
+
/**
|
|
322
|
+
* Scan for projects with caching
|
|
323
|
+
* Returns cached version if still valid and options match
|
|
324
|
+
*/
|
|
325
|
+
scan(options) {
|
|
326
|
+
const now = Date.now();
|
|
327
|
+
const optionsMatch = JSON.stringify(options) === JSON.stringify(this.lastOptions);
|
|
328
|
+
if (this.cache && optionsMatch && now - this.cacheTime < this.TTL) {
|
|
329
|
+
return this.cache;
|
|
330
|
+
}
|
|
331
|
+
this.cache = scanForProjects(options);
|
|
332
|
+
this.cacheTime = now;
|
|
333
|
+
this.lastOptions = options || null;
|
|
334
|
+
return this.cache;
|
|
335
|
+
}
|
|
336
|
+
/**
|
|
337
|
+
* Force a fresh scan, bypassing cache
|
|
338
|
+
*/
|
|
339
|
+
refresh(options) {
|
|
340
|
+
this.invalidate();
|
|
341
|
+
return this.scan(options);
|
|
342
|
+
}
|
|
343
|
+
/**
|
|
344
|
+
* Invalidate cache, forcing next scan to read from disk
|
|
345
|
+
*/
|
|
346
|
+
invalidate() {
|
|
347
|
+
this.cache = null;
|
|
348
|
+
this.lastOptions = null;
|
|
349
|
+
}
|
|
350
|
+
/**
|
|
351
|
+
* Check if cache is currently valid
|
|
352
|
+
*/
|
|
353
|
+
isCacheValid() {
|
|
354
|
+
return this.cache !== null && Date.now() - this.cacheTime < this.TTL;
|
|
355
|
+
}
|
|
356
|
+
/**
|
|
357
|
+
* Get cached projects without triggering a scan
|
|
358
|
+
* Returns null if cache is invalid
|
|
359
|
+
*/
|
|
360
|
+
getCached() {
|
|
361
|
+
if (this.isCacheValid()) {
|
|
362
|
+
return this.cache;
|
|
363
|
+
}
|
|
364
|
+
return null;
|
|
365
|
+
}
|
|
366
|
+
};
|
|
367
|
+
projectService = new ProjectDetectionService();
|
|
368
|
+
}
|
|
369
|
+
});
|
|
370
|
+
|
|
304
371
|
// src/lib/autocomplete-prompt.ts
|
|
305
372
|
import * as fs3 from "fs";
|
|
306
373
|
import * as path3 from "path";
|
|
@@ -1303,33 +1370,46 @@ var init_rag = __esm({
|
|
|
1303
1370
|
init_logger();
|
|
1304
1371
|
INDEX_VERSION = "1.0.0";
|
|
1305
1372
|
DEFAULT_MODEL = "Xenova/all-MiniLM-L6-v2";
|
|
1306
|
-
RAGService = class {
|
|
1307
|
-
|
|
1373
|
+
RAGService = class _RAGService {
|
|
1374
|
+
// Static cache for the pipeline to prevent reloading model for every instance
|
|
1375
|
+
static pipelineInstance = null;
|
|
1376
|
+
static activeModelName = null;
|
|
1377
|
+
static loadPromise = null;
|
|
1308
1378
|
modelName;
|
|
1309
1379
|
indexPath;
|
|
1310
1380
|
index = null;
|
|
1311
|
-
lastAccess = 0;
|
|
1312
1381
|
constructor(indexPath, modelName = DEFAULT_MODEL) {
|
|
1313
1382
|
this.indexPath = indexPath;
|
|
1314
1383
|
this.modelName = modelName;
|
|
1315
1384
|
}
|
|
1316
1385
|
/**
|
|
1317
|
-
* Lazy load the model
|
|
1386
|
+
* Lazy load the model (Singleton pattern)
|
|
1318
1387
|
*/
|
|
1319
1388
|
async getPipeline() {
|
|
1320
|
-
if (
|
|
1321
|
-
|
|
1389
|
+
if (_RAGService.activeModelName === this.modelName && _RAGService.pipelineInstance) {
|
|
1390
|
+
return _RAGService.pipelineInstance;
|
|
1391
|
+
}
|
|
1392
|
+
if (_RAGService.activeModelName === this.modelName && _RAGService.loadPromise) {
|
|
1393
|
+
return _RAGService.loadPromise;
|
|
1394
|
+
}
|
|
1395
|
+
logger.info(`RAG: Initializing model ${this.modelName}...`);
|
|
1396
|
+
_RAGService.activeModelName = this.modelName;
|
|
1397
|
+
_RAGService.loadPromise = (async () => {
|
|
1322
1398
|
try {
|
|
1323
1399
|
const { pipeline } = await import("@xenova/transformers");
|
|
1324
|
-
|
|
1400
|
+
const pipe = await pipeline("feature-extraction", this.modelName);
|
|
1401
|
+
_RAGService.pipelineInstance = pipe;
|
|
1325
1402
|
logger.info(`RAG: Model ${this.modelName} initialized successfully.`);
|
|
1403
|
+
return pipe;
|
|
1326
1404
|
} catch (error) {
|
|
1327
1405
|
logger.error(`RAG: Failed to initialize model ${this.modelName}`, error);
|
|
1406
|
+
_RAGService.pipelineInstance = null;
|
|
1407
|
+
_RAGService.activeModelName = null;
|
|
1408
|
+
_RAGService.loadPromise = null;
|
|
1328
1409
|
throw error;
|
|
1329
1410
|
}
|
|
1330
|
-
}
|
|
1331
|
-
|
|
1332
|
-
return this.pipe;
|
|
1411
|
+
})();
|
|
1412
|
+
return _RAGService.loadPromise;
|
|
1333
1413
|
}
|
|
1334
1414
|
/**
|
|
1335
1415
|
* Load index from disk
|
|
@@ -1488,7 +1568,7 @@ import * as fs13 from "fs";
|
|
|
1488
1568
|
import * as path14 from "path";
|
|
1489
1569
|
function getExposedProjects() {
|
|
1490
1570
|
const config = loadMCPConfig();
|
|
1491
|
-
const allProjects =
|
|
1571
|
+
const allProjects = projectService.scan();
|
|
1492
1572
|
const globalProjects = allProjects.filter((project) => isProjectExposed(config, project.name, project.dataPath));
|
|
1493
1573
|
const activeProject = detectActiveProject(globalProjects);
|
|
1494
1574
|
let linkedProjects = [];
|
|
@@ -1536,17 +1616,14 @@ function detectActiveProject(knownProjects) {
|
|
|
1536
1616
|
let scanList = knownProjects;
|
|
1537
1617
|
if (!scanList) {
|
|
1538
1618
|
const config = loadMCPConfig();
|
|
1539
|
-
const all =
|
|
1619
|
+
const all = projectService.scan();
|
|
1540
1620
|
scanList = all.filter((project) => isProjectExposed(config, project.name, project.dataPath));
|
|
1541
1621
|
}
|
|
1542
|
-
|
|
1543
|
-
const matches = scanList.filter((p) => cwd.startsWith(p.path));
|
|
1544
|
-
matches.sort((a, b) => b.path.length - a.path.length);
|
|
1545
|
-
return matches[0];
|
|
1622
|
+
return findClosestProject(scanList);
|
|
1546
1623
|
}
|
|
1547
1624
|
function getProjectContext(projectName) {
|
|
1548
1625
|
const config = loadMCPConfig();
|
|
1549
|
-
const projects =
|
|
1626
|
+
const projects = projectService.scan();
|
|
1550
1627
|
const project = projects.find((p) => p.name === projectName && isProjectExposed(config, p.name, p.dataPath));
|
|
1551
1628
|
if (!project) {
|
|
1552
1629
|
return null;
|
|
@@ -1566,7 +1643,7 @@ function getProjectContext(projectName) {
|
|
|
1566
1643
|
}
|
|
1567
1644
|
function getProjectTasks(projectName) {
|
|
1568
1645
|
const config = loadMCPConfig();
|
|
1569
|
-
const projects =
|
|
1646
|
+
const projects = projectService.scan();
|
|
1570
1647
|
const project = projects.find((p) => p.name === projectName && isProjectExposed(config, p.name, p.dataPath));
|
|
1571
1648
|
if (!project) {
|
|
1572
1649
|
return [];
|
|
@@ -1685,11 +1762,44 @@ async function indexKnowledge(projectName, force = false) {
|
|
|
1685
1762
|
return { success: false, message: `Indexing failed: ${error}`, filesIndexed: 0 };
|
|
1686
1763
|
}
|
|
1687
1764
|
}
|
|
1765
|
+
function getContextPreamble() {
|
|
1766
|
+
const projects = getExposedProjects();
|
|
1767
|
+
const activeProject = detectActiveProject();
|
|
1768
|
+
const projectList = projects.map((p) => {
|
|
1769
|
+
const isActive = activeProject && p.dataPath === activeProject.dataPath;
|
|
1770
|
+
return `- ${p.name} (${p.source}) ${isActive ? "**[ACTIVE]**" : ""}`;
|
|
1771
|
+
}).join("\n");
|
|
1772
|
+
let contextPreamble = `
|
|
1773
|
+
Context - Available Projects (MCP Hub):
|
|
1774
|
+
${projectList}
|
|
1775
|
+
`;
|
|
1776
|
+
if (projects.length === 0) {
|
|
1777
|
+
contextPreamble += `
|
|
1778
|
+
WARNING: No projects are currently exposed to the MCP server.
|
|
1779
|
+
The user needs to run 'npx rrce-workflow mcp configure' in their terminal to select projects to expose.
|
|
1780
|
+
Please advise the user to do this if they expect to see project context.
|
|
1781
|
+
`;
|
|
1782
|
+
}
|
|
1783
|
+
if (activeProject) {
|
|
1784
|
+
contextPreamble += `
|
|
1785
|
+
Current Active Workspace: ${activeProject.name} (${activeProject.path})
|
|
1786
|
+
`;
|
|
1787
|
+
contextPreamble += `IMPORTANT: Treat '${activeProject.path}' as the {{WORKSPACE_ROOT}}. All relative path operations (file reads/writes) MUST be performed relative to this directory.
|
|
1788
|
+
`;
|
|
1789
|
+
}
|
|
1790
|
+
contextPreamble += `
|
|
1791
|
+
Note: If the user's request refers to a project not listed here, ask them to expose it via 'rrce-workflow mcp configure'.
|
|
1792
|
+
|
|
1793
|
+
---
|
|
1794
|
+
`;
|
|
1795
|
+
return contextPreamble;
|
|
1796
|
+
}
|
|
1688
1797
|
var init_resources = __esm({
|
|
1689
1798
|
"src/mcp/resources.ts"() {
|
|
1690
1799
|
"use strict";
|
|
1691
1800
|
init_config();
|
|
1692
1801
|
init_detection();
|
|
1802
|
+
init_detection_service();
|
|
1693
1803
|
init_rag();
|
|
1694
1804
|
}
|
|
1695
1805
|
});
|
|
@@ -1951,28 +2061,7 @@ function registerToolHandlers(server) {
|
|
|
1951
2061
|
stringArgs[key] = String(val);
|
|
1952
2062
|
}
|
|
1953
2063
|
const content = renderPrompt(promptDef.content, stringArgs);
|
|
1954
|
-
const
|
|
1955
|
-
const activeProject = detectActiveProject();
|
|
1956
|
-
const projectList = projects.map((p) => {
|
|
1957
|
-
const isActive = activeProject && p.dataPath === activeProject.dataPath;
|
|
1958
|
-
return `- ${p.name} (${p.source}) ${isActive ? "**[ACTIVE]**" : ""}`;
|
|
1959
|
-
}).join("\n");
|
|
1960
|
-
let contextPreamble = `
|
|
1961
|
-
Context - Available Projects (MCP Hub):
|
|
1962
|
-
${projectList}
|
|
1963
|
-
`;
|
|
1964
|
-
if (activeProject) {
|
|
1965
|
-
contextPreamble += `
|
|
1966
|
-
Current Active Workspace: ${activeProject.name} (${activeProject.path})
|
|
1967
|
-
`;
|
|
1968
|
-
contextPreamble += `IMPORTANT: Treat '${activeProject.path}' as the {{WORKSPACE_ROOT}}. All relative path operations (file reads/writes) MUST be performed relative to this directory.
|
|
1969
|
-
`;
|
|
1970
|
-
}
|
|
1971
|
-
contextPreamble += `
|
|
1972
|
-
Note: If the user's request refers to a project not listed here, ask them to expose it via 'rrce-workflow mcp configure'.
|
|
1973
|
-
|
|
1974
|
-
---
|
|
1975
|
-
`;
|
|
2064
|
+
const contextPreamble = getContextPreamble();
|
|
1976
2065
|
return { content: [{ type: "text", text: contextPreamble + content }] };
|
|
1977
2066
|
}
|
|
1978
2067
|
case "help_setup": {
|
|
@@ -2046,35 +2135,7 @@ function registerPromptHandlers(server) {
|
|
|
2046
2135
|
renderArgs[key] = String(val);
|
|
2047
2136
|
}
|
|
2048
2137
|
const content = renderPrompt(promptDef.content, renderArgs);
|
|
2049
|
-
const
|
|
2050
|
-
const activeProject = detectActiveProject();
|
|
2051
|
-
const projectList = projects.map((p) => {
|
|
2052
|
-
const isActive = activeProject && p.dataPath === activeProject.dataPath;
|
|
2053
|
-
return `- ${p.name} (${p.source}) ${isActive ? "**[ACTIVE]**" : ""}`;
|
|
2054
|
-
}).join("\n");
|
|
2055
|
-
let contextPreamble = `
|
|
2056
|
-
Context - Available Projects (MCP Hub):
|
|
2057
|
-
${projectList}
|
|
2058
|
-
`;
|
|
2059
|
-
if (projects.length === 0) {
|
|
2060
|
-
contextPreamble += `
|
|
2061
|
-
WARNING: No projects are currently exposed to the MCP server.
|
|
2062
|
-
The user needs to run 'npx rrce-workflow mcp configure' in their terminal to select projects to expose.
|
|
2063
|
-
Please advise the user to do this if they expect to see project context.
|
|
2064
|
-
`;
|
|
2065
|
-
}
|
|
2066
|
-
if (activeProject) {
|
|
2067
|
-
contextPreamble += `
|
|
2068
|
-
Current Active Workspace: ${activeProject.name} (${activeProject.path})
|
|
2069
|
-
`;
|
|
2070
|
-
contextPreamble += `IMPORTANT: Treat '${activeProject.path}' as the {{WORKSPACE_ROOT}}. All relative path operations (file reads/writes) MUST be performed relative to this directory.
|
|
2071
|
-
`;
|
|
2072
|
-
}
|
|
2073
|
-
contextPreamble += `
|
|
2074
|
-
Note: If the user's request refers to a project not listed here, ask them to expose it via 'rrce-workflow mcp configure'.
|
|
2075
|
-
|
|
2076
|
-
---
|
|
2077
|
-
`;
|
|
2138
|
+
const contextPreamble = getContextPreamble();
|
|
2078
2139
|
return {
|
|
2079
2140
|
messages: [
|
|
2080
2141
|
{
|
|
@@ -2944,7 +3005,7 @@ var App_exports = {};
|
|
|
2944
3005
|
__export(App_exports, {
|
|
2945
3006
|
App: () => App
|
|
2946
3007
|
});
|
|
2947
|
-
import { useState as useState4, useEffect as useEffect3, useCallback } from "react";
|
|
3008
|
+
import { useState as useState4, useEffect as useEffect3, useMemo, useCallback } from "react";
|
|
2948
3009
|
import { Box as Box10, useInput as useInput3, useApp } from "ink";
|
|
2949
3010
|
import fs15 from "fs";
|
|
2950
3011
|
import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
@@ -2980,15 +3041,21 @@ var init_App = __esm({
|
|
|
2980
3041
|
pid: process.pid,
|
|
2981
3042
|
running: false
|
|
2982
3043
|
});
|
|
2983
|
-
const [
|
|
2984
|
-
const
|
|
2985
|
-
const
|
|
2986
|
-
|
|
2987
|
-
|
|
2988
|
-
|
|
2989
|
-
|
|
2990
|
-
|
|
2991
|
-
|
|
3044
|
+
const [config, setConfig] = useState4(() => loadMCPConfig());
|
|
3045
|
+
const [projects, setProjects] = useState4(() => scanForProjects());
|
|
3046
|
+
const refreshData = useCallback(() => {
|
|
3047
|
+
setConfig(loadMCPConfig());
|
|
3048
|
+
setProjects(scanForProjects());
|
|
3049
|
+
}, []);
|
|
3050
|
+
const exposedProjects = useMemo(
|
|
3051
|
+
() => projects.filter((p) => {
|
|
3052
|
+
const cfg = config.projects.find(
|
|
3053
|
+
(c) => c.path && c.path === p.path || !c.path && c.name === p.name
|
|
3054
|
+
);
|
|
3055
|
+
return cfg?.expose ?? config.defaults.includeNew;
|
|
3056
|
+
}),
|
|
3057
|
+
[projects, config]
|
|
3058
|
+
);
|
|
2992
3059
|
const workspacePath = detectWorkspaceRoot();
|
|
2993
3060
|
const installStatus = checkInstallStatus(workspacePath);
|
|
2994
3061
|
const installedCount = [
|
|
@@ -3901,7 +3968,7 @@ async function runWizard() {
|
|
|
3901
3968
|
Workspace: ${pc15.bold(workspaceName)}`,
|
|
3902
3969
|
"Context"
|
|
3903
3970
|
);
|
|
3904
|
-
const detectedProjects =
|
|
3971
|
+
const detectedProjects = projectService.scan({
|
|
3905
3972
|
excludeWorkspace: workspaceName,
|
|
3906
3973
|
workspacePath
|
|
3907
3974
|
});
|
|
@@ -3997,7 +4064,7 @@ var init_wizard = __esm({
|
|
|
3997
4064
|
"use strict";
|
|
3998
4065
|
init_git();
|
|
3999
4066
|
init_paths();
|
|
4000
|
-
|
|
4067
|
+
init_detection_service();
|
|
4001
4068
|
init_setup_flow();
|
|
4002
4069
|
init_link_flow();
|
|
4003
4070
|
init_sync_flow();
|