{(title) => (
diff --git a/packages/app/src/pages/session/timeline/message-timeline.tsx b/packages/app/src/pages/session/timeline/message-timeline.tsx
index 2e2c65af3b33..8a1e9c5fae40 100644
--- a/packages/app/src/pages/session/timeline/message-timeline.tsx
+++ b/packages/app/src/pages/session/timeline/message-timeline.tsx
@@ -160,8 +160,10 @@ function TimelineDiffSummaryRow(props: { diffs: SummaryDiff[] }) {
>
- {props.diffs.length} {language.t("ui.sessionTurn.diffs.changed")}{" "}
- {language.t(props.diffs.length === 1 ? "ui.common.file.one" : "ui.common.file.other")}
+ {language.t(
+ props.diffs.length === 1 ? "ui.sessionTurn.diffs.changed.one" : "ui.sessionTurn.diffs.changed.other",
+ { count: String(props.diffs.length) },
+ )}
0}>
@@ -325,6 +327,7 @@ export function MessageTimeline(props: {
parts: getMsgParts,
status: sessionStatus,
showReasoningSummaries: settings.general.showReasoningSummaries,
+ inlineComments: settings.general.newLayoutDesigns,
})
const activeMessageID = projection.activeMessageID
const assistantMessagesByParent = projection.assistantMessagesByParent
@@ -1133,6 +1136,10 @@ export function MessageTimeline(props: {
const m = messageByID().get(userMessageRow().userMessageID)
if (m?.role === "user") return m
})
+ const messageComments = createMemo(() => {
+ if (!settings.general.newLayoutDesigns()) return []
+ return getMsgParts(userMessageRow().userMessageID).flatMap((part) => MessageComment.fromPart(part) ?? [])
+ })
return (
@@ -1144,6 +1151,7 @@ export function MessageTimeline(props: {
parts={getMsgParts(userMessageRow().userMessageID)}
actions={props.actions}
useV2Actions={settings.general.newLayoutDesigns()}
+ comments={messageComments()}
/>
@@ -1241,12 +1249,13 @@ export function MessageTimeline(props: {
const initialRow = timelineRowByKey().get(props.rowKey)!
const item = createMemo(() => virtualItemByKey().get(props.rowKey) ?? initialItem)
const row = createMemo(() => timelineRowByKey().get(props.rowKey) ?? initialRow)
- const asyncFile = () => {
+ const tool = () => {
const value = row()
- if (value._tag !== "AssistantPart" || value.group.type !== "part") return false
+ if (value._tag !== "AssistantPart" || value.group.type !== "part") return
const part = getMsgPart(value.group.ref.messageID, value.group.ref.partID)
- return part?.type === "tool" && ["edit", "write", "apply_patch"].includes(part.tool)
+ if (part?.type === "tool") return part
}
+ const asyncFile = () => ["edit", "write", "apply_patch"].includes(tool()?.tool ?? "")
const [ready, setReady] = createSignal(initialItem.size <= timelineFallbackItemSize || !asyncFile())
let contentMeasureFrame: number | undefined
@@ -1276,6 +1285,8 @@ export function MessageTimeline(props: {
width: "100%",
height: `${item().size}px`,
overflow: "clip",
+ // Rounded virtual measurements can otherwise clip a framed row's outer paint.
+ "overflow-clip-margin": row()._tag === "TurnGap" ? undefined : "0.5px",
}}
>
Part[]
status: Accessor
showReasoningSummaries: Accessor
+ inlineComments: Accessor
}) {
const messageByID = createMemo(() => new Map(input.messages().map((message) => [message.id, message] as const)))
const assistantMessagesByParent = createMemo(() => {
@@ -59,6 +60,7 @@ export function createTimelineProjection(input: {
input.showReasoningSummaries(),
input.status().type,
activeMessageID() === userMessage.id,
+ input.inlineComments(),
),
),
),
diff --git a/packages/app/src/pages/session/timeline/rows.ts b/packages/app/src/pages/session/timeline/rows.ts
index 6a9cb669d07d..72cd9a180c00 100644
--- a/packages/app/src/pages/session/timeline/rows.ts
+++ b/packages/app/src/pages/session/timeline/rows.ts
@@ -38,6 +38,8 @@ export namespace Timeline {
showReasoning: boolean,
status: SessionStatus["type"],
isActive: boolean,
+ // v2 renders comments inside the user message attachments row instead of a strip row
+ inlineComments: boolean,
) {
const rows: TimelineRow.TimelineRow[] = []
@@ -74,7 +76,7 @@ export namespace Timeline {
: groupParts(assistantPartRefs).map((group) => ({ type: "part" as const, group }))
if (previousUserMessage) rows.push(new TimelineRow.TurnGap({ userMessageID: userMessage.id }))
- if (comments.length > 0)
+ if (comments.length > 0 && !inlineComments)
rows.push(
new TimelineRow.CommentStrip({
userMessageID: userMessage.id,
@@ -84,7 +86,7 @@ export namespace Timeline {
rows.push(
new TimelineRow.UserMessage({
userMessageID: userMessage.id,
- anchor: comments.length === 0,
+ anchor: inlineComments || comments.length === 0,
}),
)
diff --git a/packages/app/src/pages/session/use-composer-commands.tsx b/packages/app/src/pages/session/use-composer-commands.tsx
index 98239010f5c9..9b75c7bf4cb5 100644
--- a/packages/app/src/pages/session/use-composer-commands.tsx
+++ b/packages/app/src/pages/session/use-composer-commands.tsx
@@ -1,6 +1,6 @@
import { useCommand, type CommandOption } from "@/context/command"
import { useLanguage } from "@/context/language"
-import { useLocal } from "@/context/local"
+import { useLocal, type ModelSelection } from "@/context/local"
import { useSettings } from "@/context/settings"
import { useDialog } from "@opencode-ai/ui/context/dialog"
import { getCursorPosition, setCursorPosition } from "@/components/prompt-input/editor-dom"
@@ -14,7 +14,7 @@ const withCategory = (category: string) => {
})
}
-export const useComposerCommands = () => {
+export const useComposerCommands = (input: { model?: ModelSelection } = {}) => {
const command = useCommand()
const dialog = useDialog()
const language = useLanguage()
@@ -22,6 +22,7 @@ export const useComposerCommands = () => {
const settings = useSettings()
const { sessionKey } = useSessionLayout()
const sessionOwnership = createSessionOwnership(sessionKey)
+ const model = input.model ?? local.model
const modelCommand = withCategory(language.t("command.category.model"))
const agentCommand = withCategory(language.t("command.category.agent"))
@@ -43,7 +44,7 @@ export const useComposerCommands = () => {
}
const { DialogSelectModel } = await import("@/components/dialog-select-model")
owner.run(() => {
- void dialog.show(() => , restoreComposer)
+ void dialog.show(() => , restoreComposer)
})
}
@@ -61,7 +62,7 @@ export const useComposerCommands = () => {
title: language.t("command.model.variant.cycle"),
description: language.t("command.model.variant.cycle.description"),
keybind: "shift+mod+d",
- onSelect: () => local.model.variant.cycle(),
+ onSelect: () => model.variant.cycle(),
}),
agentCommand({
id: "agent.cycle",
diff --git a/packages/app/src/pages/session/use-session-commands.tsx b/packages/app/src/pages/session/use-session-commands.tsx
index fd2e29d31c69..e23268c64bbb 100644
--- a/packages/app/src/pages/session/use-session-commands.tsx
+++ b/packages/app/src/pages/session/use-session-commands.tsx
@@ -18,8 +18,6 @@ import { createSessionTabs } from "@/pages/session/helpers"
import { extractPromptFromParts } from "@/utils/prompt"
import { UserMessage } from "@opencode-ai/sdk/v2"
import { useSessionLayout } from "@/pages/session/session-layout"
-import { useTabs } from "@/context/tabs"
-import { requireServerKey } from "@/utils/session-route"
import { createSessionOwnership } from "./session-ownership"
export type SessionCommandContext = {
@@ -27,6 +25,7 @@ export type SessionCommandContext = {
setActiveMessage: (message: UserMessage | undefined) => void
focusInput: () => void
review?: () => boolean
+ fileBrowser?: () => boolean
}
const withCategory = (category: string) => {
@@ -48,7 +47,6 @@ export const useSessionCommands = (actions: SessionCommandContext) => {
const settings = useSettings()
const sync = useSync()
const terminal = useTerminal()
- const sessionTabs = useTabs()
const layout = useLayout()
const navigate = useNavigate()
const { params, sessionKey, tabs, view } = useSessionLayout()
@@ -86,6 +84,7 @@ export const useSessionCommands = (actions: SessionCommandContext) => {
normalizeTab,
review: actions.review,
hasReview,
+ fileBrowser: actions.fileBrowser,
})
const activeFileTab = tabState.activeFileTab
const closableTab = tabState.closableTab
@@ -269,6 +268,14 @@ export const useSessionCommands = (actions: SessionCommandContext) => {
view().terminal.open()
}
+ const closeTerminal = () => {
+ const id = terminal.active()
+ if (!id) return
+ const last = terminal.all().length === 1
+ void terminal.close(id)
+ if (last) view().terminal.close()
+ }
+
const chooseMcp = () => {
void openDialog(
() => import("@/components/dialog-select-mcp"),
@@ -411,9 +418,9 @@ export const useSessionCommands = (actions: SessionCommandContext) => {
title: language.t("command.session.new"),
keybind: "mod+shift+s",
slash: "new",
- onSelect: () => {
- if (params.serverKey) {
- sessionTabs.newDraft({ server: requireServerKey(params.serverKey), directory: sdk().directory })
+ onSelect: (source) => {
+ if (settings.general.newLayoutDesigns()) {
+ command.trigger("tab.new", source)
return
}
navigate(`/${params.dir}/session`)
@@ -518,6 +525,14 @@ export const useSessionCommands = (actions: SessionCommandContext) => {
]
const terminalCmds = () => [
+ terminalCommand({
+ id: "terminal.close",
+ title: language.t("terminal.close"),
+ keybind: "mod+w",
+ hidden: true,
+ when: (event) => event.target instanceof Element && !!event.target.closest('[data-component="terminal"]'),
+ onSelect: closeTerminal,
+ }),
terminalCommand({
id: "terminal.new",
title: language.t("command.terminal.new"),
diff --git a/packages/app/src/pages/session/v2/review-diff-kinds.test.ts b/packages/app/src/pages/session/v2/review-diff-kinds.test.ts
index ee37a2c8b4c9..2d069cdb186f 100644
--- a/packages/app/src/pages/session/v2/review-diff-kinds.test.ts
+++ b/packages/app/src/pages/session/v2/review-diff-kinds.test.ts
@@ -1,5 +1,5 @@
import { describe, expect, test } from "bun:test"
-import { filterReviewFiles, reviewDiffKinds } from "./review-diff-kinds"
+import { filterReviewFiles, reviewDiffDirectory, reviewDiffKinds, reviewDiffNeedsLoad } from "./review-diff-kinds"
describe("reviewDiffKinds", () => {
test("maps file and directory kinds", () => {
@@ -28,3 +28,43 @@ describe("filterReviewFiles", () => {
expect(filterReviewFiles(files, "")).toEqual(files)
})
})
+
+describe("reviewDiffNeedsLoad", () => {
+ test("loads changed files whose aggregate patch has no hunks", () => {
+ expect(
+ reviewDiffNeedsLoad({
+ file: "src/a.ts",
+ additions: 1,
+ deletions: 0,
+ patch: "diff --git a/src/a.ts b/src/a.ts\n--- a/src/a.ts\n+++ b/src/a.ts",
+ }),
+ ).toBe(true)
+ })
+
+ test("keeps complete patches and empty changes", () => {
+ expect(
+ reviewDiffNeedsLoad({
+ file: "src/a.ts",
+ additions: 1,
+ deletions: 0,
+ patch: "@@ -0,0 +1 @@\n+value",
+ }),
+ ).toBe(false)
+ expect(reviewDiffNeedsLoad({ file: "empty.txt", additions: 0, deletions: 0 })).toBe(false)
+ })
+})
+
+describe("reviewDiffDirectory", () => {
+ test("scopes nested files to their parent directory", () => {
+ expect(reviewDiffDirectory("/repo", "src/lib/a.ts")).toBe("/repo/src/lib")
+ expect(reviewDiffDirectory("C:\\repo", "src/lib/a.ts")).toBe("C:\\repo\\src\\lib")
+ })
+
+ test("does not rescope root files", () => {
+ expect(reviewDiffDirectory("/repo/", "README.md")).toBe("/repo")
+ expect(reviewDiffDirectory("/", "README.md")).toBe("/")
+ expect(reviewDiffDirectory("C:\\", "README.md")).toBe("C:\\")
+ expect(reviewDiffDirectory("/", "src/a.ts")).toBe("/src")
+ expect(reviewDiffDirectory("C:\\", "src/a.ts")).toBe("C:\\src")
+ })
+})
diff --git a/packages/app/src/pages/session/v2/review-diff-kinds.ts b/packages/app/src/pages/session/v2/review-diff-kinds.ts
index c288c357068d..49cec334bc47 100644
--- a/packages/app/src/pages/session/v2/review-diff-kinds.ts
+++ b/packages/app/src/pages/session/v2/review-diff-kinds.ts
@@ -12,6 +12,24 @@ export function filterRenderableDiff(value: SnapshotFileDiff | VcsFileDiff): val
return typeof value.file === "string"
}
+export function reviewDiffNeedsLoad(diff: RenderDiff) {
+ if (diff.additions === 0 && diff.deletions === 0) return false
+ return !diff.patch || !/^@@ /m.test(diff.patch)
+}
+
+export function reviewRootDirectory(root: string) {
+ return root === "/" || /^[A-Za-z]:[/\\]?$/.test(root) ? root : root.replace(/[/\\]+$/, "")
+}
+
+export function reviewDiffDirectory(root: string, file: string) {
+ const path = normalizePath(file)
+ const index = path.lastIndexOf("/")
+ const separator = root.includes("\\") ? "\\" : "/"
+ const base = reviewRootDirectory(root)
+ if (index < 0) return base
+ return `${base.endsWith(separator) ? base : base + separator}${path.slice(0, index).replaceAll("/", separator)}`
+}
+
export function reviewDiffKinds(diffs: RenderDiff[]) {
const merge = (a: Kind | undefined, b: Kind) => {
if (!a) return b
diff --git a/packages/app/src/pages/session/v2/review-panel-v2.tsx b/packages/app/src/pages/session/v2/review-panel-v2.tsx
index fcd52756ab08..143b4f5f528a 100644
--- a/packages/app/src/pages/session/v2/review-panel-v2.tsx
+++ b/packages/app/src/pages/session/v2/review-panel-v2.tsx
@@ -1,11 +1,10 @@
-import { createMemo, createSignal, Show, type JSX } from "solid-js"
+import { createMemo, createResource, createSignal, Show, type JSX } from "solid-js"
import type { SnapshotFileDiff, VcsFileDiff } from "@opencode-ai/sdk/v2"
import {
SESSION_REVIEW_V2_SIDEBAR_WIDTH_MAX,
SESSION_REVIEW_V2_SIDEBAR_WIDTH_MIN,
SessionReviewV2,
SessionReviewV2Sidebar,
- SessionReviewV2SidebarToggle,
} from "@opencode-ai/session-ui/v2/session-review-v2"
import { SessionReviewFilePreviewV2 } from "@opencode-ai/session-ui/v2/session-review-file-preview-v2"
import { DiffChanges } from "@opencode-ai/ui/v2/diff-changes-v2"
@@ -25,6 +24,7 @@ import {
filterRenderableDiff,
filterReviewFiles,
reviewDiffKinds,
+ reviewDiffNeedsLoad,
type RenderDiff,
} from "@/pages/session/v2/review-diff-kinds"
import type { ReviewPanelV2State } from "@/pages/session/v2/review-panel-v2-state"
@@ -37,6 +37,8 @@ export type ReviewPanelV2Props = {
empty?: JSX.Element
diffs: () => ReviewDiff[]
diffsReady: () => boolean
+ diffVersion?: number
+ loadDiff?: (path: string, version?: number) => Promise
activeFile?: string
onSelectFile: (path: string) => void
diffStyle: SessionReviewDiffStyle
@@ -63,6 +65,8 @@ export function ReviewPanelV2(props: ReviewPanelV2Props) {
)
const searching = createMemo(() => props.state.filter().trim().length > 0)
const kinds = createMemo(() => reviewDiffKinds(diffs()))
+ // Changes-only trees omit "M" — every row is already a change; A/D stay visible.
+ const treeKinds = createMemo(() => new Map([...kinds()].filter(([, kind]) => kind !== "mix")))
const activeDiff = createMemo(() => {
// A focused comment takes over the preview until the preview applies it and
// clears the focus; the owner then persists the file as the active selection.
@@ -74,7 +78,26 @@ export function ReviewPanelV2(props: ReviewPanelV2Props) {
if (active && files.includes(active)) return active
return files[0]
})
- const activeItem = createMemo(() => diffs().find((diff) => diff.file === activeDiff()))
+ const sourceActiveItem = createMemo(() => diffs().find((diff) => diff.file === activeDiff()))
+ const detailSource = createMemo(() => {
+ const diff = sourceActiveItem()
+ const load = props.loadDiff
+ if (!diff || !load || !reviewDiffNeedsLoad(diff)) return
+ return { diff, load, version: props.diffVersion }
+ })
+ const [loadedDiff] = createResource(detailSource, async ({ diff, load, version }) => {
+ const value = await load(diff.file, version)
+ if (value?.file !== diff.file) return
+ return { source: diff, version, value }
+ })
+
+ const activeItem = createMemo(() => {
+ const source = sourceActiveItem()
+ if (loadedDiff.state !== "ready") return source
+ const loaded = loadedDiff()
+ if (loaded && loaded.source === source && loaded.version === props.diffVersion) return loaded.value
+ return source
+ })
const readFile = async (path: string) =>
sdk()
@@ -91,9 +114,6 @@ export function ReviewPanelV2(props: ReviewPanelV2Props) {
stats={}
empty={props.empty}
sidebarOpen={props.state.sidebarOpened()}
- sidebarToggle={
-
- }
sidebar={
// Always mounted: the sidebar header hosts the changes-mode dropdown,
// which must stay reachable when the current mode has zero diffs.
@@ -105,7 +125,7 @@ export function ReviewPanelV2(props: ReviewPanelV2Props) {
diffs={diffs}
filteredFiles={filteredFiles}
searching={searching}
- kinds={kinds}
+ kinds={treeKinds}
activeDiff={activeDiff}
/>
}
diff --git a/packages/app/src/pages/session/v2/session-file-browser-tab.tsx b/packages/app/src/pages/session/v2/session-file-browser-tab.tsx
new file mode 100644
index 000000000000..04ad1e3c8253
--- /dev/null
+++ b/packages/app/src/pages/session/v2/session-file-browser-tab.tsx
@@ -0,0 +1,179 @@
+import { createMemo, createSignal, createUniqueId, Show } from "solid-js"
+import { createQuery } from "@tanstack/solid-query"
+import { Icon } from "@opencode-ai/ui/icon"
+import { SessionFilePanelV2, SessionFilePanelV2Empty } from "@opencode-ai/session-ui/v2/session-file-panel-v2"
+import { SessionReviewV2Sidebar } from "@opencode-ai/session-ui/v2/session-review-v2"
+import FileTreeV2, { type Kind } from "@/components/file-tree-v2"
+import { useFile } from "@/context/file"
+import { useLanguage } from "@/context/language"
+import { useLayout } from "@/context/layout"
+import { useSDK } from "@/context/sdk"
+import { displayName } from "@/pages/layout/helpers"
+import { useSessionLayout } from "@/pages/session/session-layout"
+import { SessionFileView } from "@/pages/session/file-tabs"
+import { applyFileListKeyDown, SessionFileListV2 } from "@/pages/session/v2/session-file-list-v2"
+import { pathKey } from "@/utils/path-key"
+
+const emptyFiles: string[] = []
+
+export type SessionFileBrowserState = {
+ sidebarOpened: () => boolean
+ sidebarWidth: () => number
+ resizeSidebar: (width: number) => void
+ toggleSidebar: () => void
+}
+
+export function SessionFileBrowserTab(props: {
+ tab: string
+ placeholder: boolean
+ active?: string
+ kinds: ReadonlyMap
+ state: SessionFileBrowserState
+ onSelect: (path: string) => void
+ onSelectPermanent: (path: string) => void
+ filterRef?: (element: HTMLInputElement) => void
+}) {
+ const file = useFile()
+ const language = useLanguage()
+ const layout = useLayout()
+ const sdk = useSDK()
+ const { workspaceKey } = useSessionLayout()
+ const resultsID = `session-file-browser-results-${createUniqueId()}`
+ const [filter, setFilter] = createSignal("")
+ const [explicitHighlight, setExplicitHighlight] = createSignal()
+ const sidebarOpened = () => props.placeholder || props.state.sidebarOpened()
+ const query = createMemo(() => filter().trim())
+ const search = createQuery(() => {
+ const value = query()
+ return {
+ queryKey: ["session-open-file", workspaceKey(), value] as const,
+ enabled: value.length > 0,
+ queryFn: ({ signal }) => file.searchFiles(value, { limit: 200, signal }),
+ }
+ })
+ const files = createMemo(() => {
+ if (!query() || search.isPending) return emptyFiles
+ return [...new Set(search.data ?? emptyFiles)]
+ })
+ const highlighted = createMemo(() => {
+ const values = files()
+ if (values.length === 0) return undefined
+ const explicit = explicitHighlight()
+ if (explicit && values.includes(explicit)) return explicit
+ return values[0]
+ })
+ const loading = createMemo(() => query().length > 0 && search.isPending)
+ const project = createMemo(() => {
+ const directory = pathKey(sdk().directory)
+ return layout.projects
+ .list()
+ .find(
+ (item) =>
+ pathKey(item.worktree) === directory || item.sandboxes?.some((sandbox) => pathKey(sandbox) === directory),
+ )
+ })
+ const title = createMemo(() => displayName(project() ?? { worktree: sdk().directory }))
+ const optionID = (path: string) => `${resultsID}-option-${files().indexOf(path)}`
+
+ const onFilterKeyDown = (event: KeyboardEvent & { currentTarget: HTMLInputElement }) => {
+ if (event.key === "Escape" && query()) {
+ event.preventDefault()
+ setFilter("")
+ return
+ }
+ if (!query()) return
+ applyFileListKeyDown(event, files(), highlighted(), {
+ onHighlight: setExplicitHighlight,
+ onSelect: props.onSelectPermanent,
+ })
+ }
+
+ // Keep the sidebar outside Kobalte Tabs.Content: a morphing content value
+ // unmounts the whole panel on every file-tab switch and resets sidebar scroll.
+ return (
+ {title()}}
+ filter={filter()}
+ onFilterChange={setFilter}
+ onFilterKeyDown={onFilterKeyDown}
+ filterAutofocus={props.placeholder}
+ filterRef={props.filterRef}
+ filterControls={resultsID}
+ filterActiveDescendant={highlighted() ? optionID(highlighted()!) : undefined}
+ filterExpanded={query().length > 0 && files().length > 0}
+ width={props.state.sidebarWidth()}
+ onWidthChange={props.state.resizeSidebar}
+ >
+ props.onSelect(node.path)}
+ onFileDoubleClick={(node) => props.onSelectPermanent(node.path)}
+ />
+ }
+ >
+
+ {language.t("common.loading")}
+ {language.t("common.loading.ellipsis")}
+
+ }
+ >
+ 0}
+ fallback={
+
+ {language.t("palette.empty")}
+
+ }
+ >
+ {
+ setExplicitHighlight(path)
+ props.onSelect(path)
+ }}
+ onFileDoubleClick={props.onSelectPermanent}
+ />
+
+
+
+
+ }
+ >
+
+
+
+
{language.t("command.file.open")}
+
{language.t("session.files.selectToOpen")}
+
+
+ }
+ >
+
+
+ {(tab) => }
+
+
+
+
+ )
+}
diff --git a/packages/app/src/pages/session/v2/session-file-list-v2.tsx b/packages/app/src/pages/session/v2/session-file-list-v2.tsx
index 3a0a17a487f5..16cac2a45d66 100644
--- a/packages/app/src/pages/session/v2/session-file-list-v2.tsx
+++ b/packages/app/src/pages/session/v2/session-file-list-v2.tsx
@@ -43,7 +43,11 @@ export function SessionFileListV2(props: {
active?: string
highlighted?: string
kinds?: ReadonlyMap
+ id?: string
+ role?: "listbox"
+ optionID?: (path: string) => string
onFileClick: (path: string) => void
+ onFileDoubleClick?: (path: string) => void
}) {
const active = () => normalizePath(props.active ?? "")
const highlighted = () => normalizePath(props.highlighted ?? "")
@@ -88,6 +92,8 @@ export function SessionFileListV2(props: {
return (
+ {typeLabel(name, file.mime)}
+
+
)
}}
@@ -1937,8 +1966,6 @@ ToolRegistry.register({
const title = createMemo(() => agent().name ?? i18n.t("ui.tool.agent.default"))
const tone = createMemo(() => agent().color)
const v2Tone = createMemo(() => agent().v2Color)
- const border = createMemo(() => agent().border)
- const background = createMemo(() => agent().background)
const subtitle = createMemo(() => {
const value =
typeof props.input.description === "string" && props.input.description
@@ -1983,25 +2010,34 @@ ToolRegistry.register({
style={{
"--task-agent-color": v2Tone(),
"--task-agent-legacy-color": tone(),
- "--task-agent-border": border(),
- "--task-agent-background": background(),
}}
>
-