@sylphx/flow 1.1.0 → 1.2.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 (45) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/package.json +12 -2
  3. package/src/commands/hook-command.ts +10 -230
  4. package/src/composables/index.ts +0 -1
  5. package/src/config/servers.ts +35 -78
  6. package/src/core/interfaces.ts +0 -33
  7. package/src/domains/index.ts +0 -2
  8. package/src/index.ts +0 -4
  9. package/src/services/mcp-service.ts +0 -16
  10. package/src/targets/claude-code.ts +3 -9
  11. package/src/targets/functional/claude-code-logic.ts +4 -22
  12. package/src/targets/opencode.ts +0 -6
  13. package/src/types/mcp.types.ts +29 -38
  14. package/src/types/target.types.ts +0 -2
  15. package/src/types.ts +0 -1
  16. package/src/commands/codebase-command.ts +0 -168
  17. package/src/commands/knowledge-command.ts +0 -161
  18. package/src/composables/useTargetConfig.ts +0 -45
  19. package/src/core/formatting/bytes.test.ts +0 -115
  20. package/src/core/validation/limit.test.ts +0 -155
  21. package/src/core/validation/query.test.ts +0 -44
  22. package/src/domains/codebase/index.ts +0 -5
  23. package/src/domains/codebase/tools.ts +0 -139
  24. package/src/domains/knowledge/index.ts +0 -10
  25. package/src/domains/knowledge/resources.ts +0 -537
  26. package/src/domains/knowledge/tools.ts +0 -174
  27. package/src/services/search/base-indexer.ts +0 -156
  28. package/src/services/search/codebase-indexer-types.ts +0 -38
  29. package/src/services/search/codebase-indexer.ts +0 -647
  30. package/src/services/search/embeddings-provider.ts +0 -455
  31. package/src/services/search/embeddings.ts +0 -316
  32. package/src/services/search/functional-indexer.ts +0 -323
  33. package/src/services/search/index.ts +0 -27
  34. package/src/services/search/indexer.ts +0 -380
  35. package/src/services/search/knowledge-indexer.ts +0 -422
  36. package/src/services/search/semantic-search.ts +0 -244
  37. package/src/services/search/tfidf.ts +0 -559
  38. package/src/services/search/unified-search-service.ts +0 -888
  39. package/src/services/storage/cache-storage.ts +0 -487
  40. package/src/services/storage/drizzle-storage.ts +0 -581
  41. package/src/services/storage/index.ts +0 -15
  42. package/src/services/storage/lancedb-vector-storage.ts +0 -494
  43. package/src/services/storage/memory-storage.ts +0 -268
  44. package/src/services/storage/separated-storage.ts +0 -467
  45. package/src/services/storage/vector-storage.ts +0 -13
@@ -1,155 +0,0 @@
1
- /**
2
- * Tests for Limit Validation Utilities
3
- */
4
-
5
- import { describe, expect, it } from 'bun:test';
6
- import { validateLimit } from './limit.js';
7
-
8
- describe('validateLimit', () => {
9
- describe('with default parameters (defaultLimit=50, maxLimit=1000)', () => {
10
- it('returns default limit when undefined', () => {
11
- const result = validateLimit(undefined);
12
- expect(result._tag).toBe('Success');
13
- expect(result._tag === 'Success' && result.value).toBe(50);
14
- });
15
-
16
- it('accepts valid number', () => {
17
- const result = validateLimit(100);
18
- expect(result._tag).toBe('Success');
19
- expect(result._tag === 'Success' && result.value).toBe(100);
20
- });
21
-
22
- it('accepts valid string number', () => {
23
- const result = validateLimit('500');
24
- expect(result._tag).toBe('Success');
25
- expect(result._tag === 'Success' && result.value).toBe(500);
26
- });
27
-
28
- it('accepts limit at max', () => {
29
- const result = validateLimit(1000);
30
- expect(result._tag).toBe('Success');
31
- expect(result._tag === 'Success' && result.value).toBe(1000);
32
- });
33
-
34
- it('rejects limit above max', () => {
35
- const result = validateLimit(1001);
36
- expect(result._tag).toBe('Failure');
37
- expect(result._tag === 'Failure' && result.error.message).toBe('Limit cannot exceed 1000');
38
- });
39
-
40
- it('rejects zero', () => {
41
- const result = validateLimit(0);
42
- expect(result._tag).toBe('Failure');
43
- expect(result._tag === 'Failure' && result.error.message).toBe(
44
- 'Limit must be a positive number'
45
- );
46
- });
47
-
48
- it('rejects negative number', () => {
49
- const result = validateLimit(-10);
50
- expect(result._tag).toBe('Failure');
51
- expect(result._tag === 'Failure' && result.error.message).toBe(
52
- 'Limit must be a positive number'
53
- );
54
- });
55
-
56
- it('rejects invalid string', () => {
57
- const result = validateLimit('invalid');
58
- expect(result._tag).toBe('Failure');
59
- expect(result._tag === 'Failure' && result.error.message).toBe(
60
- 'Limit must be a positive number'
61
- );
62
- });
63
-
64
- it('rejects empty string', () => {
65
- const result = validateLimit('');
66
- expect(result._tag).toBe('Failure');
67
- expect(result._tag === 'Failure' && result.error.message).toBe(
68
- 'Limit must be a positive number'
69
- );
70
- });
71
- });
72
-
73
- describe('with custom default (defaultLimit=10)', () => {
74
- it('returns custom default when undefined', () => {
75
- const result = validateLimit(undefined, 10);
76
- expect(result._tag).toBe('Success');
77
- expect(result._tag === 'Success' && result.value).toBe(10);
78
- });
79
- });
80
-
81
- describe('with custom max (maxLimit=100)', () => {
82
- it('accepts limit at custom max', () => {
83
- const result = validateLimit(100, 10, 100);
84
- expect(result._tag).toBe('Success');
85
- expect(result._tag === 'Success' && result.value).toBe(100);
86
- });
87
-
88
- it('rejects limit above custom max', () => {
89
- const result = validateLimit(101, 10, 100);
90
- expect(result._tag).toBe('Failure');
91
- expect(result._tag === 'Failure' && result.error.message).toBe('Limit cannot exceed 100');
92
- });
93
- });
94
-
95
- describe('knowledge feature defaults (defaultLimit=10, maxLimit=100)', () => {
96
- it('returns 10 when undefined', () => {
97
- const result = validateLimit(undefined, 10, 100);
98
- expect(result._tag).toBe('Success');
99
- expect(result._tag === 'Success' && result.value).toBe(10);
100
- });
101
-
102
- it('accepts 50', () => {
103
- const result = validateLimit(50, 10, 100);
104
- expect(result._tag).toBe('Success');
105
- expect(result._tag === 'Success' && result.value).toBe(50);
106
- });
107
-
108
- it('rejects 101', () => {
109
- const result = validateLimit(101, 10, 100);
110
- expect(result._tag).toBe('Failure');
111
- expect(result._tag === 'Failure' && result.error.message).toBe('Limit cannot exceed 100');
112
- });
113
- });
114
-
115
- describe('memory feature defaults (defaultLimit=50, maxLimit=1000)', () => {
116
- it('returns 50 when undefined', () => {
117
- const result = validateLimit(undefined, 50, 1000);
118
- expect(result._tag).toBe('Success');
119
- expect(result._tag === 'Success' && result.value).toBe(50);
120
- });
121
-
122
- it('accepts 500', () => {
123
- const result = validateLimit(500, 50, 1000);
124
- expect(result._tag).toBe('Success');
125
- expect(result._tag === 'Success' && result.value).toBe(500);
126
- });
127
-
128
- it('rejects 1001', () => {
129
- const result = validateLimit(1001, 50, 1000);
130
- expect(result._tag).toBe('Failure');
131
- expect(result._tag === 'Failure' && result.error.message).toBe('Limit cannot exceed 1000');
132
- });
133
- });
134
-
135
- describe('edge cases', () => {
136
- it('accepts 1 (minimum valid)', () => {
137
- const result = validateLimit(1);
138
- expect(result._tag).toBe('Success');
139
- expect(result._tag === 'Success' && result.value).toBe(1);
140
- });
141
-
142
- it('handles string with whitespace', () => {
143
- const result = validateLimit(' 100 ');
144
- expect(result._tag).toBe('Success');
145
- expect(result._tag === 'Success' && result.value).toBe(100);
146
- });
147
-
148
- it('rejects decimal numbers', () => {
149
- const result = validateLimit('10.5');
150
- expect(result._tag).toBe('Success');
151
- // parseInt truncates to 10
152
- expect(result._tag === 'Success' && result.value).toBe(10);
153
- });
154
- });
155
- });
@@ -1,44 +0,0 @@
1
- /**
2
- * Tests for Query Validation Utilities
3
- */
4
-
5
- import { describe, expect, it } from 'bun:test';
6
- import { normalizeQuery } from './query.js';
7
-
8
- describe('normalizeQuery', () => {
9
- it('trims leading whitespace', () => {
10
- expect(normalizeQuery(' hello')).toBe('hello');
11
- });
12
-
13
- it('trims trailing whitespace', () => {
14
- expect(normalizeQuery('hello ')).toBe('hello');
15
- });
16
-
17
- it('trims both leading and trailing whitespace', () => {
18
- expect(normalizeQuery(' hello ')).toBe('hello');
19
- });
20
-
21
- it('preserves internal whitespace', () => {
22
- expect(normalizeQuery('hello world')).toBe('hello world');
23
- });
24
-
25
- it('handles empty string', () => {
26
- expect(normalizeQuery('')).toBe('');
27
- });
28
-
29
- it('handles string with only whitespace', () => {
30
- expect(normalizeQuery(' ')).toBe('');
31
- });
32
-
33
- it('handles tabs and newlines', () => {
34
- expect(normalizeQuery('\t\nhello\t\n')).toBe('hello');
35
- });
36
-
37
- it('handles already trimmed string', () => {
38
- expect(normalizeQuery('hello')).toBe('hello');
39
- });
40
-
41
- it('handles multi-line queries', () => {
42
- expect(normalizeQuery(' line1\nline2 ')).toBe('line1\nline2');
43
- });
44
- });
@@ -1,5 +0,0 @@
1
- /**
2
- * Codebase domain - Code analysis and search
3
- */
4
-
5
- export { registerCodebaseSearchTool, registerCodebaseTools } from './tools.js';
@@ -1,139 +0,0 @@
1
- /**
2
- * Codebase tools
3
- * All tools for working with project source code and files
4
- */
5
-
6
- import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
7
- import { z } from 'zod';
8
- import { getSearchService } from '../../services/search/unified-search-service.js';
9
-
10
- /**
11
- * Register codebase search tool
12
- */
13
- export function registerCodebaseSearchTool(server: McpServer): void {
14
- server.registerTool(
15
- 'codebase_search',
16
- {
17
- description: `Search project source files, documentation, and code. Use this to find implementations, functions, classes, or any code-related content.
18
-
19
- **IMPORTANT: Use this tool PROACTIVELY before starting work, not reactively when stuck.**
20
-
21
- This tool searches across all codebase files and returns the most relevant matches with content snippets.
22
-
23
- When to use this tool (BEFORE starting work):
24
- - **Before implementation**: Find existing patterns, similar functions, or reusable components
25
- - **Before refactoring**: Understand current implementation and dependencies
26
- - **Before adding features**: Check for existing similar functionality or conflicting code
27
- - **Before debugging**: Search for error messages, function names, or related code
28
- - **Before writing tests**: Find existing test patterns and test utilities
29
-
30
- The search includes:
31
- - Source code files (.ts, .js, .tsx, .jsx, etc.)
32
- - Configuration files (.json, .yaml, .toml, etc.)
33
- - Documentation files (.md, .txt, etc.)
34
- - Build and deployment files
35
-
36
- **Best Practice**: Search the codebase BEFORE writing new code to avoid duplication and follow existing patterns.`,
37
- inputSchema: {
38
- query: z
39
- .string()
40
- .describe('Search query - use natural language, function names, or technical terms'),
41
- limit: z
42
- .number()
43
- .default(10)
44
- .optional()
45
- .describe('Maximum number of results to return (default: 10)'),
46
- include_content: z
47
- .boolean()
48
- .default(true)
49
- .optional()
50
- .describe('Include file content snippets in results (default: true)'),
51
- file_extensions: z
52
- .array(z.string())
53
- .optional()
54
- .describe('Filter by file extensions (e.g., [".ts", ".tsx", ".js"])'),
55
- path_filter: z
56
- .string()
57
- .optional()
58
- .describe('Filter by path pattern (e.g., "src/components", "tests", "docs")'),
59
- exclude_paths: z
60
- .array(z.string())
61
- .optional()
62
- .describe(
63
- 'Exclude paths containing these patterns (e.g., ["node_modules", ".git", "dist"])'
64
- ),
65
- },
66
- },
67
- async ({
68
- query,
69
- limit = 10,
70
- include_content = true,
71
- file_extensions,
72
- path_filter,
73
- exclude_paths,
74
- }) => {
75
- try {
76
- // Use UnifiedSearchService - same logic as CLI
77
- const searchService = getSearchService();
78
- await searchService.initialize();
79
-
80
- // Check codebase status
81
- const status = await searchService.getStatus();
82
-
83
- // If indexing in progress, show progress
84
- if (status.codebase.isIndexing) {
85
- const progressBar =
86
- '█'.repeat(Math.floor(status.codebase.progress / 5)) +
87
- '░'.repeat(20 - Math.floor(status.codebase.progress / 5));
88
- return {
89
- content: [
90
- {
91
- type: 'text',
92
- text: `⏳ **Codebase Indexing In Progress**\n\nThe codebase is currently being indexed. Please wait...\n\n**Progress:** ${status.codebase.progress}%\n\`${progressBar}\`\n\n**Status:**\n- Files indexed: ${status.codebase.progress > 0 ? Math.floor((status.codebase.fileCount * status.codebase.progress) / 100) : 0}/${status.codebase.fileCount}\n${status.codebase.currentFile ? `- Current file: \`${status.codebase.currentFile}\`` : ''}\n\n**Estimated time:** ${status.codebase.progress > 0 ? 'Less than 1 minute' : 'Starting...'}\n\n💡 **Tip:** Try your search again in a few seconds.`,
93
- },
94
- ],
95
- };
96
- }
97
-
98
- if (!status.codebase.indexed) {
99
- return {
100
- content: [
101
- {
102
- type: 'text',
103
- text: `📭 **Codebase Not Indexed**\n\nThe codebase has not been indexed yet.\n\n**To fix:**\n- Run: \`sylphx codebase reindex\` from the command line\n- This will create a search index for all source files\n\n**Why this is needed:**\nThe first time you use codebase search, you need to build an index of all files. This only needs to be done once (or when files change significantly).`,
104
- },
105
- ],
106
- };
107
- }
108
-
109
- // Perform search using unified service
110
- const result = await searchService.searchCodebase(query, {
111
- limit,
112
- include_content,
113
- file_extensions,
114
- path_filter,
115
- exclude_paths,
116
- });
117
-
118
- // Return MCP-formatted results
119
- return searchService.formatResultsForMCP(result.results, query, result.totalIndexed);
120
- } catch (error) {
121
- return {
122
- content: [
123
- {
124
- type: 'text',
125
- text: `✗ Codebase search error: ${(error as Error).message}`,
126
- },
127
- ],
128
- };
129
- }
130
- }
131
- );
132
- }
133
-
134
- /**
135
- * Register all codebase tools
136
- */
137
- export function registerCodebaseTools(server: McpServer): void {
138
- registerCodebaseSearchTool(server);
139
- }
@@ -1,10 +0,0 @@
1
- /**
2
- * Knowledge domain - Documentation and guides
3
- */
4
-
5
- export { getKnowledgeContent } from './resources.js';
6
- export {
7
- registerKnowledgeGetTool,
8
- registerKnowledgeSearchTool,
9
- registerKnowledgeTools,
10
- } from './tools.js';