chore: cleanup

This commit is contained in:
Adam 2025-12-12 13:55:46 -06:00
parent 78484f545c
commit bf420e7df6
No known key found for this signature in database
GPG key ID: 9CB48779AF150E75
3 changed files with 25 additions and 50 deletions

View file

@ -8,6 +8,7 @@ import {
ToolPart,
UserMessage,
} from "@opencode-ai/sdk/v2"
import { useData } from "../context"
import { useDiffComponent } from "../context/diff"
import { BasicTool } from "./basic-tool"
import { GenericTool } from "./basic-tool"
@ -16,26 +17,34 @@ import { Icon } from "./icon"
import { Checkbox } from "./checkbox"
import { DiffChanges } from "./diff-changes"
import { Markdown } from "./markdown"
import { getDirectory, getFilename } from "@opencode-ai/util/path"
import { sanitizePart } from "@opencode-ai/util/sanitize"
import { getDirectory as _getDirectory, getFilename } from "@opencode-ai/util/path"
export interface MessageProps {
message: MessageType
parts: PartType[]
sanitize?: RegExp
}
export interface MessagePartProps {
part: PartType
message: MessageType
hideDetails?: boolean
sanitize?: RegExp
}
export type PartComponent = Component<MessagePartProps>
export const PART_MAPPING: Record<string, PartComponent | undefined> = {}
function relativizeProjectPaths(text: string, directory?: string) {
if (!text) return ""
if (!directory) return text
return text.split(directory).join("")
}
function getDirectory(path: string | undefined) {
const data = useData()
return relativizeProjectPaths(_getDirectory(path), data.directory)
}
export function registerPartComponent(type: string, component: PartComponent) {
PART_MAPPING[type] = component
}
@ -48,26 +57,20 @@ export function Message(props: MessageProps) {
</Match>
<Match when={props.message.role === "assistant" && props.message}>
{(assistantMessage) => (
<AssistantMessageDisplay
message={assistantMessage() as AssistantMessage}
parts={props.parts}
sanitize={props.sanitize}
/>
<AssistantMessageDisplay message={assistantMessage() as AssistantMessage} parts={props.parts} />
)}
</Match>
</Switch>
)
}
export function AssistantMessageDisplay(props: { message: AssistantMessage; parts: PartType[]; sanitize?: RegExp }) {
export function AssistantMessageDisplay(props: { message: AssistantMessage; parts: PartType[] }) {
const filteredParts = createMemo(() => {
return props.parts?.filter((x) => {
return x.type !== "tool" || (x as ToolPart).tool !== "todoread"
})
})
return (
<For each={filteredParts()}>{(part) => <Part part={part} message={props.message} sanitize={props.sanitize} />}</For>
)
return <For each={filteredParts()}>{(part) => <Part part={part} message={props.message} />}</For>
}
export function UserMessageDisplay(props: { message: UserMessage; parts: PartType[] }) {
@ -82,10 +85,9 @@ export function UserMessageDisplay(props: { message: UserMessage; parts: PartTyp
export function Part(props: MessagePartProps) {
const component = createMemo(() => PART_MAPPING[props.part.type])
const part = createMemo(() => sanitizePart(props.part, props.sanitize))
return (
<Show when={component()}>
<Dynamic component={component()} part={part()} message={props.message} hideDetails={props.hideDetails} />
<Dynamic component={component()} part={props.part} message={props.message} hideDetails={props.hideDetails} />
</Show>
)
}
@ -173,12 +175,15 @@ PART_MAPPING["tool"] = function ToolPartDisplay(props) {
}
PART_MAPPING["text"] = function TextPartDisplay(props) {
const data = useData()
const part = props.part as TextPart
const sanitized = createMemo(() => (props.sanitize ? (sanitizePart(part, props.sanitize) as TextPart) : part))
const content = createMemo(() => (part.text ?? "").trim())
const displayText = createMemo(() => relativizeProjectPaths(content(), data.directory))
return (
<Show when={part.text.trim()}>
<Show when={displayText()}>
<div data-component="text-part">
<Markdown text={sanitized().text.trim()} />
<Markdown text={displayText()} />
</div>
</Show>
)

View file

@ -33,7 +33,6 @@ export function SessionTurn(
) {
const data = useData()
const diffComponent = useDiffComponent()
const sanitizer = createMemo(() => (data.directory ? new RegExp(`${data.directory}/`, "g") : undefined))
const messages = createMemo(() => (props.sessionID ? (data.store.message[props.sessionID] ?? []) : []))
const userMessages = createMemo(() =>
messages()
@ -208,7 +207,7 @@ export function SessionTurn(
</div>
</div>
<div data-slot="session-turn-message-content">
<Message message={message()} parts={parts()} sanitize={sanitizer()} />
<Message message={message()} parts={parts()} />
</div>
{/* Response */}
<div data-slot="session-turn-response-section">
@ -252,11 +251,10 @@ export function SessionTurn(
<Message
message={assistantMessage}
parts={parts().filter((p) => p?.id !== last()?.id)}
sanitize={sanitizer()}
/>
</Match>
<Match when={true}>
<Message message={assistantMessage} parts={parts()} sanitize={sanitizer()} />
<Message message={assistantMessage} parts={parts()} />
</Match>
</Switch>
)

View file

@ -1,28 +0,0 @@
import type { Part } from "@opencode-ai/sdk/v2/client"
export const sanitize = (text: string | undefined, remove?: RegExp) => (remove ? text?.replace(remove, "") : text) ?? ""
export const sanitizePart = (part: Part, remove: RegExp | undefined) => {
if (part.type === "text") {
part.text = sanitize(part.text, remove)
} else if (part.type === "reasoning") {
part.text = sanitize(part.text, remove)
} else if (part.type === "tool") {
if (part.state.status === "completed" || part.state.status === "error") {
for (const key in part.state.metadata) {
if (typeof part.state.metadata[key] === "string") {
part.state.metadata[key] = sanitize(part.state.metadata[key] as string, remove)
}
}
for (const key in part.state.input) {
if (typeof part.state.input[key] === "string") {
part.state.input[key] = sanitize(part.state.input[key] as string, remove)
}
}
if ("error" in part.state) {
part.state.error = sanitize(part.state.error as string, remove)
}
}
}
return part
}