Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
## [Unreleased]
### Fixed
- Loads on OpenCode 2.2: runtime imports moved to `@opencode/plugin` and
`@opencode/client`.
- Theme lookup ignores nested palette objects such as `text.action.primary`,
so a theme without a usable accent no longer passes a non-colour to the
renderer.

## [0.5.0] – 2026-09-25
### Changed
- The details dialog is one column with three tabs -- Turn, Session and
Expand Down
2 changes: 1 addition & 1 deletion detail.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
// Everything here is OpenCode's own data. Engine figures travel separately,
// as rows the adapter produced, so each can be marked with its source.

import type { SessionMessageAssistant } from "@opencode-ai/client"
import type { SessionMessageAssistant } from "@opencode/client"
import type { Turn } from "./universal"
import type { Row } from "./rows"

Expand Down
1,696 changes: 780 additions & 916 deletions package-lock.json

Large diffs are not rendered by default.

18 changes: 9 additions & 9 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@
"./tui": "./tui.tsx"
},
"devDependencies": {
"@opencode-ai/client": "0.0.0-beta-19271",
"@opencode-ai/plugin": "0.0.0-beta-19271",
"@opencode-ai/theme": "0.0.0-beta-19271",
"@opentui/core": "0.5.11",
"@opentui/solid": "0.5.11",
"@opencode/client": "2.2.5",
"@opencode/plugin": "2.2.5",
"@opencode/theme": "2.2.5",
"@opentui/core": "0.8.2",
"@opentui/solid": "0.8.2",
"@types/node": "^22.0.0",
"solid-js": "1.9.12",
"solid-js": "1.9.18",
"typescript": "^5.6.0"
},
"scripts": {
Expand Down Expand Up @@ -70,9 +70,9 @@
"access": "public"
},
"peerDependencies": {
"@opencode-ai/plugin": "0.0.0-beta-19271",
"@opentui/core": ">=0.5.10",
"@opentui/solid": ">=0.5.10",
"@opencode/plugin": ">=2.2.5",
"@opentui/core": ">=0.8.1",
"@opentui/solid": ">=0.8.1",
"solid-js": ">=1.9.0"
}
}
6 changes: 3 additions & 3 deletions probe.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
// { "plugins": [{ "package": "/Users/you/dev/opencode-headsup" }] }
// Then read /tmp/headsup-probe.log

import { Plugin } from "@opencode-ai/plugin/tui"
import { Plugin } from "@opencode/plugin/tui"
import { appendFileSync } from "node:fs"

const LOG = "/tmp/headsup-probe.log"
Expand Down Expand Up @@ -153,9 +153,9 @@ export default Plugin.define({
})
)
off.push(
ctx.data.on("session.message.content.updated", (evt) => {
ctx.data.on("session.text.delta", (evt) => {
// Log only the shape, not the content — this fires constantly.
log("P2.content.updated.keys", Object.keys((evt ?? {}) as object))
log("P2.text.delta.keys", Object.keys((evt ?? {}) as object))
})
)
// `session.idle` was subscribed first and never fired once across four
Expand Down
13 changes: 9 additions & 4 deletions tui.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@
// does that. Dividing only visible output by a window that also covered
// thinking is the v1 bug this comment exists to stop recurring.

import { Plugin } from "@opencode-ai/plugin/tui"
import type { SessionMessageAssistant } from "@opencode-ai/client"
import { Plugin } from "@opencode/plugin/tui"
import type { SessionMessageAssistant } from "@opencode/client"
import { appendFileSync } from "node:fs"

import { short } from "./format"
Expand Down Expand Up @@ -244,12 +244,17 @@ export default Plugin.define({
// was undefined and reading `.surface.offset` crashed the slot. Other
// plugins use at least three shapes (text.subdued; text.muted/text.base;
// textMuted; background.raised.base), so each known path is tried and a
// missing colour means "no colour", never a throw.
// missing colour means "no colour", never a throw. A path can also land on
// a nested palette (text.action.primary on 2.2.x), which is not a colour.
const colorLike = (v: unknown): boolean =>
typeof v === "string" ||
typeof v === "number" ||
(typeof v === "object" && v !== null && ("buffer" in v || typeof (v as { toInts?: unknown }).toInts === "function"))
const themeColor = (...paths: string[]): unknown => {
for (const path of paths) {
let v: unknown = ctx.theme
for (const k of path.split(".")) v = v && typeof v === "object" ? (v as Record<string, unknown>)[k] : undefined
if (v !== undefined && v !== null && typeof v !== "function") return v
if (v !== undefined && v !== null && typeof v !== "function" && colorLike(v)) return v
}
return undefined
}
Expand Down
2 changes: 1 addition & 1 deletion universal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { nn, ni, money } from "./format"
import { rowsOf, timeRows, viewText, nt, type Row, type TurnView } from "./rows"

// ---- Tier 1: universal, from OpenCode's own per-turn events -----------------
import type { SessionMessageAssistant } from "@opencode-ai/client"
import type { SessionMessageAssistant } from "@opencode/client"

export interface Turn {
startAt?: number // request start (message.time.created), for TTFT
Expand Down