2025-12-20 00:23:15 +00:00
import { Output , streamText , tool , type UIMessageStreamWriter } from "ai" ;
2026-03-20 09:37:02 +00:00
import type { Session } from "next-auth" ;
2025-09-21 11:02:31 -07:00
import { z } from "zod" ;
import { getDocumentById , saveSuggestions } from "@/lib/db/queries" ;
import type { Suggestion } from "@/lib/db/schema" ;
import type { ChatMessage } from "@/lib/types" ;
import { generateUUID } from "@/lib/utils" ;
2026-03-20 09:37:02 +00:00
import { getLanguageModel } from "../providers" ;
2025-01-23 01:19:48 +05:30
2025-09-21 11:02:31 -07:00
type RequestSuggestionsProps = {
2026-03-20 09:37:02 +00:00
session : Session ;
2025-07-03 02:26:34 -07:00
dataStream : UIMessageStreamWriter < ChatMessage > ;
2026-03-20 09:37:02 +00:00
modelId : string ;
2025-09-21 11:02:31 -07:00
} ;
2025-01-23 01:19:48 +05:30
export const requestSuggestions = ( {
session ,
dataStream ,
2026-03-20 09:37:02 +00:00
modelId ,
2025-01-23 01:19:48 +05:30
} : RequestSuggestionsProps ) = >
tool ( {
2025-12-20 00:23:15 +00:00
description :
"Request writing suggestions for an existing document artifact. Only use this when the user explicitly asks to improve or get suggestions for a document they have already created. Never use for general questions." ,
2025-07-03 02:26:34 -07:00
inputSchema : z.object ( {
2025-01-23 01:19:48 +05:30
documentId : z
. string ( )
2025-12-20 00:23:15 +00:00
. describe (
"The UUID of an existing document artifact that was previously created with createDocument"
) ,
2025-01-23 01:19:48 +05:30
} ) ,
execute : async ( { documentId } ) = > {
const document = await getDocumentById ( { id : documentId } ) ;
if ( ! document || ! document . content ) {
return {
2025-09-21 11:02:31 -07:00
error : "Document not found" ,
2025-01-23 01:19:48 +05:30
} ;
}
2026-03-20 09:37:02 +00:00
if ( document . userId !== session . user ? . id ) {
return { error : "Forbidden" } ;
}
2025-09-21 11:02:31 -07:00
const suggestions : Omit <
Suggestion ,
"userId" | "createdAt" | "documentCreatedAt"
> [ ] = [ ] ;
2025-01-23 01:19:48 +05:30
2025-12-20 00:23:15 +00:00
const { partialOutputStream } = streamText ( {
2026-03-20 09:37:02 +00:00
model : getLanguageModel ( modelId ) ,
2025-01-23 01:19:48 +05:30
system :
2026-03-20 09:37:02 +00:00
"You are a writing assistant. Given a piece of writing, offer up to 5 suggestions to improve it. Each suggestion must contain full sentences, not just individual words. Describe what changed and why." ,
2025-01-23 01:19:48 +05:30
prompt : document.content ,
2025-12-20 00:23:15 +00:00
output : Output.array ( {
element : z.object ( {
originalSentence : z.string ( ) . describe ( "The original sentence" ) ,
suggestedSentence : z.string ( ) . describe ( "The suggested sentence" ) ,
description : z
. string ( )
. describe ( "The description of the suggestion" ) ,
} ) ,
2025-01-23 01:19:48 +05:30
} ) ,
} ) ;
2025-12-20 00:23:15 +00:00
let processedCount = 0 ;
for await ( const partialOutput of partialOutputStream ) {
if ( ! partialOutput ) {
continue ;
}
2025-01-23 01:19:48 +05:30
2025-12-20 00:23:15 +00:00
for ( let i = processedCount ; i < partialOutput . length ; i ++ ) {
const element = partialOutput [ i ] ;
if (
! element ? . originalSentence ||
! element ? . suggestedSentence ||
! element ? . description
) {
continue ;
}
const suggestion = {
originalText : element.originalSentence ,
suggestedText : element.suggestedSentence ,
description : element.description ,
id : generateUUID ( ) ,
documentId ,
isResolved : false ,
} ;
dataStream . write ( {
type : "data-suggestion" ,
data : suggestion as Suggestion ,
transient : true ,
} ) ;
2025-01-23 01:19:48 +05:30
2025-12-20 00:23:15 +00:00
suggestions . push ( suggestion ) ;
processedCount ++ ;
}
2025-01-23 01:19:48 +05:30
}
if ( session . user ? . id ) {
const userId = session . user . id ;
await saveSuggestions ( {
suggestions : suggestions.map ( ( suggestion ) = > ( {
. . . suggestion ,
userId ,
createdAt : new Date ( ) ,
documentCreatedAt : document.createdAt ,
} ) ) ,
} ) ;
}
return {
id : documentId ,
title : document.title ,
kind : document.kind ,
2025-09-21 11:02:31 -07:00
message : "Suggestions have been added to the document" ,
2025-01-23 01:19:48 +05:30
} ;
} ,
} ) ;