mirror of
https://github.com/sst/opencode.git
synced 2025-08-30 17:57:25 +00:00
docs: share page add time footer back
This commit is contained in:
parent
9ca54020ac
commit
2f1acee5a1
4 changed files with 128 additions and 86 deletions
|
@ -364,7 +364,6 @@ export default function Share(props: {
|
||||||
<div data-section="part" data-part-type="summary">
|
<div data-section="part" data-part-type="summary">
|
||||||
<div data-section="decoration">
|
<div data-section="decoration">
|
||||||
<span data-status={connectionStatus()[0]}></span>
|
<span data-status={connectionStatus()[0]}></span>
|
||||||
<div></div>
|
|
||||||
</div>
|
</div>
|
||||||
<div data-section="content">
|
<div data-section="content">
|
||||||
<p data-section="copy">{getStatusText(connectionStatus())}</p>
|
<p data-section="copy">{getStatusText(connectionStatus())}</p>
|
||||||
|
|
|
@ -58,3 +58,20 @@ export function createOverflow() {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function formatDuration(ms: number): string {
|
||||||
|
const ONE_SECOND = 1000
|
||||||
|
const ONE_MINUTE = 60 * ONE_SECOND
|
||||||
|
|
||||||
|
if (ms >= ONE_MINUTE) {
|
||||||
|
const minutes = Math.floor(ms / ONE_MINUTE)
|
||||||
|
return minutes === 1 ? `1min` : `${minutes}mins`
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ms >= ONE_SECOND) {
|
||||||
|
const seconds = Math.floor(ms / ONE_SECOND)
|
||||||
|
return `${seconds}s`
|
||||||
|
}
|
||||||
|
|
||||||
|
return `${ms}ms`
|
||||||
|
}
|
||||||
|
|
|
@ -101,7 +101,12 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
[data-component="content"] {
|
[data-component="content"] {
|
||||||
|
flex: 1 1 auto;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
|
padding: 0 0 0.375rem;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
[data-component="spacer"] {
|
[data-component="spacer"] {
|
||||||
|
@ -209,7 +214,6 @@
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
gap: 0.375rem;
|
gap: 0.375rem;
|
||||||
padding-bottom: 1rem;
|
|
||||||
|
|
||||||
&[data-tool="bash"] {
|
&[data-tool="bash"] {
|
||||||
max-width: var(--sm-tool-width);
|
max-width: var(--sm-tool-width);
|
||||||
|
|
|
@ -20,6 +20,7 @@ import {
|
||||||
IconDocumentMagnifyingGlass,
|
IconDocumentMagnifyingGlass,
|
||||||
} from "../icons"
|
} from "../icons"
|
||||||
import { IconMeta, IconOpenAI, IconGemini, IconAnthropic } from "../icons/custom"
|
import { IconMeta, IconOpenAI, IconGemini, IconAnthropic } from "../icons/custom"
|
||||||
|
import { formatDuration } from "../share/common"
|
||||||
import { ContentCode } from "./content-code"
|
import { ContentCode } from "./content-code"
|
||||||
import { ContentDiff } from "./content-diff"
|
import { ContentDiff } from "./content-diff"
|
||||||
import { ContentText } from "./content-text"
|
import { ContentText } from "./content-text"
|
||||||
|
@ -31,6 +32,8 @@ import type { Diagnostic } from "vscode-languageserver-types"
|
||||||
|
|
||||||
import styles from "./part.module.css"
|
import styles from "./part.module.css"
|
||||||
|
|
||||||
|
const MIN_DURATION = 2
|
||||||
|
|
||||||
export interface PartProps {
|
export interface PartProps {
|
||||||
index: number
|
index: number
|
||||||
message: MessageV2.Info
|
message: MessageV2.Info
|
||||||
|
@ -161,95 +164,104 @@ export function Part(props: PartProps) {
|
||||||
{props.part.type === "tool" && props.part.state.status === "error" && (
|
{props.part.type === "tool" && props.part.state.status === "error" && (
|
||||||
<div data-component="tool" data-tool="error">
|
<div data-component="tool" data-tool="error">
|
||||||
<ContentError>{formatErrorString(props.part.state.error)}</ContentError>
|
<ContentError>{formatErrorString(props.part.state.error)}</ContentError>
|
||||||
|
<Spacer />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{props.part.type === "tool" &&
|
{props.part.type === "tool" &&
|
||||||
props.part.state.status === "completed" &&
|
props.part.state.status === "completed" &&
|
||||||
props.message.role === "assistant" && (
|
props.message.role === "assistant" && (
|
||||||
<div data-component="tool" data-tool={props.part.tool}>
|
<>
|
||||||
<Switch>
|
<div data-component="tool" data-tool={props.part.tool}>
|
||||||
<Match when={props.part.tool === "grep"}>
|
<Switch>
|
||||||
<GrepTool
|
<Match when={props.part.tool === "grep"}>
|
||||||
message={props.message}
|
<GrepTool
|
||||||
id={props.part.id}
|
message={props.message}
|
||||||
tool={props.part.tool}
|
id={props.part.id}
|
||||||
state={props.part.state}
|
tool={props.part.tool}
|
||||||
/>
|
state={props.part.state}
|
||||||
</Match>
|
/>
|
||||||
<Match when={props.part.tool === "glob"}>
|
</Match>
|
||||||
<GlobTool
|
<Match when={props.part.tool === "glob"}>
|
||||||
message={props.message}
|
<GlobTool
|
||||||
id={props.part.id}
|
message={props.message}
|
||||||
tool={props.part.tool}
|
id={props.part.id}
|
||||||
state={props.part.state}
|
tool={props.part.tool}
|
||||||
/>
|
state={props.part.state}
|
||||||
</Match>
|
/>
|
||||||
<Match when={props.part.tool === "list"}>
|
</Match>
|
||||||
<ListTool
|
<Match when={props.part.tool === "list"}>
|
||||||
message={props.message}
|
<ListTool
|
||||||
id={props.part.id}
|
message={props.message}
|
||||||
tool={props.part.tool}
|
id={props.part.id}
|
||||||
state={props.part.state}
|
tool={props.part.tool}
|
||||||
/>
|
state={props.part.state}
|
||||||
</Match>
|
/>
|
||||||
<Match when={props.part.tool === "read"}>
|
</Match>
|
||||||
<ReadTool
|
<Match when={props.part.tool === "read"}>
|
||||||
message={props.message}
|
<ReadTool
|
||||||
id={props.part.id}
|
message={props.message}
|
||||||
tool={props.part.tool}
|
id={props.part.id}
|
||||||
state={props.part.state}
|
tool={props.part.tool}
|
||||||
/>
|
state={props.part.state}
|
||||||
</Match>
|
/>
|
||||||
<Match when={props.part.tool === "write"}>
|
</Match>
|
||||||
<WriteTool
|
<Match when={props.part.tool === "write"}>
|
||||||
message={props.message}
|
<WriteTool
|
||||||
id={props.part.id}
|
message={props.message}
|
||||||
tool={props.part.tool}
|
id={props.part.id}
|
||||||
state={props.part.state}
|
tool={props.part.tool}
|
||||||
/>
|
state={props.part.state}
|
||||||
</Match>
|
/>
|
||||||
<Match when={props.part.tool === "edit"}>
|
</Match>
|
||||||
<EditTool
|
<Match when={props.part.tool === "edit"}>
|
||||||
message={props.message}
|
<EditTool
|
||||||
id={props.part.id}
|
message={props.message}
|
||||||
tool={props.part.tool}
|
id={props.part.id}
|
||||||
state={props.part.state}
|
tool={props.part.tool}
|
||||||
/>
|
state={props.part.state}
|
||||||
</Match>
|
/>
|
||||||
<Match when={props.part.tool === "bash"}>
|
</Match>
|
||||||
<BashTool
|
<Match when={props.part.tool === "bash"}>
|
||||||
id={props.part.id}
|
<BashTool
|
||||||
tool={props.part.tool}
|
id={props.part.id}
|
||||||
state={props.part.state}
|
tool={props.part.tool}
|
||||||
message={props.message}
|
state={props.part.state}
|
||||||
/>
|
message={props.message}
|
||||||
</Match>
|
/>
|
||||||
<Match when={props.part.tool === "todowrite"}>
|
</Match>
|
||||||
<TodoWriteTool
|
<Match when={props.part.tool === "todowrite"}>
|
||||||
message={props.message}
|
<TodoWriteTool
|
||||||
id={props.part.id}
|
message={props.message}
|
||||||
tool={props.part.tool}
|
id={props.part.id}
|
||||||
state={props.part.state}
|
tool={props.part.tool}
|
||||||
/>
|
state={props.part.state}
|
||||||
</Match>
|
/>
|
||||||
<Match when={props.part.tool === "webfetch"}>
|
</Match>
|
||||||
<WebFetchTool
|
<Match when={props.part.tool === "webfetch"}>
|
||||||
message={props.message}
|
<WebFetchTool
|
||||||
id={props.part.id}
|
message={props.message}
|
||||||
tool={props.part.tool}
|
id={props.part.id}
|
||||||
state={props.part.state}
|
tool={props.part.tool}
|
||||||
/>
|
state={props.part.state}
|
||||||
</Match>
|
/>
|
||||||
<Match when={true}>
|
</Match>
|
||||||
<FallbackTool
|
<Match when={true}>
|
||||||
message={props.message}
|
<FallbackTool
|
||||||
id={props.part.id}
|
message={props.message}
|
||||||
tool={props.part.tool}
|
id={props.part.id}
|
||||||
state={props.part.state}
|
tool={props.part.tool}
|
||||||
/>
|
state={props.part.state}
|
||||||
</Match>
|
/>
|
||||||
</Switch>
|
</Match>
|
||||||
</div>
|
</Switch>
|
||||||
|
</div>
|
||||||
|
<ToolFooter
|
||||||
|
time={
|
||||||
|
DateTime.fromMillis(props.message.time.completed || 0)
|
||||||
|
.diff(DateTime.fromMillis(props.message.time.created || 0))
|
||||||
|
.toMillis()
|
||||||
|
} />
|
||||||
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -623,6 +635,16 @@ function Footer(props: ParentProps<{ title: string }>) {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function ToolFooter(props: { time: number }) {
|
||||||
|
return props.time > MIN_DURATION ? (
|
||||||
|
<Footer title={`${props.time}ms`}>
|
||||||
|
{formatDuration(props.time)}
|
||||||
|
</Footer>
|
||||||
|
) : (
|
||||||
|
<Spacer />
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
export function FallbackTool(props: ToolProps) {
|
export function FallbackTool(props: ToolProps) {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue