@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
@@ -1,252 +0,0 @@
1
- /**
2
- * Service configuration and registration for DI container
3
- */
4
-
5
- import { targetManager } from '../core/target-manager.js';
6
- import { MemoryDatabaseClient } from '../db/memory-db.js';
7
- import { createMCPService } from '../services/mcp-service.js';
8
- import { getDefaultEmbeddingProvider } from '../services/search/embeddings.js';
9
- import { getSearchService } from '../services/search/unified-search-service.js';
10
- import { createLogger as createRealLogger } from '../utils/logger.js';
11
- // Import concrete implementations (will be updated as we refactor)
12
- import { SeparatedMemoryStorage } from '../utils/separated-storage.js';
13
- import { container, SERVICE_TOKENS } from './di-container.js';
14
- import type {
15
- IConfiguration,
16
- IDatabaseConnection,
17
- IEmbeddingProvider,
18
- ILogger,
19
- IMCPService,
20
- ISearchService,
21
- IStorage,
22
- ITargetManager,
23
- } from './interfaces.js';
24
-
25
- /**
26
- * Configure and register all core services with the DI container
27
- */
28
- export async function configureServices(): Promise<void> {
29
- // Logger Service - Singleton
30
- container.register<ILogger>(SERVICE_TOKENS.LOGGER, () => createLogger(), 'singleton');
31
-
32
- // Configuration Service - Singleton
33
- container.register<IConfiguration>(
34
- SERVICE_TOKENS.CONFIG,
35
- () => createConfiguration(),
36
- 'singleton'
37
- );
38
-
39
- // Database Connection - Singleton
40
- container.register<IDatabaseConnection>(
41
- SERVICE_TOKENS.DATABASE,
42
- async () => {
43
- const dbClient = new MemoryDatabaseClient();
44
- await dbClient.initialize();
45
- return dbClient;
46
- },
47
- 'singleton'
48
- );
49
-
50
- // Memory Storage - Singleton
51
- container.register<IStorage>(
52
- SERVICE_TOKENS.MEMORY_STORAGE,
53
- async () => {
54
- const storage = new SeparatedMemoryStorage();
55
- await storage.initialize();
56
- return storage;
57
- },
58
- 'singleton'
59
- );
60
-
61
- // Search Service - Singleton
62
- container.register<ISearchService>(
63
- SERVICE_TOKENS.SEARCH_SERVICE,
64
- async () => {
65
- const searchService = getSearchService();
66
- await searchService.initialize();
67
- return searchService;
68
- },
69
- 'singleton'
70
- );
71
-
72
- // Target Manager - Singleton
73
- container.register<ITargetManager>(
74
- SERVICE_TOKENS.TARGET_MANAGER,
75
- () => targetManager,
76
- 'singleton'
77
- );
78
-
79
- // Embedding Provider - Singleton (lazy initialization)
80
- container.register<IEmbeddingProvider>(
81
- SERVICE_TOKENS.EMBEDDING_PROVIDER,
82
- async () => {
83
- try {
84
- return await getDefaultEmbeddingProvider();
85
- } catch (_error) {
86
- // Return a fallback provider that doesn't require external dependencies
87
- return createFallbackEmbeddingProvider();
88
- }
89
- },
90
- 'singleton'
91
- );
92
-
93
- // MCP Service - Transient (since it depends on target)
94
- container.register<IMCPService>(
95
- SERVICE_TOKENS.MCP_SERVICE,
96
- (targetId: string) => {
97
- const targetOption = targetManager.getTarget(targetId);
98
- if (targetOption._tag === 'None') {
99
- throw new Error(`Target not found: ${targetId}`);
100
- }
101
-
102
- const target = targetOption.value;
103
- return createMCPService({ target });
104
- },
105
- 'transient'
106
- );
107
- }
108
-
109
- /**
110
- * Create a logger instance that adapts our Logger to the ILogger interface
111
- */
112
- function createLogger(): ILogger {
113
- const logger = createRealLogger();
114
-
115
- return {
116
- info(message: string, ...args: any[]): void {
117
- // Merge args into context for structured logging
118
- const context = args.length > 0 ? { args } : undefined;
119
- logger.info(message, context);
120
- },
121
-
122
- warn(message: string, ...args: any[]): void {
123
- const context = args.length > 0 ? { args } : undefined;
124
- logger.warn(message, context);
125
- },
126
-
127
- error(message: string, error?: Error | unknown, ...args: any[]): void {
128
- const context = args.length > 0 ? { args } : undefined;
129
- if (error instanceof Error) {
130
- logger.error(message, error, context);
131
- } else {
132
- logger.error(message, undefined, { ...context, error });
133
- }
134
- },
135
-
136
- debug(message: string, ...args: any[]): void {
137
- const context = args.length > 0 ? { args } : undefined;
138
- logger.debug(message, context);
139
- },
140
-
141
- success(message: string, ...args: any[]): void {
142
- // Success is just info with different styling
143
- const context = args.length > 0 ? { args, level: 'success' } : { level: 'success' };
144
- logger.info(message, context);
145
- },
146
- };
147
- }
148
-
149
- /**
150
- * Create a configuration service
151
- */
152
- function createConfiguration(): IConfiguration {
153
- const config = new Map<string, any>();
154
-
155
- // Load environment variables
156
- const loadEnvConfig = () => {
157
- config.set('env', process.env.NODE_ENV || 'development');
158
- config.set('debug', process.env.DEBUG === 'true');
159
- config.set('logLevel', process.env.LOG_LEVEL || 'info');
160
- config.set('databasePath', process.env.DATABASE_PATH || '.sylphx-flow/memory.db');
161
- config.set('embeddings.provider', process.env.EMBEDDINGS_PROVIDER || 'local');
162
- config.set(
163
- 'embeddings.dimension',
164
- Number.parseInt(process.env.EMBEDDINGS_DIMENSION || '384', 10)
165
- );
166
- };
167
-
168
- loadEnvConfig();
169
-
170
- return {
171
- get<T = any>(key: string, defaultValue?: T): T {
172
- return config.get(key) ?? defaultValue;
173
- },
174
-
175
- getRequired<T = any>(key: string): T {
176
- const value = config.get(key);
177
- if (value === undefined) {
178
- throw new Error(`Required configuration key missing: ${key}`);
179
- }
180
- return value;
181
- },
182
-
183
- has(key: string): boolean {
184
- return config.has(key);
185
- },
186
-
187
- set(key: string, value: any): void {
188
- config.set(key, value);
189
- },
190
-
191
- async reload(): Promise<void> {
192
- config.clear();
193
- loadEnvConfig();
194
- },
195
- };
196
- }
197
-
198
- /**
199
- * Create a fallback embedding provider for when external providers are unavailable
200
- */
201
- function createFallbackEmbeddingProvider(): IEmbeddingProvider {
202
- return {
203
- name: 'fallback-tfidf',
204
- async embed(text: string): Promise<number[]> {
205
- // Simple TF-IDF like fallback - just return a hash-based vector
206
- const words = text.toLowerCase().split(/\s+/);
207
- const vector = new Array(384).fill(0);
208
-
209
- // Create a simple hash-based embedding
210
- words.forEach((word, index) => {
211
- const hash = simpleHash(word);
212
- const index1 = hash % 384;
213
- const index2 = (hash * 2) % 384;
214
- vector[index1] = (index + 1) / words.length;
215
- vector[index2] = (index + 1) / (words.length * 2);
216
- });
217
-
218
- return vector;
219
- },
220
-
221
- async isAvailable(): Promise<boolean> {
222
- return true; // Always available as fallback
223
- },
224
- };
225
- }
226
-
227
- /**
228
- * Simple hash function for fallback embeddings
229
- */
230
- function simpleHash(str: string): number {
231
- let hash = 0;
232
- for (let i = 0; i < str.length; i++) {
233
- const char = str.charCodeAt(i);
234
- hash = (hash << 5) - hash + char;
235
- hash &= hash; // Convert to 32-bit integer
236
- }
237
- return Math.abs(hash);
238
- }
239
-
240
- /**
241
- * Get a service from the container (convenience method)
242
- */
243
- export async function getService<T>(token: string): Promise<T> {
244
- return await container.resolve<T>(token);
245
- }
246
-
247
- /**
248
- * Check if a service is registered (convenience method)
249
- */
250
- export function hasService(token: string): boolean {
251
- return container.isRegistered(token);
252
- }
@@ -1,121 +0,0 @@
1
- /**
2
- * Session Service
3
- * Centralized session management for headless mode
4
- * Uses database for persistence
5
- */
6
-
7
- import chalk from 'chalk';
8
- import { loadAIConfig, getConfiguredProviders } from '../config/ai-config.js';
9
- import type { ProviderId, ProviderConfig } from '../config/ai-config.js';
10
- import type { Session } from '../types/session.types.js';
11
- import { getProvider } from '../providers/index.js';
12
- import { fetchModels } from '../utils/ai-model-fetcher.js';
13
- import { getSessionRepository } from '../db/database.js';
14
-
15
- /**
16
- * Get default model for a provider
17
- * Priority: config default-model > first available model
18
- */
19
- export async function getDefaultModel(providerId: ProviderId, providerConfig: ProviderConfig): Promise<string | null> {
20
- // Try config first
21
- const configModel = providerConfig['default-model'] as string | undefined;
22
- if (configModel) {
23
- return configModel;
24
- }
25
-
26
- // Fetch first available model
27
- try {
28
- const models = await fetchModels(providerId, providerConfig);
29
- return models[0]?.id || null;
30
- } catch {
31
- return null;
32
- }
33
- }
34
-
35
- /**
36
- * Get or create session for headless mode
37
- */
38
- export async function getOrCreateSession(continueSession: boolean): Promise<Session | null> {
39
- const cwd = process.cwd();
40
- const configResult = await loadAIConfig(cwd);
41
-
42
- if (configResult._tag === 'Failure') {
43
- console.error(chalk.red('✗ Failed to load AI config'));
44
- return null;
45
- }
46
-
47
- const config = configResult.value;
48
- const configuredProviders = await getConfiguredProviders(cwd);
49
-
50
- if (configuredProviders.length === 0) {
51
- console.error(chalk.yellow('\n⚠️ No AI provider configured\n'));
52
- console.error(chalk.dim('Run: sylphx code (to configure AI)\n'));
53
- return null;
54
- }
55
-
56
- const providerId = config.defaultProvider ?? configuredProviders[0];
57
- if (!providerId) {
58
- console.error(chalk.yellow('\n⚠️ No provider configured\n'));
59
- return null;
60
- }
61
-
62
- const providerConfig = config.providers?.[providerId];
63
- if (!providerConfig) {
64
- console.error(chalk.yellow('\n⚠️ Provider not configured\n'));
65
- return null;
66
- }
67
-
68
- // Check if provider is properly configured
69
- const provider = getProvider(providerId);
70
- if (!provider.isConfigured(providerConfig)) {
71
- console.error(chalk.yellow(`\n⚠️ ${provider.name} is not properly configured\n`));
72
- console.error(chalk.dim('Run: sylphx code (to configure AI)\n'));
73
- return null;
74
- }
75
-
76
- // Get session repository
77
- const repository = await getSessionRepository();
78
-
79
- // Try to continue last session
80
- if (continueSession) {
81
- const lastSession = await repository.getLastSession();
82
- if (lastSession) {
83
- console.error(chalk.dim(`Continuing session: ${lastSession.id}`));
84
- console.error(chalk.dim(`Messages: ${lastSession.messages.length}\n`));
85
- return lastSession;
86
- }
87
- console.error(chalk.yellow('No previous session found, creating new one\n'));
88
- }
89
-
90
- // Get default model (last used or first available)
91
- const modelName = await getDefaultModel(providerId, providerConfig);
92
- if (!modelName) {
93
- console.error(chalk.yellow('\n⚠️ No models available for this provider\n'));
94
- return null;
95
- }
96
-
97
- // Create new session in database
98
- return await repository.createSession(providerId, modelName);
99
- }
100
-
101
- /**
102
- * Show error message for models without tool support
103
- */
104
- export function showModelToolSupportError(): void {
105
- console.error(chalk.red('\n✗ No text response received from model\n'));
106
- console.error(
107
- chalk.yellow('The model may have called tools but did not generate a final text response.')
108
- );
109
- console.error(
110
- chalk.yellow('This usually means:\n')
111
- );
112
- console.error(chalk.dim(' • The current model does not fully support multi-step tool calling'));
113
- console.error(chalk.dim(' • Some models can call tools but cannot process results and respond\n'));
114
- console.error(chalk.green('Recommended models with full tool support:'));
115
- console.error(chalk.green(' • anthropic/claude-3.5-sonnet'));
116
- console.error(chalk.green(' • anthropic/claude-3.5-haiku'));
117
- console.error(chalk.green(' • openai/gpt-4o'));
118
- console.error(chalk.green(' • google/gemini-2.0-flash-exp\n'));
119
- console.error(chalk.dim('💡 Tip: Ask questions that don\'t require tools, or switch to a model above'));
120
- console.error(chalk.dim('To configure: Run `sylphx code` (TUI mode) then type /provider\n'));
121
- }
@@ -1,115 +0,0 @@
1
- /**
2
- * Storage Factory - 簡化存儲工廠
3
- * Feature-first, composable approach
4
- */
5
-
6
- import type { StorageConfig } from '../interfaces/unified-storage.js';
7
- import { createStorage } from './unified-storage.js';
8
- import { logger } from '../utils/logger.js';
9
-
10
- /**
11
- * Storage configuration builders
12
- */
13
- export const StorageConfig = {
14
- memory: (options?: Partial<StorageConfig>): StorageConfig => ({
15
- type: 'memory',
16
- ...options,
17
- }),
18
-
19
- cache: (options?: {
20
- defaultTTL?: number;
21
- maxCacheSize?: number;
22
- storageDir?: string;
23
- }): StorageConfig => ({
24
- type: 'cache',
25
- defaultTTL: options?.defaultTTL || 3600,
26
- maxCacheSize: options?.maxCacheSize,
27
- storageDir: options?.storageDir,
28
- }),
29
-
30
- vector: (options?: {
31
- vectorDimensions?: number;
32
- connectionString?: string;
33
- storageDir?: string;
34
- }): StorageConfig => ({
35
- type: 'vector',
36
- vectorDimensions: options?.vectorDimensions || 1536,
37
- connectionString: options?.connectionString,
38
- storageDir: options?.storageDir,
39
- }),
40
- } as const;
41
-
42
- /**
43
- * Create storage from configuration
44
- */
45
- export async function createStorageFromConfig<T = unknown>(config: StorageConfig) {
46
- try {
47
- const storage = createStorage<T>(config);
48
- await storage.initialize();
49
- logger.info('Storage created successfully', { type: config.type });
50
- return storage;
51
- } catch (error) {
52
- logger.error('Failed to create storage', { type: config.type, error });
53
- throw error;
54
- }
55
- }
56
-
57
- /**
58
- * Convenience functions for creating storage
59
- */
60
- export async function createMemoryStorage<T = unknown>(options?: Partial<StorageConfig>) {
61
- return createStorageFromConfig<T>(StorageConfig.memory(options));
62
- }
63
-
64
- export async function createCacheStorage<T = unknown>(options?: {
65
- defaultTTL?: number;
66
- maxCacheSize?: number;
67
- storageDir?: string;
68
- }) {
69
- return createStorageFromConfig<T>(StorageConfig.cache(options));
70
- }
71
-
72
- export async function createVectorStorage<T = unknown>(options?: {
73
- vectorDimensions?: number;
74
- connectionString?: string;
75
- storageDir?: string;
76
- }) {
77
- return createStorageFromConfig<T>(StorageConfig.vector(options));
78
- }
79
-
80
- /**
81
- * Create storage from environment configuration
82
- */
83
- export async function createStorageFromEnv<T = unknown>(type?: string): Promise<any> {
84
- const storageType = type || process.env.STORAGE_TYPE || 'memory';
85
-
86
- const config: StorageConfig = { type: storageType as any };
87
-
88
- // Load configuration from environment variables
89
- const connectionString = process.env.STORAGE_CONNECTION_STRING;
90
- if (connectionString) {
91
- config.connectionString = connectionString;
92
- }
93
-
94
- const storageDir = process.env.STORAGE_DIR;
95
- if (storageDir) {
96
- config.storageDir = storageDir;
97
- }
98
-
99
- const defaultTTL = process.env.CACHE_DEFAULT_TTL;
100
- if (defaultTTL) {
101
- config.defaultTTL = Number.parseInt(defaultTTL, 10);
102
- }
103
-
104
- const maxCacheSize = process.env.CACHE_MAX_SIZE;
105
- if (maxCacheSize) {
106
- config.maxCacheSize = Number.parseInt(maxCacheSize, 10);
107
- }
108
-
109
- const vectorDimensions = process.env.VECTOR_DIMENSIONS;
110
- if (vectorDimensions) {
111
- config.vectorDimensions = Number.parseInt(vectorDimensions, 10);
112
- }
113
-
114
- return createStorageFromConfig<T>(config);
115
- }