Compare commits

..

1 Commits

Author SHA1 Message Date
Adam a564359e4e fix(stats): keep tablet chart tooltips above bars 2026-08-13 00:34:57 +00:00
5 changed files with 71 additions and 39 deletions
+14 -4
View File
@@ -1,6 +1,7 @@
import { $ } from "bun"
import { homedir } from "node:os"
import { join } from "node:path"
import { downloadCliToResources, windowsify } from "./utils"
import { buildCliToResources, downloadCliToResources, windowsify } from "./utils"
type ServerSource = { type: "build" } | { type: "download"; version: string }
type DevOptions = { server: ServerSource; electron: string[] }
@@ -37,9 +38,18 @@ function selectOptions(): DevOptions {
}
async function prepareServer(source: ServerSource) {
if (source.type === "download")
return downloadCliToResources(source.version, windowsify("resources/opencode-cli-dev"))
process.env.OPENCODE_DESKTOP_CLI_DEV = join(import.meta.dirname, "../../cli")
const destination = windowsify("resources/opencode-cli-dev")
if (source.type === "download") return downloadCliToResources(source.version, destination)
return buildCliToResources(destination, developmentStateHome())
}
function developmentStateHome() {
const appData = (() => {
if (process.platform === "darwin") return join(homedir(), "Library", "Application Support")
if (process.platform === "win32") return process.env.APPDATA ?? join(homedir(), "AppData", "Roaming")
return process.env.XDG_CONFIG_HOME ?? join(homedir(), ".config")
})()
return join(appData, "ai.opencode.desktop.dev")
}
async function startDesktop(args: string[]) {
+28
View File
@@ -86,6 +86,34 @@ export async function downloadCliToResources(version = CLI_VERSION, dest = windo
console.log(`Copied ${cli.package}@${version} to ${dest}`)
}
export async function buildCliToResources(dest = windowsify("resources/opencode-cli"), stateHome?: string) {
const directory = await mkdtemp(join(tmpdir(), "opencode-cli-"))
const target = `cli-${process.platform === "win32" ? "windows" : process.platform}-${process.arch}`
try {
await $`bun ${join(import.meta.dirname, "../../cli/script/build.ts")} --single --skip-install --skip-web-ui --outdir=${directory}`.env(
{
...process.env,
OPENCODE_VERSION: process.env.OPENCODE_VERSION,
},
)
if (stateHome && (await Bun.file(dest).exists())) {
const child = Bun.spawn([dest, "service", "stop"], {
env: { ...process.env, XDG_STATE_HOME: stateHome },
stdout: "inherit",
stderr: "inherit",
})
const exitCode = await child.exited
if (exitCode !== 0) throw new Error(`Failed to stop development service: ${exitCode}`)
}
await copyFile(join(directory, target, "bin", windowsify("opencode2")), dest)
} finally {
await rm(directory, { recursive: true, force: true })
}
await prepareCli(dest)
console.log(`Built local CLI at ${dest}`)
}
async function prepareCli(dest: string) {
if (process.platform !== "win32") await chmod(dest, 0o755)
if (process.platform === "win32" && process.env.GITHUB_ACTIONS === "true") {
+22 -34
View File
@@ -17,46 +17,34 @@ type Logger = {
export async function startBackgroundCli(logger: Logger) {
const isolated = !app.isPackaged && process.env.OPENCODE_DESKTOP_ISOLATED_SERVER === "1"
const development = !app.isPackaged && process.env.OPENCODE_DESKTOP_CLI_DEV
const cli = development
? {
version: "local",
command: ["bun", "run", "--cwd", development, "dev", "--"],
binary: undefined,
}
: await resolveBundledCli(isolated, logger)
if (isolated) process.env.XDG_STATE_HOME = app.getPath("userData")
const service = await Service.ensure({
file:
isolated && process.env.OPENCODE_DESKTOP_SERVER_CHANNEL === "local"
? join(app.getPath("userData"), "opencode", "service-local.json")
: undefined,
version: cli.version,
command: [...cli.command, "serve", "--service"],
onStart: (reason, previousVersion) => logger.log("v2 CLI background service starting", { reason, previousVersion }),
})
if (service.auth?.type !== "basic") throw new Error("V2 CLI background service did not provide authentication")
logger.log("v2 CLI background service ready", {
username: service.auth.username,
version: cli.version,
...endpoint(service.url),
})
if (isolated && cli.binary) await cleanCliStages(cli.binary, logger)
return {
url: service.url,
username: service.auth.username,
password: service.auth.password,
}
}
async function resolveBundledCli(isolated: boolean, logger: Logger) {
const bundled = app.isPackaged
? join(process.resourcesPath, executableName())
: join(root, "../../resources", isolated ? developmentExecutableName() : executableName())
logger.log("v2 CLI executable resolved", { bundled, packaged: app.isPackaged })
const version = parseVersion(await run(bundled, ["--version"], logger))
const binary = app.isPackaged || isolated ? await installCli(bundled, version, logger) : bundled
return { version, binary, command: [binary] }
if (isolated) process.env.XDG_STATE_HOME = app.getPath("userData")
const service = await Service.ensure({
file:
isolated && process.env.OPENCODE_DESKTOP_SERVER_CHANNEL === "local"
? join(app.getPath("userData"), "opencode", "service-local.json")
: undefined,
version,
command: [binary, "serve", "--service"],
onStart: (reason, previousVersion) => logger.log("v2 CLI background service starting", { reason, previousVersion }),
})
if (service.auth?.type !== "basic") throw new Error("V2 CLI background service did not provide authentication")
logger.log("v2 CLI background service ready", {
username: service.auth.username,
version,
...endpoint(service.url),
})
if (isolated) await cleanCliStages(binary, logger)
return {
url: service.url,
username: service.auth.username,
password: service.auth.password,
}
}
async function cleanCliStages(binary: string, logger: Logger) {
+6
View File
@@ -7771,6 +7771,12 @@ body {
}
}
@media (min-width: 48rem) and (max-width: 58rem) {
[data-page="stats"] [data-slot="top-models-bar"][data-active="true"] {
z-index: 2;
}
}
@media (max-width: 47.999rem) {
[data-page="stats"] [data-section="top-models"],
[data-page="stats"] [data-section="leaderboard"],
+1 -1
View File
@@ -2089,7 +2089,7 @@ function UserMessage(props: { message: SessionMessageUser }) {
function QueuedPromptDock(props: { prompts: { id: string; text: string }[]; onOpen: () => void }) {
const theme = useTheme("elevated")
const next = createMemo(() => props.prompts[0]?.text.replaceAll("\n", " "))
const next = createMemo(() => props.prompts[0]?.text)
return (
<box