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/agent-core/prompts/documentation.md +2 -2
- package/agent-core/prompts/executor.md +6 -9
- package/agent-core/prompts/init.md +9 -8
- package/agent-core/prompts/planning_orchestrator.md +2 -2
- package/agent-core/prompts/research_discussion.md +2 -2
- package/agent-core/prompts/sync.md +2 -2
- package/agent-core/templates/documentation_output.md +2 -2
- package/agent-core/templates/executor_output.md +2 -2
- package/agent-core/templates/init_output.md +2 -2
- package/agent-core/templates/planning_output.md +2 -2
- package/agent-core/templates/research_output.md +2 -2
- package/package.json +1 -1
- package/src/commands/wizard/index.ts +114 -0
- package/src/commands/wizard/link-flow.ts +101 -0
- package/src/commands/wizard/setup-flow.ts +356 -0
- package/src/commands/wizard/sync-flow.ts +93 -0
- package/src/commands/wizard/update-flow.ts +129 -0
- package/src/commands/wizard/utils.ts +38 -0
- package/src/commands/wizard/vscode.ts +66 -0
- package/src/index.ts +1 -1
- package/src/lib/paths.ts +117 -6
- package/src/types/prompt.ts +3 -2
- package/src/commands/wizard.ts +0 -612
package/src/commands/wizard.ts
DELETED
|
@@ -1,612 +0,0 @@
|
|
|
1
|
-
import { intro, group, text, select, multiselect, confirm, spinner, note, outro, cancel, isCancel } from '@clack/prompts';
|
|
2
|
-
import pc from 'picocolors';
|
|
3
|
-
import * as fs from 'fs';
|
|
4
|
-
import * as path from 'path';
|
|
5
|
-
import { getGitUser } from '../lib/git';
|
|
6
|
-
import { detectWorkspaceRoot, getWorkspaceName, resolveAllDataPaths, ensureDir, getAgentPromptPath, syncMetadataToAll, copyDirToAllStoragePaths, listGlobalProjects, getGlobalProjectKnowledgePath, getRRCEHome, getGlobalWorkspacePath, getLocalWorkspacePath } from '../lib/paths';
|
|
7
|
-
import type { StorageMode } from '../types/prompt';
|
|
8
|
-
import { loadPromptsFromDir, getAgentCorePromptsDir, getAgentCoreDir } from '../lib/prompts';
|
|
9
|
-
|
|
10
|
-
import type { ParsedPrompt } from '../types/prompt';
|
|
11
|
-
|
|
12
|
-
export async function runWizard() {
|
|
13
|
-
intro(pc.cyan(pc.inverse(' RRCE-Workflow Setup ')));
|
|
14
|
-
|
|
15
|
-
const s = spinner();
|
|
16
|
-
s.start('Detecting environment');
|
|
17
|
-
|
|
18
|
-
const workspacePath = detectWorkspaceRoot();
|
|
19
|
-
const workspaceName = getWorkspaceName(workspacePath);
|
|
20
|
-
const gitUser = getGitUser();
|
|
21
|
-
|
|
22
|
-
await new Promise(r => setTimeout(r, 800)); // Dramatic pause
|
|
23
|
-
s.stop('Environment detected');
|
|
24
|
-
|
|
25
|
-
note(
|
|
26
|
-
`Git User: ${pc.bold(gitUser || '(not found)')}
|
|
27
|
-
Workspace: ${pc.bold(workspaceName)}`,
|
|
28
|
-
'Context'
|
|
29
|
-
);
|
|
30
|
-
|
|
31
|
-
// Check for existing projects in global storage
|
|
32
|
-
const existingProjects = listGlobalProjects(workspaceName);
|
|
33
|
-
|
|
34
|
-
// Check if already configured
|
|
35
|
-
const configFilePath = path.join(workspacePath, '.rrce-workflow.yaml');
|
|
36
|
-
const isAlreadyConfigured = fs.existsSync(configFilePath);
|
|
37
|
-
|
|
38
|
-
// Check current storage mode from config
|
|
39
|
-
let currentStorageMode: string | null = null;
|
|
40
|
-
if (isAlreadyConfigured) {
|
|
41
|
-
try {
|
|
42
|
-
const configContent = fs.readFileSync(configFilePath, 'utf-8');
|
|
43
|
-
const modeMatch = configContent.match(/mode:\s*(global|workspace|both)/);
|
|
44
|
-
currentStorageMode = modeMatch?.[1] ?? null;
|
|
45
|
-
} catch {
|
|
46
|
-
// Ignore parse errors
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
// Check if workspace has local data that could be synced
|
|
51
|
-
const localDataPath = path.join(workspacePath, '.rrce-workflow');
|
|
52
|
-
const hasLocalData = fs.existsSync(localDataPath);
|
|
53
|
-
|
|
54
|
-
// If already configured, show menu
|
|
55
|
-
if (isAlreadyConfigured) {
|
|
56
|
-
const menuOptions: { value: string; label: string; hint?: string }[] = [];
|
|
57
|
-
|
|
58
|
-
// Add link option if other projects exist
|
|
59
|
-
if (existingProjects.length > 0) {
|
|
60
|
-
menuOptions.push({
|
|
61
|
-
value: 'link',
|
|
62
|
-
label: 'Link other project knowledge',
|
|
63
|
-
hint: `${existingProjects.length} projects available`
|
|
64
|
-
});
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
// Add sync to global option if using workspace-only mode
|
|
68
|
-
if (currentStorageMode === 'workspace' && hasLocalData) {
|
|
69
|
-
menuOptions.push({
|
|
70
|
-
value: 'sync-global',
|
|
71
|
-
label: 'Sync to global storage',
|
|
72
|
-
hint: 'Share knowledge with other projects'
|
|
73
|
-
});
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
menuOptions.push({ value: 'update', label: 'Update from package', hint: 'Get latest prompts & templates' });
|
|
77
|
-
menuOptions.push({ value: 'exit', label: 'Exit' });
|
|
78
|
-
|
|
79
|
-
const action = await select({
|
|
80
|
-
message: 'This workspace is already configured. What would you like to do?',
|
|
81
|
-
options: menuOptions,
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
if (isCancel(action) || action === 'exit') {
|
|
85
|
-
outro('Exited.');
|
|
86
|
-
process.exit(0);
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
if (action === 'link') {
|
|
90
|
-
await runLinkProjectsFlow(workspacePath, workspaceName, existingProjects);
|
|
91
|
-
return;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
if (action === 'sync-global') {
|
|
95
|
-
await runSyncToGlobalFlow(workspacePath, workspaceName);
|
|
96
|
-
return;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
if (action === 'update') {
|
|
100
|
-
await runUpdateFlow(workspacePath, workspaceName, currentStorageMode);
|
|
101
|
-
return;
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
// Full setup flow
|
|
106
|
-
const config = await group(
|
|
107
|
-
{
|
|
108
|
-
storageMode: () =>
|
|
109
|
-
select({
|
|
110
|
-
message: 'Where should workflow data be stored?',
|
|
111
|
-
options: [
|
|
112
|
-
{ value: 'global', label: 'Global (~/.rrce-workflow/)' },
|
|
113
|
-
{ value: 'workspace', label: 'Workspace (.rrce-workflow/)' },
|
|
114
|
-
{ value: 'both', label: 'Both' },
|
|
115
|
-
],
|
|
116
|
-
initialValue: 'global',
|
|
117
|
-
}),
|
|
118
|
-
tools: () =>
|
|
119
|
-
multiselect({
|
|
120
|
-
message: 'Which AI tools do you use?',
|
|
121
|
-
options: [
|
|
122
|
-
{ value: 'copilot', label: 'GitHub Copilot', hint: 'VSCode' },
|
|
123
|
-
{ value: 'antigravity', label: 'Antigravity IDE' },
|
|
124
|
-
],
|
|
125
|
-
required: false,
|
|
126
|
-
}),
|
|
127
|
-
linkedProjects: () => {
|
|
128
|
-
// Only show if there are other projects to link
|
|
129
|
-
if (existingProjects.length === 0) {
|
|
130
|
-
return Promise.resolve([]);
|
|
131
|
-
}
|
|
132
|
-
return multiselect({
|
|
133
|
-
message: 'Link knowledge from other projects?',
|
|
134
|
-
options: existingProjects.map(name => ({
|
|
135
|
-
value: name,
|
|
136
|
-
label: name,
|
|
137
|
-
hint: `~/.rrce-workflow/workspaces/${name}/knowledge`
|
|
138
|
-
})),
|
|
139
|
-
required: false,
|
|
140
|
-
});
|
|
141
|
-
},
|
|
142
|
-
confirm: () =>
|
|
143
|
-
confirm({
|
|
144
|
-
message: 'Create configuration?',
|
|
145
|
-
initialValue: true,
|
|
146
|
-
}),
|
|
147
|
-
},
|
|
148
|
-
{
|
|
149
|
-
onCancel: () => {
|
|
150
|
-
cancel('Setup process cancelled.');
|
|
151
|
-
process.exit(0);
|
|
152
|
-
},
|
|
153
|
-
}
|
|
154
|
-
);
|
|
155
|
-
|
|
156
|
-
if (!config.confirm) {
|
|
157
|
-
outro('Setup cancelled by user.');
|
|
158
|
-
process.exit(0);
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
s.start('Generating configuration');
|
|
162
|
-
|
|
163
|
-
try {
|
|
164
|
-
// Create data directories in all storage locations
|
|
165
|
-
const dataPaths = resolveAllDataPaths(config.storageMode as StorageMode, workspaceName, workspacePath);
|
|
166
|
-
|
|
167
|
-
for (const dataPath of dataPaths) {
|
|
168
|
-
ensureDir(dataPath);
|
|
169
|
-
// Create agent metadata subdirectories
|
|
170
|
-
ensureDir(path.join(dataPath, 'knowledge'));
|
|
171
|
-
ensureDir(path.join(dataPath, 'refs'));
|
|
172
|
-
ensureDir(path.join(dataPath, 'tasks'));
|
|
173
|
-
ensureDir(path.join(dataPath, 'templates'));
|
|
174
|
-
ensureDir(path.join(dataPath, 'prompts'));
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
// Get the agent-core directory path
|
|
178
|
-
const agentCoreDir = getAgentCoreDir();
|
|
179
|
-
|
|
180
|
-
// Sync metadata (knowledge, refs, tasks) from agent-core to all storage locations
|
|
181
|
-
syncMetadataToAll(agentCoreDir, dataPaths);
|
|
182
|
-
|
|
183
|
-
// Also copy templates to all storage locations
|
|
184
|
-
copyDirToAllStoragePaths(path.join(agentCoreDir, 'templates'), 'templates', dataPaths);
|
|
185
|
-
|
|
186
|
-
// Load prompts
|
|
187
|
-
const prompts = loadPromptsFromDir(getAgentCorePromptsDir());
|
|
188
|
-
|
|
189
|
-
// Copy prompts to all storage locations (for cross-project access)
|
|
190
|
-
for (const dataPath of dataPaths) {
|
|
191
|
-
const promptsDir = path.join(dataPath, 'prompts');
|
|
192
|
-
ensureDir(promptsDir);
|
|
193
|
-
copyPromptsToDir(prompts, promptsDir, '.md');
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
// Copy prompts to tool-specific locations (for IDE integration)
|
|
197
|
-
const selectedTools = config.tools as string[];
|
|
198
|
-
|
|
199
|
-
if (selectedTools.includes('copilot')) {
|
|
200
|
-
const copilotPath = getAgentPromptPath(workspacePath, 'copilot');
|
|
201
|
-
ensureDir(copilotPath);
|
|
202
|
-
copyPromptsToDir(prompts, copilotPath, '.agent.md');
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
if (selectedTools.includes('antigravity')) {
|
|
206
|
-
const antigravityPath = getAgentPromptPath(workspacePath, 'antigravity');
|
|
207
|
-
ensureDir(antigravityPath);
|
|
208
|
-
copyPromptsToDir(prompts, antigravityPath, '.md');
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
// Create workspace config
|
|
212
|
-
const linkedProjects = config.linkedProjects as string[];
|
|
213
|
-
const workspaceConfigPath = path.join(workspacePath, '.rrce-workflow.yaml');
|
|
214
|
-
let configContent = `# RRCE-Workflow Configuration
|
|
215
|
-
version: 1
|
|
216
|
-
|
|
217
|
-
storage:
|
|
218
|
-
mode: ${config.storageMode}
|
|
219
|
-
|
|
220
|
-
project:
|
|
221
|
-
name: "${workspaceName}"
|
|
222
|
-
|
|
223
|
-
tools:
|
|
224
|
-
copilot: ${selectedTools.includes('copilot')}
|
|
225
|
-
antigravity: ${selectedTools.includes('antigravity')}
|
|
226
|
-
`;
|
|
227
|
-
|
|
228
|
-
// Add linked projects if any
|
|
229
|
-
if (linkedProjects.length > 0) {
|
|
230
|
-
configContent += `\nlinked_projects:\n`;
|
|
231
|
-
linkedProjects.forEach(name => {
|
|
232
|
-
configContent += ` - ${name}\n`;
|
|
233
|
-
});
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
fs.writeFileSync(workspaceConfigPath, configContent);
|
|
237
|
-
|
|
238
|
-
// Generate VSCode workspace file if using copilot or has linked projects
|
|
239
|
-
if (selectedTools.includes('copilot') || linkedProjects.length > 0) {
|
|
240
|
-
generateVSCodeWorkspace(workspacePath, workspaceName, linkedProjects);
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
s.stop('Configuration generated');
|
|
244
|
-
|
|
245
|
-
// Show summary
|
|
246
|
-
const summary = [
|
|
247
|
-
`Storage: ${config.storageMode === 'both' ? 'global + workspace' : config.storageMode}`,
|
|
248
|
-
];
|
|
249
|
-
|
|
250
|
-
if (dataPaths.length > 0) {
|
|
251
|
-
summary.push(`Data paths:`);
|
|
252
|
-
dataPaths.forEach(p => summary.push(` - ${p}`));
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
if (selectedTools.length > 0) {
|
|
256
|
-
summary.push(`Tools: ${selectedTools.join(', ')}`);
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
if (linkedProjects.length > 0) {
|
|
260
|
-
summary.push(`Linked projects: ${linkedProjects.join(', ')}`);
|
|
261
|
-
summary.push(`Workspace file: ${pc.cyan(`${workspaceName}.code-workspace`)}`);
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
note(summary.join('\n'), 'Setup Summary');
|
|
265
|
-
|
|
266
|
-
// Show appropriate outro message
|
|
267
|
-
if (linkedProjects.length > 0) {
|
|
268
|
-
outro(pc.green(`✓ Setup complete! Open ${pc.bold(`${workspaceName}.code-workspace`)} in VSCode to access linked knowledge.`));
|
|
269
|
-
} else {
|
|
270
|
-
outro(pc.green(`✓ Setup complete! Your agents are ready to use.`));
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
} catch (error) {
|
|
274
|
-
s.stop('Error occurred');
|
|
275
|
-
cancel(`Failed to setup: ${error instanceof Error ? error.message : String(error)}`);
|
|
276
|
-
process.exit(1);
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
function copyPromptsToDir(prompts: ParsedPrompt[], targetDir: string, extension: string) {
|
|
281
|
-
for (const prompt of prompts) {
|
|
282
|
-
const baseName = path.basename(prompt.filePath, '.md');
|
|
283
|
-
const targetName = baseName + extension;
|
|
284
|
-
const targetPath = path.join(targetDir, targetName);
|
|
285
|
-
|
|
286
|
-
// Read the full content including frontmatter
|
|
287
|
-
const content = fs.readFileSync(prompt.filePath, 'utf-8');
|
|
288
|
-
fs.writeFileSync(targetPath, content);
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
interface VSCodeWorkspaceFolder {
|
|
293
|
-
path: string;
|
|
294
|
-
name?: string;
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
interface VSCodeWorkspace {
|
|
298
|
-
folders: VSCodeWorkspaceFolder[];
|
|
299
|
-
settings?: Record<string, unknown>;
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
/**
|
|
303
|
-
* Generate or update VSCode workspace file with linked project knowledge folders
|
|
304
|
-
*/
|
|
305
|
-
function generateVSCodeWorkspace(workspacePath: string, workspaceName: string, linkedProjects: string[]) {
|
|
306
|
-
const workspaceFilePath = path.join(workspacePath, `${workspaceName}.code-workspace`);
|
|
307
|
-
|
|
308
|
-
let workspace: VSCodeWorkspace;
|
|
309
|
-
|
|
310
|
-
// Check if workspace file already exists
|
|
311
|
-
if (fs.existsSync(workspaceFilePath)) {
|
|
312
|
-
try {
|
|
313
|
-
const content = fs.readFileSync(workspaceFilePath, 'utf-8');
|
|
314
|
-
workspace = JSON.parse(content);
|
|
315
|
-
} catch {
|
|
316
|
-
// If parse fails, create new
|
|
317
|
-
workspace = { folders: [] };
|
|
318
|
-
}
|
|
319
|
-
} else {
|
|
320
|
-
workspace = { folders: [] };
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
// Ensure main workspace folder is first
|
|
324
|
-
const mainFolder: VSCodeWorkspaceFolder = { path: '.' };
|
|
325
|
-
const existingMainIndex = workspace.folders.findIndex(f => f.path === '.');
|
|
326
|
-
if (existingMainIndex === -1) {
|
|
327
|
-
workspace.folders.unshift(mainFolder);
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
// Add linked project knowledge folders
|
|
331
|
-
const rrceHome = getRRCEHome();
|
|
332
|
-
for (const projectName of linkedProjects) {
|
|
333
|
-
const knowledgePath = path.join(rrceHome, 'workspaces', projectName, 'knowledge');
|
|
334
|
-
const folderEntry: VSCodeWorkspaceFolder = {
|
|
335
|
-
path: knowledgePath,
|
|
336
|
-
name: `📚 ${projectName} (knowledge)`
|
|
337
|
-
};
|
|
338
|
-
|
|
339
|
-
// Check if already exists
|
|
340
|
-
const existingIndex = workspace.folders.findIndex(f => f.path === knowledgePath);
|
|
341
|
-
if (existingIndex === -1) {
|
|
342
|
-
workspace.folders.push(folderEntry);
|
|
343
|
-
}
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
// Write workspace file
|
|
347
|
-
fs.writeFileSync(workspaceFilePath, JSON.stringify(workspace, null, 2));
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
/**
|
|
351
|
-
* Run the link-only flow for adding other project knowledge to an existing workspace
|
|
352
|
-
*/
|
|
353
|
-
async function runLinkProjectsFlow(workspacePath: string, workspaceName: string, existingProjects: string[]) {
|
|
354
|
-
const linkedProjects = await multiselect({
|
|
355
|
-
message: 'Select projects to link:',
|
|
356
|
-
options: existingProjects.map(name => ({
|
|
357
|
-
value: name,
|
|
358
|
-
label: name,
|
|
359
|
-
hint: `~/.rrce-workflow/workspaces/${name}/knowledge`
|
|
360
|
-
})),
|
|
361
|
-
required: true,
|
|
362
|
-
});
|
|
363
|
-
|
|
364
|
-
if (isCancel(linkedProjects)) {
|
|
365
|
-
cancel('Cancelled.');
|
|
366
|
-
process.exit(0);
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
const selectedProjects = linkedProjects as string[];
|
|
370
|
-
|
|
371
|
-
if (selectedProjects.length === 0) {
|
|
372
|
-
outro('No projects selected.');
|
|
373
|
-
return;
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
const s = spinner();
|
|
377
|
-
s.start('Linking projects');
|
|
378
|
-
|
|
379
|
-
// Update .rrce-workflow.yaml with linked projects
|
|
380
|
-
const configFilePath = path.join(workspacePath, '.rrce-workflow.yaml');
|
|
381
|
-
let configContent = fs.readFileSync(configFilePath, 'utf-8');
|
|
382
|
-
|
|
383
|
-
// Check if linked_projects section exists
|
|
384
|
-
if (configContent.includes('linked_projects:')) {
|
|
385
|
-
// Append to existing section - find and update
|
|
386
|
-
const lines = configContent.split('\n');
|
|
387
|
-
const linkedIndex = lines.findIndex(l => l.trim() === 'linked_projects:');
|
|
388
|
-
if (linkedIndex !== -1) {
|
|
389
|
-
// Find where to insert new projects (after existing ones)
|
|
390
|
-
let insertIndex = linkedIndex + 1;
|
|
391
|
-
while (insertIndex < lines.length && lines[insertIndex]?.startsWith(' - ')) {
|
|
392
|
-
insertIndex++;
|
|
393
|
-
}
|
|
394
|
-
// Add new projects that aren't already there
|
|
395
|
-
for (const name of selectedProjects) {
|
|
396
|
-
if (!configContent.includes(` - ${name}`)) {
|
|
397
|
-
lines.splice(insertIndex, 0, ` - ${name}`);
|
|
398
|
-
insertIndex++;
|
|
399
|
-
}
|
|
400
|
-
}
|
|
401
|
-
configContent = lines.join('\n');
|
|
402
|
-
}
|
|
403
|
-
} else {
|
|
404
|
-
// Add new linked_projects section
|
|
405
|
-
configContent += `\nlinked_projects:\n`;
|
|
406
|
-
selectedProjects.forEach(name => {
|
|
407
|
-
configContent += ` - ${name}\n`;
|
|
408
|
-
});
|
|
409
|
-
}
|
|
410
|
-
|
|
411
|
-
fs.writeFileSync(configFilePath, configContent);
|
|
412
|
-
|
|
413
|
-
// Update VSCode workspace file
|
|
414
|
-
generateVSCodeWorkspace(workspacePath, workspaceName, selectedProjects);
|
|
415
|
-
|
|
416
|
-
s.stop('Projects linked');
|
|
417
|
-
|
|
418
|
-
// Show summary
|
|
419
|
-
const workspaceFile = `${workspaceName}.code-workspace`;
|
|
420
|
-
const summary = [
|
|
421
|
-
`Linked projects:`,
|
|
422
|
-
...selectedProjects.map(p => ` ✓ ${p}`),
|
|
423
|
-
``,
|
|
424
|
-
`Workspace file: ${pc.cyan(workspaceFile)}`,
|
|
425
|
-
];
|
|
426
|
-
|
|
427
|
-
note(summary.join('\n'), 'Link Summary');
|
|
428
|
-
|
|
429
|
-
outro(pc.green(`✓ Projects linked! Open ${pc.bold(workspaceFile)} in VSCode to access linked knowledge.`));
|
|
430
|
-
}
|
|
431
|
-
|
|
432
|
-
/**
|
|
433
|
-
* Sync workspace knowledge to global storage so other projects can reference it
|
|
434
|
-
*/
|
|
435
|
-
async function runSyncToGlobalFlow(workspacePath: string, workspaceName: string) {
|
|
436
|
-
const localPath = getLocalWorkspacePath(workspacePath);
|
|
437
|
-
const globalPath = getGlobalWorkspacePath(workspaceName);
|
|
438
|
-
|
|
439
|
-
// Check what exists locally
|
|
440
|
-
const subdirs = ['knowledge', 'prompts', 'templates', 'tasks', 'refs'];
|
|
441
|
-
const existingDirs = subdirs.filter(dir =>
|
|
442
|
-
fs.existsSync(path.join(localPath, dir))
|
|
443
|
-
);
|
|
444
|
-
|
|
445
|
-
if (existingDirs.length === 0) {
|
|
446
|
-
outro(pc.yellow('No data found in workspace storage to sync.'));
|
|
447
|
-
return;
|
|
448
|
-
}
|
|
449
|
-
|
|
450
|
-
// Show what will be synced
|
|
451
|
-
note(
|
|
452
|
-
`The following will be copied to global storage:\n${existingDirs.map(d => ` • ${d}/`).join('\n')}\n\nDestination: ${pc.cyan(globalPath)}`,
|
|
453
|
-
'Sync Preview'
|
|
454
|
-
);
|
|
455
|
-
|
|
456
|
-
const shouldSync = await confirm({
|
|
457
|
-
message: 'Proceed with sync to global storage?',
|
|
458
|
-
initialValue: true,
|
|
459
|
-
});
|
|
460
|
-
|
|
461
|
-
if (isCancel(shouldSync) || !shouldSync) {
|
|
462
|
-
outro('Sync cancelled.');
|
|
463
|
-
return;
|
|
464
|
-
}
|
|
465
|
-
|
|
466
|
-
const s = spinner();
|
|
467
|
-
s.start('Syncing to global storage');
|
|
468
|
-
|
|
469
|
-
try {
|
|
470
|
-
// Ensure global directory exists
|
|
471
|
-
ensureDir(globalPath);
|
|
472
|
-
|
|
473
|
-
// Copy each directory
|
|
474
|
-
for (const dir of existingDirs) {
|
|
475
|
-
const srcDir = path.join(localPath, dir);
|
|
476
|
-
const destDir = path.join(globalPath, dir);
|
|
477
|
-
ensureDir(destDir);
|
|
478
|
-
|
|
479
|
-
// Copy files recursively
|
|
480
|
-
copyDirRecursive(srcDir, destDir);
|
|
481
|
-
}
|
|
482
|
-
|
|
483
|
-
// Update the config to reflect 'both' mode
|
|
484
|
-
const configFilePath = path.join(workspacePath, '.rrce-workflow.yaml');
|
|
485
|
-
let configContent = fs.readFileSync(configFilePath, 'utf-8');
|
|
486
|
-
configContent = configContent.replace(/mode:\s*workspace/, 'mode: both');
|
|
487
|
-
fs.writeFileSync(configFilePath, configContent);
|
|
488
|
-
|
|
489
|
-
s.stop('Sync complete');
|
|
490
|
-
|
|
491
|
-
const summary = [
|
|
492
|
-
`Synced directories:`,
|
|
493
|
-
...existingDirs.map(d => ` ✓ ${d}/`),
|
|
494
|
-
``,
|
|
495
|
-
`Global path: ${pc.cyan(globalPath)}`,
|
|
496
|
-
`Storage mode updated to: ${pc.bold('both')}`,
|
|
497
|
-
``,
|
|
498
|
-
`Other projects can now link this knowledge!`,
|
|
499
|
-
];
|
|
500
|
-
|
|
501
|
-
note(summary.join('\n'), 'Sync Summary');
|
|
502
|
-
|
|
503
|
-
outro(pc.green('✓ Workspace knowledge synced to global storage!'));
|
|
504
|
-
|
|
505
|
-
} catch (error) {
|
|
506
|
-
s.stop('Error occurred');
|
|
507
|
-
cancel(`Failed to sync: ${error instanceof Error ? error.message : String(error)}`);
|
|
508
|
-
process.exit(1);
|
|
509
|
-
}
|
|
510
|
-
}
|
|
511
|
-
|
|
512
|
-
/**
|
|
513
|
-
* Recursively copy a directory
|
|
514
|
-
*/
|
|
515
|
-
function copyDirRecursive(src: string, dest: string) {
|
|
516
|
-
const entries = fs.readdirSync(src, { withFileTypes: true });
|
|
517
|
-
|
|
518
|
-
for (const entry of entries) {
|
|
519
|
-
const srcPath = path.join(src, entry.name);
|
|
520
|
-
const destPath = path.join(dest, entry.name);
|
|
521
|
-
|
|
522
|
-
if (entry.isDirectory()) {
|
|
523
|
-
ensureDir(destPath);
|
|
524
|
-
copyDirRecursive(srcPath, destPath);
|
|
525
|
-
} else {
|
|
526
|
-
fs.copyFileSync(srcPath, destPath);
|
|
527
|
-
}
|
|
528
|
-
}
|
|
529
|
-
}
|
|
530
|
-
|
|
531
|
-
/**
|
|
532
|
-
* Update prompts and templates from the package without resetting config
|
|
533
|
-
*/
|
|
534
|
-
async function runUpdateFlow(workspacePath: string, workspaceName: string, currentStorageMode: string | null) {
|
|
535
|
-
const s = spinner();
|
|
536
|
-
s.start('Checking for updates');
|
|
537
|
-
|
|
538
|
-
try {
|
|
539
|
-
const agentCoreDir = getAgentCoreDir();
|
|
540
|
-
const prompts = loadPromptsFromDir(getAgentCorePromptsDir());
|
|
541
|
-
|
|
542
|
-
// Determine storage paths based on current mode
|
|
543
|
-
const mode = (currentStorageMode as StorageMode) || 'global';
|
|
544
|
-
const dataPaths = resolveAllDataPaths(mode, workspaceName, workspacePath);
|
|
545
|
-
|
|
546
|
-
s.stop('Updates found');
|
|
547
|
-
|
|
548
|
-
// Show what will be updated
|
|
549
|
-
note(
|
|
550
|
-
`The following will be updated from the package:\n • prompts/ (${prompts.length} agent prompts)\n • templates/ (output templates)\n\nTarget locations:\n${dataPaths.map(p => ` • ${p}`).join('\n')}`,
|
|
551
|
-
'Update Preview'
|
|
552
|
-
);
|
|
553
|
-
|
|
554
|
-
const shouldUpdate = await confirm({
|
|
555
|
-
message: 'Proceed with update?',
|
|
556
|
-
initialValue: true,
|
|
557
|
-
});
|
|
558
|
-
|
|
559
|
-
if (isCancel(shouldUpdate) || !shouldUpdate) {
|
|
560
|
-
outro('Update cancelled.');
|
|
561
|
-
return;
|
|
562
|
-
}
|
|
563
|
-
|
|
564
|
-
s.start('Updating from package');
|
|
565
|
-
|
|
566
|
-
// Update prompts and templates in all storage locations
|
|
567
|
-
for (const dataPath of dataPaths) {
|
|
568
|
-
// Update prompts
|
|
569
|
-
const promptsDir = path.join(dataPath, 'prompts');
|
|
570
|
-
ensureDir(promptsDir);
|
|
571
|
-
copyPromptsToDir(prompts, promptsDir, '.md');
|
|
572
|
-
|
|
573
|
-
// Update templates
|
|
574
|
-
copyDirToAllStoragePaths(path.join(agentCoreDir, 'templates'), 'templates', [dataPath]);
|
|
575
|
-
}
|
|
576
|
-
|
|
577
|
-
// Also update tool-specific locations if configured
|
|
578
|
-
const configFilePath = path.join(workspacePath, '.rrce-workflow.yaml');
|
|
579
|
-
const configContent = fs.readFileSync(configFilePath, 'utf-8');
|
|
580
|
-
|
|
581
|
-
if (configContent.includes('copilot: true')) {
|
|
582
|
-
const copilotPath = getAgentPromptPath(workspacePath, 'copilot');
|
|
583
|
-
ensureDir(copilotPath);
|
|
584
|
-
copyPromptsToDir(prompts, copilotPath, '.agent.md');
|
|
585
|
-
}
|
|
586
|
-
|
|
587
|
-
if (configContent.includes('antigravity: true')) {
|
|
588
|
-
const antigravityPath = getAgentPromptPath(workspacePath, 'antigravity');
|
|
589
|
-
ensureDir(antigravityPath);
|
|
590
|
-
copyPromptsToDir(prompts, antigravityPath, '.md');
|
|
591
|
-
}
|
|
592
|
-
|
|
593
|
-
s.stop('Update complete');
|
|
594
|
-
|
|
595
|
-
const summary = [
|
|
596
|
-
`Updated:`,
|
|
597
|
-
` ✓ ${prompts.length} agent prompts`,
|
|
598
|
-
` ✓ Output templates`,
|
|
599
|
-
``,
|
|
600
|
-
`Your configuration and knowledge files were preserved.`,
|
|
601
|
-
];
|
|
602
|
-
|
|
603
|
-
note(summary.join('\n'), 'Update Summary');
|
|
604
|
-
|
|
605
|
-
outro(pc.green('✓ Successfully updated from package!'));
|
|
606
|
-
|
|
607
|
-
} catch (error) {
|
|
608
|
-
s.stop('Error occurred');
|
|
609
|
-
cancel(`Failed to update: ${error instanceof Error ? error.message : String(error)}`);
|
|
610
|
-
process.exit(1);
|
|
611
|
-
}
|
|
612
|
-
}
|