Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
4 changes: 2 additions & 2 deletions docs/features/prompt-repository/playground.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ The **Playground** in Bifrost is an interactive workspace for building, testing,

## How it Works

The playground is built around three core concepts: **prompts, sessions, and versions**.
The playground is built around four core concepts: **Prompts, Sessions, and Versions**.

### Folders

Expand Down Expand Up @@ -130,7 +130,7 @@ Configure the provider, model, and parameters from the settings panel on the rig

<Step title="Run the prompt">

Click **Run** or press `Cmd + enter` / `Ctrl + enter`.
Click **Run** or press `Cmd + S` / `Ctrl + S`.

Optionally, if you do not want to execute the prompt and only want to add a message to history, use the **+ Add** button.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,18 @@ import MessageRoleSwitcher from "./messageRoleSwitcher";
import { isJson } from "@/lib/utils/validation";
import { CodeEditor } from "@/components/ui/codeEditor";

/**
* Renders the assistant message UI including role switcher, usage tooltip, edit/delete controls, and editable or view-only content.
*
* The component allows inline editing of plain text or JSON content (JSON edits are buffered and committed on blur), toggling role, and removing the message. Clicking outside the component exits edit mode.
*
* @param message - The message model to display and edit; updates are emitted via `onChange` as the message's serialized form.
* @param disabled - When true, disables editing, role changes, and delete action.
* @param isStreaming - When true, shows streaming state (loading indicator) and prevents entering edit mode.
* @param onChange - Called when the message is modified; receives the message's serialized representation.
* @param onRemove - Optional callback invoked when the delete action is triggered.
* @returns The rendered assistant message element.
*/
export function AssistantMessageView({
message,
disabled,
Expand Down
27 changes: 27 additions & 0 deletions ui/components/prompts/components/messagesView/attachmentViews.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,18 @@
import { MessageContent } from "@/lib/message";
import { Mic, FileIcon, XIcon } from "lucide-react";

/**
* Renders a compact badge for a single attachment with an inline remove control.
*
* Displays different visuals based on the attachment type:
* - image_url with a valid URL: a thumbnail and the label "Image"
* - input_audio: a microphone icon and the audio format in uppercase or "Audio"
* - other: a file icon and the filename or "File"
*
* @param attachment - The attachment to display; its `type` determines the badge content.
* @param onRemove - Callback invoked when the badge's remove button is clicked.
* @returns The rendered attachment badge element.
*/
export function AttachmentBadge({ attachment, onRemove }: { attachment: MessageContent; onRemove: () => void }) {
const isImage = attachment.type === "image_url";
const isAudio = attachment.type === "input_audio";
Expand Down Expand Up @@ -34,6 +46,21 @@ export function AttachmentBadge({ attachment, onRemove }: { attachment: MessageC
);
}

/**
* Renders a compact list of attachment previews (images, audio controls, or file rows).
*
* Renders each attachment according to its type:
* - image_url with a URL: an image thumbnail
* - input_audio: an HTML audio control built from base64 data
* - file: a row with a file icon, filename, and optional file type
*
* When `editable` is true and `onRemoveAttachment` is provided, a remove button is shown for each attachment and invokes the callback with the attachment's index when clicked.
*
* @param attachments - The attachments to render.
* @param editable - If true, show per-attachment remove controls.
* @param onRemoveAttachment - Callback invoked with the attachment index when a remove control is clicked.
* @returns A JSX element containing the rendered attachments, or `null` when `attachments` is empty.
*/
export function AttachmentDisplay({
attachments,
editable,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
import { Message } from "@/lib/message";
import { AlertCircle, XIcon } from "lucide-react";

/**
* Render a styled error message block with an optional delete control.
*
* @param message - The message object whose `content` is displayed inside the error block.
* @param disabled - When true, the remove button is not rendered.
* @param onRemove - Callback invoked when the delete button is clicked.
* @returns The React element that displays the error message view.
*/
export default function ErrorMessageView({ message, disabled, onRemove }: { message: Message; disabled?: boolean; onRemove?: () => void }) {
return (
<div className="group hover:border-destructive/30 focus-within:border-destructive/30 rounded-sm border border-transparent px-3 py-2 transition-colors">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,15 @@ const AVAILABLE_ROLES = [
{ value: "tool", label: "Tool" },
] as const;

/**
* Render a dropdown that lets the user switch the current message role.
*
* @param role - The currently selected role value shown in the trigger
* @param disabled - If true, disables interaction with the trigger
* @param onRoleChange - Callback invoked with the newly selected role value
* @param restrictedRoles - Optional list of role values that should be excluded from the menu
* @returns A JSX element rendering the role selection dropdown
*/
export default function MessageRoleSwitcher({
role,
disabled,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ import ToolResultMessageView from "./toolCallResultView";
import ToolCallMessageView from "./toolCallView";
import ErrorMessageView from "./errorMessageView";

/**
* Render and manage the chat messages list, mapping each message to its appropriate view, handling edits, removals, variable recomputation, and automatic scrolling during streaming.
*
* @returns A React element that renders the messages list and provides handlers for message changes, removals, tool submissions, and variable updates.
*/
export function MessagesView() {
const { messages, setMessages: onUpdateMessages, setVariables, isStreaming, supportsVision, handleSubmitToolResult } = usePromptContext();
const messagesEndRef = useRef<HTMLDivElement>(null);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,15 @@ import MessageRoleSwitcher from "./messageRoleSwitcher";
import { RichTextarea } from "@/components/ui/custom/richTextarea";
import { JINJA_VAR_HIGHLIGHT_PATTERNS, JINJA_VAR_REGEX } from "@/lib/message/constant";

/**
* Renders an editable system message block that supports role switching, rich-text editing, JSON editing with buffered changes, Jinja variable highlighting, and optional removal.
*
* @param message - The message model to display and edit.
* @param disabled - When true, disables interactions and makes the view read-only.
* @param onChange - Called with the message's serialized representation when the message is modified (role or content).
* @param onRemove - Optional callback invoked when the message should be removed.
* @returns The rendered system message JSX element.
*/
export function SystemMessageView({
message,
disabled,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,20 @@ import { PencilIcon, XIcon } from "lucide-react";
import { useEffect, useMemo, useRef, useState } from "react";
import MessageRoleSwitcher from "./messageRoleSwitcher";

/**
* Renders an editable view for a tool result message that supports role switching, inline text editing, JSON-aware editing, and removal.
*
* The component presents the message role selector, optional tool call id, edit/delete actions, and a content area that:
* - shows a textarea for freeform editing when in edit mode,
* - shows a JSON-aware code editor (with edits buffered and flushed on blur) when the content is valid JSON,
* - shows a read-only monospaced display when content is plain text,
* - shows a placeholder when content is empty.
*
* @param message - The Message instance to display and edit; updates emitted via `onChange` are serialized from clones of this message.
* @param disabled - When true, disables interactive controls and makes editors read-only.
* @param onChange - Called with the message's serialized form whenever the message is modified (role, content edits, or flushed JSON buffer).
* @param onRemove - Optional callback invoked when the user requests deletion of the message.
*/
export default function ToolResultMessageView({
message,
disabled,
Expand Down
14 changes: 14 additions & 0 deletions ui/components/prompts/components/messagesView/toolCallView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,20 @@ import { Wrench, XIcon } from "lucide-react";
import { useRef, useState } from "react";
import MessageRoleSwitcher from "./messageRoleSwitcher";

/**
* Renders a UI for viewing and editing tool-call entries on a message, including optional argument editing and submitting tool responses.
*
* The component displays each tool call's name, id, and arguments (JSON arguments open in an editable code editor). JSON edits are buffered locally and only committed to `onChange` when the editor loses focus or when the message role changes. The component also exposes controls for switching the message role, deleting the message, and entering/submitting a response for individual tool calls.
*
* @param message - Message instance containing zero or more toolCalls to render; edits are serialized via `onChange`.
* @param disabled - When true, disables interactive controls and makes editors read-only.
* @param onChange - Called with the message's serialized form after committed edits (e.g., buffered JSON arguments flushed or role changed).
* @param onRemove - If provided, called when the delete button is clicked.
* @param onSubmitToolResult - If provided, called with (toolCallId, content) when a user submits a response for a tool call.
* @param respondedToolCallIds - Optional set of toolCall ids that have already received responses; tool calls in this set hide the response UI.
*
* @returns The rendered React element for the tool-call message view.
*/
export default function ToolCallMessageView({
message,
disabled,
Expand Down
10 changes: 10 additions & 0 deletions ui/components/prompts/components/messagesView/userMessageView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,16 @@ import { AttachmentDisplay } from "./attachmentViews";
import { isJson } from "@/lib/utils/validation";
import { CodeEditor } from "@/components/ui/codeEditor";

/**
* Render an interactive user message block that supports viewing and editing content, role switching, file attachments (via picker or drag-and-drop), and special handling for JSON and Jinja-variable content.
*
* @param message - The message model to render and edit; its updates are emitted via `onChange`.
* @param disabled - When true, disables editing and attachment interactions.
* @param supportsVision - When true, enables attaching files (images, audio, documents) and drag-and-drop attachments.
* @param onChange - Called with the message's serialized form whenever the message is modified (content, role, or attachments).
* @param onRemove - Optional callback invoked when the message's delete action is triggered.
* @returns The JSX element that renders the user message view and its interactive controls.
*/
export function UserMessageView({
message,
disabled,
Expand Down
54 changes: 54 additions & 0 deletions ui/components/prompts/fragments/sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,13 @@ import { usePathname } from "next/navigation";
import { DragDropProvider, useDraggable, useDroppable } from "@dnd-kit/react";
import { usePromptContext } from "../context";

/**
* Renders the prompt-manager sidebar including search, folder hierarchy, root prompts, and drag-and-drop reorganization.
*
* The sidebar supports creating, renaming, and deleting folders and prompts (when permitted), selecting prompts, auto-expanding the folder that contains the selected prompt, filtering by search query, and dragging prompts between folders or to the root. Visual drag-over feedback and permission gating for create/update/delete actions are applied.
*
* @returns The sidebar React element containing the search input, folder list, root prompt drop zone, and drag-and-drop provider.
*/
export function PromptSidebar() {
const {
folders,
Expand Down Expand Up @@ -272,6 +279,19 @@ interface RootDropZoneProps {
canDelete: boolean;
}

/**
* Renders the droppable root area that lists and hosts draggable root-level prompts.
*
* @param isDragOver - Whether a draggable item is currently over the root drop zone (applies drag-over styling).
* @param rootPrompts - Array of prompts that belong at the root (no folder).
* @param selectedPromptId - ID of the currently selected prompt, used to mark its item as selected.
* @param onSelectPrompt - Callback invoked with a prompt ID when a prompt is selected.
* @param onEditPrompt - Callback invoked with a prompt when the prompt's edit action is triggered.
* @param onDeletePrompt - Callback invoked with a prompt when the prompt's delete action is triggered.
* @param canUpdate - Whether prompts are movable/editable (enables dragging).
* @param canDelete - Whether prompts may be deleted (controls delete action visibility).
* @returns The JSX element for the root drop zone containing draggable prompt items.
*/
function RootDropZone({
isDragOver,
rootPrompts,
Expand Down Expand Up @@ -320,6 +340,26 @@ interface DroppableFolderProps {
canDelete: boolean;
}

/**
* Renders a droppable folder header with optional action menu and its list of prompts.
*
* @param folder - Folder metadata (id, name, etc.)
* @param prompts - Prompts that belong to this folder
* @param isExpanded - Whether the folder is expanded to show its prompts
* @param isDragOver - Whether a draggable item is currently over this folder (affects visual state)
* @param selectedPromptId - ID of the currently selected prompt, used to highlight an item
* @param onToggle - Callback invoked to toggle the folder's expanded state
* @param onSelectPrompt - Callback invoked with a prompt ID when a prompt is selected
* @param onEdit - Callback invoked to start editing the folder
* @param onDelete - Callback invoked to start deleting the folder
* @param onCreatePrompt - Callback invoked to create a new prompt inside this folder
* @param onEditPrompt - Callback invoked with a prompt to start editing that prompt
* @param onDeletePrompt - Callback invoked with a prompt to start deleting that prompt
* @param canCreate - Whether the current user may create prompts in this folder
* @param canUpdate - Whether the current user may move/rename prompts or edit the folder
* @param canDelete - Whether the current user may delete prompts or the folder
* @returns A JSX element containing the folder row and, when expanded, its nested prompt items
*/
function DroppableFolder({
folder,
prompts,
Expand Down Expand Up @@ -455,6 +495,20 @@ interface DraggablePromptItemProps {
canDelete: boolean;
}

/**
* Renders a draggable prompt list item that shows the prompt name, selection/drag states, and an actions menu when permitted.
*
* Displays a file icon and truncated prompt name, applies visual styles for selection and dragging, prevents selection while dragging, and exposes rename/delete actions via a dropdown when `canUpdate` or `canDelete` are true.
*
* @param prompt - The prompt object to render.
* @param isSelected - Whether this prompt is currently selected; used for styling.
* @param onSelect - Callback invoked when the item is clicked (not invoked if the item is being dragged).
* @param onEdit - Callback invoked to start editing/renaming the prompt.
* @param onDelete - Callback invoked to delete the prompt.
* @param canUpdate - When true, enables dragging and shows the rename action.
* @param canDelete - When true, shows the delete action.
* @returns The rendered prompt item JSX element.
*/
function DraggablePromptItem({ prompt, isSelected, onSelect, onEdit, onDelete, canUpdate, canDelete }: DraggablePromptItemProps) {
const { ref, isDragging } = useDraggable({ id: `prompt-${prompt.id}`, disabled: !canUpdate });
const showActions = canUpdate || canDelete;
Expand Down
Loading