Skip to content

Commit dd04498

Browse files
committed
Trigger request
1 parent c673200 commit dd04498

File tree

8 files changed

+101
-17
lines changed

8 files changed

+101
-17
lines changed

apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/copilot-message/components/thinking-block.tsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,9 @@ export function ThinkingBlock({
115115
}
116116

117117
const hasContent = content && content.trim().length > 0
118-
const label = isStreaming ? 'Thinking' : 'Thought'
118+
// Thinking is "done" when streaming ends OR when there's following content (like a tool call)
119+
const isThinkingDone = !isStreaming || hasFollowingContent
120+
const label = isThinkingDone ? 'Thought' : 'Thinking'
119121
const durationText = ` for ${formatDuration(duration)}`
120122

121123
return (
@@ -136,7 +138,7 @@ export function ThinkingBlock({
136138
<span className='relative inline-block'>
137139
<span className='text-[var(--text-tertiary)]'>{label}</span>
138140
<span className='text-[var(--text-muted)]'>{durationText}</span>
139-
{isStreaming && (
141+
{!isThinkingDone && (
140142
<span
141143
aria-hidden='true'
142144
className='pointer-events-none absolute inset-0 select-none overflow-hidden'
@@ -183,7 +185,7 @@ export function ThinkingBlock({
183185
>
184186
<pre className='whitespace-pre-wrap font-[470] font-season text-[12px] text-[var(--text-tertiary)] leading-[1.15rem]'>
185187
{content}
186-
{isStreaming && (
188+
{!isThinkingDone && (
187189
<span className='ml-1 inline-block h-2 w-1 animate-pulse bg-[var(--text-tertiary)]' />
188190
)}
189191
</pre>

apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/tool-call/tool-call.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,7 @@ function SubAgentToolCall({ toolCall }: { toolCall: CopilotToolCall }) {
235235
const displayName = getDisplayNameForSubAgent(toolCall)
236236

237237
const isLoading =
238+
toolCall.state === ClientToolCallState.generating ||
238239
toolCall.state === ClientToolCallState.pending ||
239240
toolCall.state === ClientToolCallState.executing
240241

@@ -858,6 +859,7 @@ export function ToolCall({ toolCall: toolCallProp, toolCallId, onStateChange }:
858859
const displayName = getDisplayName(toolCall)
859860

860861
const isLoadingState =
862+
toolCall.state === ClientToolCallState.generating ||
861863
toolCall.state === ClientToolCallState.pending ||
862864
toolCall.state === ClientToolCallState.executing
863865

apps/sim/lib/copilot/registry.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,12 @@ export const ToolArgSchemas = {
131131
.describe(
132132
'Optional operation ID (e.g., "read", "write"). If not provided, returns full block schema.'
133133
),
134+
trigger: z
135+
.boolean()
136+
.optional()
137+
.describe(
138+
'If true, returns only the trigger-mode configuration (inputs with mode: "trigger" and trigger outputs). Only applicable for blocks that support triggers.'
139+
),
134140
}),
135141

136142
get_trigger_blocks: z.object({}),
@@ -480,6 +486,7 @@ export const ToolResultSchemas = {
480486
blockType: z.string(),
481487
blockName: z.string(),
482488
operation: z.string().optional(),
489+
trigger: z.boolean().optional(),
483490
inputs: z.record(z.any()),
484491
outputs: z.record(z.any()),
485492
}),
@@ -622,6 +629,7 @@ export const ToolResultSchemas = {
622629
blockId: z.string(),
623630
blockName: z.string(),
624631
blockType: z.string(),
632+
triggerMode: z.boolean().optional(),
625633
outputs: z.array(z.string()),
626634
insideSubflowOutputs: z.array(z.string()).optional(),
627635
outsideSubflowOutputs: z.array(z.string()).optional(),
@@ -655,6 +663,7 @@ export const ToolResultSchemas = {
655663
blockId: z.string(),
656664
blockName: z.string(),
657665
blockType: z.string(),
666+
triggerMode: z.boolean().optional(),
658667
outputs: z.array(z.string()),
659668
accessContext: z.enum(['inside', 'outside']).optional(),
660669
})

apps/sim/lib/copilot/tools/client/blocks/get-block-config.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {
1414
interface GetBlockConfigArgs {
1515
blockType: string
1616
operation?: string
17+
trigger?: boolean
1718
}
1819

1920
export class GetBlockConfigClientTool extends BaseClientTool {
@@ -65,12 +66,15 @@ export class GetBlockConfigClientTool extends BaseClientTool {
6566
try {
6667
this.setState(ClientToolCallState.executing)
6768

68-
const { blockType, operation } = GetBlockConfigInput.parse(args || {})
69+
const { blockType, operation, trigger } = GetBlockConfigInput.parse(args || {})
6970

7071
const res = await fetch('/api/copilot/execute-copilot-server-tool', {
7172
method: 'POST',
7273
headers: { 'Content-Type': 'application/json' },
73-
body: JSON.stringify({ toolName: 'get_block_config', payload: { blockType, operation } }),
74+
body: JSON.stringify({
75+
toolName: 'get_block_config',
76+
payload: { blockType, operation, trigger },
77+
}),
7478
})
7579
if (!res.ok) {
7680
const errorText = await res.text().catch(() => '')

apps/sim/lib/copilot/tools/client/workflow/get-block-outputs.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ import {
1616
GetBlockOutputsResult,
1717
type GetBlockOutputsResultType,
1818
} from '@/lib/copilot/tools/shared/schemas'
19-
import { normalizeName } from '@/executor/constants'
2019
import { useWorkflowRegistry } from '@/stores/workflows/registry/store'
2120
import { useWorkflowStore } from '@/stores/workflows/workflow/store'
2221

@@ -90,10 +89,6 @@ export class GetBlockOutputsClientTool extends BaseClientTool {
9089
if (!block?.type) continue
9190

9291
const blockName = block.name || block.type
93-
const normalizedBlockName = normalizeName(blockName)
94-
95-
let insideSubflowOutputs: string[] | undefined
96-
let outsideSubflowOutputs: string[] | undefined
9792

9893
const blockOutput: GetBlockOutputsResultType['blocks'][0] = {
9994
blockId,
@@ -102,6 +97,11 @@ export class GetBlockOutputsClientTool extends BaseClientTool {
10297
outputs: [],
10398
}
10499

100+
// Include triggerMode if the block is in trigger mode
101+
if (block.triggerMode) {
102+
blockOutput.triggerMode = true
103+
}
104+
105105
if (block.type === 'loop' || block.type === 'parallel') {
106106
const insidePaths = getSubflowInsidePaths(block.type, blockId, loops, parallels)
107107
blockOutput.insideSubflowOutputs = formatOutputsWithPrefix(insidePaths, blockName)

apps/sim/lib/copilot/tools/client/workflow/get-block-upstream-references.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,11 @@ export class GetBlockUpstreamReferencesClientTool extends BaseClientTool {
193193
outputs: formattedOutputs,
194194
}
195195

196+
// Include triggerMode if the block is in trigger mode
197+
if (block.triggerMode) {
198+
entry.triggerMode = true
199+
}
200+
196201
if (accessContext) entry.accessContext = accessContext
197202
accessibleBlocks.push(entry)
198203
}

apps/sim/lib/copilot/tools/server/blocks/get-block-config.ts

Lines changed: 65 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { registry as blockRegistry } from '@/blocks/registry'
99
import type { SubBlockConfig } from '@/blocks/types'
1010
import { PROVIDER_DEFINITIONS } from '@/providers/models'
1111
import { tools as toolsRegistry } from '@/tools/registry'
12+
import { getTrigger, isTriggerValid } from '@/triggers'
1213

1314
interface InputFieldSchema {
1415
type: string
@@ -145,13 +146,20 @@ function matchesOperation(condition: any, operation: string): boolean {
145146
*/
146147
function extractInputsFromSubBlocks(
147148
subBlocks: SubBlockConfig[],
148-
operation?: string
149+
operation?: string,
150+
triggerMode?: boolean
149151
): Record<string, InputFieldSchema> {
150152
const inputs: Record<string, InputFieldSchema> = {}
151153

152154
for (const sb of subBlocks) {
153-
// Skip trigger-mode subBlocks
154-
if (sb.mode === 'trigger') continue
155+
// Handle trigger vs non-trigger mode filtering
156+
if (triggerMode) {
157+
// In trigger mode, only include subBlocks with mode: 'trigger'
158+
if (sb.mode !== 'trigger') continue
159+
} else {
160+
// In non-trigger mode, skip trigger-mode subBlocks
161+
if (sb.mode === 'trigger') continue
162+
}
155163

156164
// Skip hidden subBlocks
157165
if (sb.hidden) continue
@@ -247,12 +255,53 @@ function mapSubBlockTypeToSchemaType(type: string): string {
247255
return typeMap[type] || 'string'
248256
}
249257

258+
/**
259+
* Extracts trigger outputs from the first available trigger
260+
*/
261+
function extractTriggerOutputs(blockConfig: any): Record<string, OutputFieldSchema> {
262+
const outputs: Record<string, OutputFieldSchema> = {}
263+
264+
if (!blockConfig.triggers?.enabled || !blockConfig.triggers?.available?.length) {
265+
return outputs
266+
}
267+
268+
// Get the first available trigger's outputs as a baseline
269+
const triggerId = blockConfig.triggers.available[0]
270+
if (triggerId && isTriggerValid(triggerId)) {
271+
const trigger = getTrigger(triggerId)
272+
if (trigger.outputs) {
273+
for (const [key, def] of Object.entries(trigger.outputs)) {
274+
if (typeof def === 'string') {
275+
outputs[key] = { type: def }
276+
} else if (typeof def === 'object' && def !== null) {
277+
const typedDef = def as { type?: string; description?: string }
278+
outputs[key] = {
279+
type: typedDef.type || 'any',
280+
description: typedDef.description,
281+
}
282+
}
283+
}
284+
}
285+
}
286+
287+
return outputs
288+
}
289+
250290
/**
251291
* Extracts output schema from block config or tool
252292
*/
253-
function extractOutputs(blockConfig: any, operation?: string): Record<string, OutputFieldSchema> {
293+
function extractOutputs(
294+
blockConfig: any,
295+
operation?: string,
296+
triggerMode?: boolean
297+
): Record<string, OutputFieldSchema> {
254298
const outputs: Record<string, OutputFieldSchema> = {}
255299

300+
// In trigger mode, return trigger outputs
301+
if (triggerMode && blockConfig.triggers?.enabled) {
302+
return extractTriggerOutputs(blockConfig)
303+
}
304+
256305
// If operation is specified, try to get outputs from the specific tool
257306
if (operation) {
258307
try {
@@ -302,15 +351,23 @@ export const getBlockConfigServerTool: BaseServerTool<
302351
async execute({
303352
blockType,
304353
operation,
354+
trigger,
305355
}: GetBlockConfigInputType): Promise<GetBlockConfigResultType> {
306356
const logger = createLogger('GetBlockConfigServerTool')
307-
logger.debug('Executing get_block_config', { blockType, operation })
357+
logger.debug('Executing get_block_config', { blockType, operation, trigger })
308358

309359
const blockConfig = blockRegistry[blockType]
310360
if (!blockConfig) {
311361
throw new Error(`Block not found: ${blockType}`)
312362
}
313363

364+
// Validate trigger mode is supported for this block
365+
if (trigger && !blockConfig.triggers?.enabled && !blockConfig.triggerAllowed) {
366+
throw new Error(
367+
`Block "${blockType}" does not support trigger mode. Only blocks with triggers.enabled or triggerAllowed can be used in trigger mode.`
368+
)
369+
}
370+
314371
// If operation is specified, validate it exists
315372
if (operation) {
316373
const operationSubBlock = blockConfig.subBlocks?.find((sb) => sb.id === 'operation')
@@ -327,13 +384,14 @@ export const getBlockConfigServerTool: BaseServerTool<
327384
}
328385

329386
const subBlocks = Array.isArray(blockConfig.subBlocks) ? blockConfig.subBlocks : []
330-
const inputs = extractInputsFromSubBlocks(subBlocks, operation)
331-
const outputs = extractOutputs(blockConfig, operation)
387+
const inputs = extractInputsFromSubBlocks(subBlocks, operation, trigger)
388+
const outputs = extractOutputs(blockConfig, operation, trigger)
332389

333390
const result = {
334391
blockType,
335392
blockName: blockConfig.name,
336393
operation,
394+
trigger,
337395
inputs,
338396
outputs,
339397
}

apps/sim/lib/copilot/tools/shared/schemas.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,11 +57,13 @@ export type GetBlockOptionsResultType = z.infer<typeof GetBlockOptionsResult>
5757
export const GetBlockConfigInput = z.object({
5858
blockType: z.string(),
5959
operation: z.string().optional(),
60+
trigger: z.boolean().optional(),
6061
})
6162
export const GetBlockConfigResult = z.object({
6263
blockType: z.string(),
6364
blockName: z.string(),
6465
operation: z.string().optional(),
66+
trigger: z.boolean().optional(),
6567
inputs: z.record(z.any()),
6668
outputs: z.record(z.any()),
6769
})
@@ -114,6 +116,7 @@ export const GetBlockOutputsResult = z.object({
114116
blockId: z.string(),
115117
blockName: z.string(),
116118
blockType: z.string(),
119+
triggerMode: z.boolean().optional(),
117120
outputs: z.array(z.string()),
118121
insideSubflowOutputs: z.array(z.string()).optional(),
119122
outsideSubflowOutputs: z.array(z.string()).optional(),
@@ -155,6 +158,7 @@ export const GetBlockUpstreamReferencesResult = z.object({
155158
blockId: z.string(),
156159
blockName: z.string(),
157160
blockType: z.string(),
161+
triggerMode: z.boolean().optional(),
158162
outputs: z.array(z.string()),
159163
accessContext: z.enum(['inside', 'outside']).optional(),
160164
})

0 commit comments

Comments
 (0)