diff options
| author | Jay V <[email protected]> | 2025-06-04 18:39:03 -0400 |
|---|---|---|
| committer | Jay V <[email protected]> | 2025-06-04 18:39:06 -0400 |
| commit | a74f27e59a5fcb20ecdf4add6b981b33ac9735cc (patch) | |
| tree | 90c44cb9974272f7d5c6241e782b754d7f55d5c4 /packages/web/src/components/Share.tsx | |
| parent | f76cdfff9b28b7632bcbcf2a58172ce2f5e6cec0 (diff) | |
| download | opencode-a74f27e59a5fcb20ecdf4add6b981b33ac9735cc.tar.gz opencode-a74f27e59a5fcb20ecdf4add6b981b33ac9735cc.zip | |
read tool share page
Diffstat (limited to 'packages/web/src/components/Share.tsx')
| -rw-r--r-- | packages/web/src/components/Share.tsx | 169 |
1 files changed, 167 insertions, 2 deletions
diff --git a/packages/web/src/components/Share.tsx b/packages/web/src/components/Share.tsx index d1874afb6..15bc7fdc2 100644 --- a/packages/web/src/components/Share.tsx +++ b/packages/web/src/components/Share.tsx @@ -21,7 +21,9 @@ import { IconCommandLine, IconChevronRight, IconPencilSquare, + IconRectangleStack, IconWrenchScrewdriver, + IconDocumentArrowDown, } from "./icons" import DiffView from "./DiffView" import CodeBlock from "./CodeBlock" @@ -158,10 +160,12 @@ function ProviderIcon(props: { provider: string; size?: number }) { } interface ResultsButtonProps extends JSX.HTMLAttributes<HTMLButtonElement> { + showCopy?: string + hideCopy?: string results: boolean } function ResultsButton(props: ResultsButtonProps) { - const [local, rest] = splitProps(props, ["results"]) + const [local, rest] = splitProps(props, ["results", "showCopy", "hideCopy"]) return ( <button type="button" @@ -169,7 +173,11 @@ function ResultsButton(props: ResultsButtonProps) { data-element-button-more {...rest} > - <span>{local.results ? "Hide results" : "Show results"}</span> + <span> + {local.results + ? local.hideCopy || "Hide results" + : local.showCopy || "Show results"} + </span> <span data-button-icon> <Show when={local.results} @@ -726,6 +734,163 @@ export default function Share(props: { api: string }) { </div> )} </Match> + {/* LS tool */} + <Match + when={ + msg.role === "assistant" && + part.type === "tool-invocation" && + part.toolInvocation.toolName === "opencode_list" && + part + } + > + {(part) => { + const metadata = createMemo(() => + msg.metadata?.tool[part().toolInvocation.toolCallId] + ) + const args = part().toolInvocation.args + const path = args.path + + const duration = createMemo(() => + DateTime.fromMillis(metadata()?.time.end || 0).diff( + DateTime.fromMillis(metadata()?.time.start || 0), + ).toMillis(), + ) + + return ( + <div data-section="part" data-part-type="tool-list"> + <div data-section="decoration"> + <div title="List files"> + <IconRectangleStack width={18} height={18} /> + </div> + <div></div> + </div> + <div data-section="content"> + <div data-part-tool-body> + <span data-part-title data-size="md"> + <span data-element-label>LS</span> + <b>{path}</b> + </span> + <Switch> + <Match + when={ + part().toolInvocation.state === + "result" && + part().toolInvocation.result + } + > + <div data-part-tool-result> + <ResultsButton + results={results()} + onClick={() => showResults((e) => !e)} + /> + <Show when={results()}> + <TextPart + expand + data-size="sm" + data-color="dimmed" + text={part().toolInvocation.result} + /> + </Show> + </div> + </Match> + </Switch> + </div> + <ToolFooter time={duration()} /> + </div> + </div> + ) + }} + </Match> + {/* Read tool */} + <Match + when={ + msg.role === "assistant" && + part.type === "tool-invocation" && + part.toolInvocation.toolName === "opencode_read" && + part + } + > + {(part) => { + const metadata = createMemo(() => msg.metadata?.tool[part().toolInvocation.toolCallId]) + const args = part().toolInvocation.args + const filePath = args.filePath + const hasError = metadata()?.error + const preview = metadata()?.preview + const result = part().toolInvocation.state === "result" && part().toolInvocation.result + + const duration = createMemo(() => + DateTime.fromMillis(metadata()?.time.end || 0).diff( + DateTime.fromMillis(metadata()?.time.start || 0), + ).toMillis(), + ) + + return ( + <div data-section="part" data-part-type="tool-read"> + <div data-section="decoration"> + <div title="Read file"> + <IconDocumentArrowDown width={18} height={18} /> + </div> + <div></div> + </div> + <div data-section="content"> + <div data-part-tool-body> + <span data-part-title data-size="md"> + <span data-element-label>Read</span> + <b>{filePath}</b> + </span> + <Switch> + <Match when={hasError}> + <div data-part-tool-result> + <TextPart + expand + text={result} + data-size="sm" + data-color="dimmed" + /> + </div> + </Match> + <Match when={preview}> + <div data-part-tool-result> + <ResultsButton + showCopy="Show preview" + hideCopy="Hide preview" + results={results()} + onClick={() => showResults((e) => !e)} + /> + <Show when={results()}> + <div data-part-tool-code> + <CodeBlock + lang={getFileType(filePath)} + code={preview} + /> + </div> + </Show> + </div> + </Match> + <Match when={result}> + <div data-part-tool-result> + <ResultsButton + results={results()} + onClick={() => showResults((e) => !e)} + /> + <Show when={results()}> + <TextPart + expand + text={result} + data-size="sm" + data-color="dimmed" + /> + </Show> + </div> + </Match> + </Switch> + </div> + <ToolFooter time={duration()} /> + </div> + </div> + ) + }} + </Match> {/* Edit tool */} <Match when={ |
