From 95c747923c44e99212f4dad32f4dfe86900f26e6 Mon Sep 17 00:00:00 2001 From: VooDisss Date: Mon, 16 Feb 2026 01:11:53 +0200 Subject: [PATCH 1/5] fix(ui): improve picker actions, directory navigation, @ handling, and message display --- packages/ui/src/components/message-item.tsx | 41 ++++++++++----- packages/ui/src/components/message-part.tsx | 20 ++++++-- .../prompt-input/usePromptKeyDown.ts | 30 +++++++++-- .../prompt-input/usePromptPicker.ts | 26 +++++++++- packages/ui/src/components/unified-picker.tsx | 49 +++++++++++++++++- packages/ui/src/lib/prompt-placeholders.ts | 50 +++++++++++++++++-- packages/ui/src/stores/session-actions.ts | 5 +- 7 files changed, 193 insertions(+), 28 deletions(-) diff --git a/packages/ui/src/components/message-item.tsx b/packages/ui/src/components/message-item.tsx index 2f8eb26e..503464b4 100644 --- a/packages/ui/src/components/message-item.tsx +++ b/packages/ui/src/components/message-item.tsx @@ -1,5 +1,5 @@ import { For, Show, createSignal } from "solid-js" -import { Copy, Split, Trash2, Undo } from "lucide-solid" +import { Copy, ExternalLink, Split, Trash2, Undo } from "lucide-solid" import type { MessageInfo, ClientPart } from "../types/message" import { partHasRenderableText } from "../types/message" import type { MessageRecord } from "../stores/message-v2/types" @@ -8,6 +8,7 @@ import { copyToClipboard } from "../lib/clipboard" import { useI18n } from "../lib/i18n" import { showAlertDialog } from "../stores/alerts" import { deleteMessagePart } from "../stores/session-actions" +import { isTauriHost } from "../lib/runtime-env" interface MessageItemProps { record: MessageRecord @@ -45,6 +46,15 @@ export default function MessageItem(props: MessageItemProps) { const messageParts = () => props.parts + // User messages can temporarily include synthetic helper parts (e.g. tool traces / file reads). + // We only want to display the primary prompt text for the user message; other synthetic text + // parts should be hidden. + const primaryUserTextPartId = () => { + if (!isUser()) return null + const firstText = messageParts().find((part) => part?.type === "text") as { id?: string } | undefined + return typeof firstText?.id === "string" ? firstText.id : null + } + const fileAttachments = () => messageParts().filter((part): part is FilePart => part?.type === "file" && typeof (part as FilePart).url === "string") @@ -96,7 +106,8 @@ export default function MessageItem(props: MessageItemProps) { } if (url.startsWith("file://")) { - window.open(url, "_blank", "noopener") + // Local filesystem URLs are not reliably downloadable from the message stream. + // We hide the download action for these chips. return } @@ -372,6 +383,7 @@ export default function MessageItem(props: MessageItemProps) { messageType={props.record.role} instanceId={props.instanceId} sessionId={props.sessionId} + primaryUserTextPartId={primaryUserTextPartId()} onRendered={props.onContentRendered} /> )} @@ -398,17 +410,20 @@ export default function MessageItem(props: MessageItemProps) { {name} {name} - + + +