Skip to content
Merged
33 changes: 33 additions & 0 deletions .changeset/opencode-v1-14-51-to-v1-15-4.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
---
"@kilocode/cli": patch
"kilo-code": patch
---

Changes from opencode v1.14.51 to v1.15.4 upstream:

- Core Improvements: Clarified how to recover when the npm package is installed without its native binary.
- Core Improvements: Reduced unnecessary prompting around shell, task, and todo flows.
- Core Bugfixes: Ignored invalid exports in custom tool modules instead of failing tool loading.
- Core Bugfixes: Ignored project instruction lookup errors so sessions keep loading when project instruction discovery fails.
- Core Bugfixes: Fixed versioned event projector lookups so event replay uses the right handlers.
- Core Bugfixes: Avoid duplicate consecutive entries in prompt history.
- Core Bugfixes: Show full config validation errors during TUI startup instead of a generic failure.
- Core Bugfixes: Fixed npm installs so the CLI can recover and fetch the right native binary on more setups.
- Core Bugfixes: Fixed multiline `@` mentions in prompts.
- Core Bugfixes: Preserved custom tool metadata from Zod schemas.
- Core Bugfixes: Preserved custom tool argument descriptions in generated schemas.
- Core Bugfixes: Fixed file watching in repos where `.git` is a symlink. (@kagura-agent)
- Core Bugfixes: Fixed sync events not reaching project-scoped subscribers in injected instances.
- Core Bugfixes: Reduced wasted work when reading very large files after output truncation.
- Core Bugfixes: Fixed project-scoped bus events so file watcher and update notifications reach the right instance.
- Core Bugfixes: Fixed custom LSP servers not sending refresh events after they initialize.
- Core Bugfixes: Hid background subagent task instructions unless experimental background mode is enabled.
- TUI Improvements: Added a collapsed thinking view that can be expanded inline.
- TUI Improvements: Added pinned sessions with quick-switch slots in the session picker.
- TUI Improvements: Newly pinned sessions now stay at the end of the pinned list instead of jumping to the top.
- TUI Improvements: Made Markdown H1 headings easier to distinguish.
- TUI Bugfixes: Fixed thinking mode defaults so reasoning starts collapsed consistently.
- TUI Bugfixes: Limited session quick-switching to pinned sessions.
- TUI Bugfixes: Fixed Markdown table rendering in chat output.
- TUI Bugfixes: Fixed `kilo run --agent` resolving project-local agents.
- TUI Bugfixes: Fixed async commands losing the active instance context, which could break agent generation and GitHub-driven runs.
11 changes: 11 additions & 0 deletions script/upstream/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ bun run merge.ts --version v1.1.50 --base-branch catrielmuller/kilo-opencode-v1.
| `merge.ts` | Main orchestration script for upstream merges |
| `list-versions.ts` | List available upstream versions |
| `analyze.ts` | Analyze changes without merging |
| `opencode-changesets.ts` | Generate Kilo changesets from upstream opencode release notes |
| `fix-kilocode-markers.ts` | Rebuild `kilocode_change` markers for one file against the last merged upstream |
| `reset-to-upstream.ts` | Reset one file to the transformed last merged upstream version |
| `find-reset-candidates.ts` | Bulk-find files that have drifted insignificantly from upstream and (optionally) reset them |
Expand All @@ -60,6 +61,16 @@ bun run merge.ts --version v1.1.50 --base-branch catrielmuller/kilo-opencode-v1.
| `codemods/transform-imports.ts` | Transform import statements using ts-morph |
| `codemods/transform-strings.ts` | Transform string literals |

## Release Notes Changesets

After merging upstream opencode releases, use `opencode-changesets.ts` to turn the upstream GitHub release notes into Kilo changesets:

```bash
bun script/upstream/opencode-changesets.ts --from 1.17.0 --to 1.17.7
```

The script fetches releases from `anomalyco/opencode`, selects published releases in the semver range `(from, to]`, and writes one `.changeset/opencode-vX-Y-Z-to-vX-Y-Z.md` file for the whole range. It requires the target release to exist, merges notes from every release into shared `##` sections and `###` categories, then folds those headings into each bullet (for example, `Core Bugfixes: ...`) so Changesets can embed the notes cleanly in package changelogs. It generates a patch changeset for the fixed release group, `@kilocode/cli` and `kilo-code`. Generated notes omit contributor thank-you blocks and the upstream `Desktop` and `SDK` sections by default because Kilo does not ship the opencode desktop app and SDK release notes are not user-facing for Kilo.

## Merge Process

The merge automation follows this process, applying **all transformations BEFORE the merge** to minimize conflicts:
Expand Down
168 changes: 168 additions & 0 deletions script/upstream/opencode-changesets.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
import { describe, expect, test } from "bun:test"

import { changeset, select, type Release } from "./opencode-changesets"

const releases: Release[] = [
{ tag_name: "v1.2.3", body: "Patch release" },
{ tag_name: "v1.2.2", body: "\r\n## Core\r\n\r\n- Fix issue\r\n" },
{ tag_name: "1.2.1", body: "Old tag without prefix" },
{ tag_name: "v1.2.0", body: "Base release" },
{ tag_name: "v1.2.4", body: "Draft release", draft: true },
{ tag_name: "v1.2.5", body: "Prerelease", prerelease: true },
]

describe("opencode changesets", () => {
test("selects releases in semver range with normalized tags", () => {
expect(select(releases, "1.2.0", "v1.2.3")).toEqual([
{ tag_name: "v1.2.1", body: "Old tag without prefix" },
{ tag_name: "v1.2.2", body: "\r\n## Core\r\n\r\n- Fix issue\r\n" },
{ tag_name: "v1.2.3", body: "Patch release" },
])
})

test("excludes prereleases", () => {
expect(() => select(releases, "1.2.3", "1.2.5")).toThrow("Target opencode release does not exist")
})

test("requires the target release to exist", () => {
expect(() => select(releases, "1.2.0", "99.9.9")).toThrow("Target opencode release does not exist")
})

test("requires the starting release to exist", () => {
expect(() => select(releases, "1.1.9", "1.2.3")).toThrow("Starting opencode release does not exist")
})

test("formats changeset markdown", () => {
expect(
changeset([{ tag_name: "v1.2.2", body: "\r\n## Core\r\n\r\n- Fix issue\r\n" }], "1.2.1", "1.2.2"),
).toBe(`---
"@kilocode/cli": patch
"kilo-code": patch
---

Changes from opencode v1.2.1 to v1.2.2 upstream:

- Core: Fix issue
`)
})

test("filters ignored sections and contributor thanks", () => {
expect(
changeset([
{
tag_name: "v1.2.2",
body: `## Core

- Keep this

## Desktop

- Drop this

## SDK

- Drop sdk

**Thank you to 1 community contributor:**

- @user:
- Helped
`,
},
], "1.2.1", "1.2.2"),
).toBe(`---
"@kilocode/cli": patch
"kilo-code": patch
---

Changes from opencode v1.2.1 to v1.2.2 upstream:

- Core: Keep this
`)
})

test("bundles release notes into shared sections", () => {
expect(
changeset([
{
tag_name: "v1.2.1",
body: `## Core

### Bugfixes

- Fix first

## TUI

### Improvements

- Improve first
`,
},
{
tag_name: "v1.2.2",
body: `## Core

### Bugfixes

- Fix second

### Improvements

- Improve core

## TUI

### Improvements

- Improve second
`,
},
], "1.2.0", "1.2.2"),
).toBe(`---
"@kilocode/cli": patch
"kilo-code": patch
---

Changes from opencode v1.2.0 to v1.2.2 upstream:

- Core Bugfixes: Fix first
- Core Bugfixes: Fix second
- Core Improvements: Improve core
- TUI Improvements: Improve first
- TUI Improvements: Improve second
`)
})

test("preserves multiline markdown blocks", () => {
expect(
changeset([
{
tag_name: "v1.2.2",
body: `## Core

### Improvements

- Parent item
- Nested item

Continuation paragraph
- Second item
`,
},
], "1.2.1", "1.2.2"),
).toBe(`---
"@kilocode/cli": patch
"kilo-code": patch
---

Changes from opencode v1.2.1 to v1.2.2 upstream:

- Core Improvements: Parent item
- Nested item

Continuation paragraph
- Core Improvements: Second item
`)
})
})
Loading
Loading