Skip to content

fix(cf-ai-gateway): route provider options through openaiCompatible key (#24432)#25573

Merged
rekram1-node merged 5 commits into
anomalyco:devfrom
NathanDrake2406:fix/cf-ai-gateway-provider-options
May 5, 2026
Merged

fix(cf-ai-gateway): route provider options through openaiCompatible key (#24432)#25573
rekram1-node merged 5 commits into
anomalyco:devfrom
NathanDrake2406:fix/cf-ai-gateway-provider-options

Conversation

@NathanDrake2406
Copy link
Copy Markdown
Contributor

@NathanDrake2406 NathanDrake2406 commented May 3, 2026

Issue for this PR

Closes #24432

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

reasoningEffort and workflow variant inputs were silently dropped for cf-ai-gateway models routed through ai-gateway-provider. The outgoing request to gateway.ai.cloudflare.com had no reasoning_effort field regardless of config.

Root cause in packages/opencode/src/provider/transform.ts:

  • sdkKey() had no "ai-gateway-provider" case, so it fell back to model.providerID = "cloudflare-ai-gateway". ai-gateway-provider/unified is createOpenAICompatible({ name: "Unified" }), and @ai-sdk/openai-compatible only reads provider options from openai-compatible / openaiCompatible / Unified / unified. Wrong key, never read.
  • variants() had no case either, so variant: xhigh returned {}.

Fix: add the sdkKey case returning "openaiCompatible" (kebab form emits a runtime deprecation warning), and a variants() case dispatching on model.api.id upstream prefix.

First commit is a refactor done so the new case could reuse logic: extracts openaiReasoningEfforts() from the @ai-sdk/openai case, names the unexplained 2025-11-13 / 2025-12-04 date literals, and replaces the gpt-5- substring matcher with an anchored regex so dotted ids like gpt-5.4 are caught.

Anthropic / Google on cf-ai-gateway resolve through bundled SDKs per models.dev and were unaffected.

How did you verify your code works?

test/provider/cf-ai-gateway-e2e.test.ts runs the real ai-gateway-provider + @ai-sdk/openai-compatible chain through a stubbed fetch and asserts reasoning_effort lands in the upstream body. Plus 7 unit tests for the variants / providerOptions / matcher changes.

bun test ... 154 pass, 0 fail

bunx tsc --noEmit clean. Manually repro'd: outgoing body went from no reasoning_effort to reasoning_effort: "xhigh".

Screenshots / recordings

N/A.

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

Copilot AI review requested due to automatic review settings May 3, 2026 09:03
@github-actions github-actions Bot added the needs:compliance This means the issue will auto-close after 2 hours. label May 3, 2026
@github-actions github-actions Bot removed the needs:compliance This means the issue will auto-close after 2 hours. label May 3, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 3, 2026

Thanks for updating your PR! It now meets our contributing guidelines. 👍

…etection

The OpenAI variants block held two undocumented date literals ("2025-11-13",
"2025-12-04") and a matcher that missed dotted gpt-5.x ids. The dates gate
which reasoning_effort tiers a model exposes, mirroring OpenAI's API rollout
schedule, but nothing in the file said so.

Extract OPENAI_NONE_EFFORT_RELEASE_DATE / OPENAI_XHIGH_EFFORT_RELEASE_DATE
with a comment naming what the dates mean, and lift the effort selection into
openaiReasoningEfforts(id, releaseDate). Replace the
"id.includes('gpt-5-') || id === 'gpt-5'" check with an anchored regex that
matches gpt-5, gpt-5-nano, gpt-5.4, openai/gpt-5.5, and rejects gpt-50 / gpt-5o.

The regex change is a real behaviour fix: gpt-5.x models now correctly expose
the "minimal" reasoning_effort tier, which OpenAI's API has accepted on the
gpt-5 family since launch. Previously variant=minimal was a no-op for any
gpt-5.x model.

Adds two regression tests pinning both halves: the dotted id now gets minimal,
and the gpt-50 lookalike still does not.
Variant input (variant: xhigh) and provider options
(provider.cloudflare-ai-gateway.models.<id>.options.reasoningEffort) on
cf-ai-gateway models routed through ai-gateway-provider were silently dropped.
Outgoing requests to gateway.ai.cloudflare.com used the OpenAI-compatible
endpoint without the reasoning_effort field set, so OpenAI upstreams ran at
their default effort regardless of user config.

sdkKey() had no case for "ai-gateway-provider" and fell back to the providerID
"cloudflare-ai-gateway". providerOptions() therefore wrote the payload under
that key, but ai-gateway-provider/unified wraps createOpenAICompatible({ name:
"Unified" }), and @ai-sdk/openai-compatible only reads compatibleOptions from
"openai-compatible" / "openaiCompatible" / "Unified" / "unified". The wrong
key was never read, so reasoningEffort never reached the request body.
variants() likewise had no "ai-gateway-provider" case, so workflow variant
inputs produced an empty options object.

Add the sdkKey case returning "openaiCompatible" (the camelCase form avoids
the SDK's deprecation warning emitted on the kebab form). Add a variants case
that dispatches on the model.api.id upstream prefix and reuses
openaiReasoningEfforts() for openai/* models, falling back to
WIDELY_SUPPORTED_EFFORTS for other upstreams since the Cloudflare /v1/compat
endpoint translates reasoning_effort to provider-native controls.

Adds an end-to-end test that wires the actual ai-gateway-provider +
@ai-sdk/openai-compatible chain through a stubbed fetch and asserts
reasoning_effort lands in the body Cloudflare AI Gateway forwards upstream.
The test also pins the legacy buggy key so a future refactor that resurrects
providerID-keyed providerOptions fails before it reaches users.

Fixes anomalyco#24432.
@NathanDrake2406 NathanDrake2406 force-pushed the fix/cf-ai-gateway-provider-options branch from ad683bd to a980260 Compare May 3, 2026 09:08

This comment was marked as low quality.

@rekram1-node
Copy link
Copy Markdown
Collaborator

/review


// Computes the reasoning_effort tiers an OpenAI (or OpenAI-compatible upstream
// routed through it, e.g. cf-ai-gateway) model exposes. Returns null for models
// with no tunable effort knob (gpt-5-pro). Effort order: weakest → strongest.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: same ASCII style note here: this new comment introduces a Unicode arrow. Consider weakest to strongest or weakest -> strongest.

import { createUnified } from "ai-gateway-provider/providers/unified"
import { ProviderTransform } from "@/provider/transform"

type Captured = { url: string; outerBody: any }
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: this new test file introduces several anys (the captured body, fetch parameters, mock model, and providerOptions). The style guide asks us to avoid any when a narrower type is practical; a small shape for the captured gateway body plus Parameters<typeof fetch> / unknown for parsed JSON would keep the regression test type-safe without much extra code.

// chain that provider.ts:811 builds at runtime, with only the network boundary
// stubbed. Asserts that `reasoning_effort` (and other provider options the
// transform emits) actually land in the body Cloudflare AI Gateway forwards
// upstream — which is the only place the bug was observable.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: the style guide says to default to ASCII when editing or creating files. This new file introduces an em dash here and Unicode arrows below; consider ASCII - / -> unless the Unicode punctuation is intentional.

NathanDrake2406 and others added 3 commits May 4, 2026 13:09
…fforts comment

A reviewer comment on PR anomalyco#25573 flagged that the new comment introduced a unicode arrow inconsistent with the repo's ASCII-default style for code comments. The arrow shows up as a glyph that does not survive every editor or terminal cleanly and breaks grep on plain ASCII.

Reword "weakest -> strongest" using ASCII so the comment matches the surrounding style guidelines without changing its meaning.
…comments

Reviewer feedback on PR anomalyco#25573 flagged two issues in the new regression test: the file used em dashes and unicode arrows in comments against the repo's ASCII-default style, and several `any` annotations (captured body, fetch parameters, mock model, providerOptions) bypassed the type system in a file whose entire purpose is catching upstream contract drift.

The wide `any` annotations meant a future change to `Provider.Model` or to the AI SDK's `providerOptions` shape would silently typecheck instead of surfacing here, which defeats the regression test. The comments used unicode purely cosmetically.

Replace `any` with the actual types the runtime uses: `Provider.Model` for the mock factory (constructed via `ModelID.make` / `ProviderID.make` to satisfy the branded ID schema), `Record<string, Record<string, JSONValue>>` for providerOptions to match what `generateText` accepts, `Parameters<typeof fetch>` for the stub's signature, and a typed `isRecord` guard to narrow parsed JSON without an `any` cast. Preserve Bun's `preconnect` method on the stub via `Object.assign` so the assignment satisfies `typeof fetch` honestly. Convert the unicode arrows and em dashes in the file's comments to ASCII.

All 283 provider tests still pass and `bunx tsc --noEmit` is clean.
@NathanDrake2406
Copy link
Copy Markdown
Contributor Author

/review

Has anyone ever told you that you look like a mix of Arnold and Andre the Giant?

@rekram1-node
Copy link
Copy Markdown
Collaborator

lol! sometimes the former but never andre hahahaaa

@rekram1-node
Copy link
Copy Markdown
Collaborator

We will merge this in today, thx for fix

@NathanDrake2406
Copy link
Copy Markdown
Contributor Author

We will merge this in today, thx for fix

ahem

@rekram1-node rekram1-node merged commit ca77b8f into anomalyco:dev May 5, 2026
8 checks passed
@rekram1-node
Copy link
Copy Markdown
Collaborator

lolll

randomm added a commit to randomm/opencode that referenced this pull request May 15, 2026
* Extract InstanceStore.provide helper (anomalyco#25372)

* Drop ALS fallbacks from containsPath and workspace routing (anomalyco#25374)

* Convert LoadInput.init to Effect + extract InstanceBootstrap as a Service (anomalyco#25376)

* chore: generate

* Migrate test inits from Promise to Effect (anomalyco#25377)

* chore: generate

* fix(httpapi): re-land workspace create payload accepts missing extra (anomalyco#25412)

* fix(httpapi): install Instance ALS for adapter Promise bridge (anomalyco#25417)

* Replace Instance.disposeAll/load with fixture helper (anomalyco#25418)

* fix(tui): keep shell-mode prompt editable (anomalyco#25419)

* upgrade opentui to 0.2.2 (anomalyco#25420)

* chore: update nix node_modules hashes

* refactor(instance-store): consolidate dispose helpers (anomalyco#25424)

* sync release versions for v1.14.32

* Delete Instance.dispose and Instance.reload (anomalyco#25427)

* chore: generate

* fix(nix): remove stale packages/shared filter (anomalyco#24930)

* docs: CLI docs for current commands and flags (anomalyco#25399)

* feat(cli): add effectCmd wrapper + convert models command (anomalyco#25429)

* chore: generate

* tweak: allow read tool to accept offset of 0 (anomalyco#25431)

* feat(models): effectify ModelsDev as Service (anomalyco#25434)

* chore: generate

* fix(telemetry): emit Tool.execute span for MCP and plugin tools (anomalyco#25452)

* refactor(cli): drop ModelsDev Promise compat shim (anomalyco#25460)

* fix(instance): restore InstanceBootstrap init parameter for non-Effec… (anomalyco#25449)

Co-authored-by: Dax Raad <d@ironbay.co>

* chore: generate

* sync release versions for v1.14.33

* refactor(cli): convert pr command to effectCmd (anomalyco#25465)

* chore: generate

* refactor(cli): convert export command to effectCmd (anomalyco#25471)

* refactor(cli): convert plugin command to effectCmd (anomalyco#25473)

* refactor(cli): convert import command to effectCmd (anomalyco#25467)

* refactor(cli): convert stats command to effectCmd (anomalyco#25474)

* chore: generate

* refactor(cli): convert session subcommands to effectCmd (anomalyco#25483)

* feat: refactor bash tool with shell-aware prompts for bash, pwsh+powershell, and cmd (anomalyco#20039)

* refactor(cli): convert debug agent command to effectCmd (anomalyco#25485)

* chore: generate

* refactor(cli): convert debug subcommands to effectCmd (anomalyco#25479)

* chore: generate

* fix(instance): run bootstrap from instance store (anomalyco#25475)

* chore: generate

* feat(cli): auto-dispose InstanceContext after effectCmd handlers (anomalyco#25481)

* docs: clarify LSP and formatter opt-in config (anomalyco#25502)

* chore: generate

* test(httpapi): add route exerciser

* chore: generate

* Normalize instance lifecycle wiring (anomalyco#25501)

* chore: generate

* refactor(cli): drop redundant explicit Effect.ensuring(store.dispose) (anomalyco#25503)

* chore: generate

* feat: default HTTP API backend to on for dev/beta channels

* feat(cli): add instance: false opt-out to effectCmd (anomalyco#25507)

* refactor(cli): convert web + account to effectCmd (instance: false) (anomalyco#25512)

* Refactor v2 session events as schemas (anomalyco#24512)

* chore: generate

* refactor(lifecycle): bootstrap as pure orchestration (anomalyco#25510)

* feat(cli): allow effectCmd instance to be a function of args (anomalyco#25517)

* refactor(cli): convert debug wait, agent list, acp to effectCmd (anomalyco#25518)

* refactor(cli): convert run command to effectCmd (anomalyco#25519)

* chore: generate

* refactor(acp): drop async from synchronous ACP.init (anomalyco#25520)

* chore: rm log statement (anomalyco#25470)

* fix(desktop): limit zoom handler to zoom keys (anomalyco#25516)

* chore(opencode): exclude .map files from CLI binary build (anomalyco#25500)

* refactor(cli): convert github subcommands to effectCmd (anomalyco#25522)

* chore: generate

* refactor(cli): convert mcp list, auth, auth list, logout to effectCmd (anomalyco#25521)

* chore: generate

* chore: bump Effect beta (anomalyco#25524)

* refactor(cli/stats): Stage 4 — fully Effect-native body (anomalyco#25523)

* fix(httpapi): pagination Link header echoes request host (anomalyco#25527)

* refactor(cli): convert agent / providers / mcp to effectCmd (anomalyco#25525)

* chore: generate

* fix(session): encode v2 session responses (anomalyco#25528)

* chore: update nix node_modules hashes

* fix: regression w/ auth login where stderr was ignored instead of inherited (anomalyco#25529)

* refactor(cli/mcp+agent): Stage 4 — drop AppRuntime.runPromise bridges (anomalyco#25530)

* refactor(cli/providers): Stage 4 — drop inline AppRuntime.runPromise calls (anomalyco#25532)

* fix(cli): bridge Instance.current ALS in effectCmd handlers (regression from anomalyco#25522) (anomalyco#25546)

* Add debug info command (anomalyco#25550)

* ci

* core: update triage agent to use qwen3.6-plus model for improved response quality

* core: simplify triage workflow to focus on issue ownership

Switch triage agent to gpt-5.4-nano for faster issue assignment. Remove label
management from the triage tool so it only assigns owners based on team
ownership rules. This reduces noise in the issue tracker and ensures issues
get to the right team member immediately without unnecessary labels.

Update team structures to reflect current ownership and add script for
processing unassigned issues.

* chore: generate

* ci: remove automatic labels from GitHub issue templates to allow manual triage

* ci: remove vouch-based contributor filtering workflows

Removes the automated vouch system that filtered issues and PRs from non-vouched users. This simplifies the contribution process by removing the requirement for maintainers to manually vouch contributors before they can participate.

* ci: stop sending daily community recap notifications

* ignore: remove triage-unassigned.ts script

This script was used to batch-triage open GitHub issues without assignees.
Removing as the triage workflow has evolved and this batch approach is no longer needed.

* fix(vcs): avoid unbounded diff memory usage (anomalyco#25581)

* refactor(server): extract Hono-coupled utilities to backend-neutral modules (anomalyco#25542)

* chore: generate

* feat(server): Server.openapi() backed by HttpApi spec, parity-checked against Hono output (anomalyco#25545)

* chore: generate

* feat(server): native HttpApi listener with Bun.serve + WS upgrade (anomalyco#25547)

* fix(acp): pass server auth to internal client (anomalyco#25591)

* fix(sdk+cli): surface real errors instead of bare {} when server returns empty body (anomalyco#25592)

* chore: generate

* fix(httpapi): add basic auth challenge for browser login

Adds a WWW-Authenticate challenge for unauthorized experimental HttpApi UI fallback responses so browsers open the Basic Auth prompt when a server password is configured.

* chore: generate

* ci: only build electron desktop (anomalyco#19067)

* feat: group changelog bugfixes (anomalyco#25597)

* fix(auth): respect server username in clients (anomalyco#25596)

* refactor(config+core): drop ConfigPaths.readFile, add AppFileSystem.readFileStringSafe, flatten TuiConfig.loadState (anomalyco#25602)

* chore: generate

* refactor(cli/github+run): Stage 4 — drop AppRuntime.runPromise bridges (anomalyco#25539)

* refactor(cli/providers): flatten — Effect-native handlers end-to-end (anomalyco#25537)

* chore: generate

* fix(auth): add username option for basic auth in RunCommand (anomalyco#25600)

Co-authored-by: Shoubhit Dash <shoubhit2005@gmail.com>

* fix(server): support desktop PTY websockets with HttpApi (anomalyco#25598)

* chore: generate

* Add v2 session failure events (anomalyco#25628)

* chore: generate

* fix(server): serve embedded UI from bunfs (anomalyco#25632)

* chore: generate

* refactor(cli): effectify provider commands (anomalyco#25633)

* fix(app): preserve auth token credentials (anomalyco#25636)

* Effectify plugin agent regression test (anomalyco#25646)

* fix: allow Codex Spark with Codex OAuth (anomalyco#25640)

* feat(server): pty websocket auth tickets (anomalyco#25660)

* chore: generate

* fix(app): prevent terminal recovery loops (anomalyco#25710)

* chore: generate

* fix(opencode): strip transfer-encoding in UI proxy and allow public manifest assets (anomalyco#25698)

Co-authored-by: Kit Langton <kit.langton@gmail.com>

* test(server): regression reproducers for anomalyco#25698 (anomalyco#25714)

* chore: generate

* fix: ensure anthropic sdk properly resolves when using azure (anomalyco#25721)

* sync

* chore(docs): rename firmware provider to frogbot (anomalyco#25453)

* fix(worktree): fork workspace worktree boot (anomalyco#25723)

* fix(server): provide fresh ConfigProvider per HttpApi listener (anomalyco#25726)

* test(agent): skip InstanceBootstrap in plugin-agent regression test (anomalyco#25737)

* sync

* fix: ensure effect server middleware properly parses errors (anomalyco#25717)

* sync release versions for v1.14.34

* fix(vcs): preserve batched patch boundaries (anomalyco#25787)

* chore: generate

* sync release versions for v1.14.35

* Run UI unit tests in CI (anomalyco#25792)

* update: normalize download asset names to match new naming convention (anomalyco#25796)

* feat(core): session warping (anomalyco#25768)

* chore: generate

* devex: Enable Electron MCP servers with DevTools debug port (anomalyco#25795)

* fix(tui): fix type error for calling workspace.warp (anomalyco#25801)

* fix(console): remove Cloudflare cache config from download fetch (anomalyco#25804)

* docs: restore v2 todo

* Improve v2 session message rendering (anomalyco#25634)

* fix(session): cancel subtask child sessions (anomalyco#25798)

* chore: generate

* fix(desktop): stabilize Windows titlebar zoom (anomalyco#25813)

* chore: generate

* refactor(desktop): consolidate desktop-electron into desktop package (anomalyco#25822)

* fix(desktop): update main process (anomalyco#25825)

* chore: update nix node_modules hashes

* sync release versions for v1.14.37

* fix(desktop): trust system certificates (anomalyco#25837)

* fix(server): allow all connect-src origins in CSP for embedded UI (anomalyco#25838)

* chore: update nix node_modules hashes

* sync release versions for v1.14.38

* fix(desktop): add error handling to store-get IPC handler (anomalyco#25850)

* fix(desktop): respect proxy environment (anomalyco#25846)

* fix(compaction): order compaction summary before retained tail (anomalyco#25851)

* sync release versions for v1.14.39

* chore: configure alerting and monitoring (anomalyco#25857)

* chore: update nix node_modules hashes

* fix: ensure mistral medium 3.5 has variants properly setup (anomalyco#25887)

* fix: retry server_is_overloaded errors (anomalyco#25888)

* fix(TUI): update agent create target path from "/agent" to "/agents" (anomalyco#14427)

* fix(core): better state handling of editor context (anomalyco#25911)

* fix(core): use current workspace with /new; fix warping into local project (anomalyco#25894)

* chore: generate

* fix(cf-ai-gateway): route provider options through openaiCompatible key (anomalyco#24432) (anomalyco#25573)

* chore: generate

* fix: sanitize surrogates (anomalyco#25934)

* chore: generate

* fix(server): restore web terminal CSP allowances (anomalyco#25937)

* fix(app): require query functions for sync queries (anomalyco#25939)

* Type session not-found errors (anomalyco#25818)

* chore: generate

* docs: update desktop app references from Tauri to Electron (anomalyco#25965)

* chore: generate

* feat(desktop): add OPENCODE_TEST_ONBOARDING env (anomalyco#25968)

* chore: generate

* go: restore Kimi K2.6 limits (anomalyco#25969)

* fix(desktop): suppress browser API Sentry errors in prod (anomalyco#25972)

* sync

* fix(desktop): disable auto install on app quit (anomalyco#25976)

* fix(desktop): suppress EPIPE errors in console transport (anomalyco#25980)

* docs: fix CLI attach section order (anomalyco#25749)

* fix(ui): preserve SVG tags in DOMPurify config for KaTeX math rendering (anomalyco#25866)

* chore(desktop): add @parcel/watcher platform packages to optionalDependencies (anomalyco#25996)

* feat(desktop): implement clipboard write permission handling (anomalyco#25998)

* fix(tui): preserve selected model on refresh (anomalyco#25993)

* chore: update nix node_modules hashes

* fix(tui): filter only connected workspaces in dialog; add warp synthetic message (anomalyco#25915)

* chore: fix model alerts (anomalyco#25990)

* fix(cli): avoid AppRuntime re-entry for network options (anomalyco#26052)

* feat(config): support well-known remote_config (anomalyco#26054)

* chore: generate

* ignore: vimtor to team members list

* go: deprecate old models

* chore: change alert type for honeycomb triggers

* sync

* zen: update rate limiter

* fix(server): apply cors before legacy auth (anomalyco#26092)

* fix(provider): preserve assistant message content when reasoning blocks present (anomalyco#21370)

Co-authored-by: Omer Koren <54630488+omer-koren@users.noreply.github.com>
Co-authored-by: Aiden Cline <aidenpcline@gmail.com>

* feat: Update ACP support, modernize and fix misc issues (anomalyco#25663)

* sync release versions for v1.14.40

* chore: update nix node_modules hashes

* zen: nano not used for title gen

* go: rate limit metadata

* docs: add opencode-jfrog-plugin to ecosystem list for JFrog integration (anomalyco#26019)

* fix(desktop): add macOS settings menu entry (anomalyco#26081)

Co-authored-by: jesse.mahnken <jesse.mahnken@tiefox.de>

* feat(desktop): move server to utilityProcess (anomalyco#25962)

Co-authored-by: LukeParkerDev <10430890+Hona@users.noreply.github.com>

* fix(format): restore stdout/stderr ignore for formatter processes (anomalyco#26037)

Co-authored-by: Aiden Cline <aidenpcline@gmail.com>

* fix(sync): restore packages/sdk/copilot and fix truncation import paths

* fix(sync): restore missing bun/registry and util/proxied modules after upstream sync

* fix(sync): remove stale codesearch import from registry after upstream sync

* fix(sync): restore missed fork-protected files (message-v2, plugin, processor, permission, batch.txt)

* fix(sync): restore fork features and manifest from dev

* docs(sync): add 2026-05-07 upstream sync report

* fix(sync): apply storage.ts formatting from upstream merge

* fix: resolve pre-existing build and database blockers

- Fix FIX 1 (Binary build): Replace incorrect import of createSolidTransformPlugin with correct default import of solidTransformPlugin from @opentui/solid/bun-plugin (lines 7 and 54 in build.ts)
- Fix FIX 2 (Database): Add missing SessionMessageTable with columns id, session_id, type, time_created, and data for storing session messages
- Fix FIX 3 (Package scripts): Add missing fix-node-pty script to package.json to resolve postinstall failure

* chore(sync): update models snapshot post-build

* fix(sync): restore upstream compaction/transform, port streamAfter onto upstream message-v2

* fix(sync): add missing ID prefixes from upstream (event, workspace, entry, account)

* fix(sync): restore upstream dependencies lockfile

* fix(sync): update @ai-sdk/provider-utils API calls to match v4.0.23 exports

- Rename createProviderDefinedToolFactoryWithOutputSchema to createProviderToolFactoryWithOutputSchema
- Rename createProviderDefinedToolFactory to createProviderToolFactory
- Fix LSP client namespace exports to be properly re-exported
- Update all copilot SDK tool definitions to use new API names

Fixes build errors blocking sync/upstream-2026-05-07 branch.

* chore(sync): update dependencies and models snapshot post-build

* fix(sync): defer zod(s) evaluation in schema withStatics and Object.assign to avoid Effect AST initialization crash

- Convert 65+ occurrences of eager zod: zod(s) to lazy getters in withStatics() calls
- Convert Object.assign zod properties to getters for lazy evaluation
- Make static zod properties getters in Schema.Class declarations
- Remove eager zod() call from optionalOmitUndefined to avoid Effect beta AST initialization issue
- Add safety checks in effect-zod walker to handle undefined encoding during schema construction

This fixes startup crashes in Effect 4.0.0-beta.59 where AST nodes don't have .encoding
initialized until schema construction completes, but eager zod() calls were accessing
it before completion.

* fix(sync): defer zod() evaluation in remaining 5 schema files - keybinds, pty, control-plane, provider, project

- Convert eager zod: zod(schema) to lazy getters in withStatics() for pty, control-plane, provider (2x), project schemas
- Use Proxy-based lazy evaluation for keybinds.ts to defer module-load-time zod() call
- Update withStatics() helper to properly copy property descriptors (getters/setters) via Object.defineProperty

This completes the fix for avoiding Effect AST initialization crashes by deferring all eager zod() calls to runtime access time.

* fix(sync): pin Effect to beta.57 to resolve AST initialization crash

* fix(sync): restore upstream schema/Effect files — dev versions incompatible with Effect beta.57

* fix(sync): make keybinds.ts zod() evaluation lazy for Effect beta.57 compatibility

* fix: convert eager zod() calls to lazy getters + defensive encoding check

29 withStatics patterns changed from zod: zod(s) to getter: get zod() { return zod(s) }
in config and lsp modules. Added defensive check in encoded() function.

Binary still crashes at Effect v4 schema initialization - issue appears to be
in Effect's own code, not our zod walker. Effect schemas have undefined encoding
property during instantiation.

Related: upstream sync issue #SYNC-2026-05-07

* fix(util/schema): remove eager zod() call from optionalOmitUndefined for Effect beta.57 compatibility

* fix: wrap Zod schemas in Effect Schema context using ZodOverride annotation

When Snapshot.FileDiff (a Zod schema) is passed directly to Effect's Schema.Array(),
the Effect walker tries to traverse it as an Effect AST, causing a crash when looking
for the 'encoding' property which Zod schemas don't have.

The fix wraps the Zod schema with Schema.Any.annotate({ [ZodOverride]: ... }),
which tells the effect-zod walker to use the provided Zod schema directly instead
of trying to traverse its structure.

Affected locations:
- packages/opencode/src/session/message-v2.ts:391 (User.summary.diffs)
- packages/opencode/src/session/session.ts:148 (Summary.diffs)
- packages/opencode/src/session/session.ts:332 (Event.Diff schema)
- packages/opencode/src/server/routes/instance/httpapi/groups/session.ts:160 (GET /diff response)

* fix(sync): restore upstream session.ts

* fix(sync): wrap Snapshot.FileDiff in Schema.Any.annotate for Effect beta.57 compatibility

When Snapshot.FileDiff (a Zod schema) is passed directly to Schema.Array(),
the Effect walker tries to traverse it as an Effect AST, causing a crash when
looking for the 'ast' property which Zod schemas don't have.

The fix wraps the Zod schema with Schema.Any.annotate({ [ZodOverride]: ... }),
which tells the effect-zod walker to use the provided Zod schema directly instead
of trying to traverse its structure.

Affected locations:
- packages/opencode/src/session/session.ts:148 (Summary.diffs)
- packages/opencode/src/session/session.ts:332 (Event.Diff schema)

* fix(effect-zod): add ZodOverride early-exit in bodyWithChecks and encoded before ast.encoding access

* fix(sync): exclude fast-check from production bundle with alias stub

- Create fast-check-stub.ts to provide no-op implementations of fast-check APIs
- Add alias mapping in Bun.build config to replace fast-check and @fast-check/compat with stub
- Comment out smoke test temporarily (needs deeper debugging of Effect/Schema initialization)
- Binary builds successfully (92MB) without bundling unused fast-check dependency

* fix(sync): resolve Effect beta.57 runtime crashes for --version

Four separate crashes fixed to make the compiled binary viable:

1. **effect-zod: body() optionalKey support**
   Schema.optionalKey(X) in Effect 4.0.0-beta.57 produces an AST node
   whose _tag matches the inner type (e.g. "String") but with
   isOptional=true. The previous body() code unconditionally called
   opt() for any isOptional node; opt() expects a Union and throws for
   non-Union tags. Fix: only delegate to opt() when _tag==="Union";
   otherwise process by _tag and wrap .optional() if isOptional.

2. **permission: ZodOverride to bypass mutable-array encoding**
   Permission.Ruleset was Schema.mutable(Schema.Array(_Rule)). Walking
   this via effect-zod's encoded() path descended into _Rule's String
   fields and crashed. Fix: annotate Ruleset with
   [ZodOverride]: PermissionNext.Ruleset so the AST walker returns the
   canonical Zod schema directly without traversal. Also removes the
   circular permission→plugin import via lazy import.

3. **session/index: use .zod accessor for MessageV2.Assistant**
   MessageV2.Assistant is an Effect Schema; calling .shape on it gives
   undefined. Fix: MessageV2.Assistant.zod.shape.error.

4. **session/prompt: use .zod accessors for MessageV2 schemas**
   PromptInput and CommandInput Zod schemas were calling .omit()/.optional()
   directly on Effect Schema instances (MessageV2.TextPart, FilePart,
   AgentPart, SubtaskPart, Format). Fix: use .zod accessor to get Zod
   schema before calling Zod methods.

* fix(sync): replace fast-check alias with onResolve Bun plugin

The Bun `alias` option only resolves from the project root, so
fast-check imported from Effect's own nested node_modules subtree
(effect/node_modules/fast-check) was not intercepted. Replace with a
Bun build plugin using onResolve that fires for any importer and always
redirects to the local stub.

Also replace Schema.isPattern with Schema.filter in config/agent.ts to
avoid toArbitraryConstraint annotation that triggers fast-check at
module initialization (Effect beta.57 issue).

Expand the fast-check-stub with all methods used by Effect's makeArbitrary
path (stringMatching, nat, double, fullUnicode, unicode, char, etc.).

* chore: normalize package.json whitespace and update bun.lock

* docs(fork-features): update manifest with effect-zod-beta-compat, fast-check-build-exclusion, permission-ruleset-zod-override (#411)

* docs(sync): update 2026-05-07 report with post-merge build fix details

* fix(sync): fix packages/app typecheck errors after upstream sync

* fix(sync): add missing ZenData.RateLimit type to console-core model

---------

Co-authored-by: Kit Langton <kit.langton@gmail.com>
Co-authored-by: opencode-agent[bot] <opencode-agent[bot]@users.noreply.github.com>
Co-authored-by: Sebastian <hasta84@gmail.com>
Co-authored-by: opencode <opencode@sst.dev>
Co-authored-by: Jérôme Benoit <jerome.benoit@sap.com>
Co-authored-by: OpeOginni <107570612+OpeOginni@users.noreply.github.com>
Co-authored-by: Aiden Cline <63023139+rekram1-node@users.noreply.github.com>
Co-authored-by: HyeokjaeLee <leehyeokjae97@gmail.com>
Co-authored-by: Dax Raad <d@ironbay.co>
Co-authored-by: Luke Parker <10430890+Hona@users.noreply.github.com>
Co-authored-by: Dax <mail@thdxr.com>
Co-authored-by: Youssef Achy <19510452+PanAchy@users.noreply.github.com>
Co-authored-by: Shoubhit Dash <shoubhit2005@gmail.com>
Co-authored-by: Brendan Allan <14191578+Brendonovich@users.noreply.github.com>
Co-authored-by: Utkub24 <76127062+Utkub24@users.noreply.github.com>
Co-authored-by: Frank <frank@anoma.ly>
Co-authored-by: Colby Gilbert <colby@firmware.ai>
Co-authored-by: James Long <longster@gmail.com>
Co-authored-by: Victor Navarro <vn4varro@gmail.com>
Co-authored-by: Nathan Nguyen <HoangAnhVu.Nguyen-1@student.uts.edu.au>
Co-authored-by: imduchuyyy 🐬 <duchuy.124dk@gmail.com>
Co-authored-by: Jack <jack@anoma.ly>
Co-authored-by: Guiii <68971828+kill74@users.noreply.github.com>
Co-authored-by: Sergei Zharinov <zharinov@users.noreply.github.com>
Co-authored-by: André Cruz <acruz@cloudflare.com>
Co-authored-by: Omer Koren <54630488+omer-koren@users.noreply.github.com>
Co-authored-by: Aiden Cline <aidenpcline@gmail.com>
Co-authored-by: carmit hershman <78722358+carmithersh@users.noreply.github.com>
Co-authored-by: Jesse <82005785+jessedi0n@users.noreply.github.com>
Co-authored-by: jesse.mahnken <jesse.mahnken@tiefox.de>
Co-authored-by: Bence Ferdinandy <bence@ferdinandy.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

cf-ai-gateway silently drops reasoningEffort, variants, and other provider options (sdkKey/variants missing ai-gateway-provider case)

3 participants