Per the package style guide, sync if/return functions that need to fail
should yield the error directly via Effect.gen rather than ladder
Effect.fail / Effect.succeed across every branch.
Touches all four adapters' tool-choice lowering. The naming-required
validation now reads as 'guard, then return' rather than embedded in a
chain of monadic returns. Behavior unchanged.
Every adapter's parse already produces LLMEvents (via the process callback in
the shared sse helper), and every raise was Stream.make(event). The Chunk type
parameter, the raise field, the RaiseState interface, and the Stream.flatMap
raise step in client.stream were all pure overhead.
- Adapter contract shrinks from <Draft, Target, Chunk> to <Draft, Target>.
- All four adapters drop their raise: (event) => Stream.make(event) line.
- client.stream skips the no-op flatMap.
- AGENTS.md adapter section reflects the simpler contract.
Updates the AGENTS.md TODO list:
- mark Responses, Anthropic, and Gemini adapter coverage as done
- mark the Gemini schema sanitizer port as done
- add concrete next-step items for OpenCode integration: ModelRef bridge,
request bridge, provider-quirk patches, request/stream parity tests, and
a flagged rollout against existing session/llm.test.ts cases
- add OpenAI-compatible Chat, Bedrock Converse, and Vertex routing as
outstanding adapter/dispatch decisions
Gemini rejects integer enums, dangling required fields, untyped arrays, and
object keywords on scalar schemas. The sanitizer was previously a divergent
copy in OpenCode; this lands it in the package as a tool-schema patch with
deterministic tests and selects it for Gemini-protocol or Gemini-named models.
Also tightens the Gemini test suite: covers tool-choice none, drops the
tool-input-delta assertion that Gemini does not actually emit, and confirms
total usage stays undefined when only thoughtsTokenCount arrives.
- shared sse helper now expects Effectful decodeChunk and process callbacks,
so adapter parsers can be Effect.gen and yield typed ProviderChunkError
instead of throwing across the sync mapAccum boundary.
- parseJson returns Effect<unknown, ProviderChunkError> via Effect.try,
matching the package style guide on yieldable errors.
- OpenAI Chat finalizes accumulated tool inputs eagerly when finish_reason
arrives, surfacing JSON parse failures at the boundary instead of at halt.
onHalt stays sync and just emits from state.
- generate's runFold reducer now mutates the accumulator instead of
reallocating the events array on every chunk, dropping O(n^2) growth on
long streams.
- Structurally match recorded requests by canonical JSON so non-deterministic
field ordering doesn't break replay.
- Pluggable header allow-list and body redaction hook on the record/replay
layer, so adapters with non-default auth (Anthropic, Bedrock) can plug in
without touching this file.
- Move the cassette-name dedupe set inside recordedTests() so two describe
files using different prefixes can run in parallel.
- Replace inline SSE template literals and per-file HTTP layers with shared
test/lib helpers (sseEvents, fixedResponse, dynamicResponse, truncatedStream).
- Tighten recorded-test assertions to exact text and usage so adapter parser
regressions surface immediately instead of passing fuzzy length>0 checks.
- Add cancellation and mid-stream transport-error tests for the OpenAI Chat
adapter.
- Add cross-phase patch tests that verify each phase sees an updated
PatchContext and that same-order patches sort deterministically by id.
The bash tool description now explicitly states that the temp directory has already been created and exists, preventing agents from unnecessarily trying to create it before use.
- Removed @effect/language-service from both packages/core and packages/opencode tsconfig files and dependencies
- Wrapped mergeDeep calls in config loading and LLM streaming to avoid expensive remeda conditional merge type instantiations in hot paths
- Narrowed Drizzle migrate() overload signature to avoid expensive variance checks during database initialization
These changes reduce TypeScript type-checking overhead and improve startup and runtime performance for config loading, LLM streaming, and database migrations.