diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/tool-call/tool-call.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/tool-call/tool-call.tsx index c97025aee..cb536c179 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/tool-call/tool-call.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/tool-call/tool-call.tsx @@ -1425,10 +1425,7 @@ function RunSkipButtons({ setIsProcessing(true) setButtonsHidden(true) try { - // Add to auto-allowed list - this also executes all pending integration tools of this type await addAutoAllowedTool(toolCall.name) - // For client tools with interrupts (not integration tools), we still need to call handleRun - // since executeIntegrationTool only works for server-side tools if (!isIntegrationTool(toolCall.name)) { await handleRun(toolCall, setToolCallState, onStateChange, editedParams) } @@ -1526,7 +1523,11 @@ export function ToolCall({ toolCall.name === 'user_memory' || toolCall.name === 'edit_respond' || toolCall.name === 'debug_respond' || - toolCall.name === 'plan_respond' + toolCall.name === 'plan_respond' || + toolCall.name === 'research_respond' || + toolCall.name === 'info_respond' || + toolCall.name === 'deploy_respond' || + toolCall.name === 'superagent_respond' ) return null diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/user-input/constants.ts b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/user-input/constants.ts index 2ad930bad..b98af5dd2 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/user-input/constants.ts +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/user-input/constants.ts @@ -209,9 +209,20 @@ export interface SlashCommand { export const TOP_LEVEL_COMMANDS: readonly SlashCommand[] = [ { id: 'fast', label: 'Fast' }, { id: 'research', label: 'Research' }, - { id: 'superagent', label: 'Actions' }, + { id: 'actions', label: 'Actions' }, ] as const +/** + * Maps UI command IDs to API command IDs. + * Some commands have different IDs for display vs API (e.g., "actions" -> "superagent") + */ +export function getApiCommandId(uiCommandId: string): string { + const commandMapping: Record = { + actions: 'superagent', + } + return commandMapping[uiCommandId] || uiCommandId +} + export const WEB_COMMANDS: readonly SlashCommand[] = [ { id: 'search', label: 'Search' }, { id: 'read', label: 'Read' }, diff --git a/apps/sim/stores/panel/copilot/store.ts b/apps/sim/stores/panel/copilot/store.ts index fd7552e12..5068cd167 100644 --- a/apps/sim/stores/panel/copilot/store.ts +++ b/apps/sim/stores/panel/copilot/store.ts @@ -2116,6 +2116,24 @@ const subAgentSSEHandlers: Record = { }) }) } + } else { + // Check if this is an integration tool (server-side) that should be auto-executed + const isIntegrationTool = !CLASS_TOOL_METADATA[name] + if (isIntegrationTool && isSubAgentAutoAllowed) { + logger.info('[SubAgent] Auto-executing integration tool (auto-allowed)', { + id, + name, + }) + // Execute integration tool via the store method + const { executeIntegrationTool } = get() + executeIntegrationTool(id).catch((err) => { + logger.error('[SubAgent] Integration tool auto-execution failed', { + id, + name, + error: err?.message || err, + }) + }) + } } } } catch (e: any) { @@ -2797,9 +2815,14 @@ export const useCopilotStore = create()( mode === 'ask' ? 'ask' : mode === 'plan' ? 'plan' : 'agent' // Extract slash commands from contexts (lowercase) and filter them out from contexts + // Map UI command IDs to API command IDs (e.g., "actions" -> "superagent") + const uiToApiCommandMap: Record = { actions: 'superagent' } const commands = contexts ?.filter((c) => c.kind === 'slash_command' && 'command' in c) - .map((c) => (c as any).command.toLowerCase()) as string[] | undefined + .map((c) => { + const uiCommand = (c as any).command.toLowerCase() + return uiToApiCommandMap[uiCommand] || uiCommand + }) as string[] | undefined const filteredContexts = contexts?.filter((c) => c.kind !== 'slash_command') const result = await sendStreamingMessage({ @@ -3923,11 +3946,16 @@ export const useCopilotStore = create()( loadAutoAllowedTools: async () => { try { + logger.info('[AutoAllowedTools] Loading from API...') const res = await fetch('/api/copilot/auto-allowed-tools') + logger.info('[AutoAllowedTools] Load response', { status: res.status, ok: res.ok }) if (res.ok) { const data = await res.json() - set({ autoAllowedTools: data.autoAllowedTools || [] }) - logger.info('[AutoAllowedTools] Loaded', { tools: data.autoAllowedTools }) + const tools = data.autoAllowedTools || [] + set({ autoAllowedTools: tools }) + logger.info('[AutoAllowedTools] Loaded successfully', { count: tools.length, tools }) + } else { + logger.warn('[AutoAllowedTools] Load failed with status', { status: res.status }) } } catch (err) { logger.error('[AutoAllowedTools] Failed to load', { error: err }) @@ -3936,15 +3964,18 @@ export const useCopilotStore = create()( addAutoAllowedTool: async (toolId: string) => { try { + logger.info('[AutoAllowedTools] Adding tool...', { toolId }) const res = await fetch('/api/copilot/auto-allowed-tools', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ toolId }), }) + logger.info('[AutoAllowedTools] API response', { toolId, status: res.status, ok: res.ok }) if (res.ok) { const data = await res.json() + logger.info('[AutoAllowedTools] API returned', { toolId, tools: data.autoAllowedTools }) set({ autoAllowedTools: data.autoAllowedTools || [] }) - logger.info('[AutoAllowedTools] Added tool', { toolId }) + logger.info('[AutoAllowedTools] Added tool to store', { toolId }) // Auto-execute all pending tools of the same type const { toolCallsById, executeIntegrationTool } = get()