rrce-workflow 0.2.98 → 0.2.99
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 +551 -231
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1266,8 +1266,10 @@ function parseMCPConfig(content) {
|
|
|
1266
1266
|
tasks: p.permissions?.tasks ?? DEFAULT_PERMISSIONS.tasks,
|
|
1267
1267
|
refs: p.permissions?.refs ?? DEFAULT_PERMISSIONS.refs
|
|
1268
1268
|
},
|
|
1269
|
-
semanticSearch: p.semanticSearch
|
|
1270
|
-
|
|
1269
|
+
semanticSearch: p.semanticSearch,
|
|
1270
|
+
last_synced_version: p.last_synced_version
|
|
1271
|
+
})) : [],
|
|
1272
|
+
last_synced_version: parsed?.last_synced_version
|
|
1271
1273
|
};
|
|
1272
1274
|
return config;
|
|
1273
1275
|
} catch (err) {
|
|
@@ -2361,7 +2363,7 @@ var init_dependency_graph = __esm({
|
|
|
2361
2363
|
// src/mcp/resources.ts
|
|
2362
2364
|
import * as fs15 from "fs";
|
|
2363
2365
|
import * as path17 from "path";
|
|
2364
|
-
import * as
|
|
2366
|
+
import * as os3 from "os";
|
|
2365
2367
|
import * as crypto from "crypto";
|
|
2366
2368
|
import ignore from "ignore";
|
|
2367
2369
|
function resolveProjectPaths(project, pathInput) {
|
|
@@ -2903,7 +2905,7 @@ function getContextPreamble() {
|
|
|
2903
2905
|
const activeProject = detectActiveProject();
|
|
2904
2906
|
let contextPreamble = "";
|
|
2905
2907
|
if (activeProject) {
|
|
2906
|
-
const rrceHome = process.env.RRCE_HOME || path17.join(
|
|
2908
|
+
const rrceHome = process.env.RRCE_HOME || path17.join(os3.homedir(), ".rrce-workflow");
|
|
2907
2909
|
const workspaceRoot = activeProject.sourcePath || activeProject.path || activeProject.dataPath;
|
|
2908
2910
|
const rrceData = activeProject.dataPath;
|
|
2909
2911
|
contextPreamble += `
|
|
@@ -2973,7 +2975,7 @@ async function createTask(projectName, taskSlug, taskData) {
|
|
|
2973
2975
|
fs15.mkdirSync(path17.join(taskDir, "planning"), { recursive: true });
|
|
2974
2976
|
fs15.mkdirSync(path17.join(taskDir, "execution"), { recursive: true });
|
|
2975
2977
|
fs15.mkdirSync(path17.join(taskDir, "docs"), { recursive: true });
|
|
2976
|
-
const rrceHome = process.env.RRCE_HOME || path17.join(
|
|
2978
|
+
const rrceHome = process.env.RRCE_HOME || path17.join(os3.homedir(), ".rrce-workflow");
|
|
2977
2979
|
const templatePath = path17.join(rrceHome, "templates", "meta.template.json");
|
|
2978
2980
|
let meta = {
|
|
2979
2981
|
task_id: crypto.randomUUID(),
|
|
@@ -3869,8 +3871,8 @@ Hidden projects: ${projects.length - exposedCount}`,
|
|
|
3869
3871
|
}
|
|
3870
3872
|
async function handleConfigureGlobalPath() {
|
|
3871
3873
|
const { resolveGlobalPath: resolveGlobalPath2 } = await Promise.resolve().then(() => (init_tui_utils(), tui_utils_exports));
|
|
3872
|
-
const
|
|
3873
|
-
const
|
|
3874
|
+
const fs26 = await import("fs");
|
|
3875
|
+
const path24 = await import("path");
|
|
3874
3876
|
note3(
|
|
3875
3877
|
`MCP Hub requires a ${pc5.bold("global storage path")} to store its configuration
|
|
3876
3878
|
and coordinate across projects.
|
|
@@ -3884,8 +3886,8 @@ locally in each project. MCP needs a central location.`,
|
|
|
3884
3886
|
return false;
|
|
3885
3887
|
}
|
|
3886
3888
|
try {
|
|
3887
|
-
if (!
|
|
3888
|
-
|
|
3889
|
+
if (!fs26.existsSync(resolvedPath)) {
|
|
3890
|
+
fs26.mkdirSync(resolvedPath, { recursive: true });
|
|
3889
3891
|
}
|
|
3890
3892
|
const config = loadMCPConfig();
|
|
3891
3893
|
saveMCPConfig(config);
|
|
@@ -3893,7 +3895,7 @@ locally in each project. MCP needs a central location.`,
|
|
|
3893
3895
|
`${pc5.green("\u2713")} Global path configured: ${pc5.cyan(resolvedPath)}
|
|
3894
3896
|
|
|
3895
3897
|
MCP config will be stored at:
|
|
3896
|
-
${
|
|
3898
|
+
${path24.join(resolvedPath, "mcp.yaml")}`,
|
|
3897
3899
|
"Configuration Saved"
|
|
3898
3900
|
);
|
|
3899
3901
|
return true;
|
|
@@ -4218,10 +4220,191 @@ var init_tasks_fs = __esm({
|
|
|
4218
4220
|
}
|
|
4219
4221
|
});
|
|
4220
4222
|
|
|
4223
|
+
// src/lib/drift-service.ts
|
|
4224
|
+
import * as fs18 from "fs";
|
|
4225
|
+
import * as path20 from "path";
|
|
4226
|
+
import * as crypto2 from "crypto";
|
|
4227
|
+
var DriftService;
|
|
4228
|
+
var init_drift_service = __esm({
|
|
4229
|
+
"src/lib/drift-service.ts"() {
|
|
4230
|
+
"use strict";
|
|
4231
|
+
DriftService = class {
|
|
4232
|
+
static CHECKSUM_FILENAME = ".rrce-checksums.json";
|
|
4233
|
+
static calculateHash(filePath) {
|
|
4234
|
+
const content = fs18.readFileSync(filePath);
|
|
4235
|
+
return crypto2.createHash("md5").update(content).digest("hex");
|
|
4236
|
+
}
|
|
4237
|
+
static getManifestPath(projectPath) {
|
|
4238
|
+
return path20.join(projectPath, this.CHECKSUM_FILENAME);
|
|
4239
|
+
}
|
|
4240
|
+
static loadManifest(projectPath) {
|
|
4241
|
+
const manifestPath = this.getManifestPath(projectPath);
|
|
4242
|
+
if (!fs18.existsSync(manifestPath)) {
|
|
4243
|
+
return {};
|
|
4244
|
+
}
|
|
4245
|
+
try {
|
|
4246
|
+
return JSON.parse(fs18.readFileSync(manifestPath, "utf8"));
|
|
4247
|
+
} catch (e) {
|
|
4248
|
+
return {};
|
|
4249
|
+
}
|
|
4250
|
+
}
|
|
4251
|
+
static saveManifest(projectPath, manifest) {
|
|
4252
|
+
const manifestPath = this.getManifestPath(projectPath);
|
|
4253
|
+
fs18.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2));
|
|
4254
|
+
}
|
|
4255
|
+
/**
|
|
4256
|
+
* Generates a manifest for the current state of files in the project
|
|
4257
|
+
*/
|
|
4258
|
+
static generateManifest(projectPath, files) {
|
|
4259
|
+
const manifest = {};
|
|
4260
|
+
for (const file of files) {
|
|
4261
|
+
const fullPath = path20.join(projectPath, file);
|
|
4262
|
+
if (fs18.existsSync(fullPath)) {
|
|
4263
|
+
const stats = fs18.statSync(fullPath);
|
|
4264
|
+
manifest[file] = {
|
|
4265
|
+
hash: this.calculateHash(fullPath),
|
|
4266
|
+
mtime: stats.mtimeMs
|
|
4267
|
+
};
|
|
4268
|
+
}
|
|
4269
|
+
}
|
|
4270
|
+
return manifest;
|
|
4271
|
+
}
|
|
4272
|
+
/**
|
|
4273
|
+
* Compares current files against the manifest to detect modifications
|
|
4274
|
+
*/
|
|
4275
|
+
static detectModifiedFiles(projectPath) {
|
|
4276
|
+
const manifest = this.loadManifest(projectPath);
|
|
4277
|
+
const modifiedFiles = [];
|
|
4278
|
+
for (const [relPath, entry] of Object.entries(manifest)) {
|
|
4279
|
+
const fullPath = path20.join(projectPath, relPath);
|
|
4280
|
+
if (!fs18.existsSync(fullPath)) {
|
|
4281
|
+
continue;
|
|
4282
|
+
}
|
|
4283
|
+
const stats = fs18.statSync(fullPath);
|
|
4284
|
+
if (stats.mtimeMs === entry.mtime) {
|
|
4285
|
+
continue;
|
|
4286
|
+
}
|
|
4287
|
+
const currentHash = this.calculateHash(fullPath);
|
|
4288
|
+
if (currentHash !== entry.hash) {
|
|
4289
|
+
modifiedFiles.push(relPath);
|
|
4290
|
+
}
|
|
4291
|
+
}
|
|
4292
|
+
return modifiedFiles;
|
|
4293
|
+
}
|
|
4294
|
+
/**
|
|
4295
|
+
* Full drift check: version + modifications
|
|
4296
|
+
*/
|
|
4297
|
+
static checkDrift(projectPath, currentVersion, runningVersion) {
|
|
4298
|
+
const modifiedFiles = this.detectModifiedFiles(projectPath);
|
|
4299
|
+
let type = "none";
|
|
4300
|
+
let hasDrift = false;
|
|
4301
|
+
if (currentVersion !== runningVersion) {
|
|
4302
|
+
hasDrift = true;
|
|
4303
|
+
type = "version";
|
|
4304
|
+
} else if (modifiedFiles.length > 0) {
|
|
4305
|
+
hasDrift = true;
|
|
4306
|
+
type = "modified";
|
|
4307
|
+
}
|
|
4308
|
+
return {
|
|
4309
|
+
hasDrift,
|
|
4310
|
+
type,
|
|
4311
|
+
modifiedFiles,
|
|
4312
|
+
version: {
|
|
4313
|
+
current: currentVersion || "0.0.0",
|
|
4314
|
+
running: runningVersion
|
|
4315
|
+
}
|
|
4316
|
+
};
|
|
4317
|
+
}
|
|
4318
|
+
};
|
|
4319
|
+
}
|
|
4320
|
+
});
|
|
4321
|
+
|
|
4322
|
+
// src/mcp/ui/ConfigContext.tsx
|
|
4323
|
+
var ConfigContext_exports = {};
|
|
4324
|
+
__export(ConfigContext_exports, {
|
|
4325
|
+
ConfigContext: () => ConfigContext,
|
|
4326
|
+
ConfigProvider: () => ConfigProvider,
|
|
4327
|
+
useConfig: () => useConfig
|
|
4328
|
+
});
|
|
4329
|
+
import { createContext, useContext, useState as useState2, useCallback, useMemo as useMemo2, useEffect as useEffect2 } from "react";
|
|
4330
|
+
import * as fs19 from "fs";
|
|
4331
|
+
import * as path21 from "path";
|
|
4332
|
+
import { jsx as jsx4 } from "react/jsx-runtime";
|
|
4333
|
+
function getPackageVersion() {
|
|
4334
|
+
try {
|
|
4335
|
+
const agentCoreDir = getAgentCoreDir();
|
|
4336
|
+
const packageJsonPath = path21.join(path21.dirname(agentCoreDir), "package.json");
|
|
4337
|
+
if (fs19.existsSync(packageJsonPath)) {
|
|
4338
|
+
return JSON.parse(fs19.readFileSync(packageJsonPath, "utf8")).version;
|
|
4339
|
+
}
|
|
4340
|
+
} catch (e) {
|
|
4341
|
+
}
|
|
4342
|
+
return "0.0.0";
|
|
4343
|
+
}
|
|
4344
|
+
function useConfig() {
|
|
4345
|
+
const context = useContext(ConfigContext);
|
|
4346
|
+
if (!context) {
|
|
4347
|
+
throw new Error("useConfig must be used within a ConfigProvider");
|
|
4348
|
+
}
|
|
4349
|
+
return context;
|
|
4350
|
+
}
|
|
4351
|
+
var ConfigContext, ConfigProvider;
|
|
4352
|
+
var init_ConfigContext = __esm({
|
|
4353
|
+
"src/mcp/ui/ConfigContext.tsx"() {
|
|
4354
|
+
"use strict";
|
|
4355
|
+
init_config();
|
|
4356
|
+
init_detection();
|
|
4357
|
+
init_config_utils();
|
|
4358
|
+
init_drift_service();
|
|
4359
|
+
init_prompts();
|
|
4360
|
+
ConfigContext = createContext(null);
|
|
4361
|
+
ConfigProvider = ({ children }) => {
|
|
4362
|
+
const [config, setConfig] = useState2(() => loadMCPConfig());
|
|
4363
|
+
const [projects, setProjects] = useState2(() => scanForProjects());
|
|
4364
|
+
const [driftReports, setDriftReports] = useState2({});
|
|
4365
|
+
const refresh = useCallback(() => {
|
|
4366
|
+
const newConfig = loadMCPConfig();
|
|
4367
|
+
const newProjects = scanForProjects();
|
|
4368
|
+
setConfig(newConfig);
|
|
4369
|
+
setProjects(newProjects);
|
|
4370
|
+
}, []);
|
|
4371
|
+
const checkAllDrift = useCallback(() => {
|
|
4372
|
+
const runningVersion = getPackageVersion();
|
|
4373
|
+
const reports = {};
|
|
4374
|
+
for (const project of projects) {
|
|
4375
|
+
const projectConfig = findProjectConfig(config, { name: project.name, path: project.path });
|
|
4376
|
+
const currentVersion = projectConfig?.last_synced_version;
|
|
4377
|
+
reports[project.path] = DriftService.checkDrift(project.dataPath, currentVersion, runningVersion);
|
|
4378
|
+
}
|
|
4379
|
+
setDriftReports(reports);
|
|
4380
|
+
}, [projects, config]);
|
|
4381
|
+
useEffect2(() => {
|
|
4382
|
+
checkAllDrift();
|
|
4383
|
+
}, [checkAllDrift]);
|
|
4384
|
+
const exposedProjects = useMemo2(
|
|
4385
|
+
() => projects.filter((p) => {
|
|
4386
|
+
const cfg = findProjectConfig(config, { name: p.name, path: p.path });
|
|
4387
|
+
return cfg?.expose ?? config.defaults.includeNew;
|
|
4388
|
+
}),
|
|
4389
|
+
[projects, config]
|
|
4390
|
+
);
|
|
4391
|
+
const value = useMemo2(() => ({
|
|
4392
|
+
config,
|
|
4393
|
+
projects,
|
|
4394
|
+
exposedProjects,
|
|
4395
|
+
driftReports,
|
|
4396
|
+
refresh,
|
|
4397
|
+
checkAllDrift
|
|
4398
|
+
}), [config, projects, exposedProjects, driftReports, refresh, checkAllDrift]);
|
|
4399
|
+
return /* @__PURE__ */ jsx4(ConfigContext.Provider, { value, children });
|
|
4400
|
+
};
|
|
4401
|
+
}
|
|
4402
|
+
});
|
|
4403
|
+
|
|
4221
4404
|
// src/mcp/ui/ProjectsView.tsx
|
|
4222
|
-
import { useEffect as
|
|
4405
|
+
import { useEffect as useEffect3, useMemo as useMemo3, useState as useState3 } from "react";
|
|
4223
4406
|
import { Box as Box4, Text as Text4, useInput as useInput2 } from "ink";
|
|
4224
|
-
import { jsx as
|
|
4407
|
+
import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
4225
4408
|
function nextStatus(current) {
|
|
4226
4409
|
const idx = STATUS_CYCLE.indexOf(current || "");
|
|
4227
4410
|
if (idx === -1) return STATUS_CYCLE[0];
|
|
@@ -4230,9 +4413,14 @@ function nextStatus(current) {
|
|
|
4230
4413
|
function projectKey(p) {
|
|
4231
4414
|
return p.sourcePath ?? p.path;
|
|
4232
4415
|
}
|
|
4233
|
-
function formatProjectLabel(p) {
|
|
4416
|
+
function formatProjectLabel(p, drift) {
|
|
4234
4417
|
const root = p.sourcePath ?? p.path;
|
|
4235
|
-
|
|
4418
|
+
const driftLabel = drift?.hasDrift ? " [UPDATE AVAILABLE]" : "";
|
|
4419
|
+
const label = `${p.name} (${p.source})${root ? ` - ${root}` : ""}`;
|
|
4420
|
+
if (drift?.hasDrift) {
|
|
4421
|
+
return `${label} ${driftLabel}`;
|
|
4422
|
+
}
|
|
4423
|
+
return label;
|
|
4236
4424
|
}
|
|
4237
4425
|
var STATUS_CYCLE, ProjectsView;
|
|
4238
4426
|
var init_ProjectsView = __esm({
|
|
@@ -4241,15 +4429,17 @@ var init_ProjectsView = __esm({
|
|
|
4241
4429
|
init_SimpleSelect();
|
|
4242
4430
|
init_config();
|
|
4243
4431
|
init_tasks_fs();
|
|
4432
|
+
init_ConfigContext();
|
|
4244
4433
|
STATUS_CYCLE = ["pending", "in_progress", "blocked", "complete"];
|
|
4245
4434
|
ProjectsView = ({ config: initialConfig, projects: allProjects, onConfigChange }) => {
|
|
4246
|
-
const
|
|
4247
|
-
const [
|
|
4248
|
-
const [
|
|
4249
|
-
const [
|
|
4250
|
-
const [
|
|
4251
|
-
const [
|
|
4252
|
-
const
|
|
4435
|
+
const { driftReports, checkAllDrift } = useConfig();
|
|
4436
|
+
const [config, setConfig] = useState3(initialConfig);
|
|
4437
|
+
const [mode, setMode] = useState3("expose");
|
|
4438
|
+
const [expanded, setExpanded] = useState3(() => /* @__PURE__ */ new Set());
|
|
4439
|
+
const [selectedIndex, setSelectedIndex] = useState3(0);
|
|
4440
|
+
const [taskCache, setTaskCache] = useState3({});
|
|
4441
|
+
const [errorLine, setErrorLine] = useState3(null);
|
|
4442
|
+
const sortedProjects = useMemo3(() => {
|
|
4253
4443
|
return [...allProjects].sort((a, b) => {
|
|
4254
4444
|
const byName = a.name.localeCompare(b.name);
|
|
4255
4445
|
if (byName !== 0) return byName;
|
|
@@ -4273,6 +4463,10 @@ var init_ProjectsView = __esm({
|
|
|
4273
4463
|
setMode((prev) => prev === "expose" ? "tasks" : "expose");
|
|
4274
4464
|
return;
|
|
4275
4465
|
}
|
|
4466
|
+
if (input === "u") {
|
|
4467
|
+
checkAllDrift();
|
|
4468
|
+
return;
|
|
4469
|
+
}
|
|
4276
4470
|
if (mode === "expose") {
|
|
4277
4471
|
if (input === "a") {
|
|
4278
4472
|
const newConfig = {
|
|
@@ -4338,27 +4532,28 @@ var init_ProjectsView = __esm({
|
|
|
4338
4532
|
}
|
|
4339
4533
|
}
|
|
4340
4534
|
});
|
|
4341
|
-
|
|
4535
|
+
useEffect3(() => {
|
|
4342
4536
|
setSelectedIndex((prev) => {
|
|
4343
4537
|
if (flattenedRows.length === 0) return 0;
|
|
4344
4538
|
return Math.min(prev, flattenedRows.length - 1);
|
|
4345
4539
|
});
|
|
4346
4540
|
}, [mode, allProjects, expanded, taskCache]);
|
|
4347
|
-
const projectItems =
|
|
4541
|
+
const projectItems = useMemo3(() => {
|
|
4348
4542
|
return allProjects.map((p) => {
|
|
4349
4543
|
const projectConfig = config.projects.find(
|
|
4350
4544
|
(c) => c.path && c.path === p.path || p.source === "global" && c.name === p.name || !c.path && c.name === p.name
|
|
4351
4545
|
);
|
|
4352
4546
|
const isExposed = projectConfig ? projectConfig.expose : config.defaults.includeNew;
|
|
4547
|
+
const drift = driftReports[p.path];
|
|
4353
4548
|
return {
|
|
4354
|
-
label: formatProjectLabel(p),
|
|
4549
|
+
label: formatProjectLabel(p, drift),
|
|
4355
4550
|
value: p.path,
|
|
4356
4551
|
key: p.path,
|
|
4357
4552
|
exposed: isExposed
|
|
4358
4553
|
};
|
|
4359
4554
|
});
|
|
4360
|
-
}, [allProjects, config]);
|
|
4361
|
-
const initialSelected =
|
|
4555
|
+
}, [allProjects, config, driftReports]);
|
|
4556
|
+
const initialSelected = useMemo3(() => {
|
|
4362
4557
|
return projectItems.filter((p) => p.exposed).map((p) => p.value);
|
|
4363
4558
|
}, [projectItems]);
|
|
4364
4559
|
const handleSubmit = (selectedIds) => {
|
|
@@ -4382,7 +4577,7 @@ var init_ProjectsView = __esm({
|
|
|
4382
4577
|
setConfig(newConfig);
|
|
4383
4578
|
onConfigChange?.();
|
|
4384
4579
|
};
|
|
4385
|
-
const flattenedRows =
|
|
4580
|
+
const flattenedRows = useMemo3(() => {
|
|
4386
4581
|
const rows = [];
|
|
4387
4582
|
for (const p of sortedProjects) {
|
|
4388
4583
|
rows.push({ kind: "project", project: p });
|
|
@@ -4403,15 +4598,15 @@ var init_ProjectsView = __esm({
|
|
|
4403
4598
|
if (mode === "expose") {
|
|
4404
4599
|
return /* @__PURE__ */ jsxs3(Box4, { flexDirection: "column", padding: 1, borderStyle: "round", borderColor: "cyan", flexGrow: 1, children: [
|
|
4405
4600
|
/* @__PURE__ */ jsxs3(Box4, { justifyContent: "space-between", children: [
|
|
4406
|
-
/* @__PURE__ */
|
|
4601
|
+
/* @__PURE__ */ jsx5(Text4, { bold: true, color: "cyan", children: " Projects (Expose Mode) " }),
|
|
4407
4602
|
/* @__PURE__ */ jsxs3(Box4, { children: [
|
|
4408
|
-
/* @__PURE__ */
|
|
4409
|
-
/* @__PURE__ */
|
|
4410
|
-
/* @__PURE__ */
|
|
4603
|
+
/* @__PURE__ */ jsx5(Text4, { dimColor: true, children: "Auto-expose new: " }),
|
|
4604
|
+
/* @__PURE__ */ jsx5(Text4, { color: config.defaults.includeNew ? "green" : "red", children: config.defaults.includeNew ? "ON" : "OFF" }),
|
|
4605
|
+
/* @__PURE__ */ jsx5(Text4, { dimColor: true, children: " (Press 'a' to toggle)" })
|
|
4411
4606
|
] })
|
|
4412
4607
|
] }),
|
|
4413
|
-
/* @__PURE__ */
|
|
4414
|
-
/* @__PURE__ */
|
|
4608
|
+
/* @__PURE__ */ jsx5(Text4, { color: "dim", children: " Space toggles, Enter saves. Press 't' to switch to Tasks Mode." }),
|
|
4609
|
+
/* @__PURE__ */ jsx5(Box4, { marginTop: 1, flexDirection: "column", children: /* @__PURE__ */ jsx5(
|
|
4415
4610
|
SimpleSelect,
|
|
4416
4611
|
{
|
|
4417
4612
|
message: "",
|
|
@@ -4430,62 +4625,69 @@ var init_ProjectsView = __esm({
|
|
|
4430
4625
|
}
|
|
4431
4626
|
return /* @__PURE__ */ jsxs3(Box4, { flexDirection: "column", padding: 1, borderStyle: "round", borderColor: "cyan", flexGrow: 1, children: [
|
|
4432
4627
|
/* @__PURE__ */ jsxs3(Box4, { justifyContent: "space-between", children: [
|
|
4433
|
-
/* @__PURE__ */
|
|
4434
|
-
/* @__PURE__ */
|
|
4628
|
+
/* @__PURE__ */ jsx5(Text4, { bold: true, color: "cyan", children: " Projects (Tasks Mode) " }),
|
|
4629
|
+
/* @__PURE__ */ jsx5(Text4, { color: "dim", children: "t:Expose Enter:Expand s:Status u:DriftCheck R:Refresh" })
|
|
4435
4630
|
] }),
|
|
4436
|
-
errorLine && /* @__PURE__ */
|
|
4631
|
+
errorLine && /* @__PURE__ */ jsx5(Box4, { marginTop: 0, children: /* @__PURE__ */ jsx5(Text4, { color: "red", children: errorLine }) }),
|
|
4437
4632
|
/* @__PURE__ */ jsxs3(Box4, { marginTop: 1, flexDirection: "row", flexGrow: 1, children: [
|
|
4438
4633
|
/* @__PURE__ */ jsxs3(Box4, { flexDirection: "column", width: "55%", children: [
|
|
4439
|
-
flattenedRows.length === 0 ? /* @__PURE__ */
|
|
4634
|
+
flattenedRows.length === 0 ? /* @__PURE__ */ jsx5(Text4, { color: "dim", children: "No projects detected." }) : flattenedRows.map((row, idx) => {
|
|
4440
4635
|
const isSel = idx === selectedIndex;
|
|
4441
4636
|
if (row.kind === "project") {
|
|
4442
4637
|
const k = projectKey(row.project);
|
|
4443
4638
|
const isOpen = expanded.has(k);
|
|
4444
4639
|
const count = (taskCache[k] || []).length;
|
|
4445
|
-
|
|
4446
|
-
|
|
4447
|
-
/* @__PURE__ */ jsxs3(
|
|
4448
|
-
|
|
4449
|
-
|
|
4640
|
+
const drift = driftReports[row.project.path];
|
|
4641
|
+
return /* @__PURE__ */ jsxs3(Box4, { flexDirection: "column", children: [
|
|
4642
|
+
/* @__PURE__ */ jsxs3(Box4, { children: [
|
|
4643
|
+
/* @__PURE__ */ jsx5(Text4, { color: isSel ? "cyan" : "white", children: isSel ? "> " : " " }),
|
|
4644
|
+
/* @__PURE__ */ jsxs3(Text4, { color: isSel ? "cyan" : "white", children: [
|
|
4645
|
+
isOpen ? "\u25BE " : "\u25B8 ",
|
|
4646
|
+
formatProjectLabel(row.project, drift)
|
|
4647
|
+
] }),
|
|
4648
|
+
/* @__PURE__ */ jsxs3(Text4, { color: "dim", children: [
|
|
4649
|
+
" ",
|
|
4650
|
+
count > 0 ? ` (tasks: ${count})` : ""
|
|
4651
|
+
] })
|
|
4450
4652
|
] }),
|
|
4451
|
-
/* @__PURE__ */ jsxs3(Text4, { color: "
|
|
4452
|
-
" ",
|
|
4453
|
-
|
|
4454
|
-
] })
|
|
4653
|
+
isSel && drift?.hasDrift && /* @__PURE__ */ jsx5(Box4, { marginLeft: 4, children: /* @__PURE__ */ jsxs3(Text4, { color: "magenta", dimColor: true, italic: true, children: [
|
|
4654
|
+
drift.type === "version" ? "New version available. " : "Modifications detected. ",
|
|
4655
|
+
"Run 'rrce-workflow wizard' to update."
|
|
4656
|
+
] }) })
|
|
4455
4657
|
] }, `p:${k}`);
|
|
4456
4658
|
}
|
|
4457
4659
|
const taskLabel = row.task.title || row.task.task_slug;
|
|
4458
4660
|
const status = row.task.status || "";
|
|
4459
4661
|
return /* @__PURE__ */ jsxs3(Box4, { children: [
|
|
4460
|
-
/* @__PURE__ */
|
|
4461
|
-
/* @__PURE__ */
|
|
4462
|
-
/* @__PURE__ */
|
|
4463
|
-
row.task.task_slug !== "__none__" && /* @__PURE__ */
|
|
4662
|
+
/* @__PURE__ */ jsx5(Text4, { color: isSel ? "cyan" : "white", children: isSel ? "> " : " " }),
|
|
4663
|
+
/* @__PURE__ */ jsx5(Text4, { color: "dim", children: " - " }),
|
|
4664
|
+
/* @__PURE__ */ jsx5(Text4, { color: isSel ? "cyan" : "white", children: taskLabel }),
|
|
4665
|
+
row.task.task_slug !== "__none__" && /* @__PURE__ */ jsx5(Text4, { color: status === "complete" ? "green" : status === "blocked" ? "red" : "yellow", children: ` [${status}]` })
|
|
4464
4666
|
] }, `t:${projectKey(row.project)}:${row.task.task_slug}`);
|
|
4465
4667
|
}),
|
|
4466
|
-
/* @__PURE__ */
|
|
4668
|
+
/* @__PURE__ */ jsx5(Box4, { marginTop: 1, children: /* @__PURE__ */ jsx5(Text4, { color: "gray", children: "\u25B2/\u25BC navigate \u2022 Enter expand/collapse \u2022 s cycle status \u2022 R refresh \u2022 t expose mode" }) })
|
|
4467
4669
|
] }),
|
|
4468
|
-
/* @__PURE__ */
|
|
4469
|
-
/* @__PURE__ */
|
|
4470
|
-
selectedTask.summary && /* @__PURE__ */
|
|
4670
|
+
/* @__PURE__ */ jsx5(Box4, { flexDirection: "column", width: "45%", paddingLeft: 2, children: !selectedTask ? /* @__PURE__ */ jsx5(Text4, { color: "dim", children: "Select a task to view details." }) : /* @__PURE__ */ jsxs3(Box4, { flexDirection: "column", children: [
|
|
4671
|
+
/* @__PURE__ */ jsx5(Text4, { bold: true, color: "cyan", children: selectedTask.title || selectedTask.task_slug }),
|
|
4672
|
+
selectedTask.summary && /* @__PURE__ */ jsx5(Text4, { children: selectedTask.summary }),
|
|
4471
4673
|
/* @__PURE__ */ jsxs3(Box4, { marginTop: 1, flexDirection: "column", children: [
|
|
4472
4674
|
/* @__PURE__ */ jsxs3(Text4, { children: [
|
|
4473
|
-
/* @__PURE__ */
|
|
4474
|
-
/* @__PURE__ */
|
|
4675
|
+
/* @__PURE__ */ jsx5(Text4, { color: "dim", children: "Status: " }),
|
|
4676
|
+
/* @__PURE__ */ jsx5(Text4, { children: selectedTask.status || "unknown" })
|
|
4475
4677
|
] }),
|
|
4476
4678
|
/* @__PURE__ */ jsxs3(Text4, { children: [
|
|
4477
|
-
/* @__PURE__ */
|
|
4478
|
-
/* @__PURE__ */
|
|
4679
|
+
/* @__PURE__ */ jsx5(Text4, { color: "dim", children: "Updated: " }),
|
|
4680
|
+
/* @__PURE__ */ jsx5(Text4, { children: selectedTask.updated_at || "\u2014" })
|
|
4479
4681
|
] }),
|
|
4480
4682
|
/* @__PURE__ */ jsxs3(Text4, { children: [
|
|
4481
|
-
/* @__PURE__ */
|
|
4482
|
-
/* @__PURE__ */
|
|
4683
|
+
/* @__PURE__ */ jsx5(Text4, { color: "dim", children: "Tags: " }),
|
|
4684
|
+
/* @__PURE__ */ jsx5(Text4, { children: (selectedTask.tags || []).join(", ") || "\u2014" })
|
|
4483
4685
|
] })
|
|
4484
4686
|
] }),
|
|
4485
4687
|
/* @__PURE__ */ jsxs3(Box4, { marginTop: 1, flexDirection: "column", children: [
|
|
4486
|
-
/* @__PURE__ */
|
|
4487
|
-
(selectedTask.checklist || []).length === 0 ? /* @__PURE__ */
|
|
4488
|
-
/* @__PURE__ */
|
|
4688
|
+
/* @__PURE__ */ jsx5(Text4, { bold: true, children: "Checklist" }),
|
|
4689
|
+
(selectedTask.checklist || []).length === 0 ? /* @__PURE__ */ jsx5(Text4, { color: "dim", children: "\u2014" }) : (selectedTask.checklist || []).slice(0, 12).map((c, i) => /* @__PURE__ */ jsxs3(Text4, { children: [
|
|
4690
|
+
/* @__PURE__ */ jsx5(Text4, { color: "dim", children: "- " }),
|
|
4489
4691
|
c.label || c.id || "item",
|
|
4490
4692
|
" ",
|
|
4491
4693
|
/* @__PURE__ */ jsxs3(Text4, { color: "dim", children: [
|
|
@@ -4496,8 +4698,8 @@ var init_ProjectsView = __esm({
|
|
|
4496
4698
|
] }, c.id || i))
|
|
4497
4699
|
] }),
|
|
4498
4700
|
/* @__PURE__ */ jsxs3(Box4, { marginTop: 1, flexDirection: "column", children: [
|
|
4499
|
-
/* @__PURE__ */
|
|
4500
|
-
!selectedTask.agents ? /* @__PURE__ */
|
|
4701
|
+
/* @__PURE__ */ jsx5(Text4, { bold: true, children: "Agents" }),
|
|
4702
|
+
!selectedTask.agents ? /* @__PURE__ */ jsx5(Text4, { color: "dim", children: "\u2014" }) : Object.entries(selectedTask.agents).map(([agent, info]) => /* @__PURE__ */ jsxs3(Text4, { children: [
|
|
4501
4703
|
/* @__PURE__ */ jsxs3(Text4, { color: "dim", children: [
|
|
4502
4704
|
"- ",
|
|
4503
4705
|
agent,
|
|
@@ -4515,9 +4717,9 @@ var init_ProjectsView = __esm({
|
|
|
4515
4717
|
});
|
|
4516
4718
|
|
|
4517
4719
|
// src/mcp/ui/components/InstallWizard.tsx
|
|
4518
|
-
import { useState as
|
|
4720
|
+
import { useState as useState4 } from "react";
|
|
4519
4721
|
import { Box as Box5, Text as Text5 } from "ink";
|
|
4520
|
-
import { jsx as
|
|
4722
|
+
import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
4521
4723
|
var InstallWizard;
|
|
4522
4724
|
var init_InstallWizard = __esm({
|
|
4523
4725
|
"src/mcp/ui/components/InstallWizard.tsx"() {
|
|
@@ -4525,8 +4727,8 @@ var init_InstallWizard = __esm({
|
|
|
4525
4727
|
init_SimpleSelect();
|
|
4526
4728
|
init_install();
|
|
4527
4729
|
InstallWizard = ({ workspacePath, onComplete, onCancel }) => {
|
|
4528
|
-
const [status, setStatus] =
|
|
4529
|
-
const [message, setMessage] =
|
|
4730
|
+
const [status, setStatus] = useState4(checkInstallStatus(workspacePath));
|
|
4731
|
+
const [message, setMessage] = useState4("");
|
|
4530
4732
|
const options = [
|
|
4531
4733
|
{
|
|
4532
4734
|
value: "opencode",
|
|
@@ -4577,8 +4779,8 @@ var init_InstallWizard = __esm({
|
|
|
4577
4779
|
}, 2e3);
|
|
4578
4780
|
};
|
|
4579
4781
|
return /* @__PURE__ */ jsxs4(Box5, { flexDirection: "column", children: [
|
|
4580
|
-
message && /* @__PURE__ */
|
|
4581
|
-
/* @__PURE__ */
|
|
4782
|
+
message && /* @__PURE__ */ jsx6(Text5, { color: "green", children: message }),
|
|
4783
|
+
/* @__PURE__ */ jsx6(
|
|
4582
4784
|
SimpleSelect,
|
|
4583
4785
|
{
|
|
4584
4786
|
message: "Select integrations to install:",
|
|
@@ -4603,7 +4805,7 @@ var init_InstallWizard = __esm({
|
|
|
4603
4805
|
// src/mcp/ui/InstallView.tsx
|
|
4604
4806
|
import "react";
|
|
4605
4807
|
import { Box as Box6, Text as Text6 } from "ink";
|
|
4606
|
-
import { jsx as
|
|
4808
|
+
import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
4607
4809
|
var InstallView;
|
|
4608
4810
|
var init_InstallView = __esm({
|
|
4609
4811
|
"src/mcp/ui/InstallView.tsx"() {
|
|
@@ -4613,9 +4815,9 @@ var init_InstallView = __esm({
|
|
|
4613
4815
|
InstallView = () => {
|
|
4614
4816
|
const workspacePath = detectWorkspaceRoot();
|
|
4615
4817
|
return /* @__PURE__ */ jsxs5(Box6, { flexDirection: "column", padding: 1, borderStyle: "round", borderColor: "magenta", flexGrow: 1, children: [
|
|
4616
|
-
/* @__PURE__ */
|
|
4617
|
-
/* @__PURE__ */
|
|
4618
|
-
/* @__PURE__ */
|
|
4818
|
+
/* @__PURE__ */ jsx7(Text6, { bold: true, color: "magenta", children: " Installation & Configuration " }),
|
|
4819
|
+
/* @__PURE__ */ jsx7(Text6, { color: "dim", children: " Configure IDE integrations for OpenCode, VSCode, Claude, and Antigravity." }),
|
|
4820
|
+
/* @__PURE__ */ jsx7(Box6, { marginTop: 1, flexDirection: "column", children: /* @__PURE__ */ jsx7(
|
|
4619
4821
|
InstallWizard,
|
|
4620
4822
|
{
|
|
4621
4823
|
workspacePath,
|
|
@@ -4633,7 +4835,7 @@ var init_InstallView = __esm({
|
|
|
4633
4835
|
// src/mcp/ui/LogViewer.tsx
|
|
4634
4836
|
import "react";
|
|
4635
4837
|
import { Box as Box7, Text as Text7 } from "ink";
|
|
4636
|
-
import { jsx as
|
|
4838
|
+
import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
4637
4839
|
var LogViewer;
|
|
4638
4840
|
var init_LogViewer = __esm({
|
|
4639
4841
|
"src/mcp/ui/LogViewer.tsx"() {
|
|
@@ -4643,16 +4845,16 @@ var init_LogViewer = __esm({
|
|
|
4643
4845
|
const emptyLines = Math.max(0, height - visibleLogs.length);
|
|
4644
4846
|
const padding = Array(emptyLines).fill("");
|
|
4645
4847
|
const formatLog = (log) => {
|
|
4646
|
-
if (log.includes("[RAG]")) return /* @__PURE__ */
|
|
4647
|
-
if (log.includes("[ERROR]")) return /* @__PURE__ */
|
|
4648
|
-
if (log.includes("[WARN]")) return /* @__PURE__ */
|
|
4649
|
-
if (log.includes("[INFO]")) return /* @__PURE__ */
|
|
4650
|
-
if (log.includes("Success")) return /* @__PURE__ */
|
|
4651
|
-
return /* @__PURE__ */
|
|
4848
|
+
if (log.includes("[RAG]")) return /* @__PURE__ */ jsx8(Text7, { color: "cyan", children: log });
|
|
4849
|
+
if (log.includes("[ERROR]")) return /* @__PURE__ */ jsx8(Text7, { color: "red", children: log });
|
|
4850
|
+
if (log.includes("[WARN]")) return /* @__PURE__ */ jsx8(Text7, { color: "yellow", children: log });
|
|
4851
|
+
if (log.includes("[INFO]")) return /* @__PURE__ */ jsx8(Text7, { color: "green", children: log });
|
|
4852
|
+
if (log.includes("Success")) return /* @__PURE__ */ jsx8(Text7, { color: "green", children: log });
|
|
4853
|
+
return /* @__PURE__ */ jsx8(Text7, { children: log });
|
|
4652
4854
|
};
|
|
4653
4855
|
return /* @__PURE__ */ jsxs6(Box7, { flexDirection: "column", borderStyle: "round", borderColor: "dim", paddingX: 1, height: height + 2, flexGrow: 1, children: [
|
|
4654
|
-
padding.map((_, i) => /* @__PURE__ */
|
|
4655
|
-
visibleLogs.map((log, i) => /* @__PURE__ */
|
|
4856
|
+
padding.map((_, i) => /* @__PURE__ */ jsx8(Text7, { children: " " }, `empty-${i}`)),
|
|
4857
|
+
visibleLogs.map((log, i) => /* @__PURE__ */ jsx8(Box7, { children: formatLog(log) }, `log-${i}`))
|
|
4656
4858
|
] });
|
|
4657
4859
|
};
|
|
4658
4860
|
}
|
|
@@ -4661,35 +4863,40 @@ var init_LogViewer = __esm({
|
|
|
4661
4863
|
// src/mcp/ui/StatusBoard.tsx
|
|
4662
4864
|
import "react";
|
|
4663
4865
|
import { Box as Box8, Text as Text8 } from "ink";
|
|
4664
|
-
import { jsx as
|
|
4866
|
+
import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
4665
4867
|
var StatusBoard;
|
|
4666
4868
|
var init_StatusBoard = __esm({
|
|
4667
4869
|
"src/mcp/ui/StatusBoard.tsx"() {
|
|
4668
4870
|
"use strict";
|
|
4669
|
-
StatusBoard = ({ exposedLabel, port, pid, running }) => {
|
|
4670
|
-
return /* @__PURE__ */
|
|
4671
|
-
running ? /* @__PURE__ */
|
|
4871
|
+
StatusBoard = ({ exposedLabel, port, pid, running, hasDrift }) => {
|
|
4872
|
+
return /* @__PURE__ */ jsx9(Box8, { borderStyle: "single", borderColor: "cyan", paddingX: 1, flexGrow: 1, children: /* @__PURE__ */ jsxs7(Text8, { children: [
|
|
4873
|
+
running ? /* @__PURE__ */ jsx9(Text8, { color: "green", children: "\u25CF RUNNING" }) : /* @__PURE__ */ jsx9(Text8, { color: "red", children: "\u25CF STOPPED" }),
|
|
4672
4874
|
" ",
|
|
4673
4875
|
"\u2502",
|
|
4674
4876
|
" \u{1F4CB} ",
|
|
4675
|
-
/* @__PURE__ */
|
|
4877
|
+
/* @__PURE__ */ jsx9(Text8, { color: "yellow", children: exposedLabel }),
|
|
4676
4878
|
" ",
|
|
4677
4879
|
"\u2502",
|
|
4678
4880
|
" Port: ",
|
|
4679
|
-
/* @__PURE__ */
|
|
4881
|
+
/* @__PURE__ */ jsx9(Text8, { color: "green", children: port }),
|
|
4680
4882
|
" ",
|
|
4681
4883
|
"\u2502",
|
|
4682
4884
|
" PID: ",
|
|
4683
|
-
/* @__PURE__ */
|
|
4885
|
+
/* @__PURE__ */ jsx9(Text8, { color: "green", children: pid }),
|
|
4886
|
+
hasDrift && /* @__PURE__ */ jsxs7(Text8, { color: "magenta", bold: true, children: [
|
|
4887
|
+
" ",
|
|
4888
|
+
"\u2502",
|
|
4889
|
+
" \u2B06 UPDATE AVAILABLE"
|
|
4890
|
+
] })
|
|
4684
4891
|
] }) });
|
|
4685
4892
|
};
|
|
4686
4893
|
}
|
|
4687
4894
|
});
|
|
4688
4895
|
|
|
4689
4896
|
// src/mcp/ui/IndexingStatus.tsx
|
|
4690
|
-
import { useState as
|
|
4897
|
+
import { useState as useState5, useEffect as useEffect5 } from "react";
|
|
4691
4898
|
import { Box as Box9, Text as Text9 } from "ink";
|
|
4692
|
-
import { jsx as
|
|
4899
|
+
import { jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
4693
4900
|
var IndexingStatus;
|
|
4694
4901
|
var init_IndexingStatus = __esm({
|
|
4695
4902
|
"src/mcp/ui/IndexingStatus.tsx"() {
|
|
@@ -4699,9 +4906,9 @@ var init_IndexingStatus = __esm({
|
|
|
4699
4906
|
init_resources();
|
|
4700
4907
|
init_config_utils();
|
|
4701
4908
|
IndexingStatus = ({ projects, config }) => {
|
|
4702
|
-
const [stats, setStats] =
|
|
4703
|
-
const [loading, setLoading] =
|
|
4704
|
-
|
|
4909
|
+
const [stats, setStats] = useState5([]);
|
|
4910
|
+
const [loading, setLoading] = useState5(true);
|
|
4911
|
+
useEffect5(() => {
|
|
4705
4912
|
const fetchStats = async () => {
|
|
4706
4913
|
const newStats = [];
|
|
4707
4914
|
for (const project of projects) {
|
|
@@ -4763,27 +4970,27 @@ var init_IndexingStatus = __esm({
|
|
|
4763
4970
|
return () => clearInterval(interval);
|
|
4764
4971
|
}, [projects, config]);
|
|
4765
4972
|
if (loading && stats.length === 0) {
|
|
4766
|
-
return /* @__PURE__ */
|
|
4973
|
+
return /* @__PURE__ */ jsx10(Text9, { children: "Loading indexing status..." });
|
|
4767
4974
|
}
|
|
4768
4975
|
return /* @__PURE__ */ jsxs8(Box9, { flexDirection: "column", padding: 1, borderStyle: "round", borderColor: "blue", flexGrow: 1, children: [
|
|
4769
|
-
/* @__PURE__ */
|
|
4976
|
+
/* @__PURE__ */ jsx10(Text9, { bold: true, color: "blue", children: " RAG Indexing Status " }),
|
|
4770
4977
|
/* @__PURE__ */ jsxs8(Box9, { marginTop: 1, flexDirection: "column", children: [
|
|
4771
4978
|
/* @__PURE__ */ jsxs8(Box9, { children: [
|
|
4772
|
-
/* @__PURE__ */
|
|
4773
|
-
/* @__PURE__ */
|
|
4774
|
-
/* @__PURE__ */
|
|
4775
|
-
/* @__PURE__ */
|
|
4776
|
-
/* @__PURE__ */
|
|
4777
|
-
/* @__PURE__ */
|
|
4778
|
-
/* @__PURE__ */
|
|
4979
|
+
/* @__PURE__ */ jsx10(Box9, { width: 25, children: /* @__PURE__ */ jsx10(Text9, { underline: true, children: "Project" }) }),
|
|
4980
|
+
/* @__PURE__ */ jsx10(Box9, { width: 15, children: /* @__PURE__ */ jsx10(Text9, { underline: true, children: "Status" }) }),
|
|
4981
|
+
/* @__PURE__ */ jsx10(Box9, { width: 15, children: /* @__PURE__ */ jsx10(Text9, { underline: true, children: "State" }) }),
|
|
4982
|
+
/* @__PURE__ */ jsx10(Box9, { width: 18, children: /* @__PURE__ */ jsx10(Text9, { underline: true, children: "Progress" }) }),
|
|
4983
|
+
/* @__PURE__ */ jsx10(Box9, { width: 15, children: /* @__PURE__ */ jsx10(Text9, { underline: true, children: "Indexed Files" }) }),
|
|
4984
|
+
/* @__PURE__ */ jsx10(Box9, { width: 15, children: /* @__PURE__ */ jsx10(Text9, { underline: true, children: "Total Chunks" }) }),
|
|
4985
|
+
/* @__PURE__ */ jsx10(Box9, { children: /* @__PURE__ */ jsx10(Text9, { underline: true, children: "Last Index" }) })
|
|
4779
4986
|
] }),
|
|
4780
|
-
stats.length === 0 ? /* @__PURE__ */
|
|
4781
|
-
/* @__PURE__ */
|
|
4782
|
-
/* @__PURE__ */
|
|
4783
|
-
/* @__PURE__ */
|
|
4784
|
-
/* @__PURE__ */
|
|
4785
|
-
/* @__PURE__ */
|
|
4786
|
-
/* @__PURE__ */
|
|
4987
|
+
stats.length === 0 ? /* @__PURE__ */ jsx10(Text9, { color: "dim", children: "No exposed projects found." }) : stats.map((s) => /* @__PURE__ */ jsxs8(Box9, { marginTop: 0, children: [
|
|
4988
|
+
/* @__PURE__ */ jsx10(Box9, { width: 25, children: /* @__PURE__ */ jsx10(Text9, { color: "white", children: s.projectName }) }),
|
|
4989
|
+
/* @__PURE__ */ jsx10(Box9, { width: 15, children: /* @__PURE__ */ jsx10(Text9, { color: s.state === "running" ? "yellow" : s.state === "failed" ? "red" : s.enabled ? "green" : "dim", children: s.enabled ? s.state : "disabled" }) }),
|
|
4990
|
+
/* @__PURE__ */ jsx10(Box9, { width: 18, children: /* @__PURE__ */ jsx10(Text9, { children: s.state === "running" ? `${s.itemsDone}/${s.itemsTotal ?? "?"}` : "-" }) }),
|
|
4991
|
+
/* @__PURE__ */ jsx10(Box9, { width: 15, children: /* @__PURE__ */ jsx10(Text9, { children: s.enabled ? s.totalFiles : "-" }) }),
|
|
4992
|
+
/* @__PURE__ */ jsx10(Box9, { width: 15, children: /* @__PURE__ */ jsx10(Text9, { children: s.enabled ? s.totalChunks : "-" }) }),
|
|
4993
|
+
/* @__PURE__ */ jsx10(Box9, { children: /* @__PURE__ */ jsx10(Text9, { children: s.lastFullIndex ? new Date(s.lastFullIndex).toLocaleTimeString() : "-" }) })
|
|
4787
4994
|
] }, s.projectName))
|
|
4788
4995
|
] })
|
|
4789
4996
|
] });
|
|
@@ -4794,7 +5001,7 @@ var init_IndexingStatus = __esm({
|
|
|
4794
5001
|
// src/mcp/ui/components/TabBar.tsx
|
|
4795
5002
|
import "react";
|
|
4796
5003
|
import { Box as Box10, Text as Text10, useInput as useInput3 } from "ink";
|
|
4797
|
-
import { jsx as
|
|
5004
|
+
import { jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
4798
5005
|
var TabBar;
|
|
4799
5006
|
var init_TabBar = __esm({
|
|
4800
5007
|
"src/mcp/ui/components/TabBar.tsx"() {
|
|
@@ -4824,7 +5031,7 @@ var init_TabBar = __esm({
|
|
|
4824
5031
|
return /* @__PURE__ */ jsxs9(Box10, { borderStyle: "single", paddingX: 1, borderColor: "gray", children: [
|
|
4825
5032
|
tabs.map((tab, index) => {
|
|
4826
5033
|
const isActive = tab.id === activeTab;
|
|
4827
|
-
return /* @__PURE__ */
|
|
5034
|
+
return /* @__PURE__ */ jsx11(Box10, { marginRight: 2, children: /* @__PURE__ */ jsx11(
|
|
4828
5035
|
Text10,
|
|
4829
5036
|
{
|
|
4830
5037
|
color: isActive ? "cyan" : "white",
|
|
@@ -4834,8 +5041,8 @@ var init_TabBar = __esm({
|
|
|
4834
5041
|
}
|
|
4835
5042
|
) }, tab.id);
|
|
4836
5043
|
}),
|
|
4837
|
-
/* @__PURE__ */
|
|
4838
|
-
/* @__PURE__ */
|
|
5044
|
+
/* @__PURE__ */ jsx11(Box10, { flexGrow: 1 }),
|
|
5045
|
+
/* @__PURE__ */ jsx11(Text10, { color: "dim", children: "Use \u25C4/\u25BA arrows to navigate" })
|
|
4839
5046
|
] });
|
|
4840
5047
|
};
|
|
4841
5048
|
}
|
|
@@ -4846,10 +5053,10 @@ var App_exports = {};
|
|
|
4846
5053
|
__export(App_exports, {
|
|
4847
5054
|
App: () => App
|
|
4848
5055
|
});
|
|
4849
|
-
import { useState as
|
|
5056
|
+
import { useState as useState6, useEffect as useEffect6, useMemo as useMemo4, useCallback as useCallback3 } from "react";
|
|
4850
5057
|
import { Box as Box11, useInput as useInput4, useApp } from "ink";
|
|
4851
|
-
import
|
|
4852
|
-
import { jsx as
|
|
5058
|
+
import fs20 from "fs";
|
|
5059
|
+
import { jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
4853
5060
|
var App;
|
|
4854
5061
|
var init_App = __esm({
|
|
4855
5062
|
"src/mcp/ui/App.tsx"() {
|
|
@@ -4869,32 +5076,28 @@ var init_App = __esm({
|
|
|
4869
5076
|
init_resources();
|
|
4870
5077
|
init_install();
|
|
4871
5078
|
init_paths();
|
|
5079
|
+
init_ConfigContext();
|
|
4872
5080
|
App = ({ onExit, initialPort }) => {
|
|
4873
5081
|
const { exit } = useApp();
|
|
4874
|
-
const
|
|
4875
|
-
const [
|
|
4876
|
-
const [
|
|
5082
|
+
const { config, projects, exposedProjects, driftReports, refresh: refreshData } = useConfig();
|
|
5083
|
+
const [activeTab, setActiveTab] = useState6("overview");
|
|
5084
|
+
const [logs, setLogs] = useState6([]);
|
|
5085
|
+
const [serverInfo, setServerInfo] = useState6({
|
|
4877
5086
|
port: initialPort,
|
|
4878
5087
|
pid: process.pid,
|
|
4879
5088
|
running: false
|
|
4880
5089
|
});
|
|
4881
|
-
const
|
|
4882
|
-
const [projects, setProjects] = useState5(() => scanForProjects());
|
|
4883
|
-
const refreshData = useCallback(() => {
|
|
4884
|
-
setConfig(loadMCPConfig());
|
|
4885
|
-
setProjects(scanForProjects());
|
|
4886
|
-
}, []);
|
|
4887
|
-
const exposedProjects = useMemo3(
|
|
4888
|
-
() => projects.filter((p) => isProjectExposed(config, p.name, p.path)),
|
|
4889
|
-
[projects, config]
|
|
4890
|
-
);
|
|
4891
|
-
const isRAGEnabled = useMemo3(() => {
|
|
5090
|
+
const isRAGEnabled = useMemo4(() => {
|
|
4892
5091
|
return exposedProjects.some((p) => {
|
|
4893
5092
|
const cfg = findProjectConfig(config, { name: p.name, path: p.path });
|
|
4894
5093
|
return cfg?.semanticSearch?.enabled || p.semanticSearchEnabled;
|
|
4895
5094
|
});
|
|
4896
5095
|
}, [exposedProjects, config]);
|
|
4897
|
-
const
|
|
5096
|
+
const hasAnyDrift = useMemo4(
|
|
5097
|
+
() => Object.values(driftReports).some((r) => r.hasDrift),
|
|
5098
|
+
[driftReports]
|
|
5099
|
+
);
|
|
5100
|
+
const tabs = useMemo4(() => {
|
|
4898
5101
|
const baseTabs = [
|
|
4899
5102
|
{ id: "overview", label: "Overview" },
|
|
4900
5103
|
{ id: "logs", label: "Logs" },
|
|
@@ -4914,7 +5117,7 @@ var init_App = __esm({
|
|
|
4914
5117
|
installStatus.vscodeGlobal,
|
|
4915
5118
|
installStatus.vscodeWorkspace
|
|
4916
5119
|
].filter(Boolean).length;
|
|
4917
|
-
|
|
5120
|
+
useEffect6(() => {
|
|
4918
5121
|
const start = async () => {
|
|
4919
5122
|
const status = getMCPServerStatus();
|
|
4920
5123
|
if (!status.running) {
|
|
@@ -4930,21 +5133,21 @@ var init_App = __esm({
|
|
|
4930
5133
|
};
|
|
4931
5134
|
start();
|
|
4932
5135
|
}, []);
|
|
4933
|
-
|
|
5136
|
+
useEffect6(() => {
|
|
4934
5137
|
const logPath = getLogFilePath();
|
|
4935
5138
|
let lastSize = 0;
|
|
4936
|
-
if (
|
|
4937
|
-
const stats =
|
|
5139
|
+
if (fs20.existsSync(logPath)) {
|
|
5140
|
+
const stats = fs20.statSync(logPath);
|
|
4938
5141
|
lastSize = stats.size;
|
|
4939
5142
|
}
|
|
4940
5143
|
const interval = setInterval(() => {
|
|
4941
|
-
if (
|
|
4942
|
-
const stats =
|
|
5144
|
+
if (fs20.existsSync(logPath)) {
|
|
5145
|
+
const stats = fs20.statSync(logPath);
|
|
4943
5146
|
if (stats.size > lastSize) {
|
|
4944
5147
|
const buffer = Buffer.alloc(stats.size - lastSize);
|
|
4945
|
-
const fd =
|
|
4946
|
-
|
|
4947
|
-
|
|
5148
|
+
const fd = fs20.openSync(logPath, "r");
|
|
5149
|
+
fs20.readSync(fd, buffer, 0, buffer.length, lastSize);
|
|
5150
|
+
fs20.closeSync(fd);
|
|
4948
5151
|
const newContent = buffer.toString("utf-8");
|
|
4949
5152
|
const newLines = newContent.split("\n").filter((l) => l.trim());
|
|
4950
5153
|
setLogs((prev) => {
|
|
@@ -4978,13 +5181,13 @@ var init_App = __esm({
|
|
|
4978
5181
|
});
|
|
4979
5182
|
const termHeight = process.stdout.rows || 24;
|
|
4980
5183
|
const contentHeight = termHeight - 8;
|
|
4981
|
-
const handleConfigChange =
|
|
5184
|
+
const handleConfigChange = useCallback3(() => {
|
|
4982
5185
|
refreshData();
|
|
4983
5186
|
}, [refreshData]);
|
|
4984
5187
|
return /* @__PURE__ */ jsxs10(Box11, { flexDirection: "column", padding: 0, height: termHeight, children: [
|
|
4985
|
-
/* @__PURE__ */
|
|
5188
|
+
/* @__PURE__ */ jsx12(TabBar, { tabs, activeTab, onChange: setActiveTab }),
|
|
4986
5189
|
/* @__PURE__ */ jsxs10(Box11, { marginTop: 1, flexGrow: 1, children: [
|
|
4987
|
-
activeTab === "overview" && /* @__PURE__ */
|
|
5190
|
+
activeTab === "overview" && /* @__PURE__ */ jsx12(
|
|
4988
5191
|
Overview,
|
|
4989
5192
|
{
|
|
4990
5193
|
serverStatus: serverInfo,
|
|
@@ -4995,18 +5198,19 @@ var init_App = __esm({
|
|
|
4995
5198
|
}
|
|
4996
5199
|
}
|
|
4997
5200
|
),
|
|
4998
|
-
activeTab === "projects" && /* @__PURE__ */
|
|
4999
|
-
activeTab === "indexing" && /* @__PURE__ */
|
|
5000
|
-
activeTab === "install" && /* @__PURE__ */
|
|
5001
|
-
activeTab === "logs" && /* @__PURE__ */
|
|
5201
|
+
activeTab === "projects" && /* @__PURE__ */ jsx12(ProjectsView, { config, projects, onConfigChange: handleConfigChange }),
|
|
5202
|
+
activeTab === "indexing" && /* @__PURE__ */ jsx12(IndexingStatus, { config, projects: exposedProjects }),
|
|
5203
|
+
activeTab === "install" && /* @__PURE__ */ jsx12(InstallView, {}),
|
|
5204
|
+
activeTab === "logs" && /* @__PURE__ */ jsx12(LogViewer, { logs, height: contentHeight })
|
|
5002
5205
|
] }),
|
|
5003
|
-
/* @__PURE__ */
|
|
5206
|
+
/* @__PURE__ */ jsx12(Box11, { marginTop: 0, children: /* @__PURE__ */ jsx12(
|
|
5004
5207
|
StatusBoard,
|
|
5005
5208
|
{
|
|
5006
5209
|
exposedLabel: `${exposedProjects.length} / ${projects.length} projects`,
|
|
5007
5210
|
port: serverInfo.port,
|
|
5008
5211
|
pid: serverInfo.pid,
|
|
5009
|
-
running: serverInfo.running
|
|
5212
|
+
running: serverInfo.running,
|
|
5213
|
+
hasDrift: hasAnyDrift
|
|
5010
5214
|
}
|
|
5011
5215
|
) })
|
|
5012
5216
|
] });
|
|
@@ -5017,9 +5221,10 @@ var init_App = __esm({
|
|
|
5017
5221
|
// src/mcp/commands/start.ts
|
|
5018
5222
|
import { confirm as confirm3, isCancel as isCancel5, text } from "@clack/prompts";
|
|
5019
5223
|
async function handleStartServer() {
|
|
5020
|
-
const
|
|
5224
|
+
const React13 = await import("react");
|
|
5021
5225
|
const { render } = await import("ink");
|
|
5022
5226
|
const { App: App2 } = await Promise.resolve().then(() => (init_App(), App_exports));
|
|
5227
|
+
const { ConfigProvider: ConfigProvider2 } = await Promise.resolve().then(() => (init_ConfigContext(), ConfigContext_exports));
|
|
5023
5228
|
const config = loadMCPConfig();
|
|
5024
5229
|
const projects = scanForProjects();
|
|
5025
5230
|
const exposedProjects = projects.filter((p) => {
|
|
@@ -5058,13 +5263,20 @@ async function handleStartServer() {
|
|
|
5058
5263
|
}
|
|
5059
5264
|
}
|
|
5060
5265
|
process.stdin.resume();
|
|
5061
|
-
const app = render(
|
|
5062
|
-
|
|
5063
|
-
|
|
5266
|
+
const app = render(
|
|
5267
|
+
React13.createElement(
|
|
5268
|
+
ConfigProvider2,
|
|
5269
|
+
null,
|
|
5270
|
+
React13.createElement(App2, {
|
|
5271
|
+
initialPort,
|
|
5272
|
+
onExit: () => {
|
|
5273
|
+
}
|
|
5274
|
+
})
|
|
5275
|
+
),
|
|
5276
|
+
{
|
|
5277
|
+
exitOnCtrlC: false
|
|
5064
5278
|
}
|
|
5065
|
-
|
|
5066
|
-
exitOnCtrlC: false
|
|
5067
|
-
});
|
|
5279
|
+
);
|
|
5068
5280
|
await app.waitUntilExit();
|
|
5069
5281
|
console.clear();
|
|
5070
5282
|
}
|
|
@@ -5155,7 +5367,7 @@ var init_mcp = __esm({
|
|
|
5155
5367
|
// src/commands/wizard/index.ts
|
|
5156
5368
|
import { intro as intro2, select as select5, spinner as spinner7, note as note11, outro as outro7, isCancel as isCancel12 } from "@clack/prompts";
|
|
5157
5369
|
import pc13 from "picocolors";
|
|
5158
|
-
import * as
|
|
5370
|
+
import * as fs25 from "fs";
|
|
5159
5371
|
|
|
5160
5372
|
// src/lib/git.ts
|
|
5161
5373
|
import { execSync } from "child_process";
|
|
@@ -5303,6 +5515,7 @@ import { stringify as stringify2 } from "yaml";
|
|
|
5303
5515
|
init_paths();
|
|
5304
5516
|
import * as fs7 from "fs";
|
|
5305
5517
|
import * as path8 from "path";
|
|
5518
|
+
import * as os2 from "os";
|
|
5306
5519
|
import "yaml";
|
|
5307
5520
|
function copyPromptsToDir(prompts, targetDir, extension) {
|
|
5308
5521
|
for (const prompt of prompts) {
|
|
@@ -5313,6 +5526,33 @@ function copyPromptsToDir(prompts, targetDir, extension) {
|
|
|
5313
5526
|
fs7.writeFileSync(targetPath, content);
|
|
5314
5527
|
}
|
|
5315
5528
|
}
|
|
5529
|
+
function updateOpenCodeConfig(newAgents) {
|
|
5530
|
+
const opencodePath = path8.join(os2.homedir(), ".config", "opencode", "opencode.json");
|
|
5531
|
+
if (!fs7.existsSync(opencodePath)) {
|
|
5532
|
+
return;
|
|
5533
|
+
}
|
|
5534
|
+
try {
|
|
5535
|
+
const config = JSON.parse(fs7.readFileSync(opencodePath, "utf8"));
|
|
5536
|
+
if (!config.agents) {
|
|
5537
|
+
config.agents = {};
|
|
5538
|
+
}
|
|
5539
|
+
const existingAgentKeys = Object.keys(config.agents);
|
|
5540
|
+
const rrceKeys = existingAgentKeys.filter((key) => key.startsWith("rrce_"));
|
|
5541
|
+
for (const key of rrceKeys) {
|
|
5542
|
+
if (!newAgents[key]) {
|
|
5543
|
+
delete config.agents[key];
|
|
5544
|
+
}
|
|
5545
|
+
}
|
|
5546
|
+
for (const [key, value] of Object.entries(newAgents)) {
|
|
5547
|
+
if (key.startsWith("rrce_")) {
|
|
5548
|
+
config.agents[key] = value;
|
|
5549
|
+
}
|
|
5550
|
+
}
|
|
5551
|
+
fs7.writeFileSync(opencodePath, JSON.stringify(config, null, 2));
|
|
5552
|
+
} catch (e) {
|
|
5553
|
+
console.error("Failed to update OpenCode config:", e);
|
|
5554
|
+
}
|
|
5555
|
+
}
|
|
5316
5556
|
function convertToOpenCodeAgent(prompt, useFileReference = false, promptFilePath) {
|
|
5317
5557
|
const { frontmatter, content } = prompt;
|
|
5318
5558
|
const tools = {};
|
|
@@ -5570,8 +5810,8 @@ linked_projects:
|
|
|
5570
5810
|
async function registerWithMCP(config, workspacePath, workspaceName) {
|
|
5571
5811
|
if (!config.exposeToMCP) return;
|
|
5572
5812
|
try {
|
|
5573
|
-
const { loadMCPConfig:
|
|
5574
|
-
const mcpConfig =
|
|
5813
|
+
const { loadMCPConfig: loadMCPConfig3, saveMCPConfig: saveMCPConfig2, setProjectConfig: setProjectConfig2 } = await Promise.resolve().then(() => (init_config(), config_exports));
|
|
5814
|
+
const mcpConfig = loadMCPConfig3();
|
|
5575
5815
|
setProjectConfig2(
|
|
5576
5816
|
mcpConfig,
|
|
5577
5817
|
workspaceName,
|
|
@@ -5836,7 +6076,7 @@ async function handlePostSetup(config, workspacePath, workspaceName, linkedProje
|
|
|
5836
6076
|
init_paths();
|
|
5837
6077
|
import { multiselect as multiselect4, spinner as spinner3, note as note7, outro as outro3, cancel as cancel3, isCancel as isCancel8, confirm as confirm6 } from "@clack/prompts";
|
|
5838
6078
|
import pc9 from "picocolors";
|
|
5839
|
-
import * as
|
|
6079
|
+
import * as fs21 from "fs";
|
|
5840
6080
|
init_detection();
|
|
5841
6081
|
async function runLinkProjectsFlow(workspacePath, workspaceName) {
|
|
5842
6082
|
const projects = scanForProjects({
|
|
@@ -5875,7 +6115,7 @@ async function runLinkProjectsFlow(workspacePath, workspaceName) {
|
|
|
5875
6115
|
const s = spinner3();
|
|
5876
6116
|
s.start("Linking projects");
|
|
5877
6117
|
const configFilePath = getConfigPath(workspacePath);
|
|
5878
|
-
let configContent =
|
|
6118
|
+
let configContent = fs21.readFileSync(configFilePath, "utf-8");
|
|
5879
6119
|
if (configContent.includes("linked_projects:")) {
|
|
5880
6120
|
const lines = configContent.split("\n");
|
|
5881
6121
|
const linkedIndex = lines.findIndex((l) => l.trim() === "linked_projects:");
|
|
@@ -5902,7 +6142,7 @@ linked_projects:
|
|
|
5902
6142
|
`;
|
|
5903
6143
|
});
|
|
5904
6144
|
}
|
|
5905
|
-
|
|
6145
|
+
fs21.writeFileSync(configFilePath, configContent);
|
|
5906
6146
|
generateVSCodeWorkspace(workspacePath, workspaceName, selectedProjects, customGlobalPath);
|
|
5907
6147
|
s.stop("Projects linked");
|
|
5908
6148
|
const workspaceFile = `${workspaceName}.code-workspace`;
|
|
@@ -5920,8 +6160,8 @@ linked_projects:
|
|
|
5920
6160
|
});
|
|
5921
6161
|
if (shouldExpose && !isCancel8(shouldExpose)) {
|
|
5922
6162
|
try {
|
|
5923
|
-
const { loadMCPConfig:
|
|
5924
|
-
const mcpConfig =
|
|
6163
|
+
const { loadMCPConfig: loadMCPConfig3, saveMCPConfig: saveMCPConfig2, setProjectConfig: setProjectConfig2 } = await Promise.resolve().then(() => (init_config(), config_exports));
|
|
6164
|
+
const mcpConfig = loadMCPConfig3();
|
|
5925
6165
|
for (const project of selectedProjects) {
|
|
5926
6166
|
setProjectConfig2(mcpConfig, project.name, true, void 0, project.dataPath);
|
|
5927
6167
|
}
|
|
@@ -5937,15 +6177,15 @@ linked_projects:
|
|
|
5937
6177
|
init_paths();
|
|
5938
6178
|
import { confirm as confirm7, spinner as spinner4, note as note8, outro as outro4, cancel as cancel4, isCancel as isCancel9 } from "@clack/prompts";
|
|
5939
6179
|
import pc10 from "picocolors";
|
|
5940
|
-
import * as
|
|
5941
|
-
import * as
|
|
6180
|
+
import * as fs22 from "fs";
|
|
6181
|
+
import * as path22 from "path";
|
|
5942
6182
|
async function runSyncToGlobalFlow(workspacePath, workspaceName) {
|
|
5943
6183
|
const localPath = getLocalWorkspacePath(workspacePath);
|
|
5944
6184
|
const customGlobalPath = getEffectiveRRCEHome(workspacePath);
|
|
5945
|
-
const globalPath =
|
|
6185
|
+
const globalPath = path22.join(customGlobalPath, "workspaces", workspaceName);
|
|
5946
6186
|
const subdirs = ["knowledge", "prompts", "templates", "tasks", "refs"];
|
|
5947
6187
|
const existingDirs = subdirs.filter(
|
|
5948
|
-
(dir) =>
|
|
6188
|
+
(dir) => fs22.existsSync(path22.join(localPath, dir))
|
|
5949
6189
|
);
|
|
5950
6190
|
if (existingDirs.length === 0) {
|
|
5951
6191
|
outro4(pc10.yellow("No data found in workspace storage to sync."));
|
|
@@ -5971,8 +6211,8 @@ Destination: ${pc10.cyan(globalPath)}`,
|
|
|
5971
6211
|
try {
|
|
5972
6212
|
ensureDir(globalPath);
|
|
5973
6213
|
for (const dir of existingDirs) {
|
|
5974
|
-
const srcDir =
|
|
5975
|
-
const destDir =
|
|
6214
|
+
const srcDir = path22.join(localPath, dir);
|
|
6215
|
+
const destDir = path22.join(globalPath, dir);
|
|
5976
6216
|
ensureDir(destDir);
|
|
5977
6217
|
copyDirRecursive(srcDir, destDir);
|
|
5978
6218
|
}
|
|
@@ -5999,29 +6239,74 @@ init_paths();
|
|
|
5999
6239
|
init_prompts();
|
|
6000
6240
|
import { confirm as confirm8, spinner as spinner5, note as note9, outro as outro5, cancel as cancel5, isCancel as isCancel10 } from "@clack/prompts";
|
|
6001
6241
|
import pc11 from "picocolors";
|
|
6002
|
-
import * as
|
|
6003
|
-
import * as
|
|
6004
|
-
import { stringify as stringify3 } from "yaml";
|
|
6242
|
+
import * as fs23 from "fs";
|
|
6243
|
+
import * as path23 from "path";
|
|
6244
|
+
import { stringify as stringify3, parse } from "yaml";
|
|
6005
6245
|
init_install();
|
|
6246
|
+
init_drift_service();
|
|
6247
|
+
function backupFile(filePath) {
|
|
6248
|
+
if (!fs23.existsSync(filePath)) return null;
|
|
6249
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").split("T")[0] + "-" + Date.now();
|
|
6250
|
+
const backupPath = `${filePath}.${timestamp}.bak`;
|
|
6251
|
+
try {
|
|
6252
|
+
fs23.copyFileSync(filePath, backupPath);
|
|
6253
|
+
return backupPath;
|
|
6254
|
+
} catch (e) {
|
|
6255
|
+
console.error(`Failed to backup ${filePath}:`, e);
|
|
6256
|
+
return null;
|
|
6257
|
+
}
|
|
6258
|
+
}
|
|
6259
|
+
function getPackageVersion2() {
|
|
6260
|
+
try {
|
|
6261
|
+
const agentCoreDir = getAgentCoreDir();
|
|
6262
|
+
const packageJsonPath = path23.join(path23.dirname(agentCoreDir), "package.json");
|
|
6263
|
+
if (fs23.existsSync(packageJsonPath)) {
|
|
6264
|
+
return JSON.parse(fs23.readFileSync(packageJsonPath, "utf8")).version;
|
|
6265
|
+
}
|
|
6266
|
+
} catch (e) {
|
|
6267
|
+
}
|
|
6268
|
+
return "0.0.0";
|
|
6269
|
+
}
|
|
6006
6270
|
async function runUpdateFlow(workspacePath, workspaceName, currentStorageMode) {
|
|
6007
6271
|
const s = spinner5();
|
|
6008
6272
|
s.start("Checking for updates");
|
|
6009
6273
|
try {
|
|
6010
6274
|
const agentCoreDir = getAgentCoreDir();
|
|
6011
6275
|
const prompts = loadPromptsFromDir(getAgentCorePromptsDir());
|
|
6276
|
+
const runningVersion = getPackageVersion2();
|
|
6012
6277
|
const mode = currentStorageMode || "global";
|
|
6013
6278
|
const customGlobalPath = getEffectiveRRCEHome(workspacePath);
|
|
6014
6279
|
const dataPaths = resolveAllDataPathsWithCustomGlobal(mode, workspaceName, workspacePath, customGlobalPath);
|
|
6280
|
+
const configFilePath = getConfigPath(workspacePath);
|
|
6281
|
+
let currentSyncedVersion;
|
|
6282
|
+
if (fs23.existsSync(configFilePath)) {
|
|
6283
|
+
try {
|
|
6284
|
+
const content = fs23.readFileSync(configFilePath, "utf-8");
|
|
6285
|
+
const config = parse(content);
|
|
6286
|
+
currentSyncedVersion = config.last_synced_version;
|
|
6287
|
+
} catch (e) {
|
|
6288
|
+
}
|
|
6289
|
+
}
|
|
6290
|
+
const driftReport = DriftService.checkDrift(dataPaths[0], currentSyncedVersion, runningVersion);
|
|
6015
6291
|
s.stop("Updates found");
|
|
6292
|
+
if (driftReport.type === "version") {
|
|
6293
|
+
note9(`New version available: ${pc11.green(runningVersion)} (Current synced: ${pc11.dim(currentSyncedVersion || "None")})`, "Update Available");
|
|
6294
|
+
}
|
|
6295
|
+
if (driftReport.modifiedFiles.length > 0) {
|
|
6296
|
+
note9(
|
|
6297
|
+
pc11.yellow(`The following files have been modified and will be backed up before updating:
|
|
6298
|
+
`) + driftReport.modifiedFiles.map((f) => ` \u2022 ${f}`).join("\n"),
|
|
6299
|
+
"Modifications Detected"
|
|
6300
|
+
);
|
|
6301
|
+
}
|
|
6016
6302
|
const updateTargets = [
|
|
6017
6303
|
` \u2022 prompts/ (${prompts.length} agent prompts)`,
|
|
6018
6304
|
` \u2022 templates/ (output templates)`,
|
|
6019
6305
|
` \u2022 docs/ (documentation)`
|
|
6020
6306
|
];
|
|
6021
|
-
const configFilePath = getConfigPath(workspacePath);
|
|
6022
6307
|
const ideTargets = [];
|
|
6023
|
-
if (
|
|
6024
|
-
const configContent =
|
|
6308
|
+
if (fs23.existsSync(configFilePath)) {
|
|
6309
|
+
const configContent = fs23.readFileSync(configFilePath, "utf-8");
|
|
6025
6310
|
if (configContent.includes("opencode: true")) ideTargets.push("OpenCode agents");
|
|
6026
6311
|
if (configContent.includes("copilot: true")) ideTargets.push("GitHub Copilot");
|
|
6027
6312
|
if (configContent.includes("antigravity: true")) ideTargets.push("Antigravity");
|
|
@@ -6047,17 +6332,41 @@ ${dataPaths.map((p) => ` \u2022 ${p}`).join("\n")}`,
|
|
|
6047
6332
|
}
|
|
6048
6333
|
s.start("Updating from package");
|
|
6049
6334
|
for (const dataPath of dataPaths) {
|
|
6050
|
-
|
|
6051
|
-
|
|
6052
|
-
|
|
6335
|
+
const dirs = ["templates", "prompts", "docs"];
|
|
6336
|
+
const updatedFiles = [];
|
|
6337
|
+
for (const dir of dirs) {
|
|
6338
|
+
const srcDir = path23.join(agentCoreDir, dir);
|
|
6339
|
+
if (!fs23.existsSync(srcDir)) continue;
|
|
6340
|
+
const syncFiles = (src, rel) => {
|
|
6341
|
+
const entries = fs23.readdirSync(src, { withFileTypes: true });
|
|
6342
|
+
for (const entry of entries) {
|
|
6343
|
+
const entrySrc = path23.join(src, entry.name);
|
|
6344
|
+
const entryRel = path23.join(rel, entry.name);
|
|
6345
|
+
const entryDest = path23.join(dataPath, entryRel);
|
|
6346
|
+
if (entry.isDirectory()) {
|
|
6347
|
+
ensureDir(entryDest);
|
|
6348
|
+
syncFiles(entrySrc, entryRel);
|
|
6349
|
+
} else {
|
|
6350
|
+
if (driftReport.modifiedFiles.includes(entryRel)) {
|
|
6351
|
+
backupFile(entryDest);
|
|
6352
|
+
}
|
|
6353
|
+
fs23.copyFileSync(entrySrc, entryDest);
|
|
6354
|
+
updatedFiles.push(entryRel);
|
|
6355
|
+
}
|
|
6356
|
+
}
|
|
6357
|
+
};
|
|
6358
|
+
syncFiles(srcDir, dir);
|
|
6359
|
+
}
|
|
6360
|
+
const manifest = DriftService.generateManifest(dataPath, updatedFiles);
|
|
6361
|
+
DriftService.saveManifest(dataPath, manifest);
|
|
6053
6362
|
}
|
|
6054
6363
|
const rrceHome = customGlobalPath || getDefaultRRCEHome2();
|
|
6055
|
-
ensureDir(
|
|
6056
|
-
ensureDir(
|
|
6057
|
-
copyDirRecursive(
|
|
6058
|
-
copyDirRecursive(
|
|
6059
|
-
if (
|
|
6060
|
-
const configContent =
|
|
6364
|
+
ensureDir(path23.join(rrceHome, "templates"));
|
|
6365
|
+
ensureDir(path23.join(rrceHome, "docs"));
|
|
6366
|
+
copyDirRecursive(path23.join(agentCoreDir, "templates"), path23.join(rrceHome, "templates"));
|
|
6367
|
+
copyDirRecursive(path23.join(agentCoreDir, "docs"), path23.join(rrceHome, "docs"));
|
|
6368
|
+
if (fs23.existsSync(configFilePath)) {
|
|
6369
|
+
const configContent = fs23.readFileSync(configFilePath, "utf-8");
|
|
6061
6370
|
if (configContent.includes("copilot: true")) {
|
|
6062
6371
|
const copilotPath = getAgentPromptPath(workspacePath, "copilot");
|
|
6063
6372
|
ensureDir(copilotPath);
|
|
@@ -6076,6 +6385,29 @@ ${dataPaths.map((p) => ` \u2022 ${p}`).join("\n")}`,
|
|
|
6076
6385
|
updateOpenCodeAgents(prompts, mode, primaryDataPath);
|
|
6077
6386
|
}
|
|
6078
6387
|
}
|
|
6388
|
+
try {
|
|
6389
|
+
const yaml = parse(configContent);
|
|
6390
|
+
yaml.last_synced_version = runningVersion;
|
|
6391
|
+
fs23.writeFileSync(configFilePath, stringify3(yaml));
|
|
6392
|
+
} catch (e) {
|
|
6393
|
+
console.error("Failed to update config.yaml version:", e);
|
|
6394
|
+
}
|
|
6395
|
+
}
|
|
6396
|
+
const mcpPath = path23.join(rrceHome, "mcp.yaml");
|
|
6397
|
+
if (fs23.existsSync(mcpPath)) {
|
|
6398
|
+
try {
|
|
6399
|
+
const content = fs23.readFileSync(mcpPath, "utf-8");
|
|
6400
|
+
const yaml = parse(content);
|
|
6401
|
+
if (yaml.projects) {
|
|
6402
|
+
const project = yaml.projects.find((p) => p.name === workspaceName);
|
|
6403
|
+
if (project) {
|
|
6404
|
+
project.last_synced_version = runningVersion;
|
|
6405
|
+
fs23.writeFileSync(mcpPath, stringify3(yaml));
|
|
6406
|
+
}
|
|
6407
|
+
}
|
|
6408
|
+
} catch (e) {
|
|
6409
|
+
console.error("Failed to update mcp.yaml version:", e);
|
|
6410
|
+
}
|
|
6079
6411
|
}
|
|
6080
6412
|
s.stop("Update complete");
|
|
6081
6413
|
const summary = [
|
|
@@ -6087,6 +6419,9 @@ ${dataPaths.map((p) => ` \u2022 ${p}`).join("\n")}`,
|
|
|
6087
6419
|
if (ideTargets.length > 0) {
|
|
6088
6420
|
summary.push(` \u2713 IDE integrations: ${ideTargets.join(", ")}`);
|
|
6089
6421
|
}
|
|
6422
|
+
if (driftReport.modifiedFiles.length > 0) {
|
|
6423
|
+
summary.push(` \u2713 ${driftReport.modifiedFiles.length} modified files backed up`);
|
|
6424
|
+
}
|
|
6090
6425
|
summary.push(
|
|
6091
6426
|
``,
|
|
6092
6427
|
`Your configuration and knowledge files were preserved.`,
|
|
@@ -6104,50 +6439,35 @@ ${dataPaths.map((p) => ` \u2022 ${p}`).join("\n")}`,
|
|
|
6104
6439
|
function updateOpenCodeAgents(prompts, mode, primaryDataPath) {
|
|
6105
6440
|
if (mode === "global") {
|
|
6106
6441
|
try {
|
|
6107
|
-
const promptsDir =
|
|
6442
|
+
const promptsDir = path23.join(path23.dirname(OPENCODE_CONFIG), "prompts");
|
|
6108
6443
|
ensureDir(promptsDir);
|
|
6109
|
-
|
|
6110
|
-
if (fs21.existsSync(OPENCODE_CONFIG)) {
|
|
6111
|
-
opencodeConfig = JSON.parse(fs21.readFileSync(OPENCODE_CONFIG, "utf-8"));
|
|
6112
|
-
}
|
|
6113
|
-
if (!opencodeConfig.agent) opencodeConfig.agent = {};
|
|
6114
|
-
const currentAgentBaseNames = prompts.map((p) => path21.basename(p.filePath, ".md"));
|
|
6115
|
-
const currentAgentIds = new Set(currentAgentBaseNames.map((base) => `rrce_${base}`));
|
|
6116
|
-
const existingAgentNames = Object.keys(opencodeConfig.agent);
|
|
6117
|
-
for (const existingName of existingAgentNames) {
|
|
6118
|
-
const isLegacyBaseName = currentAgentBaseNames.includes(existingName);
|
|
6119
|
-
const isRrcePrefixed = existingName.startsWith("rrce_");
|
|
6120
|
-
const isStaleRrcePrefixed = isRrcePrefixed && !currentAgentIds.has(existingName);
|
|
6121
|
-
if (isLegacyBaseName || isStaleRrcePrefixed) {
|
|
6122
|
-
delete opencodeConfig.agent[existingName];
|
|
6123
|
-
const legacyBaseName = isLegacyBaseName ? existingName : existingName.replace(/^rrce_/, "");
|
|
6124
|
-
const oldPromptFile = path21.join(promptsDir, `rrce-${legacyBaseName}.md`);
|
|
6125
|
-
if (fs21.existsSync(oldPromptFile)) {
|
|
6126
|
-
fs21.unlinkSync(oldPromptFile);
|
|
6127
|
-
}
|
|
6128
|
-
}
|
|
6129
|
-
}
|
|
6444
|
+
const newAgents = {};
|
|
6130
6445
|
for (const prompt of prompts) {
|
|
6131
|
-
const baseName =
|
|
6446
|
+
const baseName = path23.basename(prompt.filePath, ".md");
|
|
6132
6447
|
const agentId = `rrce_${baseName}`;
|
|
6133
6448
|
const promptFileName = `rrce-${baseName}.md`;
|
|
6134
|
-
const promptFilePath =
|
|
6135
|
-
|
|
6449
|
+
const promptFilePath = path23.join(promptsDir, promptFileName);
|
|
6450
|
+
fs23.writeFileSync(promptFilePath, prompt.content);
|
|
6136
6451
|
const agentConfig = convertToOpenCodeAgent(prompt, true, `./prompts/${promptFileName}`);
|
|
6137
|
-
|
|
6452
|
+
newAgents[agentId] = agentConfig;
|
|
6453
|
+
}
|
|
6454
|
+
updateOpenCodeConfig(newAgents);
|
|
6455
|
+
if (fs23.existsSync(OPENCODE_CONFIG)) {
|
|
6456
|
+
const config = JSON.parse(fs23.readFileSync(OPENCODE_CONFIG, "utf8"));
|
|
6457
|
+
if (!config.agents) config.agents = {};
|
|
6458
|
+
if (!config.agents.plan) config.agents.plan = {};
|
|
6459
|
+
config.agents.plan.disable = true;
|
|
6460
|
+
fs23.writeFileSync(OPENCODE_CONFIG, JSON.stringify(config, null, 2));
|
|
6138
6461
|
}
|
|
6139
|
-
if (!opencodeConfig.agent.plan) opencodeConfig.agent.plan = {};
|
|
6140
|
-
opencodeConfig.agent.plan.disable = true;
|
|
6141
|
-
fs21.writeFileSync(OPENCODE_CONFIG, JSON.stringify(opencodeConfig, null, 2) + "\n");
|
|
6142
6462
|
} catch (e) {
|
|
6143
6463
|
console.error("Failed to update global OpenCode config with agents:", e);
|
|
6144
6464
|
}
|
|
6145
6465
|
} else {
|
|
6146
|
-
const opencodeBaseDir =
|
|
6466
|
+
const opencodeBaseDir = path23.join(primaryDataPath, ".opencode", "agent");
|
|
6147
6467
|
ensureDir(opencodeBaseDir);
|
|
6148
6468
|
clearDirectory(opencodeBaseDir);
|
|
6149
6469
|
for (const prompt of prompts) {
|
|
6150
|
-
const baseName =
|
|
6470
|
+
const baseName = path23.basename(prompt.filePath, ".md");
|
|
6151
6471
|
const agentId = `rrce_${baseName}`;
|
|
6152
6472
|
const agentConfig = convertToOpenCodeAgent(prompt);
|
|
6153
6473
|
const content = `---
|
|
@@ -6157,22 +6477,22 @@ ${stringify3({
|
|
|
6157
6477
|
tools: agentConfig.tools
|
|
6158
6478
|
})}---
|
|
6159
6479
|
${agentConfig.prompt}`;
|
|
6160
|
-
|
|
6480
|
+
fs23.writeFileSync(path23.join(opencodeBaseDir, `${agentId}.md`), content);
|
|
6161
6481
|
}
|
|
6162
6482
|
}
|
|
6163
6483
|
}
|
|
6164
6484
|
function clearDirectory(dirPath) {
|
|
6165
|
-
if (!
|
|
6166
|
-
const entries =
|
|
6485
|
+
if (!fs23.existsSync(dirPath)) return;
|
|
6486
|
+
const entries = fs23.readdirSync(dirPath, { withFileTypes: true });
|
|
6167
6487
|
for (const entry of entries) {
|
|
6168
6488
|
if (entry.isFile()) {
|
|
6169
|
-
|
|
6489
|
+
fs23.unlinkSync(path23.join(dirPath, entry.name));
|
|
6170
6490
|
}
|
|
6171
6491
|
}
|
|
6172
6492
|
}
|
|
6173
6493
|
function resolveAllDataPathsWithCustomGlobal(mode, workspaceName, workspaceRoot, customGlobalPath) {
|
|
6174
|
-
const globalPath =
|
|
6175
|
-
const workspacePath =
|
|
6494
|
+
const globalPath = path23.join(customGlobalPath, "workspaces", workspaceName);
|
|
6495
|
+
const workspacePath = path23.join(workspaceRoot, ".rrce-workflow");
|
|
6176
6496
|
switch (mode) {
|
|
6177
6497
|
case "global":
|
|
6178
6498
|
return [globalPath];
|
|
@@ -6186,7 +6506,7 @@ function resolveAllDataPathsWithCustomGlobal(mode, workspaceName, workspaceRoot,
|
|
|
6186
6506
|
// src/commands/wizard/delete-flow.ts
|
|
6187
6507
|
import { multiselect as multiselect5, confirm as confirm9, spinner as spinner6, note as note10, cancel as cancel6, isCancel as isCancel11 } from "@clack/prompts";
|
|
6188
6508
|
import pc12 from "picocolors";
|
|
6189
|
-
import * as
|
|
6509
|
+
import * as fs24 from "fs";
|
|
6190
6510
|
init_detection();
|
|
6191
6511
|
init_config();
|
|
6192
6512
|
async function runDeleteGlobalProjectFlow(availableProjects) {
|
|
@@ -6230,8 +6550,8 @@ Are you sure?`,
|
|
|
6230
6550
|
for (const projectName of projectsToDelete) {
|
|
6231
6551
|
const project = globalProjects.find((p) => p.name === projectName);
|
|
6232
6552
|
if (!project) continue;
|
|
6233
|
-
if (
|
|
6234
|
-
|
|
6553
|
+
if (fs24.existsSync(project.dataPath)) {
|
|
6554
|
+
fs24.rmSync(project.dataPath, { recursive: true, force: true });
|
|
6235
6555
|
}
|
|
6236
6556
|
const newConfig = removeProjectConfig(mcpConfig, projectName);
|
|
6237
6557
|
configChanged = true;
|
|
@@ -6277,11 +6597,11 @@ Workspace: ${pc13.bold(workspaceName)}`,
|
|
|
6277
6597
|
workspacePath
|
|
6278
6598
|
});
|
|
6279
6599
|
const configFilePath = getConfigPath(workspacePath);
|
|
6280
|
-
let isAlreadyConfigured =
|
|
6600
|
+
let isAlreadyConfigured = fs25.existsSync(configFilePath);
|
|
6281
6601
|
let currentStorageMode = null;
|
|
6282
6602
|
if (isAlreadyConfigured) {
|
|
6283
6603
|
try {
|
|
6284
|
-
const configContent =
|
|
6604
|
+
const configContent = fs25.readFileSync(configFilePath, "utf-8");
|
|
6285
6605
|
const modeMatch = configContent.match(/mode:\s*(global|workspace)/);
|
|
6286
6606
|
currentStorageMode = modeMatch?.[1] ?? null;
|
|
6287
6607
|
} catch {
|
|
@@ -6298,7 +6618,7 @@ Workspace: ${pc13.bold(workspaceName)}`,
|
|
|
6298
6618
|
}
|
|
6299
6619
|
}
|
|
6300
6620
|
const localDataPath = getLocalWorkspacePath(workspacePath);
|
|
6301
|
-
const hasLocalData =
|
|
6621
|
+
const hasLocalData = fs25.existsSync(localDataPath);
|
|
6302
6622
|
if (isAlreadyConfigured) {
|
|
6303
6623
|
const menuOptions = [];
|
|
6304
6624
|
menuOptions.push({
|