Last active
October 2, 2025 16:02
-
-
Save mrwithersea/c04f6ad04e40708452879ed44a50e478 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| const ContextualSuggestions = () => { | |
| const thread = useThread(); | |
| const [suggestions, setSuggestions] = useState< | |
| Array<{ prompt: string; label: string }> | |
| >([]); | |
| useEffect(() => { | |
| const generateContextualSuggestions = () => { | |
| const messages = thread.messages; | |
| const lastAssistantMessage = messages | |
| .filter((m: { role: string }) => m.role === 'assistant') | |
| .pop(); | |
| if (!lastAssistantMessage) return []; | |
| // Extract the assistant's message text content | |
| const messageText = lastAssistantMessage.content | |
| .filter((part) => part.type === 'text') | |
| .map((part) => part.text) | |
| .join(' '); | |
| const toolCalls = | |
| lastAssistantMessage.content.filter( | |
| (part) => part.type === 'tool-call' | |
| ) || []; | |
| return toolCalls.flatMap((toolCall) => { | |
| switch (toolCall.toolName) { | |
| case 'suggest_contact': | |
| const result = toolCall.result as { | |
| structuredContent: { | |
| suggestedContacts: { contactName: string }[]; | |
| }; | |
| }; | |
| if (!result) return []; | |
| // Filter contacts to only include those mentioned in the assistant's message | |
| const mentionedContacts = | |
| result.structuredContent.suggestedContacts.filter((contact) => | |
| messageText.includes(contact.contactName) | |
| ); | |
| return mentionedContacts.map((contact) => ({ | |
| prompt: contact.contactName, | |
| label: contact.contactName, | |
| })); | |
| case 'suggest_contract_template': | |
| const contractTemplateResult = toolCall.result as { | |
| structuredContent: { | |
| nextCursor: string; | |
| templates: { | |
| templateName: string; | |
| templateId: string; | |
| }[]; | |
| }; | |
| }; | |
| if (!contractTemplateResult) return []; | |
| // Filter contract templates to only include those mentioned in the assistant's message | |
| const mentionedTemplates = | |
| contractTemplateResult.structuredContent.templates.filter( | |
| (template) => messageText.includes(template.templateName) | |
| ); | |
| return mentionedTemplates | |
| ? [ | |
| ...mentionedTemplates.map((template) => ({ | |
| prompt: `${template.templateName} (${template.templateId})`, | |
| label: template.templateName, | |
| })), | |
| ...(contractTemplateResult.structuredContent.nextCursor | |
| ? [ | |
| { | |
| prompt: 'Show more templates', | |
| label: 'Show more', | |
| }, | |
| ] | |
| : []), | |
| ] | |
| : []; | |
| default: | |
| return []; | |
| } | |
| }); | |
| }; | |
| const newSuggestions = generateContextualSuggestions(); | |
| setSuggestions(newSuggestions); | |
| }, [thread.messages]); | |
| return ( | |
| <ThreadPrimitive.If running={false}> | |
| {suggestions.length > 0 && ( | |
| <div className={styles.contextualSuggestions}> | |
| {suggestions.map((suggestion, index) => ( | |
| <ThreadPrimitive.Suggestion | |
| key={index} | |
| asChild | |
| prompt={suggestion.prompt} | |
| method="replace" | |
| autoSend | |
| > | |
| <ButtonTag IconPrefix={NewSmall}>{suggestion.label}</ButtonTag> | |
| </ThreadPrimitive.Suggestion> | |
| ))} | |
| </div> | |
| )} | |
| </ThreadPrimitive.If> | |
| ); | |
| }; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment