diff --git a/README.ja-JP.md b/README.ja-JP.md index 105542251..8e9011093 100644 --- a/README.ja-JP.md +++ b/README.ja-JP.md @@ -162,6 +162,26 @@ helm install agentteams higress.io/agentteams \ +
+OrcaRouter を使用する場合 + +[OrcaRouter](https://www.orcarouter.ai) は `https://api.orcarouter.ai/v1` で OpenAI 互換 API を提供する統合 AI ゲートウェイです。provider 名を `orcarouter` に設定すると、単一の API キーで複数のモデルを利用できます: + +```bash +helm install agentteams higress.io/agentteams \ + -n agentteams-system --create-namespace \ + --render-subchart-notes \ + --set credentials.llmApiKey= \ + --set credentials.llmProvider=orcarouter \ + --set credentials.defaultModel=orcarouter/auto \ + --set credentials.adminPassword= \ + --set gateway.publicURL=http://localhost:18080 +``` + +It also runs gateway-level, zero-trust security for AI agents on the same endpoint — screening every prompt/response and governing every tool call on a default-deny basis, with no application code changes. + +
+ | 値 | 必須 | 説明 | |---|---|---| | `credentials.llmApiKey` | 必須 | LLM プロバイダーの API キー | @@ -169,7 +189,7 @@ helm install agentteams higress.io/agentteams \ | `credentials.adminPassword` | 推奨 | Matrix 管理者パスワード。空のままだと自動生成(後で Secret から読み出す必要あり) | | `credentials.llmProvider` | 任意 | LLM プロバイダー名、デフォルトは `openai-compat` | | `credentials.defaultModel` | 任意 | デフォルトモデル、デフォルトは `gpt-5.4` | -| `credentials.llmBaseUrl` | 任意 | OpenAI 互換のベース URL(例: `https://api.deepseek.com/v1`)。公式 OpenAI API を使用する場合は空のまま | +| `credentials.llmBaseUrl` | 任意 | OpenAI 互換のベース URL(例: `https://api.deepseek.com/v1`)。公式 OpenAI API または内蔵の `orcarouter` provider を使用する場合は空のまま | | `manager.runtime` | 任意 | Manager エージェントランタイム: `openclaw`(デフォルト)、`copaw`、または `hermes` | | `worker.defaultRuntime` | 任意 | Worker デフォルトランタイム: `openclaw`(デフォルト)、`copaw`、または `hermes` | diff --git a/README.md b/README.md index d85e597d1..df3b1228a 100644 --- a/README.md +++ b/README.md @@ -169,6 +169,26 @@ helm install agentteams higress.io/agentteams \ +
+Using OrcaRouter instead + +[OrcaRouter](https://www.orcarouter.ai) is a unified AI gateway that exposes an OpenAI-compatible API at `https://api.orcarouter.ai/v1`. Set the provider name to `orcarouter` to use it with a single API key across models: + +```bash +helm install agentteams higress.io/agentteams \ + -n agentteams-system --create-namespace \ + --render-subchart-notes \ + --set credentials.llmApiKey= \ + --set credentials.llmProvider=orcarouter \ + --set credentials.defaultModel=orcarouter/auto \ + --set credentials.adminPassword= \ + --set gateway.publicURL=http://localhost:18080 +``` + +It also runs gateway-level, zero-trust security for AI agents on the same endpoint — screening every prompt/response and governing every tool call on a default-deny basis, with no application code changes. + +
+ | Value | Required | Description | |---|---|---| | `credentials.llmApiKey` | yes | API key for your LLM provider | @@ -176,7 +196,7 @@ helm install agentteams higress.io/agentteams \ | `credentials.adminPassword` | recommended | Matrix admin password; auto-generated if left empty (you'll have to read it back from the Secret) | | `credentials.llmProvider` | no | LLM provider name, defaults to `openai-compat` | | `credentials.defaultModel` | no | Default model, defaults to `gpt-5.4` | -| `credentials.llmBaseUrl` | no | OpenAI-compatible base URL (e.g. `https://api.deepseek.com/v1`). Leave empty for official OpenAI API | +| `credentials.llmBaseUrl` | no | OpenAI-compatible base URL (e.g. `https://api.deepseek.com/v1`). Leave empty for official OpenAI API or the built-in `orcarouter` provider | | `preflight.llm.enabled` | no | Run an install/upgrade hook that validates the LLM API key, base URL, and model before the controller starts. Defaults to `true` | | `preflight.llm.strict` | no | Fail the Helm install/upgrade when the LLM preflight fails. Defaults to `true`; set to `false` to emit a warning and continue | | `preflight.llm.timeoutSeconds` | no | Per-request timeout for the LLM preflight HTTP probe. Defaults to `30` | diff --git a/README.zh-CN.md b/README.zh-CN.md index 408190373..13d06c3cd 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -195,6 +195,26 @@ helm install agentteams higress.io/agentteams \ +
+使用 OrcaRouter + +[OrcaRouter](https://www.orcarouter.ai) 是一个统一的 AI 网关,在 `https://api.orcarouter.ai/v1` 提供 OpenAI 兼容 API。将 provider 名设为 `orcarouter` 即可用一个 API Key 接入多种模型: + +```bash +helm install agentteams higress.io/agentteams \ + -n agentteams-system --create-namespace \ + --render-subchart-notes \ + --set credentials.llmApiKey=<你的-OrcaRouter-API-Key> \ + --set credentials.llmProvider=orcarouter \ + --set credentials.defaultModel=orcarouter/auto \ + --set credentials.adminPassword=<你的-管理员密码> \ + --set gateway.publicURL=http://localhost:18080 +``` + +It also runs gateway-level, zero-trust security for AI agents on the same endpoint — screening every prompt/response and governing every tool call on a default-deny basis, with no application code changes. + +
+ | 参数 | 是否必填 | 说明 | |---|---|---| | `credentials.llmApiKey` | 必填 | LLM 服务商 API Key | @@ -202,7 +222,7 @@ helm install agentteams higress.io/agentteams \ | `credentials.adminPassword` | 推荐 | Matrix 管理员密码;留空时会自动生成(之后需要从 Secret 中读取) | | `credentials.llmProvider` | 可选 | LLM 服务商名,默认 `openai-compat` | | `credentials.defaultModel` | 可选 | 默认模型,默认 `gpt-5.4` | -| `credentials.llmBaseUrl` | 可选 | OpenAI 兼容的 Base URL(例如 `https://api.deepseek.com/v1`)。使用官方 OpenAI API 时留空 | +| `credentials.llmBaseUrl` | 可选 | OpenAI 兼容的 Base URL(例如 `https://api.deepseek.com/v1`)。使用官方 OpenAI API 或内置的 `orcarouter` provider 时留空 | | `preflight.llm.enabled` | 可选 | 安装或升级前通过 hook 验证 LLM API Key、Base URL 和模型;默认 `true` | | `preflight.llm.strict` | 可选 | LLM 探测失败时终止安装或升级;默认 `true`,设为 `false` 时仅告警并继续 | | `preflight.llm.timeoutSeconds` | 可选 | LLM 探测单次 HTTP 请求的超时时间;默认 `30` 秒 | diff --git a/agentteams-controller/cmd/agt/llm_preflight.go b/agentteams-controller/cmd/agt/llm_preflight.go index 8728a0a3e..f896d0d28 100644 --- a/agentteams-controller/cmd/agt/llm_preflight.go +++ b/agentteams-controller/cmd/agt/llm_preflight.go @@ -20,6 +20,7 @@ import ( const ( defaultOpenAICompatibleBaseURL = "https://api.openai.com/v1" defaultQwenCompatibleBaseURL = "https://dashscope.aliyuncs.com/compatible-mode/v1" + defaultOrcaRouterBaseURL = "https://api.orcarouter.ai/v1" defaultLLMPreflightTimeout = 30 * time.Second defaultLLMPreflightRetries = 2 defaultLLMPreflightRetryBackoff = 500 * time.Millisecond @@ -97,7 +98,7 @@ func llmPreflightCmd() *cobra.Command { }, } - cmd.Flags().StringVar(&opts.Provider, "provider", opts.Provider, "LLM provider (openai-compat|qwen|custom)") + cmd.Flags().StringVar(&opts.Provider, "provider", opts.Provider, "LLM provider (openai-compat|qwen|orcarouter|custom)") cmd.Flags().StringVar(&opts.APIKey, "api-key", opts.APIKey, "LLM API key") cmd.Flags().StringVar(&opts.BaseURL, "base-url", opts.BaseURL, "OpenAI-compatible base URL") cmd.Flags().StringVar(&opts.Model, "model", opts.Model, "Model name to probe") @@ -171,6 +172,8 @@ func resolveLLMPreflightBaseURL(provider, baseURL string) (string, error) { baseURL = defaultOpenAICompatibleBaseURL case "qwen": baseURL = defaultQwenCompatibleBaseURL + case "orcarouter": + baseURL = defaultOrcaRouterBaseURL default: return "", fmt.Errorf("LLM base URL is required for provider %q (set AGENTTEAMS_OPENAI_BASE_URL or --base-url)", provider) } diff --git a/agentteams-controller/cmd/agt/llm_preflight_test.go b/agentteams-controller/cmd/agt/llm_preflight_test.go index 44ee03638..de40f5dfe 100644 --- a/agentteams-controller/cmd/agt/llm_preflight_test.go +++ b/agentteams-controller/cmd/agt/llm_preflight_test.go @@ -40,6 +40,20 @@ func TestResolveLLMPreflightConfigDefaultsQwen(t *testing.T) { } } +func TestResolveLLMPreflightConfigDefaultsOrcaRouter(t *testing.T) { + cfg, err := resolveLLMPreflightConfig(llmPreflightOptions{ + Provider: "orcarouter", + APIKey: "sk-orca-test", + Model: "orcarouter/auto", + }) + if err != nil { + t.Fatalf("resolveLLMPreflightConfig: %v", err) + } + if cfg.BaseURL != "https://api.orcarouter.ai/v1" { + t.Fatalf("BaseURL=%q, want OrcaRouter gateway endpoint", cfg.BaseURL) + } +} + func TestResolveLLMPreflightConfigCustomProviderRequiresBaseURL(t *testing.T) { _, err := resolveLLMPreflightConfig(llmPreflightOptions{ Provider: "custom-vendor", diff --git a/agentteams-controller/internal/initializer/initializer.go b/agentteams-controller/internal/initializer/initializer.go index b8f3c402f..f129446c9 100644 --- a/agentteams-controller/internal/initializer/initializer.go +++ b/agentteams-controller/internal/initializer/initializer.go @@ -316,6 +316,28 @@ func (i *Initializer) initGatewayRoutes(ctx context.Context) error { logger.Error(err, "failed to create LLM provider (non-fatal)") } + case "orcarouter": + // OrcaRouter: OpenAI-compatible gateway (https://www.orcarouter.ai) + if err := i.Gateway.EnsureServiceSource(ctx, "orcarouter", "api.orcarouter.ai", 443, "https"); err != nil { + logger.Error(err, "failed to register orcarouter service source (non-fatal)") + } + time.Sleep(2 * time.Second) + raw := map[string]interface{}{ + "agentteamsMode": true, + "openaiCustomUrl": "https://api.orcarouter.ai/v1", + "openaiCustomServiceName": "orcarouter.dns", + "openaiCustomServicePort": 443, + } + if err := i.Gateway.EnsureAIProvider(ctx, gateway.AIProviderRequest{ + Name: "orcarouter", + Type: "openai", + Tokens: []string{cfg.LLMAPIKey}, + Protocol: "openai/v1", + Raw: raw, + }); err != nil { + logger.Error(err, "failed to create LLM provider (non-fatal)") + } + case "openai-compat": if cfg.OpenAIBaseURL == "" { // No custom base URL — fall back to official OpenAI endpoint diff --git a/helm/agentteams/values.yaml b/helm/agentteams/values.yaml index c53ba716e..103507366 100644 --- a/helm/agentteams/values.yaml +++ b/helm/agentteams/values.yaml @@ -18,7 +18,7 @@ credentials: adminUser: "admin" adminPassword: "" # Matrix admin password (auto-generated if empty) llmApiKey: "" # LLM API key (required) - llmProvider: "openai-compat" + llmProvider: "openai-compat" # openai-compat, qwen, orcarouter, or a custom name defaultModel: "gpt-5.4" llmBaseUrl: "" # OpenAI-compatible base URL (e.g. https://api.openai.com/v1) diff --git a/install/README.md b/install/README.md index af8bd5dfc..c2715827d 100644 --- a/install/README.md +++ b/install/README.md @@ -137,7 +137,7 @@ $env:AGENTTEAMS_LLM_API_KEY = "your-api-key" | Variable | Description | Default | |----------|-------------|---------| | `AGENTTEAMS_NON_INTERACTIVE` | Skip all prompts | `0` | -| `AGENTTEAMS_LLM_PROVIDER` | LLM provider (`qwen` or `openai-compat`) | `qwen` | +| `AGENTTEAMS_LLM_PROVIDER` | LLM provider (`qwen`, `orcarouter` or `openai-compat`) | `qwen` | | `AGENTTEAMS_DEFAULT_MODEL` | Default model ID | `qwen3.5-plus` | | `AGENTTEAMS_LLM_API_KEY` | LLM API key | *(required)* | | `AGENTTEAMS_ADMIN_USER` | Admin username | `admin` | diff --git a/install/agentteams-install.ps1 b/install/agentteams-install.ps1 index f622799f1..8422695d3 100644 --- a/install/agentteams-install.ps1 +++ b/install/agentteams-install.ps1 @@ -317,7 +317,8 @@ $script:Messages = @{ "llm.providers_title" = @{ zh = "可用 LLM 提供商:"; en = "Available LLM Providers:" } "llm.provider.alibaba" = @{ zh = " 1) 阿里云通义 Token 套餐 - 推荐中国用户使用"; en = " 1) Qwen Cloud - International (OpenAI-compatible API, recommended)" } "llm.provider.openai_compat" = @{ zh = " 2) OpenAI 兼容 API - 自定义 Base URL(OpenAI、DeepSeek 等)"; en = " 2) OpenAI-compatible API - Custom Base URL (OpenAI, DeepSeek, etc.)" } - "llm.provider.select" = @{ zh = "选择提供商 [1/2]"; en = "Select provider [1/2]" } + "llm.provider.orcarouter" = @{ zh = " 3) OrcaRouter - AI 网关(https://www.orcarouter.ai)"; en = " 3) OrcaRouter - AI gateway (https://www.orcarouter.ai)" } + "llm.provider.select" = @{ zh = "选择提供商 [1/2/3]"; en = "Select provider [1/2/3]" } "llm.alibaba.models_title" = @{ zh = "选择阿里云模型接入方式:"; en = "Select Alibaba Cloud model access:" } "llm.alibaba.model.tokenplan" = @{ zh = " 1) 阿里云通义 Token 套餐 - 兼容模式(推荐)"; en = " 1) Alibaba Cloud Token Plan - compatible-mode (recommended)" } "llm.alibaba.model.bailian" = @{ zh = " 2) 阿里云百炼 - DashScope 通用兼容接口"; en = " 2) Alibaba Cloud Bailian - DashScope compatible mode" } @@ -335,7 +336,7 @@ $script:Messages = @{ "llm.provider.selected_codingplan_legacy" = @{ zh = " 提供商: 阿里云 Coding 套餐(coding.dashscope)"; en = " Provider: Alibaba Cloud Coding Plan (coding.dashscope)" } "llm.provider.selected_qwen" = @{ zh = " 提供商: 阿里云百炼"; en = " Provider: Alibaba Cloud Bailian" } "llm.provider.selected_openai" = @{ zh = " 提供商: {0}(OpenAI 兼容)"; en = " Provider: {0} (OpenAI-compatible)" } - "llm.provider.invalid" = @{ zh = "无效选择: {0}(请输入 1 或 2)"; en = "Invalid choice: {0} (please enter 1 or 2)" } + "llm.provider.invalid" = @{ zh = "无效选择: {0}(请输入 1、2 或 3)"; en = "Invalid choice: {0} (please enter 1, 2, or 3)" } "llm.qwen.model_prompt" = @{ zh = "默认模型 ID"; en = "Default Model ID" } "llm.openai.base_url_prompt" = @{ zh = "Base URL"; en = "Base URL" } "llm.openai.model_prompt" = @{ zh = "默认模型 ID"; en = "Default Model ID" } @@ -1340,7 +1341,8 @@ function New-OpenAICompatProvider { param( [string]$BaseUrl, [string]$ApiKey, - [int]$ConsolePort = 18001 + [int]$ConsolePort = 18001, + [string]$ProviderName = "openai-compat" ) if (-not $BaseUrl -or -not $ApiKey) { @@ -1372,7 +1374,7 @@ function New-OpenAICompatProvider { Write-Log (Get-Msg "install.openai_compat.port" -f $port) Write-Log (Get-Msg "install.openai_compat.protocol" -f $protocol) - $serviceName = "openai-compat" + $serviceName = $ProviderName # Create DNS service source $serviceBody = @{ @@ -1396,7 +1398,7 @@ function New-OpenAICompatProvider { # Create AI provider $providerBody = @{ type = "openai" - name = "openai-compat" + name = $ProviderName tokens = @($ApiKey) version = 0 protocol = "openai/v1" @@ -1772,11 +1774,16 @@ function Step-Llm { Write-Host (Get-Msg "llm.providers_title") Write-Host (Get-Msg "llm.provider.alibaba") Write-Host (Get-Msg "llm.provider.openai_compat") + Write-Host (Get-Msg "llm.provider.orcarouter") Write-Host "" # If upgrade mode with loaded provider, show current as default if ($script:AGENTTEAMS_UPGRADE -and $script:config.LLM_PROVIDER) { - $defaultProvider = if ($script:config.LLM_PROVIDER -eq "openai-compat") { "2" } else { "1" } + $defaultProvider = switch ($script:config.LLM_PROVIDER) { + "openai-compat" { "2" } + "orcarouter" { "3" } + default { "1" } + } $providerChoice = Read-Host "$(Get-Msg 'llm.provider.select') [${defaultProvider}]" $providerChoice = if ($providerChoice) { $providerChoice } else { $defaultProvider } } elseif ($script:AGENTTEAMS_QUICKSTART) { @@ -1994,6 +2001,38 @@ function Step-Llm { Test-LlmConnectivity -BaseUrl $script:config.OPENAI_BASE_URL -ApiKey $script:config.LLM_API_KEY -Model $script:config.DEFAULT_MODEL if ($script:StepResult -eq "back") { return } } + "^(3|orcarouter)$" { + $script:config.LLM_PROVIDER = "orcarouter" + $script:config.OPENAI_BASE_URL = "https://api.orcarouter.ai/v1" + Write-Log (Get-Msg "llm.provider.selected_openai" -f "OrcaRouter") + Write-Log (Get-Msg "llm.openai.base_url_label" -f $script:config.OPENAI_BASE_URL) + if ($script:AGENTTEAMS_UPGRADE -and $env:AGENTTEAMS_UPGRADE_KEEP_ALL -eq "1") { + Write-Log (Get-Msg "prompt.upgrade_keep" -f (Get-Msg "llm.openai.model_prompt"), $script:config.DEFAULT_MODEL) + } else { + $currentModel = $script:config.DEFAULT_MODEL + if ($currentModel) { + $modelInput = Read-Host "$(Get-Msg 'llm.openai.model_prompt') [${currentModel}]" + } else { + $modelInput = Read-Host (Get-Msg 'llm.openai.model_prompt') + } + if ($modelInput -eq "b") { $script:StepResult = "back"; return } + if ($modelInput) { + $script:config.DEFAULT_MODEL = $modelInput + } elseif ($currentModel) { + $script:config.DEFAULT_MODEL = $currentModel + } else { + $script:config.DEFAULT_MODEL = "orcarouter/auto" + } + } + Write-Log (Get-Msg "llm.model.label" -f $script:config.DEFAULT_MODEL) + Request-CustomModelParams $script:config.DEFAULT_MODEL + if ($script:StepResult -eq "back") { return } + Write-Log "" + $script:config.LLM_API_KEY = Read-Prompt -VarName "AGENTTEAMS_LLM_API_KEY" -PromptText (Get-Msg "llm.apikey_prompt") -Secret + if ($script:StepResult -eq "back") { return } + Test-LlmConnectivity -BaseUrl $script:config.OPENAI_BASE_URL -ApiKey $script:config.LLM_API_KEY -Model $script:config.DEFAULT_MODEL + if ($script:StepResult -eq "back") { return } + } default { Write-Error (Get-Msg "llm.provider.invalid" -f $providerChoice) } @@ -3348,6 +3387,8 @@ function Install-Manager { # Create OpenAI-compatible provider if needed if ($config.LLM_PROVIDER -eq "openai-compat") { New-OpenAICompatProvider -BaseUrl $config.OPENAI_BASE_URL -ApiKey $config.LLM_API_KEY -ConsolePort ([int]$config.PORT_CONSOLE) + } elseif ($config.LLM_PROVIDER -eq "orcarouter") { + New-OpenAICompatProvider -BaseUrl $config.OPENAI_BASE_URL -ApiKey $config.LLM_API_KEY -ConsolePort ([int]$config.PORT_CONSOLE) -ProviderName "orcarouter" } # Print success message diff --git a/manager/scripts/init/setup-higress.sh b/manager/scripts/init/setup-higress.sh index 0d84e61d0..da06a8107 100755 --- a/manager/scripts/init/setup-higress.sh +++ b/manager/scripts/init/setup-higress.sh @@ -27,8 +27,9 @@ LLM_PROVIDER="${AGENTTEAMS_LLM_PROVIDER:-qwen}" LLM_API_URL="${AGENTTEAMS_LLM_API_URL:-}" if [ -z "${LLM_API_URL}" ]; then case "${LLM_PROVIDER}" in - qwen) LLM_API_URL="https://dashscope.aliyuncs.com/compatible-mode/v1" ;; - *) LLM_API_URL="" ;; + qwen) LLM_API_URL="https://dashscope.aliyuncs.com/compatible-mode/v1" ;; + orcarouter) LLM_API_URL="https://api.orcarouter.ai/v1" ;; + *) LLM_API_URL="" ;; esac fi @@ -195,6 +196,25 @@ if [ -n "${AGENTTEAMS_LLM_API_KEY}" ]; then higress_api POST /v1/ai/providers "Creating LLM provider (qwen)" "${PROVIDER_BODY}" fi ;; + orcarouter) + # OrcaRouter: OpenAI-compatible gateway (https://www.orcarouter.ai) + # Service source (GET → PUT if exists, POST if not) + existing_svc=$(higress_get /v1/service-sources/orcarouter) + SVC_BODY='{"type":"dns","name":"orcarouter","port":443,"protocol":"https","proxyName":"","domain":"api.orcarouter.ai"}' + if [ -n "${existing_svc}" ]; then + higress_api PUT /v1/service-sources/orcarouter "Updating orcarouter DNS service source" "${SVC_BODY}" + else + higress_api POST /v1/service-sources "Registering orcarouter DNS service source" "${SVC_BODY}" + fi + + PROVIDER_BODY='{"type":"openai","name":"orcarouter","tokens":["'"${AGENTTEAMS_LLM_API_KEY}"'"],"version":0,"protocol":"openai/v1","tokenFailoverConfig":{"enabled":false},"rawConfigs":{"openaiCustomUrl":"https://api.orcarouter.ai/v1","openaiCustomServiceName":"orcarouter.dns","openaiCustomServicePort":443,"agentteamsMode":true}}' + existing_provider=$(higress_get /v1/ai/providers/orcarouter) + if [ -n "${existing_provider}" ]; then + higress_api PUT /v1/ai/providers/orcarouter "Updating LLM provider (orcarouter)" "${PROVIDER_BODY}" + else + higress_api POST /v1/ai/providers "Creating LLM provider (orcarouter)" "${PROVIDER_BODY}" + fi + ;; openai-compat) OPENAI_BASE_URL="${AGENTTEAMS_OPENAI_BASE_URL:-}" if [ -z "${OPENAI_BASE_URL}" ]; then diff --git a/manager/scripts/init/start-manager-agent.sh b/manager/scripts/init/start-manager-agent.sh index ae0df1bf7..cef99f72e 100755 --- a/manager/scripts/init/start-manager-agent.sh +++ b/manager/scripts/init/start-manager-agent.sh @@ -430,7 +430,8 @@ if [ -n "${_HIGRESS_CONSOLE_URL}" ]; then _LLM_API_URL="${AGENTTEAMS_LLM_API_URL:-}" if [ -z "${_LLM_API_URL}" ]; then case "${_LLM_PROVIDER}" in - qwen) _LLM_API_URL="https://dashscope.aliyuncs.com/compatible-mode/v1" ;; + qwen) _LLM_API_URL="https://dashscope.aliyuncs.com/compatible-mode/v1" ;; + orcarouter) _LLM_API_URL="https://api.orcarouter.ai/v1" ;; esac fi # 4. LLM Provider type-specific config @@ -439,6 +440,11 @@ if [ -n "${_HIGRESS_CONSOLE_URL}" ]; then _k8s_higress_api POST /v1/ai/providers "Creating LLM provider (qwen)" \ '{"type":"qwen","name":"qwen","tokens":["'"${AGENTTEAMS_LLM_API_KEY}"'"],"protocol":"openai/v1","tokenFailoverConfig":{"enabled":false},"rawConfigs":{"qwenEnableSearch":false,"qwenEnableCompatible":true,"qwenFileIds":[],"agentteamsMode":true}}' ;; + orcarouter) + # OrcaRouter: OpenAI-compatible gateway (https://www.orcarouter.ai) + _k8s_higress_api POST /v1/ai/providers "Creating LLM provider (orcarouter)" \ + '{"type":"openai","name":"orcarouter","tokens":["'"${AGENTTEAMS_LLM_API_KEY}"'"],"version":0,"protocol":"openai/v1","tokenFailoverConfig":{"enabled":false},"rawConfigs":{"openaiCustomUrl":"https://api.orcarouter.ai/v1","openaiCustomServiceName":"orcarouter.dns","openaiCustomServicePort":443,"agentteamsMode":true}}' + ;; *) _BODY='{"name":"'"${_LLM_PROVIDER}"'","type":"openai","tokens":["'"${AGENTTEAMS_LLM_API_KEY}"'"],"modelMapping":{},"protocol":"openai/v1","rawConfigs":{"agentteamsMode":true}}' _k8s_higress_api POST /v1/ai/providers "Creating LLM provider (${_LLM_PROVIDER})" "${_BODY}"