Compare commits

..

1 Commits

Author SHA1 Message Date
Siddharth Ganesan
44840644ec Fix copilot slash commands blog 2026-01-23 12:38:43 -08:00
4 changed files with 12 additions and 56 deletions

View File

@@ -1425,7 +1425,10 @@ 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)
}
@@ -1523,11 +1526,7 @@ export function ToolCall({
toolCall.name === 'user_memory' ||
toolCall.name === 'edit_respond' ||
toolCall.name === 'debug_respond' ||
toolCall.name === 'plan_respond' ||
toolCall.name === 'research_respond' ||
toolCall.name === 'info_respond' ||
toolCall.name === 'deploy_respond' ||
toolCall.name === 'superagent_respond'
toolCall.name === 'plan_respond'
)
return null

View File

@@ -209,20 +209,9 @@ export interface SlashCommand {
export const TOP_LEVEL_COMMANDS: readonly SlashCommand[] = [
{ id: 'fast', label: 'Fast' },
{ id: 'research', label: 'Research' },
{ id: 'actions', label: 'Actions' },
{ id: 'superagent', 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<string, string> = {
actions: 'superagent',
}
return commandMapping[uiCommandId] || uiCommandId
}
export const WEB_COMMANDS: readonly SlashCommand[] = [
{ id: 'search', label: 'Search' },
{ id: 'read', label: 'Read' },

View File

@@ -29,10 +29,9 @@ Your workspace is indexed for hybrid retrieval. When you ask a question, Copilot
Copilot supports slash commands that trigger specialized capabilities:
- `/deep-research` — performs multi-step web research on a topic, synthesizing results from multiple sources
- `/api-docs` — fetches and parses API documentation from a URL, extracting endpoints, parameters, and authentication requirements
- `/test` — runs your current workflow with sample inputs and reports results inline
- `/build` — generates a complete workflow from a natural language description, wiring up blocks and configuring integrations
- `/actions` — lets Copilot act on your behalf using your connected integrations, like summarizing your recent emails, researching data on a topic and writing the results to a Google Sheet, or checking Slack for unread messages
- `/research` — spawns a subagent for multi-step web research, synthesizing results from multiple sources
- `/search`, `/read`, `/scrape`, `/crawl` — web interaction commands for searching, reading pages, scraping content, and crawling sites
Use `@` commands to pull specific context into your conversation. `@block` references a specific block's configuration and recent outputs. `@workflow` includes the full workflow structure. `@logs` pulls in recent execution traces. This lets you ask targeted questions like "why is `@Slack1` returning an error?" and Copilot has the exact context it needs to diagnose the issue.

View File

@@ -2116,24 +2116,6 @@ const subAgentSSEHandlers: Record<string, SSEHandler> = {
})
})
}
} 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) {
@@ -2815,14 +2797,9 @@ export const useCopilotStore = create<CopilotStore>()(
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<string, string> = { actions: 'superagent' }
const commands = contexts
?.filter((c) => c.kind === 'slash_command' && 'command' in c)
.map((c) => {
const uiCommand = (c as any).command.toLowerCase()
return uiToApiCommandMap[uiCommand] || uiCommand
}) as string[] | undefined
.map((c) => (c as any).command.toLowerCase()) as string[] | undefined
const filteredContexts = contexts?.filter((c) => c.kind !== 'slash_command')
const result = await sendStreamingMessage({
@@ -3946,16 +3923,11 @@ export const useCopilotStore = create<CopilotStore>()(
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()
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 })
set({ autoAllowedTools: data.autoAllowedTools || [] })
logger.info('[AutoAllowedTools] Loaded', { tools: data.autoAllowedTools })
}
} catch (err) {
logger.error('[AutoAllowedTools] Failed to load', { error: err })
@@ -3964,18 +3936,15 @@ export const useCopilotStore = create<CopilotStore>()(
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 to store', { toolId })
logger.info('[AutoAllowedTools] Added tool', { toolId })
// Auto-execute all pending tools of the same type
const { toolCallsById, executeIntegrationTool } = get()