refactor(integrations): retire unavailable options

Remove retired Command Code, Discord, and Telegram integration entries, search targets, and documentation. Keep Command Code provider usage and logo support available through normalized provider ID aliases.
This commit is contained in:
Bohdan Triapitsyn
2026-08-22 01:10:19 +03:00
parent 0b01f5ae2d
commit 0d50253efa
32 changed files with 98 additions and 379 deletions
+3 -15
View File
@@ -1,20 +1,17 @@
--- ---
title: Integrationen title: Integrationen
description: Nutze dein Claude-, Command-Code- oder Cursor-Abo als Provider. description: Nutze dein Claude- oder Cursor-Abo als Provider.
--- ---
# Integrationen # Integrationen
Eine Integration ist ein kleines Plugin, das OpenChamber einen Provider hinzufügt — auf Basis eines Abos, das du bereits hast. Verwalten kannst du sie unter **Settings → Integrations**. Eine Integration ist ein kleines Plugin, das OpenChamber einen Provider hinzufügt — auf Basis eines Abos, das du bereits hast. Verwalten kannst du sie unter **Settings → Integrations**.
> **Experimentelle Funktion:** Integrationen können sich ändern oder nicht mehr funktionieren. Nutze sie nach eigenem Ermessen. > **Experimentelle Funktion.** Wir bemühen uns, die Richtlinien der Anbieter zu respektieren, aber Kontobeschränkungen und Sperrungen liegen bei jedem Anbieter. Nutze Integrationen auf eigenes Risiko.
Wir haben diese Integrationen so entwickelt, dass sie die vorgesehenen Anmeldewege der Anbieter nutzen und bekannte Verstöße gegen deren Nutzungsbedingungen vermeiden. Wir können nicht garantieren, dass ein Anbieter jede Nutzung oder jedes Konto akzeptiert. Lies die Bedingungen des Anbieters und nutze Integrationen auf eigenes Risiko. OpenChamber kann keine Kontobeschränkungen, Sperrungen oder Streitfälle mit einem Anbieter klären.
Verfügbare Integrationen: Verfügbare Integrationen:
- **Claude Code** — dein Claude Pro- oder Max-Plan, ohne API-Keys - **Claude Code** — dein Claude Pro- oder Max-Plan, ohne API-Keys
- **Command Code** — dein Command-Code-Plan
- **Cursor** — die Modell-Limits deines Cursor-Plans - **Cursor** — die Modell-Limits deines Cursor-Plans
## Integration installieren ## Integration installieren
@@ -33,19 +30,10 @@ Claude Code nutzt deinen Claude Pro- oder Max-Plan — ohne API-Keys und ohne se
1. Installiere die Integration (siehe oben). 1. Installiere die Integration (siehe oben).
2. Wähle **Set up** und melde dich an. Wenn du die Claude Code CLI noch nicht hast, bietet die Einrichtung an, sie zuerst zu installieren, und meldet dich danach an. 2. Wähle **Set up** und melde dich an. Wenn du die Claude Code CLI noch nicht hast, bietet die Einrichtung an, sie zuerst zu installieren, und meldet dich danach an.
Claude Code ist die einzige Integration hier, die ihre Provider-CLI installiert und angemeldet benötigt. Command Code und Cursor brauchen ihre CLIs nicht. Claude Code ist die einzige Integration hier, die ihre Provider-CLI installiert und angemeldet benötigt. Cursor braucht seine CLI nicht.
**Wie dein Claude-Konto geschützt bleibt:** Diese Integration nutzt das offizielle Claude Agent SDK von Anthropic und deine installierte Claude Code CLI. Sie kapert kein OAuth, extrahiert oder wiederholt keine Browser-Tokens, gibt sich nicht als nicht unterstützter Client aus und umgeht nicht Anthropics Authentifizierung. Sie bleibt auf dem von Anthropic unterstützten Zugriffsweg und trägt daher nicht das mit Token-Hijacking oder unautorisierten Authentifizierungsumgehungen verbundene Sperrrisiko. **Wie dein Claude-Konto geschützt bleibt:** Diese Integration nutzt das offizielle Claude Agent SDK von Anthropic und deine installierte Claude Code CLI. Sie kapert kein OAuth, extrahiert oder wiederholt keine Browser-Tokens, gibt sich nicht als nicht unterstützter Client aus und umgeht nicht Anthropics Authentifizierung. Sie bleibt auf dem von Anthropic unterstützten Zugriffsweg und trägt daher nicht das mit Token-Hijacking oder unautorisierten Authentifizierungsumgehungen verbundene Sperrrisiko.
## Command Code
Command Code nutzt deinen Command-Code-Plan.
1. Installiere die Integration (siehe oben).
2. Wähle **Set up** — es öffnet sich eine Browserseite. Genehmige den Zugriff und kehre zu OpenChamber zurück.
Auf einem Headless-Server oder in CI setze stattdessen die Umgebungsvariable `COMMAND_CODE_API_KEY`, anstatt dich im Browser anzumelden.
## Cursor ## Cursor
Cursor macht die Modelle deines Cursor-Plans in OpenChamber nutzbar. Cursor macht die Modelle deines Cursor-Plans in OpenChamber nutzbar.
+3 -15
View File
@@ -1,20 +1,17 @@
--- ---
title: Integraciones title: Integraciones
description: Usa tu suscripción de Claude, Command Code o Cursor como proveedor. description: Usa tu suscripción de Claude o Cursor como proveedor.
--- ---
# Integraciones # Integraciones
Una integración es un pequeño plugin que añade un proveedor a OpenChamber usando una suscripción que ya tienes. Las gestionas en **Settings → Integrations**. Una integración es un pequeño plugin que añade un proveedor a OpenChamber usando una suscripción que ya tienes. Las gestionas en **Settings → Integrations**.
> **Función experimental:** las integraciones pueden cambiar o dejar de funcionar. Úsalas bajo tu propia responsabilidad. > **Función experimental.** Buscamos respetar las políticas de los proveedores, pero las restricciones y suspensiones de cuentas son decisión de cada proveedor. Usa las integraciones bajo tu propia responsabilidad.
Diseñamos estas integraciones para seguir los flujos de inicio de sesión previstos por los proveedores y evitar infracciones conocidas de sus Términos de Servicio. No podemos garantizar que un proveedor acepte cada uso o cuenta. Revisa los términos del proveedor y usa las integraciones bajo tu propia responsabilidad. OpenChamber no puede resolver restricciones, suspensiones de cuentas ni disputas con un proveedor.
Integraciones disponibles: Integraciones disponibles:
- **Claude Code** — tu plan Claude Pro o Max, sin claves de API - **Claude Code** — tu plan Claude Pro o Max, sin claves de API
- **Command Code** — tu plan de Command Code
- **Cursor** — los límites de modelos de tu plan de Cursor - **Cursor** — los límites de modelos de tu plan de Cursor
## Instalar una integración ## Instalar una integración
@@ -33,19 +30,10 @@ Claude Code usa tu plan Claude Pro o Max — sin claves de API y sin una app de
1. Instala la integración (arriba). 1. Instala la integración (arriba).
2. Elige **Set up** e inicia sesión. Si aún no tienes la CLI de Claude Code, la configuración ofrece instalarla primero y luego iniciar sesión. 2. Elige **Set up** e inicia sesión. Si aún no tienes la CLI de Claude Code, la configuración ofrece instalarla primero y luego iniciar sesión.
Claude Code es la única integración de esta página que requiere tener la CLI de su proveedor instalada y con sesión iniciada. Command Code y Cursor no requieren sus CLIs. Claude Code es la única integración de esta página que requiere tener la CLI de su proveedor instalada y con sesión iniciada. Cursor no requiere su CLI.
**Cómo se protege tu cuenta de Claude:** esta integración usa el Claude Agent SDK oficial de Anthropic y tu CLI de Claude Code instalada. No secuestra OAuth, no extrae ni reutiliza tokens del navegador, no se hace pasar por un cliente no admitido ni omite la autenticación de Anthropic. Se mantiene en la vía de acceso admitida por Anthropic, por lo que no conlleva el riesgo de baneo asociado al secuestro de tokens o a rodeos de autenticación no autorizados. **Cómo se protege tu cuenta de Claude:** esta integración usa el Claude Agent SDK oficial de Anthropic y tu CLI de Claude Code instalada. No secuestra OAuth, no extrae ni reutiliza tokens del navegador, no se hace pasar por un cliente no admitido ni omite la autenticación de Anthropic. Se mantiene en la vía de acceso admitida por Anthropic, por lo que no conlleva el riesgo de baneo asociado al secuestro de tokens o a rodeos de autenticación no autorizados.
## Command Code
Command Code usa tu plan de Command Code.
1. Instala la integración (arriba).
2. Elige **Set up** — se abre una página en el navegador. Autoriza el acceso y vuelve a OpenChamber.
En una máquina sin interfaz gráfica o en CI, define la variable de entorno `COMMAND_CODE_API_KEY` en lugar de iniciar sesión en el navegador.
## Cursor ## Cursor
Cursor hace disponibles en OpenChamber los modelos incluidos en tu plan de Cursor. Cursor hace disponibles en OpenChamber los modelos incluidos en tu plan de Cursor.
+1 -1
View File
@@ -45,6 +45,6 @@ Los inicios de sesión de los proveedores los guarda OpenCode, no OpenChamber, a
## Relacionado ## Relacionado
- [Integraciones](/es/integrations/) — usa una suscripción de Claude, Command Code o Cursor como proveedor - [Integraciones](/es/integrations/) — usa una suscripción de Claude o Cursor como proveedor
- [Servidores MCP](/es/mcp/) — añade herramientas extra para los agentes - [Servidores MCP](/es/mcp/) — añade herramientas extra para los agentes
- [Uso y cuotas](/es/usage/) — controla cuánto has consumido - [Uso y cuotas](/es/usage/) — controla cuánto has consumido
+3 -15
View File
@@ -1,20 +1,17 @@
--- ---
title: Intégrations title: Intégrations
description: Utilise ton abonnement Claude, Command Code ou Cursor comme fournisseur. description: Utilise ton abonnement Claude ou Cursor comme fournisseur.
--- ---
# Intégrations # Intégrations
Une intégration est un petit plugin qui ajoute un fournisseur à OpenChamber à partir d'un abonnement que tu possèdes déjà. Tu les gères dans **Settings → Integrations**. Une intégration est un petit plugin qui ajoute un fournisseur à OpenChamber à partir d'un abonnement que tu possèdes déjà. Tu les gères dans **Settings → Integrations**.
> **Fonctionnalité expérimentale :** les intégrations peuvent changer ou cesser de fonctionner. Utilise-les à ta discrétion. > **Fonctionnalité expérimentale.** Nous cherchons à respecter les règles des fournisseurs, mais les restrictions et suspensions de compte relèvent de leur décision. Utilise les intégrations à tes risques.
Nous avons conçu ces intégrations pour suivre les méthodes de connexion prévues par les fournisseurs et éviter les violations connues de leurs conditions d'utilisation. Nous ne pouvons pas garantir qu'un fournisseur acceptera chaque usage ou chaque compte. Consulte les conditions du fournisseur et utilise les intégrations à tes risques. OpenChamber ne peut pas résoudre les restrictions, suspensions de compte ou litiges avec un fournisseur.
Intégrations disponibles : Intégrations disponibles :
- **Claude Code** — ton plan Claude Pro ou Max, sans clés API - **Claude Code** — ton plan Claude Pro ou Max, sans clés API
- **Command Code** — ton plan Command Code
- **Cursor** — les limites de modèles de ton plan Cursor - **Cursor** — les limites de modèles de ton plan Cursor
## Installer une intégration ## Installer une intégration
@@ -33,19 +30,10 @@ Claude Code utilise ton plan Claude Pro ou Max — sans clés API et sans applic
1. Installe l'intégration (ci-dessus). 1. Installe l'intégration (ci-dessus).
2. Choisis **Set up** et connecte-toi. Si tu n'as pas encore la CLI Claude Code, la configuration propose de l'installer d'abord, puis de te connecter. 2. Choisis **Set up** et connecte-toi. Si tu n'as pas encore la CLI Claude Code, la configuration propose de l'installer d'abord, puis de te connecter.
Claude Code est la seule intégration ici qui exige que la CLI de son fournisseur soit installée et connectée. Command Code et Cursor n'exigent pas leurs CLIs. Claude Code est la seule intégration ici qui exige que la CLI de son fournisseur soit installée et connectée. Cursor n'exige pas sa CLI.
**Comment ton compte Claude reste protégé :** cette intégration utilise le Claude Agent SDK officiel d'Anthropic et ta CLI Claude Code installée. Elle ne détourne pas l'OAuth, n'extrait ni rejoue de tokens de navigateur, ne se fait pas passer pour un client non pris en charge et ne contourne pas l'authentification d'Anthropic. Elle reste sur la voie d'accès prise en charge par Anthropic et ne porte donc pas le risque de bannissement associé au détournement de tokens ou aux contournements d'authentification non autorisés. **Comment ton compte Claude reste protégé :** cette intégration utilise le Claude Agent SDK officiel d'Anthropic et ta CLI Claude Code installée. Elle ne détourne pas l'OAuth, n'extrait ni rejoue de tokens de navigateur, ne se fait pas passer pour un client non pris en charge et ne contourne pas l'authentification d'Anthropic. Elle reste sur la voie d'accès prise en charge par Anthropic et ne porte donc pas le risque de bannissement associé au détournement de tokens ou aux contournements d'authentification non autorisés.
## Command Code
Command Code utilise ton plan Command Code.
1. Installe l'intégration (ci-dessus).
2. Choisis **Set up** — une page s'ouvre dans le navigateur. Autorise l'accès, puis reviens dans OpenChamber.
Sur une machine sans interface graphique ou en CI, définis la variable d'environnement `COMMAND_CODE_API_KEY` au lieu de te connecter via le navigateur.
## Cursor ## Cursor
Cursor rend disponibles dans OpenChamber les modèles inclus dans ton plan Cursor. Cursor rend disponibles dans OpenChamber les modèles inclus dans ton plan Cursor.
+1 -1
View File
@@ -45,6 +45,6 @@ Les connexions aux fournisseurs sont stockées par OpenCode, pas OpenChamber ; e
## Pages liées ## Pages liées
- [Intégrations](/integrations/) — utiliser un abonnement Claude, Command Code ou Cursor comme fournisseur - [Intégrations](/integrations/) — utiliser un abonnement Claude ou Cursor comme fournisseur
- [Serveurs MCP](/mcp/) — ajouter des outils supplémentaires aux agents - [Serveurs MCP](/mcp/) — ajouter des outils supplémentaires aux agents
- [Utilisation et quotas](/usage/) — suivre votre consommation - [Utilisation et quotas](/usage/) — suivre votre consommation
+3 -15
View File
@@ -1,20 +1,17 @@
--- ---
title: Integrations title: Integrations
description: Use your Claude, Command Code, or Cursor subscription as a provider. description: Use your Claude or Cursor subscription as a provider.
--- ---
# Integrations # Integrations
An integration is a small plugin that adds a provider to OpenChamber using a subscription you already have. You manage them at **Settings → Integrations**. An integration is a small plugin that adds a provider to OpenChamber using a subscription you already have. You manage them at **Settings → Integrations**.
> **Experimental feature:** integrations may change or stop working. Use them at your own discretion. > **Experimental feature.** We aim to respect provider policies, but account restrictions and suspensions remain each provider's decision. Use integrations at your own risk.
We designed these integrations to follow providers' intended sign-in flows and avoid known Terms of Service violations. We cannot guarantee that a provider will accept every use or account. Review the provider's terms and use integrations at your own risk. OpenChamber cannot resolve account restrictions, suspensions, or disputes with a provider.
Available integrations: Available integrations:
- **Claude Code** — your Claude Pro or Max plan, no API keys - **Claude Code** — your Claude Pro or Max plan, no API keys
- **Command Code** — your Command Code plan
- **Cursor** — the model limits of your Cursor plan - **Cursor** — the model limits of your Cursor plan
## Install an integration ## Install an integration
@@ -33,19 +30,10 @@ Claude Code uses your Claude Pro or Max plan — no API keys and no separate Cla
1. Install the integration (above). 1. Install the integration (above).
2. Choose **Set up** and sign in. If you don't have the Claude Code CLI yet, setup offers to install it first and then sign you in. 2. Choose **Set up** and sign in. If you don't have the Claude Code CLI yet, setup offers to install it first and then sign you in.
Claude Code is the only integration here that requires its provider CLI to be installed and signed in. Command Code and Cursor do not require their CLIs. Claude Code is the only integration here that requires its provider CLI to be installed and signed in. Cursor does not require its CLI.
**How your Claude account stays safe:** this integration uses Anthropic's official Claude Agent SDK and your installed Claude Code CLI. It does not hijack OAuth, extract or replay browser tokens, impersonate an unsupported client, or bypass Anthropic's authentication flow. It stays on Anthropic's supported access path, so it does not carry the account-ban risk of token hijacking or unauthorized authentication workarounds. **How your Claude account stays safe:** this integration uses Anthropic's official Claude Agent SDK and your installed Claude Code CLI. It does not hijack OAuth, extract or replay browser tokens, impersonate an unsupported client, or bypass Anthropic's authentication flow. It stays on Anthropic's supported access path, so it does not carry the account-ban risk of token hijacking or unauthorized authentication workarounds.
## Command Code
Command Code uses your Command Code plan.
1. Install the integration (above).
2. Choose **Set up** — a browser page opens. Approve access, then return to OpenChamber.
On a headless machine or in CI, set the `COMMAND_CODE_API_KEY` environment variable instead of signing in in the browser.
## Cursor ## Cursor
Cursor makes the models included in your Cursor plan available in OpenChamber. Cursor makes the models included in your Cursor plan available in OpenChamber.
+3 -15
View File
@@ -1,20 +1,17 @@
--- ---
title: 統合機能 title: 統合機能
description: Claude、Command Code、Cursor のサブスクリプションをプロバイダーとして使う。 description: Claude または Cursor のサブスクリプションをプロバイダーとして使う。
--- ---
# 統合機能 # 統合機能
統合機能(インテグレーション)は、すでに持っているサブスクリプションを使って OpenChamber にプロバイダーを追加する小さなプラグインです。**Settings → Integrations** で管理します。 統合機能(インテグレーション)は、すでに持っているサブスクリプションを使って OpenChamber にプロバイダーを追加する小さなプラグインです。**Settings → Integrations** で管理します。
> **実験的な機能:** 連携は変更されたり、動作しなくなったりする可能性があります。自己責任で使用してください。 > **実験的な機能** プロバイダーの方針を尊重するよう努めていますが、アカウントの制限や停止は各プロバイダーの判断に委ねられます。自己責任で連携を使用してください。
これらの連携は、プロバイダーが想定するサインインの流れに従い、既知の利用規約違反を避けるよう設計しています。ただし、プロバイダーがすべての利用方法やアカウントを受け入れることは保証できません。プロバイダーの規約を確認し、自己責任で連携を使用してください。OpenChamber は、プロバイダーによるアカウント制限、停止、または紛争を解決できません。
利用できる統合機能: 利用できる統合機能:
- **Claude Code** — Claude Pro または Max プラン、API キー不要 - **Claude Code** — Claude Pro または Max プラン、API キー不要
- **Command Code** — Command Code のプラン
- **Cursor** — Cursor プランのモデル利用枠 - **Cursor** — Cursor プランのモデル利用枠
## 統合機能をインストールする ## 統合機能をインストールする
@@ -33,19 +30,10 @@ Claude Code は Claude Pro または Max プランを使います — API キー
1. 統合機能をインストールします(上記)。 1. 統合機能をインストールします(上記)。
2. **Set up** を選んでサインインします。Claude Code CLI がまだない場合は、セットアップがまずインストールを提案し、その後サインインします。 2. **Set up** を選んでサインインします。Claude Code CLI がまだない場合は、セットアップがまずインストールを提案し、その後サインインします。
Claude Code は、ここで唯一プロバイダーの CLI のインストールとサインインを必要とする統合機能です。Command Code と Cursor は CLI を必要としません。 Claude Code は、ここで唯一プロバイダーの CLI のインストールとサインインを必要とする統合機能です。Cursor は CLI を必要としません。
**Claude アカウントが守られる仕組み:** この統合機能は Anthropic の公式 Claude Agent SDK と、インストール済みの Claude Code CLI を使用します。OAuth の乗っ取り、ブラウザートークンの抽出や再生、未対応クライアントへの偽装、Anthropic の認証フローの回避は一切行いません。Anthropic がサポートする正規のアクセス経路を使うため、トークン乗っ取りや不正な認証の回避につきもののアカウント停止リスクはありません。 **Claude アカウントが守られる仕組み:** この統合機能は Anthropic の公式 Claude Agent SDK と、インストール済みの Claude Code CLI を使用します。OAuth の乗っ取り、ブラウザートークンの抽出や再生、未対応クライアントへの偽装、Anthropic の認証フローの回避は一切行いません。Anthropic がサポートする正規のアクセス経路を使うため、トークン乗っ取りや不正な認証の回避につきもののアカウント停止リスクはありません。
## Command Code
Command Code は Command Code のプランを使います。
1. 統合機能をインストールします(上記)。
2. **Set up** を選ぶとブラウザーでページが開きます。アクセスを許可して OpenChamber に戻ります。
画面のないサーバーや CI では、ブラウザーでサインインする代わりに環境変数 `COMMAND_CODE_API_KEY` を設定してください。
## Cursor ## Cursor
Cursor は Cursor プランに含まれるモデルを OpenChamber で使えるようにします。 Cursor は Cursor プランに含まれるモデルを OpenChamber で使えるようにします。
+1 -1
View File
@@ -45,6 +45,6 @@ OpenChamber が何かを行うには、少なくとも 1 つの AI プロバイ
## 関連 ## 関連
- [統合機能](/integrations/) — Claude、Command Code、Cursor のサブスクリプションをプロバイダーとして使う - [統合機能](/integrations/) — Claude または Cursor のサブスクリプションをプロバイダーとして使う
- [MCP サーバー](/mcp/) — エージェントに追加ツールを加える - [MCP サーバー](/mcp/) — エージェントに追加ツールを加える
- [使用量とクォータ](/usage/) — 使った量を追跡する - [使用量とクォータ](/usage/) — 使った量を追跡する
+3 -15
View File
@@ -1,20 +1,17 @@
--- ---
title: 통합 기능 title: 통합 기능
description: Claude, Command Code 또는 Cursor 구독을 공급자로 사용하세요. description: Claude 또는 Cursor 구독을 공급자로 사용하세요.
--- ---
# 통합 기능 # 통합 기능
통합 기능(인테그레이션)은 이미 가지고 있는 구독을 사용해 OpenChamber에 공급자를 추가하는 작은 플러그인입니다. **Settings → Integrations**에서 관리합니다. 통합 기능(인테그레이션)은 이미 가지고 있는 구독을 사용해 OpenChamber에 공급자를 추가하는 작은 플러그인입니다. **Settings → Integrations**에서 관리합니다.
> **실험 단계 기능:** 통합 기능은 변경되거나 작동하지 않을 수 있습니다. 본인의 판단에 따라 사용하세요. > **실험 단계 기능.** 프로바이더 정책을 존중하려 노력하지만, 계정 제한과 정지는 각 프로바이더의 결정입니다. 본인의 책임 아래 통합 기능을 사용하세요.
이 통합 기능은 프로바이더가 의도한 로그인 흐름을 따르고 알려진 서비스 약관 위반을 피하도록 설계했습니다. 프로바이더가 모든 사용 방식이나 계정을 허용한다고 보장할 수는 없습니다. 프로바이더의 약관을 검토하고 본인의 책임 아래 통합 기능을 사용하세요. OpenChamber는 프로바이더와의 계정 제한, 정지 또는 분쟁을 해결할 수 없습니다.
사용 가능한 통합 기능: 사용 가능한 통합 기능:
- **Claude Code** — Claude Pro 또는 Max 플랜, API 키 불필요 - **Claude Code** — Claude Pro 또는 Max 플랜, API 키 불필요
- **Command Code** — Command Code 플랜
- **Cursor** — Cursor 플랜의 모델 한도 - **Cursor** — Cursor 플랜의 모델 한도
## 통합 기능 설치 ## 통합 기능 설치
@@ -33,19 +30,10 @@ Claude Code는 Claude Pro 또는 Max 플랜을 사용합니다 — API 키도
1. 통합 기능을 설치합니다(위 참고). 1. 통합 기능을 설치합니다(위 참고).
2. **Set up**를 선택하고 로그인합니다. Claude Code CLI가 아직 없으면 설정에서 먼저 설치를 제안한 뒤 로그인을 진행합니다. 2. **Set up**를 선택하고 로그인합니다. Claude Code CLI가 아직 없으면 설정에서 먼저 설치를 제안한 뒤 로그인을 진행합니다.
Claude Code는 여기에서 유일하게 공급자 CLI 설치와 로그인을 필요로 하는 통합 기능입니다. Command Code와 Cursor는 CLI가 필요 없습니다. Claude Code는 여기에서 유일하게 공급자 CLI 설치와 로그인을 필요로 하는 통합 기능입니다. Cursor는 CLI가 필요 없습니다.
**Claude 계정이 안전하게 유지되는 방식:** 이 통합 기능은 Anthropic의 공식 Claude Agent SDK와 설치된 Claude Code CLI를 사용합니다. OAuth 탈취, 브라우저 토큰 추출·재사용, 지원되지 않는 클라이언트로의 위장, Anthropic 인증 우회를 하지 않습니다. Anthropic이 지원하는 정상 경로를 사용하므로 토큰 탈취나 비인가 인증 우회에 따른 계정 정지 위험이 없습니다. **Claude 계정이 안전하게 유지되는 방식:** 이 통합 기능은 Anthropic의 공식 Claude Agent SDK와 설치된 Claude Code CLI를 사용합니다. OAuth 탈취, 브라우저 토큰 추출·재사용, 지원되지 않는 클라이언트로의 위장, Anthropic 인증 우회를 하지 않습니다. Anthropic이 지원하는 정상 경로를 사용하므로 토큰 탈취나 비인가 인증 우회에 따른 계정 정지 위험이 없습니다.
## Command Code
Command Code는 Command Code 플랜을 사용합니다.
1. 통합 기능을 설치합니다(위 참고).
2. **Set up**를 선택하면 브라우저에서 페이지가 열립니다. 접근을 승인한 뒤 OpenChamber로 돌아옵니다.
화면이 없는 서버나 CI 환경에서는 브라우저 로그인 대신 `COMMAND_CODE_API_KEY` 환경 변수를 설정하세요.
## Cursor ## Cursor
Cursor는 Cursor 플랜에 포함된 모델을 OpenChamber에서 사용할 수 있게 합니다. Cursor는 Cursor 플랜에 포함된 모델을 OpenChamber에서 사용할 수 있게 합니다.
+1 -1
View File
@@ -45,6 +45,6 @@ OpenChamber가 무언가를 하려면 먼저 최소한 하나의 AI 공급자가
## 관련 항목 ## 관련 항목
- [통합 기능](/ko/integrations/) — Claude, Command Code, Cursor 구독을 공급자로 사용 - [통합 기능](/ko/integrations/) — Claude 또는 Cursor 구독을 공급자로 사용
- [MCP Servers](/ko/mcp/) — 에이전트에 추가 도구를 제공합니다 - [MCP Servers](/ko/mcp/) — 에이전트에 추가 도구를 제공합니다
- [Usage & Quotas](/ko/usage/) — 사용량을 추적합니다 - [Usage & Quotas](/ko/usage/) — 사용량을 추적합니다
+3 -15
View File
@@ -1,20 +1,17 @@
--- ---
title: Integracje title: Integracje
description: Używaj subskrypcji Claude, Command Code lub Cursor jako dostawcy. description: Używaj subskrypcji Claude lub Cursor jako dostawcy.
--- ---
# Integracje # Integracje
Integracja to mała wtyczka, która dodaje dostawcę do OpenChamber na podstawie subskrypcji, którą już masz. Zarządzasz nimi w **Settings → Integrations**. Integracja to mała wtyczka, która dodaje dostawcę do OpenChamber na podstawie subskrypcji, którą już masz. Zarządzasz nimi w **Settings → Integrations**.
> **Funkcja eksperymentalna:** integracje mogą się zmienić lub przestać działać. Korzystasz z nich na własną odpowiedzialność. > **Funkcja eksperymentalna.** Staramy się przestrzegać zasad dostawców, ale ograniczenia i zawieszenia kont pozostają decyzją każdego dostawcy. Używaj integracji na własne ryzyko.
Zaprojektowaliśmy te integracje tak, aby korzystały z zamierzonych przez dostawców sposobów logowania i unikały znanych naruszeń ich warunków korzystania. Nie możemy zagwarantować, że dostawca zaakceptuje każdy sposób użycia lub konto. Sprawdź warunki dostawcy i używaj integracji na własne ryzyko. OpenChamber nie może rozwiązać ograniczeń konta, zawieszeń ani sporów z dostawcą.
Dostępne integracje: Dostępne integracje:
- **Claude Code** — Twój plan Claude Pro lub Max, bez kluczy API - **Claude Code** — Twój plan Claude Pro lub Max, bez kluczy API
- **Command Code** — Twój plan Command Code
- **Cursor** — limity modeli z Twojego planu Cursor - **Cursor** — limity modeli z Twojego planu Cursor
## Instalacja integracji ## Instalacja integracji
@@ -33,19 +30,10 @@ Claude Code korzysta z Twojego planu Claude Pro lub Max — bez kluczy API i bez
1. Zainstaluj integrację (patrz wyżej). 1. Zainstaluj integrację (patrz wyżej).
2. Wybierz **Set up** i zaloguj się. Jeśli nie masz jeszcze Claude Code CLI, konfiguracja zaoferuje najpierw jego instalację, a potem logowanie. 2. Wybierz **Set up** i zaloguj się. Jeśli nie masz jeszcze Claude Code CLI, konfiguracja zaoferuje najpierw jego instalację, a potem logowanie.
Claude Code jest jedyną integracją tutaj, która wymaga zainstalowanego i zalogowanego CLI swojego dostawcy. Command Code i Cursor nie wymaga swoich CLI. Claude Code jest jedyną integracją tutaj, która wymaga zainstalowanego i zalogowanego CLI swojego dostawcy. Cursor nie wymaga swojego CLI.
**Jak chronione jest Twoje konto Claude:** ta integracja używa oficjalnego Claude Agent SDK od Anthropic i Twojego zainstalowanego Claude Code CLI. Nie przechwytuje OAuth, nie wyodrębnia ani nie odtwarza tokenów przeglądarki, nie podszywa się pod nieobsługiwany klient i nie omija uwierzytelniania Anthropic. Działa na obsługiwanej przez Anthropic ścieżce dostępu, więc nie niesie ryzyka zablokowania konta związanego z przechwytywaniem tokenów lub nieautoryzowanymi obejściami uwierzytelniania. **Jak chronione jest Twoje konto Claude:** ta integracja używa oficjalnego Claude Agent SDK od Anthropic i Twojego zainstalowanego Claude Code CLI. Nie przechwytuje OAuth, nie wyodrębnia ani nie odtwarza tokenów przeglądarki, nie podszywa się pod nieobsługiwany klient i nie omija uwierzytelniania Anthropic. Działa na obsługiwanej przez Anthropic ścieżce dostępu, więc nie niesie ryzyka zablokowania konta związanego z przechwytywaniem tokenów lub nieautoryzowanymi obejściami uwierzytelniania.
## Command Code
Command Code korzysta z Twojego planu Command Code.
1. Zainstaluj integrację (patrz wyżej).
2. Wybierz **Set up** — w przeglądarce otworzy się strona. Zatwierdź dostęp i wróć do OpenChamber.
Na maszynie bez interfejsu graficznego lub w CI ustaw zmienną środowiskową `COMMAND_CODE_API_KEY` zamiast logowania w przeglądarce.
## Cursor ## Cursor
Cursor udostępnia w OpenChamber modele zawarte w Twoim planie Cursor. Cursor udostępnia w OpenChamber modele zawarte w Twoim planie Cursor.
+1 -1
View File
@@ -45,6 +45,6 @@ Logowania dostawców są przechowywane przez OpenCode, a nie OpenChamber, więc
## Powiązane ## Powiązane
- [Integracje](/pl/integrations/) — używaj subskrypcji Claude, Command Code lub Cursor jako dostawcy - [Integracje](/pl/integrations/) — używaj subskrypcji Claude lub Cursor jako dostawcy
- [Serwery MCP](/pl/mcp/) — dodaj agentom dodatkowe narzędzia - [Serwery MCP](/pl/mcp/) — dodaj agentom dodatkowe narzędzia
- [Zużycie i limity](/pl/usage/) — śledź, ile już wykorzystałeś - [Zużycie i limity](/pl/usage/) — śledź, ile już wykorzystałeś
+1 -1
View File
@@ -57,6 +57,6 @@ Provider sign-ins are stored by OpenCode, not OpenChamber, so they're shared wit
## Related ## Related
- [Integrations](/integrations/) — use a Claude, Command Code, or Cursor subscription as a provider - [Integrations](/integrations/) — use a Claude or Cursor subscription as a provider
- [MCP Servers](/mcp/) — add extra tools for agents - [MCP Servers](/mcp/) — add extra tools for agents
- [Usage & Quotas](/usage/) — track how much you've used - [Usage & Quotas](/usage/) — track how much you've used
@@ -1,20 +1,17 @@
--- ---
title: Integrações title: Integrações
description: Use sua assinatura Claude, Command Code ou Cursor como provedor. description: Use sua assinatura Claude ou Cursor como provedor.
--- ---
# Integrações # Integrações
Uma integração é um pequeno plugin que adiciona um provedor ao OpenChamber usando uma assinatura que você já tem. Você as gerencia em **Settings → Integrations**. Uma integração é um pequeno plugin que adiciona um provedor ao OpenChamber usando uma assinatura que você já tem. Você as gerencia em **Settings → Integrations**.
> **Recurso experimental:** as integrações podem mudar ou deixar de funcionar. Use-as por sua conta e risco. > **Recurso experimental.** Buscamos respeitar as políticas dos provedores, mas restrições e suspensões de conta continuam sendo decisão de cada provedor. Use as integrações por sua conta e risco.
Projetamos estas integrações para seguir os fluxos de login pretendidos pelos provedores e evitar violações conhecidas de seus Termos de Serviço. Não podemos garantir que um provedor aceitará todos os usos ou contas. Consulte os termos do provedor e use as integrações por sua conta e risco. O OpenChamber não pode resolver restrições, suspensões de conta ou disputas com um provedor.
Integrações disponíveis: Integrações disponíveis:
- **Claude Code** — seu plano Claude Pro ou Max, sem chaves de API - **Claude Code** — seu plano Claude Pro ou Max, sem chaves de API
- **Command Code** — seu plano Command Code
- **Cursor** — os limites de modelos do seu plano Cursor - **Cursor** — os limites de modelos do seu plano Cursor
## Instalar uma integração ## Instalar uma integração
@@ -33,19 +30,10 @@ O Claude Code usa seu plano Claude Pro ou Max — sem chaves de API e sem um app
1. Instale a integração (acima). 1. Instale a integração (acima).
2. Escolha **Set up** e faça login. Se você ainda não tem a CLI do Claude Code, a configuração oferece instalá-la primeiro e depois fazer login. 2. Escolha **Set up** e faça login. Se você ainda não tem a CLI do Claude Code, a configuração oferece instalá-la primeiro e depois fazer login.
O Claude Code é a única integração aqui que exige que a CLI do provedor esteja instalada e autenticada. Command Code e Cursor não exigem suas CLIs. O Claude Code é a única integração aqui que exige que a CLI do provedor esteja instalada e autenticada. Cursor não exige sua CLI.
**Como sua conta Claude fica protegida:** esta integração usa o Claude Agent SDK oficial da Anthropic e a CLI do Claude Code instalada em sua máquina. Ela não sequestra OAuth, não extrai nem reproduz tokens do navegador, não se passa por um cliente não suportado e não contorna a autenticação da Anthropic. Ela permanece no caminho de acesso suportado pela Anthropic, portanto não traz o risco de banimento de conta associado a sequestro de tokens ou a contornos de autenticação não autorizados. **Como sua conta Claude fica protegida:** esta integração usa o Claude Agent SDK oficial da Anthropic e a CLI do Claude Code instalada em sua máquina. Ela não sequestra OAuth, não extrai nem reproduz tokens do navegador, não se passa por um cliente não suportado e não contorna a autenticação da Anthropic. Ela permanece no caminho de acesso suportado pela Anthropic, portanto não traz o risco de banimento de conta associado a sequestro de tokens ou a contornos de autenticação não autorizados.
## Command Code
O Command Code usa seu plano Command Code.
1. Instale a integração (acima).
2. Escolha **Set up** — uma página abre no navegador. Autorize o acesso e volte ao OpenChamber.
Em uma máquina sem interface gráfica ou em CI, defina a variável de ambiente `COMMAND_CODE_API_KEY` em vez de fazer login pelo navegador.
## Cursor ## Cursor
O Cursor torna disponíveis no OpenChamber os modelos incluídos no seu plano Cursor. O Cursor torna disponíveis no OpenChamber os modelos incluídos no seu plano Cursor.
@@ -45,6 +45,6 @@ Os logins de provedores são armazenados pelo OpenCode, não pelo OpenChamber, e
## Relacionado ## Relacionado
- [Integrações](/pt-br/integrations/) — use uma assinatura Claude, Command Code ou Cursor como provedor - [Integrações](/pt-br/integrations/) — use uma assinatura Claude ou Cursor como provedor
- [Servidores MCP](/pt-br/mcp/) — adicione ferramentas extras para os agentes - [Servidores MCP](/pt-br/mcp/) — adicione ferramentas extras para os agentes
- [Uso e Cotas](/pt-br/usage/) — acompanhe quanto você já usou - [Uso e Cotas](/pt-br/usage/) — acompanhe quanto você já usou
+3 -15
View File
@@ -1,20 +1,17 @@
--- ---
title: Інтеграції title: Інтеграції
description: Використовуйте підписки Claude, Command Code або Cursor як провайдерів. description: Використовуйте підписки Claude або Cursor як провайдерів.
--- ---
# Інтеграції # Інтеграції
Інтеграція — це невеликий плагін, що додає провайдера до OpenChamber на основі підписки, яка в вас уже є. Керувати ними можна в **Settings → Integrations**. Інтеграція — це невеликий плагін, що додає провайдера до OpenChamber на основі підписки, яка в вас уже є. Керувати ними можна в **Settings → Integrations**.
> **Експериментальна функція:** інтеграції можуть змінюватися або перестати працювати. Використовуйте їх на власний розсуд. > **Експериментальна функція.** Ми прагнемо дотримуватися політик провайдерів, але обмеження та блокування облікових записів залишаються рішенням кожного провайдера. Використовуйте інтеграції на власний ризик.
Ми розробили ці інтеграції так, щоб вони використовували передбачені провайдерами способи входу й не порушували відомі нам умови користування. Ми не можемо гарантувати, що провайдер прийме кожен спосіб використання або кожен обліковий запис. Ознайомтеся з умовами провайдера й використовуйте інтеграції на власний ризик. OpenChamber не може вирішувати обмеження, блокування облікових записів або суперечки з провайдером.
Доступні інтеграції: Доступні інтеграції:
- **Claude Code** — ваша підписка Claude Pro або Max, без API-ключів - **Claude Code** — ваша підписка Claude Pro або Max, без API-ключів
- **Command Code** — ваша підписка Command Code
- **Cursor** — ліміти моделей вашої підписки Cursor - **Cursor** — ліміти моделей вашої підписки Cursor
## Встановлення інтеграції ## Встановлення інтеграції
@@ -33,19 +30,10 @@ Claude Code використовує вашу підписку Claude Pro або
1. Встановіть інтеграцію (вище). 1. Встановіть інтеграцію (вище).
2. Натисніть **Set up** і увійдіть. Якщо у вас ще немає Claude Code CLI, програма встановлення спершу запропонує його встановити, а потім виконає вхід. 2. Натисніть **Set up** і увійдіть. Якщо у вас ще немає Claude Code CLI, програма встановлення спершу запропонує його встановити, а потім виконає вхід.
Claude Code — єдина інтеграція тут, яка вимагає встановленого та залогіненого CLI свого провайдера. Для Command Code і Cursor їхні CLI не потрібні. Claude Code — єдина інтеграція тут, яка вимагає встановленого та залогіненого CLI свого провайдера. Для Cursor CLI не потрібен.
**Як захищається ваш обліковий запис Claude:** ця інтеграція використовує офіційний Claude Agent SDK від Anthropic і ваш встановлений Claude Code CLI. Вона не перехоплює OAuth, не витягує й не відтворює браузерні токени, не видає себе за непідтримуваний клієнт і не обходить процес автентифікації Anthropic. Усе працює через підтримуваний Anthropic шлях доступу, тож інтеграція не несе ризику блокування облікового запису, пов'язаного з перехопленням токенів або несанкціонованими способами автентифікації. **Як захищається ваш обліковий запис Claude:** ця інтеграція використовує офіційний Claude Agent SDK від Anthropic і ваш встановлений Claude Code CLI. Вона не перехоплює OAuth, не витягує й не відтворює браузерні токени, не видає себе за непідтримуваний клієнт і не обходить процес автентифікації Anthropic. Усе працює через підтримуваний Anthropic шлях доступу, тож інтеграція не несе ризику блокування облікового запису, пов'язаного з перехопленням токенів або несанкціонованими способами автентифікації.
## Command Code
Command Code використовує вашу підписку Command Code.
1. Встановіть інтеграцію (вище).
2. Натисніть **Set up** — відкриється сторінка в браузері. Підтвердьте доступ і поверніться до OpenChamber.
На сервері без графічного інтерфейсу або в CI замість входу через браузер задайте змінну середовища `COMMAND_CODE_API_KEY`.
## Cursor ## Cursor
Cursor робить доступними в OpenChamber моделі, що входять у вашу підписку Cursor. Cursor робить доступними в OpenChamber моделі, що входять у вашу підписку Cursor.
+1 -1
View File
@@ -45,6 +45,6 @@ description: Підключайте AI-провайдерів, обирайте
## Пов'язане ## Пов'язане
- [Інтеграції](/uk/integrations/) — використовуйте підписки Claude, Command Code або Cursor як провайдерів - [Інтеграції](/uk/integrations/) — використовуйте підписки Claude або Cursor як провайдерів
- [MCP Servers](/uk/mcp/) — додайте агентам додаткові інструменти - [MCP Servers](/uk/mcp/) — додайте агентам додаткові інструменти
- [Використання та квоти](/uk/usage/) — відстежуйте, скільки ви витратили - [Використання та квоти](/uk/usage/) — відстежуйте, скільки ви витратили
@@ -1,20 +1,17 @@
--- ---
title: 集成 title: 集成
description: 将你的 Claude、Command Code 或 Cursor 订阅用作提供商。 description: 将你的 Claude 或 Cursor 订阅用作提供商。
--- ---
# 集成 # 集成
集成是一个小型插件,它使用你已有的订阅为 OpenChamber 添加一个提供商。你可以在 **Settings → Integrations** 中管理它们。 集成是一个小型插件,它使用你已有的订阅为 OpenChamber 添加一个提供商。你可以在 **Settings → Integrations** 中管理它们。
> **实验性功能**集成可能会变更或停止工作。请自行酌情使用 > **实验性功能**我们力求遵守提供商的政策,但帐户限制和暂停仍由各提供商决定。请自行承担使用集成的风险
我们设计这些集成时,力求遵循提供商预期的登录流程,并避免已知的服务条款违规。我们无法保证提供商会接受每种使用方式或每个帐户。请查看提供商的条款,并自行承担使用集成的风险。OpenChamber 无法处理提供商施加的帐户限制、暂停或争议。
可用的集成: 可用的集成:
- **Claude Code** — 你的 Claude Pro 或 Max 套餐,无需 API 密钥 - **Claude Code** — 你的 Claude Pro 或 Max 套餐,无需 API 密钥
- **Command Code** — 你的 Command Code 套餐
- **Cursor** — 你的 Cursor 套餐的模型额度 - **Cursor** — 你的 Cursor 套餐的模型额度
## 安装集成 ## 安装集成
@@ -33,19 +30,10 @@ Claude Code 使用你的 Claude Pro 或 Max 套餐 — 无需 API 密钥,也
1. 安装集成(见上文)。 1. 安装集成(见上文)。
2. 选择 **Set up** 并登录。如果你还没有 Claude Code CLI,安装向导会先提供安装,然后再登录。 2. 选择 **Set up** 并登录。如果你还没有 Claude Code CLI,安装向导会先提供安装,然后再登录。
Claude Code 是这里唯一要求安装并登录其提供商 CLI 的集成。Command Code 和 Cursor 不需要它们的 CLI。 Claude Code 是这里唯一要求安装并登录其提供商 CLI 的集成。Cursor 不需要 CLI。
**你的 Claude 账户如何受到保护:** 此集成使用 Anthropic 官方的 Claude Agent SDK 和你已安装的 Claude Code CLI。它不会劫持 OAuth,不会提取或重放浏览器令牌,不会冒充不受支持的客户端,也不会绕过 Anthropic 的身份验证。它始终运行在 Anthropic 支持的访问路径上,因此不会带来与令牌劫持或未授权身份验证变通手段相关的封号风险。 **你的 Claude 账户如何受到保护:** 此集成使用 Anthropic 官方的 Claude Agent SDK 和你已安装的 Claude Code CLI。它不会劫持 OAuth,不会提取或重放浏览器令牌,不会冒充不受支持的客户端,也不会绕过 Anthropic 的身份验证。它始终运行在 Anthropic 支持的访问路径上,因此不会带来与令牌劫持或未授权身份验证变通手段相关的封号风险。
## Command Code
Command Code 使用你的 Command Code 套餐。
1. 安装集成(见上文)。
2. 选择 **Set up** — 浏览器中会打开一个页面。授权访问,然后返回 OpenChamber。
在没有图形界面的服务器或 CI 环境中,请设置环境变量 `COMMAND_CODE_API_KEY` 来代替浏览器登录。
## Cursor ## Cursor
Cursor 让你的 Cursor 套餐中包含的模型可以在 OpenChamber 中使用。 Cursor 让你的 Cursor 套餐中包含的模型可以在 OpenChamber 中使用。
@@ -45,6 +45,6 @@ description: 连接 AI 提供商、选择模型并设置智能体。
## 相关内容 ## 相关内容
- [集成](/zh-cn/integrations/) — 将 Claude、Command Code 或 Cursor 订阅用作提供商 - [集成](/zh-cn/integrations/) — 将 Claude 或 Cursor 订阅用作提供商
- [MCP Servers](/zh-cn/mcp/) — 为智能体添加额外工具 - [MCP Servers](/zh-cn/mcp/) — 为智能体添加额外工具
- [用量与配额](/zh-cn/usage/) — 跟踪你已使用的量 - [用量与配额](/zh-cn/usage/) — 跟踪你已使用的量
@@ -1,74 +0,0 @@
import React from 'react';
import { Icon } from '@/components/icon/Icon';
import { SettingsSection } from '@/components/sections/shared/SettingsSection';
import type { IconName } from '@/components/icon/icons';
import { useI18n, type I18nKey } from '@/lib/i18n';
import { cn } from '@/lib/utils';
type ComingSoonMessenger = {
id: 'discord' | 'telegram';
icon: IconName;
brandClassName: string;
nameKey: I18nKey;
descriptionKey: I18nKey;
};
const COMING_SOON_MESSENGERS: readonly ComingSoonMessenger[] = [
{
id: 'discord',
icon: 'discord-fill',
brandClassName: 'text-[#5865F2]',
nameKey: 'settings.integrations.messengers.discord.name',
descriptionKey: 'settings.integrations.messengers.discord.description',
},
{
id: 'telegram',
icon: 'telegram-fill',
brandClassName: 'text-[#2AABEE]',
nameKey: 'settings.integrations.messengers.telegram.name',
descriptionKey: 'settings.integrations.messengers.telegram.description',
},
] as const;
/**
* Non-interactive Discord/Telegram placeholders same card chrome as live
* integrations, greyed out, with a Coming soon badge and no expandable body.
*/
export const ComingSoonMessengersSection: React.FC = () => {
const { t } = useI18n();
return (
<SettingsSection
title={t('settings.integrations.messengers.title')}
info={t('settings.integrations.messengers.info')}
divider={false}
settingsItem="integrations.messengers"
contentClassName="space-y-3"
>
{COMING_SOON_MESSENGERS.map((messenger) => (
<div
key={messenger.id}
data-settings-item={`integrations.messengers.${messenger.id}`}
aria-disabled="true"
className={cn(
'flex min-w-0 items-center gap-3 rounded-xl border border-[var(--interactive-border)] bg-[var(--surface-elevated)] px-4 py-3',
'pointer-events-none opacity-60',
)}
>
<div className="flex size-10 shrink-0 items-center justify-center rounded-[10px] bg-[var(--surface-muted)]">
<Icon name={messenger.icon} className={cn('size-5', messenger.brandClassName)} />
</div>
<div className="min-w-0 flex-1">
<div className="truncate text-sm font-semibold text-foreground">{t(messenger.nameKey)}</div>
<p className="mt-0.5 line-clamp-1 text-xs leading-snug text-muted-foreground">
{t(messenger.descriptionKey)}
</p>
</div>
<span className="max-w-36 shrink-0 truncate rounded-full bg-[var(--surface-muted)] px-2 py-0.5 text-[10px] font-medium text-muted-foreground">
{t('settings.common.state.comingSoon')}
</span>
</div>
))}
</SettingsSection>
);
};
@@ -1,6 +1,7 @@
import React from 'react'; import React from 'react';
import { Icon } from '@/components/icon/Icon'; import { Icon } from '@/components/icon/Icon';
import { SettingsPageLayout } from '@/components/sections/shared/SettingsPageLayout'; import { SettingsPageLayout } from '@/components/sections/shared/SettingsPageLayout';
import { SETTINGS_DESCRIPTION_CLASS } from '@/components/sections/shared/SettingsSection';
import { useI18n } from '@/lib/i18n'; import { useI18n } from '@/lib/i18n';
import { ThirdPartyIntegrationsSection } from './ThirdPartyIntegrationsSection'; import { ThirdPartyIntegrationsSection } from './ThirdPartyIntegrationsSection';
@@ -18,15 +19,19 @@ export const IntegrationsPage: React.FC<IntegrationsPageProps> = ({
return ( return (
<SettingsPageLayout <SettingsPageLayout
title={t('settings.page.integrations.title')} title={t('settings.page.integrations.title')}
description={t('settings.page.integrations.description')} description={(
<div className="space-y-3">
<p className={SETTINGS_DESCRIPTION_CLASS}>{t('settings.page.integrations.description')}</p>
<div role="alert" className="flex items-start gap-2 rounded-lg border border-[var(--status-warning-border)] bg-[var(--status-warning-background)] p-3">
<Icon name="error-warning" className="mt-0.5 size-4 shrink-0 text-[var(--status-warning)]" />
<p className="typography-meta text-[var(--status-warning)]">
{t('settings.integrations.experimentalWarning')}
</p>
</div>
</div>
)}
showSaveStatus={false} showSaveStatus={false}
> >
<div className="flex items-start gap-2 rounded-lg border border-[var(--status-warning-border)] bg-[var(--status-warning-background)] p-3">
<Icon name="error-warning" className="mt-0.5 size-4 shrink-0 text-[var(--status-warning)]" />
<p className="typography-meta text-[var(--status-warning)]">
{t('settings.integrations.experimentalWarning')}
</p>
</div>
<ThirdPartyIntegrationsSection <ThirdPartyIntegrationsSection
divider={false} divider={false}
onOpenProviderSetup={onOpenProviderSetup} onOpenProviderSetup={onOpenProviderSetup}
@@ -13,7 +13,6 @@ import { toast } from '@/components/ui';
import { Icon } from '@/components/icon/Icon'; import { Icon } from '@/components/icon/Icon';
import { SettingsSection } from '@/components/sections/shared/SettingsSection'; import { SettingsSection } from '@/components/sections/shared/SettingsSection';
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@/components/ui/collapsible'; import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@/components/ui/collapsible';
import { ProviderLogo } from '@/components/ui/ProviderLogo';
import { useI18n } from '@/lib/i18n'; import { useI18n } from '@/lib/i18n';
import { openExternalUrl } from '@/lib/url'; import { openExternalUrl } from '@/lib/url';
import { cn } from '@/lib/utils'; import { cn } from '@/lib/utils';
@@ -330,11 +329,7 @@ export const ThirdPartyIntegrationsSection: React.FC<ThirdPartyIntegrationsSecti
className="flex w-full min-w-0 items-center gap-3 px-4 py-3 text-left hover:bg-[var(--interactive-hover)]/50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-[var(--interactive-focus-ring)]" className="flex w-full min-w-0 items-center gap-3 px-4 py-3 text-left hover:bg-[var(--interactive-hover)]/50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-[var(--interactive-focus-ring)]"
> >
<div className="flex size-10 shrink-0 items-center justify-center rounded-[10px] bg-[var(--surface-muted)]"> <div className="flex size-10 shrink-0 items-center justify-center rounded-[10px] bg-[var(--surface-muted)]">
{plugin.providerId === 'command-code' ? ( <Icon name={plugin.icon} className={cn('size-5', plugin.brandClassName)} />
<ProviderLogo providerId={plugin.providerId} className="size-5" />
) : (
<Icon name={plugin.icon} className={cn('size-5', plugin.brandClassName)} />
)}
</div> </div>
<div className="min-w-0 flex-1"> <div className="min-w-0 flex-1">
<div className="truncate text-sm font-semibold text-foreground">{t(plugin.nameKey)}</div> <div className="truncate text-sm font-semibold text-foreground">{t(plugin.nameKey)}</div>
@@ -131,11 +131,6 @@ describe('third-party plugin catalog helpers', () => {
packageName: '@openchamber/opencode-claude', packageName: '@openchamber/opencode-claude',
homepage: 'https://github.com/openchamber/opencode-claude', homepage: 'https://github.com/openchamber/opencode-claude',
}, },
{
id: 'opencode-commandcode',
packageName: '@openchamber/opencode-commandcode',
homepage: 'https://github.com/openchamber/opencode-commandcode',
},
{ {
id: 'opencode-cursor-oauth', id: 'opencode-cursor-oauth',
packageName: '@openchamber/opencode-cursor', packageName: '@openchamber/opencode-cursor',
@@ -25,16 +25,6 @@ export const THIRD_PARTY_PLUGINS: readonly ThirdPartyPluginDefinition[] = [
descriptionKey: 'settings.integrations.thirdParty.opencodeClaude.description', descriptionKey: 'settings.integrations.thirdParty.opencodeClaude.description',
homepage: 'https://github.com/openchamber/opencode-claude', homepage: 'https://github.com/openchamber/opencode-claude',
}, },
{
id: 'opencode-commandcode',
packageName: '@openchamber/opencode-commandcode',
providerId: 'command-code',
icon: 'command-code',
brandClassName: 'text-foreground',
nameKey: 'settings.integrations.thirdParty.opencodeCommandcode.name',
descriptionKey: 'settings.integrations.thirdParty.opencodeCommandcode.description',
homepage: 'https://github.com/openchamber/opencode-commandcode',
},
{ {
id: 'opencode-cursor-oauth', id: 'opencode-cursor-oauth',
packageName: '@openchamber/opencode-cursor', packageName: '@openchamber/opencode-cursor',
@@ -2,8 +2,10 @@ import { describe, expect, test } from 'bun:test';
import { getProviderLogoFallbackIcon } from './providerLogoFallback'; import { getProviderLogoFallbackIcon } from './providerLogoFallback';
describe('provider logo fallbacks', () => { describe('provider logo fallbacks', () => {
test('uses a local terminal icon when Command Code has no resolved logo', () => { test('uses a local terminal icon for Command Code provider ID variants', () => {
expect(getProviderLogoFallbackIcon('command-code')).toBe('terminal-box'); for (const providerId of ['command-code', 'commandcode', 'command_code', 'command code']) {
expect(getProviderLogoFallbackIcon(providerId)).toBe('terminal-box');
}
}); });
test('does not replace providers with their own logo assets', () => { test('does not replace providers with their own logo assets', () => {
@@ -1,5 +1,9 @@
import type { IconName } from '@/components/icon/icons'; import type { IconName } from '@/components/icon/icons';
const COMMAND_CODE_PROVIDER_IDS = new Set(['command-code', 'commandcode', 'command_code', 'command code']);
export function getProviderLogoFallbackIcon(providerId: string | null | undefined): IconName | null { export function getProviderLogoFallbackIcon(providerId: string | null | undefined): IconName | null {
return providerId?.trim().toLowerCase() === 'command-code' ? 'terminal-box' : null; return providerId && COMMAND_CODE_PROVIDER_IDS.has(providerId.trim().toLowerCase())
? 'terminal-box'
: null;
} }
@@ -7,9 +7,6 @@ const requiredKeys = [
'settings.page.integrations.title', 'settings.page.integrations.title',
'settings.page.integrations.description', 'settings.page.integrations.description',
'settings.integrations.experimentalWarning', 'settings.integrations.experimentalWarning',
'settings.integrations.messengers.title',
'settings.integrations.messengers.discord.name',
'settings.integrations.messengers.telegram.name',
'settings.integrations.thirdParty.title', 'settings.integrations.thirdParty.title',
'settings.integrations.thirdParty.actions.install', 'settings.integrations.thirdParty.actions.install',
'settings.integrations.thirdParty.actions.update', 'settings.integrations.thirdParty.actions.update',
@@ -17,7 +14,6 @@ const requiredKeys = [
'settings.integrations.thirdParty.actions.remove', 'settings.integrations.thirdParty.actions.remove',
'settings.integrations.thirdParty.status.notInstalled', 'settings.integrations.thirdParty.status.notInstalled',
'settings.integrations.thirdParty.opencodeClaude.description', 'settings.integrations.thirdParty.opencodeClaude.description',
'settings.integrations.thirdParty.opencodeCommandcode.description',
'settings.integrations.thirdParty.opencodeCursorOauth.description', 'settings.integrations.thirdParty.opencodeCursorOauth.description',
] as const; ] as const;
@@ -3,13 +3,7 @@ export const thirdPartyIntegrationI18n = {
en: { en: {
'settings.page.integrations.title': 'Integrations', 'settings.page.integrations.title': 'Integrations',
'settings.page.integrations.description': 'Add third-party subscriptions to use as OpenChamber providers.', 'settings.page.integrations.description': 'Add third-party subscriptions to use as OpenChamber providers.',
'settings.integrations.experimentalWarning': 'This is an experimental feature. Integrations may change or stop working. Use them at your own discretion.', 'settings.integrations.experimentalWarning': 'Experimental feature. We aim to respect provider policies, but account restrictions and suspensions remain each provider\'s decision. Use integrations at your own risk.',
'settings.integrations.messengers.title': 'Messengers',
'settings.integrations.messengers.info': 'Chat with OpenChamber from Discord or Telegram. These bridges are not available yet.',
'settings.integrations.messengers.discord.name': 'Discord',
'settings.integrations.messengers.discord.description': 'Connect a Discord bot to chat with OpenChamber.',
'settings.integrations.messengers.telegram.name': 'Telegram',
'settings.integrations.messengers.telegram.description': 'Connect a Telegram bot to chat with OpenChamber.',
'settings.integrations.thirdParty.title': 'Third-party integrations', 'settings.integrations.thirdParty.title': 'Third-party integrations',
'settings.integrations.thirdParty.info': 'Install a provider plugin, then set up your subscription so OpenChamber can use it.', 'settings.integrations.thirdParty.info': 'Install a provider plugin, then set up your subscription so OpenChamber can use it.',
'settings.integrations.thirdParty.actions.install': 'Install', 'settings.integrations.thirdParty.actions.install': 'Install',
@@ -38,21 +32,13 @@ export const thirdPartyIntegrationI18n = {
'settings.integrations.thirdParty.toast.restartRequired': 'Restart OpenCode for changes to take effect', 'settings.integrations.thirdParty.toast.restartRequired': 'Restart OpenCode for changes to take effect',
'settings.integrations.thirdParty.opencodeClaude.name': 'Claude Code', 'settings.integrations.thirdParty.opencodeClaude.name': 'Claude Code',
'settings.integrations.thirdParty.opencodeClaude.description': 'Use your Claude Pro/Max plan — no API keys, no Claude apps.', 'settings.integrations.thirdParty.opencodeClaude.description': 'Use your Claude Pro/Max plan — no API keys, no Claude apps.',
'settings.integrations.thirdParty.opencodeCommandcode.name': 'Command Code',
'settings.integrations.thirdParty.opencodeCommandcode.description': '$1 Go Plan: unlimited Laguna S 2.1 + $40 DeepSeek V4 Pro. Sign in, no CLI.',
'settings.integrations.thirdParty.opencodeCursorOauth.name': 'Cursor', 'settings.integrations.thirdParty.opencodeCursorOauth.name': 'Cursor',
'settings.integrations.thirdParty.opencodeCursorOauth.description': 'Cursors generous in-house model limits, now in OpenChamber.', 'settings.integrations.thirdParty.opencodeCursorOauth.description': 'Cursors generous in-house model limits, now in OpenChamber.',
}, },
de: { de: {
'settings.page.integrations.title': 'Integrationen', 'settings.page.integrations.title': 'Integrationen',
'settings.page.integrations.description': 'Füge Drittanbieter-Abonnements hinzu, um sie als OpenChamber-Provider zu nutzen.', 'settings.page.integrations.description': 'Füge Drittanbieter-Abonnements hinzu, um sie als OpenChamber-Provider zu nutzen.',
'settings.integrations.experimentalWarning': 'Dies ist eine experimentelle Funktion. Integrationen können sich ändern oder nicht mehr funktionieren. Nutze sie nach eigenem Ermessen.', 'settings.integrations.experimentalWarning': 'Experimentelle Funktion. Wir bemühen uns, die Richtlinien der Anbieter zu respektieren, aber Kontobeschränkungen und Sperrungen liegen bei jedem Anbieter. Nutze Integrationen auf eigenes Risiko.',
'settings.integrations.messengers.title': 'Messenger',
'settings.integrations.messengers.info': 'Chatte mit OpenChamber über Discord oder Telegram. Diese Bridges sind noch nicht verfügbar.',
'settings.integrations.messengers.discord.name': 'Discord',
'settings.integrations.messengers.discord.description': 'Verbinde einen Discord-Bot, um mit OpenChamber zu chatten.',
'settings.integrations.messengers.telegram.name': 'Telegram',
'settings.integrations.messengers.telegram.description': 'Verbinde einen Telegram-Bot, um mit OpenChamber zu chatten.',
'settings.integrations.thirdParty.title': 'Drittanbieter-Integrationen', 'settings.integrations.thirdParty.title': 'Drittanbieter-Integrationen',
'settings.integrations.thirdParty.info': 'Installiere ein Provider-Plugin und richte dein Abonnement ein, damit OpenChamber es nutzen kann.', 'settings.integrations.thirdParty.info': 'Installiere ein Provider-Plugin und richte dein Abonnement ein, damit OpenChamber es nutzen kann.',
'settings.integrations.thirdParty.actions.install': 'Installieren', 'settings.integrations.thirdParty.actions.install': 'Installieren',
@@ -81,21 +67,13 @@ export const thirdPartyIntegrationI18n = {
'settings.integrations.thirdParty.toast.restartRequired': 'Starte OpenCode neu, damit die Änderungen wirksam werden', 'settings.integrations.thirdParty.toast.restartRequired': 'Starte OpenCode neu, damit die Änderungen wirksam werden',
'settings.integrations.thirdParty.opencodeClaude.name': 'Claude Code', 'settings.integrations.thirdParty.opencodeClaude.name': 'Claude Code',
'settings.integrations.thirdParty.opencodeClaude.description': 'Nutze deinen Claude-Pro/Max-Plan — ohne API-Keys, ohne Claude-Apps.', 'settings.integrations.thirdParty.opencodeClaude.description': 'Nutze deinen Claude-Pro/Max-Plan — ohne API-Keys, ohne Claude-Apps.',
'settings.integrations.thirdParty.opencodeCommandcode.name': 'Command Code',
'settings.integrations.thirdParty.opencodeCommandcode.description': 'Go-Plan für 1 $: unbegrenztes Laguna S 2.1 + 40 $ DeepSeek V4 Pro. Anmelden, kein CLI.',
'settings.integrations.thirdParty.opencodeCursorOauth.name': 'Cursor', 'settings.integrations.thirdParty.opencodeCursorOauth.name': 'Cursor',
'settings.integrations.thirdParty.opencodeCursorOauth.description': 'Die großzügigen Limits der Cursor-eigenen Modelle jetzt in OpenChamber.', 'settings.integrations.thirdParty.opencodeCursorOauth.description': 'Die großzügigen Limits der Cursor-eigenen Modelle jetzt in OpenChamber.',
}, },
fr: { fr: {
'settings.page.integrations.title': 'Intégrations', 'settings.page.integrations.title': 'Intégrations',
'settings.page.integrations.description': 'Ajoutez des abonnements tiers à utiliser comme fournisseurs OpenChamber.', 'settings.page.integrations.description': 'Ajoutez des abonnements tiers à utiliser comme fournisseurs OpenChamber.',
'settings.integrations.experimentalWarning': 'Cette fonctionnalité est expérimentale. Les intégrations peuvent changer ou cesser de fonctionner. Utilisez-les à votre discrétion.', 'settings.integrations.experimentalWarning': 'Fonctionnalité expérimentale. Nous cherchons à respecter les règles des fournisseurs, mais les restrictions et suspensions de compte relèvent de leur décision. Utilisez les intégrations à vos risques.',
'settings.integrations.messengers.title': 'Messagers',
'settings.integrations.messengers.info': 'Discutez avec OpenChamber depuis Discord ou Telegram. Ces ponts ne sont pas encore disponibles.',
'settings.integrations.messengers.discord.name': 'Discord',
'settings.integrations.messengers.discord.description': 'Connectez un bot Discord pour discuter avec OpenChamber.',
'settings.integrations.messengers.telegram.name': 'Telegram',
'settings.integrations.messengers.telegram.description': 'Connectez un bot Telegram pour discuter avec OpenChamber.',
'settings.integrations.thirdParty.title': 'Intégrations tierces', 'settings.integrations.thirdParty.title': 'Intégrations tierces',
'settings.integrations.thirdParty.info': 'Installez un plugin de fournisseur, puis configurez votre abonnement pour quOpenChamber puisse lutiliser.', 'settings.integrations.thirdParty.info': 'Installez un plugin de fournisseur, puis configurez votre abonnement pour quOpenChamber puisse lutiliser.',
'settings.integrations.thirdParty.actions.install': 'Installer', 'settings.integrations.thirdParty.actions.install': 'Installer',
@@ -124,21 +102,13 @@ export const thirdPartyIntegrationI18n = {
'settings.integrations.thirdParty.toast.restartRequired': 'Redémarrez OpenCode pour que les modifications prennent effet', 'settings.integrations.thirdParty.toast.restartRequired': 'Redémarrez OpenCode pour que les modifications prennent effet',
'settings.integrations.thirdParty.opencodeClaude.name': 'Claude Code', 'settings.integrations.thirdParty.opencodeClaude.name': 'Claude Code',
'settings.integrations.thirdParty.opencodeClaude.description': 'Utilisez votre forfait Claude Pro/Max — sans clés API, sans apps Claude.', 'settings.integrations.thirdParty.opencodeClaude.description': 'Utilisez votre forfait Claude Pro/Max — sans clés API, sans apps Claude.',
'settings.integrations.thirdParty.opencodeCommandcode.name': 'Command Code',
'settings.integrations.thirdParty.opencodeCommandcode.description': 'Go Plan à 1 $ : Laguna S 2.1 illimité + 40 $ DeepSeek V4 Pro. Connectez-vous, sans CLI.',
'settings.integrations.thirdParty.opencodeCursorOauth.name': 'Cursor', 'settings.integrations.thirdParty.opencodeCursorOauth.name': 'Cursor',
'settings.integrations.thirdParty.opencodeCursorOauth.description': 'Les généreuses limites des modèles internes Cursor, désormais dans OpenChamber.', 'settings.integrations.thirdParty.opencodeCursorOauth.description': 'Les généreuses limites des modèles internes Cursor, désormais dans OpenChamber.',
}, },
es: { es: {
'settings.page.integrations.title': 'Integraciones', 'settings.page.integrations.title': 'Integraciones',
'settings.page.integrations.description': 'Añade suscripciones de terceros para usarlas como proveedores de OpenChamber.', 'settings.page.integrations.description': 'Añade suscripciones de terceros para usarlas como proveedores de OpenChamber.',
'settings.integrations.experimentalWarning': 'Esta función es experimental. Las integraciones pueden cambiar o dejar de funcionar. Úsalas bajo tu propia responsabilidad.', 'settings.integrations.experimentalWarning': 'Función experimental. Buscamos respetar las políticas de los proveedores, pero las restricciones y suspensiones de cuentas son decisión de cada proveedor. Usa las integraciones bajo tu propia responsabilidad.',
'settings.integrations.messengers.title': 'Mensajeros',
'settings.integrations.messengers.info': 'Chatea con OpenChamber desde Discord o Telegram. Estos puentes aún no están disponibles.',
'settings.integrations.messengers.discord.name': 'Discord',
'settings.integrations.messengers.discord.description': 'Conecta un bot de Discord para chatear con OpenChamber.',
'settings.integrations.messengers.telegram.name': 'Telegram',
'settings.integrations.messengers.telegram.description': 'Conecta un bot de Telegram para chatear con OpenChamber.',
'settings.integrations.thirdParty.title': 'Integraciones de terceros', 'settings.integrations.thirdParty.title': 'Integraciones de terceros',
'settings.integrations.thirdParty.info': 'Instala un plugin de proveedor y configura tu suscripción para que OpenChamber pueda usarla.', 'settings.integrations.thirdParty.info': 'Instala un plugin de proveedor y configura tu suscripción para que OpenChamber pueda usarla.',
'settings.integrations.thirdParty.actions.install': 'Instalar', 'settings.integrations.thirdParty.actions.install': 'Instalar',
@@ -167,21 +137,13 @@ export const thirdPartyIntegrationI18n = {
'settings.integrations.thirdParty.toast.restartRequired': 'Reinicia OpenCode para que los cambios surtan efecto', 'settings.integrations.thirdParty.toast.restartRequired': 'Reinicia OpenCode para que los cambios surtan efecto',
'settings.integrations.thirdParty.opencodeClaude.name': 'Claude Code', 'settings.integrations.thirdParty.opencodeClaude.name': 'Claude Code',
'settings.integrations.thirdParty.opencodeClaude.description': 'Usa tu plan Claude Pro/Max: sin claves API ni apps de Claude.', 'settings.integrations.thirdParty.opencodeClaude.description': 'Usa tu plan Claude Pro/Max: sin claves API ni apps de Claude.',
'settings.integrations.thirdParty.opencodeCommandcode.name': 'Command Code',
'settings.integrations.thirdParty.opencodeCommandcode.description': 'Go Plan por 1 $: Laguna S 2.1 ilimitado + 40 $ de DeepSeek V4 Pro. Entra, sin CLI.',
'settings.integrations.thirdParty.opencodeCursorOauth.name': 'Cursor', 'settings.integrations.thirdParty.opencodeCursorOauth.name': 'Cursor',
'settings.integrations.thirdParty.opencodeCursorOauth.description': 'Los generosos límites de los modelos internos de Cursor, ahora en OpenChamber.', 'settings.integrations.thirdParty.opencodeCursorOauth.description': 'Los generosos límites de los modelos internos de Cursor, ahora en OpenChamber.',
}, },
ja: { ja: {
'settings.page.integrations.title': '連携', 'settings.page.integrations.title': '連携',
'settings.page.integrations.description': 'サードパーティのサブスクリプションを追加して、OpenChamber のプロバイダーとして使います。', 'settings.page.integrations.description': 'サードパーティのサブスクリプションを追加して、OpenChamber のプロバイダーとして使います。',
'settings.integrations.experimentalWarning': 'これは実験的な機能です。連携は変更されたり、動作しなくなったりする可能性があります。自己責任で使用してください。', 'settings.integrations.experimentalWarning': '実験的な機能です。プロバイダーの方針を尊重するよう努めていますが、アカウントの制限や停止は各プロバイダーの判断に委ねられます。自己責任で連携を使用してください。',
'settings.integrations.messengers.title': 'メッセンジャー',
'settings.integrations.messengers.info': 'Discord または Telegram から OpenChamber とチャットできます。これらの連携はまだ利用できません。',
'settings.integrations.messengers.discord.name': 'Discord',
'settings.integrations.messengers.discord.description': 'Discord ボットを接続して OpenChamber とチャットします。',
'settings.integrations.messengers.telegram.name': 'Telegram',
'settings.integrations.messengers.telegram.description': 'Telegram ボットを接続して OpenChamber とチャットします。',
'settings.integrations.thirdParty.title': 'サードパーティー連携', 'settings.integrations.thirdParty.title': 'サードパーティー連携',
'settings.integrations.thirdParty.info': 'プロバイダープラグインをインストールし、サブスクリプションを設定して OpenChamber で使えるようにします。', 'settings.integrations.thirdParty.info': 'プロバイダープラグインをインストールし、サブスクリプションを設定して OpenChamber で使えるようにします。',
'settings.integrations.thirdParty.actions.install': 'インストール', 'settings.integrations.thirdParty.actions.install': 'インストール',
@@ -210,21 +172,13 @@ export const thirdPartyIntegrationI18n = {
'settings.integrations.thirdParty.toast.restartRequired': '変更を反映するには OpenCode を再起動してください', 'settings.integrations.thirdParty.toast.restartRequired': '変更を反映するには OpenCode を再起動してください',
'settings.integrations.thirdParty.opencodeClaude.name': 'Claude Code', 'settings.integrations.thirdParty.opencodeClaude.name': 'Claude Code',
'settings.integrations.thirdParty.opencodeClaude.description': 'Claude Pro/Max プランを利用 — API キーも Claude アプリも不要。', 'settings.integrations.thirdParty.opencodeClaude.description': 'Claude Pro/Max プランを利用 — API キーも Claude アプリも不要。',
'settings.integrations.thirdParty.opencodeCommandcode.name': 'Command Code',
'settings.integrations.thirdParty.opencodeCommandcode.description': '1ドルの Go PlanLaguna S 2.1 無制限 + DeepSeek V4 Pro 40ドル分。ログインするだけで CLI 不要。',
'settings.integrations.thirdParty.opencodeCursorOauth.name': 'Cursor', 'settings.integrations.thirdParty.opencodeCursorOauth.name': 'Cursor',
'settings.integrations.thirdParty.opencodeCursorOauth.description': 'Cursor 内蔵モデルの余裕ある制限が、OpenChamber で使えます。', 'settings.integrations.thirdParty.opencodeCursorOauth.description': 'Cursor 内蔵モデルの余裕ある制限が、OpenChamber で使えます。',
}, },
ko: { ko: {
'settings.page.integrations.title': '통합', 'settings.page.integrations.title': '통합',
'settings.page.integrations.description': '타사 구독을 추가해 OpenChamber 프로바이더로 사용하세요.', 'settings.page.integrations.description': '타사 구독을 추가해 OpenChamber 프로바이더로 사용하세요.',
'settings.integrations.experimentalWarning': '이 기능은 실험 단계입니다. 통합 기능은 변경되거나 작동하지 않을 수 있습니다. 본인의 판단에 따라 사용하세요.', 'settings.integrations.experimentalWarning': '실험 단계 기능입니다. 프로바이더 정책을 존중하려 노력하지만, 계정 제한과 정지는 각 프로바이더의 결정입니다. 본인의 책임 아래 통합 기능을 사용하세요.',
'settings.integrations.messengers.title': '메신저',
'settings.integrations.messengers.info': 'Discord 또는 Telegram에서 OpenChamber와 채팅하세요. 이 브리지는 아직 사용할 수 없습니다.',
'settings.integrations.messengers.discord.name': 'Discord',
'settings.integrations.messengers.discord.description': 'Discord 봇을 연결해 OpenChamber와 채팅하세요.',
'settings.integrations.messengers.telegram.name': 'Telegram',
'settings.integrations.messengers.telegram.description': 'Telegram 봇을 연결해 OpenChamber와 채팅하세요.',
'settings.integrations.thirdParty.title': '서드파티 통합', 'settings.integrations.thirdParty.title': '서드파티 통합',
'settings.integrations.thirdParty.info': '프로바이더 플러그인을 설치한 뒤 구독을 설정하면 OpenChamber에서 사용할 수 있습니다.', 'settings.integrations.thirdParty.info': '프로바이더 플러그인을 설치한 뒤 구독을 설정하면 OpenChamber에서 사용할 수 있습니다.',
'settings.integrations.thirdParty.actions.install': '설치', 'settings.integrations.thirdParty.actions.install': '설치',
@@ -253,21 +207,13 @@ export const thirdPartyIntegrationI18n = {
'settings.integrations.thirdParty.toast.restartRequired': '변경 사항을 적용하려면 OpenCode를 다시 시작하세요', 'settings.integrations.thirdParty.toast.restartRequired': '변경 사항을 적용하려면 OpenCode를 다시 시작하세요',
'settings.integrations.thirdParty.opencodeClaude.name': 'Claude Code', 'settings.integrations.thirdParty.opencodeClaude.name': 'Claude Code',
'settings.integrations.thirdParty.opencodeClaude.description': 'Claude Pro/Max 요금제를 사용하세요. API 키와 Claude 앱은 필요 없습니다.', 'settings.integrations.thirdParty.opencodeClaude.description': 'Claude Pro/Max 요금제를 사용하세요. API 키와 Claude 앱은 필요 없습니다.',
'settings.integrations.thirdParty.opencodeCommandcode.name': 'Command Code',
'settings.integrations.thirdParty.opencodeCommandcode.description': '1달러 Go Plan: Laguna S 2.1 무제한 + DeepSeek V4 Pro 40달러. 로그인만 하면 되고 CLI는 필요 없습니다.',
'settings.integrations.thirdParty.opencodeCursorOauth.name': 'Cursor', 'settings.integrations.thirdParty.opencodeCursorOauth.name': 'Cursor',
'settings.integrations.thirdParty.opencodeCursorOauth.description': 'Cursor 자체 모델의 넉넉한 한도를 이제 OpenChamber에서.', 'settings.integrations.thirdParty.opencodeCursorOauth.description': 'Cursor 자체 모델의 넉넉한 한도를 이제 OpenChamber에서.',
}, },
pl: { pl: {
'settings.page.integrations.title': 'Integracje', 'settings.page.integrations.title': 'Integracje',
'settings.page.integrations.description': 'Dodaj subskrypcje zewnętrzne, aby używać ich jako dostawców OpenChamber.', 'settings.page.integrations.description': 'Dodaj subskrypcje zewnętrzne, aby używać ich jako dostawców OpenChamber.',
'settings.integrations.experimentalWarning': 'To funkcja eksperymentalna. Integracje mogą się zmienić lub przestać działać. Korzystasz z nich na własną odpowiedzialność.', 'settings.integrations.experimentalWarning': 'Funkcja eksperymentalna. Staramy się przestrzegać zasad dostawców, ale ograniczenia i zawieszenia kont pozostają decyzją każdego dostawcy. Używaj integracji na własne ryzyko.',
'settings.integrations.messengers.title': 'Komunikatory',
'settings.integrations.messengers.info': 'Czatuj z OpenChamber przez Discord lub Telegram. Te mosty nie są jeszcze dostępne.',
'settings.integrations.messengers.discord.name': 'Discord',
'settings.integrations.messengers.discord.description': 'Połącz bota Discord, aby czatować z OpenChamber.',
'settings.integrations.messengers.telegram.name': 'Telegram',
'settings.integrations.messengers.telegram.description': 'Połącz bota Telegram, aby czatować z OpenChamber.',
'settings.integrations.thirdParty.title': 'Integracje zewnętrzne', 'settings.integrations.thirdParty.title': 'Integracje zewnętrzne',
'settings.integrations.thirdParty.info': 'Zainstaluj wtyczkę dostawcy, a następnie skonfiguruj subskrypcję, aby OpenChamber mógł z niej korzystać.', 'settings.integrations.thirdParty.info': 'Zainstaluj wtyczkę dostawcy, a następnie skonfiguruj subskrypcję, aby OpenChamber mógł z niej korzystać.',
'settings.integrations.thirdParty.actions.install': 'Zainstaluj', 'settings.integrations.thirdParty.actions.install': 'Zainstaluj',
@@ -296,21 +242,13 @@ export const thirdPartyIntegrationI18n = {
'settings.integrations.thirdParty.toast.restartRequired': 'Uruchom ponownie OpenCode, aby zastosować zmiany', 'settings.integrations.thirdParty.toast.restartRequired': 'Uruchom ponownie OpenCode, aby zastosować zmiany',
'settings.integrations.thirdParty.opencodeClaude.name': 'Claude Code', 'settings.integrations.thirdParty.opencodeClaude.name': 'Claude Code',
'settings.integrations.thirdParty.opencodeClaude.description': 'Korzystaj z planu Claude Pro/Max — bez kluczy API i aplikacji Claude.', 'settings.integrations.thirdParty.opencodeClaude.description': 'Korzystaj z planu Claude Pro/Max — bez kluczy API i aplikacji Claude.',
'settings.integrations.thirdParty.opencodeCommandcode.name': 'Command Code',
'settings.integrations.thirdParty.opencodeCommandcode.description': 'Go Plan za 1 $: nielimitowane Laguna S 2.1 + 40 $ DeepSeek V4 Pro. Zaloguj się, bez CLI.',
'settings.integrations.thirdParty.opencodeCursorOauth.name': 'Cursor', 'settings.integrations.thirdParty.opencodeCursorOauth.name': 'Cursor',
'settings.integrations.thirdParty.opencodeCursorOauth.description': 'Hojne limity wewnętrznych modeli Cursor teraz w OpenChamber.', 'settings.integrations.thirdParty.opencodeCursorOauth.description': 'Hojne limity wewnętrznych modeli Cursor teraz w OpenChamber.',
}, },
'pt-BR': { 'pt-BR': {
'settings.page.integrations.title': 'Integrações', 'settings.page.integrations.title': 'Integrações',
'settings.page.integrations.description': 'Adicione assinaturas de terceiros para usar como provedores do OpenChamber.', 'settings.page.integrations.description': 'Adicione assinaturas de terceiros para usar como provedores do OpenChamber.',
'settings.integrations.experimentalWarning': 'Este recurso é experimental. As integrações podem mudar ou deixar de funcionar. Use-as por sua conta e risco.', 'settings.integrations.experimentalWarning': 'Recurso experimental. Buscamos respeitar as políticas dos provedores, mas restrições e suspensões de conta continuam sendo decisão de cada provedor. Use as integrações por sua conta e risco.',
'settings.integrations.messengers.title': 'Mensageiros',
'settings.integrations.messengers.info': 'Converse com o OpenChamber pelo Discord ou Telegram. Essas pontes ainda não estão disponíveis.',
'settings.integrations.messengers.discord.name': 'Discord',
'settings.integrations.messengers.discord.description': 'Conecte um bot do Discord para conversar com o OpenChamber.',
'settings.integrations.messengers.telegram.name': 'Telegram',
'settings.integrations.messengers.telegram.description': 'Conecte um bot do Telegram para conversar com o OpenChamber.',
'settings.integrations.thirdParty.title': 'Integrações de terceiros', 'settings.integrations.thirdParty.title': 'Integrações de terceiros',
'settings.integrations.thirdParty.info': 'Instale um plugin de provedor e configure sua assinatura para o OpenChamber poder usá-la.', 'settings.integrations.thirdParty.info': 'Instale um plugin de provedor e configure sua assinatura para o OpenChamber poder usá-la.',
'settings.integrations.thirdParty.actions.install': 'Instalar', 'settings.integrations.thirdParty.actions.install': 'Instalar',
@@ -339,21 +277,13 @@ export const thirdPartyIntegrationI18n = {
'settings.integrations.thirdParty.toast.restartRequired': 'Reinicie o OpenCode para que as alterações entrem em vigor', 'settings.integrations.thirdParty.toast.restartRequired': 'Reinicie o OpenCode para que as alterações entrem em vigor',
'settings.integrations.thirdParty.opencodeClaude.name': 'Claude Code', 'settings.integrations.thirdParty.opencodeClaude.name': 'Claude Code',
'settings.integrations.thirdParty.opencodeClaude.description': 'Use seu plano Claude Pro/Max — sem chaves de API nem apps da Claude.', 'settings.integrations.thirdParty.opencodeClaude.description': 'Use seu plano Claude Pro/Max — sem chaves de API nem apps da Claude.',
'settings.integrations.thirdParty.opencodeCommandcode.name': 'Command Code',
'settings.integrations.thirdParty.opencodeCommandcode.description': 'Go Plan por US$ 1: Laguna S 2.1 ilimitado + US$ 40 de DeepSeek V4 Pro. Entre, sem CLI.',
'settings.integrations.thirdParty.opencodeCursorOauth.name': 'Cursor', 'settings.integrations.thirdParty.opencodeCursorOauth.name': 'Cursor',
'settings.integrations.thirdParty.opencodeCursorOauth.description': 'Os limites generosos dos modelos internos do Cursor, agora no OpenChamber.', 'settings.integrations.thirdParty.opencodeCursorOauth.description': 'Os limites generosos dos modelos internos do Cursor, agora no OpenChamber.',
}, },
uk: { uk: {
'settings.page.integrations.title': 'Інтеграції', 'settings.page.integrations.title': 'Інтеграції',
'settings.page.integrations.description': 'Додайте сторонні підписки, щоб використовувати їх як провайдери OpenChamber.', 'settings.page.integrations.description': 'Додайте сторонні підписки, щоб використовувати їх як провайдери OpenChamber.',
'settings.integrations.experimentalWarning': 'Це експериментальна функція. Інтеграції можуть змінюватися або перестати працювати. Використовуйте їх на власний розсуд.', 'settings.integrations.experimentalWarning': 'Експериментальна функція. Ми прагнемо дотримуватися політик провайдерів, але обмеження та блокування облікових записів залишаються рішенням кожного провайдера. Використовуйте інтеграції на власний ризик.',
'settings.integrations.messengers.title': 'Месенджери',
'settings.integrations.messengers.info': 'Спілкуйтеся з OpenChamber у Discord або Telegram. Ці мости ще недоступні.',
'settings.integrations.messengers.discord.name': 'Discord',
'settings.integrations.messengers.discord.description': 'Підключіть бота Discord, щоб спілкуватися з OpenChamber.',
'settings.integrations.messengers.telegram.name': 'Telegram',
'settings.integrations.messengers.telegram.description': 'Підключіть бота Telegram, щоб спілкуватися з OpenChamber.',
'settings.integrations.thirdParty.title': 'Сторонні інтеграції', 'settings.integrations.thirdParty.title': 'Сторонні інтеграції',
'settings.integrations.thirdParty.info': 'Установіть плагін провайдера, а потім налаштуйте підписку, щоб OpenChamber міг її використовувати.', 'settings.integrations.thirdParty.info': 'Установіть плагін провайдера, а потім налаштуйте підписку, щоб OpenChamber міг її використовувати.',
'settings.integrations.thirdParty.actions.install': 'Встановити', 'settings.integrations.thirdParty.actions.install': 'Встановити',
@@ -382,21 +312,13 @@ export const thirdPartyIntegrationI18n = {
'settings.integrations.thirdParty.toast.restartRequired': 'Перезапустіть OpenCode, щоб застосувати зміни', 'settings.integrations.thirdParty.toast.restartRequired': 'Перезапустіть OpenCode, щоб застосувати зміни',
'settings.integrations.thirdParty.opencodeClaude.name': 'Claude Code', 'settings.integrations.thirdParty.opencodeClaude.name': 'Claude Code',
'settings.integrations.thirdParty.opencodeClaude.description': 'Claude Pro/Max за підпискою — без API-ключів і без додатків Claude.', 'settings.integrations.thirdParty.opencodeClaude.description': 'Claude Pro/Max за підпискою — без API-ключів і без додатків Claude.',
'settings.integrations.thirdParty.opencodeCommandcode.name': 'Command Code',
'settings.integrations.thirdParty.opencodeCommandcode.description': 'Go Plan за $1: безліміт Laguna S 2.1 і $40 на DeepSeek V4 Pro. Вхід без CLI.',
'settings.integrations.thirdParty.opencodeCursorOauth.name': 'Cursor', 'settings.integrations.thirdParty.opencodeCursorOauth.name': 'Cursor',
'settings.integrations.thirdParty.opencodeCursorOauth.description': 'Щедрі ліміти внутрішніх моделей Cursor — тепер в OpenChamber.', 'settings.integrations.thirdParty.opencodeCursorOauth.description': 'Щедрі ліміти внутрішніх моделей Cursor — тепер в OpenChamber.',
}, },
'zh-CN': { 'zh-CN': {
'settings.page.integrations.title': '集成', 'settings.page.integrations.title': '集成',
'settings.page.integrations.description': '添加第三方订阅,将其用作 OpenChamber 提供商。', 'settings.page.integrations.description': '添加第三方订阅,将其用作 OpenChamber 提供商。',
'settings.integrations.experimentalWarning': '这是实验性功能。集成可能会变更或停止工作。请自行酌情使用。', 'settings.integrations.experimentalWarning': '实验性功能。我们力求遵守提供商的政策,但帐户限制和暂停仍由各提供商决定。请自行承担使用集成的风险。',
'settings.integrations.messengers.title': '即时通讯',
'settings.integrations.messengers.info': '通过 Discord 或 Telegram 与 OpenChamber 聊天。这些桥接尚不可用。',
'settings.integrations.messengers.discord.name': 'Discord',
'settings.integrations.messengers.discord.description': '连接 Discord 机器人以与 OpenChamber 聊天。',
'settings.integrations.messengers.telegram.name': 'Telegram',
'settings.integrations.messengers.telegram.description': '连接 Telegram 机器人以与 OpenChamber 聊天。',
'settings.integrations.thirdParty.title': '第三方集成', 'settings.integrations.thirdParty.title': '第三方集成',
'settings.integrations.thirdParty.info': '安装提供商插件并设置订阅,以便 OpenChamber 可以使用它。', 'settings.integrations.thirdParty.info': '安装提供商插件并设置订阅,以便 OpenChamber 可以使用它。',
'settings.integrations.thirdParty.actions.install': '安装', 'settings.integrations.thirdParty.actions.install': '安装',
@@ -425,21 +347,13 @@ export const thirdPartyIntegrationI18n = {
'settings.integrations.thirdParty.toast.restartRequired': '请重启 OpenCode 以使更改生效', 'settings.integrations.thirdParty.toast.restartRequired': '请重启 OpenCode 以使更改生效',
'settings.integrations.thirdParty.opencodeClaude.name': 'Claude Code', 'settings.integrations.thirdParty.opencodeClaude.name': 'Claude Code',
'settings.integrations.thirdParty.opencodeClaude.description': '使用 Claude Pro/Max 套餐——无需 API 密钥,也无需 Claude 应用。', 'settings.integrations.thirdParty.opencodeClaude.description': '使用 Claude Pro/Max 套餐——无需 API 密钥,也无需 Claude 应用。',
'settings.integrations.thirdParty.opencodeCommandcode.name': 'Command Code',
'settings.integrations.thirdParty.opencodeCommandcode.description': '1 美元 Go Plan:无限 Laguna S 2.1,另含 40 美元 DeepSeek V4 Pro。登录即可,无需 CLI。',
'settings.integrations.thirdParty.opencodeCursorOauth.name': 'Cursor', 'settings.integrations.thirdParty.opencodeCursorOauth.name': 'Cursor',
'settings.integrations.thirdParty.opencodeCursorOauth.description': 'Cursor 内部模型的充足额度,现已可用于 OpenChamber。', 'settings.integrations.thirdParty.opencodeCursorOauth.description': 'Cursor 内部模型的充足额度,现已可用于 OpenChamber。',
}, },
'zh-TW': { 'zh-TW': {
'settings.page.integrations.title': '整合', 'settings.page.integrations.title': '整合',
'settings.page.integrations.description': '新增第三方訂閱,將其用作 OpenChamber 供應商。', 'settings.page.integrations.description': '新增第三方訂閱,將其用作 OpenChamber 供應商。',
'settings.integrations.experimentalWarning': '這是實驗性功能。整合可能會變更或停止運作。請自行斟酌使用。', 'settings.integrations.experimentalWarning': '實驗性功能。我們致力遵守供應商的政策,但帳戶限制和停用仍由各供應商決定。請自行承擔使用整合的風險。',
'settings.integrations.messengers.title': '即時通訊',
'settings.integrations.messengers.info': '透過 Discord 或 Telegram 與 OpenChamber 聊天。這些橋接尚不可用。',
'settings.integrations.messengers.discord.name': 'Discord',
'settings.integrations.messengers.discord.description': '連接 Discord 機器人以與 OpenChamber 聊天。',
'settings.integrations.messengers.telegram.name': 'Telegram',
'settings.integrations.messengers.telegram.description': '連接 Telegram 機器人以與 OpenChamber 聊天。',
'settings.integrations.thirdParty.title': '第三方整合', 'settings.integrations.thirdParty.title': '第三方整合',
'settings.integrations.thirdParty.info': '安裝供應商外掛並設定訂閱,以便 OpenChamber 可以使用它。', 'settings.integrations.thirdParty.info': '安裝供應商外掛並設定訂閱,以便 OpenChamber 可以使用它。',
'settings.integrations.thirdParty.actions.install': '安裝', 'settings.integrations.thirdParty.actions.install': '安裝',
@@ -468,8 +382,6 @@ export const thirdPartyIntegrationI18n = {
'settings.integrations.thirdParty.toast.restartRequired': '請重新啟動 OpenCode 以使變更生效', 'settings.integrations.thirdParty.toast.restartRequired': '請重新啟動 OpenCode 以使變更生效',
'settings.integrations.thirdParty.opencodeClaude.name': 'Claude Code', 'settings.integrations.thirdParty.opencodeClaude.name': 'Claude Code',
'settings.integrations.thirdParty.opencodeClaude.description': '使用 Claude Pro/Max 方案——無需 API 金鑰,也無需 Claude 應用程式。', 'settings.integrations.thirdParty.opencodeClaude.description': '使用 Claude Pro/Max 方案——無需 API 金鑰,也無需 Claude 應用程式。',
'settings.integrations.thirdParty.opencodeCommandcode.name': 'Command Code',
'settings.integrations.thirdParty.opencodeCommandcode.description': '1 美元 Go Plan:無限 Laguna S 2.1,另含 40 美元 DeepSeek V4 Pro。登入即可,無需 CLI。',
'settings.integrations.thirdParty.opencodeCursorOauth.name': 'Cursor', 'settings.integrations.thirdParty.opencodeCursorOauth.name': 'Cursor',
'settings.integrations.thirdParty.opencodeCursorOauth.description': 'Cursor 內部模型的充足額度,現已可用於 OpenChamber。', 'settings.integrations.thirdParty.opencodeCursorOauth.description': 'Cursor 內部模型的充足額度,現已可用於 OpenChamber。',
}, },
-7
View File
@@ -958,13 +958,6 @@ const SETTINGS_SEARCH_ITEMS: readonly SettingsSearchItem[] = [
descriptionKey: 'settings.integrations.thirdParty.opencodeClaude.description', descriptionKey: 'settings.integrations.thirdParty.opencodeClaude.description',
keywords: ['claude', 'anthropic', 'claude code', 'pro', 'max', 'agent sdk', '@openchamber/opencode-claude'], keywords: ['claude', 'anthropic', 'claude code', 'pro', 'max', 'agent sdk', '@openchamber/opencode-claude'],
}, },
{
id: 'integrations.third-party.opencode-commandcode',
page: 'integrations',
titleKey: 'settings.integrations.thirdParty.opencodeCommandcode.name',
descriptionKey: 'settings.integrations.thirdParty.opencodeCommandcode.description',
keywords: ['command code', 'commandcode', 'laguna', 'poolside', 'gateway', '@openchamber/opencode-commandcode'],
},
{ {
id: 'integrations.third-party.opencode-cursor-oauth', id: 'integrations.third-party.opencode-cursor-oauth',
page: 'integrations', page: 'integrations',
@@ -3,7 +3,7 @@ import { asObject, buildResult, getAuthEntry, normalizeAuthEntry, toNumber, toUs
export const providerId = 'command-code'; export const providerId = 'command-code';
export const providerName = 'Command Code'; export const providerName = 'Command Code';
export const aliases = ['command-code']; export const aliases = ['command-code', 'commandcode', 'command_code', 'command code'];
const API_BASE_URL = 'https://api.commandcode.ai'; const API_BASE_URL = 'https://api.commandcode.ai';
@@ -69,4 +69,17 @@ describe('Command Code quota provider', () => {
expect(fetchMock.mock.calls[0][1].headers.Authorization).toBe('Bearer test-token'); expect(fetchMock.mock.calls[0][1].headers.Authorization).toBe('Bearer test-token');
vi.unstubAllGlobals(); vi.unstubAllGlobals();
}); });
it('recognizes Command Code auth entries under supported provider ID variants', async () => {
for (const providerId of ['commandcode', 'command_code', 'command code']) {
const fetchMock = vi.fn()
.mockResolvedValueOnce(new Response(JSON.stringify({ org: { id: 'org-1' } })))
.mockResolvedValueOnce(new Response(JSON.stringify(creditsPayload)));
vi.stubGlobal('fetch', fetchMock);
const result = await fetchQuota({ [providerId]: { type: 'oauth', access: 'test-token' } });
expect(result).toMatchObject({ providerId: 'command-code', ok: true, configured: true });
vi.unstubAllGlobals();
}
});
}); });
@@ -160,6 +160,13 @@ const registry = {
const pendingFetches = new Map(); const pendingFetches = new Map();
const normalizeQuotaProviderId = (providerId) => {
if (typeof providerId !== 'string') return providerId;
return ['command-code', 'commandcode', 'command_code', 'command code'].includes(providerId.trim().toLowerCase())
? 'command-code'
: providerId;
};
export const listConfiguredQuotaProviders = () => { export const listConfiguredQuotaProviders = () => {
const configured = []; const configured = [];
@@ -203,13 +210,14 @@ const fetchQuotaForProviderUncoalesced = async (providerId) => {
}; };
export const fetchQuotaForProvider = (providerId) => { export const fetchQuotaForProvider = (providerId) => {
const existing = pendingFetches.get(providerId); const normalizedProviderId = normalizeQuotaProviderId(providerId);
const existing = pendingFetches.get(normalizedProviderId);
if (existing) return existing; if (existing) return existing;
const pending = fetchQuotaForProviderUncoalesced(providerId).finally(() => { const pending = fetchQuotaForProviderUncoalesced(normalizedProviderId).finally(() => {
if (pendingFetches.get(providerId) === pending) pendingFetches.delete(providerId); if (pendingFetches.get(normalizedProviderId) === pending) pendingFetches.delete(normalizedProviderId);
}); });
pendingFetches.set(providerId, pending); pendingFetches.set(normalizedProviderId, pending);
return pending; return pending;
}; };