rrce-workflow 0.2.24 → 0.2.26

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.
Files changed (2) hide show
  1. package/dist/index.js +129 -101
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -865,6 +865,13 @@ function getExposedProjects() {
865
865
  const allProjects = scanForProjects();
866
866
  return allProjects.filter((project) => isProjectExposed(config, project.name));
867
867
  }
868
+ function detectActiveProject() {
869
+ const exposed = getExposedProjects();
870
+ const cwd = process.cwd();
871
+ const matches = exposed.filter((p) => cwd.startsWith(p.path));
872
+ matches.sort((a, b) => b.path.length - a.path.length);
873
+ return matches[0];
874
+ }
868
875
  function getProjectContext(projectName) {
869
876
  const config = loadMCPConfig();
870
877
  if (!isProjectExposed(config, projectName)) {
@@ -961,64 +968,46 @@ var init_resources = __esm({
961
968
  });
962
969
 
963
970
  // src/mcp/prompts.ts
964
- var AGENT_PROMPTS;
971
+ function getAllPrompts() {
972
+ const prompts = loadPromptsFromDir(getAgentCorePromptsDir());
973
+ return prompts.map((p) => {
974
+ const args = [];
975
+ if (p.frontmatter["required-args"]) {
976
+ args.push(...p.frontmatter["required-args"].map((a) => ({
977
+ name: a.name,
978
+ description: a.prompt || a.name,
979
+ required: true
980
+ })));
981
+ }
982
+ if (p.frontmatter["optional-args"]) {
983
+ args.push(...p.frontmatter["optional-args"].map((a) => ({
984
+ name: a.name,
985
+ description: a.prompt || a.name,
986
+ required: false
987
+ })));
988
+ }
989
+ return {
990
+ name: p.frontmatter.name,
991
+ description: p.frontmatter.description,
992
+ arguments: args,
993
+ content: p.content
994
+ };
995
+ });
996
+ }
997
+ function getPromptDef(name) {
998
+ return getAllPrompts().find((p) => p.name === name);
999
+ }
1000
+ function renderPrompt(content, args) {
1001
+ let rendered = content;
1002
+ for (const [key, val] of Object.entries(args)) {
1003
+ rendered = rendered.replace(new RegExp(`{{${key}}}`, "g"), val);
1004
+ }
1005
+ return rendered;
1006
+ }
965
1007
  var init_prompts2 = __esm({
966
1008
  "src/mcp/prompts.ts"() {
967
1009
  "use strict";
968
- AGENT_PROMPTS = [
969
- {
970
- name: "init",
971
- description: "Initialize project context by analyzing codebase structure, tech stack, and conventions",
972
- file: "init.md",
973
- arguments: [
974
- { name: "PROJECT_NAME", description: "Project name (optional, auto-detected if omitted)", required: false }
975
- ]
976
- },
977
- {
978
- name: "research",
979
- description: "Research and clarify requirements for a new task",
980
- file: "research_discussion.md",
981
- arguments: [
982
- { name: "REQUEST", description: "Description of the task or feature to research", required: true },
983
- { name: "TASK_SLUG", description: "Kebab-case identifier for the task", required: true },
984
- { name: "TITLE", description: "Human-readable title for the task", required: false }
985
- ]
986
- },
987
- {
988
- name: "plan",
989
- description: "Create an actionable execution plan from research findings",
990
- file: "planning_orchestrator.md",
991
- arguments: [
992
- { name: "TASK_SLUG", description: "Task slug to create plan for", required: true }
993
- ]
994
- },
995
- {
996
- name: "execute",
997
- description: "Implement the planned work with code and tests",
998
- file: "executor.md",
999
- arguments: [
1000
- { name: "TASK_SLUG", description: "Task slug to execute", required: true },
1001
- { name: "BRANCH", description: "Git branch reference (optional)", required: false }
1002
- ]
1003
- },
1004
- {
1005
- name: "docs",
1006
- description: "Generate documentation for completed work",
1007
- file: "documentation.md",
1008
- arguments: [
1009
- { name: "DOC_TYPE", description: "Type of documentation (api, architecture, runbook, changelog)", required: true },
1010
- { name: "TASK_SLUG", description: "Task slug if documenting specific task", required: false }
1011
- ]
1012
- },
1013
- {
1014
- name: "sync",
1015
- description: "Reconcile knowledge base with actual codebase state",
1016
- file: "sync.md",
1017
- arguments: [
1018
- { name: "SCOPE", description: "Specific path or module to sync (optional)", required: false }
1019
- ]
1020
- }
1021
- ];
1010
+ init_prompts();
1022
1011
  }
1023
1012
  });
1024
1013
 
@@ -1033,8 +1022,6 @@ import {
1033
1022
  ListPromptsRequestSchema,
1034
1023
  GetPromptRequestSchema
1035
1024
  } from "@modelcontextprotocol/sdk/types.js";
1036
- import * as fs15 from "fs";
1037
- import * as path14 from "path";
1038
1025
  async function startMCPServer() {
1039
1026
  try {
1040
1027
  logger.info("Starting MCP Server...");
@@ -1202,31 +1189,72 @@ function registerToolHandlers(server) {
1202
1189
  });
1203
1190
  }
1204
1191
  function registerPromptHandlers(server) {
1205
- server.setRequestHandler(ListPromptsRequestSchema, async () => ({
1206
- prompts: AGENT_PROMPTS.map((p) => ({
1207
- name: p.name,
1208
- description: p.description,
1209
- arguments: p.arguments.map((a) => ({ name: a.name, description: a.description, required: a.required }))
1210
- }))
1211
- }));
1192
+ server.setRequestHandler(ListPromptsRequestSchema, async () => {
1193
+ logger.debug("Listing prompts");
1194
+ const prompts = getAllPrompts();
1195
+ return {
1196
+ prompts: prompts.map((p) => ({
1197
+ name: p.name,
1198
+ description: p.description,
1199
+ arguments: p.arguments.map((a) => ({
1200
+ name: a.name,
1201
+ description: a.description,
1202
+ required: a.required
1203
+ }))
1204
+ }))
1205
+ };
1206
+ });
1212
1207
  server.setRequestHandler(GetPromptRequestSchema, async (request) => {
1213
1208
  const { name, arguments: args } = request.params;
1214
1209
  logger.info(`Getting prompt: ${name}`, args);
1210
+ const promptDef = getPromptDef(name);
1211
+ if (!promptDef) {
1212
+ logger.error(`Prompt not found: ${name}`);
1213
+ throw new Error(`Prompt not found: ${name}`);
1214
+ }
1215
1215
  try {
1216
- const promptDef = AGENT_PROMPTS.find((p) => p.name === name);
1217
- if (!promptDef) throw new Error(`Unknown prompt: ${name}`);
1218
- const promptsDir = getAgentCorePromptsDir();
1219
- const promptPath = path14.join(promptsDir, promptDef.file);
1220
- if (!fs15.existsSync(promptPath)) throw new Error(`Prompt file not found: ${promptDef.file}`);
1221
- let promptContent = fs15.readFileSync(promptPath, "utf-8");
1222
- if (args) {
1223
- for (const [key, value] of Object.entries(args)) {
1224
- promptContent = promptContent.replace(new RegExp(`\\{\\{${key}\\}\\}`, "g"), String(value));
1225
- }
1216
+ const providedArgs = args || {};
1217
+ const missingArgs = promptDef.arguments.filter((a) => a.required && !providedArgs[a.name]).map((a) => a.name);
1218
+ if (missingArgs.length > 0) {
1219
+ throw new Error(`Missing required arguments: ${missingArgs.join(", ")}`);
1220
+ }
1221
+ const renderArgs = {};
1222
+ for (const [key, val] of Object.entries(providedArgs)) {
1223
+ renderArgs[key] = String(val);
1226
1224
  }
1225
+ const content = renderPrompt(promptDef.content, renderArgs);
1226
+ const projects = getExposedProjects();
1227
+ const activeProject = detectActiveProject();
1228
+ const projectList = projects.map((p) => {
1229
+ const isActive = activeProject && p.dataPath === activeProject.dataPath;
1230
+ return `- ${p.name} (${p.source}) ${isActive ? "**[ACTIVE]**" : ""}`;
1231
+ }).join("\n");
1232
+ let contextPreamble = `
1233
+ Context - Available Projects (MCP Hub):
1234
+ ${projectList}
1235
+ `;
1236
+ if (activeProject) {
1237
+ contextPreamble += `
1238
+ Current Active Workspace: ${activeProject.name} (${activeProject.path})
1239
+ `;
1240
+ contextPreamble += `IMPORTANT: Treat '${activeProject.path}' as the {{WORKSPACE_ROOT}}. All relative path operations (file reads/writes) MUST be performed relative to this directory.
1241
+ `;
1242
+ }
1243
+ contextPreamble += `
1244
+ Note: If the user's request refers to a project not listed here, ask them to expose it via 'rrce-workflow mcp configure'.
1245
+
1246
+ ---
1247
+ `;
1227
1248
  return {
1228
- description: promptDef.description,
1229
- messages: [{ role: "user", content: { type: "text", text: promptContent } }]
1249
+ messages: [
1250
+ {
1251
+ role: "user",
1252
+ content: {
1253
+ type: "text",
1254
+ text: contextPreamble + content
1255
+ }
1256
+ }
1257
+ ]
1230
1258
  };
1231
1259
  } catch (error) {
1232
1260
  logger.error(`Failed to get prompt: ${name}`, error);
@@ -1262,8 +1290,8 @@ var init_server = __esm({
1262
1290
  });
1263
1291
 
1264
1292
  // src/mcp/install.ts
1265
- import * as fs16 from "fs";
1266
- import * as path15 from "path";
1293
+ import * as fs15 from "fs";
1294
+ import * as path14 from "path";
1267
1295
  import * as os from "os";
1268
1296
  function checkInstallStatus() {
1269
1297
  return {
@@ -1272,9 +1300,9 @@ function checkInstallStatus() {
1272
1300
  };
1273
1301
  }
1274
1302
  function checkConfigFile(configPath) {
1275
- if (!fs16.existsSync(configPath)) return false;
1303
+ if (!fs15.existsSync(configPath)) return false;
1276
1304
  try {
1277
- const content = JSON.parse(fs16.readFileSync(configPath, "utf-8"));
1305
+ const content = JSON.parse(fs15.readFileSync(configPath, "utf-8"));
1278
1306
  return !!content.mcpServers?.["rrce"];
1279
1307
  } catch {
1280
1308
  return false;
@@ -1282,14 +1310,14 @@ function checkConfigFile(configPath) {
1282
1310
  }
1283
1311
  function installToConfig(target) {
1284
1312
  const configPath = target === "antigravity" ? ANTIGRAVITY_CONFIG : CLAUDE_CONFIG;
1285
- const dir = path15.dirname(configPath);
1286
- if (!fs16.existsSync(dir)) {
1287
- fs16.mkdirSync(dir, { recursive: true });
1313
+ const dir = path14.dirname(configPath);
1314
+ if (!fs15.existsSync(dir)) {
1315
+ fs15.mkdirSync(dir, { recursive: true });
1288
1316
  }
1289
1317
  let config = { mcpServers: {} };
1290
- if (fs16.existsSync(configPath)) {
1318
+ if (fs15.existsSync(configPath)) {
1291
1319
  try {
1292
- config = JSON.parse(fs16.readFileSync(configPath, "utf-8"));
1320
+ config = JSON.parse(fs15.readFileSync(configPath, "utf-8"));
1293
1321
  } catch {
1294
1322
  }
1295
1323
  }
@@ -1300,7 +1328,7 @@ function installToConfig(target) {
1300
1328
  // -y to avoid interactive prompts
1301
1329
  };
1302
1330
  try {
1303
- fs16.writeFileSync(configPath, JSON.stringify(config, null, 2));
1331
+ fs15.writeFileSync(configPath, JSON.stringify(config, null, 2));
1304
1332
  return true;
1305
1333
  } catch {
1306
1334
  return false;
@@ -1310,8 +1338,8 @@ var ANTIGRAVITY_CONFIG, CLAUDE_CONFIG;
1310
1338
  var init_install = __esm({
1311
1339
  "src/mcp/install.ts"() {
1312
1340
  "use strict";
1313
- ANTIGRAVITY_CONFIG = path15.join(os.homedir(), ".gemini/antigravity/mcp_config.json");
1314
- CLAUDE_CONFIG = path15.join(os.homedir(), ".config/claude/claude_desktop_config.json");
1341
+ ANTIGRAVITY_CONFIG = path14.join(os.homedir(), ".gemini/antigravity/mcp_config.json");
1342
+ CLAUDE_CONFIG = path14.join(os.homedir(), ".config/claude/claude_desktop_config.json");
1315
1343
  }
1316
1344
  });
1317
1345
 
@@ -1429,7 +1457,7 @@ async function handleInstallWizard() {
1429
1457
  }
1430
1458
  }
1431
1459
  async function handleStartServer() {
1432
- const fs17 = await import("fs");
1460
+ const fs16 = await import("fs");
1433
1461
  const { getLogFilePath: getLogFilePath2 } = await Promise.resolve().then(() => (init_logger(), logger_exports));
1434
1462
  const config = loadMCPConfig();
1435
1463
  const exposedCount = config.projects.filter((p) => p.expose).length;
@@ -1478,8 +1506,8 @@ async function handleStartServer() {
1478
1506
  try {
1479
1507
  await startMCPServer();
1480
1508
  let lastSize = 0;
1481
- if (fs17.existsSync(logPath)) {
1482
- const stats = fs17.statSync(logPath);
1509
+ if (fs16.existsSync(logPath)) {
1510
+ const stats = fs16.statSync(logPath);
1483
1511
  lastSize = stats.size;
1484
1512
  }
1485
1513
  let isRunning = true;
@@ -1502,10 +1530,10 @@ async function handleStartServer() {
1502
1530
  process.stdin.on("data", onKey);
1503
1531
  const interval = setInterval(() => {
1504
1532
  if (!isRunning) return;
1505
- if (fs17.existsSync(logPath)) {
1506
- const stats = fs17.statSync(logPath);
1533
+ if (fs16.existsSync(logPath)) {
1534
+ const stats = fs16.statSync(logPath);
1507
1535
  if (stats.size > lastSize) {
1508
- const stream = fs17.createReadStream(logPath, {
1536
+ const stream = fs16.createReadStream(logPath, {
1509
1537
  start: lastSize,
1510
1538
  end: stats.size,
1511
1539
  encoding: "utf-8"
@@ -1539,8 +1567,8 @@ async function handleStartServer() {
1539
1567
  }
1540
1568
  async function handleConfigureGlobalPath() {
1541
1569
  const { resolveGlobalPath: resolveGlobalPath2 } = await Promise.resolve().then(() => (init_tui_utils(), tui_utils_exports));
1542
- const fs17 = await import("fs");
1543
- const path17 = await import("path");
1570
+ const fs16 = await import("fs");
1571
+ const path16 = await import("path");
1544
1572
  note7(
1545
1573
  `MCP Hub requires a ${pc8.bold("global storage path")} to store its configuration
1546
1574
  and coordinate across projects.
@@ -1554,8 +1582,8 @@ locally in each project. MCP needs a central location.`,
1554
1582
  return false;
1555
1583
  }
1556
1584
  try {
1557
- if (!fs17.existsSync(resolvedPath)) {
1558
- fs17.mkdirSync(resolvedPath, { recursive: true });
1585
+ if (!fs16.existsSync(resolvedPath)) {
1586
+ fs16.mkdirSync(resolvedPath, { recursive: true });
1559
1587
  }
1560
1588
  const config = loadMCPConfig();
1561
1589
  saveMCPConfig(config);
@@ -1563,7 +1591,7 @@ locally in each project. MCP needs a central location.`,
1563
1591
  `${pc8.green("\u2713")} Global path configured: ${pc8.cyan(resolvedPath)}
1564
1592
 
1565
1593
  MCP config will be stored at:
1566
- ${path17.join(resolvedPath, "mcp.yaml")}`,
1594
+ ${path16.join(resolvedPath, "mcp.yaml")}`,
1567
1595
  "Configuration Saved"
1568
1596
  );
1569
1597
  return true;
@@ -2412,9 +2440,9 @@ Workspace: ${pc7.bold(workspaceName)}`,
2412
2440
  init_prompts();
2413
2441
  import { intro as intro3, select as select5, note as note8, cancel as cancel7, isCancel as isCancel8, outro as outro7 } from "@clack/prompts";
2414
2442
  import pc9 from "picocolors";
2415
- import * as path16 from "path";
2443
+ import * as path15 from "path";
2416
2444
  async function runSelector() {
2417
- const workspaceName = path16.basename(process.cwd());
2445
+ const workspaceName = path15.basename(process.cwd());
2418
2446
  intro3(pc9.cyan(pc9.inverse(` RRCE-Workflow | ${workspaceName} `)));
2419
2447
  const prompts = loadPromptsFromDir(getAgentCorePromptsDir());
2420
2448
  if (prompts.length === 0) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rrce-workflow",
3
- "version": "0.2.24",
3
+ "version": "0.2.26",
4
4
  "description": "RRCE-Workflow TUI - Agentic code workflow generator for AI-assisted development",
5
5
  "author": "RRCE Team",
6
6
  "license": "MIT",