rrce-workflow 0.2.15 → 0.2.16

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 +148 -158
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -49,18 +49,6 @@ function getWorkspaceName(workspaceRoot) {
49
49
  function getRRCEHome() {
50
50
  return RRCE_HOME;
51
51
  }
52
- function listGlobalProjects(excludeWorkspace) {
53
- const workspacesDir = path.join(RRCE_HOME, "workspaces");
54
- if (!fs.existsSync(workspacesDir)) {
55
- return [];
56
- }
57
- try {
58
- const entries = fs.readdirSync(workspacesDir, { withFileTypes: true });
59
- return entries.filter((entry) => entry.isDirectory() && entry.name !== excludeWorkspace).map((entry) => entry.name);
60
- } catch {
61
- return [];
62
- }
63
- }
64
52
  function getLocalWorkspacePath(workspaceRoot) {
65
53
  return path.join(workspaceRoot, ".rrce-workflow");
66
54
  }
@@ -145,115 +133,9 @@ function getEffectiveRRCEHome(workspaceRoot) {
145
133
  return getDefaultRRCEHome();
146
134
  }
147
135
 
148
- // src/commands/wizard/setup-flow.ts
149
- import { group, select, multiselect, confirm, spinner, note, outro, cancel, isCancel as isCancel2 } from "@clack/prompts";
150
- import pc2 from "picocolors";
151
- import * as fs7 from "fs";
152
- import * as path7 from "path";
153
-
154
- // src/lib/prompts.ts
136
+ // src/lib/detection.ts
155
137
  import * as fs2 from "fs";
156
138
  import * as path2 from "path";
157
- import { fileURLToPath } from "url";
158
- import matter from "gray-matter";
159
-
160
- // src/types/prompt.ts
161
- import { z } from "zod";
162
- var PromptArgSchema = z.object({
163
- name: z.string(),
164
- default: z.string().optional(),
165
- prompt: z.string().optional()
166
- });
167
- var AutoIdentitySchema = z.object({
168
- user: z.string(),
169
- model: z.string()
170
- });
171
- var PromptFrontmatterSchema = z.object({
172
- name: z.string(),
173
- description: z.string(),
174
- "argument-hint": z.union([z.string(), z.array(z.string())]).optional(),
175
- tools: z.array(z.string()).optional(),
176
- "required-args": z.array(PromptArgSchema).optional(),
177
- "optional-args": z.array(PromptArgSchema).optional(),
178
- "auto-identity": AutoIdentitySchema.optional()
179
- });
180
-
181
- // src/lib/prompts.ts
182
- var __filename = fileURLToPath(import.meta.url);
183
- var __dirname = path2.dirname(__filename);
184
- function parsePromptFile(filePath) {
185
- try {
186
- const fileContent = fs2.readFileSync(filePath, "utf-8");
187
- const { data, content } = matter(fileContent);
188
- const parsed = PromptFrontmatterSchema.safeParse(data);
189
- if (!parsed.success) {
190
- console.error(`Failed to parse frontmatter in ${filePath}:`, parsed.error);
191
- return null;
192
- }
193
- return {
194
- frontmatter: parsed.data,
195
- content: content.trim(),
196
- filePath
197
- };
198
- } catch (error) {
199
- console.error(`Error reading prompt file ${filePath}:`, error);
200
- return null;
201
- }
202
- }
203
- function loadPromptsFromDir(dirPath) {
204
- if (!fs2.existsSync(dirPath)) {
205
- return [];
206
- }
207
- const files = fs2.readdirSync(dirPath).filter((f) => f.endsWith(".md"));
208
- const prompts = [];
209
- for (const file of files) {
210
- const prompt = parsePromptFile(path2.join(dirPath, file));
211
- if (prompt) {
212
- prompts.push(prompt);
213
- }
214
- }
215
- return prompts;
216
- }
217
- function getAgentCoreDir() {
218
- return path2.join(__dirname, "..", "..", "agent-core");
219
- }
220
- function getAgentCorePromptsDir() {
221
- return path2.join(getAgentCoreDir(), "prompts");
222
- }
223
-
224
- // src/commands/wizard/utils.ts
225
- import * as fs3 from "fs";
226
- import * as path3 from "path";
227
- function copyPromptsToDir(prompts, targetDir, extension) {
228
- for (const prompt of prompts) {
229
- const baseName = path3.basename(prompt.filePath, ".md");
230
- const targetName = baseName + extension;
231
- const targetPath = path3.join(targetDir, targetName);
232
- const content = fs3.readFileSync(prompt.filePath, "utf-8");
233
- fs3.writeFileSync(targetPath, content);
234
- }
235
- }
236
- function copyDirRecursive(src, dest) {
237
- const entries = fs3.readdirSync(src, { withFileTypes: true });
238
- for (const entry of entries) {
239
- const srcPath = path3.join(src, entry.name);
240
- const destPath = path3.join(dest, entry.name);
241
- if (entry.isDirectory()) {
242
- ensureDir(destPath);
243
- copyDirRecursive(srcPath, destPath);
244
- } else {
245
- fs3.copyFileSync(srcPath, destPath);
246
- }
247
- }
248
- }
249
-
250
- // src/commands/wizard/vscode.ts
251
- import * as fs5 from "fs";
252
- import * as path5 from "path";
253
-
254
- // src/lib/detection.ts
255
- import * as fs4 from "fs";
256
- import * as path4 from "path";
257
139
  function scanForProjects(options = {}) {
258
140
  const { excludeWorkspace, workspacePath, scanSiblings = true } = options;
259
141
  const projects = [];
@@ -278,29 +160,29 @@ function scanForProjects(options = {}) {
278
160
  }
279
161
  function scanGlobalStorage(excludeWorkspace) {
280
162
  const rrceHome = getDefaultRRCEHome();
281
- const workspacesDir = path4.join(rrceHome, "workspaces");
163
+ const workspacesDir = path2.join(rrceHome, "workspaces");
282
164
  const projects = [];
283
- if (!fs4.existsSync(workspacesDir)) {
165
+ if (!fs2.existsSync(workspacesDir)) {
284
166
  return projects;
285
167
  }
286
168
  try {
287
- const entries = fs4.readdirSync(workspacesDir, { withFileTypes: true });
169
+ const entries = fs2.readdirSync(workspacesDir, { withFileTypes: true });
288
170
  for (const entry of entries) {
289
171
  if (!entry.isDirectory()) continue;
290
172
  if (entry.name === excludeWorkspace) continue;
291
- const projectDataPath = path4.join(workspacesDir, entry.name);
292
- const knowledgePath = path4.join(projectDataPath, "knowledge");
293
- const refsPath = path4.join(projectDataPath, "refs");
294
- const tasksPath = path4.join(projectDataPath, "tasks");
173
+ const projectDataPath = path2.join(workspacesDir, entry.name);
174
+ const knowledgePath = path2.join(projectDataPath, "knowledge");
175
+ const refsPath = path2.join(projectDataPath, "refs");
176
+ const tasksPath = path2.join(projectDataPath, "tasks");
295
177
  projects.push({
296
178
  name: entry.name,
297
179
  path: projectDataPath,
298
180
  // For global projects, path is the data path
299
181
  dataPath: projectDataPath,
300
182
  source: "global",
301
- knowledgePath: fs4.existsSync(knowledgePath) ? knowledgePath : void 0,
302
- refsPath: fs4.existsSync(refsPath) ? refsPath : void 0,
303
- tasksPath: fs4.existsSync(tasksPath) ? tasksPath : void 0
183
+ knowledgePath: fs2.existsSync(knowledgePath) ? knowledgePath : void 0,
184
+ refsPath: fs2.existsSync(refsPath) ? refsPath : void 0,
185
+ tasksPath: fs2.existsSync(tasksPath) ? tasksPath : void 0
304
186
  });
305
187
  }
306
188
  } catch {
@@ -308,32 +190,32 @@ function scanGlobalStorage(excludeWorkspace) {
308
190
  return projects;
309
191
  }
310
192
  function scanSiblingDirectories(workspacePath, excludeWorkspace) {
311
- const parentDir = path4.dirname(workspacePath);
193
+ const parentDir = path2.dirname(workspacePath);
312
194
  const projects = [];
313
195
  try {
314
- const entries = fs4.readdirSync(parentDir, { withFileTypes: true });
196
+ const entries = fs2.readdirSync(parentDir, { withFileTypes: true });
315
197
  for (const entry of entries) {
316
198
  if (!entry.isDirectory()) continue;
317
- const projectPath = path4.join(parentDir, entry.name);
199
+ const projectPath = path2.join(parentDir, entry.name);
318
200
  if (projectPath === workspacePath) continue;
319
201
  if (entry.name === excludeWorkspace) continue;
320
- const configPath = path4.join(projectPath, ".rrce-workflow", "config.yaml");
321
- if (!fs4.existsSync(configPath)) continue;
202
+ const configPath = path2.join(projectPath, ".rrce-workflow", "config.yaml");
203
+ if (!fs2.existsSync(configPath)) continue;
322
204
  const config = parseWorkspaceConfig(configPath);
323
205
  if (!config) continue;
324
- const dataPath = path4.join(projectPath, ".rrce-workflow");
325
- const knowledgePath = path4.join(dataPath, "knowledge");
326
- const refsPath = path4.join(dataPath, "refs");
327
- const tasksPath = path4.join(dataPath, "tasks");
206
+ const dataPath = path2.join(projectPath, ".rrce-workflow");
207
+ const knowledgePath = path2.join(dataPath, "knowledge");
208
+ const refsPath = path2.join(dataPath, "refs");
209
+ const tasksPath = path2.join(dataPath, "tasks");
328
210
  projects.push({
329
211
  name: config.name || entry.name,
330
212
  path: projectPath,
331
213
  dataPath,
332
214
  source: "sibling",
333
215
  storageMode: config.storageMode,
334
- knowledgePath: fs4.existsSync(knowledgePath) ? knowledgePath : void 0,
335
- refsPath: fs4.existsSync(refsPath) ? refsPath : void 0,
336
- tasksPath: fs4.existsSync(tasksPath) ? tasksPath : void 0
216
+ knowledgePath: fs2.existsSync(knowledgePath) ? knowledgePath : void 0,
217
+ refsPath: fs2.existsSync(refsPath) ? refsPath : void 0,
218
+ tasksPath: fs2.existsSync(tasksPath) ? tasksPath : void 0
337
219
  });
338
220
  }
339
221
  } catch {
@@ -342,7 +224,7 @@ function scanSiblingDirectories(workspacePath, excludeWorkspace) {
342
224
  }
343
225
  function parseWorkspaceConfig(configPath) {
344
226
  try {
345
- const content = fs4.readFileSync(configPath, "utf-8");
227
+ const content = fs2.readFileSync(configPath, "utf-8");
346
228
  const nameMatch = content.match(/name:\s*["']?([^"'\n]+)["']?/);
347
229
  const modeMatch = content.match(/mode:\s*(global|workspace|both)/);
348
230
  const linkedProjects = [];
@@ -357,7 +239,7 @@ function parseWorkspaceConfig(configPath) {
357
239
  }
358
240
  }
359
241
  return {
360
- name: nameMatch?.[1]?.trim() || path4.basename(path4.dirname(path4.dirname(configPath))),
242
+ name: nameMatch?.[1]?.trim() || path2.basename(path2.dirname(path2.dirname(configPath))),
361
243
  storageMode: modeMatch?.[1] || "global",
362
244
  linkedProjects: linkedProjects.length > 0 ? linkedProjects : void 0
363
245
  };
@@ -401,7 +283,111 @@ function getProjectFolders(project) {
401
283
  return folders;
402
284
  }
403
285
 
286
+ // src/commands/wizard/setup-flow.ts
287
+ import { group, select, multiselect, confirm, spinner, note, outro, cancel, isCancel as isCancel2 } from "@clack/prompts";
288
+ import pc2 from "picocolors";
289
+ import * as fs7 from "fs";
290
+ import * as path7 from "path";
291
+
292
+ // src/lib/prompts.ts
293
+ import * as fs3 from "fs";
294
+ import * as path3 from "path";
295
+ import { fileURLToPath } from "url";
296
+ import matter from "gray-matter";
297
+
298
+ // src/types/prompt.ts
299
+ import { z } from "zod";
300
+ var PromptArgSchema = z.object({
301
+ name: z.string(),
302
+ default: z.string().optional(),
303
+ prompt: z.string().optional()
304
+ });
305
+ var AutoIdentitySchema = z.object({
306
+ user: z.string(),
307
+ model: z.string()
308
+ });
309
+ var PromptFrontmatterSchema = z.object({
310
+ name: z.string(),
311
+ description: z.string(),
312
+ "argument-hint": z.union([z.string(), z.array(z.string())]).optional(),
313
+ tools: z.array(z.string()).optional(),
314
+ "required-args": z.array(PromptArgSchema).optional(),
315
+ "optional-args": z.array(PromptArgSchema).optional(),
316
+ "auto-identity": AutoIdentitySchema.optional()
317
+ });
318
+
319
+ // src/lib/prompts.ts
320
+ var __filename = fileURLToPath(import.meta.url);
321
+ var __dirname = path3.dirname(__filename);
322
+ function parsePromptFile(filePath) {
323
+ try {
324
+ const fileContent = fs3.readFileSync(filePath, "utf-8");
325
+ const { data, content } = matter(fileContent);
326
+ const parsed = PromptFrontmatterSchema.safeParse(data);
327
+ if (!parsed.success) {
328
+ console.error(`Failed to parse frontmatter in ${filePath}:`, parsed.error);
329
+ return null;
330
+ }
331
+ return {
332
+ frontmatter: parsed.data,
333
+ content: content.trim(),
334
+ filePath
335
+ };
336
+ } catch (error) {
337
+ console.error(`Error reading prompt file ${filePath}:`, error);
338
+ return null;
339
+ }
340
+ }
341
+ function loadPromptsFromDir(dirPath) {
342
+ if (!fs3.existsSync(dirPath)) {
343
+ return [];
344
+ }
345
+ const files = fs3.readdirSync(dirPath).filter((f) => f.endsWith(".md"));
346
+ const prompts = [];
347
+ for (const file of files) {
348
+ const prompt = parsePromptFile(path3.join(dirPath, file));
349
+ if (prompt) {
350
+ prompts.push(prompt);
351
+ }
352
+ }
353
+ return prompts;
354
+ }
355
+ function getAgentCoreDir() {
356
+ return path3.join(__dirname, "..", "..", "agent-core");
357
+ }
358
+ function getAgentCorePromptsDir() {
359
+ return path3.join(getAgentCoreDir(), "prompts");
360
+ }
361
+
362
+ // src/commands/wizard/utils.ts
363
+ import * as fs4 from "fs";
364
+ import * as path4 from "path";
365
+ function copyPromptsToDir(prompts, targetDir, extension) {
366
+ for (const prompt of prompts) {
367
+ const baseName = path4.basename(prompt.filePath, ".md");
368
+ const targetName = baseName + extension;
369
+ const targetPath = path4.join(targetDir, targetName);
370
+ const content = fs4.readFileSync(prompt.filePath, "utf-8");
371
+ fs4.writeFileSync(targetPath, content);
372
+ }
373
+ }
374
+ function copyDirRecursive(src, dest) {
375
+ const entries = fs4.readdirSync(src, { withFileTypes: true });
376
+ for (const entry of entries) {
377
+ const srcPath = path4.join(src, entry.name);
378
+ const destPath = path4.join(dest, entry.name);
379
+ if (entry.isDirectory()) {
380
+ ensureDir(destPath);
381
+ copyDirRecursive(srcPath, destPath);
382
+ } else {
383
+ fs4.copyFileSync(srcPath, destPath);
384
+ }
385
+ }
386
+ }
387
+
404
388
  // src/commands/wizard/vscode.ts
389
+ import * as fs5 from "fs";
390
+ import * as path5 from "path";
405
391
  var REFERENCE_GROUP_PREFIX = "\u{1F4C1} References";
406
392
  function generateVSCodeWorkspace(workspacePath, workspaceName, linkedProjects, customGlobalPath) {
407
393
  const workspaceFilePath = path5.join(workspacePath, `${workspaceName}.code-workspace`);
@@ -647,10 +633,10 @@ async function runSetupFlow(workspacePath, workspaceName, existingProjects) {
647
633
  }
648
634
  return multiselect({
649
635
  message: "Link knowledge from other projects?",
650
- options: existingProjects.map((name) => ({
651
- value: name,
652
- label: name,
653
- hint: `~/.rrce-workflow/workspaces/${name}/knowledge`
636
+ options: existingProjects.map((project) => ({
637
+ value: project.name,
638
+ label: project.name,
639
+ hint: pc2.dim(getProjectDisplayLabel(project))
654
640
  })),
655
641
  required: false
656
642
  });
@@ -686,7 +672,7 @@ async function runSetupFlow(workspacePath, workspaceName, existingProjects) {
686
672
  globalPath: customGlobalPath,
687
673
  tools: config.tools,
688
674
  linkedProjects: config.linkedProjects
689
- }, workspacePath, workspaceName);
675
+ }, workspacePath, workspaceName, existingProjects);
690
676
  s.stop("Configuration generated");
691
677
  const dataPaths = getDataPaths(
692
678
  config.storageMode,
@@ -782,7 +768,7 @@ Please choose a custom path instead.`,
782
768
  }
783
769
  return customPath;
784
770
  }
785
- async function generateConfiguration(config, workspacePath, workspaceName) {
771
+ async function generateConfiguration(config, workspacePath, workspaceName, allProjects = []) {
786
772
  const dataPaths = getDataPaths(config.storageMode, workspaceName, workspacePath, config.globalPath);
787
773
  for (const dataPath of dataPaths) {
788
774
  ensureDir(dataPath);
@@ -836,7 +822,8 @@ linked_projects:
836
822
  }
837
823
  fs7.writeFileSync(workspaceConfigPath, configContent);
838
824
  if (config.tools.includes("copilot") || config.linkedProjects.length > 0) {
839
- generateVSCodeWorkspace(workspacePath, workspaceName, config.linkedProjects, config.globalPath);
825
+ const selectedProjects = allProjects.filter((p) => config.linkedProjects.includes(p.name));
826
+ generateVSCodeWorkspace(workspacePath, workspaceName, selectedProjects, config.globalPath);
840
827
  }
841
828
  }
842
829
  function getDataPaths(mode, workspaceName, workspaceRoot, customGlobalPath) {
@@ -858,13 +845,12 @@ function getDataPaths(mode, workspaceName, workspaceRoot, customGlobalPath) {
858
845
  import { multiselect as multiselect2, spinner as spinner2, note as note2, outro as outro2, cancel as cancel2, isCancel as isCancel3 } from "@clack/prompts";
859
846
  import pc3 from "picocolors";
860
847
  import * as fs8 from "fs";
861
- async function runLinkProjectsFlow(workspacePath, workspaceName, existingProjects) {
862
- const detectedProjects = scanForProjects({
848
+ async function runLinkProjectsFlow(workspacePath, workspaceName) {
849
+ const projects = scanForProjects({
863
850
  excludeWorkspace: workspaceName,
864
851
  workspacePath,
865
852
  scanSiblings: true
866
853
  });
867
- const projects = existingProjects ? existingProjects.map((name) => ({ name, source: "global" })) : detectedProjects;
868
854
  if (projects.length === 0) {
869
855
  outro2(pc3.yellow("No other projects found. Try setting up another project first."));
870
856
  return;
@@ -1093,7 +1079,11 @@ async function runWizard() {
1093
1079
  Workspace: ${pc6.bold(workspaceName)}`,
1094
1080
  "Context"
1095
1081
  );
1096
- const existingProjects = listGlobalProjects(workspaceName);
1082
+ const detectedProjects = scanForProjects({
1083
+ excludeWorkspace: workspaceName,
1084
+ workspacePath,
1085
+ scanSiblings: true
1086
+ });
1097
1087
  const configFilePath = getConfigPath(workspacePath);
1098
1088
  const isAlreadyConfigured = fs11.existsSync(configFilePath);
1099
1089
  let currentStorageMode = null;
@@ -1109,11 +1099,11 @@ Workspace: ${pc6.bold(workspaceName)}`,
1109
1099
  const hasLocalData = fs11.existsSync(localDataPath);
1110
1100
  if (isAlreadyConfigured) {
1111
1101
  const menuOptions = [];
1112
- if (existingProjects.length > 0) {
1102
+ if (detectedProjects.length > 0) {
1113
1103
  menuOptions.push({
1114
1104
  value: "link",
1115
1105
  label: "Link other project knowledge",
1116
- hint: `${existingProjects.length} projects available`
1106
+ hint: `${detectedProjects.length} projects detected (global + sibling)`
1117
1107
  });
1118
1108
  }
1119
1109
  if (currentStorageMode === "workspace" && hasLocalData) {
@@ -1134,7 +1124,7 @@ Workspace: ${pc6.bold(workspaceName)}`,
1134
1124
  process.exit(0);
1135
1125
  }
1136
1126
  if (action === "link") {
1137
- await runLinkProjectsFlow(workspacePath, workspaceName, existingProjects);
1127
+ await runLinkProjectsFlow(workspacePath, workspaceName);
1138
1128
  return;
1139
1129
  }
1140
1130
  if (action === "sync-global") {
@@ -1146,7 +1136,7 @@ Workspace: ${pc6.bold(workspaceName)}`,
1146
1136
  return;
1147
1137
  }
1148
1138
  }
1149
- await runSetupFlow(workspacePath, workspaceName, existingProjects);
1139
+ await runSetupFlow(workspacePath, workspaceName, detectedProjects);
1150
1140
  }
1151
1141
 
1152
1142
  // src/commands/selector.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rrce-workflow",
3
- "version": "0.2.15",
3
+ "version": "0.2.16",
4
4
  "description": "RRCE-Workflow TUI - Agentic code workflow generator for AI-assisted development",
5
5
  "author": "RRCE Team",
6
6
  "license": "MIT",