on main help sign in
Merge remote-tracking branch 'origin/main' into crush-fantasy
commit2f5d389f88b59f626ba9e49153cf4f59bc704ad7 authorKujtim Hoxha <kujtimii.h@gmail.com> dateMon 13 Oct 2025, 13:33 (1 year ago) parent62545b0e5f171b
16 files changed+261−323
.github/cla-signatures.json+32 .github/workflows/schema-update.yml+1−1 Taskfile.yaml+9−4 go.mod+24−29 go.sum+51−133 internal/agent/tools/mcp-tools.go+93−108 internal/app/app.go+7−4 internal/cmd/root.go+2−1 internal/config/config.go+1−1 internal/fsext/ls.go+1−1 internal/tui/components/core/core.go+5−2 internal/tui/components/core/testdata/TestStatus/EmptyDescription.golden+1−1 internal/tui/components/lsp/lsp.go+25−26 internal/tui/components/mcp/mcp.go+1−1 internal/tui/tui.go+6 main.go+2−11
.github/cla-signatures.json+32
@@ -679,6 +679,38 @@
679679 "created_at": "2025-09-29T01:19:40Z",
680680 "repoId": 987670088,
681681 "pullRequestNo": 1148
682+ },
683+ {
684+ "name": "kucukkanat",
685+ "id": 914316,
686+ "comment_id": 3369230313,
687+ "created_at": "2025-10-05T18:13:57Z",
688+ "repoId": 987670088,
689+ "pullRequestNo": 1195
690+ },
691+ {
692+ "name": "thuggys",
693+ "id": 150315417,
694+ "comment_id": 3369149503,
695+ "created_at": "2025-10-05T15:59:55Z",
696+ "repoId": 987670088,
697+ "pullRequestNo": 1194
698+ },
699+ {
700+ "name": "nikaro",
701+ "id": 3918653,
702+ "comment_id": 3373586148,
703+ "created_at": "2025-10-06T19:31:50Z",
704+ "repoId": 987670088,
705+ "pullRequestNo": 1200
706+ },
707+ {
708+ "name": "daps94",
709+ "id": 35882689,
710+ "comment_id": 3395964275,
711+ "created_at": "2025-10-13T05:56:20Z",
712+ "repoId": 987670088,
713+ "pullRequestNo": 1223
682714 }
683715 ]
684716}
.github/workflows/schema-update.yml+1−1
@@ -17,7 +17,7 @@ jobs:
1717 with:
1818 go-version-file: go.mod
1919 - run: go run . schema > ./schema.json
20− - uses: stefanzweifel/git-auto-commit-action@778341af668090896ca464160c2def5d1d1a3eb0 # v5
20+ - uses: stefanzweifel/git-auto-commit-action@28e16e81777b558cc906c8750092100bbb34c5e3 # v5
2121 with:
2222 commit_message: "chore: auto-update generated files"
2323 branch: main
Taskfile.yaml+9−4
@@ -38,7 +38,7 @@ tasks:
3838 run:
3939 desc: Run build
4040 cmds:
41− - go run .
41+ - go run . {{.CLI_ARGS}}
4242
4343 test:
4444 desc: Run tests
@@ -89,16 +89,21 @@ tasks:
8989 desc: Create and push a new tag following semver
9090 vars:
9191 NEXT:
92− sh: go run github.com/caarlos0/svu/v3@latest next --always
93− prompt: "This will release {{.NEXT}}. Please make sure you've fetch tags. Continue?"
92+ sh: svu next --always || go run github.com/caarlos0/svu/v3@latest next --always
93+ prompt: "This will release {{.NEXT}}. Continue?"
9494 preconditions:
9595 - sh: '[ $(git symbolic-ref --short HEAD) = "main" ]'
9696 msg: Not on main branch
9797 - sh: "[ $(git status --porcelain=2 | wc -l) = 0 ]"
9898 msg: "Git is dirty"
9999 cmds:
100+ - task: fetch-tags
100101 - git commit --allow-empty -m "{{.NEXT}}"
101− - git tag -d nightly
102102 - git tag --annotate --sign {{.NEXT}} {{.CLI_ARGS}}
103103 - echo "Pushing {{.NEXT}}..."
104104 - git push origin --tags
105+
106+ fetch-tags:
107+ cmds:
108+ - git tag -d nightly || true
109+ - git fetch --tags
go.mod+24−29
@@ -12,23 +12,23 @@ require (
1212 github.com/bmatcuk/doublestar/v4 v4.9.1
1313 github.com/charlievieth/fastwalk v1.0.14
1414 github.com/charmbracelet/bubbles/v2 v2.0.0-beta.1.0.20250820203609-601216f68ee2
15− github.com/charmbracelet/bubbletea/v2 v2.0.0-beta.4.0.20250910155747-997384b0b35e
15+ github.com/charmbracelet/bubbletea/v2 v2.0.0-beta.4.0.20251011205917-3b687ffc1619
1616 github.com/charmbracelet/catwalk v0.6.5-0.20251013041345-e6202aaa8c46
17− github.com/charmbracelet/fang v0.4.2
17+ github.com/charmbracelet/fang v0.4.3
1818 github.com/charmbracelet/fantasy v0.0.0-20251010114724-801d5df11cef
1919 github.com/charmbracelet/glamour/v2 v2.0.0-20250811143442-a27abb32f018
2020 github.com/charmbracelet/lipgloss/v2 v2.0.0-beta.3.0.20250917201909-41ff0bf215ea
2121 github.com/charmbracelet/log/v2 v2.0.0-20250226163916-c379e29ff706
22− github.com/charmbracelet/x/ansi v0.10.1
22+ github.com/charmbracelet/x/ansi v0.10.2
2323 github.com/charmbracelet/x/exp/charmtone v0.0.0-20250708181618-a60a724ba6c3
2424 github.com/charmbracelet/x/exp/golden v0.0.0-20250207160936-21c02780d27a
2525 github.com/disintegration/imageorient v0.0.0-20180920195336-8147d86e83ec
2626 github.com/google/uuid v1.6.0
2727 github.com/invopop/jsonschema v0.13.0
2828 github.com/joho/godotenv v1.5.1
29− github.com/mark3labs/mcp-go v0.41.0
29+ github.com/modelcontextprotocol/go-sdk v1.0.0
3030 github.com/muesli/termenv v0.16.0
31− github.com/ncruces/go-sqlite3 v0.29.0
31+ github.com/ncruces/go-sqlite3 v0.29.1
3232 github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646
3333 github.com/nxadm/tail v1.4.11
3434 github.com/pressly/goose/v3 v3.25.0
@@ -48,22 +48,11 @@ require (
4848)
4949
5050require (
51+ cloud.google.com/go v0.116.0 // indirect
52+ cloud.google.com/go/auth v0.12.1 // indirect
53+ cloud.google.com/go/compute/metadata v0.5.2 // indirect
5154 github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.0 // indirect
5255 github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 // indirect
53− github.com/beorn7/perks v1.0.1 // indirect
54− github.com/cespare/xxhash/v2 v2.3.0 // indirect
55− github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
56− github.com/prometheus/client_golang v1.23.2 // indirect
57− github.com/prometheus/client_model v0.6.2 // indirect
58− github.com/prometheus/common v0.66.1 // indirect
59− github.com/prometheus/procfs v0.16.1 // indirect
60− go.yaml.in/yaml/v2 v2.4.2 // indirect
61−)
62−
63−require (
64− cloud.google.com/go v0.116.0 // indirect
65− cloud.google.com/go/auth v0.9.3 // indirect
66− cloud.google.com/go/compute/metadata v0.5.0 // indirect
6756 github.com/andybalholm/cascadia v1.3.3 // indirect
6857 github.com/anthropics/anthropic-sdk-go v1.12.0 // indirect
6958 github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
@@ -84,11 +73,14 @@ require (
8473 github.com/disintegration/gift v1.1.2 // indirect
8574 github.com/dlclark/regexp2 v1.11.5 // indirect
8675 github.com/dustin/go-humanize v1.0.1 // indirect
76+ github.com/felixge/httpsnoop v1.0.4 // indirect
8777 github.com/fsnotify/fsnotify v1.9.0 // indirect
8878 github.com/go-logfmt/logfmt v0.6.0 // indirect
79+ github.com/go-logr/logr v1.4.3 // indirect
80+ github.com/go-logr/stdr v1.2.2 // indirect
8981 github.com/go-viper/mapstructure/v2 v2.4.0 // indirect
90− github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
9182 github.com/google/go-cmp v0.7.0 // indirect
83+ github.com/google/jsonschema-go v0.3.0 // indirect
9284 github.com/google/s2a-go v0.1.8 // indirect
9385 github.com/googleapis/enterprise-certificate-proxy v0.3.4 // indirect
9486 github.com/gorilla/css v1.0.1 // indirect
@@ -101,7 +93,7 @@ require (
10193 github.com/lucasb-eyer/go-colorful v1.3.0
10294 github.com/mailru/easyjson v0.7.7 // indirect
10395 github.com/mattn/go-isatty v0.0.20 // indirect
104− github.com/mattn/go-runewidth v0.0.16 // indirect
96+ github.com/mattn/go-runewidth v0.0.17 // indirect
10597 github.com/mfridman/interpolate v0.0.2 // indirect
10698 github.com/microcosm-cc/bluemonday v1.0.27 // indirect
10799 github.com/mitchellh/mapstructure v1.5.0 // indirect
@@ -114,12 +106,11 @@ require (
114106 github.com/openai/openai-go/v2 v2.3.0 // indirect
115107 github.com/pierrec/lz4/v4 v4.1.22 // indirect
116108 github.com/pmezard/go-difflib v1.0.0 // indirect
117− github.com/posthog/posthog-go v1.6.10
109+ github.com/posthog/posthog-go v1.6.11
118110 github.com/rivo/uniseg v0.4.7
119111 github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect
120112 github.com/sethvargo/go-retry v0.3.0 // indirect
121113 github.com/sourcegraph/jsonrpc2 v0.2.1 // indirect
122− github.com/spf13/cast v1.7.1 // indirect
123114 github.com/spf13/pflag v1.0.9 // indirect
124115 github.com/tetratelabs/wazero v1.9.0 // indirect
125116 github.com/tidwall/gjson v1.18.0 // indirect
@@ -132,19 +123,23 @@ require (
132123 github.com/yosida95/uritemplate/v3 v3.0.2 // indirect
133124 github.com/yuin/goldmark v1.7.8 // indirect
134125 github.com/yuin/goldmark-emoji v1.0.5 // indirect
135− go.opencensus.io v0.24.0 // indirect
126+ go.opentelemetry.io/auto/sdk v1.1.0 // indirect
127+ go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 // indirect
128+ go.opentelemetry.io/otel v1.37.0 // indirect
129+ go.opentelemetry.io/otel/metric v1.37.0 // indirect
130+ go.opentelemetry.io/otel/trace v1.37.0 // indirect
136131 go.uber.org/multierr v1.11.0 // indirect
137− golang.org/x/crypto v0.41.0 // indirect
132+ golang.org/x/crypto v0.42.0 // indirect
138133 golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b // indirect
139134 golang.org/x/image v0.27.0 // indirect
140135 golang.org/x/net v0.43.0 // indirect
141136 golang.org/x/sync v0.17.0 // indirect
142137 golang.org/x/sys v0.36.0 // indirect
143− golang.org/x/term v0.34.0 // indirect
144− golang.org/x/text v0.29.0
138+ golang.org/x/term v0.35.0 // indirect
139+ golang.org/x/text v0.30.0
145140 google.golang.org/genai v1.26.0 // indirect
146− google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect
147− google.golang.org/grpc v1.66.2 // indirect
141+ google.golang.org/genproto/googleapis/rpc v0.0.0-20241206012308-a4fef0638583 // indirect
142+ google.golang.org/grpc v1.67.1 // indirect
148143 google.golang.org/protobuf v1.36.8 // indirect
149144 gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
150145 gopkg.in/yaml.v3 v3.0.1 // indirect
go.sum+51−133
@@ -1,10 +1,9 @@
1−cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
21cloud.google.com/go v0.116.0 h1:B3fRrSDkLRt5qSHWe40ERJvhvnQwdZiHu0bJOpldweE=
32cloud.google.com/go v0.116.0/go.mod h1:cEPSRWPzZEswwdr9BxE6ChEn01dWlTaF05LiC2Xs70U=
4−cloud.google.com/go/auth v0.9.3 h1:VOEUIAADkkLtyfr3BLa3R8Ed/j6w1jTBmARx+wb5w5U=
5−cloud.google.com/go/auth v0.9.3/go.mod h1:7z6VY+7h3KUdRov5F1i8NDP5ZzWKYmEPO842BgCsmTk=
6−cloud.google.com/go/compute/metadata v0.5.0 h1:Zr0eK8JbFv6+Wi4ilXAR8FJ3wyNdpxHKJNPos6LTZOY=
7−cloud.google.com/go/compute/metadata v0.5.0/go.mod h1:aHnloV2TPI38yx4s9+wAZhHykWvVCfu7hQbF+9CWoiY=
3+cloud.google.com/go/auth v0.12.1 h1:n2Bj25BUMM0nvE9D2XLTiImanwZhO3DkfWSYS/SAJP4=
4+cloud.google.com/go/auth v0.12.1/go.mod h1:BFMu+TNpF3DmvfBO9ClqTR/SiqVIm7LukKF9mbendF4=
5+cloud.google.com/go/compute/metadata v0.5.2 h1:UxK4uu/Tn+I3p2dYWTfiX4wva7aYlKixAHn3fyqngqo=
6+cloud.google.com/go/compute/metadata v0.5.2/go.mod h1:C66sj2AluDcIqakBq/M8lw8/ybHgOZqin2obFxa/E5k=
87github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.0 h1:g0EZJwz7xkXQiZAI5xi9f3WWFYBlX1CPTrR+NDToRkQ=
98github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.0/go.mod h1:XCW7KnZet0Opnr7HccfUw1PLc4CjHqpcaxW8DHklNkQ=
109github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0 h1:tfLQ34V6F7tVSwoTf/4lH5sE0o6eCJuNDTmH09nDpbc=
@@ -13,7 +12,6 @@ github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 h1:ywEEhmNahHBihViHepv3xP
1312github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0/go.mod h1:iZDifYGJTIgIIkYRNWPENUnqx6bJ2xnSDFI2tjwZNuY=
1413github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 h1:XHOnouVk1mxXfQidrMEnLlPk9UMeRtyBTnEFtxkV0kU=
1514github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI=
16−github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
1715github.com/JohannesKaufmann/html-to-markdown v1.6.0 h1:04VXMiE50YYfCfLboJCLcgqF5x+rHJnb1ssNmqpLH/k=
1816github.com/JohannesKaufmann/html-to-markdown v1.6.0/go.mod h1:NUI78lGg/a7vpEJTz/0uOcYMaibytE4BUOQS8k78yPQ=
1917github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ=
@@ -42,29 +40,22 @@ github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuP
4240github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4=
4341github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPnH1Wvgk=
4442github.com/bahlo/generic-list-go v0.2.0/go.mod h1:2KvAjgMlE5NNynlg/5iLrrCCZ2+5xWbdbCW3pNTGyYg=
45−github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
46−github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
4743github.com/bmatcuk/doublestar/v4 v4.9.1 h1:X8jg9rRZmJd4yRy7ZeNDRnM+T3ZfHv15JiBJ/avrEXE=
4844github.com/bmatcuk/doublestar/v4 v4.9.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
4945github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs=
5046github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0=
51−github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
52−github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
53−github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
5447github.com/charlievieth/fastwalk v1.0.14 h1:3Eh5uaFGwHZd8EGwTjJnSpBkfwfsak9h6ICgnWlhAyg=
5548github.com/charlievieth/fastwalk v1.0.14/go.mod h1:diVcUreiU1aQ4/Wu3NbxxH4/KYdKpLDojrQ1Bb2KgNY=
5649github.com/charmbracelet/bubbles/v2 v2.0.0-beta.1.0.20250820203609-601216f68ee2 h1:973OHYuq2Jx9deyuPwe/6lsuQrDCatOsjP8uCd02URE=
5750github.com/charmbracelet/bubbles/v2 v2.0.0-beta.1.0.20250820203609-601216f68ee2/go.mod h1:6HamsBKWqEC/FVHuQMHgQL+knPyvHH55HwJDHl/adMw=
58−github.com/charmbracelet/bubbletea/v2 v2.0.0-beta.4.0.20250910155747-997384b0b35e h1:4BBnKWFwJ5FLyhw/ijFxKE04i9rubr8WIPR1kjO57iA=
59−github.com/charmbracelet/bubbletea/v2 v2.0.0-beta.4.0.20250910155747-997384b0b35e/go.mod h1:F7AfLKYQqpM3NNBVs7ctW417tavhvoh9SBjsgtwpzbY=
60−github.com/charmbracelet/catwalk v0.6.5-0.20251010111259-a1bafd2530bb h1:1dANrQJF+y+irksWTqd4dvN91JP7e/gdYZscef3PxkY=
61−github.com/charmbracelet/catwalk v0.6.5-0.20251010111259-a1bafd2530bb/go.mod h1:ReU4SdrLfe63jkEjWMdX2wlZMV3k9r11oQAmzN0m+KY=
51+github.com/charmbracelet/bubbletea/v2 v2.0.0-beta.4.0.20251011205917-3b687ffc1619 h1:hjOhtqsxa+LVuCAkzhfA43wtusOaUPyQdSTg/wbRscw=
52+github.com/charmbracelet/bubbletea/v2 v2.0.0-beta.4.0.20251011205917-3b687ffc1619/go.mod h1:5IzIGXU1n0foRc8bRAherC8ZuQCQURPlwx3ANLq1138=
6253github.com/charmbracelet/catwalk v0.6.5-0.20251013041345-e6202aaa8c46 h1:Uo9eLh7tblCfVnuKmF48MFpk27j2whgnLyDUYyylucg=
6354github.com/charmbracelet/catwalk v0.6.5-0.20251013041345-e6202aaa8c46/go.mod h1:ReU4SdrLfe63jkEjWMdX2wlZMV3k9r11oQAmzN0m+KY=
6455github.com/charmbracelet/colorprofile v0.3.2 h1:9J27WdztfJQVAQKX2WOlSSRB+5gaKqqITmrvb1uTIiI=
6556github.com/charmbracelet/colorprofile v0.3.2/go.mod h1:mTD5XzNeWHj8oqHb+S1bssQb7vIHbepiebQ2kPKVKbI=
66−github.com/charmbracelet/fang v0.4.2 h1:nWr7Tb82/TTNNGMGG35aTZ1X68loAOQmpb0qxkKXjas=
67−github.com/charmbracelet/fang v0.4.2/go.mod h1:wHJKQYO5ReYsxx+yZl+skDtrlKO/4LLEQ6EXsdHhRhg=
57+github.com/charmbracelet/fang v0.4.3 h1:qXeMxnL4H6mSKBUhDefHu8NfikFbP/MBNTfqTrXvzmY=
58+github.com/charmbracelet/fang v0.4.3/go.mod h1:wHJKQYO5ReYsxx+yZl+skDtrlKO/4LLEQ6EXsdHhRhg=
6859github.com/charmbracelet/fantasy v0.0.0-20251010114724-801d5df11cef h1:4GmaYNj/NifjXbW6K3QExrCuiRpoNMWAlJESzmppdGU=
6960github.com/charmbracelet/fantasy v0.0.0-20251010114724-801d5df11cef/go.mod h1:3XBTxXYYvBX1UsKa5FHicJUQJkoHHmUjXRfr0BcqV4A=
7061github.com/charmbracelet/glamour/v2 v2.0.0-20250811143442-a27abb32f018 h1:PU4Zvpagsk5sgaDxn5W4sxHuLp9QRMBZB3bFSk40A4w=
@@ -75,8 +66,8 @@ github.com/charmbracelet/log/v2 v2.0.0-20250226163916-c379e29ff706 h1:WkwO6Ks3mS
7566github.com/charmbracelet/log/v2 v2.0.0-20250226163916-c379e29ff706/go.mod h1:mjJGp00cxcfvD5xdCa+bso251Jt4owrQvuimJtVmEmM=
7667github.com/charmbracelet/ultraviolet v0.0.0-20250915111650-81d4262876ef h1:VrWaUi2LXYLjfjCHowdSOEc6dQ9Ro14KY7Bw4IWd19M=
7768github.com/charmbracelet/ultraviolet v0.0.0-20250915111650-81d4262876ef/go.mod h1:AThRsQH1t+dfyOKIwXRoJBniYFQUkUpQq4paheHMc2o=
78−github.com/charmbracelet/x/ansi v0.10.1 h1:rL3Koar5XvX0pHGfovN03f5cxLbCF2YvLeyz7D2jVDQ=
79−github.com/charmbracelet/x/ansi v0.10.1/go.mod h1:3RQDQ6lDnROptfpWuUVIUG64bD2g2BgntdxH0Ya5TeE=
69+github.com/charmbracelet/x/ansi v0.10.2 h1:ith2ArZS0CJG30cIUfID1LXN7ZFXRCww6RUvAPA+Pzw=
70+github.com/charmbracelet/x/ansi v0.10.2/go.mod h1:HbLdJjQH4UH4AqA2HpRWuWNluRE6zxJH/yteYEYCFa8=
8071github.com/charmbracelet/x/cellbuf v0.0.14-0.20250811133356-e0c5dbe5ea4a h1:zYSNtEJM9jwHbJts2k+Hroj+xQwsW1yxc4Wopdv7KaI=
8172github.com/charmbracelet/x/cellbuf v0.0.14-0.20250811133356-e0c5dbe5ea4a/go.mod h1:rc2bsPC6MWae3LdOxNO1mOb443NlMrrDL0xEya48NNc=
8273github.com/charmbracelet/x/exp/charmtone v0.0.0-20250708181618-a60a724ba6c3 h1:1xwHZg6eMZ9Wv5TE1UGub6ARubyOd1Lo5kPUI/6VL50=
@@ -95,8 +86,6 @@ github.com/charmbracelet/x/termios v0.1.1 h1:o3Q2bT8eqzGnGPOYheoYS8eEleT5ZVNYNy8
9586github.com/charmbracelet/x/termios v0.1.1/go.mod h1:rB7fnv1TgOPOyyKRJ9o+AsTU/vK5WHJ2ivHeut/Pcwo=
9687github.com/charmbracelet/x/windows v0.2.2 h1:IofanmuvaxnKHuV04sC0eBy/smG6kIKrWG2/jYn2GuM=
9788github.com/charmbracelet/x/windows v0.2.2/go.mod h1:/8XtdKZzedat74NQFn0NGlGL4soHB0YQZrETF96h75k=
98−github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
99−github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
10089github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
10190github.com/creack/pty v1.1.24 h1:bJrF4RRfyJnbTJqzRLHzcGaZK1NeM5kTC9jGgovnR1s=
10291github.com/creack/pty v1.1.24/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE=
@@ -113,49 +102,31 @@ github.com/dlclark/regexp2 v1.11.5 h1:Q/sSnsKerHeCkc/jSTNq1oCm7KiVgUMZRDUoRu0JQZ
113102github.com/dlclark/regexp2 v1.11.5/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
114103github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
115104github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
116−github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
117−github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
118−github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
119−github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
120−github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
121−github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
105+github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
106+github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
122107github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
123108github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
124109github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
125110github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4=
126111github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
112+github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
113+github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
114+github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
115+github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
116+github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
127117github.com/go-quicktest/qt v1.101.0 h1:O1K29Txy5P2OK0dGo59b7b0LR6wKfIhttaAhHUyn7eI=
128118github.com/go-quicktest/qt v1.101.0/go.mod h1:14Bz/f7NwaXPtdYEgzsx46kqSxVwTbzVZsDC26tQJow=
129119github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs=
130120github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
131−github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk=
132−github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
133−github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
134−github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
135−github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
136−github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
137−github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
138−github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
139−github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
140−github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
141−github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
142−github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
143−github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
144−github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
145−github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
146−github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
147−github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
148−github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
149−github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
150−github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
151−github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
152−github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
121+github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeDy8=
122+github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
153123github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
154124github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
155125github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
126+github.com/google/jsonschema-go v0.3.0 h1:6AH2TxVNtk3IlvkkhjrtbUc4S8AvO0Xii0DxIygDg+Q=
127+github.com/google/jsonschema-go v0.3.0/go.mod h1:r5quNTdLOYEz95Ru18zA0ydNbBuYoo9tgaYcxEYhJVE=
156128github.com/google/s2a-go v0.1.8 h1:zZDs9gcbt9ZPLV0ndSyQk6Kacx2g/X+SKYovpnz3SMM=
157129github.com/google/s2a-go v0.1.8/go.mod h1:6iNWHTpQ+nfNRN5E00MSdfDwVesa8hhS32PhPO8deJA=
158−github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
159130github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
160131github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
161132github.com/googleapis/enterprise-certificate-proxy v0.3.4 h1:XYIDZApgAnrN1c855gTgghdIA6Stxb52D5RnLI1SLyw=
@@ -195,18 +166,18 @@ github.com/lucasb-eyer/go-colorful v1.3.0 h1:2/yBRLdWBZKrf7gB40FoiKfAWYQ0lqNcbuQ
195166github.com/lucasb-eyer/go-colorful v1.3.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
196167github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
197168github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
198−github.com/mark3labs/mcp-go v0.41.0 h1:IFfJaovCet65F3av00bE1HzSnmHpMRWM1kz96R98I70=
199−github.com/mark3labs/mcp-go v0.41.0/go.mod h1:T7tUa2jO6MavG+3P25Oy/jR7iCeJPHImCZHRymCn39g=
200169github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
201170github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
202−github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
203−github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
171+github.com/mattn/go-runewidth v0.0.17 h1:78v8ZlW0bP43XfmAfPsdXcoNCelfMHsDmd/pkENfrjQ=
172+github.com/mattn/go-runewidth v0.0.17/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
204173github.com/mfridman/interpolate v0.0.2 h1:pnuTK7MQIxxFz1Gr+rjSIx9u7qVjf5VOoM/u6BbAxPY=
205174github.com/mfridman/interpolate v0.0.2/go.mod h1:p+7uk6oE07mpE/Ik1b8EckO0O4ZXiGAfshKBWLUM9Xg=
206175github.com/microcosm-cc/bluemonday v1.0.27 h1:MpEUotklkwCSLeH+Qdx1VJgNqLlpY2KXwXFM08ygZfk=
207176github.com/microcosm-cc/bluemonday v1.0.27/go.mod h1:jFi9vgW+H7c3V0lb6nR74Ib/DIB5OBs92Dimizgw2cA=
208177github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
209178github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
179+github.com/modelcontextprotocol/go-sdk v1.0.0 h1:Z4MSjLi38bTgLrd/LjSmofqRqyBiVKRyQSJgw8q8V74=
180+github.com/modelcontextprotocol/go-sdk v1.0.0/go.mod h1:nYtYQroQ2KQiM0/SbyEPUWQ6xs4B95gJjEalc9AQyOs=
210181github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA=
211182github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo=
212183github.com/muesli/mango v0.1.0 h1:DZQK45d2gGbql1arsYA4vfg4d7I9Hfx5rX/GCmzsAvI=
@@ -219,10 +190,8 @@ github.com/muesli/roff v0.1.0 h1:YD0lalCotmYuF5HhZliKWlIx7IEhiXeSfq7hNjFqGF8=
219190github.com/muesli/roff v0.1.0/go.mod h1:pjAHQM9hdUUwm/krAfrLGgJkXJ+YuhtsfZ42kieB2Ig=
220191github.com/muesli/termenv v0.16.0 h1:S5AlUN9dENB57rsbnkPyfdGuWIlkmzJjbFf0Tf5FWUc=
221192github.com/muesli/termenv v0.16.0/go.mod h1:ZRfOIKPFDYQoDFF4Olj7/QJbW60Ol/kL1pU3VfY/Cnk=
222−github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
223−github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
224−github.com/ncruces/go-sqlite3 v0.29.0 h1:1tsLiagCoqZEfcHDeKsNSv5jvrY/Iu393pAnw2wLNJU=
225−github.com/ncruces/go-sqlite3 v0.29.0/go.mod h1:r1hSvYKPNJ+OlUA1O3r8o9LAawzPAlqeZiIdxTBBBJ0=
193+github.com/ncruces/go-sqlite3 v0.29.1 h1:NIi8AISWBToRHyoz01FXiTNvU147Tqdibgj2tFzJCqM=
194+github.com/ncruces/go-sqlite3 v0.29.1/go.mod h1:PpccBNNhvjwUOwDQEn2gXQPFPTWdlromj0+fSkd5KSg=
226195github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4=
227196github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
228197github.com/ncruces/julianday v1.0.0 h1:fH0OKwa7NWvniGQtxdJRxAgkBMolni2BjDHaWTxqt7M=
@@ -240,19 +209,10 @@ github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjL
240209github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
241210github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
242211github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
243−github.com/posthog/posthog-go v1.6.10 h1:OA6bkiUg89rI7f5cSXbcrH5+wLinyS6hHplnD92Pu/M=
244−github.com/posthog/posthog-go v1.6.10/go.mod h1:LcC1Nu4AgvV22EndTtrMXTy+7RGVC0MhChSw7Qk5XkY=
212+github.com/posthog/posthog-go v1.6.11 h1:5G8Y3pxnOpc3S4+PK1z1dCmZRuldiWxBsqqvvSfC2+w=
213+github.com/posthog/posthog-go v1.6.11/go.mod h1:LcC1Nu4AgvV22EndTtrMXTy+7RGVC0MhChSw7Qk5XkY=
245214github.com/pressly/goose/v3 v3.25.0 h1:6WeYhMWGRCzpyd89SpODFnCBCKz41KrVbRT58nVjGng=
246215github.com/pressly/goose/v3 v3.25.0/go.mod h1:4hC1KrritdCxtuFsqgs1R4AU5bWtTAf+cnWvfhf2DNY=
247−github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o=
248−github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg=
249−github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
250−github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
251−github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
252−github.com/prometheus/common v0.66.1 h1:h5E0h5/Y8niHc5DlaLlWLArTQI7tMrsfQjHV+d9ZoGs=
253−github.com/prometheus/common v0.66.1/go.mod h1:gcaUsgf3KfRSwHY4dIMXLPV0K/Wg1oZ8+SbZk/HH/dA=
254−github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg=
255−github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is=
256216github.com/qjebbs/go-jsons v1.0.0-alpha.4 h1:Qsb4ohRUHQODIUAsJKdKJ/SIDbsO7oGOzsfy+h1yQZs=
257217github.com/qjebbs/go-jsons v1.0.0-alpha.4/go.mod h1:wNJrtinHyC3YSf6giEh4FJN8+yZV7nXBjvmfjhBIcw4=
258218github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
@@ -277,8 +237,6 @@ github.com/sethvargo/go-retry v0.3.0 h1:EEt31A35QhrcRZtrYFDTBg91cqZVnFL2navjDrah
277237github.com/sethvargo/go-retry v0.3.0/go.mod h1:mNX17F0C/HguQMyMyJxcnU471gOZGxCLyYaFyAZraas=
278238github.com/sourcegraph/jsonrpc2 v0.2.1 h1:2GtljixMQYUYCmIg7W9aF2dFmniq/mOr2T9tFRh6zSQ=
279239github.com/sourcegraph/jsonrpc2 v0.2.1/go.mod h1:ZafdZgk/axhT1cvZAPOhw+95nz2I/Ra5qMlU4gTRwIo=
280−github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y=
281−github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
282240github.com/spf13/cobra v1.10.1 h1:lJeBwCfmrnXthfAupyUTzJ/J4Nc1RsHC/mSRU2dll/s=
283241github.com/spf13/cobra v1.10.1/go.mod h1:7SmJGaTHFVBY0jW4NXGluQoLvhqFQM+6XSKD+P4XaB0=
284242github.com/spf13/pflag v1.0.9 h1:9exaQaMOCwffKiiiYk6/BndUBv+iRViNW+4lEMi0PvY=
@@ -288,14 +246,9 @@ github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c/go.mod h1:cNQ3dwVJtS
288246github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef h1:Ch6Q+AZUxDBCVqdkI8FSpFyZDtCVBc2VmejdNrm5rRQ=
289247github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef/go.mod h1:nXTWP6+gD5+LUJ8krVhhoeHjvHTutPxMYl5SvkcnJNE=
290248github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
291−github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
292−github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
293249github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
294250github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
295251github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
296−github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
297−github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
298−github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
299252github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
300253github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
301254github.com/tetratelabs/wazero v1.9.0 h1:IcZ56OuxrtaEz8UYNRHBrUa9bYeX9oVY93KspZZBf/I=
@@ -330,44 +283,39 @@ github.com/zeebo/assert v1.3.0 h1:g7C04CbJuIDKNPFHmsk4hwZDO5O+kntRxzaUoNXj+IQ=
330283github.com/zeebo/assert v1.3.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0=
331284github.com/zeebo/xxh3 v1.0.2 h1:xZmwmqxHZA8AI603jOQ0tMqmBr9lPeFwGg6d+xy9DC0=
332285github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaDcA=
333−go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
334−go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
286+go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
287+go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
288+go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 h1:TT4fX+nBOA/+LUkobKGW1ydGcn+G3vRw9+g5HwCphpk=
289+go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0/go.mod h1:L7UH0GbB0p47T4Rri3uHjbpCFYrVrwc1I25QhNPiGK8=
290+go.opentelemetry.io/otel v1.37.0 h1:9zhNfelUvx0KBfu/gb+ZgeAfAgtWrfHJZcAqFC228wQ=
291+go.opentelemetry.io/otel v1.37.0/go.mod h1:ehE/umFRLnuLa/vSccNq9oS1ErUlkkK71gMcN34UG8I=
292+go.opentelemetry.io/otel/metric v1.37.0 h1:mvwbQS5m0tbmqML4NqK+e3aDiO02vsf/WgbsdpcPoZE=
293+go.opentelemetry.io/otel/metric v1.37.0/go.mod h1:04wGrZurHYKOc+RKeye86GwKiTb9FKm1WHtO+4EVr2E=
294+go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mxVK7z4=
295+go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0=
335296go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
336297go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
337−go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI=
338−go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU=
339298go.yaml.in/yaml/v4 v4.0.0-rc.2 h1:/FrI8D64VSr4HtGIlUtlFMGsm7H7pWTbj6vOLVZcA6s=
340299go.yaml.in/yaml/v4 v4.0.0-rc.2/go.mod h1:aZqd9kCMsGL7AuUv/m/PvWLdg5sjJsZ4oHDEnfPPfY0=
341300golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
342−golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
343301golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
344302golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
345303golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
346304golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M=
347305golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
348306golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
349−golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4=
350−golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc=
351−golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
307+golang.org/x/crypto v0.42.0 h1:chiH31gIWm57EkTXpwnqf8qeuMUi0yekh6mT2AvFlqI=
308+golang.org/x/crypto v0.42.0/go.mod h1:4+rDnOTJhQCx2q7/j6rAN5XDw8kPjeaXEUR2eL94ix8=
352309golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b h1:M2rDM6z3Fhozi9O7NWsxAkg/yqS/lQJ6PmkyIV3YP+o=
353310golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b/go.mod h1:3//PLf8L/X+8b4vuAfHzxeRUl04Adcb341+IGKfnqS8=
354311golang.org/x/image v0.27.0 h1:C8gA4oWU/tKkdCfYT6T2u4faJu3MeNS5O8UPWlPF61w=
355312golang.org/x/image v0.27.0/go.mod h1:xbdrClrAUway1MUTEZDq9mz/UpRwYAkFFNUslZtcB+g=
356−golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
357−golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
358−golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
359313golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
360314golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
361315golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
362316golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
363317golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
364−golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
365−golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
366−golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
367−golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
368−golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
369318golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
370−golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
371319golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
372320golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
373321golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
@@ -380,9 +328,6 @@ golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
380328golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
381329golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE=
382330golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg=
383−golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
384−golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
385−golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
386331golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
387332golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
388333golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -392,10 +337,7 @@ golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
392337golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
393338golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug=
394339golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
395−golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
396340golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
397−golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
398−golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
399341golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
400342golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
401343golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -423,8 +365,8 @@ golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
423365golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk=
424366golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
425367golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
426−golang.org/x/term v0.34.0 h1:O/2T7POpk0ZZ7MAzMeWFSg6S5IpWd/RXDlM9hgM3DR4=
427−golang.org/x/term v0.34.0/go.mod h1:5jC53AEywhIVebHgPVeg0mj8OD3VO9OzclacVrqpaAw=
368+golang.org/x/term v0.35.0 h1:bZBVKBudEyhRcajGcNc3jIfWPqV4y/Kt2XcoigOWtDQ=
369+golang.org/x/term v0.35.0/go.mod h1:TPGtkTLesOwf2DE8CgVYiZinHAOuy5AYUYT1lENIZnA=
428370golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
429371golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
430372golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
@@ -434,45 +376,23 @@ golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
434376golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
435377golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
436378golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
437−golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk=
438−golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4=
379+golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k=
380+golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM=
439381golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
440−golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
441−golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
442−golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
443−golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
444382golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
445383golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
446384golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
447385golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
448386golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
387+golang.org/x/tools v0.37.0 h1:DVSRzp7FwePZW356yEAChSdNcQo6Nsp+fex1SUW09lE=
388+golang.org/x/tools v0.37.0/go.mod h1:MBN5QPQtLMHVdvsbtarmTNukZDdgwdwlO5qGacAzF0w=
449389golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
450−golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
451−google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
452−google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
453390google.golang.org/genai v1.26.0 h1:r4HGL54kFv/WCRMTAbZg05Ct+vXfhAbTRlXhFyBkEQo=
454391google.golang.org/genai v1.26.0/go.mod h1:OClfdf+r5aaD+sCd4aUSkPzJItmg2wD/WON9lQnRPaY=
455−google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
456−google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
457−google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
458−google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ=
459−google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU=
460−google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
461−google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
462−google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
463−google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
464−google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
465−google.golang.org/grpc v1.66.2 h1:3QdXkuq3Bkh7w+ywLdLvM56cmGvQHUMZpiCzt6Rqaoo=
466−google.golang.org/grpc v1.66.2/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y=
467−google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
468−google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
469−google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
470−google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
471−google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
472−google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
473−google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
474−google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
475−google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
392+google.golang.org/genproto/googleapis/rpc v0.0.0-20241206012308-a4fef0638583 h1:IfdSdTcLFy4lqUQrQJLkLt1PB+AsqVz6lwkWPzWEz10=
393+google.golang.org/genproto/googleapis/rpc v0.0.0-20241206012308-a4fef0638583/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU=
394+google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E=
395+google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA=
476396google.golang.org/protobuf v1.36.8 h1:xHScyCOEuuwZEc6UtSOvPbAT4zRh0xcNRYekJwfqyMc=
477397google.golang.org/protobuf v1.36.8/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU=
478398gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
@@ -491,8 +411,6 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
491411gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
492412gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
493413gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
494−honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
495−honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
496414modernc.org/libc v1.66.3 h1:cfCbjTUcdsKyyZZfEUKfoHcP3S0Wkvz3jgSzByEWVCQ=
497415modernc.org/libc v1.66.3/go.mod h1:XD9zO8kt59cANKvHPXpx7yS2ELPheAey0vjIuZOhOU8=
498416modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU=
internal/agent/tools/mcp-tools.go+93−108
@@ -6,8 +6,11 @@ import (
66 "encoding/json"
77 "errors"
88 "fmt"
9+ "io"
910 "log/slog"
1011 "maps"
12+ "net/http"
13+ "os/exec"
1114 "slices"
1215 "strings"
1316 "sync"
@@ -20,9 +23,7 @@ import (
2023 "github.com/charmbracelet/crush/internal/pubsub"
2124 "github.com/charmbracelet/crush/internal/version"
2225 "github.com/charmbracelet/fantasy/ai"
23− "github.com/mark3labs/mcp-go/client"
24− "github.com/mark3labs/mcp-go/client/transport"
25− "github.com/mark3labs/mcp-go/mcp"
26+ "github.com/modelcontextprotocol/go-sdk/mcp"
2627)
2728
2829// MCPState represents the current state of an MCP client
@@ -72,7 +73,7 @@ type MCPClientInfo struct {
7273 Name string
7374 State MCPState
7475 Error error
75− Client *client.Client
76+ Client *mcp.ClientSession
7677 ToolCount int
7778 ConnectedAt time.Time
7879}
@@ -81,14 +82,14 @@ var (
8182 mcpToolsOnce sync.Once
8283 mcpTools = csync.NewMap[string, *McpTool]()
8384 mcpClient2Tools = csync.NewMap[string, []*McpTool]()
84− mcpClients = csync.NewMap[string, *client.Client]()
85+ mcpClients = csync.NewMap[string, *mcp.ClientSession]()
8586 mcpStates = csync.NewMap[string, MCPClientInfo]()
8687 mcpBroker = pubsub.NewBroker[MCPEvent]()
8788)
8889
8990type McpTool struct {
9091 mcpName string
91− tool mcp.Tool
92+ tool *mcp.Tool
9293 permissions permission.Service
9394 workingDir string
9495 providerOptions ai.ProviderOptions
@@ -114,18 +115,19 @@ func (m *McpTool) MCPToolName() string {
114115 return m.tool.Name
115116}
116117
117−func (m *McpTool) Info() ai.ToolInfo {
118− required := m.tool.InputSchema.Required
118+func (b *McpTool) Info() ai.ToolInfo {
119+ input := b.tool.InputSchema.(map[string]any)
120+ required, _ := input["required"].([]string)
119121 if required == nil {
120122 required = make([]string, 0)
121123 }
122− parameters := m.tool.InputSchema.Properties
124+ parameters, _ := input["properties"].(map[string]any)
123125 if parameters == nil {
124126 parameters = make(map[string]any)
125127 }
126128 return ai.ToolInfo{
127− Name: fmt.Sprintf("mcp_%s_%s", m.mcpName, m.tool.Name),
128− Description: m.tool.Description,
129+ Name: fmt.Sprintf("mcp_%s_%s", b.mcpName, b.tool.Name),
130+ Description: b.tool.Description,
129131 Parameters: parameters,
130132 Required: required,
131133 }
@@ -141,11 +143,9 @@ func runTool(ctx context.Context, name, toolName string, input string) (ai.ToolR
141143 if err != nil {
142144 return ai.NewTextErrorResponse(err.Error()), nil
143145 }
144− result, err := c.CallTool(ctx, mcp.CallToolRequest{
145− Params: mcp.CallToolParams{
146− Name: toolName,
147− Arguments: args,
148− },
146+ result, err := c.CallTool(ctx, &mcp.CallToolParams{
147+ Name: toolName,
148+ Arguments: args,
149149 })
150150 if err != nil {
151151 return ai.NewTextErrorResponse(err.Error()), nil
@@ -153,8 +153,8 @@ func runTool(ctx context.Context, name, toolName string, input string) (ai.ToolR
153153
154154 output := make([]string, 0, len(result.Content))
155155 for _, v := range result.Content {
156− if v, ok := v.(mcp.TextContent); ok {
157− output = append(output, v.Text)
156+ if vv, ok := v.(*mcp.TextContent); ok {
157+ output = append(output, vv.Text)
158158 } else {
159159 output = append(output, fmt.Sprintf("%v", v))
160160 }
@@ -162,8 +162,8 @@ func runTool(ctx context.Context, name, toolName string, input string) (ai.ToolR
162162 return ai.NewTextResponse(strings.Join(output, "\n")), nil
163163}
164164
165−func getOrRenewClient(ctx context.Context, name string) (*client.Client, error) {
166− c, ok := mcpClients.Get(name)
165+func getOrRenewClient(ctx context.Context, name string) (*mcp.ClientSession, error) {
166+ sess, ok := mcpClients.Get(name)
167167 if !ok {
168168 return nil, fmt.Errorf("mcp '%s' not available", name)
169169 }
@@ -175,20 +175,20 @@ func getOrRenewClient(ctx context.Context, name string) (*client.Client, error)
175175 timeout := mcpTimeout(m)
176176 pingCtx, cancel := context.WithTimeout(ctx, timeout)
177177 defer cancel()
178− err := c.Ping(pingCtx)
178+ err := sess.Ping(pingCtx, nil)
179179 if err == nil {
180− return c, nil
180+ return sess, nil
181181 }
182182 updateMCPState(name, MCPStateError, maybeTimeoutErr(err, timeout), nil, state.ToolCount)
183183
184− c, err = createAndInitializeClient(ctx, name, m, cfg.Resolver())
184+ sess, err = createMCPSession(ctx, name, m, cfg.Resolver())
185185 if err != nil {
186186 return nil, err
187187 }
188188
189− updateMCPState(name, MCPStateConnected, nil, c, state.ToolCount)
190− mcpClients.Set(name, c)
191− return c, nil
189+ updateMCPState(name, MCPStateConnected, nil, sess, state.ToolCount)
190+ mcpClients.Set(name, sess)
191+ return sess, nil
192192}
193193
194194func (m *McpTool) Run(ctx context.Context, params ai.ToolCall) (ai.ToolResponse, error) {
@@ -215,8 +215,8 @@ func (m *McpTool) Run(ctx context.Context, params ai.ToolCall) (ai.ToolResponse,
215215 return runTool(ctx, m.mcpName, m.tool.Name, params.Input)
216216}
217217
218−func getTools(ctx context.Context, name string, permissions permission.Service, c *client.Client, workingDir string) ([]*McpTool, error) {
219− result, err := c.ListTools(ctx, mcp.ListToolsRequest{})
218+func getTools(ctx context.Context, name string, permissions permission.Service, c *mcp.ClientSession, workingDir string) ([]*McpTool, error) {
219+ result, err := c.ListTools(ctx, &mcp.ListToolsParams{})
220220 if err != nil {
221221 return nil, err
222222 }
@@ -248,7 +248,7 @@ func GetMCPState(name string) (MCPClientInfo, bool) {
248248}
249249
250250// updateMCPState updates the state of an MCP client and publishes an event
251−func updateMCPState(name string, state MCPState, err error, client *client.Client, toolCount int) {
251+func updateMCPState(name string, state MCPState, err error, client *mcp.ClientSession, toolCount int) {
252252 info := MCPClientInfo{
253253 Name: name,
254254 State: state,
@@ -275,19 +275,14 @@ func updateMCPState(name string, state MCPState, err error, client *client.Clien
275275 })
276276}
277277
278−// publishMCPEventToolsListChanged publishes a tool list changed event
279−func publishMCPEventToolsListChanged(name string) {
280− mcpBroker.Publish(pubsub.UpdatedEvent, MCPEvent{
281− Type: MCPEventToolsListChanged,
282− Name: name,
283− })
284−}
285−
286278// CloseMCPClients closes all MCP clients. This should be called during application shutdown.
287279func CloseMCPClients() error {
288280 var errs []error
289281 for name, c := range mcpClients.Seq2() {
290− if err := c.Close(); err != nil {
282+ if err := c.Close(); err != nil &&
283+ !errors.Is(err, io.EOF) &&
284+ !errors.Is(err, context.Canceled) &&
285+ err.Error() != "signal: killed" {
291286 errs = append(errs, fmt.Errorf("close mcp: %s: %w", name, err))
292287 }
293288 }
@@ -295,16 +290,6 @@ func CloseMCPClients() error {
295290 return errors.Join(errs...)
296291}
297292
298−var mcpInitRequest = mcp.InitializeRequest{
299− Params: mcp.InitializeParams{
300− ProtocolVersion: mcp.LATEST_PROTOCOL_VERSION,
301− ClientInfo: mcp.Implementation{
302− Name: "Crush",
303− Version: version.Version,
304− },
305− },
306−}
307−
308293func GetMCPTools(ctx context.Context, permissions permission.Service, cfg *config.Config) []*McpTool {
309294 mcpToolsOnce.Do(func() {
310295 var wg sync.WaitGroup
@@ -337,18 +322,14 @@ func GetMCPTools(ctx context.Context, permissions permission.Service, cfg *confi
337322 slog.Error("panic in mcp client initialization", "error", err, "name", name)
338323 }
339324 }()
340−
341− mcpCtx, cancel := context.WithTimeout(ctx, mcpTimeout(m))
342− defer cancel()
343−
344− c, err := createAndInitializeClient(mcpCtx, name, m, cfg.Resolver())
325+ c, err := createMCPSession(ctx, name, m, cfg.Resolver())
345326 if err != nil {
346327 return
347328 }
348329
349330 mcpClients.Set(name, c)
350331
351− tools, err := getTools(mcpCtx, name, permissions, c, cfg.WorkingDir())
332+ tools, err := getTools(ctx, name, permissions, c, cfg.WorkingDir())
352333 if err != nil {
353334 slog.Error("error listing tools", "error", err)
354335 updateMCPState(name, MCPStateError, err, nil, 0)
@@ -375,54 +356,51 @@ func updateMcpTools(mcpName string, tools []*McpTool) {
375356 }
376357 for _, tools := range mcpClient2Tools.Seq2() {
377358 for _, t := range tools {
378− mcpTools.Set(t.Info().Name, t)
359+ mcpTools.Set(t.Name(), t)
379360 }
380361 }
381362}
382363
383−func createAndInitializeClient(ctx context.Context, name string, m config.MCPConfig, resolver config.VariableResolver) (*client.Client, error) {
384− c, err := createMcpClient(name, m, resolver)
364+func createMCPSession(ctx context.Context, name string, m config.MCPConfig, resolver config.VariableResolver) (*mcp.ClientSession, error) {
365+ timeout := mcpTimeout(m)
366+ mcpCtx, cancel := context.WithCancel(ctx)
367+ cancelTimer := time.AfterFunc(timeout, cancel)
368+
369+ transport, err := createMCPTransport(mcpCtx, m, resolver)
385370 if err != nil {
386371 updateMCPState(name, MCPStateError, err, nil, 0)
387372 slog.Error("error creating mcp client", "error", err, "name", name)
388373 return nil, err
389374 }
390375
391− c.OnNotification(func(n mcp.JSONRPCNotification) {
392− slog.Debug("Received MCP notification", "name", name, "notification", n)
393− switch n.Method {
394− case "notifications/tools/list_changed":
395− publishMCPEventToolsListChanged(name)
396− default:
397− slog.Debug("Unhandled MCP notification", "name", name, "method", n.Method)
398− }
399− })
400−
401− // XXX: ideally we should be able to use context.WithTimeout here, but,
402− // the SSE MCP client will start failing once that context is canceled.
403− timeout := mcpTimeout(m)
404− mcpCtx, cancel := context.WithCancel(ctx)
405− cancelTimer := time.AfterFunc(timeout, cancel)
376+ client := mcp.NewClient(
377+ &mcp.Implementation{
378+ Name: "crush",
379+ Version: version.Version,
380+ Title: "Crush",
381+ },
382+ &mcp.ClientOptions{
383+ ToolListChangedHandler: func(context.Context, *mcp.ToolListChangedRequest) {
384+ mcpBroker.Publish(pubsub.UpdatedEvent, MCPEvent{
385+ Type: MCPEventToolsListChanged,
386+ Name: name,
387+ })
388+ },
389+ KeepAlive: time.Minute * 10,
390+ },
391+ )
406392
407− if err := c.Start(mcpCtx); err != nil {
393+ session, err := client.Connect(mcpCtx, transport, nil)
394+ if err != nil {
408395 updateMCPState(name, MCPStateError, maybeTimeoutErr(err, timeout), nil, 0)
409396 slog.Error("error starting mcp client", "error", err, "name", name)
410− _ = c.Close()
411− cancel()
412− return nil, err
413− }
414−
415− if _, err := c.Initialize(mcpCtx, mcpInitRequest); err != nil {
416− updateMCPState(name, MCPStateError, maybeTimeoutErr(err, timeout), nil, 0)
417− slog.Error("error initializing mcp client", "error", err, "name", name)
418− _ = c.Close()
419397 cancel()
420398 return nil, err
421399 }
422400
423401 cancelTimer.Stop()
424402 slog.Info("Initialized mcp client", "name", name)
425− return c, nil
403+ return session, nil
426404}
427405
428406func maybeTimeoutErr(err error, timeout time.Duration) error {
@@ -432,7 +410,7 @@ func maybeTimeoutErr(err error, timeout time.Duration) error {
432410 return err
433411}
434412
435−func createMcpClient(name string, m config.MCPConfig, resolver config.VariableResolver) (*client.Client, error) {
413+func createMCPTransport(ctx context.Context, m config.MCPConfig, resolver config.VariableResolver) (mcp.Transport, error) {
436414 switch m.Type {
437415 case config.MCPStdio:
438416 command, err := resolver.ResolveValue(m.Command)
@@ -442,44 +420,51 @@ func createMcpClient(name string, m config.MCPConfig, resolver config.VariableRe
442420 if strings.TrimSpace(command) == "" {
443421 return nil, fmt.Errorf("mcp stdio config requires a non-empty 'command' field")
444422 }
445− return client.NewStdioMCPClientWithOptions(
446− home.Long(command),
447− m.ResolvedEnv(),
448− m.Args,
449− transport.WithCommandLogger(mcpLogger{name: name}),
450− )
423+ cmd := exec.CommandContext(ctx, home.Long(command), m.Args...)
424+ cmd.Env = m.ResolvedEnv()
425+ return &mcp.CommandTransport{
426+ Command: cmd,
427+ }, nil
451428 case config.MCPHttp:
452429 if strings.TrimSpace(m.URL) == "" {
453430 return nil, fmt.Errorf("mcp http config requires a non-empty 'url' field")
454431 }
455− return client.NewStreamableHttpClient(
456− m.URL,
457− transport.WithHTTPHeaders(m.ResolvedHeaders()),
458− transport.WithHTTPLogger(mcpLogger{name: name}),
459− )
460− case config.MCPSse:
432+ client := &http.Client{
433+ Transport: &headerRoundTripper{
434+ headers: m.ResolvedHeaders(),
435+ },
436+ }
437+ return &mcp.StreamableClientTransport{
438+ Endpoint: m.URL,
439+ HTTPClient: client,
440+ }, nil
441+ case config.MCPSSE:
461442 if strings.TrimSpace(m.URL) == "" {
462443 return nil, fmt.Errorf("mcp sse config requires a non-empty 'url' field")
463444 }
464− return client.NewSSEMCPClient(
465− m.URL,
466− client.WithHeaders(m.ResolvedHeaders()),
467− transport.WithSSELogger(mcpLogger{name: name}),
468− )
445+ client := &http.Client{
446+ Transport: &headerRoundTripper{
447+ headers: m.ResolvedHeaders(),
448+ },
449+ }
450+ return &mcp.SSEClientTransport{
451+ Endpoint: m.URL,
452+ HTTPClient: client,
453+ }, nil
469454 default:
470455 return nil, fmt.Errorf("unsupported mcp type: %s", m.Type)
471456 }
472457}
473458
474−// for MCP's clients.
475−type mcpLogger struct{ name string }
476−
477−func (l mcpLogger) Errorf(format string, v ...any) {
478− slog.Error(fmt.Sprintf(format, v...), "name", l.name)
459+type headerRoundTripper struct {
460+ headers map[string]string
479461}
480462
481−func (l mcpLogger) Infof(format string, v ...any) {
482− slog.Info(fmt.Sprintf(format, v...), "name", l.name)
463+func (rt headerRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
464+ for k, v := range rt.headers {
465+ req.Header.Set(k, v)
466+ }
467+ return http.DefaultTransport.RoundTrip(req)
483468}
484469
485470func mcpTimeout(m config.MCPConfig) time.Duration {
internal/app/app.go+7−4
@@ -18,13 +18,13 @@ import (
1818 "github.com/charmbracelet/crush/internal/format"
1919 "github.com/charmbracelet/crush/internal/history"
2020 "github.com/charmbracelet/crush/internal/log"
21− "github.com/charmbracelet/crush/internal/pubsub"
22− "github.com/charmbracelet/fantasy/ai"
23−
2421 "github.com/charmbracelet/crush/internal/lsp"
2522 "github.com/charmbracelet/crush/internal/message"
2623 "github.com/charmbracelet/crush/internal/permission"
24+ "github.com/charmbracelet/crush/internal/pubsub"
2725 "github.com/charmbracelet/crush/internal/session"
26+ "github.com/charmbracelet/fantasy/ai"
27+ "github.com/charmbracelet/x/ansi"
2828)
2929
3030type App struct {
@@ -109,7 +109,6 @@ func (app *App) RunNonInteractive(ctx context.Context, prompt string, quiet bool
109109 ctx, cancel := context.WithCancel(ctx)
110110 defer cancel()
111111
112− // Start spinner if not in quiet mode.
113112 var spinner *format.Spinner
114113 if !quiet {
115114 spinner = format.NewSpinner(ctx, cancel, "Generating")
@@ -166,7 +165,11 @@ func (app *App) RunNonInteractive(ctx context.Context, prompt string, quiet bool
166165 messageEvents := app.Messages.Subscribe(ctx)
167166 messageReadBytes := make(map[string]int)
168167
168+ defer fmt.Printf(ansi.ResetProgressBar)
169169 for {
170+ // HACK: add it again on every iteration so it doesn't get hidden by
171+ // the terminal due to inactivity.
172+ fmt.Printf(ansi.SetIndeterminateProgressBar)
170173 select {
171174 case result := <-done:
172175 stopSpinner()
internal/cmd/root.go+2−1
@@ -3,6 +3,7 @@ package cmd
33import (
44 "bytes"
55 "context"
6+ "errors"
67 "fmt"
78 "io"
89 "log/slog"
@@ -93,7 +94,7 @@ crush -y
9394 if _, err := program.Run(); err != nil {
9495 event.Error(err)
9596 slog.Error("TUI run error", "error", err)
96− return fmt.Errorf("TUI error: %v", err)
97+ return errors.New("Crush crashed. If metrics are enabled, we were notified about it. If you'd like to report it, please copy the stacktrace above and open an issue at https://github.com/charmbracelet/crush/issues/new?template=bug.yml") //nolint:staticcheck
9798 }
9899 return nil
99100 },
internal/config/config.go+1−1
@@ -114,7 +114,7 @@ type MCPType string
114114
115115const (
116116 MCPStdio MCPType = "stdio"
117− MCPSse MCPType = "sse"
117+ MCPSSE MCPType = "sse"
118118 MCPHttp MCPType = "http"
119119)
120120
internal/fsext/ls.go+1−1
@@ -210,7 +210,7 @@ func ListDirectory(initialPath string, ignorePatterns []string, depth, limit int
210210 found := csync.NewSlice[string]()
211211 dl := NewDirectoryLister(initialPath)
212212
213− slog.Warn("listing directory", "path", initialPath, "depth", depth, "limit", limit, "ignorePatterns", ignorePatterns)
213+ slog.Debug("listing directory", "path", initialPath, "depth", depth, "limit", limit, "ignorePatterns", ignorePatterns)
214214
215215 conf := fastwalk.Config{
216216 Follow: true,
internal/tui/components/core/core.go+5−2
@@ -110,14 +110,17 @@ func Status(opts StatusOpts, width int) string {
110110 extraContentWidth += 1
111111 }
112112 description = ansi.Truncate(description, width-lipgloss.Width(icon)-lipgloss.Width(title)-2-extraContentWidth, "…")
113+ description = t.S().Base.Foreground(descriptionColor).Render(description)
113114 }
114− description = t.S().Base.Foreground(descriptionColor).Render(description)
115115
116116 content := []string{}
117117 if icon != "" {
118118 content = append(content, icon)
119119 }
120− content = append(content, title, description)
120+ content = append(content, title)
121+ if description != "" {
122+ content = append(content, description)
123+ }
121124 if opts.ExtraContent != "" {
122125 content = append(content, opts.ExtraContent)
123126 }
internal/tui/components/core/testdata/TestStatus/EmptyDescription.golden+1−1
@@ -1 +1 @@
1−● Title Only 
1+● Title Only
internal/tui/components/lsp/lsp.go+25−26
@@ -56,32 +56,7 @@ func RenderLSPList(lspClients *csync.Map[string, *lsp.Client], opts RenderOption
5656 break
5757 }
5858
59− // Determine icon color and description based on state
60− icon := t.ItemOfflineIcon
61− description := l.LSP.Command
62−
63− if l.LSP.Disabled {
64− description = t.S().Subtle.Render("disabled")
65− } else if state, exists := lspStates[l.Name]; exists {
66− switch state.State {
67− case lsp.StateStarting:
68− icon = t.ItemBusyIcon
69− description = t.S().Subtle.Render("starting...")
70− case lsp.StateReady:
71− icon = t.ItemOnlineIcon
72− description = l.LSP.Command
73− case lsp.StateError:
74− icon = t.ItemErrorIcon
75− if state.Error != nil {
76− description = t.S().Subtle.Render(fmt.Sprintf("error: %s", state.Error.Error()))
77− } else {
78− description = t.S().Subtle.Render("error")
79− }
80− case lsp.StateDisabled:
81− icon = t.ItemOfflineIcon.Foreground(t.FgMuted)
82− description = t.S().Base.Foreground(t.FgMuted).Render("no root markers found")
83− }
84− }
59+ icon, description := iconAndDescription(l, t, lspStates)
8560
8661 // Calculate diagnostic counts if we have LSP clients
8762 var extraContent string
@@ -134,6 +109,30 @@ func RenderLSPList(lspClients *csync.Map[string, *lsp.Client], opts RenderOption
134109 return lspList
135110}
136111
112+func iconAndDescription(l config.LSP, t *styles.Theme, states map[string]app.LSPClientInfo) (lipgloss.Style, string) {
113+ if l.LSP.Disabled {
114+ return t.ItemOfflineIcon.Foreground(t.FgMuted), t.S().Subtle.Render("disabled")
115+ }
116+
117+ info := states[l.Name]
118+ switch info.State {
119+ case lsp.StateStarting:
120+ return t.ItemBusyIcon, t.S().Subtle.Render("starting...")
121+ case lsp.StateReady:
122+ return t.ItemOnlineIcon, ""
123+ case lsp.StateError:
124+ description := t.S().Subtle.Render("error")
125+ if info.Error != nil {
126+ description = t.S().Subtle.Render(fmt.Sprintf("error: %s", info.Error.Error()))
127+ }
128+ return t.ItemErrorIcon, description
129+ case lsp.StateDisabled:
130+ return t.ItemOfflineIcon.Foreground(t.FgMuted), t.S().Subtle.Render("inactive")
131+ default:
132+ return t.ItemOfflineIcon, ""
133+ }
134+}
135+
137136// RenderLSPBlock renders a complete LSP block with optional truncation indicator.
138137func RenderLSPBlock(lspClients *csync.Map[string, *lsp.Client], opts RenderOptions, showTruncationIndicator bool) string {
139138 t := styles.CurrentTheme()
internal/tui/components/mcp/mcp.go+1−1
@@ -55,7 +55,7 @@ func RenderMCPList(opts RenderOptions) []string {
5555
5656 // Determine icon and color based on state
5757 icon := t.ItemOfflineIcon
58− description := l.MCP.Command
58+ description := ""
5959 extraContent := ""
6060
6161 if state, exists := mcpStates[l.Name]; exists {
internal/tui/tui.go+6
@@ -3,6 +3,7 @@ package tui
33import (
44 "context"
55 "fmt"
6+ "math/rand"
67 "strings"
78 "time"
89
@@ -572,6 +573,11 @@ func (a *appModel) View() tea.View {
572573
573574 view.Layer = canvas
574575 view.Cursor = cursor
576+ if a.app != nil && a.app.AgentCoordinator != nil && a.app.AgentCoordinator.IsBusy() {
577+ // HACK: use a random percentage to prevent ghostty from hiding it
578+ // after a timeout.
579+ view.ProgressBar = tea.NewProgressBar(tea.ProgressBarIndeterminate, rand.Intn(100))
580+ }
575581 return view
576582}
577583
main.go+2−11
@@ -3,23 +3,14 @@ package main
33import (
44 "log/slog"
55 "net/http"
6+ _ "net/http/pprof"
67 "os"
78
8− _ "net/http/pprof" // profiling
9−
10− _ "github.com/joho/godotenv/autoload" // automatically load .env files
11−
129 "github.com/charmbracelet/crush/internal/cmd"
13− "github.com/charmbracelet/crush/internal/event"
14− "github.com/charmbracelet/crush/internal/log"
10+ _ "github.com/joho/godotenv/autoload"
1511)
1612
1713func main() {
18− defer log.RecoverPanic("main", func() {
19− event.Flush()
20− slog.Error("Application terminated due to unhandled panic")
21− })
22−
2314 if os.Getenv("CRUSH_PROFILE") != "" {
2415 go func() {
2516 slog.Info("Serving pprof at localhost:6060")