@within-7/minto 0.1.4 → 0.1.6
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/dist/commands/agents/AgentsCommand.js +2342 -0
- package/dist/commands/agents/AgentsCommand.js.map +7 -0
- package/dist/commands/agents/constants.js +58 -0
- package/dist/commands/agents/constants.js.map +7 -0
- package/dist/commands/agents/index.js +37 -0
- package/dist/commands/agents/index.js.map +7 -0
- package/dist/commands/agents/types.js +10 -0
- package/dist/commands/agents/types.js.map +7 -0
- package/dist/commands/agents/utils/fileOperations.js +185 -0
- package/dist/commands/agents/utils/fileOperations.js.map +7 -0
- package/dist/commands/agents/utils/index.js +21 -0
- package/dist/commands/agents/utils/index.js.map +7 -0
- package/dist/commands/bug.js +2 -2
- package/dist/commands/bug.js.map +2 -2
- package/dist/commands/compact.js +5 -5
- package/dist/commands/compact.js.map +2 -2
- package/dist/commands/ctx_viz.js +55 -22
- package/dist/commands/ctx_viz.js.map +2 -2
- package/dist/commands/mcp-interactive.js +11 -11
- package/dist/commands/mcp-interactive.js.map +2 -2
- package/dist/commands/model.js +94 -32
- package/dist/commands/model.js.map +3 -3
- package/dist/commands/plugin/AddMarketplaceForm.js +49 -21
- package/dist/commands/plugin/AddMarketplaceForm.js.map +2 -2
- package/dist/commands/plugin/ConfirmDialog.js +38 -26
- package/dist/commands/plugin/ConfirmDialog.js.map +2 -2
- package/dist/commands/plugin/InstalledPluginsByMarketplace.js +24 -8
- package/dist/commands/plugin/InstalledPluginsByMarketplace.js.map +2 -2
- package/dist/commands/plugin/InstalledPluginsManager.js +3 -1
- package/dist/commands/plugin/InstalledPluginsManager.js.map +2 -2
- package/dist/commands/plugin/MainMenu.js +16 -7
- package/dist/commands/plugin/MainMenu.js.map +2 -2
- package/dist/commands/plugin/MarketplaceManager.js +84 -39
- package/dist/commands/plugin/MarketplaceManager.js.map +2 -2
- package/dist/commands/plugin/MarketplaceSelector.js +7 -3
- package/dist/commands/plugin/MarketplaceSelector.js.map +2 -2
- package/dist/commands/plugin/PlaceholderScreen.js +16 -2
- package/dist/commands/plugin/PlaceholderScreen.js.map +2 -2
- package/dist/commands/plugin/PluginBrowser.js +4 -2
- package/dist/commands/plugin/PluginBrowser.js.map +2 -2
- package/dist/commands/plugin/PluginDetailsInstall.js +12 -6
- package/dist/commands/plugin/PluginDetailsInstall.js.map +2 -2
- package/dist/commands/plugin/PluginDetailsManage.js +14 -5
- package/dist/commands/plugin/PluginDetailsManage.js.map +2 -2
- package/dist/commands/plugin/example-usage.js.map +2 -2
- package/dist/commands/plugin/utils.js.map +2 -2
- package/dist/commands/plugin.js +226 -46
- package/dist/commands/plugin.js.map +2 -2
- package/dist/commands/refreshCommands.js +6 -3
- package/dist/commands/refreshCommands.js.map +2 -2
- package/dist/commands/resume.js +2 -1
- package/dist/commands/resume.js.map +2 -2
- package/dist/commands/setup.js +19 -5
- package/dist/commands/setup.js.map +2 -2
- package/dist/commands/terminalSetup.js +2 -2
- package/dist/commands/terminalSetup.js.map +1 -1
- package/dist/commands.js +14 -30
- package/dist/commands.js.map +2 -2
- package/dist/components/AskUserQuestionDialog/AskUserQuestionDialog.js.map +2 -2
- package/dist/components/AskUserQuestionDialog/QuestionView.js +10 -1
- package/dist/components/AskUserQuestionDialog/QuestionView.js.map +2 -2
- package/dist/components/BackgroundTasksPanel.js +5 -1
- package/dist/components/BackgroundTasksPanel.js.map +2 -2
- package/dist/components/Config.js +17 -4
- package/dist/components/Config.js.map +2 -2
- package/dist/components/ConsoleOAuthFlow.js.map +2 -2
- package/dist/components/CustomSelect/select-option.js +4 -1
- package/dist/components/CustomSelect/select-option.js.map +2 -2
- package/dist/components/Help.js +6 -8
- package/dist/components/Help.js.map +2 -2
- package/dist/components/Logo.js +1 -1
- package/dist/components/Logo.js.map +2 -2
- package/dist/components/ModelListManager.js.map +2 -2
- package/dist/components/ModelSelector/ModelSelector.js +2030 -0
- package/dist/components/ModelSelector/ModelSelector.js.map +7 -0
- package/dist/components/ModelSelector/ScreenContainer.js +27 -0
- package/dist/components/ModelSelector/ScreenContainer.js.map +7 -0
- package/dist/components/ModelSelector/constants.js +37 -0
- package/dist/components/ModelSelector/constants.js.map +7 -0
- package/dist/components/ModelSelector/hooks/index.js +5 -0
- package/dist/components/ModelSelector/hooks/index.js.map +7 -0
- package/dist/components/ModelSelector/hooks/useEscapeNavigation.js +21 -0
- package/dist/components/ModelSelector/hooks/useEscapeNavigation.js.map +7 -0
- package/dist/components/ModelSelector/index.js +17 -0
- package/dist/components/ModelSelector/index.js.map +7 -0
- package/dist/components/ModelSelector/types.js +1 -0
- package/dist/components/ModelSelector/types.js.map +7 -0
- package/dist/components/PressEnterToContinue.js +1 -1
- package/dist/components/PressEnterToContinue.js.map +2 -2
- package/dist/components/ProjectOnboarding.js +1 -1
- package/dist/components/ProjectOnboarding.js.map +2 -2
- package/dist/components/PromptInput.js +88 -37
- package/dist/components/PromptInput.js.map +2 -2
- package/dist/components/QuitSummary.js +17 -10
- package/dist/components/QuitSummary.js.map +2 -2
- package/dist/components/SentryErrorBoundary.js.map +2 -2
- package/dist/components/StreamingBashOutput.js.map +2 -2
- package/dist/components/StructuredDiff.js.map +2 -2
- package/dist/components/SubagentProgress.js.map +2 -2
- package/dist/components/TaskCard.js.map +2 -2
- package/dist/components/TextInput.js.map +1 -1
- package/dist/components/TodoItem.js.map +1 -1
- package/dist/components/binary-feedback/BinaryFeedbackOption.js +1 -3
- package/dist/components/binary-feedback/BinaryFeedbackOption.js.map +2 -2
- package/dist/components/messages/AssistantLocalCommandOutputMessage.js.map +1 -1
- package/dist/components/messages/AssistantToolUseMessage.js +3 -1
- package/dist/components/messages/AssistantToolUseMessage.js.map +2 -2
- package/dist/components/messages/TaskProgressMessage.js.map +2 -2
- package/dist/components/messages/TaskToolMessage.js.map +2 -2
- package/dist/components/messages/UserToolResultMessage/utils.js.map +2 -2
- package/dist/components/permissions/FileEditPermissionRequest/FileEditToolDiff.js.map +2 -2
- package/dist/components/permissions/FileWritePermissionRequest/FileWriteToolDiff.js.map +2 -2
- package/dist/components/permissions/hooks.js.map +2 -2
- package/dist/constants/modelCapabilities.js +1 -1
- package/dist/constants/modelCapabilities.js.map +2 -2
- package/dist/constants/prompts.js.map +1 -1
- package/dist/constants/timing.js +34 -0
- package/dist/constants/timing.js.map +7 -0
- package/dist/entrypoints/cli.js +128 -33
- package/dist/entrypoints/cli.js.map +3 -3
- package/dist/entrypoints/mcp.js +13 -18
- package/dist/entrypoints/mcp.js.map +2 -2
- package/dist/hooks/useCanUseTool.js.map +2 -2
- package/dist/hooks/useCancelRequest.js.map +1 -1
- package/dist/hooks/useHistorySearch.js.map +2 -2
- package/dist/hooks/useLogStartupTime.js.map +2 -2
- package/dist/hooks/usePermissionRequestLogging.js.map +2 -2
- package/dist/hooks/useTextInput.js.map +1 -1
- package/dist/hooks/useUnifiedCompletion.js +493 -394
- package/dist/hooks/useUnifiedCompletion.js.map +2 -2
- package/dist/index.js.map +2 -2
- package/dist/permissions.js +4 -7
- package/dist/permissions.js.map +2 -2
- package/dist/query.js +6 -1
- package/dist/query.js.map +2 -2
- package/dist/screens/REPL.js +72 -36
- package/dist/screens/REPL.js.map +2 -2
- package/dist/screens/ResumeConversation.js +2 -1
- package/dist/screens/ResumeConversation.js.map +2 -2
- package/dist/services/adapters/base.js.map +2 -2
- package/dist/services/adapters/chatCompletions.js.map +2 -2
- package/dist/services/adapters/responsesAPI.js +3 -1
- package/dist/services/adapters/responsesAPI.js.map +2 -2
- package/dist/services/claude.js +327 -328
- package/dist/services/claude.js.map +2 -2
- package/dist/services/customCommands.js +6 -1
- package/dist/services/customCommands.js.map +2 -2
- package/dist/services/fileFreshness.js.map +2 -2
- package/dist/services/gpt5ConnectionTest.js +20 -7
- package/dist/services/gpt5ConnectionTest.js.map +2 -2
- package/dist/services/hookExecutor.js +6 -12
- package/dist/services/hookExecutor.js.map +2 -2
- package/dist/services/mcpClient.js +29 -2
- package/dist/services/mcpClient.js.map +2 -2
- package/dist/services/mentionProcessor.js +23 -10
- package/dist/services/mentionProcessor.js.map +2 -2
- package/dist/services/modelAdapterFactory.js.map +2 -2
- package/dist/services/oauth.js.map +2 -2
- package/dist/services/openai.js +109 -72
- package/dist/services/openai.js.map +3 -3
- package/dist/services/responseStateManager.js.map +2 -2
- package/dist/services/systemReminder.js.map +2 -2
- package/dist/tools/ArchitectTool/ArchitectTool.js.map +1 -1
- package/dist/tools/AskExpertModelTool/AskExpertModelTool.js +14 -8
- package/dist/tools/AskExpertModelTool/AskExpertModelTool.js.map +2 -2
- package/dist/tools/BashOutputTool/BashOutputTool.js.map +2 -2
- package/dist/tools/BashTool/BashTool.js.map +2 -2
- package/dist/tools/FileReadTool/FileReadTool.js.map +1 -1
- package/dist/tools/FileWriteTool/FileWriteTool.js.map +2 -2
- package/dist/tools/GrepTool/GrepTool.js +1 -4
- package/dist/tools/GrepTool/GrepTool.js.map +2 -2
- package/dist/tools/MultiEditTool/MultiEditTool.js +4 -1
- package/dist/tools/MultiEditTool/MultiEditTool.js.map +2 -2
- package/dist/tools/NotebookReadTool/NotebookReadTool.js +3 -1
- package/dist/tools/NotebookReadTool/NotebookReadTool.js.map +2 -2
- package/dist/tools/SkillTool/SkillTool.js +12 -6
- package/dist/tools/SkillTool/SkillTool.js.map +2 -2
- package/dist/tools/TaskTool/TaskTool.js +14 -5
- package/dist/tools/TaskTool/TaskTool.js.map +2 -2
- package/dist/tools/TaskTool/prompt.js.map +2 -2
- package/dist/tools/ThinkTool/ThinkTool.js +6 -1
- package/dist/tools/ThinkTool/ThinkTool.js.map +2 -2
- package/dist/tools/TodoWriteTool/TodoWriteTool.js +23 -3
- package/dist/tools/TodoWriteTool/TodoWriteTool.js.map +2 -2
- package/dist/tools/URLFetcherTool/URLFetcherTool.js +2 -2
- package/dist/tools/URLFetcherTool/URLFetcherTool.js.map +2 -2
- package/dist/tools/URLFetcherTool/cache.js +6 -3
- package/dist/tools/URLFetcherTool/cache.js.map +2 -2
- package/dist/tools/URLFetcherTool/htmlToMarkdown.js +3 -1
- package/dist/tools/URLFetcherTool/htmlToMarkdown.js.map +2 -2
- package/dist/tools/WebSearchTool/WebSearchTool.js.map +2 -2
- package/dist/tools/WebSearchTool/prompt.js.map +2 -2
- package/dist/tools/WebSearchTool/searchProviders.js +15 -6
- package/dist/tools/WebSearchTool/searchProviders.js.map +2 -2
- package/dist/tools.js +4 -1
- package/dist/tools.js.map +2 -2
- package/dist/types/core.js +1 -0
- package/dist/types/core.js.map +7 -0
- package/dist/types/hooks.js +1 -4
- package/dist/types/hooks.js.map +2 -2
- package/dist/types/marketplace.js +8 -2
- package/dist/types/marketplace.js.map +2 -2
- package/dist/types/plugin.js +9 -6
- package/dist/types/plugin.js.map +2 -2
- package/dist/utils/BackgroundShellManager.js +76 -10
- package/dist/utils/BackgroundShellManager.js.map +2 -2
- package/dist/utils/PersistentShell.js +7 -2
- package/dist/utils/PersistentShell.js.map +2 -2
- package/dist/utils/advancedFuzzyMatcher.js +4 -1
- package/dist/utils/advancedFuzzyMatcher.js.map +2 -2
- package/dist/utils/agentLoader.js +69 -35
- package/dist/utils/agentLoader.js.map +2 -2
- package/dist/utils/agentStorage.js.map +2 -2
- package/dist/utils/async.js +163 -0
- package/dist/utils/async.js.map +7 -0
- package/dist/utils/autoUpdater.js +8 -2
- package/dist/utils/autoUpdater.js.map +2 -2
- package/dist/utils/commands.js +23 -11
- package/dist/utils/commands.js.map +2 -2
- package/dist/utils/commonUnixCommands.js +3 -1
- package/dist/utils/commonUnixCommands.js.map +2 -2
- package/dist/utils/compressionMode.js.map +2 -2
- package/dist/utils/config.js +30 -14
- package/dist/utils/config.js.map +2 -2
- package/dist/utils/debugLogger.js.map +2 -2
- package/dist/utils/env.js.map +2 -2
- package/dist/utils/envConfig.js +82 -0
- package/dist/utils/envConfig.js.map +7 -0
- package/dist/utils/errorHandling.js +89 -0
- package/dist/utils/errorHandling.js.map +7 -0
- package/dist/utils/expertChatStorage.js.map +2 -2
- package/dist/utils/fuzzyMatcher.js +13 -7
- package/dist/utils/fuzzyMatcher.js.map +2 -2
- package/dist/utils/hookManager.js +14 -4
- package/dist/utils/hookManager.js.map +2 -2
- package/dist/utils/log.js.map +2 -2
- package/dist/utils/marketplaceManager.js +44 -9
- package/dist/utils/marketplaceManager.js.map +2 -2
- package/dist/utils/messageContextManager.js.map +1 -1
- package/dist/utils/messages.js +6 -3
- package/dist/utils/messages.js.map +2 -2
- package/dist/utils/model.js +3 -1
- package/dist/utils/model.js.map +2 -2
- package/dist/utils/pluginInstaller.js +3 -15
- package/dist/utils/pluginInstaller.js.map +2 -2
- package/dist/utils/pluginLoader.js +41 -13
- package/dist/utils/pluginLoader.js.map +2 -2
- package/dist/utils/pluginRegistry.js.map +2 -2
- package/dist/utils/pluginValidator.js +71 -49
- package/dist/utils/pluginValidator.js.map +2 -2
- package/dist/utils/ptyCompat.js.map +2 -2
- package/dist/utils/roundConverter.js.map +2 -2
- package/dist/utils/secureFile.js +43 -14
- package/dist/utils/secureFile.js.map +2 -2
- package/dist/utils/sessionState.js.map +2 -2
- package/dist/utils/skillLoader.js.map +2 -2
- package/dist/utils/teamConfig.js +7 -4
- package/dist/utils/teamConfig.js.map +2 -2
- package/dist/utils/theme.js.map +2 -2
- package/dist/utils/thinking.js.map +2 -2
- package/dist/utils/unaryLogging.js.map +2 -2
- package/dist/version.js +2 -2
- package/dist/version.js.map +1 -1
- package/package.json +5 -5
|
@@ -44,33 +44,39 @@ function useUnifiedCompletion({
|
|
|
44
44
|
emptyDirMessage: ""
|
|
45
45
|
}));
|
|
46
46
|
}, []);
|
|
47
|
-
const activateCompletion = useCallback(
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
47
|
+
const activateCompletion = useCallback(
|
|
48
|
+
(suggestions2, context) => {
|
|
49
|
+
setState((prev) => ({
|
|
50
|
+
...prev,
|
|
51
|
+
suggestions: suggestions2,
|
|
52
|
+
// Keep the order from generateSuggestions (already sorted with weights)
|
|
53
|
+
selectedIndex: 0,
|
|
54
|
+
isActive: true,
|
|
55
|
+
context,
|
|
56
|
+
preview: null
|
|
57
|
+
}));
|
|
58
|
+
},
|
|
59
|
+
[]
|
|
60
|
+
);
|
|
58
61
|
const { suggestions, selectedIndex, isActive, emptyDirMessage } = state;
|
|
59
|
-
const findCommonPrefix = useCallback(
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
j
|
|
62
|
+
const findCommonPrefix = useCallback(
|
|
63
|
+
(suggestions2) => {
|
|
64
|
+
if (suggestions2.length === 0) return "";
|
|
65
|
+
if (suggestions2.length === 1) return suggestions2[0].value;
|
|
66
|
+
let prefix = suggestions2[0].value;
|
|
67
|
+
for (let i = 1; i < suggestions2.length; i++) {
|
|
68
|
+
const str = suggestions2[i].value;
|
|
69
|
+
let j = 0;
|
|
70
|
+
while (j < prefix.length && j < str.length && prefix[j] === str[j]) {
|
|
71
|
+
j++;
|
|
72
|
+
}
|
|
73
|
+
prefix = prefix.slice(0, j);
|
|
74
|
+
if (prefix.length === 0) return "";
|
|
68
75
|
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
}, []);
|
|
76
|
+
return prefix;
|
|
77
|
+
},
|
|
78
|
+
[]
|
|
79
|
+
);
|
|
74
80
|
const getWordAtCursor = useCallback(() => {
|
|
75
81
|
if (!input) return null;
|
|
76
82
|
let start = cursorOffset;
|
|
@@ -147,38 +153,67 @@ function useUnifiedCompletion({
|
|
|
147
153
|
}, [input, cursorOffset]);
|
|
148
154
|
const [systemCommands, setSystemCommands] = useState([]);
|
|
149
155
|
const [isLoadingCommands, setIsLoadingCommands] = useState(false);
|
|
150
|
-
const classifyCommand = useCallback(
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
156
|
+
const classifyCommand = useCallback(
|
|
157
|
+
(cmd) => {
|
|
158
|
+
const lowerCmd = cmd.toLowerCase();
|
|
159
|
+
let score = 0;
|
|
160
|
+
if (cmd.length <= 4) score += 40;
|
|
161
|
+
else if (cmd.length <= 6) score += 20;
|
|
162
|
+
else if (cmd.length <= 8) score += 10;
|
|
163
|
+
else if (cmd.length > 15) score -= 30;
|
|
164
|
+
if (/^[a-z]+$/.test(lowerCmd)) score += 30;
|
|
165
|
+
if (/[A-Z]/.test(cmd)) score -= 15;
|
|
166
|
+
if (/\d/.test(cmd)) score -= 20;
|
|
167
|
+
if (cmd.includes(".")) score -= 25;
|
|
168
|
+
if (cmd.includes("-")) score -= 10;
|
|
169
|
+
if (cmd.includes("_")) score -= 15;
|
|
170
|
+
const commonWords = [
|
|
171
|
+
"list",
|
|
172
|
+
"copy",
|
|
173
|
+
"move",
|
|
174
|
+
"find",
|
|
175
|
+
"print",
|
|
176
|
+
"show",
|
|
177
|
+
"edit",
|
|
178
|
+
"view"
|
|
179
|
+
];
|
|
180
|
+
if (commonWords.some((word) => lowerCmd.includes(word.slice(0, 3))))
|
|
181
|
+
score += 25;
|
|
182
|
+
const devPrefixes = ["git", "npm", "node", "py", "docker", "kubectl"];
|
|
183
|
+
if (devPrefixes.some((prefix) => lowerCmd.startsWith(prefix))) score += 15;
|
|
184
|
+
const systemIndicators = [
|
|
185
|
+
"daemon",
|
|
186
|
+
"helper",
|
|
187
|
+
"responder",
|
|
188
|
+
"service",
|
|
189
|
+
"d$",
|
|
190
|
+
"ctl$"
|
|
191
|
+
];
|
|
192
|
+
if (systemIndicators.some(
|
|
193
|
+
(indicator) => indicator.endsWith("$") ? lowerCmd.endsWith(indicator.slice(0, -1)) : lowerCmd.includes(indicator)
|
|
194
|
+
))
|
|
195
|
+
score -= 40;
|
|
196
|
+
if (/\.(pl|py|sh|rb|js)$/.test(lowerCmd)) score -= 35;
|
|
197
|
+
const buildToolPatterns = [
|
|
198
|
+
"bindep",
|
|
199
|
+
"render",
|
|
200
|
+
"mako",
|
|
201
|
+
"webpack",
|
|
202
|
+
"babel",
|
|
203
|
+
"eslint"
|
|
204
|
+
];
|
|
205
|
+
if (buildToolPatterns.some((pattern) => lowerCmd.includes(pattern)))
|
|
206
|
+
score -= 25;
|
|
207
|
+
const vowelRatio = (lowerCmd.match(/[aeiou]/g) || []).length / lowerCmd.length;
|
|
208
|
+
if (vowelRatio < 0.2) score += 15;
|
|
209
|
+
if (vowelRatio > 0.5) score -= 10;
|
|
210
|
+
if (score >= 50) return "core";
|
|
211
|
+
if (score >= 20) return "common";
|
|
212
|
+
if (score >= -10) return "dev";
|
|
213
|
+
return "system";
|
|
214
|
+
},
|
|
215
|
+
[]
|
|
216
|
+
);
|
|
182
217
|
const loadSystemCommands = useCallback(async () => {
|
|
183
218
|
if (systemCommands.length > 0 || isLoadingCommands) return;
|
|
184
219
|
setIsLoadingCommands(true);
|
|
@@ -218,72 +253,89 @@ function useUnifiedCompletion({
|
|
|
218
253
|
useEffect(() => {
|
|
219
254
|
loadSystemCommands();
|
|
220
255
|
}, [loadSystemCommands]);
|
|
221
|
-
const generateCommandSuggestions = useCallback(
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
256
|
+
const generateCommandSuggestions = useCallback(
|
|
257
|
+
(prefix) => {
|
|
258
|
+
const filteredCommands = commands.filter((cmd) => !cmd.isHidden);
|
|
259
|
+
if (!prefix) {
|
|
260
|
+
return filteredCommands.map((cmd) => ({
|
|
261
|
+
value: cmd.userFacingName(),
|
|
262
|
+
displayValue: `/${cmd.userFacingName()}`,
|
|
263
|
+
type: "command",
|
|
264
|
+
score: 100
|
|
265
|
+
}));
|
|
266
|
+
}
|
|
267
|
+
return filteredCommands.filter((cmd) => {
|
|
268
|
+
const names = [cmd.userFacingName(), ...cmd.aliases || []];
|
|
269
|
+
return names.some(
|
|
270
|
+
(name) => name.toLowerCase().startsWith(prefix.toLowerCase())
|
|
271
|
+
);
|
|
272
|
+
}).map((cmd) => ({
|
|
225
273
|
value: cmd.userFacingName(),
|
|
226
274
|
displayValue: `/${cmd.userFacingName()}`,
|
|
227
275
|
type: "command",
|
|
228
|
-
score: 100
|
|
276
|
+
score: 100 - prefix.length + (cmd.userFacingName().startsWith(prefix) ? 10 : 0)
|
|
229
277
|
}));
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
metadata: { isLoading: true }
|
|
254
|
-
}];
|
|
255
|
-
}
|
|
256
|
-
const commonCommands = getCommonSystemCommands(systemCommands);
|
|
257
|
-
const uniqueCommands = Array.from(new Set(commonCommands));
|
|
258
|
-
const matches = matchCommands(uniqueCommands, prefix);
|
|
259
|
-
const boostedMatches = matches.map((match) => {
|
|
260
|
-
const priority = getCommandPriority(match.command);
|
|
261
|
-
return {
|
|
262
|
-
...match,
|
|
263
|
-
score: match.score + priority * 0.5
|
|
264
|
-
// Add priority boost
|
|
265
|
-
};
|
|
266
|
-
}).sort((a, b) => b.score - a.score);
|
|
267
|
-
let results = boostedMatches.slice(0, 8);
|
|
268
|
-
const perfectMatches = boostedMatches.filter((m) => m.score >= 900);
|
|
269
|
-
if (perfectMatches.length > 0 && perfectMatches.length <= 3) {
|
|
270
|
-
results = perfectMatches;
|
|
271
|
-
} else if (boostedMatches.length > 8) {
|
|
272
|
-
const goodMatches = boostedMatches.filter((m) => m.score >= 100);
|
|
273
|
-
if (goodMatches.length <= 5) {
|
|
274
|
-
results = goodMatches;
|
|
278
|
+
},
|
|
279
|
+
[commands]
|
|
280
|
+
);
|
|
281
|
+
const calculateUnixCommandScore = useCallback(
|
|
282
|
+
(cmd, prefix) => {
|
|
283
|
+
const result = matchCommands([cmd], prefix);
|
|
284
|
+
return result.length > 0 ? result[0].score : 0;
|
|
285
|
+
},
|
|
286
|
+
[]
|
|
287
|
+
);
|
|
288
|
+
const generateUnixCommandSuggestions = useCallback(
|
|
289
|
+
(prefix) => {
|
|
290
|
+
if (!prefix) return [];
|
|
291
|
+
if (isLoadingCommands) {
|
|
292
|
+
return [
|
|
293
|
+
{
|
|
294
|
+
value: "loading...",
|
|
295
|
+
displayValue: `\u23F3 Loading system commands...`,
|
|
296
|
+
type: "file",
|
|
297
|
+
score: 0,
|
|
298
|
+
metadata: { isLoading: true }
|
|
299
|
+
}
|
|
300
|
+
];
|
|
275
301
|
}
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
302
|
+
const commonCommands = getCommonSystemCommands(systemCommands);
|
|
303
|
+
const uniqueCommands = Array.from(new Set(commonCommands));
|
|
304
|
+
const matches = matchCommands(uniqueCommands, prefix);
|
|
305
|
+
const boostedMatches = matches.map((match) => {
|
|
306
|
+
const priority = getCommandPriority(match.command);
|
|
307
|
+
return {
|
|
308
|
+
...match,
|
|
309
|
+
score: match.score + priority * 0.5
|
|
310
|
+
// Add priority boost
|
|
311
|
+
};
|
|
312
|
+
}).sort((a, b) => b.score - a.score);
|
|
313
|
+
let results = boostedMatches.slice(0, 8);
|
|
314
|
+
const perfectMatches = boostedMatches.filter((m) => m.score >= 900);
|
|
315
|
+
if (perfectMatches.length > 0 && perfectMatches.length <= 3) {
|
|
316
|
+
results = perfectMatches;
|
|
317
|
+
} else if (boostedMatches.length > 8) {
|
|
318
|
+
const goodMatches = boostedMatches.filter((m) => m.score >= 100);
|
|
319
|
+
if (goodMatches.length <= 5) {
|
|
320
|
+
results = goodMatches;
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
return results.map((item) => ({
|
|
324
|
+
value: item.command,
|
|
325
|
+
displayValue: `$ ${item.command}`,
|
|
326
|
+
type: "command",
|
|
327
|
+
score: item.score,
|
|
328
|
+
metadata: { isUnixCommand: true }
|
|
329
|
+
}));
|
|
330
|
+
},
|
|
331
|
+
[systemCommands, isLoadingCommands]
|
|
332
|
+
);
|
|
333
|
+
const [agentSuggestions, setAgentSuggestions] = useState(
|
|
334
|
+
[]
|
|
335
|
+
);
|
|
336
|
+
const [modelSuggestions, setModelSuggestions] = useState(
|
|
337
|
+
[]
|
|
338
|
+
);
|
|
287
339
|
useEffect(() => {
|
|
288
340
|
try {
|
|
289
341
|
const modelManager = getModelManager();
|
|
@@ -370,260 +422,292 @@ function useUnifiedCompletion({
|
|
|
370
422
|
setAgentSuggestions([]);
|
|
371
423
|
});
|
|
372
424
|
}, []);
|
|
373
|
-
const generateMentionSuggestions = useCallback(
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
425
|
+
const generateMentionSuggestions = useCallback(
|
|
426
|
+
(prefix) => {
|
|
427
|
+
const allSuggestions = [...agentSuggestions, ...modelSuggestions];
|
|
428
|
+
if (!prefix) {
|
|
429
|
+
return allSuggestions.sort((a, b) => {
|
|
430
|
+
if (a.type === "ask" && b.type === "agent") return -1;
|
|
431
|
+
if (a.type === "agent" && b.type === "ask") return 1;
|
|
432
|
+
return b.score - a.score;
|
|
433
|
+
});
|
|
434
|
+
}
|
|
435
|
+
const candidates = allSuggestions.map((s) => s.value);
|
|
436
|
+
const matches = matchCommands(candidates, prefix);
|
|
437
|
+
const fuzzyResults = matches.map((match) => {
|
|
438
|
+
const suggestion = allSuggestions.find(
|
|
439
|
+
(s) => s.value === match.command
|
|
440
|
+
);
|
|
441
|
+
return {
|
|
442
|
+
...suggestion,
|
|
443
|
+
score: match.score
|
|
444
|
+
// Use fuzzy match score instead of simple scoring
|
|
445
|
+
};
|
|
446
|
+
}).sort((a, b) => {
|
|
377
447
|
if (a.type === "ask" && b.type === "agent") return -1;
|
|
378
448
|
if (a.type === "agent" && b.type === "ask") return 1;
|
|
379
449
|
return b.score - a.score;
|
|
380
450
|
});
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
} else if (isAbsolutePath) {
|
|
408
|
-
searchPath = userPath;
|
|
409
|
-
} else {
|
|
410
|
-
searchPath = resolve(cwd, userPath);
|
|
411
|
-
}
|
|
412
|
-
const endsWithSlash = userPath.endsWith("/");
|
|
413
|
-
const searchStat = existsSync(searchPath) ? statSync(searchPath) : null;
|
|
414
|
-
let searchDir;
|
|
415
|
-
let nameFilter;
|
|
416
|
-
if (endsWithSlash || searchStat?.isDirectory()) {
|
|
417
|
-
searchDir = searchPath;
|
|
418
|
-
nameFilter = "";
|
|
419
|
-
} else {
|
|
420
|
-
searchDir = dirname(searchPath);
|
|
421
|
-
nameFilter = basename(searchPath);
|
|
422
|
-
}
|
|
423
|
-
if (!existsSync(searchDir)) return [];
|
|
424
|
-
const showHidden = nameFilter.startsWith(".") || userPath.includes("/.");
|
|
425
|
-
const entries = readdirSync(searchDir).filter((entry) => {
|
|
426
|
-
if (!showHidden && entry.startsWith(".")) return false;
|
|
427
|
-
if (nameFilter && !entry.toLowerCase().startsWith(nameFilter.toLowerCase())) return false;
|
|
428
|
-
return true;
|
|
429
|
-
}).sort((a, b) => {
|
|
430
|
-
const aPath = join(searchDir, a);
|
|
431
|
-
const bPath = join(searchDir, b);
|
|
432
|
-
const aIsDir = statSync(aPath).isDirectory();
|
|
433
|
-
const bIsDir = statSync(bPath).isDirectory();
|
|
434
|
-
if (aIsDir && !bIsDir) return -1;
|
|
435
|
-
if (!aIsDir && bIsDir) return 1;
|
|
436
|
-
return a.toLowerCase().localeCompare(b.toLowerCase());
|
|
437
|
-
}).slice(0, 25);
|
|
438
|
-
return entries.map((entry) => {
|
|
439
|
-
const entryPath = join(searchDir, entry);
|
|
440
|
-
const isDir = statSync(entryPath).isDirectory();
|
|
441
|
-
const icon = isDir ? "\u{1F4C1}" : "\u{1F4C4}";
|
|
442
|
-
let value;
|
|
443
|
-
if (userPath.includes("/")) {
|
|
444
|
-
if (endsWithSlash) {
|
|
445
|
-
value = userPath + entry + (isDir ? "/" : "");
|
|
446
|
-
} else if (searchStat?.isDirectory()) {
|
|
447
|
-
value = userPath + "/" + entry + (isDir ? "/" : "");
|
|
448
|
-
} else {
|
|
449
|
-
const userDir = userPath.includes("/") ? userPath.substring(0, userPath.lastIndexOf("/")) : "";
|
|
450
|
-
value = userDir ? userDir + "/" + entry + (isDir ? "/" : "") : entry + (isDir ? "/" : "");
|
|
451
|
-
}
|
|
451
|
+
return fuzzyResults;
|
|
452
|
+
},
|
|
453
|
+
[agentSuggestions, modelSuggestions]
|
|
454
|
+
);
|
|
455
|
+
const generateFileSuggestions = useCallback(
|
|
456
|
+
(prefix, isAtReference = false) => {
|
|
457
|
+
try {
|
|
458
|
+
const cwd = getCwd();
|
|
459
|
+
const userPath = prefix || ".";
|
|
460
|
+
const isAbsolutePath = userPath.startsWith("/");
|
|
461
|
+
const isHomePath = userPath.startsWith("~");
|
|
462
|
+
let searchPath;
|
|
463
|
+
if (isHomePath) {
|
|
464
|
+
searchPath = userPath.replace("~", process.env.HOME || "");
|
|
465
|
+
} else if (isAbsolutePath) {
|
|
466
|
+
searchPath = userPath;
|
|
467
|
+
} else {
|
|
468
|
+
searchPath = resolve(cwd, userPath);
|
|
469
|
+
}
|
|
470
|
+
const endsWithSlash = userPath.endsWith("/");
|
|
471
|
+
const searchStat = existsSync(searchPath) ? statSync(searchPath) : null;
|
|
472
|
+
let searchDir;
|
|
473
|
+
let nameFilter;
|
|
474
|
+
if (endsWithSlash || searchStat?.isDirectory()) {
|
|
475
|
+
searchDir = searchPath;
|
|
476
|
+
nameFilter = "";
|
|
452
477
|
} else {
|
|
453
|
-
|
|
454
|
-
|
|
478
|
+
searchDir = dirname(searchPath);
|
|
479
|
+
nameFilter = basename(searchPath);
|
|
480
|
+
}
|
|
481
|
+
if (!existsSync(searchDir)) return [];
|
|
482
|
+
const showHidden = nameFilter.startsWith(".") || userPath.includes("/.");
|
|
483
|
+
const entries = readdirSync(searchDir).filter((entry) => {
|
|
484
|
+
if (!showHidden && entry.startsWith(".")) return false;
|
|
485
|
+
if (nameFilter && !entry.toLowerCase().startsWith(nameFilter.toLowerCase()))
|
|
486
|
+
return false;
|
|
487
|
+
return true;
|
|
488
|
+
}).sort((a, b) => {
|
|
489
|
+
const aPath = join(searchDir, a);
|
|
490
|
+
const bPath = join(searchDir, b);
|
|
491
|
+
const aIsDir = statSync(aPath).isDirectory();
|
|
492
|
+
const bIsDir = statSync(bPath).isDirectory();
|
|
493
|
+
if (aIsDir && !bIsDir) return -1;
|
|
494
|
+
if (!aIsDir && bIsDir) return 1;
|
|
495
|
+
return a.toLowerCase().localeCompare(b.toLowerCase());
|
|
496
|
+
}).slice(0, 25);
|
|
497
|
+
return entries.map((entry) => {
|
|
498
|
+
const entryPath = join(searchDir, entry);
|
|
499
|
+
const isDir = statSync(entryPath).isDirectory();
|
|
500
|
+
const icon = isDir ? "\u{1F4C1}" : "\u{1F4C4}";
|
|
501
|
+
let value;
|
|
502
|
+
if (userPath.includes("/")) {
|
|
503
|
+
if (endsWithSlash) {
|
|
504
|
+
value = userPath + entry + (isDir ? "/" : "");
|
|
505
|
+
} else if (searchStat?.isDirectory()) {
|
|
506
|
+
value = userPath + "/" + entry + (isDir ? "/" : "");
|
|
507
|
+
} else {
|
|
508
|
+
const userDir = userPath.includes("/") ? userPath.substring(0, userPath.lastIndexOf("/")) : "";
|
|
509
|
+
value = userDir ? userDir + "/" + entry + (isDir ? "/" : "") : entry + (isDir ? "/" : "");
|
|
510
|
+
}
|
|
455
511
|
} else {
|
|
456
|
-
|
|
512
|
+
if (searchStat?.isDirectory()) {
|
|
513
|
+
value = userPath + "/" + entry + (isDir ? "/" : "");
|
|
514
|
+
} else {
|
|
515
|
+
value = entry + (isDir ? "/" : "");
|
|
516
|
+
}
|
|
457
517
|
}
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
};
|
|
465
|
-
}
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
}
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
} else if (value.includes(lowerPrefix)) {
|
|
480
|
-
matchFound = true;
|
|
481
|
-
score = 95;
|
|
482
|
-
} else if (displayValue.includes(lowerPrefix)) {
|
|
483
|
-
matchFound = true;
|
|
484
|
-
score = 90;
|
|
485
|
-
} else {
|
|
486
|
-
const words = value.split(/[-_]/);
|
|
487
|
-
if (words.some((word) => word.startsWith(lowerPrefix))) {
|
|
518
|
+
return {
|
|
519
|
+
value,
|
|
520
|
+
displayValue: `${icon} ${entry}${isDir ? "/" : ""}`,
|
|
521
|
+
type: "file",
|
|
522
|
+
score: isDir ? 80 : 70
|
|
523
|
+
};
|
|
524
|
+
});
|
|
525
|
+
} catch {
|
|
526
|
+
return [];
|
|
527
|
+
}
|
|
528
|
+
},
|
|
529
|
+
[]
|
|
530
|
+
);
|
|
531
|
+
const calculateMatchScore = useCallback(
|
|
532
|
+
(suggestion, prefix) => {
|
|
533
|
+
const lowerPrefix = prefix.toLowerCase();
|
|
534
|
+
const value = suggestion.value.toLowerCase();
|
|
535
|
+
const displayValue = suggestion.displayValue.toLowerCase();
|
|
536
|
+
let matchFound = false;
|
|
537
|
+
let score = 0;
|
|
538
|
+
if (value.startsWith(lowerPrefix)) {
|
|
488
539
|
matchFound = true;
|
|
489
|
-
score =
|
|
540
|
+
score = 100;
|
|
541
|
+
} else if (value.includes(lowerPrefix)) {
|
|
542
|
+
matchFound = true;
|
|
543
|
+
score = 95;
|
|
544
|
+
} else if (displayValue.includes(lowerPrefix)) {
|
|
545
|
+
matchFound = true;
|
|
546
|
+
score = 90;
|
|
490
547
|
} else {
|
|
491
|
-
const
|
|
492
|
-
if (
|
|
548
|
+
const words = value.split(/[-_]/);
|
|
549
|
+
if (words.some((word) => word.startsWith(lowerPrefix))) {
|
|
493
550
|
matchFound = true;
|
|
494
|
-
score =
|
|
551
|
+
score = 93;
|
|
552
|
+
} else {
|
|
553
|
+
const acronym = words.map((word) => word[0]).join("");
|
|
554
|
+
if (acronym.startsWith(lowerPrefix)) {
|
|
555
|
+
matchFound = true;
|
|
556
|
+
score = 88;
|
|
557
|
+
}
|
|
495
558
|
}
|
|
496
559
|
}
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
const
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
// Only modify display for clarity, keep value clean
|
|
515
|
-
displayValue: `\u{1F3AF} ${suggestion.displayValue}`
|
|
516
|
-
};
|
|
517
|
-
}).filter(Boolean).sort((a, b) => b.score - a.score).slice(0, 5);
|
|
518
|
-
}, [agentSuggestions, modelSuggestions, calculateMatchScore]);
|
|
519
|
-
const generateSuggestions = useCallback((context) => {
|
|
520
|
-
switch (context.type) {
|
|
521
|
-
case "command":
|
|
522
|
-
return generateCommandSuggestions(context.prefix);
|
|
523
|
-
case "agent": {
|
|
524
|
-
const mentionSuggestions = generateMentionSuggestions(context.prefix);
|
|
525
|
-
const fileSuggestions = generateFileSuggestions(context.prefix, true);
|
|
526
|
-
const weightedSuggestions = [
|
|
527
|
-
...mentionSuggestions.map((s) => ({
|
|
528
|
-
...s,
|
|
529
|
-
// In @ context, agents/models get high priority
|
|
530
|
-
weightedScore: s.score + 150
|
|
531
|
-
})),
|
|
532
|
-
...fileSuggestions.map((s) => ({
|
|
533
|
-
...s,
|
|
534
|
-
// Files get lower priority but still visible
|
|
535
|
-
weightedScore: s.score + 10
|
|
536
|
-
// Small boost to ensure visibility
|
|
537
|
-
}))
|
|
538
|
-
];
|
|
539
|
-
return weightedSuggestions.sort((a, b) => b.weightedScore - a.weightedScore).map(({ weightedScore, ...suggestion }) => suggestion);
|
|
540
|
-
}
|
|
541
|
-
case "file": {
|
|
542
|
-
const fileSuggestions = generateFileSuggestions(context.prefix, false);
|
|
543
|
-
const unixSuggestions = generateUnixCommandSuggestions(context.prefix);
|
|
544
|
-
const mentionMatches = generateMentionSuggestions(context.prefix).map((s) => ({
|
|
545
|
-
...s,
|
|
560
|
+
if (!matchFound) return 0;
|
|
561
|
+
if (suggestion.type === "ask") score += 2;
|
|
562
|
+
if (suggestion.type === "agent") score += 1;
|
|
563
|
+
return score;
|
|
564
|
+
},
|
|
565
|
+
[]
|
|
566
|
+
);
|
|
567
|
+
const generateSmartMentionSuggestions = useCallback(
|
|
568
|
+
(prefix, sourceContext = "file") => {
|
|
569
|
+
if (!prefix || prefix.length < 2) return [];
|
|
570
|
+
const allSuggestions = [...agentSuggestions, ...modelSuggestions];
|
|
571
|
+
return allSuggestions.map((suggestion) => {
|
|
572
|
+
const matchScore = calculateMatchScore(suggestion, prefix);
|
|
573
|
+
if (matchScore === 0) return null;
|
|
574
|
+
return {
|
|
575
|
+
...suggestion,
|
|
576
|
+
score: matchScore,
|
|
546
577
|
isSmartMatch: true,
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
}
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
return
|
|
577
|
-
}
|
|
578
|
-
|
|
578
|
+
originalContext: sourceContext,
|
|
579
|
+
// Only modify display for clarity, keep value clean
|
|
580
|
+
displayValue: `\u{1F3AF} ${suggestion.displayValue}`
|
|
581
|
+
};
|
|
582
|
+
}).filter(Boolean).sort((a, b) => b.score - a.score).slice(0, 5);
|
|
583
|
+
},
|
|
584
|
+
[agentSuggestions, modelSuggestions, calculateMatchScore]
|
|
585
|
+
);
|
|
586
|
+
const generateSuggestions = useCallback(
|
|
587
|
+
(context) => {
|
|
588
|
+
switch (context.type) {
|
|
589
|
+
case "command":
|
|
590
|
+
return generateCommandSuggestions(context.prefix);
|
|
591
|
+
case "agent": {
|
|
592
|
+
const mentionSuggestions = generateMentionSuggestions(context.prefix);
|
|
593
|
+
const fileSuggestions = generateFileSuggestions(context.prefix, true);
|
|
594
|
+
const weightedSuggestions = [
|
|
595
|
+
...mentionSuggestions.map((s) => ({
|
|
596
|
+
...s,
|
|
597
|
+
// In @ context, agents/models get high priority
|
|
598
|
+
weightedScore: s.score + 150
|
|
599
|
+
})),
|
|
600
|
+
...fileSuggestions.map((s) => ({
|
|
601
|
+
...s,
|
|
602
|
+
// Files get lower priority but still visible
|
|
603
|
+
weightedScore: s.score + 10
|
|
604
|
+
// Small boost to ensure visibility
|
|
605
|
+
}))
|
|
606
|
+
];
|
|
607
|
+
return weightedSuggestions.sort((a, b) => b.weightedScore - a.weightedScore).map(({ weightedScore, ...suggestion }) => suggestion);
|
|
608
|
+
}
|
|
609
|
+
case "file": {
|
|
610
|
+
const fileSuggestions = generateFileSuggestions(context.prefix, false);
|
|
611
|
+
const unixSuggestions = generateUnixCommandSuggestions(context.prefix);
|
|
612
|
+
const mentionMatches = generateMentionSuggestions(context.prefix).map(
|
|
613
|
+
(s) => ({
|
|
614
|
+
...s,
|
|
615
|
+
isSmartMatch: true,
|
|
616
|
+
// Show that @ will be added when selected
|
|
617
|
+
displayValue: `\u2192 ${s.displayValue}`
|
|
618
|
+
// Arrow to indicate it will transform
|
|
619
|
+
})
|
|
620
|
+
);
|
|
621
|
+
const weightedSuggestions = [
|
|
622
|
+
...unixSuggestions.map((s) => ({
|
|
623
|
+
...s,
|
|
624
|
+
// Unix commands get boost, but exact matches get huge boost
|
|
625
|
+
sourceWeight: s.score >= 1e4 ? 5e3 : 200,
|
|
626
|
+
// Exact match gets massive boost
|
|
627
|
+
weightedScore: s.score >= 1e4 ? s.score + 5e3 : s.score + 200
|
|
628
|
+
})),
|
|
629
|
+
...mentionMatches.map((s) => ({
|
|
630
|
+
...s,
|
|
631
|
+
// Agents/models get medium priority boost (but less to avoid overriding exact Unix)
|
|
632
|
+
sourceWeight: 50,
|
|
633
|
+
weightedScore: s.score + 50
|
|
634
|
+
})),
|
|
635
|
+
...fileSuggestions.map((s) => ({
|
|
636
|
+
...s,
|
|
637
|
+
// Files get no boost (baseline)
|
|
638
|
+
sourceWeight: 0,
|
|
639
|
+
weightedScore: s.score
|
|
640
|
+
}))
|
|
641
|
+
];
|
|
642
|
+
const seen = /* @__PURE__ */ new Set();
|
|
643
|
+
const deduplicatedResults = weightedSuggestions.sort((a, b) => b.weightedScore - a.weightedScore).filter((item) => {
|
|
644
|
+
if (seen.has(item.value)) return false;
|
|
645
|
+
seen.add(item.value);
|
|
646
|
+
return true;
|
|
647
|
+
}).map(({ weightedScore, sourceWeight, ...suggestion }) => suggestion);
|
|
648
|
+
return deduplicatedResults;
|
|
649
|
+
}
|
|
650
|
+
default:
|
|
651
|
+
return [];
|
|
579
652
|
}
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
653
|
+
},
|
|
654
|
+
[
|
|
655
|
+
generateCommandSuggestions,
|
|
656
|
+
generateMentionSuggestions,
|
|
657
|
+
generateFileSuggestions,
|
|
658
|
+
generateUnixCommandSuggestions,
|
|
659
|
+
generateSmartMentionSuggestions
|
|
660
|
+
]
|
|
661
|
+
);
|
|
662
|
+
const completeWith = useCallback(
|
|
663
|
+
(suggestion, context) => {
|
|
664
|
+
let completion;
|
|
665
|
+
if (context.type === "command") {
|
|
666
|
+
completion = `/${suggestion.value} `;
|
|
667
|
+
} else if (context.type === "agent") {
|
|
668
|
+
if (suggestion.type === "agent") {
|
|
669
|
+
completion = `@${suggestion.value} `;
|
|
670
|
+
} else if (suggestion.type === "ask") {
|
|
671
|
+
completion = `@${suggestion.value} `;
|
|
672
|
+
} else {
|
|
673
|
+
const isDirectory = suggestion.value.endsWith("/");
|
|
674
|
+
completion = `@${suggestion.value}${isDirectory ? "" : " "}`;
|
|
675
|
+
}
|
|
593
676
|
} else {
|
|
594
|
-
|
|
595
|
-
|
|
677
|
+
if (suggestion.isSmartMatch) {
|
|
678
|
+
completion = `@${suggestion.value} `;
|
|
679
|
+
} else {
|
|
680
|
+
const isDirectory = suggestion.value.endsWith("/");
|
|
681
|
+
completion = suggestion.value + (isDirectory ? "" : " ");
|
|
682
|
+
}
|
|
596
683
|
}
|
|
597
|
-
|
|
598
|
-
if (suggestion.isSmartMatch) {
|
|
599
|
-
|
|
684
|
+
let actualEndPos;
|
|
685
|
+
if (context.type === "file" && suggestion.value.startsWith("/") && !suggestion.isSmartMatch) {
|
|
686
|
+
let end = context.startPos;
|
|
687
|
+
while (end < input.length && input[end] !== " " && input[end] !== "\n") {
|
|
688
|
+
end++;
|
|
689
|
+
}
|
|
690
|
+
actualEndPos = end;
|
|
600
691
|
} else {
|
|
601
|
-
const
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
}
|
|
605
|
-
let actualEndPos;
|
|
606
|
-
if (context.type === "file" && suggestion.value.startsWith("/") && !suggestion.isSmartMatch) {
|
|
607
|
-
let end = context.startPos;
|
|
608
|
-
while (end < input.length && input[end] !== " " && input[end] !== "\n") {
|
|
609
|
-
end++;
|
|
692
|
+
const currentWord = input.slice(context.startPos);
|
|
693
|
+
const nextSpaceIndex = currentWord.indexOf(" ");
|
|
694
|
+
actualEndPos = nextSpaceIndex === -1 ? input.length : context.startPos + nextSpaceIndex;
|
|
610
695
|
}
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
onInputChange
|
|
625
|
-
|
|
626
|
-
}, [input, onInputChange, setCursorOffset]);
|
|
696
|
+
const newInput = input.slice(0, context.startPos) + completion + input.slice(actualEndPos);
|
|
697
|
+
onInputChange(newInput);
|
|
698
|
+
setCursorOffset(context.startPos + completion.length);
|
|
699
|
+
},
|
|
700
|
+
[input, onInputChange, setCursorOffset, onSubmit, commands]
|
|
701
|
+
);
|
|
702
|
+
const partialComplete = useCallback(
|
|
703
|
+
(prefix, context) => {
|
|
704
|
+
const completion = context.type === "command" ? `/${prefix}` : context.type === "agent" ? `@${prefix}` : prefix;
|
|
705
|
+
const newInput = input.slice(0, context.startPos) + completion + input.slice(context.endPos);
|
|
706
|
+
onInputChange(newInput);
|
|
707
|
+
setCursorOffset(context.startPos + completion.length);
|
|
708
|
+
},
|
|
709
|
+
[input, onInputChange, setCursorOffset]
|
|
710
|
+
);
|
|
627
711
|
useInput((input_str, key) => {
|
|
628
712
|
if (!key.tab) return false;
|
|
629
713
|
if (key.shift) return false;
|
|
@@ -654,7 +738,10 @@ function useUnifiedCompletion({
|
|
|
654
738
|
preview: {
|
|
655
739
|
isActive: true,
|
|
656
740
|
originalInput: input,
|
|
657
|
-
wordRange: [
|
|
741
|
+
wordRange: [
|
|
742
|
+
state.context.startPos,
|
|
743
|
+
state.context.startPos + preview.length
|
|
744
|
+
]
|
|
658
745
|
}
|
|
659
746
|
});
|
|
660
747
|
}
|
|
@@ -736,7 +823,10 @@ function useUnifiedCompletion({
|
|
|
736
823
|
selectedIndex: newIndex,
|
|
737
824
|
preview: {
|
|
738
825
|
...state.preview,
|
|
739
|
-
wordRange: [
|
|
826
|
+
wordRange: [
|
|
827
|
+
state.context.startPos,
|
|
828
|
+
state.context.startPos + preview.length
|
|
829
|
+
]
|
|
740
830
|
}
|
|
741
831
|
});
|
|
742
832
|
} else {
|
|
@@ -843,9 +933,12 @@ function useUnifiedCompletion({
|
|
|
843
933
|
const lastInputRef = useRef("");
|
|
844
934
|
useEffect(() => {
|
|
845
935
|
if (lastInputRef.current === input) return;
|
|
846
|
-
const inputLengthChange = Math.abs(
|
|
936
|
+
const inputLengthChange = Math.abs(
|
|
937
|
+
input.length - lastInputRef.current.length
|
|
938
|
+
);
|
|
847
939
|
const isHistoryNavigation = (inputLengthChange > 10 || // Large content change
|
|
848
|
-
inputLengthChange > 5 && !input.includes(lastInputRef.current.slice(-5))) &&
|
|
940
|
+
inputLengthChange > 5 && !input.includes(lastInputRef.current.slice(-5))) && // Different content
|
|
941
|
+
input !== lastInputRef.current;
|
|
849
942
|
lastInputRef.current = input;
|
|
850
943
|
if (state.preview?.isActive || Date.now() < state.suppressUntil) {
|
|
851
944
|
return;
|
|
@@ -871,51 +964,57 @@ function useUnifiedCompletion({
|
|
|
871
964
|
}
|
|
872
965
|
}
|
|
873
966
|
}, [input, cursorOffset]);
|
|
874
|
-
const shouldAutoTrigger = useCallback(
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
case "agent":
|
|
879
|
-
return true;
|
|
880
|
-
case "file":
|
|
881
|
-
const prefix = context.prefix;
|
|
882
|
-
if (prefix.startsWith("./") || prefix.startsWith("../") || prefix.startsWith("/") || prefix.startsWith("~") || prefix.includes("/")) {
|
|
967
|
+
const shouldAutoTrigger = useCallback(
|
|
968
|
+
(context) => {
|
|
969
|
+
switch (context.type) {
|
|
970
|
+
case "command":
|
|
883
971
|
return true;
|
|
972
|
+
case "agent":
|
|
973
|
+
return true;
|
|
974
|
+
case "file":
|
|
975
|
+
const prefix = context.prefix;
|
|
976
|
+
if (prefix.startsWith("./") || prefix.startsWith("../") || prefix.startsWith("/") || prefix.startsWith("~") || prefix.includes("/")) {
|
|
977
|
+
return true;
|
|
978
|
+
}
|
|
979
|
+
if (prefix.startsWith(".") && prefix.length >= 2) {
|
|
980
|
+
return true;
|
|
981
|
+
}
|
|
982
|
+
return false;
|
|
983
|
+
default:
|
|
984
|
+
return false;
|
|
985
|
+
}
|
|
986
|
+
},
|
|
987
|
+
[]
|
|
988
|
+
);
|
|
989
|
+
const shouldAutoHideSingleMatch = useCallback(
|
|
990
|
+
(suggestion, context) => {
|
|
991
|
+
const currentInput = input.slice(context.startPos, context.endPos);
|
|
992
|
+
if (context.type === "file") {
|
|
993
|
+
if (suggestion.value.endsWith("/")) {
|
|
994
|
+
return false;
|
|
884
995
|
}
|
|
885
|
-
if (
|
|
996
|
+
if (currentInput === suggestion.value) {
|
|
997
|
+
return true;
|
|
998
|
+
}
|
|
999
|
+
if (currentInput.endsWith("/" + suggestion.value) || currentInput.endsWith(suggestion.value)) {
|
|
886
1000
|
return true;
|
|
887
1001
|
}
|
|
888
|
-
return false;
|
|
889
|
-
default:
|
|
890
|
-
return false;
|
|
891
|
-
}
|
|
892
|
-
}, []);
|
|
893
|
-
const shouldAutoHideSingleMatch = useCallback((suggestion, context) => {
|
|
894
|
-
const currentInput = input.slice(context.startPos, context.endPos);
|
|
895
|
-
if (context.type === "file") {
|
|
896
|
-
if (suggestion.value.endsWith("/")) {
|
|
897
1002
|
return false;
|
|
898
1003
|
}
|
|
899
|
-
if (
|
|
900
|
-
|
|
1004
|
+
if (context.type === "command") {
|
|
1005
|
+
const fullCommand = `/${suggestion.value}`;
|
|
1006
|
+
const matches = currentInput === fullCommand;
|
|
1007
|
+
return matches;
|
|
901
1008
|
}
|
|
902
|
-
if (
|
|
903
|
-
|
|
1009
|
+
if (context.type === "agent") {
|
|
1010
|
+
const fullAgent = `@${suggestion.value}`;
|
|
1011
|
+
const matches = currentInput === fullAgent;
|
|
1012
|
+
return matches;
|
|
904
1013
|
}
|
|
905
1014
|
return false;
|
|
906
|
-
}
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
const matches = currentInput === fullCommand;
|
|
910
|
-
return matches;
|
|
911
|
-
}
|
|
912
|
-
if (context.type === "agent") {
|
|
913
|
-
const fullAgent = `@${suggestion.value}`;
|
|
914
|
-
const matches = currentInput === fullAgent;
|
|
915
|
-
return matches;
|
|
916
|
-
}
|
|
917
|
-
return false;
|
|
918
|
-
}, [input]);
|
|
1015
|
+
},
|
|
1016
|
+
[input]
|
|
1017
|
+
);
|
|
919
1018
|
return {
|
|
920
1019
|
suggestions,
|
|
921
1020
|
selectedIndex,
|