Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion DIVERGENCES.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ from the squash message first, or use a plain merge.
| `packages/tui/src/ui/dialog-prompt.tsx` | Added `persistent?` (hides the `esc` hint + `DialogPrompt.show` re-arms the store flag), `onInput?` (fires on textarea content change), and `ref?` props | The configure flow's prompts (SSO login, manual credentials) are non-dismissable, and the SSO view watches `onInput` for the lone-`c` copy shortcut on the paste-back link (needs the `ref` to clear the field). | Keep our three props, the `Show` around the esc label, the textarea `onContentChange`, and the `.show` re-arm; take upstream's surrounding changes. |
| `packages/tui/src/ui/dialog-prompt.tsx`, `packages/tui/src/config/keybind.ts`, `packages/tui/src/app.tsx` | Ctrl+V paste in dialog prompts. keybind.ts: added `"dialog.prompt.paste"` definition (`ctrl+v`, `preventDefault: false`, no CommandMap entry — dotted keys map to themselves). dialog-prompt.tsx: a `dialog.prompt.paste` command in the existing priority-1 binding layer reads `useClipboard().read?.()` and inserts `text/plain` content (newlines stripped, matching the single-line `InputRenderable` paste — dialog prompts are single-line fields and some upstream consumers store the value untrimmed); the command list is gathered alongside `dialog.prompt.submit`. app.tsx: `TuiInput.clipboard?: ClipboardService` passed to `<ClipboardProvider value=…>` so tests inject a deterministic clipboard. Covered by the ctrl+v test in the fork-only `packages/tui/test/custom-provider.view.test.tsx`. | Many Windows terminals deliver ctrl+v as a key event instead of a bracketed paste, and upstream's clipboard-reading `prompt.paste` command targets only the main session prompt — so dialog fields (API keys in /connect, the custom-provider flow) could not paste at all (upstream issue anomalyco/opencode#39837). Bracketed paste still goes through the textarea's built-in default handler; the binding layer's `!props.busy` guard disables paste while busy. | Keep the keybind definition, the paste command + gathered binding list, and the `clipboard` input plumbing; take upstream's surrounding changes. Sent upstream as anomalyco/opencode#39844 (identical code) — once it lands in a synced release this row collapses to nothing; if upstream ships a different dialog paste fix, prefer theirs and drop this row. |
| `packages/opencode/script/build.ts` | Platform packages' `package.json` name `codev-code-<platform>` (dist dir names unchanged — the bun compile target derives from them); compiled binary emitted as `bin/codev` (was `bin/opencode`; smoke-test path follows) | npm publishing under the fork's names; the binary inside platform packages carries the fork's name (postinstall.mjs copies it into the `codev` bin shim). The `Script.release` upload block stays upstream-shaped and unused — the fork's `.github/workflows/release.yml` packages and uploads GitHub-release artifacts itself. | Keep our `name:` line and `bin/codev` paths; take upstream's surrounding changes. |
| `packages/opencode/script/publish.ts` | `PUBLISH_NAME = "codev-code"` const; published-name→dir map; main pkg name + bin `codev` → `./bin/codev.exe` (postinstall stub file renamed from `${pkg.name}.exe`, matching the renamed platform binary); embedded README; no `repository` field in the generated package.json (npm renders it as the Repository link and derives a `#readme` Homepage from it — both kept off the npm page); env-guarded exit before the Docker/AUR/Homebrew section | npm-only publishing under the fork's names (unscoped, public on npmjs); the installed command is `codev`; upstream's other channels target anomalyco infra; the npm page should not link the fork's GitHub repo. | Keep our names, description, bin mapping, omitted `repository` + early exit; take upstream's npm-section changes above the exit. |
| `packages/opencode/script/publish.ts` | `PUBLISH_NAME = "codev-code"` const; published-name→dir map; main pkg name + bin `codev` → `./bin/codev.exe` (postinstall stub file renamed from `${pkg.name}.exe`, matching the renamed platform binary); embedded README; no `repository` field in the generated package.json (npm renders it as the Repository link and derives a `#readme` Homepage from it — both kept off the npm page); env-guarded exit before the Docker/AUR/Homebrew section; `npm publish` retried up to 5 times with linear backoff, treating a version that turns up on the registry after a failed attempt as published; the dist manifest scan skips the generated main package directory | npm-only publishing under the fork's names (unscoped, public on npmjs); the installed command is `codev`; upstream's other channels target anomalyco infra; the npm page should not link the fork's GitHub repo. Releases run from a laptop rather than CI, where the 13 concurrent 40-60MB uploads regularly time one package out (`npm error FETCH_ERROR`) and abort the release mid-way; resuming such a release must not make the main package depend on itself. | Keep our names, description, bin mapping, omitted `repository`, retry loop + early exit; take upstream's npm-section changes above the exit. If upstream adds its own publish retry, drop ours for theirs. |
| `packages/opencode/bin/opencode` | `base` prefix `opencode-` → `codev-code-` | Runtime platform-binary lookup must match the published names. | Keep our prefix. |
| `packages/opencode/script/postinstall.mjs` | `base` prefix `opencode-` → `codev-code-`; source/target binary names `opencode`/`opencode.exe` → `codev`/`codev.exe` (matches build.ts's `bin/codev` and publish.ts's `bin/codev.exe` stub); temp-dir prefix and failure message rebranded | Install-time platform-binary fetch must match the published package and binary names. | Keep our prefix and binary names. |
| `packages/tui/src/logo.ts` | Pixel glyphs "open"+"code" → "co"+"dev"; added a `brand` export (`navy` `#19224c` / `red` `#ee0033`, the landing page's `--color-brand-navy`/`--color-brand-red`), a `wordmarkHalves` export (each row's "co" and "dev" halves with the shadow marks substituted to glyphs, so each half can take its own brand color), the composed `wordmark` (plain lines, built from `wordmarkHalves`) and `ansiWordmark` (bold, no shadow: "co" in the terminal's default foreground, "dev" in brand red truecolor) exports for CLI banners; added a `badge` export (the "c" of the wordmark — `logo.left` rows 1-3 sliced to the first glyph, with the `_` shadow-fill marks stripped to spaces so it renders as a flat outline) for the `--mini` splashes | Branded wordmark art; `ansiWordmark` feeds the CLI help banner and session epilogue. | Keep our glyphs + exports; take upstream's surrounding changes. |
Expand Down
28 changes: 24 additions & 4 deletions packages/opencode/script/publish.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ process.chdir(dir)
// compile target from them); only package.json `name` fields differ.
const PUBLISH_NAME = "codev-code"

// All 13 packages publish concurrently and every tarball is 40-60MB, so the
// registry routinely times out one of them mid-upload (`npm error FETCH_ERROR`)
// and takes the whole release down with it.
const ATTEMPTS = 5

async function published(name: string, version: string) {
return (await $`npm view ${name}@${version} version`.nothrow()).exitCode === 0
}
Expand All @@ -26,16 +31,31 @@ async function publish(dir: string, name: string, version: string) {
return
}
await $`bun pm pack`.cwd(dir)
await $`npm publish *.tgz --access public --tag ${Script.channel}`.cwd(dir)
for (let attempt = 1; attempt <= ATTEMPTS; attempt++) {
if ((await $`npm publish *.tgz --access public --tag ${Script.channel}`.cwd(dir).nothrow()).exitCode === 0) return
// A timed-out request can still have landed the version, in which case a
// retry would only fail with "cannot publish over existing version".
if (await published(name, version)) {
console.log(`published ${name}@${version} despite the error above`)
return
}
if (attempt === ATTEMPTS) throw new Error(`failed to publish ${name}@${version} after ${ATTEMPTS} attempts`)
console.log(`retrying ${name}@${version} (attempt ${attempt + 1}/${ATTEMPTS})`)
await Bun.sleep(attempt * 10_000)
}
}

const binaries: Record<string, string> = {}
// Scoped published name -> unscoped dist directory (they differ in this fork).
const dirs: Record<string, string> = {}
for (const filepath of new Bun.Glob("*/package.json").scanSync({ cwd: "./dist" })) {
const pkg = await Bun.file(`./dist/${filepath}`).json()
binaries[pkg.name] = pkg.version
dirs[pkg.name] = filepath.replace("/package.json", "")
// A re-run (`release --skip-build` after a failed publish) scans a dist/
// that already holds the main package directory generated below — leave it
// out or it lands in its own optionalDependencies.
if (filepath === `${pkg.name}/package.json`) continue
const manifest = await Bun.file(`./dist/${filepath}`).json()
binaries[manifest.name] = manifest.version
dirs[manifest.name] = filepath.replace("/package.json", "")
}
console.log("binaries", binaries)
const version = Object.values(binaries)[0]
Expand Down
Loading