Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -494,7 +494,7 @@ export const PromptSchemaControl = memo(function PromptSchemaControl({
}

return (
<div className={cn("flex flex-col gap-3", className)}>
<div className={cn("flex flex-col gap-2", className)}>
{/* Messages list */}
<ChatMessageList
messages={messages}
Expand Down Expand Up @@ -541,6 +541,8 @@ export const PromptSchemaControl = memo(function PromptSchemaControl({
showToolbar={false}
enableTokens={false}
id={`tool-editor-${index}`}
// Drop the wrapper's min-h-[70px] so it hugs collapsed cards.
className="!min-h-0"
>
{toolControl}
</EditorProvider>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
import {memo, useCallback, useEffect, useMemo, useRef, useState} from "react"

import {safeStringify} from "@agenta/shared/utils"
import {CollapseToggleButton, getCollapseStyle} from "@agenta/ui/components/presentational"
import {CollapseToggleButton} from "@agenta/ui/components/presentational"
import {useDrillInUI} from "@agenta/ui/drill-in"
import {getProviderIcon} from "@agenta/ui/select-llm-provider"
import {CopySimple, MinusCircle} from "@phosphor-icons/react"
Expand Down Expand Up @@ -256,7 +256,6 @@ interface ToolHeaderProps {
builtinToolLabel?: string
builtinIcon?: React.ReactNode
gatewayHeader?: React.ReactNode
containerRef?: React.RefObject<HTMLElement | null>
}

function GatewayToolHeaderIdentity({
Expand Down Expand Up @@ -344,11 +343,10 @@ const ToolHeader = memo(function ToolHeader({
builtinToolLabel,
builtinIcon,
gatewayHeader,
containerRef,
}: ToolHeaderProps) {
Comment thread
jp-agenta marked this conversation as resolved.
return (
<div className="w-full flex items-start justify-between py-1">
<div className="grow min-w-0">
<div className="grow min-w-0 pl-2">
{gatewayHeader ? (
gatewayHeader
) : isBuiltinTool ? (
Expand Down Expand Up @@ -391,31 +389,33 @@ const ToolHeader = memo(function ToolHeader({
)}
</div>

<div className="flex items-center gap-1 invisible group-hover/tool:visible shrink-0">
{!isReadOnly && onDuplicate && (
<Tooltip title="Duplicate">
<Button
icon={<CopySimple size={14} />}
type="text"
onClick={onDuplicate}
size="small"
/>
</Tooltip>
)}
{!isReadOnly && onDelete && (
<Tooltip title="Remove">
<Button
icon={<MinusCircle size={14} />}
type="text"
onClick={onDelete}
size="small"
/>
</Tooltip>
)}
<div className="flex items-center gap-1 shrink-0">
<div className="flex items-center gap-1 invisible group-hover/tool:visible">
{!isReadOnly && onDuplicate && (
Comment on lines +392 to +394
<Tooltip title="Duplicate">
<Button
icon={<CopySimple size={14} />}
type="text"
onClick={onDuplicate}
size="small"
/>
</Tooltip>
)}
{!isReadOnly && onDelete && (
<Tooltip title="Remove">
<Button
icon={<MinusCircle size={14} />}
type="text"
onClick={onDelete}
size="small"
/>
</Tooltip>
)}
</div>
Comment thread
coderabbitai[bot] marked this conversation as resolved.
<CollapseToggleButton
collapsed={minimized}
onToggle={onToggleMinimize}
contentRef={containerRef}
className="!transition-opacity !duration-0 !delay-200 group-hover/tool:!delay-0 opacity-50 group-hover/tool:opacity-100"
/>
Comment on lines 415 to 419
</div>
</div>
Expand Down Expand Up @@ -467,16 +467,8 @@ export const ToolItemControl = memo(function ToolItemControl({
const effectiveRenderProviderIcon = renderProviderIcon ?? defaultRenderProviderIcon

const isReadOnly = disabled
const [minimized, setMinimized] = useState(() => {
if (value && typeof value === "object" && !Array.isArray(value)) {
const obj = value as Record<string, unknown>
if (obj.agenta_metadata && typeof obj.agenta_metadata === "object") {
const meta = obj.agenta_metadata as Record<string, unknown>
return meta.source === "gateway" || meta.source === "builtin"
}
}
return false
})
// Default collapsed: tool cards open to just their title + description.
const [minimized, setMinimized] = useState(true)
const containerRef = useRef<HTMLDivElement>(null)

// Strip agenta_metadata if present (re-attach on change)
Expand Down Expand Up @@ -652,7 +644,6 @@ export const ToolItemControl = memo(function ToolItemControl({
builtinToolLabel={toolLabel}
builtinIcon={providerIcon}
gatewayHeader={gatewayHeader}
containerRef={containerRef}
/>
{!minimized && (
<textarea
Expand All @@ -666,10 +657,34 @@ export const ToolItemControl = memo(function ToolItemControl({
)
}

const toolFunction = (toolObj as Record<string, unknown>)?.function as
| Record<string, string>
| undefined
const header = (
<ToolHeader
name={toolFunction ? (toolFunction.name ?? "") : ""}
desc={toolFunction ? (toolFunction.description ?? "") : ""}
isReadOnly={isReadOnly}
minimized={minimized}
onToggleMinimize={() => setMinimized((v) => !v)}
onDelete={onDelete}
onDuplicate={onDuplicate}
isBuiltinTool={isBuiltinTool}
builtinProviderLabel={providerLabel}
builtinToolLabel={toolLabel}
builtinIcon={providerIcon}
gatewayHeader={gatewayHeader}
containerRef={containerRef}
/>
Comment thread
Copilot marked this conversation as resolved.
)

// Collapsed = header only. Keep a SINGLE SharedEditor in both states (same
// border, padding and chrome — no fork, no pixel shift) and just hide the
// editor body when minimized. Header drives the height naturally, so it
// works for every header variant (title, title+desc, builtin icon row).
return (
<div
ref={containerRef}
style={getCollapseStyle(minimized)}
className={clsx("group/tool flex flex-col", "w-full max-w-full", className)}
>
<SharedEditor
Expand All @@ -689,43 +704,18 @@ export const ToolItemControl = memo(function ToolItemControl({
disableDebounce
syncWithInitialValueChanges
editorType="border"
className={clsx("group/tool")}
className={clsx(
"group/tool",
// Symmetric padding (codeOnly forces pt-0); zero the editor body's
// own bottom margin/padding so open & closed end the same 11px below.
"!pt-[11px] !pb-[11px] [&_.agenta-editor-wrapper]:!mb-0 [&_.editor-code]:!pb-0",
// Indent the JSON body to align with the pl-2 header (cancel the
// codeOnly -ml-[12px] pull, then add the 8px message-matched indent).
"[&_.agenta-editor-wrapper]:!pl-[20px]",
minimized && "[&_.agenta-editor-wrapper]:!hidden",
)}
state={isReadOnly ? "readOnly" : "filled"}
header={
<ToolHeader
name={
(toolObj as Record<string, unknown>)?.function
? ((
(toolObj as Record<string, unknown>).function as Record<
string,
string
>
)?.name ?? "")
: ""
}
desc={
(toolObj as Record<string, unknown>)?.function
? ((
(toolObj as Record<string, unknown>).function as Record<
string,
string
>
)?.description ?? "")
: ""
}
isReadOnly={isReadOnly}
minimized={minimized}
onToggleMinimize={() => setMinimized((v) => !v)}
onDelete={onDelete}
onDuplicate={onDuplicate}
isBuiltinTool={isBuiltinTool}
builtinProviderLabel={providerLabel}
builtinToolLabel={toolLabel}
builtinIcon={providerIcon}
gatewayHeader={gatewayHeader}
containerRef={containerRef}
/>
}
header={header}
/>
</div>
)
Expand Down
100 changes: 54 additions & 46 deletions web/packages/agenta-ui/src/ChatMessage/components/ChatMessageList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {Copy, MinusCircle, Plus} from "@phosphor-icons/react"
import {Button, Tooltip} from "antd"
import {useAtom} from "jotai"

import {CollapseToggleButton, getCollapseStyle} from "../../components/presentational/buttons"
import {CollapseToggleButton} from "../../components/presentational/buttons"
import {ViewModeDropdown} from "../../drill-in/core/ViewModeDropdown"
import {messageViewModeAtom} from "../../drill-in/state/messageViewModeAtom"
import {getViewOptions, toMessageViewMode, type ViewMode} from "../../drill-in/utils/getViewOptions"
Expand Down Expand Up @@ -163,9 +163,16 @@ const ChatMessageItem: React.FC<{

return (
<div
className={cn(flexLayouts.column)}
className={cn(
flexLayouts.column,
// Collapsed = role row + one line of content, clipped vertically so
// formatting (indentation, markdown, JSON) is preserved instead of
// collapsed to a single run-on line. Height is a clean line-height
// multiple so it never bleeds a half-line.
isMinimized &&
"[&_.agenta-editor-wrapper]:!max-h-[1lh] [&_.agenta-editor-wrapper]:overflow-hidden",
)}
Comment thread
jp-agenta marked this conversation as resolved.
Outdated
Comment thread
jp-agenta marked this conversation as resolved.
Outdated
ref={containerRef}
style={getCollapseStyle(isMinimized, 72)}
>
<ChatMessageEditor
id={editorId}
Expand Down Expand Up @@ -194,54 +201,55 @@ const ChatMessageItem: React.FC<{
) : undefined
}
Comment thread
jp-agenta marked this conversation as resolved.
headerRight={
<div
className={cn(
flexLayouts.rowCenter,
gapClasses.xs,
"invisible group-hover/item:visible",
)}
>
<ViewModeDropdown<ChatViewMode>
value={chatViewMode}
options={viewOptions}
onChange={setViewMode}
/>
{allowFileUpload && !disabled && (
<AttachmentButton
onAddImage={(url) => onAddImage(index, url)}
onAddFile={(data, name, format) =>
onAddFile(index, data, name, format)
}
disabled={disabled}
<div className={cn(flexLayouts.rowCenter, gapClasses.xs)}>
<div
className={cn(
flexLayouts.rowCenter,
gapClasses.xs,
"invisible group-hover/item:visible",
)}
>
Comment on lines +198 to +204
<ViewModeDropdown<ChatViewMode>
value={chatViewMode}
options={viewOptions}
onChange={setViewMode}
/>
)}
{showCopyButton && (
<Tooltip title="Copy">
<Button
type="text"
size="small"
icon={<Copy size={14} />}
onClick={() => {
navigator.clipboard.writeText(textContent)
}}
/>
</Tooltip>
)}
{(showRemoveButton ?? showControls) && !disabled && (
<Tooltip title="Remove">
<Button
type="text"
size="small"
icon={<MinusCircle size={14} />}
onClick={() => onRemove(index)}
{allowFileUpload && !disabled && (
<AttachmentButton
onAddImage={(url) => onAddImage(index, url)}
onAddFile={(data, name, format) =>
onAddFile(index, data, name, format)
}
disabled={disabled}
/>
</Tooltip>
)}
)}
{showCopyButton && (
<Tooltip title="Copy">
<Button
type="text"
size="small"
icon={<Copy size={14} />}
onClick={() => {
navigator.clipboard.writeText(textContent)
}}
/>
</Tooltip>
)}
{(showRemoveButton ?? showControls) && !disabled && (
<Tooltip title="Remove">
<Button
type="text"
size="small"
icon={<MinusCircle size={14} />}
onClick={() => onRemove(index)}
/>
</Tooltip>
)}
</div>
<CollapseToggleButton
collapsed={isMinimized}
onToggle={() => onToggleMinimize(index)}
contentRef={containerRef}
collapsedMaxHeight={48}
className="!transition-opacity !duration-0 !delay-200 group-hover/item:!delay-0 opacity-50 group-hover/item:opacity-100"
/>
Comment on lines 242 to 246
</div>
}
Expand Down
Loading