fix: ResetData provider - reasoning chains, URL paths, error parsing, model list
- Add Reasoning/ReasoningContent fields to ResetDataMessage struct - Wire reasoning extraction to TaskResponse.Reasoning in ExecuteTask - Fix double /v1 in makeRequest and testConnection URL construction - Handle both ResetData error formats (flat string and nested object) - Update supported models to actual ResetData beta inventory Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -30,8 +30,10 @@ type ResetDataRequest struct {
|
|||||||
|
|
||||||
// ResetDataMessage represents a message in the ResetData format
|
// ResetDataMessage represents a message in the ResetData format
|
||||||
type ResetDataMessage struct {
|
type ResetDataMessage struct {
|
||||||
Role string `json:"role"` // system, user, assistant
|
Role string `json:"role"` // system, user, assistant
|
||||||
Content string `json:"content"`
|
Content string `json:"content"`
|
||||||
|
Reasoning string `json:"reasoning,omitempty"` // reasoning chain (GLM-4.7, GPT-OSS, Nemotron 3 Nano)
|
||||||
|
ReasoningContent string `json:"reasoning_content,omitempty"` // alternate reasoning field (GPT-OSS)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ResetDataResponse represents a response from ResetData LaaS API
|
// ResetDataResponse represents a response from ResetData LaaS API
|
||||||
@@ -107,7 +109,7 @@ func (p *ResetDataProvider) ExecuteTask(ctx context.Context, request *TaskReques
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Execute the request
|
// Execute the request
|
||||||
response, err := p.makeRequest(ctx, "/v1/chat/completions", resetDataReq)
|
response, err := p.makeRequest(ctx, "/chat/completions", resetDataReq)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -122,6 +124,12 @@ func (p *ResetDataProvider) ExecuteTask(ctx context.Context, request *TaskReques
|
|||||||
choice := response.Choices[0]
|
choice := response.Choices[0]
|
||||||
responseText := choice.Message.Content
|
responseText := choice.Message.Content
|
||||||
|
|
||||||
|
// Extract reasoning chain - prefer Reasoning field, fall back to ReasoningContent
|
||||||
|
reasoning := choice.Message.Reasoning
|
||||||
|
if reasoning == "" {
|
||||||
|
reasoning = choice.Message.ReasoningContent
|
||||||
|
}
|
||||||
|
|
||||||
// Parse response for actions and artifacts
|
// Parse response for actions and artifacts
|
||||||
actions, artifacts := p.parseResponseForActions(responseText, request)
|
actions, artifacts := p.parseResponseForActions(responseText, request)
|
||||||
|
|
||||||
@@ -132,6 +140,7 @@ func (p *ResetDataProvider) ExecuteTask(ctx context.Context, request *TaskReques
|
|||||||
ModelUsed: response.Model,
|
ModelUsed: response.Model,
|
||||||
Provider: "resetdata",
|
Provider: "resetdata",
|
||||||
Response: responseText,
|
Response: responseText,
|
||||||
|
Reasoning: reasoning,
|
||||||
Actions: actions,
|
Actions: actions,
|
||||||
Artifacts: artifacts,
|
Artifacts: artifacts,
|
||||||
StartTime: startTime,
|
StartTime: startTime,
|
||||||
@@ -405,7 +414,7 @@ func (p *ResetDataProvider) makeRequest(ctx context.Context, endpoint string, re
|
|||||||
|
|
||||||
// testConnection tests the connection to ResetData API
|
// testConnection tests the connection to ResetData API
|
||||||
func (p *ResetDataProvider) testConnection(ctx context.Context) error {
|
func (p *ResetDataProvider) testConnection(ctx context.Context) error {
|
||||||
url := strings.TrimSuffix(p.config.Endpoint, "/") + "/v1/models"
|
url := strings.TrimSuffix(p.config.Endpoint, "/") + "/models"
|
||||||
req, err := http.NewRequestWithContext(ctx, "GET", url, nil)
|
req, err := http.NewRequestWithContext(ctx, "GET", url, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -429,52 +438,92 @@ func (p *ResetDataProvider) testConnection(ctx context.Context) error {
|
|||||||
|
|
||||||
// getSupportedModels returns a list of supported ResetData models
|
// getSupportedModels returns a list of supported ResetData models
|
||||||
func (p *ResetDataProvider) getSupportedModels() []string {
|
func (p *ResetDataProvider) getSupportedModels() []string {
|
||||||
// Common models available through ResetData LaaS
|
// Models available through ResetData beta (as of 2026-02)
|
||||||
return []string{
|
return []string{
|
||||||
"llama3.1:8b", "llama3.1:70b",
|
"zai-org/glm-4.7-fp8",
|
||||||
"mistral:7b", "mixtral:8x7b",
|
"openai/gpt-oss-120b",
|
||||||
"qwen2:7b", "qwen2:72b",
|
"google/gemma-3-27b-it",
|
||||||
"gemma:7b", "gemma2:9b",
|
"meta/llama-3.1-8b-instruct",
|
||||||
"codellama:7b", "codellama:13b",
|
"nvidia/nemotron-3-nano-30b-a3b",
|
||||||
|
"nvidia/cosmos-reason2-8b",
|
||||||
|
"nvidia/nemotron-nano-2-vl",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// handleHTTPError converts HTTP errors to provider errors
|
// handleHTTPError converts HTTP errors to provider errors
|
||||||
func (p *ResetDataProvider) handleHTTPError(statusCode int, body []byte) *ProviderError {
|
func (p *ResetDataProvider) handleHTTPError(statusCode int, body []byte) *ProviderError {
|
||||||
bodyStr := string(body)
|
// Extract a human-readable error message from the response body.
|
||||||
|
// ResetData returns two formats:
|
||||||
|
// Format 1 (auth): {"success":false,"error":"Invalid or expired token"}
|
||||||
|
// Format 2 (model/validation): {"error":{"message":"...","type":"...","code":"..."}}
|
||||||
|
errMsg := p.extractErrorMessage(body)
|
||||||
|
|
||||||
switch statusCode {
|
switch statusCode {
|
||||||
case http.StatusUnauthorized:
|
case http.StatusUnauthorized:
|
||||||
return &ProviderError{
|
return &ProviderError{
|
||||||
Code: "UNAUTHORIZED",
|
Code: "UNAUTHORIZED",
|
||||||
Message: "Invalid ResetData API key",
|
Message: fmt.Sprintf("ResetData auth failed: %s", errMsg),
|
||||||
Details: bodyStr,
|
Details: string(body),
|
||||||
Retryable: false,
|
Retryable: false,
|
||||||
}
|
}
|
||||||
case http.StatusTooManyRequests:
|
case http.StatusTooManyRequests:
|
||||||
return &ProviderError{
|
return &ProviderError{
|
||||||
Code: "RATE_LIMIT_EXCEEDED",
|
Code: "RATE_LIMIT_EXCEEDED",
|
||||||
Message: "ResetData API rate limit exceeded",
|
Message: fmt.Sprintf("ResetData rate limit: %s", errMsg),
|
||||||
Details: bodyStr,
|
Details: string(body),
|
||||||
Retryable: true,
|
Retryable: true,
|
||||||
}
|
}
|
||||||
case http.StatusInternalServerError, http.StatusBadGateway, http.StatusServiceUnavailable:
|
case http.StatusInternalServerError, http.StatusBadGateway, http.StatusServiceUnavailable:
|
||||||
return &ProviderError{
|
return &ProviderError{
|
||||||
Code: "SERVICE_UNAVAILABLE",
|
Code: "SERVICE_UNAVAILABLE",
|
||||||
Message: "ResetData API service unavailable",
|
Message: fmt.Sprintf("ResetData unavailable: %s", errMsg),
|
||||||
Details: bodyStr,
|
Details: string(body),
|
||||||
Retryable: true,
|
Retryable: true,
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return &ProviderError{
|
return &ProviderError{
|
||||||
Code: "API_ERROR",
|
Code: "API_ERROR",
|
||||||
Message: fmt.Sprintf("ResetData API error (status %d)", statusCode),
|
Message: fmt.Sprintf("ResetData error (status %d): %s", statusCode, errMsg),
|
||||||
Details: bodyStr,
|
Details: string(body),
|
||||||
Retryable: true,
|
Retryable: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// extractErrorMessage parses error details from ResetData API response bodies.
|
||||||
|
func (p *ResetDataProvider) extractErrorMessage(body []byte) string {
|
||||||
|
// Try Format 2: {"error":{"message":"...","type":"...","code":"..."}}
|
||||||
|
var nestedErr struct {
|
||||||
|
Error struct {
|
||||||
|
Message string `json:"message"`
|
||||||
|
Type string `json:"type"`
|
||||||
|
Code string `json:"code"`
|
||||||
|
} `json:"error"`
|
||||||
|
}
|
||||||
|
if err := json.Unmarshal(body, &nestedErr); err == nil && nestedErr.Error.Message != "" {
|
||||||
|
if nestedErr.Error.Type != "" {
|
||||||
|
return fmt.Sprintf("%s (%s)", nestedErr.Error.Message, nestedErr.Error.Type)
|
||||||
|
}
|
||||||
|
return nestedErr.Error.Message
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try Format 1: {"success":false,"error":"string message"}
|
||||||
|
var flatErr struct {
|
||||||
|
Success bool `json:"success"`
|
||||||
|
Error string `json:"error"`
|
||||||
|
}
|
||||||
|
if err := json.Unmarshal(body, &flatErr); err == nil && flatErr.Error != "" {
|
||||||
|
return flatErr.Error
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback: return raw body truncated
|
||||||
|
s := string(body)
|
||||||
|
if len(s) > 200 {
|
||||||
|
s = s[:200] + "..."
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
// parseResponseForActions extracts actions from the response text
|
// parseResponseForActions extracts actions from the response text
|
||||||
func (p *ResetDataProvider) parseResponseForActions(response string, request *TaskRequest) ([]TaskAction, []Artifact) {
|
func (p *ResetDataProvider) parseResponseForActions(response string, request *TaskRequest) ([]TaskAction, []Artifact) {
|
||||||
var actions []TaskAction
|
var actions []TaskAction
|
||||||
|
|||||||
Reference in New Issue
Block a user