viberag 0.1.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/LICENSE +661 -0
- package/README.md +219 -0
- package/dist/cli/__tests__/mcp-setup.test.d.ts +6 -0
- package/dist/cli/__tests__/mcp-setup.test.js +597 -0
- package/dist/cli/app.d.ts +2 -0
- package/dist/cli/app.js +238 -0
- package/dist/cli/commands/handlers.d.ts +57 -0
- package/dist/cli/commands/handlers.js +231 -0
- package/dist/cli/commands/index.d.ts +2 -0
- package/dist/cli/commands/index.js +2 -0
- package/dist/cli/commands/mcp-setup.d.ts +107 -0
- package/dist/cli/commands/mcp-setup.js +509 -0
- package/dist/cli/commands/useRagCommands.d.ts +23 -0
- package/dist/cli/commands/useRagCommands.js +180 -0
- package/dist/cli/components/CleanWizard.d.ts +17 -0
- package/dist/cli/components/CleanWizard.js +169 -0
- package/dist/cli/components/InitWizard.d.ts +20 -0
- package/dist/cli/components/InitWizard.js +370 -0
- package/dist/cli/components/McpSetupWizard.d.ts +37 -0
- package/dist/cli/components/McpSetupWizard.js +387 -0
- package/dist/cli/components/SearchResultsDisplay.d.ts +13 -0
- package/dist/cli/components/SearchResultsDisplay.js +130 -0
- package/dist/cli/components/WelcomeBanner.d.ts +10 -0
- package/dist/cli/components/WelcomeBanner.js +26 -0
- package/dist/cli/components/index.d.ts +1 -0
- package/dist/cli/components/index.js +1 -0
- package/dist/cli/data/mcp-editors.d.ts +80 -0
- package/dist/cli/data/mcp-editors.js +270 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.js +26 -0
- package/dist/cli-bundle.cjs +5269 -0
- package/dist/common/commands/terminalSetup.d.ts +2 -0
- package/dist/common/commands/terminalSetup.js +144 -0
- package/dist/common/components/CommandSuggestions.d.ts +9 -0
- package/dist/common/components/CommandSuggestions.js +20 -0
- package/dist/common/components/StaticWithResize.d.ts +23 -0
- package/dist/common/components/StaticWithResize.js +62 -0
- package/dist/common/components/StatusBar.d.ts +8 -0
- package/dist/common/components/StatusBar.js +64 -0
- package/dist/common/components/TextInput.d.ts +12 -0
- package/dist/common/components/TextInput.js +239 -0
- package/dist/common/components/index.d.ts +3 -0
- package/dist/common/components/index.js +3 -0
- package/dist/common/hooks/index.d.ts +4 -0
- package/dist/common/hooks/index.js +4 -0
- package/dist/common/hooks/useCommandHistory.d.ts +7 -0
- package/dist/common/hooks/useCommandHistory.js +51 -0
- package/dist/common/hooks/useCtrlC.d.ts +9 -0
- package/dist/common/hooks/useCtrlC.js +40 -0
- package/dist/common/hooks/useKittyKeyboard.d.ts +10 -0
- package/dist/common/hooks/useKittyKeyboard.js +26 -0
- package/dist/common/hooks/useStaticOutputBuffer.d.ts +31 -0
- package/dist/common/hooks/useStaticOutputBuffer.js +58 -0
- package/dist/common/hooks/useTerminalResize.d.ts +28 -0
- package/dist/common/hooks/useTerminalResize.js +51 -0
- package/dist/common/hooks/useTextBuffer.d.ts +13 -0
- package/dist/common/hooks/useTextBuffer.js +165 -0
- package/dist/common/index.d.ts +13 -0
- package/dist/common/index.js +17 -0
- package/dist/common/types.d.ts +162 -0
- package/dist/common/types.js +1 -0
- package/dist/mcp/index.d.ts +12 -0
- package/dist/mcp/index.js +66 -0
- package/dist/mcp/server.d.ts +25 -0
- package/dist/mcp/server.js +837 -0
- package/dist/mcp/watcher.d.ts +86 -0
- package/dist/mcp/watcher.js +334 -0
- package/dist/rag/__tests__/grammar-smoke.test.d.ts +9 -0
- package/dist/rag/__tests__/grammar-smoke.test.js +161 -0
- package/dist/rag/__tests__/helpers.d.ts +30 -0
- package/dist/rag/__tests__/helpers.js +67 -0
- package/dist/rag/__tests__/merkle.test.d.ts +5 -0
- package/dist/rag/__tests__/merkle.test.js +161 -0
- package/dist/rag/__tests__/metadata-extraction.test.d.ts +10 -0
- package/dist/rag/__tests__/metadata-extraction.test.js +202 -0
- package/dist/rag/__tests__/multi-language.test.d.ts +13 -0
- package/dist/rag/__tests__/multi-language.test.js +535 -0
- package/dist/rag/__tests__/rag.test.d.ts +10 -0
- package/dist/rag/__tests__/rag.test.js +311 -0
- package/dist/rag/__tests__/search-exhaustive.test.d.ts +9 -0
- package/dist/rag/__tests__/search-exhaustive.test.js +87 -0
- package/dist/rag/__tests__/search-filters.test.d.ts +10 -0
- package/dist/rag/__tests__/search-filters.test.js +250 -0
- package/dist/rag/__tests__/search-modes.test.d.ts +8 -0
- package/dist/rag/__tests__/search-modes.test.js +133 -0
- package/dist/rag/config/index.d.ts +61 -0
- package/dist/rag/config/index.js +111 -0
- package/dist/rag/constants.d.ts +41 -0
- package/dist/rag/constants.js +57 -0
- package/dist/rag/embeddings/fastembed.d.ts +62 -0
- package/dist/rag/embeddings/fastembed.js +124 -0
- package/dist/rag/embeddings/gemini.d.ts +26 -0
- package/dist/rag/embeddings/gemini.js +116 -0
- package/dist/rag/embeddings/index.d.ts +10 -0
- package/dist/rag/embeddings/index.js +9 -0
- package/dist/rag/embeddings/local-4b.d.ts +28 -0
- package/dist/rag/embeddings/local-4b.js +51 -0
- package/dist/rag/embeddings/local.d.ts +29 -0
- package/dist/rag/embeddings/local.js +119 -0
- package/dist/rag/embeddings/mistral.d.ts +22 -0
- package/dist/rag/embeddings/mistral.js +85 -0
- package/dist/rag/embeddings/openai.d.ts +22 -0
- package/dist/rag/embeddings/openai.js +85 -0
- package/dist/rag/embeddings/types.d.ts +37 -0
- package/dist/rag/embeddings/types.js +1 -0
- package/dist/rag/gitignore/index.d.ts +57 -0
- package/dist/rag/gitignore/index.js +178 -0
- package/dist/rag/index.d.ts +15 -0
- package/dist/rag/index.js +25 -0
- package/dist/rag/indexer/chunker.d.ts +129 -0
- package/dist/rag/indexer/chunker.js +1352 -0
- package/dist/rag/indexer/index.d.ts +6 -0
- package/dist/rag/indexer/index.js +6 -0
- package/dist/rag/indexer/indexer.d.ts +73 -0
- package/dist/rag/indexer/indexer.js +356 -0
- package/dist/rag/indexer/types.d.ts +68 -0
- package/dist/rag/indexer/types.js +47 -0
- package/dist/rag/logger/index.d.ts +20 -0
- package/dist/rag/logger/index.js +75 -0
- package/dist/rag/manifest/index.d.ts +50 -0
- package/dist/rag/manifest/index.js +97 -0
- package/dist/rag/merkle/diff.d.ts +26 -0
- package/dist/rag/merkle/diff.js +95 -0
- package/dist/rag/merkle/hash.d.ts +34 -0
- package/dist/rag/merkle/hash.js +165 -0
- package/dist/rag/merkle/index.d.ts +68 -0
- package/dist/rag/merkle/index.js +298 -0
- package/dist/rag/merkle/node.d.ts +51 -0
- package/dist/rag/merkle/node.js +69 -0
- package/dist/rag/search/filters.d.ts +21 -0
- package/dist/rag/search/filters.js +100 -0
- package/dist/rag/search/fts.d.ts +32 -0
- package/dist/rag/search/fts.js +61 -0
- package/dist/rag/search/hybrid.d.ts +17 -0
- package/dist/rag/search/hybrid.js +58 -0
- package/dist/rag/search/index.d.ts +89 -0
- package/dist/rag/search/index.js +367 -0
- package/dist/rag/search/types.d.ts +130 -0
- package/dist/rag/search/types.js +4 -0
- package/dist/rag/search/vector.d.ts +25 -0
- package/dist/rag/search/vector.js +44 -0
- package/dist/rag/storage/index.d.ts +92 -0
- package/dist/rag/storage/index.js +287 -0
- package/dist/rag/storage/lancedb-native.d.ts +7 -0
- package/dist/rag/storage/lancedb-native.js +10 -0
- package/dist/rag/storage/schema.d.ts +23 -0
- package/dist/rag/storage/schema.js +50 -0
- package/dist/rag/storage/types.d.ts +100 -0
- package/dist/rag/storage/types.js +68 -0
- package/package.json +67 -0
- package/scripts/check-node-version.js +37 -0
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { useRef, useCallback, useEffect } from 'react';
|
|
2
|
+
import { useApp } from 'ink';
|
|
3
|
+
export function useCtrlC({ onFirstPress, onStatusClear, timeout = 2000, }) {
|
|
4
|
+
const { exit } = useApp();
|
|
5
|
+
const lastPressTime = useRef(0);
|
|
6
|
+
const timeoutId = useRef(null);
|
|
7
|
+
// Cleanup timeout on unmount
|
|
8
|
+
useEffect(() => {
|
|
9
|
+
return () => {
|
|
10
|
+
if (timeoutId.current) {
|
|
11
|
+
clearTimeout(timeoutId.current);
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
}, []);
|
|
15
|
+
const handleCtrlC = useCallback(() => {
|
|
16
|
+
const now = Date.now();
|
|
17
|
+
const timeSinceLastPress = now - lastPressTime.current;
|
|
18
|
+
if (timeSinceLastPress < timeout && lastPressTime.current !== 0) {
|
|
19
|
+
// Second press within timeout - exit
|
|
20
|
+
if (timeoutId.current) {
|
|
21
|
+
clearTimeout(timeoutId.current);
|
|
22
|
+
}
|
|
23
|
+
exit();
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
// First press - show message and start timer
|
|
27
|
+
lastPressTime.current = now;
|
|
28
|
+
onFirstPress();
|
|
29
|
+
// Clear the message after timeout
|
|
30
|
+
if (timeoutId.current) {
|
|
31
|
+
clearTimeout(timeoutId.current);
|
|
32
|
+
}
|
|
33
|
+
timeoutId.current = setTimeout(() => {
|
|
34
|
+
lastPressTime.current = 0;
|
|
35
|
+
onStatusClear();
|
|
36
|
+
}, timeout);
|
|
37
|
+
}
|
|
38
|
+
}, [exit, onFirstPress, onStatusClear, timeout]);
|
|
39
|
+
return { handleCtrlC };
|
|
40
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Enables the Kitty keyboard protocol on mount and disables it on unmount.
|
|
3
|
+
*
|
|
4
|
+
* When enabled, terminals that support the protocol (iTerm2, Kitty, WezTerm)
|
|
5
|
+
* will send CSI u encoded key sequences that include modifier information.
|
|
6
|
+
* For example, Shift+Enter sends \x1b[13;2u instead of plain \r.
|
|
7
|
+
*
|
|
8
|
+
* Terminals that don't support the protocol simply ignore the escape sequence.
|
|
9
|
+
*/
|
|
10
|
+
export declare function useKittyKeyboard(): void;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { useEffect } from 'react';
|
|
2
|
+
import { useStdout } from 'ink';
|
|
3
|
+
// Kitty keyboard protocol escape sequences
|
|
4
|
+
// https://sw.kovidgoyal.net/kitty/keyboard-protocol/
|
|
5
|
+
const KITTY_ENABLE = '\x1b[>1u'; // Enable progressive enhancement mode 1
|
|
6
|
+
const KITTY_DISABLE = '\x1b[<u'; // Pop/disable keyboard mode
|
|
7
|
+
/**
|
|
8
|
+
* Enables the Kitty keyboard protocol on mount and disables it on unmount.
|
|
9
|
+
*
|
|
10
|
+
* When enabled, terminals that support the protocol (iTerm2, Kitty, WezTerm)
|
|
11
|
+
* will send CSI u encoded key sequences that include modifier information.
|
|
12
|
+
* For example, Shift+Enter sends \x1b[13;2u instead of plain \r.
|
|
13
|
+
*
|
|
14
|
+
* Terminals that don't support the protocol simply ignore the escape sequence.
|
|
15
|
+
*/
|
|
16
|
+
export function useKittyKeyboard() {
|
|
17
|
+
const { stdout } = useStdout();
|
|
18
|
+
useEffect(() => {
|
|
19
|
+
// Enable Kitty keyboard protocol on mount
|
|
20
|
+
stdout.write(KITTY_ENABLE);
|
|
21
|
+
// Disable on unmount
|
|
22
|
+
return () => {
|
|
23
|
+
stdout.write(KITTY_DISABLE);
|
|
24
|
+
};
|
|
25
|
+
}, [stdout]);
|
|
26
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export type UseStaticOutputBufferResult = {
|
|
2
|
+
/**
|
|
3
|
+
* Append output to the buffer.
|
|
4
|
+
*/
|
|
5
|
+
appendOutput: (id: string, content: string) => void;
|
|
6
|
+
/**
|
|
7
|
+
* Clear all buffered output.
|
|
8
|
+
*/
|
|
9
|
+
clearOutput: () => void;
|
|
10
|
+
/**
|
|
11
|
+
* Get number of items in buffer.
|
|
12
|
+
*/
|
|
13
|
+
getBufferSize: () => number;
|
|
14
|
+
/**
|
|
15
|
+
* Get the full buffer as a single string.
|
|
16
|
+
*/
|
|
17
|
+
getFullBuffer: () => string;
|
|
18
|
+
/**
|
|
19
|
+
* Clear terminal and re-render all buffered output.
|
|
20
|
+
* This is the key function for resize recovery.
|
|
21
|
+
*/
|
|
22
|
+
rerender: () => void;
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Hook to track static output and provide re-render capability.
|
|
26
|
+
*
|
|
27
|
+
* Stores all output in a buffer (using ref to avoid re-renders on append).
|
|
28
|
+
* On resize, the rerender() function clears the terminal and writes
|
|
29
|
+
* all buffered content, restoring the display.
|
|
30
|
+
*/
|
|
31
|
+
export declare function useStaticOutputBuffer(): UseStaticOutputBufferResult;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { useRef, useCallback } from 'react';
|
|
2
|
+
import { useStdout } from 'ink';
|
|
3
|
+
/**
|
|
4
|
+
* ANSI escape sequences for terminal control.
|
|
5
|
+
*/
|
|
6
|
+
const ANSI = {
|
|
7
|
+
/** Clear visible screen */
|
|
8
|
+
CLEAR_SCREEN: '\x1B[2J',
|
|
9
|
+
/** Clear scrollback buffer */
|
|
10
|
+
CLEAR_SCROLLBACK: '\x1B[3J',
|
|
11
|
+
/** Move cursor to top-left */
|
|
12
|
+
CURSOR_HOME: '\x1B[H',
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Hook to track static output and provide re-render capability.
|
|
16
|
+
*
|
|
17
|
+
* Stores all output in a buffer (using ref to avoid re-renders on append).
|
|
18
|
+
* On resize, the rerender() function clears the terminal and writes
|
|
19
|
+
* all buffered content, restoring the display.
|
|
20
|
+
*/
|
|
21
|
+
export function useStaticOutputBuffer() {
|
|
22
|
+
const { stdout } = useStdout();
|
|
23
|
+
const bufferRef = useRef([]);
|
|
24
|
+
const appendOutput = useCallback((id, content) => {
|
|
25
|
+
// Check if item already exists (by id)
|
|
26
|
+
const exists = bufferRef.current.some(item => item.id === id);
|
|
27
|
+
if (!exists) {
|
|
28
|
+
bufferRef.current.push({ id, content });
|
|
29
|
+
}
|
|
30
|
+
}, []);
|
|
31
|
+
const clearOutput = useCallback(() => {
|
|
32
|
+
bufferRef.current = [];
|
|
33
|
+
}, []);
|
|
34
|
+
const getBufferSize = useCallback(() => {
|
|
35
|
+
return bufferRef.current.length;
|
|
36
|
+
}, []);
|
|
37
|
+
const getFullBuffer = useCallback(() => {
|
|
38
|
+
return bufferRef.current.map(item => item.content).join('\n');
|
|
39
|
+
}, []);
|
|
40
|
+
const rerender = useCallback(() => {
|
|
41
|
+
if (!stdout)
|
|
42
|
+
return;
|
|
43
|
+
const fullContent = getFullBuffer();
|
|
44
|
+
// Only clear and rewrite if we have content to restore
|
|
45
|
+
// Otherwise we'd just blank the screen for no reason
|
|
46
|
+
if (!fullContent.trim())
|
|
47
|
+
return;
|
|
48
|
+
// Clear screen and scrollback, move cursor home, write all content
|
|
49
|
+
stdout.write(ANSI.CLEAR_SCREEN + ANSI.CLEAR_SCROLLBACK + ANSI.CURSOR_HOME + fullContent);
|
|
50
|
+
}, [stdout, getFullBuffer]);
|
|
51
|
+
return {
|
|
52
|
+
appendOutput,
|
|
53
|
+
clearOutput,
|
|
54
|
+
getBufferSize,
|
|
55
|
+
getFullBuffer,
|
|
56
|
+
rerender,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { TerminalDimensions } from '../types.js';
|
|
2
|
+
export type UseTerminalResizeOptions = {
|
|
3
|
+
/**
|
|
4
|
+
* Callback invoked on resize (after debounce).
|
|
5
|
+
*/
|
|
6
|
+
onResize?: (dimensions: TerminalDimensions, previousDimensions: TerminalDimensions | null) => void;
|
|
7
|
+
/**
|
|
8
|
+
* Debounce delay in milliseconds. Default: 50
|
|
9
|
+
*/
|
|
10
|
+
debounceMs?: number;
|
|
11
|
+
};
|
|
12
|
+
export type UseTerminalResizeResult = {
|
|
13
|
+
/**
|
|
14
|
+
* Current terminal dimensions.
|
|
15
|
+
*/
|
|
16
|
+
dimensions: TerminalDimensions;
|
|
17
|
+
/**
|
|
18
|
+
* Previous terminal dimensions (null on first render).
|
|
19
|
+
*/
|
|
20
|
+
previousDimensions: TerminalDimensions | null;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Hook to detect terminal resize events.
|
|
24
|
+
*
|
|
25
|
+
* Subscribes to stdout 'resize' events and provides current/previous dimensions.
|
|
26
|
+
* Debounces rapid resize events to avoid excessive re-renders.
|
|
27
|
+
*/
|
|
28
|
+
export declare function useTerminalResize(options?: UseTerminalResizeOptions): UseTerminalResizeResult;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { useEffect, useState, useRef, useCallback } from 'react';
|
|
2
|
+
import { useStdout } from 'ink';
|
|
3
|
+
/**
|
|
4
|
+
* Hook to detect terminal resize events.
|
|
5
|
+
*
|
|
6
|
+
* Subscribes to stdout 'resize' events and provides current/previous dimensions.
|
|
7
|
+
* Debounces rapid resize events to avoid excessive re-renders.
|
|
8
|
+
*/
|
|
9
|
+
export function useTerminalResize(options = {}) {
|
|
10
|
+
const { onResize, debounceMs = 50 } = options;
|
|
11
|
+
const { stdout } = useStdout();
|
|
12
|
+
const getDimensions = useCallback(() => {
|
|
13
|
+
return {
|
|
14
|
+
rows: stdout?.rows ?? 24,
|
|
15
|
+
columns: stdout?.columns ?? 80,
|
|
16
|
+
};
|
|
17
|
+
}, [stdout]);
|
|
18
|
+
const [dimensions, setDimensions] = useState(getDimensions);
|
|
19
|
+
const [previousDimensions, setPreviousDimensions] = useState(null);
|
|
20
|
+
const debounceTimerRef = useRef(null);
|
|
21
|
+
const onResizeRef = useRef(onResize);
|
|
22
|
+
// Keep callback ref up to date
|
|
23
|
+
useEffect(() => {
|
|
24
|
+
onResizeRef.current = onResize;
|
|
25
|
+
}, [onResize]);
|
|
26
|
+
useEffect(() => {
|
|
27
|
+
const handleResize = () => {
|
|
28
|
+
// Clear any pending debounce
|
|
29
|
+
if (debounceTimerRef.current) {
|
|
30
|
+
clearTimeout(debounceTimerRef.current);
|
|
31
|
+
}
|
|
32
|
+
debounceTimerRef.current = setTimeout(() => {
|
|
33
|
+
const newDimensions = getDimensions();
|
|
34
|
+
setDimensions(prev => {
|
|
35
|
+
setPreviousDimensions(prev);
|
|
36
|
+
onResizeRef.current?.(newDimensions, prev);
|
|
37
|
+
return newDimensions;
|
|
38
|
+
});
|
|
39
|
+
debounceTimerRef.current = null;
|
|
40
|
+
}, debounceMs);
|
|
41
|
+
};
|
|
42
|
+
process.stdout.on('resize', handleResize);
|
|
43
|
+
return () => {
|
|
44
|
+
process.stdout.off('resize', handleResize);
|
|
45
|
+
if (debounceTimerRef.current) {
|
|
46
|
+
clearTimeout(debounceTimerRef.current);
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
}, [getDimensions, debounceMs]);
|
|
50
|
+
return { dimensions, previousDimensions };
|
|
51
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { TextBufferState } from '../types.js';
|
|
2
|
+
export declare function useTextBuffer(): {
|
|
3
|
+
state: TextBufferState;
|
|
4
|
+
insertChar: (char: string) => void;
|
|
5
|
+
insertNewline: () => void;
|
|
6
|
+
deleteChar: () => void;
|
|
7
|
+
deleteCharBefore: () => void;
|
|
8
|
+
moveCursor: (direction: "left" | "right" | "up" | "down") => void;
|
|
9
|
+
clear: () => void;
|
|
10
|
+
setText: (text: string) => void;
|
|
11
|
+
getText: () => string;
|
|
12
|
+
isEmpty: () => boolean;
|
|
13
|
+
};
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import { useState, useCallback } from 'react';
|
|
2
|
+
export function useTextBuffer() {
|
|
3
|
+
const [state, setState] = useState({
|
|
4
|
+
lines: [''],
|
|
5
|
+
cursorLine: 0,
|
|
6
|
+
cursorCol: 0,
|
|
7
|
+
});
|
|
8
|
+
const insertChar = useCallback((char) => {
|
|
9
|
+
setState(prev => {
|
|
10
|
+
const newLines = [...prev.lines];
|
|
11
|
+
const line = newLines[prev.cursorLine] ?? '';
|
|
12
|
+
newLines[prev.cursorLine] =
|
|
13
|
+
line.slice(0, prev.cursorCol) + char + line.slice(prev.cursorCol);
|
|
14
|
+
return {
|
|
15
|
+
...prev,
|
|
16
|
+
lines: newLines,
|
|
17
|
+
cursorCol: prev.cursorCol + char.length,
|
|
18
|
+
};
|
|
19
|
+
});
|
|
20
|
+
}, []);
|
|
21
|
+
const insertNewline = useCallback(() => {
|
|
22
|
+
setState(prev => {
|
|
23
|
+
const newLines = [...prev.lines];
|
|
24
|
+
const line = newLines[prev.cursorLine] ?? '';
|
|
25
|
+
const before = line.slice(0, prev.cursorCol);
|
|
26
|
+
const after = line.slice(prev.cursorCol);
|
|
27
|
+
newLines[prev.cursorLine] = before;
|
|
28
|
+
newLines.splice(prev.cursorLine + 1, 0, after);
|
|
29
|
+
return {
|
|
30
|
+
lines: newLines,
|
|
31
|
+
cursorLine: prev.cursorLine + 1,
|
|
32
|
+
cursorCol: 0,
|
|
33
|
+
};
|
|
34
|
+
});
|
|
35
|
+
}, []);
|
|
36
|
+
const deleteChar = useCallback(() => {
|
|
37
|
+
setState(prev => {
|
|
38
|
+
if (prev.cursorCol === 0 && prev.cursorLine === 0)
|
|
39
|
+
return prev;
|
|
40
|
+
const newLines = [...prev.lines];
|
|
41
|
+
if (prev.cursorCol === 0) {
|
|
42
|
+
// Merge with previous line
|
|
43
|
+
const currentLine = newLines[prev.cursorLine] ?? '';
|
|
44
|
+
const prevLineLen = (newLines[prev.cursorLine - 1] ?? '').length;
|
|
45
|
+
newLines[prev.cursorLine - 1] =
|
|
46
|
+
(newLines[prev.cursorLine - 1] ?? '') + currentLine;
|
|
47
|
+
newLines.splice(prev.cursorLine, 1);
|
|
48
|
+
return {
|
|
49
|
+
lines: newLines,
|
|
50
|
+
cursorLine: prev.cursorLine - 1,
|
|
51
|
+
cursorCol: prevLineLen,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
// Delete character before cursor
|
|
56
|
+
const line = newLines[prev.cursorLine] ?? '';
|
|
57
|
+
newLines[prev.cursorLine] =
|
|
58
|
+
line.slice(0, prev.cursorCol - 1) + line.slice(prev.cursorCol);
|
|
59
|
+
return {
|
|
60
|
+
...prev,
|
|
61
|
+
lines: newLines,
|
|
62
|
+
cursorCol: prev.cursorCol - 1,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
}, []);
|
|
67
|
+
// Delete single character before cursor (for backslash+enter handling)
|
|
68
|
+
const deleteCharBefore = useCallback(() => {
|
|
69
|
+
setState(prev => {
|
|
70
|
+
if (prev.cursorCol === 0)
|
|
71
|
+
return prev; // Nothing before cursor on this line
|
|
72
|
+
const newLines = [...prev.lines];
|
|
73
|
+
const line = newLines[prev.cursorLine] ?? '';
|
|
74
|
+
newLines[prev.cursorLine] =
|
|
75
|
+
line.slice(0, prev.cursorCol - 1) + line.slice(prev.cursorCol);
|
|
76
|
+
return {
|
|
77
|
+
...prev,
|
|
78
|
+
lines: newLines,
|
|
79
|
+
cursorCol: prev.cursorCol - 1,
|
|
80
|
+
};
|
|
81
|
+
});
|
|
82
|
+
}, []);
|
|
83
|
+
const moveCursor = useCallback((direction) => {
|
|
84
|
+
setState(prev => {
|
|
85
|
+
switch (direction) {
|
|
86
|
+
case 'left':
|
|
87
|
+
if (prev.cursorCol > 0) {
|
|
88
|
+
return { ...prev, cursorCol: prev.cursorCol - 1 };
|
|
89
|
+
}
|
|
90
|
+
else if (prev.cursorLine > 0) {
|
|
91
|
+
const prevLineLen = (prev.lines[prev.cursorLine - 1] ?? '')
|
|
92
|
+
.length;
|
|
93
|
+
return {
|
|
94
|
+
...prev,
|
|
95
|
+
cursorLine: prev.cursorLine - 1,
|
|
96
|
+
cursorCol: prevLineLen,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
return prev;
|
|
100
|
+
case 'right': {
|
|
101
|
+
const lineLen = (prev.lines[prev.cursorLine] ?? '').length;
|
|
102
|
+
if (prev.cursorCol < lineLen) {
|
|
103
|
+
return { ...prev, cursorCol: prev.cursorCol + 1 };
|
|
104
|
+
}
|
|
105
|
+
else if (prev.cursorLine < prev.lines.length - 1) {
|
|
106
|
+
return { ...prev, cursorLine: prev.cursorLine + 1, cursorCol: 0 };
|
|
107
|
+
}
|
|
108
|
+
return prev;
|
|
109
|
+
}
|
|
110
|
+
case 'up':
|
|
111
|
+
if (prev.cursorLine > 0) {
|
|
112
|
+
const newLineLen = (prev.lines[prev.cursorLine - 1] ?? '').length;
|
|
113
|
+
return {
|
|
114
|
+
...prev,
|
|
115
|
+
cursorLine: prev.cursorLine - 1,
|
|
116
|
+
cursorCol: Math.min(prev.cursorCol, newLineLen),
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
return prev;
|
|
120
|
+
case 'down':
|
|
121
|
+
if (prev.cursorLine < prev.lines.length - 1) {
|
|
122
|
+
const newLineLen = (prev.lines[prev.cursorLine + 1] ?? '').length;
|
|
123
|
+
return {
|
|
124
|
+
...prev,
|
|
125
|
+
cursorLine: prev.cursorLine + 1,
|
|
126
|
+
cursorCol: Math.min(prev.cursorCol, newLineLen),
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
return prev;
|
|
130
|
+
default:
|
|
131
|
+
return prev;
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
}, []);
|
|
135
|
+
const clear = useCallback(() => {
|
|
136
|
+
setState({ lines: [''], cursorLine: 0, cursorCol: 0 });
|
|
137
|
+
}, []);
|
|
138
|
+
const setText = useCallback((text) => {
|
|
139
|
+
const lines = text.split('\n');
|
|
140
|
+
const lastLine = lines[lines.length - 1] ?? '';
|
|
141
|
+
setState({
|
|
142
|
+
lines,
|
|
143
|
+
cursorLine: lines.length - 1,
|
|
144
|
+
cursorCol: lastLine.length,
|
|
145
|
+
});
|
|
146
|
+
}, []);
|
|
147
|
+
const getText = useCallback(() => {
|
|
148
|
+
return state.lines.join('\n');
|
|
149
|
+
}, [state.lines]);
|
|
150
|
+
const isEmpty = useCallback(() => {
|
|
151
|
+
return state.lines.length === 1 && state.lines[0] === '';
|
|
152
|
+
}, [state.lines]);
|
|
153
|
+
return {
|
|
154
|
+
state,
|
|
155
|
+
insertChar,
|
|
156
|
+
insertNewline,
|
|
157
|
+
deleteChar,
|
|
158
|
+
deleteCharBefore,
|
|
159
|
+
moveCursor,
|
|
160
|
+
clear,
|
|
161
|
+
setText,
|
|
162
|
+
getText,
|
|
163
|
+
isEmpty,
|
|
164
|
+
};
|
|
165
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Common infrastructure for React/Ink CLI applications.
|
|
3
|
+
* Generic components and hooks with no RAG-specific dependencies.
|
|
4
|
+
*/
|
|
5
|
+
export * from './types.js';
|
|
6
|
+
export { default as TextInput } from './components/TextInput.js';
|
|
7
|
+
export { default as StatusBar } from './components/StatusBar.js';
|
|
8
|
+
export { default as CommandSuggestions } from './components/CommandSuggestions.js';
|
|
9
|
+
export { useCtrlC } from './hooks/useCtrlC.js';
|
|
10
|
+
export { useCommandHistory } from './hooks/useCommandHistory.js';
|
|
11
|
+
export { useTextBuffer } from './hooks/useTextBuffer.js';
|
|
12
|
+
export { useKittyKeyboard } from './hooks/useKittyKeyboard.js';
|
|
13
|
+
export { setupVSCodeTerminal } from './commands/terminalSetup.js';
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Common infrastructure for React/Ink CLI applications.
|
|
3
|
+
* Generic components and hooks with no RAG-specific dependencies.
|
|
4
|
+
*/
|
|
5
|
+
// Types
|
|
6
|
+
export * from './types.js';
|
|
7
|
+
// Components
|
|
8
|
+
export { default as TextInput } from './components/TextInput.js';
|
|
9
|
+
export { default as StatusBar } from './components/StatusBar.js';
|
|
10
|
+
export { default as CommandSuggestions } from './components/CommandSuggestions.js';
|
|
11
|
+
// Hooks
|
|
12
|
+
export { useCtrlC } from './hooks/useCtrlC.js';
|
|
13
|
+
export { useCommandHistory } from './hooks/useCommandHistory.js';
|
|
14
|
+
export { useTextBuffer } from './hooks/useTextBuffer.js';
|
|
15
|
+
export { useKittyKeyboard } from './hooks/useKittyKeyboard.js';
|
|
16
|
+
// Commands
|
|
17
|
+
export { setupVSCodeTerminal } from './commands/terminalSetup.js';
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A single search result item for display.
|
|
3
|
+
*/
|
|
4
|
+
export type SearchResultItem = {
|
|
5
|
+
type: string;
|
|
6
|
+
name: string;
|
|
7
|
+
filepath: string;
|
|
8
|
+
filename: string;
|
|
9
|
+
startLine: number;
|
|
10
|
+
endLine: number;
|
|
11
|
+
score: number;
|
|
12
|
+
text: string;
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Search results data for display.
|
|
16
|
+
*/
|
|
17
|
+
export type SearchResultsData = {
|
|
18
|
+
query: string;
|
|
19
|
+
elapsedMs: number;
|
|
20
|
+
results: SearchResultItem[];
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Output items for the CLI display.
|
|
24
|
+
*/
|
|
25
|
+
export type OutputItem = {
|
|
26
|
+
id: string;
|
|
27
|
+
type: 'user';
|
|
28
|
+
content: string;
|
|
29
|
+
} | {
|
|
30
|
+
id: string;
|
|
31
|
+
type: 'system';
|
|
32
|
+
content: string;
|
|
33
|
+
} | {
|
|
34
|
+
id: string;
|
|
35
|
+
type: 'welcome';
|
|
36
|
+
content: string;
|
|
37
|
+
} | {
|
|
38
|
+
id: string;
|
|
39
|
+
type: 'search-results';
|
|
40
|
+
data: SearchResultsData;
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* Terminal dimensions for resize handling.
|
|
44
|
+
*/
|
|
45
|
+
export type TerminalDimensions = {
|
|
46
|
+
rows: number;
|
|
47
|
+
columns: number;
|
|
48
|
+
};
|
|
49
|
+
export type TextBufferState = {
|
|
50
|
+
lines: string[];
|
|
51
|
+
cursorLine: number;
|
|
52
|
+
cursorCol: number;
|
|
53
|
+
};
|
|
54
|
+
/**
|
|
55
|
+
* App status for the status bar.
|
|
56
|
+
*/
|
|
57
|
+
export type AppStatus = {
|
|
58
|
+
state: 'ready';
|
|
59
|
+
} | {
|
|
60
|
+
state: 'indexing';
|
|
61
|
+
current: number;
|
|
62
|
+
total: number;
|
|
63
|
+
stage: string;
|
|
64
|
+
} | {
|
|
65
|
+
state: 'searching';
|
|
66
|
+
} | {
|
|
67
|
+
state: 'warning';
|
|
68
|
+
message: string;
|
|
69
|
+
};
|
|
70
|
+
/**
|
|
71
|
+
* Index statistics for display.
|
|
72
|
+
*/
|
|
73
|
+
export type IndexDisplayStats = {
|
|
74
|
+
totalFiles: number;
|
|
75
|
+
totalChunks: number;
|
|
76
|
+
};
|
|
77
|
+
/**
|
|
78
|
+
* Embedding provider types.
|
|
79
|
+
*
|
|
80
|
+
* Local providers (no API key required):
|
|
81
|
+
* - local: Qwen3-Embedding-0.6B Q8 (1024d) - ~700MB download, ~1.2GB RAM
|
|
82
|
+
* - local-4b: Qwen3-Embedding-4B FP32 (2560d) - ~8GB download, ~8GB RAM
|
|
83
|
+
*
|
|
84
|
+
* API providers:
|
|
85
|
+
* - gemini: gemini-embedding-001 (768d) - Free tier
|
|
86
|
+
* - mistral: codestral-embed (1024d) - Code-optimized
|
|
87
|
+
* - openai: text-embedding-3-small (1536d) - Fast API
|
|
88
|
+
*/
|
|
89
|
+
export type EmbeddingProviderType = 'local' | 'local-4b' | 'gemini' | 'mistral' | 'openai';
|
|
90
|
+
/**
|
|
91
|
+
* Configuration collected from the init wizard.
|
|
92
|
+
*/
|
|
93
|
+
export type InitWizardConfig = {
|
|
94
|
+
provider: EmbeddingProviderType;
|
|
95
|
+
/** API key for cloud providers (gemini, mistral, openai) */
|
|
96
|
+
apiKey?: string;
|
|
97
|
+
};
|
|
98
|
+
/**
|
|
99
|
+
* MCP editor identifiers.
|
|
100
|
+
*/
|
|
101
|
+
export type McpEditorId = 'claude-code' | 'vscode' | 'cursor' | 'windsurf' | 'roo-code' | 'zed' | 'gemini-cli' | 'codex' | 'jetbrains' | 'opencode';
|
|
102
|
+
/**
|
|
103
|
+
* MCP setup result.
|
|
104
|
+
*/
|
|
105
|
+
export type McpSetupResultType = {
|
|
106
|
+
success: boolean;
|
|
107
|
+
editor: McpEditorId;
|
|
108
|
+
method: 'file-created' | 'file-merged' | 'cli-command' | 'instructions-shown';
|
|
109
|
+
configPath?: string;
|
|
110
|
+
error?: string;
|
|
111
|
+
};
|
|
112
|
+
/**
|
|
113
|
+
* Configuration collected from the MCP setup wizard.
|
|
114
|
+
*/
|
|
115
|
+
export type McpSetupWizardConfig = {
|
|
116
|
+
selectedEditors: McpEditorId[];
|
|
117
|
+
results: McpSetupResultType[];
|
|
118
|
+
};
|
|
119
|
+
/**
|
|
120
|
+
* MCP setup wizard step types.
|
|
121
|
+
*/
|
|
122
|
+
export type McpSetupStep = 'prompt' | 'select' | 'configure' | 'summary';
|
|
123
|
+
/**
|
|
124
|
+
* Wizard mode state for the app.
|
|
125
|
+
*/
|
|
126
|
+
export type WizardMode = {
|
|
127
|
+
active: false;
|
|
128
|
+
} | {
|
|
129
|
+
active: true;
|
|
130
|
+
type: 'init';
|
|
131
|
+
step: number;
|
|
132
|
+
config: Partial<InitWizardConfig>;
|
|
133
|
+
isReinit: boolean;
|
|
134
|
+
} | {
|
|
135
|
+
active: true;
|
|
136
|
+
type: 'mcp-setup';
|
|
137
|
+
step: McpSetupStep;
|
|
138
|
+
config: Partial<McpSetupWizardConfig>;
|
|
139
|
+
showPrompt: boolean;
|
|
140
|
+
} | {
|
|
141
|
+
active: true;
|
|
142
|
+
type: 'clean';
|
|
143
|
+
};
|
|
144
|
+
/**
|
|
145
|
+
* Provider configuration with model specs.
|
|
146
|
+
*/
|
|
147
|
+
export type ProviderConfig = {
|
|
148
|
+
name: string;
|
|
149
|
+
model: string;
|
|
150
|
+
dimensions: number;
|
|
151
|
+
context: string;
|
|
152
|
+
performance: string;
|
|
153
|
+
pricing: string;
|
|
154
|
+
description: string;
|
|
155
|
+
};
|
|
156
|
+
/**
|
|
157
|
+
* Command info for autocomplete with descriptions.
|
|
158
|
+
*/
|
|
159
|
+
export type CommandInfo = {
|
|
160
|
+
command: string;
|
|
161
|
+
description: string;
|
|
162
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* VibeRAG MCP Server Entry Point
|
|
4
|
+
*
|
|
5
|
+
* Exposes VibeRAG functionality via Model Context Protocol.
|
|
6
|
+
* Uses current working directory as project root.
|
|
7
|
+
* Includes file watcher for automatic incremental indexing.
|
|
8
|
+
*
|
|
9
|
+
* Usage with Claude Code:
|
|
10
|
+
* claude mcp add viberag -- npx viberag-mcp
|
|
11
|
+
*/
|
|
12
|
+
export {};
|