@sylphx/flow 1.1.1 → 1.3.0

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 (47) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/package.json +1 -1
  3. package/src/commands/flow-command.ts +28 -0
  4. package/src/commands/hook-command.ts +10 -230
  5. package/src/composables/index.ts +0 -1
  6. package/src/config/servers.ts +35 -78
  7. package/src/core/interfaces.ts +0 -33
  8. package/src/domains/index.ts +0 -2
  9. package/src/index.ts +0 -4
  10. package/src/services/mcp-service.ts +0 -16
  11. package/src/targets/claude-code.ts +3 -9
  12. package/src/targets/functional/claude-code-logic.ts +4 -22
  13. package/src/targets/opencode.ts +0 -6
  14. package/src/types/mcp.types.ts +29 -38
  15. package/src/types/target.types.ts +0 -2
  16. package/src/types.ts +0 -1
  17. package/src/utils/sync-utils.ts +106 -0
  18. package/src/commands/codebase-command.ts +0 -168
  19. package/src/commands/knowledge-command.ts +0 -161
  20. package/src/composables/useTargetConfig.ts +0 -45
  21. package/src/core/formatting/bytes.test.ts +0 -115
  22. package/src/core/validation/limit.test.ts +0 -155
  23. package/src/core/validation/query.test.ts +0 -44
  24. package/src/domains/codebase/index.ts +0 -5
  25. package/src/domains/codebase/tools.ts +0 -139
  26. package/src/domains/knowledge/index.ts +0 -10
  27. package/src/domains/knowledge/resources.ts +0 -537
  28. package/src/domains/knowledge/tools.ts +0 -174
  29. package/src/services/search/base-indexer.ts +0 -156
  30. package/src/services/search/codebase-indexer-types.ts +0 -38
  31. package/src/services/search/codebase-indexer.ts +0 -647
  32. package/src/services/search/embeddings-provider.ts +0 -455
  33. package/src/services/search/embeddings.ts +0 -316
  34. package/src/services/search/functional-indexer.ts +0 -323
  35. package/src/services/search/index.ts +0 -27
  36. package/src/services/search/indexer.ts +0 -380
  37. package/src/services/search/knowledge-indexer.ts +0 -422
  38. package/src/services/search/semantic-search.ts +0 -244
  39. package/src/services/search/tfidf.ts +0 -559
  40. package/src/services/search/unified-search-service.ts +0 -888
  41. package/src/services/storage/cache-storage.ts +0 -487
  42. package/src/services/storage/drizzle-storage.ts +0 -581
  43. package/src/services/storage/index.ts +0 -15
  44. package/src/services/storage/lancedb-vector-storage.ts +0 -494
  45. package/src/services/storage/memory-storage.ts +0 -268
  46. package/src/services/storage/separated-storage.ts +0 -467
  47. package/src/services/storage/vector-storage.ts +0 -13
@@ -1,487 +0,0 @@
1
- /**
2
- * Cache Storage Implementation - 緩存存儲實現
3
- * 專門處理臨時緩存數據(可以重新生成,不應該上 Git)
4
- */
5
-
6
- import { count, desc, eq } from 'drizzle-orm';
7
- import { type CacheDatabase, CacheDatabaseClient } from '../../db/cache-db.js';
8
- import {
9
- codebaseFiles,
10
- codebaseMetadata,
11
- type NewCodebaseFile,
12
- type NewTfidfDocument,
13
- type NewTfidfIdf,
14
- type NewTfidfTerm,
15
- tfidfDocuments,
16
- tfidfIdf,
17
- tfidfTerms,
18
- } from '../../db/cache-schema.js';
19
- import { executeOperation } from '../../utils/database-errors.js';
20
-
21
- // Codebase file entry interface
22
- export interface CodebaseFileEntry {
23
- path: string;
24
- mtime: number;
25
- hash: string;
26
- content?: string;
27
- language?: string;
28
- size?: number;
29
- indexedAt: string;
30
- }
31
-
32
- // TF-IDF term entry interface
33
- export interface TfidfTermEntry {
34
- filePath: string;
35
- term: string;
36
- frequency: number;
37
- }
38
-
39
- // TF-IDF document entry interface
40
- export interface TfidfDocumentEntry {
41
- filePath: string;
42
- magnitude: number;
43
- termCount: number;
44
- rawTerms: string;
45
- }
46
-
47
- // TF-IDF IDF entry interface
48
- export interface TfidfIdfEntry {
49
- term: string;
50
- idfValue: number;
51
- }
52
-
53
- /**
54
- * Cache storage implementation
55
- */
56
- export class CacheStorage {
57
- private cacheDb: CacheDatabaseClient;
58
- private cache: CacheDatabase;
59
-
60
- constructor() {
61
- this.cacheDb = new CacheDatabaseClient();
62
- this.cache = this.cacheDb.db;
63
- }
64
-
65
- async initialize(): Promise<void> {
66
- await this.cacheDb.initialize();
67
- }
68
-
69
- // === Codebase Files Operations ===
70
-
71
- /**
72
- * Store a codebase file entry
73
- */
74
- async setCodebaseFile(file: NewCodebaseFile): Promise<void> {
75
- return executeOperation(`set codebase file: ${file.path}`, async () => {
76
- await this.cache
77
- .insert(codebaseFiles)
78
- .values(file)
79
- .onConflictDoUpdate({
80
- target: codebaseFiles.path,
81
- set: {
82
- mtime: file.mtime,
83
- hash: file.hash,
84
- content: file.content,
85
- language: file.language,
86
- size: file.size,
87
- indexedAt: file.indexedAt,
88
- },
89
- });
90
- });
91
- }
92
-
93
- /**
94
- * Get a codebase file entry
95
- */
96
- async getCodebaseFile(path: string): Promise<CodebaseFileEntry | null> {
97
- return executeOperation(`get codebase file: ${path}`, async () => {
98
- const result = await this.cache
99
- .select()
100
- .from(codebaseFiles)
101
- .where(eq(codebaseFiles.path, path))
102
- .limit(1);
103
-
104
- if (result.length === 0) {
105
- return null;
106
- }
107
-
108
- const entry = result[0];
109
- return {
110
- path: entry.path,
111
- mtime: entry.mtime,
112
- hash: entry.hash,
113
- content: entry.content || undefined,
114
- language: entry.language || undefined,
115
- size: entry.size || undefined,
116
- indexedAt: entry.indexedAt,
117
- };
118
- });
119
- }
120
-
121
- /**
122
- * Get all codebase files
123
- */
124
- async getAllCodebaseFiles(): Promise<CodebaseFileEntry[]> {
125
- return executeOperation('get all codebase files', async () => {
126
- const results = await this.cache
127
- .select()
128
- .from(codebaseFiles)
129
- .orderBy(desc(codebaseFiles.mtime));
130
-
131
- return results.map((entry) => ({
132
- path: entry.path,
133
- mtime: entry.mtime,
134
- hash: entry.hash,
135
- content: entry.content || undefined,
136
- language: entry.language || undefined,
137
- size: entry.size || undefined,
138
- indexedAt: entry.indexedAt,
139
- }));
140
- });
141
- }
142
-
143
- /**
144
- * Delete a codebase file entry
145
- */
146
- async deleteCodebaseFile(path: string): Promise<boolean> {
147
- return executeOperation(`delete codebase file: ${path}`, async () => {
148
- const _result = await this.cache.delete(codebaseFiles).where(eq(codebaseFiles.path, path));
149
-
150
- // For libSQL, we need to check if the deletion was successful
151
- // by trying to select the record afterwards
152
- const exists = await this.cache
153
- .select()
154
- .from(codebaseFiles)
155
- .where(eq(codebaseFiles.path, path))
156
- .limit(1);
157
-
158
- return exists.length === 0;
159
- });
160
- }
161
-
162
- /**
163
- * Clear all codebase files
164
- */
165
- async clearCodebaseFiles(): Promise<void> {
166
- return executeOperation('clear codebase files', async () => {
167
- await this.cache.delete(codebaseFiles);
168
- });
169
- }
170
-
171
- // === Codebase Metadata Operations ===
172
-
173
- /**
174
- * Set metadata value
175
- */
176
- async setMetadata(key: string, value: string): Promise<void> {
177
- return executeOperation(`set metadata: ${key}`, async () => {
178
- await this.cache.insert(codebaseMetadata).values({ key, value }).onConflictDoUpdate({
179
- target: codebaseMetadata.key,
180
- set: { value },
181
- });
182
- });
183
- }
184
-
185
- /**
186
- * Get metadata value
187
- */
188
- async getMetadata(key: string): Promise<string | null> {
189
- return executeOperation(`get metadata: ${key}`, async () => {
190
- const result = await this.cache
191
- .select()
192
- .from(codebaseMetadata)
193
- .where(eq(codebaseMetadata.key, key))
194
- .limit(1);
195
-
196
- return result.length > 0 ? result[0].value : null;
197
- });
198
- }
199
-
200
- /**
201
- * Get all metadata
202
- */
203
- async getAllMetadata(): Promise<Record<string, string>> {
204
- return executeOperation('get all metadata', async () => {
205
- const results = await this.cache.select().from(codebaseMetadata);
206
- const metadata: Record<string, string> = {};
207
-
208
- for (const entry of results) {
209
- metadata[entry.key] = entry.value;
210
- }
211
-
212
- return metadata;
213
- });
214
- }
215
-
216
- /**
217
- * Delete metadata
218
- */
219
- async deleteMetadata(key: string): Promise<boolean> {
220
- return executeOperation(`delete metadata: ${key}`, async () => {
221
- const _result = await this.cache
222
- .delete(codebaseMetadata)
223
- .where(eq(codebaseMetadata.key, key));
224
-
225
- // Check if deletion was successful
226
- const exists = await this.cache
227
- .select()
228
- .from(codebaseMetadata)
229
- .where(eq(codebaseMetadata.key, key))
230
- .limit(1);
231
-
232
- return exists.length === 0;
233
- });
234
- }
235
-
236
- // === TF-IDF Terms Operations ===
237
-
238
- /**
239
- * Store TF-IDF terms for a file
240
- */
241
- async setTfidfTerms(terms: NewTfidfTerm[]): Promise<void> {
242
- return executeOperation('set TF-IDF terms', async () => {
243
- // Clear existing terms for these files
244
- const filePaths = [...new Set(terms.map((t) => t.filePath))];
245
- for (const filePath of filePaths) {
246
- await this.cache.delete(tfidfTerms).where(eq(tfidfTerms.filePath, filePath));
247
- }
248
-
249
- // Insert new terms in batches to avoid SQLite limits
250
- if (terms.length > 0) {
251
- const batchSize = 500; // SQLite can handle this comfortably
252
- for (let i = 0; i < terms.length; i += batchSize) {
253
- const batch = terms.slice(i, i + batchSize);
254
- await this.cache.insert(tfidfTerms).values(batch);
255
- }
256
- }
257
- });
258
- }
259
-
260
- /**
261
- * Get TF-IDF terms for a file
262
- */
263
- async getTfidfTerms(filePath: string): Promise<TfidfTermEntry[]> {
264
- return executeOperation(`get TF-IDF terms for file: ${filePath}`, async () => {
265
- const results = await this.cache
266
- .select()
267
- .from(tfidfTerms)
268
- .where(eq(tfidfTerms.filePath, filePath));
269
-
270
- return results.map((entry) => ({
271
- filePath: entry.filePath,
272
- term: entry.term,
273
- frequency: entry.frequency,
274
- }));
275
- });
276
- }
277
-
278
- /**
279
- * Get TF-IDF terms by term
280
- */
281
- async getTfidfTermsByTerm(term: string): Promise<TfidfTermEntry[]> {
282
- return executeOperation(`get TF-IDF terms by term: ${term}`, async () => {
283
- const results = await this.cache.select().from(tfidfTerms).where(eq(tfidfTerms.term, term));
284
-
285
- return results.map((entry) => ({
286
- filePath: entry.filePath,
287
- term: entry.term,
288
- frequency: entry.frequency,
289
- }));
290
- });
291
- }
292
-
293
- /**
294
- * Clear all TF-IDF terms
295
- */
296
- async clearTfidfTerms(): Promise<void> {
297
- return executeOperation('clear TF-IDF terms', async () => {
298
- await this.cache.delete(tfidfTerms);
299
- });
300
- }
301
-
302
- // === TF-IDF Documents Operations ===
303
-
304
- /**
305
- * Store TF-IDF document vector
306
- */
307
- async setTfidfDocument(document: NewTfidfDocument): Promise<void> {
308
- return executeOperation(`set TF-IDF document: ${document.filePath}`, async () => {
309
- await this.cache
310
- .insert(tfidfDocuments)
311
- .values(document)
312
- .onConflictDoUpdate({
313
- target: tfidfDocuments.filePath,
314
- set: {
315
- magnitude: document.magnitude,
316
- termCount: document.termCount,
317
- rawTerms: document.rawTerms,
318
- },
319
- });
320
- });
321
- }
322
-
323
- /**
324
- * Get TF-IDF document vector
325
- */
326
- async getTfidfDocument(filePath: string): Promise<TfidfDocumentEntry | null> {
327
- return executeOperation(`get TF-IDF document: ${filePath}`, async () => {
328
- const result = await this.cache
329
- .select()
330
- .from(tfidfDocuments)
331
- .where(eq(tfidfDocuments.filePath, filePath))
332
- .limit(1);
333
-
334
- if (result.length === 0) {
335
- return null;
336
- }
337
-
338
- const entry = result[0];
339
- return {
340
- filePath: entry.filePath,
341
- magnitude: entry.magnitude,
342
- termCount: entry.termCount,
343
- rawTerms: entry.rawTerms,
344
- };
345
- });
346
- }
347
-
348
- /**
349
- * Get all TF-IDF documents
350
- */
351
- async getAllTfidfDocuments(): Promise<TfidfDocumentEntry[]> {
352
- return executeOperation('get all TF-IDF documents', async () => {
353
- const results = await this.cache.select().from(tfidfDocuments);
354
-
355
- return results.map((entry) => ({
356
- filePath: entry.filePath,
357
- magnitude: entry.magnitude,
358
- termCount: entry.termCount,
359
- rawTerms: entry.rawTerms,
360
- }));
361
- });
362
- }
363
-
364
- /**
365
- * Clear all TF-IDF documents
366
- */
367
- async clearTfidfDocuments(): Promise<void> {
368
- return executeOperation('clear TF-IDF documents', async () => {
369
- await this.cache.delete(tfidfDocuments);
370
- });
371
- }
372
-
373
- // === TF-IDF IDF Operations ===
374
-
375
- /**
376
- * Store IDF value
377
- */
378
- async setTfidfIdf(idf: NewTfidfIdf): Promise<void> {
379
- return executeOperation(`set TF-IDF IDF: ${idf.term}`, async () => {
380
- await this.cache
381
- .insert(tfidfIdf)
382
- .values(idf)
383
- .onConflictDoUpdate({
384
- target: tfidfIdf.term,
385
- set: { idfValue: idf.idfValue },
386
- });
387
- });
388
- }
389
-
390
- /**
391
- * Get IDF value
392
- */
393
- async getTfidfIdf(term: string): Promise<TfidfIdfEntry | null> {
394
- return executeOperation(`get TF-IDF IDF: ${term}`, async () => {
395
- const result = await this.cache
396
- .select()
397
- .from(tfidfIdf)
398
- .where(eq(tfidfIdf.term, term))
399
- .limit(1);
400
-
401
- if (result.length === 0) {
402
- return null;
403
- }
404
-
405
- const entry = result[0];
406
- return {
407
- term: entry.term,
408
- idfValue: entry.idfValue,
409
- };
410
- });
411
- }
412
-
413
- /**
414
- * Get all IDF values
415
- */
416
- async getAllTfidfIdf(): Promise<TfidfIdfEntry[]> {
417
- return executeOperation('get all TF-IDF IDF values', async () => {
418
- const results = await this.cache.select().from(tfidfIdf);
419
-
420
- return results.map((entry) => ({
421
- term: entry.term,
422
- idfValue: entry.idfValue,
423
- }));
424
- });
425
- }
426
-
427
- /**
428
- * Clear all IDF values
429
- */
430
- async clearTfidfIdf(): Promise<void> {
431
- return executeOperation('clear TF-IDF IDF values', async () => {
432
- await this.cache.delete(tfidfIdf);
433
- });
434
- }
435
-
436
- // === Utility Operations ===
437
-
438
- /**
439
- * Get cache statistics
440
- */
441
- async getStats(): Promise<{
442
- codebaseFiles: number;
443
- metadataEntries: number;
444
- tfidfTerms: number;
445
- tfidfDocuments: number;
446
- tfidfIdfValues: number;
447
- }> {
448
- return executeOperation('get cache statistics', async () => {
449
- const [
450
- codebaseFilesResult,
451
- metadataResult,
452
- tfidfTermsResult,
453
- tfidfDocumentsResult,
454
- tfidfIdfResult,
455
- ] = await Promise.all([
456
- this.cache.select({ count: count() }).from(codebaseFiles),
457
- this.cache.select({ count: count() }).from(codebaseMetadata),
458
- this.cache.select({ count: count() }).from(tfidfTerms),
459
- this.cache.select({ count: count() }).from(tfidfDocuments),
460
- this.cache.select({ count: count() }).from(tfidfIdf),
461
- ]);
462
-
463
- return {
464
- codebaseFiles: codebaseFilesResult[0]?.count || 0,
465
- metadataEntries: metadataResult[0]?.count || 0,
466
- tfidfTerms: tfidfTermsResult[0]?.count || 0,
467
- tfidfDocuments: tfidfDocumentsResult[0]?.count || 0,
468
- tfidfIdfValues: tfidfIdfResult[0]?.count || 0,
469
- };
470
- });
471
- }
472
-
473
- /**
474
- * Clear all cache data
475
- */
476
- async clearAll(): Promise<void> {
477
- return executeOperation('clear all cache data', async () => {
478
- await Promise.all([
479
- this.cache.delete(codebaseFiles),
480
- this.cache.delete(codebaseMetadata),
481
- this.cache.delete(tfidfTerms),
482
- this.cache.delete(tfidfDocuments),
483
- this.cache.delete(tfidfIdf),
484
- ]);
485
- });
486
- }
487
- }