mirror of
https://github.com/harivansh-afk/sandbox-agent.git
synced 2026-04-15 07:04:48 +00:00
chore(release): update version to 0.2.1
This commit is contained in:
parent
a0955ba752
commit
ee9ad25069
23 changed files with 76 additions and 82 deletions
|
|
@ -1,6 +1,5 @@
|
|||
import { useState } from "react";
|
||||
import { getAvatarLabel, getMessageClass } from "./messageUtils";
|
||||
import renderContentPart from "./renderContentPart";
|
||||
import type { TimelineEntry } from "./types";
|
||||
import { AlertTriangle, Settings, ChevronRight, ChevronDown } from "lucide-react";
|
||||
|
||||
|
|
@ -34,17 +33,17 @@ const CollapsibleMessage = ({
|
|||
const ChatMessages = ({
|
||||
entries,
|
||||
sessionError,
|
||||
eventError,
|
||||
messagesEndRef
|
||||
}: {
|
||||
entries: TimelineEntry[];
|
||||
sessionError: string | null;
|
||||
eventError: string | null;
|
||||
messagesEndRef: React.RefObject<HTMLDivElement>;
|
||||
}) => {
|
||||
return (
|
||||
<div className="messages">
|
||||
{entries.map((entry) => {
|
||||
const messageClass = getMessageClass(entry);
|
||||
|
||||
if (entry.kind === "meta") {
|
||||
const isError = entry.meta?.severity === "error";
|
||||
const title = entry.meta?.title ?? "Status";
|
||||
|
|
@ -63,7 +62,6 @@ const ChatMessages = ({
|
|||
);
|
||||
}
|
||||
|
||||
// Other status messages - collapsible
|
||||
return (
|
||||
<CollapsibleMessage
|
||||
key={entry.id}
|
||||
|
|
@ -77,74 +75,71 @@ const ChatMessages = ({
|
|||
);
|
||||
}
|
||||
|
||||
const item = entry.item;
|
||||
if (!item) return null;
|
||||
const hasParts = (item.content ?? []).length > 0;
|
||||
const isInProgress = item.status === "in_progress";
|
||||
const isFailed = item.status === "failed";
|
||||
const messageClass = getMessageClass(item);
|
||||
const statusLabel = item.status !== "completed" ? item.status.replace("_", " ") : "";
|
||||
const kindLabel = item.kind.replace("_", " ");
|
||||
const isTool = messageClass === "tool";
|
||||
if (entry.kind === "reasoning") {
|
||||
return (
|
||||
<div key={entry.id} className="message assistant">
|
||||
<div className="avatar">{getAvatarLabel("assistant")}</div>
|
||||
<div className="message-content">
|
||||
<div className="message-meta">
|
||||
<span>reasoning - {entry.reasoning?.visibility ?? "public"}</span>
|
||||
</div>
|
||||
<div className="part-body muted">{entry.reasoning?.text ?? ""}</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (entry.kind === "tool") {
|
||||
const isComplete = entry.toolStatus === "completed" || entry.toolStatus === "failed";
|
||||
const isFailed = entry.toolStatus === "failed";
|
||||
const statusLabel = entry.toolStatus && entry.toolStatus !== "completed"
|
||||
? entry.toolStatus.replace("_", " ")
|
||||
: "";
|
||||
|
||||
// Tool results - collapsible
|
||||
if (isTool) {
|
||||
return (
|
||||
<CollapsibleMessage
|
||||
key={entry.id}
|
||||
id={entry.id}
|
||||
icon={<span className="tool-icon">T</span>}
|
||||
label={`${kindLabel}${statusLabel ? ` (${statusLabel})` : ""}`}
|
||||
className="tool"
|
||||
label={`tool call - ${entry.toolName ?? "tool"}${statusLabel ? ` (${statusLabel})` : ""}`}
|
||||
className={`tool${isFailed ? " error" : ""}`}
|
||||
>
|
||||
{hasParts ? (
|
||||
(item.content ?? []).map(renderContentPart)
|
||||
) : entry.deltaText ? (
|
||||
<span>{entry.deltaText}</span>
|
||||
) : (
|
||||
<span className="muted">No content.</span>
|
||||
{entry.toolInput && <pre className="code-block">{entry.toolInput}</pre>}
|
||||
{isComplete && entry.toolOutput && (
|
||||
<div className="part">
|
||||
<div className="part-title">result</div>
|
||||
<pre className="code-block">{entry.toolOutput}</pre>
|
||||
</div>
|
||||
)}
|
||||
{!isComplete && !entry.toolInput && (
|
||||
<span className="thinking-indicator">
|
||||
<span className="thinking-dot" />
|
||||
<span className="thinking-dot" />
|
||||
<span className="thinking-dot" />
|
||||
</span>
|
||||
)}
|
||||
</CollapsibleMessage>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div key={entry.id} className={`message ${messageClass} ${isFailed ? "error no-avatar" : ""}`}>
|
||||
{!isFailed && <div className="avatar">{getAvatarLabel(messageClass)}</div>}
|
||||
<div key={entry.id} className={`message ${messageClass}`}>
|
||||
<div className="avatar">{getAvatarLabel(messageClass)}</div>
|
||||
<div className="message-content">
|
||||
{(item.kind !== "message" || item.status !== "completed") && (
|
||||
<div className="message-meta">
|
||||
{isFailed && <AlertTriangle size={14} className="error-icon" />}
|
||||
<span>{kindLabel}</span>
|
||||
{statusLabel && (
|
||||
<span className={`pill ${item.status === "failed" ? "danger" : "accent"}`}>
|
||||
{statusLabel}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
{hasParts ? (
|
||||
(item.content ?? []).map(renderContentPart)
|
||||
) : entry.deltaText ? (
|
||||
<span>
|
||||
{entry.deltaText}
|
||||
{isInProgress && <span className="cursor" />}
|
||||
</span>
|
||||
) : isInProgress ? (
|
||||
{entry.text ? (
|
||||
<div className="part-body">{entry.text}</div>
|
||||
) : (
|
||||
<span className="thinking-indicator">
|
||||
<span className="thinking-dot" />
|
||||
<span className="thinking-dot" />
|
||||
<span className="thinking-dot" />
|
||||
</span>
|
||||
) : (
|
||||
<span className="muted">No content yet.</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
{sessionError && <div className="message-error">{sessionError}</div>}
|
||||
{eventError && <div className="message-error">{eventError}</div>}
|
||||
<div ref={messagesEndRef} />
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,13 +1,12 @@
|
|||
import type { UniversalItem } from "sandbox-agent";
|
||||
import type { TimelineEntry } from "./types";
|
||||
import { Settings, AlertTriangle, User } from "lucide-react";
|
||||
import type { ReactNode } from "react";
|
||||
|
||||
export const getMessageClass = (item: UniversalItem) => {
|
||||
if (item.kind === "tool_call" || item.kind === "tool_result") return "tool";
|
||||
if (item.kind === "system" || item.kind === "status") return "system";
|
||||
if (item.role === "user") return "user";
|
||||
if (item.role === "tool") return "tool";
|
||||
if (item.role === "system") return "system";
|
||||
export const getMessageClass = (entry: TimelineEntry) => {
|
||||
if (entry.kind === "tool") return "tool";
|
||||
if (entry.kind === "meta") return entry.meta?.severity === "error" ? "error" : "system";
|
||||
if (entry.kind === "reasoning") return "assistant";
|
||||
if (entry.role === "user") return "user";
|
||||
return "assistant";
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue