v1.0.105
A focused stability release: every reported bug from the OpenCode community is fixed, the timeout policy in ctx_execute* no longer murders long-running builds, and the renderer-safe doctor output unblocks Z.ai users.
What's new
OpenCode SessionStart actually works now (PR #376 follow-up — @mikij)
Mickey reported three concrete bugs against the OpenCode plugin path. All three landed in this release.
db.getResume()always returned null/undefined. Root cause: we hookedexperimental.chat.messages.transform, whose SDK contract isinput: {}(nosessionID) andoutput: { messages: { info, parts }[] }. Our prioroutput.messages.unshift({ role, content })was the wrong shape and got silently dropped. Verified against OpenCode source (packages/plugin/src/index.ts:281-295). Fix: pivot toexperimental.chat.system.transform(input: { sessionID?, model },output: { system: string[] }). Snapshots now actually reach the model.sessionStartInjected = truesurvived only the first session per process. A closure-scope boolean plus a process-globalrandomUUID()binding meant any plugin process that handled more than one session (i.e. all of them) tripped the flag once and never reset it. Fix: droprandomUUID()entirely; plumbinput.sessionIDfrom each hook; gate injection with aSet<string>keyed by sessionID.- Snapshot insertion preserves OpenCode's prompt-cache header. OpenCode (
packages/opencode/src/session/llm.ts:117-128) savesheader = system[0]before the hook fires, then folds[header, body]only whensystem[0] === headerafterwards. We nowsplice(1, 0, snapshot)instead ofunshift, so cache fold survives every resume injection. Without this, everyctx_executeinvocation on a resumed OpenCode session would have invalidated the provider prompt cache and 3-5×'d input token cost.
Cross-session resume claim is now race-safe: SessionDB.claimLatestUnconsumedResume() runs a single atomic UPDATE … WHERE id = (SELECT id … LIMIT 1) RETURNING so two concurrent processes for the same project can never both inject the same snapshot.
Z.ai GLM 4.7 → "client is not defined" on ctx_doctor is gone (PR #376 follow-up — @mikij)
Z.ai's MCP renderer mounts a custom React component for GFM task-list syntax (- [x], - [ ], - [-]) that depends on a missing client context, throwing ReferenceError. We refactored ctx_doctor output to plain-text [OK]/[FAIL]/[WARN] prefixes and dropped the ## h2 header. Renderer-safe across every MCP client we've checked.
Long Gradle/Maven/SBT builds no longer get murdered at 30s (Issue #406 — @wax911)
Maxwell hit a real pain point: the implicit .default(30000) Zod timeout on ctx_execute / ctx_execute_file (and 60_000 on ctx_batch_execute) was killing legitimate Gradle test runs whenever the LLM forgot to pass an explicit value.
We rejected the "add env var defaults + 30-min build floor" approach — server-side timeout policy is the wrong layer when every MCP host already enforces its own RPC timeout. Stacking another policy creates dead config that drifts.
Fix: drop the implicit Zod defaults entirely. When the caller omits timeout, the server fires no kill timer at all — the host's RPC timeout governs (which is the right layer). When the caller passes an explicit value, behaviour is unchanged. Tool descriptions now spell this out so the LLM picks an appropriate timeout for long builds without relying on a magic default.
Bonus: sbt is now redirected alongside gradle/mvn in hooks/core/routing.mjs (it was missing from the regex). Word-boundary guards prevent false positives on substrings like gradle-wrapper-config.
Other changes (came in via #404 / #405)
fix(insight): keep directory overrides in source (#404)— @mksglufix: add ps1 extension for Windows PowerShell -File scripts (#405)— community contribution
Tests added
All in existing files per CONTRIBUTING.md L275:
tests/session/session-db.test.ts— 4 atomic-claim slicestests/opencode-plugin.test.ts— 5 system.transform behaviour tests (including the cache-fold header preservation regression)tests/core/server.test.ts— Z.ai renderer regression + 2 batch undefined-timeout teststests/executor.test.ts— 2 no-timeout tests (JS + shell)tests/hooks/core-routing.test.ts— 3 sbt + word-boundary tests
tests/opencode-session-start.test.ts was removed — orphan file that asserted the now-deleted messages.transform hook; coverage moved into tests/opencode-plugin.test.ts.
Validation
Reviewed across 8 parallel sub-agent passes (3 diagnose + 3 grill + 2 architect/14×3-OS validation). All converged on SHIP after the cache-fold splice fix landed.
- 14 adapter × 3 OS coverage verified
- 10 hook-paradigm adapters unaffected (chat.system.transform is OpenCode-SDK-only)
- SQLite 3.53 bundled with
better-sqlite3—UPDATE … RETURNINGworks on Windows - openclaw + pi paths unchanged — they receive a real
session_startevent, so the Mickey #2 closure-flag pattern doesn't apply
Contributors
Big thanks to the community catching this round:
- @mikij — three excellent bug reports against PR #376 with concrete repros, all landed
- @wax911 — Issue #406 with a fully sketched proposal; we went a different direction but the use case was 100% real
- #404 / #405 reporters — Windows PowerShell extension fix + insight directory override fix
Upgrade
npm update -g context-modeOr use the in-product ctx_upgrade MCP tool.
If you hit anything weird, please open an issue with the platform name (Claude Code / Cursor / Codex / OpenCode / etc.), OS, and ctx_doctor output — that triplet covers ~95% of the variance.