Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 90 additions & 0 deletions frontend/src/components/SystemPromptIndicator.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import { useState, useCallback } from "react";
import { Bot, Copy, Check } from "lucide-react";
import {
Dialog,
DialogContent,
DialogDescription,
DialogHeader,
DialogTitle,
DialogTrigger
} from "@/components/ui/dialog";
import { Button } from "@/components/ui/button";
import { cn } from "@/utils/utils";

interface SystemPromptIndicatorProps {
systemPrompt?: string;
className?: string;
}

export function SystemPromptIndicator({ systemPrompt, className }: SystemPromptIndicatorProps) {
const [isCopied, setIsCopied] = useState(false);
const [isOpen, setIsOpen] = useState(false);

const handleCopy = useCallback(async () => {
if (!systemPrompt) return;

try {
await navigator.clipboard.writeText(systemPrompt);
setIsCopied(true);
setTimeout(() => setIsCopied(false), 2000);
} catch (error) {
console.error("Failed to copy system prompt:", error);
}
Comment thread
AnthonyRonning marked this conversation as resolved.
}, [systemPrompt]);

// Don't render if there's no system prompt
if (!systemPrompt?.trim()) {
return null;
}

return (
<Dialog open={isOpen} onOpenChange={setIsOpen}>
<DialogTrigger asChild>
<button
className={cn(
"inline-flex items-center gap-1 px-2 py-1 rounded-md",
"text-xs text-muted-foreground/70 hover:text-muted-foreground",
"bg-muted/30 hover:bg-muted/50 transition-colors",
"border border-muted-foreground/10",
className
)}
title="View system prompt"
>
<Bot className="h-3 w-3" />
<span>System</span>
</button>
</DialogTrigger>
<DialogContent className="max-w-2xl max-h-[80vh] overflow-y-auto">
<DialogHeader>
<DialogTitle className="flex items-center gap-2">
<Bot className="h-4 w-4" />
System Prompt
</DialogTitle>
<DialogDescription>
The system prompt that was used for this conversation
</DialogDescription>
</DialogHeader>
<div className="space-y-4">
<div className="bg-muted/50 rounded-lg p-4 font-mono text-sm whitespace-pre-wrap">
{systemPrompt}
</div>
<div className="flex justify-end">
<Button onClick={handleCopy} variant="outline" size="sm" className="gap-2">
{isCopied ? (
<>
<Check className="h-4 w-4" />
Copied!
</>
) : (
<>
<Copy className="h-4 w-4" />
Copy System Prompt
</>
)}
</Button>
</div>
</div>
</DialogContent>
</Dialog>
);
}
12 changes: 9 additions & 3 deletions frontend/src/routes/_auth.chat.$chatId.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { useQuery, useQueryClient } from "@tanstack/react-query";
import { Button } from "@/components/ui/button";
import { BillingStatus } from "@/billing/billingApi";
import { useNavigate } from "@tanstack/react-router";
import { SystemPromptIndicator } from "@/components/SystemPromptIndicator";

export const Route = createFileRoute("/_auth/chat/$chatId")({
component: ChatComponent
Expand Down Expand Up @@ -579,9 +580,14 @@ END OF INSTRUCTIONS`;
className="flex-1 min-h-0 overflow-y-auto flex flex-col relative"
>
<div className="mt-4 md:mt-8 w-full h-10 flex items-center justify-center">
<h2 className="text-lg font-semibold self-center truncate max-w-[20rem] mx-[6rem] py-2">
{localChat.title}
</h2>
<div className="flex items-center gap-3 mx-[6rem]">
<h2 className="text-lg font-semibold truncate max-w-[20rem] py-2">
{localChat.title}
</h2>
<SystemPromptIndicator
systemPrompt={localChat.messages.find((msg) => msg.role === "system")?.content}
/>
</div>
</div>
<div className="flex flex-col w-full max-w-[45rem] mx-auto gap-4 px-2 pt-4">
{/* Show user and assistant messages, excluding system messages */}
Expand Down