on main help sign in
Merge branch 'main' into ui
d334355Ayman Bagabas
.github/workflows/build.yml+1−1
@@ -18,7 +18,7 @@ jobs:
18 - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
18 - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
19 with:
19 with:
20 persist-credentials: false
20 persist-credentials: false
21− - uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0
21+ - uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0
22 with:
22 with:
23 go-version-file: go.mod
23 go-version-file: go.mod
24 - run: go mod tidy
24 - run: go mod tidy
.github/workflows/schema-update.yml+1−1
@@ -14,7 +14,7 @@ jobs:
14 - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
14 - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
15 with:
15 with:
16 token: ${{ secrets.PERSONAL_ACCESS_TOKEN }}
16 token: ${{ secrets.PERSONAL_ACCESS_TOKEN }}
17− - uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0
17+ - uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0
18 with:
18 with:
19 go-version-file: go.mod
19 go-version-file: go.mod
20 - run: go run . schema > ./schema.json
20 - run: go run . schema > ./schema.json
.github/workflows/security.yml+6−6
@@ -30,11 +30,11 @@ jobs:
30 - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
30 - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
31 with:
31 with:
32 persist-credentials: false
32 persist-credentials: false
33− - uses: github/codeql-action/init@cf1bb45a277cb3c205638b2cd5c984db1c46a412 # v4.31.7
33+ - uses: github/codeql-action/init@cdefb33c0f6224e58673d9004f47f7cb3e328b89 # v4.31.10
34 with:
34 with:
35 languages: ${{ matrix.language }}
35 languages: ${{ matrix.language }}
36− - uses: github/codeql-action/autobuild@cf1bb45a277cb3c205638b2cd5c984db1c46a412 # v4.31.7
36+ - uses: github/codeql-action/autobuild@cdefb33c0f6224e58673d9004f47f7cb3e328b89 # v4.31.10
37− - uses: github/codeql-action/analyze@cf1bb45a277cb3c205638b2cd5c984db1c46a412 # v4.31.7
37+ - uses: github/codeql-action/analyze@cdefb33c0f6224e58673d9004f47f7cb3e328b89 # v4.31.10
38
38
39 grype:
39 grype:
40 runs-on: ubuntu-latest
40 runs-on: ubuntu-latest
@@ -46,13 +46,13 @@ jobs:
46 - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
46 - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
47 with:
47 with:
48 persist-credentials: false
48 persist-credentials: false
49− - uses: anchore/scan-action@40a61b52209e9d50e87917c5b901783d546b12d0 # v7.2.1
49+ - uses: anchore/scan-action@62b74fb7bb810d2c45b1865f47a77655621862a5 # v7.2.3
50 id: scan
50 id: scan
51 with:
51 with:
52 path: "."
52 path: "."
53 fail-build: true
53 fail-build: true
54 severity-cutoff: critical
54 severity-cutoff: critical
55− - uses: github/codeql-action/upload-sarif@cf1bb45a277cb3c205638b2cd5c984db1c46a412 # v4.31.7
55+ - uses: github/codeql-action/upload-sarif@cdefb33c0f6224e58673d9004f47f7cb3e328b89 # v4.31.10
56 with:
56 with:
57 sarif_file: ${{ steps.scan.outputs.sarif }}
57 sarif_file: ${{ steps.scan.outputs.sarif }}
58
58
@@ -73,7 +73,7 @@ jobs:
73 - name: Run govulncheck
73 - name: Run govulncheck
74 run: |
74 run: |
75 govulncheck -C . -format sarif ./... > results.sarif
75 govulncheck -C . -format sarif ./... > results.sarif
76− - uses: github/codeql-action/upload-sarif@cf1bb45a277cb3c205638b2cd5c984db1c46a412 # v4.31.7
76+ - uses: github/codeql-action/upload-sarif@cdefb33c0f6224e58673d9004f47f7cb3e328b89 # v4.31.10
77 with:
77 with:
78 sarif_file: results.sarif
78 sarif_file: results.sarif
79
79
internal/app/app.go+8−1
@@ -40,6 +40,13 @@ import (
40 "github.com/charmbracelet/x/term"
40 "github.com/charmbracelet/x/term"
41)
41)
42
42
43+// UpdateAvailableMsg is sent when a new version is available.
44+type UpdateAvailableMsg struct {
45+ CurrentVersion string
46+ LatestVersion string
47+ IsDevelopment bool
48+}
49+
43type App struct {
50type App struct {
44 Sessions session.Service
51 Sessions session.Service
45 Messages message.Service
52 Messages message.Service
@@ -452,7 +459,7 @@ func (app *App) checkForUpdates(ctx context.Context) {
452 if err != nil || !info.Available() {
459 if err != nil || !info.Available() {
453 return
460 return
454 }
461 }
455− app.events <- pubsub.UpdateAvailableMsg{
462+ app.events <- UpdateAvailableMsg{
456 CurrentVersion: info.Current,
463 CurrentVersion: info.Current,
457 LatestVersion: info.Latest,
464 LatestVersion: info.Latest,
458 IsDevelopment: info.IsDevelopment(),
465 IsDevelopment: info.IsDevelopment(),
internal/env/env.go+1−12
@@ -2,7 +2,6 @@ package env
2
2
3import (
3import (
4 "os"
4 "os"
5− "testing"
6)
5)
7
6
8type Env interface {
7type Env interface {
@@ -18,17 +17,10 @@ func (o *osEnv) Get(key string) string {
18}
17}
19
18
20func (o *osEnv) Env() []string {
19func (o *osEnv) Env() []string {
21− env := os.Environ()
20+ return os.Environ()
22− if len(env) == 0 {
23− return nil
24− }
25− return env
26}
21}
27
22
28func New() Env {
23func New() Env {
29− if testing.Testing() {
30− return NewFromMap(nil)
31− }
32 return &osEnv{}
24 return &osEnv{}
33}
25}
34
26
@@ -46,9 +38,6 @@ func (m *mapEnv) Get(key string) string {
46
38
47// Env implements Env.
39// Env implements Env.
48func (m *mapEnv) Env() []string {
40func (m *mapEnv) Env() []string {
49− if len(m.m) == 0 {
50− return nil
51− }
52 env := make([]string, 0, len(m.m))
41 env := make([]string, 0, len(m.m))
53 for k, v := range m.m {
42 for k, v := range m.m {
54 env = append(env, k+"="+v)
43 env = append(env, k+"="+v)
internal/env/env_test.go+4−2
@@ -90,13 +90,15 @@ func TestMapEnv_Env(t *testing.T) {
90 t.Run("empty map", func(t *testing.T) {
90 t.Run("empty map", func(t *testing.T) {
91 env := NewFromMap(map[string]string{})
91 env := NewFromMap(map[string]string{})
92 envVars := env.Env()
92 envVars := env.Env()
93+ require.NotNil(t, envVars)
93− require.Nil(t, envVars)
94+ require.Len(t, envVars, 0)
94 })
95 })
95
96
96 t.Run("nil map", func(t *testing.T) {
97 t.Run("nil map", func(t *testing.T) {
97 env := NewFromMap(nil)
98 env := NewFromMap(nil)
98 envVars := env.Env()
99 envVars := env.Env()
100+ require.NotNil(t, envVars)
99− require.Nil(t, envVars)
101+ require.Len(t, envVars, 0)
100 })
102 })
101}
103}
102
104
internal/lsp/client.go+1−1
@@ -345,7 +345,7 @@ func (c *Client) CloseAllFiles(ctx context.Context) {
345 slog.Debug("Closing file", "file", uri)
345 slog.Debug("Closing file", "file", uri)
346 }
346 }
347 if err := c.client.NotifyDidCloseTextDocument(ctx, uri); err != nil {
347 if err := c.client.NotifyDidCloseTextDocument(ctx, uri); err != nil {
348− slog.Warn("Error closing rile", "uri", uri, "error", err)
348+ slog.Warn("Error closing file", "uri", uri, "error", err)
349 continue
349 continue
350 }
350 }
351 c.openFiles.Del(uri)
351 c.openFiles.Del(uri)
internal/message/message.go+5−5
@@ -63,7 +63,7 @@ func (s *service) Create(ctx context.Context, sessionID string, params CreateMes
63 Reason: "stop",
63 Reason: "stop",
64 })
64 })
65 }
65 }
66− partsJSON, err := marshallParts(params.Parts)
66+ partsJSON, err := marshalParts(params.Parts)
67 if err != nil {
67 if err != nil {
68 return Message{}, err
68 return Message{}, err
69 }
69 }
@@ -110,7 +110,7 @@ func (s *service) DeleteSessionMessages(ctx context.Context, sessionID string) e
110}
110}
111
111
112func (s *service) Update(ctx context.Context, message Message) error {
112func (s *service) Update(ctx context.Context, message Message) error {
113− parts, err := marshallParts(message.Parts)
113+ parts, err := marshalParts(message.Parts)
114 if err != nil {
114 if err != nil {
115 return err
115 return err
116 }
116 }
@@ -158,7 +158,7 @@ func (s *service) List(ctx context.Context, sessionID string) ([]Message, error)
158}
158}
159
159
160func (s *service) fromDBItem(item db.Message) (Message, error) {
160func (s *service) fromDBItem(item db.Message) (Message, error) {
161− parts, err := unmarshallParts([]byte(item.Parts))
161+ parts, err := unmarshalParts([]byte(item.Parts))
162 if err != nil {
162 if err != nil {
163 return Message{}, err
163 return Message{}, err
164 }
164 }
@@ -192,7 +192,7 @@ type partWrapper struct {
192 Data ContentPart `json:"data"`
192 Data ContentPart `json:"data"`
193}
193}
194
194
195−func marshallParts(parts []ContentPart) ([]byte, error) {
195+func marshalParts(parts []ContentPart) ([]byte, error) {
196 wrappedParts := make([]partWrapper, len(parts))
196 wrappedParts := make([]partWrapper, len(parts))
197
197
198 for i, part := range parts {
198 for i, part := range parts {
@@ -225,7 +225,7 @@ func marshallParts(parts []ContentPart) ([]byte, error) {
225 return json.Marshal(wrappedParts)
225 return json.Marshal(wrappedParts)
226}
226}
227
227
228−func unmarshallParts(data []byte) ([]ContentPart, error) {
228+func unmarshalParts(data []byte) ([]ContentPart, error) {
229 temp := []json.RawMessage{}
229 temp := []json.RawMessage{}
230
230
231 if err := json.Unmarshal(data, &temp); err != nil {
231 if err := json.Unmarshal(data, &temp); err != nil {
internal/pubsub/broker.go+1−3
@@ -20,13 +20,11 @@ func NewBroker[T any]() *Broker[T] {
20}
20}
21
21
22func NewBrokerWithOptions[T any](channelBufferSize, maxEvents int) *Broker[T] {
22func NewBrokerWithOptions[T any](channelBufferSize, maxEvents int) *Broker[T] {
23− b := &Broker[T]{
23+ return &Broker[T]{
24 subs: make(map[chan Event[T]]struct{}),
24 subs: make(map[chan Event[T]]struct{}),
25 done: make(chan struct{}),
25 done: make(chan struct{}),
26− subCount: 0,
27 maxEvents: maxEvents,
26 maxEvents: maxEvents,
28 }
27 }
29− return b
30}
28}
31
29
32func (b *Broker[T]) Shutdown() {
30func (b *Broker[T]) Shutdown() {
internal/pubsub/events.go−7
@@ -26,10 +26,3 @@ type (
26 Publish(EventType, T)
26 Publish(EventType, T)
27 }
27 }
28)
28)
29−
30−// UpdateAvailableMsg is sent when a new version is available.
31−type UpdateAvailableMsg struct {
32− CurrentVersion string
33− LatestVersion string
34− IsDevelopment bool
35−}
internal/tui/tui.go+1−1
@@ -385,7 +385,7 @@ func (a *appModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
385 }
385 }
386 return a, tea.Batch(cmds...)
386 return a, tea.Batch(cmds...)
387 // Update Available
387 // Update Available
388− case pubsub.UpdateAvailableMsg:
388+ case app.UpdateAvailableMsg:
389 // Show update notification in status bar
389 // Show update notification in status bar
390 statusMsg := fmt.Sprintf("Crush update available: v%s → v%s.", msg.CurrentVersion, msg.LatestVersion)
390 statusMsg := fmt.Sprintf("Crush update available: v%s → v%s.", msg.CurrentVersion, msg.LatestVersion)
391 if msg.IsDevelopment {
391 if msg.IsDevelopment {