-
Name
-
Type
-
Value
+
+ Name
+
+
+ Type
+
+
+ Value
+
{ops.map((op, idx) => (
- {String(op.name || '')}
+
+ {String(op.name || '')}
+
- {String(op.type || '')}
+
+ {String(op.type || '')}
+
- {op.value !== undefined ? String(op.value) : '—'}
+
+ {op.value !== undefined ? String(op.value) : '—'}
+
))}
@@ -572,7 +592,11 @@ function SubAgentToolCall({ toolCall: toolCallProp }: { toolCall: CopilotToolCal
if (toolCall.name === 'run_workflow') {
let inputs = params.input || params.inputs || params.workflow_input
if (typeof inputs === 'string') {
- try { inputs = JSON.parse(inputs) } catch { inputs = {} }
+ try {
+ inputs = JSON.parse(inputs)
+ } catch {
+ inputs = {}
+ }
}
if (params.workflow_input && typeof params.workflow_input === 'object') {
inputs = params.workflow_input
@@ -589,18 +613,26 @@ function SubAgentToolCall({ toolCall: toolCallProp }: { toolCall: CopilotToolCal
- | Input |
- Value |
+
+ Input
+ |
+
+ Value
+ |
{inputEntries.map(([key, value]) => (
|
- {key}
+
+ {key}
+
|
- {String(value)}
+
+ {String(value)}
+
|
))}
@@ -785,7 +817,10 @@ function SubAgentContent({
{hasContent && (
)}
@@ -833,7 +868,9 @@ function SubAgentContent({
{/* Render WorkflowEditSummary outside the collapsible container for edit_workflow tool calls */}
{blocks
- .filter((block) => block.type === 'subagent_tool_call' && block.toolCall?.name === 'edit_workflow')
+ .filter(
+ (block) => block.type === 'subagent_tool_call' && block.toolCall?.name === 'edit_workflow'
+ )
.map((block, index) => (
tag */}
- {toolName === 'plan' && (() => {
- // Combine all text content from blocks
- const allText = blocks
- .filter((b) => b.type === 'subagent_text' && b.content)
- .map((b) => b.content)
- .join('')
- const parsed = parseSpecialTags(allText)
- if (parsed.plan && Object.keys(parsed.plan).length > 0) {
- return
- }
- return null
- })()}
+ {toolName === 'plan' &&
+ (() => {
+ // Combine all text content from blocks
+ const allText = blocks
+ .filter((b) => b.type === 'subagent_text' && b.content)
+ .map((b) => b.content)
+ .join('')
+ const parsed = parseSpecialTags(allText)
+ if (parsed.plan && Object.keys(parsed.plan).length > 0) {
+ return
+ }
+ return null
+ })()}
)
}
@@ -904,9 +942,10 @@ function WorkflowEditSummary({ toolCall }: { toolCall: CopilotToolCall }) {
}
// Extract operations from tool call params
- const params = (toolCall as any).parameters || (toolCall as any).input || (toolCall as any).params || {}
+ const params =
+ (toolCall as any).parameters || (toolCall as any).input || (toolCall as any).params || {}
let operations = Array.isArray(params.operations) ? params.operations : []
-
+
// Fallback: check if operations are at top level of toolCall
if (operations.length === 0 && Array.isArray((toolCall as any).operations)) {
operations = (toolCall as any).operations
@@ -1049,10 +1088,7 @@ function WorkflowEditSummary({ toolCall }: { toolCall: CopilotToolCall }) {
}
// Render a single block item with action icon and details
- const renderBlockItem = (
- change: BlockChange,
- type: 'add' | 'edit' | 'delete'
- ) => {
+ const renderBlockItem = (change: BlockChange, type: 'add' | 'edit' | 'delete') => {
const blockConfig = getBlockConfig(change.blockType)
const Icon = blockConfig?.icon
const bgColor = blockConfig?.bgColor || '#6B7280'
@@ -1064,12 +1100,13 @@ function WorkflowEditSummary({ toolCall }: { toolCall: CopilotToolCall }) {
}
const { symbol, color } = actionIcons[type]
- const subBlocksToShow = type === 'add' ? change.subBlocks : type === 'edit' ? change.changedSubBlocks : undefined
+ const subBlocksToShow =
+ type === 'add' ? change.subBlocks : type === 'edit' ? change.changedSubBlocks : undefined
return (
{/* Block header */}
@@ -1088,21 +1125,20 @@ function WorkflowEditSummary({ toolCall }: { toolCall: CopilotToolCall }) {
{/* Action icon in top right */}
-
{symbol}
+
{symbol}
{/* Subblock details */}
{subBlocksToShow && subBlocksToShow.length > 0 && (
-
+
{subBlocksToShow.map((sb) => (
-
-
+
+
{formatSubBlockLabel(sb.id)}:
-
+
{formatSubBlockValue(sb.value)}
@@ -1441,7 +1477,20 @@ export function ToolCall({ toolCall: toolCallProp, toolCallId, onStateChange }:
if (toolCall.name === 'checkoff_todo' || toolCall.name === 'mark_todo_in_progress') return null
// Special rendering for subagent tools - only show the collapsible SubAgentContent
- const SUBAGENT_TOOLS = ['plan', 'edit', 'debug', 'test', 'deploy', 'auth', 'research', 'knowledge', 'custom_tool', 'tour', 'info', 'workflow']
+ const SUBAGENT_TOOLS = [
+ 'plan',
+ 'edit',
+ 'debug',
+ 'test',
+ 'deploy',
+ 'auth',
+ 'research',
+ 'knowledge',
+ 'custom_tool',
+ 'tour',
+ 'info',
+ 'workflow',
+ ]
const isSubagentTool = SUBAGENT_TOOLS.includes(toolCall.name)
if (isSubagentTool && toolCall.subAgentBlocks && toolCall.subAgentBlocks.length > 0) {
return (
@@ -1779,55 +1828,52 @@ export function ToolCall({ toolCall: toolCallProp, toolCallId, onStateChange }:
{inputEntries.map(([key, value]) => (
-
- |
-
-
- {key}
-
-
- |
-
-
- {
- const newInputs = { ...safeInputs, [key]: e.target.value }
+
+ |
+
+
+ {key}
+
+
+ |
+
+
+ {
+ const newInputs = { ...safeInputs, [key]: e.target.value }
- // Determine how to update based on original structure
- if (isNestedInWorkflowInput) {
- // Update workflow_input
- setEditedParams({ ...editedParams, workflow_input: newInputs })
- } else if (typeof editedParams.input === 'string') {
- // Input was a JSON string, serialize back
- setEditedParams({ ...editedParams, input: JSON.stringify(newInputs) })
- } else if (
- editedParams.input &&
- typeof editedParams.input === 'object'
- ) {
- // Input is an object
- setEditedParams({ ...editedParams, input: newInputs })
- } else if (
- editedParams.inputs &&
- typeof editedParams.inputs === 'object'
- ) {
- // Inputs is an object
- setEditedParams({ ...editedParams, inputs: newInputs })
- } else {
- // Flat structure - update at base level
- setEditedParams({ ...editedParams, [key]: e.target.value })
- }
- }}
- className='w-full bg-transparent font-mono text-[var(--text-muted)] text-xs outline-none focus:text-[var(--text-primary)]'
- />
-
- |
-
- ))}
+ // Determine how to update based on original structure
+ if (isNestedInWorkflowInput) {
+ // Update workflow_input
+ setEditedParams({ ...editedParams, workflow_input: newInputs })
+ } else if (typeof editedParams.input === 'string') {
+ // Input was a JSON string, serialize back
+ setEditedParams({ ...editedParams, input: JSON.stringify(newInputs) })
+ } else if (editedParams.input && typeof editedParams.input === 'object') {
+ // Input is an object
+ setEditedParams({ ...editedParams, input: newInputs })
+ } else if (
+ editedParams.inputs &&
+ typeof editedParams.inputs === 'object'
+ ) {
+ // Inputs is an object
+ setEditedParams({ ...editedParams, inputs: newInputs })
+ } else {
+ // Flat structure - update at base level
+ setEditedParams({ ...editedParams, [key]: e.target.value })
+ }
+ }}
+ className='w-full bg-transparent font-mono text-[var(--text-muted)] text-xs outline-none focus:text-[var(--text-primary)]'
+ />
+
+ |
+
+ ))}
diff --git a/apps/sim/lib/copilot/registry.ts b/apps/sim/lib/copilot/registry.ts
index 4cbf207bdf..544b12f0f9 100644
--- a/apps/sim/lib/copilot/registry.ts
+++ b/apps/sim/lib/copilot/registry.ts
@@ -213,7 +213,9 @@ export const ToolArgSchemas = {
manage_custom_tool: z.object({
operation: z
.enum(['add', 'edit', 'delete', 'list'])
- .describe('The operation to perform: add (create new), edit (update existing), delete, or list (get all tools)'),
+ .describe(
+ 'The operation to perform: add (create new), edit (update existing), delete, or list (get all tools)'
+ ),
toolId: z
.string()
.optional()
diff --git a/apps/sim/lib/copilot/tools/client/blocks/get-block-options.ts b/apps/sim/lib/copilot/tools/client/blocks/get-block-options.ts
index 57c8b32fd7..f55dc42b64 100644
--- a/apps/sim/lib/copilot/tools/client/blocks/get-block-options.ts
+++ b/apps/sim/lib/copilot/tools/client/blocks/get-block-options.ts
@@ -66,7 +66,11 @@ export class GetBlockOptionsClientTool extends BaseClientTool {
// Handle both camelCase and snake_case parameter names, plus blockType as an alias
const normalizedArgs = args
? {
- blockId: args.blockId || (args as any).block_id || (args as any).blockType || (args as any).block_type,
+ blockId:
+ args.blockId ||
+ (args as any).block_id ||
+ (args as any).blockType ||
+ (args as any).block_type,
}
: {}
diff --git a/apps/sim/lib/copilot/tools/client/other/auth.ts b/apps/sim/lib/copilot/tools/client/other/auth.ts
index e910f46694..9685c07b41 100644
--- a/apps/sim/lib/copilot/tools/client/other/auth.ts
+++ b/apps/sim/lib/copilot/tools/client/other/auth.ts
@@ -42,4 +42,3 @@ export class AuthClientTool extends BaseClientTool {
this.setState(ClientToolCallState.executing)
}
}
-
diff --git a/apps/sim/lib/copilot/tools/client/other/custom-tool.ts b/apps/sim/lib/copilot/tools/client/other/custom-tool.ts
index 410486b7da..def81fce14 100644
--- a/apps/sim/lib/copilot/tools/client/other/custom-tool.ts
+++ b/apps/sim/lib/copilot/tools/client/other/custom-tool.ts
@@ -42,4 +42,3 @@ export class CustomToolClientTool extends BaseClientTool {
this.setState(ClientToolCallState.executing)
}
}
-
diff --git a/apps/sim/lib/copilot/tools/client/other/debug.ts b/apps/sim/lib/copilot/tools/client/other/debug.ts
index 47671f4c07..8c464a101b 100644
--- a/apps/sim/lib/copilot/tools/client/other/debug.ts
+++ b/apps/sim/lib/copilot/tools/client/other/debug.ts
@@ -46,4 +46,3 @@ export class DebugClientTool extends BaseClientTool {
// when the debug subagent completes its work
}
}
-
diff --git a/apps/sim/lib/copilot/tools/client/other/deploy.ts b/apps/sim/lib/copilot/tools/client/other/deploy.ts
index fbe1e2e783..87c51f3f4c 100644
--- a/apps/sim/lib/copilot/tools/client/other/deploy.ts
+++ b/apps/sim/lib/copilot/tools/client/other/deploy.ts
@@ -42,4 +42,3 @@ export class DeployClientTool extends BaseClientTool {
this.setState(ClientToolCallState.executing)
}
}
-
diff --git a/apps/sim/lib/copilot/tools/client/other/edit.ts b/apps/sim/lib/copilot/tools/client/other/edit.ts
index 302ddc453d..399378d8f1 100644
--- a/apps/sim/lib/copilot/tools/client/other/edit.ts
+++ b/apps/sim/lib/copilot/tools/client/other/edit.ts
@@ -45,4 +45,3 @@ export class EditClientTool extends BaseClientTool {
// when the edit subagent completes its work
}
}
-
diff --git a/apps/sim/lib/copilot/tools/client/other/info.ts b/apps/sim/lib/copilot/tools/client/other/info.ts
index 60a9083b97..50643e34ca 100644
--- a/apps/sim/lib/copilot/tools/client/other/info.ts
+++ b/apps/sim/lib/copilot/tools/client/other/info.ts
@@ -42,4 +42,3 @@ export class InfoClientTool extends BaseClientTool {
this.setState(ClientToolCallState.executing)
}
}
-
diff --git a/apps/sim/lib/copilot/tools/client/other/knowledge.ts b/apps/sim/lib/copilot/tools/client/other/knowledge.ts
index b4dbd70690..c084d1fb11 100644
--- a/apps/sim/lib/copilot/tools/client/other/knowledge.ts
+++ b/apps/sim/lib/copilot/tools/client/other/knowledge.ts
@@ -42,4 +42,3 @@ export class KnowledgeClientTool extends BaseClientTool {
this.setState(ClientToolCallState.executing)
}
}
-
diff --git a/apps/sim/lib/copilot/tools/client/other/research.ts b/apps/sim/lib/copilot/tools/client/other/research.ts
index 7ce52fda2a..2a2d6360cf 100644
--- a/apps/sim/lib/copilot/tools/client/other/research.ts
+++ b/apps/sim/lib/copilot/tools/client/other/research.ts
@@ -42,4 +42,3 @@ export class ResearchClientTool extends BaseClientTool {
this.setState(ClientToolCallState.executing)
}
}
-
diff --git a/apps/sim/lib/copilot/tools/client/other/test.ts b/apps/sim/lib/copilot/tools/client/other/test.ts
index cbb188df46..17419891ed 100644
--- a/apps/sim/lib/copilot/tools/client/other/test.ts
+++ b/apps/sim/lib/copilot/tools/client/other/test.ts
@@ -42,4 +42,3 @@ export class TestClientTool extends BaseClientTool {
this.setState(ClientToolCallState.executing)
}
}
-
diff --git a/apps/sim/lib/copilot/tools/client/other/tour.ts b/apps/sim/lib/copilot/tools/client/other/tour.ts
index 0f59773ce1..947b68d7fc 100644
--- a/apps/sim/lib/copilot/tools/client/other/tour.ts
+++ b/apps/sim/lib/copilot/tools/client/other/tour.ts
@@ -42,4 +42,3 @@ export class TourClientTool extends BaseClientTool {
this.setState(ClientToolCallState.executing)
}
}
-
diff --git a/apps/sim/lib/copilot/tools/client/other/workflow.ts b/apps/sim/lib/copilot/tools/client/other/workflow.ts
index b66ec50068..f7f0b61df6 100644
--- a/apps/sim/lib/copilot/tools/client/other/workflow.ts
+++ b/apps/sim/lib/copilot/tools/client/other/workflow.ts
@@ -42,4 +42,3 @@ export class WorkflowClientTool extends BaseClientTool {
this.setState(ClientToolCallState.executing)
}
}
-
diff --git a/apps/sim/stores/panel/copilot/store.ts b/apps/sim/stores/panel/copilot/store.ts
index 41dd27ec66..9aee4557b5 100644
--- a/apps/sim/stores/panel/copilot/store.ts
+++ b/apps/sim/stores/panel/copilot/store.ts
@@ -25,27 +25,27 @@ import {
registerToolStateSync,
} from '@/lib/copilot/tools/client/manager'
import { NavigateUIClientTool } from '@/lib/copilot/tools/client/navigation/navigate-ui'
+import { AuthClientTool } from '@/lib/copilot/tools/client/other/auth'
import { CheckoffTodoClientTool } from '@/lib/copilot/tools/client/other/checkoff-todo'
+import { CustomToolClientTool } from '@/lib/copilot/tools/client/other/custom-tool'
+import { DebugClientTool } from '@/lib/copilot/tools/client/other/debug'
+import { DeployClientTool } from '@/lib/copilot/tools/client/other/deploy'
+import { EditClientTool } from '@/lib/copilot/tools/client/other/edit'
+import { InfoClientTool } from '@/lib/copilot/tools/client/other/info'
+import { KnowledgeClientTool } from '@/lib/copilot/tools/client/other/knowledge'
import { MakeApiRequestClientTool } from '@/lib/copilot/tools/client/other/make-api-request'
import { MarkTodoInProgressClientTool } from '@/lib/copilot/tools/client/other/mark-todo-in-progress'
import { OAuthRequestAccessClientTool } from '@/lib/copilot/tools/client/other/oauth-request-access'
import { PlanClientTool } from '@/lib/copilot/tools/client/other/plan'
import { RememberDebugClientTool } from '@/lib/copilot/tools/client/other/remember-debug'
+import { ResearchClientTool } from '@/lib/copilot/tools/client/other/research'
import { SearchDocumentationClientTool } from '@/lib/copilot/tools/client/other/search-documentation'
import { SearchErrorsClientTool } from '@/lib/copilot/tools/client/other/search-errors'
-import { EditClientTool } from '@/lib/copilot/tools/client/other/edit'
-import { DebugClientTool } from '@/lib/copilot/tools/client/other/debug'
import { SearchOnlineClientTool } from '@/lib/copilot/tools/client/other/search-online'
import { SearchPatternsClientTool } from '@/lib/copilot/tools/client/other/search-patterns'
import { SleepClientTool } from '@/lib/copilot/tools/client/other/sleep'
import { TestClientTool } from '@/lib/copilot/tools/client/other/test'
-import { DeployClientTool } from '@/lib/copilot/tools/client/other/deploy'
-import { AuthClientTool } from '@/lib/copilot/tools/client/other/auth'
-import { ResearchClientTool } from '@/lib/copilot/tools/client/other/research'
-import { KnowledgeClientTool } from '@/lib/copilot/tools/client/other/knowledge'
-import { CustomToolClientTool } from '@/lib/copilot/tools/client/other/custom-tool'
import { TourClientTool } from '@/lib/copilot/tools/client/other/tour'
-import { InfoClientTool } from '@/lib/copilot/tools/client/other/info'
import { WorkflowClientTool } from '@/lib/copilot/tools/client/other/workflow'
import { createExecutionContext, getTool } from '@/lib/copilot/tools/client/registry'
import { GetCredentialsClientTool } from '@/lib/copilot/tools/client/user/get-credentials'
@@ -1690,7 +1690,7 @@ const subAgentSSEHandlers: Record
= {
// Arguments can come in different locations depending on SSE format
// Check multiple possible locations
let args = toolData.arguments || toolData.input || data?.arguments || data?.input
-
+
// If arguments is a string, try to parse it as JSON
if (typeof args === 'string') {
try {
@@ -1721,7 +1721,9 @@ const subAgentSSEHandlers: Record = {
ensureClientToolInstance(name, id)
// Create or update the subagent tool call
- const existingIndex = context.subAgentToolCalls[parentToolCallId].findIndex((tc) => tc.id === id)
+ const existingIndex = context.subAgentToolCalls[parentToolCallId].findIndex(
+ (tc) => tc.id === id
+ )
const subAgentToolCall: CopilotToolCall = {
id,
name,
@@ -1755,7 +1757,9 @@ const subAgentSSEHandlers: Record = {
const def = getTool(name)
if (def) {
const hasInterrupt =
- typeof def.hasInterrupt === 'function' ? !!def.hasInterrupt(args || {}) : !!def.hasInterrupt
+ typeof def.hasInterrupt === 'function'
+ ? !!def.hasInterrupt(args || {})
+ : !!def.hasInterrupt
if (!hasInterrupt) {
// Auto-execute tools without interrupts
const ctx = createExecutionContext({ toolCallId: id, toolName: name })
@@ -1774,7 +1778,11 @@ const subAgentSSEHandlers: Record = {
try {
await instance.execute(args || {})
} catch (execErr: any) {
- logger.error('[SubAgent] Class tool execution failed', { id, name, error: execErr?.message })
+ logger.error('[SubAgent] Class tool execution failed', {
+ id,
+ name,
+ error: execErr?.message,
+ })
}
}
}
@@ -2339,7 +2347,9 @@ export const useCopilotStore = create()(
// If already sending a message, queue this one instead
if (isSendingMessage) {
get().addToQueue(message, { fileAttachments, contexts })
- logger.info('[Copilot] Message queued (already sending)', { queueLength: get().messageQueue.length + 1 })
+ logger.info('[Copilot] Message queued (already sending)', {
+ queueLength: get().messageQueue.length + 1,
+ })
return
}
@@ -2551,7 +2561,6 @@ export const useCopilotStore = create()(
}).catch(() => {})
} catch {}
}
-
} catch {
set({ isSendingMessage: false, isAborting: false, abortController: null })
}
@@ -2992,14 +3001,14 @@ export const useCopilotStore = create()(
})
continue
}
-
+
logger.info('[SSE] Processing subagent event', {
type: data.type,
subagent: data.subagent,
parentToolCallId,
hasHandler: !!subAgentSSEHandlers[data.type],
})
-
+
const subAgentHandler = subAgentSSEHandlers[data.type]
if (subAgentHandler) {
await subAgentHandler(data, context, get, set)
@@ -3065,7 +3074,10 @@ export const useCopilotStore = create()(
// Process next message in queue if any
const nextInQueue = get().messageQueue[0]
if (nextInQueue) {
- logger.info('[Queue] Processing next queued message', { id: nextInQueue.id, queueLength: get().messageQueue.length })
+ logger.info('[Queue] Processing next queued message', {
+ id: nextInQueue.id,
+ queueLength: get().messageQueue.length,
+ })
// Remove from queue and send
get().removeFromQueue(nextInQueue.id)
// Use setTimeout to avoid blocking the current execution
@@ -3493,12 +3505,18 @@ export const useCopilotStore = create()(
queuedAt: Date.now(),
}
set({ messageQueue: [...get().messageQueue, queuedMessage] })
- logger.info('[Queue] Message added to queue', { id: queuedMessage.id, queueLength: get().messageQueue.length })
+ logger.info('[Queue] Message added to queue', {
+ id: queuedMessage.id,
+ queueLength: get().messageQueue.length,
+ })
},
removeFromQueue: (id) => {
set({ messageQueue: get().messageQueue.filter((m) => m.id !== id) })
- logger.info('[Queue] Message removed from queue', { id, queueLength: get().messageQueue.length })
+ logger.info('[Queue] Message removed from queue', {
+ id,
+ queueLength: get().messageQueue.length,
+ })
},
moveUpInQueue: (id) => {