@sylphx/flow 1.1.1 → 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.
- package/CHANGELOG.md +14 -0
- package/package.json +1 -1
- package/src/commands/hook-command.ts +10 -230
- package/src/composables/index.ts +0 -1
- package/src/config/servers.ts +35 -78
- package/src/core/interfaces.ts +0 -33
- package/src/domains/index.ts +0 -2
- package/src/index.ts +0 -4
- package/src/services/mcp-service.ts +0 -16
- package/src/targets/claude-code.ts +3 -9
- package/src/targets/functional/claude-code-logic.ts +4 -22
- package/src/targets/opencode.ts +0 -6
- package/src/types/mcp.types.ts +29 -38
- package/src/types/target.types.ts +0 -2
- package/src/types.ts +0 -1
- package/src/commands/codebase-command.ts +0 -168
- package/src/commands/knowledge-command.ts +0 -161
- package/src/composables/useTargetConfig.ts +0 -45
- package/src/core/formatting/bytes.test.ts +0 -115
- package/src/core/validation/limit.test.ts +0 -155
- package/src/core/validation/query.test.ts +0 -44
- package/src/domains/codebase/index.ts +0 -5
- package/src/domains/codebase/tools.ts +0 -139
- package/src/domains/knowledge/index.ts +0 -10
- package/src/domains/knowledge/resources.ts +0 -537
- package/src/domains/knowledge/tools.ts +0 -174
- package/src/services/search/base-indexer.ts +0 -156
- package/src/services/search/codebase-indexer-types.ts +0 -38
- package/src/services/search/codebase-indexer.ts +0 -647
- package/src/services/search/embeddings-provider.ts +0 -455
- package/src/services/search/embeddings.ts +0 -316
- package/src/services/search/functional-indexer.ts +0 -323
- package/src/services/search/index.ts +0 -27
- package/src/services/search/indexer.ts +0 -380
- package/src/services/search/knowledge-indexer.ts +0 -422
- package/src/services/search/semantic-search.ts +0 -244
- package/src/services/search/tfidf.ts +0 -559
- package/src/services/search/unified-search-service.ts +0 -888
- package/src/services/storage/cache-storage.ts +0 -487
- package/src/services/storage/drizzle-storage.ts +0 -581
- package/src/services/storage/index.ts +0 -15
- package/src/services/storage/lancedb-vector-storage.ts +0 -494
- package/src/services/storage/memory-storage.ts +0 -268
- package/src/services/storage/separated-storage.ts +0 -467
- package/src/services/storage/vector-storage.ts +0 -13
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# @sylphx/flow
|
|
2
2
|
|
|
3
|
+
## 1.2.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 2272596: Enhanced agent system prompts with Minimal Effective Prompt principles:
|
|
8
|
+
|
|
9
|
+
- **Workflow Standards**: Added continuous atomic commits, semver discipline (minor-first), TypeScript release workflow with changeset + CI, and proactive pre-commit cleanup
|
|
10
|
+
- **Research-First Mindset**: Enforced research before implementation to prevent outdated approaches
|
|
11
|
+
- **Silent Mode Fix**: Prevented agents from creating report files to compensate for not speaking
|
|
12
|
+
- **Proactive Cleanup**: Added mandatory pre-commit hygiene - refactor, remove unused code, delete outdated docs, fix tech debt
|
|
13
|
+
- **MEP Refactor**: Refactored all prompts (coder, orchestrator, reviewer, writer, core, code-standards, silent) using Minimal Effective Prompt principles - trust LLM, WHAT+WHEN not HOW+WHY, condition→action format, ~40% token reduction
|
|
14
|
+
|
|
15
|
+
Prime directive: Never accumulate misleading artifacts. Research is mandatory. Tests and benchmarks required (.test.ts, .bench.ts).
|
|
16
|
+
|
|
3
17
|
## 1.1.1
|
|
4
18
|
|
|
5
19
|
### Patch Changes
|
package/package.json
CHANGED
|
@@ -1,21 +1,17 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
* Hook command -
|
|
3
|
+
* Hook command - OS notification for Claude Code startup
|
|
4
4
|
*
|
|
5
|
-
* Purpose:
|
|
6
|
-
* instead of installing them as static files
|
|
5
|
+
* Purpose: Send OS-level notifications when Claude Code starts
|
|
7
6
|
*
|
|
8
7
|
* DESIGN RATIONALE:
|
|
9
|
-
* -
|
|
10
|
-
* -
|
|
11
|
-
* -
|
|
12
|
-
* - Consistent: Follows sysinfo command pattern
|
|
8
|
+
* - Simple notification: Just notify user when Claude Code is ready
|
|
9
|
+
* - Cross-platform: Supports macOS, Linux, and Windows
|
|
10
|
+
* - Non-intrusive: Fails silently if notification system not available
|
|
13
11
|
*/
|
|
14
12
|
|
|
15
13
|
import { exec } from 'node:child_process';
|
|
16
|
-
import fsSync from 'node:fs';
|
|
17
14
|
import os from 'node:os';
|
|
18
|
-
import path from 'node:path';
|
|
19
15
|
import { promisify } from 'node:util';
|
|
20
16
|
import { Command } from 'commander';
|
|
21
17
|
import { cli } from '../utils/cli-output.js';
|
|
@@ -25,7 +21,7 @@ const execAsync = promisify(exec);
|
|
|
25
21
|
/**
|
|
26
22
|
* Hook types supported
|
|
27
23
|
*/
|
|
28
|
-
type HookType = '
|
|
24
|
+
type HookType = 'notification';
|
|
29
25
|
|
|
30
26
|
/**
|
|
31
27
|
* Target platforms supported
|
|
@@ -37,7 +33,7 @@ type TargetPlatform = 'claude-code';
|
|
|
37
33
|
*/
|
|
38
34
|
export const hookCommand = new Command('hook')
|
|
39
35
|
.description('Load dynamic system information for Claude Code hooks')
|
|
40
|
-
.requiredOption('--type <type>', 'Hook type (
|
|
36
|
+
.requiredOption('--type <type>', 'Hook type (notification)')
|
|
41
37
|
.option('--target <target>', 'Target platform (claude-code)', 'claude-code')
|
|
42
38
|
.option('--verbose', 'Show verbose output', false)
|
|
43
39
|
.action(async (options) => {
|
|
@@ -46,10 +42,8 @@ export const hookCommand = new Command('hook')
|
|
|
46
42
|
const target = options.target as TargetPlatform;
|
|
47
43
|
|
|
48
44
|
// Validate hook type
|
|
49
|
-
if (
|
|
50
|
-
throw new Error(
|
|
51
|
-
`Invalid hook type: ${hookType}. Must be 'session', 'message', or 'notification'`
|
|
52
|
-
);
|
|
45
|
+
if (hookType !== 'notification') {
|
|
46
|
+
throw new Error(`Invalid hook type: ${hookType}. Must be 'notification'`);
|
|
53
47
|
}
|
|
54
48
|
|
|
55
49
|
// Validate target
|
|
@@ -83,17 +77,9 @@ export const hookCommand = new Command('hook')
|
|
|
83
77
|
*/
|
|
84
78
|
async function loadHookContent(
|
|
85
79
|
hookType: HookType,
|
|
86
|
-
|
|
80
|
+
_target: TargetPlatform,
|
|
87
81
|
verbose: boolean = false
|
|
88
82
|
): Promise<string> {
|
|
89
|
-
if (hookType === 'session') {
|
|
90
|
-
return await loadSessionContent(target, verbose);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
if (hookType === 'message') {
|
|
94
|
-
return await loadMessageContent(target, verbose);
|
|
95
|
-
}
|
|
96
|
-
|
|
97
83
|
if (hookType === 'notification') {
|
|
98
84
|
return await sendNotification(verbose);
|
|
99
85
|
}
|
|
@@ -101,212 +87,6 @@ async function loadHookContent(
|
|
|
101
87
|
return '';
|
|
102
88
|
}
|
|
103
89
|
|
|
104
|
-
/**
|
|
105
|
-
* Load content for session start hook
|
|
106
|
-
* Includes: system info only (rules and output styles are static files)
|
|
107
|
-
*/
|
|
108
|
-
async function loadSessionContent(_target: TargetPlatform, verbose: boolean): Promise<string> {
|
|
109
|
-
// Load system info for session
|
|
110
|
-
if (verbose) {
|
|
111
|
-
cli.info('Loading system info...');
|
|
112
|
-
}
|
|
113
|
-
return await getSystemInfo('session');
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
/**
|
|
117
|
-
* Load content for message hook
|
|
118
|
-
* Includes: system status
|
|
119
|
-
*/
|
|
120
|
-
async function loadMessageContent(_target: TargetPlatform, verbose: boolean): Promise<string> {
|
|
121
|
-
if (verbose) {
|
|
122
|
-
cli.info('Loading system status...');
|
|
123
|
-
}
|
|
124
|
-
return await getSystemInfo('message');
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
/**
|
|
128
|
-
* Get system information
|
|
129
|
-
*/
|
|
130
|
-
async function getSystemInfo(hookType: 'session' | 'message'): Promise<string> {
|
|
131
|
-
const currentTime = new Date().toISOString();
|
|
132
|
-
const tempDir = os.tmpdir();
|
|
133
|
-
|
|
134
|
-
// Get memory information
|
|
135
|
-
const totalMem = os.totalmem();
|
|
136
|
-
const freeMem = os.freemem();
|
|
137
|
-
const usedMem = totalMem - freeMem;
|
|
138
|
-
const memoryUsage = ((usedMem / totalMem) * 100).toFixed(1);
|
|
139
|
-
|
|
140
|
-
// Get CPU information
|
|
141
|
-
const cpus = os.cpus();
|
|
142
|
-
const cpuCores = cpus.length;
|
|
143
|
-
|
|
144
|
-
// Get CPU usage (using load average for fast detection)
|
|
145
|
-
const loadAvg = os.loadavg();
|
|
146
|
-
const cpuUsagePercent = Math.round((loadAvg[0] / cpuCores) * 100);
|
|
147
|
-
|
|
148
|
-
// Get platform information
|
|
149
|
-
const platform = os.platform();
|
|
150
|
-
const arch = os.arch();
|
|
151
|
-
|
|
152
|
-
if (hookType === 'session') {
|
|
153
|
-
// Session info includes project information
|
|
154
|
-
const projectInfo = await detectProjectInfo();
|
|
155
|
-
|
|
156
|
-
return `## Session Information
|
|
157
|
-
|
|
158
|
-
**Platform:** ${platform} (${arch})
|
|
159
|
-
**Working Directory:** ${process.cwd()}
|
|
160
|
-
**Temp Directory:** ${tempDir}
|
|
161
|
-
**CPU:** ${cpuCores} cores
|
|
162
|
-
**Total Memory:** ${formatBytes(totalMem)}
|
|
163
|
-
|
|
164
|
-
## Project Information
|
|
165
|
-
|
|
166
|
-
**Project Type:** ${projectInfo.type}
|
|
167
|
-
**Package Manager:** ${projectInfo.packageManager}${
|
|
168
|
-
projectInfo.name && projectInfo.name !== 'unnamed'
|
|
169
|
-
? `\n**Project:** ${projectInfo.name} (${projectInfo.version})`
|
|
170
|
-
: ''
|
|
171
|
-
}`;
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
// Message info - just current status
|
|
175
|
-
return `## System Status
|
|
176
|
-
|
|
177
|
-
**Current Time:** ${new Date(currentTime).toLocaleString()}
|
|
178
|
-
**CPU:** ${cpuUsagePercent}%
|
|
179
|
-
**Memory:** ${memoryUsage}% used (${formatBytes(freeMem)} free)`;
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
/**
|
|
183
|
-
* Detect project information
|
|
184
|
-
*/
|
|
185
|
-
async function detectProjectInfo() {
|
|
186
|
-
const cwd = process.cwd();
|
|
187
|
-
const packageJsonPath = path.join(cwd, 'package.json');
|
|
188
|
-
|
|
189
|
-
// Check if package.json exists
|
|
190
|
-
if (!fsSync.existsSync(packageJsonPath)) {
|
|
191
|
-
return {
|
|
192
|
-
type: 'unknown',
|
|
193
|
-
packageManager: 'none',
|
|
194
|
-
description: 'No package.json found',
|
|
195
|
-
};
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
try {
|
|
199
|
-
// Read package.json
|
|
200
|
-
const packageJson = JSON.parse(fsSync.readFileSync(packageJsonPath, 'utf8'));
|
|
201
|
-
|
|
202
|
-
// Detect project type based on dependencies and scripts
|
|
203
|
-
const projectType = detectProjectType(packageJson);
|
|
204
|
-
|
|
205
|
-
// Detect package manager based on package.json field, then lock files
|
|
206
|
-
const packageManager = detectPackageManager(cwd, packageJson);
|
|
207
|
-
|
|
208
|
-
return {
|
|
209
|
-
type: projectType,
|
|
210
|
-
packageManager: packageManager,
|
|
211
|
-
name: packageJson.name || 'unnamed',
|
|
212
|
-
version: packageJson.version || '0.0.0',
|
|
213
|
-
description: packageJson.description || '',
|
|
214
|
-
};
|
|
215
|
-
} catch (_error) {
|
|
216
|
-
return {
|
|
217
|
-
type: 'js/ts',
|
|
218
|
-
packageManager: 'unknown',
|
|
219
|
-
description: 'Invalid package.json',
|
|
220
|
-
};
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
/**
|
|
225
|
-
* Detect project type from package.json
|
|
226
|
-
*/
|
|
227
|
-
function detectProjectType(packageJson: Record<string, unknown>): string {
|
|
228
|
-
// Check for TypeScript
|
|
229
|
-
const hasTypescript =
|
|
230
|
-
packageJson.devDependencies?.typescript ||
|
|
231
|
-
packageJson.dependencies?.typescript ||
|
|
232
|
-
packageJson.devDependencies?.['@types/node'] ||
|
|
233
|
-
packageJson.scripts?.build?.includes('tsc') ||
|
|
234
|
-
packageJson.scripts?.dev?.includes('ts-node');
|
|
235
|
-
|
|
236
|
-
if (hasTypescript) {
|
|
237
|
-
return 'typescript';
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
// Check for React
|
|
241
|
-
const hasReact =
|
|
242
|
-
packageJson.dependencies?.react ||
|
|
243
|
-
packageJson.devDependencies?.react ||
|
|
244
|
-
packageJson.scripts?.dev?.includes('vite') ||
|
|
245
|
-
packageJson.scripts?.build?.includes('vite');
|
|
246
|
-
|
|
247
|
-
if (hasReact) {
|
|
248
|
-
return 'react';
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
// Check for Next.js
|
|
252
|
-
const hasNext =
|
|
253
|
-
packageJson.dependencies?.next ||
|
|
254
|
-
packageJson.devDependencies?.next ||
|
|
255
|
-
packageJson.scripts?.dev === 'next dev' ||
|
|
256
|
-
packageJson.scripts?.build === 'next build';
|
|
257
|
-
|
|
258
|
-
if (hasNext) {
|
|
259
|
-
return 'next.js';
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
// Default to JavaScript
|
|
263
|
-
return 'javascript';
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
/**
|
|
267
|
-
* Detect package manager from lock files
|
|
268
|
-
*/
|
|
269
|
-
function detectPackageManager(cwd: string, packageJson?: any): string {
|
|
270
|
-
// First, check package.json for explicit packageManager field (most accurate)
|
|
271
|
-
if (packageJson?.packageManager) {
|
|
272
|
-
const packageManagerField = packageJson.packageManager;
|
|
273
|
-
// Extract manager name from "bun@1.3.1" format
|
|
274
|
-
const managerName = packageManagerField.split('@')[0];
|
|
275
|
-
if (['npm', 'yarn', 'pnpm', 'bun'].includes(managerName)) {
|
|
276
|
-
return managerName;
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
// Fallback: Check for lock files in order of preference
|
|
281
|
-
const lockFiles = [
|
|
282
|
-
{ file: 'pnpm-lock.yaml', manager: 'pnpm' },
|
|
283
|
-
{ file: 'yarn.lock', manager: 'yarn' },
|
|
284
|
-
{ file: 'package-lock.json', manager: 'npm' },
|
|
285
|
-
{ file: 'bun.lockb', manager: 'bun' },
|
|
286
|
-
];
|
|
287
|
-
|
|
288
|
-
for (const { file, manager } of lockFiles) {
|
|
289
|
-
if (fsSync.existsSync(path.join(cwd, file))) {
|
|
290
|
-
return manager;
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
return 'npm'; // Default to npm
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
/**
|
|
298
|
-
* Format bytes to human-readable string
|
|
299
|
-
*/
|
|
300
|
-
function formatBytes(bytes: number): string {
|
|
301
|
-
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
|
|
302
|
-
if (bytes === 0) {
|
|
303
|
-
return '0 Bytes';
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
const i = Math.floor(Math.log(bytes) / Math.log(1024));
|
|
307
|
-
return `${Math.round((bytes / 1024 ** i) * 100) / 100} ${sizes[i]}`;
|
|
308
|
-
}
|
|
309
|
-
|
|
310
90
|
/**
|
|
311
91
|
* Send OS-level notification
|
|
312
92
|
*/
|
package/src/composables/index.ts
CHANGED
package/src/config/servers.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import type { MCPServerConfigUnion } from '../types.js';
|
|
2
|
-
import { envSecurity, securitySchemas } from '../utils/security.js';
|
|
3
2
|
|
|
4
3
|
/**
|
|
5
4
|
* Central MCP server registry for Sylphx Flow
|
|
@@ -44,83 +43,6 @@ export interface MCPServerDefinition {
|
|
|
44
43
|
* This replaces all hardcoded server lists throughout the codebase
|
|
45
44
|
*/
|
|
46
45
|
export const MCP_SERVER_REGISTRY: Record<string, MCPServerDefinition> = {
|
|
47
|
-
'sylphx-flow': {
|
|
48
|
-
id: 'sylphx-flow',
|
|
49
|
-
name: 'sylphx-flow',
|
|
50
|
-
description: 'Sylphx Flow MCP server for agent coordination and memory management',
|
|
51
|
-
config: {
|
|
52
|
-
type: 'stdio' as const,
|
|
53
|
-
command: 'sylphx-flow',
|
|
54
|
-
args: ['mcp', 'start'],
|
|
55
|
-
env: {
|
|
56
|
-
OPENAI_API_KEY: '',
|
|
57
|
-
OPENAI_BASE_URL: 'https://api.openai.com/v1',
|
|
58
|
-
EMBEDDING_MODEL: 'text-embedding-3-small',
|
|
59
|
-
},
|
|
60
|
-
},
|
|
61
|
-
envVars: {
|
|
62
|
-
OPENAI_API_KEY: {
|
|
63
|
-
description: 'OpenAI API key for vector search embeddings',
|
|
64
|
-
required: false,
|
|
65
|
-
secret: true,
|
|
66
|
-
},
|
|
67
|
-
OPENAI_BASE_URL: {
|
|
68
|
-
description: 'Base URL for OpenAI-compatible embedding API',
|
|
69
|
-
required: false,
|
|
70
|
-
default: 'https://api.openai.com/v1',
|
|
71
|
-
},
|
|
72
|
-
EMBEDDING_MODEL: {
|
|
73
|
-
description: 'Embedding model to use for vector search',
|
|
74
|
-
required: false,
|
|
75
|
-
default: 'text-embedding-3-small',
|
|
76
|
-
dependsOn: ['OPENAI_API_KEY', 'OPENAI_BASE_URL'],
|
|
77
|
-
fetchChoices: async () => {
|
|
78
|
-
// Validate environment variables
|
|
79
|
-
const validatedBaseUrl = envSecurity.getEnvVar(
|
|
80
|
-
'OPENAI_BASE_URL',
|
|
81
|
-
'https://api.openai.com/v1'
|
|
82
|
-
);
|
|
83
|
-
const validatedApiKey = envSecurity.getEnvVar('OPENAI_API_KEY');
|
|
84
|
-
|
|
85
|
-
if (!validatedApiKey) {
|
|
86
|
-
throw new Error('OPENAI_API_KEY is required to fetch embedding models');
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
// Additional validation for API key format
|
|
90
|
-
try {
|
|
91
|
-
securitySchemas.apiKey.parse(validatedApiKey);
|
|
92
|
-
} catch (_error) {
|
|
93
|
-
throw new Error('Invalid OPENAI_API_KEY format');
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
const response = await fetch(`${validatedBaseUrl}/models`, {
|
|
97
|
-
headers: { Authorization: `Bearer ${validatedApiKey}` },
|
|
98
|
-
timeout: 10000, // Add timeout to prevent hanging
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
if (!response.ok) {
|
|
102
|
-
throw new Error(`Failed to fetch models: ${response.statusText}`);
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
const data = await response.json();
|
|
106
|
-
const embeddingModels = data.data
|
|
107
|
-
.filter((m: { id: string }) => m.id.includes('embedding'))
|
|
108
|
-
.map((m: { id: string }) => m.id)
|
|
109
|
-
.sort();
|
|
110
|
-
|
|
111
|
-
if (embeddingModels.length === 0) {
|
|
112
|
-
throw new Error('No embedding models found');
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
return embeddingModels;
|
|
116
|
-
},
|
|
117
|
-
},
|
|
118
|
-
},
|
|
119
|
-
category: 'core',
|
|
120
|
-
defaultInInit: true,
|
|
121
|
-
required: true,
|
|
122
|
-
},
|
|
123
|
-
|
|
124
46
|
'gpt-image': {
|
|
125
47
|
id: 'gpt-image',
|
|
126
48
|
name: 'gpt-image-1-mcp',
|
|
@@ -219,6 +141,41 @@ export const MCP_SERVER_REGISTRY: Record<string, MCPServerDefinition> = {
|
|
|
219
141
|
category: 'external',
|
|
220
142
|
defaultInInit: true,
|
|
221
143
|
},
|
|
144
|
+
|
|
145
|
+
coderag: {
|
|
146
|
+
id: 'coderag',
|
|
147
|
+
name: 'coderag',
|
|
148
|
+
description: 'CodeRAG - Lightning-fast hybrid code search (TF-IDF + Vector) for RAG',
|
|
149
|
+
config: {
|
|
150
|
+
type: 'stdio' as const,
|
|
151
|
+
command: 'npx',
|
|
152
|
+
args: ['-y', '@sylphx/coderag-mcp'],
|
|
153
|
+
env: {
|
|
154
|
+
OPENAI_API_KEY: '',
|
|
155
|
+
CODEBASE_ROOT: '',
|
|
156
|
+
INDEX_PATH: '.coderag',
|
|
157
|
+
},
|
|
158
|
+
},
|
|
159
|
+
envVars: {
|
|
160
|
+
OPENAI_API_KEY: {
|
|
161
|
+
description: 'OpenAI API key for embeddings (vector search)',
|
|
162
|
+
required: false,
|
|
163
|
+
secret: true,
|
|
164
|
+
},
|
|
165
|
+
CODEBASE_ROOT: {
|
|
166
|
+
description: 'Root directory of codebase to index',
|
|
167
|
+
required: false,
|
|
168
|
+
default: '.',
|
|
169
|
+
},
|
|
170
|
+
INDEX_PATH: {
|
|
171
|
+
description: 'Path to store index files',
|
|
172
|
+
required: false,
|
|
173
|
+
default: '.coderag',
|
|
174
|
+
},
|
|
175
|
+
},
|
|
176
|
+
category: 'core',
|
|
177
|
+
defaultInInit: true,
|
|
178
|
+
},
|
|
222
179
|
};
|
|
223
180
|
|
|
224
181
|
/**
|
package/src/core/interfaces.ts
CHANGED
|
@@ -46,39 +46,6 @@ export interface IStorage<T = unknown> {
|
|
|
46
46
|
healthCheck(): Promise<{ healthy: boolean; error?: string }>;
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
-
// Search service interface
|
|
50
|
-
export interface ISearchService {
|
|
51
|
-
initialize(): Promise<void>;
|
|
52
|
-
searchCodebase(query: string, options?: SearchOptions): Promise<SearchResult[]>;
|
|
53
|
-
searchKnowledge(query: string, options?: SearchOptions): Promise<SearchResult[]>;
|
|
54
|
-
getStatus(): Promise<SearchServiceStatus>;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
// Search options
|
|
58
|
-
export interface SearchOptions {
|
|
59
|
-
limit?: number;
|
|
60
|
-
offset?: number;
|
|
61
|
-
filters?: Record<string, unknown>;
|
|
62
|
-
sortBy?: string;
|
|
63
|
-
sortOrder?: 'asc' | 'desc';
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
// Search result
|
|
67
|
-
export interface SearchResult {
|
|
68
|
-
id: string;
|
|
69
|
-
content: string;
|
|
70
|
-
score: number;
|
|
71
|
-
metadata: Record<string, unknown>;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
// Search service status
|
|
75
|
-
export interface SearchServiceStatus {
|
|
76
|
-
indexed: number;
|
|
77
|
-
total: number;
|
|
78
|
-
lastIndexed: string;
|
|
79
|
-
healthy: boolean;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
49
|
// Target manager interface
|
|
83
50
|
export interface ITargetManager {
|
|
84
51
|
getTarget(id: string): Target | null;
|
package/src/domains/index.ts
CHANGED
package/src/index.ts
CHANGED
|
@@ -8,9 +8,7 @@ import { readFileSync } from 'node:fs';
|
|
|
8
8
|
import { dirname, join } from 'node:path';
|
|
9
9
|
import { fileURLToPath } from 'node:url';
|
|
10
10
|
import { Command } from 'commander';
|
|
11
|
-
import { codebaseCommand } from './commands/codebase-command.js';
|
|
12
11
|
import { hookCommand } from './commands/hook-command.js';
|
|
13
|
-
import { knowledgeCommand } from './commands/knowledge-command.js';
|
|
14
12
|
import {
|
|
15
13
|
flowCommand,
|
|
16
14
|
statusCommand,
|
|
@@ -95,8 +93,6 @@ export function createCLI(): Command {
|
|
|
95
93
|
program.addCommand(statusCommand);
|
|
96
94
|
program.addCommand(doctorCommand);
|
|
97
95
|
program.addCommand(upgradeCommand);
|
|
98
|
-
program.addCommand(codebaseCommand);
|
|
99
|
-
program.addCommand(knowledgeCommand);
|
|
100
96
|
program.addCommand(hookCommand);
|
|
101
97
|
|
|
102
98
|
return program;
|
|
@@ -293,22 +293,6 @@ export const createMCPService = (deps: MCPServiceDeps): MCPService => {
|
|
|
293
293
|
? await resolveConfig(server.config.command)
|
|
294
294
|
: undefined;
|
|
295
295
|
resolvedArgs = server.config.args ? await resolveConfig(server.config.args) : [];
|
|
296
|
-
|
|
297
|
-
// Apply target-specific flags for sylphx-flow server
|
|
298
|
-
if (serverId === 'sylphx-flow' && Array.isArray(resolvedArgs)) {
|
|
299
|
-
const targetConfig = deps.target.mcpServerConfig;
|
|
300
|
-
if (targetConfig) {
|
|
301
|
-
if (targetConfig.disableTime) {
|
|
302
|
-
resolvedArgs.push('--disable-time');
|
|
303
|
-
}
|
|
304
|
-
if (targetConfig.disableKnowledge) {
|
|
305
|
-
resolvedArgs.push('--disable-knowledge');
|
|
306
|
-
}
|
|
307
|
-
if (targetConfig.disableCodebase) {
|
|
308
|
-
resolvedArgs.push('--disable-codebase');
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
296
|
}
|
|
313
297
|
|
|
314
298
|
// Update the config with resolved values (only for CLI servers)
|
|
@@ -22,12 +22,6 @@ export const claudeCodeTarget: Target = {
|
|
|
22
22
|
isImplemented: true,
|
|
23
23
|
isDefault: false,
|
|
24
24
|
|
|
25
|
-
mcpServerConfig: {
|
|
26
|
-
disableTime: true,
|
|
27
|
-
disableKnowledge: false,
|
|
28
|
-
disableCodebase: true,
|
|
29
|
-
},
|
|
30
|
-
|
|
31
25
|
config: {
|
|
32
26
|
agentDir: '.claude/agents',
|
|
33
27
|
agentExtension: '.md',
|
|
@@ -424,10 +418,10 @@ Please begin your response with a comprehensive summary of all the instructions
|
|
|
424
418
|
throw new Error(`Failed to write settings: ${writeResult.error.message}`);
|
|
425
419
|
}
|
|
426
420
|
|
|
427
|
-
// Return
|
|
421
|
+
// Return 1 hook configured (Notification only)
|
|
428
422
|
return {
|
|
429
|
-
count:
|
|
430
|
-
message: 'Configured
|
|
423
|
+
count: 1,
|
|
424
|
+
message: 'Configured notification hook',
|
|
431
425
|
};
|
|
432
426
|
},
|
|
433
427
|
|
|
@@ -31,7 +31,6 @@ export interface ClaudeCodeSettings {
|
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
export interface HookConfig {
|
|
34
|
-
sessionCommand?: string;
|
|
35
34
|
notificationCommand?: string;
|
|
36
35
|
}
|
|
37
36
|
|
|
@@ -41,17 +40,15 @@ export interface HookConfig {
|
|
|
41
40
|
*/
|
|
42
41
|
export const generateHookCommands = async (targetId: string): Promise<HookConfig> => {
|
|
43
42
|
return {
|
|
44
|
-
sessionCommand: `sylphx-flow hook --type session --target ${targetId}`,
|
|
45
43
|
notificationCommand: `sylphx-flow hook --type notification --target ${targetId}`,
|
|
46
44
|
};
|
|
47
45
|
};
|
|
48
46
|
|
|
49
47
|
/**
|
|
50
48
|
* Default hook commands (fallback)
|
|
51
|
-
* Simplified to only include
|
|
49
|
+
* Simplified to only include notification hook
|
|
52
50
|
*/
|
|
53
51
|
export const DEFAULT_HOOKS: HookConfig = {
|
|
54
|
-
sessionCommand: 'sylphx-flow hook --type session --target claude-code',
|
|
55
52
|
notificationCommand: 'sylphx-flow hook --type notification --target claude-code',
|
|
56
53
|
};
|
|
57
54
|
|
|
@@ -74,20 +71,9 @@ export const parseSettings = (content: string): Result<ClaudeCodeSettings, Confi
|
|
|
74
71
|
export const buildHookConfiguration = (
|
|
75
72
|
config: HookConfig = DEFAULT_HOOKS
|
|
76
73
|
): ClaudeCodeSettings['hooks'] => {
|
|
77
|
-
const sessionCommand = config.sessionCommand || DEFAULT_HOOKS.sessionCommand!;
|
|
78
74
|
const notificationCommand = config.notificationCommand || DEFAULT_HOOKS.notificationCommand!;
|
|
79
75
|
|
|
80
76
|
return {
|
|
81
|
-
SessionStart: [
|
|
82
|
-
{
|
|
83
|
-
hooks: [
|
|
84
|
-
{
|
|
85
|
-
type: 'command',
|
|
86
|
-
command: sessionCommand,
|
|
87
|
-
},
|
|
88
|
-
],
|
|
89
|
-
},
|
|
90
|
-
],
|
|
91
77
|
Notification: [
|
|
92
78
|
{
|
|
93
79
|
matcher: '',
|
|
@@ -140,7 +126,7 @@ export const serializeSettings = (settings: ClaudeCodeSettings): string => {
|
|
|
140
126
|
* Get success message (pure)
|
|
141
127
|
*/
|
|
142
128
|
export const getSuccessMessage = (): string => {
|
|
143
|
-
return 'Claude Code
|
|
129
|
+
return 'Claude Code hook configured: Notification';
|
|
144
130
|
};
|
|
145
131
|
|
|
146
132
|
/**
|
|
@@ -173,12 +159,8 @@ export const processSettings = (
|
|
|
173
159
|
* Validate hook configuration (pure)
|
|
174
160
|
*/
|
|
175
161
|
export const validateHookConfig = (config: HookConfig): Result<HookConfig, ConfigError> => {
|
|
176
|
-
if (config.
|
|
177
|
-
return failure(configError('
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
if (config.messageCommand !== undefined && config.messageCommand.trim() === '') {
|
|
181
|
-
return failure(configError('Message command cannot be empty'));
|
|
162
|
+
if (config.notificationCommand !== undefined && config.notificationCommand.trim() === '') {
|
|
163
|
+
return failure(configError('Notification command cannot be empty'));
|
|
182
164
|
}
|
|
183
165
|
|
|
184
166
|
return success(config);
|
package/src/targets/opencode.ts
CHANGED
|
@@ -23,12 +23,6 @@ export const opencodeTarget: Target = {
|
|
|
23
23
|
isImplemented: true,
|
|
24
24
|
isDefault: true,
|
|
25
25
|
|
|
26
|
-
mcpServerConfig: {
|
|
27
|
-
disableTime: false,
|
|
28
|
-
disableKnowledge: false,
|
|
29
|
-
disableCodebase: false,
|
|
30
|
-
},
|
|
31
|
-
|
|
32
26
|
config: {
|
|
33
27
|
agentDir: '.opencode/agent',
|
|
34
28
|
agentExtension: '.md',
|