|
|
@@ -11,7 +11,7 @@ import { useDiffComponent } from "../context/diff"
|
|
|
import { getDirectory, getFilename } from "@opencode-ai/util/path"
|
|
|
|
|
|
import { Binary } from "@opencode-ai/util/binary"
|
|
|
-import { createEffect, createMemo, For, Match, on, onCleanup, ParentProps, Show, Switch } from "solid-js"
|
|
|
+import { createEffect, createMemo, createSignal, For, Match, on, onCleanup, ParentProps, Show, Switch } from "solid-js"
|
|
|
import { createResizeObserver } from "@solid-primitives/resize-observer"
|
|
|
import { DiffChanges } from "./diff-changes"
|
|
|
import { Typewriter } from "./typewriter"
|
|
|
@@ -21,6 +21,8 @@ import { Accordion } from "./accordion"
|
|
|
import { StickyAccordionHeader } from "./sticky-accordion-header"
|
|
|
import { FileIcon } from "./file-icon"
|
|
|
import { Icon } from "./icon"
|
|
|
+import { IconButton } from "./icon-button"
|
|
|
+import { Tooltip } from "./tooltip"
|
|
|
import { Card } from "./card"
|
|
|
import { Dynamic } from "solid-js/web"
|
|
|
import { Button } from "./button"
|
|
|
@@ -328,6 +330,15 @@ export function SessionTurn(
|
|
|
const hasDiffs = createMemo(() => message()?.summary?.diffs?.length)
|
|
|
const hideResponsePart = createMemo(() => !working() && !!responsePartId())
|
|
|
|
|
|
+ const [responseCopied, setResponseCopied] = createSignal(false)
|
|
|
+ const handleCopyResponse = async () => {
|
|
|
+ const content = response()
|
|
|
+ if (!content) return
|
|
|
+ await navigator.clipboard.writeText(content)
|
|
|
+ setResponseCopied(true)
|
|
|
+ setTimeout(() => setResponseCopied(false), 2000)
|
|
|
+ }
|
|
|
+
|
|
|
function duration() {
|
|
|
const msg = message()
|
|
|
if (!msg) return ""
|
|
|
@@ -556,6 +567,15 @@ export function SessionTurn(
|
|
|
{/* Response */}
|
|
|
<Show when={!working() && (response() || hasDiffs())}>
|
|
|
<div data-slot="session-turn-summary-section">
|
|
|
+ <div data-slot="session-turn-summary-copy">
|
|
|
+ <Tooltip value={responseCopied() ? "Copied!" : "Copy"} placement="top" gutter={8}>
|
|
|
+ <IconButton
|
|
|
+ icon={responseCopied() ? "check" : "copy"}
|
|
|
+ variant="secondary"
|
|
|
+ onClick={handleCopyResponse}
|
|
|
+ />
|
|
|
+ </Tooltip>
|
|
|
+ </div>
|
|
|
<div data-slot="session-turn-summary-header">
|
|
|
<h2 data-slot="session-turn-summary-title">Response</h2>
|
|
|
<Markdown
|