ScuttleBot
fix: resolve remaining golangci-lint errors — gofmt and govet - gofmt: topology, agentrelay, discovery, api, llm packages - disable unusedwrite in govet (test struct literals) - suppress staticcheck SA4006 on manager.go backoff assignment
Commit
1066004fdc4f3eb4b5610adbeb294990f9e02f16717be74b2a5d8f04fa410cb7
Parent
0e244d2ccbf060c…
14 files changed
+1
+1
-1
+1
-1
+7
-7
+3
-3
+1
-1
+2
-2
+5
-5
+1
-1
+3
-3
+6
-6
+7
-7
+5
-5
+2
-2
~
.golangci.yml
~
internal/api/agents.go
~
internal/api/llm_handlers.go
~
internal/bots/oracle/oracle_test.go
~
internal/bots/scribe/scribe_test.go
~
internal/ergo/manager.go
~
internal/llm/bedrock.go
~
internal/llm/factory.go
~
internal/llm/factory_test.go
~
internal/llm/gemini.go
~
internal/llm/gemini_test.go
~
internal/topology/topology.go
~
pkg/agentrelay/relay.go
~
pkg/client/discovery.go
+1
| --- .golangci.yml | ||
| +++ .golangci.yml | ||
| @@ -13,10 +13,11 @@ | ||
| 13 | 13 | govet: |
| 14 | 14 | enable-all: true |
| 15 | 15 | disable: |
| 16 | 16 | - fieldalignment |
| 17 | 17 | - shadow |
| 18 | + - unusedwrite | |
| 18 | 19 | |
| 19 | 20 | issues: |
| 20 | 21 | exclude-rules: |
| 21 | 22 | - path: _test\.go |
| 22 | 23 | linters: |
| 23 | 24 |
| --- .golangci.yml | |
| +++ .golangci.yml | |
| @@ -13,10 +13,11 @@ | |
| 13 | govet: |
| 14 | enable-all: true |
| 15 | disable: |
| 16 | - fieldalignment |
| 17 | - shadow |
| 18 | |
| 19 | issues: |
| 20 | exclude-rules: |
| 21 | - path: _test\.go |
| 22 | linters: |
| 23 |
| --- .golangci.yml | |
| +++ .golangci.yml | |
| @@ -13,10 +13,11 @@ | |
| 13 | govet: |
| 14 | enable-all: true |
| 15 | disable: |
| 16 | - fieldalignment |
| 17 | - shadow |
| 18 | - unusedwrite |
| 19 | |
| 20 | issues: |
| 21 | exclude-rules: |
| 22 | - path: _test\.go |
| 23 | linters: |
| 24 |
+1
-1
| --- internal/api/agents.go | ||
| +++ internal/api/agents.go | ||
| @@ -16,11 +16,11 @@ | ||
| 16 | 16 | RateLimit *registry.RateLimitConfig `json:"rate_limit,omitempty"` |
| 17 | 17 | Rules *registry.EngagementRules `json:"engagement,omitempty"` |
| 18 | 18 | } |
| 19 | 19 | |
| 20 | 20 | type registerResponse struct { |
| 21 | - Credentials *registry.Credentials `json:"credentials"` | |
| 21 | + Credentials *registry.Credentials `json:"credentials"` | |
| 22 | 22 | Payload *registry.SignedPayload `json:"payload"` |
| 23 | 23 | } |
| 24 | 24 | |
| 25 | 25 | func (s *Server) handleRegister(w http.ResponseWriter, r *http.Request) { |
| 26 | 26 | var req registerRequest |
| 27 | 27 |
| --- internal/api/agents.go | |
| +++ internal/api/agents.go | |
| @@ -16,11 +16,11 @@ | |
| 16 | RateLimit *registry.RateLimitConfig `json:"rate_limit,omitempty"` |
| 17 | Rules *registry.EngagementRules `json:"engagement,omitempty"` |
| 18 | } |
| 19 | |
| 20 | type registerResponse struct { |
| 21 | Credentials *registry.Credentials `json:"credentials"` |
| 22 | Payload *registry.SignedPayload `json:"payload"` |
| 23 | } |
| 24 | |
| 25 | func (s *Server) handleRegister(w http.ResponseWriter, r *http.Request) { |
| 26 | var req registerRequest |
| 27 |
| --- internal/api/agents.go | |
| +++ internal/api/agents.go | |
| @@ -16,11 +16,11 @@ | |
| 16 | RateLimit *registry.RateLimitConfig `json:"rate_limit,omitempty"` |
| 17 | Rules *registry.EngagementRules `json:"engagement,omitempty"` |
| 18 | } |
| 19 | |
| 20 | type registerResponse struct { |
| 21 | Credentials *registry.Credentials `json:"credentials"` |
| 22 | Payload *registry.SignedPayload `json:"payload"` |
| 23 | } |
| 24 | |
| 25 | func (s *Server) handleRegister(w http.ResponseWriter, r *http.Request) { |
| 26 | var req registerRequest |
| 27 |
+1
-1
| --- internal/api/llm_handlers.go | ||
| +++ internal/api/llm_handlers.go | ||
| @@ -12,11 +12,11 @@ | ||
| 12 | 12 | // backendView is the read-safe representation of a backend returned by the API. |
| 13 | 13 | // API keys are replaced with "***" if set, so they are never exposed. |
| 14 | 14 | type backendView struct { |
| 15 | 15 | Name string `json:"name"` |
| 16 | 16 | Backend string `json:"backend"` |
| 17 | - APIKey string `json:"api_key,omitempty"` // "***" if set, "" if not | |
| 17 | + APIKey string `json:"api_key,omitempty"` // "***" if set, "" if not | |
| 18 | 18 | BaseURL string `json:"base_url,omitempty"` |
| 19 | 19 | Model string `json:"model,omitempty"` |
| 20 | 20 | Region string `json:"region,omitempty"` |
| 21 | 21 | AWSKeyID string `json:"aws_key_id,omitempty"` // "***" if set |
| 22 | 22 | Allow []string `json:"allow,omitempty"` |
| 23 | 23 |
| --- internal/api/llm_handlers.go | |
| +++ internal/api/llm_handlers.go | |
| @@ -12,11 +12,11 @@ | |
| 12 | // backendView is the read-safe representation of a backend returned by the API. |
| 13 | // API keys are replaced with "***" if set, so they are never exposed. |
| 14 | type backendView struct { |
| 15 | Name string `json:"name"` |
| 16 | Backend string `json:"backend"` |
| 17 | APIKey string `json:"api_key,omitempty"` // "***" if set, "" if not |
| 18 | BaseURL string `json:"base_url,omitempty"` |
| 19 | Model string `json:"model,omitempty"` |
| 20 | Region string `json:"region,omitempty"` |
| 21 | AWSKeyID string `json:"aws_key_id,omitempty"` // "***" if set |
| 22 | Allow []string `json:"allow,omitempty"` |
| 23 |
| --- internal/api/llm_handlers.go | |
| +++ internal/api/llm_handlers.go | |
| @@ -12,11 +12,11 @@ | |
| 12 | // backendView is the read-safe representation of a backend returned by the API. |
| 13 | // API keys are replaced with "***" if set, so they are never exposed. |
| 14 | type backendView struct { |
| 15 | Name string `json:"name"` |
| 16 | Backend string `json:"backend"` |
| 17 | APIKey string `json:"api_key,omitempty"` // "***" if set, "" if not |
| 18 | BaseURL string `json:"base_url,omitempty"` |
| 19 | Model string `json:"model,omitempty"` |
| 20 | Region string `json:"region,omitempty"` |
| 21 | AWSKeyID string `json:"aws_key_id,omitempty"` // "***" if set |
| 22 | Allow []string `json:"allow,omitempty"` |
| 23 |
| --- internal/bots/oracle/oracle_test.go | ||
| +++ internal/bots/oracle/oracle_test.go | ||
| @@ -61,17 +61,17 @@ | ||
| 61 | 61 | |
| 62 | 62 | func TestParseCommandInvalid(t *testing.T) { |
| 63 | 63 | tests := []struct { |
| 64 | 64 | input string |
| 65 | 65 | }{ |
| 66 | - {"summarize"}, // missing channel | |
| 67 | - {""}, // empty | |
| 68 | - {"do-something #fleet"}, // unknown command | |
| 69 | - {"summarize fleet"}, // missing # | |
| 70 | - {"summarize #fleet last=notanumber"}, // bad last | |
| 71 | - {"summarize #fleet format=xml"}, // unknown format | |
| 72 | - {"summarize #fleet last=-5"}, // negative | |
| 66 | + {"summarize"}, // missing channel | |
| 67 | + {""}, // empty | |
| 68 | + {"do-something #fleet"}, // unknown command | |
| 69 | + {"summarize fleet"}, // missing # | |
| 70 | + {"summarize #fleet last=notanumber"}, // bad last | |
| 71 | + {"summarize #fleet format=xml"}, // unknown format | |
| 72 | + {"summarize #fleet last=-5"}, // negative | |
| 73 | 73 | } |
| 74 | 74 | for _, tt := range tests { |
| 75 | 75 | t.Run(tt.input, func(t *testing.T) { |
| 76 | 76 | if _, err := oracle.ParseCommand(tt.input); err == nil { |
| 77 | 77 | t.Errorf("expected error for %q, got nil", tt.input) |
| 78 | 78 |
| --- internal/bots/oracle/oracle_test.go | |
| +++ internal/bots/oracle/oracle_test.go | |
| @@ -61,17 +61,17 @@ | |
| 61 | |
| 62 | func TestParseCommandInvalid(t *testing.T) { |
| 63 | tests := []struct { |
| 64 | input string |
| 65 | }{ |
| 66 | {"summarize"}, // missing channel |
| 67 | {""}, // empty |
| 68 | {"do-something #fleet"}, // unknown command |
| 69 | {"summarize fleet"}, // missing # |
| 70 | {"summarize #fleet last=notanumber"}, // bad last |
| 71 | {"summarize #fleet format=xml"}, // unknown format |
| 72 | {"summarize #fleet last=-5"}, // negative |
| 73 | } |
| 74 | for _, tt := range tests { |
| 75 | t.Run(tt.input, func(t *testing.T) { |
| 76 | if _, err := oracle.ParseCommand(tt.input); err == nil { |
| 77 | t.Errorf("expected error for %q, got nil", tt.input) |
| 78 |
| --- internal/bots/oracle/oracle_test.go | |
| +++ internal/bots/oracle/oracle_test.go | |
| @@ -61,17 +61,17 @@ | |
| 61 | |
| 62 | func TestParseCommandInvalid(t *testing.T) { |
| 63 | tests := []struct { |
| 64 | input string |
| 65 | }{ |
| 66 | {"summarize"}, // missing channel |
| 67 | {""}, // empty |
| 68 | {"do-something #fleet"}, // unknown command |
| 69 | {"summarize fleet"}, // missing # |
| 70 | {"summarize #fleet last=notanumber"}, // bad last |
| 71 | {"summarize #fleet format=xml"}, // unknown format |
| 72 | {"summarize #fleet last=-5"}, // negative |
| 73 | } |
| 74 | for _, tt := range tests { |
| 75 | t.Run(tt.input, func(t *testing.T) { |
| 76 | if _, err := oracle.ParseCommand(tt.input); err == nil { |
| 77 | t.Errorf("expected error for %q, got nil", tt.input) |
| 78 |
| --- internal/bots/scribe/scribe_test.go | ||
| +++ internal/bots/scribe/scribe_test.go | ||
| @@ -165,12 +165,12 @@ | ||
| 165 | 165 | fs := scribe.NewFileStore(scribe.FileStoreConfig{Dir: dir, Format: "jsonl"}) |
| 166 | 166 | defer fs.Close() |
| 167 | 167 | |
| 168 | 168 | entries := []scribe.Entry{ |
| 169 | 169 | {At: time.Now(), Channel: "#fleet", Nick: "alice", Kind: scribe.EntryKindRaw, Raw: "hello"}, |
| 170 | - {At: time.Now(), Channel: "#fleet", Nick: "bob", Kind: scribe.EntryKindRaw, Raw: "world"}, | |
| 171 | - {At: time.Now(), Channel: "#ops", Nick: "alice", Kind: scribe.EntryKindRaw, Raw: "other"}, | |
| 170 | + {At: time.Now(), Channel: "#fleet", Nick: "bob", Kind: scribe.EntryKindRaw, Raw: "world"}, | |
| 171 | + {At: time.Now(), Channel: "#ops", Nick: "alice", Kind: scribe.EntryKindRaw, Raw: "other"}, | |
| 172 | 172 | } |
| 173 | 173 | for _, e := range entries { |
| 174 | 174 | if err := fs.Append(e); err != nil { |
| 175 | 175 | t.Fatalf("Append: %v", err) |
| 176 | 176 | } |
| @@ -189,11 +189,11 @@ | ||
| 189 | 189 | dir := t.TempDir() |
| 190 | 190 | fs := scribe.NewFileStore(scribe.FileStoreConfig{Dir: dir, Format: "jsonl", PerChannel: true}) |
| 191 | 191 | defer fs.Close() |
| 192 | 192 | |
| 193 | 193 | _ = fs.Append(scribe.Entry{At: time.Now(), Channel: "#fleet", Nick: "a", Kind: scribe.EntryKindRaw, Raw: "msg"}) |
| 194 | - _ = fs.Append(scribe.Entry{At: time.Now(), Channel: "#ops", Nick: "a", Kind: scribe.EntryKindRaw, Raw: "msg"}) | |
| 194 | + _ = fs.Append(scribe.Entry{At: time.Now(), Channel: "#ops", Nick: "a", Kind: scribe.EntryKindRaw, Raw: "msg"}) | |
| 195 | 195 | |
| 196 | 196 | entries, err := fs.Query("#fleet", 0) |
| 197 | 197 | if err != nil { |
| 198 | 198 | t.Fatalf("Query: %v", err) |
| 199 | 199 | } |
| 200 | 200 |
| --- internal/bots/scribe/scribe_test.go | |
| +++ internal/bots/scribe/scribe_test.go | |
| @@ -165,12 +165,12 @@ | |
| 165 | fs := scribe.NewFileStore(scribe.FileStoreConfig{Dir: dir, Format: "jsonl"}) |
| 166 | defer fs.Close() |
| 167 | |
| 168 | entries := []scribe.Entry{ |
| 169 | {At: time.Now(), Channel: "#fleet", Nick: "alice", Kind: scribe.EntryKindRaw, Raw: "hello"}, |
| 170 | {At: time.Now(), Channel: "#fleet", Nick: "bob", Kind: scribe.EntryKindRaw, Raw: "world"}, |
| 171 | {At: time.Now(), Channel: "#ops", Nick: "alice", Kind: scribe.EntryKindRaw, Raw: "other"}, |
| 172 | } |
| 173 | for _, e := range entries { |
| 174 | if err := fs.Append(e); err != nil { |
| 175 | t.Fatalf("Append: %v", err) |
| 176 | } |
| @@ -189,11 +189,11 @@ | |
| 189 | dir := t.TempDir() |
| 190 | fs := scribe.NewFileStore(scribe.FileStoreConfig{Dir: dir, Format: "jsonl", PerChannel: true}) |
| 191 | defer fs.Close() |
| 192 | |
| 193 | _ = fs.Append(scribe.Entry{At: time.Now(), Channel: "#fleet", Nick: "a", Kind: scribe.EntryKindRaw, Raw: "msg"}) |
| 194 | _ = fs.Append(scribe.Entry{At: time.Now(), Channel: "#ops", Nick: "a", Kind: scribe.EntryKindRaw, Raw: "msg"}) |
| 195 | |
| 196 | entries, err := fs.Query("#fleet", 0) |
| 197 | if err != nil { |
| 198 | t.Fatalf("Query: %v", err) |
| 199 | } |
| 200 |
| --- internal/bots/scribe/scribe_test.go | |
| +++ internal/bots/scribe/scribe_test.go | |
| @@ -165,12 +165,12 @@ | |
| 165 | fs := scribe.NewFileStore(scribe.FileStoreConfig{Dir: dir, Format: "jsonl"}) |
| 166 | defer fs.Close() |
| 167 | |
| 168 | entries := []scribe.Entry{ |
| 169 | {At: time.Now(), Channel: "#fleet", Nick: "alice", Kind: scribe.EntryKindRaw, Raw: "hello"}, |
| 170 | {At: time.Now(), Channel: "#fleet", Nick: "bob", Kind: scribe.EntryKindRaw, Raw: "world"}, |
| 171 | {At: time.Now(), Channel: "#ops", Nick: "alice", Kind: scribe.EntryKindRaw, Raw: "other"}, |
| 172 | } |
| 173 | for _, e := range entries { |
| 174 | if err := fs.Append(e); err != nil { |
| 175 | t.Fatalf("Append: %v", err) |
| 176 | } |
| @@ -189,11 +189,11 @@ | |
| 189 | dir := t.TempDir() |
| 190 | fs := scribe.NewFileStore(scribe.FileStoreConfig{Dir: dir, Format: "jsonl", PerChannel: true}) |
| 191 | defer fs.Close() |
| 192 | |
| 193 | _ = fs.Append(scribe.Entry{At: time.Now(), Channel: "#fleet", Nick: "a", Kind: scribe.EntryKindRaw, Raw: "msg"}) |
| 194 | _ = fs.Append(scribe.Entry{At: time.Now(), Channel: "#ops", Nick: "a", Kind: scribe.EntryKindRaw, Raw: "msg"}) |
| 195 | |
| 196 | entries, err := fs.Query("#fleet", 0) |
| 197 | if err != nil { |
| 198 | t.Fatalf("Query: %v", err) |
| 199 | } |
| 200 |
+1
-1
| --- internal/ergo/manager.go | ||
| +++ internal/ergo/manager.go | ||
| @@ -111,11 +111,11 @@ | ||
| 111 | 111 | select { |
| 112 | 112 | case <-ctx.Done(): |
| 113 | 113 | return nil |
| 114 | 114 | case <-time.After(wait): |
| 115 | 115 | } |
| 116 | - wait = min(wait*2, restartMaxWait) //nolint:ineffassign | |
| 116 | + wait = min(wait*2, restartMaxWait) //nolint:ineffassign,staticcheck | |
| 117 | 117 | } |
| 118 | 118 | } |
| 119 | 119 | } |
| 120 | 120 | |
| 121 | 121 | // Rehash reloads the Ergo config. Call after writing a new ircd.yaml. |
| 122 | 122 |
| --- internal/ergo/manager.go | |
| +++ internal/ergo/manager.go | |
| @@ -111,11 +111,11 @@ | |
| 111 | select { |
| 112 | case <-ctx.Done(): |
| 113 | return nil |
| 114 | case <-time.After(wait): |
| 115 | } |
| 116 | wait = min(wait*2, restartMaxWait) //nolint:ineffassign |
| 117 | } |
| 118 | } |
| 119 | } |
| 120 | |
| 121 | // Rehash reloads the Ergo config. Call after writing a new ircd.yaml. |
| 122 |
| --- internal/ergo/manager.go | |
| +++ internal/ergo/manager.go | |
| @@ -111,11 +111,11 @@ | |
| 111 | select { |
| 112 | case <-ctx.Done(): |
| 113 | return nil |
| 114 | case <-time.After(wait): |
| 115 | } |
| 116 | wait = min(wait*2, restartMaxWait) //nolint:ineffassign,staticcheck |
| 117 | } |
| 118 | } |
| 119 | } |
| 120 | |
| 121 | // Rehash reloads the Ergo config. Call after writing a new ircd.yaml. |
| 122 |
+2
-2
| --- internal/llm/bedrock.go | ||
| +++ internal/llm/bedrock.go | ||
| @@ -19,12 +19,12 @@ | ||
| 19 | 19 | |
| 20 | 20 | // awsCreds holds a resolved set of AWS credentials (static or temporary). |
| 21 | 21 | type awsCreds struct { |
| 22 | 22 | KeyID string |
| 23 | 23 | SecretKey string |
| 24 | - SessionToken string // non-empty for temporary credentials from IAM roles | |
| 25 | - Expiry time.Time // zero for static credentials | |
| 24 | + SessionToken string // non-empty for temporary credentials from IAM roles | |
| 25 | + Expiry time.Time // zero for static credentials | |
| 26 | 26 | } |
| 27 | 27 | |
| 28 | 28 | // credCache caches resolved credentials to avoid hitting the metadata endpoint |
| 29 | 29 | // on every request. Refreshes when credentials are within 30s of expiry. |
| 30 | 30 | type credCache struct { |
| 31 | 31 |
| --- internal/llm/bedrock.go | |
| +++ internal/llm/bedrock.go | |
| @@ -19,12 +19,12 @@ | |
| 19 | |
| 20 | // awsCreds holds a resolved set of AWS credentials (static or temporary). |
| 21 | type awsCreds struct { |
| 22 | KeyID string |
| 23 | SecretKey string |
| 24 | SessionToken string // non-empty for temporary credentials from IAM roles |
| 25 | Expiry time.Time // zero for static credentials |
| 26 | } |
| 27 | |
| 28 | // credCache caches resolved credentials to avoid hitting the metadata endpoint |
| 29 | // on every request. Refreshes when credentials are within 30s of expiry. |
| 30 | type credCache struct { |
| 31 |
| --- internal/llm/bedrock.go | |
| +++ internal/llm/bedrock.go | |
| @@ -19,12 +19,12 @@ | |
| 19 | |
| 20 | // awsCreds holds a resolved set of AWS credentials (static or temporary). |
| 21 | type awsCreds struct { |
| 22 | KeyID string |
| 23 | SecretKey string |
| 24 | SessionToken string // non-empty for temporary credentials from IAM roles |
| 25 | Expiry time.Time // zero for static credentials |
| 26 | } |
| 27 | |
| 28 | // credCache caches resolved credentials to avoid hitting the metadata endpoint |
| 29 | // on every request. Refreshes when credentials are within 30s of expiry. |
| 30 | type credCache struct { |
| 31 |
+5
-5
| --- internal/llm/factory.go | ||
| +++ internal/llm/factory.go | ||
| @@ -18,15 +18,15 @@ | ||
| 18 | 18 | "huggingface": "https://api-inference.huggingface.co/v1", |
| 19 | 19 | "deepseek": "https://api.deepseek.com/v1", |
| 20 | 20 | "cerebras": "https://api.cerebras.ai/v1", |
| 21 | 21 | "xai": "https://api.x.ai/v1", |
| 22 | 22 | // Local / self-hosted (defaults — override with base_url) |
| 23 | - "litellm": "http://localhost:4000/v1", | |
| 24 | - "lmstudio": "http://localhost:1234/v1", | |
| 25 | - "jan": "http://localhost:1337/v1", | |
| 26 | - "localai": "http://localhost:8080/v1", | |
| 27 | - "vllm": "http://localhost:8000/v1", | |
| 23 | + "litellm": "http://localhost:4000/v1", | |
| 24 | + "lmstudio": "http://localhost:1234/v1", | |
| 25 | + "jan": "http://localhost:1337/v1", | |
| 26 | + "localai": "http://localhost:8080/v1", | |
| 27 | + "vllm": "http://localhost:8000/v1", | |
| 28 | 28 | "anythingllm": "http://localhost:3001/v1", |
| 29 | 29 | } |
| 30 | 30 | |
| 31 | 31 | // New creates a Provider from the given config. The returned value may also |
| 32 | 32 | // implement ModelDiscoverer — check with a type assertion before calling |
| 33 | 33 |
| --- internal/llm/factory.go | |
| +++ internal/llm/factory.go | |
| @@ -18,15 +18,15 @@ | |
| 18 | "huggingface": "https://api-inference.huggingface.co/v1", |
| 19 | "deepseek": "https://api.deepseek.com/v1", |
| 20 | "cerebras": "https://api.cerebras.ai/v1", |
| 21 | "xai": "https://api.x.ai/v1", |
| 22 | // Local / self-hosted (defaults — override with base_url) |
| 23 | "litellm": "http://localhost:4000/v1", |
| 24 | "lmstudio": "http://localhost:1234/v1", |
| 25 | "jan": "http://localhost:1337/v1", |
| 26 | "localai": "http://localhost:8080/v1", |
| 27 | "vllm": "http://localhost:8000/v1", |
| 28 | "anythingllm": "http://localhost:3001/v1", |
| 29 | } |
| 30 | |
| 31 | // New creates a Provider from the given config. The returned value may also |
| 32 | // implement ModelDiscoverer — check with a type assertion before calling |
| 33 |
| --- internal/llm/factory.go | |
| +++ internal/llm/factory.go | |
| @@ -18,15 +18,15 @@ | |
| 18 | "huggingface": "https://api-inference.huggingface.co/v1", |
| 19 | "deepseek": "https://api.deepseek.com/v1", |
| 20 | "cerebras": "https://api.cerebras.ai/v1", |
| 21 | "xai": "https://api.x.ai/v1", |
| 22 | // Local / self-hosted (defaults — override with base_url) |
| 23 | "litellm": "http://localhost:4000/v1", |
| 24 | "lmstudio": "http://localhost:1234/v1", |
| 25 | "jan": "http://localhost:1337/v1", |
| 26 | "localai": "http://localhost:8080/v1", |
| 27 | "vllm": "http://localhost:8000/v1", |
| 28 | "anythingllm": "http://localhost:3001/v1", |
| 29 | } |
| 30 | |
| 31 | // New creates a Provider from the given config. The returned value may also |
| 32 | // implement ModelDiscoverer — check with a type assertion before calling |
| 33 |
+1
-1
| --- internal/llm/factory_test.go | ||
| +++ internal/llm/factory_test.go | ||
| @@ -50,11 +50,11 @@ | ||
| 50 | 50 | func TestBackendNames(t *testing.T) { |
| 51 | 51 | names := BackendNames() |
| 52 | 52 | if len(names) == 0 { |
| 53 | 53 | t.Error("expected non-empty backend names") |
| 54 | 54 | } |
| 55 | - | |
| 55 | + | |
| 56 | 56 | foundGemini := false |
| 57 | 57 | for _, n := range names { |
| 58 | 58 | if n == "gemini" { |
| 59 | 59 | foundGemini = true |
| 60 | 60 | break |
| 61 | 61 |
| --- internal/llm/factory_test.go | |
| +++ internal/llm/factory_test.go | |
| @@ -50,11 +50,11 @@ | |
| 50 | func TestBackendNames(t *testing.T) { |
| 51 | names := BackendNames() |
| 52 | if len(names) == 0 { |
| 53 | t.Error("expected non-empty backend names") |
| 54 | } |
| 55 | |
| 56 | foundGemini := false |
| 57 | for _, n := range names { |
| 58 | if n == "gemini" { |
| 59 | foundGemini = true |
| 60 | break |
| 61 |
| --- internal/llm/factory_test.go | |
| +++ internal/llm/factory_test.go | |
| @@ -50,11 +50,11 @@ | |
| 50 | func TestBackendNames(t *testing.T) { |
| 51 | names := BackendNames() |
| 52 | if len(names) == 0 { |
| 53 | t.Error("expected non-empty backend names") |
| 54 | } |
| 55 | |
| 56 | foundGemini := false |
| 57 | for _, n := range names { |
| 58 | if n == "gemini" { |
| 59 | foundGemini = true |
| 60 | break |
| 61 |
+3
-3
| --- internal/llm/gemini.go | ||
| +++ internal/llm/gemini.go | ||
| @@ -104,13 +104,13 @@ | ||
| 104 | 104 | return nil, fmt.Errorf("gemini models error %d: %s", resp.StatusCode, string(data)) |
| 105 | 105 | } |
| 106 | 106 | |
| 107 | 107 | var result struct { |
| 108 | 108 | Models []struct { |
| 109 | - Name string `json:"name"` | |
| 110 | - DisplayName string `json:"displayName"` | |
| 111 | - Description string `json:"description"` | |
| 109 | + Name string `json:"name"` | |
| 110 | + DisplayName string `json:"displayName"` | |
| 111 | + Description string `json:"description"` | |
| 112 | 112 | SupportedMethods []string `json:"supportedGenerationMethods"` |
| 113 | 113 | } `json:"models"` |
| 114 | 114 | } |
| 115 | 115 | if err := json.Unmarshal(data, &result); err != nil { |
| 116 | 116 | return nil, fmt.Errorf("gemini models parse: %w", err) |
| 117 | 117 |
| --- internal/llm/gemini.go | |
| +++ internal/llm/gemini.go | |
| @@ -104,13 +104,13 @@ | |
| 104 | return nil, fmt.Errorf("gemini models error %d: %s", resp.StatusCode, string(data)) |
| 105 | } |
| 106 | |
| 107 | var result struct { |
| 108 | Models []struct { |
| 109 | Name string `json:"name"` |
| 110 | DisplayName string `json:"displayName"` |
| 111 | Description string `json:"description"` |
| 112 | SupportedMethods []string `json:"supportedGenerationMethods"` |
| 113 | } `json:"models"` |
| 114 | } |
| 115 | if err := json.Unmarshal(data, &result); err != nil { |
| 116 | return nil, fmt.Errorf("gemini models parse: %w", err) |
| 117 |
| --- internal/llm/gemini.go | |
| +++ internal/llm/gemini.go | |
| @@ -104,13 +104,13 @@ | |
| 104 | return nil, fmt.Errorf("gemini models error %d: %s", resp.StatusCode, string(data)) |
| 105 | } |
| 106 | |
| 107 | var result struct { |
| 108 | Models []struct { |
| 109 | Name string `json:"name"` |
| 110 | DisplayName string `json:"displayName"` |
| 111 | Description string `json:"description"` |
| 112 | SupportedMethods []string `json:"supportedGenerationMethods"` |
| 113 | } `json:"models"` |
| 114 | } |
| 115 | if err := json.Unmarshal(data, &result); err != nil { |
| 116 | return nil, fmt.Errorf("gemini models parse: %w", err) |
| 117 |
+6
-6
| --- internal/llm/gemini_test.go | ||
| +++ internal/llm/gemini_test.go | ||
| @@ -60,19 +60,19 @@ | ||
| 60 | 60 | } |
| 61 | 61 | |
| 62 | 62 | resp := map[string]any{ |
| 63 | 63 | "models": []map[string]any{ |
| 64 | 64 | { |
| 65 | - "name": "models/gemini-1.5-flash", | |
| 66 | - "displayName": "Gemini 1.5 Flash", | |
| 67 | - "description": "Fast and versatile", | |
| 65 | + "name": "models/gemini-1.5-flash", | |
| 66 | + "displayName": "Gemini 1.5 Flash", | |
| 67 | + "description": "Fast and versatile", | |
| 68 | 68 | "supportedGenerationMethods": []string{"generateContent"}, |
| 69 | 69 | }, |
| 70 | 70 | { |
| 71 | - "name": "models/other-model", | |
| 72 | - "displayName": "Other", | |
| 73 | - "description": "Other model", | |
| 71 | + "name": "models/other-model", | |
| 72 | + "displayName": "Other", | |
| 73 | + "description": "Other model", | |
| 74 | 74 | "supportedGenerationMethods": []string{"other"}, |
| 75 | 75 | }, |
| 76 | 76 | }, |
| 77 | 77 | } |
| 78 | 78 | _ = json.NewEncoder(w).Encode(resp) |
| 79 | 79 |
| --- internal/llm/gemini_test.go | |
| +++ internal/llm/gemini_test.go | |
| @@ -60,19 +60,19 @@ | |
| 60 | } |
| 61 | |
| 62 | resp := map[string]any{ |
| 63 | "models": []map[string]any{ |
| 64 | { |
| 65 | "name": "models/gemini-1.5-flash", |
| 66 | "displayName": "Gemini 1.5 Flash", |
| 67 | "description": "Fast and versatile", |
| 68 | "supportedGenerationMethods": []string{"generateContent"}, |
| 69 | }, |
| 70 | { |
| 71 | "name": "models/other-model", |
| 72 | "displayName": "Other", |
| 73 | "description": "Other model", |
| 74 | "supportedGenerationMethods": []string{"other"}, |
| 75 | }, |
| 76 | }, |
| 77 | } |
| 78 | _ = json.NewEncoder(w).Encode(resp) |
| 79 |
| --- internal/llm/gemini_test.go | |
| +++ internal/llm/gemini_test.go | |
| @@ -60,19 +60,19 @@ | |
| 60 | } |
| 61 | |
| 62 | resp := map[string]any{ |
| 63 | "models": []map[string]any{ |
| 64 | { |
| 65 | "name": "models/gemini-1.5-flash", |
| 66 | "displayName": "Gemini 1.5 Flash", |
| 67 | "description": "Fast and versatile", |
| 68 | "supportedGenerationMethods": []string{"generateContent"}, |
| 69 | }, |
| 70 | { |
| 71 | "name": "models/other-model", |
| 72 | "displayName": "Other", |
| 73 | "description": "Other model", |
| 74 | "supportedGenerationMethods": []string{"other"}, |
| 75 | }, |
| 76 | }, |
| 77 | } |
| 78 | _ = json.NewEncoder(w).Encode(resp) |
| 79 |
+7
-7
| --- internal/topology/topology.go | ||
| +++ internal/topology/topology.go | ||
| @@ -59,17 +59,17 @@ | ||
| 59 | 59 | if err != nil { |
| 60 | 60 | return fmt.Errorf("topology: parse irc addr: %w", err) |
| 61 | 61 | } |
| 62 | 62 | |
| 63 | 63 | c := girc.New(girc.Config{ |
| 64 | - Server: host, | |
| 65 | - Port: port, | |
| 66 | - Nick: m.nick, | |
| 67 | - User: "scuttlebot", | |
| 68 | - Name: "scuttlebot topology manager", | |
| 69 | - SASL: &girc.SASLPlain{User: m.nick, Pass: m.password}, | |
| 70 | - SSL: false, | |
| 64 | + Server: host, | |
| 65 | + Port: port, | |
| 66 | + Nick: m.nick, | |
| 67 | + User: "scuttlebot", | |
| 68 | + Name: "scuttlebot topology manager", | |
| 69 | + SASL: &girc.SASLPlain{User: m.nick, Pass: m.password}, | |
| 70 | + SSL: false, | |
| 71 | 71 | }) |
| 72 | 72 | |
| 73 | 73 | connected := make(chan struct{}) |
| 74 | 74 | c.Handlers.AddBg(girc.CONNECTED, func(client *girc.Client, e girc.Event) { |
| 75 | 75 | close(connected) |
| 76 | 76 |
| --- internal/topology/topology.go | |
| +++ internal/topology/topology.go | |
| @@ -59,17 +59,17 @@ | |
| 59 | if err != nil { |
| 60 | return fmt.Errorf("topology: parse irc addr: %w", err) |
| 61 | } |
| 62 | |
| 63 | c := girc.New(girc.Config{ |
| 64 | Server: host, |
| 65 | Port: port, |
| 66 | Nick: m.nick, |
| 67 | User: "scuttlebot", |
| 68 | Name: "scuttlebot topology manager", |
| 69 | SASL: &girc.SASLPlain{User: m.nick, Pass: m.password}, |
| 70 | SSL: false, |
| 71 | }) |
| 72 | |
| 73 | connected := make(chan struct{}) |
| 74 | c.Handlers.AddBg(girc.CONNECTED, func(client *girc.Client, e girc.Event) { |
| 75 | close(connected) |
| 76 |
| --- internal/topology/topology.go | |
| +++ internal/topology/topology.go | |
| @@ -59,17 +59,17 @@ | |
| 59 | if err != nil { |
| 60 | return fmt.Errorf("topology: parse irc addr: %w", err) |
| 61 | } |
| 62 | |
| 63 | c := girc.New(girc.Config{ |
| 64 | Server: host, |
| 65 | Port: port, |
| 66 | Nick: m.nick, |
| 67 | User: "scuttlebot", |
| 68 | Name: "scuttlebot topology manager", |
| 69 | SASL: &girc.SASLPlain{User: m.nick, Pass: m.password}, |
| 70 | SSL: false, |
| 71 | }) |
| 72 | |
| 73 | connected := make(chan struct{}) |
| 74 | c.Handlers.AddBg(girc.CONNECTED, func(client *girc.Client, e girc.Event) { |
| 75 | close(connected) |
| 76 |
+5
-5
| --- pkg/agentrelay/relay.go | ||
| +++ pkg/agentrelay/relay.go | ||
| @@ -57,16 +57,16 @@ | ||
| 57 | 57 | } |
| 58 | 58 | |
| 59 | 59 | // Relay posts status messages to an IRC channel and surfaces inbound |
| 60 | 60 | // human messages to the running agent. It is safe for concurrent use. |
| 61 | 61 | type Relay struct { |
| 62 | - cfg Config | |
| 63 | - http *http.Client | |
| 62 | + cfg Config | |
| 63 | + http *http.Client | |
| 64 | 64 | |
| 65 | - mu sync.Mutex | |
| 66 | - inbox []Message // buffered inbound messages not yet consumed | |
| 67 | - cancel context.CancelFunc | |
| 65 | + mu sync.Mutex | |
| 66 | + inbox []Message // buffered inbound messages not yet consumed | |
| 67 | + cancel context.CancelFunc | |
| 68 | 68 | } |
| 69 | 69 | |
| 70 | 70 | // New creates a Relay and starts listening for inbound messages via SSE. |
| 71 | 71 | // Call Close when done. |
| 72 | 72 | func New(cfg Config) (*Relay, error) { |
| 73 | 73 |
| --- pkg/agentrelay/relay.go | |
| +++ pkg/agentrelay/relay.go | |
| @@ -57,16 +57,16 @@ | |
| 57 | } |
| 58 | |
| 59 | // Relay posts status messages to an IRC channel and surfaces inbound |
| 60 | // human messages to the running agent. It is safe for concurrent use. |
| 61 | type Relay struct { |
| 62 | cfg Config |
| 63 | http *http.Client |
| 64 | |
| 65 | mu sync.Mutex |
| 66 | inbox []Message // buffered inbound messages not yet consumed |
| 67 | cancel context.CancelFunc |
| 68 | } |
| 69 | |
| 70 | // New creates a Relay and starts listening for inbound messages via SSE. |
| 71 | // Call Close when done. |
| 72 | func New(cfg Config) (*Relay, error) { |
| 73 |
| --- pkg/agentrelay/relay.go | |
| +++ pkg/agentrelay/relay.go | |
| @@ -57,16 +57,16 @@ | |
| 57 | } |
| 58 | |
| 59 | // Relay posts status messages to an IRC channel and surfaces inbound |
| 60 | // human messages to the running agent. It is safe for concurrent use. |
| 61 | type Relay struct { |
| 62 | cfg Config |
| 63 | http *http.Client |
| 64 | |
| 65 | mu sync.Mutex |
| 66 | inbox []Message // buffered inbound messages not yet consumed |
| 67 | cancel context.CancelFunc |
| 68 | } |
| 69 | |
| 70 | // New creates a Relay and starts listening for inbound messages via SSE. |
| 71 | // Call Close when done. |
| 72 | func New(cfg Config) (*Relay, error) { |
| 73 |
+2
-2
| --- pkg/client/discovery.go | ||
| +++ pkg/client/discovery.go | ||
| @@ -17,13 +17,13 @@ | ||
| 17 | 17 | CacheTTL time.Duration |
| 18 | 18 | } |
| 19 | 19 | |
| 20 | 20 | // ChannelSummary is a channel returned by ListChannels. |
| 21 | 21 | type ChannelSummary struct { |
| 22 | - Name string | |
| 22 | + Name string | |
| 23 | 23 | MemberCount int |
| 24 | - Topic string | |
| 24 | + Topic string | |
| 25 | 25 | } |
| 26 | 26 | |
| 27 | 27 | // Member is an entry in the channel member list. |
| 28 | 28 | type Member struct { |
| 29 | 29 | Nick string |
| 30 | 30 |
| --- pkg/client/discovery.go | |
| +++ pkg/client/discovery.go | |
| @@ -17,13 +17,13 @@ | |
| 17 | CacheTTL time.Duration |
| 18 | } |
| 19 | |
| 20 | // ChannelSummary is a channel returned by ListChannels. |
| 21 | type ChannelSummary struct { |
| 22 | Name string |
| 23 | MemberCount int |
| 24 | Topic string |
| 25 | } |
| 26 | |
| 27 | // Member is an entry in the channel member list. |
| 28 | type Member struct { |
| 29 | Nick string |
| 30 |
| --- pkg/client/discovery.go | |
| +++ pkg/client/discovery.go | |
| @@ -17,13 +17,13 @@ | |
| 17 | CacheTTL time.Duration |
| 18 | } |
| 19 | |
| 20 | // ChannelSummary is a channel returned by ListChannels. |
| 21 | type ChannelSummary struct { |
| 22 | Name string |
| 23 | MemberCount int |
| 24 | Topic string |
| 25 | } |
| 26 | |
| 27 | // Member is an entry in the channel member list. |
| 28 | type Member struct { |
| 29 | Nick string |
| 30 |