@sylphx/flow 2.1.3 ā 2.1.5
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 +28 -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/checkbox-config.ts +128 -0
- package/src/commands/settings/index.ts +6 -0
- package/src/commands/settings-command.ts +84 -156
- package/src/config/ai-config.ts +60 -41
- package/src/core/agent-loader.ts +11 -6
- package/src/core/attach/file-attacher.ts +172 -0
- package/src/core/attach/index.ts +5 -0
- package/src/core/attach-manager.ts +117 -171
- 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 +3 -3
- package/src/services/target-installer.ts +11 -26
- package/src/targets/claude-code.ts +35 -81
- package/src/targets/opencode.ts +28 -68
- package/src/targets/shared/index.ts +7 -0
- package/src/targets/shared/mcp-transforms.ts +132 -0
- package/src/targets/shared/target-operations.ts +135 -0
- 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 +6 -8
- 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
package/src/utils/index.ts
CHANGED
|
@@ -3,57 +3,49 @@
|
|
|
3
3
|
* Feature-based organization for better modularity
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
+
// ============================================================================
|
|
7
|
+
// SHARED UTILITIES
|
|
8
|
+
// ============================================================================
|
|
9
|
+
export * from '../shared/index.js';
|
|
10
|
+
// ============================================================================
|
|
11
|
+
// AGENTS
|
|
12
|
+
// ============================================================================
|
|
13
|
+
export * from './agent-enhancer.js';
|
|
14
|
+
export * from './config/mcp-config.js';
|
|
15
|
+
export * from './config/paths.js';
|
|
6
16
|
// ============================================================================
|
|
7
17
|
// CONFIG & SETTINGS
|
|
8
18
|
// ============================================================================
|
|
9
19
|
export * from './config/settings.js';
|
|
10
|
-
export * from './config/mcp-config.js';
|
|
11
20
|
export * from './config/target-config.js';
|
|
12
21
|
export * from './config/target-utils.js';
|
|
13
|
-
export * from './config/paths.js';
|
|
14
|
-
|
|
15
22
|
// ============================================================================
|
|
16
23
|
// DISPLAY & OUTPUT
|
|
17
24
|
// ============================================================================
|
|
18
25
|
export * from './display/banner.js';
|
|
19
|
-
export * from './display/status.js';
|
|
20
26
|
export * from './display/cli-output.js';
|
|
21
27
|
export * from './display/logger.js';
|
|
22
28
|
export * from './display/notifications.js';
|
|
23
|
-
|
|
29
|
+
export * from './display/status.js';
|
|
30
|
+
// ============================================================================
|
|
31
|
+
// ERROR HANDLING
|
|
32
|
+
// ============================================================================
|
|
33
|
+
export * from './error-handler.js';
|
|
24
34
|
// ============================================================================
|
|
25
35
|
// FILES & SYNC
|
|
26
36
|
// ============================================================================
|
|
27
37
|
export * from './files/file-operations.js';
|
|
28
38
|
export * from './files/sync-utils.js';
|
|
29
|
-
|
|
30
39
|
// ============================================================================
|
|
31
|
-
//
|
|
40
|
+
// FUNCTIONAL PROGRAMMING
|
|
32
41
|
// ============================================================================
|
|
33
|
-
export * from './
|
|
42
|
+
export * from './functional.js';
|
|
34
43
|
export * from './security/secret-utils.js';
|
|
35
|
-
|
|
36
44
|
// ============================================================================
|
|
37
|
-
//
|
|
45
|
+
// SECURITY
|
|
38
46
|
// ============================================================================
|
|
39
|
-
export * from './
|
|
40
|
-
|
|
47
|
+
export * from './security/security.js';
|
|
41
48
|
// ============================================================================
|
|
42
49
|
// VERSIONING
|
|
43
50
|
// ============================================================================
|
|
44
51
|
export * from './version.js';
|
|
45
|
-
|
|
46
|
-
// ============================================================================
|
|
47
|
-
// AGENTS
|
|
48
|
-
// ============================================================================
|
|
49
|
-
export * from './agent-enhancer.js';
|
|
50
|
-
|
|
51
|
-
// ============================================================================
|
|
52
|
-
// FUNCTIONAL PROGRAMMING
|
|
53
|
-
// ============================================================================
|
|
54
|
-
export * from './functional.js';
|
|
55
|
-
|
|
56
|
-
// ============================================================================
|
|
57
|
-
// SHARED UTILITIES
|
|
58
|
-
// ============================================================================
|
|
59
|
-
export * from '../shared/index.js';
|
|
@@ -27,10 +27,18 @@ export function detectPackageManagerFromUserAgent(): PackageManager | null {
|
|
|
27
27
|
return null;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
if (userAgent.includes('bun'))
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
if (userAgent.includes('
|
|
30
|
+
if (userAgent.includes('bun')) {
|
|
31
|
+
return 'bun';
|
|
32
|
+
}
|
|
33
|
+
if (userAgent.includes('pnpm')) {
|
|
34
|
+
return 'pnpm';
|
|
35
|
+
}
|
|
36
|
+
if (userAgent.includes('yarn')) {
|
|
37
|
+
return 'yarn';
|
|
38
|
+
}
|
|
39
|
+
if (userAgent.includes('npm')) {
|
|
40
|
+
return 'npm';
|
|
41
|
+
}
|
|
34
42
|
|
|
35
43
|
return null;
|
|
36
44
|
}
|
|
@@ -38,7 +46,9 @@ export function detectPackageManagerFromUserAgent(): PackageManager | null {
|
|
|
38
46
|
/**
|
|
39
47
|
* Detect package manager from lock files in directory
|
|
40
48
|
*/
|
|
41
|
-
export function detectPackageManagerFromLockFiles(
|
|
49
|
+
export function detectPackageManagerFromLockFiles(
|
|
50
|
+
dir: string = process.cwd()
|
|
51
|
+
): PackageManager | null {
|
|
42
52
|
const lockFiles: Record<PackageManager, string[]> = {
|
|
43
53
|
bun: ['bun.lockb', 'bun.lock'],
|
|
44
54
|
pnpm: ['pnpm-lock.yaml'],
|
|
@@ -209,11 +209,15 @@ export const commandSecurity = {
|
|
|
209
209
|
|
|
210
210
|
try {
|
|
211
211
|
return await execFileAsync(command, validatedArgs, secureOptions);
|
|
212
|
-
} catch (error:
|
|
212
|
+
} catch (error: unknown) {
|
|
213
213
|
// Sanitize error message to prevent information disclosure
|
|
214
|
-
const
|
|
215
|
-
sanitizedError
|
|
216
|
-
|
|
214
|
+
const err = error as NodeJS.ErrnoException & { signal?: string };
|
|
215
|
+
const sanitizedError = new Error(`Command execution failed: ${command}`) as Error & {
|
|
216
|
+
code?: string;
|
|
217
|
+
signal?: string;
|
|
218
|
+
};
|
|
219
|
+
sanitizedError.code = err.code;
|
|
220
|
+
sanitizedError.signal = err.signal;
|
|
217
221
|
throw sanitizedError;
|
|
218
222
|
}
|
|
219
223
|
},
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
import chalk from 'chalk';
|
|
7
7
|
import inquirer from 'inquirer';
|
|
8
|
-
import { TargetInstaller } from '../services/target-installer.js';
|
|
8
|
+
import type { TargetInstaller } from '../services/target-installer.js';
|
|
9
9
|
import { handlePromptError } from './prompt-helpers.js';
|
|
10
10
|
|
|
11
11
|
/**
|
|
@@ -15,7 +15,7 @@ export interface TargetChoice {
|
|
|
15
15
|
/** Display name of the target */
|
|
16
16
|
name: string;
|
|
17
17
|
/** Target identifier */
|
|
18
|
-
value: 'claude-code' | 'opencode'
|
|
18
|
+
value: 'claude-code' | 'opencode';
|
|
19
19
|
/** Whether the target is currently installed */
|
|
20
20
|
installed: boolean;
|
|
21
21
|
}
|
|
@@ -37,11 +37,6 @@ export function buildAvailableTargets(installedTargets: string[]): TargetChoice[
|
|
|
37
37
|
value: 'opencode',
|
|
38
38
|
installed: installedTargets.includes('opencode'),
|
|
39
39
|
},
|
|
40
|
-
{
|
|
41
|
-
name: 'Cursor',
|
|
42
|
-
value: 'cursor',
|
|
43
|
-
installed: installedTargets.includes('cursor'),
|
|
44
|
-
},
|
|
45
40
|
];
|
|
46
41
|
}
|
|
47
42
|
|
|
@@ -51,7 +46,10 @@ export function buildAvailableTargets(installedTargets: string[]): TargetChoice[
|
|
|
51
46
|
* @param context - Context where choice is displayed (affects status message)
|
|
52
47
|
* @returns Formatted string with target name and installation status
|
|
53
48
|
*/
|
|
54
|
-
export function formatTargetChoice(
|
|
49
|
+
export function formatTargetChoice(
|
|
50
|
+
target: TargetChoice,
|
|
51
|
+
context: 'execution' | 'settings'
|
|
52
|
+
): string {
|
|
55
53
|
const status = target.installed
|
|
56
54
|
? chalk.green(' ā installed')
|
|
57
55
|
: context === 'execution'
|
package/src/utils/version.ts
CHANGED
|
@@ -34,9 +34,11 @@ export function isVersionOutdated(current: string, latest: string): boolean {
|
|
|
34
34
|
/**
|
|
35
35
|
* Parse version string into components
|
|
36
36
|
*/
|
|
37
|
-
export function parseVersion(
|
|
37
|
+
export function parseVersion(
|
|
38
|
+
version: string
|
|
39
|
+
): { major: number; minor: number; patch: number } | null {
|
|
38
40
|
const parts = version.split('.').map(Number);
|
|
39
|
-
if (parts.length < 3 || parts.some(isNaN)) {
|
|
41
|
+
if (parts.length < 3 || parts.some(Number.isNaN)) {
|
|
40
42
|
return null;
|
|
41
43
|
}
|
|
42
44
|
return {
|
|
@@ -1,328 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Flow Orchestrator - Simplified flow management
|
|
3
|
-
* Separates concerns and reduces complexity
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import chalk from 'chalk';
|
|
7
|
-
import type { FlowOptions } from './flow/types.js';
|
|
8
|
-
import { StateDetector, type ProjectState } from '../core/state-detector.js';
|
|
9
|
-
import { UpgradeManager } from '../core/upgrade-manager.js';
|
|
10
|
-
import { targetManager } from '../core/target-manager.js';
|
|
11
|
-
import { detectPackageManager, getUpgradeCommand } from '../utils/package-manager-detector.js';
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Step 1: Check for available upgrades
|
|
15
|
-
*/
|
|
16
|
-
export async function checkUpgrades(
|
|
17
|
-
state: ProjectState,
|
|
18
|
-
options: FlowOptions
|
|
19
|
-
): Promise<void> {
|
|
20
|
-
if (options.initOnly || options.runOnly) return;
|
|
21
|
-
|
|
22
|
-
const upgradeManager = new UpgradeManager();
|
|
23
|
-
const updates = await upgradeManager.checkUpdates();
|
|
24
|
-
const packageManager = detectPackageManager();
|
|
25
|
-
|
|
26
|
-
// Check Flow upgrade
|
|
27
|
-
if (updates.flowUpdate && updates.flowVersion) {
|
|
28
|
-
const upgradeCmd = getUpgradeCommand('@sylphx/flow', packageManager);
|
|
29
|
-
console.log(
|
|
30
|
-
chalk.yellow(
|
|
31
|
-
`š¦ Sylphx Flow update available: ${updates.flowVersion.current} ā ${updates.flowVersion.latest}`
|
|
32
|
-
)
|
|
33
|
-
);
|
|
34
|
-
console.log(chalk.dim(` Quick upgrade: ${chalk.cyan('sylphx-flow upgrade --auto')}`));
|
|
35
|
-
console.log(chalk.dim(` Or run: ${chalk.cyan(upgradeCmd)}\n`));
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
// Check target upgrade
|
|
39
|
-
if (updates.targetUpdate && updates.targetVersion) {
|
|
40
|
-
console.log(
|
|
41
|
-
chalk.yellow(
|
|
42
|
-
`š¦ Target update available: ${updates.targetVersion.current} ā ${updates.targetVersion.latest}`
|
|
43
|
-
)
|
|
44
|
-
);
|
|
45
|
-
console.log(chalk.dim(` Run: ${chalk.cyan('sylphx-flow upgrade --target --auto')}\n`));
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Step 2: Check component integrity and prompt for repair
|
|
52
|
-
*/
|
|
53
|
-
export async function checkComponentIntegrity(
|
|
54
|
-
state: ProjectState,
|
|
55
|
-
options: FlowOptions
|
|
56
|
-
): Promise<void> {
|
|
57
|
-
// Skip if not initialized or cleaning or init-only
|
|
58
|
-
if (!state.initialized || options.clean || options.initOnly) return;
|
|
59
|
-
|
|
60
|
-
// Skip in quick mode
|
|
61
|
-
if (options.quick) return;
|
|
62
|
-
|
|
63
|
-
// Find missing components (target-aware)
|
|
64
|
-
const missing: string[] = [];
|
|
65
|
-
|
|
66
|
-
// Agents are always required
|
|
67
|
-
if (!state.components.agents.installed) missing.push('agents');
|
|
68
|
-
|
|
69
|
-
// For OpenCode: check rules (separate AGENTS.md file)
|
|
70
|
-
// For Claude Code: rules are included in agent files, so skip this check
|
|
71
|
-
if (state.target === 'opencode' && !state.components.rules.installed) {
|
|
72
|
-
missing.push('rules');
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
// Hooks are optional - don't check
|
|
76
|
-
// Claude Code can have hooks in .claude/hooks/*.js but they're optional
|
|
77
|
-
// OpenCode doesn't have separate hooks
|
|
78
|
-
|
|
79
|
-
// MCP is optional now - many users don't use MCP
|
|
80
|
-
// if (!state.components.mcp.installed) missing.push('mcp');
|
|
81
|
-
|
|
82
|
-
// Output styles:
|
|
83
|
-
// - Claude Code: included in agent files, so skip check
|
|
84
|
-
// - OpenCode: included in AGENTS.md, so skip check
|
|
85
|
-
|
|
86
|
-
// Slash commands are optional
|
|
87
|
-
// if (!state.components.slashCommands.installed) missing.push('slash commands');
|
|
88
|
-
|
|
89
|
-
// If no missing components, we're good
|
|
90
|
-
if (missing.length === 0) return;
|
|
91
|
-
|
|
92
|
-
// Prompt user to repair
|
|
93
|
-
console.log(chalk.yellow(`\nā ļø Missing components detected: ${missing.join(', ')}\n`));
|
|
94
|
-
const { default: inquirer } = await import('inquirer');
|
|
95
|
-
const { repair } = await inquirer.prompt([
|
|
96
|
-
{
|
|
97
|
-
type: 'confirm',
|
|
98
|
-
name: 'repair',
|
|
99
|
-
message: 'Install missing components now?',
|
|
100
|
-
default: true,
|
|
101
|
-
},
|
|
102
|
-
]);
|
|
103
|
-
|
|
104
|
-
if (repair) {
|
|
105
|
-
// Set repair mode - will trigger component installation without full re-init
|
|
106
|
-
options.repair = true;
|
|
107
|
-
console.log(chalk.cyan('\nš§ Repairing components...\n'));
|
|
108
|
-
} else {
|
|
109
|
-
console.log(chalk.dim('Skipping repair. Components may not work correctly.\n'));
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
/**
|
|
114
|
-
* Step 2.5: Check sync status (new templates available)
|
|
115
|
-
* Only checks for missing templates, ignores unknown files
|
|
116
|
-
*/
|
|
117
|
-
export async function checkSyncStatus(
|
|
118
|
-
state: ProjectState,
|
|
119
|
-
options: FlowOptions
|
|
120
|
-
): Promise<void> {
|
|
121
|
-
// Skip if not initialized, syncing, or init-only
|
|
122
|
-
if (!state.initialized || options.sync || options.initOnly) return;
|
|
123
|
-
|
|
124
|
-
// Skip in quick mode
|
|
125
|
-
if (options.quick) return;
|
|
126
|
-
|
|
127
|
-
// Need target to check sync status
|
|
128
|
-
if (!state.target) return;
|
|
129
|
-
|
|
130
|
-
try {
|
|
131
|
-
const { buildSyncManifest } = await import('../utils/files/sync-utils.js');
|
|
132
|
-
const target = targetManager.getTarget(state.target);
|
|
133
|
-
|
|
134
|
-
if (target._tag === 'None') return;
|
|
135
|
-
|
|
136
|
-
const manifest = await buildSyncManifest(process.cwd(), target.value);
|
|
137
|
-
|
|
138
|
-
// Count missing templates (new templates not installed locally)
|
|
139
|
-
const missingCount =
|
|
140
|
-
manifest.agents.missing.length +
|
|
141
|
-
manifest.slashCommands.missing.length +
|
|
142
|
-
manifest.rules.missing.length;
|
|
143
|
-
|
|
144
|
-
// Only prompt if there are missing templates
|
|
145
|
-
if (missingCount > 0) {
|
|
146
|
-
const missing: string[] = [];
|
|
147
|
-
|
|
148
|
-
if (manifest.agents.missing.length > 0) {
|
|
149
|
-
missing.push(`${manifest.agents.missing.length} agent${manifest.agents.missing.length > 1 ? 's' : ''}`);
|
|
150
|
-
}
|
|
151
|
-
if (manifest.slashCommands.missing.length > 0) {
|
|
152
|
-
missing.push(`${manifest.slashCommands.missing.length} command${manifest.slashCommands.missing.length > 1 ? 's' : ''}`);
|
|
153
|
-
}
|
|
154
|
-
if (manifest.rules.missing.length > 0) {
|
|
155
|
-
missing.push(`${manifest.rules.missing.length} rule${manifest.rules.missing.length > 1 ? 's' : ''}`);
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
console.log(chalk.yellow(`\nš¦ New templates available: ${missing.join(', ')}\n`));
|
|
159
|
-
console.log(chalk.dim(` Run ${chalk.cyan('sylphx-flow --sync')} to install new templates\n`));
|
|
160
|
-
}
|
|
161
|
-
} catch (error) {
|
|
162
|
-
// Silently ignore sync check errors - don't block execution
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
/**
|
|
167
|
-
* Step 3: Handle target selection
|
|
168
|
-
* Returns the selected target ID
|
|
169
|
-
*/
|
|
170
|
-
export async function selectTarget(
|
|
171
|
-
state: ProjectState,
|
|
172
|
-
options: FlowOptions
|
|
173
|
-
): Promise<string | undefined> {
|
|
174
|
-
// Force target selection when cleaning
|
|
175
|
-
if (options.clean) {
|
|
176
|
-
try {
|
|
177
|
-
const targetId = await targetManager.promptForTargetSelection();
|
|
178
|
-
console.log(chalk.green(`ā
Selected target: ${targetId}`));
|
|
179
|
-
return targetId;
|
|
180
|
-
} catch (error) {
|
|
181
|
-
// User cancelled with Ctrl+C - exit gracefully
|
|
182
|
-
if (error instanceof Error && error.name === 'ExitPromptError') {
|
|
183
|
-
console.log('\n');
|
|
184
|
-
process.exit(0);
|
|
185
|
-
}
|
|
186
|
-
throw error;
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
// Use existing target or option
|
|
191
|
-
return options.target || state.target;
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
/**
|
|
195
|
-
* Step 3: Initialize project
|
|
196
|
-
*/
|
|
197
|
-
export async function initializeProject(
|
|
198
|
-
targetId: string | undefined,
|
|
199
|
-
options: FlowOptions
|
|
200
|
-
): Promise<void> {
|
|
201
|
-
if (options.runOnly && !options.clean) return;
|
|
202
|
-
|
|
203
|
-
console.log(chalk.cyan.bold('ā Initializing Project\n'));
|
|
204
|
-
|
|
205
|
-
const { runInit } = await import('./init-command.js');
|
|
206
|
-
|
|
207
|
-
const initOptions = {
|
|
208
|
-
target: targetId,
|
|
209
|
-
verbose: options.verbose,
|
|
210
|
-
dryRun: options.dryRun,
|
|
211
|
-
clear: options.clean || false,
|
|
212
|
-
mcp: options.mcp !== false,
|
|
213
|
-
agents: options.agents !== false,
|
|
214
|
-
rules: options.rules !== false,
|
|
215
|
-
outputStyles: options.outputStyles !== false,
|
|
216
|
-
slashCommands: options.slashCommands !== false,
|
|
217
|
-
hooks: options.hooks !== false,
|
|
218
|
-
helpOption: () => {},
|
|
219
|
-
};
|
|
220
|
-
|
|
221
|
-
try {
|
|
222
|
-
await runInit(initOptions);
|
|
223
|
-
|
|
224
|
-
if (!options.dryRun) {
|
|
225
|
-
console.log(chalk.green.bold('\nā Initialization complete\n'));
|
|
226
|
-
} else {
|
|
227
|
-
console.log(chalk.dim('\nā Dry run complete - skipping execution\n'));
|
|
228
|
-
}
|
|
229
|
-
} catch (error) {
|
|
230
|
-
console.error(chalk.red.bold('\nā Initialization failed:'), error);
|
|
231
|
-
throw error;
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
/**
|
|
236
|
-
* Step 4: Launch target
|
|
237
|
-
*/
|
|
238
|
-
export async function launchTarget(
|
|
239
|
-
targetId: string | undefined,
|
|
240
|
-
prompt: string | undefined,
|
|
241
|
-
options: FlowOptions,
|
|
242
|
-
state: ProjectState
|
|
243
|
-
): Promise<void> {
|
|
244
|
-
if (options.initOnly) return;
|
|
245
|
-
|
|
246
|
-
// Resolve target
|
|
247
|
-
const resolvedTarget = await targetManager.resolveTarget({
|
|
248
|
-
target: targetId || state.target,
|
|
249
|
-
allowSelection: false,
|
|
250
|
-
});
|
|
251
|
-
|
|
252
|
-
console.log(chalk.cyan.bold(`ā Launching ${resolvedTarget}\n`));
|
|
253
|
-
|
|
254
|
-
// Check if target supports command execution
|
|
255
|
-
const { getTargetsWithCommandSupport } = await import('../config/targets.js');
|
|
256
|
-
const supportedTargets = getTargetsWithCommandSupport().map(t => t.id);
|
|
257
|
-
|
|
258
|
-
if (!supportedTargets.includes(resolvedTarget)) {
|
|
259
|
-
console.log(chalk.red.bold('ā Unsupported target platform\n'));
|
|
260
|
-
console.log(
|
|
261
|
-
chalk.yellow(`Target '${resolvedTarget}' does not support agent execution.`)
|
|
262
|
-
);
|
|
263
|
-
console.log(chalk.cyan(`Supported platforms: ${supportedTargets.join(', ')}\n`));
|
|
264
|
-
throw new Error(`Unsupported target: ${resolvedTarget}`);
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
// Handle Claude Code specific setup
|
|
268
|
-
if (resolvedTarget === 'claude-code') {
|
|
269
|
-
await setupClaudeCode(options);
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
// Execute command
|
|
273
|
-
await executeCommand(resolvedTarget, prompt, options);
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
/**
|
|
277
|
-
* Setup Claude Code (provider + agent selection)
|
|
278
|
-
*/
|
|
279
|
-
async function setupClaudeCode(options: FlowOptions): Promise<void> {
|
|
280
|
-
const { SmartConfigService } = await import('../services/smart-config-service.js');
|
|
281
|
-
const { ConfigService } = await import('../services/config-service.js');
|
|
282
|
-
|
|
283
|
-
// Check if API keys are configured
|
|
284
|
-
if (!(await ConfigService.hasInitialSetup())) {
|
|
285
|
-
console.log(chalk.cyan('\nš First-time setup for Claude Code:\n'));
|
|
286
|
-
await SmartConfigService.initialSetup();
|
|
287
|
-
console.log(chalk.green('\nā
Claude Code setup complete!\n'));
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
// Select provider and agent
|
|
291
|
-
const runtimeChoices = await SmartConfigService.selectRuntimeChoices({
|
|
292
|
-
selectProvider: options.selectProvider,
|
|
293
|
-
selectAgent: options.selectAgent,
|
|
294
|
-
useDefaults: options.useDefaults,
|
|
295
|
-
provider: options.provider,
|
|
296
|
-
agent: options.agent,
|
|
297
|
-
});
|
|
298
|
-
|
|
299
|
-
// Setup environment
|
|
300
|
-
await SmartConfigService.setupEnvironment(runtimeChoices.provider!);
|
|
301
|
-
|
|
302
|
-
// Store selected agent
|
|
303
|
-
options.agent = runtimeChoices.agent;
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
/**
|
|
307
|
-
* Execute the target command
|
|
308
|
-
*/
|
|
309
|
-
async function executeCommand(
|
|
310
|
-
targetId: string,
|
|
311
|
-
prompt: string | undefined,
|
|
312
|
-
options: FlowOptions
|
|
313
|
-
): Promise<void> {
|
|
314
|
-
const agent = options.agent || 'coder';
|
|
315
|
-
const verbose = options.verbose || false;
|
|
316
|
-
|
|
317
|
-
if (verbose || options.runOnly) {
|
|
318
|
-
console.log(`š¤ Agent: ${agent}`);
|
|
319
|
-
console.log(`šÆ Target: ${targetId}`);
|
|
320
|
-
if (prompt) {
|
|
321
|
-
console.log(`š¬ Prompt: ${prompt}\n`);
|
|
322
|
-
}
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
// Run the command
|
|
326
|
-
const { runCommand } = await import('./run-command.js');
|
|
327
|
-
await runCommand({ target: targetId, agent, prompt, verbose });
|
|
328
|
-
}
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
import boxen from 'boxen';
|
|
2
|
-
import chalk from 'chalk';
|
|
3
|
-
import gradient from 'gradient-string';
|
|
4
|
-
import {
|
|
5
|
-
selectAndValidateTarget,
|
|
6
|
-
previewDryRun,
|
|
7
|
-
installComponents,
|
|
8
|
-
type InitOptions,
|
|
9
|
-
} from './init-core.js';
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Legacy init with full UI - used by setup command for backward compatibility
|
|
13
|
-
* The flow command uses init-core functions directly for better integration
|
|
14
|
-
*/
|
|
15
|
-
export async function runInit(options: InitOptions): Promise<void> {
|
|
16
|
-
// Create ASCII art title
|
|
17
|
-
const title = `
|
|
18
|
-
āāāāāāāāāāā āāāāāā āāāāāāā āāā āāāāāā āāā āāāāāāāāāāā āāāāāāā āāā āāā
|
|
19
|
-
āāāāāāāāāāāā āāāāāāā āāāāāāāāāāā āāāāāāāāāāā āāāāāāāāāāā āāāāāāāāāāāā āāā
|
|
20
|
-
āāāāāāāā āāāāāāā āāā āāāāāāāāāāāāāāāā āāāāāā āāāāāā āāā āāā āāāāāā āā āāā
|
|
21
|
-
āāāāāāāā āāāāā āāā āāāāāāā āāāāāāāā āāāāāā āāāāāā āāā āāā āāāāāāāāāāāāā
|
|
22
|
-
āāāāāāāā āāā āāāāāāāāāāā āāā āāāāāāā āāā āāā āāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
23
|
-
āāāāāāāā āāā āāāāāāāāāāā āāā āāāāāā āāā āāā āāāāāāāā āāāāāāā āāāāāāāā
|
|
24
|
-
`;
|
|
25
|
-
|
|
26
|
-
console.log(gradient(['cyan', 'blue'])(title));
|
|
27
|
-
console.log(chalk.dim.cyan(' Project Initialization\n'));
|
|
28
|
-
|
|
29
|
-
// Select and validate target using core function
|
|
30
|
-
const targetId = await selectAndValidateTarget(options);
|
|
31
|
-
|
|
32
|
-
// Dry run preview
|
|
33
|
-
if (options.dryRun) {
|
|
34
|
-
console.log(
|
|
35
|
-
boxen(
|
|
36
|
-
chalk.yellow('ā Dry Run Mode') + chalk.dim('\nNo changes will be made to your project'),
|
|
37
|
-
{
|
|
38
|
-
padding: 1,
|
|
39
|
-
margin: { top: 0, bottom: 1, left: 0, right: 0 },
|
|
40
|
-
borderStyle: 'round',
|
|
41
|
-
borderColor: 'yellow',
|
|
42
|
-
}
|
|
43
|
-
)
|
|
44
|
-
);
|
|
45
|
-
|
|
46
|
-
await previewDryRun(targetId, options);
|
|
47
|
-
|
|
48
|
-
console.log(
|
|
49
|
-
'\n' +
|
|
50
|
-
boxen(chalk.green.bold('ā Dry run complete'), {
|
|
51
|
-
padding: { top: 0, bottom: 0, left: 2, right: 2 },
|
|
52
|
-
margin: 0,
|
|
53
|
-
borderStyle: 'round',
|
|
54
|
-
borderColor: 'green',
|
|
55
|
-
}) +
|
|
56
|
-
'\n'
|
|
57
|
-
);
|
|
58
|
-
return;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
console.log(chalk.cyan.bold('\nāāā Installing Core Components āāā\n'));
|
|
62
|
-
|
|
63
|
-
// Install components using core function
|
|
64
|
-
const result = await installComponents(targetId, options);
|
|
65
|
-
|
|
66
|
-
// Success summary
|
|
67
|
-
console.log(
|
|
68
|
-
'\n' +
|
|
69
|
-
boxen(
|
|
70
|
-
chalk.green.bold('ā Setup complete!') +
|
|
71
|
-
'\n\n' +
|
|
72
|
-
chalk.dim(`Target: ${result.targetName}`) +
|
|
73
|
-
'\n\n' +
|
|
74
|
-
chalk.cyan('Ready to code with Sylphx Flow'),
|
|
75
|
-
{
|
|
76
|
-
padding: 1,
|
|
77
|
-
margin: 0,
|
|
78
|
-
borderStyle: 'round',
|
|
79
|
-
borderColor: 'green',
|
|
80
|
-
}
|
|
81
|
-
) +
|
|
82
|
-
'\n'
|
|
83
|
-
);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* LEGACY: init command has been integrated into the flow command.
|
|
88
|
-
* Use `flow --init-only` instead of standalone `init` command.
|
|
89
|
-
*
|
|
90
|
-
* This export is kept for backward compatibility but will be removed in future versions.
|
|
91
|
-
* The runInit() function is the core implementation used by flow command.
|
|
92
|
-
*/
|