sync: upstream 195f59264 (between v1.14.50 and v1.14.51)#70
Conversation
Co-authored-by: Andrew Suffield <asuffield@cloudflare.com> Co-authored-by: Aiden Cline <aidenpcline@gmail.com>
Pulls anomalyco/opencode from ce66b19 (v1.14.48) to 195f592. 379 upstream commits. Targeted 195f592 explicitly because v1.14.51 itself ships with a broken openapi.json regen that drops EventMessageUpdated/EventMessagePartUpdated from the v2 SDK while consumers still string-compare against them (207 typecheck errors on a pristine v1.14.51). 195f592 is the last commit before that regen and is the latest point that includes the image-fix PR #26805 we wanted. Notable: - Adopts upstream's image fix (PR #26805) — replaces our PR #69 photon loader. Cleaner shape (top-level import-with-attributes + path resolution instead of new Function/createRequire eval). Renames PhotonUnavailableError to ResizerUnavailableError. - Keeps our PR #69 typed omitted-image-message UX in processor.ts (upstream did not adopt that part). Updated the case label to the renamed error tag. - Keeps our PR #64 temperature operand swap — upstream did not include it. - Absorbs the runtime-flags refactor wave (channelDb / autoShare / embeddedWebUi / icon / oxfmt / bash-timeout / experimental models / output- token-max / llm client / event system migrated to RuntimeFlags). - Absorbs new core packages from upstream (auth/catalog/instance/model/ plugin/provider/etc.), AppFileSystem and AppProcess migrations, BackgroundJob service, task_status tool, DigitalOcean auth plugin. - Rebrands USER_AGENT in the new packages/core/src/models.ts (opencode/... -> browsercode/...). Conflicts: 17 source-side + bun.lock + 30 workflow re-deletes. See UPSTREAM.md row for the full per-file resolution log.
There was a problem hiding this comment.
7 issues found across 774 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name=".opencode/opencode.jsonc">
<violation number="1" location=".opencode/opencode.jsonc:4">
P2: This removes the migration-path edit approval guard; with default-permissive permissions, edits in `packages/opencode/migration/*` will no longer require confirmation.</violation>
</file>
<file name="packages/app/src/context/command.tsx">
<violation number="1" location="packages/app/src/context/command.tsx:285">
P2: Persist the `hidden` flag when building `command.catalog`; otherwise hidden commands can reappear from catalog metadata in settings.</violation>
</file>
<file name="packages/core/src/auth.ts">
<violation number="1" location="packages/core/src/auth.ts:136">
P1: Migrating `auth.json` before reading `auth-v2.json` can overwrite newer v2 auth data with stale legacy content when both files exist.</violation>
</file>
<file name="packages/core/src/plugin/provider/azure.ts">
<violation number="1" location="packages/core/src/plugin/provider/azure.ts:28">
P2: Treat `resourceName` as missing when it is an empty/whitespace string; the current truthiness check allows invalid values to bypass Azure configuration validation.</violation>
</file>
<file name="packages/console/app/src/routes/zen/util/modelTpsLimiter.ts">
<violation number="1" location="packages/console/app/src/routes/zen/util/modelTpsLimiter.ts:74">
P2: Guard against non-positive elapsed time before computing TPS to avoid `Infinity`/invalid TPS values.</violation>
</file>
<file name="packages/app/src/components/settings-keybinds.tsx">
<violation number="1" location="packages/app/src/components/settings-keybinds.tsx:126">
P2: Skipping hidden commands here removes them from keybind conflict detection, so users can assign shortcuts that collide with active hidden keybinds.</violation>
</file>
<file name="packages/core/src/plugin/auth.ts">
<violation number="1" location="packages/core/src/plugin/auth.ts:19">
P2: `Object.assign` after setting `apiKey` may overwrite it if `metadata` contains an `apiKey` field. Swap the order so the explicit key wins, or destructure `apiKey` out of metadata before assigning.</violation>
</file>
Tip: instead of fixing issues one by one fix them all with cubic
Note: This PR contains a large number of files. cubic only reviews up to 100 files per PR, so some files may not have been reviewed. cubic prioritizes the most important files to review.
On a pro plan you can use ultrareview for larger PRs.
Re-trigger cubic
|
|
||
| const raw = yield* fsys.readJson(file).pipe(Effect.orElseSucceed(() => null)) | ||
| const legacy = yield* fsys.readJson(legacyFile).pipe(Effect.orElseSucceed(() => null)) | ||
| if (legacy && typeof legacy === "object") return yield* writeMigrated(legacy as Record<string, unknown>) |
There was a problem hiding this comment.
P1: Migrating auth.json before reading auth-v2.json can overwrite newer v2 auth data with stale legacy content when both files exist.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/core/src/auth.ts, line 136:
<comment>Migrating `auth.json` before reading `auth-v2.json` can overwrite newer v2 auth data with stale legacy content when both files exist.</comment>
<file context>
@@ -106,25 +106,43 @@ export const layer = Layer.effect(
- const raw = yield* fsys.readJson(file).pipe(Effect.orElseSucceed(() => null))
+ const legacy = yield* fsys.readJson(legacyFile).pipe(Effect.orElseSucceed(() => null))
+ if (legacy && typeof legacy === "object") return yield* writeMigrated(legacy as Record<string, unknown>)
- if (!raw || typeof raw !== "object") return { version: 2, accounts: {}, active: {} }
</file context>
| "packages/opencode/migration/*": "ask", | ||
| }, | ||
| }, | ||
| "permission": {}, |
There was a problem hiding this comment.
P2: This removes the migration-path edit approval guard; with default-permissive permissions, edits in packages/opencode/migration/* will no longer require confirmation.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At .opencode/opencode.jsonc, line 4:
<comment>This removes the migration-path edit approval guard; with default-permissive permissions, edits in `packages/opencode/migration/*` will no longer require confirmation.</comment>
<file context>
@@ -1,11 +1,7 @@
- "packages/opencode/migration/*": "ask",
- },
- },
+ "permission": {},
"mcp": {},
"tools": {
</file context>
| "permission": {}, | |
| "permission": { | |
| "edit": { | |
| "packages/opencode/migration/*": "ask", | |
| }, | |
| }, |
| acc[id] = { | ||
| title: opt.title, | ||
| description: opt.description, | ||
| category: opt.category, | ||
| keybind: opt.keybind, | ||
| slash: opt.slash, | ||
| } |
There was a problem hiding this comment.
P2: Persist the hidden flag when building command.catalog; otherwise hidden commands can reappear from catalog metadata in settings.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/app/src/context/command.tsx, line 285:
<comment>Persist the `hidden` flag when building `command.catalog`; otherwise hidden commands can reappear from catalog metadata in settings.</comment>
<file context>
@@ -279,13 +281,14 @@ export const { use: useCommand, provider: CommandProvider } = createSimpleContex
- slash: opt.slash,
- }
+ if (opt.title)
+ acc[id] = {
+ title: opt.title,
+ description: opt.description,
</file context>
| acc[id] = { | |
| title: opt.title, | |
| description: opt.description, | |
| category: opt.category, | |
| keybind: opt.keybind, | |
| slash: opt.slash, | |
| } | |
| acc[id] = { | |
| title: opt.title, | |
| description: opt.description, | |
| category: opt.category, | |
| keybind: opt.keybind, | |
| slash: opt.slash, | |
| hidden: opt.hidden, | |
| } |
| if (evt.package !== "@ai-sdk/azure") return | ||
| if (evt.model.providerID === ProviderV2.ID.azure) { | ||
| if ( | ||
| !evt.options.resourceName && |
There was a problem hiding this comment.
P2: Treat resourceName as missing when it is an empty/whitespace string; the current truthiness check allows invalid values to bypass Azure configuration validation.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/core/src/plugin/provider/azure.ts, line 28:
<comment>Treat `resourceName` as missing when it is an empty/whitespace string; the current truthiness check allows invalid values to bypass Azure configuration validation.</comment>
<file context>
@@ -0,0 +1,64 @@
+ if (evt.package !== "@ai-sdk/azure") return
+ if (evt.model.providerID === ProviderV2.ID.azure) {
+ if (
+ !evt.options.resourceName &&
+ !evt.options.baseURL &&
+ (evt.model.endpoint.type !== "aisdk" || !evt.model.endpoint.url)
</file context>
| const tokens = usageInfo.outputTokens | ||
| if (tokens <= 10) return | ||
|
|
||
| const tps = (tokens / (tsLastByte - tsFirstByte)) * 1000 |
There was a problem hiding this comment.
P2: Guard against non-positive elapsed time before computing TPS to avoid Infinity/invalid TPS values.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/console/app/src/routes/zen/util/modelTpsLimiter.ts, line 74:
<comment>Guard against non-positive elapsed time before computing TPS to avoid `Infinity`/invalid TPS values.</comment>
<file context>
@@ -0,0 +1,95 @@
+ const tokens = usageInfo.outputTokens
+ if (tokens <= 10) return
+
+ const tps = (tokens / (tsLastByte - tsFirstByte)) * 1000
+ const qualify = tps >= tpsGoal ? 1 : 0
+ const unqualify = tps < tpsGoal ? 1 : 0
</file context>
|
|
||
| for (const opt of command.catalog) { | ||
| if (opt.id.startsWith("suggested.")) continue | ||
| if (opt.hidden) continue |
There was a problem hiding this comment.
P2: Skipping hidden commands here removes them from keybind conflict detection, so users can assign shortcuts that collide with active hidden keybinds.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/app/src/components/settings-keybinds.tsx, line 126:
<comment>Skipping hidden commands here removes them from keybind conflict detection, so users can assign shortcuts that collide with active hidden keybinds.</comment>
<file context>
@@ -123,11 +123,13 @@ function listFor(command: CommandContext, map: KeybindMap, palette: string) {
for (const opt of command.catalog) {
if (opt.id.startsWith("suggested.")) continue
+ if (opt.hidden) continue
out.set(opt.id, { title: opt.title, group: groupFor(opt.id) })
}
</file context>
| } | ||
| if (account.credential.type === "api") { | ||
| evt.provider.options.aisdk.provider.apiKey = account.credential.key | ||
| Object.assign(evt.provider.options.aisdk.provider, account.credential.metadata ?? {}) |
There was a problem hiding this comment.
P2: Object.assign after setting apiKey may overwrite it if metadata contains an apiKey field. Swap the order so the explicit key wins, or destructure apiKey out of metadata before assigning.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/core/src/plugin/auth.ts, line 19:
<comment>`Object.assign` after setting `apiKey` may overwrite it if `metadata` contains an `apiKey` field. Swap the order so the explicit key wins, or destructure `apiKey` out of metadata before assigning.</comment>
<file context>
@@ -0,0 +1,27 @@
+ }
+ if (account.credential.type === "api") {
+ evt.provider.options.aisdk.provider.apiKey = account.credential.key
+ Object.assign(evt.provider.options.aisdk.provider, account.credential.metadata ?? {})
+ }
+ if (account.credential.type === "oauth") {
</file context>
Summary
Brings
anomalyco/opencodefromce66b191d(v1.14.48, our previous anchor) to195f59264(refactor(server): simplify listener lifecycle, between v1.14.50 and v1.14.51). 379 upstream commits.Did NOT target v1.14.51. Upstream's
chore: generatecommite62ebd8fe(the parent of4e7a60dac/v1.14.51) regeneratedpackages/sdk/openapi.json+ the v2 SDK in a way that dropsEventMessageUpdated/EventMessagePartUpdatedfrom the SDK's Event union — whilecli/cmd/run.ts,acp/agent.ts,cli/cmd/run/{demo,session-data,stream.transport}.ts, etc. still string-compare against those types. A pristine checkout of4e7a60dacproduces 207 typecheck errors. The parent commit195f59264is the last clean point that still includes the upstream image-fix PR #26805 we wanted, so I anchored there. Recommend retrying once upstream re-aligns its event consumers with the new SyncEvent shape.Why this sync now
User pointed at our PRs #64 (
fix/strict-temperature-required-models) and #69 (fix/photon-load-and-typed-omitted-message) and asked whether upstream had fixed those independently and if so to adopt upstream and drop our exceptions.981e00971(PR #26805) fixes the photon WASM loading bug differently and more cleanly — top-levelimport photonWasm from ".../photon_rs_bg.wasm" with { type: "file" }thenpath.isAbsolute/fileURLToPathto compute__OPENCODE_PHOTON_WASM_PATH, replacing our runtimenew Function/createRequireeval path. Upstream also renamedImagePhotonUnavailableError→ImageResizerUnavailableErrorand changedloadPhotonto fail-fast (nonullfallback). Adopted upstream'simage.tsverbatim. Our PR fix(image): load Photon via runtime eval on compiled binaries; surface typed errors in omitted-image message #69 exception onimage.tscan be removed fromEXCEPTIONS.mdafter this lands.processor.tsfalls back to[N image(s) omitted: could not be resized below the image size limit.]regardless of whichImage.Errorfired. Our PR fix(image): load Photon via runtime eval on compiled binaries; surface typed errors in omitted-image message #69 surfaces typed reasons (decode / size / unavailable / malformed URL) grouped by_tag. Kept our version, just updated thecaselabel fromImagePhotonUnavailableErrortoImageResizerUnavailableError.Conflicts resolved
packages/opencode/package.json@browser-use/browsercode-core, bumped version string to 1.14.51bun.lock--theirs, regenerated viabun install.github/workflows/*.ymlsrc/agent/agent.tsSkills+Flagimports + ScoutreferencePrompt/referenceDescriptionblock. Added missingReferenceimport (auto-merge dropped it).src/cli/cmd/tui/feature-plugins/home/tips-view.tsxsrc/image/image.tssrc/index.tstrace+isRecordimports.src/installation/index.tsMethodsurface but rebuilt on upstream's newappProcess.runshape +userAgent(client)factory. Added backFlagimport for the UA default.src/plugin/index.tssrc/provider/provider.tsbcode.sh/bcodeheaders for nvidia. Dropped upstream's newX-BILLING-INVOKE-ORIGIN: OpenCode(would phone home wrong brand).src/server/shared/ui.tsembeddedUI(disableEmbeddedWebUi)signature. Kept F7 phone-home removal (droppedrequestBody/proxyResponseHeaders/upstreamURL).src/session/processor.tsImagePhotonUnavailableErrorcase toImageResizerUnavailableError.src/storage/db.tsflags: ChannelDbFlagssignature. Keptbcode.db/bcode-<channel>.dbfilenames.src/tool/registry.tsFetchUse.layerinto its own.pipe()call (Effect caps.pipe()at 20 args; pre-piped withFetchHttpClient.layerso its HttpClient dep doesn't escape).src/tool/webfetch.tstest/storage/db.test.tsit.effect+RuntimeFlags.layershape. Keptbcode.dbfilenames.test/tool/registry.test.tstest/tool/webfetch.test.tsEffect.acquireUseReleasetest shape. Promoted topit = testEffect(...)to include FetchUse + Config layers.Brand sweep
packages/core/src/models.tsis a NEW file from upstream that includesUSER_AGENT = \"opencode/...\". Rebranded tobrowsercode/...in the F7-style sweep so it doesn't ship as a regression of that work.Verification
bun install: clean, regenerated lockfile.bun run typecheck: 7/7 packages passed in ~10s (one-time cold run).Yellow-zone audit
12 files touched upstream + at our zone: customizations preserved across the board (banner/title BC,
bcode.shHTTP-Referer/X-Title/X-Source across 8 providers, CerebrasX-Cerebras-3rd-Party-Integration: bcode,.bcode/plans,.bcode/agent-workspace,Skillsimport, BrowserExecute renderer,bcode.dbfilenames,bcode.sh/installcurl bootstrap,Methodsurface stays curl-only,userAgent(client)returnsbrowsercode/...).EXCEPTIONS.md follow-up
Not in this PR (lives outside this repo in the maintainer's agent memory). To be updated to:
image/image.tsexception (now adopted upstream).session/processor.tstyped-message exception (BrowserCode-specific UX).session/llm.tstemperature exception (still slated to be opened upstream).Summary by cubic
Sync with upstream to a clean pre-v1.14.51 point to pull in image handling and core/server updates, and add console-side TPS limiting + sticky provider persistence. Kept our typed image error UX and temperature fix; skipped v1.14.51 due to an upstream SDK event regression.
New Features
Statfor TPS history.mod+1…mod+9); improved “session working” state; review panel unmounts when closed.hiddencommands; dialog excludes hidden options.aisdkbridge (adds SSE timeout guard) andcatalogmodule for providers/models.effect-zod; moved/renamed GitHub Copilot helpers.Dependencies
effect/@effect/*4.0.0-beta.65 and@opentui/{core,keymap,solid}0.2.10.bun.lockand Nix hashes refreshed.actions/checkout,actions/create-github-app-token, andoven-sh/setup-bun; split cache restore/save;bunfig.tomladdsminimumReleaseAge.Written for commit 22e180b. Summary will update on new commits. Review in cubic