mirror of
https://gitee.com/zhangsken/opencode.git
synced 2026-10-26 10:24:42 +08:00
Compare commits
4 Commits
mismatch-error
...
v2.0.9
| Author | SHA1 | Date | |
|---|---|---|---|
| 6608799d35 | |||
| e50d845451 | |||
| 56816621f8 | |||
| 7125f5f8b5 |
@@ -32,7 +32,7 @@
|
||||
},
|
||||
"packages/ai": {
|
||||
"name": "@opencode/ai",
|
||||
"version": "2.0.8",
|
||||
"version": "2.0.9",
|
||||
"dependencies": {
|
||||
"@aws-sdk/credential-providers": "3.1057.0",
|
||||
"@opencode/schema": "workspace:*",
|
||||
@@ -54,7 +54,7 @@
|
||||
},
|
||||
"packages/app": {
|
||||
"name": "@opencode/app",
|
||||
"version": "2.0.8",
|
||||
"version": "2.0.9",
|
||||
"dependencies": {
|
||||
"@corvu/drawer": "catalog:",
|
||||
"@dnd-kit/abstract": "0.5.0",
|
||||
@@ -111,7 +111,7 @@
|
||||
},
|
||||
"packages/cli": {
|
||||
"name": "@opencode/cli",
|
||||
"version": "2.0.8",
|
||||
"version": "2.0.9",
|
||||
"bin": {
|
||||
"opencode2": "./bin/opencode2.cjs",
|
||||
},
|
||||
@@ -175,7 +175,7 @@
|
||||
},
|
||||
"packages/client": {
|
||||
"name": "@opencode/client",
|
||||
"version": "2.0.8",
|
||||
"version": "2.0.9",
|
||||
"dependencies": {
|
||||
"@opencode/protocol": "workspace:*",
|
||||
"@opencode/schema": "workspace:*",
|
||||
@@ -201,7 +201,7 @@
|
||||
},
|
||||
"packages/codemode": {
|
||||
"name": "@opencode/codemode",
|
||||
"version": "2.0.8",
|
||||
"version": "2.0.9",
|
||||
"dependencies": {
|
||||
"acorn": "8.15.0",
|
||||
"effect": "catalog:",
|
||||
@@ -214,7 +214,7 @@
|
||||
},
|
||||
"packages/console/app": {
|
||||
"name": "@opencode/console-app",
|
||||
"version": "2.0.8",
|
||||
"version": "2.0.9",
|
||||
"dependencies": {
|
||||
"@cloudflare/vite-plugin": "1.15.2",
|
||||
"@ibm/plex": "6.4.1",
|
||||
@@ -250,7 +250,7 @@
|
||||
},
|
||||
"packages/console/core": {
|
||||
"name": "@opencode/console-core",
|
||||
"version": "2.0.8",
|
||||
"version": "2.0.9",
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-sts": "3.782.0",
|
||||
"@jsx-email/render": "1.1.1",
|
||||
@@ -277,7 +277,7 @@
|
||||
},
|
||||
"packages/console/function": {
|
||||
"name": "@opencode/console-function",
|
||||
"version": "2.0.8",
|
||||
"version": "2.0.9",
|
||||
"dependencies": {
|
||||
"@openauthjs/openauth": "0.0.0-20250322224806",
|
||||
"@opencode/console-core": "workspace:*",
|
||||
@@ -294,7 +294,7 @@
|
||||
},
|
||||
"packages/console/mail": {
|
||||
"name": "@opencode/console-mail",
|
||||
"version": "2.0.8",
|
||||
"version": "2.0.9",
|
||||
"dependencies": {
|
||||
"@jsx-email/all": "2.2.3",
|
||||
"@jsx-email/cli": "1.4.3",
|
||||
@@ -318,7 +318,7 @@
|
||||
},
|
||||
"packages/console/support": {
|
||||
"name": "@opencode/console-support",
|
||||
"version": "2.0.8",
|
||||
"version": "2.0.9",
|
||||
"dependencies": {
|
||||
"@cloudflare/vite-plugin": "1.15.2",
|
||||
"@opencode/console-core": "workspace:*",
|
||||
@@ -338,7 +338,7 @@
|
||||
},
|
||||
"packages/core": {
|
||||
"name": "@opencode/core",
|
||||
"version": "2.0.8",
|
||||
"version": "2.0.9",
|
||||
"dependencies": {
|
||||
"@ai-sdk/cohere": "3.0.27",
|
||||
"@ai-sdk/gateway": "3.0.104",
|
||||
@@ -406,7 +406,7 @@
|
||||
},
|
||||
"packages/desktop": {
|
||||
"name": "@opencode/desktop",
|
||||
"version": "2.0.8",
|
||||
"version": "2.0.9",
|
||||
"dependencies": {
|
||||
"@zip.js/zip.js": "2.7.62",
|
||||
"electron-context-menu": "4.1.2",
|
||||
@@ -455,7 +455,7 @@
|
||||
},
|
||||
"packages/enterprise": {
|
||||
"name": "@opencode/enterprise",
|
||||
"version": "2.0.8",
|
||||
"version": "2.0.9",
|
||||
"dependencies": {
|
||||
"@hono/standard-validator": "catalog:",
|
||||
"@opencode-ai/sdk": "1.18.21",
|
||||
@@ -492,7 +492,7 @@
|
||||
},
|
||||
"packages/function": {
|
||||
"name": "@opencode/function",
|
||||
"version": "2.0.8",
|
||||
"version": "2.0.9",
|
||||
"dependencies": {
|
||||
"@octokit/auth-app": "8.0.1",
|
||||
"@octokit/rest": "catalog:",
|
||||
@@ -508,7 +508,7 @@
|
||||
},
|
||||
"packages/http-recorder": {
|
||||
"name": "@opencode/http-recorder",
|
||||
"version": "2.0.8",
|
||||
"version": "2.0.9",
|
||||
"dependencies": {
|
||||
"@effect/platform-node-shared": "4.0.0-rc.112",
|
||||
},
|
||||
@@ -527,7 +527,7 @@
|
||||
},
|
||||
"packages/httpapi-codegen": {
|
||||
"name": "@opencode/httpapi-codegen",
|
||||
"version": "2.0.8",
|
||||
"version": "2.0.9",
|
||||
"dependencies": {
|
||||
"effect": "catalog:",
|
||||
"prettier": "3.6.2",
|
||||
@@ -540,7 +540,7 @@
|
||||
},
|
||||
"packages/latex": {
|
||||
"name": "@opencode/latex",
|
||||
"version": "2.0.8",
|
||||
"version": "2.0.9",
|
||||
"dependencies": {
|
||||
"@opencode/plugin": "workspace:*",
|
||||
"@opentui/core": "catalog:",
|
||||
@@ -554,7 +554,7 @@
|
||||
},
|
||||
"packages/merman": {
|
||||
"name": "@opencode/merman",
|
||||
"version": "2.0.8",
|
||||
"version": "2.0.9",
|
||||
"dependencies": {
|
||||
"@opencode/plugin": "workspace:*",
|
||||
"@opentui/core": "catalog:",
|
||||
@@ -569,7 +569,7 @@
|
||||
},
|
||||
"packages/plugin": {
|
||||
"name": "@opencode/plugin",
|
||||
"version": "2.0.8",
|
||||
"version": "2.0.9",
|
||||
"dependencies": {
|
||||
"@ai-sdk/provider": "3.0.8",
|
||||
"@opencode/ai": "workspace:*",
|
||||
@@ -608,7 +608,7 @@
|
||||
},
|
||||
"packages/plugin-browser": {
|
||||
"name": "@opencode/plugin-browser",
|
||||
"version": "2.0.8",
|
||||
"version": "2.0.9",
|
||||
"dependencies": {
|
||||
"@opencode/plugin": "workspace:*",
|
||||
"@opencode/schema": "workspace:*",
|
||||
@@ -638,7 +638,7 @@
|
||||
},
|
||||
"packages/protocol": {
|
||||
"name": "@opencode/protocol",
|
||||
"version": "2.0.8",
|
||||
"version": "2.0.9",
|
||||
"dependencies": {
|
||||
"@opencode/schema": "workspace:*",
|
||||
"effect": "catalog:",
|
||||
@@ -653,7 +653,7 @@
|
||||
},
|
||||
"packages/schema": {
|
||||
"name": "@opencode/schema",
|
||||
"version": "2.0.8",
|
||||
"version": "2.0.9",
|
||||
"dependencies": {
|
||||
"@standard-schema/spec": "catalog:",
|
||||
"effect": "catalog:",
|
||||
@@ -677,7 +677,7 @@
|
||||
},
|
||||
"packages/sdk": {
|
||||
"name": "@opencode/sdk",
|
||||
"version": "2.0.8",
|
||||
"version": "2.0.9",
|
||||
"dependencies": {
|
||||
"@opencode/client": "workspace:*",
|
||||
"@opencode/core": "workspace:*",
|
||||
@@ -698,7 +698,7 @@
|
||||
},
|
||||
"packages/server": {
|
||||
"name": "@opencode/server",
|
||||
"version": "2.0.8",
|
||||
"version": "2.0.9",
|
||||
"dependencies": {
|
||||
"@effect/platform-node": "catalog:",
|
||||
"@effect/platform-node-shared": "catalog:",
|
||||
@@ -720,7 +720,7 @@
|
||||
},
|
||||
"packages/session-ui": {
|
||||
"name": "@opencode/session-ui",
|
||||
"version": "2.0.8",
|
||||
"version": "2.0.9",
|
||||
"dependencies": {
|
||||
"@kobalte/core": "catalog:",
|
||||
"@opencode/client": "workspace:*",
|
||||
@@ -755,7 +755,7 @@
|
||||
},
|
||||
"packages/simulation": {
|
||||
"name": "@opencode/simulation",
|
||||
"version": "2.0.8",
|
||||
"version": "2.0.9",
|
||||
"dependencies": {
|
||||
"@opencode/ai": "workspace:*",
|
||||
"@opencode/core": "workspace:*",
|
||||
@@ -775,7 +775,7 @@
|
||||
},
|
||||
"packages/stats/app": {
|
||||
"name": "@opencode/stats-app",
|
||||
"version": "2.0.8",
|
||||
"version": "2.0.9",
|
||||
"dependencies": {
|
||||
"@ibm/plex": "6.4.1",
|
||||
"@kobalte/core": "catalog:",
|
||||
@@ -809,7 +809,7 @@
|
||||
},
|
||||
"packages/stats/core": {
|
||||
"name": "@opencode/stats-core",
|
||||
"version": "2.0.8",
|
||||
"version": "2.0.9",
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-athena": "3.933.0",
|
||||
"@planetscale/database": "1.19.0",
|
||||
@@ -828,7 +828,7 @@
|
||||
},
|
||||
"packages/stats/server": {
|
||||
"name": "@opencode/stats-server",
|
||||
"version": "2.0.8",
|
||||
"version": "2.0.9",
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-firehose": "3.933.0",
|
||||
"@effect/platform-node": "catalog:",
|
||||
@@ -874,7 +874,7 @@
|
||||
},
|
||||
"packages/theme": {
|
||||
"name": "@opencode/theme",
|
||||
"version": "2.0.8",
|
||||
"version": "2.0.9",
|
||||
"dependencies": {
|
||||
"@opentui/core": "catalog:",
|
||||
"effect": "catalog:",
|
||||
@@ -888,7 +888,7 @@
|
||||
},
|
||||
"packages/tui": {
|
||||
"name": "@opencode/tui",
|
||||
"version": "2.0.8",
|
||||
"version": "2.0.9",
|
||||
"dependencies": {
|
||||
"@opencode/client": "workspace:*",
|
||||
"@opencode/core": "workspace:*",
|
||||
@@ -923,7 +923,7 @@
|
||||
},
|
||||
"packages/ui": {
|
||||
"name": "@opencode/ui",
|
||||
"version": "2.0.8",
|
||||
"version": "2.0.9",
|
||||
"dependencies": {
|
||||
"@kobalte/core": "catalog:",
|
||||
"@pierre/diffs": "catalog:",
|
||||
@@ -958,7 +958,7 @@
|
||||
},
|
||||
"packages/util": {
|
||||
"name": "@opencode/util",
|
||||
"version": "2.0.8",
|
||||
"version": "2.0.9",
|
||||
"dependencies": {
|
||||
"@effect/opentelemetry": "catalog:",
|
||||
"@effect/platform-node": "catalog:",
|
||||
@@ -991,7 +991,7 @@
|
||||
},
|
||||
"packages/web": {
|
||||
"name": "@opencode/web",
|
||||
"version": "2.0.8",
|
||||
"version": "2.0.9",
|
||||
"dependencies": {
|
||||
"@astrojs/cloudflare": "12.6.3",
|
||||
"@astrojs/markdown-remark": "6.3.1",
|
||||
@@ -1032,7 +1032,7 @@
|
||||
},
|
||||
"services/update": {
|
||||
"name": "@opencode/update",
|
||||
"version": "2.0.8",
|
||||
"version": "2.0.9",
|
||||
"dependencies": {
|
||||
"jose": "6.0.11",
|
||||
"semver": "catalog:",
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"name": "opencode",
|
||||
"description": "AI-powered development tool",
|
||||
"version": "2.0.8",
|
||||
"version": "2.0.9",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"packageManager": "bun@1.4.2",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"version": "2.0.8",
|
||||
"version": "2.0.9",
|
||||
"name": "@opencode/ai",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opencode/app",
|
||||
"version": "2.0.8",
|
||||
"version": "2.0.9",
|
||||
"description": "",
|
||||
"type": "module",
|
||||
"exports": {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"name": "@opencode/cli",
|
||||
"version": "2.0.8",
|
||||
"version": "2.0.9",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"name": "@opencode/client",
|
||||
"version": "2.0.8",
|
||||
"version": "2.0.9",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"name": "@opencode/codemode",
|
||||
"version": "2.0.8",
|
||||
"version": "2.0.9",
|
||||
"description": "Effect-native confined code execution over schema-described tools",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opencode/console-app",
|
||||
"version": "2.0.8",
|
||||
"version": "2.0.9",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"name": "@opencode/console-core",
|
||||
"version": "2.0.8",
|
||||
"version": "2.0.9",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opencode/console-function",
|
||||
"version": "2.0.8",
|
||||
"version": "2.0.9",
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opencode/console-mail",
|
||||
"version": "2.0.8",
|
||||
"version": "2.0.9",
|
||||
"dependencies": {
|
||||
"@jsx-email/all": "2.2.3",
|
||||
"@jsx-email/cli": "1.4.3",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opencode/console-support",
|
||||
"version": "2.0.8",
|
||||
"version": "2.0.9",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"version": "2.0.8",
|
||||
"version": "2.0.9",
|
||||
"name": "@opencode/core",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@opencode/desktop",
|
||||
"private": true,
|
||||
"version": "2.0.8",
|
||||
"version": "2.0.9",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"homepage": "https://opencode.ai",
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
//
|
||||
// bun run bench:startup -- [--exe <path>] [--compare <path>] [--runs 5] [--warmup 1] [--service warm|cold]
|
||||
// [--fresh] [--offline] [--seed <userData dir>] [--profile-main] [--profile-renderer]
|
||||
// [--trace] [--out <dir>] [--home <dir>]
|
||||
// [--trace] [--out <dir>] [--home <dir>] [--window-at x,y]
|
||||
//
|
||||
// The app runs in an isolated home directory (its own %APPDATA%, XDG dirs, OpenCode DB, config and
|
||||
// service registration) with the developer's OPENCODE_* / OTEL_* environment stripped, so it never
|
||||
@@ -21,7 +21,15 @@
|
||||
// main-process CPU profile from the first statement (via --inspect-brk) on the first run,
|
||||
// `--profile-renderer` records the renderer main thread from the moment its debug target appears,
|
||||
// and `--trace` records Chromium's startup trace on the last run. Raw samples are written as JSON.
|
||||
import { spawn } from "node:child_process"
|
||||
//
|
||||
// What is on screen is sampled from the screen itself (Windows): a helper pins the window topmost
|
||||
// without activating it the moment it exists, then records when the window's pixels first differ
|
||||
// from the background colour (`screenPainted`) and when they stop changing (`screenSettled`).
|
||||
// Renderer paint timing alone is not enough: Chromium stops painting an occluded window, and a
|
||||
// splash or a fade reads as "painted" long before the interface is on screen. `--window-at` puts
|
||||
// the window somewhere the developer's foreground window does not cover. BENCH_SCREEN_DUMP=<dir>
|
||||
// also saves every sample as PNG, BENCH_EXTRA_ARGS passes extra Chromium switches to the app.
|
||||
import { execFileSync, spawn } from "node:child_process"
|
||||
import { cpSync, existsSync, mkdirSync, readdirSync, readFileSync, rmSync, statSync, writeFileSync } from "node:fs"
|
||||
import { createServer } from "node:net"
|
||||
import { tmpdir } from "node:os"
|
||||
@@ -45,6 +53,9 @@ const args = parseArgs({
|
||||
"profile-renderer": { type: "boolean", default: false },
|
||||
trace: { type: "boolean", default: false },
|
||||
"settle-ms": { type: "string", default: "1500" },
|
||||
// Restore the bench window at "x,y" (and treat that display as trusted), for example on a display
|
||||
// that the developer's foreground window does not cover; Chromium stops painting an occluded window.
|
||||
"window-at": { type: "string" },
|
||||
},
|
||||
allowPositionals: true,
|
||||
})
|
||||
@@ -112,10 +123,12 @@ const probe = `(() => ({
|
||||
origin: performance.timeOrigin,
|
||||
firstPaint: performance.getEntriesByType('paint').find((e) => e.name === 'first-paint')?.startTime,
|
||||
domInteractive: performance.getEntriesByType('navigation')[0]?.domInteractive,
|
||||
shell: !!document.querySelector('[data-titlebar-tab-link], [data-action="vertical-tabs-home"]'),
|
||||
editor: !!document.querySelector('[data-component="composer-editor"][contenteditable="true"]'),
|
||||
rows: document.querySelectorAll('[data-timeline-row]').length,
|
||||
home: !!document.querySelector('[data-action="home-new-session"], [data-action="home-add-project-row"]'),
|
||||
prepaint: !!document.getElementById('oc-prepaint'),
|
||||
visible: document.visibilityState === 'visible',
|
||||
shell: !!document.querySelector('#root [data-titlebar-tab-link], #root [data-action="vertical-tabs-home"]'),
|
||||
editor: !!document.querySelector('#root [data-component="composer-editor"][contenteditable="true"]'),
|
||||
rows: document.querySelectorAll('#root [data-timeline-row]').length,
|
||||
home: !!document.querySelector('#root [data-action="home-new-session"], #root [data-action="home-add-project-row"]'),
|
||||
url: location.pathname + location.search,
|
||||
}))()`
|
||||
// Main-process bootstrap timing, read after the run: when the process was created, when Node
|
||||
@@ -237,6 +250,8 @@ type Probe = {
|
||||
origin: number
|
||||
firstPaint?: number
|
||||
domInteractive?: number
|
||||
prepaint: boolean
|
||||
visible: boolean
|
||||
shell: boolean
|
||||
editor: boolean
|
||||
rows: number
|
||||
@@ -273,6 +288,7 @@ async function launch(build: { label: string; exe: string }, run: number): Promi
|
||||
const trace = args.values.trace && run === runs
|
||||
const tracePath = join(outDir, `startup-trace-${Date.now()}.json`)
|
||||
const launchArgs = [
|
||||
...(process.env.BENCH_EXTRA_ARGS?.split(" ").filter(Boolean) ?? []),
|
||||
`--remote-debugging-port=${cdpPort}`,
|
||||
profile ? `--inspect-brk=${inspectPort}` : `--inspect=${inspectPort}`,
|
||||
...(trace
|
||||
@@ -284,10 +300,12 @@ async function launch(build: { label: string; exe: string }, run: number): Promi
|
||||
]
|
||||
: []),
|
||||
]
|
||||
const raiser = await windowRaiser()
|
||||
const spawnAt = Date.now()
|
||||
const child = spawn(build.exe, launchArgs, { env, detached: true, stdio: "ignore" })
|
||||
child.unref()
|
||||
appPid = child.pid
|
||||
raiser.raise(child.pid!)
|
||||
|
||||
let mainProfile: Promise<unknown> | undefined
|
||||
if (profile) mainProfile = profileMain(spawnAt)
|
||||
@@ -309,6 +327,7 @@ async function launch(build: { label: string; exe: string }, run: number): Promi
|
||||
// when the shell is up and the main thread has spent under 10 % of any 500 ms window in tasks for `settleMs`.
|
||||
const seen: Record<string, number> = {}
|
||||
let last: Probe | undefined
|
||||
let prepaintSeen = false
|
||||
let quietSince: number | undefined
|
||||
let taskMs = 0
|
||||
let scriptMs = 0
|
||||
@@ -318,6 +337,9 @@ async function launch(build: { label: string; exe: string }, run: number): Promi
|
||||
const result = await cdp.send("Runtime.evaluate", { expression: probe, returnByValue: true })
|
||||
last = result.result?.result?.value as Probe | undefined
|
||||
const t = Date.now() - spawnAt
|
||||
if (last?.prepaint) prepaintSeen = true
|
||||
// Chromium marks a window it considers occluded hidden and the renderer stops painting.
|
||||
if (last?.visible && !seen.documentVisible) seen.documentVisible = t
|
||||
if (last?.shell && !seen.shellVisible) seen.shellVisible = t
|
||||
if (last?.editor && !seen.composerEditable) seen.composerEditable = t
|
||||
if (last?.rows && !seen.timelineRows) seen.timelineRows = t
|
||||
@@ -356,6 +378,7 @@ async function launch(build: { label: string; exe: string }, run: number): Promi
|
||||
const timelineResult = await cdp.send("Runtime.evaluate", { expression: rendererTimeline, returnByValue: true })
|
||||
cdp.close()
|
||||
const processes = appPid ? await processTree(appPid) : []
|
||||
const screenChanges = await raiser.screen()
|
||||
const boot = profile ? undefined : await mainBootTiming()
|
||||
await sleep(300)
|
||||
// Chromium writes the startup trace when --trace-startup-duration elapses; keep the app alive until then.
|
||||
@@ -385,7 +408,16 @@ async function launch(build: { label: string; exe: string }, run: number): Promi
|
||||
domInteractive:
|
||||
last?.domInteractive !== undefined && origin !== undefined ? Math.round(origin + last.domInteractive) : undefined,
|
||||
firstPaint: last?.firstPaint !== undefined && origin !== undefined ? Math.round(origin + last.firstPaint) : undefined,
|
||||
// With a shell snapshot in the early document, first paint is the snapshot, not the app.
|
||||
prepaintVisible:
|
||||
prepaintSeen && last?.firstPaint !== undefined && origin !== undefined
|
||||
? Math.round(origin + last.firstPaint)
|
||||
: undefined,
|
||||
...seen,
|
||||
// First sampled screen change inside the window: the ground truth for "the user sees something".
|
||||
screenPainted: screenChanges.changed[0],
|
||||
// When the sampled window content stopped changing: the interface, not a splash, is on screen.
|
||||
screenSettled: screenChanges.settled,
|
||||
rendererIdle: rendererIdleMs,
|
||||
},
|
||||
final: { url: last?.url, timelineRows: last?.rows },
|
||||
@@ -451,6 +483,22 @@ function prepareHome() {
|
||||
})
|
||||
}
|
||||
mkdirSync(paths.logs, { recursive: true })
|
||||
const at = args.values["window-at"]?.split(",").map(Number)
|
||||
if (at?.length === 2 && existsSync(userData)) {
|
||||
for (const file of readdirSync(userData).filter((name) => /^window-state-.*\.json$/.test(name))) {
|
||||
const state = JSON.parse(readFileSync(join(userData, file), "utf8"))
|
||||
const bounds = displayAt(at[0], at[1])
|
||||
writeFileSync(join(userData, file), JSON.stringify({ ...state, x: at[0], y: at[1], isMaximized: false, isFullScreen: false, displayBounds: bounds }))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function displayAt(x: number, y: number) {
|
||||
if (process.platform !== "win32") return undefined
|
||||
const out = execFileSync("pwsh", ["-NoProfile", "-NonInteractive", "-Command", "Add-Type -AssemblyName System.Windows.Forms; [System.Windows.Forms.Screen]::AllScreens | ForEach-Object { \"$($_.Bounds.X),$($_.Bounds.Y),$($_.Bounds.Width),$($_.Bounds.Height)\" }"], { encoding: "utf8" })
|
||||
const displays = out.trim().split(/\r?\n/).map((line) => line.split(",").map(Number))
|
||||
const hit = displays.find(([dx, dy, dw, dh]) => x >= dx && y >= dy && x < dx + dw && y < dy + dh)
|
||||
return hit ? { x: hit[0], y: hit[1], width: hit[2], height: hit[3] } : undefined
|
||||
}
|
||||
|
||||
async function freePort() {
|
||||
@@ -565,6 +613,86 @@ function mainLog() {
|
||||
}
|
||||
|
||||
// Working set of every process in the launched app's tree once it is idle.
|
||||
// Windows places a window launched from a background process behind the foreground one, and
|
||||
// Chromium then marks it occluded and the renderer stops painting, so paint timings would depend on
|
||||
// what else is on screen. A helper started before the app polls for its main window and pins it
|
||||
// topmost without activating it, so the user keeps their focus and the bench window is visible.
|
||||
async function windowRaiser(): Promise<{ raise: (pid: number) => void; screen: () => Promise<number[]> }> {
|
||||
if (process.platform !== "win32") return { raise: () => {}, screen: async () => [] }
|
||||
const script = join(outDir, "raise-window.ps1")
|
||||
writeFileSync(
|
||||
script,
|
||||
[
|
||||
`Add-Type -AssemblyName System.Drawing`,
|
||||
`Add-Type -Namespace Bench -Name User32 -MemberDefinition '[DllImport("user32.dll")] public static extern bool SetWindowPos(IntPtr h, IntPtr a, int x, int y, int w, int z, uint f); [StructLayout(LayoutKind.Sequential)] public struct RECT { public int L; public int T; public int R; public int B; } [DllImport("user32.dll")] public static extern bool GetWindowRect(IntPtr h, out RECT r);'`,
|
||||
`[Console]::Out.WriteLine("ready")`,
|
||||
`$target = [int][Console]::In.ReadLine()`,
|
||||
`$clock = [Diagnostics.Stopwatch]::StartNew()`,
|
||||
`$h = 0`,
|
||||
`for ($i = 0; $i -lt 600; $i++) {`,
|
||||
` $h = (Get-Process -Id $target -ErrorAction SilentlyContinue).MainWindowHandle`,
|
||||
` if ($h -and $h -ne 0) { [Bench.User32]::SetWindowPos($h, [IntPtr](-1), 0, 0, 0, 0, 0x13) | Out-Null; [Console]::Out.WriteLine("raised " + $clock.ElapsedMilliseconds); break }`,
|
||||
` Start-Sleep -Milliseconds 10`,
|
||||
`}`,
|
||||
`if (-not $h -or $h -eq 0) { exit }`,
|
||||
// Sample a 16x16 grid of pixels inside the window: cheap, and enough to tell the background
|
||||
// colour, a splash and the interface apart.
|
||||
`$r = New-Object Bench.User32+RECT`,
|
||||
`while ($clock.ElapsedMilliseconds -lt 3000) {`,
|
||||
` [Bench.User32]::GetWindowRect($h, [ref]$r) | Out-Null`,
|
||||
` $w = $r.R - $r.L; $ht = $r.B - $r.T`,
|
||||
` if ($w -le 48 -or $ht -le 48) { Start-Sleep -Milliseconds 30; continue }`,
|
||||
` $t = $clock.ElapsedMilliseconds`,
|
||||
` $bmp = New-Object System.Drawing.Bitmap $w, $ht`,
|
||||
` $g = [System.Drawing.Graphics]::FromImage($bmp)`,
|
||||
` try { $g.CopyFromScreen($r.L, $r.T, 0, 0, $bmp.Size) } catch { $g.Dispose(); $bmp.Dispose(); Start-Sleep -Milliseconds 30; continue }`,
|
||||
` $sum = 0`,
|
||||
` for ($i = 1; $i -le 16; $i++) { for ($j = 1; $j -le 16; $j++) { $p = $bmp.GetPixel([int]($w * $j / 17), [int]($ht * $i / 17)); $sum += [int]$p.R + [int]$p.G + [int]$p.B } }`,
|
||||
` [Console]::Out.WriteLine("screen " + $t + " " + $sum)`,
|
||||
` if ($env:BENCH_SCREEN_DUMP) { $bmp.Save((Join-Path $env:BENCH_SCREEN_DUMP ("screen-" + $t.ToString().PadLeft(4, "0") + ".png"))) }`,
|
||||
` $g.Dispose(); $bmp.Dispose()`,
|
||||
` Start-Sleep -Milliseconds 30`,
|
||||
`}`,
|
||||
].join("\n"),
|
||||
)
|
||||
const helper = spawn("pwsh", ["-NoProfile", "-NonInteractive", "-File", script], { stdio: ["pipe", "pipe", "pipe"] })
|
||||
const lines: string[] = []
|
||||
let buffer = ""
|
||||
await new Promise<void>((resolve) => {
|
||||
helper.stdout!.on("data", (chunk: Buffer) => {
|
||||
buffer += chunk.toString()
|
||||
const parts = buffer.split(/\r?\n/)
|
||||
buffer = parts.pop() ?? ""
|
||||
for (const line of parts) {
|
||||
if (line === "ready") resolve()
|
||||
else lines.push(line)
|
||||
}
|
||||
})
|
||||
helper.stderr!.on("data", (chunk: Buffer) => console.error(`raise-window: ${chunk.toString().trim()}`))
|
||||
helper.on("exit", () => resolve())
|
||||
})
|
||||
const exited = new Promise<void>((resolve) => helper.on("exit", () => resolve()))
|
||||
return {
|
||||
raise: (pid) => helper.stdin!.write(`${pid}\n`),
|
||||
// Resolves with the times (ms since the pid was sent, ~spawn) at which the sampled screen
|
||||
// content differed from the first sample, i.e. when something other than the background colour
|
||||
// was on screen.
|
||||
screen: async () => {
|
||||
await exited
|
||||
const samples = lines
|
||||
.filter((line) => line.startsWith("screen "))
|
||||
.map((line) => line.split(" ").slice(1).map(Number) as [number, number])
|
||||
if (process.env.BENCH_DEBUG) console.log(lines.filter((line) => line.startsWith("raised")).join(" "), `${samples.length} screen samples`)
|
||||
const first = samples[0]?.[1]
|
||||
const last = samples.at(-1)?.[1]
|
||||
const differs = (a: number, b: number) => Math.abs(a - b) > 16 * 16 * 12
|
||||
const changed = samples.filter(([, sum]) => differs(sum, first)).map(([t]) => t)
|
||||
// The last sample that still differed from the final content, i.e. when the window stopped changing.
|
||||
const settledIndex = samples.findLastIndex(([, sum]) => last !== undefined && differs(sum, last))
|
||||
return { changed, settled: settledIndex >= 0 ? samples[settledIndex + 1]?.[0] : samples[0]?.[0] }
|
||||
},
|
||||
}
|
||||
}
|
||||
async function processTree(root: number) {
|
||||
const script =
|
||||
process.platform === "win32"
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
import { expect, test } from "bun:test"
|
||||
import { listInstalledWslDistros, probeWslRuntime, runWslSh, wslArgs } from "./runtime"
|
||||
|
||||
test("wslArgs bypasses the distro default shell", () => {
|
||||
expect(wslArgs(["sh", "-lc", 'printf "%s\\n" "$HOME"'], "Debian")).toEqual([
|
||||
"-d",
|
||||
"Debian",
|
||||
"--exec",
|
||||
"sh",
|
||||
"-lc",
|
||||
'printf "%s\\n" "$HOME"',
|
||||
])
|
||||
expect(wslArgs(["bash", "-se"], "Debian", "root")).toEqual([
|
||||
"-d",
|
||||
"Debian",
|
||||
"--user",
|
||||
"root",
|
||||
"--exec",
|
||||
"bash",
|
||||
"-se",
|
||||
])
|
||||
})
|
||||
|
||||
// Exercise the real wsl.exe argv path: with `--`, WSL routes the command line through the distro's
|
||||
// default shell, which expands `$cli` to "" before `sh` runs the script (#48640).
|
||||
const distro =
|
||||
process.platform === "win32" && (await probeWslRuntime()).available
|
||||
? (await listInstalledWslDistros().catch(() => [])).find((item) => item.isDefault)?.name
|
||||
: undefined
|
||||
|
||||
test.skipIf(!distro)("inline scripts keep their own variable expansion inside WSL", async () => {
|
||||
const result = await runWslSh(['cli="from-script"', 'printf "%s\\n" "$cli"'].join("\n"), distro)
|
||||
expect(result.code).toBe(0)
|
||||
expect(result.stdout.trim()).toBe("from-script")
|
||||
})
|
||||
@@ -38,7 +38,9 @@ const DEFAULT_WSL_TIMEOUT_MS = 20_000
|
||||
const DEFAULT_WSL_INSTALL_TIMEOUT_MS = 15 * 60_000
|
||||
|
||||
export function wslArgs(args: string[], distro?: string | null, user?: string | null) {
|
||||
return [...(distro ? ["-d", distro] : []), ...(user ? ["--user", user] : []), "--", ...args]
|
||||
// `--` hands the command line to the distro's default shell, which expands `$VAR` and `$(...)`
|
||||
// inside our inline scripts before `sh -lc` ever runs them. `--exec` runs the command directly.
|
||||
return [...(distro ? ["-d", distro] : []), ...(user ? ["--user", user] : []), "--exec", ...args]
|
||||
}
|
||||
|
||||
export function runWsl(args: string[], opts: RunWslOptions = {}) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opencode/enterprise",
|
||||
"version": "2.0.8",
|
||||
"version": "2.0.9",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opencode/function",
|
||||
"version": "2.0.8",
|
||||
"version": "2.0.9",
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"version": "2.0.8",
|
||||
"version": "2.0.9",
|
||||
"name": "@opencode/http-recorder",
|
||||
"description": "Record and replay Effect HTTP and WebSocket traffic with deterministic cassettes",
|
||||
"type": "module",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"name": "@opencode/httpapi-codegen",
|
||||
"version": "2.0.8",
|
||||
"version": "2.0.9",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"exports": {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"name": "@opencode/latex",
|
||||
"version": "2.0.8",
|
||||
"version": "2.0.9",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"exports": {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"name": "@opencode/merman",
|
||||
"version": "2.0.8",
|
||||
"version": "2.0.9",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"exports": {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"name": "@opencode/plugin-browser",
|
||||
"version": "2.0.8",
|
||||
"version": "2.0.9",
|
||||
"description": "OpenCode's desktop browser plugin",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"name": "@opencode/plugin",
|
||||
"version": "2.0.8",
|
||||
"version": "2.0.9",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"name": "@opencode/protocol",
|
||||
"version": "2.0.8",
|
||||
"version": "2.0.9",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"name": "@opencode/schema",
|
||||
"version": "2.0.8",
|
||||
"version": "2.0.9",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"version": "2.0.8",
|
||||
"version": "2.0.9",
|
||||
"name": "@opencode/sdk",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"name": "@opencode/server",
|
||||
"version": "2.0.8",
|
||||
"version": "2.0.9",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opencode/session-ui",
|
||||
"version": "2.0.8",
|
||||
"version": "2.0.9",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"name": "@opencode/simulation",
|
||||
"version": "2.0.8",
|
||||
"version": "2.0.9",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"name": "@opencode/stats-app",
|
||||
"version": "2.0.8",
|
||||
"version": "2.0.9",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"name": "@opencode/stats-core",
|
||||
"version": "2.0.8",
|
||||
"version": "2.0.9",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"name": "@opencode/stats-server",
|
||||
"version": "2.0.8",
|
||||
"version": "2.0.9",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"name": "@opencode/theme",
|
||||
"version": "2.0.8",
|
||||
"version": "2.0.9",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"name": "@opencode/tui",
|
||||
"version": "2.0.8",
|
||||
"version": "2.0.9",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -120,7 +120,7 @@ const glowTextColor = (base: RGBA, glow: RGBA, index: number, width: number, lev
|
||||
tint(base, glow, 0.12 * unreadGlowIntensity(index, width) * level)
|
||||
|
||||
function tabFeedbackColor(status: SessionTabsStatus, theme: ReturnType<typeof useTheme>) {
|
||||
if (status.attention) return theme.hue.interactive[800]
|
||||
if (status.attention) return theme.hue.interactive[200]
|
||||
if (status.unread === "error") return theme.text.feedback.error.base
|
||||
return undefined
|
||||
}
|
||||
@@ -528,8 +528,8 @@ function VerticalSessionTabs(props: {
|
||||
const compact = createMemo(() => width() < SESSION_TABS_COMPACT_BREAKPOINT)
|
||||
const tooltipWidth = () => Math.min(54, dimensions().width - width())
|
||||
const stride = () => (compact() ? 2 : 3)
|
||||
const unreadColor = () => theme.hue.interactive[800]
|
||||
const activeNumber = () => theme.hue.accent[800]
|
||||
const unreadColor = () => theme.hue.interactive[200]
|
||||
const activeNumber = () => theme.hue.accent[200]
|
||||
const idleNumber = () => tint(theme.text.formfield.base, background(), 0.55)
|
||||
const separatorUpperPulseColor = createMemo(() => tint(background(), theme.text.base, 0.04))
|
||||
const separatorLowerPulseColor = createMemo(() => tint(background(), theme.text.base, 0.05))
|
||||
@@ -1291,8 +1291,8 @@ function HorizontalSessionTabs(props: {
|
||||
onCleanup(clearCloseHold)
|
||||
// A captured drag ends with a synthetic up on its drop target; do not turn that into a click.
|
||||
let suppressClick = false
|
||||
const unreadColor = () => theme.hue.interactive[800]
|
||||
const activeNumber = () => theme.hue.accent[800]
|
||||
const unreadColor = () => theme.hue.interactive[200]
|
||||
const activeNumber = () => theme.hue.accent[200]
|
||||
const idleNumber = () => tint(theme.text.formfield.base, theme.background.base, 0.55)
|
||||
const newTab = () => tabs.newTab?.() ?? false
|
||||
const activeID = createMemo(() => (newTab() ? NEW_SESSION_TAB.sessionID : tabs.current()))
|
||||
|
||||
@@ -32,7 +32,7 @@ export default Plugin.define({
|
||||
return (
|
||||
<Show when={pending() > 0}>
|
||||
<box flexShrink={0}>
|
||||
<Spinner color={theme.hue.accent[800]}>/btw</Spinner>
|
||||
<Spinner color={theme.hue.accent[200]}>/btw</Spinner>
|
||||
</box>
|
||||
</Show>
|
||||
)
|
||||
|
||||
@@ -181,7 +181,7 @@ function OneCellSpinnerStory(props: { context: Plugin.Context }) {
|
||||
animations={animations()}
|
||||
paused={paused()}
|
||||
glow={glow()}
|
||||
color={theme.hue.accent[800]}
|
||||
color={theme.hue.accent[200]}
|
||||
/>
|
||||
</box>
|
||||
)}
|
||||
@@ -236,7 +236,7 @@ function OneCellSpinnerStory(props: { context: Plugin.Context }) {
|
||||
animations={animations()}
|
||||
paused={paused()}
|
||||
glow={glow()}
|
||||
color={theme.hue.accent[800]}
|
||||
color={theme.hue.accent[200]}
|
||||
/>
|
||||
<text fg={theme.text.base}> esc stop</text>
|
||||
</box>
|
||||
|
||||
@@ -284,10 +284,10 @@ function SessionTabsStory(props: { context: Plugin.Context }) {
|
||||
{ text: "", color: theme.text.base },
|
||||
)
|
||||
if (status.attention === "question")
|
||||
lines.push({ text: "? Which approach should I take?", color: theme.hue.interactive[800] })
|
||||
lines.push({ text: "? Which approach should I take?", color: theme.hue.interactive[200] })
|
||||
else if (status.attention === "permission")
|
||||
lines.push({ text: "! Waiting for permission to run the command", color: theme.hue.interactive[800] })
|
||||
else if (status.busy) lines.push({ text: "● Working…", color: theme.hue.accent[800] })
|
||||
lines.push({ text: "! Waiting for permission to run the command", color: theme.hue.interactive[200] })
|
||||
else if (status.busy) lines.push({ text: "● Working…", color: theme.hue.accent[200] })
|
||||
else if (outcome === "failed")
|
||||
lines.push({
|
||||
text: `✗ bun run test failed — 3 tests failing in ${file}`,
|
||||
|
||||
@@ -142,9 +142,9 @@ function map(
|
||||
formfieldFocusedBg: exact(theme.background.formfield.focused),
|
||||
formfieldFocusedText: exact(theme.text.formfield.focused),
|
||||
selection: exact(theme.text.formfield.selected),
|
||||
running: exact(theme.hue.accent[800]),
|
||||
question: exact(theme.hue.interactive[800]),
|
||||
permission: exact(theme.hue.interactive[800]),
|
||||
running: exact(theme.hue.accent[200]),
|
||||
question: exact(theme.hue.interactive[200]),
|
||||
permission: exact(theme.hue.interactive[200]),
|
||||
success: exact(theme.text.feedback.success.base),
|
||||
link: exact(theme.markdown.link),
|
||||
categorical: dedupeWith(
|
||||
|
||||
@@ -139,7 +139,7 @@ for (const orientation of ["horizontal", "vertical"] as const) {
|
||||
.captureSpans()
|
||||
.lines.flatMap((line) => line.spans)
|
||||
.find((span) => span.text.trim() === (attention === "question" ? "?" : "!"))?.fg
|
||||
expect(indicatorColor()?.toInts()).toEqual(theme.hue.interactive[800].toInts())
|
||||
expect(indicatorColor()?.toInts()).toEqual(theme.hue.interactive[200].toInts())
|
||||
const glow = () => {
|
||||
const colors = app
|
||||
.captureSpans()
|
||||
@@ -156,7 +156,7 @@ for (const orientation of ["horizontal", "vertical"] as const) {
|
||||
expect(full).toBeGreaterThan(0)
|
||||
setActive("first")
|
||||
await app.renderOnce()
|
||||
expect(indicatorColor()?.toInts()).toEqual(theme.hue.interactive[800].toInts())
|
||||
expect(indicatorColor()?.toInts()).toEqual(theme.hue.interactive[200].toInts())
|
||||
const dim = glow()
|
||||
expect(dim).toBeGreaterThan(0)
|
||||
expect(dim).toBeLessThan(full)
|
||||
@@ -172,7 +172,7 @@ for (const orientation of ["horizontal", "vertical"] as const) {
|
||||
.lines.flatMap((line) => line.spans)
|
||||
.find((span) => span.text.trim() === glyph)?.fg
|
||||
expect(color?.toInts()).toEqual(
|
||||
(unread === "error" ? theme.text.feedback.error.base : theme.hue.interactive[800]).toInts(),
|
||||
(unread === "error" ? theme.text.feedback.error.base : theme.hue.interactive[200]).toInts(),
|
||||
)
|
||||
await app.mockMouse.click(1, orientation === "vertical" ? 1 : 0)
|
||||
await app.renderOnce()
|
||||
|
||||
@@ -90,9 +90,9 @@ function expectFooter(actual: RunTheme, theme: ResolvedTheme) {
|
||||
formfieldFocusedBg: theme.background.formfield.focused,
|
||||
formfieldFocusedText: theme.text.formfield.focused,
|
||||
selection: theme.text.formfield.selected,
|
||||
running: theme.hue.accent[800],
|
||||
question: theme.hue.interactive[800],
|
||||
permission: theme.hue.interactive[800],
|
||||
running: theme.hue.accent[200],
|
||||
question: theme.hue.interactive[200],
|
||||
permission: theme.hue.interactive[200],
|
||||
success: theme.text.feedback.success.base,
|
||||
link: theme.markdown.link,
|
||||
shade: theme.background.raised.base,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opencode/ui",
|
||||
"version": "2.0.8",
|
||||
"version": "2.0.9",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"name": "@opencode/util",
|
||||
"version": "2.0.8",
|
||||
"version": "2.0.9",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"name": "@opencode/web",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"version": "2.0.8",
|
||||
"version": "2.0.9",
|
||||
"scripts": {
|
||||
"dev": "astro dev",
|
||||
"dev:remote": "VITE_API_URL=https://api.opencode.ai astro dev",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"name": "opencode",
|
||||
"displayName": "opencode",
|
||||
"description": "opencode for VS Code",
|
||||
"version": "2.0.8",
|
||||
"version": "2.0.9",
|
||||
"publisher": "sst-dev",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"name": "@opencode/update",
|
||||
"version": "2.0.8",
|
||||
"version": "2.0.9",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
|
||||
Reference in New Issue
Block a user