Skip to content

feat(sdk): add ConfigProvider seam to embedded OpenCode hosts - #34920

Closed
kitlangton wants to merge 2 commits into
config-ownershipfrom
embedded-config-seam
Closed

kitlangton wants to merge 2 commits into
config-ownershipfrom
embedded-config-seam

Conversation

@kitlangton

@kitlangton kitlangton commented Jul 2, 2026 •

Copy link
Copy Markdown
Contributor

Stacked on #34846. Follow-up to the sharp edge noted there: the default ConfigProvider.fromEnv() snapshots the process environment on first use, so runtime env mutation cannot steer later layer builds — and embedded OpenCode.create() had no way to inject a provider.

What changed

packages/sdk-next/src/opencode.ts

  • OpenCode.create(options?) accepts an optional configProvider. When present, it is built once into a ConfigProvider.layer and provided to both the application-node build and the embedded routes layer, so config reads during that host's layer builds — for example OPENCODE_DB database placement — resolve against it.
  • Scope is documented precisely: the seam covers the host's process-global layer builds. Location-scoped layers (currently only the websearch config) build lazily outside host construction and still read the process default; threading the provider into Location builds is possible follow-up work in LocationServiceMap if a real need appears.
  • Replacement semantics are deliberate: the host's provider fully replaces the default. Hosts that want environment fallback compose it explicitly with ConfigProvider.orElse(ConfigProvider.fromEnv()).
  • OpenCode.layerWith(options) mirrors create(options) for the layer form (naming follows core's Global.layerWith); layer is now layerWith({}).

packages/sdk-next/test/embedded.test.ts

  • Drops the file-scoped shared process.env.OPENCODE_DB workaround from refactor(core): resolve database and websearch config through Effect Config #34846. Each embedded host now gets its own database through the seam: OpenCode.create({ configProvider: ConfigProvider.fromUnknown({ OPENCODE_DB: ... }) }).
  • The first test asserts end to end that the database materializes at the path the host's ConfigProvider chose — per-host placement that env mutation fundamentally could not express.

Review notes

  • memoMap deduplication is unaffected: Layer.provide wraps without rewriting inner layer identities, and both builds inside one create() share one memoMap and one provider, so memoized leaves stay consistent.
  • Known adjacent footgun (pre-existing, untouched): packages/server/src/routes.ts webHandler() builds a fresh memoMap — and therefore a fresh database — per call. It has no production consumers today; worth deleting or memoizing separately.

Verification

  • bun typecheck in packages/sdk-next
  • packages/sdk-next suite: 5 pass / 0 fail
  • oxlint + Prettier on changed files
  • Three-agent simplify/safety review pass; findings addressed

@kitlangton

Copy link
Copy Markdown
Contributor Author

Superseded by #34935, which consolidates this and #34846 against the v2 branch.

@kitlangton kitlangton closed this Jul 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant