Skip to content

0.9.0-preview.10

Pre-release
Pre-release

Choose a tag to compare

@Blind-Striker Blind-Striker released this 14 Oct 18:01

The packages target netstandard2.0, net472, net10.0, and net11.0: net8.0 and net9.0
leave ahead of their end of support, and net11.0 joins on its go-live release candidate.
A
project on .NET 8 or 9 still installs the packages through the netstandard2.0 asset, now with a
build warning. The pin moves to upstream release tag v2.0.29, which adds provider compatibility
defaults, request-body encoding and top-level config policies. OpenCodeServer.Exited reports how
a started server ended, and on Windows a server's exit is observed on the operating system's own
wait thread, so a busy host no longer reports a crashed start as a closed stdout. The breaking
changes come first: besides the target frameworks, OpenCodeServerOptions refuses an out-of-range
timeout when it is set, IOpenCodeClientOptions is removed,
OpenCodeStreamFailureException.Cause is now Causes, and PersistentPtyReplayBounds takes
camelCase constructor parameters.

💥 Breaking changes

  • The packages target netstandard2.0, net472, net10.0, and net11.0. net8.0 and
    net9.0 leave ahead of their end of support on 2026-11-10, and net11.0 joins on its go-live
    release candidate. 0.9.0-preview.9 is the last version with net8.0 and net9.0 assets. A
    net8.0 or net9.0 project still installs the packages through the netstandard2.0 asset, now
    with a build warning, because that runtime is not one the packages are tested on; set
    <SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings> to silence it, or move
    the project to net10.0 or later. A project that treats warnings as errors fails its build on it
    until it does one or the other.
  • OpenCodeServerOptions refuses an out-of-range timeout when it is set. ReadinessTimeout
    takes a value above zero and at most int.MaxValue milliseconds, or
    Timeout.InfiniteTimeSpan to wait until the start's cancellation token fires;
    GracefulShutdownTimeout takes zero to int.MaxValue milliseconds. A value outside that range
    throws ArgumentOutOfRangeException from the setter. A zero or negative readiness timeout and a
    negative grace were refused by OpenCodeServer.StartAsync before; a value past the ceiling was
    accepted and failed only after the server had been spawned.
  • IOpenCodeClientOptions is removed. No public API accepted it, and every option added
    later would have broken its implementers, because net472 and netstandard2.0 have no default
    interface members. Configure clients through OpenCodeClientOptions, which a client still
    snapshots at construction. Code that declared a variable or parameter as
    IOpenCodeClientOptions uses OpenCodeClientOptions instead.
  • OpenCodeStreamFailureException.Cause is now Causes. It is a list of causes, so the name
    is now plural. The constructor parameter is now causes as well. Read failure.Causes where
    you read failure.Cause, and pass causes: where you named the argument.
  • PersistentPtyReplayBounds takes camelCase constructor parameters. They are
    requestedOffset, availableOffset, endOffset and truncated, like the other frame types'
    constructors. The properties keep their names, and positional construction, with and
    deconstruction are unchanged. Only a call that named an argument (RequestedOffset: 0) changes.

✨ Added

  • OpenCodeServer.Exited reports how a started server ended. The task completes with an
    OpenCodeServerExit. It holds an exit code (on Windows the full 32-bit code), a terminating
    signal by name and number, or Unknown when the exit status could not be read, for example
    because something else reaped the server. It completes whether the server ended on its own or
    disposal ended it, once its output has ended or one second after the exit, as upstream's
    exited does. It never faults. On a handle from
    DiscoverAsync or EnsureAsync it throws InvalidOperationException, because that handle owns
    no process.
  • The accepted snapshot moved to upstream release tag v2.0.29
    (042d0832f5f3a73eaa039a58a7d565776f6d4290), published as @opencode/cli@2.0.29; install it
    with npm install -g @opencode/cli@2.0.29. It adds and changes no operation, so all 142 remain
    callable.
  • Provider compatibility defaults. ProviderInfo.Compatibility and
    ConfigProvider.Compatibility carry a ProviderCompatibility, the defaults a provider's models
    inherit: ReasoningField, RequireReasoning, MaxTokensField, RequireFinishReason,
    RequireAssistantAfterTool, SupportsPromptCacheKey, and CacheFormat.
  • Prompt-cache marker format. ModelCompatibility.CacheFormat and
    ProviderCompatibility.CacheFormat name the marker syntax the endpoint accepts, as the new
    ModelCacheFormat enum (Anthropic, Alibaba).
  • Request-body encoding. ProviderSettings.Encoding, ConfigProviderSettings.Encoding,
    ModelSettings.Encoding, and ConfigModelSettings.Encoding name the compression upstream applies
    to the provider request body, as the new ProviderEncoding enum (Zstd, Gzip, None).
  • Top-level config policies. ConfigInfo.Policies carries the ordered policies that control
    access to providers, tools, and integrations, as the new ConfigInfoPolicies (Action,
    Resource, Effect) with the new ConfigInfoPoliciesAction (ProviderUse, ToolUse,
    IntegrationUse) and ConfigInfoPoliciesEffect (Allow, Deny) enums. Upstream deprecates
    experimental.policies: a 2.0.29 server reports those policies here, and
    ConfigInfoExperimental.Policies stays null.

🔧 Changes

  • The packages depend on the .NET 10.0.13 servicing builds of their dependencies.
    OpenCodeDotNet.Sdk requires System.Text.Json, Microsoft.Bcl.AsyncInterfaces,
    Microsoft.Bcl.Memory, Microsoft.Bcl.TimeProvider, System.Collections.Immutable, and
    System.Threading.Channels 10.0.13 on netstandard2.0 and net472, up from 10.0.11; its
    net10.0 and net11.0 assets declare no dependency. OpenCodeDotNet.Sdk.Extensions requires
    Microsoft.Extensions.DependencyInjection.Abstractions and
    Microsoft.Extensions.Options.ConfigurationExtensions 10.0.13 on every target, up from 10.0.10.
    No security advisory covers the versions they replace. A project that references one of these
    packages directly at a lower version must raise it, or restore reports a package downgrade
    (NU1605, an error by default).

  • A server that does not report readiness in time fails with the timeout as the inner
    exception.
    The OpenCodeServerException that OpenCodeServer.StartAsync throws then carries
    the readiness bound's OperationCanceledException as its InnerException, which was null.

  • A settings encoding member is read as the typed Encoding. On ProviderSettings,
    ConfigProviderSettings, ModelSettings, and ConfigModelSettings it is no longer in
    AdditionalProperties, where 0.9.0-preview.9 kept it as an undeclared member.

  • The source is laid out in feature folders, and the internal namespaces are flattened into
    OpenCode.Sdk.Internal.
    The public API is unchanged, byte for byte. Only the names of internal
    types differ, as a stack trace or reflection shows them.

🐛 Fixes

  • On a busy Windows host, a server's exit is no longer reported late. The launcher learned of a
    Windows server's exit through a callback queued to the .NET thread pool, so under load it could
    arrive seconds after the server had exited. A server that exited before readiness then failed
    its start as one that closed its stdout, without its exit code; OpenCodeServer.Exited
    completed late; and ending a server that had already exited could still end the descendants it
    left running. The exit is now observed on the operating system's own wait thread, as libuv
    observes it, so each of these reads the exit as soon as the kernel reports it.
  • OpenCodeServer.EnsureAsync started through a .cmd or .bat shim on Windows opens no
    console window.
    With a batch shim such as npm's opencode.cmd as the command, the background
    service took a new console of its own, with a visible terminal window that took the focus and
    stayed open for the service's life, and its startup output went to that window instead of to
    the SDK. The shim now starts with a console that has no window, which the service inherits, so
    its window stays hidden and its startup output reaches the SDK again. A service started from an
    .exe still starts detached, with no console.
  • On Unix under Mono, a failed chmod of an owner-only file fails its write. The
    netstandard2.0 and net472 assets set mode 0600 on the files discovery and EnsureAsync
    write through a chmod child process after the create. That process now receives a quoted path,
    and a nonzero exit removes the file and fails the create, as the modern targets' atomic
    owner-only create does. Behaviour change: such a file was kept at the process umask before.

📋 Important Notes

  • This release is built on the .NET 11 release-candidate SDK. A preview package may build on a
    go-live release candidate (ADR-0002); the first non-preview package waits for the GA SDK. The
    net11.0 asset needs the .NET 11 runtime, and a net10.0 app keeps using the net10.0 asset.
  • From 1.0.0, a minor version may move the protocol pin and change the generated surface the
    way upstream changed it, each change listed under protocol changes; only a major version breaks
    the hand-written design (ADR-0034).