rrce-workflow 0.1.5 → 0.2.6

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/src/lib/paths.ts CHANGED
@@ -18,8 +18,10 @@ export function detectWorkspaceRoot(): string {
18
18
  let current = process.cwd();
19
19
 
20
20
  while (current !== '/') {
21
- // Check for .git or .rrce-workflow.yaml
21
+ // Check for .git or .rrce-workflow/config.yaml (new location)
22
+ // Also check legacy .rrce-workflow.yaml for backwards compatibility
22
23
  if (fs.existsSync(path.join(current, '.git')) ||
24
+ fs.existsSync(path.join(current, '.rrce-workflow', 'config.yaml')) ||
23
25
  fs.existsSync(path.join(current, '.rrce-workflow.yaml'))) {
24
26
  return current;
25
27
  }
@@ -29,6 +31,27 @@ export function detectWorkspaceRoot(): string {
29
31
  return process.cwd();
30
32
  }
31
33
 
34
+ /**
35
+ * Get the config file path for a workspace
36
+ * New location: .rrce-workflow/config.yaml
37
+ * Legacy location: .rrce-workflow.yaml (for backwards compatibility)
38
+ */
39
+ export function getConfigPath(workspaceRoot: string): string {
40
+ const newPath = path.join(workspaceRoot, '.rrce-workflow', 'config.yaml');
41
+ const legacyPath = path.join(workspaceRoot, '.rrce-workflow.yaml');
42
+
43
+ // Prefer new location, fall back to legacy
44
+ if (fs.existsSync(newPath)) {
45
+ return newPath;
46
+ }
47
+ if (fs.existsSync(legacyPath)) {
48
+ return legacyPath;
49
+ }
50
+
51
+ // Default to new location for new configs
52
+ return newPath;
53
+ }
54
+
32
55
  /**
33
56
  * Get workspace name from directory or config
34
57
  */
@@ -139,13 +162,10 @@ export function ensureDir(dirPath: string): void {
139
162
 
140
163
  /**
141
164
  * Get path for agent prompts based on tool
165
+ * Now consolidated under .rrce-workflow/prompts/<tool>/
142
166
  */
143
167
  export function getAgentPromptPath(workspaceRoot: string, tool: 'copilot' | 'antigravity'): string {
144
- if (tool === 'copilot') {
145
- return path.join(workspaceRoot, '.github', 'agents');
146
- } else {
147
- return path.join(workspaceRoot, '.agent', 'workflows');
148
- }
168
+ return path.join(workspaceRoot, '.rrce-workflow', 'prompts', tool);
149
169
  }
150
170
 
151
171
  /**
@@ -215,3 +235,94 @@ export function syncMetadataToAll(agentCorePath: string, dataPaths: string[]): v
215
235
  copyDirToAllStoragePaths(sourceDir, dir, dataPaths);
216
236
  }
217
237
  }
238
+
239
+ /**
240
+ * Check if a directory path is writable
241
+ * Creates a test file and removes it to verify write access
242
+ */
243
+ export function checkWriteAccess(dirPath: string): boolean {
244
+ const testFile = path.join(dirPath, '.rrce-write-test');
245
+
246
+ try {
247
+ // Ensure directory exists first
248
+ if (!fs.existsSync(dirPath)) {
249
+ fs.mkdirSync(dirPath, { recursive: true });
250
+ }
251
+
252
+ // Try to write and delete a test file
253
+ fs.writeFileSync(testFile, 'write-test');
254
+ fs.unlinkSync(testFile);
255
+ return true;
256
+ } catch {
257
+ // Clean up if test file was created but couldn't be deleted
258
+ try {
259
+ if (fs.existsSync(testFile)) {
260
+ fs.unlinkSync(testFile);
261
+ }
262
+ } catch {
263
+ // Ignore cleanup errors
264
+ }
265
+ return false;
266
+ }
267
+ }
268
+
269
+ /**
270
+ * Get the default RRCE_HOME path (from env or ~/.rrce-workflow)
271
+ */
272
+ export function getDefaultRRCEHome(): string {
273
+ return process.env.RRCE_HOME || path.join(process.env.HOME || '~', '.rrce-workflow');
274
+ }
275
+
276
+ /**
277
+ * Get suggested global paths for user selection
278
+ * Returns array of { path, label, isWritable } objects
279
+ */
280
+ export function getSuggestedGlobalPaths(): Array<{ path: string; label: string; isWritable: boolean }> {
281
+ const suggestions: Array<{ path: string; label: string; isWritable: boolean }> = [];
282
+
283
+ // Option 1: RRCE_HOME environment variable (if explicitly set)
284
+ if (process.env.RRCE_HOME) {
285
+ suggestions.push({
286
+ path: process.env.RRCE_HOME,
287
+ label: 'RRCE_HOME (environment)',
288
+ isWritable: checkWriteAccess(process.env.RRCE_HOME),
289
+ });
290
+ }
291
+
292
+ // Option 2: Standard ~/.rrce-workflow
293
+ const homeDefault = path.join(process.env.HOME || '~', '.rrce-workflow');
294
+ if (!process.env.RRCE_HOME || process.env.RRCE_HOME !== homeDefault) {
295
+ suggestions.push({
296
+ path: homeDefault,
297
+ label: '~/.rrce-workflow (default)',
298
+ isWritable: checkWriteAccess(homeDefault),
299
+ });
300
+ }
301
+
302
+ return suggestions;
303
+ }
304
+
305
+ /**
306
+ * Get effective RRCE_HOME by reading from workspace config if available
307
+ * Falls back to default RRCE_HOME if no custom path is configured
308
+ */
309
+ export function getEffectiveRRCEHome(workspaceRoot?: string): string {
310
+ // Check workspace config for custom globalPath
311
+ if (workspaceRoot) {
312
+ const configPath = getConfigPath(workspaceRoot);
313
+ if (fs.existsSync(configPath)) {
314
+ try {
315
+ const content = fs.readFileSync(configPath, 'utf-8');
316
+ const globalPathMatch = content.match(/globalPath:\s*["']?([^"'\n]+)["']?/);
317
+ if (globalPathMatch?.[1]) {
318
+ return globalPathMatch[1].trim();
319
+ }
320
+ } catch {
321
+ // Ignore parse errors
322
+ }
323
+ }
324
+ }
325
+
326
+ // Fall back to default
327
+ return getDefaultRRCEHome();
328
+ }
@@ -41,13 +41,14 @@ export interface RRCEConfig {
41
41
  version: number;
42
42
  storage: {
43
43
  mode: StorageMode;
44
+ globalPath?: string; // Custom global storage path (when not using default ~/.rrce-workflow)
44
45
  };
45
- workspace: {
46
+ project: {
46
47
  name: string;
47
- path: string;
48
48
  };
49
49
  tools: {
50
50
  copilot: boolean;
51
51
  antigravity: boolean;
52
52
  };
53
+ linked_projects?: string[];
53
54
  }