Skip to content

chore: bump devShell to Go 1.27 - #3832

Merged
taciturnaxolotl merged 1 commit into
charmbracelet:mainfrom
LarsArtmann:chore/devshell-go-1_27
Sep 16, 2026
Merged

taciturnaxolotl merged 1 commit into
charmbracelet:mainfrom
LarsArtmann:chore/devshell-go-1_27

Conversation

@LarsArtmann

Copy link
Copy Markdown
Contributor

Why

go.mod requires go >= 1.27.0, but the devShell pins go_1_26. Inside nix develop, go build/go vet/gopls all fail with go.mod requires go >= 1.27.0 (running go 1.26.7).

What changed

  • flake.nix: go_1_26 → go_1_27
  • flake.lock: bumped the nixpkgs input — the previously pinned rev (68d8aa3d) has no go_1_27 attribute, so the one-line flake change alone does not evaluate (undefined variable 'go_1_27')

No other inputs or packages touched.

Test plan

  • nix develop -c go version → go1.27.1
  • go build ./... passes inside the shell

💘 Generated with Crush

@andrinoff

Copy link
Copy Markdown
Member

@taciturnaxolotl review, please, small nix change

go.mod requires go >= 1.27.0, but the devShell pinned go_1_26, so
nix develop could not build or vet the module (gopls/golangci-lint
failed with "go.mod requires go >= 1.27.0 (running go 1.26.7)").

- flake.nix: go_1_26 -> go_1_27
- flake.lock: bump nixpkgs (the pinned rev has no go_1_27 attr)

Verified: nix develop -c go version -> go1.27.1; go build ./... passes.
@LarsArtmann
LarsArtmann force-pushed the chore/devshell-go-1_27 branch from 34e0531 to c39860a Compare September 15, 2026 08:10
@taciturnaxolotl
taciturnaxolotl merged commit 5911679 into charmbracelet:main Sep 16, 2026
15 checks passed
@LarsArtmann

Copy link
Copy Markdown
Contributor Author

Nice :)

@LarsArtmann
LarsArtmann deleted the chore/devshell-go-1_27 branch September 17, 2026 12:56
andikapradanaarif added a commit to andikapradanaarif/crush that referenced this pull request Sep 18, 2026
* fix(tui): unfreeze spinner clock when the boot busy probe lands (charmbracelet#3839)

A session loaded before the first busy probe returns reads the
zero-value memoized busy cache and freezes the shared animation clock,
so a spinner rendered on boot never ticks. Re-enable the clock when
the authoritative probe reports the agent busy; idle probes leave the
gate alone so the ghost-spinner guard stands.

Assisted-by: Crush:prism

* fifix(ui): color the to-do task name while the tool is still running

* perf(ui): skip the global prompt-history scan when a session is loading

Starting with a session was far slower than switching to the same one
with ctrl+s: 2,750ms against 58ms for identical work, almost all of it a
single-row GetSession waiting 2,681ms to run.

Init batches prompt history alongside the initial session load. The
session is not set yet at that point, so history takes its no-session
branch and reads every user message in the database, which SQLite serves
by walking all 126,717 rows of a 743MB table in index order. The pool is
one connection, so the session load waits behind it. Switching sessions
never hit this: a session is set by then, so history reads only that
session's messages.

The work was redundant anyway. loadSessionMsg already reloads prompt
history for the session that arrives, so the startup result was
discarded. Asking only when no session is coming leaves loadSession at
63ms, matching the ctrl+s path.

* perf(db): index messages by role so user-message reads stop scanning

Listing every user message is how prompt history loads when no session is
set. There is no index on role, so SQLite walks all 126,717 rows of a
743MB messages table in created_at order to return the 7,478 that match.

Leading the index with role turns that into a seek, and keeping
created_at second returns them already ordered, so the DESC ordering
needs no sort. Measured on a copy of a 1.1GB database:

  plan     SCAN messages USING INDEX idx_messages_created_at
        -> SEARCH messages USING INDEX idx_messages_role_created_at (role=?)
  query    0.24-0.53s -> 0.02-0.04s warm
  service  335ms -> 157ms end to end, the rest being JSON decoding
  index    2.44MB, 0.2% of the database
  migrate  ~4s once on that database, 0.33s of it the scan and sort

Streaming writes are unaffected: UpdateMessage sets parts and timestamps,
neither of which this index covers, so there is no index maintenance on
the hot path. Measured at 2,000 inserts and 5,000 updates, the difference
was inside the noise.

* perf(db): cap prompt history at the 200 most recent messages

Both user-message queries exist only to fill up-arrow recall, and both
read every matching message with its full parts: 7,478 rows and 12.5MB of
JSON on this database, to populate a list walked one entry at a time.

200 is well past what anyone reaches a keystroke at a time, and the cap
compounds with the role index: SQLite seeks to the user rows and stops
after 200 instead of reading them all. ListAllUserMessages goes from
335ms warm (1.98s cold) to 3.8ms.

Paginating instead would suit a history that could be searched or jumped
into. This one only steps backwards from the newest entry, so paging
would add offset tracking and an in-flight guard to serve a reader 200
presses deep, and put a database read in the middle of a keystroke to do
it. The cap is the simpler shape for how the list is actually used.

The limit lives in the SQL because these two queries have exactly one
consumer between them; threading a parameter would cross the message
service, the workspace interface, both workspace implementations, the
backend and the wire protocol to carry a constant.

* fix(ui): read the session transcript off the event loop

Update handled loadSessionMsg by calling ListMessages inline, so the
whole TUI froze while it ran, with no spinner to say why. A 5000-message
session takes ~470ms, nine tenths of it JSON decoding rather than
SQLite. The load cmd already fetches the session, its files and its read
files off-thread; the transcript goes with them.

* perf(agent): read only the post-summary tail of a compacted session

getSessionMessages read the whole transcript and then discarded
everything before the summary. The cost is almost entirely JSON decoding
and so scales with bytes kept: across the 34 compacted sessions on hand,
3.09s of decoding to use 0.76s of it, and one session decodes 34.2MB to
keep a single message. ListFromSummary asks for the tail instead,
falling back to the full session when the summary message is gone so a
dangling id cannot erase the history.

* perf(message): decode message parts in one structural pass

unmarshalParts walked each stored blob three times: once to split it into
json.RawMessage, once per part to read the type tag, and once more to
decode the payload. Decoding straight into a []rawPartWrapper gets the
tag and the still-encoded payload together, dropping the middle walk.

Across all 126,719 stored messages (780MB) this decodes 1.34x faster and
produces byte-identical parts. Decoding is ~90% of the cost of loading a
session, the rest being SQLite, so this is the part worth cutting.

A token-stream decoder reaches 1.55x by walking the payload once too, but
needs ~90 lines of hand-rolled token handling and a fallback for when
"data" precedes "type". Struct decoding handles key order for free.

* chore(legal): @paulhovey has signed the CLA

* chore(legal): @vulragrag-star has signed the CLA

* chore(legal): @dakaii has signed the CLA

* feat: add plan mode (charmbracelet#2822)

* fix(test): make stdioCheck timeout configurable and add WaitDelay

* feat: add plan mode

* fix(ui): show both yolo and plan markers when both modes are active

* fix(plan): add risks consideration

* fix(ui): show plan in status bar only

* fix(plan): added instructs

* fix: check status exists

* fix(plan): refine workflow and style guidelines for clarity and precision

* fix(plan): mutate model synchronously in toggleInputMode to prevent cursor glitch

* fix(plan): enhance plan mode description

* fix(plan): clarify wording for search tools in workflow instructions

* chore: rebase maintenance

* feat(plan): implement plan handoff dialog and add question tool usage

* fix(plan): refine question tool usage and confirmation process in planning rules

* feat(plan): implement inline plan handoff prompt and update related logic

* chore(plan): fix

* feat(plan): add plan-ready marker detection and styling for final plan messages

* feat(plan): add "Critical Files" section to final plan response

* feat(plan): implement plan-ready marker handling and UI updates

* feat(styles): enhance PlanMarkdown styling for headings in quickStyle

* feat(styles): update PlanMarkdown to replace raw markdown prefixes with clean indentation

* chore: lint

* feat(plan): implement plan card rendering with uniform background

* chore(plan): update inline prompt button text

* feat(plan): implement feedback editor for plan handoff

* feat(plan): enhance plan card rendering to fit available width and improve layout handling

* fix: align vertical button hits

* feat: improve plan handoff input

* fix(plan): refine handoff copy and styling

* test: parallelize plan card width subtests

* feat(backend): add SetMainAgent to switch active workspace agent

* fix(plan): reconcile plan mode with upstream agent-ready and busy APIs

Post-rebase fixes for API changes that landed on main while the plan
mode branch was in flight:

- handleClickFocus: drop the unconditional m.chat.Blur() when an inline
  editor takes focus; focusActiveInline already blurs the chat and is
  nil-safe.
- testWorkspace: implement AgentReadyErr, which sendMessage now uses
  instead of AgentIsReady.
- TestToggleInputMode_BlockedWhileAgentBusy: seed agentBusyCache, since
  isAgentBusy now reads the memoized cache rather than the workspace.

* feat(core): support hidden user messages

* docs(plan): relax sub-agent workflow

* feat(plan): add YOLO handoff and prompt indicator

* feat(ui): add dedicated yolo coding key to plan handoff dialog

* fix(ui): only let Shift+Tab cycle disable cycle-enabled YOLO

* fix(ui): preserve plan code backgrounds

* fix(ui): report yolo input mode

* fix: make inline code in plan red

Signed-off-by: drew <me@andrinoff.com>

* remove plan-yolo

Signed-off-by: drew <me@andrinoff.com>

* chore: fixup the code

Signed-off-by: drew <me@andrinoff.com>

* chore: lint

Signed-off-by: drew <me@andrinoff.com>

* feat: UI improvements

Signed-off-by: drew <me@andrinoff.com>

* fix: add border around plan card

Signed-off-by: drew <me@andrinoff.com>

* fix: improve selection of coding options

Signed-off-by: drew <me@andrinoff.com>

* address review

Signed-off-by: drew <me@andrinoff.com>

* address feedback 2

Signed-off-by: drew <me@andrinoff.com>

* final review addressed

Signed-off-by: drew <me@andrinoff.com>

* fix: add a start marker for UI

Signed-off-by: drew <me@andrinoff.com>

* correct color

Signed-off-by: drew <me@andrinoff.com>

---------

Signed-off-by: drew <me@andrinoff.com>
Co-authored-by: drew <me@andrinoff.com>
Co-authored-by: Christian Rocha <christian@rocha.is>

* chore: auto-update files

* v0.95.0

Signed-off-by: drew <me@andrinoff.com>

* chore: bump devShell to Go 1.27 (charmbracelet#3832)

* chore(legal): @Applone has signed the CLA

* fix(ui): set the finish banner off from the message above it (charmbracelet#3815)

* chore: double default request timeout from 60 to 120 seconds (charmbracelet#3862)

* chore: auto-update files

* chore(legal): @workingdad365 has signed the CLA

* fix(ui): nudge the yolo/plan badges + align help (charmbracelet#3863)

* chore(legal): @angelinaaziz has signed the CLA

* fix(ui): drop the empty gap under a failed edit (charmbracelet#3851)

* test: disable recall/notebook_search in every-read-only test

* docs: fix stale sub-agent recall comment

---------

Signed-off-by: drew <me@andrinoff.com>
Co-authored-by: Andrey Nering <andrey@nering.com.br>
Co-authored-by: Kieran Klukas <kieran@dunkirk.sh>
Co-authored-by: Charm <124303983+charmcli@users.noreply.github.com>
Co-authored-by: Vadim Inshakov <vadiminshakov@gmail.com>
Co-authored-by: drew <me@andrinoff.com>
Co-authored-by: Christian Rocha <christian@rocha.is>
Co-authored-by: Lars Artmann <git@lars.software>
Co-authored-by: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
joestump-agent added a commit to joestump-agent/crush that referenced this pull request Sep 23, 2026
* fix(copilot): route GPT-6 Astra through Responses API (charmbracelet#3724)

* chore(legal): @is7Qin has signed the CLA

* chore(legal): @jackgene has signed the CLA

* docs(db): fix timestamp unit comments in initial migration (charmbracelet#3576)

* chore(legal): @RyanAOGallagher has signed the CLA

* fix(config): resolve the provider cache through the global data dir (charmbracelet#3738)

* chore: auto-update files

* chore(legal): @kthy has signed the CLA

* feat(tui): add option to disable mouse support (charmbracelet#3542)

Co-authored-by: drew <me@andrinoff.com>

* chore: auto-update files

* fix: keep `top_k` for known custom providers (charmbracelet#3736)

* chore: add CC-BY-4.0 to allowed licenses (charmbracelet#3755)

* fix: do not upload images if vision is not supported (charmbracelet#3754)

Signed-off-by: drew <me@andrinoff.com>

* fix: bump mcp sdk (charmbracelet#3716)

Signed-off-by: drew <me@andrinoff.com>

* fix(alibaba): do not send `enable_thinking` when we have an effort (charmbracelet#3758)

* chore(deps): migrate `mvdan.cc/sh/moreinterp` to `mvdan.cc/sh/x` (charmbracelet#3761)

* chore(deps): bump github/issue-labeler from 3.4 to 3.5 in the all group (charmbracelet#3763)

Bumps the all group with 1 update: [github/issue-labeler](https://github.com/github/issue-labeler).


Updates `github/issue-labeler` from 3.4 to 3.5
- [Release notes](https://github.com/github/issue-labeler/releases)
- [Commits](github/issue-labeler@c1b0f9f...ccca1e1)

---
updated-dependencies:
- dependency-name: github/issue-labeler
  dependency-version: '3.5'
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: all
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore(deps): bump the all group with 12 updates

Bumps the all group with 12 updates:

| Package | From | To |
| --- | --- | --- |
| [charm.land/catwalk](https://github.com/charmbracelet/catwalk) | `0.52.19` | `0.52.28` |
| [charm.land/log/v2](https://github.com/charmbracelet/log) | `2.0.0` | `2.0.1` |
| [github.com/modelcontextprotocol/go-sdk](https://github.com/modelcontextprotocol/go-sdk) | `1.7.1-0.20260825092617-32404652e60b` | `1.8.0-pre.2` |
| [github.com/ncruces/go-sqlite3](https://github.com/ncruces/go-sqlite3) | `0.35.3` | `0.35.4` |
| [github.com/openai/openai-go/v3](https://github.com/openai/openai-go) | `3.54.0` | `3.56.0` |
| [github.com/posthog/posthog-go](https://github.com/posthog/posthog-go) | `1.24.3` | `1.25.1` |
| [github.com/pressly/goose/v3](https://github.com/pressly/goose) | `3.27.3` | `3.28.0` |
| [golang.org/x/oauth2](https://github.com/golang/oauth2) | `0.36.0` | `0.37.0` |
| [golang.org/x/sync](https://github.com/golang/sync) | `0.22.0` | `0.23.0` |
| [golang.org/x/sys](https://github.com/golang/sys) | `0.47.0` | `0.48.0` |
| [modernc.org/sqlite](https://gitlab.com/cznic/sqlite) | `1.57.0` | `1.58.0` |
| [mvdan.cc/sh/v3](https://github.com/mvdan/sh) | `3.13.1` | `3.14.1` |


Updates `charm.land/catwalk` from 0.52.19 to 0.52.28
- [Release notes](https://github.com/charmbracelet/catwalk/releases)
- [Commits](charmbracelet/catwalk@v0.52.19...v0.52.28)

Updates `charm.land/log/v2` from 2.0.0 to 2.0.1
- [Release notes](https://github.com/charmbracelet/log/releases)
- [Commits](charmbracelet/log@v2.0.0...v2.0.1)

Updates `github.com/modelcontextprotocol/go-sdk` from 1.7.1-0.20260825092617-32404652e60b to 1.8.0-pre.2
- [Release notes](https://github.com/modelcontextprotocol/go-sdk/releases)
- [Commits](https://github.com/modelcontextprotocol/go-sdk/commits/v1.8.0-pre.2)

Updates `github.com/ncruces/go-sqlite3` from 0.35.3 to 0.35.4
- [Release notes](https://github.com/ncruces/go-sqlite3/releases)
- [Commits](ncruces/go-sqlite3@v0.35.3...v0.35.4)

Updates `github.com/openai/openai-go/v3` from 3.54.0 to 3.56.0
- [Release notes](https://github.com/openai/openai-go/releases)
- [Changelog](https://github.com/openai/openai-go/blob/main/CHANGELOG.md)
- [Commits](openai/openai-go@v3.54.0...v3.56.0)

Updates `github.com/posthog/posthog-go` from 1.24.3 to 1.25.1
- [Release notes](https://github.com/posthog/posthog-go/releases)
- [Changelog](https://github.com/PostHog/posthog-go/blob/main/CHANGELOG.md)
- [Commits](PostHog/posthog-go@v1.24.3...v1.25.1)

Updates `github.com/pressly/goose/v3` from 3.27.3 to 3.28.0
- [Release notes](https://github.com/pressly/goose/releases)
- [Changelog](https://github.com/pressly/goose/blob/main/CHANGELOG.md)
- [Commits](pressly/goose@v3.27.3...v3.28.0)

Updates `golang.org/x/oauth2` from 0.36.0 to 0.37.0
- [Commits](golang/oauth2@v0.36.0...v0.37.0)

Updates `golang.org/x/sync` from 0.22.0 to 0.23.0
- [Commits](golang/sync@v0.22.0...v0.23.0)

Updates `golang.org/x/sys` from 0.47.0 to 0.48.0
- [Commits](golang/sys@v0.47.0...v0.48.0)

Updates `modernc.org/sqlite` from 1.57.0 to 1.58.0
- [Changelog](https://gitlab.com/cznic/sqlite/blob/master/CHANGELOG.md)
- [Commits](https://gitlab.com/cznic/sqlite/compare/v1.57.0...v1.58.0)

Updates `mvdan.cc/sh/v3` from 3.13.1 to 3.14.1
- [Release notes](https://github.com/mvdan/sh/releases)
- [Changelog](https://github.com/mvdan/sh/blob/master/CHANGELOG.md)
- [Commits](mvdan/sh@v3.13.1...v3.14.1)

---
updated-dependencies:
- dependency-name: charm.land/catwalk
  dependency-version: 0.52.28
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: all
- dependency-name: charm.land/log/v2
  dependency-version: 2.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: all
- dependency-name: github.com/modelcontextprotocol/go-sdk
  dependency-version: 1.8.0-pre.2
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: all
- dependency-name: github.com/ncruces/go-sqlite3
  dependency-version: 0.35.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: all
- dependency-name: github.com/openai/openai-go/v3
  dependency-version: 3.56.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: all
- dependency-name: github.com/posthog/posthog-go
  dependency-version: 1.25.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: all
- dependency-name: github.com/pressly/goose/v3
  dependency-version: 3.28.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: all
- dependency-name: golang.org/x/oauth2
  dependency-version: 0.37.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: all
- dependency-name: golang.org/x/sync
  dependency-version: 0.23.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: all
- dependency-name: golang.org/x/sys
  dependency-version: 0.48.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: all
- dependency-name: modernc.org/sqlite
  dependency-version: 1.58.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: all
- dependency-name: mvdan.cc/sh/v3
  dependency-version: 3.14.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: all
...

Signed-off-by: dependabot[bot] <support@github.com>

* chore(deps): revert mcp sdk to previous version

* v0.93.0

* ci: fix goreleaser

* v0.93.1

* chore(legal): @ifsin has signed the CLA

* fix(sessions): keep list position after deletion (charmbracelet#3769)

* chore(event-bus): make event fan-in helpers generic methods (charmbracelet#3768)

Co-authored-by: Tai Groot <amittai.groot@gsa.gov>

* ui-perf: memoize rendered frames for scroll-only updates

Bubble Tea runs Update+View synchronously per message, so a flood of
wheel events pays for a full redraw each even when the scroll offset is
clamped or returns to a recent position. Cache frames keyed by chat
scroll position with a 3s TTL, LRU cap of 32, sweep-on-put and an idle
GC tick so memory cannot grow unbounded. Only chat scroll handlers mark
an update as scroll-only; everything else resets the cache, and layout
changes during Draw discard the frame.

Co-Authored-By: Tai Groot <amittai.groot@gsa.gov>

* ui-perf: stop coalesced wheel scrolls from rewinding to the selection

With delta coalescing, one wheel message can carry many lines of
scroll, but the handler only moved the selection one item and then
scrolled back to it, undoing most of the delta. Move an out-of-view
selection to the nearest visible edge instead so the full coalesced
delta is applied.

Co-Authored-By: Tai Groot <amittai.groot@gsa.gov>

* chore(legal): @Cubixmeister has signed the CLA

* ui-perf: drive all spinners from one shared animation clock

Every anim.Anim used to schedule its own 20Hz tea.Tick chain, so N
running spinners meant N full Update+View passes per frame, each also
resetting the frame cache and re-pinning follow mode. Replace the
per-item chains with a single animTickMsg owned by Chat: one tick per
frame advances every visible spinner, the clock stops itself when
nothing visible spins, and Update's tail re-arms it whenever a spinner
appears. Ticks carry a generation so a delayed tick can never run
alongside a replacement clock, and frames that change nothing are
served from the frame cache. Animatable becomes Spinning/Advance;
pausedAnimations, RestartPausedVisibleAnimations and startItemAnimations
are gone.

Co-authored-by: Tai Groot <amittai.groot@gsa.gov>

* chore(legal): @sam0uly has signed the CLA

* chore(legal): @S2thend has signed the CLA

* noninteractive: add --reasoning-effort flag with model validation

💘 Generated with Crush

Assisted-by: Crush:glm-5.3-flash

* chore: auto-update files

* fix: always emit tool results right after calls (charmbracelet#3743)

* fix: always emit tool results right after calls

Signed-off-by: drew <me@andrinoff.com>

* fix: add warning

Co-authored-by: Christian Rocha <christian@rocha.is>

---------

Signed-off-by: drew <me@andrinoff.com>
Co-authored-by: Christian Rocha <christian@rocha.is>

* fix: dropped reasoning effort (charmbracelet#3748)

Signed-off-by: drew <me@andrinoff.com>

* fix: always show full bash command in tui, output stays collapsible

Assisted-by: Crush:prism

* fix: keep scroll position when expanding or collapsing chat items

Assisted-by: Crush:prism

* fix: show content in full when collapsing would hide only one line

Assisted-by: Crush:prism

* refactor: replace swaggo annotations with a Go-native endpoint registry

API routes and docs now share one source of truth: a fluent registry
(internal/apigen) whose entries drive both mux registration and the
docs served at /v1/docs/ (plain HTML page plus an OpenAPI 3.1 spec).
Body schemas are derived from the real proto types via a small stdlib
reflection walker, so renamed types break the build and stale
annotation comments can no longer drift from the routes.

Removes the generated internal/swagger artifacts, the task swag
codegen step, and the swaggo dependencies.

💘 Generated with Crush

Assisted-by: Crush:kimi-k3

* feat: OpenAI oAuth

Signed-off-by: drew <me@andrinoff.com>

* chore: lint

Signed-off-by: drew <me@andrinoff.com>

* chore: bump fantasy

Signed-off-by: drew <me@andrinoff.com>

* fix: remove re-routing logic

Signed-off-by: drew <me@andrinoff.com>

* fix: do not remove from API catalogue

Signed-off-by: drew <me@andrinoff.com>

* fix: refine first page

Signed-off-by: drew <me@andrinoff.com>

* fix: match ex. anthropic UI on choice

Signed-off-by: drew <me@andrinoff.com>

* fix: remove the separate sections

Signed-off-by: drew <me@andrinoff.com>

* fix: remove the Sign In with ChatGPT in catalogue

Signed-off-by: drew <me@andrinoff.com>

* fix: colorize CLI mode and use localhost URL

Signed-off-by: drew <me@andrinoff.com>

* fix: @meowgorithm review

Signed-off-by: drew <me@andrinoff.com>

* oauth-ui: small nudges

* oauth-ui: use ChatGPT instead of OpenAI in the auth dialog copy

* oauth-cli: overhaul and unify oauth TUIs

* oauth-cli: adjust inline logout TUIs

* chore: auto-update files

* v0.94.1

* chore(legal): @aashish00021 has signed the CLA

* chore(legal): @yanyukang2003-ux has signed the CLA

* chore(legal): @cloudcodec has signed the CLA

* chore(legal): @m1k3s0 has signed the CLA

* chore(legal): @notrudyyy has signed the CLA

* fix(home): require path boundary when shortening or expanding ~ (charmbracelet#3552)

* openaicompat: bump fantasy to fix regression around reasoning-only turns

Some recent Kimi/Deepseek fixes in Fantasy introduced a regression that
could break the conversation if a turn was canceled while thinking. This
fixes that.

* deps: go mod tidy

* v0.94.2

* fix(tui): unfreeze spinner clock when the boot busy probe lands (charmbracelet#3839)

A session loaded before the first busy probe returns reads the
zero-value memoized busy cache and freezes the shared animation clock,
so a spinner rendered on boot never ticks. Re-enable the clock when
the authoritative probe reports the agent busy; idle probes leave the
gate alone so the ghost-spinner guard stands.

Assisted-by: Crush:prism

* fifix(ui): color the to-do task name while the tool is still running

* perf(ui): skip the global prompt-history scan when a session is loading

Starting with a session was far slower than switching to the same one
with ctrl+s: 2,750ms against 58ms for identical work, almost all of it a
single-row GetSession waiting 2,681ms to run.

Init batches prompt history alongside the initial session load. The
session is not set yet at that point, so history takes its no-session
branch and reads every user message in the database, which SQLite serves
by walking all 126,717 rows of a 743MB table in index order. The pool is
one connection, so the session load waits behind it. Switching sessions
never hit this: a session is set by then, so history reads only that
session's messages.

The work was redundant anyway. loadSessionMsg already reloads prompt
history for the session that arrives, so the startup result was
discarded. Asking only when no session is coming leaves loadSession at
63ms, matching the ctrl+s path.

* perf(db): index messages by role so user-message reads stop scanning

Listing every user message is how prompt history loads when no session is
set. There is no index on role, so SQLite walks all 126,717 rows of a
743MB messages table in created_at order to return the 7,478 that match.

Leading the index with role turns that into a seek, and keeping
created_at second returns them already ordered, so the DESC ordering
needs no sort. Measured on a copy of a 1.1GB database:

  plan     SCAN messages USING INDEX idx_messages_created_at
        -> SEARCH messages USING INDEX idx_messages_role_created_at (role=?)
  query    0.24-0.53s -> 0.02-0.04s warm
  service  335ms -> 157ms end to end, the rest being JSON decoding
  index    2.44MB, 0.2% of the database
  migrate  ~4s once on that database, 0.33s of it the scan and sort

Streaming writes are unaffected: UpdateMessage sets parts and timestamps,
neither of which this index covers, so there is no index maintenance on
the hot path. Measured at 2,000 inserts and 5,000 updates, the difference
was inside the noise.

* perf(db): cap prompt history at the 200 most recent messages

Both user-message queries exist only to fill up-arrow recall, and both
read every matching message with its full parts: 7,478 rows and 12.5MB of
JSON on this database, to populate a list walked one entry at a time.

200 is well past what anyone reaches a keystroke at a time, and the cap
compounds with the role index: SQLite seeks to the user rows and stops
after 200 instead of reading them all. ListAllUserMessages goes from
335ms warm (1.98s cold) to 3.8ms.

Paginating instead would suit a history that could be searched or jumped
into. This one only steps backwards from the newest entry, so paging
would add offset tracking and an in-flight guard to serve a reader 200
presses deep, and put a database read in the middle of a keystroke to do
it. The cap is the simpler shape for how the list is actually used.

The limit lives in the SQL because these two queries have exactly one
consumer between them; threading a parameter would cross the message
service, the workspace interface, both workspace implementations, the
backend and the wire protocol to carry a constant.

* fix(ui): read the session transcript off the event loop

Update handled loadSessionMsg by calling ListMessages inline, so the
whole TUI froze while it ran, with no spinner to say why. A 5000-message
session takes ~470ms, nine tenths of it JSON decoding rather than
SQLite. The load cmd already fetches the session, its files and its read
files off-thread; the transcript goes with them.

* perf(agent): read only the post-summary tail of a compacted session

getSessionMessages read the whole transcript and then discarded
everything before the summary. The cost is almost entirely JSON decoding
and so scales with bytes kept: across the 34 compacted sessions on hand,
3.09s of decoding to use 0.76s of it, and one session decodes 34.2MB to
keep a single message. ListFromSummary asks for the tail instead,
falling back to the full session when the summary message is gone so a
dangling id cannot erase the history.

* perf(message): decode message parts in one structural pass

unmarshalParts walked each stored blob three times: once to split it into
json.RawMessage, once per part to read the type tag, and once more to
decode the payload. Decoding straight into a []rawPartWrapper gets the
tag and the still-encoded payload together, dropping the middle walk.

Across all 126,719 stored messages (780MB) this decodes 1.34x faster and
produces byte-identical parts. Decoding is ~90% of the cost of loading a
session, the rest being SQLite, so this is the part worth cutting.

A token-stream decoder reaches 1.55x by walking the payload once too, but
needs ~90 lines of hand-rolled token handling and a fallback for when
"data" precedes "type". Struct decoding handles key order for free.

* chore(legal): @paulhovey has signed the CLA

* chore(legal): @vulragrag-star has signed the CLA

* chore(legal): @dakaii has signed the CLA

* feat: add plan mode (charmbracelet#2822)

* fix(test): make stdioCheck timeout configurable and add WaitDelay

* feat: add plan mode

* fix(ui): show both yolo and plan markers when both modes are active

* fix(plan): add risks consideration

* fix(ui): show plan in status bar only

* fix(plan): added instructs

* fix: check status exists

* fix(plan): refine workflow and style guidelines for clarity and precision

* fix(plan): mutate model synchronously in toggleInputMode to prevent cursor glitch

* fix(plan): enhance plan mode description

* fix(plan): clarify wording for search tools in workflow instructions

* chore: rebase maintenance

* feat(plan): implement plan handoff dialog and add question tool usage

* fix(plan): refine question tool usage and confirmation process in planning rules

* feat(plan): implement inline plan handoff prompt and update related logic

* chore(plan): fix

* feat(plan): add plan-ready marker detection and styling for final plan messages

* feat(plan): add "Critical Files" section to final plan response

* feat(plan): implement plan-ready marker handling and UI updates

* feat(styles): enhance PlanMarkdown styling for headings in quickStyle

* feat(styles): update PlanMarkdown to replace raw markdown prefixes with clean indentation

* chore: lint

* feat(plan): implement plan card rendering with uniform background

* chore(plan): update inline prompt button text

* feat(plan): implement feedback editor for plan handoff

* feat(plan): enhance plan card rendering to fit available width and improve layout handling

* fix: align vertical button hits

* feat: improve plan handoff input

* fix(plan): refine handoff copy and styling

* test: parallelize plan card width subtests

* feat(backend): add SetMainAgent to switch active workspace agent

* fix(plan): reconcile plan mode with upstream agent-ready and busy APIs

Post-rebase fixes for API changes that landed on main while the plan
mode branch was in flight:

- handleClickFocus: drop the unconditional m.chat.Blur() when an inline
  editor takes focus; focusActiveInline already blurs the chat and is
  nil-safe.
- testWorkspace: implement AgentReadyErr, which sendMessage now uses
  instead of AgentIsReady.
- TestToggleInputMode_BlockedWhileAgentBusy: seed agentBusyCache, since
  isAgentBusy now reads the memoized cache rather than the workspace.

* feat(core): support hidden user messages

* docs(plan): relax sub-agent workflow

* feat(plan): add YOLO handoff and prompt indicator

* feat(ui): add dedicated yolo coding key to plan handoff dialog

* fix(ui): only let Shift+Tab cycle disable cycle-enabled YOLO

* fix(ui): preserve plan code backgrounds

* fix(ui): report yolo input mode

* fix: make inline code in plan red

Signed-off-by: drew <me@andrinoff.com>

* remove plan-yolo

Signed-off-by: drew <me@andrinoff.com>

* chore: fixup the code

Signed-off-by: drew <me@andrinoff.com>

* chore: lint

Signed-off-by: drew <me@andrinoff.com>

* feat: UI improvements

Signed-off-by: drew <me@andrinoff.com>

* fix: add border around plan card

Signed-off-by: drew <me@andrinoff.com>

* fix: improve selection of coding options

Signed-off-by: drew <me@andrinoff.com>

* address review

Signed-off-by: drew <me@andrinoff.com>

* address feedback 2

Signed-off-by: drew <me@andrinoff.com>

* final review addressed

Signed-off-by: drew <me@andrinoff.com>

* fix: add a start marker for UI

Signed-off-by: drew <me@andrinoff.com>

* correct color

Signed-off-by: drew <me@andrinoff.com>

---------

Signed-off-by: drew <me@andrinoff.com>
Co-authored-by: drew <me@andrinoff.com>
Co-authored-by: Christian Rocha <christian@rocha.is>

* chore: auto-update files

* v0.95.0

Signed-off-by: drew <me@andrinoff.com>

* chore: bump devShell to Go 1.27 (charmbracelet#3832)

* chore(legal): @Applone has signed the CLA

* fix(ui): set the finish banner off from the message above it (charmbracelet#3815)

* chore: double default request timeout from 60 to 120 seconds (charmbracelet#3862)

* chore: auto-update files

* chore(legal): @workingdad365 has signed the CLA

* fix(ui): nudge the yolo/plan badges + align help (charmbracelet#3863)

* chore(legal): @angelinaaziz has signed the CLA

* fix(ui): drop the empty gap under a failed edit (charmbracelet#3851)

* chore(legal): @lleqsnoom has signed the CLA

* chore(legal): @rpx99 has signed the CLA

* chore(legal): @Oscar-Williams has signed the CLA

* fix: wrapping in plan display (charmbracelet#3888)

* chore(legal): @x1uc has signed the CLA

* fix(ui): keep syntax highlighting across a wrapped tool parameter (charmbracelet#3850)

* chore(legal): @0xrytter has signed the CLA

* fix(shell): bound bang-mode output and spill the rest to a file

Bang-mode output was persisted and sent to the model in full, so a single
`git log` could hand the agent the entire repo history. Keep the head and
tail of oversized output, write the complete text to the data directory,
and point the agent at it. Spills are swept after a week.

* fix(bash): let the agent recover truncated tool output

The bash and job_output tools cut the middle out of long output and
dropped it for good. Spill the full text alongside the truncation marker
so the agent can read back what it needs.

* test: regen golden files

* chore(legal): @feiiiiii5 has signed the CLA

* feat: add theme support (charmbracelet#3884)

Co-authored-by: drew <me@andrinoff.com>
Co-authored-by: Gurney Buchanan <gurney.buchanan@gmail.com>
Co-authored-by: Christian Rocha <christian@rocha.is>
Signed-off-by: drew <me@andrinoff.com>

* chore: auto-update files

* feat(hyper): live display of hypercredits (charmbracelet#3699)

Signed-off-by: drew <me@andrinoff.com>

* v0.96.0

Signed-off-by: drew <me@andrinoff.com>

* themes: small adjustments to the key names in the theme API

insert_bg -> insert_code_bg
delete_bg -> delete_code_bg

This is a breaking change, though a small one.

* themes: prefix diff theme keys with diff_

* v0.96.1

* chore(deps): update fantasy and catwalk, return to openai sdk fork (charmbracelet#3911)

This patch updates Fantasy, which includes improvements to invalid JSON
recovery and beings back our internal OpenAI ASK fixes for issues when
the provider return invalid JSON (HTML, for example).

* OpenAI SDK PR: openai/openai-go#914
* Fantasy PR: charmbracelet/fantasy#381

* chore(legal): @samuelmarinsoto has signed the CLA

* chore: fantasy v0.45.1

* test(server): pin the fork-only routes across the upstream sync port

The sync replaced the hand-written mux.HandleFunc list with the declarative
endpoint registry, so the fork's four extra routes had to be ported by hand.
A route dropped in that port fails only at runtime as a 404 from a client
that used to work, with nothing at compile time to catch it. Assert each
route is registered, and that mcp/call-tool still declares the 403 its
allow-list guard returns.

* test(ui): pin the plan and A2UI content-cache key contract

The sync folded the fork's finish-state cache bit and upstream's plan-state
bit into two separate bits of one content key. Both renders share the
contentSec slot, so collapsing the bits or reordering the render switch would
let a plan card and an A2UI surface serve each other a cached render. Assert
the bits stay orthogonal, that the two renders do not collide, and that the
plan branches still drop surfaces held from an earlier render.

---------

Signed-off-by: drew <me@andrinoff.com>
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Dan Xin <davinci42.cn@gmail.com>
Co-authored-by: Charm <124303983+charmcli@users.noreply.github.com>
Co-authored-by: Lars Artmann <github@d1rk.art>
Co-authored-by: Yash Raj Pandey <55940078+devYRPauli@users.noreply.github.com>
Co-authored-by: Tim Hawes <trhawes@gmail.com>
Co-authored-by: drew <me@andrinoff.com>
Co-authored-by: Jack Leow <jackgene@gmail.com>
Co-authored-by: Drew Smirnoff <drew@charm.land>
Co-authored-by: Andrey Nering <andrey@nering.com.br>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Ifsin <57553565+ifsin@users.noreply.github.com>
Co-authored-by: Christian Rocha <christian@rocha.is>
Co-authored-by: Tai Groot <amittai.groot@gsa.gov>
Co-authored-by: Teddy Tennant <teddytennant@icloud.com>
Co-authored-by: Kieran Klukas <kieran@dunkirk.sh>
Co-authored-by: Vadim Inshakov <vadiminshakov@gmail.com>
Co-authored-by: Lars Artmann <git@lars.software>
Co-authored-by: Gurney Buchanan <gurney.buchanan@gmail.com>
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Co-authored-by: joestump-agent <agent@stump.wtf>
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.

3 participants