mirror of
https://github.com/anomalyco/opencode.git
synced 2026-07-10 04:48:32 +00:00
fix(simulation): stabilize screenshot artifacts (#35933)
This commit is contained in:
parent
b3cf749a7f
commit
e1d72fa338
6 changed files with 37 additions and 14 deletions
3
bun.lock
3
bun.lock
|
|
@ -873,6 +873,7 @@
|
|||
"name": "@opencode-ai/simulation",
|
||||
"version": "1.17.13",
|
||||
"dependencies": {
|
||||
"@fontsource/adwaita-mono": "5.2.1",
|
||||
"@napi-rs/canvas": "1.0.2",
|
||||
"@opencode-ai/core": "workspace:*",
|
||||
"@opencode-ai/llm": "workspace:*",
|
||||
|
|
@ -1724,6 +1725,8 @@
|
|||
|
||||
"@floating-ui/utils": ["@floating-ui/utils@0.2.11", "", {}, "sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg=="],
|
||||
|
||||
"@fontsource/adwaita-mono": ["@fontsource/adwaita-mono@5.2.1", "", {}, "sha512-6+Q1UIvklJ9REijs6kv7YlRNt6yktRj0iW8H69YIugdD9P2h3eIX1AB8/9ICMfpVyVeywlsrCXg82y/LfRrjyg=="],
|
||||
|
||||
"@fontsource/ibm-plex-mono": ["@fontsource/ibm-plex-mono@5.2.5", "", {}, "sha512-G09N3GfuT9qj3Ax2FDZvKqZttzM3v+cco2l8uXamhKyXLdmlaUDH5o88/C3vtTHj2oT7yRKsvxz9F+BXbWKMYA=="],
|
||||
|
||||
"@fontsource/inter": ["@fontsource/inter@5.2.8", "", {}, "sha512-P6r5WnJoKiNVV+zvW2xM13gNdFhAEpQ9dQJHt3naLvfg+LkF2ldgSLiF4T41lf1SQCM9QmkqPTn4TH568IRagg=="],
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
"typecheck": "tsgo --noEmit"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fontsource/adwaita-mono": "5.2.1",
|
||||
"@napi-rs/canvas": "1.0.2",
|
||||
"@opencode-ai/core": "workspace:*",
|
||||
"@opencode-ai/llm": "workspace:*",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { mkdir, mkdtemp } from "node:fs/promises"
|
||||
import { mkdir } from "node:fs/promises"
|
||||
import { tmpdir } from "node:os"
|
||||
import { dirname, join } from "node:path"
|
||||
import { extname, join, resolve } from "node:path"
|
||||
import type { CliRenderer, Renderable } from "@opentui/core"
|
||||
import { createMockKeys, createMockMouse, type MockInput, type MockMouse } from "@opentui/core/testing"
|
||||
import type { SimulationProtocol } from "../protocol"
|
||||
|
|
@ -104,11 +104,23 @@ export function state(harness: Harness) {
|
|||
}
|
||||
}
|
||||
|
||||
export async function screenshot(harness: Harness, output?: string) {
|
||||
export async function screenshot(harness: Harness, name?: string) {
|
||||
await harness.renderOnce()
|
||||
const image = SimulationPng.screenshot(harness.renderer)
|
||||
const path = output ?? join(await mkdtemp(join(tmpdir(), "opencode-drive-")), "screenshot.png")
|
||||
if (output) await mkdir(dirname(output), { recursive: true })
|
||||
const filename = name ?? `screenshot-${crypto.randomUUID()}`
|
||||
if (
|
||||
!filename ||
|
||||
filename.includes("/") ||
|
||||
filename.includes("\\") ||
|
||||
extname(filename)
|
||||
)
|
||||
throw new Error("screenshot name must not contain a path or extension")
|
||||
const directory = resolve(
|
||||
process.env.OPENCODE_DRIVE_MEDIA_DIR ??
|
||||
join(tmpdir(), "opencode-drive", "output"),
|
||||
)
|
||||
await mkdir(directory, { recursive: true })
|
||||
const path = join(directory, `${filename}.png`)
|
||||
await Bun.write(path, image.data)
|
||||
return path
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,12 +5,19 @@ import { TextAttributes, type CapturedFrame, type CliRenderer, type RGBA } from
|
|||
const CellWidth = 10
|
||||
const CellHeight = 20
|
||||
const FontSize = 16
|
||||
const FontFamily = "OpenCode Screenshot"
|
||||
const FontFamily = "OpenCode Mono"
|
||||
|
||||
GlobalFonts.registerFromPath(
|
||||
fileURLToPath(new URL("../../../ui/src/assets/fonts/JetBrainsMonoNerdFontMono-Regular.woff2", import.meta.url)),
|
||||
FontFamily,
|
||||
)
|
||||
for (const file of [
|
||||
"adwaita-mono-latin-400-normal.woff2",
|
||||
"adwaita-mono-latin-700-normal.woff2",
|
||||
"adwaita-mono-latin-400-italic.woff2",
|
||||
"adwaita-mono-latin-700-italic.woff2",
|
||||
]) {
|
||||
GlobalFonts.registerFromPath(
|
||||
fileURLToPath(import.meta.resolve(`@fontsource/adwaita-mono/files/${file}`)),
|
||||
FontFamily,
|
||||
)
|
||||
}
|
||||
|
||||
export function screenshot(renderer: CliRenderer) {
|
||||
return screenshotFrame({
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ async function handle(
|
|||
) {
|
||||
switch (request.method) {
|
||||
case "ui.screenshot":
|
||||
return SimulationActions.screenshot(harness, request.params?.path)
|
||||
return SimulationActions.screenshot(harness, request.params?.name)
|
||||
case "ui.state": {
|
||||
return SimulationActions.state(harness)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -97,8 +97,8 @@ export namespace Frontend {
|
|||
export const RecordingFinish = Schema.String
|
||||
export type RecordingFinish = Schema.Schema.Type<typeof RecordingFinish>
|
||||
|
||||
export const ArtifactParams = Schema.Struct({ path: Schema.optional(Schema.String) })
|
||||
export interface ArtifactParams extends Schema.Schema.Type<typeof ArtifactParams> {}
|
||||
export const ScreenshotParams = Schema.Struct({ name: Schema.optional(Schema.String) })
|
||||
export interface ScreenshotParams extends Schema.Schema.Type<typeof ScreenshotParams> {}
|
||||
|
||||
export const TypeParams = Schema.Struct({ text: Schema.String })
|
||||
export interface TypeParams extends Schema.Schema.Type<typeof TypeParams> {}
|
||||
|
|
@ -124,7 +124,7 @@ export namespace Frontend {
|
|||
Schema.Struct({
|
||||
...JsonRpc.RequestFields,
|
||||
method: Schema.Literal("ui.screenshot"),
|
||||
params: Schema.optional(ArtifactParams),
|
||||
params: Schema.optional(ScreenshotParams),
|
||||
}),
|
||||
Schema.Struct({
|
||||
...JsonRpc.RequestFields,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue