Skip to content

Commit d55072a

Browse files
authored
feat(copilot): add context7 (#2779)
* Add context7 * Fix edit diff block ring color * Remove server side impl * Fix duplicated message on edit old message * Tables in markdown
1 parent 684ad5a commit d55072a

File tree

6 files changed

+77
-10
lines changed

6 files changed

+77
-10
lines changed

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -326,8 +326,8 @@ export default function CopilotMarkdownRenderer({ content }: CopilotMarkdownRend
326326
),
327327

328328
table: ({ children }: React.TableHTMLAttributes<HTMLTableElement>) => (
329-
<div className='my-4 max-w-full overflow-x-auto'>
330-
<table className='min-w-full table-auto border border-[var(--border-1)] font-season text-sm'>
329+
<div className='my-3 max-w-full overflow-x-auto'>
330+
<table className='min-w-full table-auto border border-[var(--border-1)] font-season text-xs'>
331331
{children}
332332
</table>
333333
</div>
@@ -346,12 +346,12 @@ export default function CopilotMarkdownRenderer({ content }: CopilotMarkdownRend
346346
</tr>
347347
),
348348
th: ({ children }: React.ThHTMLAttributes<HTMLTableCellElement>) => (
349-
<th className='border-[var(--border-1)] border-r px-4 py-2 align-top font-base text-[var(--text-secondary)] last:border-r-0 dark:font-[470]'>
349+
<th className='border-[var(--border-1)] border-r px-2.5 py-1.5 align-top font-base text-[var(--text-secondary)] last:border-r-0 dark:font-[470]'>
350350
{children}
351351
</th>
352352
),
353353
td: ({ children }: React.TdHTMLAttributes<HTMLTableCellElement>) => (
354-
<td className='break-words border-[var(--border-1)] border-r px-4 py-2 align-top font-base text-[var(--text-primary)] last:border-r-0 dark:font-[470]'>
354+
<td className='break-words border-[var(--border-1)] border-r px-2.5 py-1.5 align-top font-base text-[var(--text-primary)] last:border-r-0 dark:font-[470]'>
355355
{children}
356356
</td>
357357
),

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,7 @@ export function ThinkingBlock({
246246
)}
247247
>
248248
{/* Render markdown during streaming with thinking text styling */}
249-
<div className='[&_*]:!text-[var(--text-muted)] [&_*]:!text-[12px] [&_*]:!leading-none [&_*]:!m-0 [&_*]:!p-0 [&_*]:!mb-0 [&_*]:!mt-0 [&_p]:!m-0 [&_h1]:!text-[12px] [&_h1]:!font-semibold [&_h2]:!text-[12px] [&_h2]:!font-semibold [&_h3]:!text-[12px] [&_h3]:!font-semibold [&_code]:!text-[11px] [&_ul]:!pl-4 [&_ul]:!my-0 [&_ol]:!pl-4 [&_ol]:!my-0 [&_li]:!my-0 [&_li]:!py-0 [&_br]:!leading-[0.5] whitespace-pre-wrap font-[470] font-season text-[12px] text-[var(--text-muted)] leading-none'>
249+
<div className='[&_*]:!text-[var(--text-muted)] [&_*]:!text-[12px] [&_*]:!leading-[1.3] [&_p]:!m-0 [&_p]:!mb-1 [&_h1]:!text-[12px] [&_h1]:!font-semibold [&_h1]:!m-0 [&_h1]:!mb-1 [&_h2]:!text-[12px] [&_h2]:!font-semibold [&_h2]:!m-0 [&_h2]:!mb-1 [&_h3]:!text-[12px] [&_h3]:!font-semibold [&_h3]:!m-0 [&_h3]:!mb-1 [&_code]:!text-[11px] [&_ul]:!pl-5 [&_ul]:!my-1 [&_ol]:!pl-6 [&_ol]:!my-1 [&_li]:!my-0.5 [&_li]:!py-0 [&_br]:!leading-[0.5] [&_table]:!my-2 [&_th]:!px-2 [&_th]:!py-1 [&_th]:!text-[11px] [&_td]:!px-2 [&_td]:!py-1 [&_td]:!text-[11px] whitespace-pre-wrap font-[470] font-season text-[12px] text-[var(--text-muted)]'>
250250
<CopilotMarkdownRenderer content={content} />
251251
<span className='ml-1 inline-block h-2 w-1 animate-pulse bg-[var(--text-muted)]' />
252252
</div>
@@ -286,7 +286,7 @@ export function ThinkingBlock({
286286
)}
287287
>
288288
{/* Use markdown renderer for completed content */}
289-
<div className='[&_*]:!text-[var(--text-muted)] [&_*]:!text-[12px] [&_*]:!leading-none [&_*]:!m-0 [&_*]:!p-0 [&_*]:!mb-0 [&_*]:!mt-0 [&_p]:!m-0 [&_h1]:!text-[12px] [&_h1]:!font-semibold [&_h2]:!text-[12px] [&_h2]:!font-semibold [&_h3]:!text-[12px] [&_h3]:!font-semibold [&_code]:!text-[11px] [&_ul]:!pl-4 [&_ul]:!my-0 [&_ol]:!pl-4 [&_ol]:!my-0 [&_li]:!my-0 [&_li]:!py-0 [&_br]:!leading-[0.5] whitespace-pre-wrap font-[470] font-season text-[12px] text-[var(--text-muted)] leading-none'>
289+
<div className='[&_*]:!text-[var(--text-muted)] [&_*]:!text-[12px] [&_*]:!leading-[1.3] [&_p]:!m-0 [&_p]:!mb-1 [&_h1]:!text-[12px] [&_h1]:!font-semibold [&_h1]:!m-0 [&_h1]:!mb-1 [&_h2]:!text-[12px] [&_h2]:!font-semibold [&_h2]:!m-0 [&_h2]:!mb-1 [&_h3]:!text-[12px] [&_h3]:!font-semibold [&_h3]:!m-0 [&_h3]:!mb-1 [&_code]:!text-[11px] [&_ul]:!pl-5 [&_ul]:!my-1 [&_ol]:!pl-6 [&_ol]:!my-1 [&_li]:!my-0.5 [&_li]:!py-0 [&_br]:!leading-[0.5] [&_table]:!my-2 [&_th]:!px-2 [&_th]:!py-1 [&_th]:!text-[11px] [&_td]:!px-2 [&_td]:!py-1 [&_td]:!text-[11px] whitespace-pre-wrap font-[470] font-season text-[12px] text-[var(--text-muted)]'>
290290
<CopilotMarkdownRenderer content={content} />
291291
</div>
292292
</div>

apps/sim/app/workspace/[workspaceId]/w/[workflowId]/utils/block-ring-utils.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ export function getBlockRingStyles(options: BlockRingOptions): {
5050
!isPending &&
5151
!isDeletedBlock &&
5252
diffStatus === 'new' &&
53-
'ring-[var(--brand-tertiary)]',
53+
'ring-[var(--brand-tertiary-2)]',
5454
!isActive &&
5555
!isPending &&
5656
!isDeletedBlock &&
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import { BookOpen, Loader2, MinusCircle, 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 SearchLibraryDocsClientTool extends BaseClientTool {
9+
static readonly id = 'search_library_docs'
10+
11+
constructor(toolCallId: string) {
12+
super(toolCallId, SearchLibraryDocsClientTool.id, SearchLibraryDocsClientTool.metadata)
13+
}
14+
15+
static readonly metadata: BaseClientToolMetadata = {
16+
displayNames: {
17+
[ClientToolCallState.generating]: { text: 'Reading docs', icon: Loader2 },
18+
[ClientToolCallState.pending]: { text: 'Reading docs', icon: Loader2 },
19+
[ClientToolCallState.executing]: { text: 'Reading docs', icon: Loader2 },
20+
[ClientToolCallState.success]: { text: 'Read docs', icon: BookOpen },
21+
[ClientToolCallState.error]: { text: 'Failed to read docs', icon: XCircle },
22+
[ClientToolCallState.aborted]: { text: 'Aborted reading docs', icon: XCircle },
23+
[ClientToolCallState.rejected]: { text: 'Skipped reading docs', icon: MinusCircle },
24+
},
25+
getDynamicText: (params, state) => {
26+
const libraryName = params?.library_name
27+
if (libraryName && typeof libraryName === 'string') {
28+
switch (state) {
29+
case ClientToolCallState.success:
30+
return `Read ${libraryName} docs`
31+
case ClientToolCallState.executing:
32+
case ClientToolCallState.generating:
33+
case ClientToolCallState.pending:
34+
return `Reading ${libraryName} docs`
35+
case ClientToolCallState.error:
36+
return `Failed to read ${libraryName} docs`
37+
case ClientToolCallState.aborted:
38+
return `Aborted reading ${libraryName} docs`
39+
case ClientToolCallState.rejected:
40+
return `Skipped reading ${libraryName} docs`
41+
}
42+
}
43+
return undefined
44+
},
45+
}
46+
47+
async execute(): Promise<void> {
48+
return
49+
}
50+
}

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

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ import { RememberDebugClientTool } from '@/lib/copilot/tools/client/other/rememb
4242
import { ResearchClientTool } from '@/lib/copilot/tools/client/other/research'
4343
import { SearchDocumentationClientTool } from '@/lib/copilot/tools/client/other/search-documentation'
4444
import { SearchErrorsClientTool } from '@/lib/copilot/tools/client/other/search-errors'
45+
import { SearchLibraryDocsClientTool } from '@/lib/copilot/tools/client/other/search-library-docs'
4546
import { SearchOnlineClientTool } from '@/lib/copilot/tools/client/other/search-online'
4647
import { SearchPatternsClientTool } from '@/lib/copilot/tools/client/other/search-patterns'
4748
import { SleepClientTool } from '@/lib/copilot/tools/client/other/sleep'
@@ -116,6 +117,7 @@ const CLIENT_TOOL_INSTANTIATORS: Record<string, (id: string) => any> = {
116117
get_trigger_blocks: (id) => new GetTriggerBlocksClientTool(id),
117118
search_online: (id) => new SearchOnlineClientTool(id),
118119
search_documentation: (id) => new SearchDocumentationClientTool(id),
120+
search_library_docs: (id) => new SearchLibraryDocsClientTool(id),
119121
search_patterns: (id) => new SearchPatternsClientTool(id),
120122
search_errors: (id) => new SearchErrorsClientTool(id),
121123
remember_debug: (id) => new RememberDebugClientTool(id),
@@ -174,6 +176,7 @@ export const CLASS_TOOL_METADATA: Record<string, BaseClientToolMetadata | undefi
174176
get_trigger_blocks: (GetTriggerBlocksClientTool as any)?.metadata,
175177
search_online: (SearchOnlineClientTool as any)?.metadata,
176178
search_documentation: (SearchDocumentationClientTool as any)?.metadata,
179+
search_library_docs: (SearchLibraryDocsClientTool as any)?.metadata,
177180
search_patterns: (SearchPatternsClientTool as any)?.metadata,
178181
search_errors: (SearchErrorsClientTool as any)?.metadata,
179182
remember_debug: (RememberDebugClientTool as any)?.metadata,
@@ -2433,9 +2436,10 @@ export const useCopilotStore = create<CopilotStore>()(
24332436

24342437
// If already sending a message, queue this one instead
24352438
if (isSendingMessage) {
2436-
get().addToQueue(message, { fileAttachments, contexts })
2439+
get().addToQueue(message, { fileAttachments, contexts, messageId })
24372440
logger.info('[Copilot] Message queued (already sending)', {
24382441
queueLength: get().messageQueue.length + 1,
2442+
originalMessageId: messageId,
24392443
})
24402444
return
24412445
}
@@ -3161,8 +3165,12 @@ export const useCopilotStore = create<CopilotStore>()(
31613165
// Process next message in queue if any
31623166
const nextInQueue = get().messageQueue[0]
31633167
if (nextInQueue) {
3168+
// Use originalMessageId if available (from edit/resend), otherwise use queue entry id
3169+
const messageIdToUse = nextInQueue.originalMessageId || nextInQueue.id
31643170
logger.info('[Queue] Processing next queued message', {
31653171
id: nextInQueue.id,
3172+
originalMessageId: nextInQueue.originalMessageId,
3173+
messageIdToUse,
31663174
queueLength: get().messageQueue.length,
31673175
})
31683176
// Remove from queue and send
@@ -3173,7 +3181,7 @@ export const useCopilotStore = create<CopilotStore>()(
31733181
stream: true,
31743182
fileAttachments: nextInQueue.fileAttachments,
31753183
contexts: nextInQueue.contexts,
3176-
messageId: nextInQueue.id,
3184+
messageId: messageIdToUse,
31773185
})
31783186
}, 100)
31793187
}
@@ -3615,10 +3623,12 @@ export const useCopilotStore = create<CopilotStore>()(
36153623
fileAttachments: options?.fileAttachments,
36163624
contexts: options?.contexts,
36173625
queuedAt: Date.now(),
3626+
originalMessageId: options?.messageId,
36183627
}
36193628
set({ messageQueue: [...get().messageQueue, queuedMessage] })
36203629
logger.info('[Queue] Message added to queue', {
36213630
id: queuedMessage.id,
3631+
originalMessageId: options?.messageId,
36223632
queueLength: get().messageQueue.length,
36233633
})
36243634
},
@@ -3659,12 +3669,15 @@ export const useCopilotStore = create<CopilotStore>()(
36593669
await new Promise((resolve) => setTimeout(resolve, 50))
36603670
}
36613671

3672+
// Use originalMessageId if available (from edit/resend), otherwise use queue entry id
3673+
const messageIdToUse = message.originalMessageId || message.id
3674+
36623675
// Send the message
36633676
await get().sendMessage(message.content, {
36643677
stream: true,
36653678
fileAttachments: message.fileAttachments,
36663679
contexts: message.contexts,
3667-
messageId: message.id,
3680+
messageId: messageIdToUse,
36683681
})
36693682
},
36703683

apps/sim/stores/panel/copilot/types.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ export interface QueuedMessage {
7070
fileAttachments?: MessageFileAttachment[]
7171
contexts?: ChatContext[]
7272
queuedAt: number
73+
/** Original messageId to use when processing (for edit/resend flows) */
74+
originalMessageId?: string
7375
}
7476

7577
// Contexts attached to a user message
@@ -249,6 +251,8 @@ export interface CopilotActions {
249251
options?: {
250252
fileAttachments?: MessageFileAttachment[]
251253
contexts?: ChatContext[]
254+
/** Original messageId to preserve (for edit/resend flows) */
255+
messageId?: string
252256
}
253257
) => void
254258
removeFromQueue: (id: string) => void

0 commit comments

Comments
 (0)