Compare commits

...

1 Commits

Author SHA1 Message Date
Zeno Kapitein 38226b9413 Simplify AI Chat
- Add new `note` field
- Always clear `messages` when posting a message
- Remove follow-up questions
2025-09-16 16:29:10 +02:00
3 changed files with 62 additions and 51 deletions
+5
View File
@@ -0,0 +1,5 @@
---
"gitbook": patch
---
Simplify AI Chat
@@ -21,6 +21,7 @@ export type AIChatMessage = {
role: AIMessageRole; role: AIMessageRole;
content: React.ReactNode; content: React.ReactNode;
query?: string; query?: string;
note?: string;
}; };
export type AIChatPendingTool = { export type AIChatPendingTool = {
@@ -391,11 +392,11 @@ export function AIChatProvider(props: {
return { return {
...state, ...state,
messages: [ messages: [
...state.messages,
{ {
role: AIMessageRole.User, role: AIMessageRole.User,
content: input.message, content: input.message,
query: input.message, query: input.message,
note: state.messages.length > 0 ? 'Starting a new chat' : undefined,
}, },
], ],
query: input.message, query: input.message,
@@ -6,14 +6,13 @@ import type React from 'react';
import type { AIChatController, AIChatState } from '../AI'; import type { AIChatController, AIChatState } from '../AI';
import { AIChatToolConfirmations } from './AIChatToolConfirmations'; import { AIChatToolConfirmations } from './AIChatToolConfirmations';
import { AIResponseFeedback } from './AIResponseFeedback'; import { AIResponseFeedback } from './AIResponseFeedback';
import { AIChatFollowupSuggestions } from './AiChatFollowupSuggestions';
export function AIChatMessages(props: { export function AIChatMessages(props: {
chat: AIChatState; chat: AIChatState;
chatController: AIChatController; chatController: AIChatController;
lastUserMessageRef?: React.RefObject<HTMLDivElement>; lastUserMessageRef?: React.RefObject<HTMLDivElement>;
}) { }) {
const { chat, chatController, lastUserMessageRef } = props; const { chat, lastUserMessageRef } = props;
return ( return (
<> <>
@@ -24,57 +23,63 @@ export function AIChatMessages(props: {
index === chat.messages.map((m) => m.role).lastIndexOf(AIMessageRole.User); index === chat.messages.map((m) => m.role).lastIndexOf(AIMessageRole.User);
return ( return (
<div <>
ref={isLastUserMessage ? lastUserMessageRef : undefined} {message.note ? (
data-testid="ai-chat-message" <div
className={tcls( key={`${index}-note`}
message.content ? 'animate-fade-in-slow' : '', className="self-center text-tint-subtle text-xs"
'shrink-0', >
'last:min-h-[calc(100%-5rem)]', {message.note}
'scroll-mt-36',
'lg:scroll-mt-0',
'flex flex-col gap-6',
'break-words',
'group/message',
message.role === AIMessageRole.User
? 'max-w-[80%] self-end circular-corners:rounded-2xl rounded-corners:rounded-md bg-tint px-4 py-2'
: 'text-tint-strong'
)}
style={{
animationDelay: `${Math.min(index * 0.05, 0.5)}s`,
}}
key={index}
>
{message.content ? message.content : null}
{isLastMessage && chat.loading ? (
<div className="flex w-full animate-fade-in-slow flex-col gap-2">
{!message.content ? <HoldMessage /> : null}
<LoadingSkeleton />
</div> </div>
) : null} ) : null}
<div
ref={isLastUserMessage ? lastUserMessageRef : undefined}
data-testid="ai-chat-message"
className={tcls(
message.content ? 'animate-fade-in-slow' : '',
'shrink-0',
'last:min-h-[calc(100%-5rem)]',
'scroll-mt-36',
'lg:scroll-mt-0',
'flex flex-col gap-6',
'break-words',
'group/message',
message.role === AIMessageRole.User
? 'max-w-[80%] self-end circular-corners:rounded-2xl rounded-corners:rounded-md bg-tint px-4 py-2'
: 'text-tint-strong'
)}
style={{
animationDelay: `${Math.min(index * 0.05, 0.5)}s`,
}}
key={index}
>
{message.content ? message.content : null}
{isLastMessage ? ( {isLastMessage && chat.loading ? (
<> <div className="flex w-full animate-fade-in-slow flex-col gap-2">
{!chat.loading && {!message.content ? <HoldMessage /> : null}
!chat.error && <LoadingSkeleton />
chat.query && </div>
chat.responseId && ) : null}
chat.pendingTools.length === 0 ? (
<AIResponseFeedback {isLastMessage ? (
responseId={chat.responseId} <>
query={chat.query} {!chat.loading &&
className="-ml-1 -mt-4" !chat.error &&
/> chat.query &&
) : null} chat.responseId &&
<AIChatToolConfirmations chat={chat} /> chat.pendingTools.length === 0 ? (
<AIChatFollowupSuggestions <AIResponseFeedback
chat={chat} responseId={chat.responseId}
chatController={chatController} query={chat.query}
/> className="-ml-1 -mt-4"
</> />
) : null} ) : null}
</div> <AIChatToolConfirmations chat={chat} />
</>
) : null}
</div>
</>
); );
})} })}
</> </>