@defai.digital/ax-cli 3.12.10 → 3.13.1
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 +17 -5
- package/dist/agent/loop-detector.d.ts +2 -0
- package/dist/agent/loop-detector.js +11 -15
- package/dist/agent/loop-detector.js.map +1 -1
- package/dist/agent/subagent.js +3 -3
- package/dist/agent/subagent.js.map +1 -1
- package/dist/analyzers/git/churn-calculator.js +4 -1
- package/dist/analyzers/git/churn-calculator.js.map +1 -1
- package/dist/constants.js +1 -1
- package/dist/hooks/hook-runner.js +1 -1
- package/dist/hooks/hook-runner.js.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/llm/tools.d.ts +39 -0
- package/dist/llm/tools.js +55 -0
- package/dist/llm/tools.js.map +1 -1
- package/dist/mcp/client-v2.d.ts +43 -0
- package/dist/mcp/client-v2.js +96 -0
- package/dist/mcp/client-v2.js.map +1 -1
- package/dist/mcp/client.d.ts +27 -0
- package/dist/mcp/client.js +24 -0
- package/dist/mcp/client.js.map +1 -1
- package/dist/mcp/error-formatter.js +219 -33
- package/dist/mcp/error-formatter.js.map +1 -1
- package/dist/mcp/index.d.ts +3 -1
- package/dist/mcp/index.js +3 -0
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp/prompts.d.ts +68 -0
- package/dist/mcp/prompts.js +129 -0
- package/dist/mcp/prompts.js.map +1 -0
- package/dist/mcp/resources.d.ts +1 -0
- package/dist/mcp/resources.js +9 -2
- package/dist/mcp/resources.js.map +1 -1
- package/dist/planner/task-planner.js +2 -2
- package/dist/planner/task-planner.js.map +1 -1
- package/dist/sdk/index.d.ts +5 -1
- package/dist/sdk/index.js +9 -1
- package/dist/sdk/index.js.map +1 -1
- package/dist/tools/ask-user.js +2 -1
- package/dist/tools/ask-user.js.map +1 -1
- package/dist/tools/bash.js +4 -5
- package/dist/tools/bash.js.map +1 -1
- package/dist/ui/components/chat-history.js +2 -63
- package/dist/ui/components/chat-history.js.map +1 -1
- package/dist/ui/components/chat-interface.js +11 -5
- package/dist/ui/components/chat-interface.js.map +1 -1
- package/dist/ui/components/collapsible-tool-result.d.ts +12 -0
- package/dist/ui/components/collapsible-tool-result.js +56 -50
- package/dist/ui/components/collapsible-tool-result.js.map +1 -1
- package/dist/ui/components/mcp-dashboard.d.ts +15 -0
- package/dist/ui/components/mcp-dashboard.js +520 -0
- package/dist/ui/components/mcp-dashboard.js.map +1 -0
- package/dist/ui/components/mcp-status.js +37 -15
- package/dist/ui/components/mcp-status.js.map +1 -1
- package/dist/ui/components/phase-progress.js +26 -69
- package/dist/ui/components/phase-progress.js.map +1 -1
- package/dist/ui/components/status-bar.d.ts +8 -0
- package/dist/ui/components/status-bar.js +53 -19
- package/dist/ui/components/status-bar.js.map +1 -1
- package/dist/ui/components/subagent-monitor.js +2 -25
- package/dist/ui/components/subagent-monitor.js.map +1 -1
- package/dist/ui/components/toast-notification.js +9 -14
- package/dist/ui/components/toast-notification.js.map +1 -1
- package/dist/ui/components/tool-group-display.js +8 -4
- package/dist/ui/components/tool-group-display.js.map +1 -1
- package/dist/ui/components/virtualized-chat-history.js +1 -44
- package/dist/ui/components/virtualized-chat-history.js.map +1 -1
- package/dist/ui/hooks/use-enhanced-input.js +10 -11
- package/dist/ui/hooks/use-enhanced-input.js.map +1 -1
- package/dist/ui/hooks/use-input-handler.d.ts +5 -1
- package/dist/ui/hooks/use-input-handler.js +277 -14
- package/dist/ui/hooks/use-input-handler.js.map +1 -1
- package/dist/ui/utils/change-summarizer.js +25 -11
- package/dist/ui/utils/change-summarizer.js.map +1 -1
- package/dist/ui/utils/semantic-action-detector.js +33 -30
- package/dist/ui/utils/semantic-action-detector.js.map +1 -1
- package/dist/ui/utils/tool-grouper.d.ts +4 -0
- package/dist/ui/utils/tool-grouper.js +71 -67
- package/dist/ui/utils/tool-grouper.js.map +1 -1
- package/eslint.config.js +2 -0
- package/package.json +2 -2
|
@@ -20,14 +20,21 @@ import { openExternalEditor, getPreferredEditor, getEditorDisplayName } from "..
|
|
|
20
20
|
import { extractErrorMessage } from "../../utils/error-handler.js";
|
|
21
21
|
import { getCustomCommandsManager } from "../../commands/custom-commands.js";
|
|
22
22
|
import { getHooksManager } from "../../hooks/index.js";
|
|
23
|
+
import { getMCPPrompts, getMCPManager, getMCPResources } from "../../llm/tools.js";
|
|
24
|
+
import { promptToSlashCommand, parsePromptCommand, formatPromptResult, getPromptDescription } from "../../mcp/prompts.js";
|
|
25
|
+
import { getPermissionManager, PermissionTier } from "../../permissions/permission-manager.js";
|
|
23
26
|
import { parseFileMentions } from "../../utils/file-mentions.js";
|
|
24
27
|
import * as fs from "fs";
|
|
25
28
|
import * as path from "path";
|
|
26
29
|
export function useInputHandler({ agent, chatHistory, setChatHistory, setIsProcessing, setIsStreaming, setTokenCount, setProcessingTime, processingStartTime, isProcessing, isStreaming, isConfirmationActive = false, onQuickActionsToggle, onVerboseModeChange, onBackgroundModeChange, onAutoEditModeChange, onTaskMovedToBackground, onOperationInterrupted, onChatCleared, onCopyLastResponse, onMemoryWarmed, onMemoryRefreshed, onCheckpointCreated: _onCheckpointCreated, // Reserved for future checkpoint UI
|
|
27
30
|
onCheckpointRestored: _onCheckpointRestored, // Reserved for future checkpoint UI
|
|
28
|
-
onLargePaste, onPasteTruncated, onKeyboardHelp, onThinkingModeChange, onEditorOpening, onEditorSuccess, onEditorCancelled, onEditorError, }) {
|
|
31
|
+
onLargePaste, onPasteTruncated, onKeyboardHelp, onMcpDashboardToggle, onThinkingModeChange, onEditorOpening, onEditorSuccess, onEditorCancelled, onEditorError, }) {
|
|
29
32
|
const [showCommandSuggestions, setShowCommandSuggestions] = useState(false);
|
|
30
33
|
const [selectedCommandIndex, setSelectedCommandIndex] = useState(0);
|
|
34
|
+
const [resourceSuggestions, setResourceSuggestions] = useState([]);
|
|
35
|
+
const [suggestionMode, setSuggestionMode] = useState("command");
|
|
36
|
+
// BUG FIX: Track current MCP query to prevent race condition with stale async results
|
|
37
|
+
const currentMcpQueryRef = useRef(null);
|
|
31
38
|
const retryTimeoutRef = useRef(null);
|
|
32
39
|
const [autoEditEnabled, setAutoEditEnabled] = useState(() => {
|
|
33
40
|
const confirmationService = ConfirmationService.getInstance();
|
|
@@ -69,6 +76,11 @@ onLargePaste, onPasteTruncated, onKeyboardHelp, onThinkingModeChange, onEditorOp
|
|
|
69
76
|
if (showCommandSuggestions) {
|
|
70
77
|
setShowCommandSuggestions(false);
|
|
71
78
|
setSelectedCommandIndex(0);
|
|
79
|
+
// Reset resource mode if active
|
|
80
|
+
if (suggestionMode === "resource") {
|
|
81
|
+
setResourceSuggestions([]);
|
|
82
|
+
setSuggestionMode("command");
|
|
83
|
+
}
|
|
72
84
|
return true;
|
|
73
85
|
}
|
|
74
86
|
if (isProcessing || isStreaming) {
|
|
@@ -84,33 +96,51 @@ onLargePaste, onPasteTruncated, onKeyboardHelp, onThinkingModeChange, onEditorOp
|
|
|
84
96
|
}
|
|
85
97
|
return false; // Let default escape handling work
|
|
86
98
|
}
|
|
87
|
-
// Handle command suggestions navigation
|
|
99
|
+
// Handle command/resource suggestions navigation
|
|
88
100
|
if (showCommandSuggestions) {
|
|
89
|
-
|
|
90
|
-
|
|
101
|
+
// Get appropriate suggestions based on mode
|
|
102
|
+
const currentSuggestions = suggestionMode === "resource"
|
|
103
|
+
? resourceSuggestions.map((r) => ({ command: r.reference, description: r.description || r.name }))
|
|
104
|
+
: filterCommandSuggestions(commandSuggestions, input);
|
|
105
|
+
if (currentSuggestions.length === 0) {
|
|
91
106
|
setShowCommandSuggestions(false);
|
|
92
107
|
setSelectedCommandIndex(0);
|
|
93
108
|
return false; // Continue processing
|
|
94
109
|
}
|
|
95
110
|
else {
|
|
96
111
|
if (key.upArrow) {
|
|
97
|
-
setSelectedCommandIndex((prev) => prev === 0 ?
|
|
112
|
+
setSelectedCommandIndex((prev) => prev === 0 ? currentSuggestions.length - 1 : prev - 1);
|
|
98
113
|
return true;
|
|
99
114
|
}
|
|
100
115
|
if (key.downArrow) {
|
|
101
|
-
setSelectedCommandIndex((prev) => (prev + 1) %
|
|
116
|
+
setSelectedCommandIndex((prev) => (prev + 1) % currentSuggestions.length);
|
|
102
117
|
return true;
|
|
103
118
|
}
|
|
104
119
|
if (key.tab || key.return) {
|
|
105
120
|
// Check if there are any suggestions available
|
|
106
|
-
if (
|
|
121
|
+
if (currentSuggestions.length === 0) {
|
|
107
122
|
return true; // No suggestions, do nothing
|
|
108
123
|
}
|
|
109
|
-
const safeIndex = Math.min(selectedCommandIndex,
|
|
110
|
-
const
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
124
|
+
const safeIndex = Math.min(selectedCommandIndex, currentSuggestions.length - 1);
|
|
125
|
+
const selected = currentSuggestions[safeIndex];
|
|
126
|
+
if (suggestionMode === "resource") {
|
|
127
|
+
// Replace @mcp:partial with the full reference
|
|
128
|
+
const mcpMatch = input.match(/@mcp:[^\s]*$/);
|
|
129
|
+
if (mcpMatch) {
|
|
130
|
+
const newInput = input.replace(/@mcp:[^\s]*$/, selected.command + " ");
|
|
131
|
+
setInput(newInput);
|
|
132
|
+
setCursorPosition(newInput.length);
|
|
133
|
+
}
|
|
134
|
+
// Reset resource mode
|
|
135
|
+
setResourceSuggestions([]);
|
|
136
|
+
setSuggestionMode("command");
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
// Command suggestion - replace entire input
|
|
140
|
+
const newInput = selected.command + " ";
|
|
141
|
+
setInput(newInput);
|
|
142
|
+
setCursorPosition(newInput.length);
|
|
143
|
+
}
|
|
114
144
|
setShowCommandSuggestions(false);
|
|
115
145
|
setSelectedCommandIndex(0);
|
|
116
146
|
return true;
|
|
@@ -132,6 +162,41 @@ onLargePaste, onPasteTruncated, onKeyboardHelp, onThinkingModeChange, onEditorOp
|
|
|
132
162
|
}
|
|
133
163
|
};
|
|
134
164
|
const handleInputChange = useCallback((newInput) => {
|
|
165
|
+
// Check for @mcp: resource auto-complete
|
|
166
|
+
const mcpMatch = newInput.match(/@mcp:([^\s]*)$/);
|
|
167
|
+
if (mcpMatch) {
|
|
168
|
+
const query = mcpMatch[1].toLowerCase();
|
|
169
|
+
// BUG FIX: Track current query to prevent race condition
|
|
170
|
+
// If user types faster than async completes, stale results are discarded
|
|
171
|
+
currentMcpQueryRef.current = query;
|
|
172
|
+
// Load resources asynchronously
|
|
173
|
+
getMCPResources().then((resources) => {
|
|
174
|
+
// BUG FIX: Only apply results if query hasn't changed (prevents stale suggestions)
|
|
175
|
+
if (currentMcpQueryRef.current !== query) {
|
|
176
|
+
return; // Query changed, discard stale results
|
|
177
|
+
}
|
|
178
|
+
const filtered = resources.filter((r) => r.reference.toLowerCase().includes(query) ||
|
|
179
|
+
r.name.toLowerCase().includes(query) ||
|
|
180
|
+
(r.description && r.description.toLowerCase().includes(query)));
|
|
181
|
+
setResourceSuggestions(filtered);
|
|
182
|
+
setSuggestionMode("resource");
|
|
183
|
+
setShowCommandSuggestions(true);
|
|
184
|
+
setSelectedCommandIndex(0);
|
|
185
|
+
}).catch(() => {
|
|
186
|
+
// Only clear if this is still the current query
|
|
187
|
+
if (currentMcpQueryRef.current === query) {
|
|
188
|
+
setResourceSuggestions([]);
|
|
189
|
+
}
|
|
190
|
+
});
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
// Reset resource mode if it was active but no longer matches
|
|
194
|
+
// BUG FIX: Also clear the query ref when leaving resource mode
|
|
195
|
+
if (suggestionMode === "resource") {
|
|
196
|
+
currentMcpQueryRef.current = null;
|
|
197
|
+
setResourceSuggestions([]);
|
|
198
|
+
setSuggestionMode("command");
|
|
199
|
+
}
|
|
135
200
|
// Update command suggestions based on input
|
|
136
201
|
if (newInput.startsWith("/")) {
|
|
137
202
|
setShowCommandSuggestions(true);
|
|
@@ -141,7 +206,7 @@ onLargePaste, onPasteTruncated, onKeyboardHelp, onThinkingModeChange, onEditorOp
|
|
|
141
206
|
setShowCommandSuggestions(false);
|
|
142
207
|
setSelectedCommandIndex(0);
|
|
143
208
|
}
|
|
144
|
-
}, []);
|
|
209
|
+
}, [suggestionMode]);
|
|
145
210
|
const handleVerboseToggle = useCallback(() => {
|
|
146
211
|
// Cycle through verbosity levels: QUIET -> CONCISE -> VERBOSE -> QUIET
|
|
147
212
|
setVerbosityLevel((prev) => {
|
|
@@ -265,6 +330,8 @@ onLargePaste, onPasteTruncated, onKeyboardHelp, onThinkingModeChange, onEditorOp
|
|
|
265
330
|
{ command: "/init", description: "Initialize project with smart analysis" },
|
|
266
331
|
{ command: "/usage", description: "Show API usage statistics" },
|
|
267
332
|
{ command: "/doctor", description: "Run health check diagnostics" },
|
|
333
|
+
{ command: "/mcp", description: "Open MCP server dashboard" },
|
|
334
|
+
{ command: "/permissions", description: "View/manage tool permissions" },
|
|
268
335
|
{ command: "/tasks", description: "List background tasks" },
|
|
269
336
|
{ command: "/task", description: "View output of a background task" },
|
|
270
337
|
{ command: "/kill", description: "Kill a background task" },
|
|
@@ -291,7 +358,13 @@ onLargePaste, onPasteTruncated, onKeyboardHelp, onThinkingModeChange, onEditorOp
|
|
|
291
358
|
command: `/${cmd.name}`,
|
|
292
359
|
description: `${cmd.description} [${cmd.scope}]`,
|
|
293
360
|
}));
|
|
294
|
-
|
|
361
|
+
// Add MCP prompts as slash commands
|
|
362
|
+
const mcpPrompts = getMCPPrompts();
|
|
363
|
+
const mcpPromptSuggestions = mcpPrompts.map((prompt) => ({
|
|
364
|
+
command: promptToSlashCommand(prompt),
|
|
365
|
+
description: getPromptDescription(prompt),
|
|
366
|
+
}));
|
|
367
|
+
return [...builtIn, ...customSuggestions, ...mcpPromptSuggestions];
|
|
295
368
|
}, [customCommandsManager]);
|
|
296
369
|
// Load models from configuration with fallback to defaults
|
|
297
370
|
const availableModels = useMemo(() => {
|
|
@@ -626,6 +699,7 @@ Built-in Commands:
|
|
|
626
699
|
/shortcuts - Show keyboard shortcuts guide
|
|
627
700
|
/usage - Show API usage statistics
|
|
628
701
|
/doctor - Run health check diagnostics
|
|
702
|
+
/mcp - Open MCP server dashboard
|
|
629
703
|
/exit - Exit application
|
|
630
704
|
exit, quit - Exit application
|
|
631
705
|
|
|
@@ -819,6 +893,193 @@ Examples:
|
|
|
819
893
|
clearInput();
|
|
820
894
|
return true;
|
|
821
895
|
}
|
|
896
|
+
// MCP Dashboard command
|
|
897
|
+
if (trimmedInput === "/mcp") {
|
|
898
|
+
if (onMcpDashboardToggle) {
|
|
899
|
+
onMcpDashboardToggle();
|
|
900
|
+
}
|
|
901
|
+
clearInput();
|
|
902
|
+
return true;
|
|
903
|
+
}
|
|
904
|
+
// Permissions management command
|
|
905
|
+
if (trimmedInput === "/permissions" || trimmedInput.startsWith("/permissions ")) {
|
|
906
|
+
const args = trimmedInput.replace("/permissions", "").trim();
|
|
907
|
+
const permManager = getPermissionManager();
|
|
908
|
+
const config = permManager.getConfig();
|
|
909
|
+
if (!args || args === "show" || args === "list") {
|
|
910
|
+
// Show current permissions configuration
|
|
911
|
+
const permissionLines = [
|
|
912
|
+
"**Permission Configuration**\n",
|
|
913
|
+
`Default Tier: **${config.permissions.default_tier}**\n`,
|
|
914
|
+
"\n**Tool Permissions:**\n",
|
|
915
|
+
];
|
|
916
|
+
const tierEmoji = {
|
|
917
|
+
[PermissionTier.AutoApprove]: "✅",
|
|
918
|
+
[PermissionTier.Notify]: "🔔",
|
|
919
|
+
[PermissionTier.Confirm]: "⚠️",
|
|
920
|
+
[PermissionTier.Block]: "🚫",
|
|
921
|
+
};
|
|
922
|
+
for (const [tool, toolConfig] of Object.entries(config.permissions.tools)) {
|
|
923
|
+
const emoji = tierEmoji[toolConfig.tier] || "❓";
|
|
924
|
+
permissionLines.push(`- ${emoji} **${tool}**: ${toolConfig.tier}\n`);
|
|
925
|
+
}
|
|
926
|
+
permissionLines.push("\n**Session Settings:**\n");
|
|
927
|
+
permissionLines.push(`- Allow all bash: ${config.permissions.session_approvals.allow_all_bash ? "Yes" : "No"}\n`);
|
|
928
|
+
permissionLines.push(`- Trust current directory: ${config.permissions.session_approvals.trust_current_directory ? "Yes" : "No"}\n`);
|
|
929
|
+
permissionLines.push("\n*Tip: Use `/permissions set <tool> <tier>` to change permissions*\n");
|
|
930
|
+
permissionLines.push("*Tiers: auto_approve, notify, confirm, block*");
|
|
931
|
+
const permEntry = {
|
|
932
|
+
type: "assistant",
|
|
933
|
+
content: permissionLines.join(""),
|
|
934
|
+
timestamp: new Date(),
|
|
935
|
+
};
|
|
936
|
+
setChatHistory((prev) => [...prev, permEntry]);
|
|
937
|
+
}
|
|
938
|
+
else if (args.startsWith("set ")) {
|
|
939
|
+
// Set permission for a tool
|
|
940
|
+
const setArgs = args.replace("set ", "").trim().split(/\s+/);
|
|
941
|
+
if (setArgs.length >= 2) {
|
|
942
|
+
const [tool, tier] = setArgs;
|
|
943
|
+
const validTiers = ["auto_approve", "notify", "confirm", "block"];
|
|
944
|
+
if (!validTiers.includes(tier)) {
|
|
945
|
+
const errorEntry = {
|
|
946
|
+
type: "assistant",
|
|
947
|
+
content: `❌ Invalid tier: "${tier}"\n\nValid tiers are: ${validTiers.join(", ")}`,
|
|
948
|
+
timestamp: new Date(),
|
|
949
|
+
};
|
|
950
|
+
setChatHistory((prev) => [...prev, errorEntry]);
|
|
951
|
+
}
|
|
952
|
+
else {
|
|
953
|
+
// Update the permission
|
|
954
|
+
const newTools = { ...config.permissions.tools };
|
|
955
|
+
newTools[tool] = { tier: tier };
|
|
956
|
+
permManager.updateConfig({ tools: newTools }).then(() => {
|
|
957
|
+
const successEntry = {
|
|
958
|
+
type: "assistant",
|
|
959
|
+
content: `✅ Set **${tool}** permission to **${tier}**`,
|
|
960
|
+
timestamp: new Date(),
|
|
961
|
+
};
|
|
962
|
+
setChatHistory((prev) => [...prev, successEntry]);
|
|
963
|
+
}).catch((error) => {
|
|
964
|
+
const errorEntry = {
|
|
965
|
+
type: "assistant",
|
|
966
|
+
content: `❌ Failed to update permission: ${extractErrorMessage(error)}`,
|
|
967
|
+
timestamp: new Date(),
|
|
968
|
+
};
|
|
969
|
+
setChatHistory((prev) => [...prev, errorEntry]);
|
|
970
|
+
});
|
|
971
|
+
}
|
|
972
|
+
}
|
|
973
|
+
else {
|
|
974
|
+
const helpEntry = {
|
|
975
|
+
type: "assistant",
|
|
976
|
+
content: "Usage: `/permissions set <tool> <tier>`\n\nExample: `/permissions set bash confirm`",
|
|
977
|
+
timestamp: new Date(),
|
|
978
|
+
};
|
|
979
|
+
setChatHistory((prev) => [...prev, helpEntry]);
|
|
980
|
+
}
|
|
981
|
+
}
|
|
982
|
+
else if (args === "reset") {
|
|
983
|
+
// Reset to default permissions
|
|
984
|
+
permManager.clearSessionApprovals();
|
|
985
|
+
const resetEntry = {
|
|
986
|
+
type: "assistant",
|
|
987
|
+
content: "✅ Session permissions cleared. Tool permissions reset to defaults.",
|
|
988
|
+
timestamp: new Date(),
|
|
989
|
+
};
|
|
990
|
+
setChatHistory((prev) => [...prev, resetEntry]);
|
|
991
|
+
}
|
|
992
|
+
else {
|
|
993
|
+
// Show help
|
|
994
|
+
const helpEntry = {
|
|
995
|
+
type: "assistant",
|
|
996
|
+
content: "**Permission Commands:**\n\n" +
|
|
997
|
+
"- `/permissions` - Show current permissions\n" +
|
|
998
|
+
"- `/permissions set <tool> <tier>` - Set tool permission tier\n" +
|
|
999
|
+
"- `/permissions reset` - Reset session approvals\n\n" +
|
|
1000
|
+
"**Permission Tiers:**\n" +
|
|
1001
|
+
"- `auto_approve` - Automatically allow (safe operations)\n" +
|
|
1002
|
+
"- `notify` - Allow with notification\n" +
|
|
1003
|
+
"- `confirm` - Require user confirmation\n" +
|
|
1004
|
+
"- `block` - Always block",
|
|
1005
|
+
timestamp: new Date(),
|
|
1006
|
+
};
|
|
1007
|
+
setChatHistory((prev) => [...prev, helpEntry]);
|
|
1008
|
+
}
|
|
1009
|
+
clearInput();
|
|
1010
|
+
return true;
|
|
1011
|
+
}
|
|
1012
|
+
// MCP Prompt commands (format: /mcp__servername__promptname [args])
|
|
1013
|
+
if (trimmedInput.startsWith("/mcp__")) {
|
|
1014
|
+
const parts = trimmedInput.split(" ");
|
|
1015
|
+
const commandPart = parts[0];
|
|
1016
|
+
const argsPart = parts.slice(1).join(" ");
|
|
1017
|
+
const parsed = parsePromptCommand(commandPart);
|
|
1018
|
+
if (parsed) {
|
|
1019
|
+
const { serverName, promptName } = parsed;
|
|
1020
|
+
// Add user command to chat history
|
|
1021
|
+
const userEntry = {
|
|
1022
|
+
type: "user",
|
|
1023
|
+
content: trimmedInput,
|
|
1024
|
+
timestamp: new Date(),
|
|
1025
|
+
};
|
|
1026
|
+
setChatHistory((prev) => [...prev, userEntry]);
|
|
1027
|
+
// Execute the prompt asynchronously
|
|
1028
|
+
(async () => {
|
|
1029
|
+
try {
|
|
1030
|
+
const manager = getMCPManager();
|
|
1031
|
+
const v2 = manager.getV2Instance();
|
|
1032
|
+
const { createServerName } = await import("../../mcp/client-v2.js");
|
|
1033
|
+
const serverNameBranded = createServerName(serverName);
|
|
1034
|
+
if (!serverNameBranded) {
|
|
1035
|
+
throw new Error(`Invalid server name: ${serverName}`);
|
|
1036
|
+
}
|
|
1037
|
+
// Parse arguments if provided (format: key=value key2=value2)
|
|
1038
|
+
const promptArgs = {};
|
|
1039
|
+
if (argsPart) {
|
|
1040
|
+
const argMatches = argsPart.match(/(\w+)=("[^"]+"|[^\s]+)/g);
|
|
1041
|
+
if (argMatches) {
|
|
1042
|
+
for (const match of argMatches) {
|
|
1043
|
+
const [key, ...valueParts] = match.split("=");
|
|
1044
|
+
let value = valueParts.join("=");
|
|
1045
|
+
// Remove quotes if present
|
|
1046
|
+
if (value.startsWith('"') && value.endsWith('"')) {
|
|
1047
|
+
value = value.slice(1, -1);
|
|
1048
|
+
}
|
|
1049
|
+
promptArgs[key] = value;
|
|
1050
|
+
}
|
|
1051
|
+
}
|
|
1052
|
+
}
|
|
1053
|
+
const result = await v2.getPrompt(serverNameBranded, promptName, Object.keys(promptArgs).length > 0 ? promptArgs : undefined);
|
|
1054
|
+
if (!result.success) {
|
|
1055
|
+
throw result.error;
|
|
1056
|
+
}
|
|
1057
|
+
// Cast to GetPromptResult format for formatPromptResult
|
|
1058
|
+
const promptResult = result.value;
|
|
1059
|
+
const formattedContent = formatPromptResult(promptResult);
|
|
1060
|
+
// Add the prompt result as an assistant message
|
|
1061
|
+
const promptEntry = {
|
|
1062
|
+
type: "assistant",
|
|
1063
|
+
content: `**MCP Prompt: ${serverName}/${promptName}**\n\n${formattedContent}`,
|
|
1064
|
+
timestamp: new Date(),
|
|
1065
|
+
};
|
|
1066
|
+
setChatHistory((prev) => [...prev, promptEntry]);
|
|
1067
|
+
}
|
|
1068
|
+
catch (error) {
|
|
1069
|
+
const errorMessage = extractErrorMessage(error);
|
|
1070
|
+
// Use assistant type with error content since "error" is not a valid ChatEntry type
|
|
1071
|
+
const errorEntry = {
|
|
1072
|
+
type: "assistant",
|
|
1073
|
+
content: `❌ **Failed to execute MCP prompt:** ${errorMessage}`,
|
|
1074
|
+
timestamp: new Date(),
|
|
1075
|
+
};
|
|
1076
|
+
setChatHistory((prev) => [...prev, errorEntry]);
|
|
1077
|
+
}
|
|
1078
|
+
})();
|
|
1079
|
+
clearInput();
|
|
1080
|
+
return true;
|
|
1081
|
+
}
|
|
1082
|
+
}
|
|
822
1083
|
if (trimmedInput === "/exit") {
|
|
823
1084
|
process.exit(0);
|
|
824
1085
|
return true;
|
|
@@ -1708,6 +1969,8 @@ Respond with ONLY the commit message, no additional text.`;
|
|
|
1708
1969
|
showCommandSuggestions,
|
|
1709
1970
|
selectedCommandIndex,
|
|
1710
1971
|
commandSuggestions,
|
|
1972
|
+
resourceSuggestions,
|
|
1973
|
+
suggestionMode,
|
|
1711
1974
|
availableModels,
|
|
1712
1975
|
agent,
|
|
1713
1976
|
autoEditEnabled,
|