rrce-workflow 0.2.97 → 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/README.md +46 -18
- package/agent-core/prompts/orchestrator.md +350 -0
- package/agent-core/templates/orchestrator_output.md +51 -0
- package/dist/index.js +559 -232
- package/docs/opencode-guide.md +631 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1031,6 +1031,7 @@ var init_prompt = __esm({
|
|
|
1031
1031
|
description: z.string(),
|
|
1032
1032
|
"argument-hint": z.union([z.string(), z.array(z.string())]).optional(),
|
|
1033
1033
|
tools: z.array(z.string()).optional(),
|
|
1034
|
+
mode: z.enum(["primary", "subagent"]).optional(),
|
|
1034
1035
|
"required-args": z.array(PromptArgSchema).optional(),
|
|
1035
1036
|
"optional-args": z.array(PromptArgSchema).optional(),
|
|
1036
1037
|
"auto-identity": AutoIdentitySchema.optional()
|
|
@@ -1265,8 +1266,10 @@ function parseMCPConfig(content) {
|
|
|
1265
1266
|
tasks: p.permissions?.tasks ?? DEFAULT_PERMISSIONS.tasks,
|
|
1266
1267
|
refs: p.permissions?.refs ?? DEFAULT_PERMISSIONS.refs
|
|
1267
1268
|
},
|
|
1268
|
-
semanticSearch: p.semanticSearch
|
|
1269
|
-
|
|
1269
|
+
semanticSearch: p.semanticSearch,
|
|
1270
|
+
last_synced_version: p.last_synced_version
|
|
1271
|
+
})) : [],
|
|
1272
|
+
last_synced_version: parsed?.last_synced_version
|
|
1270
1273
|
};
|
|
1271
1274
|
return config;
|
|
1272
1275
|
} catch (err) {
|
|
@@ -2360,7 +2363,7 @@ var init_dependency_graph = __esm({
|
|
|
2360
2363
|
// src/mcp/resources.ts
|
|
2361
2364
|
import * as fs15 from "fs";
|
|
2362
2365
|
import * as path17 from "path";
|
|
2363
|
-
import * as
|
|
2366
|
+
import * as os3 from "os";
|
|
2364
2367
|
import * as crypto from "crypto";
|
|
2365
2368
|
import ignore from "ignore";
|
|
2366
2369
|
function resolveProjectPaths(project, pathInput) {
|
|
@@ -2902,7 +2905,7 @@ function getContextPreamble() {
|
|
|
2902
2905
|
const activeProject = detectActiveProject();
|
|
2903
2906
|
let contextPreamble = "";
|
|
2904
2907
|
if (activeProject) {
|
|
2905
|
-
const rrceHome = process.env.RRCE_HOME || path17.join(
|
|
2908
|
+
const rrceHome = process.env.RRCE_HOME || path17.join(os3.homedir(), ".rrce-workflow");
|
|
2906
2909
|
const workspaceRoot = activeProject.sourcePath || activeProject.path || activeProject.dataPath;
|
|
2907
2910
|
const rrceData = activeProject.dataPath;
|
|
2908
2911
|
contextPreamble += `
|
|
@@ -2972,7 +2975,7 @@ async function createTask(projectName, taskSlug, taskData) {
|
|
|
2972
2975
|
fs15.mkdirSync(path17.join(taskDir, "planning"), { recursive: true });
|
|
2973
2976
|
fs15.mkdirSync(path17.join(taskDir, "execution"), { recursive: true });
|
|
2974
2977
|
fs15.mkdirSync(path17.join(taskDir, "docs"), { recursive: true });
|
|
2975
|
-
const rrceHome = process.env.RRCE_HOME || path17.join(
|
|
2978
|
+
const rrceHome = process.env.RRCE_HOME || path17.join(os3.homedir(), ".rrce-workflow");
|
|
2976
2979
|
const templatePath = path17.join(rrceHome, "templates", "meta.template.json");
|
|
2977
2980
|
let meta = {
|
|
2978
2981
|
task_id: crypto.randomUUID(),
|
|
@@ -3868,8 +3871,8 @@ Hidden projects: ${projects.length - exposedCount}`,
|
|
|
3868
3871
|
}
|
|
3869
3872
|
async function handleConfigureGlobalPath() {
|
|
3870
3873
|
const { resolveGlobalPath: resolveGlobalPath2 } = await Promise.resolve().then(() => (init_tui_utils(), tui_utils_exports));
|
|
3871
|
-
const
|
|
3872
|
-
const
|
|
3874
|
+
const fs26 = await import("fs");
|
|
3875
|
+
const path24 = await import("path");
|
|
3873
3876
|
note3(
|
|
3874
3877
|
`MCP Hub requires a ${pc5.bold("global storage path")} to store its configuration
|
|
3875
3878
|
and coordinate across projects.
|
|
@@ -3883,8 +3886,8 @@ locally in each project. MCP needs a central location.`,
|
|
|
3883
3886
|
return false;
|
|
3884
3887
|
}
|
|
3885
3888
|
try {
|
|
3886
|
-
if (!
|
|
3887
|
-
|
|
3889
|
+
if (!fs26.existsSync(resolvedPath)) {
|
|
3890
|
+
fs26.mkdirSync(resolvedPath, { recursive: true });
|
|
3888
3891
|
}
|
|
3889
3892
|
const config = loadMCPConfig();
|
|
3890
3893
|
saveMCPConfig(config);
|
|
@@ -3892,7 +3895,7 @@ locally in each project. MCP needs a central location.`,
|
|
|
3892
3895
|
`${pc5.green("\u2713")} Global path configured: ${pc5.cyan(resolvedPath)}
|
|
3893
3896
|
|
|
3894
3897
|
MCP config will be stored at:
|
|
3895
|
-
${
|
|
3898
|
+
${path24.join(resolvedPath, "mcp.yaml")}`,
|
|
3896
3899
|
"Configuration Saved"
|
|
3897
3900
|
);
|
|
3898
3901
|
return true;
|
|
@@ -4217,10 +4220,191 @@ var init_tasks_fs = __esm({
|
|
|
4217
4220
|
}
|
|
4218
4221
|
});
|
|
4219
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
|
+
|
|
4220
4404
|
// src/mcp/ui/ProjectsView.tsx
|
|
4221
|
-
import { useEffect as
|
|
4405
|
+
import { useEffect as useEffect3, useMemo as useMemo3, useState as useState3 } from "react";
|
|
4222
4406
|
import { Box as Box4, Text as Text4, useInput as useInput2 } from "ink";
|
|
4223
|
-
import { jsx as
|
|
4407
|
+
import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
4224
4408
|
function nextStatus(current) {
|
|
4225
4409
|
const idx = STATUS_CYCLE.indexOf(current || "");
|
|
4226
4410
|
if (idx === -1) return STATUS_CYCLE[0];
|
|
@@ -4229,9 +4413,14 @@ function nextStatus(current) {
|
|
|
4229
4413
|
function projectKey(p) {
|
|
4230
4414
|
return p.sourcePath ?? p.path;
|
|
4231
4415
|
}
|
|
4232
|
-
function formatProjectLabel(p) {
|
|
4416
|
+
function formatProjectLabel(p, drift) {
|
|
4233
4417
|
const root = p.sourcePath ?? p.path;
|
|
4234
|
-
|
|
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;
|
|
4235
4424
|
}
|
|
4236
4425
|
var STATUS_CYCLE, ProjectsView;
|
|
4237
4426
|
var init_ProjectsView = __esm({
|
|
@@ -4240,15 +4429,17 @@ var init_ProjectsView = __esm({
|
|
|
4240
4429
|
init_SimpleSelect();
|
|
4241
4430
|
init_config();
|
|
4242
4431
|
init_tasks_fs();
|
|
4432
|
+
init_ConfigContext();
|
|
4243
4433
|
STATUS_CYCLE = ["pending", "in_progress", "blocked", "complete"];
|
|
4244
4434
|
ProjectsView = ({ config: initialConfig, projects: allProjects, onConfigChange }) => {
|
|
4245
|
-
const
|
|
4246
|
-
const [
|
|
4247
|
-
const [
|
|
4248
|
-
const [
|
|
4249
|
-
const [
|
|
4250
|
-
const [
|
|
4251
|
-
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(() => {
|
|
4252
4443
|
return [...allProjects].sort((a, b) => {
|
|
4253
4444
|
const byName = a.name.localeCompare(b.name);
|
|
4254
4445
|
if (byName !== 0) return byName;
|
|
@@ -4272,6 +4463,10 @@ var init_ProjectsView = __esm({
|
|
|
4272
4463
|
setMode((prev) => prev === "expose" ? "tasks" : "expose");
|
|
4273
4464
|
return;
|
|
4274
4465
|
}
|
|
4466
|
+
if (input === "u") {
|
|
4467
|
+
checkAllDrift();
|
|
4468
|
+
return;
|
|
4469
|
+
}
|
|
4275
4470
|
if (mode === "expose") {
|
|
4276
4471
|
if (input === "a") {
|
|
4277
4472
|
const newConfig = {
|
|
@@ -4337,27 +4532,28 @@ var init_ProjectsView = __esm({
|
|
|
4337
4532
|
}
|
|
4338
4533
|
}
|
|
4339
4534
|
});
|
|
4340
|
-
|
|
4535
|
+
useEffect3(() => {
|
|
4341
4536
|
setSelectedIndex((prev) => {
|
|
4342
4537
|
if (flattenedRows.length === 0) return 0;
|
|
4343
4538
|
return Math.min(prev, flattenedRows.length - 1);
|
|
4344
4539
|
});
|
|
4345
4540
|
}, [mode, allProjects, expanded, taskCache]);
|
|
4346
|
-
const projectItems =
|
|
4541
|
+
const projectItems = useMemo3(() => {
|
|
4347
4542
|
return allProjects.map((p) => {
|
|
4348
4543
|
const projectConfig = config.projects.find(
|
|
4349
4544
|
(c) => c.path && c.path === p.path || p.source === "global" && c.name === p.name || !c.path && c.name === p.name
|
|
4350
4545
|
);
|
|
4351
4546
|
const isExposed = projectConfig ? projectConfig.expose : config.defaults.includeNew;
|
|
4547
|
+
const drift = driftReports[p.path];
|
|
4352
4548
|
return {
|
|
4353
|
-
label: formatProjectLabel(p),
|
|
4549
|
+
label: formatProjectLabel(p, drift),
|
|
4354
4550
|
value: p.path,
|
|
4355
4551
|
key: p.path,
|
|
4356
4552
|
exposed: isExposed
|
|
4357
4553
|
};
|
|
4358
4554
|
});
|
|
4359
|
-
}, [allProjects, config]);
|
|
4360
|
-
const initialSelected =
|
|
4555
|
+
}, [allProjects, config, driftReports]);
|
|
4556
|
+
const initialSelected = useMemo3(() => {
|
|
4361
4557
|
return projectItems.filter((p) => p.exposed).map((p) => p.value);
|
|
4362
4558
|
}, [projectItems]);
|
|
4363
4559
|
const handleSubmit = (selectedIds) => {
|
|
@@ -4381,7 +4577,7 @@ var init_ProjectsView = __esm({
|
|
|
4381
4577
|
setConfig(newConfig);
|
|
4382
4578
|
onConfigChange?.();
|
|
4383
4579
|
};
|
|
4384
|
-
const flattenedRows =
|
|
4580
|
+
const flattenedRows = useMemo3(() => {
|
|
4385
4581
|
const rows = [];
|
|
4386
4582
|
for (const p of sortedProjects) {
|
|
4387
4583
|
rows.push({ kind: "project", project: p });
|
|
@@ -4402,15 +4598,15 @@ var init_ProjectsView = __esm({
|
|
|
4402
4598
|
if (mode === "expose") {
|
|
4403
4599
|
return /* @__PURE__ */ jsxs3(Box4, { flexDirection: "column", padding: 1, borderStyle: "round", borderColor: "cyan", flexGrow: 1, children: [
|
|
4404
4600
|
/* @__PURE__ */ jsxs3(Box4, { justifyContent: "space-between", children: [
|
|
4405
|
-
/* @__PURE__ */
|
|
4601
|
+
/* @__PURE__ */ jsx5(Text4, { bold: true, color: "cyan", children: " Projects (Expose Mode) " }),
|
|
4406
4602
|
/* @__PURE__ */ jsxs3(Box4, { children: [
|
|
4407
|
-
/* @__PURE__ */
|
|
4408
|
-
/* @__PURE__ */
|
|
4409
|
-
/* @__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)" })
|
|
4410
4606
|
] })
|
|
4411
4607
|
] }),
|
|
4412
|
-
/* @__PURE__ */
|
|
4413
|
-
/* @__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(
|
|
4414
4610
|
SimpleSelect,
|
|
4415
4611
|
{
|
|
4416
4612
|
message: "",
|
|
@@ -4429,62 +4625,69 @@ var init_ProjectsView = __esm({
|
|
|
4429
4625
|
}
|
|
4430
4626
|
return /* @__PURE__ */ jsxs3(Box4, { flexDirection: "column", padding: 1, borderStyle: "round", borderColor: "cyan", flexGrow: 1, children: [
|
|
4431
4627
|
/* @__PURE__ */ jsxs3(Box4, { justifyContent: "space-between", children: [
|
|
4432
|
-
/* @__PURE__ */
|
|
4433
|
-
/* @__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" })
|
|
4434
4630
|
] }),
|
|
4435
|
-
errorLine && /* @__PURE__ */
|
|
4631
|
+
errorLine && /* @__PURE__ */ jsx5(Box4, { marginTop: 0, children: /* @__PURE__ */ jsx5(Text4, { color: "red", children: errorLine }) }),
|
|
4436
4632
|
/* @__PURE__ */ jsxs3(Box4, { marginTop: 1, flexDirection: "row", flexGrow: 1, children: [
|
|
4437
4633
|
/* @__PURE__ */ jsxs3(Box4, { flexDirection: "column", width: "55%", children: [
|
|
4438
|
-
flattenedRows.length === 0 ? /* @__PURE__ */
|
|
4634
|
+
flattenedRows.length === 0 ? /* @__PURE__ */ jsx5(Text4, { color: "dim", children: "No projects detected." }) : flattenedRows.map((row, idx) => {
|
|
4439
4635
|
const isSel = idx === selectedIndex;
|
|
4440
4636
|
if (row.kind === "project") {
|
|
4441
4637
|
const k = projectKey(row.project);
|
|
4442
4638
|
const isOpen = expanded.has(k);
|
|
4443
4639
|
const count = (taskCache[k] || []).length;
|
|
4444
|
-
|
|
4445
|
-
|
|
4446
|
-
/* @__PURE__ */ jsxs3(
|
|
4447
|
-
|
|
4448
|
-
|
|
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
|
+
] })
|
|
4449
4652
|
] }),
|
|
4450
|
-
/* @__PURE__ */ jsxs3(Text4, { color: "
|
|
4451
|
-
" ",
|
|
4452
|
-
|
|
4453
|
-
] })
|
|
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
|
+
] }) })
|
|
4454
4657
|
] }, `p:${k}`);
|
|
4455
4658
|
}
|
|
4456
4659
|
const taskLabel = row.task.title || row.task.task_slug;
|
|
4457
4660
|
const status = row.task.status || "";
|
|
4458
4661
|
return /* @__PURE__ */ jsxs3(Box4, { children: [
|
|
4459
|
-
/* @__PURE__ */
|
|
4460
|
-
/* @__PURE__ */
|
|
4461
|
-
/* @__PURE__ */
|
|
4462
|
-
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}]` })
|
|
4463
4666
|
] }, `t:${projectKey(row.project)}:${row.task.task_slug}`);
|
|
4464
4667
|
}),
|
|
4465
|
-
/* @__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" }) })
|
|
4466
4669
|
] }),
|
|
4467
|
-
/* @__PURE__ */
|
|
4468
|
-
/* @__PURE__ */
|
|
4469
|
-
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 }),
|
|
4470
4673
|
/* @__PURE__ */ jsxs3(Box4, { marginTop: 1, flexDirection: "column", children: [
|
|
4471
4674
|
/* @__PURE__ */ jsxs3(Text4, { children: [
|
|
4472
|
-
/* @__PURE__ */
|
|
4473
|
-
/* @__PURE__ */
|
|
4675
|
+
/* @__PURE__ */ jsx5(Text4, { color: "dim", children: "Status: " }),
|
|
4676
|
+
/* @__PURE__ */ jsx5(Text4, { children: selectedTask.status || "unknown" })
|
|
4474
4677
|
] }),
|
|
4475
4678
|
/* @__PURE__ */ jsxs3(Text4, { children: [
|
|
4476
|
-
/* @__PURE__ */
|
|
4477
|
-
/* @__PURE__ */
|
|
4679
|
+
/* @__PURE__ */ jsx5(Text4, { color: "dim", children: "Updated: " }),
|
|
4680
|
+
/* @__PURE__ */ jsx5(Text4, { children: selectedTask.updated_at || "\u2014" })
|
|
4478
4681
|
] }),
|
|
4479
4682
|
/* @__PURE__ */ jsxs3(Text4, { children: [
|
|
4480
|
-
/* @__PURE__ */
|
|
4481
|
-
/* @__PURE__ */
|
|
4683
|
+
/* @__PURE__ */ jsx5(Text4, { color: "dim", children: "Tags: " }),
|
|
4684
|
+
/* @__PURE__ */ jsx5(Text4, { children: (selectedTask.tags || []).join(", ") || "\u2014" })
|
|
4482
4685
|
] })
|
|
4483
4686
|
] }),
|
|
4484
4687
|
/* @__PURE__ */ jsxs3(Box4, { marginTop: 1, flexDirection: "column", children: [
|
|
4485
|
-
/* @__PURE__ */
|
|
4486
|
-
(selectedTask.checklist || []).length === 0 ? /* @__PURE__ */
|
|
4487
|
-
/* @__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: "- " }),
|
|
4488
4691
|
c.label || c.id || "item",
|
|
4489
4692
|
" ",
|
|
4490
4693
|
/* @__PURE__ */ jsxs3(Text4, { color: "dim", children: [
|
|
@@ -4495,8 +4698,8 @@ var init_ProjectsView = __esm({
|
|
|
4495
4698
|
] }, c.id || i))
|
|
4496
4699
|
] }),
|
|
4497
4700
|
/* @__PURE__ */ jsxs3(Box4, { marginTop: 1, flexDirection: "column", children: [
|
|
4498
|
-
/* @__PURE__ */
|
|
4499
|
-
!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: [
|
|
4500
4703
|
/* @__PURE__ */ jsxs3(Text4, { color: "dim", children: [
|
|
4501
4704
|
"- ",
|
|
4502
4705
|
agent,
|
|
@@ -4514,9 +4717,9 @@ var init_ProjectsView = __esm({
|
|
|
4514
4717
|
});
|
|
4515
4718
|
|
|
4516
4719
|
// src/mcp/ui/components/InstallWizard.tsx
|
|
4517
|
-
import { useState as
|
|
4720
|
+
import { useState as useState4 } from "react";
|
|
4518
4721
|
import { Box as Box5, Text as Text5 } from "ink";
|
|
4519
|
-
import { jsx as
|
|
4722
|
+
import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
4520
4723
|
var InstallWizard;
|
|
4521
4724
|
var init_InstallWizard = __esm({
|
|
4522
4725
|
"src/mcp/ui/components/InstallWizard.tsx"() {
|
|
@@ -4524,8 +4727,8 @@ var init_InstallWizard = __esm({
|
|
|
4524
4727
|
init_SimpleSelect();
|
|
4525
4728
|
init_install();
|
|
4526
4729
|
InstallWizard = ({ workspacePath, onComplete, onCancel }) => {
|
|
4527
|
-
const [status, setStatus] =
|
|
4528
|
-
const [message, setMessage] =
|
|
4730
|
+
const [status, setStatus] = useState4(checkInstallStatus(workspacePath));
|
|
4731
|
+
const [message, setMessage] = useState4("");
|
|
4529
4732
|
const options = [
|
|
4530
4733
|
{
|
|
4531
4734
|
value: "opencode",
|
|
@@ -4576,8 +4779,8 @@ var init_InstallWizard = __esm({
|
|
|
4576
4779
|
}, 2e3);
|
|
4577
4780
|
};
|
|
4578
4781
|
return /* @__PURE__ */ jsxs4(Box5, { flexDirection: "column", children: [
|
|
4579
|
-
message && /* @__PURE__ */
|
|
4580
|
-
/* @__PURE__ */
|
|
4782
|
+
message && /* @__PURE__ */ jsx6(Text5, { color: "green", children: message }),
|
|
4783
|
+
/* @__PURE__ */ jsx6(
|
|
4581
4784
|
SimpleSelect,
|
|
4582
4785
|
{
|
|
4583
4786
|
message: "Select integrations to install:",
|
|
@@ -4602,7 +4805,7 @@ var init_InstallWizard = __esm({
|
|
|
4602
4805
|
// src/mcp/ui/InstallView.tsx
|
|
4603
4806
|
import "react";
|
|
4604
4807
|
import { Box as Box6, Text as Text6 } from "ink";
|
|
4605
|
-
import { jsx as
|
|
4808
|
+
import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
4606
4809
|
var InstallView;
|
|
4607
4810
|
var init_InstallView = __esm({
|
|
4608
4811
|
"src/mcp/ui/InstallView.tsx"() {
|
|
@@ -4612,9 +4815,9 @@ var init_InstallView = __esm({
|
|
|
4612
4815
|
InstallView = () => {
|
|
4613
4816
|
const workspacePath = detectWorkspaceRoot();
|
|
4614
4817
|
return /* @__PURE__ */ jsxs5(Box6, { flexDirection: "column", padding: 1, borderStyle: "round", borderColor: "magenta", flexGrow: 1, children: [
|
|
4615
|
-
/* @__PURE__ */
|
|
4616
|
-
/* @__PURE__ */
|
|
4617
|
-
/* @__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(
|
|
4618
4821
|
InstallWizard,
|
|
4619
4822
|
{
|
|
4620
4823
|
workspacePath,
|
|
@@ -4632,7 +4835,7 @@ var init_InstallView = __esm({
|
|
|
4632
4835
|
// src/mcp/ui/LogViewer.tsx
|
|
4633
4836
|
import "react";
|
|
4634
4837
|
import { Box as Box7, Text as Text7 } from "ink";
|
|
4635
|
-
import { jsx as
|
|
4838
|
+
import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
4636
4839
|
var LogViewer;
|
|
4637
4840
|
var init_LogViewer = __esm({
|
|
4638
4841
|
"src/mcp/ui/LogViewer.tsx"() {
|
|
@@ -4642,16 +4845,16 @@ var init_LogViewer = __esm({
|
|
|
4642
4845
|
const emptyLines = Math.max(0, height - visibleLogs.length);
|
|
4643
4846
|
const padding = Array(emptyLines).fill("");
|
|
4644
4847
|
const formatLog = (log) => {
|
|
4645
|
-
if (log.includes("[RAG]")) return /* @__PURE__ */
|
|
4646
|
-
if (log.includes("[ERROR]")) return /* @__PURE__ */
|
|
4647
|
-
if (log.includes("[WARN]")) return /* @__PURE__ */
|
|
4648
|
-
if (log.includes("[INFO]")) return /* @__PURE__ */
|
|
4649
|
-
if (log.includes("Success")) return /* @__PURE__ */
|
|
4650
|
-
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 });
|
|
4651
4854
|
};
|
|
4652
4855
|
return /* @__PURE__ */ jsxs6(Box7, { flexDirection: "column", borderStyle: "round", borderColor: "dim", paddingX: 1, height: height + 2, flexGrow: 1, children: [
|
|
4653
|
-
padding.map((_, i) => /* @__PURE__ */
|
|
4654
|
-
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}`))
|
|
4655
4858
|
] });
|
|
4656
4859
|
};
|
|
4657
4860
|
}
|
|
@@ -4660,35 +4863,40 @@ var init_LogViewer = __esm({
|
|
|
4660
4863
|
// src/mcp/ui/StatusBoard.tsx
|
|
4661
4864
|
import "react";
|
|
4662
4865
|
import { Box as Box8, Text as Text8 } from "ink";
|
|
4663
|
-
import { jsx as
|
|
4866
|
+
import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
4664
4867
|
var StatusBoard;
|
|
4665
4868
|
var init_StatusBoard = __esm({
|
|
4666
4869
|
"src/mcp/ui/StatusBoard.tsx"() {
|
|
4667
4870
|
"use strict";
|
|
4668
|
-
StatusBoard = ({ exposedLabel, port, pid, running }) => {
|
|
4669
|
-
return /* @__PURE__ */
|
|
4670
|
-
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" }),
|
|
4671
4874
|
" ",
|
|
4672
4875
|
"\u2502",
|
|
4673
4876
|
" \u{1F4CB} ",
|
|
4674
|
-
/* @__PURE__ */
|
|
4877
|
+
/* @__PURE__ */ jsx9(Text8, { color: "yellow", children: exposedLabel }),
|
|
4675
4878
|
" ",
|
|
4676
4879
|
"\u2502",
|
|
4677
4880
|
" Port: ",
|
|
4678
|
-
/* @__PURE__ */
|
|
4881
|
+
/* @__PURE__ */ jsx9(Text8, { color: "green", children: port }),
|
|
4679
4882
|
" ",
|
|
4680
4883
|
"\u2502",
|
|
4681
4884
|
" PID: ",
|
|
4682
|
-
/* @__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
|
+
] })
|
|
4683
4891
|
] }) });
|
|
4684
4892
|
};
|
|
4685
4893
|
}
|
|
4686
4894
|
});
|
|
4687
4895
|
|
|
4688
4896
|
// src/mcp/ui/IndexingStatus.tsx
|
|
4689
|
-
import { useState as
|
|
4897
|
+
import { useState as useState5, useEffect as useEffect5 } from "react";
|
|
4690
4898
|
import { Box as Box9, Text as Text9 } from "ink";
|
|
4691
|
-
import { jsx as
|
|
4899
|
+
import { jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
4692
4900
|
var IndexingStatus;
|
|
4693
4901
|
var init_IndexingStatus = __esm({
|
|
4694
4902
|
"src/mcp/ui/IndexingStatus.tsx"() {
|
|
@@ -4698,9 +4906,9 @@ var init_IndexingStatus = __esm({
|
|
|
4698
4906
|
init_resources();
|
|
4699
4907
|
init_config_utils();
|
|
4700
4908
|
IndexingStatus = ({ projects, config }) => {
|
|
4701
|
-
const [stats, setStats] =
|
|
4702
|
-
const [loading, setLoading] =
|
|
4703
|
-
|
|
4909
|
+
const [stats, setStats] = useState5([]);
|
|
4910
|
+
const [loading, setLoading] = useState5(true);
|
|
4911
|
+
useEffect5(() => {
|
|
4704
4912
|
const fetchStats = async () => {
|
|
4705
4913
|
const newStats = [];
|
|
4706
4914
|
for (const project of projects) {
|
|
@@ -4762,27 +4970,27 @@ var init_IndexingStatus = __esm({
|
|
|
4762
4970
|
return () => clearInterval(interval);
|
|
4763
4971
|
}, [projects, config]);
|
|
4764
4972
|
if (loading && stats.length === 0) {
|
|
4765
|
-
return /* @__PURE__ */
|
|
4973
|
+
return /* @__PURE__ */ jsx10(Text9, { children: "Loading indexing status..." });
|
|
4766
4974
|
}
|
|
4767
4975
|
return /* @__PURE__ */ jsxs8(Box9, { flexDirection: "column", padding: 1, borderStyle: "round", borderColor: "blue", flexGrow: 1, children: [
|
|
4768
|
-
/* @__PURE__ */
|
|
4976
|
+
/* @__PURE__ */ jsx10(Text9, { bold: true, color: "blue", children: " RAG Indexing Status " }),
|
|
4769
4977
|
/* @__PURE__ */ jsxs8(Box9, { marginTop: 1, flexDirection: "column", children: [
|
|
4770
4978
|
/* @__PURE__ */ jsxs8(Box9, { children: [
|
|
4771
|
-
/* @__PURE__ */
|
|
4772
|
-
/* @__PURE__ */
|
|
4773
|
-
/* @__PURE__ */
|
|
4774
|
-
/* @__PURE__ */
|
|
4775
|
-
/* @__PURE__ */
|
|
4776
|
-
/* @__PURE__ */
|
|
4777
|
-
/* @__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" }) })
|
|
4778
4986
|
] }),
|
|
4779
|
-
stats.length === 0 ? /* @__PURE__ */
|
|
4780
|
-
/* @__PURE__ */
|
|
4781
|
-
/* @__PURE__ */
|
|
4782
|
-
/* @__PURE__ */
|
|
4783
|
-
/* @__PURE__ */
|
|
4784
|
-
/* @__PURE__ */
|
|
4785
|
-
/* @__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() : "-" }) })
|
|
4786
4994
|
] }, s.projectName))
|
|
4787
4995
|
] })
|
|
4788
4996
|
] });
|
|
@@ -4793,7 +5001,7 @@ var init_IndexingStatus = __esm({
|
|
|
4793
5001
|
// src/mcp/ui/components/TabBar.tsx
|
|
4794
5002
|
import "react";
|
|
4795
5003
|
import { Box as Box10, Text as Text10, useInput as useInput3 } from "ink";
|
|
4796
|
-
import { jsx as
|
|
5004
|
+
import { jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
4797
5005
|
var TabBar;
|
|
4798
5006
|
var init_TabBar = __esm({
|
|
4799
5007
|
"src/mcp/ui/components/TabBar.tsx"() {
|
|
@@ -4823,7 +5031,7 @@ var init_TabBar = __esm({
|
|
|
4823
5031
|
return /* @__PURE__ */ jsxs9(Box10, { borderStyle: "single", paddingX: 1, borderColor: "gray", children: [
|
|
4824
5032
|
tabs.map((tab, index) => {
|
|
4825
5033
|
const isActive = tab.id === activeTab;
|
|
4826
|
-
return /* @__PURE__ */
|
|
5034
|
+
return /* @__PURE__ */ jsx11(Box10, { marginRight: 2, children: /* @__PURE__ */ jsx11(
|
|
4827
5035
|
Text10,
|
|
4828
5036
|
{
|
|
4829
5037
|
color: isActive ? "cyan" : "white",
|
|
@@ -4833,8 +5041,8 @@ var init_TabBar = __esm({
|
|
|
4833
5041
|
}
|
|
4834
5042
|
) }, tab.id);
|
|
4835
5043
|
}),
|
|
4836
|
-
/* @__PURE__ */
|
|
4837
|
-
/* @__PURE__ */
|
|
5044
|
+
/* @__PURE__ */ jsx11(Box10, { flexGrow: 1 }),
|
|
5045
|
+
/* @__PURE__ */ jsx11(Text10, { color: "dim", children: "Use \u25C4/\u25BA arrows to navigate" })
|
|
4838
5046
|
] });
|
|
4839
5047
|
};
|
|
4840
5048
|
}
|
|
@@ -4845,10 +5053,10 @@ var App_exports = {};
|
|
|
4845
5053
|
__export(App_exports, {
|
|
4846
5054
|
App: () => App
|
|
4847
5055
|
});
|
|
4848
|
-
import { useState as
|
|
5056
|
+
import { useState as useState6, useEffect as useEffect6, useMemo as useMemo4, useCallback as useCallback3 } from "react";
|
|
4849
5057
|
import { Box as Box11, useInput as useInput4, useApp } from "ink";
|
|
4850
|
-
import
|
|
4851
|
-
import { jsx as
|
|
5058
|
+
import fs20 from "fs";
|
|
5059
|
+
import { jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
4852
5060
|
var App;
|
|
4853
5061
|
var init_App = __esm({
|
|
4854
5062
|
"src/mcp/ui/App.tsx"() {
|
|
@@ -4868,32 +5076,28 @@ var init_App = __esm({
|
|
|
4868
5076
|
init_resources();
|
|
4869
5077
|
init_install();
|
|
4870
5078
|
init_paths();
|
|
5079
|
+
init_ConfigContext();
|
|
4871
5080
|
App = ({ onExit, initialPort }) => {
|
|
4872
5081
|
const { exit } = useApp();
|
|
4873
|
-
const
|
|
4874
|
-
const [
|
|
4875
|
-
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({
|
|
4876
5086
|
port: initialPort,
|
|
4877
5087
|
pid: process.pid,
|
|
4878
5088
|
running: false
|
|
4879
5089
|
});
|
|
4880
|
-
const
|
|
4881
|
-
const [projects, setProjects] = useState5(() => scanForProjects());
|
|
4882
|
-
const refreshData = useCallback(() => {
|
|
4883
|
-
setConfig(loadMCPConfig());
|
|
4884
|
-
setProjects(scanForProjects());
|
|
4885
|
-
}, []);
|
|
4886
|
-
const exposedProjects = useMemo3(
|
|
4887
|
-
() => projects.filter((p) => isProjectExposed(config, p.name, p.path)),
|
|
4888
|
-
[projects, config]
|
|
4889
|
-
);
|
|
4890
|
-
const isRAGEnabled = useMemo3(() => {
|
|
5090
|
+
const isRAGEnabled = useMemo4(() => {
|
|
4891
5091
|
return exposedProjects.some((p) => {
|
|
4892
5092
|
const cfg = findProjectConfig(config, { name: p.name, path: p.path });
|
|
4893
5093
|
return cfg?.semanticSearch?.enabled || p.semanticSearchEnabled;
|
|
4894
5094
|
});
|
|
4895
5095
|
}, [exposedProjects, config]);
|
|
4896
|
-
const
|
|
5096
|
+
const hasAnyDrift = useMemo4(
|
|
5097
|
+
() => Object.values(driftReports).some((r) => r.hasDrift),
|
|
5098
|
+
[driftReports]
|
|
5099
|
+
);
|
|
5100
|
+
const tabs = useMemo4(() => {
|
|
4897
5101
|
const baseTabs = [
|
|
4898
5102
|
{ id: "overview", label: "Overview" },
|
|
4899
5103
|
{ id: "logs", label: "Logs" },
|
|
@@ -4913,7 +5117,7 @@ var init_App = __esm({
|
|
|
4913
5117
|
installStatus.vscodeGlobal,
|
|
4914
5118
|
installStatus.vscodeWorkspace
|
|
4915
5119
|
].filter(Boolean).length;
|
|
4916
|
-
|
|
5120
|
+
useEffect6(() => {
|
|
4917
5121
|
const start = async () => {
|
|
4918
5122
|
const status = getMCPServerStatus();
|
|
4919
5123
|
if (!status.running) {
|
|
@@ -4929,21 +5133,21 @@ var init_App = __esm({
|
|
|
4929
5133
|
};
|
|
4930
5134
|
start();
|
|
4931
5135
|
}, []);
|
|
4932
|
-
|
|
5136
|
+
useEffect6(() => {
|
|
4933
5137
|
const logPath = getLogFilePath();
|
|
4934
5138
|
let lastSize = 0;
|
|
4935
|
-
if (
|
|
4936
|
-
const stats =
|
|
5139
|
+
if (fs20.existsSync(logPath)) {
|
|
5140
|
+
const stats = fs20.statSync(logPath);
|
|
4937
5141
|
lastSize = stats.size;
|
|
4938
5142
|
}
|
|
4939
5143
|
const interval = setInterval(() => {
|
|
4940
|
-
if (
|
|
4941
|
-
const stats =
|
|
5144
|
+
if (fs20.existsSync(logPath)) {
|
|
5145
|
+
const stats = fs20.statSync(logPath);
|
|
4942
5146
|
if (stats.size > lastSize) {
|
|
4943
5147
|
const buffer = Buffer.alloc(stats.size - lastSize);
|
|
4944
|
-
const fd =
|
|
4945
|
-
|
|
4946
|
-
|
|
5148
|
+
const fd = fs20.openSync(logPath, "r");
|
|
5149
|
+
fs20.readSync(fd, buffer, 0, buffer.length, lastSize);
|
|
5150
|
+
fs20.closeSync(fd);
|
|
4947
5151
|
const newContent = buffer.toString("utf-8");
|
|
4948
5152
|
const newLines = newContent.split("\n").filter((l) => l.trim());
|
|
4949
5153
|
setLogs((prev) => {
|
|
@@ -4977,13 +5181,13 @@ var init_App = __esm({
|
|
|
4977
5181
|
});
|
|
4978
5182
|
const termHeight = process.stdout.rows || 24;
|
|
4979
5183
|
const contentHeight = termHeight - 8;
|
|
4980
|
-
const handleConfigChange =
|
|
5184
|
+
const handleConfigChange = useCallback3(() => {
|
|
4981
5185
|
refreshData();
|
|
4982
5186
|
}, [refreshData]);
|
|
4983
5187
|
return /* @__PURE__ */ jsxs10(Box11, { flexDirection: "column", padding: 0, height: termHeight, children: [
|
|
4984
|
-
/* @__PURE__ */
|
|
5188
|
+
/* @__PURE__ */ jsx12(TabBar, { tabs, activeTab, onChange: setActiveTab }),
|
|
4985
5189
|
/* @__PURE__ */ jsxs10(Box11, { marginTop: 1, flexGrow: 1, children: [
|
|
4986
|
-
activeTab === "overview" && /* @__PURE__ */
|
|
5190
|
+
activeTab === "overview" && /* @__PURE__ */ jsx12(
|
|
4987
5191
|
Overview,
|
|
4988
5192
|
{
|
|
4989
5193
|
serverStatus: serverInfo,
|
|
@@ -4994,18 +5198,19 @@ var init_App = __esm({
|
|
|
4994
5198
|
}
|
|
4995
5199
|
}
|
|
4996
5200
|
),
|
|
4997
|
-
activeTab === "projects" && /* @__PURE__ */
|
|
4998
|
-
activeTab === "indexing" && /* @__PURE__ */
|
|
4999
|
-
activeTab === "install" && /* @__PURE__ */
|
|
5000
|
-
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 })
|
|
5001
5205
|
] }),
|
|
5002
|
-
/* @__PURE__ */
|
|
5206
|
+
/* @__PURE__ */ jsx12(Box11, { marginTop: 0, children: /* @__PURE__ */ jsx12(
|
|
5003
5207
|
StatusBoard,
|
|
5004
5208
|
{
|
|
5005
5209
|
exposedLabel: `${exposedProjects.length} / ${projects.length} projects`,
|
|
5006
5210
|
port: serverInfo.port,
|
|
5007
5211
|
pid: serverInfo.pid,
|
|
5008
|
-
running: serverInfo.running
|
|
5212
|
+
running: serverInfo.running,
|
|
5213
|
+
hasDrift: hasAnyDrift
|
|
5009
5214
|
}
|
|
5010
5215
|
) })
|
|
5011
5216
|
] });
|
|
@@ -5016,9 +5221,10 @@ var init_App = __esm({
|
|
|
5016
5221
|
// src/mcp/commands/start.ts
|
|
5017
5222
|
import { confirm as confirm3, isCancel as isCancel5, text } from "@clack/prompts";
|
|
5018
5223
|
async function handleStartServer() {
|
|
5019
|
-
const
|
|
5224
|
+
const React13 = await import("react");
|
|
5020
5225
|
const { render } = await import("ink");
|
|
5021
5226
|
const { App: App2 } = await Promise.resolve().then(() => (init_App(), App_exports));
|
|
5227
|
+
const { ConfigProvider: ConfigProvider2 } = await Promise.resolve().then(() => (init_ConfigContext(), ConfigContext_exports));
|
|
5022
5228
|
const config = loadMCPConfig();
|
|
5023
5229
|
const projects = scanForProjects();
|
|
5024
5230
|
const exposedProjects = projects.filter((p) => {
|
|
@@ -5057,13 +5263,20 @@ async function handleStartServer() {
|
|
|
5057
5263
|
}
|
|
5058
5264
|
}
|
|
5059
5265
|
process.stdin.resume();
|
|
5060
|
-
const app = render(
|
|
5061
|
-
|
|
5062
|
-
|
|
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
|
|
5063
5278
|
}
|
|
5064
|
-
|
|
5065
|
-
exitOnCtrlC: false
|
|
5066
|
-
});
|
|
5279
|
+
);
|
|
5067
5280
|
await app.waitUntilExit();
|
|
5068
5281
|
console.clear();
|
|
5069
5282
|
}
|
|
@@ -5154,7 +5367,7 @@ var init_mcp = __esm({
|
|
|
5154
5367
|
// src/commands/wizard/index.ts
|
|
5155
5368
|
import { intro as intro2, select as select5, spinner as spinner7, note as note11, outro as outro7, isCancel as isCancel12 } from "@clack/prompts";
|
|
5156
5369
|
import pc13 from "picocolors";
|
|
5157
|
-
import * as
|
|
5370
|
+
import * as fs25 from "fs";
|
|
5158
5371
|
|
|
5159
5372
|
// src/lib/git.ts
|
|
5160
5373
|
import { execSync } from "child_process";
|
|
@@ -5302,6 +5515,7 @@ import { stringify as stringify2 } from "yaml";
|
|
|
5302
5515
|
init_paths();
|
|
5303
5516
|
import * as fs7 from "fs";
|
|
5304
5517
|
import * as path8 from "path";
|
|
5518
|
+
import * as os2 from "os";
|
|
5305
5519
|
import "yaml";
|
|
5306
5520
|
function copyPromptsToDir(prompts, targetDir, extension) {
|
|
5307
5521
|
for (const prompt of prompts) {
|
|
@@ -5312,10 +5526,37 @@ function copyPromptsToDir(prompts, targetDir, extension) {
|
|
|
5312
5526
|
fs7.writeFileSync(targetPath, content);
|
|
5313
5527
|
}
|
|
5314
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
|
+
}
|
|
5315
5556
|
function convertToOpenCodeAgent(prompt, useFileReference = false, promptFilePath) {
|
|
5316
5557
|
const { frontmatter, content } = prompt;
|
|
5317
5558
|
const tools = {};
|
|
5318
|
-
const hostTools = ["read", "write", "edit", "bash", "grep", "glob", "webfetch", "terminalLastCommand"];
|
|
5559
|
+
const hostTools = ["read", "write", "edit", "bash", "grep", "glob", "webfetch", "terminalLastCommand", "task"];
|
|
5319
5560
|
if (frontmatter.tools) {
|
|
5320
5561
|
for (const tool of frontmatter.tools) {
|
|
5321
5562
|
if (hostTools.includes(tool)) {
|
|
@@ -5326,10 +5567,11 @@ function convertToOpenCodeAgent(prompt, useFileReference = false, promptFilePath
|
|
|
5326
5567
|
}
|
|
5327
5568
|
}
|
|
5328
5569
|
tools["webfetch"] = true;
|
|
5329
|
-
const
|
|
5570
|
+
const mode = frontmatter.mode || "subagent";
|
|
5571
|
+
const invocationHint = mode === "primary" ? "" : " (Invoke via @rrce_*)";
|
|
5330
5572
|
return {
|
|
5331
5573
|
description: `${frontmatter.description}${invocationHint}`,
|
|
5332
|
-
mode
|
|
5574
|
+
mode,
|
|
5333
5575
|
prompt: useFileReference && promptFilePath ? `{file:${promptFilePath}}` : content,
|
|
5334
5576
|
tools
|
|
5335
5577
|
};
|
|
@@ -5491,6 +5733,9 @@ async function installAgentPrompts(config, workspacePath, dataPaths) {
|
|
|
5491
5733
|
const agentConfig = convertToOpenCodeAgent(prompt, true, `./prompts/${promptFileName}`);
|
|
5492
5734
|
opencodeConfig.agent[agentId] = agentConfig;
|
|
5493
5735
|
}
|
|
5736
|
+
if (!opencodeConfig.agent) opencodeConfig.agent = {};
|
|
5737
|
+
if (!opencodeConfig.agent.plan) opencodeConfig.agent.plan = {};
|
|
5738
|
+
opencodeConfig.agent.plan.disable = true;
|
|
5494
5739
|
fs10.writeFileSync(OPENCODE_CONFIG, JSON.stringify(opencodeConfig, null, 2) + "\n");
|
|
5495
5740
|
} catch (e) {
|
|
5496
5741
|
console.error("Failed to update global OpenCode config with agents:", e);
|
|
@@ -5565,8 +5810,8 @@ linked_projects:
|
|
|
5565
5810
|
async function registerWithMCP(config, workspacePath, workspaceName) {
|
|
5566
5811
|
if (!config.exposeToMCP) return;
|
|
5567
5812
|
try {
|
|
5568
|
-
const { loadMCPConfig:
|
|
5569
|
-
const mcpConfig =
|
|
5813
|
+
const { loadMCPConfig: loadMCPConfig3, saveMCPConfig: saveMCPConfig2, setProjectConfig: setProjectConfig2 } = await Promise.resolve().then(() => (init_config(), config_exports));
|
|
5814
|
+
const mcpConfig = loadMCPConfig3();
|
|
5570
5815
|
setProjectConfig2(
|
|
5571
5816
|
mcpConfig,
|
|
5572
5817
|
workspaceName,
|
|
@@ -5831,7 +6076,7 @@ async function handlePostSetup(config, workspacePath, workspaceName, linkedProje
|
|
|
5831
6076
|
init_paths();
|
|
5832
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";
|
|
5833
6078
|
import pc9 from "picocolors";
|
|
5834
|
-
import * as
|
|
6079
|
+
import * as fs21 from "fs";
|
|
5835
6080
|
init_detection();
|
|
5836
6081
|
async function runLinkProjectsFlow(workspacePath, workspaceName) {
|
|
5837
6082
|
const projects = scanForProjects({
|
|
@@ -5870,7 +6115,7 @@ async function runLinkProjectsFlow(workspacePath, workspaceName) {
|
|
|
5870
6115
|
const s = spinner3();
|
|
5871
6116
|
s.start("Linking projects");
|
|
5872
6117
|
const configFilePath = getConfigPath(workspacePath);
|
|
5873
|
-
let configContent =
|
|
6118
|
+
let configContent = fs21.readFileSync(configFilePath, "utf-8");
|
|
5874
6119
|
if (configContent.includes("linked_projects:")) {
|
|
5875
6120
|
const lines = configContent.split("\n");
|
|
5876
6121
|
const linkedIndex = lines.findIndex((l) => l.trim() === "linked_projects:");
|
|
@@ -5897,7 +6142,7 @@ linked_projects:
|
|
|
5897
6142
|
`;
|
|
5898
6143
|
});
|
|
5899
6144
|
}
|
|
5900
|
-
|
|
6145
|
+
fs21.writeFileSync(configFilePath, configContent);
|
|
5901
6146
|
generateVSCodeWorkspace(workspacePath, workspaceName, selectedProjects, customGlobalPath);
|
|
5902
6147
|
s.stop("Projects linked");
|
|
5903
6148
|
const workspaceFile = `${workspaceName}.code-workspace`;
|
|
@@ -5915,8 +6160,8 @@ linked_projects:
|
|
|
5915
6160
|
});
|
|
5916
6161
|
if (shouldExpose && !isCancel8(shouldExpose)) {
|
|
5917
6162
|
try {
|
|
5918
|
-
const { loadMCPConfig:
|
|
5919
|
-
const mcpConfig =
|
|
6163
|
+
const { loadMCPConfig: loadMCPConfig3, saveMCPConfig: saveMCPConfig2, setProjectConfig: setProjectConfig2 } = await Promise.resolve().then(() => (init_config(), config_exports));
|
|
6164
|
+
const mcpConfig = loadMCPConfig3();
|
|
5920
6165
|
for (const project of selectedProjects) {
|
|
5921
6166
|
setProjectConfig2(mcpConfig, project.name, true, void 0, project.dataPath);
|
|
5922
6167
|
}
|
|
@@ -5932,15 +6177,15 @@ linked_projects:
|
|
|
5932
6177
|
init_paths();
|
|
5933
6178
|
import { confirm as confirm7, spinner as spinner4, note as note8, outro as outro4, cancel as cancel4, isCancel as isCancel9 } from "@clack/prompts";
|
|
5934
6179
|
import pc10 from "picocolors";
|
|
5935
|
-
import * as
|
|
5936
|
-
import * as
|
|
6180
|
+
import * as fs22 from "fs";
|
|
6181
|
+
import * as path22 from "path";
|
|
5937
6182
|
async function runSyncToGlobalFlow(workspacePath, workspaceName) {
|
|
5938
6183
|
const localPath = getLocalWorkspacePath(workspacePath);
|
|
5939
6184
|
const customGlobalPath = getEffectiveRRCEHome(workspacePath);
|
|
5940
|
-
const globalPath =
|
|
6185
|
+
const globalPath = path22.join(customGlobalPath, "workspaces", workspaceName);
|
|
5941
6186
|
const subdirs = ["knowledge", "prompts", "templates", "tasks", "refs"];
|
|
5942
6187
|
const existingDirs = subdirs.filter(
|
|
5943
|
-
(dir) =>
|
|
6188
|
+
(dir) => fs22.existsSync(path22.join(localPath, dir))
|
|
5944
6189
|
);
|
|
5945
6190
|
if (existingDirs.length === 0) {
|
|
5946
6191
|
outro4(pc10.yellow("No data found in workspace storage to sync."));
|
|
@@ -5966,8 +6211,8 @@ Destination: ${pc10.cyan(globalPath)}`,
|
|
|
5966
6211
|
try {
|
|
5967
6212
|
ensureDir(globalPath);
|
|
5968
6213
|
for (const dir of existingDirs) {
|
|
5969
|
-
const srcDir =
|
|
5970
|
-
const destDir =
|
|
6214
|
+
const srcDir = path22.join(localPath, dir);
|
|
6215
|
+
const destDir = path22.join(globalPath, dir);
|
|
5971
6216
|
ensureDir(destDir);
|
|
5972
6217
|
copyDirRecursive(srcDir, destDir);
|
|
5973
6218
|
}
|
|
@@ -5994,29 +6239,74 @@ init_paths();
|
|
|
5994
6239
|
init_prompts();
|
|
5995
6240
|
import { confirm as confirm8, spinner as spinner5, note as note9, outro as outro5, cancel as cancel5, isCancel as isCancel10 } from "@clack/prompts";
|
|
5996
6241
|
import pc11 from "picocolors";
|
|
5997
|
-
import * as
|
|
5998
|
-
import * as
|
|
5999
|
-
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";
|
|
6000
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
|
+
}
|
|
6001
6270
|
async function runUpdateFlow(workspacePath, workspaceName, currentStorageMode) {
|
|
6002
6271
|
const s = spinner5();
|
|
6003
6272
|
s.start("Checking for updates");
|
|
6004
6273
|
try {
|
|
6005
6274
|
const agentCoreDir = getAgentCoreDir();
|
|
6006
6275
|
const prompts = loadPromptsFromDir(getAgentCorePromptsDir());
|
|
6276
|
+
const runningVersion = getPackageVersion2();
|
|
6007
6277
|
const mode = currentStorageMode || "global";
|
|
6008
6278
|
const customGlobalPath = getEffectiveRRCEHome(workspacePath);
|
|
6009
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);
|
|
6010
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
|
+
}
|
|
6011
6302
|
const updateTargets = [
|
|
6012
6303
|
` \u2022 prompts/ (${prompts.length} agent prompts)`,
|
|
6013
6304
|
` \u2022 templates/ (output templates)`,
|
|
6014
6305
|
` \u2022 docs/ (documentation)`
|
|
6015
6306
|
];
|
|
6016
|
-
const configFilePath = getConfigPath(workspacePath);
|
|
6017
6307
|
const ideTargets = [];
|
|
6018
|
-
if (
|
|
6019
|
-
const configContent =
|
|
6308
|
+
if (fs23.existsSync(configFilePath)) {
|
|
6309
|
+
const configContent = fs23.readFileSync(configFilePath, "utf-8");
|
|
6020
6310
|
if (configContent.includes("opencode: true")) ideTargets.push("OpenCode agents");
|
|
6021
6311
|
if (configContent.includes("copilot: true")) ideTargets.push("GitHub Copilot");
|
|
6022
6312
|
if (configContent.includes("antigravity: true")) ideTargets.push("Antigravity");
|
|
@@ -6042,17 +6332,41 @@ ${dataPaths.map((p) => ` \u2022 ${p}`).join("\n")}`,
|
|
|
6042
6332
|
}
|
|
6043
6333
|
s.start("Updating from package");
|
|
6044
6334
|
for (const dataPath of dataPaths) {
|
|
6045
|
-
|
|
6046
|
-
|
|
6047
|
-
|
|
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);
|
|
6048
6362
|
}
|
|
6049
6363
|
const rrceHome = customGlobalPath || getDefaultRRCEHome2();
|
|
6050
|
-
ensureDir(
|
|
6051
|
-
ensureDir(
|
|
6052
|
-
copyDirRecursive(
|
|
6053
|
-
copyDirRecursive(
|
|
6054
|
-
if (
|
|
6055
|
-
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");
|
|
6056
6370
|
if (configContent.includes("copilot: true")) {
|
|
6057
6371
|
const copilotPath = getAgentPromptPath(workspacePath, "copilot");
|
|
6058
6372
|
ensureDir(copilotPath);
|
|
@@ -6071,6 +6385,29 @@ ${dataPaths.map((p) => ` \u2022 ${p}`).join("\n")}`,
|
|
|
6071
6385
|
updateOpenCodeAgents(prompts, mode, primaryDataPath);
|
|
6072
6386
|
}
|
|
6073
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
|
+
}
|
|
6074
6411
|
}
|
|
6075
6412
|
s.stop("Update complete");
|
|
6076
6413
|
const summary = [
|
|
@@ -6082,6 +6419,9 @@ ${dataPaths.map((p) => ` \u2022 ${p}`).join("\n")}`,
|
|
|
6082
6419
|
if (ideTargets.length > 0) {
|
|
6083
6420
|
summary.push(` \u2713 IDE integrations: ${ideTargets.join(", ")}`);
|
|
6084
6421
|
}
|
|
6422
|
+
if (driftReport.modifiedFiles.length > 0) {
|
|
6423
|
+
summary.push(` \u2713 ${driftReport.modifiedFiles.length} modified files backed up`);
|
|
6424
|
+
}
|
|
6085
6425
|
summary.push(
|
|
6086
6426
|
``,
|
|
6087
6427
|
`Your configuration and knowledge files were preserved.`,
|
|
@@ -6099,48 +6439,35 @@ ${dataPaths.map((p) => ` \u2022 ${p}`).join("\n")}`,
|
|
|
6099
6439
|
function updateOpenCodeAgents(prompts, mode, primaryDataPath) {
|
|
6100
6440
|
if (mode === "global") {
|
|
6101
6441
|
try {
|
|
6102
|
-
const promptsDir =
|
|
6442
|
+
const promptsDir = path23.join(path23.dirname(OPENCODE_CONFIG), "prompts");
|
|
6103
6443
|
ensureDir(promptsDir);
|
|
6104
|
-
|
|
6105
|
-
if (fs21.existsSync(OPENCODE_CONFIG)) {
|
|
6106
|
-
opencodeConfig = JSON.parse(fs21.readFileSync(OPENCODE_CONFIG, "utf-8"));
|
|
6107
|
-
}
|
|
6108
|
-
if (!opencodeConfig.agent) opencodeConfig.agent = {};
|
|
6109
|
-
const currentAgentBaseNames = prompts.map((p) => path21.basename(p.filePath, ".md"));
|
|
6110
|
-
const currentAgentIds = new Set(currentAgentBaseNames.map((base) => `rrce_${base}`));
|
|
6111
|
-
const existingAgentNames = Object.keys(opencodeConfig.agent);
|
|
6112
|
-
for (const existingName of existingAgentNames) {
|
|
6113
|
-
const isLegacyBaseName = currentAgentBaseNames.includes(existingName);
|
|
6114
|
-
const isRrcePrefixed = existingName.startsWith("rrce_");
|
|
6115
|
-
const isStaleRrcePrefixed = isRrcePrefixed && !currentAgentIds.has(existingName);
|
|
6116
|
-
if (isLegacyBaseName || isStaleRrcePrefixed) {
|
|
6117
|
-
delete opencodeConfig.agent[existingName];
|
|
6118
|
-
const legacyBaseName = isLegacyBaseName ? existingName : existingName.replace(/^rrce_/, "");
|
|
6119
|
-
const oldPromptFile = path21.join(promptsDir, `rrce-${legacyBaseName}.md`);
|
|
6120
|
-
if (fs21.existsSync(oldPromptFile)) {
|
|
6121
|
-
fs21.unlinkSync(oldPromptFile);
|
|
6122
|
-
}
|
|
6123
|
-
}
|
|
6124
|
-
}
|
|
6444
|
+
const newAgents = {};
|
|
6125
6445
|
for (const prompt of prompts) {
|
|
6126
|
-
const baseName =
|
|
6446
|
+
const baseName = path23.basename(prompt.filePath, ".md");
|
|
6127
6447
|
const agentId = `rrce_${baseName}`;
|
|
6128
6448
|
const promptFileName = `rrce-${baseName}.md`;
|
|
6129
|
-
const promptFilePath =
|
|
6130
|
-
|
|
6449
|
+
const promptFilePath = path23.join(promptsDir, promptFileName);
|
|
6450
|
+
fs23.writeFileSync(promptFilePath, prompt.content);
|
|
6131
6451
|
const agentConfig = convertToOpenCodeAgent(prompt, true, `./prompts/${promptFileName}`);
|
|
6132
|
-
|
|
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));
|
|
6133
6461
|
}
|
|
6134
|
-
fs21.writeFileSync(OPENCODE_CONFIG, JSON.stringify(opencodeConfig, null, 2) + "\n");
|
|
6135
6462
|
} catch (e) {
|
|
6136
6463
|
console.error("Failed to update global OpenCode config with agents:", e);
|
|
6137
6464
|
}
|
|
6138
6465
|
} else {
|
|
6139
|
-
const opencodeBaseDir =
|
|
6466
|
+
const opencodeBaseDir = path23.join(primaryDataPath, ".opencode", "agent");
|
|
6140
6467
|
ensureDir(opencodeBaseDir);
|
|
6141
6468
|
clearDirectory(opencodeBaseDir);
|
|
6142
6469
|
for (const prompt of prompts) {
|
|
6143
|
-
const baseName =
|
|
6470
|
+
const baseName = path23.basename(prompt.filePath, ".md");
|
|
6144
6471
|
const agentId = `rrce_${baseName}`;
|
|
6145
6472
|
const agentConfig = convertToOpenCodeAgent(prompt);
|
|
6146
6473
|
const content = `---
|
|
@@ -6150,22 +6477,22 @@ ${stringify3({
|
|
|
6150
6477
|
tools: agentConfig.tools
|
|
6151
6478
|
})}---
|
|
6152
6479
|
${agentConfig.prompt}`;
|
|
6153
|
-
|
|
6480
|
+
fs23.writeFileSync(path23.join(opencodeBaseDir, `${agentId}.md`), content);
|
|
6154
6481
|
}
|
|
6155
6482
|
}
|
|
6156
6483
|
}
|
|
6157
6484
|
function clearDirectory(dirPath) {
|
|
6158
|
-
if (!
|
|
6159
|
-
const entries =
|
|
6485
|
+
if (!fs23.existsSync(dirPath)) return;
|
|
6486
|
+
const entries = fs23.readdirSync(dirPath, { withFileTypes: true });
|
|
6160
6487
|
for (const entry of entries) {
|
|
6161
6488
|
if (entry.isFile()) {
|
|
6162
|
-
|
|
6489
|
+
fs23.unlinkSync(path23.join(dirPath, entry.name));
|
|
6163
6490
|
}
|
|
6164
6491
|
}
|
|
6165
6492
|
}
|
|
6166
6493
|
function resolveAllDataPathsWithCustomGlobal(mode, workspaceName, workspaceRoot, customGlobalPath) {
|
|
6167
|
-
const globalPath =
|
|
6168
|
-
const workspacePath =
|
|
6494
|
+
const globalPath = path23.join(customGlobalPath, "workspaces", workspaceName);
|
|
6495
|
+
const workspacePath = path23.join(workspaceRoot, ".rrce-workflow");
|
|
6169
6496
|
switch (mode) {
|
|
6170
6497
|
case "global":
|
|
6171
6498
|
return [globalPath];
|
|
@@ -6179,7 +6506,7 @@ function resolveAllDataPathsWithCustomGlobal(mode, workspaceName, workspaceRoot,
|
|
|
6179
6506
|
// src/commands/wizard/delete-flow.ts
|
|
6180
6507
|
import { multiselect as multiselect5, confirm as confirm9, spinner as spinner6, note as note10, cancel as cancel6, isCancel as isCancel11 } from "@clack/prompts";
|
|
6181
6508
|
import pc12 from "picocolors";
|
|
6182
|
-
import * as
|
|
6509
|
+
import * as fs24 from "fs";
|
|
6183
6510
|
init_detection();
|
|
6184
6511
|
init_config();
|
|
6185
6512
|
async function runDeleteGlobalProjectFlow(availableProjects) {
|
|
@@ -6223,8 +6550,8 @@ Are you sure?`,
|
|
|
6223
6550
|
for (const projectName of projectsToDelete) {
|
|
6224
6551
|
const project = globalProjects.find((p) => p.name === projectName);
|
|
6225
6552
|
if (!project) continue;
|
|
6226
|
-
if (
|
|
6227
|
-
|
|
6553
|
+
if (fs24.existsSync(project.dataPath)) {
|
|
6554
|
+
fs24.rmSync(project.dataPath, { recursive: true, force: true });
|
|
6228
6555
|
}
|
|
6229
6556
|
const newConfig = removeProjectConfig(mcpConfig, projectName);
|
|
6230
6557
|
configChanged = true;
|
|
@@ -6270,11 +6597,11 @@ Workspace: ${pc13.bold(workspaceName)}`,
|
|
|
6270
6597
|
workspacePath
|
|
6271
6598
|
});
|
|
6272
6599
|
const configFilePath = getConfigPath(workspacePath);
|
|
6273
|
-
let isAlreadyConfigured =
|
|
6600
|
+
let isAlreadyConfigured = fs25.existsSync(configFilePath);
|
|
6274
6601
|
let currentStorageMode = null;
|
|
6275
6602
|
if (isAlreadyConfigured) {
|
|
6276
6603
|
try {
|
|
6277
|
-
const configContent =
|
|
6604
|
+
const configContent = fs25.readFileSync(configFilePath, "utf-8");
|
|
6278
6605
|
const modeMatch = configContent.match(/mode:\s*(global|workspace)/);
|
|
6279
6606
|
currentStorageMode = modeMatch?.[1] ?? null;
|
|
6280
6607
|
} catch {
|
|
@@ -6291,7 +6618,7 @@ Workspace: ${pc13.bold(workspaceName)}`,
|
|
|
6291
6618
|
}
|
|
6292
6619
|
}
|
|
6293
6620
|
const localDataPath = getLocalWorkspacePath(workspacePath);
|
|
6294
|
-
const hasLocalData =
|
|
6621
|
+
const hasLocalData = fs25.existsSync(localDataPath);
|
|
6295
6622
|
if (isAlreadyConfigured) {
|
|
6296
6623
|
const menuOptions = [];
|
|
6297
6624
|
menuOptions.push({
|