Skip to content
Open
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
1 change: 1 addition & 0 deletions .dev.vars.example
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
# .dev.vars is gitignored and used by wrangler dev

ANTHROPIC_API_KEY=sk-ant-...
# MINIMAX_API_KEY=sk-minimax-...

# Local development mode - skips Cloudflare Access auth and bypasses device pairing
# DEV_MODE=true
Expand Down
30 changes: 30 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,35 @@ npm run deploy

The `AI_GATEWAY_*` variables take precedence over `ANTHROPIC_*` if both are set.

## Optional: MiniMax Provider

To use the MiniMax provider, set the `MINIMAX_API_KEY` secret and configure the provider in your OpenClaw config file (`clawdbot.json`):

```bash
npx wrangler secret put MINIMAX_API_KEY
```

Then add a `minimax` entry under `models.providers` in the config (via the Control UI or by editing the config directly):

```json
{
"models": {
"providers": {
"minimax": {
"baseUrl": "<your MiniMax-compatible API base URL>",
"api": "anthropic-messages",
"apiKey": "${MINIMAX_API_KEY}",
"models": [
{ "id": "<model-id>", "name": "<display name>", "contextWindow": 200000 }
]
}
}
}
}
```

The `MINIMAX_API_KEY` environment variable is forwarded into the container automatically. If you set `model.primary` to a minimax model in the config, it will be preserved across restarts.

## All Secrets Reference

| Secret | Required | Description |
Expand All @@ -364,6 +393,7 @@ The `AI_GATEWAY_*` variables take precedence over `ANTHROPIC_*` if both are set.
| `ANTHROPIC_API_KEY` | Yes* | Direct Anthropic API key (fallback if AI Gateway not configured) |
| `ANTHROPIC_BASE_URL` | No | Direct Anthropic API base URL (fallback) |
| `OPENAI_API_KEY` | No | OpenAI API key (alternative provider) |
| `MINIMAX_API_KEY` | No | MiniMax API key for OpenClaw/OpenClawd provider (optional) |
| `CF_ACCESS_TEAM_DOMAIN` | Yes* | Cloudflare Access team domain (required for admin UI) |
| `CF_ACCESS_AUD` | Yes* | Cloudflare Access application audience (required for admin UI) |
| `MOLTBOT_GATEWAY_TOKEN` | Yes | Gateway token for authentication (pass via `?token=` query param) |
Expand Down
6 changes: 6 additions & 0 deletions src/gateway/env.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,12 @@ describe('buildEnvVars', () => {
expect(result.OPENAI_API_KEY).toBe('sk-openai-key');
});

it('includes MINIMAX_API_KEY when set', () => {
const env = createMockEnv({ MINIMAX_API_KEY: 'sk-minimax-key' });
const result = buildEnvVars(env);
expect(result.MINIMAX_API_KEY).toBe('sk-minimax-key');
});

it('maps MOLTBOT_GATEWAY_TOKEN to CLAWDBOT_GATEWAY_TOKEN for container', () => {
const env = createMockEnv({ MOLTBOT_GATEWAY_TOKEN: 'my-token' });
const result = buildEnvVars(env);
Expand Down
3 changes: 3 additions & 0 deletions src/gateway/env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ export function buildEnvVars(env: MoltbotEnv): Record<string, string> {
if (!envVars.OPENAI_API_KEY && env.OPENAI_API_KEY) {
envVars.OPENAI_API_KEY = env.OPENAI_API_KEY;
}
if (env.MINIMAX_API_KEY) {
envVars.MINIMAX_API_KEY = env.MINIMAX_API_KEY;
}

// Pass base URL (used by start-moltbot.sh to determine provider)
if (normalizedBaseUrl) {
Expand Down
2 changes: 2 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ export interface MoltbotEnv {
ANTHROPIC_API_KEY?: string;
ANTHROPIC_BASE_URL?: string;
OPENAI_API_KEY?: string;
// MiniMax provider (OpenClaw/OpenClawd)
MINIMAX_API_KEY?: string;
MOLTBOT_GATEWAY_TOKEN?: string; // Gateway token (mapped to CLAWDBOT_GATEWAY_TOKEN for container)

CLAWDBOT_BIND_MODE?: string;
Expand Down
39 changes: 36 additions & 3 deletions start-moltbot.sh
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,15 @@ if (isOpenAI) {
config.agents.defaults.models['openai/gpt-5.2'] = { alias: 'GPT-5.2' };
config.agents.defaults.models['openai/gpt-5'] = { alias: 'GPT-5' };
config.agents.defaults.models['openai/gpt-4.5-preview'] = { alias: 'GPT-4.5' };
config.agents.defaults.model.primary = 'openai/gpt-5.2';

// Preserve user-selected primary model only if it is valid for the current provider catalog.
// If the primary points to a model that isn't in the allowlist, Moltbot may reject the config.
const desiredPrimary = 'openai/gpt-5.2';
const currentPrimary = config.agents.defaults.model.primary;
const allowlisted = config.agents.defaults.models && currentPrimary && config.agents.defaults.models[currentPrimary];
if (!currentPrimary || !allowlisted) {
config.agents.defaults.model.primary = desiredPrimary;
}
} else if (baseUrl) {
console.log('Configuring Anthropic provider with base URL:', baseUrl);
config.models = config.models || {};
Expand All @@ -259,10 +267,35 @@ if (isOpenAI) {
config.agents.defaults.models['anthropic/claude-opus-4-5-20251101'] = { alias: 'Opus 4.5' };
config.agents.defaults.models['anthropic/claude-sonnet-4-5-20250929'] = { alias: 'Sonnet 4.5' };
config.agents.defaults.models['anthropic/claude-haiku-4-5-20251001'] = { alias: 'Haiku 4.5' };
config.agents.defaults.model.primary = 'anthropic/claude-opus-4-5-20251101';

// Preserve user-selected primary model only if it is valid for the current provider catalog.
// If the primary points to a model that isn't in the allowlist, Moltbot may reject the config.
const desiredPrimary = 'anthropic/claude-opus-4-5-20251101';
const currentPrimary = config.agents.defaults.model.primary;
const allowlisted = config.agents.defaults.models && currentPrimary && config.agents.defaults.models[currentPrimary];
if (!currentPrimary || !allowlisted) {
config.agents.defaults.model.primary = desiredPrimary;
}
} else {
// Default to Anthropic without custom base URL (uses built-in pi-ai catalog)
config.agents.defaults.model.primary = 'anthropic/claude-opus-4-5';
// Preserve a user-selected primary only when it is plausibly supported by the current config.
// If env/provider settings changed and the primary is no longer supported, Moltbot may reject the config.
const defaultPrimary = 'anthropic/claude-opus-4-5';
const currentPrimary = config.agents.defaults.model.primary;
const hasMinimaxProvider = !!(config.models?.providers?.minimax);
const hasOpenAIProvider = !!(config.models?.providers?.openai);
const hasAnthropicProvider = !!(config.models?.providers?.anthropic);

const keepPrimary = !!(
currentPrimary === defaultPrimary ||
(hasMinimaxProvider && currentPrimary?.startsWith('minimax/')) ||
(hasOpenAIProvider && currentPrimary?.startsWith('openai/')) ||
(hasAnthropicProvider && currentPrimary?.startsWith('anthropic/'))
);

if (!currentPrimary || !keepPrimary) {
config.agents.defaults.model.primary = defaultPrimary;
}
}

// Write updated config
Expand Down