rrce-workflow 0.1.0 → 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 +11 -12
- package/src/commands/selector.ts +42 -0
- package/src/commands/wizard.ts +130 -0
- package/src/index.ts +11 -0
- package/src/App.tsx +0 -110
- package/src/components/AgentSelector.tsx +0 -43
- package/src/components/Wizard.tsx +0 -135
- package/src/index.tsx +0 -9
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rrce-workflow",
|
|
3
|
-
"version": "0.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.
|
|
27
|
+
"module": "src/index.ts",
|
|
28
28
|
"bin": {
|
|
29
29
|
"rrce-workflow": "bin/rrce-workflow.js"
|
|
30
30
|
},
|
|
@@ -35,23 +35,22 @@
|
|
|
35
35
|
"bin"
|
|
36
36
|
],
|
|
37
37
|
"scripts": {
|
|
38
|
-
"dev": "bun run src/index.
|
|
39
|
-
"wizard": "bun run src/index.
|
|
40
|
-
"
|
|
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"
|
|
41
42
|
},
|
|
42
43
|
"engines": {
|
|
43
44
|
"node": ">=18",
|
|
44
45
|
"bun": ">=1.0"
|
|
45
46
|
},
|
|
46
47
|
"dependencies": {
|
|
48
|
+
"@clack/prompts": "^0.11.0",
|
|
47
49
|
"gray-matter": "^4.0.3",
|
|
48
|
-
"
|
|
49
|
-
"
|
|
50
|
-
"react": "^18",
|
|
51
|
-
"zod": "^4"
|
|
50
|
+
"picocolors": "^1.1.1",
|
|
51
|
+
"zod": "^4.2.1"
|
|
52
52
|
},
|
|
53
53
|
"devDependencies": {
|
|
54
|
-
"@types/bun": "latest"
|
|
55
|
-
"@types/react": "^18"
|
|
54
|
+
"@types/bun": "latest"
|
|
56
55
|
}
|
|
57
|
-
}
|
|
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
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 === 'wizard' ? 'wizard' : 'select');
|
|
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,135 +0,0 @@
|
|
|
1
|
-
import * as React from 'react';
|
|
2
|
-
import { Box, Text, useInput } from 'ink';
|
|
3
|
-
import SelectInput from 'ink-select-input';
|
|
4
|
-
import type { StorageMode } from '../types/prompt';
|
|
5
|
-
import { getGitUser } from '../lib/git';
|
|
6
|
-
import { detectWorkspaceRoot, getWorkspaceName } from '../lib/paths';
|
|
7
|
-
|
|
8
|
-
interface WizardProps {
|
|
9
|
-
onComplete: (config: WizardConfig) => void;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export interface WizardConfig {
|
|
13
|
-
workspaceName: string;
|
|
14
|
-
workspacePath: string;
|
|
15
|
-
storageMode: StorageMode;
|
|
16
|
-
tools: {
|
|
17
|
-
copilot: boolean;
|
|
18
|
-
antigravity: boolean;
|
|
19
|
-
};
|
|
20
|
-
gitUser: string | null;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
type WizardStep = 'welcome' | 'storage' | 'tools' | 'confirm';
|
|
24
|
-
|
|
25
|
-
const storageModeItems = [
|
|
26
|
-
{ label: 'Global (~/.rrce-workflow/)', value: 'global' as StorageMode },
|
|
27
|
-
{ label: 'Workspace (.rrce-workflow/)', value: 'workspace' as StorageMode },
|
|
28
|
-
{ label: 'Both', value: 'both' as StorageMode },
|
|
29
|
-
];
|
|
30
|
-
|
|
31
|
-
export function Wizard({ onComplete }: WizardProps) {
|
|
32
|
-
const workspacePath = detectWorkspaceRoot();
|
|
33
|
-
const workspaceName = getWorkspaceName(workspacePath);
|
|
34
|
-
const gitUser = getGitUser();
|
|
35
|
-
|
|
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
|
-
useInput((input, key) => {
|
|
41
|
-
if (step === 'welcome' && key.return) {
|
|
42
|
-
setStep('storage');
|
|
43
|
-
} else if (step === 'confirm' && key.return) {
|
|
44
|
-
onComplete({
|
|
45
|
-
workspaceName,
|
|
46
|
-
workspacePath,
|
|
47
|
-
storageMode,
|
|
48
|
-
tools,
|
|
49
|
-
gitUser,
|
|
50
|
-
});
|
|
51
|
-
}
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
const handleStorageSelect = (item: { value: StorageMode }) => {
|
|
55
|
-
setStorageMode(item.value);
|
|
56
|
-
setStep('tools');
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
const handleToolsSelect = (item: { value: string }) => {
|
|
60
|
-
if (item.value === 'done') {
|
|
61
|
-
setStep('confirm');
|
|
62
|
-
} else if (item.value === 'copilot') {
|
|
63
|
-
setTools((t: typeof tools) => ({ ...t, copilot: !t.copilot }));
|
|
64
|
-
} else if (item.value === 'antigravity') {
|
|
65
|
-
setTools((t: typeof tools) => ({ ...t, antigravity: !t.antigravity }));
|
|
66
|
-
}
|
|
67
|
-
};
|
|
68
|
-
|
|
69
|
-
return (
|
|
70
|
-
<Box flexDirection="column" padding={1}>
|
|
71
|
-
<Box borderStyle="round" borderColor="cyan" paddingX={2}>
|
|
72
|
-
<Text bold color="cyan">RRCE-Workflow Setup</Text>
|
|
73
|
-
</Box>
|
|
74
|
-
|
|
75
|
-
<Box marginTop={1}>
|
|
76
|
-
{step === 'welcome' && (
|
|
77
|
-
<Box flexDirection="column">
|
|
78
|
-
<Text>Welcome! Detecting your environment...</Text>
|
|
79
|
-
<Box marginTop={1} flexDirection="column">
|
|
80
|
-
<Text>
|
|
81
|
-
<Text color="green">✓</Text> Git user: <Text bold>{gitUser || '(not found)'}</Text>
|
|
82
|
-
</Text>
|
|
83
|
-
<Text>
|
|
84
|
-
<Text color="green">✓</Text> Workspace: <Text bold>{workspaceName}</Text>
|
|
85
|
-
</Text>
|
|
86
|
-
</Box>
|
|
87
|
-
<Box marginTop={1}>
|
|
88
|
-
<Text dimColor>Press Enter to continue...</Text>
|
|
89
|
-
</Box>
|
|
90
|
-
</Box>
|
|
91
|
-
)}
|
|
92
|
-
|
|
93
|
-
{step === 'storage' && (
|
|
94
|
-
<Box flexDirection="column">
|
|
95
|
-
<Text>Where should workflow data be stored?</Text>
|
|
96
|
-
<Box marginTop={1}>
|
|
97
|
-
<SelectInput items={storageModeItems} onSelect={handleStorageSelect} />
|
|
98
|
-
</Box>
|
|
99
|
-
</Box>
|
|
100
|
-
)}
|
|
101
|
-
|
|
102
|
-
{step === 'tools' && (
|
|
103
|
-
<Box flexDirection="column">
|
|
104
|
-
<Text>Which AI tools do you use?</Text>
|
|
105
|
-
<Box marginTop={1}>
|
|
106
|
-
<SelectInput
|
|
107
|
-
items={[
|
|
108
|
-
{ label: `[${tools.copilot ? 'x' : ' '}] GitHub Copilot (VSCode)`, value: 'copilot' },
|
|
109
|
-
{ label: `[${tools.antigravity ? 'x' : ' '}] Antigravity IDE`, value: 'antigravity' },
|
|
110
|
-
{ label: '───────────────', value: 'sep' },
|
|
111
|
-
{ label: 'Done', value: 'done' },
|
|
112
|
-
]}
|
|
113
|
-
onSelect={handleToolsSelect}
|
|
114
|
-
/>
|
|
115
|
-
</Box>
|
|
116
|
-
</Box>
|
|
117
|
-
)}
|
|
118
|
-
|
|
119
|
-
{step === 'confirm' && (
|
|
120
|
-
<Box flexDirection="column">
|
|
121
|
-
<Text bold color="green">Configuration Summary</Text>
|
|
122
|
-
<Box marginTop={1} flexDirection="column">
|
|
123
|
-
<Text>• Storage: <Text bold>{storageMode}</Text></Text>
|
|
124
|
-
<Text>• Copilot: <Text bold>{tools.copilot ? 'Yes' : 'No'}</Text></Text>
|
|
125
|
-
<Text>• Antigravity: <Text bold>{tools.antigravity ? 'Yes' : 'No'}</Text></Text>
|
|
126
|
-
</Box>
|
|
127
|
-
<Box marginTop={1}>
|
|
128
|
-
<Text dimColor>Press Enter to create configuration...</Text>
|
|
129
|
-
</Box>
|
|
130
|
-
</Box>
|
|
131
|
-
)}
|
|
132
|
-
</Box>
|
|
133
|
-
</Box>
|
|
134
|
-
);
|
|
135
|
-
}
|