From 1f9f1904df18c820f620e1a02a27d4b15a325001 Mon Sep 17 00:00:00 2001 From: Charm <124303983+charmcli@users.noreply.github.com> Date: Thu, 12 Feb 2026 18:34:31 -0300 Subject: [PATCH 01/10] chore(legal): @PHPCraftdream has signed the CLA --- .github/cla-signatures.json | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/cla-signatures.json b/.github/cla-signatures.json index 93395e6498d3c35c3e24f0b9504c2ea362ad05a8..2fcd5045c25b332a7c728de6830a787db131094f 100644 --- a/.github/cla-signatures.json +++ b/.github/cla-signatures.json @@ -1239,6 +1239,14 @@ "created_at": "2026-02-12T11:58:04Z", "repoId": 987670088, "pullRequestNo": 2203 + }, + { + "name": "PHPCraftdream", + "id": 14233546, + "comment_id": 3893502046, + "created_at": "2026-02-12T21:34:20Z", + "repoId": 987670088, + "pullRequestNo": 2212 } ] } \ No newline at end of file From d34c56b019110ed23d886555b0209dd70cc2c34f Mon Sep 17 00:00:00 2001 From: Ayman Bagabas Date: Fri, 13 Feb 2026 14:20:26 +0300 Subject: [PATCH 02/10] Merge pull request #2204 from charmbracelet/charm-1151-toggling-open-a-block-while-streaming-causes-jitter fix(ui): chat: use follow indicator to determine auto-scrolling behavior --- internal/ui/list/list.go | 6 ++-- internal/ui/model/chat.go | 71 ++++++++++++++++++++++++++++++++------- internal/ui/model/ui.go | 20 ++++++----- 3 files changed, 71 insertions(+), 26 deletions(-) diff --git a/internal/ui/list/list.go b/internal/ui/list/list.go index aec21715fcd924fde40ab9c41e9a4b6e65727ee8..32a8e661a5caaba2c8f36235eb554a2044ee14e0 100644 --- a/internal/ui/list/list.go +++ b/internal/ui/list/list.go @@ -77,9 +77,7 @@ func (l *List) Gap() int { // AtBottom returns whether the list is showing the last item at the bottom. func (l *List) AtBottom() bool { - const margin = 2 - - if len(l.items) == 0 || l.offsetIdx >= len(l.items)-1 { + if len(l.items) == 0 { return true } @@ -94,7 +92,7 @@ func (l *List) AtBottom() bool { totalHeight += itemHeight } - return totalHeight-l.offsetLine-margin <= l.height + return totalHeight-l.offsetLine <= l.height } // SetReverse shows the list in reverse order. diff --git a/internal/ui/model/chat.go b/internal/ui/model/chat.go index a424bd1053134496688d422b0ee19aef3a0b4e35..ccd2325507545b35c9ee2e664cd869da9d2a8a4f 100644 --- a/internal/ui/model/chat.go +++ b/internal/ui/model/chat.go @@ -59,6 +59,10 @@ type Chat struct { // Pending single click action (delayed to detect double-click) pendingClickID int // Incremented on each click to invalidate old pending clicks + + // follow is a flag to indicate whether the view should auto-scroll to + // bottom on new messages. + follow bool } // NewChat creates a new instance of [Chat] that handles chat interactions and @@ -93,8 +97,8 @@ func (m *Chat) Draw(scr uv.Screen, area uv.Rectangle) { func (m *Chat) SetSize(width, height int) { m.list.SetSize(width, height) // Anchor to bottom if we were at the bottom. - if m.list.AtBottom() { - m.list.ScrollToBottom() + if m.AtBottom() { + m.ScrollToBottom() } } @@ -120,7 +124,7 @@ func (m *Chat) SetMessages(msgs ...chat.MessageItem) { items[i] = msg } m.list.SetItems(items...) - m.list.ScrollToBottom() + m.ScrollToBottom() } // AppendMessages appends a new message item to the chat list. @@ -239,31 +243,72 @@ func (m *Chat) Blur() { m.list.Blur() } +// AtBottom returns whether the chat list is currently scrolled to the bottom. +func (m *Chat) AtBottom() bool { + return m.list.AtBottom() +} + +// Follow returns whether the chat view is in follow mode (auto-scroll to +// bottom on new messages). +func (m *Chat) Follow() bool { + return m.follow +} + +// ScrollToBottom scrolls the chat view to the bottom. +func (m *Chat) ScrollToBottom() { + m.list.ScrollToBottom() + m.follow = true // Enable follow mode when user scrolls to bottom +} + +// ScrollToTop scrolls the chat view to the top. +func (m *Chat) ScrollToTop() { + m.list.ScrollToTop() + m.follow = false // Disable follow mode when user scrolls up +} + +// ScrollBy scrolls the chat view by the given number of line deltas. +func (m *Chat) ScrollBy(lines int) { + m.list.ScrollBy(lines) + m.follow = lines > 0 && m.AtBottom() // Disable follow mode if user scrolls up +} + +// ScrollToSelected scrolls the chat view to the selected item. +func (m *Chat) ScrollToSelected() { + m.list.ScrollToSelected() + m.follow = m.AtBottom() // Disable follow mode if user scrolls up +} + +// ScrollToIndex scrolls the chat view to the item at the given index. +func (m *Chat) ScrollToIndex(index int) { + m.list.ScrollToIndex(index) + m.follow = m.AtBottom() // Disable follow mode if user scrolls up +} + // ScrollToTopAndAnimate scrolls the chat view to the top and returns a command to restart // any paused animations that are now visible. func (m *Chat) ScrollToTopAndAnimate() tea.Cmd { - m.list.ScrollToTop() + m.ScrollToTop() return m.RestartPausedVisibleAnimations() } // ScrollToBottomAndAnimate scrolls the chat view to the bottom and returns a command to // restart any paused animations that are now visible. func (m *Chat) ScrollToBottomAndAnimate() tea.Cmd { - m.list.ScrollToBottom() + m.ScrollToBottom() return m.RestartPausedVisibleAnimations() } // ScrollByAndAnimate scrolls the chat view by the given number of line deltas and returns // a command to restart any paused animations that are now visible. func (m *Chat) ScrollByAndAnimate(lines int) tea.Cmd { - m.list.ScrollBy(lines) + m.ScrollBy(lines) return m.RestartPausedVisibleAnimations() } // ScrollToSelectedAndAnimate scrolls the chat view to the selected item and returns a // command to restart any paused animations that are now visible. func (m *Chat) ScrollToSelectedAndAnimate() tea.Cmd { - m.list.ScrollToSelected() + m.ScrollToSelected() return m.RestartPausedVisibleAnimations() } @@ -438,10 +483,10 @@ func (m *Chat) MessageItem(id string) chat.MessageItem { func (m *Chat) ToggleExpandedSelectedItem() { if expandable, ok := m.list.SelectedItem().(chat.Expandable); ok { if !expandable.ToggleExpanded() { - m.list.ScrollToIndex(m.list.Selected()) + m.ScrollToIndex(m.list.Selected()) } - if m.list.AtBottom() { - m.list.ScrollToBottom() + if m.AtBottom() { + m.ScrollToBottom() } } } @@ -549,11 +594,11 @@ func (m *Chat) HandleDelayedClick(msg DelayedClickMsg) bool { // Toggle expansion if applicable. if expandable, ok := selectedItem.(chat.Expandable); ok { if !expandable.ToggleExpanded() { - m.list.ScrollToIndex(m.list.Selected()) + m.ScrollToIndex(m.list.Selected()) } } - if m.list.AtBottom() { - m.list.ScrollToBottom() + if m.AtBottom() { + m.ScrollToBottom() } return handled } diff --git a/internal/ui/model/ui.go b/internal/ui/model/ui.go index 04b644361be47ed223201ba9d0744e084feb7119..52b12fd4ff827d5fd9ad7a8061eda81c8d767912 100644 --- a/internal/ui/model/ui.go +++ b/internal/ui/model/ui.go @@ -53,6 +53,10 @@ import ( "github.com/charmbracelet/x/editor" ) +// MouseScrollThreshold defines how many lines to scroll the chat when a mouse +// wheel event occurs. +const MouseScrollThreshold = 5 + // Compact mode breakpoints. const ( compactModeWidthBreakpoint = 120 @@ -661,7 +665,7 @@ func (m *UI) Update(msg tea.Msg) (tea.Model, tea.Cmd) { case uiChat: switch msg.Button { case tea.MouseWheelUp: - if cmd := m.chat.ScrollByAndAnimate(-5); cmd != nil { + if cmd := m.chat.ScrollByAndAnimate(-MouseScrollThreshold); cmd != nil { cmds = append(cmds, cmd) } if !m.chat.SelectedItemInView() { @@ -671,7 +675,7 @@ func (m *UI) Update(msg tea.Msg) (tea.Model, tea.Cmd) { } } case tea.MouseWheelDown: - if cmd := m.chat.ScrollByAndAnimate(5); cmd != nil { + if cmd := m.chat.ScrollByAndAnimate(MouseScrollThreshold); cmd != nil { cmds = append(cmds, cmd) } if !m.chat.SelectedItemInView() { @@ -882,7 +886,6 @@ func (m *UI) loadNestedToolCalls(items []chat.MessageItem) { // if the message is a tool result it will update the corresponding tool call message func (m *UI) appendSessionMessage(msg message.Message) tea.Cmd { var cmds []tea.Cmd - atBottom := m.chat.list.AtBottom() existing := m.chat.MessageItem(msg.ID) if existing != nil { @@ -915,7 +918,7 @@ func (m *UI) appendSessionMessage(msg message.Message) tea.Cmd { } } m.chat.AppendMessages(items...) - if atBottom { + if m.chat.Follow() { if cmd := m.chat.ScrollToBottomAndAnimate(); cmd != nil { cmds = append(cmds, cmd) } @@ -923,7 +926,7 @@ func (m *UI) appendSessionMessage(msg message.Message) tea.Cmd { if msg.FinishPart() != nil && msg.FinishPart().Reason == message.FinishReasonEndTurn { infoItem := chat.NewAssistantInfoItem(m.com.Styles, &msg, m.com.Config(), time.Unix(m.lastUserMessageTime, 0)) m.chat.AppendMessages(infoItem) - if atBottom { + if m.chat.Follow() { if cmd := m.chat.ScrollToBottomAndAnimate(); cmd != nil { cmds = append(cmds, cmd) } @@ -938,7 +941,7 @@ func (m *UI) appendSessionMessage(msg message.Message) tea.Cmd { } if toolMsgItem, ok := toolItem.(chat.ToolMessageItem); ok { toolMsgItem.SetResult(&tr) - if atBottom { + if m.chat.Follow() { if cmd := m.chat.ScrollToBottomAndAnimate(); cmd != nil { cmds = append(cmds, cmd) } @@ -973,7 +976,6 @@ func (m *UI) handleClickFocus(msg tea.MouseClickMsg) (cmd tea.Cmd) { func (m *UI) updateSessionMessage(msg message.Message) tea.Cmd { var cmds []tea.Cmd existingItem := m.chat.MessageItem(msg.ID) - atBottom := m.chat.list.AtBottom() if existingItem != nil { if assistantItem, ok := existingItem.(*chat.AssistantMessageItem); ok { @@ -1022,7 +1024,7 @@ func (m *UI) updateSessionMessage(msg message.Message) tea.Cmd { } m.chat.AppendMessages(items...) - if atBottom { + if m.chat.Follow() { if cmd := m.chat.ScrollToBottomAndAnimate(); cmd != nil { cmds = append(cmds, cmd) } @@ -1035,7 +1037,7 @@ func (m *UI) updateSessionMessage(msg message.Message) tea.Cmd { func (m *UI) handleChildSessionMessage(event pubsub.Event[message.Message]) tea.Cmd { var cmds []tea.Cmd - atBottom := m.chat.list.AtBottom() + atBottom := m.chat.AtBottom() // Only process messages with tool calls or results. if len(event.Payload.ToolCalls()) == 0 && len(event.Payload.ToolResults()) == 0 { return nil From 27548b6424ec062185ebbe2a435ba8fdda698d9f Mon Sep 17 00:00:00 2001 From: Andrey Nering Date: Thu, 12 Feb 2026 15:44:00 -0300 Subject: [PATCH 03/10] docs(readme): mention io.net provider --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 8e9f145434a04c749c223166676bdcc323712c75..49563822772d28762215f90f257e17a9710ac25f 100644 --- a/README.md +++ b/README.md @@ -191,6 +191,7 @@ That said, you can also set environment variables for preferred providers. | `HF_TOKEN` | Hugging Face Inference | | `CEREBRAS_API_KEY` | Cerebras | | `OPENROUTER_API_KEY` | OpenRouter | +| `IONET_API_KEY` | io.net | | `GROQ_API_KEY` | Groq | | `VERTEXAI_PROJECT` | Google Cloud VertexAI (Gemini) | | `VERTEXAI_LOCATION` | Google Cloud VertexAI (Gemini) | From aa1ea496985d81e219a537271ca9ba993a3d0f0f Mon Sep 17 00:00:00 2001 From: Andrey Nering Date: Thu, 12 Feb 2026 15:44:30 -0300 Subject: [PATCH 04/10] fix: add io.net api key validation fallback --- internal/config/config.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/internal/config/config.go b/internal/config/config.go index 753151509315545dfbed9bd74c1455785313c8aa..626fbe327491eb28d41e2972c3cb221b1deeb0c6 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -799,6 +799,11 @@ func (c *ProviderConfig) TestConnection(resolver VariableResolver) error { return fmt.Errorf("invalid API key format for provider %s", c.ID) } return nil + case catwalk.InferenceProviderIoNet: + if !strings.HasPrefix(apiKey, "io-") { + return fmt.Errorf("invalid API key format for provider %s", c.ID) + } + return nil } switch c.Type { From 45663b77649a540f4ffcc2f24478475c99bfd944 Mon Sep 17 00:00:00 2001 From: Andrey Nering Date: Fri, 13 Feb 2026 10:32:16 -0300 Subject: [PATCH 05/10] chore: update catwalk to v0.19.0 --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 13493454d8b6a0583b834bc6aa19a5c73be83327..3fee4e8f4af0049807972e58d3985efc7e8114ed 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.25.5 require ( charm.land/bubbles/v2 v2.0.0-rc.1.0.20260109112849-ae99f46cec66 charm.land/bubbletea/v2 v2.0.0-rc.2.0.20260209074636-30878e43d7b0 - charm.land/catwalk v0.18.0 + charm.land/catwalk v0.19.0 charm.land/fantasy v0.7.2 charm.land/glamour/v2 v2.0.0-20260123212943-6014aa153a9b charm.land/lipgloss/v2 v2.0.0-beta.3.0.20260212100304-e18737634dea diff --git a/go.sum b/go.sum index f29030cec4205073c997229175b4fc70d65e1934..9dc601ff8dce695c151a7eb08501cab1cb118d41 100644 --- a/go.sum +++ b/go.sum @@ -2,8 +2,8 @@ charm.land/bubbles/v2 v2.0.0-rc.1.0.20260109112849-ae99f46cec66 h1:2BdJynsAW+8rv charm.land/bubbles/v2 v2.0.0-rc.1.0.20260109112849-ae99f46cec66/go.mod h1:5AbN6cEd/47gkEf8TgiQ2O3RZ5QxMS14l9W+7F9fPC4= charm.land/bubbletea/v2 v2.0.0-rc.2.0.20260209074636-30878e43d7b0 h1:HAbpM9TPjZM18D677ww3VnkKXdd2hyMQtHUsVV0HcPQ= charm.land/bubbletea/v2 v2.0.0-rc.2.0.20260209074636-30878e43d7b0/go.mod h1:3LRff2U4WIYXy7MTxfbAQ+AdfM3D8Xuvz2wbsOD9OHQ= -charm.land/catwalk v0.18.0 h1:vBbhhxuGqkx2qVzom54ElJyBCQHn30dOnPYG977za4Q= -charm.land/catwalk v0.18.0/go.mod h1:kAdk/GjAJbl1AjRjmfU5c9lZfs7PeC3Uy9TgaVtlN64= +charm.land/catwalk v0.19.0 h1:h9w0VPYbDMoCUA7Vg4uqeCpLLUzGgUvKantwsGGUD+4= +charm.land/catwalk v0.19.0/go.mod h1:rFC/V96rIHX7VES215c/qzI1EW/Moo1ggs1Q6seTy5s= charm.land/fantasy v0.7.2 h1:OUBgbs7hllZE7rpJP9SzdsGE/hMCm+mr11iEIqU02hE= charm.land/fantasy v0.7.2/go.mod h1:vH6F5eYqaxgNEvDQdXRsOsfvoRyT3f/uJngPNJmcDmw= charm.land/glamour/v2 v2.0.0-20260123212943-6014aa153a9b h1:A6IUUyChZDWP16RUdRJCfmYISAKWQGyIcfhZJUCViQ0= From db46f5e1c8d5fe3a76dc00eec215e94c6b954c4c Mon Sep 17 00:00:00 2001 From: Charm <124303983+charmcli@users.noreply.github.com> Date: Fri, 13 Feb 2026 13:45:22 +0000 Subject: [PATCH 06/10] chore: auto-update files --- internal/agent/hyper/provider.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/agent/hyper/provider.json b/internal/agent/hyper/provider.json index d10867bfc2568f826915074bbc7d2a0f99a42f6a..94bb0305e08c1cf869d237136193551aace9670e 100644 --- a/internal/agent/hyper/provider.json +++ b/internal/agent/hyper/provider.json @@ -1 +1 @@ -{"name":"Charm Hyper","id":"hyper","api_endpoint":"https://hyper.charm.land/api/v1/fantasy","type":"hyper","default_large_model_id":"claude-opus-4-5","default_small_model_id":"claude-haiku-4-5","models":[{"id":"claude-haiku-4-5","name":"Claude Haiku 4.5","cost_per_1m_in":1,"cost_per_1m_out":5,"cost_per_1m_in_cached":1.25,"cost_per_1m_out_cached":0.09999999999999999,"context_window":200000,"default_max_tokens":32000,"can_reason":true,"supports_attachments":true,"options":{}},{"id":"claude-opus-4-5","name":"Claude Opus 4.5","cost_per_1m_in":5,"cost_per_1m_out":25,"cost_per_1m_in_cached":6.25,"cost_per_1m_out_cached":0.5,"context_window":200000,"default_max_tokens":50000,"can_reason":true,"supports_attachments":true,"options":{}},{"id":"claude-opus-4-6","name":"Claude Opus 4.6","cost_per_1m_in":5,"cost_per_1m_out":25,"cost_per_1m_in_cached":6.25,"cost_per_1m_out_cached":0.5,"context_window":200000,"default_max_tokens":126000,"can_reason":true,"supports_attachments":true,"options":{}},{"id":"claude-sonnet-4-5","name":"Claude Sonnet 4.5","cost_per_1m_in":3,"cost_per_1m_out":15,"cost_per_1m_in_cached":3.75,"cost_per_1m_out_cached":0.3,"context_window":200000,"default_max_tokens":50000,"can_reason":true,"supports_attachments":true,"options":{}},{"id":"gemini-3-flash","name":"Gemini 3 Flash","cost_per_1m_in":0.5,"cost_per_1m_out":3,"cost_per_1m_in_cached":0.049999999999999996,"cost_per_1m_out_cached":0,"context_window":1000000,"default_max_tokens":8000,"can_reason":true,"reasoning_levels":["low","medium","high"],"default_reasoning_effort":"medium","supports_attachments":true,"options":{}},{"id":"gemini-3-pro-preview","name":"Gemini 3 Pro","cost_per_1m_in":2,"cost_per_1m_out":12,"cost_per_1m_in_cached":0.19999999999999998,"cost_per_1m_out_cached":0,"context_window":1000000,"default_max_tokens":8000,"can_reason":true,"reasoning_levels":["low","medium","high"],"default_reasoning_effort":"medium","supports_attachments":true,"options":{}},{"id":"glm-4.6","name":"GLM 4.6","cost_per_1m_in":0.44999999999999996,"cost_per_1m_out":1.7999999999999998,"cost_per_1m_in_cached":0.11,"cost_per_1m_out_cached":0,"context_window":200000,"default_max_tokens":8000,"can_reason":true,"reasoning_levels":["low","medium","high"],"default_reasoning_effort":"medium","supports_attachments":false,"options":{}},{"id":"glm-4.7","name":"GLM 4.7","cost_per_1m_in":0.43,"cost_per_1m_out":1.75,"cost_per_1m_in_cached":0.08,"cost_per_1m_out_cached":0,"context_window":202752,"default_max_tokens":8000,"can_reason":true,"reasoning_levels":["low","medium","high"],"default_reasoning_effort":"medium","supports_attachments":false,"options":{}},{"id":"gpt-5.1-codex","name":"GPT 5.1 Codex","cost_per_1m_in":1.25,"cost_per_1m_out":10,"cost_per_1m_in_cached":0.125,"cost_per_1m_out_cached":0.125,"context_window":400000,"default_max_tokens":128000,"can_reason":true,"reasoning_levels":["minimal","low","medium","high"],"default_reasoning_effort":"medium","supports_attachments":true,"options":{}},{"id":"gpt-5.1-codex-max","name":"GPT 5.1 Codex Max","cost_per_1m_in":1.25,"cost_per_1m_out":10,"cost_per_1m_in_cached":0.125,"cost_per_1m_out_cached":0.125,"context_window":400000,"default_max_tokens":128000,"can_reason":true,"reasoning_levels":["minimal","low","medium","high"],"default_reasoning_effort":"medium","supports_attachments":true,"options":{}},{"id":"gpt-5.1-codex-mini","name":"GPT 5.1 Codex Mini","cost_per_1m_in":0.25,"cost_per_1m_out":2,"cost_per_1m_in_cached":0.025,"cost_per_1m_out_cached":0.025,"context_window":400000,"default_max_tokens":128000,"can_reason":true,"reasoning_levels":["low","medium","high"],"default_reasoning_effort":"medium","supports_attachments":true,"options":{}},{"id":"gpt-5.2","name":"GPT 5.2","cost_per_1m_in":1.75,"cost_per_1m_out":14,"cost_per_1m_in_cached":0.175,"cost_per_1m_out_cached":0.175,"context_window":400000,"default_max_tokens":128000,"can_reason":true,"reasoning_levels":["minimal","low","medium","high"],"default_reasoning_effort":"medium","supports_attachments":true,"options":{}},{"id":"gpt-5.2-codex","name":"GPT 5.2 Codex","cost_per_1m_in":1.75,"cost_per_1m_out":14,"cost_per_1m_in_cached":0.175,"cost_per_1m_out_cached":0.175,"context_window":400000,"default_max_tokens":128000,"can_reason":true,"reasoning_levels":["minimal","low","medium","high"],"default_reasoning_effort":"medium","supports_attachments":true,"options":{}},{"id":"grok-4.1-fast-non-reasoning","name":"Grok 4.1 Fast Non Reasoning","cost_per_1m_in":0.2,"cost_per_1m_out":0.5,"cost_per_1m_in_cached":0,"cost_per_1m_out_cached":0.05,"context_window":2000000,"default_max_tokens":200000,"can_reason":false,"supports_attachments":true,"options":{}},{"id":"grok-4.1-fast-reasoning","name":"Grok 4.1 Fast Reasoning","cost_per_1m_in":0.2,"cost_per_1m_out":0.5,"cost_per_1m_in_cached":0,"cost_per_1m_out_cached":0.05,"context_window":2000000,"default_max_tokens":200000,"can_reason":true,"supports_attachments":true,"options":{}},{"id":"grok-code-fast-1","name":"Grok Code Fast","cost_per_1m_in":0.2,"cost_per_1m_out":1.5,"cost_per_1m_in_cached":0,"cost_per_1m_out_cached":0.02,"context_window":256000,"default_max_tokens":20000,"can_reason":true,"supports_attachments":false,"options":{}},{"id":"kimi-k2-0905","name":"Kimi K2","cost_per_1m_in":0.55,"cost_per_1m_out":2.19,"cost_per_1m_in_cached":0,"cost_per_1m_out_cached":0,"context_window":256000,"default_max_tokens":10000,"can_reason":true,"default_reasoning_effort":"medium","supports_attachments":false,"options":{}},{"id":"kimi-k2.5","name":"Kimi K2.5","cost_per_1m_in":0.6,"cost_per_1m_out":3,"cost_per_1m_in_cached":0.09999999999999999,"cost_per_1m_out_cached":0,"context_window":256000,"default_max_tokens":8000,"can_reason":true,"reasoning_levels":["low","medium","high"],"default_reasoning_effort":"medium","supports_attachments":true,"options":{}}]} \ No newline at end of file +{"name":"Charm Hyper","id":"hyper","api_endpoint":"https://hyper.charm.land/api/v1/fantasy","type":"hyper","default_large_model_id":"claude-opus-4-5","default_small_model_id":"claude-haiku-4-5","models":[{"id":"claude-haiku-4-5","name":"Claude Haiku 4.5","cost_per_1m_in":1,"cost_per_1m_out":5,"cost_per_1m_in_cached":1.25,"cost_per_1m_out_cached":0.09999999999999999,"context_window":200000,"default_max_tokens":32000,"can_reason":true,"supports_attachments":true,"options":{}},{"id":"claude-opus-4-5","name":"Claude Opus 4.5","cost_per_1m_in":5,"cost_per_1m_out":25,"cost_per_1m_in_cached":6.25,"cost_per_1m_out_cached":0.5,"context_window":200000,"default_max_tokens":50000,"can_reason":true,"supports_attachments":true,"options":{}},{"id":"claude-opus-4-6","name":"Claude Opus 4.6","cost_per_1m_in":5,"cost_per_1m_out":25,"cost_per_1m_in_cached":6.25,"cost_per_1m_out_cached":0.5,"context_window":200000,"default_max_tokens":126000,"can_reason":true,"supports_attachments":true,"options":{}},{"id":"claude-sonnet-4-5","name":"Claude Sonnet 4.5","cost_per_1m_in":3,"cost_per_1m_out":15,"cost_per_1m_in_cached":3.75,"cost_per_1m_out_cached":0.3,"context_window":200000,"default_max_tokens":50000,"can_reason":true,"supports_attachments":true,"options":{}},{"id":"gemini-3-flash","name":"Gemini 3 Flash","cost_per_1m_in":0.5,"cost_per_1m_out":3,"cost_per_1m_in_cached":0.049999999999999996,"cost_per_1m_out_cached":0,"context_window":1000000,"default_max_tokens":8000,"can_reason":true,"reasoning_levels":["low","medium","high"],"default_reasoning_effort":"medium","supports_attachments":true,"options":{}},{"id":"gemini-3-pro-preview","name":"Gemini 3 Pro","cost_per_1m_in":2,"cost_per_1m_out":12,"cost_per_1m_in_cached":0.19999999999999998,"cost_per_1m_out_cached":0,"context_window":1000000,"default_max_tokens":8000,"can_reason":true,"reasoning_levels":["low","medium","high"],"default_reasoning_effort":"medium","supports_attachments":true,"options":{}},{"id":"glm-4.7","name":"GLM-4.7","cost_per_1m_in":0.43,"cost_per_1m_out":1.75,"cost_per_1m_in_cached":0.08,"cost_per_1m_out_cached":0,"context_window":202752,"default_max_tokens":8000,"can_reason":true,"reasoning_levels":["low","medium","high"],"default_reasoning_effort":"medium","supports_attachments":false,"options":{}},{"id":"glm-4.7-flashx","name":"GLM-4.7 Flash","cost_per_1m_in":0.06,"cost_per_1m_out":0.39999999999999997,"cost_per_1m_in_cached":0.01,"cost_per_1m_out_cached":0,"context_window":200000,"default_max_tokens":8000,"can_reason":true,"reasoning_levels":["low","medium","high"],"default_reasoning_effort":"medium","supports_attachments":false,"options":{}},{"id":"glm-5","name":"GLM-5","cost_per_1m_in":1,"cost_per_1m_out":3.1999999999999997,"cost_per_1m_in_cached":0.19999999999999998,"cost_per_1m_out_cached":0,"context_window":202800,"default_max_tokens":8000,"can_reason":true,"reasoning_levels":["low","medium","high"],"default_reasoning_effort":"medium","supports_attachments":false,"options":{}},{"id":"gpt-5.1-codex","name":"GPT-5.1 Codex","cost_per_1m_in":1.25,"cost_per_1m_out":10,"cost_per_1m_in_cached":0.125,"cost_per_1m_out_cached":0.125,"context_window":400000,"default_max_tokens":128000,"can_reason":true,"reasoning_levels":["minimal","low","medium","high"],"default_reasoning_effort":"medium","supports_attachments":true,"options":{}},{"id":"gpt-5.1-codex-max","name":"GPT-5.1 Codex Max","cost_per_1m_in":1.25,"cost_per_1m_out":10,"cost_per_1m_in_cached":0.125,"cost_per_1m_out_cached":0.125,"context_window":400000,"default_max_tokens":128000,"can_reason":true,"reasoning_levels":["minimal","low","medium","high"],"default_reasoning_effort":"medium","supports_attachments":true,"options":{}},{"id":"gpt-5.1-codex-mini","name":"GPT-5.1 Codex Mini","cost_per_1m_in":0.25,"cost_per_1m_out":2,"cost_per_1m_in_cached":0.025,"cost_per_1m_out_cached":0.025,"context_window":400000,"default_max_tokens":128000,"can_reason":true,"reasoning_levels":["low","medium","high"],"default_reasoning_effort":"medium","supports_attachments":true,"options":{}},{"id":"gpt-5.2","name":"GPT-5.2","cost_per_1m_in":1.75,"cost_per_1m_out":14,"cost_per_1m_in_cached":0.175,"cost_per_1m_out_cached":0.175,"context_window":400000,"default_max_tokens":128000,"can_reason":true,"reasoning_levels":["minimal","low","medium","high"],"default_reasoning_effort":"medium","supports_attachments":true,"options":{}},{"id":"gpt-5.2-codex","name":"GPT-5.2 Codex","cost_per_1m_in":1.75,"cost_per_1m_out":14,"cost_per_1m_in_cached":0.175,"cost_per_1m_out_cached":0.175,"context_window":400000,"default_max_tokens":128000,"can_reason":true,"reasoning_levels":["minimal","low","medium","high"],"default_reasoning_effort":"medium","supports_attachments":true,"options":{}},{"id":"grok-4.1-fast-non-reasoning","name":"Grok 4.1 Fast Non Reasoning","cost_per_1m_in":0.2,"cost_per_1m_out":0.5,"cost_per_1m_in_cached":0,"cost_per_1m_out_cached":0.05,"context_window":2000000,"default_max_tokens":200000,"can_reason":false,"supports_attachments":true,"options":{}},{"id":"grok-4.1-fast-reasoning","name":"Grok 4.1 Fast Reasoning","cost_per_1m_in":0.2,"cost_per_1m_out":0.5,"cost_per_1m_in_cached":0,"cost_per_1m_out_cached":0.05,"context_window":2000000,"default_max_tokens":200000,"can_reason":true,"supports_attachments":true,"options":{}},{"id":"grok-code-fast-1","name":"Grok Code Fast","cost_per_1m_in":0.2,"cost_per_1m_out":1.5,"cost_per_1m_in_cached":0,"cost_per_1m_out_cached":0.02,"context_window":256000,"default_max_tokens":20000,"can_reason":true,"supports_attachments":false,"options":{}},{"id":"kimi-k2-0905","name":"Kimi K2","cost_per_1m_in":0.55,"cost_per_1m_out":2.19,"cost_per_1m_in_cached":0,"cost_per_1m_out_cached":0,"context_window":256000,"default_max_tokens":10000,"can_reason":true,"default_reasoning_effort":"medium","supports_attachments":false,"options":{}},{"id":"kimi-k2.5","name":"Kimi K2.5","cost_per_1m_in":0.5,"cost_per_1m_out":2.8,"cost_per_1m_in_cached":0,"cost_per_1m_out_cached":0,"context_window":256000,"default_max_tokens":8000,"can_reason":true,"reasoning_levels":["low","medium","high"],"default_reasoning_effort":"medium","supports_attachments":true,"options":{}}]} \ No newline at end of file From b68521facf334a58d80224b26e3ff658a3d04e91 Mon Sep 17 00:00:00 2001 From: Andrey Nering Date: Fri, 13 Feb 2026 14:05:29 -0300 Subject: [PATCH 07/10] chore(deps): update fantasy (#2220) --- go.mod | 3 +-- go.sum | 6 ++---- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 3fee4e8f4af0049807972e58d3985efc7e8114ed..a9e2e554d5fc53546a0a8c2075193e5cc72e7198 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( charm.land/bubbles/v2 v2.0.0-rc.1.0.20260109112849-ae99f46cec66 charm.land/bubbletea/v2 v2.0.0-rc.2.0.20260209074636-30878e43d7b0 charm.land/catwalk v0.19.0 - charm.land/fantasy v0.7.2 + charm.land/fantasy v0.8.0 charm.land/glamour/v2 v2.0.0-20260123212943-6014aa153a9b charm.land/lipgloss/v2 v2.0.0-beta.3.0.20260212100304-e18737634dea charm.land/log/v2 v2.0.0-20251110204020-529bb77f35da @@ -79,7 +79,6 @@ require ( cloud.google.com/go/compute/metadata v0.9.0 // indirect github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.0 // indirect github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 // indirect - github.com/RealAlexandreAI/json-repair v0.0.15 // indirect github.com/andybalholm/cascadia v1.3.3 // indirect github.com/aws/aws-sdk-go-v2 v1.41.1 // indirect github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.3 // indirect diff --git a/go.sum b/go.sum index 9dc601ff8dce695c151a7eb08501cab1cb118d41..198c94adafecea46859d2fbc486fbe134739b7b1 100644 --- a/go.sum +++ b/go.sum @@ -4,8 +4,8 @@ charm.land/bubbletea/v2 v2.0.0-rc.2.0.20260209074636-30878e43d7b0 h1:HAbpM9TPjZM charm.land/bubbletea/v2 v2.0.0-rc.2.0.20260209074636-30878e43d7b0/go.mod h1:3LRff2U4WIYXy7MTxfbAQ+AdfM3D8Xuvz2wbsOD9OHQ= charm.land/catwalk v0.19.0 h1:h9w0VPYbDMoCUA7Vg4uqeCpLLUzGgUvKantwsGGUD+4= charm.land/catwalk v0.19.0/go.mod h1:rFC/V96rIHX7VES215c/qzI1EW/Moo1ggs1Q6seTy5s= -charm.land/fantasy v0.7.2 h1:OUBgbs7hllZE7rpJP9SzdsGE/hMCm+mr11iEIqU02hE= -charm.land/fantasy v0.7.2/go.mod h1:vH6F5eYqaxgNEvDQdXRsOsfvoRyT3f/uJngPNJmcDmw= +charm.land/fantasy v0.8.0 h1:w0FNH2K7DF0xxXJL1AqojMa5HQhK1sK/Rogo0NwjWmQ= +charm.land/fantasy v0.8.0/go.mod h1:KJ8vjy9FH7G2aeR/fL+os2uFHkQ4js2+UJVbsUKCXYM= charm.land/glamour/v2 v2.0.0-20260123212943-6014aa153a9b h1:A6IUUyChZDWP16RUdRJCfmYISAKWQGyIcfhZJUCViQ0= charm.land/glamour/v2 v2.0.0-20260123212943-6014aa153a9b/go.mod h1:J3kVhY6oHXZq5f+8vC3hmDO95fEvbqj3z7xDwxrfzU8= charm.land/lipgloss/v2 v2.0.0-beta.3.0.20260212100304-e18737634dea h1:XBmpGhIKPN8o9VjuXg+X5WXFsEqUs/YtPx0Q0zzmTTA= @@ -37,8 +37,6 @@ github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6 github.com/PuerkitoBio/goquery v1.9.2/go.mod h1:GHPCaP0ODyyxqcNoFGYlAprUFH81NuRPd0GX3Zu2Mvk= github.com/PuerkitoBio/goquery v1.11.0 h1:jZ7pwMQXIITcUXNH83LLk+txlaEy6NVOfTuP43xxfqw= github.com/PuerkitoBio/goquery v1.11.0/go.mod h1:wQHgxUOU3JGuj3oD/QFfxUdlzW6xPHfqyHre6VMY4DQ= -github.com/RealAlexandreAI/json-repair v0.0.15 h1:AN8/yt8rcphwQrIs/FZeki+cKaIERUNr25zf1flirIs= -github.com/RealAlexandreAI/json-repair v0.0.15/go.mod h1:GKJi5borR78O8c7HCVbgqjhoiVibZ6hJldxbc6dGrAI= github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0= github.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k= github.com/alecthomas/chroma/v2 v2.23.1 h1:nv2AVZdTyClGbVQkIzlDm/rnhk1E9bU9nXwmZ/Vk/iY= From 4f5d31d2f0f7939c873d4f906b21ecc3b04b4396 Mon Sep 17 00:00:00 2001 From: Andrey Nering Date: Fri, 13 Feb 2026 14:21:00 -0300 Subject: [PATCH 08/10] chore(deps): update catwalk --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index a9e2e554d5fc53546a0a8c2075193e5cc72e7198..eb3841ad009877c16a1aadcaf46ce33199d871f3 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.25.5 require ( charm.land/bubbles/v2 v2.0.0-rc.1.0.20260109112849-ae99f46cec66 charm.land/bubbletea/v2 v2.0.0-rc.2.0.20260209074636-30878e43d7b0 - charm.land/catwalk v0.19.0 + charm.land/catwalk v0.19.1 charm.land/fantasy v0.8.0 charm.land/glamour/v2 v2.0.0-20260123212943-6014aa153a9b charm.land/lipgloss/v2 v2.0.0-beta.3.0.20260212100304-e18737634dea diff --git a/go.sum b/go.sum index 198c94adafecea46859d2fbc486fbe134739b7b1..4cac60b5c39a1d9bb3253c1d76c8b1efcc95c150 100644 --- a/go.sum +++ b/go.sum @@ -2,8 +2,8 @@ charm.land/bubbles/v2 v2.0.0-rc.1.0.20260109112849-ae99f46cec66 h1:2BdJynsAW+8rv charm.land/bubbles/v2 v2.0.0-rc.1.0.20260109112849-ae99f46cec66/go.mod h1:5AbN6cEd/47gkEf8TgiQ2O3RZ5QxMS14l9W+7F9fPC4= charm.land/bubbletea/v2 v2.0.0-rc.2.0.20260209074636-30878e43d7b0 h1:HAbpM9TPjZM18D677ww3VnkKXdd2hyMQtHUsVV0HcPQ= charm.land/bubbletea/v2 v2.0.0-rc.2.0.20260209074636-30878e43d7b0/go.mod h1:3LRff2U4WIYXy7MTxfbAQ+AdfM3D8Xuvz2wbsOD9OHQ= -charm.land/catwalk v0.19.0 h1:h9w0VPYbDMoCUA7Vg4uqeCpLLUzGgUvKantwsGGUD+4= -charm.land/catwalk v0.19.0/go.mod h1:rFC/V96rIHX7VES215c/qzI1EW/Moo1ggs1Q6seTy5s= +charm.land/catwalk v0.19.1 h1:CaeC/D60F4bqYBK9dopPuSwE2uLTPWLWxr7OIsLhr54= +charm.land/catwalk v0.19.1/go.mod h1:rFC/V96rIHX7VES215c/qzI1EW/Moo1ggs1Q6seTy5s= charm.land/fantasy v0.8.0 h1:w0FNH2K7DF0xxXJL1AqojMa5HQhK1sK/Rogo0NwjWmQ= charm.land/fantasy v0.8.0/go.mod h1:KJ8vjy9FH7G2aeR/fL+os2uFHkQ4js2+UJVbsUKCXYM= charm.land/glamour/v2 v2.0.0-20260123212943-6014aa153a9b h1:A6IUUyChZDWP16RUdRJCfmYISAKWQGyIcfhZJUCViQ0= From 889d2ceef42854bc2818dd3a2caddf5dcac54de3 Mon Sep 17 00:00:00 2001 From: Andrey Nering Date: Fri, 13 Feb 2026 14:41:29 -0300 Subject: [PATCH 09/10] chore(deps): update catwalk --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index eb3841ad009877c16a1aadcaf46ce33199d871f3..c10d4101d809f64c2e9f9d2580d9360309c25b6a 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.25.5 require ( charm.land/bubbles/v2 v2.0.0-rc.1.0.20260109112849-ae99f46cec66 charm.land/bubbletea/v2 v2.0.0-rc.2.0.20260209074636-30878e43d7b0 - charm.land/catwalk v0.19.1 + charm.land/catwalk v0.19.2 charm.land/fantasy v0.8.0 charm.land/glamour/v2 v2.0.0-20260123212943-6014aa153a9b charm.land/lipgloss/v2 v2.0.0-beta.3.0.20260212100304-e18737634dea diff --git a/go.sum b/go.sum index 4cac60b5c39a1d9bb3253c1d76c8b1efcc95c150..1473f5f4e9965146abffbfcf6199abc44ed5a3b8 100644 --- a/go.sum +++ b/go.sum @@ -2,8 +2,8 @@ charm.land/bubbles/v2 v2.0.0-rc.1.0.20260109112849-ae99f46cec66 h1:2BdJynsAW+8rv charm.land/bubbles/v2 v2.0.0-rc.1.0.20260109112849-ae99f46cec66/go.mod h1:5AbN6cEd/47gkEf8TgiQ2O3RZ5QxMS14l9W+7F9fPC4= charm.land/bubbletea/v2 v2.0.0-rc.2.0.20260209074636-30878e43d7b0 h1:HAbpM9TPjZM18D677ww3VnkKXdd2hyMQtHUsVV0HcPQ= charm.land/bubbletea/v2 v2.0.0-rc.2.0.20260209074636-30878e43d7b0/go.mod h1:3LRff2U4WIYXy7MTxfbAQ+AdfM3D8Xuvz2wbsOD9OHQ= -charm.land/catwalk v0.19.1 h1:CaeC/D60F4bqYBK9dopPuSwE2uLTPWLWxr7OIsLhr54= -charm.land/catwalk v0.19.1/go.mod h1:rFC/V96rIHX7VES215c/qzI1EW/Moo1ggs1Q6seTy5s= +charm.land/catwalk v0.19.2 h1:exy+egllV6VEuR0e5eGkefnL6xnlszNxy9FpH2vjss4= +charm.land/catwalk v0.19.2/go.mod h1:rFC/V96rIHX7VES215c/qzI1EW/Moo1ggs1Q6seTy5s= charm.land/fantasy v0.8.0 h1:w0FNH2K7DF0xxXJL1AqojMa5HQhK1sK/Rogo0NwjWmQ= charm.land/fantasy v0.8.0/go.mod h1:KJ8vjy9FH7G2aeR/fL+os2uFHkQ4js2+UJVbsUKCXYM= charm.land/glamour/v2 v2.0.0-20260123212943-6014aa153a9b h1:A6IUUyChZDWP16RUdRJCfmYISAKWQGyIcfhZJUCViQ0=