diff --git a/docs/providers/index.md b/docs/providers/index.md index a63a642cc..869dcd61b 100644 --- a/docs/providers/index.md +++ b/docs/providers/index.md @@ -46,6 +46,7 @@ See [Venice AI](/providers/venice). - [GLM models](/providers/glm) - [MiniMax](/providers/minimax) - [Venius (Venice AI, privacy-focused)](/providers/venice) +- [NEAR AI (private, verifiable)](/providers/nearai) - [Ollama (local models)](/providers/ollama) ## Transcription providers diff --git a/docs/providers/models.md b/docs/providers/models.md index 8c2ed4f5b..a61b44280 100644 --- a/docs/providers/models.md +++ b/docs/providers/models.md @@ -42,6 +42,7 @@ See [Venice AI](/providers/venice). - [GLM models](/providers/glm) - [MiniMax](/providers/minimax) - [Venius (Venice AI)](/providers/venice) +- [NEAR AI (private, verifiable)](/providers/nearai) - [Amazon Bedrock](/bedrock) For the full provider catalog (xAI, Groq, Mistral, etc.) and advanced configuration, diff --git a/docs/providers/nearai.md b/docs/providers/nearai.md new file mode 100644 index 000000000..85497a739 --- /dev/null +++ b/docs/providers/nearai.md @@ -0,0 +1,179 @@ +--- +summary: "Use NEAR AI private inference in Moltbot" +read_when: + - You want private inference with Intel TDX/NVIDIA TEE + - You want NEAR AI setup guidance +--- +# NEAR AI + +NEAR AI provides privacy-focused AI inference using confidential computing. All inference runs inside Intel TDX (Trust Domain Extensions) and NVIDIA TEE (Trusted Execution Environment), ensuring your prompts and responses are never logged or exposed to the host system. + +## Why NEAR AI in Moltbot + +- **Private inference** - all computation happens inside secure enclaves. +- **Cryptographic verification** - outputs are signed inside TEE before leaving. +- **No logging** - prompts and responses are never stored. +- OpenAI-compatible `/v1` endpoints. + +## Privacy Technology + +NEAR AI uses two layers of hardware-based security: + +| Technology | Purpose | +|------------|---------| +| **Intel TDX** | Isolates AI workloads in confidential VMs | +| **NVIDIA TEE** | GPU-level isolation for model weights and computations | + +All AI outputs are cryptographically signed inside the TEE before leaving the secure environment, ensuring authenticity and integrity of responses. + +## Features + +- **OpenAI-compatible APIs**: Standard endpoints like `/v1/chat/completions`, `v1/responses`, `/v1/images/generations`, etc. +- **Streaming**: Supported on all models +- **Function calling**: Supported +- **Vision**: Supported on vision-capable models + +## Setup + +### 1. Get API Key + +1. Sign up at [cloud.near.ai](https://cloud.near.ai) +2. Go to your dashboard and generate an API key +3. Copy your API key + +### 2. Configure Moltbot + +**Option A: Environment Variable** + +```bash +export NEARAI_API_KEY="your-api-key" +``` + +**Option B: Interactive Setup (Recommended)** + +```bash +moltbot onboard --auth-choice nearai-api-key +``` + +This will: +1. Prompt for your API key (or use existing `NEARAI_API_KEY`) +2. Configure the provider automatically +3. Set NEAR AI as your default model + +**Option C: Non-interactive** + +```bash +moltbot onboard --non-interactive \ + --auth-choice nearai-api-key \ + --nearai-api-key "your-api-key" +``` + +### 3. Verify Setup + +```bash +moltbot chat --model nearai/zai-org/GLM-4.7 "Hello, are you working?" +``` + +## Model Selection + +After setup, you can use any available NEAR AI model: + +```bash +moltbot models set nearai/zai-org/GLM-4.7 +moltbot models set nearai/deepseek-ai/DeepSeek-V3.1 +``` + +List all available models: + +```bash +moltbot models list | grep nearai +``` + +## Available Models + +> **Note:** The model list may change. See the latest available models at [cloud.near.ai/models](https://cloud.near.ai/models). + +| Model ID | Name | Privacy | Reasoning | Context | Cost | +|----------|------|---------|-----------|---------|------| +| `anthropic/claude-sonnet-4-5` | Claude Sonnet 4.5 | Anonymized | ✅ | 200K | $3.00 in / $15.50 out ($/M tokens) | +| `black-forest-labs/FLUX.2-klein-4B` | FLUX.2-klein-4B | Private | ❌ | 128K | $0.012/image | +| `deepseek-ai/DeepSeek-V3.1` | DeepSeek V3.1 | Private | ❌ | 128K | $1.05 in / $3.10 out ($/M tokens) | +| `google/gemini-3-pro` | Gemini 3 Pro Preview | Anonymized | ✅ | 1M | $1.25 in / $15.00 out ($/M tokens) | +| `openai/gpt-5.2` | OpenAI GPT-5.2 | Anonymized | ✅ | 400K | $1.80 in / $15.50 out ($/M tokens) | +| `openai/gpt-oss-120b` | GPT OSS 120B | Private | ✅ | 131K | $0.15 in / $0.55 out ($/M tokens) | +| `Qwen/Qwen3-30B-A3B-Instruct-2507` | Qwen3 30B | Private | ❌ | 262K | $0.15 in / $0.55 out ($/M tokens) | +| `zai-org/GLM-4.7` | GLM 4.7 (default) | Private | ✅ | 131K | $0.85 in / $3.30 out ($/M tokens) | + +## Configure via `moltbot configure` + +1. Run `moltbot configure` +2. Select **Model/auth** +3. Choose **NEAR AI** + +## Usage Examples + +```bash +# Use default model (GLM 4.7) +moltbot chat --model nearai/zai-org/GLM-4.7 + +# Use Claude Sonnet 4.5 for advanced reasoning +moltbot chat --model nearai/anthropic/claude-sonnet-4-5 + +# Use Gemini 3 Pro for ultra-long context (1M tokens!) +moltbot chat --model nearai/google/gemini-3-pro + +# Use GPT-5.2 for deep reasoning +moltbot chat --model nearai/openai/gpt-5.2 + +# Use DeepSeek for cost-effective tasks +moltbot chat --model nearai/deepseek-ai/DeepSeek-V3.1 + +# Use Qwen for long context (262K!) +moltbot chat --model nearai/Qwen/Qwen3-30B-A3B-Instruct-2507 + +# Use FLUX for image generation +moltbot chat --model nearai/black-forest-labs/FLUX.2-klein-4B + +# Send a message +moltbot agent --message "Explain quantum computing" --model nearai/zai-org/GLM-4.7 +``` + +## Troubleshooting + +### API key not recognized + +```bash +echo $NEARAI_API_KEY +moltbot models list | grep nearai +``` + +Ensure the environment variable is set correctly. + +### Connection issues + +NEAR AI API is at `https://cloud-api.near.ai/v1`. Ensure your network allows HTTPS connections. + +## Config file example + +```json5 +{ + env: { NEARAI_API_KEY: "..." }, + agents: { defaults: { model: { primary: "nearai/zai-org/GLM-4.7" } } }, + models: { + mode: "merge", + providers: { + "nearai": { + baseUrl: "https://cloud-api.near.ai/v1", + apiKey: "${NEARAI_API_KEY}", + api: "openai-completions" + // Models are auto-discovered from the built-in catalog + } + } + } +} +``` + +## Links + +- [NEAR AI Cloud](https://cloud.near.ai) +- [NEAR AI Documentation](https://docs.near.ai) diff --git a/src/agents/model-auth.ts b/src/agents/model-auth.ts index 5d1c095d2..6c45c95f7 100644 --- a/src/agents/model-auth.ts +++ b/src/agents/model-auth.ts @@ -286,6 +286,7 @@ export function resolveEnvApiKey(provider: string): EnvApiKeyResult | null { venice: "VENICE_API_KEY", mistral: "MISTRAL_API_KEY", opencode: "OPENCODE_API_KEY", + nearai: "NEARAI_API_KEY", }; const envVar = envMap[normalized]; if (!envVar) return null; diff --git a/src/agents/model-compat.test.ts b/src/agents/model-compat.test.ts index ce6d12d4b..9b6538cd2 100644 --- a/src/agents/model-compat.test.ts +++ b/src/agents/model-compat.test.ts @@ -41,4 +41,26 @@ describe("normalizeModelCompat", () => { const normalized = normalizeModelCompat(model); expect(normalized.compat?.supportsDeveloperRole).toBe(false); }); + + it("forces supportsDeveloperRole off for nearai provider", () => { + const model = { + ...baseModel(), + provider: "nearai", + baseUrl: "https://cloud-api.near.ai/v1", + }; + delete (model as { compat?: unknown }).compat; + const normalized = normalizeModelCompat(model); + expect(normalized.compat?.supportsDeveloperRole).toBe(false); + }); + + it("forces supportsDeveloperRole off for near.ai baseUrl", () => { + const model = { + ...baseModel(), + provider: "custom", + baseUrl: "https://cloud-api.near.ai/v1", + }; + delete (model as { compat?: unknown }).compat; + const normalized = normalizeModelCompat(model); + expect(normalized.compat?.supportsDeveloperRole).toBe(false); + }); }); diff --git a/src/agents/model-compat.ts b/src/agents/model-compat.ts index 741819073..b9aa38c3e 100644 --- a/src/agents/model-compat.ts +++ b/src/agents/model-compat.ts @@ -7,7 +7,8 @@ function isOpenAiCompletionsModel(model: Model): model is Model<"openai-com export function normalizeModelCompat(model: Model): Model { const baseUrl = model.baseUrl ?? ""; const isZai = model.provider === "zai" || baseUrl.includes("api.z.ai"); - if (!isZai || !isOpenAiCompletionsModel(model)) return model; + const isNearAi = model.provider === "nearai" || baseUrl.includes("cloud-api.near.ai"); + if ((!isZai && !isNearAi) || !isOpenAiCompletionsModel(model)) return model; const openaiModel = model as Model<"openai-completions">; const compat = openaiModel.compat ?? undefined; diff --git a/src/agents/models-config.providers.ts b/src/agents/models-config.providers.ts index f38ad46c7..c0b646253 100644 --- a/src/agents/models-config.providers.ts +++ b/src/agents/models-config.providers.ts @@ -13,6 +13,11 @@ import { SYNTHETIC_MODEL_CATALOG, } from "./synthetic-models.js"; import { discoverVeniceModels, VENICE_BASE_URL } from "./venice-models.js"; +import { + buildNearAiModelDefinition, + NEAR_AI_BASE_URL, + NEAR_AI_MODEL_CATALOG, +} from "./nearai-models.js"; type ModelsConfig = NonNullable; export type ProviderConfig = NonNullable[string]; @@ -379,6 +384,14 @@ async function buildVeniceProvider(): Promise { }; } +function buildNearAiProvider(): ProviderConfig { + return { + baseUrl: NEAR_AI_BASE_URL, + api: "openai-completions", + models: NEAR_AI_MODEL_CATALOG.map(buildNearAiModelDefinition), + }; +} + async function buildOllamaProvider(): Promise { const models = await discoverOllamaModels(); return { @@ -431,6 +444,13 @@ export async function resolveImplicitProviders(params: { providers.venice = { ...(await buildVeniceProvider()), apiKey: veniceKey }; } + const nearAiKey = + resolveEnvApiKeyVarName("nearai") ?? + resolveApiKeyFromProfiles({ provider: "nearai", store: authStore }); + if (nearAiKey) { + providers["nearai"] = { ...buildNearAiProvider(), apiKey: nearAiKey }; + } + const qwenProfiles = listProfilesForProvider(authStore, "qwen-portal"); if (qwenProfiles.length > 0) { providers["qwen-portal"] = { diff --git a/src/agents/nearai-models.ts b/src/agents/nearai-models.ts new file mode 100644 index 000000000..1ff9f8d68 --- /dev/null +++ b/src/agents/nearai-models.ts @@ -0,0 +1,115 @@ +import type { ModelDefinitionConfig } from "../config/types.js"; + +export const NEAR_AI_BASE_URL = "https://cloud-api.near.ai/v1"; +export const NEAR_AI_DEFAULT_MODEL_ID = "zai-org/GLM-4.7"; +export const NEAR_AI_DEFAULT_MODEL_REF = `nearai/${NEAR_AI_DEFAULT_MODEL_ID}`; + +// NEAR AI uses credit-based pricing (per million tokens). +export const NEAR_AI_DEFAULT_COST = { + input: 0, + output: 0, + cacheRead: 0, + cacheWrite: 0, +}; + +/** + * Static catalog of NEAR AI models. + * + * NEAR AI provides privacy-focused inference using: + * - Intel TDX (Trust Domain Extensions) for confidential VMs + * - NVIDIA TEE for GPU-level isolation + * - Cryptographic signing of all AI outputs inside TEE + * + * Models marked as "private" are fully private - prompts/responses are not logged. + * Models marked as "anonymized" use anonymized proxy endpoints (not TEE-protected). + * The `privacy` field indicates the privacy level for each model. + */ +export const NEAR_AI_MODEL_CATALOG = [ + { + id: "anthropic/claude-sonnet-4-5", + name: "Claude Sonnet 4.5", + reasoning: true, + input: ["text"], + contextWindow: 200000, + maxTokens: 8192, + cost: { input: 3, output: 15.5, cacheRead: 0, cacheWrite: 0 }, + privacy: "anonymized", + }, + { + id: "deepseek-ai/DeepSeek-V3.1", + name: "DeepSeek V3.1", + reasoning: false, + input: ["text"], + contextWindow: 128000, + maxTokens: 8192, + cost: { input: 1.05, output: 3.1, cacheRead: 0, cacheWrite: 0 }, + privacy: "private", + }, + { + id: "google/gemini-3-pro", + name: "Gemini 3 Pro Preview", + reasoning: true, + input: ["text"], + contextWindow: 1000000, + maxTokens: 8192, + cost: { input: 1.25, output: 15, cacheRead: 0, cacheWrite: 0 }, + privacy: "anonymized", + }, + { + id: "openai/gpt-5.2", + name: "OpenAI GPT-5.2", + reasoning: true, + input: ["text"], + contextWindow: 400000, + maxTokens: 8192, + cost: { input: 1.8, output: 15.5, cacheRead: 0, cacheWrite: 0 }, + privacy: "anonymized", + }, + { + id: "openai/gpt-oss-120b", + name: "GPT OSS 120B", + reasoning: true, + input: ["text"], + contextWindow: 131000, + maxTokens: 8192, + cost: { input: 0.15, output: 0.55, cacheRead: 0, cacheWrite: 0 }, + privacy: "private", + }, + { + id: "Qwen/Qwen3-30B-A3B-Instruct-2507", + name: "Qwen3 30B Instruct", + reasoning: false, + input: ["text"], + contextWindow: 262144, + maxTokens: 8192, + cost: { input: 0.15, output: 0.55, cacheRead: 0, cacheWrite: 0 }, + privacy: "private", + }, + { + id: "zai-org/GLM-4.7", + name: "GLM 4.7", + reasoning: true, + input: ["text"], + contextWindow: 131072, + maxTokens: 8192, + cost: { input: 0.85, output: 3.3, cacheRead: 0, cacheWrite: 0 }, + privacy: "private", + }, +] as const; + +export type NearAiCatalogEntry = (typeof NEAR_AI_MODEL_CATALOG)[number]; + +/** + * Build a ModelDefinitionConfig from a NEAR AI catalog entry. + */ +export function buildNearAiModelDefinition(entry: NearAiCatalogEntry): ModelDefinitionConfig { + return { + id: entry.id, + name: entry.name, + reasoning: entry.reasoning, + input: [...entry.input], + cost: entry.cost, + contextWindow: entry.contextWindow, + maxTokens: entry.maxTokens, + }; +} diff --git a/src/commands/auth-choice-options.ts b/src/commands/auth-choice-options.ts index 5acddf4e3..afde25ee3 100644 --- a/src/commands/auth-choice-options.ts +++ b/src/commands/auth-choice-options.ts @@ -21,6 +21,7 @@ export type AuthChoiceGroupId = | "minimax" | "synthetic" | "venice" + | "nearai" | "qwen"; export type AuthChoiceGroup = { @@ -72,6 +73,12 @@ const AUTH_CHOICE_GROUP_DEFS: { hint: "Privacy-focused (uncensored models)", choices: ["venice-api-key"], }, + { + value: "nearai", + label: "NEAR AI", + hint: "Private and verifiable inference (TEE)", + choices: ["nearai-api-key"], + }, { value: "google", label: "Google", @@ -154,6 +161,11 @@ export function buildAuthChoiceOptions(params: { label: "Venice AI API key", hint: "Privacy-focused inference (uncensored models)", }); + options.push({ + value: "nearai-api-key", + label: "NEAR AI API key", + hint: "Private and verifiable inference with Intel TDX/NVIDIA TEE", + }); options.push({ value: "github-copilot", label: "GitHub Copilot (GitHub device login)", diff --git a/src/commands/auth-choice.apply.api-providers.ts b/src/commands/auth-choice.apply.api-providers.ts index fa4fc77e7..29480ca9a 100644 --- a/src/commands/auth-choice.apply.api-providers.ts +++ b/src/commands/auth-choice.apply.api-providers.ts @@ -25,6 +25,8 @@ import { applySyntheticProviderConfig, applyVeniceConfig, applyVeniceProviderConfig, + applyNearAiConfig, + applyNearAiProviderConfig, applyVercelAiGatewayConfig, applyVercelAiGatewayProviderConfig, applyXiaomiConfig, @@ -35,6 +37,7 @@ import { OPENROUTER_DEFAULT_MODEL_REF, SYNTHETIC_DEFAULT_MODEL_REF, VENICE_DEFAULT_MODEL_REF, + NEAR_AI_DEFAULT_MODEL_REF, VERCEL_AI_GATEWAY_DEFAULT_MODEL_REF, XIAOMI_DEFAULT_MODEL_REF, setGeminiApiKey, @@ -44,6 +47,7 @@ import { setOpenrouterApiKey, setSyntheticApiKey, setVeniceApiKey, + setNearAiApiKey, setVercelAiGatewayApiKey, setXiaomiApiKey, setZaiApiKey, @@ -89,6 +93,8 @@ export async function applyAuthChoiceApiProviders( authChoice = "synthetic-api-key"; } else if (params.opts.tokenProvider === "venice") { authChoice = "venice-api-key"; + } else if (params.opts.tokenProvider === "nearai") { + authChoice = "nearai-api-key"; } else if (params.opts.tokenProvider === "opencode") { authChoice = "opencode-zen"; } @@ -576,6 +582,65 @@ export async function applyAuthChoiceApiProviders( return { config: nextConfig, agentModelOverride }; } + if (authChoice === "nearai-api-key") { + let hasCredential = false; + + if (!hasCredential && params.opts?.token && params.opts?.tokenProvider === "nearai") { + await setNearAiApiKey(normalizeApiKeyInput(params.opts.token), params.agentDir); + hasCredential = true; + } + + if (!hasCredential) { + await params.prompter.note( + [ + "NEAR AI provides privacy-focused inference using Intel TDX and NVIDIA TEE.", + "Get your API key at: https://cloud.near.ai", + "All inference is private - prompts/responses are not logged.", + ].join("\n"), + "NEAR AI", + ); + } + + const envKey = resolveEnvApiKey("nearai"); + if (envKey) { + const useExisting = await params.prompter.confirm({ + message: `Use existing NEARAI_API_KEY (${envKey.source}, ${formatApiKeyPreview(envKey.apiKey)})?`, + initialValue: true, + }); + if (useExisting) { + await setNearAiApiKey(envKey.apiKey, params.agentDir); + hasCredential = true; + } + } + if (!hasCredential) { + const key = await params.prompter.text({ + message: "Enter NEAR AI API key", + validate: validateApiKeyInput, + }); + await setNearAiApiKey(normalizeApiKeyInput(String(key)), params.agentDir); + } + nextConfig = applyAuthProfileConfig(nextConfig, { + profileId: "nearai:default", + provider: "nearai", + mode: "api_key", + }); + { + const applied = await applyDefaultModelChoice({ + config: nextConfig, + setDefaultModel: params.setDefaultModel, + defaultModel: NEAR_AI_DEFAULT_MODEL_REF, + applyDefaultConfig: applyNearAiConfig, + applyProviderConfig: applyNearAiProviderConfig, + noteDefault: NEAR_AI_DEFAULT_MODEL_REF, + noteAgentModel, + prompter: params.prompter, + }); + nextConfig = applied.config; + agentModelOverride = applied.agentModelOverride ?? agentModelOverride; + } + return { config: nextConfig, agentModelOverride }; + } + if (authChoice === "opencode-zen") { let hasCredential = false; if (!hasCredential && params.opts?.token && params.opts?.tokenProvider === "opencode") { diff --git a/src/commands/auth-choice.preferred-provider.ts b/src/commands/auth-choice.preferred-provider.ts index a4d831c92..ee45391da 100644 --- a/src/commands/auth-choice.preferred-provider.ts +++ b/src/commands/auth-choice.preferred-provider.ts @@ -21,6 +21,7 @@ const PREFERRED_PROVIDER_BY_AUTH_CHOICE: Partial> = { "xiaomi-api-key": "xiaomi", "synthetic-api-key": "synthetic", "venice-api-key": "venice", + "nearai-api-key": "nearai", "github-copilot": "github-copilot", "copilot-proxy": "copilot-proxy", "minimax-cloud": "minimax", diff --git a/src/commands/onboard-auth.config-core.ts b/src/commands/onboard-auth.config-core.ts index 222f0a5c6..47098b050 100644 --- a/src/commands/onboard-auth.config-core.ts +++ b/src/commands/onboard-auth.config-core.ts @@ -11,6 +11,12 @@ import { VENICE_DEFAULT_MODEL_REF, VENICE_MODEL_CATALOG, } from "../agents/venice-models.js"; +import { + buildNearAiModelDefinition, + NEAR_AI_BASE_URL, + NEAR_AI_DEFAULT_MODEL_REF, + NEAR_AI_MODEL_CATALOG, +} from "../agents/nearai-models.js"; import type { MoltbotConfig } from "../config/config.js"; import { OPENROUTER_DEFAULT_MODEL_REF, @@ -484,6 +490,81 @@ export function applyVeniceConfig(cfg: MoltbotConfig): MoltbotConfig { }; } +/** + * Apply NEAR AI provider configuration without changing the default model. + * Registers NEAR AI models and sets up the provider, but preserves existing model selection. + */ +export function applyNearAiProviderConfig(cfg: MoltbotConfig): MoltbotConfig { + const models = { ...cfg.agents?.defaults?.models }; + models[NEAR_AI_DEFAULT_MODEL_REF] = { + ...models[NEAR_AI_DEFAULT_MODEL_REF], + alias: models[NEAR_AI_DEFAULT_MODEL_REF]?.alias ?? "GLM-4.7", + }; + + const providers = { ...cfg.models?.providers }; + const existingProvider = providers["nearai"]; + const existingModels = Array.isArray(existingProvider?.models) ? existingProvider.models : []; + const nearAiModels = NEAR_AI_MODEL_CATALOG.map(buildNearAiModelDefinition); + const mergedModels = [ + ...existingModels, + ...nearAiModels.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["nearai"] = { + ...existingProviderRest, + baseUrl: NEAR_AI_BASE_URL, + api: "openai-completions", + ...(normalizedApiKey ? { apiKey: normalizedApiKey } : {}), + models: mergedModels.length > 0 ? mergedModels : nearAiModels, + }; + + return { + ...cfg, + agents: { + ...cfg.agents, + defaults: { + ...cfg.agents?.defaults, + models, + }, + }, + models: { + mode: cfg.models?.mode ?? "merge", + providers, + }, + }; +} + +/** + * Apply NEAR AI provider configuration AND set NEAR AI as the default model. + * Use this when NEAR AI is the primary provider choice during onboarding. + */ +export function applyNearAiConfig(cfg: MoltbotConfig): MoltbotConfig { + const next = applyNearAiProviderConfig(cfg); + const existingModel = next.agents?.defaults?.model; + return { + ...next, + agents: { + ...next.agents, + defaults: { + ...next.agents?.defaults, + model: { + ...(existingModel && "fallbacks" in (existingModel as Record) + ? { + fallbacks: (existingModel as { fallbacks?: string[] }).fallbacks, + } + : undefined), + primary: NEAR_AI_DEFAULT_MODEL_REF, + }, + }, + }, + }; +} + export function applyAuthProfileConfig( cfg: MoltbotConfig, params: { diff --git a/src/commands/onboard-auth.credentials.ts b/src/commands/onboard-auth.credentials.ts index 053026162..cfa3cb423 100644 --- a/src/commands/onboard-auth.credentials.ts +++ b/src/commands/onboard-auth.credentials.ts @@ -112,6 +112,19 @@ export async function setVeniceApiKey(key: string, agentDir?: string) { }); } +export async function setNearAiApiKey(key: string, agentDir?: string) { + // Write to resolved agent dir so gateway finds credentials on startup. + upsertAuthProfile({ + profileId: "nearai:default", + credential: { + type: "api_key", + provider: "nearai", + key, + }, + agentDir: resolveAuthAgentDir(agentDir), + }); +} + export const ZAI_DEFAULT_MODEL_REF = "zai/glm-4.7"; export const XIAOMI_DEFAULT_MODEL_REF = "xiaomi/mimo-v2-flash"; export const OPENROUTER_DEFAULT_MODEL_REF = "openrouter/auto"; diff --git a/src/commands/onboard-auth.ts b/src/commands/onboard-auth.ts index 612b24865..a76462fd0 100644 --- a/src/commands/onboard-auth.ts +++ b/src/commands/onboard-auth.ts @@ -3,6 +3,7 @@ export { SYNTHETIC_DEFAULT_MODEL_REF, } from "../agents/synthetic-models.js"; export { VENICE_DEFAULT_MODEL_ID, VENICE_DEFAULT_MODEL_REF } from "../agents/venice-models.js"; +export { NEAR_AI_DEFAULT_MODEL_ID, NEAR_AI_DEFAULT_MODEL_REF } from "../agents/nearai-models.js"; export { applyAuthProfileConfig, applyKimiCodeConfig, @@ -15,6 +16,8 @@ export { applySyntheticProviderConfig, applyVeniceConfig, applyVeniceProviderConfig, + applyNearAiConfig, + applyNearAiProviderConfig, applyVercelAiGatewayConfig, applyVercelAiGatewayProviderConfig, applyXiaomiConfig, @@ -45,6 +48,7 @@ export { setOpenrouterApiKey, setSyntheticApiKey, setVeniceApiKey, + setNearAiApiKey, setVercelAiGatewayApiKey, setXiaomiApiKey, setZaiApiKey, diff --git a/src/commands/onboard-types.ts b/src/commands/onboard-types.ts index f4154bc6d..df5a3a1af 100644 --- a/src/commands/onboard-types.ts +++ b/src/commands/onboard-types.ts @@ -17,6 +17,7 @@ export type AuthChoice = | "kimi-code-api-key" | "synthetic-api-key" | "venice-api-key" + | "nearai-api-key" | "codex-cli" | "apiKey" | "gemini-api-key" @@ -72,6 +73,7 @@ export type OnboardOptions = { minimaxApiKey?: string; syntheticApiKey?: string; veniceApiKey?: string; + nearaiApiKey?: string; opencodeZenApiKey?: string; gatewayPort?: number; gatewayBind?: GatewayBind;