Skip to content

Commit 0aff604

Browse files
Fix TUI sidebar failing to load on OpenCode 1.17.10 (missing OpenTUI deps)
OpenCode 1.17.10 bumped OpenTUI to 0.4.2. Our raw-TSX ./tui entry (src/tui/index.tsx) compiles against @opentui/solid's JSX runtime via /** @jsxImportSource @opentui/solid */, but packages/plugin/package.json declared neither @opentui/solid nor solid-js, so the entry failed to load with 'Cannot find module @opentui/solid/jsx-dev-runtime' — the sidebar silently broke for anyone on 1.17.10. (Diagnosed with the OpenCode maintainer.) Declare the runtime deps so they resolve from the plugin package itself: @opentui/core ^0.4.2, @opentui/solid ^0.4.2 (minor-locked to the 0.4.x the host ships, not >=0.4.2 which could drift to 0.5.x while the host is still 0.4.x), and solid-js pinned to 1.9.12 (OpenTUI's pinned peer — avoid a second Solid runtime). They are NOT bundled into dist/index.js (verified: externalizing them yields a byte-identical server bundle); the TUI ships as raw TSX via ./tui. Add scripts/smoke-tui-import.ts (wired into ci.yml + release.yml) that imports the ./tui entry the way OpenCode loads it, so a missing or mismatched OpenTUI/Solid runtime fails CI instead of shipping a TUI that won't load — bun test never imports the TSX entry and could not catch this. Removed the 3-day supply-chain release-age gate (bunfig.toml minimumReleaseAge in all four packages + the .npmrc min-release-age) so host-lockstep deps like @OpenTui 0.4.2 (published same-day as the OpenCode bump) can be pinned to the exact version the host requires instead of lagging 3 days behind. Co-authored-by: Alfonso [Magic Context] <288211368+alfonso-magic-context@users.noreply.github.com>
1 parent 9503da9 commit 0aff604

10 files changed

Lines changed: 316 additions & 44 deletions

File tree

.github/workflows/ci.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,13 @@ jobs:
7373
- name: Smoke (smart-note wasm bundle)
7474
run: bun packages/plugin/scripts/smoke-smartnote-wasm.ts
7575

76+
# The raw-TSX ./tui entry imports @opentui/solid's JSX runtime. `bun test`
77+
# never imports it, so a missing/mismatched OpenTUI or Solid dep (as broke
78+
# on OpenCode 1.17.10's OpenTUI 0.4.2 bump) ships a TUI that won't load.
79+
# Import the entry the way OpenCode loads the ./tui export to catch it.
80+
- name: Smoke (TUI entry import)
81+
run: bun packages/plugin/scripts/smoke-tui-import.ts
82+
7683
check-pi-plugin:
7784
name: Check (pi-plugin)
7885
runs-on: ubuntu-latest

.github/workflows/release.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,11 @@ jobs:
8989
- name: Smoke (smart-note wasm bundle)
9090
run: bun packages/plugin/scripts/smoke-smartnote-wasm.ts
9191

92+
# Verify the raw-TSX ./tui entry imports (OpenTUI/Solid runtime resolves)
93+
# before publishing — a missing dep ships a TUI that won't load.
94+
- name: Smoke (TUI entry import)
95+
run: bun packages/plugin/scripts/smoke-tui-import.ts
96+
9297
test-pi:
9398
name: Test (pi-plugin)
9499
runs-on: ubuntu-latest

.npmrc

Lines changed: 0 additions & 11 deletions
This file was deleted.

bun.lock

Lines changed: 251 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

bunfig.toml

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,3 @@
1-
# Supply-chain protection: refuse Bun-installed packages published within the
2-
# last 3 days. Honored by Bun 1.2+ (the `minimumReleaseAge` setting introduced
3-
# alongside the npm v11 equivalent in response to recent supply-chain attacks).
4-
#
5-
# Older Bun versions silently ignore unknown settings. CI is on Bun 1.3+, so CI
6-
# does enforce. Local dev should run `bun upgrade` to pick this up.
7-
#
8-
# 3 days = 259200 seconds. Adjust upward if you want a wider safety net.
9-
10-
[install]
11-
minimumReleaseAge = 259200
12-
131
# Test isolation for a bare `bun test` run from the monorepo ROOT (which
142
# recursively discovers every package's *.test.ts). Without this, a root-CWD
153
# `bun test` runs all suites with NO preload and a bare openDatabase() would hit

packages/cli/bunfig.toml

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,3 @@
1-
# Supply-chain protection (mirrors the root bunfig): refuse Bun-installed
2-
# packages published within the last 3 days.
3-
[install]
4-
minimumReleaseAge = 259200
5-
61
# Test isolation: force the shared cortexkit DB onto a throwaway temp dir for the
72
# whole test process so NO cli test can read or migrate the user's real shared
83
# database (shared with OpenCode + Pi). The CLI imports plugin storage via

packages/pi-plugin/bunfig.toml

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,3 @@
1-
# Supply-chain protection (mirrors the root bunfig): refuse Bun-installed
2-
# packages published within the last 3 days.
3-
[install]
4-
minimumReleaseAge = 259200
5-
61
# Test isolation: force XDG_DATA_HOME to a throwaway temp dir for the whole test
72
# process so NO test can read or migrate the user's real shared cortexkit
83
# database (shared with OpenCode). See test-preload.ts for the rationale

packages/plugin/bunfig.toml

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,3 @@
1-
# Supply-chain protection (mirrors the root bunfig): refuse Bun-installed
2-
# packages published within the last 3 days.
3-
[install]
4-
minimumReleaseAge = 259200
5-
61
# Test isolation: force XDG_DATA_HOME to a throwaway temp dir for the whole test
72
# process so NO test can ever read or migrate the user's real shared cortexkit
83
# database. See test-preload.ts for the full rationale (2026-06-01 incident: a

packages/plugin/package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,12 @@
4444
"@jitl/quickjs-singlefile-cjs-release-asyncify": "0.32.0",
4545
"@opencode-ai/plugin": "^1.15.13",
4646
"@opencode-ai/sdk": "^1.15.13",
47+
"@opentui/core": "^0.4.2",
48+
"@opentui/solid": "^0.4.2",
4749
"ai-tokenizer": "^1.0.6",
4850
"comment-json": "^4.2.5",
4951
"quickjs-emscripten": "^0.32.0",
52+
"solid-js": "1.9.12",
5053
"zod": "^4.1.8"
5154
},
5255
"devDependencies": {
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// Import smoke test for the raw-TSX TUI entry (`./tui` export).
2+
//
3+
// The TUI entry (src/tui/index.tsx) uses `/** @jsxImportSource @opentui/solid */`,
4+
// so loading it requires @opentui/solid + solid-js to resolve from the plugin
5+
// package itself. When those weren't declared as deps, OpenCode 1.17.10's
6+
// OpenTUI 0.4.2 bump surfaced an immediate load failure:
7+
// Cannot find module '@opentui/solid/jsx-dev-runtime'
8+
// `bun test` doesn't catch this because no suite imports the TSX entry. This
9+
// script imports it exactly like OpenCode loads the `./tui` export, so a missing
10+
// or version-mismatched OpenTUI/Solid runtime fails the smoke instead of shipping
11+
// a TUI that won't load. Run: bun packages/plugin/scripts/smoke-tui-import.ts
12+
import { dirname, join } from "node:path";
13+
import { fileURLToPath } from "node:url";
14+
15+
const here = dirname(fileURLToPath(import.meta.url));
16+
const entry = join(here, "../src/tui/index.tsx");
17+
18+
let failures = 0;
19+
function check(name: string, cond: boolean, detail?: string): void {
20+
if (cond) {
21+
console.log(` ok ${name}`);
22+
} else {
23+
failures++;
24+
console.log(`FAIL ${name}${detail ? ` — ${detail}` : ""}`);
25+
}
26+
}
27+
28+
try {
29+
// Resolving the OpenTUI JSX runtime the TSX entry compiles against is the
30+
// exact thing that broke; importing the entry exercises it end to end.
31+
const mod = (await import(entry)) as { default?: { id?: string; tui?: unknown } };
32+
check("TUI entry imports without a missing-runtime error", true);
33+
check(
34+
"exports the { id, tui } plugin shape",
35+
mod.default?.id === "opencode-magic-context" && typeof mod.default?.tui === "function",
36+
`got id=${mod.default?.id} tui=${typeof mod.default?.tui}`,
37+
);
38+
} catch (error) {
39+
check(
40+
"TUI entry imports without a missing-runtime error",
41+
false,
42+
error instanceof Error ? error.message : String(error),
43+
);
44+
}
45+
46+
if (failures > 0) {
47+
console.error(`\nsmoke-tui-import: ${failures} check(s) failed`);
48+
process.exit(1);
49+
}
50+
console.log("\nsmoke-tui-import: all checks passed");

0 commit comments

Comments
 (0)