Merge pull request #1 from Veightor/main

Changes from V
This commit is contained in:
V 2026-01-26 16:28:37 -05:00 committed by GitHub
commit 5d05d3eb5f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
19 changed files with 445 additions and 3 deletions

83
docs/providers/chutes.md Normal file
View File

@ -0,0 +1,83 @@
---
summary: "Use Chutes AI with Clawdbot"
read_when:
- You want to use Chutes AI models in Clawdbot
- You need to configure Chutes via OAuth or API key
---
# Chutes AI
Chutes provides high-performance inference for open-weight models, including GLM 4.7 Flash. Clawdbot supports Chutes via both OAuth and API key authentication.
Models are fetched dynamically from the Chutes API, ensuring you always have access to the latest models, accurate pricing, and context window limits.
## CLI setup
To configure Chutes with an API key:
```bash
clawdbot onboard --auth-choice chutes-api-key
# or non-interactive
clawdbot onboard --chutes-api-key "$CHUTES_API_KEY"
```
To configure Chutes with OAuth (browser-based):
```bash
clawdbot onboard --auth-choice chutes
```
OAuth allows you to use your Chutes account without manually managing API keys. Clawdbot uses the standard [Sign in with Chutes](https://github.com/chutesai/Sign-in-with-Chutes) flow.
### OAuth Scopes
Clawdbot requests the following scopes by default:
- `openid` (Required for authentication)
- `profile` (Access to username)
- `chutes:invoke` (Required to make AI API calls on your behalf)
### Custom OAuth App (Advanced)
If you wish to use your own OAuth application instead of the default, set these environment variables before running onboarding:
- `CHUTES_CLIENT_ID`: Your OAuth client ID
- `CHUTES_CLIENT_SECRET`: Your OAuth client secret (if applicable)
- `CHUTES_OAUTH_REDIRECT_URI`: Your redirect URI (default: `http://127.0.0.1:1456/oauth-callback`)
## Config snippet
```json5
{
env: { CHUTES_API_KEY: "sk-..." },
agents: { defaults: { model: { primary: "chutes/zai-org/GLM-4.7-Flash" } } },
models: {
providers: {
chutes: {
baseUrl: "https://llm.chutes.ai/v1",
api: "openai-completions",
apiKey: "${CHUTES_API_KEY}",
teeOnly: false // Set to true to filter models by Trusted Execution Environment
}
}
}
}
```
## Notes
- Chutes models are available under the `chutes/` provider prefix.
- The default model is `chutes/zai-org/GLM-4.7-Flash`.
- Chutes uses OpenAI-compatible endpoints.
- **Trusted Execution Environment (TEE)**: Models running in a TEE are marked with a "TEE" badge in the model picker. You can filter for these models by setting `teeOnly: true` in your provider config.
- Many top models on Chutes support tool calling, including:
- `Qwen/Qwen3-235B-A22B-Instruct-2507-TEE` (TEE)
- `deepseek-ai/DeepSeek-V3.2-TEE` (TEE)
- `chutesai/Mistral-Small-3.1-24B-Instruct-2503`
- `NousResearch/Hermes-4-14B`
- For a full list of available models, see the [Chutes Models API](https://llm.chutes.ai/v1/models). Popular models include:
- `deepseek-ai/DeepSeek-V3.2-TEE`
- `Qwen/Qwen3-235B-A22B-Instruct-2507-TEE`
- `mistralai/Mistral-Small-24B-Instruct-2501-TEE`
- `NousResearch/Hermes-4-14B`

View File

@ -40,6 +40,7 @@ See [Venice AI](/providers/venice).
- [Vercel AI Gateway](/providers/vercel-ai-gateway)
- [Moonshot AI (Kimi + Kimi Code)](/providers/moonshot)
- [OpenCode Zen](/providers/opencode)
- [Chutes AI](/providers/chutes)
- [Amazon Bedrock](/bedrock)
- [Z.AI](/providers/zai)
- [GLM models](/providers/glm)

View File

@ -0,0 +1,76 @@
import type { ModelDefinitionConfig } from "../config/types.models.js";
export const CHUTES_BASE_URL = "https://llm.chutes.ai/v1";
export const CHUTES_DEFAULT_MODEL_ID = "zai-org/GLM-4.7-Flash";
export const CHUTES_DEFAULT_MODEL_REF = `chutes/${CHUTES_DEFAULT_MODEL_ID}`;
export interface ChutesModelEntry {
id: string;
name?: string;
context_length?: number;
max_output_length?: number;
confidential_compute?: boolean;
pricing?: { prompt: number; completion: number };
supported_features?: string[];
}
export async function fetchChutesModels(): Promise<ChutesModelEntry[]> {
try {
const response = await fetch(`${CHUTES_BASE_URL}/models`, {
signal: AbortSignal.timeout(5000),
});
if (!response.ok) {
throw new Error(`Failed to fetch Chutes models: ${response.statusText}`);
}
const data = (await response.json()) as { data: ChutesModelEntry[] };
return data.data || [];
} catch (error) {
console.warn(`[chutes-models] Failed to fetch models: ${String(error)}`);
return [];
}
}
export function mapChutesModelToDefinition(entry: ChutesModelEntry): ModelDefinitionConfig {
return {
id: entry.id,
name: entry.name || entry.id,
reasoning: entry.supported_features?.includes("reasoning") ?? false,
input: ["text"],
cost: {
input: entry.pricing?.prompt ?? 0,
output: entry.pricing?.completion ?? 0,
cacheRead: 0,
cacheWrite: 0,
},
contextWindow: entry.context_length || 128000,
maxTokens: entry.max_output_length || 4096,
confidentialCompute: entry.confidential_compute,
};
}
export async function discoverChutesModels(opts?: {
teeOnly?: boolean;
}): Promise<ModelDefinitionConfig[]> {
const models = await fetchChutesModels();
if (models.length === 0) {
// Fallback to minimal list
return [
{
id: CHUTES_DEFAULT_MODEL_ID,
name: "GLM 4.7 Flash",
reasoning: false,
input: ["text"],
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
contextWindow: 128000,
maxTokens: 4096,
},
];
}
let filtered = models;
if (opts?.teeOnly) {
filtered = models.filter((m) => m.confidential_compute === true);
}
return filtered.map(mapChutesModelToDefinition);
}

View File

@ -278,6 +278,7 @@ export function resolveEnvApiKey(provider: string): EnvApiKeyResult | null {
xai: "XAI_API_KEY",
openrouter: "OPENROUTER_API_KEY",
"vercel-ai-gateway": "AI_GATEWAY_API_KEY",
chutes: "CHUTES_API_KEY",
moonshot: "MOONSHOT_API_KEY",
"kimi-code": "KIMICODE_API_KEY",
minimax: "MINIMAX_API_KEY",

View File

@ -8,6 +8,7 @@ export type ModelCatalogEntry = {
provider: string;
contextWindow?: number;
reasoning?: boolean;
confidentialCompute?: boolean;
input?: Array<"text" | "image">;
};
@ -17,6 +18,7 @@ type DiscoveredModel = {
provider: string;
contextWindow?: number;
reasoning?: boolean;
confidentialCompute?: boolean;
input?: Array<"text" | "image">;
};
@ -82,10 +84,12 @@ export async function loadModelCatalog(params?: {
? entry.contextWindow
: undefined;
const reasoning = typeof entry?.reasoning === "boolean" ? entry.reasoning : undefined;
const confidentialCompute =
typeof entry?.confidentialCompute === "boolean" ? entry.confidentialCompute : undefined;
const input = Array.isArray(entry?.input)
? (entry.input as Array<"text" | "image">)
: undefined;
models.push({ id, name, provider, contextWindow, reasoning, input });
models.push({ id, name, provider, contextWindow, reasoning, confidentialCompute, input });
}
if (models.length === 0) {

View File

@ -7,6 +7,7 @@ import {
import { ensureAuthProfileStore, listProfilesForProvider } from "./auth-profiles.js";
import { resolveAwsSdkEnvVarName, resolveEnvApiKey } from "./model-auth.js";
import { discoverBedrockModels } from "./bedrock-discovery.js";
import { discoverChutesModels } from "./chutes-models.js";
import {
buildSyntheticModelDefinition,
SYNTHETIC_BASE_URL,
@ -40,6 +41,9 @@ const MOONSHOT_DEFAULT_COST = {
cacheRead: 0,
cacheWrite: 0,
};
const CHUTES_BASE_URL = "https://llm.chutes.ai/v1";
const KIMI_CODE_BASE_URL = "https://api.kimi.com/coding/v1";
const KIMI_CODE_MODEL_ID = "kimi-for-coding";
const KIMI_CODE_CONTEXT_WINDOW = 262144;
@ -286,6 +290,16 @@ function buildMoonshotProvider(): ProviderConfig {
};
}
async function buildChutesProvider(opts?: { teeOnly?: boolean }): Promise<ProviderConfig> {
const models = await discoverChutesModels(opts);
return {
baseUrl: CHUTES_BASE_URL,
api: "openai-completions",
models,
teeOnly: opts?.teeOnly,
};
}
function buildKimiCodeProvider(): ProviderConfig {
return {
baseUrl: KIMI_CODE_BASE_URL,
@ -381,6 +395,13 @@ export async function resolveImplicitProviders(params: {
providers.moonshot = { ...buildMoonshotProvider(), apiKey: moonshotKey };
}
const chutesKey =
resolveEnvApiKeyVarName("chutes") ??
resolveApiKeyFromProfiles({ provider: "chutes", store: authStore });
if (chutesKey) {
providers.chutes = { ...(await buildChutesProvider()), apiKey: chutesKey };
}
const kimiCodeKey =
resolveEnvApiKeyVarName("kimi-code") ??
resolveApiKeyFromProfiles({ provider: "kimi-code", store: authStore });

View File

@ -52,7 +52,7 @@ export function registerOnboardCommand(program: Command) {
.option("--mode <mode>", "Wizard mode: local|remote")
.option(
"--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|chutes-api-key|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|codex-cli|gemini-api-key|zai-api-key|apiKey|minimax-api|minimax-api-lightning|opencode-zen|skip",
)
.option(
"--token-provider <id>",
@ -69,12 +69,13 @@ export function registerOnboardCommand(program: Command) {
.option("--openrouter-api-key <key>", "OpenRouter API key")
.option("--ai-gateway-api-key <key>", "Vercel AI Gateway API key")
.option("--moonshot-api-key <key>", "Moonshot API key")
.option("--chutes-api-key <key>", "Chutes API key")
.option("--kimi-code-api-key <key>", "Kimi Code API key")
.option("--gemini-api-key <key>", "Gemini API key")
.option("--zai-api-key <key>", "Z.AI API key")
.option("--minimax-api-key <key>", "MiniMax API key")
.option("--synthetic-api-key <key>", "Synthetic API key")
.option("--venice-api-key <key>", "Venice API key")
.option("--venice-api-key <key>", "Venice AI API key")
.option("--opencode-zen-api-key <key>", "OpenCode Zen API key")
.option("--gateway-port <port>", "Gateway port")
.option("--gateway-bind <mode>", "Gateway bind: loopback|tailnet|lan|auto|custom")
@ -119,6 +120,7 @@ export function registerOnboardCommand(program: Command) {
openrouterApiKey: opts.openrouterApiKey as string | undefined,
aiGatewayApiKey: opts.aiGatewayApiKey as string | undefined,
moonshotApiKey: opts.moonshotApiKey as string | undefined,
chutesApiKey: opts.chutesApiKey as string | undefined,
kimiCodeApiKey: opts.kimiCodeApiKey as string | undefined,
geminiApiKey: opts.geminiApiKey as string | undefined,
zaiApiKey: opts.zaiApiKey as string | undefined,

View File

@ -16,6 +16,7 @@ export type AuthChoiceGroupId =
| "ai-gateway"
| "moonshot"
| "zai"
| "chutes"
| "opencode-zen"
| "minimax"
| "synthetic"
@ -101,6 +102,12 @@ const AUTH_CHOICE_GROUP_DEFS: {
hint: "Kimi K2 + Kimi Code",
choices: ["moonshot-api-key", "kimi-code-api-key"],
},
{
value: "chutes",
label: "Chutes",
hint: "OAuth + API key",
choices: ["chutes", "chutes-api-key"],
},
{
value: "zai",
label: "Z.AI (GLM 4.7)",
@ -133,6 +140,7 @@ export function buildAuthChoiceOptions(params: {
label: "OpenAI Codex (ChatGPT OAuth)",
});
options.push({ value: "chutes", label: "Chutes (OAuth)" });
options.push({ value: "chutes-api-key", label: "Chutes API key" });
options.push({ value: "openai-api-key", label: "OpenAI API key" });
options.push({ value: "openrouter-api-key", label: "OpenRouter API key" });
options.push({

View File

@ -13,6 +13,8 @@ import {
} from "./google-gemini-model-default.js";
import {
applyAuthProfileConfig,
applyChutesConfig,
applyChutesProviderConfig,
applyKimiCodeConfig,
applyKimiCodeProviderConfig,
applyMoonshotConfig,
@ -34,6 +36,8 @@ import {
SYNTHETIC_DEFAULT_MODEL_REF,
VENICE_DEFAULT_MODEL_REF,
VERCEL_AI_GATEWAY_DEFAULT_MODEL_REF,
CHUTES_DEFAULT_MODEL_REF,
setChutesApiKey,
setGeminiApiKey,
setKimiCodeApiKey,
setMoonshotApiKey,
@ -265,6 +269,53 @@ export async function applyAuthChoiceApiProviders(
return { config: nextConfig, agentModelOverride };
}
if (authChoice === "chutes-api-key") {
let hasCredential = false;
if (!hasCredential && params.opts?.token && params.opts?.tokenProvider === "chutes") {
await setChutesApiKey(normalizeApiKeyInput(params.opts.token), params.agentDir);
hasCredential = true;
}
const envKey = resolveEnvApiKey("chutes");
if (envKey) {
const useExisting = await params.prompter.confirm({
message: `Use existing CHUTES_API_KEY (${envKey.source}, ${formatApiKeyPreview(envKey.apiKey)})?`,
initialValue: true,
});
if (useExisting) {
await setChutesApiKey(envKey.apiKey, params.agentDir);
hasCredential = true;
}
}
if (!hasCredential) {
const key = await params.prompter.text({
message: "Enter Chutes API key",
validate: validateApiKeyInput,
});
await setChutesApiKey(normalizeApiKeyInput(String(key)), params.agentDir);
}
nextConfig = applyAuthProfileConfig(nextConfig, {
profileId: "chutes:default",
provider: "chutes",
mode: "api_key",
});
{
const applied = await applyDefaultModelChoice({
config: nextConfig,
setDefaultModel: params.setDefaultModel,
defaultModel: CHUTES_DEFAULT_MODEL_REF,
applyDefaultConfig: applyChutesConfig,
applyProviderConfig: applyChutesProviderConfig,
noteAgentModel,
prompter: params.prompter,
});
nextConfig = applied.config;
agentModelOverride = applied.agentModelOverride ?? agentModelOverride;
}
return { config: nextConfig, agentModelOverride };
}
if (authChoice === "kimi-code-api-key") {
let hasCredential = false;
if (!hasCredential && params.opts?.token && params.opts?.tokenProvider === "kimi-code") {

View File

@ -9,6 +9,7 @@ const PREFERRED_PROVIDER_BY_AUTH_CHOICE: Partial<Record<AuthChoice, string>> = {
"openai-codex": "openai-codex",
"codex-cli": "openai-codex",
chutes: "chutes",
"chutes-api-key": "chutes",
"openai-api-key": "openai",
"openrouter-api-key": "openrouter",
"ai-gateway-api-key": "vercel-ai-gateway",

View File

@ -205,6 +205,7 @@ export async function promptDefaultModel(
name?: string;
contextWindow?: number;
reasoning?: boolean;
confidentialCompute?: boolean;
}) => {
const key = modelKey(entry.provider, entry.id);
if (seen.has(key)) return;
@ -214,6 +215,7 @@ export async function promptDefaultModel(
if (entry.name && entry.name !== entry.id) hints.push(entry.name);
if (entry.contextWindow) hints.push(`ctx ${formatTokenK(entry.contextWindow)}`);
if (entry.reasoning) hints.push("reasoning");
if (entry.confidentialCompute) hints.push("TEE");
const aliases = aliasIndex.byKey.get(key);
if (aliases?.length) hints.push(`alias: ${aliases.join(", ")}`);
if (!hasAuth(entry.provider)) hints.push("auth missing");
@ -341,6 +343,7 @@ export async function promptModelAllowlist(params: {
if (entry.name && entry.name !== entry.id) hints.push(entry.name);
if (entry.contextWindow) hints.push(`ctx ${formatTokenK(entry.contextWindow)}`);
if (entry.reasoning) hints.push("reasoning");
if ((entry as any).confidentialCompute) hints.push("TEE");
const aliases = aliasIndex.byKey.get(key);
if (aliases?.length) hints.push(`alias: ${aliases.join(", ")}`);
if (!hasAuth(entry.provider)) hints.push("auth missing");

View File

@ -80,6 +80,11 @@ export function toModelRow(params: {
: (availableKeys?.has(modelKey(model.provider, model.id)) ?? false);
const aliasTags = aliases.length > 0 ? [`alias:${aliases.join(",")}`] : [];
const mergedTags = new Set(tags);
if ((model as any).confidentialCompute) {
mergedTags.add("TEE");
}
if (aliasTags.length > 0) {
for (const tag of mergedTags) {
if (tag === "alias" || tag.startsWith("alias:")) mergedTags.delete(tag);

View File

@ -25,6 +25,9 @@ import {
MOONSHOT_BASE_URL,
MOONSHOT_DEFAULT_MODEL_ID,
MOONSHOT_DEFAULT_MODEL_REF,
CHUTES_BASE_URL,
CHUTES_DEFAULT_MODEL_REF,
buildChutesModelDefinition,
} from "./onboard-auth.models.js";
export function applyZaiConfig(cfg: ClawdbotConfig): ClawdbotConfig {
@ -202,6 +205,70 @@ export function applyMoonshotConfig(cfg: ClawdbotConfig): ClawdbotConfig {
};
}
export function applyChutesProviderConfig(cfg: ClawdbotConfig): ClawdbotConfig {
const models = { ...cfg.agents?.defaults?.models };
models[CHUTES_DEFAULT_MODEL_REF] = {
...models[CHUTES_DEFAULT_MODEL_REF],
alias: models[CHUTES_DEFAULT_MODEL_REF]?.alias ?? "GLM 4.7 Flash",
};
const providers = { ...cfg.models?.providers };
const existingProvider = providers.chutes;
const { apiKey: existingApiKey, ...existingProviderRest } = (existingProvider ?? {}) as Record<
string,
unknown
> as { apiKey?: string; teeOnly?: boolean };
const resolvedApiKey = typeof existingApiKey === "string" ? existingApiKey : undefined;
const normalizedApiKey = resolvedApiKey?.trim();
providers.chutes = {
...existingProviderRest,
baseUrl: CHUTES_BASE_URL,
api: "openai-completions",
...(normalizedApiKey ? { apiKey: normalizedApiKey } : {}),
// Models will be refreshed dynamically at startup,
// but we can pre-populate the default one for onboarding.
models: existingProvider?.models || [buildChutesModelDefinition()],
};
return {
...cfg,
agents: {
...cfg.agents,
defaults: {
...cfg.agents?.defaults,
models,
},
},
models: {
mode: cfg.models?.mode ?? "merge",
providers,
},
};
}
export function applyChutesConfig(cfg: ClawdbotConfig): ClawdbotConfig {
const next = applyChutesProviderConfig(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: CHUTES_DEFAULT_MODEL_REF,
},
},
},
};
}
export function applyKimiCodeProviderConfig(cfg: ClawdbotConfig): ClawdbotConfig {
const models = { ...cfg.agents?.defaults?.models };
models[KIMI_CODE_MODEL_REF] = {

View File

@ -73,6 +73,19 @@ export async function setMoonshotApiKey(key: string, agentDir?: string) {
});
}
export async function setChutesApiKey(key: string, agentDir?: string) {
// Write to resolved agent dir so gateway finds credentials on startup.
upsertAuthProfile({
profileId: "chutes:default",
credential: {
type: "api_key",
provider: "chutes",
key,
},
agentDir: resolveAuthAgentDir(agentDir),
});
}
export async function setKimiCodeApiKey(key: string, agentDir?: string) {
// Write to resolved agent dir so gateway finds credentials on startup.
upsertAuthProfile({
@ -113,6 +126,7 @@ export async function setVeniceApiKey(key: string, agentDir?: string) {
}
export const ZAI_DEFAULT_MODEL_REF = "zai/glm-4.7";
export const CHUTES_DEFAULT_MODEL_REF = "chutes/zai-org/GLM-4.7-Flash";
export const OPENROUTER_DEFAULT_MODEL_REF = "openrouter/auto";
export const VERCEL_AI_GATEWAY_DEFAULT_MODEL_REF = "vercel-ai-gateway/anthropic/claude-opus-4.5";

View File

@ -12,6 +12,13 @@ export const MOONSHOT_DEFAULT_MODEL_ID = "kimi-k2-0905-preview";
export const MOONSHOT_DEFAULT_MODEL_REF = `moonshot/${MOONSHOT_DEFAULT_MODEL_ID}`;
export const MOONSHOT_DEFAULT_CONTEXT_WINDOW = 256000;
export const MOONSHOT_DEFAULT_MAX_TOKENS = 8192;
export const CHUTES_BASE_URL = "https://llm.chutes.ai/v1";
export const CHUTES_DEFAULT_MODEL_ID = "zai-org/GLM-4.7-Flash";
export const CHUTES_DEFAULT_MODEL_REF = `chutes/${CHUTES_DEFAULT_MODEL_ID}`;
export const CHUTES_DEFAULT_CONTEXT_WINDOW = 128000;
export const CHUTES_DEFAULT_MAX_TOKENS = 4096;
export const KIMI_CODE_BASE_URL = "https://api.kimi.com/coding/v1";
export const KIMI_CODE_MODEL_ID = "kimi-for-coding";
export const KIMI_CODE_MODEL_REF = `kimi-code/${KIMI_CODE_MODEL_ID}`;
@ -45,6 +52,12 @@ export const MOONSHOT_DEFAULT_COST = {
cacheRead: 0,
cacheWrite: 0,
};
export const CHUTES_DEFAULT_COST = {
input: 0,
output: 0,
cacheRead: 0,
cacheWrite: 0,
};
export const KIMI_CODE_DEFAULT_COST = {
input: 0,
output: 0,
@ -103,6 +116,64 @@ export function buildMoonshotModelDefinition(): ModelDefinitionConfig {
};
}
export function buildChutesModelDefinition(
modelId: string = CHUTES_DEFAULT_MODEL_ID,
): ModelDefinitionConfig {
if (modelId === "Qwen/Qwen3-235B-A22B-Instruct-2507-TEE") {
return {
id: modelId,
name: "Qwen 3 235B (Tools)",
reasoning: false,
input: ["text"],
cost: CHUTES_DEFAULT_COST,
contextWindow: 262144,
maxTokens: 4096,
};
}
if (modelId === "deepseek-ai/DeepSeek-V3.2-TEE") {
return {
id: modelId,
name: "DeepSeek V3.2 (Tools)",
reasoning: false,
input: ["text"],
cost: CHUTES_DEFAULT_COST,
contextWindow: 202752,
maxTokens: 4096,
};
}
if (modelId === "chutesai/Mistral-Small-3.1-24B-Instruct-2503") {
return {
id: modelId,
name: "Mistral Small 3.1 (Tools)",
reasoning: false,
input: ["text"],
cost: CHUTES_DEFAULT_COST,
contextWindow: 131072,
maxTokens: 4096,
};
}
if (modelId === "NousResearch/Hermes-4-14B") {
return {
id: modelId,
name: "Hermes 4 14B (Tools)",
reasoning: false,
input: ["text"],
cost: CHUTES_DEFAULT_COST,
contextWindow: 40960,
maxTokens: 4096,
};
}
return {
id: CHUTES_DEFAULT_MODEL_ID,
name: "GLM 4.7 Flash",
reasoning: false,
input: ["text"],
cost: CHUTES_DEFAULT_COST,
contextWindow: CHUTES_DEFAULT_CONTEXT_WINDOW,
maxTokens: CHUTES_DEFAULT_MAX_TOKENS,
};
}
export function buildKimiCodeModelDefinition(): ModelDefinitionConfig {
return {
id: KIMI_CODE_MODEL_ID,

View File

@ -5,6 +5,8 @@ export {
export { VENICE_DEFAULT_MODEL_ID, VENICE_DEFAULT_MODEL_REF } from "../agents/venice-models.js";
export {
applyAuthProfileConfig,
applyChutesConfig,
applyChutesProviderConfig,
applyKimiCodeConfig,
applyKimiCodeProviderConfig,
applyMoonshotConfig,
@ -35,6 +37,7 @@ export {
export {
OPENROUTER_DEFAULT_MODEL_REF,
setAnthropicApiKey,
setChutesApiKey,
setGeminiApiKey,
setKimiCodeApiKey,
setMinimaxApiKey,
@ -54,7 +57,11 @@ export {
buildMinimaxApiModelDefinition,
buildMinimaxModelDefinition,
buildMoonshotModelDefinition,
buildChutesModelDefinition,
DEFAULT_MINIMAX_BASE_URL,
CHUTES_BASE_URL,
CHUTES_DEFAULT_MODEL_ID,
CHUTES_DEFAULT_MODEL_REF,
KIMI_CODE_BASE_URL,
KIMI_CODE_MODEL_ID,
KIMI_CODE_MODEL_REF,

View File

@ -8,6 +8,7 @@ import { buildTokenProfileId, validateAnthropicSetupToken } from "../../auth-tok
import { applyGoogleGeminiModelDefault } from "../../google-gemini-model-default.js";
import {
applyAuthProfileConfig,
applyChutesConfig,
applyKimiCodeConfig,
applyMinimaxApiConfig,
applyMinimaxConfig,
@ -19,6 +20,7 @@ import {
applyVercelAiGatewayConfig,
applyZaiConfig,
setAnthropicApiKey,
setChutesApiKey,
setGeminiApiKey,
setKimiCodeApiKey,
setMinimaxApiKey,
@ -252,6 +254,25 @@ export async function applyNonInteractiveAuthChoice(params: {
return applyMoonshotConfig(nextConfig);
}
if (authChoice === "chutes-api-key") {
const resolved = await resolveNonInteractiveApiKey({
provider: "chutes",
cfg: baseConfig,
flagValue: opts.chutesApiKey,
flagName: "--chutes-api-key",
envVar: "CHUTES_API_KEY",
runtime,
});
if (!resolved) return null;
if (resolved.source !== "profile") await setChutesApiKey(resolved.key);
nextConfig = applyAuthProfileConfig(nextConfig, {
profileId: "chutes:default",
provider: "chutes",
mode: "api_key",
});
return applyChutesConfig(nextConfig);
}
if (authChoice === "kimi-code-api-key") {
const resolved = await resolveNonInteractiveApiKey({
provider: "kimi-code",

View File

@ -14,6 +14,7 @@ export type AuthChoice =
| "openrouter-api-key"
| "ai-gateway-api-key"
| "moonshot-api-key"
| "chutes-api-key"
| "kimi-code-api-key"
| "synthetic-api-key"
| "venice-api-key"
@ -64,6 +65,7 @@ export type OnboardOptions = {
openrouterApiKey?: string;
aiGatewayApiKey?: string;
moonshotApiKey?: string;
chutesApiKey?: string;
kimiCodeApiKey?: string;
geminiApiKey?: string;
zaiApiKey?: string;

View File

@ -31,6 +31,8 @@ export type ModelDefinitionConfig = {
maxTokens: number;
headers?: Record<string, string>;
compat?: ModelCompatConfig;
/** Chutes-only: indicates the model runs in a Trusted Execution Environment */
confidentialCompute?: boolean;
};
export type ModelProviderConfig = {
@ -41,6 +43,8 @@ export type ModelProviderConfig = {
headers?: Record<string, string>;
authHeader?: boolean;
models: ModelDefinitionConfig[];
/** Chutes-only: filter models by confidential_compute: true */
teeOnly?: boolean;
};
export type BedrockDiscoveryConfig = {