rrce-workflow 0.2.15 → 0.2.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +200 -245
- 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/
|
|
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 =
|
|
163
|
+
const workspacesDir = path2.join(rrceHome, "workspaces");
|
|
282
164
|
const projects = [];
|
|
283
|
-
if (!
|
|
165
|
+
if (!fs2.existsSync(workspacesDir)) {
|
|
284
166
|
return projects;
|
|
285
167
|
}
|
|
286
168
|
try {
|
|
287
|
-
const entries =
|
|
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 =
|
|
292
|
-
const knowledgePath =
|
|
293
|
-
const refsPath =
|
|
294
|
-
const tasksPath =
|
|
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:
|
|
302
|
-
refsPath:
|
|
303
|
-
tasksPath:
|
|
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 =
|
|
193
|
+
const parentDir = path2.dirname(workspacePath);
|
|
312
194
|
const projects = [];
|
|
313
195
|
try {
|
|
314
|
-
const entries =
|
|
196
|
+
const entries = fs2.readdirSync(parentDir, { withFileTypes: true });
|
|
315
197
|
for (const entry of entries) {
|
|
316
198
|
if (!entry.isDirectory()) continue;
|
|
317
|
-
const projectPath =
|
|
199
|
+
const projectPath = path2.join(parentDir, entry.name);
|
|
318
200
|
if (projectPath === workspacePath) continue;
|
|
319
201
|
if (entry.name === excludeWorkspace) continue;
|
|
320
|
-
const configPath =
|
|
321
|
-
if (!
|
|
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 =
|
|
325
|
-
const knowledgePath =
|
|
326
|
-
const refsPath =
|
|
327
|
-
const tasksPath =
|
|
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:
|
|
335
|
-
refsPath:
|
|
336
|
-
tasksPath:
|
|
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 =
|
|
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() ||
|
|
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
|
};
|
|
@@ -365,44 +247,112 @@ function parseWorkspaceConfig(configPath) {
|
|
|
365
247
|
return null;
|
|
366
248
|
}
|
|
367
249
|
}
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
250
|
+
|
|
251
|
+
// src/commands/wizard/setup-flow.ts
|
|
252
|
+
import { group, select, multiselect, confirm, spinner, note, outro, cancel, isCancel as isCancel2 } from "@clack/prompts";
|
|
253
|
+
import pc2 from "picocolors";
|
|
254
|
+
import * as fs7 from "fs";
|
|
255
|
+
import * as path7 from "path";
|
|
256
|
+
|
|
257
|
+
// src/lib/prompts.ts
|
|
258
|
+
import * as fs3 from "fs";
|
|
259
|
+
import * as path3 from "path";
|
|
260
|
+
import { fileURLToPath } from "url";
|
|
261
|
+
import matter from "gray-matter";
|
|
262
|
+
|
|
263
|
+
// src/types/prompt.ts
|
|
264
|
+
import { z } from "zod";
|
|
265
|
+
var PromptArgSchema = z.object({
|
|
266
|
+
name: z.string(),
|
|
267
|
+
default: z.string().optional(),
|
|
268
|
+
prompt: z.string().optional()
|
|
269
|
+
});
|
|
270
|
+
var AutoIdentitySchema = z.object({
|
|
271
|
+
user: z.string(),
|
|
272
|
+
model: z.string()
|
|
273
|
+
});
|
|
274
|
+
var PromptFrontmatterSchema = z.object({
|
|
275
|
+
name: z.string(),
|
|
276
|
+
description: z.string(),
|
|
277
|
+
"argument-hint": z.union([z.string(), z.array(z.string())]).optional(),
|
|
278
|
+
tools: z.array(z.string()).optional(),
|
|
279
|
+
"required-args": z.array(PromptArgSchema).optional(),
|
|
280
|
+
"optional-args": z.array(PromptArgSchema).optional(),
|
|
281
|
+
"auto-identity": AutoIdentitySchema.optional()
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
// src/lib/prompts.ts
|
|
285
|
+
var __filename = fileURLToPath(import.meta.url);
|
|
286
|
+
var __dirname = path3.dirname(__filename);
|
|
287
|
+
function parsePromptFile(filePath) {
|
|
288
|
+
try {
|
|
289
|
+
const fileContent = fs3.readFileSync(filePath, "utf-8");
|
|
290
|
+
const { data, content } = matter(fileContent);
|
|
291
|
+
const parsed = PromptFrontmatterSchema.safeParse(data);
|
|
292
|
+
if (!parsed.success) {
|
|
293
|
+
console.error(`Failed to parse frontmatter in ${filePath}:`, parsed.error);
|
|
294
|
+
return null;
|
|
295
|
+
}
|
|
296
|
+
return {
|
|
297
|
+
frontmatter: parsed.data,
|
|
298
|
+
content: content.trim(),
|
|
299
|
+
filePath
|
|
300
|
+
};
|
|
301
|
+
} catch (error) {
|
|
302
|
+
console.error(`Error reading prompt file ${filePath}:`, error);
|
|
303
|
+
return null;
|
|
376
304
|
}
|
|
377
305
|
}
|
|
378
|
-
function
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
folders.push({
|
|
382
|
-
path: project.knowledgePath,
|
|
383
|
-
type: "knowledge",
|
|
384
|
-
displayName: `\u{1F4DA} ${project.name} (knowledge)`
|
|
385
|
-
});
|
|
306
|
+
function loadPromptsFromDir(dirPath) {
|
|
307
|
+
if (!fs3.existsSync(dirPath)) {
|
|
308
|
+
return [];
|
|
386
309
|
}
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
310
|
+
const files = fs3.readdirSync(dirPath).filter((f) => f.endsWith(".md"));
|
|
311
|
+
const prompts = [];
|
|
312
|
+
for (const file of files) {
|
|
313
|
+
const prompt = parsePromptFile(path3.join(dirPath, file));
|
|
314
|
+
if (prompt) {
|
|
315
|
+
prompts.push(prompt);
|
|
316
|
+
}
|
|
393
317
|
}
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
318
|
+
return prompts;
|
|
319
|
+
}
|
|
320
|
+
function getAgentCoreDir() {
|
|
321
|
+
return path3.join(__dirname, "..", "..", "agent-core");
|
|
322
|
+
}
|
|
323
|
+
function getAgentCorePromptsDir() {
|
|
324
|
+
return path3.join(getAgentCoreDir(), "prompts");
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
// src/commands/wizard/utils.ts
|
|
328
|
+
import * as fs4 from "fs";
|
|
329
|
+
import * as path4 from "path";
|
|
330
|
+
function copyPromptsToDir(prompts, targetDir, extension) {
|
|
331
|
+
for (const prompt of prompts) {
|
|
332
|
+
const baseName = path4.basename(prompt.filePath, ".md");
|
|
333
|
+
const targetName = baseName + extension;
|
|
334
|
+
const targetPath = path4.join(targetDir, targetName);
|
|
335
|
+
const content = fs4.readFileSync(prompt.filePath, "utf-8");
|
|
336
|
+
fs4.writeFileSync(targetPath, content);
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
function copyDirRecursive(src, dest) {
|
|
340
|
+
const entries = fs4.readdirSync(src, { withFileTypes: true });
|
|
341
|
+
for (const entry of entries) {
|
|
342
|
+
const srcPath = path4.join(src, entry.name);
|
|
343
|
+
const destPath = path4.join(dest, entry.name);
|
|
344
|
+
if (entry.isDirectory()) {
|
|
345
|
+
ensureDir(destPath);
|
|
346
|
+
copyDirRecursive(srcPath, destPath);
|
|
347
|
+
} else {
|
|
348
|
+
fs4.copyFileSync(srcPath, destPath);
|
|
349
|
+
}
|
|
400
350
|
}
|
|
401
|
-
return folders;
|
|
402
351
|
}
|
|
403
352
|
|
|
404
353
|
// src/commands/wizard/vscode.ts
|
|
405
|
-
|
|
354
|
+
import * as fs5 from "fs";
|
|
355
|
+
import * as path5 from "path";
|
|
406
356
|
function generateVSCodeWorkspace(workspacePath, workspaceName, linkedProjects, customGlobalPath) {
|
|
407
357
|
const workspaceFilePath = path5.join(workspacePath, `${workspaceName}.code-workspace`);
|
|
408
358
|
let workspace;
|
|
@@ -419,60 +369,47 @@ function generateVSCodeWorkspace(workspacePath, workspaceName, linkedProjects, c
|
|
|
419
369
|
if (!workspace.settings) {
|
|
420
370
|
workspace.settings = {};
|
|
421
371
|
}
|
|
422
|
-
|
|
423
|
-
(f) => f.path === "." || !f.name?.
|
|
372
|
+
workspace.folders = workspace.folders.filter(
|
|
373
|
+
(f) => f.path === "." || !f.name?.startsWith("\u{1F4C1}") && !f.name?.startsWith("\u{1F4DA}") && !f.name?.startsWith("\u{1F4CE}") && !f.name?.startsWith("\u{1F4CB}")
|
|
424
374
|
);
|
|
425
|
-
workspace.folders
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
375
|
+
const mainFolderIndex = workspace.folders.findIndex((f) => f.path === ".");
|
|
376
|
+
if (mainFolderIndex === -1) {
|
|
377
|
+
workspace.folders.unshift({
|
|
378
|
+
path: ".",
|
|
379
|
+
name: `\u{1F3E0} ${workspaceName} (workspace)`
|
|
380
|
+
});
|
|
381
|
+
} else {
|
|
382
|
+
workspace.folders[mainFolderIndex] = {
|
|
383
|
+
path: ".",
|
|
384
|
+
name: `\u{1F3E0} ${workspaceName} (workspace)`
|
|
385
|
+
};
|
|
435
386
|
}
|
|
436
387
|
const referenceFolderPaths = [];
|
|
437
388
|
const isDetectedProjects = linkedProjects.length > 0 && typeof linkedProjects[0] === "object";
|
|
438
389
|
if (isDetectedProjects) {
|
|
439
390
|
const projects = linkedProjects;
|
|
440
391
|
for (const project of projects) {
|
|
441
|
-
const folders = getProjectFolders(project);
|
|
442
392
|
const sourceLabel = project.source === "global" ? "global" : "local";
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
});
|
|
451
|
-
}
|
|
393
|
+
const folderPath = project.dataPath;
|
|
394
|
+
if (fs5.existsSync(folderPath)) {
|
|
395
|
+
referenceFolderPaths.push(folderPath);
|
|
396
|
+
workspace.folders.push({
|
|
397
|
+
path: folderPath,
|
|
398
|
+
name: `\u{1F4C1} ${project.name} [${sourceLabel}]`
|
|
399
|
+
});
|
|
452
400
|
}
|
|
453
401
|
}
|
|
454
402
|
} else {
|
|
455
403
|
const projectNames = linkedProjects;
|
|
456
404
|
const rrceHome = customGlobalPath || getRRCEHome();
|
|
457
405
|
for (const projectName of projectNames) {
|
|
458
|
-
const
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
{
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
const folderPath = path5.join(projectDataPath, subpath);
|
|
466
|
-
if (fs5.existsSync(folderPath)) {
|
|
467
|
-
referenceFolderPaths.push(folderPath);
|
|
468
|
-
const existingIndex = workspace.folders.findIndex((f) => f.path === folderPath);
|
|
469
|
-
if (existingIndex === -1) {
|
|
470
|
-
workspace.folders.push({
|
|
471
|
-
path: folderPath,
|
|
472
|
-
name: `${icon} ${projectName} (${type}) [global]`
|
|
473
|
-
});
|
|
474
|
-
}
|
|
475
|
-
}
|
|
406
|
+
const folderPath = path5.join(rrceHome, "workspaces", projectName);
|
|
407
|
+
if (fs5.existsSync(folderPath)) {
|
|
408
|
+
referenceFolderPaths.push(folderPath);
|
|
409
|
+
workspace.folders.push({
|
|
410
|
+
path: folderPath,
|
|
411
|
+
name: `\u{1F4C1} ${projectName} [global]`
|
|
412
|
+
});
|
|
476
413
|
}
|
|
477
414
|
}
|
|
478
415
|
}
|
|
@@ -482,12 +419,17 @@ function generateVSCodeWorkspace(workspacePath, workspaceName, linkedProjects, c
|
|
|
482
419
|
readonlyPatterns[`${folderPath}/**`] = true;
|
|
483
420
|
}
|
|
484
421
|
const existingReadonly = workspace.settings["files.readonlyInclude"] || {};
|
|
422
|
+
const cleanedReadonly = {};
|
|
423
|
+
for (const [pattern, value] of Object.entries(existingReadonly)) {
|
|
424
|
+
if (!pattern.includes(".rrce-workflow") && !pattern.includes("rrce-workflow/workspaces")) {
|
|
425
|
+
cleanedReadonly[pattern] = value;
|
|
426
|
+
}
|
|
427
|
+
}
|
|
485
428
|
workspace.settings["files.readonlyInclude"] = {
|
|
486
|
-
...
|
|
429
|
+
...cleanedReadonly,
|
|
487
430
|
...readonlyPatterns
|
|
488
431
|
};
|
|
489
432
|
}
|
|
490
|
-
workspace.settings["explorer.sortOrder"] = workspace.settings["explorer.sortOrder"] || "default";
|
|
491
433
|
fs5.writeFileSync(workspaceFilePath, JSON.stringify(workspace, null, 2));
|
|
492
434
|
}
|
|
493
435
|
|
|
@@ -647,10 +589,13 @@ async function runSetupFlow(workspacePath, workspaceName, existingProjects) {
|
|
|
647
589
|
}
|
|
648
590
|
return multiselect({
|
|
649
591
|
message: "Link knowledge from other projects?",
|
|
650
|
-
options: existingProjects.map((
|
|
651
|
-
value: name
|
|
652
|
-
|
|
653
|
-
|
|
592
|
+
options: existingProjects.map((project) => ({
|
|
593
|
+
value: `${project.name}:${project.source}`,
|
|
594
|
+
// Unique key
|
|
595
|
+
label: `${project.name} ${pc2.dim(`(${project.source})`)}`,
|
|
596
|
+
hint: pc2.dim(
|
|
597
|
+
project.source === "global" ? `~/.rrce-workflow/workspaces/${project.name}` : project.dataPath
|
|
598
|
+
)
|
|
654
599
|
})),
|
|
655
600
|
required: false
|
|
656
601
|
});
|
|
@@ -686,7 +631,7 @@ async function runSetupFlow(workspacePath, workspaceName, existingProjects) {
|
|
|
686
631
|
globalPath: customGlobalPath,
|
|
687
632
|
tools: config.tools,
|
|
688
633
|
linkedProjects: config.linkedProjects
|
|
689
|
-
}, workspacePath, workspaceName);
|
|
634
|
+
}, workspacePath, workspaceName, existingProjects);
|
|
690
635
|
s.stop("Configuration generated");
|
|
691
636
|
const dataPaths = getDataPaths(
|
|
692
637
|
config.storageMode,
|
|
@@ -782,7 +727,7 @@ Please choose a custom path instead.`,
|
|
|
782
727
|
}
|
|
783
728
|
return customPath;
|
|
784
729
|
}
|
|
785
|
-
async function generateConfiguration(config, workspacePath, workspaceName) {
|
|
730
|
+
async function generateConfiguration(config, workspacePath, workspaceName, allProjects = []) {
|
|
786
731
|
const dataPaths = getDataPaths(config.storageMode, workspaceName, workspacePath, config.globalPath);
|
|
787
732
|
for (const dataPath of dataPaths) {
|
|
788
733
|
ensureDir(dataPath);
|
|
@@ -836,7 +781,10 @@ linked_projects:
|
|
|
836
781
|
}
|
|
837
782
|
fs7.writeFileSync(workspaceConfigPath, configContent);
|
|
838
783
|
if (config.tools.includes("copilot") || config.linkedProjects.length > 0) {
|
|
839
|
-
|
|
784
|
+
const selectedProjects = allProjects.filter(
|
|
785
|
+
(p) => config.linkedProjects.includes(`${p.name}:${p.source}`)
|
|
786
|
+
);
|
|
787
|
+
generateVSCodeWorkspace(workspacePath, workspaceName, selectedProjects, config.globalPath);
|
|
840
788
|
}
|
|
841
789
|
}
|
|
842
790
|
function getDataPaths(mode, workspaceName, workspaceRoot, customGlobalPath) {
|
|
@@ -858,13 +806,12 @@ function getDataPaths(mode, workspaceName, workspaceRoot, customGlobalPath) {
|
|
|
858
806
|
import { multiselect as multiselect2, spinner as spinner2, note as note2, outro as outro2, cancel as cancel2, isCancel as isCancel3 } from "@clack/prompts";
|
|
859
807
|
import pc3 from "picocolors";
|
|
860
808
|
import * as fs8 from "fs";
|
|
861
|
-
async function runLinkProjectsFlow(workspacePath, workspaceName
|
|
862
|
-
const
|
|
809
|
+
async function runLinkProjectsFlow(workspacePath, workspaceName) {
|
|
810
|
+
const projects = scanForProjects({
|
|
863
811
|
excludeWorkspace: workspaceName,
|
|
864
812
|
workspacePath,
|
|
865
813
|
scanSiblings: true
|
|
866
814
|
});
|
|
867
|
-
const projects = existingProjects ? existingProjects.map((name) => ({ name, source: "global" })) : detectedProjects;
|
|
868
815
|
if (projects.length === 0) {
|
|
869
816
|
outro2(pc3.yellow("No other projects found. Try setting up another project first."));
|
|
870
817
|
return;
|
|
@@ -873,9 +820,12 @@ async function runLinkProjectsFlow(workspacePath, workspaceName, existingProject
|
|
|
873
820
|
const linkedProjects = await multiselect2({
|
|
874
821
|
message: "Select projects to link:",
|
|
875
822
|
options: projects.map((project) => ({
|
|
876
|
-
value: project.name
|
|
877
|
-
|
|
878
|
-
|
|
823
|
+
value: `${project.name}:${project.source}`,
|
|
824
|
+
// Unique key
|
|
825
|
+
label: `${project.name} ${pc3.dim(`(${project.source})`)}`,
|
|
826
|
+
hint: pc3.dim(
|
|
827
|
+
project.source === "global" ? `~/.rrce-workflow/workspaces/${project.name}` : project.dataPath
|
|
828
|
+
)
|
|
879
829
|
})),
|
|
880
830
|
required: true
|
|
881
831
|
});
|
|
@@ -883,12 +833,14 @@ async function runLinkProjectsFlow(workspacePath, workspaceName, existingProject
|
|
|
883
833
|
cancel2("Cancelled.");
|
|
884
834
|
process.exit(0);
|
|
885
835
|
}
|
|
886
|
-
const
|
|
887
|
-
if (
|
|
836
|
+
const selectedKeys = linkedProjects;
|
|
837
|
+
if (selectedKeys.length === 0) {
|
|
888
838
|
outro2("No projects selected.");
|
|
889
839
|
return;
|
|
890
840
|
}
|
|
891
|
-
const selectedProjects = projects.filter(
|
|
841
|
+
const selectedProjects = projects.filter(
|
|
842
|
+
(p) => selectedKeys.includes(`${p.name}:${p.source}`)
|
|
843
|
+
);
|
|
892
844
|
const s = spinner2();
|
|
893
845
|
s.start("Linking projects");
|
|
894
846
|
const configFilePath = getConfigPath(workspacePath);
|
|
@@ -901,9 +853,10 @@ async function runLinkProjectsFlow(workspacePath, workspaceName, existingProject
|
|
|
901
853
|
while (insertIndex < lines.length && lines[insertIndex]?.startsWith(" - ")) {
|
|
902
854
|
insertIndex++;
|
|
903
855
|
}
|
|
904
|
-
for (const
|
|
905
|
-
|
|
906
|
-
|
|
856
|
+
for (const project of selectedProjects) {
|
|
857
|
+
const entry = ` - ${project.name}:${project.source}`;
|
|
858
|
+
if (!configContent.includes(entry)) {
|
|
859
|
+
lines.splice(insertIndex, 0, entry);
|
|
907
860
|
insertIndex++;
|
|
908
861
|
}
|
|
909
862
|
}
|
|
@@ -913,8 +866,8 @@ async function runLinkProjectsFlow(workspacePath, workspaceName, existingProject
|
|
|
913
866
|
configContent += `
|
|
914
867
|
linked_projects:
|
|
915
868
|
`;
|
|
916
|
-
|
|
917
|
-
configContent += ` - ${name}
|
|
869
|
+
selectedProjects.forEach((project) => {
|
|
870
|
+
configContent += ` - ${project.name}:${project.source}
|
|
918
871
|
`;
|
|
919
872
|
});
|
|
920
873
|
}
|
|
@@ -926,12 +879,10 @@ linked_projects:
|
|
|
926
879
|
`Linked projects:`,
|
|
927
880
|
...selectedProjects.map((p) => ` \u2713 ${p.name} ${pc3.dim(`(${p.source})`)}`),
|
|
928
881
|
``,
|
|
929
|
-
`Workspace file: ${pc3.cyan(workspaceFile)}
|
|
930
|
-
``,
|
|
931
|
-
pc3.dim("Includes: knowledge, refs, tasks folders")
|
|
882
|
+
`Workspace file: ${pc3.cyan(workspaceFile)}`
|
|
932
883
|
];
|
|
933
884
|
note2(summary.join("\n"), "Link Summary");
|
|
934
|
-
outro2(pc3.green(`\u2713 Projects linked! Open ${pc3.bold(workspaceFile)} in VSCode to access linked
|
|
885
|
+
outro2(pc3.green(`\u2713 Projects linked! Open ${pc3.bold(workspaceFile)} in VSCode to access linked data.`));
|
|
935
886
|
}
|
|
936
887
|
|
|
937
888
|
// src/commands/wizard/sync-flow.ts
|
|
@@ -1093,7 +1044,11 @@ async function runWizard() {
|
|
|
1093
1044
|
Workspace: ${pc6.bold(workspaceName)}`,
|
|
1094
1045
|
"Context"
|
|
1095
1046
|
);
|
|
1096
|
-
const
|
|
1047
|
+
const detectedProjects = scanForProjects({
|
|
1048
|
+
excludeWorkspace: workspaceName,
|
|
1049
|
+
workspacePath,
|
|
1050
|
+
scanSiblings: true
|
|
1051
|
+
});
|
|
1097
1052
|
const configFilePath = getConfigPath(workspacePath);
|
|
1098
1053
|
const isAlreadyConfigured = fs11.existsSync(configFilePath);
|
|
1099
1054
|
let currentStorageMode = null;
|
|
@@ -1109,11 +1064,11 @@ Workspace: ${pc6.bold(workspaceName)}`,
|
|
|
1109
1064
|
const hasLocalData = fs11.existsSync(localDataPath);
|
|
1110
1065
|
if (isAlreadyConfigured) {
|
|
1111
1066
|
const menuOptions = [];
|
|
1112
|
-
if (
|
|
1067
|
+
if (detectedProjects.length > 0) {
|
|
1113
1068
|
menuOptions.push({
|
|
1114
1069
|
value: "link",
|
|
1115
1070
|
label: "Link other project knowledge",
|
|
1116
|
-
hint: `${
|
|
1071
|
+
hint: `${detectedProjects.length} projects detected (global + sibling)`
|
|
1117
1072
|
});
|
|
1118
1073
|
}
|
|
1119
1074
|
if (currentStorageMode === "workspace" && hasLocalData) {
|
|
@@ -1134,7 +1089,7 @@ Workspace: ${pc6.bold(workspaceName)}`,
|
|
|
1134
1089
|
process.exit(0);
|
|
1135
1090
|
}
|
|
1136
1091
|
if (action === "link") {
|
|
1137
|
-
await runLinkProjectsFlow(workspacePath, workspaceName
|
|
1092
|
+
await runLinkProjectsFlow(workspacePath, workspaceName);
|
|
1138
1093
|
return;
|
|
1139
1094
|
}
|
|
1140
1095
|
if (action === "sync-global") {
|
|
@@ -1146,7 +1101,7 @@ Workspace: ${pc6.bold(workspaceName)}`,
|
|
|
1146
1101
|
return;
|
|
1147
1102
|
}
|
|
1148
1103
|
}
|
|
1149
|
-
await runSetupFlow(workspacePath, workspaceName,
|
|
1104
|
+
await runSetupFlow(workspacePath, workspaceName, detectedProjects);
|
|
1150
1105
|
}
|
|
1151
1106
|
|
|
1152
1107
|
// src/commands/selector.ts
|