mirror of
https://github.com/Heretek-AI/opencode.git
synced 2026-11-10 02:11:36 -10:00
144 lines
5.2 KiB
TypeScript
144 lines
5.2 KiB
TypeScript
/// <reference types="vite/client" />
|
|
|
|
import { render } from "solid-js/web"
|
|
import { Show } from "solid-js"
|
|
import { createStore } from "solid-js/store"
|
|
import { ThemeProvider } from "@opencode/ui/theme"
|
|
import { CurrentSessionProviders } from "../../../../session-ui/src/storybook/current-session-story"
|
|
import { emptySessionDocument } from "../../../../session-ui/src/storybook/current-session-fixtures"
|
|
import { CurrentFileToolGroup, ToolDisplay } from "../../../../session-ui/src/tools/tool-renderer"
|
|
import { patchFileGroups } from "../../../../session-ui/src/components/apply-patch-file"
|
|
import type { SessionMessageAssistantTool } from "@opencode/client/promise"
|
|
import { createTwoFilesPatch, diffLines } from "diff"
|
|
import edit from "../../../../core/src/tool/plugin/edit.ts?raw"
|
|
import patch from "../../../../core/src/tool/plugin/patch.ts?raw"
|
|
import read from "../../../../core/src/tool/plugin/read.ts?raw"
|
|
import shell from "../../../../core/src/tool/plugin/shell.ts?raw"
|
|
import "../../../src/index.css"
|
|
|
|
const scenario = new URLSearchParams(location.search).get("scenario") ?? "complete"
|
|
const sources = [edit, patch, read, shell].map((text) => text.replaceAll("\r\n", "\n"))
|
|
const names = ["edit", "patch", "read", "shell"]
|
|
const changed = (text: string) => text.replaceAll(/\bcontext\b/g, "invocation")
|
|
const entry = (index: number, before: string, after: string) => ({
|
|
file: `src/tool/plugin/${names[index]}.ts`,
|
|
patch: createTwoFilesPatch(names[index], names[index], before, after, "", "", {
|
|
context: scenario === "partial" ? 3 : Infinity,
|
|
}),
|
|
...diffLines(before, after).reduce(
|
|
(counts, item) => ({
|
|
additions: counts.additions + (item.added ? item.count : 0),
|
|
deletions: counts.deletions + (item.removed ? item.count : 0),
|
|
}),
|
|
{ additions: 0, deletions: 0 },
|
|
),
|
|
status: "modified" as const,
|
|
})
|
|
const files =
|
|
scenario === "multi"
|
|
? sources.map((text, index) => entry(index, text, changed(text)))
|
|
: [
|
|
entry(0, sources[0], changed(sources[0])),
|
|
...(scenario === "chained"
|
|
? [entry(0, changed(sources[0]), changed(sources[0]).replaceAll(/\binput\b/g, "parameters"))]
|
|
: []),
|
|
]
|
|
const tools: SessionMessageAssistantTool[] = files.map((file, index) => ({
|
|
id: `fixture-edit-${index}`,
|
|
type: "tool",
|
|
name: "edit",
|
|
state: {
|
|
status: "completed",
|
|
input: { path: file.file, oldString: "context", newString: "invocation", replaceAll: true },
|
|
metadata: { files: [file] },
|
|
content: [{ type: "text", text: `Edited ${file.file}` }],
|
|
},
|
|
time: { created: 1, ran: 2, completed: 3 },
|
|
}))
|
|
|
|
declare global {
|
|
interface Window {
|
|
patchBenchmark: {
|
|
payloadBytes: number
|
|
sourceBytes: number
|
|
files: number
|
|
tools: number
|
|
grouping: (expanded: boolean) => { ms: number; groups: number; views: number }
|
|
}
|
|
}
|
|
}
|
|
window.patchBenchmark = {
|
|
payloadBytes: new TextEncoder().encode(JSON.stringify(tools)).length,
|
|
sourceBytes: new TextEncoder().encode(sources.slice(0, scenario === "multi" ? 4 : 1).join("")).length,
|
|
files: new Set(files.map((file) => file.file)).size,
|
|
tools: tools.length,
|
|
grouping(expanded) {
|
|
const start = performance.now()
|
|
const groups = patchFileGroups(files)
|
|
const views = expanded ? groups.reduce((count, file) => count + file.views.length, 0) : 0
|
|
return { ms: performance.now() - start, groups: groups.length, views }
|
|
},
|
|
}
|
|
|
|
function Fixture() {
|
|
const [state, setState] = createStore({ mounted: false, duration: 0, rendered: 0 })
|
|
let start = 0
|
|
return (
|
|
<ThemeProvider>
|
|
<section style={{ margin: "24px auto", "max-width": "960px" }}>
|
|
<button
|
|
onClick={() => {
|
|
start = performance.now()
|
|
setState("mounted", true)
|
|
document.querySelector("[data-component=apply-patch-tool]")!.getBoundingClientRect()
|
|
setState("duration", performance.now() - start)
|
|
}}
|
|
>
|
|
Mount tools
|
|
</button>
|
|
<button
|
|
onClick={() => {
|
|
setState({ mounted: false, rendered: 0 })
|
|
}}
|
|
>
|
|
Unmount tools
|
|
</button>
|
|
<output data-testid="mount-ms">{state.duration}</output>
|
|
<output data-testid="rendered">{state.rendered}</output>
|
|
<div
|
|
on:click={{
|
|
capture: true,
|
|
handleEvent() {
|
|
start = performance.now()
|
|
},
|
|
}}
|
|
>
|
|
<Show when={state.mounted}>
|
|
<CurrentSessionProviders document={emptySessionDocument}>
|
|
<Show
|
|
when={scenario === "direct"}
|
|
fallback={
|
|
<CurrentFileToolGroup
|
|
tools={tools}
|
|
onSizeChange={() => setState("rendered", performance.now() - start)}
|
|
/>
|
|
}
|
|
>
|
|
<ToolDisplay
|
|
id="fixture-patch"
|
|
tool="patch"
|
|
input={{}}
|
|
metadata={{ files }}
|
|
status="completed"
|
|
onContentRendered={() => setState("rendered", performance.now() - start)}
|
|
/>
|
|
</Show>
|
|
</CurrentSessionProviders>
|
|
</Show>
|
|
</div>
|
|
</section>
|
|
</ThemeProvider>
|
|
)
|
|
}
|
|
render(() => <Fixture />, document.getElementById("root")!)
|