Skip to content

Commit 75a7dbc

Browse files
committed
Search patterns tool
1 parent 8dc8414 commit 75a7dbc

3 files changed

Lines changed: 78 additions & 1 deletion

File tree

apps/sim/lib/copilot/registry.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ export const ToolIds = z.enum([
1313
'get_operations_examples',
1414
'search_documentation',
1515
'search_online',
16+
'search_patterns',
1617
'make_api_request',
1718
'get_environment_variables',
1819
'set_environment_variables',
@@ -128,6 +129,11 @@ export const ToolArgSchemas = {
128129
hl: z.string().optional(),
129130
}),
130131

132+
search_patterns: z.object({
133+
queries: z.array(z.string()).min(1).max(3),
134+
limit: z.number().optional().default(3),
135+
}),
136+
131137
make_api_request: z.object({
132138
url: z.string(),
133139
method: z.enum(['GET', 'POST', 'PUT']),
@@ -208,6 +214,7 @@ export const ToolSSESchemas = {
208214
),
209215
search_documentation: toolCallSSEFor('search_documentation', ToolArgSchemas.search_documentation),
210216
search_online: toolCallSSEFor('search_online', ToolArgSchemas.search_online),
217+
search_patterns: toolCallSSEFor('search_patterns', ToolArgSchemas.search_patterns),
211218
make_api_request: toolCallSSEFor('make_api_request', ToolArgSchemas.make_api_request),
212219
get_environment_variables: toolCallSSEFor(
213220
'get_environment_variables',
@@ -339,6 +346,18 @@ export const ToolResultSchemas = {
339346
}),
340347
search_documentation: z.object({ results: z.array(z.any()) }),
341348
search_online: z.object({ results: z.array(z.any()) }),
349+
search_patterns: z.object({
350+
patterns: z.array(
351+
z.object({
352+
blocks_involved: z.array(z.string()).optional(),
353+
description: z.string().optional(),
354+
pattern_category: z.string().optional(),
355+
pattern_name: z.string().optional(),
356+
use_cases: z.array(z.string()).optional(),
357+
workflow_json: z.any().optional(),
358+
})
359+
),
360+
}),
342361
make_api_request: z.object({
343362
status: z.number(),
344363
statusText: z.string().optional(),
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import { Loader2, MinusCircle, Search, XCircle } from 'lucide-react'
2+
import {
3+
BaseClientTool,
4+
type BaseClientToolMetadata,
5+
ClientToolCallState,
6+
} from '@/lib/copilot/tools/client/base-tool'
7+
8+
export class SearchPatternsClientTool extends BaseClientTool {
9+
static readonly id = 'search_patterns'
10+
11+
constructor(toolCallId: string) {
12+
super(toolCallId, SearchPatternsClientTool.id, SearchPatternsClientTool.metadata)
13+
}
14+
15+
static readonly metadata: BaseClientToolMetadata = {
16+
displayNames: {
17+
[ClientToolCallState.generating]: { text: 'Searching workflow patterns', icon: Loader2 },
18+
[ClientToolCallState.pending]: { text: 'Searching workflow patterns', icon: Loader2 },
19+
[ClientToolCallState.executing]: { text: 'Searching workflow patterns', icon: Loader2 },
20+
[ClientToolCallState.success]: { text: 'Found workflow patterns', icon: Search },
21+
[ClientToolCallState.error]: { text: 'Failed to search patterns', icon: XCircle },
22+
[ClientToolCallState.aborted]: { text: 'Aborted pattern search', icon: MinusCircle },
23+
[ClientToolCallState.rejected]: { text: 'Skipped pattern search', icon: MinusCircle },
24+
},
25+
interrupt: undefined,
26+
}
27+
28+
async execute(): Promise<void> {
29+
return
30+
}
31+
}
32+

apps/sim/stores/panel-new/copilot/store.ts

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import { OAuthRequestAccessClientTool } from '@/lib/copilot/tools/client/other/o
3030
import { PlanClientTool } from '@/lib/copilot/tools/client/other/plan'
3131
import { SearchDocumentationClientTool } from '@/lib/copilot/tools/client/other/search-documentation'
3232
import { SearchOnlineClientTool } from '@/lib/copilot/tools/client/other/search-online'
33+
import { SearchPatternsClientTool } from '@/lib/copilot/tools/client/other/search-patterns'
3334
import { createExecutionContext, getTool } from '@/lib/copilot/tools/client/registry'
3435
import { GetEnvironmentVariablesClientTool } from '@/lib/copilot/tools/client/user/get-environment-variables'
3536
import { GetOAuthCredentialsClientTool } from '@/lib/copilot/tools/client/user/get-oauth-credentials'
@@ -73,6 +74,7 @@ const CLIENT_TOOL_INSTANTIATORS: Record<string, (id: string) => any> = {
7374
get_trigger_blocks: (id) => new GetTriggerBlocksClientTool(id),
7475
search_online: (id) => new SearchOnlineClientTool(id),
7576
search_documentation: (id) => new SearchDocumentationClientTool(id),
77+
search_patterns: (id) => new SearchPatternsClientTool(id),
7678
get_environment_variables: (id) => new GetEnvironmentVariablesClientTool(id),
7779
set_environment_variables: (id) => new SetEnvironmentVariablesClientTool(id),
7880
list_gdrive_files: (id) => new ListGDriveFilesClientTool(id),
@@ -105,6 +107,7 @@ export const CLASS_TOOL_METADATA: Record<string, BaseClientToolMetadata | undefi
105107
get_trigger_blocks: (GetTriggerBlocksClientTool as any)?.metadata,
106108
search_online: (SearchOnlineClientTool as any)?.metadata,
107109
search_documentation: (SearchDocumentationClientTool as any)?.metadata,
110+
search_patterns: (SearchPatternsClientTool as any)?.metadata,
108111
get_environment_variables: (GetEnvironmentVariablesClientTool as any)?.metadata,
109112
set_environment_variables: (SetEnvironmentVariablesClientTool as any)?.metadata,
110113
list_gdrive_files: (ListGDriveFilesClientTool as any)?.metadata,
@@ -159,7 +162,30 @@ function resolveToolDisplay(
159162
const meta = def?.metadata?.displayNames || CLASS_TOOL_METADATA[toolName]?.displayNames || {}
160163
// Exact state first
161164
const ds = meta?.[state]
162-
if (ds?.text || ds?.icon) return { text: ds.text, icon: ds.icon }
165+
if (ds?.text || ds?.icon) {
166+
// Special handling for search_patterns to show the first query
167+
if (toolName === 'search_patterns' && params?.queries && Array.isArray(params.queries)) {
168+
const firstQuery = params.queries[0]
169+
if (firstQuery && typeof firstQuery === 'string') {
170+
const truncatedQuery = firstQuery.length > 50 ? `${firstQuery.slice(0, 50)}...` : firstQuery
171+
const capitalizedQuery = truncatedQuery.charAt(0).toUpperCase() + truncatedQuery.slice(1)
172+
let dynamicText = ds.text
173+
if (state === ClientToolCallState.success) {
174+
dynamicText = `Searched ${capitalizedQuery}`
175+
} else if (state === ClientToolCallState.executing || state === ClientToolCallState.generating || state === ClientToolCallState.pending) {
176+
dynamicText = `Searching ${capitalizedQuery}`
177+
} else if (state === ClientToolCallState.error) {
178+
dynamicText = `Failed to search ${capitalizedQuery}`
179+
} else if (state === ClientToolCallState.aborted) {
180+
dynamicText = `Aborted searching ${capitalizedQuery}`
181+
} else if (state === ClientToolCallState.rejected) {
182+
dynamicText = `Skipped searching ${capitalizedQuery}`
183+
}
184+
return { text: dynamicText, icon: ds.icon }
185+
}
186+
}
187+
return { text: ds.text, icon: ds.icon }
188+
}
163189
// Fallback order (prefer pre-execution states for unknown states like pending)
164190
const fallbackOrder: ClientToolCallState[] = [
165191
(ClientToolCallState as any).generating,

0 commit comments

Comments
 (0)