// plexum-minimax-provider-plugin is a Plexum ProviderPlugin that // serves MiniMax models via MiniMax's Anthropic-compatible endpoint. // // Backend is fixed to "api" (per scope): global endpoint // https://api.minimax.io/anthropic, CN endpoint https://api.minimaxi.com/anthropic. // Authentication: a single API key sourced from the plugin's config // file at /plugins/plexum-minimax-provider/config.json. // // Declared models (advertised in manifest.contracts.provider.models): // - MiniMax-M2.7 // - MiniMax-M2.7-highspeed // // Operator points an agent at one of these via agent.json.model and // Plexum's ProviderRouter dispatches each turn here. package main import ( "context" "encoding/json" "errors" "fmt" "os" "path/filepath" "git.hangman-lab.top/hzhang/Plexum-sdk-go/canonical" plugin "git.hangman-lab.top/hzhang/Plexum-sdk-go/plugin" "git.hangman-lab.top/hzhang/Plexum-minimax-provider/internal/anthropic" "git.hangman-lab.top/hzhang/Plexum-minimax-provider/internal/translate" ) const ( pluginName = "plexum-minimax-provider" defaultBaseURLGlobal = "https://api.minimax.io/anthropic" defaultBaseURLCN = "https://api.minimaxi.com/anthropic" defaultMaxTokens = 4096 // MiniMax M2.7 can serve up to 131072 — but most turns want less ) // supportedModels = what the manifest's provider.models advertises. // Operator agent.json.model values must match one of these. var supportedModels = []string{"MiniMax-M2.7", "MiniMax-M2.7-highspeed"} // HostConfig is the per-profile plugin config at // /plugins/plexum-minimax-provider/config.json: // // { // "api_key": "sk-cp-...", // required // "region": "global" | "cn", // default "global" // "base_url": "https://...", // optional override // "max_tokens_default": 4096 // optional default when TurnRequest.MaxTokens unset // } type HostConfig struct { APIKey string `json:"api_key"` Region string `json:"region"` BaseURL string `json:"base_url"` MaxTokensDefault int `json:"max_tokens_default"` } type minimaxPlugin struct { host plugin.HostAPI cfg HostConfig cli *anthropic.Client } func (p *minimaxPlugin) Manifest() plugin.Manifest { return plugin.Manifest{ Name: pluginName, Version: "0.1.0", Activation: plugin.ActivationLazy, Executable: "plexum-minimax-provider-plugin", Contracts: plugin.Contracts{ Provider: &plugin.ProviderContract{Models: supportedModels}, }, } } func (p *minimaxPlugin) Init(ctx context.Context, host plugin.HostAPI) error { p.host = host profileRoot := os.Getenv("PLEXUM_PROFILE_ROOT") if profileRoot == "" { home, _ := os.UserHomeDir() profileRoot = filepath.Join(home, ".plexum") } cfgPath := filepath.Join(profileRoot, "plugins", pluginName, "config.json") raw, err := os.ReadFile(cfgPath) if err != nil && !errors.Is(err, os.ErrNotExist) { return fmt.Errorf("read %s: %w", cfgPath, err) } if len(raw) > 0 { if err := json.Unmarshal(raw, &p.cfg); err != nil { return fmt.Errorf("parse %s: %w", cfgPath, err) } } if p.cfg.APIKey == "" { return fmt.Errorf("minimax: api_key missing in %s", cfgPath) } base := p.cfg.BaseURL if base == "" { if p.cfg.Region == "cn" { base = defaultBaseURLCN } else { base = defaultBaseURLGlobal } } if p.cfg.MaxTokensDefault <= 0 { p.cfg.MaxTokensDefault = defaultMaxTokens } p.cli = anthropic.New(base, p.cfg.APIKey) host.Log("info", "minimax provider initialized", map[string]any{ "base": base, "models": supportedModels, "max_tokens_default": p.cfg.MaxTokensDefault, }) return nil } // Stream is the ProviderPlugin entrypoint. canonical.TurnRequest in, // channel of canonical.TurnEvent out (plugin author owns + closes the // channel; SDK forwards the stream over MCP notifications). func (p *minimaxPlugin) Stream(ctx context.Context, modelID string, req canonical.TurnRequest) (<-chan canonical.TurnEvent, error) { apiReq, err := translate.CanonicalToAnthropic(req, modelID, p.cfg.MaxTokensDefault) if err != nil { return nil, err } raw, err := p.cli.StreamMessages(ctx, apiReq) if err != nil { return nil, err } out := make(chan canonical.TurnEvent, 32) go func() { defer close(out) tr := translate.NewTranslator() for ev := range raw { for _, te := range tr.Translate(ev) { select { case out <- te: case <-ctx.Done(): return } } } }() return out, nil } func main() { if err := plugin.Serve(&minimaxPlugin{}); err != nil { fmt.Fprintf(os.Stderr, "plexum-minimax-provider-plugin: %v\n", err) os.Exit(1) } }