This commit is contained in:
Dylan Huang 2026-01-29 09:01:15 -08:00 committed by GitHub
commit 30ac7227a4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 741 additions and 2 deletions

View File

@ -297,7 +297,7 @@ Options:
- `--non-interactive` - `--non-interactive`
- `--mode <local|remote>` - `--mode <local|remote>`
- `--flow <quickstart|advanced|manual>` (manual is an alias for advanced) - `--flow <quickstart|advanced|manual>` (manual is an alias for advanced)
- `--auth-choice <setup-token|token|chutes|openai-codex|openai-api-key|openrouter-api-key|ai-gateway-api-key|moonshot-api-key|kimi-code-api-key|synthetic-api-key|venice-api-key|gemini-api-key|zai-api-key|apiKey|minimax-api|minimax-api-lightning|opencode-zen|skip>` - `--auth-choice <setup-token|claude-cli|token|chutes|openai-codex|openai-api-key|openrouter-api-key|ai-gateway-api-key|moonshot-api-key|kimi-code-api-key|synthetic-api-key|venice-api-key|fireworks-api-key|codex-cli|gemini-api-key|zai-api-key|apiKey|minimax-api|minimax-api-lightning|opencode-zen|skip>`
- `--token-provider <id>` (non-interactive; used with `--auth-choice token`) - `--token-provider <id>` (non-interactive; used with `--auth-choice token`)
- `--token <token>` (non-interactive; used with `--auth-choice token`) - `--token <token>` (non-interactive; used with `--auth-choice token`)
- `--token-profile-id <id>` (non-interactive; default: `<provider>:manual`) - `--token-profile-id <id>` (non-interactive; default: `<provider>:manual`)
@ -311,6 +311,8 @@ Options:
- `--gemini-api-key <key>` - `--gemini-api-key <key>`
- `--zai-api-key <key>` - `--zai-api-key <key>`
- `--minimax-api-key <key>` - `--minimax-api-key <key>`
- `--venice-api-key <key>`
- `--fireworks-api-key <key>`
- `--opencode-zen-api-key <key>` - `--opencode-zen-api-key <key>`
- `--gateway-port <port>` - `--gateway-port <port>`
- `--gateway-bind <loopback|lan|tailnet|auto|custom>` - `--gateway-bind <loopback|lan|tailnet|auto|custom>`

View File

@ -1014,6 +1014,8 @@
"providers/vercel-ai-gateway", "providers/vercel-ai-gateway",
"providers/openrouter", "providers/openrouter",
"providers/synthetic", "providers/synthetic",
"providers/venice",
"providers/fireworks",
"providers/opencode", "providers/opencode",
"providers/glm", "providers/glm",
"providers/zai" "providers/zai"

245
docs/providers/fireworks.md Normal file
View File

@ -0,0 +1,245 @@
---
summary: "Use Fireworks AI serverless models in Clawdbot"
read_when:
- You want fast serverless inference in Clawdbot
- You want Fireworks AI setup guidance
---
# Fireworks AI
Fireworks AI provides fast, cost-effective serverless inference for popular open-source models including DeepSeek, Qwen, Llama, GLM, and more. All models run on optimized infrastructure with low latency and competitive pricing.
## Why Fireworks in Clawdbot
- **Fast inference** with optimized serving infrastructure.
- **Wide model selection** including DeepSeek V3.2, Qwen3, Llama 3.3, GLM-4.7, and more.
- **Serverless** — no infrastructure management, pay per token.
- **OpenAI-compatible** `/v1` endpoints.
## Features
- **Serverless inference**: No GPU management, instant scaling
- **OpenAI-compatible API**: Standard `/v1` endpoints for easy integration
- **Streaming**: Supported on all models
- **Function calling**: Supported on most models
- **Vision**: Supported on vision-capable models (Qwen VL series)
- **Reasoning models**: DeepSeek R1, Qwen3 Thinking, Kimi K2 Thinking, Kimi K2.5
## Setup
### 1. Get API Key
1. Sign up at [fireworks.ai](https://fireworks.ai)
2. Go to **Account → API Keys → Create API Key**
3. Copy your API key
### 2. Configure Clawdbot
**Option A: Environment Variable**
```bash
export FIREWORKS_API_KEY="fw_xxxxxxxxxxxx"
```
**Option B: Interactive Setup (Recommended)**
```bash
clawdbot onboard --auth-choice fireworks-api-key
```
This will:
1. Prompt for your API key (or use existing `FIREWORKS_API_KEY`)
2. Configure the Fireworks provider with available models
3. Let you pick your default model
4. Set up the provider automatically
**Option C: Non-interactive**
```bash
clawdbot onboard --non-interactive \
--auth-choice fireworks-api-key \
--fireworks-api-key "fw_xxxxxxxxxxxx"
```
### 3. Verify Setup
```bash
clawdbot chat --model fireworks/accounts/fireworks/models/deepseek-v3p2 "Hello, are you working?"
```
## Model Selection
Clawdbot includes a curated catalog of popular Fireworks models. Pick based on your needs:
- **Default**: `deepseek-v3p2` (DeepSeek V3.2) — strong reasoning, balanced performance.
- **Best reasoning**: `deepseek-r1-0528` or `qwen3-235b-a22b-thinking-2507`
- **Coding**: `qwen3-coder-480b-a35b-instruct`
- **Vision**: `qwen3-vl-235b-a22b-instruct` or `qwen2p5-vl-32b-instruct`
Change your default model anytime:
```bash
clawdbot models set fireworks/accounts/fireworks/models/deepseek-v3p2
clawdbot models set fireworks/accounts/fireworks/models/qwen3-235b-a22b-thinking-2507
```
List all available models:
```bash
clawdbot models list | grep fireworks
```
## Which Model Should I Use?
| Use Case | Recommended Model | Why |
|----------|-------------------|-----|
| **General chat** | `deepseek-v3p2` | Strong all-around performance |
| **Complex reasoning** | `deepseek-r1-0528` | Best for step-by-step reasoning |
| **Agentic tasks** | `gpt-oss-120b` | Designed for reasoning and agentic use |
| **Coding** | `qwen3-coder-480b-a35b-instruct` | Code-optimized, 262k context |
| **Vision tasks** | `qwen3-vl-235b-a22b-instruct` | Best multimodal capabilities |
| **Fast + cheap** | `qwen3-8b` | Lightweight, low latency |
| **Long context** | `kimi-k2-instruct-0905` | 262k context window |
## Available Models (26 Total)
### Text Models
| Model ID | Name | Context | Features |
|----------|------|---------|----------|
| `deepseek-r1-0528` | Deepseek R1 05/28 | 163k | Reasoning |
| `deepseek-v3-0324` | Deepseek V3 03-24 | 163k | General |
| `deepseek-v3p1` | DeepSeek V3.1 | 163k | General |
| `deepseek-v3p1-terminus` | DeepSeek V3.1 Terminus | 163k | General |
| `deepseek-v3p2` | Deepseek v3.2 | 163k | General |
| `glm-4p6` | GLM-4.6 | 202k | Reasoning |
| `glm-4p7` | GLM-4.7 | 202k | Reasoning |
| `gpt-oss-120b` | OpenAI gpt-oss-120b | 131k | Reasoning |
| `gpt-oss-20b` | OpenAI gpt-oss-20b | 131k | Reasoning |
| `kimi-k2-instruct-0905` | Kimi K2 Instruct 0905 | 262k | Long context |
| `kimi-k2p5` | Kimi K2.5 | 262k | Vision, reasoning |
| `kimi-k2-thinking` | Kimi K2 Thinking | 256k | Reasoning |
| `llama-v3p3-70b-instruct` | Llama 3.3 70B Instruct | 131k | General |
| `minimax-m2` | MiniMax-M2 | 196k | Agentic, coding |
| `minimax-m2p1` | MiniMax-M2.1 | 204k | Agentic, coding |
| `qwen3-235b-a22b` | Qwen3 235B A22B | 131k | General |
| `qwen3-235b-a22b-instruct-2507` | Qwen3 235B A22B Instruct 2507 | 262k | General |
| `qwen3-235b-a22b-thinking-2507` | Qwen3 235B A22B Thinking 2507 | 262k | Reasoning |
| `qwen3-8b` | Qwen3 8B | 40k | Fast |
| `qwen3-coder-480b-a35b-instruct` | Qwen3 Coder 480B A35B Instruct | 262k | Coding |
### Vision Models
| Model ID | Name | Context | Features |
|----------|------|---------|----------|
| `qwen2p5-vl-32b-instruct` | Qwen2.5-VL 32B Instruct | 128k | Vision |
| `qwen3-vl-235b-a22b-instruct` | Qwen3 VL 235B A22B Instruct | 262k | Vision |
| `qwen3-vl-235b-a22b-thinking` | Qwen3 VL 235B A22B Thinking | 262k | Vision, reasoning |
| `qwen3-vl-30b-a3b-instruct` | Qwen3 VL 30B A3B Instruct | 262k | Vision |
| `qwen3-vl-30b-a3b-thinking` | Qwen3 VL 30B A3B Thinking | 262k | Vision, reasoning |
## Model Catalog
Clawdbot includes a curated catalog of popular Fireworks serverless LLM models.
## Model IDs
Fireworks model IDs use the full resource path format:
```
accounts/fireworks/models/<model-name>
```
When using models in Clawdbot, prefix with the provider:
```bash
clawdbot chat --model fireworks/accounts/fireworks/models/deepseek-v3p2
```
## Streaming and Tool Support
| Feature | Support |
|---------|---------|
| **Streaming** | All models |
| **Function calling** | Most models (check `supportsTools` in API) |
| **Vision/Images** | Vision models only |
| **JSON mode** | Supported via `response_format` |
## Pricing
Fireworks uses pay-per-token pricing. Check [fireworks.ai/pricing](https://fireworks.ai/pricing) for current rates. Generally:
- Smaller models (8B-30B): Lower cost, faster
- Larger models (70B+): Higher quality, higher cost
- MoE models: Cost-effective for their capability
## Usage Examples
```bash
# Use DeepSeek V3.2 (recommended default)
clawdbot chat --model fireworks/accounts/fireworks/models/deepseek-v3p2
# Use reasoning model
clawdbot chat --model fireworks/accounts/fireworks/models/deepseek-r1-0528
# Use coding model
clawdbot chat --model fireworks/accounts/fireworks/models/qwen3-coder-480b-a35b-instruct
# Use vision model
clawdbot chat --model fireworks/accounts/fireworks/models/qwen3-vl-235b-a22b-instruct
```
## Troubleshooting
### API key not recognized
```bash
echo $FIREWORKS_API_KEY
clawdbot models list | grep fireworks
```
Ensure the key is valid and has not expired.
### Model not available
Run `clawdbot models list` to see currently available models in the catalog. If a model you need is missing, you can add it manually to your config file.
### Connection issues
Fireworks API is at `https://api.fireworks.ai`. Ensure your network allows HTTPS connections.
## Config file example
```json5
{
env: { FIREWORKS_API_KEY: "fw_..." },
agents: { defaults: { model: { primary: "fireworks/accounts/fireworks/models/deepseek-v3p2" } } },
models: {
mode: "merge",
providers: {
fireworks: {
baseUrl: "https://api.fireworks.ai/inference/v1",
apiKey: "${FIREWORKS_API_KEY}",
api: "openai-completions",
models: [
{
id: "accounts/fireworks/models/deepseek-v3p2",
name: "DeepSeek V3.2",
reasoning: false,
input: ["text"],
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
contextWindow: 163840,
maxTokens: 8192
}
]
}
}
}
}
```
## Links
- [Fireworks AI](https://fireworks.ai)
- [API Documentation](https://docs.fireworks.ai)
- [Pricing](https://fireworks.ai/pricing)
- [Model List](https://fireworks.ai/models)

View File

@ -45,6 +45,7 @@ See [Venice AI](/providers/venice).
- [GLM models](/providers/glm) - [GLM models](/providers/glm)
- [MiniMax](/providers/minimax) - [MiniMax](/providers/minimax)
- [Venius (Venice AI, privacy-focused)](/providers/venice) - [Venius (Venice AI, privacy-focused)](/providers/venice)
- [Fireworks AI (serverless inference)](/providers/fireworks)
- [Ollama (local models)](/providers/ollama) - [Ollama (local models)](/providers/ollama)
## Transcription providers ## Transcription providers

View File

@ -0,0 +1,265 @@
import type { ModelDefinitionConfig } from "../config/types.js";
export const FIREWORKS_BASE_URL = "https://api.fireworks.ai/inference/v1";
export const FIREWORKS_DEFAULT_MODEL_ID = "accounts/fireworks/models/deepseek-v3p2";
export const FIREWORKS_DEFAULT_MODEL_REF = `fireworks/${FIREWORKS_DEFAULT_MODEL_ID}`;
// Fireworks uses pay-per-token pricing; rates vary by model.
// Set to 0 as a default; override in models.json for accurate costs.
export const FIREWORKS_DEFAULT_COST = {
input: 0,
output: 0,
cacheRead: 0,
cacheWrite: 0,
};
/**
* Static catalog of Fireworks AI serverless models.
*
* Only includes LLM models (no image generation), non-deprecated models,
* and models that support serverless inference.
*
* Model IDs use the full format: accounts/fireworks/models/<model>
*/
export const FIREWORKS_MODEL_CATALOG = [
// DeepSeek models
{
id: "accounts/fireworks/models/deepseek-r1-0528",
name: "Deepseek R1 05/28",
reasoning: true,
input: ["text"] as const,
contextWindow: 163840,
maxTokens: 8192,
},
{
id: "accounts/fireworks/models/deepseek-v3-0324",
name: "Deepseek V3 03-24",
reasoning: false,
input: ["text"] as const,
contextWindow: 163840,
maxTokens: 8192,
},
{
id: "accounts/fireworks/models/deepseek-v3p1",
name: "DeepSeek V3.1",
reasoning: false,
input: ["text"] as const,
contextWindow: 163840,
maxTokens: 8192,
},
{
id: "accounts/fireworks/models/deepseek-v3p1-terminus",
name: "DeepSeek V3.1 Terminus",
reasoning: false,
input: ["text"] as const,
contextWindow: 163840,
maxTokens: 8192,
},
{
id: "accounts/fireworks/models/deepseek-v3p2",
name: "Deepseek v3.2",
reasoning: false,
input: ["text"] as const,
contextWindow: 163840,
maxTokens: 8192,
},
// GLM models - both support "advanced thinking controls"
{
id: "accounts/fireworks/models/glm-4p6",
name: "GLM-4.6",
reasoning: true,
input: ["text"] as const,
contextWindow: 202752,
maxTokens: 8192,
},
{
id: "accounts/fireworks/models/glm-4p7",
name: "GLM-4.7",
reasoning: true,
input: ["text"] as const,
contextWindow: 202752,
maxTokens: 8192,
},
// OpenAI gpt-oss models - designed for "powerful reasoning, agentic tasks"
{
id: "accounts/fireworks/models/gpt-oss-120b",
name: "OpenAI gpt-oss-120b",
reasoning: true,
input: ["text"] as const,
contextWindow: 131072,
maxTokens: 8192,
},
{
id: "accounts/fireworks/models/gpt-oss-20b",
name: "OpenAI gpt-oss-20b",
reasoning: true,
input: ["text"] as const,
contextWindow: 131072,
maxTokens: 8192,
},
// Kimi models
{
id: "accounts/fireworks/models/kimi-k2-instruct-0905",
name: "Kimi K2 Instruct 0905",
reasoning: false,
input: ["text"] as const,
contextWindow: 262144,
maxTokens: 8192,
},
{
id: "accounts/fireworks/models/kimi-k2p5",
name: "Kimi K2.5",
reasoning: true,
input: ["text", "image"] as const,
contextWindow: 262144,
maxTokens: 8192,
},
{
id: "accounts/fireworks/models/kimi-k2-thinking",
name: "Kimi K2 Thinking",
reasoning: true,
input: ["text"] as const,
// API returns 0 but description says 256k
contextWindow: 256000,
maxTokens: 8192,
},
// Llama models
{
id: "accounts/fireworks/models/llama-v3p3-70b-instruct",
name: "Llama 3.3 70B Instruct",
reasoning: false,
input: ["text"] as const,
contextWindow: 131072,
maxTokens: 8192,
},
// MiniMax models - compact MoE for coding and agentic tasks
{
id: "accounts/fireworks/models/minimax-m2",
name: "MiniMax-M2",
reasoning: false,
input: ["text"] as const,
contextWindow: 196608,
maxTokens: 8192,
},
{
id: "accounts/fireworks/models/minimax-m2p1",
name: "MiniMax-M2.1",
reasoning: false,
input: ["text"] as const,
contextWindow: 204800,
maxTokens: 8192,
},
// Qwen text models
{
id: "accounts/fireworks/models/qwen3-235b-a22b",
name: "Qwen3 235B A22B",
reasoning: false,
input: ["text"] as const,
contextWindow: 131072,
maxTokens: 8192,
},
{
id: "accounts/fireworks/models/qwen3-235b-a22b-instruct-2507",
name: "Qwen3 235B A22B Instruct 2507",
reasoning: false,
input: ["text"] as const,
contextWindow: 262144,
maxTokens: 8192,
},
{
id: "accounts/fireworks/models/qwen3-235b-a22b-thinking-2507",
name: "Qwen3 235B A22B Thinking 2507",
reasoning: true,
input: ["text"] as const,
contextWindow: 262144,
maxTokens: 8192,
},
{
id: "accounts/fireworks/models/qwen3-8b",
name: "Qwen3 8B",
reasoning: false,
input: ["text"] as const,
contextWindow: 40960,
maxTokens: 8192,
},
{
id: "accounts/fireworks/models/qwen3-coder-480b-a35b-instruct",
name: "Qwen3 Coder 480B A35B Instruct",
reasoning: false,
input: ["text"] as const,
contextWindow: 262144,
maxTokens: 8192,
},
// Qwen vision models
{
id: "accounts/fireworks/models/qwen2p5-vl-32b-instruct",
name: "Qwen2.5-VL 32B Instruct",
reasoning: false,
input: ["text", "image"] as const,
contextWindow: 128000,
maxTokens: 8192,
},
{
id: "accounts/fireworks/models/qwen3-vl-235b-a22b-instruct",
name: "Qwen3 VL 235B A22B Instruct",
reasoning: false,
input: ["text", "image"] as const,
contextWindow: 262144,
maxTokens: 8192,
},
{
id: "accounts/fireworks/models/qwen3-vl-235b-a22b-thinking",
name: "Qwen3 VL 235B A22B Thinking",
reasoning: true,
input: ["text", "image"] as const,
contextWindow: 262144,
maxTokens: 8192,
},
{
id: "accounts/fireworks/models/qwen3-vl-30b-a3b-instruct",
name: "Qwen3 VL 30B A3B Instruct",
reasoning: false,
input: ["text", "image"] as const,
contextWindow: 262144,
maxTokens: 8192,
},
{
id: "accounts/fireworks/models/qwen3-vl-30b-a3b-thinking",
name: "Qwen3 VL 30B A3B Thinking",
reasoning: true,
input: ["text", "image"] as const,
contextWindow: 262144,
maxTokens: 8192,
},
] as const;
export type FireworksCatalogEntry = (typeof FIREWORKS_MODEL_CATALOG)[number];
/**
* Build a ModelDefinitionConfig from a Fireworks catalog entry.
*/
export function buildFireworksModelDefinition(entry: FireworksCatalogEntry): ModelDefinitionConfig {
return {
id: entry.id,
name: entry.name,
reasoning: entry.reasoning,
input: [...entry.input],
cost: FIREWORKS_DEFAULT_COST,
contextWindow: entry.contextWindow,
maxTokens: entry.maxTokens,
};
}
/**
* Returns Fireworks models from the static catalog.
*/
export function discoverFireworksModels(): ModelDefinitionConfig[] {
return FIREWORKS_MODEL_CATALOG.map(buildFireworksModelDefinition);
}

View File

@ -283,6 +283,7 @@ export function resolveEnvApiKey(provider: string): EnvApiKeyResult | null {
minimax: "MINIMAX_API_KEY", minimax: "MINIMAX_API_KEY",
synthetic: "SYNTHETIC_API_KEY", synthetic: "SYNTHETIC_API_KEY",
venice: "VENICE_API_KEY", venice: "VENICE_API_KEY",
fireworks: "FIREWORKS_API_KEY",
mistral: "MISTRAL_API_KEY", mistral: "MISTRAL_API_KEY",
opencode: "OPENCODE_API_KEY", opencode: "OPENCODE_API_KEY",
}; };

View File

@ -12,6 +12,7 @@ import {
SYNTHETIC_BASE_URL, SYNTHETIC_BASE_URL,
SYNTHETIC_MODEL_CATALOG, SYNTHETIC_MODEL_CATALOG,
} from "./synthetic-models.js"; } from "./synthetic-models.js";
import { discoverFireworksModels, FIREWORKS_BASE_URL } from "./fireworks-models.js";
import { discoverVeniceModels, VENICE_BASE_URL } from "./venice-models.js"; import { discoverVeniceModels, VENICE_BASE_URL } from "./venice-models.js";
type ModelsConfig = NonNullable<MoltbotConfig["models"]>; type ModelsConfig = NonNullable<MoltbotConfig["models"]>;
@ -350,6 +351,15 @@ async function buildVeniceProvider(): Promise<ProviderConfig> {
}; };
} }
function buildFireworksProvider(): ProviderConfig {
const models = discoverFireworksModels();
return {
baseUrl: FIREWORKS_BASE_URL,
api: "openai-completions",
models,
};
}
async function buildOllamaProvider(): Promise<ProviderConfig> { async function buildOllamaProvider(): Promise<ProviderConfig> {
const models = await discoverOllamaModels(); const models = await discoverOllamaModels();
return { return {
@ -402,6 +412,13 @@ export async function resolveImplicitProviders(params: {
providers.venice = { ...(await buildVeniceProvider()), apiKey: veniceKey }; providers.venice = { ...(await buildVeniceProvider()), apiKey: veniceKey };
} }
const fireworksKey =
resolveEnvApiKeyVarName("fireworks") ??
resolveApiKeyFromProfiles({ provider: "fireworks", store: authStore });
if (fireworksKey) {
providers.fireworks = { ...buildFireworksProvider(), apiKey: fireworksKey };
}
const qwenProfiles = listProfilesForProvider(authStore, "qwen-portal"); const qwenProfiles = listProfilesForProvider(authStore, "qwen-portal");
if (qwenProfiles.length > 0) { if (qwenProfiles.length > 0) {
providers["qwen-portal"] = { providers["qwen-portal"] = {

View File

@ -52,7 +52,7 @@ export function registerOnboardCommand(program: Command) {
.option("--mode <mode>", "Wizard mode: local|remote") .option("--mode <mode>", "Wizard mode: local|remote")
.option( .option(
"--auth-choice <choice>", "--auth-choice <choice>",
"Auth: setup-token|token|chutes|openai-codex|openai-api-key|openrouter-api-key|ai-gateway-api-key|moonshot-api-key|kimi-code-api-key|synthetic-api-key|venice-api-key|gemini-api-key|zai-api-key|apiKey|minimax-api|minimax-api-lightning|opencode-zen|skip", "Auth: setup-token|claude-cli|token|chutes|openai-codex|openai-api-key|openrouter-api-key|ai-gateway-api-key|moonshot-api-key|kimi-code-api-key|synthetic-api-key|venice-api-key|fireworks-api-key|codex-cli|gemini-api-key|zai-api-key|apiKey|minimax-api|minimax-api-lightning|opencode-zen|skip",
) )
.option( .option(
"--token-provider <id>", "--token-provider <id>",
@ -75,6 +75,7 @@ export function registerOnboardCommand(program: Command) {
.option("--minimax-api-key <key>", "MiniMax API key") .option("--minimax-api-key <key>", "MiniMax API key")
.option("--synthetic-api-key <key>", "Synthetic API key") .option("--synthetic-api-key <key>", "Synthetic API key")
.option("--venice-api-key <key>", "Venice API key") .option("--venice-api-key <key>", "Venice API key")
.option("--fireworks-api-key <key>", "Fireworks API key")
.option("--opencode-zen-api-key <key>", "OpenCode Zen API key") .option("--opencode-zen-api-key <key>", "OpenCode Zen API key")
.option("--gateway-port <port>", "Gateway port") .option("--gateway-port <port>", "Gateway port")
.option("--gateway-bind <mode>", "Gateway bind: loopback|tailnet|lan|auto|custom") .option("--gateway-bind <mode>", "Gateway bind: loopback|tailnet|lan|auto|custom")
@ -125,6 +126,7 @@ export function registerOnboardCommand(program: Command) {
minimaxApiKey: opts.minimaxApiKey as string | undefined, minimaxApiKey: opts.minimaxApiKey as string | undefined,
syntheticApiKey: opts.syntheticApiKey as string | undefined, syntheticApiKey: opts.syntheticApiKey as string | undefined,
veniceApiKey: opts.veniceApiKey as string | undefined, veniceApiKey: opts.veniceApiKey as string | undefined,
fireworksApiKey: opts.fireworksApiKey as string | undefined,
opencodeZenApiKey: opts.opencodeZenApiKey as string | undefined, opencodeZenApiKey: opts.opencodeZenApiKey as string | undefined,
gatewayPort: gatewayPort:
typeof gatewayPort === "number" && Number.isFinite(gatewayPort) typeof gatewayPort === "number" && Number.isFinite(gatewayPort)

View File

@ -20,6 +20,7 @@ export type AuthChoiceGroupId =
| "minimax" | "minimax"
| "synthetic" | "synthetic"
| "venice" | "venice"
| "fireworks"
| "qwen"; | "qwen";
export type AuthChoiceGroup = { export type AuthChoiceGroup = {
@ -71,6 +72,12 @@ const AUTH_CHOICE_GROUP_DEFS: {
hint: "Privacy-focused (uncensored models)", hint: "Privacy-focused (uncensored models)",
choices: ["venice-api-key"], choices: ["venice-api-key"],
}, },
{
value: "fireworks",
label: "Fireworks AI",
hint: "US-based fast inference (DeepSeek, Qwen, Llama)",
choices: ["fireworks-api-key"],
},
{ {
value: "google", value: "google",
label: "Google", label: "Google",
@ -147,6 +154,11 @@ export function buildAuthChoiceOptions(params: {
label: "Venice AI API key", label: "Venice AI API key",
hint: "Privacy-focused inference (uncensored models)", hint: "Privacy-focused inference (uncensored models)",
}); });
options.push({
value: "fireworks-api-key",
label: "Fireworks AI API key",
hint: "US-based fast inference (DeepSeek, Qwen, Llama, and more)",
});
options.push({ options.push({
value: "github-copilot", value: "github-copilot",
label: "GitHub Copilot (GitHub device login)", label: "GitHub Copilot (GitHub device login)",

View File

@ -13,6 +13,8 @@ import {
} from "./google-gemini-model-default.js"; } from "./google-gemini-model-default.js";
import { import {
applyAuthProfileConfig, applyAuthProfileConfig,
applyFireworksConfig,
applyFireworksProviderConfig,
applyKimiCodeConfig, applyKimiCodeConfig,
applyKimiCodeProviderConfig, applyKimiCodeProviderConfig,
applyMoonshotConfig, applyMoonshotConfig,
@ -28,12 +30,14 @@ import {
applyVercelAiGatewayConfig, applyVercelAiGatewayConfig,
applyVercelAiGatewayProviderConfig, applyVercelAiGatewayProviderConfig,
applyZaiConfig, applyZaiConfig,
FIREWORKS_DEFAULT_MODEL_REF,
KIMI_CODE_MODEL_REF, KIMI_CODE_MODEL_REF,
MOONSHOT_DEFAULT_MODEL_REF, MOONSHOT_DEFAULT_MODEL_REF,
OPENROUTER_DEFAULT_MODEL_REF, OPENROUTER_DEFAULT_MODEL_REF,
SYNTHETIC_DEFAULT_MODEL_REF, SYNTHETIC_DEFAULT_MODEL_REF,
VENICE_DEFAULT_MODEL_REF, VENICE_DEFAULT_MODEL_REF,
VERCEL_AI_GATEWAY_DEFAULT_MODEL_REF, VERCEL_AI_GATEWAY_DEFAULT_MODEL_REF,
setFireworksApiKey,
setGeminiApiKey, setGeminiApiKey,
setKimiCodeApiKey, setKimiCodeApiKey,
setMoonshotApiKey, setMoonshotApiKey,
@ -83,6 +87,8 @@ export async function applyAuthChoiceApiProviders(
authChoice = "synthetic-api-key"; authChoice = "synthetic-api-key";
} else if (params.opts.tokenProvider === "venice") { } else if (params.opts.tokenProvider === "venice") {
authChoice = "venice-api-key"; authChoice = "venice-api-key";
} else if (params.opts.tokenProvider === "fireworks") {
authChoice = "fireworks-api-key";
} else if (params.opts.tokenProvider === "opencode") { } else if (params.opts.tokenProvider === "opencode") {
authChoice = "opencode-zen"; authChoice = "opencode-zen";
} }
@ -522,6 +528,65 @@ export async function applyAuthChoiceApiProviders(
return { config: nextConfig, agentModelOverride }; return { config: nextConfig, agentModelOverride };
} }
if (authChoice === "fireworks-api-key") {
let hasCredential = false;
if (!hasCredential && params.opts?.token && params.opts?.tokenProvider === "fireworks") {
await setFireworksApiKey(normalizeApiKeyInput(params.opts.token), params.agentDir);
hasCredential = true;
}
if (!hasCredential) {
await params.prompter.note(
[
"Fireworks AI provides fast serverless inference for open models.",
"Get your API key at: https://fireworks.ai/account/api-keys",
"Supports DeepSeek, Qwen, Llama, and many more models.",
].join("\n"),
"Fireworks AI",
);
}
const envKey = resolveEnvApiKey("fireworks");
if (envKey) {
const useExisting = await params.prompter.confirm({
message: `Use existing FIREWORKS_API_KEY (${envKey.source}, ${formatApiKeyPreview(envKey.apiKey)})?`,
initialValue: true,
});
if (useExisting) {
await setFireworksApiKey(envKey.apiKey, params.agentDir);
hasCredential = true;
}
}
if (!hasCredential) {
const key = await params.prompter.text({
message: "Enter Fireworks AI API key",
validate: validateApiKeyInput,
});
await setFireworksApiKey(normalizeApiKeyInput(String(key)), params.agentDir);
}
nextConfig = applyAuthProfileConfig(nextConfig, {
profileId: "fireworks:default",
provider: "fireworks",
mode: "api_key",
});
{
const applied = await applyDefaultModelChoice({
config: nextConfig,
setDefaultModel: params.setDefaultModel,
defaultModel: FIREWORKS_DEFAULT_MODEL_REF,
applyDefaultConfig: applyFireworksConfig,
applyProviderConfig: applyFireworksProviderConfig,
noteDefault: FIREWORKS_DEFAULT_MODEL_REF,
noteAgentModel,
prompter: params.prompter,
});
nextConfig = applied.config;
agentModelOverride = applied.agentModelOverride ?? agentModelOverride;
}
return { config: nextConfig, agentModelOverride };
}
if (authChoice === "opencode-zen") { if (authChoice === "opencode-zen") {
let hasCredential = false; let hasCredential = false;
if (!hasCredential && params.opts?.token && params.opts?.tokenProvider === "opencode") { if (!hasCredential && params.opts?.token && params.opts?.tokenProvider === "opencode") {

View File

@ -20,6 +20,7 @@ const PREFERRED_PROVIDER_BY_AUTH_CHOICE: Partial<Record<AuthChoice, string>> = {
"zai-api-key": "zai", "zai-api-key": "zai",
"synthetic-api-key": "synthetic", "synthetic-api-key": "synthetic",
"venice-api-key": "venice", "venice-api-key": "venice",
"fireworks-api-key": "fireworks",
"github-copilot": "github-copilot", "github-copilot": "github-copilot",
"copilot-proxy": "copilot-proxy", "copilot-proxy": "copilot-proxy",
"minimax-cloud": "minimax", "minimax-cloud": "minimax",

View File

@ -1,3 +1,9 @@
import {
buildFireworksModelDefinition,
FIREWORKS_BASE_URL,
FIREWORKS_DEFAULT_MODEL_REF,
FIREWORKS_MODEL_CATALOG,
} from "../agents/fireworks-models.js";
import { import {
buildSyntheticModelDefinition, buildSyntheticModelDefinition,
SYNTHETIC_BASE_URL, SYNTHETIC_BASE_URL,
@ -411,6 +417,83 @@ export function applyVeniceConfig(cfg: MoltbotConfig): MoltbotConfig {
}; };
} }
/**
* Apply Fireworks provider configuration without changing the default model.
* Registers Fireworks models and sets up the provider, but preserves existing model selection.
*/
export function applyFireworksProviderConfig(cfg: ClawdbotConfig): ClawdbotConfig {
const models = { ...cfg.agents?.defaults?.models };
models[FIREWORKS_DEFAULT_MODEL_REF] = {
...models[FIREWORKS_DEFAULT_MODEL_REF],
alias: models[FIREWORKS_DEFAULT_MODEL_REF]?.alias ?? "DeepSeek V3.2",
};
const providers = { ...cfg.models?.providers };
const existingProvider = providers.fireworks;
const existingModels = Array.isArray(existingProvider?.models) ? existingProvider.models : [];
const fireworksModels = FIREWORKS_MODEL_CATALOG.map(buildFireworksModelDefinition);
const mergedModels = [
...existingModels,
...fireworksModels.filter(
(model) => !existingModels.some((existing) => existing.id === model.id),
),
];
const { apiKey: existingApiKey, ...existingProviderRest } = (existingProvider ?? {}) as Record<
string,
unknown
> as { apiKey?: string };
const resolvedApiKey = typeof existingApiKey === "string" ? existingApiKey : undefined;
const normalizedApiKey = resolvedApiKey?.trim();
providers.fireworks = {
...existingProviderRest,
baseUrl: FIREWORKS_BASE_URL,
api: "openai-completions",
...(normalizedApiKey ? { apiKey: normalizedApiKey } : {}),
models: mergedModels.length > 0 ? mergedModels : fireworksModels,
};
return {
...cfg,
agents: {
...cfg.agents,
defaults: {
...cfg.agents?.defaults,
models,
},
},
models: {
mode: cfg.models?.mode ?? "merge",
providers,
},
};
}
/**
* Apply Fireworks provider configuration AND set Fireworks as the default model.
* Use this when Fireworks is the primary provider choice during onboarding.
*/
export function applyFireworksConfig(cfg: ClawdbotConfig): ClawdbotConfig {
const next = applyFireworksProviderConfig(cfg);
const existingModel = next.agents?.defaults?.model;
return {
...next,
agents: {
...next.agents,
defaults: {
...next.agents?.defaults,
model: {
...(existingModel && "fallbacks" in (existingModel as Record<string, unknown>)
? {
fallbacks: (existingModel as { fallbacks?: string[] }).fallbacks,
}
: undefined),
primary: FIREWORKS_DEFAULT_MODEL_REF,
},
},
},
};
}
export function applyAuthProfileConfig( export function applyAuthProfileConfig(
cfg: MoltbotConfig, cfg: MoltbotConfig,
params: { params: {

View File

@ -112,6 +112,19 @@ export async function setVeniceApiKey(key: string, agentDir?: string) {
}); });
} }
export async function setFireworksApiKey(key: string, agentDir?: string) {
// Write to resolved agent dir so gateway finds credentials on startup.
upsertAuthProfile({
profileId: "fireworks:default",
credential: {
type: "api_key",
provider: "fireworks",
key,
},
agentDir: resolveAuthAgentDir(agentDir),
});
}
export const ZAI_DEFAULT_MODEL_REF = "zai/glm-4.7"; export const ZAI_DEFAULT_MODEL_REF = "zai/glm-4.7";
export const OPENROUTER_DEFAULT_MODEL_REF = "openrouter/auto"; export const OPENROUTER_DEFAULT_MODEL_REF = "openrouter/auto";
export const VERCEL_AI_GATEWAY_DEFAULT_MODEL_REF = "vercel-ai-gateway/anthropic/claude-opus-4.5"; export const VERCEL_AI_GATEWAY_DEFAULT_MODEL_REF = "vercel-ai-gateway/anthropic/claude-opus-4.5";

View File

@ -1,3 +1,7 @@
export {
FIREWORKS_DEFAULT_MODEL_ID,
FIREWORKS_DEFAULT_MODEL_REF,
} from "../agents/fireworks-models.js";
export { export {
SYNTHETIC_DEFAULT_MODEL_ID, SYNTHETIC_DEFAULT_MODEL_ID,
SYNTHETIC_DEFAULT_MODEL_REF, SYNTHETIC_DEFAULT_MODEL_REF,
@ -5,6 +9,8 @@ export {
export { VENICE_DEFAULT_MODEL_ID, VENICE_DEFAULT_MODEL_REF } from "../agents/venice-models.js"; export { VENICE_DEFAULT_MODEL_ID, VENICE_DEFAULT_MODEL_REF } from "../agents/venice-models.js";
export { export {
applyAuthProfileConfig, applyAuthProfileConfig,
applyFireworksConfig,
applyFireworksProviderConfig,
applyKimiCodeConfig, applyKimiCodeConfig,
applyKimiCodeProviderConfig, applyKimiCodeProviderConfig,
applyMoonshotConfig, applyMoonshotConfig,
@ -35,6 +41,7 @@ export {
export { export {
OPENROUTER_DEFAULT_MODEL_REF, OPENROUTER_DEFAULT_MODEL_REF,
setAnthropicApiKey, setAnthropicApiKey,
setFireworksApiKey,
setGeminiApiKey, setGeminiApiKey,
setKimiCodeApiKey, setKimiCodeApiKey,
setMinimaxApiKey, setMinimaxApiKey,

View File

@ -8,6 +8,7 @@ import { buildTokenProfileId, validateAnthropicSetupToken } from "../../auth-tok
import { applyGoogleGeminiModelDefault } from "../../google-gemini-model-default.js"; import { applyGoogleGeminiModelDefault } from "../../google-gemini-model-default.js";
import { import {
applyAuthProfileConfig, applyAuthProfileConfig,
applyFireworksConfig,
applyKimiCodeConfig, applyKimiCodeConfig,
applyMinimaxApiConfig, applyMinimaxApiConfig,
applyMinimaxConfig, applyMinimaxConfig,
@ -19,6 +20,7 @@ import {
applyVercelAiGatewayConfig, applyVercelAiGatewayConfig,
applyZaiConfig, applyZaiConfig,
setAnthropicApiKey, setAnthropicApiKey,
setFireworksApiKey,
setGeminiApiKey, setGeminiApiKey,
setKimiCodeApiKey, setKimiCodeApiKey,
setMinimaxApiKey, setMinimaxApiKey,
@ -309,6 +311,25 @@ export async function applyNonInteractiveAuthChoice(params: {
return applyVeniceConfig(nextConfig); return applyVeniceConfig(nextConfig);
} }
if (authChoice === "fireworks-api-key") {
const resolved = await resolveNonInteractiveApiKey({
provider: "fireworks",
cfg: baseConfig,
flagValue: opts.fireworksApiKey,
flagName: "--fireworks-api-key",
envVar: "FIREWORKS_API_KEY",
runtime,
});
if (!resolved) return null;
if (resolved.source !== "profile") await setFireworksApiKey(resolved.key);
nextConfig = applyAuthProfileConfig(nextConfig, {
profileId: "fireworks:default",
provider: "fireworks",
mode: "api_key",
});
return applyFireworksConfig(nextConfig);
}
if ( if (
authChoice === "minimax-cloud" || authChoice === "minimax-cloud" ||
authChoice === "minimax-api" || authChoice === "minimax-api" ||

View File

@ -17,6 +17,7 @@ export type AuthChoice =
| "kimi-code-api-key" | "kimi-code-api-key"
| "synthetic-api-key" | "synthetic-api-key"
| "venice-api-key" | "venice-api-key"
| "fireworks-api-key"
| "codex-cli" | "codex-cli"
| "apiKey" | "apiKey"
| "gemini-api-key" | "gemini-api-key"
@ -70,6 +71,7 @@ export type OnboardOptions = {
minimaxApiKey?: string; minimaxApiKey?: string;
syntheticApiKey?: string; syntheticApiKey?: string;
veniceApiKey?: string; veniceApiKey?: string;
fireworksApiKey?: string;
opencodeZenApiKey?: string; opencodeZenApiKey?: string;
gatewayPort?: number; gatewayPort?: number;
gatewayBind?: GatewayBind; gatewayBind?: GatewayBind;