Repository navigation
chore: bump devShell to Go 1.27 - #3832
Merged
taciturnaxolotl merged 1 commit intoSep 16, 2026
Merged
Conversation
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
force-pushed
the
chore/devshell-go-1_27
branch
from
September 15, 2026 08:10
34e0531 to
c39860a
Compare
Contributor
Author
|
Nice :) |
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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
go.modrequiresgo >= 1.27.0, but the devShell pinsgo_1_26. Insidenix develop,go build/go vet/gopls all fail withgo.mod requires go >= 1.27.0 (running go 1.26.7).What changed
flake.nix:go_1_26→go_1_27flake.lock: bumped thenixpkgsinput — the previously pinned rev (68d8aa3d) has nogo_1_27attribute, 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.1go build ./...passes inside the shell💘 Generated with Crush