feat(providers): add Fireworks AI provider integration
- Add fireworks-models.ts with static catalog of 24 serverless LLM models - Add dynamic model discovery from Fireworks API with pagination - Integrate into onboarding (interactive + non-interactive flows) - Add fireworks-api-key auth choice and --fireworks-api-key CLI flag - Add FIREWORKS_API_KEY to envMap for auto-detection - Add Fireworks to resolveImplicitProviders - Add docs/providers/fireworks.md documentation - Update docs navigation and CLI reference Model IDs use full format: accounts/fireworks/models/<model> Default model: deepseek-v3p2 (DeepSeek V3.2)
This commit is contained in:
parent
6cbdd767af
commit
4bf61bc930
@ -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>`
|
||||||
|
|||||||
@ -1012,6 +1012,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"
|
||||||
|
|||||||
251
docs/providers/fireworks.md
Normal file
251
docs/providers/fireworks.md
Normal file
@ -0,0 +1,251 @@
|
|||||||
|
---
|
||||||
|
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
|
||||||
|
|
||||||
|
## 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. Discover available Fireworks models via API
|
||||||
|
3. Let you pick your default model
|
||||||
|
4. Configure 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
|
||||||
|
|
||||||
|
After setup, Clawdbot discovers models from the Fireworks API. 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, reasoning support |
|
||||||
|
| **Complex reasoning** | `deepseek-r1-0528` | Best for step-by-step reasoning |
|
||||||
|
| **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 (24 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 | Reasoning |
|
||||||
|
| `glm-4p6` | GLM-4.6 | 202k | General |
|
||||||
|
| `glm-4p7` | GLM-4.7 | 202k | Reasoning |
|
||||||
|
| `gpt-oss-120b` | OpenAI gpt-oss-120b | 131k | General |
|
||||||
|
| `gpt-oss-20b` | OpenAI gpt-oss-20b | 131k | General |
|
||||||
|
| `kimi-k2-instruct-0905` | Kimi K2 Instruct 0905 | 262k | Long context |
|
||||||
|
| `kimi-k2-thinking` | Kimi K2 Thinking | 256k | Reasoning |
|
||||||
|
| `llama-v3p3-70b-instruct` | Llama 3.3 70B Instruct | 131k | General |
|
||||||
|
| `minimax-m2` | MiniMax-M2 | 196k | General |
|
||||||
|
| `minimax-m2p1` | MiniMax-M2.1 | 204k | General |
|
||||||
|
| `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-thinking` | Qwen3 VL 30B A3B Thinking | 262k | Vision, reasoning |
|
||||||
|
|
||||||
|
## Model Discovery
|
||||||
|
|
||||||
|
Clawdbot automatically discovers models from the Fireworks API when `FIREWORKS_API_KEY` is set. The discovery:
|
||||||
|
|
||||||
|
- Fetches all serverless models (`supports_serverless=true`)
|
||||||
|
- Filters out deprecated models
|
||||||
|
- Filters out non-LLM models (image generation)
|
||||||
|
- Falls back to a static catalog if the API is unreachable
|
||||||
|
|
||||||
|
## 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
|
||||||
|
|
||||||
|
The Fireworks model catalog updates dynamically. Run `clawdbot models list` to see currently available models. Some models may be temporarily offline or deprecated.
|
||||||
|
|
||||||
|
### Connection issues
|
||||||
|
|
||||||
|
Fireworks API is at `https://api.fireworks.ai`. Ensure your network allows HTTPS connections.
|
||||||
|
|
||||||
|
### Model discovery fails
|
||||||
|
|
||||||
|
If model discovery fails, Clawdbot falls back to a static catalog of popular models. Check your API key and network connection.
|
||||||
|
|
||||||
|
## 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: true,
|
||||||
|
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)
|
||||||
@ -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
|
||||||
|
|||||||
373
src/agents/fireworks-models.ts
Normal file
373
src/agents/fireworks-models.ts
Normal file
@ -0,0 +1,373 @@
|
|||||||
|
import type { ModelDefinitionConfig } from "../config/types.js";
|
||||||
|
|
||||||
|
export const FIREWORKS_BASE_URL = "https://api.fireworks.ai/inference/v1";
|
||||||
|
export const FIREWORKS_API_BASE_URL = "https://api.fireworks.ai";
|
||||||
|
export const FIREWORKS_ACCOUNT_ID = "fireworks";
|
||||||
|
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.
|
||||||
|
*
|
||||||
|
* This catalog serves as a fallback when the Fireworks API is unreachable.
|
||||||
|
* 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: true,
|
||||||
|
input: ["text"] as const,
|
||||||
|
contextWindow: 163840,
|
||||||
|
maxTokens: 8192,
|
||||||
|
},
|
||||||
|
|
||||||
|
// GLM models
|
||||||
|
{
|
||||||
|
id: "accounts/fireworks/models/glm-4p6",
|
||||||
|
name: "GLM-4.6",
|
||||||
|
reasoning: false,
|
||||||
|
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
|
||||||
|
{
|
||||||
|
id: "accounts/fireworks/models/gpt-oss-120b",
|
||||||
|
name: "OpenAI gpt-oss-120b",
|
||||||
|
reasoning: false,
|
||||||
|
input: ["text"] as const,
|
||||||
|
contextWindow: 131072,
|
||||||
|
maxTokens: 8192,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "accounts/fireworks/models/gpt-oss-20b",
|
||||||
|
name: "OpenAI gpt-oss-20b",
|
||||||
|
reasoning: false,
|
||||||
|
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-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
|
||||||
|
{
|
||||||
|
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-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,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fireworks API response types
|
||||||
|
interface FireworksModel {
|
||||||
|
name: string; // Full resource name: accounts/fireworks/models/<id>
|
||||||
|
displayName?: string;
|
||||||
|
description?: string;
|
||||||
|
contextLength?: number;
|
||||||
|
kind?: string; // HF_BASE_MODEL, FLUMINA_BASE_MODEL, etc.
|
||||||
|
supportsImageInput?: boolean;
|
||||||
|
supportsTools?: boolean;
|
||||||
|
supportsServerless?: boolean;
|
||||||
|
deprecationDate?: { year: number; month: number; day: number } | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface FireworksModelsResponse {
|
||||||
|
models: FireworksModel[];
|
||||||
|
nextPageToken?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
function isDeprecated(
|
||||||
|
deprecationDate?: { year: number; month: number; day: number } | null,
|
||||||
|
): boolean {
|
||||||
|
if (!deprecationDate) return false;
|
||||||
|
const { year, month, day } = deprecationDate;
|
||||||
|
const depDate = new Date(year, month - 1, day);
|
||||||
|
return depDate < new Date();
|
||||||
|
}
|
||||||
|
|
||||||
|
function isLlmModel(model: FireworksModel): boolean {
|
||||||
|
// Skip image generation models (FLUX, etc.) - they use FLUMINA_BASE_MODEL kind
|
||||||
|
// and have contextLength of 0
|
||||||
|
if (model.kind === "FLUMINA_BASE_MODEL") return false;
|
||||||
|
if (!model.contextLength || model.contextLength === 0) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Discover serverless LLM models from Fireworks API with fallback to static catalog.
|
||||||
|
*/
|
||||||
|
export async function discoverFireworksModels(params?: {
|
||||||
|
apiKey?: string;
|
||||||
|
}): Promise<ModelDefinitionConfig[]> {
|
||||||
|
// Skip API discovery in test environment
|
||||||
|
if (process.env.NODE_ENV === "test" || process.env.VITEST) {
|
||||||
|
return FIREWORKS_MODEL_CATALOG.map(buildFireworksModelDefinition);
|
||||||
|
}
|
||||||
|
|
||||||
|
const apiKey = params?.apiKey ?? process.env.FIREWORKS_API_KEY;
|
||||||
|
if (!apiKey) {
|
||||||
|
console.warn("[fireworks-models] No API key available, using static catalog");
|
||||||
|
return FIREWORKS_MODEL_CATALOG.map(buildFireworksModelDefinition);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const allModels: FireworksModel[] = [];
|
||||||
|
let pageToken: string | undefined;
|
||||||
|
|
||||||
|
// Paginate through results
|
||||||
|
do {
|
||||||
|
const url = new URL(`${FIREWORKS_API_BASE_URL}/v1/accounts/${FIREWORKS_ACCOUNT_ID}/models`);
|
||||||
|
url.searchParams.set("filter", "supports_serverless=true");
|
||||||
|
url.searchParams.set("pageSize", "200");
|
||||||
|
if (pageToken) {
|
||||||
|
url.searchParams.set("pageToken", pageToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await fetch(url.toString(), {
|
||||||
|
headers: { Authorization: `Bearer ${apiKey}` },
|
||||||
|
signal: AbortSignal.timeout(10000),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
console.warn(
|
||||||
|
`[fireworks-models] Failed to list models: HTTP ${response.status}, using static catalog`,
|
||||||
|
);
|
||||||
|
return FIREWORKS_MODEL_CATALOG.map(buildFireworksModelDefinition);
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = (await response.json()) as FireworksModelsResponse;
|
||||||
|
allModels.push(...(data.models ?? []));
|
||||||
|
pageToken = data.nextPageToken;
|
||||||
|
} while (pageToken);
|
||||||
|
|
||||||
|
// Filter and build model definitions
|
||||||
|
const catalogById = new Map<string, FireworksCatalogEntry>(
|
||||||
|
FIREWORKS_MODEL_CATALOG.map((m) => [m.id, m]),
|
||||||
|
);
|
||||||
|
const models: ModelDefinitionConfig[] = [];
|
||||||
|
|
||||||
|
for (const apiModel of allModels) {
|
||||||
|
// Skip deprecated models
|
||||||
|
if (isDeprecated(apiModel.deprecationDate)) continue;
|
||||||
|
// Skip non-LLM models (image gen, etc.)
|
||||||
|
if (!isLlmModel(apiModel)) continue;
|
||||||
|
|
||||||
|
// Use the full name as the ID (accounts/fireworks/models/<model>)
|
||||||
|
const id = apiModel.name;
|
||||||
|
const catalogEntry = catalogById.get(id);
|
||||||
|
|
||||||
|
if (catalogEntry) {
|
||||||
|
// Use catalog metadata for known models
|
||||||
|
models.push(buildFireworksModelDefinition(catalogEntry));
|
||||||
|
} else {
|
||||||
|
// Create definition for newly discovered models not in catalog
|
||||||
|
const isReasoning =
|
||||||
|
id.toLowerCase().includes("r1") ||
|
||||||
|
id.toLowerCase().includes("thinking") ||
|
||||||
|
id.toLowerCase().includes("reasoning") ||
|
||||||
|
(apiModel.description?.toLowerCase().includes("reasoning") ?? false);
|
||||||
|
|
||||||
|
models.push({
|
||||||
|
id,
|
||||||
|
name: apiModel.displayName ?? id.replace(/^accounts\/fireworks\/models\//, ""),
|
||||||
|
reasoning: isReasoning,
|
||||||
|
input: apiModel.supportsImageInput ? ["text", "image"] : ["text"],
|
||||||
|
cost: FIREWORKS_DEFAULT_COST,
|
||||||
|
contextWindow: apiModel.contextLength ?? 128000,
|
||||||
|
maxTokens: 8192,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return models.length > 0 ? models : FIREWORKS_MODEL_CATALOG.map(buildFireworksModelDefinition);
|
||||||
|
} catch (error) {
|
||||||
|
console.warn(`[fireworks-models] Discovery failed: ${String(error)}, using static catalog`);
|
||||||
|
return FIREWORKS_MODEL_CATALOG.map(buildFireworksModelDefinition);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -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",
|
||||||
};
|
};
|
||||||
|
|||||||
@ -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<ClawdbotConfig["models"]>;
|
type ModelsConfig = NonNullable<ClawdbotConfig["models"]>;
|
||||||
@ -350,6 +351,15 @@ async function buildVeniceProvider(): Promise<ProviderConfig> {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function buildFireworksProvider(apiKey?: string): Promise<ProviderConfig> {
|
||||||
|
const models = await discoverFireworksModels({ apiKey });
|
||||||
|
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 = { ...(await buildFireworksProvider(fireworksKey)), 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"] = {
|
||||||
|
|||||||
@ -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)
|
||||||
|
|||||||
@ -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: "Serverless 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: "Serverless 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)",
|
||||||
|
|||||||
@ -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") {
|
||||||
|
|||||||
@ -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",
|
||||||
|
|||||||
@ -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: ClawdbotConfig): ClawdbotConfig {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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: ClawdbotConfig,
|
cfg: ClawdbotConfig,
|
||||||
params: {
|
params: {
|
||||||
|
|||||||
@ -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";
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
@ -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" ||
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user