|
|
@@ -38,6 +38,7 @@ import type {
|
|
|
} from "@opencode-ai/sdk/v2"
|
|
|
import { useLocal } from "../../context/local"
|
|
|
import { Locale } from "../../util/locale"
|
|
|
+import { FilePath } from "../../ui/file-path"
|
|
|
import { webSearchProviderLabel } from "../../util/tool-display"
|
|
|
import { useRenderer, useTerminalDimensions, type JSX } from "@opentui/solid"
|
|
|
import { useSDK } from "../../context/sdk"
|
|
|
@@ -1402,6 +1403,7 @@ function RevertMessage(props: {
|
|
|
readonly deletions: number
|
|
|
}>
|
|
|
}) {
|
|
|
+ const ctx = use()
|
|
|
const { theme } = useTheme()
|
|
|
const route = useRouteData("session")
|
|
|
const sdk = useSDK()
|
|
|
@@ -1444,9 +1446,17 @@ function RevertMessage(props: {
|
|
|
{(file) => (
|
|
|
<box flexDirection="row" gap={1} flexShrink={0}>
|
|
|
<text fg={theme.textMuted}>{statusLabel(file.status)}</text>
|
|
|
- <text fg={theme.text} wrapMode="none">
|
|
|
- {Locale.truncateLeft(file.file, 60)}
|
|
|
- </text>
|
|
|
+ <FilePath
|
|
|
+ value={file.file}
|
|
|
+ maxWidth={Math.max(
|
|
|
+ 2,
|
|
|
+ ctx.width -
|
|
|
+ 5 -
|
|
|
+ (file.additions > 0 ? Bun.stringWidth(`+${file.additions}`) + 1 : 0) -
|
|
|
+ (file.deletions > 0 ? Bun.stringWidth(`-${file.deletions}`) + 1 : 0),
|
|
|
+ )}
|
|
|
+ fg={theme.text}
|
|
|
+ />
|
|
|
<Show when={file.additions > 0}>
|
|
|
<text fg={theme.diffAdded}>+{file.additions}</text>
|
|
|
</Show>
|
|
|
@@ -2138,6 +2148,7 @@ export function InlineToolRow(props: {
|
|
|
|
|
|
function BlockTool(props: {
|
|
|
title?: string
|
|
|
+ path?: { label: string; value: string }
|
|
|
children?: JSX.Element
|
|
|
onClick?: () => void
|
|
|
part?: SessionMessageAssistantTool
|
|
|
@@ -2171,18 +2182,45 @@ function BlockTool(props: {
|
|
|
props.onClick?.()
|
|
|
}}
|
|
|
>
|
|
|
- <Show when={props.title}>
|
|
|
- {(title) => (
|
|
|
- <Show
|
|
|
- when={props.spinner}
|
|
|
- fallback={
|
|
|
- <text paddingLeft={3} fg={permission() ? theme.warning : theme.textMuted}>
|
|
|
- {title()}
|
|
|
- </text>
|
|
|
- }
|
|
|
- >
|
|
|
- <Spinner color={permission() ? theme.warning : theme.textMuted}>{title().replace(/^# /, "")}</Spinner>
|
|
|
+ <Show
|
|
|
+ when={props.path}
|
|
|
+ fallback={
|
|
|
+ <Show when={props.title}>
|
|
|
+ {(title) => (
|
|
|
+ <Show
|
|
|
+ when={props.spinner}
|
|
|
+ fallback={
|
|
|
+ <text fg={permission() ? theme.warning : theme.textMuted}>
|
|
|
+ {title()}
|
|
|
+ </text>
|
|
|
+ }
|
|
|
+ >
|
|
|
+ <Spinner color={permission() ? theme.warning : theme.textMuted}>{title().replace(/^# /, "")}</Spinner>
|
|
|
+ </Show>
|
|
|
+ )}
|
|
|
</Show>
|
|
|
+ }
|
|
|
+ >
|
|
|
+ {(path) => (
|
|
|
+ <box flexDirection="row" gap={1} minWidth={0}>
|
|
|
+ <Show
|
|
|
+ when={props.spinner}
|
|
|
+ fallback={
|
|
|
+ <text flexShrink={0} fg={permission() ? theme.warning : theme.textMuted}>
|
|
|
+ {path().label}
|
|
|
+ </text>
|
|
|
+ }
|
|
|
+ >
|
|
|
+ <Spinner color={permission() ? theme.warning : theme.textMuted}>
|
|
|
+ {path().label.replace(/^# /, "")}
|
|
|
+ </Spinner>
|
|
|
+ </Show>
|
|
|
+ <FilePath
|
|
|
+ value={path().value}
|
|
|
+ maxWidth={Math.max(2, ctx.width - 4 - Bun.stringWidth(path().label) - (props.spinner ? 2 : 0))}
|
|
|
+ fg={permission() ? theme.warning : theme.textMuted}
|
|
|
+ />
|
|
|
+ </box>
|
|
|
)}
|
|
|
</Show>
|
|
|
{props.children}
|
|
|
@@ -2277,7 +2315,10 @@ function Write(props: ToolProps) {
|
|
|
return (
|
|
|
<Switch>
|
|
|
<Match when={props.metadata.diagnostics !== undefined}>
|
|
|
- <BlockTool title={"# Wrote " + pathFormatter.format(stringValue(props.input.path))} part={props.part}>
|
|
|
+ <BlockTool
|
|
|
+ path={{ label: "# Wrote", value: pathFormatter.format(stringValue(props.input.path)) }}
|
|
|
+ part={props.part}
|
|
|
+ >
|
|
|
<line_number fg={theme.textMuted} minWidth={3} paddingRight={1}>
|
|
|
<code
|
|
|
conceal={false}
|
|
|
@@ -2503,7 +2544,7 @@ function Edit(props: ToolProps) {
|
|
|
<Switch>
|
|
|
<Match when={file()}>
|
|
|
{(item) => (
|
|
|
- <BlockTool title={"← Edit " + pathFormatter.format(path())} part={props.part}>
|
|
|
+ <BlockTool path={{ label: "← Edit", value: pathFormatter.format(path()) }} part={props.part}>
|
|
|
<box paddingLeft={1}>
|
|
|
<diff
|
|
|
diff={item().patch}
|
|
|
@@ -2531,11 +2572,12 @@ function Edit(props: ToolProps) {
|
|
|
</Match>
|
|
|
<Match when={true}>
|
|
|
<BlockTool
|
|
|
- title={
|
|
|
+ path={
|
|
|
stringValue(props.input.path)
|
|
|
- ? "← Edit " + pathFormatter.format(stringValue(props.input.path))
|
|
|
- : "# Preparing edit..."
|
|
|
+ ? { label: "← Edit", value: pathFormatter.format(stringValue(props.input.path)) }
|
|
|
+ : undefined
|
|
|
}
|
|
|
+ title={stringValue(props.input.path) ? undefined : "# Preparing edit..."}
|
|
|
part={props.part}
|
|
|
spinner={props.part.state.status === "streaming"}
|
|
|
/>
|
|
|
@@ -2576,7 +2618,10 @@ function ApplyPatch(props: ToolProps) {
|
|
|
<For each={files()}>
|
|
|
{(file) => (
|
|
|
<BlockTool
|
|
|
- title={`${file.type === "add" ? "# Created" : file.type === "delete" ? "# Deleted" : "← Patched"} ${pathFormatter.format(file.relativePath)}`}
|
|
|
+ path={{
|
|
|
+ label: file.type === "add" ? "# Created" : file.type === "delete" ? "# Deleted" : "← Patched",
|
|
|
+ value: pathFormatter.format(file.relativePath),
|
|
|
+ }}
|
|
|
part={props.part}
|
|
|
>
|
|
|
<box paddingLeft={1}>
|
|
|
@@ -2610,10 +2655,17 @@ function ApplyPatch(props: ToolProps) {
|
|
|
<For each={applied()}>
|
|
|
{(file) => (
|
|
|
<BlockTool
|
|
|
- title={`${file.type === "add" ? "# Created" : file.type === "delete" ? "# Deleted" : "← Patched"} ${pathFormatter.format(file.resource)}`}
|
|
|
+ path={{
|
|
|
+ label: file.type === "add" ? "# Created" : file.type === "delete" ? "# Deleted" : "← Patched",
|
|
|
+ value: pathFormatter.format(file.resource),
|
|
|
+ }}
|
|
|
part={props.part}
|
|
|
>
|
|
|
- <text fg={file.type === "delete" ? theme.diffRemoved : theme.textMuted}>{file.resource}</text>
|
|
|
+ <FilePath
|
|
|
+ value={file.resource}
|
|
|
+ maxWidth={Math.max(2, ctx.width - 3)}
|
|
|
+ fg={file.type === "delete" ? theme.diffRemoved : theme.textMuted}
|
|
|
+ />
|
|
|
</BlockTool>
|
|
|
)}
|
|
|
</For>
|
|
|
@@ -2621,15 +2673,23 @@ function ApplyPatch(props: ToolProps) {
|
|
|
</Match>
|
|
|
<Match when={true}>
|
|
|
<BlockTool
|
|
|
+ path={
|
|
|
+ targets().length === 1
|
|
|
+ ? {
|
|
|
+ label: props.part.state.status === "error" ? "# Patch failed" : "Patching",
|
|
|
+ value: pathFormatter.format(targets()[0]),
|
|
|
+ }
|
|
|
+ : undefined
|
|
|
+ }
|
|
|
title={
|
|
|
targets().length === 1
|
|
|
- ? `${props.part.state.status === "error" ? "# Patch failed" : "# Preparing patch"} ${pathFormatter.format(targets()[0])}`
|
|
|
+ ? undefined
|
|
|
: props.part.state.status === "error"
|
|
|
? "# Patch failed"
|
|
|
- : "# Preparing patch..."
|
|
|
+ : "Patching"
|
|
|
}
|
|
|
part={props.part}
|
|
|
- spinner={props.part.state.status === "streaming"}
|
|
|
+ spinner={props.part.state.status === "streaming" || props.part.state.status === "running"}
|
|
|
/>
|
|
|
</Match>
|
|
|
</Switch>
|