viberag 0.3.2 → 0.4.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/README.md +2 -2
- package/dist/cli/app.d.ts +3 -0
- package/dist/cli/app.js +100 -102
- package/dist/cli/commands/handlers.d.ts +8 -6
- package/dist/cli/commands/handlers.js +90 -32
- package/dist/cli/commands/useCommands.d.ts +20 -0
- package/dist/cli/commands/useCommands.js +189 -0
- package/dist/cli/commands/useRagCommands.d.ts +2 -5
- package/dist/cli/commands/useRagCommands.js +11 -18
- package/dist/cli/components/InitWizard.js +66 -27
- package/dist/cli/components/McpSetupWizard.js +23 -4
- package/dist/cli/components/SlotRow.d.ts +22 -0
- package/dist/cli/components/SlotRow.js +55 -0
- package/dist/cli/components/StatusBar.d.ts +14 -0
- package/dist/cli/components/StatusBar.js +156 -0
- package/dist/cli/contexts/DaemonStatusContext.d.ts +38 -0
- package/dist/cli/contexts/DaemonStatusContext.js +106 -0
- package/dist/cli/hooks/useStatusPolling.d.ts +34 -0
- package/dist/cli/hooks/useStatusPolling.js +121 -0
- package/dist/cli/store/app/selectors.d.ts +87 -0
- package/dist/cli/store/app/selectors.js +28 -0
- package/dist/cli/store/app/slice.d.ts +1013 -0
- package/dist/cli/store/app/slice.js +112 -0
- package/dist/cli/store/hooks.d.ts +22 -0
- package/dist/cli/store/hooks.js +17 -0
- package/dist/cli/store/store.d.ts +17 -0
- package/dist/cli/store/store.js +18 -0
- package/dist/cli/store/wizard/selectors.d.ts +115 -0
- package/dist/cli/store/wizard/selectors.js +36 -0
- package/dist/cli/store/wizard/slice.d.ts +523 -0
- package/dist/cli/store/wizard/slice.js +119 -0
- package/dist/cli/utils/error-handler.d.ts +55 -0
- package/dist/cli/utils/error-handler.js +92 -0
- package/dist/client/auto-start.d.ts +42 -0
- package/dist/client/auto-start.js +250 -0
- package/dist/client/connection.d.ts +48 -0
- package/dist/client/connection.js +200 -0
- package/dist/client/index.d.ts +93 -0
- package/dist/client/index.js +209 -0
- package/dist/client/types.d.ts +105 -0
- package/dist/client/types.js +7 -0
- package/dist/common/components/SlotRow.d.ts +22 -0
- package/dist/common/components/SlotRow.js +53 -0
- package/dist/common/components/StatusBar.js +82 -31
- package/dist/common/types.d.ts +12 -13
- package/dist/daemon/handlers.d.ts +15 -0
- package/dist/daemon/handlers.js +157 -0
- package/dist/daemon/index.d.ts +21 -0
- package/dist/daemon/index.js +123 -0
- package/dist/daemon/lib/chunker/bounded-channel.d.ts +51 -0
- package/dist/daemon/lib/chunker/bounded-channel.js +138 -0
- package/dist/daemon/lib/chunker/index.d.ts +135 -0
- package/dist/daemon/lib/chunker/index.js +1370 -0
- package/dist/daemon/lib/chunker/types.d.ts +77 -0
- package/dist/daemon/lib/chunker/types.js +50 -0
- package/dist/daemon/lib/config.d.ts +73 -0
- package/dist/daemon/lib/config.js +149 -0
- package/dist/daemon/lib/constants.d.ts +75 -0
- package/dist/daemon/lib/constants.js +114 -0
- package/dist/daemon/lib/gitignore.d.ts +57 -0
- package/dist/daemon/lib/gitignore.js +246 -0
- package/dist/daemon/lib/logger.d.ts +51 -0
- package/dist/daemon/lib/logger.js +167 -0
- package/dist/daemon/lib/manifest.d.ts +58 -0
- package/dist/daemon/lib/manifest.js +116 -0
- package/dist/daemon/lib/merkle/diff.d.ts +32 -0
- package/dist/daemon/lib/merkle/diff.js +107 -0
- package/dist/daemon/lib/merkle/hash.d.ts +40 -0
- package/dist/daemon/lib/merkle/hash.js +180 -0
- package/dist/daemon/lib/merkle/index.d.ts +71 -0
- package/dist/daemon/lib/merkle/index.js +309 -0
- package/dist/daemon/lib/merkle/node.d.ts +55 -0
- package/dist/daemon/lib/merkle/node.js +82 -0
- package/dist/daemon/lifecycle.d.ts +50 -0
- package/dist/daemon/lifecycle.js +142 -0
- package/dist/daemon/owner.d.ts +175 -0
- package/dist/daemon/owner.js +609 -0
- package/dist/daemon/protocol.d.ts +100 -0
- package/dist/daemon/protocol.js +163 -0
- package/dist/daemon/providers/api-utils.d.ts +130 -0
- package/dist/daemon/providers/api-utils.js +248 -0
- package/dist/daemon/providers/gemini.d.ts +39 -0
- package/dist/daemon/providers/gemini.js +205 -0
- package/dist/daemon/providers/index.d.ts +14 -0
- package/dist/daemon/providers/index.js +14 -0
- package/dist/daemon/providers/local-4b.d.ts +28 -0
- package/dist/daemon/providers/local-4b.js +51 -0
- package/dist/daemon/providers/local.d.ts +36 -0
- package/dist/daemon/providers/local.js +166 -0
- package/dist/daemon/providers/mistral.d.ts +35 -0
- package/dist/daemon/providers/mistral.js +160 -0
- package/dist/daemon/providers/mock.d.ts +35 -0
- package/dist/daemon/providers/mock.js +69 -0
- package/dist/daemon/providers/openai.d.ts +41 -0
- package/dist/daemon/providers/openai.js +190 -0
- package/dist/daemon/providers/types.d.ts +68 -0
- package/dist/daemon/providers/types.js +6 -0
- package/dist/daemon/providers/validate.d.ts +30 -0
- package/dist/daemon/providers/validate.js +162 -0
- package/dist/daemon/server.d.ts +79 -0
- package/dist/daemon/server.js +293 -0
- package/dist/daemon/services/index.d.ts +11 -0
- package/dist/daemon/services/index.js +16 -0
- package/dist/daemon/services/indexing.d.ts +117 -0
- package/dist/daemon/services/indexing.js +573 -0
- package/dist/daemon/services/search/filters.d.ts +21 -0
- package/dist/daemon/services/search/filters.js +106 -0
- package/dist/daemon/services/search/fts.d.ts +32 -0
- package/dist/daemon/services/search/fts.js +61 -0
- package/dist/daemon/services/search/hybrid.d.ts +17 -0
- package/dist/daemon/services/search/hybrid.js +58 -0
- package/dist/daemon/services/search/index.d.ts +108 -0
- package/dist/daemon/services/search/index.js +417 -0
- package/dist/daemon/services/search/types.d.ts +126 -0
- package/dist/daemon/services/search/types.js +4 -0
- package/dist/daemon/services/search/vector.d.ts +25 -0
- package/dist/daemon/services/search/vector.js +44 -0
- package/dist/daemon/services/storage/index.d.ts +110 -0
- package/dist/daemon/services/storage/index.js +378 -0
- package/dist/daemon/services/storage/schema.d.ts +24 -0
- package/dist/daemon/services/storage/schema.js +51 -0
- package/dist/daemon/services/storage/types.d.ts +105 -0
- package/dist/daemon/services/storage/types.js +71 -0
- package/dist/daemon/services/types.d.ts +192 -0
- package/dist/daemon/services/types.js +53 -0
- package/dist/daemon/services/watcher.d.ts +98 -0
- package/dist/daemon/services/watcher.js +386 -0
- package/dist/daemon/state.d.ts +119 -0
- package/dist/daemon/state.js +161 -0
- package/dist/mcp/index.d.ts +1 -1
- package/dist/mcp/index.js +44 -60
- package/dist/mcp/server.d.ts +10 -14
- package/dist/mcp/server.js +75 -74
- package/dist/mcp/services/lazy-loader.d.ts +23 -0
- package/dist/mcp/services/lazy-loader.js +34 -0
- package/dist/mcp/warmup.d.ts +3 -3
- package/dist/mcp/warmup.js +39 -40
- package/dist/mcp/watcher.d.ts +5 -7
- package/dist/mcp/watcher.js +73 -64
- package/dist/rag/config/index.d.ts +2 -0
- package/dist/rag/constants.d.ts +30 -0
- package/dist/rag/constants.js +38 -0
- package/dist/rag/embeddings/api-utils.d.ts +121 -0
- package/dist/rag/embeddings/api-utils.js +259 -0
- package/dist/rag/embeddings/gemini.d.ts +4 -12
- package/dist/rag/embeddings/gemini.js +22 -72
- package/dist/rag/embeddings/index.d.ts +5 -3
- package/dist/rag/embeddings/index.js +5 -2
- package/dist/rag/embeddings/local-4b.d.ts +2 -2
- package/dist/rag/embeddings/local-4b.js +1 -1
- package/dist/rag/embeddings/local.d.ts +10 -3
- package/dist/rag/embeddings/local.js +58 -12
- package/dist/rag/embeddings/mistral.d.ts +4 -12
- package/dist/rag/embeddings/mistral.js +22 -72
- package/dist/rag/embeddings/mock.d.ts +35 -0
- package/dist/rag/embeddings/mock.js +69 -0
- package/dist/rag/embeddings/openai.d.ts +11 -13
- package/dist/rag/embeddings/openai.js +47 -75
- package/dist/rag/embeddings/types.d.ts +27 -1
- package/dist/rag/embeddings/validate.d.ts +9 -1
- package/dist/rag/embeddings/validate.js +17 -4
- package/dist/rag/index.d.ts +2 -2
- package/dist/rag/index.js +1 -1
- package/dist/rag/indexer/bounded-channel.d.ts +51 -0
- package/dist/rag/indexer/bounded-channel.js +138 -0
- package/dist/rag/indexer/indexer.d.ts +4 -14
- package/dist/rag/indexer/indexer.js +246 -169
- package/dist/rag/indexer/types.d.ts +1 -0
- package/dist/rag/logger/index.d.ts +22 -0
- package/dist/rag/logger/index.js +78 -1
- package/dist/rag/manifest/index.js +1 -2
- package/dist/rag/search/index.js +1 -1
- package/dist/rag/storage/schema.d.ts +2 -4
- package/dist/rag/storage/schema.js +3 -5
- package/dist/store/app/selectors.d.ts +87 -0
- package/dist/store/app/selectors.js +28 -0
- package/dist/store/app/slice.d.ts +1013 -0
- package/dist/store/app/slice.js +112 -0
- package/dist/store/hooks.d.ts +22 -0
- package/dist/store/hooks.js +17 -0
- package/dist/store/index.d.ts +12 -0
- package/dist/store/index.js +18 -0
- package/dist/store/indexing/listeners.d.ts +25 -0
- package/dist/store/indexing/listeners.js +46 -0
- package/dist/store/indexing/selectors.d.ts +195 -0
- package/dist/store/indexing/selectors.js +69 -0
- package/dist/store/indexing/slice.d.ts +309 -0
- package/dist/store/indexing/slice.js +113 -0
- package/dist/store/slot-progress/listeners.d.ts +23 -0
- package/dist/store/slot-progress/listeners.js +33 -0
- package/dist/store/slot-progress/selectors.d.ts +67 -0
- package/dist/store/slot-progress/selectors.js +36 -0
- package/dist/store/slot-progress/slice.d.ts +246 -0
- package/dist/store/slot-progress/slice.js +70 -0
- package/dist/store/store.d.ts +17 -0
- package/dist/store/store.js +18 -0
- package/dist/store/warmup/selectors.d.ts +109 -0
- package/dist/store/warmup/selectors.js +44 -0
- package/dist/store/warmup/slice.d.ts +137 -0
- package/dist/store/warmup/slice.js +72 -0
- package/dist/store/watcher/selectors.d.ts +115 -0
- package/dist/store/watcher/selectors.js +52 -0
- package/dist/store/watcher/slice.d.ts +269 -0
- package/dist/store/watcher/slice.js +100 -0
- package/dist/store/wizard/selectors.d.ts +115 -0
- package/dist/store/wizard/selectors.js +36 -0
- package/dist/store/wizard/slice.d.ts +523 -0
- package/dist/store/wizard/slice.js +119 -0
- package/package.json +10 -2
package/dist/mcp/index.js
CHANGED
|
@@ -4,78 +4,62 @@
|
|
|
4
4
|
*
|
|
5
5
|
* Exposes VibeRAG functionality via Model Context Protocol.
|
|
6
6
|
* Uses current working directory as project root.
|
|
7
|
-
*
|
|
7
|
+
* Connects to the daemon for all RAG operations.
|
|
8
8
|
*
|
|
9
9
|
* Usage with Claude Code:
|
|
10
10
|
* claude mcp add viberag -- npx viberag-mcp
|
|
11
11
|
*/
|
|
12
12
|
import { createMcpServer } from './server.js';
|
|
13
|
-
import { configExists
|
|
13
|
+
import { configExists } from '../daemon/lib/config.js';
|
|
14
14
|
// Use current working directory as project root (same behavior as CLI)
|
|
15
15
|
const projectRoot = process.cwd();
|
|
16
|
-
const { server,
|
|
16
|
+
const { server, connectDaemon, disconnectDaemon } = createMcpServer(projectRoot);
|
|
17
17
|
// Handle shutdown signals
|
|
18
18
|
async function shutdown(signal) {
|
|
19
19
|
console.error(`[viberag-mcp] Received ${signal}, shutting down...`);
|
|
20
|
-
await
|
|
20
|
+
await disconnectDaemon();
|
|
21
21
|
process.exit(0);
|
|
22
22
|
}
|
|
23
|
-
process.on('SIGINT', () =>
|
|
24
|
-
|
|
25
|
-
// Start the server, then start the watcher
|
|
26
|
-
server.start({
|
|
27
|
-
transportType: 'stdio',
|
|
23
|
+
process.on('SIGINT', () => {
|
|
24
|
+
void shutdown('SIGINT');
|
|
28
25
|
});
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
console.error('[viberag-mcp] Failed to start warmup:', error instanceof Error ? error.message : error);
|
|
46
|
-
}
|
|
47
|
-
// Start watcher (will queue any changes during sync)
|
|
48
|
-
try {
|
|
49
|
-
await startWatcher();
|
|
50
|
-
}
|
|
51
|
-
catch (error) {
|
|
52
|
-
// Watcher errors shouldn't crash the server
|
|
53
|
-
console.error('[viberag-mcp] Failed to start watcher:', error instanceof Error ? error.message : error);
|
|
54
|
-
}
|
|
55
|
-
// Sync index on startup if project is initialized
|
|
56
|
-
// This catches any changes made while MCP server was offline
|
|
57
|
-
try {
|
|
58
|
-
if (await configExists(projectRoot)) {
|
|
59
|
-
console.error('[viberag-mcp] Running startup sync...');
|
|
60
|
-
const indexer = new Indexer(projectRoot);
|
|
61
|
-
try {
|
|
62
|
-
const stats = await indexer.index({ force: false });
|
|
63
|
-
if (stats.filesNew > 0 ||
|
|
64
|
-
stats.filesModified > 0 ||
|
|
65
|
-
stats.filesDeleted > 0) {
|
|
66
|
-
console.error(`[viberag-mcp] Startup sync complete: ${stats.filesNew} new, ${stats.filesModified} modified, ${stats.filesDeleted} deleted`);
|
|
67
|
-
}
|
|
68
|
-
else {
|
|
69
|
-
console.error('[viberag-mcp] Startup sync: index up to date');
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
finally {
|
|
73
|
-
indexer.close();
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
catch (error) {
|
|
78
|
-
// Sync errors shouldn't crash the server
|
|
79
|
-
console.error('[viberag-mcp] Startup sync failed:', error instanceof Error ? error.message : error);
|
|
26
|
+
process.on('SIGTERM', () => {
|
|
27
|
+
void shutdown('SIGTERM');
|
|
28
|
+
});
|
|
29
|
+
/**
|
|
30
|
+
* Run startup tasks after MCP client connects.
|
|
31
|
+
* This is deferred to ensure the MCP handshake completes first.
|
|
32
|
+
*/
|
|
33
|
+
async function runStartupTasks() {
|
|
34
|
+
// Check if project is initialized
|
|
35
|
+
const isInitialized = await configExists(projectRoot);
|
|
36
|
+
if (!isInitialized) {
|
|
37
|
+
console.error('[viberag-mcp] Project not initialized.');
|
|
38
|
+
console.error('[viberag-mcp] Run "npx viberag" in this directory and use /init to configure.');
|
|
39
|
+
console.error('[viberag-mcp] Use viberag_status tool for details on how to initialize.');
|
|
40
|
+
// For uninitialized projects, we're done
|
|
41
|
+
return;
|
|
80
42
|
}
|
|
43
|
+
// Connect to daemon (starts it if needed)
|
|
44
|
+
// The daemon handles warmup, watcher, and startup sync
|
|
45
|
+
await connectDaemon();
|
|
46
|
+
}
|
|
47
|
+
// Wait for client to connect before running startup tasks
|
|
48
|
+
// This ensures the MCP handshake completes before any file I/O
|
|
49
|
+
server.on('connect', () => {
|
|
50
|
+
// Run startup tasks in the background (don't block the connection)
|
|
51
|
+
runStartupTasks().catch(error => {
|
|
52
|
+
// Pass Error object directly to preserve stack trace (ADR-011)
|
|
53
|
+
console.error('[viberag-mcp] Startup tasks failed:', error);
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
// Start the server (await to ensure transport is ready)
|
|
57
|
+
server
|
|
58
|
+
.start({
|
|
59
|
+
transportType: 'stdio',
|
|
60
|
+
})
|
|
61
|
+
.catch(error => {
|
|
62
|
+
// Pass Error object directly to preserve stack trace (ADR-011)
|
|
63
|
+
console.error('[viberag-mcp] Failed to start server:', error);
|
|
64
|
+
process.exit(1);
|
|
81
65
|
});
|
package/dist/mcp/server.d.ts
CHANGED
|
@@ -7,23 +7,19 @@
|
|
|
7
7
|
* Includes file watcher for automatic incremental indexing.
|
|
8
8
|
*/
|
|
9
9
|
import { FastMCP } from 'fastmcp';
|
|
10
|
-
import {
|
|
11
|
-
import { WarmupManager } from './warmup.js';
|
|
10
|
+
import { DaemonClient } from '../client/index.js';
|
|
12
11
|
/**
|
|
13
|
-
* MCP server with
|
|
12
|
+
* MCP server with daemon client.
|
|
14
13
|
*/
|
|
15
|
-
export interface
|
|
14
|
+
export interface McpServerWithDaemon {
|
|
16
15
|
server: FastMCP;
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
stopWatcher: () => Promise<void>;
|
|
23
|
-
/** Start warmup (call after server.start) */
|
|
24
|
-
startWarmup: () => void;
|
|
16
|
+
client: DaemonClient;
|
|
17
|
+
/** Connect to daemon (call after server.start) */
|
|
18
|
+
connectDaemon: () => Promise<void>;
|
|
19
|
+
/** Disconnect from daemon (call before exit) */
|
|
20
|
+
disconnectDaemon: () => Promise<void>;
|
|
25
21
|
}
|
|
26
22
|
/**
|
|
27
|
-
* Create and configure the MCP server with
|
|
23
|
+
* Create and configure the MCP server with daemon client.
|
|
28
24
|
*/
|
|
29
|
-
export declare function createMcpServer(projectRoot: string):
|
|
25
|
+
export declare function createMcpServer(projectRoot: string): McpServerWithDaemon;
|
package/dist/mcp/server.js
CHANGED
|
@@ -9,9 +9,11 @@
|
|
|
9
9
|
import { createRequire } from 'node:module';
|
|
10
10
|
import { FastMCP } from 'fastmcp';
|
|
11
11
|
import { z } from 'zod';
|
|
12
|
-
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
12
|
+
// Direct imports from daemon for fast startup (avoid barrel file)
|
|
13
|
+
import { configExists, loadConfig } from '../daemon/lib/config.js';
|
|
14
|
+
import { loadManifest, manifestExists, getSchemaVersionInfo, } from '../daemon/lib/manifest.js';
|
|
15
|
+
import { DaemonClient } from '../client/index.js';
|
|
16
|
+
import { createServiceLogger } from '../daemon/lib/logger.js';
|
|
15
17
|
const require = createRequire(import.meta.url);
|
|
16
18
|
const pkg = require('../../package.json');
|
|
17
19
|
/**
|
|
@@ -20,7 +22,7 @@ const pkg = require('../../package.json');
|
|
|
20
22
|
class NotInitializedError extends Error {
|
|
21
23
|
constructor(projectRoot) {
|
|
22
24
|
super(`VibeRAG not initialized in ${projectRoot}. ` +
|
|
23
|
-
`
|
|
25
|
+
`Use viberag_status tool for details, or run 'npx viberag' CLI and use /init command.`);
|
|
24
26
|
this.name = 'NotInitializedError';
|
|
25
27
|
}
|
|
26
28
|
}
|
|
@@ -187,17 +189,23 @@ function formatIndexStats(stats) {
|
|
|
187
189
|
});
|
|
188
190
|
}
|
|
189
191
|
/**
|
|
190
|
-
* Create and configure the MCP server with
|
|
192
|
+
* Create and configure the MCP server with daemon client.
|
|
191
193
|
*/
|
|
192
194
|
export function createMcpServer(projectRoot) {
|
|
193
195
|
const server = new FastMCP({
|
|
194
196
|
name: 'viberag',
|
|
195
197
|
version: pkg.version,
|
|
196
198
|
});
|
|
197
|
-
// Create
|
|
198
|
-
const
|
|
199
|
-
// Create
|
|
200
|
-
|
|
199
|
+
// Create daemon client (auto-starts daemon if needed)
|
|
200
|
+
const client = new DaemonClient(projectRoot);
|
|
201
|
+
// Create logger for error tracking (writes to .viberag/logs/mcp/)
|
|
202
|
+
let logger = null;
|
|
203
|
+
const getLogger = () => {
|
|
204
|
+
if (!logger) {
|
|
205
|
+
logger = createServiceLogger(projectRoot, 'mcp');
|
|
206
|
+
}
|
|
207
|
+
return logger;
|
|
208
|
+
};
|
|
201
209
|
// Filters schema for transparent, AI-controlled filtering
|
|
202
210
|
const filtersSchema = z
|
|
203
211
|
.object({
|
|
@@ -408,16 +416,15 @@ Production code: { path_not_contains: ["test", "mock", "fixture"], is_exported:
|
|
|
408
416
|
hasDocstring: args.filters.has_docstring,
|
|
409
417
|
}
|
|
410
418
|
: undefined;
|
|
411
|
-
// Get shared search engine from warmup manager (waits for warmup if needed)
|
|
412
|
-
const engine = await warmupManager.getSearchEngine();
|
|
413
419
|
// Determine if debug info should be returned
|
|
414
420
|
const returnDebug = args.return_debug ??
|
|
415
421
|
(args.mode === 'hybrid' || args.mode === undefined);
|
|
416
|
-
|
|
422
|
+
// Search via daemon client
|
|
423
|
+
const results = await client.search(args.query, {
|
|
417
424
|
mode: args.mode,
|
|
418
425
|
limit: args.limit,
|
|
419
426
|
minScore: args.min_score,
|
|
420
|
-
filters,
|
|
427
|
+
filters: filters,
|
|
421
428
|
codeSnippet: args.code_snippet,
|
|
422
429
|
symbolName: args.symbol_name,
|
|
423
430
|
bm25Weight: args.bm25_weight,
|
|
@@ -425,7 +432,6 @@ Production code: { path_not_contains: ["test", "mock", "fixture"], is_exported:
|
|
|
425
432
|
autoBoostThreshold: args.auto_boost_threshold,
|
|
426
433
|
returnDebug,
|
|
427
434
|
});
|
|
428
|
-
// Don't close engine - it's shared across calls
|
|
429
435
|
return formatSearchResults(results, returnDebug, args.max_response_size);
|
|
430
436
|
},
|
|
431
437
|
});
|
|
@@ -446,29 +452,9 @@ Production code: { path_not_contains: ["test", "mock", "fixture"], is_exported:
|
|
|
446
452
|
}),
|
|
447
453
|
execute: async (args) => {
|
|
448
454
|
await ensureInitialized(projectRoot);
|
|
449
|
-
//
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
const config = await loadConfig(projectRoot);
|
|
453
|
-
const currentDimensions = PROVIDER_CONFIGS[config.embeddingProvider]?.dimensions;
|
|
454
|
-
if (currentDimensions &&
|
|
455
|
-
config.embeddingDimensions !== currentDimensions) {
|
|
456
|
-
const updatedConfig = {
|
|
457
|
-
...config,
|
|
458
|
-
embeddingDimensions: currentDimensions,
|
|
459
|
-
embeddingModel: PROVIDER_CONFIGS[config.embeddingProvider].model,
|
|
460
|
-
};
|
|
461
|
-
await saveConfig(projectRoot, updatedConfig);
|
|
462
|
-
}
|
|
463
|
-
}
|
|
464
|
-
const indexer = new Indexer(projectRoot);
|
|
465
|
-
try {
|
|
466
|
-
const stats = await indexer.index({ force: args.force });
|
|
467
|
-
return formatIndexStats(stats);
|
|
468
|
-
}
|
|
469
|
-
finally {
|
|
470
|
-
indexer.close();
|
|
471
|
-
}
|
|
455
|
+
// Index via daemon client (handles dimension sync internally)
|
|
456
|
+
const stats = await client.index({ force: args.force });
|
|
457
|
+
return formatIndexStats(stats);
|
|
472
458
|
},
|
|
473
459
|
});
|
|
474
460
|
// Tool: viberag_status
|
|
@@ -476,10 +462,24 @@ Production code: { path_not_contains: ["test", "mock", "fixture"], is_exported:
|
|
|
476
462
|
name: 'viberag_status',
|
|
477
463
|
description: 'Get index status including file count, chunk count, embedding provider, schema version, and last update time. ' +
|
|
478
464
|
'If schema version is outdated, run viberag_index with force=true to reindex. ' +
|
|
479
|
-
'TIP: Check status before delegating exploration to sub-agents to ensure the index is current.'
|
|
465
|
+
'TIP: Check status before delegating exploration to sub-agents to ensure the index is current. ' +
|
|
466
|
+
'This tool also works when the project is not initialized, providing guidance on how to set up.',
|
|
480
467
|
parameters: z.object({}),
|
|
481
468
|
execute: async () => {
|
|
482
|
-
|
|
469
|
+
// Check if project is initialized (don't throw, return helpful status)
|
|
470
|
+
if (!(await configExists(projectRoot))) {
|
|
471
|
+
return JSON.stringify({
|
|
472
|
+
status: 'not_initialized',
|
|
473
|
+
message: 'VibeRAG is not initialized in this project.',
|
|
474
|
+
projectRoot,
|
|
475
|
+
instructions: {
|
|
476
|
+
step1: 'Run "npx viberag" in a terminal in this project directory',
|
|
477
|
+
step2: 'Use the /init command to configure an embedding provider',
|
|
478
|
+
providers: 'Choose from: Gemini (free tier), OpenAI, Mistral, or Local (no API key)',
|
|
479
|
+
note: 'After initialization, run viberag_index to create the search index',
|
|
480
|
+
},
|
|
481
|
+
});
|
|
482
|
+
}
|
|
483
483
|
if (!(await manifestExists(projectRoot))) {
|
|
484
484
|
return JSON.stringify({
|
|
485
485
|
status: 'not_indexed',
|
|
@@ -507,16 +507,25 @@ Production code: { path_not_contains: ["test", "mock", "fixture"], is_exported:
|
|
|
507
507
|
`Schema version ${schemaInfo.current} is outdated (current: ${schemaInfo.required}). ` +
|
|
508
508
|
`Run viberag_index with force=true to reindex and enable new features.`;
|
|
509
509
|
}
|
|
510
|
-
// Add warmup state
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
510
|
+
// Add warmup state from daemon status
|
|
511
|
+
try {
|
|
512
|
+
const daemonStatus = await client.status();
|
|
513
|
+
response['warmup'] = {
|
|
514
|
+
status: daemonStatus.warmupStatus,
|
|
515
|
+
elapsedMs: daemonStatus.warmupElapsedMs,
|
|
516
|
+
};
|
|
517
|
+
}
|
|
518
|
+
catch (error) {
|
|
519
|
+
// Log unexpected errors (expected: daemon not running)
|
|
520
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
521
|
+
const isExpected = message.includes('ENOENT') || message.includes('ECONNREFUSED');
|
|
522
|
+
if (!isExpected) {
|
|
523
|
+
// Log to both stderr and debug.log - pass Error object for full stack
|
|
524
|
+
console.error('[mcp] Failed to get daemon warmup status:', error);
|
|
525
|
+
getLogger().error('MCP', 'Failed to get daemon warmup status', error instanceof Error ? error : new Error(message));
|
|
526
|
+
}
|
|
527
|
+
response['warmup'] = { status: 'unknown' };
|
|
528
|
+
}
|
|
520
529
|
return JSON.stringify(response);
|
|
521
530
|
},
|
|
522
531
|
});
|
|
@@ -527,7 +536,7 @@ Production code: { path_not_contains: ["test", "mock", "fixture"], is_exported:
|
|
|
527
536
|
'how many files are being watched, pending changes, and last update time.',
|
|
528
537
|
parameters: z.object({}),
|
|
529
538
|
execute: async () => {
|
|
530
|
-
const status =
|
|
539
|
+
const status = await client.watchStatus();
|
|
531
540
|
return JSON.stringify(status);
|
|
532
541
|
},
|
|
533
542
|
});
|
|
@@ -666,14 +675,12 @@ Metadata filters:
|
|
|
666
675
|
.max(MAX_RESPONSE_SIZE)
|
|
667
676
|
.optional()
|
|
668
677
|
.default(DEFAULT_MAX_RESPONSE_SIZE)
|
|
669
|
-
.describe('Maximum response size in bytes (default: 100KB). ' +
|
|
678
|
+
.describe('Maximum response size in bytes (default: 50KB, max: 100KB). ' +
|
|
670
679
|
'Reduces merged result count to fit; does NOT truncate text.'),
|
|
671
680
|
}),
|
|
672
681
|
execute: async (args) => {
|
|
673
682
|
await ensureInitialized(projectRoot);
|
|
674
|
-
//
|
|
675
|
-
const engine = await warmupManager.getSearchEngine();
|
|
676
|
-
// Run all searches in parallel
|
|
683
|
+
// Run all searches in parallel via daemon client
|
|
677
684
|
const searchPromises = args.searches.map(async (config, index) => {
|
|
678
685
|
const filters = config.filters
|
|
679
686
|
? {
|
|
@@ -687,10 +694,10 @@ Metadata filters:
|
|
|
687
694
|
hasDocstring: config.filters.has_docstring,
|
|
688
695
|
}
|
|
689
696
|
: undefined;
|
|
690
|
-
const results = await
|
|
697
|
+
const results = await client.search(config.query, {
|
|
691
698
|
mode: config.mode,
|
|
692
699
|
limit: config.limit,
|
|
693
|
-
filters,
|
|
700
|
+
filters: filters,
|
|
694
701
|
bm25Weight: config.bm25_weight,
|
|
695
702
|
autoBoost: config.auto_boost,
|
|
696
703
|
returnDebug: true,
|
|
@@ -813,7 +820,6 @@ Metadata filters:
|
|
|
813
820
|
results: mergedResults,
|
|
814
821
|
};
|
|
815
822
|
}
|
|
816
|
-
// Don't close engine - it's shared across calls
|
|
817
823
|
return JSON.stringify({
|
|
818
824
|
searchCount: args.searches.length,
|
|
819
825
|
individual,
|
|
@@ -823,26 +829,21 @@ Metadata filters:
|
|
|
823
829
|
});
|
|
824
830
|
return {
|
|
825
831
|
server,
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
// Only start watcher if project is initialized
|
|
832
|
+
client,
|
|
833
|
+
connectDaemon: async () => {
|
|
834
|
+
// Only connect if project is initialized
|
|
830
835
|
if (await configExists(projectRoot)) {
|
|
831
|
-
|
|
836
|
+
try {
|
|
837
|
+
await client.connect();
|
|
838
|
+
console.error('[viberag-mcp] Connected to daemon');
|
|
839
|
+
}
|
|
840
|
+
catch (error) {
|
|
841
|
+
console.error('[viberag-mcp] Failed to connect to daemon:', error instanceof Error ? error.message : error);
|
|
842
|
+
}
|
|
832
843
|
}
|
|
833
844
|
},
|
|
834
|
-
|
|
835
|
-
await
|
|
836
|
-
warmupManager.close();
|
|
837
|
-
},
|
|
838
|
-
startWarmup: () => {
|
|
839
|
-
warmupManager.startWarmup({
|
|
840
|
-
onProgress: state => {
|
|
841
|
-
if (state.status === 'ready') {
|
|
842
|
-
console.error(`[viberag-mcp] Warmup complete (${state.elapsedMs}ms)`);
|
|
843
|
-
}
|
|
844
|
-
},
|
|
845
|
-
});
|
|
845
|
+
disconnectDaemon: async () => {
|
|
846
|
+
await client.disconnect();
|
|
846
847
|
},
|
|
847
848
|
};
|
|
848
849
|
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lazy Loader Service
|
|
3
|
+
*
|
|
4
|
+
* Provides lazy-loaded access to heavy RAG modules that have native dependencies.
|
|
5
|
+
* These modules (Indexer, SearchEngine) load tree-sitter WASM and lancedb native bindings,
|
|
6
|
+
* which takes ~500-1000ms. By loading them lazily, the MCP server can respond to
|
|
7
|
+
* the initialize handshake immediately.
|
|
8
|
+
*
|
|
9
|
+
* Pattern: Singleton with memoization
|
|
10
|
+
* Thread-safety: Safe - single-threaded Node.js environment
|
|
11
|
+
*/
|
|
12
|
+
import type { Indexer as IndexerType } from '../../rag/indexer/index.js';
|
|
13
|
+
import type { SearchEngine as SearchEngineType } from '../../rag/search/index.js';
|
|
14
|
+
/**
|
|
15
|
+
* Get the Indexer class, loading the module on first access.
|
|
16
|
+
* Subsequent calls return the cached reference.
|
|
17
|
+
*/
|
|
18
|
+
export declare function getIndexer(): Promise<typeof IndexerType>;
|
|
19
|
+
/**
|
|
20
|
+
* Get the SearchEngine class, loading the module on first access.
|
|
21
|
+
* Subsequent calls return the cached reference.
|
|
22
|
+
*/
|
|
23
|
+
export declare function getSearchEngine(): Promise<typeof SearchEngineType>;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lazy Loader Service
|
|
3
|
+
*
|
|
4
|
+
* Provides lazy-loaded access to heavy RAG modules that have native dependencies.
|
|
5
|
+
* These modules (Indexer, SearchEngine) load tree-sitter WASM and lancedb native bindings,
|
|
6
|
+
* which takes ~500-1000ms. By loading them lazily, the MCP server can respond to
|
|
7
|
+
* the initialize handshake immediately.
|
|
8
|
+
*
|
|
9
|
+
* Pattern: Singleton with memoization
|
|
10
|
+
* Thread-safety: Safe - single-threaded Node.js environment
|
|
11
|
+
*/
|
|
12
|
+
// Memoized module references
|
|
13
|
+
let indexerModule = null;
|
|
14
|
+
let searchModule = null;
|
|
15
|
+
/**
|
|
16
|
+
* Get the Indexer class, loading the module on first access.
|
|
17
|
+
* Subsequent calls return the cached reference.
|
|
18
|
+
*/
|
|
19
|
+
export async function getIndexer() {
|
|
20
|
+
if (!indexerModule) {
|
|
21
|
+
indexerModule = await import('../../rag/indexer/index.js');
|
|
22
|
+
}
|
|
23
|
+
return indexerModule.Indexer;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Get the SearchEngine class, loading the module on first access.
|
|
27
|
+
* Subsequent calls return the cached reference.
|
|
28
|
+
*/
|
|
29
|
+
export async function getSearchEngine() {
|
|
30
|
+
if (!searchModule) {
|
|
31
|
+
searchModule = await import('../../rag/search/index.js');
|
|
32
|
+
}
|
|
33
|
+
return searchModule.SearchEngine;
|
|
34
|
+
}
|
package/dist/mcp/warmup.d.ts
CHANGED
|
@@ -4,12 +4,13 @@
|
|
|
4
4
|
* Manages singleton SearchEngine initialization and state.
|
|
5
5
|
* Ensures embedding model is loaded once and shared across tool calls.
|
|
6
6
|
*
|
|
7
|
+
* State is tracked in Redux for consistency with the rest of the codebase.
|
|
7
8
|
* The idempotent promise pattern solves the race condition:
|
|
8
9
|
* - First call: Creates the warmup promise, starts initialization
|
|
9
10
|
* - Concurrent calls: All await the SAME promise (no duplicate work)
|
|
10
11
|
* - After ready: Returns cached SearchEngine immediately
|
|
11
12
|
*/
|
|
12
|
-
import { SearchEngine } from '../rag/index.js';
|
|
13
|
+
import type { SearchEngine } from '../rag/search/index.js';
|
|
13
14
|
/**
|
|
14
15
|
* Warmup status enum.
|
|
15
16
|
*/
|
|
@@ -41,10 +42,9 @@ export declare class WarmupManager {
|
|
|
41
42
|
private readonly projectRoot;
|
|
42
43
|
private searchEngine;
|
|
43
44
|
private warmupPromise;
|
|
44
|
-
private state;
|
|
45
45
|
constructor(projectRoot: string);
|
|
46
46
|
/**
|
|
47
|
-
* Get current warmup state.
|
|
47
|
+
* Get current warmup state from Redux.
|
|
48
48
|
*/
|
|
49
49
|
getState(): WarmupState;
|
|
50
50
|
/**
|