@rawwee/interactive-mcp 1.5.2 → 1.5.3
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.
|
@@ -11,8 +11,8 @@ const IGNORED_DIRECTORIES = new Set([
|
|
|
11
11
|
'.vscode',
|
|
12
12
|
'.DS_Store',
|
|
13
13
|
]);
|
|
14
|
-
const
|
|
15
|
-
const
|
|
14
|
+
const MAX_REPOSITORY_ENTRIES = 50000;
|
|
15
|
+
const MAX_SUGGESTIONS_WITH_EMPTY_QUERY = 24;
|
|
16
16
|
const toPosixPath = (value) => value.replaceAll(path.sep, '/');
|
|
17
17
|
const getFuzzyScore = (candidate, query) => {
|
|
18
18
|
const candidateLower = candidate.toLowerCase();
|
|
@@ -76,7 +76,7 @@ export const getAutocompleteTarget = (value, caret) => {
|
|
|
76
76
|
};
|
|
77
77
|
export const rankFileSuggestions = (files, query) => {
|
|
78
78
|
if (query.length === 0) {
|
|
79
|
-
return files.slice(0,
|
|
79
|
+
return files.slice(0, MAX_SUGGESTIONS_WITH_EMPTY_QUERY);
|
|
80
80
|
}
|
|
81
81
|
return files
|
|
82
82
|
.map((filePath) => ({
|
|
@@ -85,16 +85,15 @@ export const rankFileSuggestions = (files, query) => {
|
|
|
85
85
|
}))
|
|
86
86
|
.filter((entry) => typeof entry.score === 'number')
|
|
87
87
|
.sort((a, b) => b.score - a.score || a.filePath.localeCompare(b.filePath))
|
|
88
|
-
.slice(0, MAX_SUGGESTIONS)
|
|
89
88
|
.map((entry) => entry.filePath);
|
|
90
89
|
};
|
|
91
90
|
export const readRepositoryFiles = async (repoRoot) => {
|
|
92
91
|
const discoveredFiles = [];
|
|
93
92
|
const visitDirectory = async (directoryPath) => {
|
|
94
|
-
if (discoveredFiles.length >=
|
|
93
|
+
if (discoveredFiles.length >= MAX_REPOSITORY_ENTRIES) {
|
|
95
94
|
return;
|
|
96
95
|
}
|
|
97
|
-
let entries
|
|
96
|
+
let entries;
|
|
98
97
|
try {
|
|
99
98
|
entries = await fs.readdir(directoryPath, { withFileTypes: true });
|
|
100
99
|
}
|
|
@@ -102,22 +101,23 @@ export const readRepositoryFiles = async (repoRoot) => {
|
|
|
102
101
|
return;
|
|
103
102
|
}
|
|
104
103
|
for (const entry of entries) {
|
|
105
|
-
if (discoveredFiles.length >=
|
|
104
|
+
if (discoveredFiles.length >= MAX_REPOSITORY_ENTRIES) {
|
|
106
105
|
return;
|
|
107
106
|
}
|
|
108
107
|
if (IGNORED_DIRECTORIES.has(entry.name)) {
|
|
109
108
|
continue;
|
|
110
109
|
}
|
|
111
110
|
const entryAbsolutePath = path.join(directoryPath, entry.name);
|
|
111
|
+
const relativePath = path.relative(repoRoot, entryAbsolutePath);
|
|
112
|
+
if (!relativePath || relativePath.startsWith('..')) {
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
112
115
|
if (entry.isDirectory()) {
|
|
116
|
+
discoveredFiles.push(`${toPosixPath(relativePath)}/`);
|
|
113
117
|
await visitDirectory(entryAbsolutePath);
|
|
114
118
|
continue;
|
|
115
119
|
}
|
|
116
120
|
if (entry.isFile()) {
|
|
117
|
-
const relativePath = path.relative(repoRoot, entryAbsolutePath);
|
|
118
|
-
if (!relativePath || relativePath.startsWith('..')) {
|
|
119
|
-
continue;
|
|
120
|
-
}
|
|
121
121
|
discoveredFiles.push(toPosixPath(relativePath));
|
|
122
122
|
}
|
|
123
123
|
}
|
|
@@ -12,8 +12,8 @@ export const OptionList = ({ mode, options, selectedIndex, onSelectOption, onAct
|
|
|
12
12
|
};
|
|
13
13
|
export const InputEditor = ({ questionId, textareaRenderVersion, textareaRef, textareaContainerHeight, textareaRows, hasSuggestions, keyBindings, onFocusRequest, onContentSync, onSubmitFromTextarea, }) => (_jsxs("box", { flexDirection: "column", marginBottom: 0, width: "100%", children: [_jsx("text", { fg: "gray", children: "Input" }), _jsx("box", { border: true, borderStyle: "single", borderColor: hasSuggestions ? 'cyan' : 'gray', backgroundColor: "#1f1f1f", height: textareaContainerHeight, paddingLeft: 1, paddingRight: 1, onClick: onFocusRequest, children: _jsx("textarea", { ref: textareaRef, focused: true, height: textareaRows, wrapMode: "word", backgroundColor: "#1f1f1f", focusedBackgroundColor: "#1f1f1f", textColor: "white", focusedTextColor: "white", placeholderColor: "gray", placeholder: "Type your answer...", keyBindings: keyBindings, onContentChange: onContentSync, onCursorChange: onContentSync, onSubmit: onSubmitFromTextarea }, `textarea-${questionId}-${textareaRenderVersion}`) })] }));
|
|
14
14
|
export const SuggestionsPanel = ({ hasOptions, isIndexingFiles, fileSuggestions, selectedSuggestionIndex, selectedSuggestionVscodeLink, hasSearchRoot, }) => (_jsxs("box", { flexDirection: "column", marginBottom: 0, width: "100%", gap: 0, children: [_jsx("text", { fg: "gray", children: hasOptions
|
|
15
|
-
? '
|
|
16
|
-
: '
|
|
15
|
+
? 'Path suggestions (files + folders) • ↑/↓ or Ctrl+N/P navigate • Enter apply'
|
|
16
|
+
: 'Path suggestions (files + folders) • ↑/↓ or Ctrl+N/P navigate • Enter/Tab apply' }), isIndexingFiles ? (_jsx("text", { fg: "gray", children: "Indexing files..." })) : fileSuggestions.length > 0 ? (_jsxs("box", { flexDirection: "column", width: "100%", children: [fileSuggestions.map((suggestion, index) => (_jsx("box", { paddingLeft: 0, paddingRight: 1, gap: 0, children: _jsxs("text", { fg: index === selectedSuggestionIndex ? 'cyan' : 'gray', wrapMode: "char", children: [index === selectedSuggestionIndex ? '› ' : ' ', suggestion] }) }, suggestion))), selectedSuggestionVscodeLink && (_jsxs("box", { flexDirection: "column", width: "100%", children: [_jsx("text", { fg: "gray", wrapMode: "word", children: "open file with:" }), _jsx("text", { fg: "cyan", wrapMode: "word", onMouseUp: () => {
|
|
17
17
|
void openExternalLink(selectedSuggestionVscodeLink, 'vscode');
|
|
18
18
|
}, children: "\u2022 VS Code" }), _jsx("text", { fg: "cyan", wrapMode: "word", onMouseUp: () => {
|
|
19
19
|
void openExternalLink(selectedSuggestionVscodeLink, 'vscode-insiders');
|
|
@@ -25,7 +25,7 @@ export const SearchStatus = ({ isIndexingFiles, repositoryFiles, searchRoot, has
|
|
|
25
25
|
? `#search root: ${searchRoot}`
|
|
26
26
|
: '#search root: no search root' }), _jsx("text", { fg: "gray", children: isIndexingFiles
|
|
27
27
|
? '#search index: indexing...'
|
|
28
|
-
: `#search index: ${repositoryFiles.length}
|
|
28
|
+
: `#search index: ${repositoryFiles.length} paths indexed` })] }));
|
|
29
29
|
export const InputStatus = ({ mode, isNarrow, inputValue, queuedAttachments, }) => (_jsxs("box", { flexDirection: isNarrow ? 'column' : 'row', justifyContent: "space-between", marginBottom: 0, gap: isNarrow ? 0 : undefined, children: [_jsx("text", { fg: "gray", children: mode === 'input' ? 'Custom input' : 'Option selection' }), _jsx("text", { fg: "gray", children: mode === 'input' && queuedAttachments.length > 0
|
|
30
30
|
? `${inputValue.length} chars + ${queuedAttachments.length} queued`
|
|
31
31
|
: `${inputValue.length} chars` })] }));
|
|
@@ -33,5 +33,5 @@ export const ClipboardStatus = ({ status }) => (_jsx("text", { fg: status.starts
|
|
|
33
33
|
export const AttachmentsDisplay = ({ queuedAttachments, }) => (_jsxs("box", { flexDirection: "column", width: "100%", gap: 0, children: [_jsxs("text", { fg: "yellow", children: [_jsx("strong", { children: "QUEUED ATTACHMENTS" }), " (Delete placeholder text to remove)"] }), queuedAttachments.map((attachment, index) => (_jsxs("text", { fg: "gray", wrapMode: "word", children: ["[File ", index + 1, "] ", attachment.label] }, attachment.id)))] }));
|
|
34
34
|
export const SendButton = () => (_jsx("box", { backgroundColor: "cyan", paddingLeft: 1, paddingRight: 1, alignSelf: "flex-start", marginBottom: 0, children: _jsxs("text", { fg: "black", children: [_jsx("strong", { children: "Send" }), " \u2303S"] }) }));
|
|
35
35
|
export const HelpText = ({ hasOptions }) => (_jsx("text", { fg: "gray", wrapMode: "word", children: hasOptions
|
|
36
|
-
? 'Enter/Ctrl+J newline (or #search apply) • #search nav: ↑/↓ or Ctrl+N/P • Tab mode switch • #path for repo file autocomplete • Cmd/Ctrl+C copy input • Cmd/Ctrl+V paste/attach • Cmd/Ctrl+Z undo • Cmd/Ctrl+Shift+Z redo'
|
|
37
|
-
: 'Enter/Ctrl+J newline • #search nav: ↑/↓ or Ctrl+N/P • Enter/Tab #search apply • #path for repo file autocomplete • Cmd/Ctrl+C copy input • Cmd/Ctrl+V paste/attach • Cmd/Ctrl+Z undo • Cmd/Ctrl+Shift+Z redo' }));
|
|
36
|
+
? 'Enter/Ctrl+J newline (or #search apply) • #search nav: ↑/↓ or Ctrl+N/P • Tab mode switch • #path for repo file/folder autocomplete • Cmd/Ctrl+C copy input • Cmd/Ctrl+V paste/attach • Cmd/Ctrl+Z undo • Cmd/Ctrl+Shift+Z redo'
|
|
37
|
+
: 'Enter/Ctrl+J newline • #search nav: ↑/↓ or Ctrl+N/P • Enter/Tab #search apply • #path for repo file/folder autocomplete • Cmd/Ctrl+C copy input • Cmd/Ctrl+V paste/attach • Cmd/Ctrl+Z undo • Cmd/Ctrl+Shift+Z redo' }));
|