Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 12 additions & 40 deletions internal/api/community_instance.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import (
)

const communityAgentInstancePath = "/api/v1/agent/instances"
const communityInstanceTemplatePendingCode = "error.AGENT-ERR-22"
const communityInstanceTemplatePendingCode = "AGENT-ERR-22"
const communityInstanceDeployRetries = 3
const communityInstanceDeployRetryDelay = time.Second

Expand All @@ -30,15 +30,14 @@ type communityAgentInstanceRequest struct {
}

type communityAgentInstanceResponse struct {
Code json.RawMessage `json:"code"`
Msg string `json:"msg"`
Code string `json:"code"`
Msg string `json:"msg"`
Context struct {
RepoPath string `json:"repo_path"`
} `json:"context"`
Data json.RawMessage `json:"data"`
}

type communityInstanceErrorMessage struct {
Other string `json:"other"`
}

var createCommunityAgentInstance = createCommunityAgentInstanceRequest
var communityInstanceHTTPClient = &http.Client{Timeout: 30 * time.Second}
var waitForCommunityInstanceRetry = func(ctx context.Context) error {
Expand Down Expand Up @@ -144,52 +143,25 @@ func createCommunityAgentInstanceOnce(req *http.Request) (bool, error) {
if err != nil {
return false, fmt.Errorf("read community instance response: %w", err)
}
if message, ok := communityInstanceError(responseBody, communityInstanceTemplatePendingCode); ok {
return true, fmt.Errorf("create community instance: %s", message)
}
var result communityAgentInstanceResponse
if err := json.Unmarshal(responseBody, &result); err != nil {
if resp.StatusCode != http.StatusOK {
return false, fmt.Errorf("create community instance: HTTP %d: %s", resp.StatusCode, strings.TrimSpace(string(responseBody)))
}
return false, fmt.Errorf("decode community instance response: %w", err)
}
message := strings.TrimSpace(result.Msg)
if message == "" {
message = "unknown error"
if result.Code == communityInstanceTemplatePendingCode {
message := strings.TrimSpace(result.Msg)
if message == "" {
message = communityInstanceTemplatePendingCode
}
return true, fmt.Errorf("create community instance: %s", message)
}
if resp.StatusCode != http.StatusOK {
return false, fmt.Errorf("create community instance: HTTP %d: %s", resp.StatusCode, strings.TrimSpace(string(responseBody)))
}
if code := communityInstanceCode(result.Code); code != "" && code != "0" {
return false, fmt.Errorf("create community instance: %s", message)
}
if len(result.Data) == 0 || string(result.Data) == "null" {
return false, fmt.Errorf("create community instance: response data is missing")
}
return false, nil
}

func communityInstanceError(body []byte, code string) (string, bool) {
var errorsByCode map[string]communityInstanceErrorMessage
if json.Unmarshal(body, &errorsByCode) != nil {
return "", false
}
detail, ok := errorsByCode[code]
if !ok {
return "", false
}
message := strings.TrimSpace(detail.Other)
if message == "" {
message = code
}
return message, true
}

func communityInstanceCode(raw json.RawMessage) string {
var text string
if json.Unmarshal(raw, &text) == nil {
return strings.TrimSpace(text)
}
return strings.TrimSpace(string(raw))
}
10 changes: 5 additions & 5 deletions internal/api/community_instance_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ func TestCreateCommunityAgentInstanceUsesCSGClawType(t *testing.T) {
t.Fatalf("decode request: %v", err)
}
w.Header().Set("Content-Type", "application/json")
_, _ = w.Write([]byte(`{"code":0,"data":{"id":"instance-1"}}`))
_, _ = w.Write([]byte(`{"msg":"OK","data":{"id":"instance-1"}}`))
}))
defer server.Close()

Expand Down Expand Up @@ -96,10 +96,10 @@ func TestCreateCommunityAgentInstanceRetriesTemplatePendingCode(t *testing.T) {
w.Header().Set("Content-Type", "application/json")
if attempts <= communityInstanceDeployRetries {
w.WriteHeader(http.StatusInternalServerError)
_, _ = w.Write([]byte(`{"error.AGENT-ERR-22":{"other":"csgclaw template not found for repository path alice/ReviewBot"}}`))
_, _ = w.Write([]byte(`{"code":"AGENT-ERR-22","msg":"AGENT-ERR-22: csgclaw template not found for repository path alice/ReviewBot","context":{"repo_path":"alice/ReviewBot"}}`))
return
}
_, _ = w.Write([]byte(`{"code":0,"data":{"id":"instance-1"}}`))
_, _ = w.Write([]byte(`{"msg":"OK","data":{"id":"instance-1"}}`))
}))
defer server.Close()

Expand Down Expand Up @@ -132,7 +132,7 @@ func TestCreateCommunityAgentInstanceReturnsLastTemplatePendingError(t *testing.
attempts++
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusInternalServerError)
_, _ = w.Write([]byte(`{"error.AGENT-ERR-22":{"other":"csgclaw template not found for repository path alice/ReviewBot"}}`))
_, _ = w.Write([]byte(`{"code":"AGENT-ERR-22","msg":"AGENT-ERR-22: csgclaw template not found for repository path alice/ReviewBot","context":{"repo_path":"alice/ReviewBot"}}`))
}))
defer server.Close()

Expand Down Expand Up @@ -165,7 +165,7 @@ func TestCreateCommunityAgentInstanceDoesNotRetryOtherCodes(t *testing.T) {
attempts++
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusBadRequest)
_, _ = w.Write([]byte(`{"error.AGENT-ERR-21":{"other":"invalid request"}}`))
_, _ = w.Write([]byte(`{"code":"AGENT-ERR-21","msg":"invalid request","context":{}}`))
}))
defer server.Close()

Expand Down
Loading