Skip to content

add minimax coding plan support by anthropic api like#765

Open
JoeEmp wants to merge 3 commits intosipeed:mainfrom
JoeEmp:main
Open

add minimax coding plan support by anthropic api like#765
JoeEmp wants to merge 3 commits intosipeed:mainfrom
JoeEmp:main

Conversation

@JoeEmp
Copy link

@JoeEmp JoeEmp commented Feb 25, 2026

📝 Description

🗣️ Type of Change

  • [ ] 🐞 Bug fix (non-breaking change which fixes an issue)
  • ✨ New feature (non-breaking change which adds functionality)
  • [ ] 📖 Documentation update
  • [ ] ⚡ Code refactoring (no functional changes, no api changes)

🤖 AI Code Generation

  • 🤖 Fully AI-generated (100% AI, 0% Human)
  • [ ] 🛠️ Mostly AI-generated (AI draft, Human verified/modified)
  • [ ] 👨‍💻 Mostly Human-written (Human lead, AI assisted or none)

🔗 Related Issue

📚 Technical Context (Skip for Docs)

  • Reference URL:
  • Reasoning: use virtually unlimited tokens to unleash more of the user's imagination
  • config: model_list config
{
  "agents": {
    "defaults": {
      "workspace": "~/.picoclaw/workspace",
      "restrict_to_workspace": true,
      "provider": "",
      "model": "MiniMax-M2.5-CodingPlan",
      "max_tokens": 8192,
      "max_tool_iterations": 20
    }
   "model_list": [
    {
      "model_name": "MiniMax-M2.5-CodingPlan",
      "model": "anthropic/MiniMax-M2.5",
      "api_base": "https://api.minimaxi.com/anthropic/v1",
      "api_key": "your-api-key"
    }
   ]
}

🧪 Test Environment

  • Hardware: MacBook Air M1
  • OS: MacOS 15.7.3
  • Model/Provider: MiniMax2.5
  • Channels: qq

📸 Evidence (Optional)

Click to view Logs/Screenshots 截屏2026-02-25 14 33 01

☑️ Checklist

  • My code/docs follow the style of this project.
  • I have performed a self-review of my own changes.
  • I have updated the documentation accordingly.

@xiaket xiaket added type: enhancement New feature or request domain: provider labels Feb 25, 2026
Copy link
Collaborator

@yinwm yinwm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@yinwm
Copy link
Collaborator

yinwm commented Feb 25, 2026

@JoeEmp please fix Linter bug

@zither
Copy link

zither commented Feb 25, 2026

Bug Summary

Problem: Using anthropic-compatible APIs (like minimax coding plan) fails after the first request with error:

invalid params, messages.X.content.0.tool_use.input: Input should be a valid dictionary

Root Cause: In pkg/agent/loop.go:643, when building assistant messages with tool calls, the Arguments field (map type) was missing - only Function.Arguments (JSON string) was set.

This was introduced in commit 7f24164 ("feat(providers): add thought_signature support for gemini") which accidentally removed Arguments: tc.Arguments when adding thought_signature support.

Fix: Add Arguments: tc.Arguments back:

assistantMsg.ToolCalls = append(assistantMsg.ToolCalls, providers.ToolCall{
    ID:        tc.ID,
    Type:      "function",
    Name:      tc.Name,
    Arguments: tc.Arguments,  // ADD THIS
    Function: &providers.FunctionCall{
        Name:             tc.Name,
        Arguments:        string(argumentsJSON),
        ThoughtSignature: thoughtSignature,
    },
    // ...
})

Note: This bug existed before PR-765 but was only exposed by the new anthropic_compat provider which directly uses the Arguments field.

@JoeEmp
Copy link
Author

JoeEmp commented Feb 25, 2026

Bug Summary

Problem: Using anthropic-compatible APIs (like minimax coding plan) fails after the first request with error:

invalid params, messages.X.content.0.tool_use.input: Input should be a valid dictionary

Root Cause: In pkg/agent/loop.go:643, when building assistant messages with tool calls, the Arguments field (map type) was missing - only Function.Arguments (JSON string) was set.

This was introduced in commit 7f24164 ("feat(providers): add thought_signature support for gemini") which accidentally removed Arguments: tc.Arguments when adding thought_signature support.

Fix: Add Arguments: tc.Arguments back:

assistantMsg.ToolCalls = append(assistantMsg.ToolCalls, providers.ToolCall{
    ID:        tc.ID,
    Type:      "function",
    Name:      tc.Name,
    Arguments: tc.Arguments,  // ADD THIS
    Function: &providers.FunctionCall{
        Name:             tc.Name,
        Arguments:        string(argumentsJSON),
        ThoughtSignature: thoughtSignature,
    },
    // ...
})

Note: This bug existed before PR-765 but was only exposed by the new anthropic_compat provider which directly uses the Arguments field.

i got it

Copy link

@nikolasdehor nikolasdehor left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a substantial new provider implementation with good test coverage (464 lines of tests). Several observations:

Positives:

  • Clean separation via httpDelegate interface in http_provider.go
  • Thorough test suite covering happy path, tool calls, system messages, options, error handling, and proxy config
  • Proper context propagation with http.NewRequestWithContext

Issues to address:

  1. system field type mismatch: buildRequestBody sets requestBody["system"] = system where system is []string. The Anthropic Messages API expects system to be either a single string or an array of content blocks ([{"type":"text","text":"..."}]), not a []string. This will likely cause 400 errors from Anthropic-compatible endpoints. Should be either strings.Join(system, "\n") or structured content blocks.

  2. Duplicate user messages for tool results: When msg.Role == "user" and msg.ToolCallID != "", the code creates a message with tool_result content — but this case is already handled by the case "tool" branch. The "user" case should probably not handle ToolCallID at all, or the "tool" branch is redundant. As-is, if something sends a message with Role:"user" and a ToolCallID, it gets double-mapped.

  3. Silent proxy error: In NewProvider, if proxy URL parsing fails, it logs and continues without a proxy. This means a misconfigured proxy silently falls back to direct connection — which could be a security issue if the proxy is required (e.g., for network isolation). Consider returning an error instead.

  4. max_tokens type assertion: options["max_tokens"].(int) will fail if the value comes from JSON unmarshaling (where numbers are float64). The test for AcceptsOptions passes int directly, but in production the config is likely JSON-sourced. Should handle both int and float64.

  5. Breaking change in factory_provider.go: The anthropic protocol case changed from NewHTTPProviderWithMaxTokensField to NewHTTPProviderWithProtocol, which drops the MaxTokensField configuration. If any existing anthropic-protocol users relied on custom max_tokens_field names, this is a regression.

  6. No streaming support: The provider does synchronous request/response. If picoclaw supports streaming for other providers, this will be a feature gap for MiniMax users. Not a blocker but worth noting.

@yinwm
Copy link
Collaborator

yinwm commented Feb 26, 2026

Thanks for adding the anthropic_compat provider! The code structure is clean and test coverage is good. However, there are several issues that need to be addressed before merging:

🔴 Critical Issues

1. system field type mismatch (line 114)

if len(system) > 0 {
    requestBody["system"] = system  // system is []string
}

The Anthropic Messages API expects system to be a string or content blocks [{"type":"text","text":"..."}], not []string. This will cause a 400 error.

Fix:

requestBody["system"] = strings.Join(system, "\n")

2. Duplicate tool_result handling
Both case "user" (with ToolCallID check) and case "tool" create tool_result messages. If someone sends Role:"user" + ToolCallID, the behavior is ambiguous. The user case should probably not handle ToolCallID at all.

🟡 Medium Priority Issues

3. Proxy config fails silently (security concern)

if err != nil {
    log.Printf("anthropic_compat: invalid proxy URL %q: %v", proxy, err)
    // continues without proxy
}

If the proxy is required (e.g., for network isolation), silent fallback to direct connection is a security issue. Consider returning an error instead.

4. max_tokens type assertion will fail with JSON-sourced values

if mt, ok := options["max_tokens"].(int); ok {

When options comes from JSON unmarshaling, numbers are float64, not int. The assertion will silently fail and use the default value. Should handle both int and float64.

5. Breaking change - MaxTokensField config dropped

- return NewHTTPProviderWithMaxTokensField(cfg.APIKey, apiBase, cfg.Proxy, cfg.MaxTokensField)
+ return NewHTTPProviderWithProtocol(cfg.APIKey, apiBase, cfg.Proxy, "anthropic")

If any existing users relied on custom max_tokens_field names, this is a regression.


Please address at least the critical issues (#1, #2) before merging. Issues #3 and #4 would also be good to fix for production readiness.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants