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
5 changes: 5 additions & 0 deletions .changeset/inline-read-images.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"kilo-code": minor
---

Render images inline in the chat view when the agent reads an image file. Images appear below the read tool card and can be clicked to open a full-size preview.
29 changes: 29 additions & 0 deletions packages/kilo-ui/src/components/message-part.css
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,35 @@ html[data-theme="kilo-vscode"] [data-component="bash-output"] {
margin-bottom: 0px;
}

[data-slot="tool-read-images"] {
display: flex;
flex-wrap: wrap;
gap: 8px;
padding-top: 8px;
max-width: min(100%, 64ch);
}

[data-slot="tool-read-image"] {
max-width: 200px;
max-height: 200px;
border-radius: var(--radius-sm, 6px);
overflow: hidden;
border: 1px solid var(--border-weak-base);
cursor: pointer;
transition: border-color 0.15s ease;

&:hover {
border-color: var(--border-strong-base);
}
}

[data-slot="tool-read-image-img"] {
display: block;
max-width: 100%;
max-height: 200px;
object-fit: contain;
}

[data-component="todos"] {
[data-slot="message-part-todo-hidden"] {
padding: 2px 0 2px 28px;
Expand Down
25 changes: 25 additions & 0 deletions packages/kilo-ui/src/components/message-part.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -995,6 +995,7 @@ export interface ToolProps {
callID?: string
output?: string
status?: string
attachments?: FilePart[]
hideDetails?: boolean
defaultOpen?: boolean
forceOpen?: boolean
Expand Down Expand Up @@ -1243,6 +1244,8 @@ PART_MAPPING["tool"] = function ToolPartDisplay(props) {
// @ts-expect-error
output={part.state.output}
status={part.state.status}
// @ts-expect-error
attachments={part.state.attachments}
hideDetails={props.hideDetails}
defaultOpen={props.defaultOpen}
animate
Expand Down Expand Up @@ -1746,6 +1749,7 @@ ToolRegistry.register({
render(props) {
const data = useData()
const i18n = useI18n()
const dialog = useDialog()
const args: string[] = []
if (props.input.offset) args.push("offset=" + props.input.offset)
if (props.input.limit) args.push("limit=" + props.input.limit)
Expand All @@ -1755,6 +1759,10 @@ ToolRegistry.register({
return value.filter((p): p is string => typeof p === "string")
})
const pending = createMemo(() => busy(props.status))
const images = createMemo(() =>
(props.attachments ?? []).filter((f) => f.mime.startsWith("image/") && f.url),
)
const preview = (url: string, alt?: string) => dialog.show(() => <ImagePreview src={url} alt={alt} />)
return (
<>
<BasicTool
Expand Down Expand Up @@ -1783,6 +1791,23 @@ ToolRegistry.register({
/>
)}
</For>
<Show when={images().length > 0}>
<div data-slot="tool-read-images">
<For each={images()}>
{(file) => (
<div data-slot="tool-read-image" onClick={() => preview(file.url, file.filename)}>
<img
data-slot="tool-read-image-img"
src={file.url}
alt={file.filename ?? i18n.t("ui.message.attachment.alt")}
loading="lazy"
decoding="async"
/>
</div>
)}
</For>
</div>
</Show>
</>
)
},
Expand Down
Loading