rrce-workflow 0.1.1 → 0.1.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rrce-workflow",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "RRCE-Workflow TUI - Agentic code workflow generator for AI-assisted development",
5
5
  "author": "RRCE Team",
6
6
  "license": "MIT",
@@ -24,7 +24,7 @@
24
24
  "ink"
25
25
  ],
26
26
  "type": "module",
27
- "module": "src/index.tsx",
27
+ "module": "src/index.ts",
28
28
  "bin": {
29
29
  "rrce-workflow": "bin/rrce-workflow.js"
30
30
  },
@@ -35,28 +35,22 @@
35
35
  "bin"
36
36
  ],
37
37
  "scripts": {
38
- "dev": "bun run src/index.tsx",
39
- "wizard": "bun run src/index.tsx wizard",
40
- "select": "bun run src/index.tsx select",
41
- "start": "bun run src/index.tsx"
38
+ "dev": "bun run src/index.ts",
39
+ "wizard": "bun run src/index.ts wizard",
40
+ "select": "bun run src/index.ts select",
41
+ "start": "bun run src/index.ts"
42
42
  },
43
43
  "engines": {
44
44
  "node": ">=18",
45
45
  "bun": ">=1.0"
46
46
  },
47
47
  "dependencies": {
48
+ "@clack/prompts": "^0.11.0",
48
49
  "gray-matter": "^4.0.3",
49
- "ink": "^5.0.0",
50
- "ink-big-text": "^2.0.0",
51
- "ink-gradient": "^3.0.0",
52
- "ink-select-input": "^5.0.0",
53
- "ink-spinner": "^5.0.0",
54
- "pastel": "^4.0.0",
55
- "react": "^18",
56
- "zod": "^4"
50
+ "picocolors": "^1.1.1",
51
+ "zod": "^4.2.1"
57
52
  },
58
53
  "devDependencies": {
59
- "@types/bun": "latest",
60
- "@types/react": "^18"
54
+ "@types/bun": "latest"
61
55
  }
62
56
  }
@@ -0,0 +1,42 @@
1
+ import { intro, select, note, cancel, isCancel, outro } from '@clack/prompts';
2
+ import pc from 'picocolors';
3
+ import * as path from 'path';
4
+ import { loadPromptsFromDir, getAgentCorePromptsDir } from '../lib/prompts';
5
+ import type { ParsedPrompt } from '../types/prompt';
6
+
7
+ export async function runSelector() {
8
+ const workspaceName = path.basename(process.cwd());
9
+
10
+ intro(pc.cyan(pc.inverse(` RRCE-Workflow | ${workspaceName} `)));
11
+
12
+ const prompts = loadPromptsFromDir(getAgentCorePromptsDir());
13
+
14
+ if (prompts.length === 0) {
15
+ cancel('No agents found. Run `rrce-workflow` to set up.');
16
+ process.exit(0);
17
+ }
18
+
19
+ const selection = await select({
20
+ message: 'Select an agent:',
21
+ options: prompts.map(p => ({
22
+ value: p,
23
+ label: p.frontmatter.name,
24
+ hint: p.frontmatter.description
25
+ })),
26
+ });
27
+
28
+ if (isCancel(selection)) {
29
+ cancel('Selection cancelled.');
30
+ process.exit(0);
31
+ }
32
+
33
+ const prompt = selection as ParsedPrompt;
34
+
35
+ note(
36
+ `Use this agent in your IDE by invoking:
37
+ ${pc.bold(pc.cyan(`@${prompt.frontmatter.name}`))}`,
38
+ 'Agent Selected'
39
+ );
40
+
41
+ outro('Done');
42
+ }
@@ -0,0 +1,130 @@
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, resolveDataPath, ensureDir, getAgentPromptPath } from '../lib/paths';
7
+ import type { StorageMode } from '../types/prompt';
8
+ import { loadPromptsFromDir, getAgentCorePromptsDir } 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
+ const config = await group(
32
+ {
33
+ storageMode: () =>
34
+ select({
35
+ message: 'Where should workflow data be stored?',
36
+ options: [
37
+ { value: 'global', label: 'Global (~/.rrce-workflow/)' },
38
+ { value: 'workspace', label: 'Workspace (.rrce-workflow/)' },
39
+ { value: 'both', label: 'Both' },
40
+ ],
41
+ initialValue: 'global',
42
+ }),
43
+ tools: () =>
44
+ multiselect({
45
+ message: 'Which AI tools do you use?',
46
+ options: [
47
+ { value: 'copilot', label: 'GitHub Copilot', hint: 'VSCode' },
48
+ { value: 'antigravity', label: 'Antigravity IDE' },
49
+ ],
50
+ required: false,
51
+ }),
52
+ confirm: () =>
53
+ confirm({
54
+ message: 'Create configuration?',
55
+ initialValue: true,
56
+ }),
57
+ },
58
+ {
59
+ onCancel: () => {
60
+ cancel('Setup process cancelled.');
61
+ process.exit(0);
62
+ },
63
+ }
64
+ );
65
+
66
+ if (!config.confirm) {
67
+ outro('Setup cancelled by user.');
68
+ process.exit(0);
69
+ }
70
+
71
+ s.start('Generating configuration');
72
+
73
+ try {
74
+ // Create config file
75
+ const dataPath = resolveDataPath(config.storageMode as StorageMode, workspaceName, workspacePath);
76
+ ensureDir(dataPath);
77
+
78
+ // Load prompts
79
+ const prompts = loadPromptsFromDir(getAgentCorePromptsDir());
80
+
81
+ // Copy prompts
82
+ const selectedTools = config.tools as string[];
83
+
84
+ if (selectedTools.includes('copilot')) {
85
+ const copilotPath = getAgentPromptPath(workspacePath, 'copilot');
86
+ ensureDir(copilotPath);
87
+ copyPromptsToDir(prompts, copilotPath, '.agent.md');
88
+ }
89
+
90
+ if (selectedTools.includes('antigravity')) {
91
+ const antigravityPath = getAgentPromptPath(workspacePath, 'antigravity');
92
+ ensureDir(antigravityPath);
93
+ copyPromptsToDir(prompts, antigravityPath, '.md');
94
+ }
95
+
96
+ // Create workspace config
97
+ const workspaceConfigPath = path.join(workspacePath, '.rrce-workflow.yaml');
98
+ const configContent = `# RRCE-Workflow Configuration
99
+ version: 1
100
+
101
+ storage:
102
+ mode: ${config.storageMode}
103
+
104
+ project:
105
+ name: "${workspaceName}"
106
+ `;
107
+ fs.writeFileSync(workspaceConfigPath, configContent);
108
+
109
+ s.stop('Configuration generated');
110
+
111
+ outro(pc.green(`✓ Setup complete! You can now run "rrce-workflow select" to start using agents.`));
112
+
113
+ } catch (error) {
114
+ s.stop('Error occurred');
115
+ cancel(`Failed to setup: ${error instanceof Error ? error.message : String(error)}`);
116
+ process.exit(1);
117
+ }
118
+ }
119
+
120
+ function copyPromptsToDir(prompts: ParsedPrompt[], targetDir: string, extension: string) {
121
+ for (const prompt of prompts) {
122
+ const baseName = path.basename(prompt.filePath, '.md');
123
+ const targetName = baseName + extension;
124
+ const targetPath = path.join(targetDir, targetName);
125
+
126
+ // Read the full content including frontmatter
127
+ const content = fs.readFileSync(prompt.filePath, 'utf-8');
128
+ fs.writeFileSync(targetPath, content);
129
+ }
130
+ }
package/src/index.ts ADDED
@@ -0,0 +1,11 @@
1
+ import { runWizard } from './commands/wizard';
2
+ import { runSelector } from './commands/selector';
3
+
4
+ // Get command from args
5
+ const command = process.argv[2];
6
+
7
+ if (!command || command === 'wizard') {
8
+ runWizard();
9
+ } else {
10
+ runSelector();
11
+ }
package/src/App.tsx DELETED
@@ -1,110 +0,0 @@
1
- import * as React from 'react';
2
- import { Box, Text } from 'ink';
3
- import { Wizard, type WizardConfig } from './components/Wizard';
4
- import { AgentSelector } from './components/AgentSelector';
5
- import { loadPromptsFromDir, getAgentCorePromptsDir } from './lib/prompts';
6
- import { ensureDir, getAgentPromptPath, resolveDataPath, getRRCEHome } from './lib/paths';
7
- import type { ParsedPrompt } from './types/prompt';
8
- import * as fs from 'fs';
9
- import * as path from 'path';
10
-
11
- type AppMode = 'wizard' | 'select' | 'done';
12
-
13
- interface AppProps {
14
- command?: string;
15
- }
16
-
17
- export function App({ command }: AppProps) {
18
- const [mode, setMode] = React.useState<AppMode>(command === 'select' ? 'select' : 'wizard');
19
- const [selectedPrompt, setSelectedPrompt] = React.useState<ParsedPrompt | null>(null);
20
- const [message, setMessage] = React.useState<string | null>(null);
21
-
22
- // Load prompts from agent-core
23
- const prompts = loadPromptsFromDir(getAgentCorePromptsDir());
24
-
25
- const handleWizardComplete = (config: WizardConfig) => {
26
- // Create config file
27
- const dataPath = resolveDataPath(config.storageMode, config.workspaceName, config.workspacePath);
28
- ensureDir(dataPath);
29
-
30
- // Copy prompts to appropriate locations
31
- if (config.tools.copilot) {
32
- const copilotPath = getAgentPromptPath(config.workspacePath, 'copilot');
33
- ensureDir(copilotPath);
34
- copyPromptsToDir(prompts, copilotPath, '.agent.md');
35
- }
36
-
37
- if (config.tools.antigravity) {
38
- const antigravityPath = getAgentPromptPath(config.workspacePath, 'antigravity');
39
- ensureDir(antigravityPath);
40
- copyPromptsToDir(prompts, antigravityPath, '.md');
41
- }
42
-
43
- // Create workspace config
44
- const workspaceConfigPath = path.join(config.workspacePath, '.rrce-workflow.yaml');
45
- const configContent = `# RRCE-Workflow Configuration
46
- version: 1
47
-
48
- storage:
49
- mode: ${config.storageMode}
50
-
51
- project:
52
- name: "${config.workspaceName}"
53
- `;
54
- fs.writeFileSync(workspaceConfigPath, configContent);
55
-
56
- setMessage(`✓ Setup complete! Created config and copied agents.`);
57
- setMode('done');
58
- };
59
-
60
- const handleAgentSelect = (prompt: ParsedPrompt) => {
61
- setSelectedPrompt(prompt);
62
- setMessage(`Selected: ${prompt.frontmatter.name}\n\nUse this agent in your IDE by invoking @${prompt.frontmatter.name}`);
63
- setMode('done');
64
- };
65
-
66
- if (mode === 'wizard') {
67
- return <Wizard onComplete={handleWizardComplete} />;
68
- }
69
-
70
- if (mode === 'done') {
71
- return (
72
- <Box flexDirection="column" padding={1}>
73
- <Box borderStyle="round" borderColor="green" paddingX={2}>
74
- <Text bold color="green">RRCE-Workflow</Text>
75
- </Box>
76
- <Box marginTop={1}>
77
- <Text>{message}</Text>
78
- </Box>
79
- </Box>
80
- );
81
- }
82
-
83
- if (prompts.length === 0) {
84
- return (
85
- <Box flexDirection="column" padding={1}>
86
- <Text color="yellow">No prompts found. Run `rrce-workflow wizard` to set up.</Text>
87
- </Box>
88
- );
89
- }
90
-
91
- return (
92
- <AgentSelector
93
- prompts={prompts}
94
- workspaceName={path.basename(process.cwd())}
95
- onSelect={handleAgentSelect}
96
- />
97
- );
98
- }
99
-
100
- function copyPromptsToDir(prompts: ParsedPrompt[], targetDir: string, extension: string) {
101
- for (const prompt of prompts) {
102
- const baseName = path.basename(prompt.filePath, '.md');
103
- const targetName = baseName + extension;
104
- const targetPath = path.join(targetDir, targetName);
105
-
106
- // Read the full content including frontmatter
107
- const content = fs.readFileSync(prompt.filePath, 'utf-8');
108
- fs.writeFileSync(targetPath, content);
109
- }
110
- }
@@ -1,43 +0,0 @@
1
- import * as React from 'react';
2
- import { Box, Text } from 'ink';
3
- import SelectInput from 'ink-select-input';
4
- import type { ParsedPrompt } from '../types/prompt';
5
-
6
- interface AgentSelectorProps {
7
- prompts: ParsedPrompt[];
8
- workspaceName: string;
9
- onSelect: (prompt: ParsedPrompt) => void;
10
- }
11
-
12
- export function AgentSelector({ prompts, workspaceName, onSelect }: AgentSelectorProps) {
13
- const items = prompts.map((p, i) => ({
14
- key: p.filePath,
15
- label: `${p.frontmatter.name} - ${p.frontmatter.description}`,
16
- value: p,
17
- }));
18
-
19
- const handleSelect = (item: { value: ParsedPrompt }) => {
20
- onSelect(item.value);
21
- };
22
-
23
- return (
24
- <Box flexDirection="column" padding={1}>
25
- <Box borderStyle="round" borderColor="cyan" paddingX={2}>
26
- <Text bold color="cyan">RRCE-Workflow</Text>
27
- <Text> </Text>
28
- <Text dimColor>| {workspaceName}</Text>
29
- </Box>
30
-
31
- <Box marginTop={1} flexDirection="column">
32
- <Text>Select an agent:</Text>
33
- <Box marginTop={1}>
34
- <SelectInput items={items} onSelect={handleSelect} />
35
- </Box>
36
- </Box>
37
-
38
- <Box marginTop={1}>
39
- <Text dimColor>↑↓ to navigate, Enter to select</Text>
40
- </Box>
41
- </Box>
42
- );
43
- }
@@ -1,17 +0,0 @@
1
- import * as React from 'react';
2
- import Gradient from 'ink-gradient';
3
- import BigText from 'ink-big-text';
4
- import { Box } from 'ink';
5
-
6
- export function Logo() {
7
- return (
8
- <Box flexDirection="column" alignItems="center" marginBottom={1}>
9
- <Gradient name="morning">
10
- <BigText text="RRCE" align='center' font='block'/>
11
- </Gradient>
12
- <Gradient name="cristal">
13
- <BigText text="Workflow" align='center' font='chrome'/>
14
- </Gradient>
15
- </Box>
16
- );
17
- }
@@ -1,170 +0,0 @@
1
- import * as React from 'react';
2
- import { Box, Text, useInput } from 'ink';
3
- import SelectInput from 'ink-select-input';
4
- import Spinner from 'ink-spinner';
5
- import Gradient from 'ink-gradient';
6
- import { Logo } from './Logo';
7
- import type { StorageMode } from '../types/prompt';
8
- import { getGitUser } from '../lib/git';
9
- import { detectWorkspaceRoot, getWorkspaceName } from '../lib/paths';
10
-
11
- interface WizardProps {
12
- onComplete: (config: WizardConfig) => void;
13
- }
14
-
15
- export interface WizardConfig {
16
- workspaceName: string;
17
- workspacePath: string;
18
- storageMode: StorageMode;
19
- tools: {
20
- copilot: boolean;
21
- antigravity: boolean;
22
- };
23
- gitUser: string | null;
24
- }
25
-
26
- type WizardStep = 'welcome' | 'storage' | 'tools' | 'confirm';
27
-
28
- const storageModeItems = [
29
- { label: 'Global (~/.rrce-workflow/)', value: 'global' as StorageMode },
30
- { label: 'Workspace (.rrce-workflow/)', value: 'workspace' as StorageMode },
31
- { label: 'Both', value: 'both' as StorageMode },
32
- ];
33
-
34
- export function Wizard({ onComplete }: WizardProps) {
35
- const [loading, setLoading] = React.useState(true);
36
- const [step, setStep] = React.useState<WizardStep>('welcome');
37
- const [storageMode, setStorageMode] = React.useState<StorageMode>('global');
38
- const [tools, setTools] = React.useState({ copilot: true, antigravity: true });
39
-
40
- // Data state
41
- const [workspacePath, setWorkspacePath] = React.useState('');
42
- const [workspaceName, setWorkspaceName] = React.useState('');
43
- const [gitUser, setGitUser] = React.useState<string | null>(null);
44
-
45
- React.useEffect(() => {
46
- // Simulate a small delay for dramatic effect/loading feeling
47
- const timer = setTimeout(() => {
48
- setWorkspacePath(detectWorkspaceRoot());
49
- setWorkspaceName(getWorkspaceName(detectWorkspaceRoot()));
50
- setGitUser(getGitUser());
51
- setLoading(false);
52
- }, 800);
53
- return () => clearTimeout(timer);
54
- }, []);
55
-
56
- useInput((input, key) => {
57
- if (loading) return;
58
-
59
- if (step === 'welcome' && key.return) {
60
- setStep('storage');
61
- } else if (step === 'confirm' && key.return) {
62
- onComplete({
63
- workspaceName,
64
- workspacePath,
65
- storageMode,
66
- tools,
67
- gitUser,
68
- });
69
- }
70
- });
71
-
72
- const handleStorageSelect = (item: { value: StorageMode }) => {
73
- setStorageMode(item.value);
74
- setStep('tools');
75
- };
76
-
77
- const handleToolsSelect = (item: { value: string }) => {
78
- if (item.value === 'done') {
79
- setStep('confirm');
80
- } else if (item.value === 'copilot') {
81
- setTools((t: typeof tools) => ({ ...t, copilot: !t.copilot }));
82
- } else if (item.value === 'antigravity') {
83
- setTools((t: typeof tools) => ({ ...t, antigravity: !t.antigravity }));
84
- }
85
- };
86
-
87
- return (
88
- <Box flexDirection="column" padding={1} alignItems="center">
89
- <Logo />
90
-
91
- <Box borderStyle="round" borderColor="cyan" paddingX={2} paddingY={1} width={60} flexDirection="column">
92
- {step === 'welcome' && (
93
- <Box flexDirection="column" alignItems="center">
94
- {loading ? (
95
- <Box>
96
- <Text color="cyan"><Spinner type="dots" /> </Text>
97
- <Text> Detecting environment...</Text>
98
- </Box>
99
- ) : (
100
- <Box flexDirection="column" alignItems="center">
101
- <Box marginBottom={1}>
102
- <Text bold color="cyan">Welcome to RRCE-Workflow Setup</Text>
103
- </Box>
104
-
105
- <Box flexDirection="column" width="100%" marginBottom={1}>
106
- <Box>
107
- <Text color="green">✓</Text>
108
- <Text> Git User: </Text>
109
- <Text bold color="white">{gitUser || '(not found)'}</Text>
110
- </Box>
111
- <Box>
112
- <Text color="green">✓</Text>
113
- <Text> Workspace: </Text>
114
- <Text bold color="white">{workspaceName}</Text>
115
- </Box>
116
- </Box>
117
-
118
- <Text dimColor>Press Enter to continue ❯</Text>
119
- </Box>
120
- )}
121
- </Box>
122
- )}
123
-
124
- {step === 'storage' && (
125
- <Box flexDirection="column">
126
- <Box marginBottom={1}><Text bold underline>Storage Configuration</Text></Box>
127
- <Box marginBottom={1}><Text>Where should workflow data be stored?</Text></Box>
128
- <SelectInput items={storageModeItems} onSelect={handleStorageSelect} />
129
- </Box>
130
- )}
131
-
132
- {step === 'tools' && (
133
- <Box flexDirection="column">
134
- <Box marginBottom={1}><Text bold underline>AI Tools Integration</Text></Box>
135
- <Box marginBottom={1}><Text>Select the tools you want to generate prompts for:</Text></Box>
136
- <SelectInput
137
- items={[
138
- { label: `[${tools.copilot ? 'x' : ' '}] GitHub Copilot`, value: 'copilot' },
139
- { label: `[${tools.antigravity ? 'x' : ' '}] Antigravity IDE`, value: 'antigravity' },
140
- { label: '───────────────', value: 'sep' },
141
- { label: 'Done (Continue)', value: 'done' },
142
- ]}
143
- onSelect={handleToolsSelect}
144
- />
145
- </Box>
146
- )}
147
-
148
- {step === 'confirm' && (
149
- <Box flexDirection="column">
150
- <Box marginBottom={1}><Text bold underline>Summary</Text></Box>
151
- <Box flexDirection="column" marginBottom={1}>
152
- <Box><Text bold>Storage:</Text><Text> {storageMode}</Text></Box>
153
- <Box><Text bold>Copilot:</Text><Text color={tools.copilot ? 'green' : 'red'}> {tools.copilot ? 'Enabled' : 'Disabled'}</Text></Box>
154
- <Box><Text bold>Antigravity:</Text><Text color={tools.antigravity ? 'green' : 'red'}> {tools.antigravity ? 'Enabled' : 'Disabled'}</Text></Box>
155
- </Box>
156
- <Box marginTop={1} alignItems="center">
157
- <Text dimColor>Press Enter to generate config ❯</Text>
158
- </Box>
159
- </Box>
160
- )}
161
- </Box>
162
-
163
- {!loading && (
164
- <Box marginTop={1}>
165
- <Text dimColor>v{process.env.npm_package_version || '0.1.0'}</Text>
166
- </Box>
167
- )}
168
- </Box>
169
- );
170
- }
package/src/index.tsx DELETED
@@ -1,9 +0,0 @@
1
- #!/usr/bin/env bun
2
- import * as React from 'react';
3
- import { render } from 'ink';
4
- import { App } from './App';
5
-
6
- // Get command from args
7
- const command = process.argv[2];
8
-
9
- render(<App command={command} />);