11'use client' ;
22
3+ import {
4+ Conversation ,
5+ ConversationContent ,
6+ ConversationScrollButton ,
7+ } from '@comp/ui/ai-elements/conversation' ;
38import {
49 PromptInput ,
510 PromptInputFooter ,
@@ -9,13 +14,7 @@ import {
914import { Tool , ToolHeader } from '@comp/ui/ai-elements/tool' ;
1015import { Button } from '@comp/ui/button' ;
1116import { cn } from '@comp/ui/cn' ;
12- import {
13- getToolName ,
14- isToolUIPart ,
15- type ChatStatus ,
16- type ToolUIPart ,
17- type UIMessage ,
18- } from 'ai' ;
17+ import { getToolName , isToolUIPart , type ChatStatus , type ToolUIPart , type UIMessage } from 'ai' ;
1918import { X } from 'lucide-react' ;
2019import { useState } from 'react' ;
2120
@@ -42,8 +41,7 @@ export function PolicyAiAssistant({
4241 ( m ) =>
4342 m . role === 'assistant' &&
4443 m . parts . some (
45- ( p ) =>
46- isToolUIPart ( p ) && ( p . state === 'input-streaming' || p . state === 'input-available' ) ,
44+ ( p ) => isToolUIPart ( p ) && ( p . state === 'input-streaming' || p . state === 'input-available' ) ,
4745 ) ,
4846 ) ;
4947
@@ -64,59 +62,65 @@ export function PolicyAiAssistant({
6462 ) }
6563 </ div >
6664
67- < div className = "flex-1 overflow-y-auto p-3 space-y-3" >
68- { messages . length === 0 ? (
69- < div className = "text-sm text-muted-foreground py-4" >
70- < p > Ask me to help edit this policy.</ p >
71- < ul className = "mt-2 space-y-1 text-xs" >
72- < li > "Add a data retention section"</ li >
73- < li > "Make this more SOC 2 compliant"</ li >
74- < li > "Simplify the language"</ li >
75- </ ul >
76- </ div >
77- ) : (
78- messages . map ( ( message ) => (
79- < div
80- key = { message . id }
81- className = { cn (
82- 'text-sm' ,
83- message . role === 'user'
84- ? 'ml-auto max-w-[85%] rounded-lg bg-secondary px-3 py-2'
85- : 'text-foreground'
86- ) }
87- >
88- { message . parts . map ( ( part , index ) => {
89- if ( part . type === 'text' ) {
90- return (
91- < div key = { `${ message . id } -${ index } ` } className = "whitespace-pre-wrap" >
92- { part . text }
93- </ div >
94- ) ;
95- }
65+ < Conversation >
66+ < ConversationContent className = "gap-3 p-3" >
67+ { messages . length === 0 ? (
68+ < div className = "text-sm text-muted-foreground py-4" >
69+ < p > Ask me to help edit this policy.</ p >
70+ < ul className = "mt-2 space-y-1 text-xs" >
71+ < li > "Add a data retention section"</ li >
72+ < li > "Make this more SOC 2 compliant"</ li >
73+ < li > "Simplify the language"</ li >
74+ </ ul >
75+ </ div >
76+ ) : (
77+ messages . map ( ( message ) => (
78+ < div
79+ key = { message . id }
80+ className = { cn (
81+ 'text-sm' ,
82+ message . role === 'user'
83+ ? 'ml-auto max-w-[85%] rounded-lg bg-secondary px-3 py-2'
84+ : 'text-foreground' ,
85+ ) }
86+ >
87+ { message . parts . map ( ( part , index ) => {
88+ if ( part . type === 'text' ) {
89+ return (
90+ < div key = { `${ message . id } -${ index } ` } className = "whitespace-pre-wrap" >
91+ { part . text }
92+ </ div >
93+ ) ;
94+ }
9695
97- if ( isToolUIPart ( part ) && getToolName ( part ) === 'proposePolicy' ) {
98- const toolPart = part as ToolUIPart ;
99- const toolInput = toolPart . input as { content ?: string ; summary ?: string } ;
100- return (
101- < Tool key = { `${ message . id } -${ index } ` } className = "mt-2" >
102- < ToolHeader
103- title = { toolInput ?. summary || 'Proposing policy changes' }
104- type = { toolPart . type }
105- state = { toolPart . state }
106- />
107- </ Tool >
108- ) ;
109- }
96+ if ( isToolUIPart ( part ) && getToolName ( part ) === 'proposePolicy' ) {
97+ const toolPart = part as ToolUIPart ;
98+ const toolInput = toolPart . input as { content ?: string ; summary ?: string } ;
99+ return (
100+ < Tool key = { `${ message . id } -${ index } ` } className = "mt-2" >
101+ < ToolHeader
102+ title = { toolInput ?. summary || 'Proposing policy changes' }
103+ type = { toolPart . type }
104+ state = { toolPart . state }
105+ />
106+ < p className = "px-3 pb-2 text-xs text-muted-foreground" >
107+ View the proposed changes in the editor preview
108+ </ p >
109+ </ Tool >
110+ ) ;
111+ }
110112
111- return null ;
112- } ) }
113- </ div >
114- ) )
115- ) }
116- { isLoading && ! hasActiveTool && (
117- < div className = "text-sm text-muted-foreground" > Thinking...</ div >
118- ) }
119- </ div >
113+ return null ;
114+ } ) }
115+ </ div >
116+ ) )
117+ ) }
118+ { isLoading && ! hasActiveTool && (
119+ < div className = "text-sm text-muted-foreground" > Thinking...</ div >
120+ ) }
121+ </ ConversationContent >
122+ < ConversationScrollButton />
123+ </ Conversation >
120124
121125 { errorMessage && (
122126 < div className = "border-t bg-destructive/10 px-3 py-2" >
0 commit comments