@sylphx/flow 2.1.3 ā 2.1.4
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/CHANGELOG.md +12 -0
- package/README.md +44 -0
- package/package.json +79 -73
- package/src/commands/flow/execute-v2.ts +37 -29
- package/src/commands/flow/prompt.ts +5 -3
- package/src/commands/flow/types.ts +0 -2
- package/src/commands/flow-command.ts +20 -13
- package/src/commands/hook-command.ts +1 -3
- package/src/commands/settings-command.ts +36 -33
- package/src/config/ai-config.ts +60 -41
- package/src/core/agent-loader.ts +11 -6
- package/src/core/attach-manager.ts +92 -84
- package/src/core/backup-manager.ts +35 -29
- package/src/core/cleanup-handler.ts +11 -8
- package/src/core/error-handling.ts +23 -30
- package/src/core/flow-executor.ts +58 -76
- package/src/core/formatting/bytes.ts +2 -4
- package/src/core/functional/async.ts +5 -4
- package/src/core/functional/error-handler.ts +2 -2
- package/src/core/git-stash-manager.ts +21 -10
- package/src/core/installers/file-installer.ts +0 -1
- package/src/core/installers/mcp-installer.ts +0 -1
- package/src/core/project-manager.ts +24 -18
- package/src/core/secrets-manager.ts +54 -73
- package/src/core/session-manager.ts +20 -22
- package/src/core/state-detector.ts +139 -80
- package/src/core/template-loader.ts +13 -31
- package/src/core/upgrade-manager.ts +122 -69
- package/src/index.ts +8 -5
- package/src/services/auto-upgrade.ts +1 -1
- package/src/services/config-service.ts +41 -29
- package/src/services/global-config.ts +2 -2
- package/src/services/target-installer.ts +9 -7
- package/src/targets/claude-code.ts +24 -12
- package/src/targets/opencode.ts +17 -6
- package/src/types/cli.types.ts +2 -2
- package/src/types/provider.types.ts +1 -7
- package/src/types/session.types.ts +11 -11
- package/src/types/target.types.ts +3 -1
- package/src/types/todo.types.ts +1 -1
- package/src/types.ts +1 -1
- package/src/utils/__tests__/package-manager-detector.test.ts +6 -6
- package/src/utils/agent-enhancer.ts +4 -4
- package/src/utils/config/paths.ts +3 -1
- package/src/utils/config/target-utils.ts +2 -2
- package/src/utils/display/banner.ts +2 -2
- package/src/utils/display/notifications.ts +58 -45
- package/src/utils/display/status.ts +29 -12
- package/src/utils/files/file-operations.ts +1 -1
- package/src/utils/files/sync-utils.ts +38 -41
- package/src/utils/index.ts +19 -27
- package/src/utils/package-manager-detector.ts +15 -5
- package/src/utils/security/security.ts +8 -4
- package/src/utils/target-selection.ts +5 -2
- package/src/utils/version.ts +4 -2
- package/src/commands/flow-orchestrator.ts +0 -328
- package/src/commands/init-command.ts +0 -92
- package/src/commands/init-core.ts +0 -331
- package/src/core/agent-manager.ts +0 -174
- package/src/core/loop-controller.ts +0 -200
- package/src/core/rule-loader.ts +0 -147
- package/src/core/rule-manager.ts +0 -240
- package/src/services/claude-config-service.ts +0 -252
- package/src/services/first-run-setup.ts +0 -220
- package/src/services/smart-config-service.ts +0 -269
- package/src/types/api.types.ts +0 -9
|
@@ -1,252 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Claude Configuration Service
|
|
3
|
-
* Handles Claude Code provider configuration with layered settings
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import inquirer from 'inquirer';
|
|
7
|
-
import chalk from 'chalk';
|
|
8
|
-
import { ConfigService } from './config-service.js';
|
|
9
|
-
import { loadAllAgents } from '../core/agent-loader.js';
|
|
10
|
-
|
|
11
|
-
export interface ClaudeConfig {
|
|
12
|
-
claudeProvider?: string;
|
|
13
|
-
claudeProviderConfig?: {
|
|
14
|
-
ANTHROPIC_BASE_URL: string;
|
|
15
|
-
description: string;
|
|
16
|
-
};
|
|
17
|
-
claudeApiKey?: string;
|
|
18
|
-
defaultAgent?: string;
|
|
19
|
-
target?: string;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export class ClaudeConfigService {
|
|
23
|
-
/**
|
|
24
|
-
* Load layered Claude configuration from all sources
|
|
25
|
-
*/
|
|
26
|
-
static async loadConfig(): Promise<ClaudeConfig> {
|
|
27
|
-
// API keys are in home directory
|
|
28
|
-
const userSettings = await ConfigService.loadHomeSettings();
|
|
29
|
-
|
|
30
|
-
// Other settings are in project directory
|
|
31
|
-
const projectSettings = await ConfigService.loadProjectSettings();
|
|
32
|
-
|
|
33
|
-
// Merge with project settings taking precedence over home (except API key)
|
|
34
|
-
const merged = {
|
|
35
|
-
claudeProvider: userSettings.claudeProvider || projectSettings.claudeProvider,
|
|
36
|
-
claudeProviderConfig: userSettings.claudeProviderConfig || projectSettings.claudeProviderConfig,
|
|
37
|
-
claudeApiKey: userSettings.claudeApiKey,
|
|
38
|
-
defaultAgent: projectSettings.defaultAgent,
|
|
39
|
-
target: projectSettings.target,
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
// Local settings have highest priority for everything except API key
|
|
43
|
-
const localSettings = await ConfigService.loadLocalSettings();
|
|
44
|
-
|
|
45
|
-
return {
|
|
46
|
-
...merged,
|
|
47
|
-
...localSettings,
|
|
48
|
-
// Keep API key from user settings
|
|
49
|
-
claudeApiKey: merged.claudeApiKey,
|
|
50
|
-
};
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Save user-specific config (API keys to home, project settings to project)
|
|
55
|
-
*/
|
|
56
|
-
static async saveConfig(config: ClaudeConfig): Promise<void> {
|
|
57
|
-
// Separate user-specific settings (API keys)
|
|
58
|
-
const userSettings = {
|
|
59
|
-
claudeApiKey: config.claudeApiKey,
|
|
60
|
-
claudeProvider: config.claudeProvider,
|
|
61
|
-
claudeProviderConfig: config.claudeProviderConfig,
|
|
62
|
-
};
|
|
63
|
-
|
|
64
|
-
// Other settings go to project (shareable)
|
|
65
|
-
const projectSettings = {
|
|
66
|
-
claudeProvider: config.claudeProvider,
|
|
67
|
-
defaultAgent: config.defaultAgent,
|
|
68
|
-
target: config.target,
|
|
69
|
-
};
|
|
70
|
-
|
|
71
|
-
// Save API keys to home directory (never commit)
|
|
72
|
-
if (userSettings.claudeApiKey) {
|
|
73
|
-
await ConfigService.saveHomeSettings(userSettings);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
// Save project settings
|
|
77
|
-
await ConfigService.saveProjectSettings(projectSettings);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* Configure Claude provider interactively - saves API keys to home dir
|
|
82
|
-
*/
|
|
83
|
-
static async configureProvider(verbose: boolean = false): Promise<ClaudeConfig> {
|
|
84
|
-
const config = await this.loadConfig();
|
|
85
|
-
|
|
86
|
-
// Check if we already have API key configured
|
|
87
|
-
if (!config.claudeApiKey || !config.claudeProvider || verbose) {
|
|
88
|
-
console.log(chalk.cyan('š Claude Code Configuration\n'));
|
|
89
|
-
|
|
90
|
-
const providerAnswer = await inquirer.prompt([
|
|
91
|
-
{
|
|
92
|
-
type: 'list',
|
|
93
|
-
name: 'provider',
|
|
94
|
-
message: 'Select Claude API Provider:',
|
|
95
|
-
choices: [
|
|
96
|
-
{ name: 'Anthropic (Official)', value: 'anthropic' },
|
|
97
|
-
{ name: 'Z.ai (Recommended)', value: 'z.ai' },
|
|
98
|
-
{ name: 'Kimi', value: 'kimi' },
|
|
99
|
-
],
|
|
100
|
-
default: config.claudeProvider || 'z.ai',
|
|
101
|
-
},
|
|
102
|
-
]);
|
|
103
|
-
|
|
104
|
-
// Ask for API Key
|
|
105
|
-
const keyAnswer = await inquirer.prompt([
|
|
106
|
-
{
|
|
107
|
-
type: 'password',
|
|
108
|
-
name: 'apiKey',
|
|
109
|
-
message: `Enter API Key for ${providerAnswer.provider}:`,
|
|
110
|
-
mask: '*',
|
|
111
|
-
validate: (input) => input.length > 10 || 'API Key appears too short',
|
|
112
|
-
},
|
|
113
|
-
]);
|
|
114
|
-
|
|
115
|
-
// Provider configurations
|
|
116
|
-
const providerEnvs = {
|
|
117
|
-
'anthropic': {
|
|
118
|
-
ANTHROPIC_BASE_URL: 'https://api.anthropic.com',
|
|
119
|
-
description: 'Anthropic Official API',
|
|
120
|
-
},
|
|
121
|
-
'z.ai': {
|
|
122
|
-
ANTHROPIC_BASE_URL: 'https://api.z.ai/api/anthropic',
|
|
123
|
-
description: 'Z.ai Proxy',
|
|
124
|
-
},
|
|
125
|
-
'kimi': {
|
|
126
|
-
ANTHROPIC_BASE_URL: 'https://api.kimi.com/coding/',
|
|
127
|
-
description: 'Kimi Proxy',
|
|
128
|
-
},
|
|
129
|
-
};
|
|
130
|
-
|
|
131
|
-
const providerConfig = providerEnvs[providerAnswer.provider as keyof typeof providerEnvs];
|
|
132
|
-
|
|
133
|
-
// Save API keys to home directory (never commit)
|
|
134
|
-
await ConfigService.saveHomeSettings({
|
|
135
|
-
claudeProvider: providerAnswer.provider,
|
|
136
|
-
claudeProviderConfig: providerConfig,
|
|
137
|
-
claudeApiKey: keyAnswer.apiKey,
|
|
138
|
-
});
|
|
139
|
-
|
|
140
|
-
console.log(chalk.green(`ā API Key saved to ~/.sylphx-flow/settings.json (secure)\n`));
|
|
141
|
-
console.log(chalk.dim(` Provider: ${providerConfig.description}`));
|
|
142
|
-
console.log(chalk.dim(` API Key: ${keyAnswer.apiKey.slice(0, 5)}...${keyAnswer.apiKey.slice(-4)}\n`));
|
|
143
|
-
|
|
144
|
-
// Update config for return
|
|
145
|
-
config.claudeProvider = providerAnswer.provider;
|
|
146
|
-
config.claudeProviderConfig = providerConfig;
|
|
147
|
-
config.claudeApiKey = keyAnswer.apiKey;
|
|
148
|
-
|
|
149
|
-
return config;
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
if (verbose) {
|
|
153
|
-
console.log(chalk.green('ā Claude provider already configured\n'));
|
|
154
|
-
console.log(chalk.dim(` Provider: ${config.claudeProviderConfig?.description}\n`));
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
return config;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
/**
|
|
161
|
-
* Configure agent interactively - saves to project config (shareable)
|
|
162
|
-
* Dynamically loads available agents instead of hardcoded list
|
|
163
|
-
*/
|
|
164
|
-
static async configureAgent(verbose: boolean = false): Promise<string> {
|
|
165
|
-
const config = await this.loadConfig();
|
|
166
|
-
|
|
167
|
-
if (!config.defaultAgent || verbose) {
|
|
168
|
-
try {
|
|
169
|
-
// Dynamically load all available agents
|
|
170
|
-
const agents = await loadAllAgents(process.cwd());
|
|
171
|
-
|
|
172
|
-
if (agents.length === 0) {
|
|
173
|
-
console.log(chalk.yellow('ā No agents found. Defaulting to "coder".\n'));
|
|
174
|
-
const defaultAgent = 'coder';
|
|
175
|
-
await ConfigService.saveProjectSettings({
|
|
176
|
-
defaultAgent,
|
|
177
|
-
});
|
|
178
|
-
return defaultAgent;
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
// Create choices from dynamically loaded agents
|
|
182
|
-
const choices = agents.map(agent => ({
|
|
183
|
-
name: agent.metadata.name || agent.id,
|
|
184
|
-
value: agent.id,
|
|
185
|
-
}));
|
|
186
|
-
|
|
187
|
-
const agentAnswer = await inquirer.prompt([
|
|
188
|
-
{
|
|
189
|
-
type: 'list',
|
|
190
|
-
name: 'agent',
|
|
191
|
-
message: 'Select default Agent:',
|
|
192
|
-
choices,
|
|
193
|
-
default: config.defaultAgent || (agents.find(a => a.id === 'coder')?.id || agents[0].id),
|
|
194
|
-
},
|
|
195
|
-
]);
|
|
196
|
-
|
|
197
|
-
// Save to project-level config (shareable)
|
|
198
|
-
await ConfigService.saveProjectSettings({
|
|
199
|
-
defaultAgent: agentAnswer.agent,
|
|
200
|
-
});
|
|
201
|
-
|
|
202
|
-
const selectedAgent = agents.find(a => a.id === agentAnswer.agent);
|
|
203
|
-
const displayName = selectedAgent?.metadata.name || agentAnswer.agent;
|
|
204
|
-
console.log(chalk.green(`ā Agent set to: ${displayName}\n`));
|
|
205
|
-
|
|
206
|
-
return agentAnswer.agent;
|
|
207
|
-
} catch (error) {
|
|
208
|
-
console.log(chalk.yellow('ā Failed to load agents. Defaulting to "coder".\n'));
|
|
209
|
-
console.error(error);
|
|
210
|
-
|
|
211
|
-
const defaultAgent = 'coder';
|
|
212
|
-
await ConfigService.saveProjectSettings({
|
|
213
|
-
defaultAgent,
|
|
214
|
-
});
|
|
215
|
-
return defaultAgent;
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
return config.defaultAgent;
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
/**
|
|
223
|
-
* Setup environment variables for Claude Code
|
|
224
|
-
*/
|
|
225
|
-
static async setupEnvironment(verbose: boolean = false): Promise<void> {
|
|
226
|
-
const config = await this.loadConfig();
|
|
227
|
-
|
|
228
|
-
if (!config.claudeProviderConfig) {
|
|
229
|
-
throw new Error('Provider not configured. Run configureProvider() first.');
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
// Set environment variables
|
|
233
|
-
process.env.ANTHROPIC_BASE_URL = config.claudeProviderConfig.ANTHROPIC_BASE_URL;
|
|
234
|
-
|
|
235
|
-
if (config.claudeApiKey) {
|
|
236
|
-
process.env.ANTHROPIC_API_KEY = config.claudeApiKey;
|
|
237
|
-
|
|
238
|
-
if (verbose) {
|
|
239
|
-
console.log(chalk.dim(` Provider: ${config.claudeProviderConfig.description}`));
|
|
240
|
-
console.log(chalk.dim(` API Key: ${config.claudeApiKey.slice(0, 5)}...${config.claudeApiKey.slice(-4)}\n`));
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
/**
|
|
246
|
-
* Get the default agent
|
|
247
|
-
*/
|
|
248
|
-
static async getDefaultAgent(): Promise<string> {
|
|
249
|
-
const config = await this.loadConfig();
|
|
250
|
-
return config.defaultAgent || 'coder';
|
|
251
|
-
}
|
|
252
|
-
}
|
|
@@ -1,220 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* First Run Setup
|
|
3
|
-
* Quick configuration wizard for new users
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import chalk from 'chalk';
|
|
7
|
-
import inquirer from 'inquirer';
|
|
8
|
-
import { GlobalConfigService } from './global-config.js';
|
|
9
|
-
import { UserCancelledError } from '../utils/errors.js';
|
|
10
|
-
|
|
11
|
-
export interface QuickSetupResult {
|
|
12
|
-
target: 'claude-code' | 'opencode';
|
|
13
|
-
provider?: 'default' | 'kimi' | 'zai' | 'ask-every-time';
|
|
14
|
-
mcpServers: string[];
|
|
15
|
-
apiKeys: Record<string, Record<string, string>>;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export class FirstRunSetup {
|
|
19
|
-
private configService: GlobalConfigService;
|
|
20
|
-
|
|
21
|
-
constructor() {
|
|
22
|
-
this.configService = new GlobalConfigService();
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Run setup wizard
|
|
27
|
-
*/
|
|
28
|
-
async run(): Promise<QuickSetupResult> {
|
|
29
|
-
try {
|
|
30
|
-
console.log(chalk.cyan.bold('\nāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā®'));
|
|
31
|
-
console.log(chalk.cyan.bold('ā ā'));
|
|
32
|
-
console.log(chalk.cyan.bold('ā Welcome to Sylphx Flow! ā'));
|
|
33
|
-
console.log(chalk.cyan.bold('ā Let\'s configure your environment ā'));
|
|
34
|
-
console.log(chalk.cyan.bold('ā ā'));
|
|
35
|
-
console.log(chalk.cyan.bold('ā°āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāÆ\n'));
|
|
36
|
-
|
|
37
|
-
// Step 1: Select target platform
|
|
38
|
-
console.log(chalk.cyan('š§ Setup (1/3) - Target Platform\n'));
|
|
39
|
-
const { target } = await inquirer.prompt([
|
|
40
|
-
{
|
|
41
|
-
type: 'list',
|
|
42
|
-
name: 'target',
|
|
43
|
-
message: 'Select your preferred platform:',
|
|
44
|
-
choices: [
|
|
45
|
-
{ name: 'Claude Code', value: 'claude-code' },
|
|
46
|
-
{ name: 'OpenCode', value: 'opencode' },
|
|
47
|
-
],
|
|
48
|
-
default: 'claude-code',
|
|
49
|
-
},
|
|
50
|
-
]);
|
|
51
|
-
|
|
52
|
-
let provider: string | undefined = 'ask-every-time';
|
|
53
|
-
const apiKeys: Record<string, Record<string, string>> = {};
|
|
54
|
-
|
|
55
|
-
// Step 2: Provider setup (Claude Code only)
|
|
56
|
-
if (target === 'claude-code') {
|
|
57
|
-
console.log(chalk.cyan('\nš§ Setup (2/3) - Provider\n'));
|
|
58
|
-
const { selectedProvider } = await inquirer.prompt([
|
|
59
|
-
{
|
|
60
|
-
type: 'list',
|
|
61
|
-
name: 'selectedProvider',
|
|
62
|
-
message: 'Select your preferred provider:',
|
|
63
|
-
choices: [
|
|
64
|
-
{ name: 'Ask me every time', value: 'ask-every-time' },
|
|
65
|
-
{ name: 'Default (Claude Code built-in)', value: 'default' },
|
|
66
|
-
{ name: 'Kimi (requires API key)', value: 'kimi' },
|
|
67
|
-
{ name: 'Z.ai (requires API key)', value: 'zai' },
|
|
68
|
-
],
|
|
69
|
-
default: 'ask-every-time',
|
|
70
|
-
},
|
|
71
|
-
]);
|
|
72
|
-
|
|
73
|
-
provider = selectedProvider;
|
|
74
|
-
|
|
75
|
-
// Configure API key if needed
|
|
76
|
-
if (provider === 'kimi' || provider === 'zai') {
|
|
77
|
-
const { apiKey } = await inquirer.prompt([
|
|
78
|
-
{
|
|
79
|
-
type: 'password',
|
|
80
|
-
name: 'apiKey',
|
|
81
|
-
message: provider === 'kimi' ? 'Enter Kimi API key:' : 'Enter Z.ai API key:',
|
|
82
|
-
mask: '*',
|
|
83
|
-
},
|
|
84
|
-
]);
|
|
85
|
-
|
|
86
|
-
apiKeys[provider] = { apiKey };
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
// Step 3: MCP Servers
|
|
91
|
-
const stepNumber = target === 'claude-code' ? '3/3' : '2/2';
|
|
92
|
-
console.log(chalk.cyan('\nš§ Setup (' + stepNumber + ') - MCP Servers\n'));
|
|
93
|
-
|
|
94
|
-
const { mcpServers } = await inquirer.prompt([
|
|
95
|
-
{
|
|
96
|
-
type: 'checkbox',
|
|
97
|
-
name: 'mcpServers',
|
|
98
|
-
message: 'Select MCP servers to enable:',
|
|
99
|
-
choices: [
|
|
100
|
-
{ name: 'GitHub Code Search (grep.app)', value: 'grep', checked: true },
|
|
101
|
-
{ name: 'Context7 Docs', value: 'context7', checked: true },
|
|
102
|
-
{ name: 'Playwright Browser Control', value: 'playwright', checked: true },
|
|
103
|
-
{ name: 'GitHub (requires GITHUB_TOKEN)', value: 'github' },
|
|
104
|
-
{ name: 'Notion (requires NOTION_API_KEY)', value: 'notion' },
|
|
105
|
-
],
|
|
106
|
-
},
|
|
107
|
-
]);
|
|
108
|
-
|
|
109
|
-
// Configure MCP API keys
|
|
110
|
-
const mcpServerRequirements: Record<string, string[]> = {
|
|
111
|
-
github: ['GITHUB_TOKEN'],
|
|
112
|
-
notion: ['NOTION_API_KEY'],
|
|
113
|
-
};
|
|
114
|
-
|
|
115
|
-
for (const serverKey of mcpServers) {
|
|
116
|
-
const requirements = mcpServerRequirements[serverKey];
|
|
117
|
-
if (requirements) {
|
|
118
|
-
const configMessage = 'Configure ' + requirements[0] + ' for ' + serverKey + '?';
|
|
119
|
-
const { shouldConfigure } = await inquirer.prompt([
|
|
120
|
-
{
|
|
121
|
-
type: 'confirm',
|
|
122
|
-
name: 'shouldConfigure',
|
|
123
|
-
message: configMessage,
|
|
124
|
-
default: true,
|
|
125
|
-
},
|
|
126
|
-
]);
|
|
127
|
-
|
|
128
|
-
if (shouldConfigure) {
|
|
129
|
-
const questions = requirements.map((key) => {
|
|
130
|
-
return {
|
|
131
|
-
type: 'password' as const,
|
|
132
|
-
name: key,
|
|
133
|
-
message: 'Enter ' + key + ':',
|
|
134
|
-
mask: '*',
|
|
135
|
-
};
|
|
136
|
-
});
|
|
137
|
-
const answers = await inquirer.prompt(questions);
|
|
138
|
-
|
|
139
|
-
apiKeys[serverKey] = answers;
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
// Save configuration
|
|
145
|
-
await this.saveConfiguration({
|
|
146
|
-
target,
|
|
147
|
-
provider,
|
|
148
|
-
mcpServers,
|
|
149
|
-
apiKeys,
|
|
150
|
-
});
|
|
151
|
-
|
|
152
|
-
console.log(chalk.green('\nā Configuration saved to ~/.sylphx-flow/\n'));
|
|
153
|
-
|
|
154
|
-
return {
|
|
155
|
-
target,
|
|
156
|
-
provider: provider as any,
|
|
157
|
-
mcpServers,
|
|
158
|
-
apiKeys,
|
|
159
|
-
};
|
|
160
|
-
} catch (error: any) {
|
|
161
|
-
// Handle user cancellation (Ctrl+C)
|
|
162
|
-
if (error.name === 'ExitPromptError' || error.message?.includes('force closed')) {
|
|
163
|
-
throw new UserCancelledError('Setup cancelled by user');
|
|
164
|
-
}
|
|
165
|
-
throw error;
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
/**
|
|
170
|
-
* Save configuration to global config files
|
|
171
|
-
*/
|
|
172
|
-
private async saveConfiguration(result: QuickSetupResult): Promise<void> {
|
|
173
|
-
// Save global settings
|
|
174
|
-
await this.configService.saveSettings({
|
|
175
|
-
version: '1.0.0',
|
|
176
|
-
defaultTarget: result.target,
|
|
177
|
-
firstRun: false,
|
|
178
|
-
lastUpdated: new Date().toISOString(),
|
|
179
|
-
});
|
|
180
|
-
|
|
181
|
-
// Save provider config (Claude Code)
|
|
182
|
-
if (result.target === 'claude-code' && result.provider) {
|
|
183
|
-
const providerConfig = await this.configService.loadProviderConfig();
|
|
184
|
-
providerConfig.claudeCode.defaultProvider = result.provider;
|
|
185
|
-
|
|
186
|
-
// Save API keys
|
|
187
|
-
if (result.provider === 'kimi' && result.apiKeys.kimi) {
|
|
188
|
-
providerConfig.claudeCode.providers.kimi = {
|
|
189
|
-
apiKey: result.apiKeys.kimi.apiKey,
|
|
190
|
-
enabled: true,
|
|
191
|
-
};
|
|
192
|
-
}
|
|
193
|
-
if (result.provider === 'zai' && result.apiKeys.zai) {
|
|
194
|
-
providerConfig.claudeCode.providers.zai = {
|
|
195
|
-
apiKey: result.apiKeys.zai.apiKey,
|
|
196
|
-
enabled: true,
|
|
197
|
-
};
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
await this.configService.saveProviderConfig(providerConfig);
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
// Save MCP config
|
|
204
|
-
const mcpConfig = await this.configService.loadMCPConfig();
|
|
205
|
-
for (const serverKey of result.mcpServers) {
|
|
206
|
-
mcpConfig.servers[serverKey] = {
|
|
207
|
-
enabled: true,
|
|
208
|
-
env: result.apiKeys[serverKey] || {},
|
|
209
|
-
};
|
|
210
|
-
}
|
|
211
|
-
await this.configService.saveMCPConfig(mcpConfig);
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
/**
|
|
215
|
-
* Check if we should run quick setup
|
|
216
|
-
*/
|
|
217
|
-
async shouldRun(): Promise<boolean> {
|
|
218
|
-
return await this.configService.isFirstRun();
|
|
219
|
-
}
|
|
220
|
-
}
|