From 91b05f57f57e0bc63c7401dc930b1f083c61b1c8 Mon Sep 17 00:00:00 2001 From: Ayman Bagabas Date: Tue, 8 Jul 2025 17:03:01 -0400 Subject: [PATCH 01/10] fix(tui): copy textarea value to editor on open --- internal/tui/components/chat/editor/editor.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/internal/tui/components/chat/editor/editor.go b/internal/tui/components/chat/editor/editor.go index 30d3aeef80c57487e665952f699cd7b4522db214..4b94900903cce6dc5105d384e78e200301c3fc2d 100644 --- a/internal/tui/components/chat/editor/editor.go +++ b/internal/tui/components/chat/editor/editor.go @@ -67,7 +67,7 @@ const ( maxAttachments = 5 ) -func (m *editorCmp) openEditor() tea.Cmd { +func (m *editorCmp) openEditor(value string) tea.Cmd { editor := os.Getenv("EDITOR") if editor == "" { // Use platform-appropriate default editor @@ -82,6 +82,7 @@ func (m *editorCmp) openEditor() tea.Cmd { if err != nil { return util.ReportError(err) } + _, _ = tmpfile.WriteString(value) tmpfile.Close() c := exec.Command(editor, tmpfile.Name()) c.Stdin = os.Stdin @@ -239,7 +240,7 @@ func (m *editorCmp) Update(msg tea.Msg) (tea.Model, tea.Cmd) { if m.app.CoderAgent.IsSessionBusy(m.session.ID) { return m, util.ReportWarn("Agent is working, please wait...") } - return m, m.openEditor() + return m, m.openEditor(m.textarea.Value()) } if key.Matches(msg, DeleteKeyMaps.Escape) { m.deleteMode = false From 0016e441ebc803cac346e11312470cb642be3eb4 Mon Sep 17 00:00:00 2001 From: Ayman Bagabas Date: Thu, 10 Jul 2025 10:31:09 -0400 Subject: [PATCH 02/10] chore(tui): editor: return error on write failure --- internal/tui/components/chat/editor/editor.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/internal/tui/components/chat/editor/editor.go b/internal/tui/components/chat/editor/editor.go index 4b94900903cce6dc5105d384e78e200301c3fc2d..5f8a3548aa47810c3583f6d2b6a6c184809ba178 100644 --- a/internal/tui/components/chat/editor/editor.go +++ b/internal/tui/components/chat/editor/editor.go @@ -82,8 +82,10 @@ func (m *editorCmp) openEditor(value string) tea.Cmd { if err != nil { return util.ReportError(err) } - _, _ = tmpfile.WriteString(value) - tmpfile.Close() + defer tmpfile.Close() //nolint:errcheck + if _, err := tmpfile.WriteString(value); err != nil { + return util.ReportError(err) + } c := exec.Command(editor, tmpfile.Name()) c.Stdin = os.Stdin c.Stdout = os.Stdout From d34161b9e77b6d7914f351f8c675e8ee7953de02 Mon Sep 17 00:00:00 2001 From: Carlos Alexandro Becker Date: Thu, 10 Jul 2025 13:40:43 -0300 Subject: [PATCH 03/10] ci: only build nightlies if there are something to build (#126) this should save us a bit of actions money --- .github/workflows/nightly.yml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 1e271bbb6e180557b241a6ab5e40acf7b82705df..fdc2d260570dd0acb7abe0d5371bed32b05b29f2 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -6,7 +6,25 @@ on: workflow_dispatch: # allows manual triggering jobs: + check: + runs-on: ubuntu-latest + outputs: + should_run: ${{ steps.check.outputs.should_run }} + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 1 + - id: check + env: + GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" + run: | + if gh run list --workflow nightly.yml -c $(git rev-parse HEAD) -s success | grep 'completed'; then + echo "should_run=false" >> $GITHUB_OUTPUT + else + echo "should_run=true" >> $GITHUB_OUTPUT + fi nightly: + needs: check uses: charmbracelet/meta/.github/workflows/nightly.yml@main secrets: goreleaser_key: ${{ secrets.GORELEASER_KEY }} From 2d6f2bd99c38a6ede214b136832c13c6cb46255c Mon Sep 17 00:00:00 2001 From: Christian Rocha Date: Thu, 10 Jul 2025 12:41:43 -0400 Subject: [PATCH 04/10] chore: remove background color on 'waiting for tool to start' --- internal/tui/components/chat/messages/renderer.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/tui/components/chat/messages/renderer.go b/internal/tui/components/chat/messages/renderer.go index 2d86d103bc60f2122c3eaf58883bd6d9ac42a47e..5762583870e99591ded1bff84f80c34b3335b190 100644 --- a/internal/tui/components/chat/messages/renderer.go +++ b/internal/tui/components/chat/messages/renderer.go @@ -623,7 +623,7 @@ func earlyState(header string, v *toolCallCmp) (string, bool) { case v.cancelled: message = t.S().Base.Padding(0, 1).Background(t.Border).Render("Cancelled") case v.result.ToolCallID == "": - message = t.S().Base.Padding(0, 1).Background(t.Accent).Foreground(t.FgSubtle).Render("Waiting for tool to start...") + message = t.S().Base.Foreground(t.FgSubtle).Render("Waiting for tool to start...") default: return "", false } From 6156b38e281b47eb2e299a4e1c4052ad8fe135f6 Mon Sep 17 00:00:00 2001 From: Christian Rocha Date: Thu, 10 Jul 2025 12:42:50 -0400 Subject: [PATCH 05/10] chore(lint): add missing GoDoc --- internal/tui/components/chat/editor/editor.go | 1 + 1 file changed, 1 insertion(+) diff --git a/internal/tui/components/chat/editor/editor.go b/internal/tui/components/chat/editor/editor.go index ee374a6c1e0e68aaebef74fee07edb62292d68fe..b835aed20a9d07ddccd5f292f36503856a5d241d 100644 --- a/internal/tui/components/chat/editor/editor.go +++ b/internal/tui/components/chat/editor/editor.go @@ -378,6 +378,7 @@ func (c *editorCmp) IsFocused() bool { return c.textarea.Focused() } +// Bindings implements Container. func (c *editorCmp) Bindings() []key.Binding { return c.keyMap.KeyBindings() } From a7407034dcd4278af6013d1e70cc5f5653c1a64b Mon Sep 17 00:00:00 2001 From: Christian Rocha Date: Thu, 10 Jul 2025 12:52:13 -0400 Subject: [PATCH 06/10] chore(deps): bump charmtone --- go.mod | 2 +- go.sum | 2 + .../x/exp/charmtone/charmtone.go | 58 +++++++++++++++++-- vendor/modules.txt | 2 +- 4 files changed, 56 insertions(+), 8 deletions(-) diff --git a/go.mod b/go.mod index 7f4d7493c34e10a1d62bb311afc71b12e930ecd1..584d744aee92be227731f5447185f58f16932bc3 100644 --- a/go.mod +++ b/go.mod @@ -23,7 +23,7 @@ require ( github.com/charmbracelet/lipgloss/v2 v2.0.0-beta.2.0.20250703152125-8e1c474f8a71 github.com/charmbracelet/log/v2 v2.0.0-20250226163916-c379e29ff706 github.com/charmbracelet/x/ansi v0.9.3 - github.com/charmbracelet/x/exp/charmtone v0.0.0-20250627134340-c144409e381c + github.com/charmbracelet/x/exp/charmtone v0.0.0-20250708181618-a60a724ba6c3 github.com/charmbracelet/x/exp/golden v0.0.0-20250207160936-21c02780d27a github.com/disintegration/imageorient v0.0.0-20180920195336-8147d86e83ec github.com/fsnotify/fsnotify v1.8.0 diff --git a/go.sum b/go.sum index d35233348b9c20b1d5556294a2f2bce4b2f9e2a9..19a95dddf7907257558b02b0dece77e8482a0067 100644 --- a/go.sum +++ b/go.sum @@ -90,6 +90,8 @@ github.com/charmbracelet/x/cellbuf v0.0.14-0.20250516160309-24eee56f89fa h1:lphz github.com/charmbracelet/x/cellbuf v0.0.14-0.20250516160309-24eee56f89fa/go.mod h1:xBlh2Yi3DL3zy/2n15kITpg0YZardf/aa/hgUaIM6Rk= github.com/charmbracelet/x/exp/charmtone v0.0.0-20250627134340-c144409e381c h1:2GELBLPgfSbHU53bsQhR9XIgNuVZ6w+Rz8RWV5Lq+A4= github.com/charmbracelet/x/exp/charmtone v0.0.0-20250627134340-c144409e381c/go.mod h1:T9jr8CzFpjhFVHjNjKwbAD7KwBNyFnj2pntAO7F2zw0= +github.com/charmbracelet/x/exp/charmtone v0.0.0-20250708181618-a60a724ba6c3 h1:1xwHZg6eMZ9Wv5TE1UGub6ARubyOd1Lo5kPUI/6VL50= +github.com/charmbracelet/x/exp/charmtone v0.0.0-20250708181618-a60a724ba6c3/go.mod h1:T9jr8CzFpjhFVHjNjKwbAD7KwBNyFnj2pntAO7F2zw0= github.com/charmbracelet/x/exp/golden v0.0.0-20250207160936-21c02780d27a h1:FsHEJ52OC4VuTzU8t+n5frMjLvpYWEznSr/u8tnkCYw= github.com/charmbracelet/x/exp/golden v0.0.0-20250207160936-21c02780d27a/go.mod h1:wDlXFlCrmJ8J+swcL/MnGUuYnqgQdW9rhSD61oNMb6U= github.com/charmbracelet/x/exp/slice v0.0.0-20250611152503-f53cdd7e01ef h1:v7qwsZ2OxzlwvpKwz8dtZXp7fIJlcDEUOyFBNE4fz4Q= diff --git a/vendor/github.com/charmbracelet/x/exp/charmtone/charmtone.go b/vendor/github.com/charmbracelet/x/exp/charmtone/charmtone.go index 48cb93adfb19bfedfcda0e1ce2fcb42c2f64785e..6e32f7f5405de89eeea58003f8860e255861ccee 100644 --- a/vendor/github.com/charmbracelet/x/exp/charmtone/charmtone.go +++ b/vendor/github.com/charmbracelet/x/exp/charmtone/charmtone.go @@ -65,7 +65,7 @@ const ( Citron Zest Pepper - Barbeque + BBQ Charcoal Iron Oyster @@ -74,6 +74,22 @@ const ( Ash Salt Butter + + // Diffs: additions. The brightest color in this set is Julep, defined + // above. + Pickle + Gator + Spinach + + // Diffs: deletions. The brightest color in this set is Cherry, defined + // above. + Pom + Steak + Toast + + // Provisional. + NeueGuac + NeueZinc ) // RGBA returns the red, green, blue, and alpha values of the color. It @@ -139,7 +155,7 @@ func (k Key) String() string { Citron: "Citron", Zest: "Zest", Pepper: "Pepper", - Barbeque: "Barbeque", + BBQ: "BBQ", Charcoal: "Charcoal", Iron: "Iron", Oyster: "Oyster", @@ -148,6 +164,20 @@ func (k Key) String() string { Salt: "Salt", Ash: "Ash", Butter: "Butter", + + // Diffs: additions. + Pickle: "Pickle", + Gator: "Gator", + Spinach: "Spinach", + + // Diffs: deletions. + Pom: "Pom", + Steak: "Steak", + Toast: "Toast", + + // Provisional. + NeueGuac: "Neue Guac", + NeueZinc: "Neue Zinc", }[k] } @@ -193,17 +223,17 @@ func (k Key) Hex() string { Damson: "#007AB8", Malibu: "#00A4FF", Sardine: "#4FBEFE", - Zinc: "#0e9996", + Zinc: "#10B1AE", Turtle: "#0ADCD9", Lichen: "#5CDFEA", - Guac: "#00b875", + Guac: "#12C78F", Julep: "#00FFB2", Bok: "#68FFD6", Mustard: "#F5EF34", Citron: "#E8FF27", Zest: "#E8FE96", Pepper: "#201F26", - Barbeque: "#2d2c35", + BBQ: "#2d2c35", Charcoal: "#3A3943", Iron: "#4D4C57", Oyster: "#605F6B", @@ -212,6 +242,20 @@ func (k Key) Hex() string { Ash: "#DFDBDD", Salt: "#F1EFEF", Butter: "#FFFAF1", + + // Diffs: additions. + Pickle: "#00A475", + Gator: "#18463D", + Spinach: "#1C3634", + + // Diffs: deletions. + Pom: "#AB2454", + Steak: "#582238", + Toast: "#412130", + + // Provisional. + NeueGuac: "#00b875", + NeueZinc: "#0e9996", }[k] } @@ -267,7 +311,7 @@ func Keys() []Key { Citron, Zest, Pepper, - Barbeque, + BBQ, Charcoal, Iron, Oyster, @@ -276,6 +320,8 @@ func Keys() []Key { Ash, Salt, Butter, + + // XXX: additions and deletions are not included, yet. } } diff --git a/vendor/modules.txt b/vendor/modules.txt index e256e639e4098adadaf25a32fa4a05937e2066d7..efb2e6060edbc66478d6086ee6e5f5df266c881d 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -288,7 +288,7 @@ github.com/charmbracelet/x/ansi/parser # github.com/charmbracelet/x/cellbuf v0.0.14-0.20250516160309-24eee56f89fa ## explicit; go 1.23.0 github.com/charmbracelet/x/cellbuf -# github.com/charmbracelet/x/exp/charmtone v0.0.0-20250627134340-c144409e381c +# github.com/charmbracelet/x/exp/charmtone v0.0.0-20250708181618-a60a724ba6c3 ## explicit; go 1.23.0 github.com/charmbracelet/x/exp/charmtone # github.com/charmbracelet/x/exp/golden v0.0.0-20250207160936-21c02780d27a From b323656771961e9354121f7a48f165769224d4f7 Mon Sep 17 00:00:00 2001 From: Christian Rocha Date: Thu, 10 Jul 2025 12:52:35 -0400 Subject: [PATCH 07/10] chore(theme): use new BBQ tone --- internal/tui/styles/crush.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/tui/styles/crush.go b/internal/tui/styles/crush.go index f59b78ac2202a268337af48913fd2e3a397f4ef5..48911d7096f7b0d104b0361ae5f6632c9658e536 100644 --- a/internal/tui/styles/crush.go +++ b/internal/tui/styles/crush.go @@ -16,7 +16,7 @@ func NewCrushTheme() *Theme { // Backgrounds BgBase: charmtone.Pepper, - BgBaseLighter: Lighten(charmtone.Pepper, 2), + BgBaseLighter: charmtone.BBQ, BgSubtle: charmtone.Charcoal, BgOverlay: charmtone.Iron, From 0134f81f45180c486995b56815a81c4c026c8f3d Mon Sep 17 00:00:00 2001 From: Christian Rocha Date: Thu, 10 Jul 2025 12:55:31 -0400 Subject: [PATCH 08/10] chore: simplify 'canceled' styling + use american spelling --- internal/tui/components/chat/messages/renderer.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/tui/components/chat/messages/renderer.go b/internal/tui/components/chat/messages/renderer.go index 5762583870e99591ded1bff84f80c34b3335b190..c5cc2bc8f8bf4754c459ace83a8ec4c9cf4c94a6 100644 --- a/internal/tui/components/chat/messages/renderer.go +++ b/internal/tui/components/chat/messages/renderer.go @@ -621,7 +621,7 @@ func earlyState(header string, v *toolCallCmp) (string, bool) { case v.result.IsError: message = v.renderToolError() case v.cancelled: - message = t.S().Base.Padding(0, 1).Background(t.Border).Render("Cancelled") + message = t.S().Base.Foreground(t.FgSubtle).Render("Canceled.") case v.result.ToolCallID == "": message = t.S().Base.Foreground(t.FgSubtle).Render("Waiting for tool to start...") default: From 573c9a064806ecc4b5686708a6a1d34217870f11 Mon Sep 17 00:00:00 2001 From: Christian Rocha Date: Thu, 10 Jul 2025 13:00:03 -0400 Subject: [PATCH 09/10] chore: use american spelling for 'canceled' in all user-facing copy --- cmd/root.go | 4 ++-- internal/llm/agent/agent.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cmd/root.go b/cmd/root.go index 20c92f19357ed3350a36633c9b1be7bd91cd7ce0..8c407ace937510a192245033d2fff2b1f242641a 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -237,11 +237,11 @@ func setupSubscriber[T any]( case <-time.After(2 * time.Second): slog.Warn("message dropped due to slow consumer", "name", name) case <-ctx.Done(): - slog.Info("subscription cancelled", "name", name) + slog.Info("subscription canceled", "name", name) return } case <-ctx.Done(): - slog.Info("subscription cancelled", "name", name) + slog.Info("subscription canceled", "name", name) return } } diff --git a/internal/llm/agent/agent.go b/internal/llm/agent/agent.go index 6d9a825f600e79d3161c6b653669abe8773db116..313b83c0448d8a668e2390368c6797c82dd22452 100644 --- a/internal/llm/agent/agent.go +++ b/internal/llm/agent/agent.go @@ -26,7 +26,7 @@ import ( // Common errors var ( - ErrRequestCancelled = errors.New("request cancelled by user") + ErrRequestCancelled = errors.New("request canceled by user") ErrSessionBusy = errors.New("session is currently processing another request") ) From 710f1be5f295d06137e9a95902ed9f5c332302c3 Mon Sep 17 00:00:00 2001 From: Carlos Alexandro Becker Date: Thu, 10 Jul 2025 14:22:45 -0300 Subject: [PATCH 10/10] ci(pro): nightly Signed-off-by: Carlos Alexandro Becker --- .github/workflows/nightly.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index fdc2d260570dd0acb7abe0d5371bed32b05b29f2..2589af4376279ce3fc5902d370f7b85bad1dcff6 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -25,6 +25,7 @@ jobs: fi nightly: needs: check + if: needs.check.outputs.should_run == 'true' uses: charmbracelet/meta/.github/workflows/nightly.yml@main secrets: goreleaser_key: ${{ secrets.GORELEASER_KEY }}