@sylphx/flow 1.7.0 → 1.8.1

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.
Files changed (131) hide show
  1. package/CHANGELOG.md +78 -0
  2. package/assets/agents/coder.md +72 -119
  3. package/assets/agents/orchestrator.md +26 -90
  4. package/assets/agents/reviewer.md +76 -47
  5. package/assets/agents/writer.md +82 -63
  6. package/assets/output-styles/silent.md +141 -8
  7. package/assets/rules/code-standards.md +9 -33
  8. package/assets/rules/core.md +67 -59
  9. package/package.json +2 -12
  10. package/src/commands/flow/execute.ts +470 -0
  11. package/src/commands/flow/index.ts +11 -0
  12. package/src/commands/flow/prompt.ts +35 -0
  13. package/src/commands/flow/setup.ts +312 -0
  14. package/src/commands/flow/targets.ts +18 -0
  15. package/src/commands/flow/types.ts +47 -0
  16. package/src/commands/flow-command.ts +18 -967
  17. package/src/commands/flow-orchestrator.ts +14 -5
  18. package/src/commands/hook-command.ts +1 -1
  19. package/src/commands/init-core.ts +12 -3
  20. package/src/commands/run-command.ts +1 -1
  21. package/src/config/rules.ts +1 -1
  22. package/src/core/error-handling.ts +1 -1
  23. package/src/core/loop-controller.ts +1 -1
  24. package/src/core/state-detector.ts +1 -1
  25. package/src/core/target-manager.ts +1 -1
  26. package/src/index.ts +1 -1
  27. package/src/shared/files/index.ts +1 -1
  28. package/src/shared/processing/index.ts +1 -1
  29. package/src/targets/claude-code.ts +3 -3
  30. package/src/targets/opencode.ts +3 -3
  31. package/src/utils/agent-enhancer.ts +2 -2
  32. package/src/utils/{mcp-config.ts → config/mcp-config.ts} +4 -4
  33. package/src/utils/{paths.ts → config/paths.ts} +1 -1
  34. package/src/utils/{settings.ts → config/settings.ts} +1 -1
  35. package/src/utils/{target-config.ts → config/target-config.ts} +5 -5
  36. package/src/utils/{target-utils.ts → config/target-utils.ts} +3 -3
  37. package/src/utils/display/banner.ts +25 -0
  38. package/src/utils/display/status.ts +55 -0
  39. package/src/utils/{file-operations.ts → files/file-operations.ts} +2 -2
  40. package/src/utils/files/jsonc.ts +36 -0
  41. package/src/utils/{sync-utils.ts → files/sync-utils.ts} +3 -3
  42. package/src/utils/index.ts +42 -61
  43. package/src/utils/version.ts +47 -0
  44. package/src/components/benchmark-monitor.tsx +0 -331
  45. package/src/components/reindex-progress.tsx +0 -261
  46. package/src/composables/functional/index.ts +0 -14
  47. package/src/composables/functional/useEnvironment.ts +0 -171
  48. package/src/composables/functional/useFileSystem.ts +0 -139
  49. package/src/composables/index.ts +0 -4
  50. package/src/composables/useEnv.ts +0 -13
  51. package/src/composables/useRuntimeConfig.ts +0 -27
  52. package/src/core/ai-sdk.ts +0 -603
  53. package/src/core/app-factory.ts +0 -381
  54. package/src/core/builtin-agents.ts +0 -9
  55. package/src/core/command-system.ts +0 -550
  56. package/src/core/config-system.ts +0 -550
  57. package/src/core/connection-pool.ts +0 -390
  58. package/src/core/di-container.ts +0 -155
  59. package/src/core/headless-display.ts +0 -96
  60. package/src/core/interfaces/index.ts +0 -22
  61. package/src/core/interfaces/repository.interface.ts +0 -91
  62. package/src/core/interfaces/service.interface.ts +0 -133
  63. package/src/core/interfaces.ts +0 -96
  64. package/src/core/result.ts +0 -351
  65. package/src/core/service-config.ts +0 -252
  66. package/src/core/session-service.ts +0 -121
  67. package/src/core/storage-factory.ts +0 -115
  68. package/src/core/stream-handler.ts +0 -288
  69. package/src/core/type-utils.ts +0 -427
  70. package/src/core/unified-storage.ts +0 -456
  71. package/src/core/validation/limit.ts +0 -46
  72. package/src/core/validation/query.ts +0 -20
  73. package/src/db/auto-migrate.ts +0 -322
  74. package/src/db/base-database-client.ts +0 -144
  75. package/src/db/cache-db.ts +0 -218
  76. package/src/db/cache-schema.ts +0 -75
  77. package/src/db/database.ts +0 -70
  78. package/src/db/index.ts +0 -252
  79. package/src/db/memory-db.ts +0 -153
  80. package/src/db/memory-schema.ts +0 -29
  81. package/src/db/schema.ts +0 -289
  82. package/src/db/session-repository.ts +0 -733
  83. package/src/domains/index.ts +0 -6
  84. package/src/domains/utilities/index.ts +0 -6
  85. package/src/domains/utilities/time/index.ts +0 -5
  86. package/src/domains/utilities/time/tools.ts +0 -291
  87. package/src/services/agent-service.ts +0 -273
  88. package/src/services/evaluation-service.ts +0 -271
  89. package/src/services/functional/evaluation-logic.ts +0 -296
  90. package/src/services/functional/file-processor.ts +0 -273
  91. package/src/services/functional/index.ts +0 -12
  92. package/src/services/memory.service.ts +0 -476
  93. package/src/types/api/batch.ts +0 -108
  94. package/src/types/api/errors.ts +0 -118
  95. package/src/types/api/index.ts +0 -55
  96. package/src/types/api/requests.ts +0 -76
  97. package/src/types/api/responses.ts +0 -180
  98. package/src/types/api/websockets.ts +0 -85
  99. package/src/types/benchmark.ts +0 -49
  100. package/src/types/database.types.ts +0 -510
  101. package/src/types/memory-types.ts +0 -63
  102. package/src/utils/advanced-tokenizer.ts +0 -191
  103. package/src/utils/ai-model-fetcher.ts +0 -19
  104. package/src/utils/async-file-operations.ts +0 -516
  105. package/src/utils/audio-player.ts +0 -345
  106. package/src/utils/codebase-helpers.ts +0 -211
  107. package/src/utils/console-ui.ts +0 -79
  108. package/src/utils/database-errors.ts +0 -140
  109. package/src/utils/debug-logger.ts +0 -49
  110. package/src/utils/file-scanner.ts +0 -259
  111. package/src/utils/help.ts +0 -20
  112. package/src/utils/immutable-cache.ts +0 -106
  113. package/src/utils/jsonc.ts +0 -158
  114. package/src/utils/memory-tui.ts +0 -414
  115. package/src/utils/models-dev.ts +0 -91
  116. package/src/utils/parallel-operations.ts +0 -487
  117. package/src/utils/process-manager.ts +0 -155
  118. package/src/utils/prompts.ts +0 -120
  119. package/src/utils/search-tool-builder.ts +0 -214
  120. package/src/utils/session-manager.ts +0 -168
  121. package/src/utils/session-title.ts +0 -87
  122. package/src/utils/simplified-errors.ts +0 -410
  123. package/src/utils/template-engine.ts +0 -94
  124. package/src/utils/test-audio.ts +0 -71
  125. package/src/utils/todo-context.ts +0 -46
  126. package/src/utils/token-counter.ts +0 -288
  127. /package/src/utils/{cli-output.ts → display/cli-output.ts} +0 -0
  128. /package/src/utils/{logger.ts → display/logger.ts} +0 -0
  129. /package/src/utils/{notifications.ts → display/notifications.ts} +0 -0
  130. /package/src/utils/{secret-utils.ts → security/secret-utils.ts} +0 -0
  131. /package/src/utils/{security.ts → security/security.ts} +0 -0
@@ -0,0 +1,312 @@
1
+ /**
2
+ * Setup Phase for Flow Command
3
+ * One-time initialization and preparation for command execution
4
+ */
5
+
6
+ import chalk from 'chalk';
7
+ import { targetManager } from '../../core/target-manager.js';
8
+ import { StateDetector, type ProjectState } from '../../core/state-detector.js';
9
+ import { projectSettings } from '../../utils/config/settings.js';
10
+ import { showWelcome } from '../../utils/display/banner.js';
11
+ import { showStatus } from '../../utils/display/status.js';
12
+ import { loadAgentContent, extractAgentInstructions } from '../run-command.js';
13
+ import type { RunCommandOptions } from '../../types.js';
14
+ import type { FlowOptions, SetupContext } from './types.js';
15
+
16
+ /**
17
+ * Execute setup phase once (for loop mode)
18
+ * Returns context needed for repeated command execution
19
+ */
20
+ export async function executeSetupPhase(prompt: string | undefined, options: FlowOptions): Promise<SetupContext> {
21
+ // Quick mode: enable useDefaults and skip prompts
22
+ if (options.quick) {
23
+ options.useDefaults = true;
24
+ console.log(chalk.cyan('⚡ Quick mode enabled - using saved defaults\n'));
25
+ }
26
+
27
+ // Import orchestrator functions
28
+ const {
29
+ checkUpgrades,
30
+ checkComponentIntegrity,
31
+ } = await import('../flow-orchestrator.js');
32
+
33
+ // Show welcome banner (only once)
34
+ showWelcome();
35
+
36
+ let selectedTarget: string | undefined;
37
+ let state: ProjectState | undefined;
38
+
39
+ // Determine target
40
+ const initialTarget = options.target || (await projectSettings.getDefaultTarget());
41
+
42
+ // Detect state if we have a target
43
+ if (initialTarget && !options.sync) {
44
+ const detector = new StateDetector();
45
+
46
+ if (options.verbose) {
47
+ console.log(chalk.dim('🤔 Checking project status...\n'));
48
+ }
49
+
50
+ state = await detector.detect();
51
+
52
+ if (options.verbose) {
53
+ await showStatus(state);
54
+ }
55
+
56
+ // Check for upgrades
57
+ if (!options.quick) {
58
+ await checkUpgrades(state, options);
59
+ }
60
+
61
+ // Check component integrity
62
+ await checkComponentIntegrity(state, options);
63
+ }
64
+
65
+ // Initialize if needed
66
+ const shouldInitialize =
67
+ !state?.initialized ||
68
+ options.sync ||
69
+ options.repair ||
70
+ options.initOnly;
71
+
72
+ if (shouldInitialize) {
73
+ selectedTarget = await initializeWithTarget(options);
74
+ }
75
+
76
+ // Resolve target
77
+ const targetForResolution = resolveTargetPriority(options.target, state?.target, selectedTarget);
78
+
79
+ if (!targetForResolution) {
80
+ console.error(chalk.red.bold('✗ No target selected. Use --target or run init first.'));
81
+ process.exit(1);
82
+ }
83
+
84
+ const resolvedTarget = await targetManager.resolveTarget({
85
+ target: targetForResolution,
86
+ allowSelection: false,
87
+ });
88
+
89
+ console.log(chalk.cyan.bold(`━━━ 🎯 Launching ${resolvedTarget}\n`));
90
+
91
+ // Validate target support
92
+ await validateTargetSupport(resolvedTarget);
93
+
94
+ // Handle Claude Code specific setup
95
+ if (resolvedTarget === 'claude-code') {
96
+ await setupClaudeCode(options);
97
+ }
98
+
99
+ const agent = options.agent || 'coder';
100
+ const verbose = options.verbose || false;
101
+
102
+ if (verbose || options.runOnly || !options.quick) {
103
+ console.log(` 🤖 Agent: ${chalk.cyan(agent)}`);
104
+ console.log(` 🎯 Target: ${chalk.cyan(resolvedTarget)}`);
105
+ if (prompt) {
106
+ console.log(` 💬 Prompt: ${chalk.dim(prompt)}\n`);
107
+ } else {
108
+ console.log(` 💬 Mode: ${chalk.dim('Interactive')}\n`);
109
+ }
110
+ }
111
+
112
+ // Load agent and prepare prompts
113
+ const agentContent = await loadAgentContent(agent, options.agentFile);
114
+ const agentInstructions = extractAgentInstructions(agentContent);
115
+ const systemPrompt = `AGENT INSTRUCTIONS:\n${agentInstructions}`;
116
+
117
+ // Prepare run options
118
+ const runOptions: RunCommandOptions = {
119
+ target: resolvedTarget,
120
+ verbose,
121
+ dryRun: options.dryRun,
122
+ agent,
123
+ agentFile: options.agentFile,
124
+ prompt,
125
+ print: options.print,
126
+ continue: options.continue,
127
+ };
128
+
129
+ return {
130
+ resolvedTarget,
131
+ initializedSuccessfully: true,
132
+ systemPrompt,
133
+ runOptions,
134
+ };
135
+ }
136
+
137
+ /**
138
+ * Initialize project with target selection and component installation
139
+ */
140
+ async function initializeWithTarget(options: FlowOptions): Promise<string | undefined> {
141
+ let selectedTarget: string | undefined;
142
+
143
+ try {
144
+ const { selectAndValidateTarget, previewDryRun, installComponents } =
145
+ await import('../init-core.js');
146
+
147
+ const initOptions = {
148
+ target: options.target,
149
+ verbose: options.verbose || false,
150
+ dryRun: options.dryRun || false,
151
+ clear: options.sync || false,
152
+ mcp: options.mcp !== false,
153
+ agents: options.agents !== false,
154
+ rules: options.rules !== false,
155
+ outputStyles: options.outputStyles !== false,
156
+ slashCommands: options.slashCommands !== false,
157
+ hooks: options.hooks !== false,
158
+ };
159
+
160
+ // Handle sync mode - delete template files first
161
+ if (options.sync && !options.dryRun) {
162
+ selectedTarget = await handleSyncMode(initOptions);
163
+ } else if (!options.sync) {
164
+ const targetId = await selectAndValidateTarget(initOptions);
165
+ selectedTarget = targetId;
166
+ }
167
+
168
+ if (options.dryRun) {
169
+ // Ensure we have a target ID for dry run
170
+ if (!selectedTarget) {
171
+ const targetId = await selectAndValidateTarget(initOptions);
172
+ selectedTarget = targetId;
173
+ }
174
+
175
+ await previewDryRun(selectedTarget, initOptions);
176
+ console.log(chalk.dim('✓ Initialization dry run complete\n'));
177
+ } else {
178
+ // Ensure we have a target ID for installation
179
+ if (!selectedTarget) {
180
+ const targetId = await selectAndValidateTarget(initOptions);
181
+ selectedTarget = targetId;
182
+ }
183
+
184
+ await installComponents(selectedTarget, initOptions);
185
+ console.log(chalk.green.bold('✓ Initialization complete\n'));
186
+ }
187
+ } catch (error) {
188
+ console.error(chalk.red.bold('✗ Initialization failed:'), error);
189
+ process.exit(1);
190
+ }
191
+
192
+ return selectedTarget;
193
+ }
194
+
195
+ /**
196
+ * Handle sync mode: delete templates then reinstall
197
+ */
198
+ async function handleSyncMode(initOptions: any): Promise<string> {
199
+ const { buildSyncManifest, showSyncPreview, selectUnknownFilesToRemove, showFinalSummary, confirmSync, executeSyncDelete, removeMCPServers, removeHooks } = await import('../../utils/files/sync-utils.js');
200
+ const { selectAndValidateTarget } = await import('../init-core.js');
201
+
202
+ // Need target to build manifest
203
+ const targetId = await selectAndValidateTarget(initOptions);
204
+
205
+ const targetOption = targetManager.getTarget(targetId);
206
+ if (targetOption._tag === 'None') {
207
+ throw new Error(`Target not found: ${targetId}`);
208
+ }
209
+
210
+ const target = targetOption.value;
211
+ const manifest = await buildSyncManifest(process.cwd(), target);
212
+
213
+ // Show preview
214
+ console.log(chalk.cyan.bold('━━━ 🔄 Synchronizing Files\n'));
215
+ showSyncPreview(manifest, process.cwd(), target);
216
+
217
+ // Select unknown files to remove
218
+ const selectedUnknowns = await selectUnknownFilesToRemove(manifest);
219
+
220
+ // Show final summary
221
+ showFinalSummary(manifest, selectedUnknowns);
222
+
223
+ // Confirm
224
+ const confirmed = await confirmSync();
225
+ if (!confirmed) {
226
+ console.log(chalk.yellow('\n✗ Sync cancelled\n'));
227
+ process.exit(0);
228
+ }
229
+
230
+ // Execute deletion
231
+ const { templates, unknowns } = await executeSyncDelete(manifest, selectedUnknowns);
232
+
233
+ // Remove MCP servers
234
+ let mcpRemoved = 0;
235
+ if (selectedUnknowns.mcpServers.length > 0) {
236
+ mcpRemoved = await removeMCPServers(process.cwd(), selectedUnknowns.mcpServers);
237
+ }
238
+
239
+ // Remove hooks
240
+ let hooksRemoved = 0;
241
+ if (selectedUnknowns.hooks.length > 0) {
242
+ hooksRemoved = await removeHooks(process.cwd(), selectedUnknowns.hooks);
243
+ }
244
+
245
+ // Summary
246
+ console.log(chalk.green(`\n✓ Synced ${templates} templates`));
247
+ const totalRemoved = unknowns + mcpRemoved + hooksRemoved;
248
+ if (totalRemoved > 0) {
249
+ console.log(chalk.green(`✓ Removed ${totalRemoved} items`));
250
+ }
251
+ const totalSelected = selectedUnknowns.files.length + selectedUnknowns.mcpServers.length + selectedUnknowns.hooks.length;
252
+ const preserved = manifest.agents.unknown.length + manifest.slashCommands.unknown.length + manifest.rules.unknown.length + manifest.mcpServers.notInRegistry.length + manifest.hooks.orphaned.length - totalSelected;
253
+ if (preserved > 0) {
254
+ console.log(chalk.green(`✓ Preserved ${preserved} custom items`));
255
+ }
256
+ console.log('');
257
+
258
+ return targetId;
259
+ }
260
+
261
+ /**
262
+ * Resolve target priority: options > state > selected
263
+ */
264
+ function resolveTargetPriority(
265
+ optionsTarget: string | undefined,
266
+ stateTarget: string | undefined,
267
+ selectedTarget: string | undefined
268
+ ): string | undefined {
269
+ return selectedTarget || optionsTarget || stateTarget;
270
+ }
271
+
272
+ /**
273
+ * Validate that target supports command execution
274
+ */
275
+ async function validateTargetSupport(resolvedTarget: string): Promise<void> {
276
+ const { getTargetsWithCommandSupport } = await import('../../config/targets.js');
277
+ const supportedTargets = getTargetsWithCommandSupport().map(t => t.id);
278
+
279
+ if (!supportedTargets.includes(resolvedTarget)) {
280
+ console.log(chalk.red.bold('✗ Unsupported target platform\n'));
281
+ console.log(chalk.yellow(`Target '${resolvedTarget}' does not support agent execution.`));
282
+ console.log(chalk.cyan(`Supported platforms: ${supportedTargets.join(', ')}\n`));
283
+ console.log(chalk.dim('Tip: Use --target claude-code to specify Claude Code platform'));
284
+ console.log(chalk.dim('Example: bun dev:flow --target claude-code\n'));
285
+ process.exit(1);
286
+ }
287
+ }
288
+
289
+ /**
290
+ * Setup Claude Code provider and agent
291
+ */
292
+ async function setupClaudeCode(options: FlowOptions): Promise<void> {
293
+ const { SmartConfigService } = await import('../../services/smart-config-service.js');
294
+ const { ConfigService } = await import('../../services/config-service.js');
295
+
296
+ if (!(await ConfigService.hasInitialSetup())) {
297
+ console.log(chalk.cyan('🔑 First-time setup for Claude Code\n'));
298
+ await SmartConfigService.initialSetup();
299
+ console.log(chalk.green('✓ Setup complete!\n'));
300
+ }
301
+
302
+ const runtimeChoices = await SmartConfigService.selectRuntimeChoices({
303
+ selectProvider: options.selectProvider,
304
+ selectAgent: options.selectAgent,
305
+ useDefaults: options.useDefaults,
306
+ provider: options.provider,
307
+ agent: options.agent,
308
+ });
309
+
310
+ await SmartConfigService.setupEnvironment(runtimeChoices.provider!);
311
+ options.agent = runtimeChoices.agent;
312
+ }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Target Management for Flow Commands
3
+ */
4
+
5
+ import { targetManager } from '../../core/target-manager.js';
6
+
7
+ /**
8
+ * Get executable targets
9
+ */
10
+ export function getExecutableTargets(): string[] {
11
+ return targetManager.getImplementedTargetIDs().filter((targetId) => {
12
+ const targetOption = targetManager.getTarget(targetId);
13
+ if (targetOption._tag === 'None') {
14
+ return false;
15
+ }
16
+ return targetOption.value.executeCommand !== undefined;
17
+ });
18
+ }
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Flow Command Types
3
+ */
4
+
5
+ import type { RunCommandOptions } from '../../types.js';
6
+
7
+ export interface FlowOptions {
8
+ target?: string;
9
+ verbose?: boolean;
10
+ dryRun?: boolean;
11
+ sync?: boolean;
12
+ initOnly?: boolean;
13
+ runOnly?: boolean;
14
+ repair?: boolean;
15
+ upgrade?: boolean;
16
+ upgradeTarget?: boolean;
17
+ mcp?: boolean;
18
+ agents?: boolean;
19
+ rules?: boolean;
20
+ outputStyles?: boolean;
21
+ slashCommands?: boolean;
22
+ hooks?: boolean;
23
+ agent?: string;
24
+ agentFile?: string;
25
+
26
+ // Smart configuration options
27
+ selectProvider?: boolean;
28
+ selectAgent?: boolean;
29
+ useDefaults?: boolean;
30
+ provider?: string;
31
+ quick?: boolean;
32
+
33
+ // Execution modes
34
+ print?: boolean;
35
+ continue?: boolean;
36
+
37
+ // Loop mode
38
+ loop?: number;
39
+ maxRuns?: number;
40
+ }
41
+
42
+ export interface SetupContext {
43
+ resolvedTarget: string;
44
+ initializedSuccessfully: boolean;
45
+ systemPrompt?: string;
46
+ runOptions?: RunCommandOptions;
47
+ }