packages/workerd-spike runs the full opencode core + server stack inside a
real Durable Object via @cloudflare/vitest-pool-workers: boot with all 42
migrations journaled on real DO SQLite, session create over the HTTP API, a
complete prompt turn against a fetchMock'd OpenAI-compatible provider read
back through the durable session log cursor route, a turn that completes with
no request in flight, and recovery of a session evicted mid-turn.
Eviction is simulated with DurableObjectState.abort() between prompt-accepted
and turn-complete; a fresh instance boots over the same storage, resumes the
claimed execution, and replays the drain. The durable log stays gapless
across the death, so a consumer resuming from a pre-eviction cursor sees no
gaps and no duplicates.
The profile persists durable events because that history is what recovery
replays. Harness notes: pins pool 0.12.6 (newer pool/workerd pairings segfault
on macOS) with a patch extending the stale workerd builtin allowlist and
fixing fallback-service handling of case-insensitive filesystems, /@fs ids,
JSON requires, and unanchored module-rule globs; missing node builtins resolve
to unenv polyfills via vite aliases.
createEmbeddedRoutes accepts runtime-profile service replacements, and the
embedded SDK exposes them through EmbedOptions: overrides applied after the
standard set, plus an opt-in boot-time resume of Sessions whose execution
claim was never released, for runtimes that die without teardown.
@opencode-ai/sdk-next/workerd composes the workerd profile
(ServerWorkerd.serverOptions + replacements) with the embedded SDK, so a
Durable Object host gets the same typed client and event streams as any other
sdk-next consumer, over Durable Object SQLite, with no network hop.
Health reports pid 0 where the runtime has no OS process identity, and the
drizzle session delegates to the client's native withTransaction when the
client rejects BEGIN/SAVEPOINT (Durable Object SQLite). Node platform modules
are deep-imported so the barrel's eager undici and node:sqlite side imports
never load.
ServerWorkerd.create builds the fetch handler for a Durable Object's fetch(),
with every intentionally-local service replaced: the database runs on the
injected DO SQLite, plugin discovery is precompiled-only, MCP is remote-only,
Snapshot and Vcs degrade to empty results, and Shell/FileSystem/Pty fail with
a clear defect until a remote sandbox backs them.
Threading it through needs one seam: createRoutes and ServerFetch.make take
runtime-profile replacements applied after the standard set, so later entries
win. script/workerd-probe.ts pins that the graph bundles under the workerd
condition without bun builtins.
Resolve the native-module import conditions (#pty, #fff, #photon-wasm,
#shell-parser-wasm, #process-lock-ffi) to inert workerd stubs, so the module
graph loads in a runtime with no subprocesses, FFI, or filesystem artifacts.
Loopback OAuth servers import node:http lazily for the same reason, MCP gains
an stdio flag for runtimes that cannot spawn local servers, and Global roots
every path under one writable directory (tmp on workerd, OPENCODE_GLOBAL_ROOT
anywhere).