From f254fff6e3a6613b7a1cac6b69e0ce7b9a4a1aa2 Mon Sep 17 00:00:00 2001 From: Kit Langton Date: Thu, 27 Aug 2026 23:54:46 -0400 Subject: [PATCH 1/3] test(drive): cover current V2 server relaunch --- .../drive/test/manual/current-v2-relaunch.ts | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 packages/drive/test/manual/current-v2-relaunch.ts diff --git a/packages/drive/test/manual/current-v2-relaunch.ts b/packages/drive/test/manual/current-v2-relaunch.ts new file mode 100644 index 0000000..9da65d2 --- /dev/null +++ b/packages/drive/test/manual/current-v2-relaunch.ts @@ -0,0 +1,41 @@ +import assert from "node:assert/strict" +import { Effect } from "effect" +import { defineScript, Llm } from "opencode-drive" + +// Check first, then `drive start --script ... --dev ` +// with OPENCODE_DRIVE_DB=release-relaunch.sqlite to retain the first session. +export default defineScript({ + launch: "manual", + config: { autoupdate: false }, + tui: { viewport: { cols: 100, rows: 35 } }, + run: ({ server, tuis, llm }) => + Effect.gen(function* () { + yield* llm.title(() => Effect.succeed("Drive relaunch")) + const first = yield* server.launch() + const tui = yield* tuis.launch("release-relaunch") + yield* llm.queue(Llm.text("BEFORE_RELAUNCH_OK", { delay: 0 })) + yield* tui.ui.submit("First generation fixture") + yield* tui.ui.waitFor("BEFORE_RELAUNCH_OK") + const sessionID = (yield* first.session.list({ limit: 1, order: "desc" })).data[0]?.id + assert(sessionID) + yield* first.session.wait({ sessionID }) + yield* tui.close() + yield* server.kill() + + const second = yield* server.launch() + assert.equal((yield* second.session.get({ sessionID })).id, sessionID) + const relaunched = yield* tuis.launch("release-relaunch") + yield* llm.queue(Llm.text("AFTER_RELAUNCH_OK", { delay: 0 })) + yield* relaunched.ui.submit("Second generation fixture") + yield* relaunched.ui.waitFor("AFTER_RELAUNCH_OK") + const secondID = (yield* second.session.list({ limit: 1, order: "desc" })).data[0]?.id + assert(secondID) + yield* second.session.wait({ sessionID: secondID }) + assert.deepEqual(yield* second.session.inbox.list({ sessionID: secondID }), []) + assert.equal((yield* relaunched.ui.capture()).cols, 100) + console.log(yield* relaunched.ui.screenshot("release-relaunch")) + yield* relaunched.close() + yield* server.kill() + console.log("CHECKED_SCRIPT_RELAUNCH_OK") + }).pipe(Effect.timeout("90 seconds")), +}) From 67598a8da4ec27ae556383a7d1063b4739796093 Mon Sep 17 00:00:00 2001 From: Kit Langton Date: Thu, 27 Aug 2026 23:59:17 -0400 Subject: [PATCH 2/3] fix(drive): align the published V2 stack with Effect rc112 --- .changeset/current-v2.md | 8 ++++---- apps/catalog/package.json | 2 +- bun.lock | 30 +++++++++++++++--------------- package.json | 2 +- packages/drive/README.md | 6 +++--- packages/drive/package.json | 12 ++++++------ 6 files changed, 30 insertions(+), 30 deletions(-) diff --git a/.changeset/current-v2.md b/.changeset/current-v2.md index f857bc7..609e2ba 100644 --- a/.changeset/current-v2.md +++ b/.changeset/current-v2.md @@ -2,11 +2,11 @@ "opencode-drive": major --- -Update Drive to the current OpenCode V2 client (`0.0.0-dev-18516`) and its -matching Effect V4 stack (`4.0.0-rc.111`). Effect is now an exact peer dependency +Update Drive to the current OpenCode V2 client (`0.0.0-dev-18535`) and its +matching Effect V4 stack (`4.0.0-rc.112`). Effect is now an exact peer dependency so consumer programs and Drive share the same Effect types and runtime. -Effect `rc.112` is available, but the current V2 client, protocol, and schema -packages still require `rc.111`. +The client, protocol, schema, platform, and test packages use the same +coherent `rc.112` stack. Migrate schema-backed errors and RPC JSON codecs, and preserve optional CLI boolean flags with explicit false defaults. Static tool adapters now emit diff --git a/apps/catalog/package.json b/apps/catalog/package.json index 21ba6b8..e6519b4 100644 --- a/apps/catalog/package.json +++ b/apps/catalog/package.json @@ -32,7 +32,7 @@ "@types/bun": "^1.3.14", "@types/react": "^19.2.17", "@types/react-dom": "^19.2.3", - "effect": "4.0.0-rc.111", + "effect": "4.0.0-rc.112", "opencode-drive": "workspace:*", "oxlint": "1.60.0", "typescript": "^7.0.2", diff --git a/bun.lock b/bun.lock index c2b93f4..d927edc 100644 --- a/bun.lock +++ b/bun.lock @@ -23,7 +23,7 @@ "@types/bun": "^1.3.14", "@types/react": "^19.2.17", "@types/react-dom": "^19.2.3", - "effect": "4.0.0-rc.111", + "effect": "4.0.0-rc.112", "opencode-drive": "workspace:*", "oxlint": "1.60.0", "typescript": "^7.0.2", @@ -37,10 +37,10 @@ "opencode-drive": "bin/opencode-drive", }, "dependencies": { - "@effect/platform-node": "4.0.0-rc.111", - "@effect/platform-node-shared": "4.0.0-rc.111", + "@effect/platform-node": "4.0.0-rc.112", + "@effect/platform-node-shared": "4.0.0-rc.112", "@napi-rs/canvas": "1.0.2", - "@opencode-ai/client": "0.0.0-dev-18516", + "@opencode-ai/client": "0.0.0-dev-18535", "@opentui/core": "0.4.5", "@types/bun": "1.3.13", "@typescript/native-preview": "7.0.0-dev.20251207.1", @@ -48,21 +48,21 @@ "@wterm/ghostty": "0.3.0", }, "devDependencies": { - "@effect/vitest": "4.0.0-rc.111", + "@effect/vitest": "4.0.0-rc.112", "@tsconfig/bun": "1.0.9", - "effect": "4.0.0-rc.111", + "effect": "4.0.0-rc.112", "oxlint": "1.60.0", "oxlint-tsgolint": "0.21.0", "typescript": "5.8.2", "vitest": "4.1.10", }, "peerDependencies": { - "effect": "4.0.0-rc.111", + "effect": "4.0.0-rc.112", }, }, }, "overrides": { - "@effect/platform-node-shared": "4.0.0-rc.111", + "@effect/platform-node-shared": "4.0.0-rc.112", }, "packages": { "@babel/runtime": ["@babel/runtime@7.29.7", "", {}, "sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw=="], @@ -117,11 +117,11 @@ "@cspotcode/source-map-support": ["@cspotcode/source-map-support@0.8.1", "", { "dependencies": { "@jridgewell/trace-mapping": "0.3.9" } }, "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw=="], - "@effect/platform-node": ["@effect/platform-node@4.0.0-rc.111", "", { "dependencies": { "@effect/platform-node-shared": "^4.0.0-rc.111", "mime": "^4.1.0", "undici": "^8.10.0" }, "peerDependencies": { "effect": "^4.0.0-rc.111", "redis": ">=5.0.0 <7.0.0" } }, "sha512-oy1i7HsOGg/5r+DuBe5+ddmnUhnXmyZFPFPXZCBdO/RQpHK3PIFe1/2UMGxZE+ngDymrSksuQTSgQLF6P+MLqw=="], + "@effect/platform-node": ["@effect/platform-node@4.0.0-rc.112", "", { "dependencies": { "@effect/platform-node-shared": "^4.0.0-rc.112", "mime": "^4.1.0", "undici": "^8.10.0" }, "peerDependencies": { "effect": "^4.0.0-rc.112", "redis": ">=5.0.0 <7.0.0" } }, "sha512-/BMAcdNGQQskLmI0Zoa95KfTZkr9HV9N4NSxaSrusG6GeW6Ulp9KvZ+Rlaiw8lnOt43CXjFLdfll5/k5rxL4hQ=="], - "@effect/platform-node-shared": ["@effect/platform-node-shared@4.0.0-rc.111", "", { "dependencies": { "@types/ws": "^8.18.1", "ws": "^8.21.3" }, "peerDependencies": { "effect": "^4.0.0-rc.111" } }, "sha512-iES0Q9vmjhaUKqeW9ceonuD45MUg/Ouk08LzRSptZ+B5qB0w9WlRjDmUz5TJmY2betNop5FRI5k4AD4mtQt3Bw=="], + "@effect/platform-node-shared": ["@effect/platform-node-shared@4.0.0-rc.112", "", { "dependencies": { "@types/ws": "^8.18.1", "ws": "^8.21.3" }, "peerDependencies": { "effect": "^4.0.0-rc.112" } }, "sha512-ttjz0xKamFN7vL8pNDYVwddJLjZvqKePc05djlz2VcdaKbLsnYbtMnL1rbOfHgEnIUSHGh7FkjaN4DM1Ov81sQ=="], - "@effect/vitest": ["@effect/vitest@4.0.0-rc.111", "", { "peerDependencies": { "effect": "^4.0.0-rc.111", "vitest": ">=4.1.0 <5.0.0" } }, "sha512-YDaEVT+grREBVMzykRNFtJwGxy02achzT0WXZYwMJA4ukzuB9krkgQ5roc3N6zhC3NQq/j4IyM32/Pcov7AhHw=="], + "@effect/vitest": ["@effect/vitest@4.0.0-rc.112", "", { "peerDependencies": { "effect": "^4.0.0-rc.112", "vitest": ">=4.1.0 <5.0.0" } }, "sha512-mEKh/FI64mt8JK1/v9mpOrJYdnp+UFZdRUBMEdZMiKz7klg6NPqVgg/oeAGH6wOOQc2iAPcfc2H9BbAv1KyzMQ=="], "@emnapi/core": ["@emnapi/core@1.11.1", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.2", "tslib": "^2.4.0" } }, "sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ=="], @@ -295,11 +295,11 @@ "@nodelib/fs.walk": ["@nodelib/fs.walk@1.2.8", "", { "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg=="], - "@opencode-ai/client": ["@opencode-ai/client@0.0.0-dev-18516", "", { "dependencies": { "@opencode-ai/protocol": "0.0.0-dev-18516", "@opencode-ai/schema": "0.0.0-dev-18516" }, "peerDependencies": { "effect": "4.0.0-rc.111", "solid-js": ">=1.9.0" }, "optionalPeers": ["effect", "solid-js"] }, "sha512-Mirtx/MIk0IxppfYGNhjwiDxMkH6tRKbaC2zS2m5nfA1trm2UPAq/MmFCgaKjZjAg/oiG2TEhvjT8HlVYz+D3Q=="], + "@opencode-ai/client": ["@opencode-ai/client@0.0.0-dev-18535", "", { "dependencies": { "@opencode-ai/protocol": "0.0.0-dev-18535", "@opencode-ai/schema": "0.0.0-dev-18535" }, "peerDependencies": { "effect": "4.0.0-rc.112", "solid-js": ">=1.9.0" }, "optionalPeers": ["effect", "solid-js"] }, "sha512-rmStzHx3SA97uyz8sW+qv1piO4tdy0a6+vNzunpGfI5srfzUff5WAFRGK4Bc6xZ/bKJ4P2zqwBeoxljk0nIdVw=="], - "@opencode-ai/protocol": ["@opencode-ai/protocol@0.0.0-dev-18516", "", { "dependencies": { "@opencode-ai/schema": "0.0.0-dev-18516", "effect": "4.0.0-rc.111" } }, "sha512-IhjPwVDt0aGJb3aN63riUUte0B5ScrBhwmajeBM/L3CU8YUgndIZv+XWxCZhCp0KOj3zKWdyrSMd/nlwAeyO2A=="], + "@opencode-ai/protocol": ["@opencode-ai/protocol@0.0.0-dev-18535", "", { "dependencies": { "@opencode-ai/schema": "0.0.0-dev-18535", "effect": "4.0.0-rc.112" } }, "sha512-hNk03O1c6cHFaQrArbL7ATEIPptFmlvBkIfsesXhiJG3jBwtZg/JX8937+5XHMI/55c6BGW0QQl45QXelTHw2w=="], - "@opencode-ai/schema": ["@opencode-ai/schema@0.0.0-dev-18516", "", { "dependencies": { "@standard-schema/spec": "1.1.0", "effect": "4.0.0-rc.111" } }, "sha512-WbNo0D6u6NG4En9zKdDfJLtP5DutgWDH3K7sckn3OtHElHLGNbaQ/dV/8qPQNDhrbac2uxfJDGtoND0ku7f0zA=="], + "@opencode-ai/schema": ["@opencode-ai/schema@0.0.0-dev-18535", "", { "dependencies": { "@standard-schema/spec": "1.1.0", "effect": "4.0.0-rc.112" } }, "sha512-O4oUxyMESm+IVKvP2/DM+mi4fGzzaAto9K0QzQxwcC3Pv1jd1CUfn69p6FywVUn60hI4EIlr+FoXcyHyaCltZA=="], "@opencode-drive/catalog": ["@opencode-drive/catalog@workspace:apps/catalog"], @@ -563,7 +563,7 @@ "dir-glob": ["dir-glob@3.0.1", "", { "dependencies": { "path-type": "^4.0.0" } }, "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA=="], - "effect": ["effect@4.0.0-rc.111", "", { "dependencies": { "@standard-schema/spec": "^1.1.0", "fast-check": "^4.9.0", "msgpackr": "^2.0.5" } }, "sha512-ASd5L58EIR0CUNueZNKKjSsyOCd+2alxOAIaTcHaqkJkPsaYSsw5Cg/cfANk5K4Jr2YsX756xvX11shzqsreWA=="], + "effect": ["effect@4.0.0-rc.112", "", { "dependencies": { "fast-check": "^4.9.0", "msgpackr": "^2.0.5" } }, "sha512-wXxwuh1Ywnv4cPRM3Wfa0vDwuOHnZ1TsTgHJkG9XgzND6inhBH9n1vBxhg3iIXOia/OrpmvVmd3lrD4vq6bF3A=="], "emoji-regex": ["emoji-regex@10.6.0", "", {}, "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A=="], diff --git a/package.json b/package.json index 4a28bf2..2e062a9 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,6 @@ "@changesets/cli": "2.31.0" }, "overrides": { - "@effect/platform-node-shared": "4.0.0-rc.111" + "@effect/platform-node-shared": "4.0.0-rc.112" } } diff --git a/packages/drive/README.md b/packages/drive/README.md index dd69af7..aed0778 100644 --- a/packages/drive/README.md +++ b/packages/drive/README.md @@ -9,10 +9,10 @@ This project gives your agents control over OpenCode: OpenCode Drive requires [Bun](https://bun.sh/) 1.3.14 or newer. MP4 recording export also requires `ffmpeg` on `PATH`. -Effect programs must use `effect@4.0.0-rc.111`, Drive's exact peer dependency. +Effect programs must use `effect@4.0.0-rc.112`, Drive's exact peer dependency. The platform and test packages use the same release as the current V2 client, -`@opencode-ai/client@0.0.0-dev-18516`. Effect's `latest` tag still selects V3; -`rc.112` is newer but does not satisfy this client's exact Effect requirement. +`@opencode-ai/client@0.0.0-dev-18535` and its matching protocol and schema +packages. Effect's `latest` tag still selects V3; install the exact V4 peer. Install dependencies with: diff --git a/packages/drive/package.json b/packages/drive/package.json index 7b4fd31..b989929 100644 --- a/packages/drive/package.json +++ b/packages/drive/package.json @@ -58,10 +58,10 @@ "release:validate": "bun run check && bun run test && bun pm pack --dry-run" }, "dependencies": { - "@effect/platform-node": "4.0.0-rc.111", - "@effect/platform-node-shared": "4.0.0-rc.111", + "@effect/platform-node": "4.0.0-rc.112", + "@effect/platform-node-shared": "4.0.0-rc.112", "@napi-rs/canvas": "1.0.2", - "@opencode-ai/client": "0.0.0-dev-18516", + "@opencode-ai/client": "0.0.0-dev-18535", "@opentui/core": "0.4.5", "@types/bun": "1.3.13", "@typescript/native-preview": "7.0.0-dev.20251207.1", @@ -69,12 +69,12 @@ "@wterm/ghostty": "0.3.0" }, "peerDependencies": { - "effect": "4.0.0-rc.111" + "effect": "4.0.0-rc.112" }, "devDependencies": { - "@effect/vitest": "4.0.0-rc.111", + "@effect/vitest": "4.0.0-rc.112", "@tsconfig/bun": "1.0.9", - "effect": "4.0.0-rc.111", + "effect": "4.0.0-rc.112", "oxlint": "1.60.0", "oxlint-tsgolint": "0.21.0", "typescript": "5.8.2", From fec5b1a73b44b35477303a90f3d296cc54cca138 Mon Sep 17 00:00:00 2001 From: Kit Langton Date: Thu, 27 Aug 2026 23:59:47 -0400 Subject: [PATCH 3/3] chore(drive): release 2.0.0 --- .changeset/abandoned-response-not-failure.md | 5 --- .changeset/bright-keys-float.md | 5 --- .changeset/chaos-network-proxy.md | 9 ----- .changeset/current-v2.md | 20 ----------- .changeset/recording-annotations.md | 5 --- .changeset/tool-transport-hardening.md | 5 --- .changeset/wait-timeout-split.md | 5 --- packages/drive/CHANGELOG.md | 38 ++++++++++++++++++++ packages/drive/package.json | 2 +- 9 files changed, 39 insertions(+), 55 deletions(-) delete mode 100644 .changeset/abandoned-response-not-failure.md delete mode 100644 .changeset/bright-keys-float.md delete mode 100644 .changeset/chaos-network-proxy.md delete mode 100644 .changeset/current-v2.md delete mode 100644 .changeset/recording-annotations.md delete mode 100644 .changeset/tool-transport-hardening.md delete mode 100644 .changeset/wait-timeout-split.md diff --git a/.changeset/abandoned-response-not-failure.md b/.changeset/abandoned-response-not-failure.md deleted file mode 100644 index c84264c..0000000 --- a/.changeset/abandoned-response-not-failure.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"opencode-drive": patch ---- - -A served or queued LLM response whose backend detaches mid-stream (for example `server.kill()` while a reply is streaming) is now abandoned instead of recorded as a controller failure. Previously the interrupt-only cause poisoned the run with a phantom `LlmControllerError: All fibers interrupted without error`, making restart scenarios impossible to script. diff --git a/.changeset/bright-keys-float.md b/.changeset/bright-keys-float.md deleted file mode 100644 index 31ff5e9..0000000 --- a/.changeset/bright-keys-float.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"opencode-drive": minor ---- - -Add an opt-in KeyCastr-style overlay for semantic key presses in screenshots and recording exports. diff --git a/.changeset/chaos-network-proxy.md b/.changeset/chaos-network-proxy.md deleted file mode 100644 index 7d7e1c8..0000000 --- a/.changeset/chaos-network-proxy.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -"opencode-drive": minor ---- - -Add a controllable chaos network proxy between launched TUIs and the OpenCode server, plus configurable simulated-LLM timeouts. - -Enabling the new `network` option (on `defineScript`, driver options, and instance options) routes every launched TUI through a chaos TCP proxy: TUIs connect with an explicit `--server` pinned to the proxy and authenticate through the registered service password, so reconnects always cross the proxy, the TUI never elects a replacement server, and the drive control plane plus the driver's SDK client stay unaffected. Scripts and drivers control conditions through the new `network` capability: `set({ latencyMs, jitterMs, refuseNew, blackhole })` (replace-whole-state semantics), `clear()`, `killConnections()`, and `connections()`. The proxy resolves its upstream lazily from the service registration, so it follows server restarts that change ports. - -The new `llm` option (`requestTimeout`, `settlementTimeout`) surfaces the existing LLM controller timeouts for scenarios that intentionally hold responses open longer than the 30s defaults. diff --git a/.changeset/current-v2.md b/.changeset/current-v2.md deleted file mode 100644 index 609e2ba..0000000 --- a/.changeset/current-v2.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -"opencode-drive": major ---- - -Update Drive to the current OpenCode V2 client (`0.0.0-dev-18535`) and its -matching Effect V4 stack (`4.0.0-rc.112`). Effect is now an exact peer dependency -so consumer programs and Drive share the same Effect types and runtime. -The client, protocol, schema, platform, and test packages use the same -coherent `rc.112` stack. - -Migrate schema-backed errors and RPC JSON codecs, and preserve optional CLI -boolean flags with explicit false defaults. Static tool adapters now emit -native V2 progress metadata, result metadata, and `Tool.Error` failures. - -Dynamic tool controls follow the current V2 protocol: change -`invocation.progress({ structured: { phase: "searching" } })` to -`invocation.progress({ phase: "searching" })`, and read the model call ID from -`invocation.context.id` instead of `invocation.context.callID`. -`finish({ structured, content })` and LLM queue/send/serve/title sequencing, -cancellation, reconnection, supervision, and settlement retain their contracts. diff --git a/.changeset/recording-annotations.md b/.changeset/recording-annotations.md deleted file mode 100644 index 132fe17..0000000 --- a/.changeset/recording-annotations.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"opencode-drive": minor ---- - -Annotated recording exports. `tui.recording.mark(label)` labels the current instant during a recorded run; marks become a burned-in footer in the exported video (segment label bottom-left, elapsed timecode and "drive" branding bottom-right). `exportRecording` gains `footer`, `annotations`, and `clips` options — clips trim, re-speed (`speed`), and freeze (`holdMs`) segments of the raw timeline, concatenated in order. `SampledFrame` now carries `sourceAtMs` (raw timeline time before trim/rebase) alongside the exported `atMs`. diff --git a/.changeset/tool-transport-hardening.md b/.changeset/tool-transport-hardening.md deleted file mode 100644 index 39aa825..0000000 --- a/.changeset/tool-transport-hardening.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"opencode-drive": patch ---- - -Fix two controlled-tool transport defects: `/execute` requests are exempt from Bun's idle timeout (a silent controlled tool no longer has its transport killed at the 255s ceiling), and plugin tool results no longer carry an `output` value, which opencode's tool runtime rejects for tools that declare no output schema. diff --git a/.changeset/wait-timeout-split.md b/.changeset/wait-timeout-split.md deleted file mode 100644 index 448f9ea..0000000 --- a/.changeset/wait-timeout-split.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"opencode-drive": minor ---- - -Split wait deadlines from control-plane timeouts. `ui.waitFor`, `ui.getElement`, and `ui.getNode` now fail with the new catchable `UiWaitTimeoutError` when their deadline passes, so scripts can branch on "did X appear in time?" (for example with `Effect.catchTag("UiWaitTimeoutError", ...)`). `UiTimeoutError` is reserved for unanswered UI RPCs — an unresponsive control plane — and remains fatal to script runs even when caught. diff --git a/packages/drive/CHANGELOG.md b/packages/drive/CHANGELOG.md index 9e0b14e..cf838fa 100644 --- a/packages/drive/CHANGELOG.md +++ b/packages/drive/CHANGELOG.md @@ -1,5 +1,43 @@ # opencode-drive +## 2.0.0 + +### Major Changes + +- 04013ce: Update Drive to the current OpenCode V2 client (`0.0.0-dev-18535`) and its + matching Effect V4 stack (`4.0.0-rc.112`). Effect is now an exact peer dependency + so consumer programs and Drive share the same Effect types and runtime. + The client, protocol, schema, platform, and test packages use the same + coherent `rc.112` stack. + + Migrate schema-backed errors and RPC JSON codecs, and preserve optional CLI + boolean flags with explicit false defaults. Static tool adapters now emit + native V2 progress metadata, result metadata, and `Tool.Error` failures. + + Dynamic tool controls follow the current V2 protocol: change + `invocation.progress({ structured: { phase: "searching" } })` to + `invocation.progress({ phase: "searching" })`, and read the model call ID from + `invocation.context.id` instead of `invocation.context.callID`. + `finish({ structured, content })` and LLM queue/send/serve/title sequencing, + cancellation, reconnection, supervision, and settlement retain their contracts. + +### Minor Changes + +- 6e16c14: Add an opt-in KeyCastr-style overlay for semantic key presses in screenshots and recording exports. +- b02239e: Add a controllable chaos network proxy between launched TUIs and the OpenCode server, plus configurable simulated-LLM timeouts. + + Enabling the new `network` option (on `defineScript`, driver options, and instance options) routes every launched TUI through a chaos TCP proxy: TUIs connect with an explicit `--server` pinned to the proxy and authenticate through the registered service password, so reconnects always cross the proxy, the TUI never elects a replacement server, and the drive control plane plus the driver's SDK client stay unaffected. Scripts and drivers control conditions through the new `network` capability: `set({ latencyMs, jitterMs, refuseNew, blackhole })` (replace-whole-state semantics), `clear()`, `killConnections()`, and `connections()`. The proxy resolves its upstream lazily from the service registration, so it follows server restarts that change ports. + + The new `llm` option (`requestTimeout`, `settlementTimeout`) surfaces the existing LLM controller timeouts for scenarios that intentionally hold responses open longer than the 30s defaults. + +- 56c42f5: Annotated recording exports. `tui.recording.mark(label)` labels the current instant during a recorded run; marks become a burned-in footer in the exported video (segment label bottom-left, elapsed timecode and "drive" branding bottom-right). `exportRecording` gains `footer`, `annotations`, and `clips` options — clips trim, re-speed (`speed`), and freeze (`holdMs`) segments of the raw timeline, concatenated in order. `SampledFrame` now carries `sourceAtMs` (raw timeline time before trim/rebase) alongside the exported `atMs`. +- b7ddb73: Split wait deadlines from control-plane timeouts. `ui.waitFor`, `ui.getElement`, and `ui.getNode` now fail with the new catchable `UiWaitTimeoutError` when their deadline passes, so scripts can branch on "did X appear in time?" (for example with `Effect.catchTag("UiWaitTimeoutError", ...)`). `UiTimeoutError` is reserved for unanswered UI RPCs — an unresponsive control plane — and remains fatal to script runs even when caught. + +### Patch Changes + +- 97d65df: A served or queued LLM response whose backend detaches mid-stream (for example `server.kill()` while a reply is streaming) is now abandoned instead of recorded as a controller failure. Previously the interrupt-only cause poisoned the run with a phantom `LlmControllerError: All fibers interrupted without error`, making restart scenarios impossible to script. +- c591d43: Fix two controlled-tool transport defects: `/execute` requests are exempt from Bun's idle timeout (a silent controlled tool no longer has its transport killed at the 255s ceiling), and plugin tool results no longer carry an `output` value, which opencode's tool runtime rejects for tools that declare no output schema. + ## 1.4.5 ### Patch Changes diff --git a/packages/drive/package.json b/packages/drive/package.json index b989929..fb24fef 100644 --- a/packages/drive/package.json +++ b/packages/drive/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "opencode-drive", - "version": "1.4.5", + "version": "2.0.0", "description": "Drive real and simulated OpenCode instances", "license": "MIT", "repository": {