frontmatter in skills/t/p
This commit is contained in:
@@ -5,6 +5,21 @@ import type { ChatMessage } from './types';
|
||||
import { ToolActivity } from './ToolActivity';
|
||||
import { QuestionActivity } from './QuestionActivity';
|
||||
|
||||
const FRONTMATTER_RE = /^<frontmatter>([\s\S]*?)<\/frontmatter>\s*/;
|
||||
|
||||
const CollapsibleBlock = ({ label, content }: { label: string; content: string }) => (
|
||||
<div className="flex justify-center">
|
||||
<details className="max-w-[85%] rounded-2xl bg-duck-dark/5 border border-duck-dark/10 px-4 py-2 text-sm">
|
||||
<summary className="text-xs text-duck-dark/40 hover:text-duck-dark/60 cursor-pointer select-none">
|
||||
{label}
|
||||
</summary>
|
||||
<div className="mt-1.5 text-xs text-duck-dark/40 whitespace-pre-wrap border-l-2 border-duck-dark/10 pl-2 max-h-48 overflow-y-auto">
|
||||
{content}
|
||||
</div>
|
||||
</details>
|
||||
</div>
|
||||
);
|
||||
|
||||
type MessageBubbleProps = {
|
||||
message: ChatMessage;
|
||||
onAnswer?: (text: string) => void;
|
||||
@@ -12,31 +27,27 @@ type MessageBubbleProps = {
|
||||
|
||||
export const MessageBubble = ({ message, onAnswer }: MessageBubbleProps) => {
|
||||
switch (message.role) {
|
||||
case 'user':
|
||||
case 'user': {
|
||||
const match = message.text.match(FRONTMATTER_RE);
|
||||
const metadata = match ? match[1]!.trim() : null;
|
||||
const text = match ? message.text.slice(match[0]!.length) : message.text;
|
||||
return (
|
||||
<div className="flex justify-end">
|
||||
<div className="max-w-[80%] rounded-2xl rounded-tr-sm bg-duck-yellow/10 border border-duck-yellow/20 px-4 py-2.5 text-sm text-duck-dark">
|
||||
{message.images?.map((img, i) => (
|
||||
<img key={i} src={img.dataUrl} alt={img.filename} className="max-w-full max-h-64 rounded-lg mb-2" />
|
||||
))}
|
||||
<div className="whitespace-pre-wrap">{message.text}</div>
|
||||
<>
|
||||
{metadata && <CollapsibleBlock label="Frontmatter" content={metadata} />}
|
||||
<div className="flex justify-end">
|
||||
<div className="max-w-[80%] rounded-2xl rounded-tr-sm bg-duck-yellow/10 border border-duck-yellow/20 px-4 py-2.5 text-sm text-duck-dark">
|
||||
{message.images?.map((img, i) => (
|
||||
<img key={i} src={img.dataUrl} alt={img.filename} className="max-w-full max-h-64 rounded-lg mb-2" />
|
||||
))}
|
||||
<div className="whitespace-pre-wrap">{text}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
case 'system':
|
||||
return (
|
||||
<div className="flex justify-center">
|
||||
<details className="max-w-[85%] rounded-2xl bg-duck-dark/5 border border-duck-dark/10 px-4 py-2 text-sm">
|
||||
<summary className="text-xs text-duck-dark/40 hover:text-duck-dark/60 cursor-pointer select-none">
|
||||
System prompt
|
||||
</summary>
|
||||
<div className="mt-1.5 text-xs text-duck-dark/40 whitespace-pre-wrap border-l-2 border-duck-dark/10 pl-2 max-h-48 overflow-y-auto">
|
||||
{message.text}
|
||||
</div>
|
||||
</details>
|
||||
</div>
|
||||
);
|
||||
return <CollapsibleBlock label="System prompt" content={message.text} />;
|
||||
|
||||
case 'assistant':
|
||||
if (!message.text) return null;
|
||||
|
||||
Reference in New Issue
Block a user