From 0f51055ee191799c293c2b23ee26f3bd0de9e700 Mon Sep 17 00:00:00 2001 From: Siddharth Ganesan Date: Mon, 12 Jan 2026 11:53:28 -0800 Subject: [PATCH 1/5] Add context7 --- .../tools/client/other/search-library-docs.ts | 83 ++++++++++ .../tools/server/docs/search-library-docs.ts | 156 ++++++++++++++++++ apps/sim/lib/copilot/tools/server/router.ts | 2 + apps/sim/stores/panel/copilot/store.ts | 3 + 4 files changed, 244 insertions(+) create mode 100644 apps/sim/lib/copilot/tools/client/other/search-library-docs.ts create mode 100644 apps/sim/lib/copilot/tools/server/docs/search-library-docs.ts diff --git a/apps/sim/lib/copilot/tools/client/other/search-library-docs.ts b/apps/sim/lib/copilot/tools/client/other/search-library-docs.ts new file mode 100644 index 0000000000..a9fccbdbaf --- /dev/null +++ b/apps/sim/lib/copilot/tools/client/other/search-library-docs.ts @@ -0,0 +1,83 @@ +import { createLogger } from '@sim/logger' +import { BookOpen, Loader2, MinusCircle, XCircle } from 'lucide-react' +import { + BaseClientTool, + type BaseClientToolMetadata, + ClientToolCallState, +} from '@/lib/copilot/tools/client/base-tool' +import { ExecuteResponseSuccessSchema } from '@/lib/copilot/tools/shared/schemas' + +interface SearchLibraryDocsArgs { + library_name: string + query: string + version?: string +} + +export class SearchLibraryDocsClientTool extends BaseClientTool { + static readonly id = 'search_library_docs' + + constructor(toolCallId: string) { + super(toolCallId, SearchLibraryDocsClientTool.id, SearchLibraryDocsClientTool.metadata) + } + + static readonly metadata: BaseClientToolMetadata = { + displayNames: { + [ClientToolCallState.generating]: { text: 'Reading docs', icon: Loader2 }, + [ClientToolCallState.pending]: { text: 'Reading docs', icon: Loader2 }, + [ClientToolCallState.executing]: { text: 'Reading docs', icon: Loader2 }, + [ClientToolCallState.success]: { text: 'Read docs', icon: BookOpen }, + [ClientToolCallState.error]: { text: 'Failed to read docs', icon: XCircle }, + [ClientToolCallState.aborted]: { text: 'Aborted reading docs', icon: XCircle }, + [ClientToolCallState.rejected]: { text: 'Skipped reading docs', icon: MinusCircle }, + }, + getDynamicText: (params, state) => { + const libraryName = params?.library_name + if (libraryName && typeof libraryName === 'string') { + switch (state) { + case ClientToolCallState.success: + return `Read ${libraryName} docs` + case ClientToolCallState.executing: + case ClientToolCallState.generating: + case ClientToolCallState.pending: + return `Reading ${libraryName} docs` + case ClientToolCallState.error: + return `Failed to read ${libraryName} docs` + case ClientToolCallState.aborted: + return `Aborted reading ${libraryName} docs` + case ClientToolCallState.rejected: + return `Skipped reading ${libraryName} docs` + } + } + return undefined + }, + } + + async execute(args?: SearchLibraryDocsArgs): Promise { + const logger = createLogger('SearchLibraryDocsClientTool') + try { + this.setState(ClientToolCallState.executing) + const res = await fetch('/api/copilot/execute-copilot-server-tool', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ toolName: 'search_library_docs', payload: args || {} }), + }) + if (!res.ok) { + const txt = await res.text().catch(() => '') + throw new Error(txt || `Server error (${res.status})`) + } + const json = await res.json() + const parsed = ExecuteResponseSuccessSchema.parse(json) + this.setState(ClientToolCallState.success) + await this.markToolComplete( + 200, + `Library documentation search complete for ${args?.library_name || 'unknown'}`, + parsed.result + ) + this.setState(ClientToolCallState.success) + } catch (e: any) { + logger.error('execute failed', { message: e?.message }) + this.setState(ClientToolCallState.error) + await this.markToolComplete(500, e?.message || 'Library documentation search failed') + } + } +} diff --git a/apps/sim/lib/copilot/tools/server/docs/search-library-docs.ts b/apps/sim/lib/copilot/tools/server/docs/search-library-docs.ts new file mode 100644 index 0000000000..cc76a02777 --- /dev/null +++ b/apps/sim/lib/copilot/tools/server/docs/search-library-docs.ts @@ -0,0 +1,156 @@ +import { createLogger } from '@sim/logger' +import type { BaseServerTool } from '@/lib/copilot/tools/server/base-tool' +import { env } from '@/lib/core/config/env' +import { executeTool } from '@/tools' + +interface SearchLibraryDocsParams { + library_name: string + query: string + version?: string +} + +interface SearchLibraryDocsResult { + results: Array<{ + title: string + link: string + snippet: string + position?: number + }> + query: string + library: string + version?: string + totalResults: number +} + +export const searchLibraryDocsServerTool: BaseServerTool< + SearchLibraryDocsParams, + SearchLibraryDocsResult +> = { + name: 'search_library_docs', + async execute(params: SearchLibraryDocsParams): Promise { + const logger = createLogger('SearchLibraryDocsServerTool') + const { library_name, query, version } = params + + if (!library_name || typeof library_name !== 'string') { + throw new Error('library_name is required') + } + if (!query || typeof query !== 'string') { + throw new Error('query is required') + } + + // Build a search query that targets the library's documentation + const searchQuery = version + ? `${library_name} ${version} documentation ${query}` + : `${library_name} documentation ${query}` + + logger.info('Searching library documentation', { + library: library_name, + query, + version, + fullSearchQuery: searchQuery, + }) + + // Check which API keys are available + const hasExaApiKey = Boolean(env.EXA_API_KEY && String(env.EXA_API_KEY).length > 0) + const hasSerperApiKey = Boolean(env.SERPER_API_KEY && String(env.SERPER_API_KEY).length > 0) + + // Try Exa first if available (better for documentation searches) + if (hasExaApiKey) { + try { + logger.debug('Attempting exa_search for library docs', { library: library_name }) + const exaResult = await executeTool('exa_search', { + query: searchQuery, + numResults: 10, + type: 'auto', + apiKey: env.EXA_API_KEY || '', + }) + + const exaResults = (exaResult as any)?.output?.results || [] + const count = Array.isArray(exaResults) ? exaResults.length : 0 + + logger.info('exa_search for library docs completed', { + success: exaResult.success, + resultsCount: count, + library: library_name, + }) + + if (exaResult.success && count > 0) { + const transformedResults = exaResults.map((result: any, idx: number) => ({ + title: result.title || '', + link: result.url || '', + snippet: result.text || result.summary || '', + position: idx + 1, + })) + + return { + results: transformedResults, + query, + library: library_name, + version, + totalResults: count, + } + } + + logger.warn('exa_search returned no results for library docs, falling back to Serper', { + library: library_name, + }) + } catch (exaError: any) { + logger.warn('exa_search failed for library docs, falling back to Serper', { + error: exaError?.message, + library: library_name, + }) + } + } + + // Fall back to Serper if Exa failed or wasn't available + if (!hasSerperApiKey) { + throw new Error('No search API keys available (EXA_API_KEY or SERPER_API_KEY required)') + } + + try { + logger.debug('Calling serper_search for library docs', { library: library_name }) + const result = await executeTool('serper_search', { + query: searchQuery, + num: 10, + type: 'search', + apiKey: env.SERPER_API_KEY || '', + }) + + const results = (result as any)?.output?.searchResults || [] + const count = Array.isArray(results) ? results.length : 0 + + logger.info('serper_search for library docs completed', { + success: result.success, + resultsCount: count, + library: library_name, + }) + + if (!result.success) { + logger.error('serper_search failed for library docs', { error: (result as any)?.error }) + throw new Error((result as any)?.error || 'Library documentation search failed') + } + + // Transform serper results to match expected format + const transformedResults = results.map((result: any, idx: number) => ({ + title: result.title || '', + link: result.link || '', + snippet: result.snippet || '', + position: idx + 1, + })) + + return { + results: transformedResults, + query, + library: library_name, + version, + totalResults: count, + } + } catch (e: any) { + logger.error('search_library_docs execution error', { + message: e?.message, + library: library_name, + }) + throw e + } + }, +} diff --git a/apps/sim/lib/copilot/tools/server/router.ts b/apps/sim/lib/copilot/tools/server/router.ts index c8d76e0155..caf870c591 100644 --- a/apps/sim/lib/copilot/tools/server/router.ts +++ b/apps/sim/lib/copilot/tools/server/router.ts @@ -6,6 +6,7 @@ import { getBlocksAndToolsServerTool } from '@/lib/copilot/tools/server/blocks/g import { getBlocksMetadataServerTool } from '@/lib/copilot/tools/server/blocks/get-blocks-metadata-tool' import { getTriggerBlocksServerTool } from '@/lib/copilot/tools/server/blocks/get-trigger-blocks' import { searchDocumentationServerTool } from '@/lib/copilot/tools/server/docs/search-documentation' +import { searchLibraryDocsServerTool } from '@/lib/copilot/tools/server/docs/search-library-docs' import { KnowledgeBaseInput, knowledgeBaseServerTool, @@ -47,6 +48,7 @@ serverToolRegistry[getTriggerBlocksServerTool.name] = getTriggerBlocksServerTool serverToolRegistry[editWorkflowServerTool.name] = editWorkflowServerTool serverToolRegistry[getWorkflowConsoleServerTool.name] = getWorkflowConsoleServerTool serverToolRegistry[searchDocumentationServerTool.name] = searchDocumentationServerTool +serverToolRegistry[searchLibraryDocsServerTool.name] = searchLibraryDocsServerTool serverToolRegistry[searchOnlineServerTool.name] = searchOnlineServerTool serverToolRegistry[setEnvironmentVariablesServerTool.name] = setEnvironmentVariablesServerTool serverToolRegistry[getCredentialsServerTool.name] = getCredentialsServerTool diff --git a/apps/sim/stores/panel/copilot/store.ts b/apps/sim/stores/panel/copilot/store.ts index d4e926c91e..b45148ecb1 100644 --- a/apps/sim/stores/panel/copilot/store.ts +++ b/apps/sim/stores/panel/copilot/store.ts @@ -42,6 +42,7 @@ import { RememberDebugClientTool } from '@/lib/copilot/tools/client/other/rememb 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 { SearchLibraryDocsClientTool } from '@/lib/copilot/tools/client/other/search-library-docs' 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' @@ -116,6 +117,7 @@ const CLIENT_TOOL_INSTANTIATORS: Record any> = { get_trigger_blocks: (id) => new GetTriggerBlocksClientTool(id), search_online: (id) => new SearchOnlineClientTool(id), search_documentation: (id) => new SearchDocumentationClientTool(id), + search_library_docs: (id) => new SearchLibraryDocsClientTool(id), search_patterns: (id) => new SearchPatternsClientTool(id), search_errors: (id) => new SearchErrorsClientTool(id), remember_debug: (id) => new RememberDebugClientTool(id), @@ -174,6 +176,7 @@ export const CLASS_TOOL_METADATA: Record Date: Mon, 12 Jan 2026 12:51:44 -0800 Subject: [PATCH 2/5] Fix edit diff block ring color --- .../[workspaceId]/w/[workflowId]/utils/block-ring-utils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/utils/block-ring-utils.ts b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/utils/block-ring-utils.ts index 1490d6040b..634d28a86e 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/utils/block-ring-utils.ts +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/utils/block-ring-utils.ts @@ -50,7 +50,7 @@ export function getBlockRingStyles(options: BlockRingOptions): { !isPending && !isDeletedBlock && diffStatus === 'new' && - 'ring-[var(--brand-tertiary)]', + 'ring-[var(--brand-tertiary-2)]', !isActive && !isPending && !isDeletedBlock && From 94eff3f74236cf6b7339a90608ae66635b98d10e Mon Sep 17 00:00:00 2001 From: Siddharth Ganesan Date: Mon, 12 Jan 2026 13:14:05 -0800 Subject: [PATCH 3/5] Remove server side impl --- .../tools/client/other/search-library-docs.ts | 37 +---- .../tools/server/docs/search-library-docs.ts | 156 ------------------ apps/sim/lib/copilot/tools/server/router.ts | 2 - 3 files changed, 2 insertions(+), 193 deletions(-) delete mode 100644 apps/sim/lib/copilot/tools/server/docs/search-library-docs.ts diff --git a/apps/sim/lib/copilot/tools/client/other/search-library-docs.ts b/apps/sim/lib/copilot/tools/client/other/search-library-docs.ts index a9fccbdbaf..7dcff295b2 100644 --- a/apps/sim/lib/copilot/tools/client/other/search-library-docs.ts +++ b/apps/sim/lib/copilot/tools/client/other/search-library-docs.ts @@ -1,17 +1,9 @@ -import { createLogger } from '@sim/logger' import { BookOpen, Loader2, MinusCircle, XCircle } from 'lucide-react' import { BaseClientTool, type BaseClientToolMetadata, ClientToolCallState, } from '@/lib/copilot/tools/client/base-tool' -import { ExecuteResponseSuccessSchema } from '@/lib/copilot/tools/shared/schemas' - -interface SearchLibraryDocsArgs { - library_name: string - query: string - version?: string -} export class SearchLibraryDocsClientTool extends BaseClientTool { static readonly id = 'search_library_docs' @@ -52,32 +44,7 @@ export class SearchLibraryDocsClientTool extends BaseClientTool { }, } - async execute(args?: SearchLibraryDocsArgs): Promise { - const logger = createLogger('SearchLibraryDocsClientTool') - try { - this.setState(ClientToolCallState.executing) - const res = await fetch('/api/copilot/execute-copilot-server-tool', { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ toolName: 'search_library_docs', payload: args || {} }), - }) - if (!res.ok) { - const txt = await res.text().catch(() => '') - throw new Error(txt || `Server error (${res.status})`) - } - const json = await res.json() - const parsed = ExecuteResponseSuccessSchema.parse(json) - this.setState(ClientToolCallState.success) - await this.markToolComplete( - 200, - `Library documentation search complete for ${args?.library_name || 'unknown'}`, - parsed.result - ) - this.setState(ClientToolCallState.success) - } catch (e: any) { - logger.error('execute failed', { message: e?.message }) - this.setState(ClientToolCallState.error) - await this.markToolComplete(500, e?.message || 'Library documentation search failed') - } + async execute(): Promise { + return } } diff --git a/apps/sim/lib/copilot/tools/server/docs/search-library-docs.ts b/apps/sim/lib/copilot/tools/server/docs/search-library-docs.ts deleted file mode 100644 index cc76a02777..0000000000 --- a/apps/sim/lib/copilot/tools/server/docs/search-library-docs.ts +++ /dev/null @@ -1,156 +0,0 @@ -import { createLogger } from '@sim/logger' -import type { BaseServerTool } from '@/lib/copilot/tools/server/base-tool' -import { env } from '@/lib/core/config/env' -import { executeTool } from '@/tools' - -interface SearchLibraryDocsParams { - library_name: string - query: string - version?: string -} - -interface SearchLibraryDocsResult { - results: Array<{ - title: string - link: string - snippet: string - position?: number - }> - query: string - library: string - version?: string - totalResults: number -} - -export const searchLibraryDocsServerTool: BaseServerTool< - SearchLibraryDocsParams, - SearchLibraryDocsResult -> = { - name: 'search_library_docs', - async execute(params: SearchLibraryDocsParams): Promise { - const logger = createLogger('SearchLibraryDocsServerTool') - const { library_name, query, version } = params - - if (!library_name || typeof library_name !== 'string') { - throw new Error('library_name is required') - } - if (!query || typeof query !== 'string') { - throw new Error('query is required') - } - - // Build a search query that targets the library's documentation - const searchQuery = version - ? `${library_name} ${version} documentation ${query}` - : `${library_name} documentation ${query}` - - logger.info('Searching library documentation', { - library: library_name, - query, - version, - fullSearchQuery: searchQuery, - }) - - // Check which API keys are available - const hasExaApiKey = Boolean(env.EXA_API_KEY && String(env.EXA_API_KEY).length > 0) - const hasSerperApiKey = Boolean(env.SERPER_API_KEY && String(env.SERPER_API_KEY).length > 0) - - // Try Exa first if available (better for documentation searches) - if (hasExaApiKey) { - try { - logger.debug('Attempting exa_search for library docs', { library: library_name }) - const exaResult = await executeTool('exa_search', { - query: searchQuery, - numResults: 10, - type: 'auto', - apiKey: env.EXA_API_KEY || '', - }) - - const exaResults = (exaResult as any)?.output?.results || [] - const count = Array.isArray(exaResults) ? exaResults.length : 0 - - logger.info('exa_search for library docs completed', { - success: exaResult.success, - resultsCount: count, - library: library_name, - }) - - if (exaResult.success && count > 0) { - const transformedResults = exaResults.map((result: any, idx: number) => ({ - title: result.title || '', - link: result.url || '', - snippet: result.text || result.summary || '', - position: idx + 1, - })) - - return { - results: transformedResults, - query, - library: library_name, - version, - totalResults: count, - } - } - - logger.warn('exa_search returned no results for library docs, falling back to Serper', { - library: library_name, - }) - } catch (exaError: any) { - logger.warn('exa_search failed for library docs, falling back to Serper', { - error: exaError?.message, - library: library_name, - }) - } - } - - // Fall back to Serper if Exa failed or wasn't available - if (!hasSerperApiKey) { - throw new Error('No search API keys available (EXA_API_KEY or SERPER_API_KEY required)') - } - - try { - logger.debug('Calling serper_search for library docs', { library: library_name }) - const result = await executeTool('serper_search', { - query: searchQuery, - num: 10, - type: 'search', - apiKey: env.SERPER_API_KEY || '', - }) - - const results = (result as any)?.output?.searchResults || [] - const count = Array.isArray(results) ? results.length : 0 - - logger.info('serper_search for library docs completed', { - success: result.success, - resultsCount: count, - library: library_name, - }) - - if (!result.success) { - logger.error('serper_search failed for library docs', { error: (result as any)?.error }) - throw new Error((result as any)?.error || 'Library documentation search failed') - } - - // Transform serper results to match expected format - const transformedResults = results.map((result: any, idx: number) => ({ - title: result.title || '', - link: result.link || '', - snippet: result.snippet || '', - position: idx + 1, - })) - - return { - results: transformedResults, - query, - library: library_name, - version, - totalResults: count, - } - } catch (e: any) { - logger.error('search_library_docs execution error', { - message: e?.message, - library: library_name, - }) - throw e - } - }, -} diff --git a/apps/sim/lib/copilot/tools/server/router.ts b/apps/sim/lib/copilot/tools/server/router.ts index caf870c591..c8d76e0155 100644 --- a/apps/sim/lib/copilot/tools/server/router.ts +++ b/apps/sim/lib/copilot/tools/server/router.ts @@ -6,7 +6,6 @@ import { getBlocksAndToolsServerTool } from '@/lib/copilot/tools/server/blocks/g import { getBlocksMetadataServerTool } from '@/lib/copilot/tools/server/blocks/get-blocks-metadata-tool' import { getTriggerBlocksServerTool } from '@/lib/copilot/tools/server/blocks/get-trigger-blocks' import { searchDocumentationServerTool } from '@/lib/copilot/tools/server/docs/search-documentation' -import { searchLibraryDocsServerTool } from '@/lib/copilot/tools/server/docs/search-library-docs' import { KnowledgeBaseInput, knowledgeBaseServerTool, @@ -48,7 +47,6 @@ serverToolRegistry[getTriggerBlocksServerTool.name] = getTriggerBlocksServerTool serverToolRegistry[editWorkflowServerTool.name] = editWorkflowServerTool serverToolRegistry[getWorkflowConsoleServerTool.name] = getWorkflowConsoleServerTool serverToolRegistry[searchDocumentationServerTool.name] = searchDocumentationServerTool -serverToolRegistry[searchLibraryDocsServerTool.name] = searchLibraryDocsServerTool serverToolRegistry[searchOnlineServerTool.name] = searchOnlineServerTool serverToolRegistry[setEnvironmentVariablesServerTool.name] = setEnvironmentVariablesServerTool serverToolRegistry[getCredentialsServerTool.name] = getCredentialsServerTool From 6c1c13c4e27c2c45d7ee5e0572f6f88aaa25ce6d Mon Sep 17 00:00:00 2001 From: Siddharth Ganesan Date: Mon, 12 Jan 2026 16:54:41 -0800 Subject: [PATCH 4/5] Fix duplicated message on edit old message --- apps/sim/stores/panel/copilot/store.ts | 16 +++++++++++++--- apps/sim/stores/panel/copilot/types.ts | 4 ++++ 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/apps/sim/stores/panel/copilot/store.ts b/apps/sim/stores/panel/copilot/store.ts index b45148ecb1..97b785177a 100644 --- a/apps/sim/stores/panel/copilot/store.ts +++ b/apps/sim/stores/panel/copilot/store.ts @@ -2436,9 +2436,10 @@ export const useCopilotStore = create()( // If already sending a message, queue this one instead if (isSendingMessage) { - get().addToQueue(message, { fileAttachments, contexts }) + get().addToQueue(message, { fileAttachments, contexts, messageId }) logger.info('[Copilot] Message queued (already sending)', { queueLength: get().messageQueue.length + 1, + originalMessageId: messageId, }) return } @@ -3164,8 +3165,12 @@ export const useCopilotStore = create()( // Process next message in queue if any const nextInQueue = get().messageQueue[0] if (nextInQueue) { + // Use originalMessageId if available (from edit/resend), otherwise use queue entry id + const messageIdToUse = nextInQueue.originalMessageId || nextInQueue.id logger.info('[Queue] Processing next queued message', { id: nextInQueue.id, + originalMessageId: nextInQueue.originalMessageId, + messageIdToUse, queueLength: get().messageQueue.length, }) // Remove from queue and send @@ -3176,7 +3181,7 @@ export const useCopilotStore = create()( stream: true, fileAttachments: nextInQueue.fileAttachments, contexts: nextInQueue.contexts, - messageId: nextInQueue.id, + messageId: messageIdToUse, }) }, 100) } @@ -3618,10 +3623,12 @@ export const useCopilotStore = create()( fileAttachments: options?.fileAttachments, contexts: options?.contexts, queuedAt: Date.now(), + originalMessageId: options?.messageId, } set({ messageQueue: [...get().messageQueue, queuedMessage] }) logger.info('[Queue] Message added to queue', { id: queuedMessage.id, + originalMessageId: options?.messageId, queueLength: get().messageQueue.length, }) }, @@ -3662,12 +3669,15 @@ export const useCopilotStore = create()( await new Promise((resolve) => setTimeout(resolve, 50)) } + // Use originalMessageId if available (from edit/resend), otherwise use queue entry id + const messageIdToUse = message.originalMessageId || message.id + // Send the message await get().sendMessage(message.content, { stream: true, fileAttachments: message.fileAttachments, contexts: message.contexts, - messageId: message.id, + messageId: messageIdToUse, }) }, diff --git a/apps/sim/stores/panel/copilot/types.ts b/apps/sim/stores/panel/copilot/types.ts index bf9b210d88..fbb6404aac 100644 --- a/apps/sim/stores/panel/copilot/types.ts +++ b/apps/sim/stores/panel/copilot/types.ts @@ -70,6 +70,8 @@ export interface QueuedMessage { fileAttachments?: MessageFileAttachment[] contexts?: ChatContext[] queuedAt: number + /** Original messageId to use when processing (for edit/resend flows) */ + originalMessageId?: string } // Contexts attached to a user message @@ -249,6 +251,8 @@ export interface CopilotActions { options?: { fileAttachments?: MessageFileAttachment[] contexts?: ChatContext[] + /** Original messageId to preserve (for edit/resend flows) */ + messageId?: string } ) => void removeFromQueue: (id: string) => void From 2f28fb1e4c3c24383b7cafe0461f703c2097b8e7 Mon Sep 17 00:00:00 2001 From: Siddharth Ganesan Date: Mon, 12 Jan 2026 16:57:43 -0800 Subject: [PATCH 5/5] Tables in markdown --- .../copilot-message/components/markdown-renderer.tsx | 8 ++++---- .../copilot-message/components/thinking-block.tsx | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/copilot-message/components/markdown-renderer.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/copilot-message/components/markdown-renderer.tsx index dd9e45cfcc..dcc2dffd06 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/copilot-message/components/markdown-renderer.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/copilot-message/components/markdown-renderer.tsx @@ -326,8 +326,8 @@ export default function CopilotMarkdownRenderer({ content }: CopilotMarkdownRend ), table: ({ children }: React.TableHTMLAttributes) => ( -
- +
+
{children}
@@ -346,12 +346,12 @@ export default function CopilotMarkdownRenderer({ content }: CopilotMarkdownRend ), th: ({ children }: React.ThHTMLAttributes) => ( - + {children} ), td: ({ children }: React.TdHTMLAttributes) => ( - + {children} ), diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/copilot-message/components/thinking-block.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/copilot-message/components/thinking-block.tsx index e1bfda0baa..54c7042e75 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/copilot-message/components/thinking-block.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/copilot-message/components/thinking-block.tsx @@ -246,7 +246,7 @@ export function ThinkingBlock({ )} > {/* Render markdown during streaming with thinking text styling */} -
+
@@ -286,7 +286,7 @@ export function ThinkingBlock({ )} > {/* Use markdown renderer for completed content */} -
+